bug 8029 handle expired in transit entries
[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 com.google.common.collect.Lists;
11
12 import java.util.ArrayList;
13 import java.util.Collections;
14 import java.util.HashMap;
15 import java.util.List;
16 import java.util.Map;
17 import java.util.Optional;
18 import java.util.concurrent.ExecutionException;
19 import java.util.function.Function;
20
21 import org.opendaylight.ovsdb.lib.notation.Condition;
22 import org.opendaylight.ovsdb.lib.notation.Row;
23 import org.opendaylight.ovsdb.lib.notation.UUID;
24 import org.opendaylight.ovsdb.lib.operations.Operation;
25 import org.opendaylight.ovsdb.lib.operations.OperationResult;
26 import org.opendaylight.ovsdb.lib.operations.Select;
27 import org.opendaylight.ovsdb.lib.schema.DatabaseSchema;
28 import org.opendaylight.ovsdb.lib.schema.GenericTableSchema;
29 import org.opendaylight.ovsdb.lib.schema.typed.TypedBaseTable;
30 import org.opendaylight.ovsdb.lib.schema.typed.TyperUtils;
31 import org.opendaylight.ovsdb.schema.hardwarevtep.LogicalSwitch;
32 import org.opendaylight.ovsdb.schema.hardwarevtep.McastMacsRemote;
33 import org.opendaylight.ovsdb.schema.hardwarevtep.PhysicalLocator;
34 import org.opendaylight.ovsdb.schema.hardwarevtep.UcastMacsRemote;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitches;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacs;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteUcastMacs;
38 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
39 import org.opendaylight.yangtools.yang.binding.Identifiable;
40 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
41 import org.slf4j.Logger;
42 import org.slf4j.LoggerFactory;
43
44 import static org.opendaylight.ovsdb.lib.operations.Operations.op;
45
46 public class HwvtepTableReader {
47
48     private static final Logger LOG = LoggerFactory.getLogger(HwvtepTableReader.class);
49
50     private final Map<Class, Function<InstanceIdentifier, List<Condition>>> whereClauseGetterMap = new HashMap();
51     private final Map<Class, Class> tableMap = new HashMap();
52     private final Map<Class, TypedBaseTable> tables = new HashMap<>();
53
54     private final HwvtepConnectionInstance connectionInstance;
55
56     public HwvtepTableReader(HwvtepConnectionInstance connectionInstance) {
57         this.connectionInstance = connectionInstance;
58         DatabaseSchema dbSchema = null;
59         try {
60             dbSchema = connectionInstance.getSchema(HwvtepSchemaConstants.HARDWARE_VTEP).get();
61         } catch (InterruptedException | ExecutionException e) {
62             LOG.warn("Not able to fetch schema for database {} from device {}",
63                     HwvtepSchemaConstants.HARDWARE_VTEP, connectionInstance.getConnectionInfo(), e);
64         }
65
66         tableMap.put(RemoteMcastMacs.class, McastMacsRemote.class);
67         tableMap.put(RemoteUcastMacs.class, UcastMacsRemote.class);
68         tableMap.put(LogicalSwitches.class, LogicalSwitch.class);
69         tableMap.put(TerminationPoint.class, PhysicalLocator.class);
70
71         whereClauseGetterMap.put(RemoteMcastMacs.class, new RemoteMcastMacWhereClauseGetter());
72         whereClauseGetterMap.put(RemoteUcastMacs.class, new RemoteUcastMacWhereClauseGetter());
73         whereClauseGetterMap.put(LogicalSwitches.class, new LogicalSwitchWhereClauseGetter());
74         whereClauseGetterMap.put(TerminationPoint.class, new LocatorWhereClauseGetter());
75
76         tables.put(McastMacsRemote.class, TyperUtils.getTypedRowWrapper(dbSchema, McastMacsRemote.class, null));
77         tables.put(UcastMacsRemote.class, TyperUtils.getTypedRowWrapper(dbSchema, UcastMacsRemote.class, null));
78         tables.put(LogicalSwitch.class, TyperUtils.getTypedRowWrapper(dbSchema, LogicalSwitch.class, null));
79         tables.put(PhysicalLocator.class, TyperUtils.getTypedRowWrapper(dbSchema, PhysicalLocator.class, null));
80     }
81
82     class RemoteMcastMacWhereClauseGetter implements Function<InstanceIdentifier, List<Condition>> {
83         @Override
84         public List<Condition> apply(InstanceIdentifier iid) {
85             InstanceIdentifier<RemoteMcastMacs> macIid = iid;
86             String mac = macIid.firstKeyOf(RemoteMcastMacs.class).getMacEntryKey().getValue();
87             InstanceIdentifier<LogicalSwitches> lsIid = (InstanceIdentifier<LogicalSwitches>) macIid.firstKeyOf(
88                     RemoteMcastMacs.class).getLogicalSwitchRef().getValue();
89             UUID lsUUID = connectionInstance.getDeviceInfo().getUUID(LogicalSwitches.class, lsIid);
90             if (lsUUID == null) {
91                 LOG.error("Could not find uuid for ls key {}", lsIid);
92                 return null;
93             }
94
95             McastMacsRemote macTable = (McastMacsRemote) tables.get(McastMacsRemote.class);
96             ArrayList<Condition> conditions = new ArrayList<>();
97             conditions.add(macTable.getLogicalSwitchColumn().getSchema().opEqual(lsUUID));
98             conditions.add(macTable.getMacColumn().getSchema().opEqual(mac));
99             return conditions;
100         }
101     }
102
103     class RemoteUcastMacWhereClauseGetter implements Function<InstanceIdentifier, List<Condition>> {
104         @Override
105         public List<Condition> apply(InstanceIdentifier iid) {
106             InstanceIdentifier<RemoteUcastMacs> macIid = iid;
107             String mac = macIid.firstKeyOf(RemoteUcastMacs.class).getMacEntryKey().getValue();
108             InstanceIdentifier<LogicalSwitches> lsIid = (InstanceIdentifier<LogicalSwitches>) macIid.firstKeyOf(
109                     RemoteUcastMacs.class).getLogicalSwitchRef().getValue();
110             UUID lsUUID = connectionInstance.getDeviceInfo().getUUID(LogicalSwitches.class, lsIid);
111             if (lsUUID == null) {
112                 LOG.error("Could not find uuid for ls key {}", lsIid);
113                 return null;
114             }
115
116             UcastMacsRemote macTable = (UcastMacsRemote) tables.get(UcastMacsRemote.class);
117             ArrayList<Condition> conditions = new ArrayList<>();
118             conditions.add(macTable.getLogicalSwitchColumn().getSchema().opEqual(lsUUID));
119             conditions.add(macTable.getMacColumn().getSchema().opEqual(mac));
120             return conditions;
121         }
122     }
123
124     class LogicalSwitchWhereClauseGetter implements Function<InstanceIdentifier, List<Condition>> {
125         @Override
126         public List<Condition> apply(InstanceIdentifier iid) {
127             InstanceIdentifier<LogicalSwitches> lsIid = iid;
128             String lsName = lsIid.firstKeyOf(LogicalSwitches.class).getHwvtepNodeName().getValue();
129             LogicalSwitch logicalSwitch = (LogicalSwitch) tables.get(LogicalSwitch.class);
130             return Lists.newArrayList(logicalSwitch.getNameColumn().getSchema().opEqual(lsName));
131         }
132     }
133
134     class LocatorWhereClauseGetter implements Function<InstanceIdentifier, List<Condition>> {
135         @Override
136         public List<Condition> apply(InstanceIdentifier iid) {
137             InstanceIdentifier<TerminationPoint> tepIid = iid;
138             String locatorIp = tepIid.firstKeyOf(TerminationPoint.class).getTpId().getValue();
139             locatorIp = locatorIp.substring(locatorIp.indexOf(":") + 1);
140             LOG.info("Locator ip to look for {}", locatorIp);
141             PhysicalLocator locatorTable = (PhysicalLocator) tables.get(PhysicalLocator.class);
142             return Lists.newArrayList(locatorTable.getDstIpColumn().getSchema().opEqual(locatorIp));
143         }
144     }
145
146     public Optional<TypedBaseTable> getHwvtepTableEntryUUID(Class<? extends Identifiable> cls,
147                                                             InstanceIdentifier iid,
148                                                             UUID existingUUID) {
149         try {
150             DatabaseSchema dbSchema = null;
151             TypedBaseTable globalRow = null;
152             Class<TypedBaseTable> tableClass = tableMap.get(cls);
153             try {
154                 dbSchema = connectionInstance.getSchema(HwvtepSchemaConstants.HARDWARE_VTEP).get();
155             } catch (InterruptedException | ExecutionException e) {
156                 LOG.warn("Not able to fetch schema for database {} from device {}",
157                         HwvtepSchemaConstants.HARDWARE_VTEP, connectionInstance.getConnectionInfo(), e);
158             }
159
160             if (dbSchema != null) {
161                 GenericTableSchema hwvtepSchema = TyperUtils.getTableSchema(dbSchema, tableClass);
162
163                 List<String> hwvtepTableColumn = new ArrayList<>();
164                 hwvtepTableColumn.addAll(hwvtepSchema.getColumns());
165                 Select<GenericTableSchema> selectOperation = op.select(hwvtepSchema);
166                 selectOperation.setColumns(hwvtepTableColumn);
167
168                 if (existingUUID != null) {
169                     TypedBaseTable table = tables.get(tableClass);
170                     LOG.info("Setting uuid condition {} ", existingUUID);
171                     selectOperation.where(table.getUuidColumn().getSchema().opEqual(existingUUID));
172                 } else {
173                     if (whereClauseGetterMap.get(cls) != null) {
174                         List<Condition> conditions = whereClauseGetterMap.get(cls).apply(iid);
175                         if (conditions != null) {
176                             if (conditions.size() == 2) {
177                                 selectOperation.where(conditions.get(0)).and(conditions.get(1));
178                             } else {
179                                 selectOperation.where(conditions.get(0));
180                             }
181                         } else {
182                             LOG.error("Could not get where conditions for cls {} key {}", cls, iid);
183                             return Optional.empty();
184                         }
185                     } else {
186                         LOG.error("Could not get where class for cls {} ", cls);
187                         return Optional.empty();
188                     }
189                 }
190                 ArrayList<Operation> operations = new ArrayList<>();
191                 operations.add(selectOperation);
192                 try {
193                     List<OperationResult> results = connectionInstance.transact(dbSchema, operations).get();
194                     if (results != null && !results.isEmpty()) {
195                         OperationResult selectResult = results.get(0);
196                         if (selectResult.getRows() != null && !selectResult.getRows().isEmpty()) {
197                             globalRow = TyperUtils.getTypedRowWrapper(
198                                     dbSchema, tableClass, selectResult.getRows().get(0));
199                         }
200                     }
201                 } catch (InterruptedException | ExecutionException e) {
202                     LOG.warn("Not able to fetch hardware_vtep table row from device {}",
203                             connectionInstance.getConnectionInfo(), e);
204                 }
205             }
206             LOG.trace("Fetched {} from hardware_vtep schema", globalRow);
207             if (globalRow != null && globalRow.getUuid() != null) {
208                 return Optional.of(globalRow);
209             }
210             return Optional.empty();
211         } catch (Throwable e) {
212             LOG.error("Failed to get the hwvtep row for iid {} {} ", iid, e);
213             return Optional.empty();
214         }
215     }
216
217     public List<TypedBaseTable> getHwvtepTableEntries(Class<? extends Identifiable> cls) {
218         try {
219             List<TypedBaseTable> tableRows = new ArrayList<>();
220             DatabaseSchema dbSchema = null;
221             TypedBaseTable globalRow = null;
222             Class<TypedBaseTable> tableClass = tableMap.get(cls);
223             try {
224                 dbSchema = connectionInstance.getSchema(HwvtepSchemaConstants.HARDWARE_VTEP).get();
225             } catch (InterruptedException | ExecutionException e) {
226                 LOG.error("Not able to fetch schema for database {} from device {}",
227                         HwvtepSchemaConstants.HARDWARE_VTEP, connectionInstance.getConnectionInfo(), e);
228             }
229
230             if (dbSchema != null) {
231                 GenericTableSchema hwvtepSchema = TyperUtils.getTableSchema(dbSchema, tableClass);
232
233                 List<String> hwvtepTableColumn = new ArrayList<>();
234                 hwvtepTableColumn.addAll(hwvtepSchema.getColumns());
235                 Select<GenericTableSchema> selectOperation = op.select(hwvtepSchema);
236                 selectOperation.setColumns(hwvtepTableColumn);
237
238                 ArrayList<Operation> operations = Lists.newArrayList(selectOperation);
239                 try {
240                     List<OperationResult> results = connectionInstance.transact(dbSchema, operations).get();
241                     if (results != null && !results.isEmpty()) {
242                         for (OperationResult selectResult : results) {
243                             if (selectResult.getRows() != null && !selectResult.getRows().isEmpty()) {
244                                 for (Row<GenericTableSchema> row : selectResult.getRows()) {
245                                     tableRows.add(TyperUtils.getTypedRowWrapper(dbSchema, tableClass, row));
246                                 }
247                             }
248                         }
249                     }
250                 } catch (InterruptedException | ExecutionException e) {
251                     LOG.error("Not able to fetch hardware_vtep table row from device {}",
252                             connectionInstance.getConnectionInfo(), e);
253                 }
254             }
255             return tableRows;
256         } catch (Throwable e) {
257             LOG.error("Failed to get the hwvtep ", e);
258         }
259         return Collections.emptyList();
260     }
261 }