2 * Copyright (c) 2017 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.ovsdb.hwvtepsouthbound;
10 import static org.opendaylight.ovsdb.lib.operations.Operations.op;
12 import com.google.common.collect.Lists;
13 import java.util.ArrayList;
14 import java.util.Arrays;
15 import java.util.Collections;
16 import java.util.HashMap;
17 import java.util.List;
19 import java.util.Optional;
20 import java.util.concurrent.ExecutionException;
21 import java.util.function.Function;
22 import java.util.stream.Collectors;
23 import org.opendaylight.ovsdb.lib.message.TableUpdate;
24 import org.opendaylight.ovsdb.lib.message.TableUpdates;
25 import org.opendaylight.ovsdb.lib.notation.Condition;
26 import org.opendaylight.ovsdb.lib.notation.Row;
27 import org.opendaylight.ovsdb.lib.notation.UUID;
28 import org.opendaylight.ovsdb.lib.operations.Operation;
29 import org.opendaylight.ovsdb.lib.operations.OperationResult;
30 import org.opendaylight.ovsdb.lib.operations.Select;
31 import org.opendaylight.ovsdb.lib.schema.DatabaseSchema;
32 import org.opendaylight.ovsdb.lib.schema.GenericTableSchema;
33 import org.opendaylight.ovsdb.lib.schema.typed.TypedBaseTable;
34 import org.opendaylight.ovsdb.lib.schema.typed.TypedDatabaseSchema;
35 import org.opendaylight.ovsdb.lib.schema.typed.TyperUtils;
36 import org.opendaylight.ovsdb.schema.hardwarevtep.ACL;
37 import org.opendaylight.ovsdb.schema.hardwarevtep.ACLEntry;
38 import org.opendaylight.ovsdb.schema.hardwarevtep.ArpSourcesLocal;
39 import org.opendaylight.ovsdb.schema.hardwarevtep.ArpSourcesRemote;
40 import org.opendaylight.ovsdb.schema.hardwarevtep.Global;
41 import org.opendaylight.ovsdb.schema.hardwarevtep.LogicalRouter;
42 import org.opendaylight.ovsdb.schema.hardwarevtep.LogicalSwitch;
43 import org.opendaylight.ovsdb.schema.hardwarevtep.Manager;
44 import org.opendaylight.ovsdb.schema.hardwarevtep.McastMacsLocal;
45 import org.opendaylight.ovsdb.schema.hardwarevtep.McastMacsRemote;
46 import org.opendaylight.ovsdb.schema.hardwarevtep.PhysicalLocator;
47 import org.opendaylight.ovsdb.schema.hardwarevtep.PhysicalLocatorSet;
48 import org.opendaylight.ovsdb.schema.hardwarevtep.PhysicalPort;
49 import org.opendaylight.ovsdb.schema.hardwarevtep.PhysicalSwitch;
50 import org.opendaylight.ovsdb.schema.hardwarevtep.Tunnel;
51 import org.opendaylight.ovsdb.schema.hardwarevtep.UcastMacsLocal;
52 import org.opendaylight.ovsdb.schema.hardwarevtep.UcastMacsRemote;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitches;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacs;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteUcastMacs;
56 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
57 import org.opendaylight.yangtools.yang.binding.Identifiable;
58 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
59 import org.slf4j.Logger;
60 import org.slf4j.LoggerFactory;
62 public class HwvtepTableReader {
64 private static final Logger LOG = LoggerFactory.getLogger(HwvtepTableReader.class);
66 private final Class[] alltables = new Class[] {
69 ArpSourcesLocal.class,
71 ArpSourcesRemote.class,
76 PhysicalLocator.class,
77 McastMacsRemote.class,
80 PhysicalLocatorSet.class,
86 private final Map<Class, Function<InstanceIdentifier, List<Condition>>> whereClauseGetterMap = new HashMap();
87 private final Map<Class, Class> tableMap = new HashMap();
88 private final Map<Class, TypedBaseTable> tables = new HashMap<>();
90 private final HwvtepConnectionInstance connectionInstance;
92 public HwvtepTableReader(final HwvtepConnectionInstance connectionInstance) {
93 this.connectionInstance = connectionInstance;
94 DatabaseSchema dbSchema = null;
96 dbSchema = connectionInstance.getSchema(HwvtepSchemaConstants.HARDWARE_VTEP).get();
97 } catch (InterruptedException | ExecutionException e) {
98 LOG.warn("Not able to fetch schema for database {} from device {}",
99 HwvtepSchemaConstants.HARDWARE_VTEP, connectionInstance.getConnectionInfo(), e);
102 tableMap.put(RemoteMcastMacs.class, McastMacsRemote.class);
103 tableMap.put(RemoteUcastMacs.class, UcastMacsRemote.class);
104 tableMap.put(LogicalSwitches.class, LogicalSwitch.class);
105 tableMap.put(TerminationPoint.class, PhysicalLocator.class);
107 whereClauseGetterMap.put(RemoteMcastMacs.class, new RemoteMcastMacWhereClauseGetter());
108 whereClauseGetterMap.put(RemoteUcastMacs.class, new RemoteUcastMacWhereClauseGetter());
109 whereClauseGetterMap.put(LogicalSwitches.class, new LogicalSwitchWhereClauseGetter());
110 whereClauseGetterMap.put(TerminationPoint.class, new LocatorWhereClauseGetter());
112 tables.put(McastMacsRemote.class, TyperUtils.getTypedRowWrapper(dbSchema, McastMacsRemote.class, null));
113 tables.put(UcastMacsRemote.class, TyperUtils.getTypedRowWrapper(dbSchema, UcastMacsRemote.class, null));
114 tables.put(LogicalSwitch.class, TyperUtils.getTypedRowWrapper(dbSchema, LogicalSwitch.class, null));
115 tables.put(PhysicalLocator.class, TyperUtils.getTypedRowWrapper(dbSchema, PhysicalLocator.class, null));
118 class RemoteMcastMacWhereClauseGetter implements Function<InstanceIdentifier, List<Condition>> {
120 public List<Condition> apply(final InstanceIdentifier iid) {
121 InstanceIdentifier<RemoteMcastMacs> macIid = iid;
122 String mac = macIid.firstKeyOf(RemoteMcastMacs.class).getMacEntryKey().getValue();
123 InstanceIdentifier<LogicalSwitches> lsIid = (InstanceIdentifier<LogicalSwitches>) macIid.firstKeyOf(
124 RemoteMcastMacs.class).getLogicalSwitchRef().getValue();
125 UUID lsUUID = connectionInstance.getDeviceInfo().getUUID(LogicalSwitches.class, lsIid);
126 if (lsUUID == null) {
127 LOG.error("Could not find uuid for ls key {}", lsIid);
131 McastMacsRemote macTable = (McastMacsRemote) tables.get(McastMacsRemote.class);
132 ArrayList<Condition> conditions = new ArrayList<>();
133 conditions.add(macTable.getLogicalSwitchColumn().getSchema().opEqual(lsUUID));
134 conditions.add(macTable.getMacColumn().getSchema().opEqual(mac));
139 class RemoteUcastMacWhereClauseGetter implements Function<InstanceIdentifier, List<Condition>> {
141 public List<Condition> apply(final InstanceIdentifier iid) {
142 InstanceIdentifier<RemoteUcastMacs> macIid = iid;
143 String mac = macIid.firstKeyOf(RemoteUcastMacs.class).getMacEntryKey().getValue();
144 InstanceIdentifier<LogicalSwitches> lsIid = (InstanceIdentifier<LogicalSwitches>) macIid.firstKeyOf(
145 RemoteUcastMacs.class).getLogicalSwitchRef().getValue();
146 UUID lsUUID = connectionInstance.getDeviceInfo().getUUID(LogicalSwitches.class, lsIid);
147 if (lsUUID == null) {
148 LOG.error("Could not find uuid for ls key {}", lsIid);
152 UcastMacsRemote macTable = (UcastMacsRemote) tables.get(UcastMacsRemote.class);
153 ArrayList<Condition> conditions = new ArrayList<>();
154 conditions.add(macTable.getLogicalSwitchColumn().getSchema().opEqual(lsUUID));
155 conditions.add(macTable.getMacColumn().getSchema().opEqual(mac));
160 class LogicalSwitchWhereClauseGetter implements Function<InstanceIdentifier, List<Condition>> {
162 public List<Condition> apply(final InstanceIdentifier iid) {
163 InstanceIdentifier<LogicalSwitches> lsIid = iid;
164 String lsName = lsIid.firstKeyOf(LogicalSwitches.class).getHwvtepNodeName().getValue();
165 LogicalSwitch logicalSwitch = (LogicalSwitch) tables.get(LogicalSwitch.class);
166 return Lists.newArrayList(logicalSwitch.getNameColumn().getSchema().opEqual(lsName));
170 class LocatorWhereClauseGetter implements Function<InstanceIdentifier, List<Condition>> {
172 public List<Condition> apply(final InstanceIdentifier iid) {
173 InstanceIdentifier<TerminationPoint> tepIid = iid;
174 String locatorIp = tepIid.firstKeyOf(TerminationPoint.class).getTpId().getValue();
175 locatorIp = locatorIp.substring(locatorIp.indexOf(":") + 1);
176 LOG.info("Locator ip to look for {}", locatorIp);
177 PhysicalLocator locatorTable = (PhysicalLocator) tables.get(PhysicalLocator.class);
178 return Lists.newArrayList(locatorTable.getDstIpColumn().getSchema().opEqual(locatorIp));
182 @SuppressWarnings("checkstyle:IllegalCatch")
183 public Optional<TypedBaseTable> getHwvtepTableEntryUUID(final Class<? extends Identifiable> cls,
184 final InstanceIdentifier iid,
185 final UUID existingUUID) {
186 final TypedDatabaseSchema dbSchema;
188 dbSchema = connectionInstance.getSchema(HwvtepSchemaConstants.HARDWARE_VTEP).get();
189 } catch (InterruptedException | ExecutionException e) {
190 LOG.warn("Not able to fetch schema for database {} from device {}",
191 HwvtepSchemaConstants.HARDWARE_VTEP, connectionInstance.getConnectionInfo(), e);
192 return Optional.empty();
195 final Class<TypedBaseTable> tableClass = tableMap.get(cls);
196 final GenericTableSchema hwvtepSchema = dbSchema.getTableSchema(tableClass);
198 final Select<GenericTableSchema> selectOperation = op.select(hwvtepSchema);
199 selectOperation.setColumns(new ArrayList<>(hwvtepSchema.getColumns()));
201 if (existingUUID == null) {
202 final Function<InstanceIdentifier, List<Condition>> whereClausule = whereClauseGetterMap.get(cls);
203 if (whereClausule == null) {
204 LOG.error("Could not get where class for cls {} ", cls);
205 return Optional.empty();
207 final List<Condition> conditions = whereClausule.apply(iid);
208 if (conditions == null) {
209 LOG.error("Could not get where conditions for cls {} key {}", cls, iid);
210 return Optional.empty();
213 if (conditions.size() == 2) {
214 selectOperation.where(conditions.get(0)).and(conditions.get(1));
216 selectOperation.where(conditions.get(0));
219 TypedBaseTable table = tables.get(tableClass);
220 LOG.info("Setting uuid condition {} ", existingUUID);
221 selectOperation.where(table.getUuidColumn().getSchema().opEqual(existingUUID));
224 ArrayList<Operation> operations = new ArrayList<>();
225 operations.add(selectOperation);
227 final List<OperationResult> results;
229 results = connectionInstance.transact(dbSchema, operations).get();
230 } catch (InterruptedException | ExecutionException e) {
231 LOG.warn("Not able to fetch hardware_vtep table row from device {}",
232 connectionInstance.getConnectionInfo(), e);
233 return Optional.empty();
235 if (results == null || results.isEmpty()) {
236 return Optional.empty();
239 final List<Row<GenericTableSchema>> selectResult = results.get(0).getRows();
240 if (selectResult == null || selectResult.isEmpty()) {
241 return Optional.empty();
244 final TypedBaseTable globalRow = dbSchema.getTypedRowWrapper(tableClass, selectResult.get(0));
245 LOG.trace("Fetched {} from hardware_vtep schema", globalRow);
246 return globalRow != null && globalRow.getUuid() != null ? Optional.of(globalRow) : Optional.empty();
249 @SuppressWarnings("checkstyle:IllegalCatch")
250 public List<TypedBaseTable> getHwvtepTableEntries(final Class<? extends Identifiable> cls) {
251 final TypedDatabaseSchema dbSchema;
253 dbSchema = connectionInstance.getSchema(HwvtepSchemaConstants.HARDWARE_VTEP).get();
254 } catch (InterruptedException | ExecutionException e) {
255 LOG.error("Not able to fetch schema for database {} from device {}",
256 HwvtepSchemaConstants.HARDWARE_VTEP, connectionInstance.getConnectionInfo(), e);
260 final Class<TypedBaseTable> tableClass = tableMap.get(cls);
261 final GenericTableSchema hwvtepSchema = dbSchema.getTableSchema(tableClass);
262 final Select<GenericTableSchema> selectOperation = op.select(hwvtepSchema);
263 selectOperation.setColumns(new ArrayList<>(hwvtepSchema.getColumns()));
265 final List<OperationResult> results;
267 results = connectionInstance.transact(dbSchema, Lists.newArrayList(selectOperation)).get();
268 } catch (InterruptedException | ExecutionException e) {
269 LOG.error("Not able to fetch hardware_vtep table row from device {}",
270 connectionInstance.getConnectionInfo(), e);
271 return Collections.emptyList();
273 if (results == null || results.isEmpty()) {
274 return Collections.emptyList();
278 final List<TypedBaseTable> tableRows = new ArrayList<>();
279 for (OperationResult selectResult : results) {
280 if (selectResult.getRows() != null && !selectResult.getRows().isEmpty()) {
281 for (Row<GenericTableSchema> row : selectResult.getRows()) {
282 tableRows.add(dbSchema.getTypedRowWrapper(tableClass, row));
287 } catch (RuntimeException e) {
288 LOG.error("Failed to get the hwvtep ", e);
289 return Collections.emptyList();
293 public TableUpdates readAllTables() throws ExecutionException, InterruptedException {
294 Map<String, TableUpdate> tableUpdates = new HashMap<>();
295 TypedDatabaseSchema dbSchema = connectionInstance.getSchema(HwvtepSchemaConstants.HARDWARE_VTEP).get();
297 List<Operation> operations = Arrays.asList(alltables).stream()
298 .map(tableClass -> dbSchema.getTableSchema(tableClass))
299 .map(tableSchema -> buildSelectOperationFor(tableSchema))
300 .collect(Collectors.toList());
302 List<OperationResult> results = connectionInstance.transact(dbSchema, operations).get();
303 if (results != null && !results.isEmpty()) {
305 .filter(result -> result.getRows() != null)
306 .flatMap(result -> result.getRows().stream())
308 tableUpdates.compute(row.getTableSchema().getName(), (tableName, tableUpdate) -> {
309 if (tableUpdate == null) {
310 tableUpdate = new TableUpdate();
312 tableUpdate.addRow(getRowUuid(row), null, row);
317 return new TableUpdates(tableUpdates);
320 private Select<GenericTableSchema> buildSelectOperationFor(final GenericTableSchema tableSchema) {
321 Select<GenericTableSchema> selectOpearation = op.select(tableSchema);
322 selectOpearation.setColumns(new ArrayList<>(tableSchema.getColumns()));
323 return selectOpearation;
326 private UUID getRowUuid(final Row<GenericTableSchema> row) {
327 return row.getColumns().stream()
328 .filter(column -> column.getSchema().getName().equals("_uuid"))
329 .map(column -> (UUID) column.getData())
330 .findFirst().orElse(new UUID("test"));