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 java.util.Objects.requireNonNull;
11 import static org.opendaylight.ovsdb.lib.operations.Operations.op;
13 import com.google.common.collect.ImmutableClassToInstanceMap;
14 import com.google.common.collect.ImmutableClassToInstanceMap.Builder;
15 import com.google.common.collect.ImmutableMap;
16 import com.google.common.collect.Lists;
17 import java.util.ArrayList;
18 import java.util.Arrays;
19 import java.util.Collections;
20 import java.util.HashMap;
21 import java.util.List;
23 import java.util.Optional;
24 import java.util.concurrent.ExecutionException;
25 import java.util.function.Function;
26 import java.util.stream.Collectors;
27 import org.opendaylight.ovsdb.lib.message.TableUpdate;
28 import org.opendaylight.ovsdb.lib.message.TableUpdates;
29 import org.opendaylight.ovsdb.lib.notation.Condition;
30 import org.opendaylight.ovsdb.lib.notation.Row;
31 import org.opendaylight.ovsdb.lib.notation.UUID;
32 import org.opendaylight.ovsdb.lib.operations.Operation;
33 import org.opendaylight.ovsdb.lib.operations.OperationResult;
34 import org.opendaylight.ovsdb.lib.operations.Select;
35 import org.opendaylight.ovsdb.lib.schema.GenericTableSchema;
36 import org.opendaylight.ovsdb.lib.schema.typed.TypedBaseTable;
37 import org.opendaylight.ovsdb.lib.schema.typed.TypedDatabaseSchema;
38 import org.opendaylight.ovsdb.schema.hardwarevtep.ACL;
39 import org.opendaylight.ovsdb.schema.hardwarevtep.ACLEntry;
40 import org.opendaylight.ovsdb.schema.hardwarevtep.ArpSourcesLocal;
41 import org.opendaylight.ovsdb.schema.hardwarevtep.ArpSourcesRemote;
42 import org.opendaylight.ovsdb.schema.hardwarevtep.Global;
43 import org.opendaylight.ovsdb.schema.hardwarevtep.LogicalRouter;
44 import org.opendaylight.ovsdb.schema.hardwarevtep.LogicalSwitch;
45 import org.opendaylight.ovsdb.schema.hardwarevtep.Manager;
46 import org.opendaylight.ovsdb.schema.hardwarevtep.McastMacsLocal;
47 import org.opendaylight.ovsdb.schema.hardwarevtep.McastMacsRemote;
48 import org.opendaylight.ovsdb.schema.hardwarevtep.PhysicalLocator;
49 import org.opendaylight.ovsdb.schema.hardwarevtep.PhysicalLocatorSet;
50 import org.opendaylight.ovsdb.schema.hardwarevtep.PhysicalPort;
51 import org.opendaylight.ovsdb.schema.hardwarevtep.PhysicalSwitch;
52 import org.opendaylight.ovsdb.schema.hardwarevtep.Tunnel;
53 import org.opendaylight.ovsdb.schema.hardwarevtep.UcastMacsLocal;
54 import org.opendaylight.ovsdb.schema.hardwarevtep.UcastMacsRemote;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentation;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepNodeName;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitches;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitchesKey;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacs;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacsKey;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteUcastMacs;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteUcastMacsKey;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical.port.attributes.VlanBindings;
64 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
65 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
66 import org.opendaylight.yangtools.yang.binding.DataObject;
67 import org.opendaylight.yangtools.yang.binding.Identifiable;
68 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
69 import org.slf4j.Logger;
70 import org.slf4j.LoggerFactory;
72 public class HwvtepTableReader {
74 private static final Logger LOG = LoggerFactory.getLogger(HwvtepTableReader.class);
75 private static final Class<?>[] ALL_TABLES = new Class[] {
78 ArpSourcesLocal.class,
80 ArpSourcesRemote.class,
85 PhysicalLocator.class,
86 McastMacsRemote.class,
89 PhysicalLocatorSet.class,
95 private static final ImmutableMap<Class<?>, Class<? extends TypedBaseTable<?>>> TABLE_MAP = ImmutableMap.of(
96 RemoteMcastMacs.class, McastMacsRemote.class,
97 RemoteUcastMacs.class, UcastMacsRemote.class,
98 LogicalSwitches.class, LogicalSwitch.class,
99 TerminationPoint.class, PhysicalLocator.class,
100 VlanBindings.class, PhysicalPort.class);
102 private final ImmutableMap<Class<? extends Identifiable<?>>, WhereClauseGetter<?>> whereClauseGetters;
103 private final ImmutableClassToInstanceMap<TypedBaseTable<?>> tables;
104 private final HwvtepConnectionInstance connectionInstance;
106 public HwvtepTableReader(final HwvtepConnectionInstance connectionInstance) {
107 this.connectionInstance = connectionInstance;
108 TypedDatabaseSchema dbSchema = null;
110 dbSchema = connectionInstance.getSchema(HwvtepSchemaConstants.HARDWARE_VTEP).get();
111 } catch (InterruptedException | ExecutionException e) {
112 LOG.warn("Not able to fetch schema for database {} from device {}",
113 HwvtepSchemaConstants.HARDWARE_VTEP, connectionInstance.getConnectionInfo(), e);
116 final Builder<TypedBaseTable<?>> tableBuilder = ImmutableClassToInstanceMap.<TypedBaseTable<?>>builder();
117 final ImmutableMap.Builder<Class<? extends Identifiable<?>>, WhereClauseGetter<?>> whereBuilder =
118 ImmutableMap.builderWithExpectedSize(4);
120 if (dbSchema != null) {
121 final McastMacsRemote mcastMacsTable = dbSchema.getTypedRowWrapper(McastMacsRemote.class, null);
122 if (mcastMacsTable != null) {
123 tableBuilder.put(McastMacsRemote.class, mcastMacsTable);
124 whereBuilder.put(RemoteMcastMacs.class, new RemoteMcastMacWhereClauseGetter(mcastMacsTable));
126 final UcastMacsRemote ucastMacsTable = dbSchema.getTypedRowWrapper(UcastMacsRemote.class, null);
127 if (ucastMacsTable != null) {
128 tableBuilder.put(UcastMacsRemote.class, ucastMacsTable);
129 whereBuilder.put(RemoteUcastMacs.class, new RemoteUcastMacWhereClauseGetter(ucastMacsTable));
131 final LogicalSwitch lsTable = dbSchema.getTypedRowWrapper(LogicalSwitch.class, null);
132 if (lsTable != null) {
133 tableBuilder.put(LogicalSwitch.class, lsTable);
134 whereBuilder.put(LogicalSwitches.class, new LogicalSwitchWhereClauseGetter(lsTable));
136 final PhysicalLocator plTable = dbSchema.getTypedRowWrapper(PhysicalLocator.class, null);
137 if (plTable != null) {
138 tableBuilder.put(PhysicalLocator.class, plTable);
139 whereBuilder.put(TerminationPoint.class, new LocatorWhereClauseGetter(plTable));
141 final PhysicalPort physicalPort = dbSchema.getTypedRowWrapper(PhysicalPort.class, null);
142 if (physicalPort != null) {
143 tableBuilder.put(PhysicalPort.class, physicalPort);
147 tables = tableBuilder.build();
148 whereClauseGetters = whereBuilder.build();
152 private interface WhereClauseGetter<T extends DataObject> extends Function<InstanceIdentifier<T>, List<Condition>> {
156 class RemoteMcastMacWhereClauseGetter implements WhereClauseGetter<RemoteMcastMacs> {
157 private final McastMacsRemote macTable;
159 RemoteMcastMacWhereClauseGetter(final McastMacsRemote macTable) {
160 this.macTable = requireNonNull(macTable);
164 public List<Condition> apply(final InstanceIdentifier<RemoteMcastMacs> iid) {
165 RemoteMcastMacsKey key = iid.firstKeyOf(RemoteMcastMacs.class);
166 InstanceIdentifier<LogicalSwitches> lsIid = (InstanceIdentifier<LogicalSwitches>) key.getLogicalSwitchRef()
168 UUID lsUUID = getLsUuid(lsIid);
169 if (lsUUID == null) {
170 LOG.warn("Could not find uuid for ls key {}", getNodeKeyStr(lsIid));
174 ArrayList<Condition> conditions = new ArrayList<>();
175 conditions.add(macTable.getLogicalSwitchColumn().getSchema().opEqual(lsUUID));
180 protected <T extends DataObject> String getNodeKeyStr(InstanceIdentifier<T> iid) {
181 return iid.firstKeyOf(Node.class).getNodeId().getValue() + "." + getLsKeyStr(iid);
184 protected <T extends DataObject> String getLsKeyStr(InstanceIdentifier<T> iid) {
185 return ((InstanceIdentifier<LogicalSwitches>)iid).firstKeyOf(LogicalSwitches.class)
186 .getHwvtepNodeName().getValue();
189 public UUID getLsUuid(InstanceIdentifier lsIid) {
190 UUID lsUUID = connectionInstance.getDeviceInfo().getUUID(LogicalSwitches.class, lsIid);
191 if (lsUUID == null) {
192 Optional<TypedBaseTable> optional =
193 getHwvtepTableEntryUUID(LogicalSwitches.class, lsIid, null);
194 if (optional.isPresent()) {
195 lsUUID = optional.get().getUuid();
201 class RemoteUcastMacWhereClauseGetter implements WhereClauseGetter<RemoteUcastMacs> {
202 private final UcastMacsRemote macTable;
204 RemoteUcastMacWhereClauseGetter(final UcastMacsRemote macTable) {
205 this.macTable = requireNonNull(macTable);
209 public List<Condition> apply(final InstanceIdentifier<RemoteUcastMacs> iid) {
210 RemoteUcastMacsKey key = iid.firstKeyOf(RemoteUcastMacs.class);
211 InstanceIdentifier<LogicalSwitches> lsIid = (InstanceIdentifier<LogicalSwitches>) key.getLogicalSwitchRef()
213 UUID lsUUID = connectionInstance.getDeviceInfo().getUUID(LogicalSwitches.class, lsIid);
214 if (lsUUID == null) {
215 LOG.error("Could not find uuid for ls key {}", lsIid);
219 ArrayList<Condition> conditions = new ArrayList<>();
220 conditions.add(macTable.getLogicalSwitchColumn().getSchema().opEqual(lsUUID));
221 conditions.add(macTable.getMacColumn().getSchema().opEqual(key.getMacEntryKey().getValue()));
226 static class LogicalSwitchWhereClauseGetter implements WhereClauseGetter<LogicalSwitches> {
227 private final LogicalSwitch logicalSwitch;
229 LogicalSwitchWhereClauseGetter(final LogicalSwitch logicalSwitch) {
230 this.logicalSwitch = requireNonNull(logicalSwitch);
234 public List<Condition> apply(final InstanceIdentifier<LogicalSwitches> iid) {
235 String lsName = iid.firstKeyOf(LogicalSwitches.class).getHwvtepNodeName().getValue();
236 return Lists.newArrayList(logicalSwitch.getNameColumn().getSchema().opEqual(lsName));
240 static class LocatorWhereClauseGetter implements WhereClauseGetter<TerminationPoint> {
241 private final PhysicalLocator locatorTable;
243 LocatorWhereClauseGetter(final PhysicalLocator locatorTable) {
244 this.locatorTable = requireNonNull(locatorTable);
248 public List<Condition> apply(final InstanceIdentifier<TerminationPoint> iid) {
249 String locatorIp = iid.firstKeyOf(TerminationPoint.class).getTpId().getValue();
250 locatorIp = locatorIp.substring(locatorIp.indexOf(":") + 1);
251 LOG.info("Locator ip to look for {}", locatorIp);
252 return Lists.newArrayList(locatorTable.getDstIpColumn().getSchema().opEqual(locatorIp));
256 @SuppressWarnings("checkstyle:IllegalCatch")
257 public Optional<TypedBaseTable> getHwvtepTableEntryUUID(final Class<? extends Identifiable> cls,
258 final InstanceIdentifier iid,
259 final UUID existingUUID) {
260 final TypedDatabaseSchema dbSchema;
262 dbSchema = connectionInstance.getSchema(HwvtepSchemaConstants.HARDWARE_VTEP).get();
263 } catch (InterruptedException | ExecutionException e) {
264 LOG.warn("Not able to fetch schema for database {} from device {}",
265 HwvtepSchemaConstants.HARDWARE_VTEP, connectionInstance.getConnectionInfo(), e);
266 return Optional.empty();
269 final Class<? extends TypedBaseTable<?>> tableClass = TABLE_MAP.get(cls);
270 final GenericTableSchema hwvtepSchema = dbSchema.getTableSchema(tableClass);
272 final Select<GenericTableSchema> selectOperation = op.select(hwvtepSchema);
273 selectOperation.setColumns(hwvtepSchema.getColumnList());
275 if (existingUUID == null) {
276 final WhereClauseGetter<?> whereClausule = whereClauseGetters.get(cls);
277 if (whereClausule == null) {
278 LOG.error("Could not get where class for cls {} ", cls);
279 return Optional.empty();
281 final List<Condition> conditions = whereClausule.apply(iid);
282 if (conditions == null) {
283 LOG.error("Could not get where conditions for cls {} key {}", cls, iid);
284 return Optional.empty();
287 if (conditions.size() == 2) {
288 selectOperation.where(conditions.get(0)).and(conditions.get(1));
290 selectOperation.where(conditions.get(0));
293 TypedBaseTable<?> table = tables.get(tableClass);
294 LOG.info("Setting uuid condition {} ", existingUUID);
295 selectOperation.where(table.getUuidColumn().getSchema().opEqual(existingUUID));
298 final List<OperationResult> results;
300 results = connectionInstance.transact(dbSchema, Collections.singletonList(selectOperation)).get();
301 } catch (InterruptedException | ExecutionException e) {
302 LOG.warn("Not able to fetch hardware_vtep table row from device {}",
303 connectionInstance.getConnectionInfo(), e);
304 return Optional.empty();
306 if (results == null || results.isEmpty()) {
307 return Optional.empty();
310 final List<Row<GenericTableSchema>> selectResult = results.get(0).getRows();
311 if (selectResult == null || selectResult.isEmpty()) {
312 return Optional.empty();
315 final TypedBaseTable globalRow = dbSchema.getTypedRowWrapper(tableClass, selectResult.get(0));
316 LOG.trace("Fetched {} from hardware_vtep schema", globalRow);
317 return globalRow != null && globalRow.getUuid() != null ? Optional.of(globalRow) : Optional.empty();
320 @SuppressWarnings("checkstyle:IllegalCatch")
321 public List<TypedBaseTable> getHwvtepTableEntries(final Class<? extends Identifiable> cls) {
322 final TypedDatabaseSchema dbSchema;
324 dbSchema = connectionInstance.getSchema(HwvtepSchemaConstants.HARDWARE_VTEP).get();
325 } catch (InterruptedException | ExecutionException e) {
326 LOG.error("Not able to fetch schema for database {} from device {}",
327 HwvtepSchemaConstants.HARDWARE_VTEP, connectionInstance.getConnectionInfo(), e);
331 final Class<? extends TypedBaseTable<?>> tableClass = TABLE_MAP.get(cls);
332 final GenericTableSchema hwvtepSchema = dbSchema.getTableSchema(tableClass);
333 final Select<GenericTableSchema> selectOperation = op.select(hwvtepSchema);
334 selectOperation.setColumns(hwvtepSchema.getColumnList());
336 final List<OperationResult> results;
338 results = connectionInstance.transact(dbSchema, Collections.singletonList(selectOperation)).get();
339 } catch (InterruptedException | ExecutionException e) {
340 LOG.error("Not able to fetch hardware_vtep table row from device {}",
341 connectionInstance.getConnectionInfo(), e);
342 return Collections.emptyList();
344 if (results == null || results.isEmpty()) {
345 return Collections.emptyList();
349 final List<TypedBaseTable> tableRows = new ArrayList<>();
350 for (OperationResult selectResult : results) {
351 if (selectResult.getRows() != null && !selectResult.getRows().isEmpty()) {
352 for (Row<GenericTableSchema> row : selectResult.getRows()) {
353 tableRows.add(dbSchema.getTypedRowWrapper(tableClass, row));
358 } catch (RuntimeException e) {
359 LOG.error("Failed to get the hwvtep ", e);
360 return Collections.emptyList();
364 public TableUpdates readAllTables() throws ExecutionException, InterruptedException {
365 TypedDatabaseSchema dbSchema = connectionInstance.getSchema(HwvtepSchemaConstants.HARDWARE_VTEP).get();
366 List<Operation> operations = Arrays.stream(ALL_TABLES)
367 .map(tableClass -> dbSchema.getTableSchema(tableClass))
368 .map(HwvtepTableReader::buildSelectOperationFor)
369 .collect(Collectors.toList());
370 List<OperationResult> results = connectionInstance.transact(dbSchema, operations).get();
372 Map<String, TableUpdate> tableUpdates = new HashMap<>();
373 if (results != null) {
374 for (OperationResult result : results) {
375 final List<Row<GenericTableSchema>> rows = result.getRows();
377 for (Row<GenericTableSchema> row : rows) {
378 tableUpdates.computeIfAbsent(row.getTableSchema().getName(), key -> new TableUpdate<>())
379 .addRow(getRowUuid(row), null, row);
384 return new TableUpdates(tableUpdates);
387 public void refreshLocators() {
388 List<TypedBaseTable> physicalLocators = connectionInstance.getHwvtepTableReader()
389 .getHwvtepTableEntries(TerminationPoint.class);
390 for (TypedBaseTable row : physicalLocators) {
391 PhysicalLocator physicalLocator = (PhysicalLocator)row;
392 InstanceIdentifier<TerminationPoint> tpPath =
393 HwvtepSouthboundMapper.createInstanceIdentifier(connectionInstance.getInstanceIdentifier(),
395 connectionInstance.getDeviceInfo().updateDeviceOperData(
396 TerminationPoint.class, tpPath, physicalLocator.getUuid(), physicalLocator);
400 public void refreshLogicalSwitches() {
401 List<TypedBaseTable> logicalSwitches = connectionInstance.getHwvtepTableReader()
402 .getHwvtepTableEntries(LogicalSwitches.class);
403 for (TypedBaseTable row : logicalSwitches) {
404 LogicalSwitch logicalSwitch = (LogicalSwitch)row;
405 InstanceIdentifier<LogicalSwitches> switchIid = connectionInstance.getInstanceIdentifier()
406 .augmentation(HwvtepGlobalAugmentation.class)
407 .child(LogicalSwitches.class, new LogicalSwitchesKey(new HwvtepNodeName(logicalSwitch.getName())));
408 connectionInstance.getDeviceInfo().updateDeviceOperData(LogicalSwitches.class, switchIid,
409 logicalSwitch.getUuid(), logicalSwitch);
413 private static Select<GenericTableSchema> buildSelectOperationFor(final GenericTableSchema tableSchema) {
414 Select<GenericTableSchema> selectOperation = op.select(tableSchema);
415 selectOperation.setColumns(tableSchema.getColumnList());
416 return selectOperation;
419 private static UUID getRowUuid(final Row<GenericTableSchema> row) {
420 return row.getColumns().stream()
421 .filter(column -> column.getSchema().getName().equals("_uuid"))
422 .map(column -> (UUID) column.getData())
423 .findFirst().orElse(new UUID("test"));