Migrate TyperUtils.getTableSchema() users
[ovsdb.git] / hwvtepsouthbound / hwvtepsouthbound-impl / src / main / java / org / opendaylight / ovsdb / hwvtepsouthbound / HwvtepTableReader.java
1 /*
2  * Copyright (c) 2017 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.ovsdb.hwvtepsouthbound;
9
10 import static org.opendaylight.ovsdb.lib.operations.Operations.op;
11
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;
18 import java.util.Map;
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;
61
62 public class HwvtepTableReader {
63
64     private static final Logger LOG = LoggerFactory.getLogger(HwvtepTableReader.class);
65
66     private final Class[] alltables = new Class[] {
67         ACLEntry.class,
68         ACL.class,
69         ArpSourcesLocal.class,
70         Global.class,
71         ArpSourcesRemote.class,
72         LogicalRouter.class,
73         Manager.class,
74         LogicalSwitch.class,
75         McastMacsLocal.class,
76         PhysicalLocator.class,
77         McastMacsRemote.class,
78         PhysicalPort.class,
79         Tunnel.class,
80         PhysicalLocatorSet.class,
81         PhysicalSwitch.class,
82         UcastMacsLocal.class,
83         UcastMacsRemote.class
84     };
85
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<>();
89
90     private final HwvtepConnectionInstance connectionInstance;
91
92     public HwvtepTableReader(final HwvtepConnectionInstance connectionInstance) {
93         this.connectionInstance = connectionInstance;
94         DatabaseSchema dbSchema = null;
95         try {
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);
100         }
101
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);
106
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());
111
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));
116     }
117
118     class RemoteMcastMacWhereClauseGetter implements Function<InstanceIdentifier, List<Condition>> {
119         @Override
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);
128                 return null;
129             }
130
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));
135             return conditions;
136         }
137     }
138
139     class RemoteUcastMacWhereClauseGetter implements Function<InstanceIdentifier, List<Condition>> {
140         @Override
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);
149                 return null;
150             }
151
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));
156             return conditions;
157         }
158     }
159
160     class LogicalSwitchWhereClauseGetter implements Function<InstanceIdentifier, List<Condition>> {
161         @Override
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));
167         }
168     }
169
170     class LocatorWhereClauseGetter implements Function<InstanceIdentifier, List<Condition>> {
171         @Override
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));
179         }
180     }
181
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;
187         try {
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();
193         }
194
195         final Class<TypedBaseTable> tableClass = tableMap.get(cls);
196         final GenericTableSchema hwvtepSchema = dbSchema.getTableSchema(tableClass);
197
198         final Select<GenericTableSchema> selectOperation = op.select(hwvtepSchema);
199         selectOperation.setColumns(new ArrayList<>(hwvtepSchema.getColumns()));
200
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();
206             }
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();
211             }
212
213             if (conditions.size() == 2) {
214                 selectOperation.where(conditions.get(0)).and(conditions.get(1));
215             } else {
216                 selectOperation.where(conditions.get(0));
217             }
218         } else {
219             TypedBaseTable table = tables.get(tableClass);
220             LOG.info("Setting uuid condition {} ", existingUUID);
221             selectOperation.where(table.getUuidColumn().getSchema().opEqual(existingUUID));
222         }
223
224         ArrayList<Operation> operations = new ArrayList<>();
225         operations.add(selectOperation);
226
227         final List<OperationResult> results;
228         try {
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();
234         }
235         if (results == null || results.isEmpty()) {
236             return Optional.empty();
237         }
238
239         final List<Row<GenericTableSchema>> selectResult = results.get(0).getRows();
240         if (selectResult == null || selectResult.isEmpty()) {
241             return Optional.empty();
242         }
243
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();
247     }
248
249     @SuppressWarnings("checkstyle:IllegalCatch")
250     public List<TypedBaseTable> getHwvtepTableEntries(final Class<? extends Identifiable> cls) {
251         final TypedDatabaseSchema dbSchema;
252         try {
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);
257             return null;
258         }
259
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()));
264
265         final List<OperationResult> results;
266         try {
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();
272         }
273         if (results == null || results.isEmpty()) {
274             return Collections.emptyList();
275         }
276
277         try {
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));
283                     }
284                 }
285             }
286             return tableRows;
287         } catch (RuntimeException e) {
288             LOG.error("Failed to get the hwvtep ", e);
289             return Collections.emptyList();
290         }
291     }
292
293     public TableUpdates readAllTables() throws ExecutionException, InterruptedException {
294         Map<String, TableUpdate> tableUpdates =  new HashMap<>();
295         TypedDatabaseSchema dbSchema = connectionInstance.getSchema(HwvtepSchemaConstants.HARDWARE_VTEP).get();
296
297         List<Operation> operations = Arrays.asList(alltables).stream()
298                 .map(tableClass -> dbSchema.getTableSchema(tableClass))
299                 .map(tableSchema -> buildSelectOperationFor(tableSchema))
300                 .collect(Collectors.toList());
301
302         List<OperationResult> results = connectionInstance.transact(dbSchema, operations).get();
303         if (results != null && !results.isEmpty()) {
304             results.stream()
305                     .filter(result -> result.getRows() != null)
306                     .flatMap(result -> result.getRows().stream())
307                     .forEach(row -> {
308                         tableUpdates.compute(row.getTableSchema().getName(), (tableName, tableUpdate) -> {
309                             if (tableUpdate == null) {
310                                 tableUpdate = new TableUpdate();
311                             }
312                             tableUpdate.addRow(getRowUuid(row), null, row);
313                             return tableUpdate;
314                         });
315                     });
316         }
317         return new TableUpdates(tableUpdates);
318     }
319
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;
324     }
325
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"));
331     }
332 }