Merge "Fixed for bug : 1171 - issue while creating subnet"
[controller.git] / opendaylight / md-sal / compatibility / sal-compatibility / src / main / java / org / opendaylight / controller / sal / compatibility / InventoryAndReadAdapter.java
1 /**
2  * Copyright (c) 2014 Cisco Systems, Inc. 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.controller.sal.compatibility;
9
10 import com.google.common.collect.Iterables;
11
12 import java.util.ArrayList;
13 import java.util.Collections;
14 import java.util.HashSet;
15 import java.util.Iterator;
16 import java.util.List;
17 import java.util.Map;
18 import java.util.Set;
19 import java.util.concurrent.ConcurrentHashMap;
20 import java.util.concurrent.ConcurrentMap;
21 import java.util.concurrent.CopyOnWriteArrayList;
22
23 import org.opendaylight.controller.md.sal.binding.util.TypeSafeDataReader;
24 import org.opendaylight.controller.sal.binding.api.data.DataBrokerService;
25 import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
26 import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
27 import org.opendaylight.controller.sal.core.ConstructionException;
28 import org.opendaylight.controller.sal.core.Edge;
29 import org.opendaylight.controller.sal.core.Node;
30 import org.opendaylight.controller.sal.core.NodeConnector;
31 import org.opendaylight.controller.sal.core.NodeTable;
32 import org.opendaylight.controller.sal.core.NodeTable.NodeTableIDType;
33 import org.opendaylight.controller.sal.core.Property;
34 import org.opendaylight.controller.sal.core.UpdateType;
35 import org.opendaylight.controller.sal.inventory.IPluginInInventoryService;
36 import org.opendaylight.controller.sal.inventory.IPluginOutInventoryService;
37 import org.opendaylight.controller.sal.reader.FlowOnNode;
38 import org.opendaylight.controller.sal.reader.IPluginInReadService;
39 import org.opendaylight.controller.sal.reader.IPluginOutReadService;
40 import org.opendaylight.controller.sal.reader.NodeConnectorStatistics;
41 import org.opendaylight.controller.sal.reader.NodeDescription;
42 import org.opendaylight.controller.sal.reader.NodeTableStatistics;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.AggregateFlowStatisticsUpdate;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowStatisticsData;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowsStatisticsUpdate;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAllFlowsStatisticsFromAllFlowTablesInputBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetFlowStatisticsFromFlowTableInputBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.OpendaylightFlowStatisticsListener;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.OpendaylightFlowStatisticsService;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.flow.and.statistics.map.list.FlowAndStatisticsMapList;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.FlowTableStatisticsData;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.FlowTableStatisticsUpdate;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.GetFlowTablesStatisticsInputBuilder;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.OpendaylightFlowTableStatisticsListener;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.OpendaylightFlowTableStatisticsService;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.flow.table.and.statistics.map.FlowTableAndStatisticsMap;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.flow.table.statistics.FlowTableStatistics;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.topology.discovery.rev130819.FlowTopologyDiscoveryService;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.topology.discovery.rev130819.Link;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRemoved;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorUpdated;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRemoved;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeUpdated;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.OpendaylightInventoryListener;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.GenericStatistics;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.node.connector.statistics.Bytes;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.node.connector.statistics.Packets;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.FlowCapableNodeConnectorStatistics;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.FlowCapableNodeConnectorStatisticsData;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.GetAllNodeConnectorsStatisticsInputBuilder;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.GetNodeConnectorStatisticsInputBuilder;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.NodeConnectorStatisticsUpdate;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.OpendaylightPortStatisticsListener;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.OpendaylightPortStatisticsService;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.node.connector.statistics.and.port.number.map.NodeConnectorStatisticsAndPortNumberMap;
88 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
89 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
90 import org.slf4j.Logger;
91 import org.slf4j.LoggerFactory;
92
93 public class InventoryAndReadAdapter implements IPluginInReadService, IPluginInInventoryService, OpendaylightInventoryListener, OpendaylightFlowStatisticsListener, OpendaylightFlowTableStatisticsListener, OpendaylightPortStatisticsListener {
94     private static final Logger LOG = LoggerFactory.getLogger(InventoryAndReadAdapter.class);
95     private static final short OPENFLOWV10_TABLE_ID = 0;
96
97     private final InventoryNotificationProvider inventoryNotificationProvider = new InventoryNotificationProvider();
98     private final Map<PathArgument,List<PathArgument>> nodeToNodeConnectorsMap = new ConcurrentHashMap<>();
99     private List<IPluginOutInventoryService> inventoryPublisher = new CopyOnWriteArrayList<>();
100     private List<IPluginOutReadService> statisticsPublisher = new CopyOnWriteArrayList<>();
101
102     private OpendaylightFlowTableStatisticsService flowTableStatisticsService;
103     private OpendaylightPortStatisticsService nodeConnectorStatisticsService;
104     private OpendaylightFlowStatisticsService flowStatisticsService;
105     private FlowTopologyDiscoveryService topologyDiscovery;
106     private DataProviderService dataProviderService;
107     private DataBrokerService dataService;
108
109     public DataBrokerService getDataService() {
110         return dataService;
111     }
112
113     public void setDataService(final DataBrokerService dataService) {
114         this.dataService = dataService;
115     }
116
117     public DataProviderService getDataProviderService() {
118         return dataProviderService;
119     }
120
121     public void setDataProviderService(final DataProviderService dataProviderService) {
122         this.dataProviderService = dataProviderService;
123     }
124
125     public OpendaylightFlowStatisticsService getFlowStatisticsService() {
126         return flowStatisticsService;
127     }
128
129     public void setFlowStatisticsService(final OpendaylightFlowStatisticsService flowStatisticsService) {
130         this.flowStatisticsService = flowStatisticsService;
131     }
132
133     public OpendaylightPortStatisticsService getNodeConnectorStatisticsService() {
134         return nodeConnectorStatisticsService;
135     }
136
137     public void setNodeConnectorStatisticsService(final OpendaylightPortStatisticsService nodeConnectorStatisticsService) {
138         this.nodeConnectorStatisticsService = nodeConnectorStatisticsService;
139     }
140
141     public OpendaylightFlowTableStatisticsService getFlowTableStatisticsService() {
142         return flowTableStatisticsService;
143     }
144
145     public void setFlowTableStatisticsService(final OpendaylightFlowTableStatisticsService flowTableStatisticsService) {
146         this.flowTableStatisticsService = flowTableStatisticsService;
147     }
148
149     public FlowTopologyDiscoveryService getTopologyDiscovery() {
150         return topologyDiscovery;
151     }
152
153     public void setTopologyDiscovery(final FlowTopologyDiscoveryService topologyDiscovery) {
154         this.topologyDiscovery = topologyDiscovery;
155     }
156
157     public List<IPluginOutReadService> getStatisticsPublisher() {
158         return statisticsPublisher;
159     }
160
161     public void setStatisticsPublisher(final List<IPluginOutReadService> statisticsPublisher) {
162         this.statisticsPublisher = statisticsPublisher;
163     }
164
165     public List<IPluginOutInventoryService> getInventoryPublisher() {
166         return inventoryPublisher;
167     }
168
169     public void setInventoryPublisher(final List<IPluginOutInventoryService> inventoryPublisher) {
170         this.inventoryPublisher = inventoryPublisher;
171     }
172
173     public void startAdapter() {
174         inventoryNotificationProvider.setDataProviderService(getDataProviderService());
175         inventoryNotificationProvider.setInventoryPublisher(getInventoryPublisher());
176         // inventoryNotificationProvider.start();
177     }
178
179     public boolean setInventoryPublisher(final IPluginOutInventoryService listener) {
180         return getInventoryPublisher().add(listener);
181     }
182
183     public boolean unsetInventoryPublisher(final IPluginOutInventoryService listener) {
184         return getInventoryPublisher().remove(listener);
185     }
186
187     public boolean setReadPublisher(final IPluginOutReadService listener) {
188         return getStatisticsPublisher().add(listener);
189     }
190
191     public Boolean unsetReadPublisher(final IPluginOutReadService listener) {
192         if (listener != null) {
193             return getStatisticsPublisher().remove(listener);
194         }
195         return false;
196     }
197
198     protected DataModificationTransaction startChange() {
199         return getDataProviderService().beginTransaction();
200     }
201
202     @Override
203     public long getTransmitRate(final NodeConnector connector) {
204         final FlowCapableNodeConnector nodeConnector = this.readOperFlowCapableNodeConnector(NodeMapping.toNodeConnectorRef(connector));
205         return nodeConnector.getCurrentSpeed().longValue();
206     }
207
208     private FlowCapableNode readOperFlowCapableNode(final NodeRef ref) {
209         final org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node node =
210                 (org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node)getDataService().readOperationalData(ref.getValue());
211         if (node == null) {
212             return null;
213         }
214
215         return node.getAugmentation(FlowCapableNode.class);
216     }
217
218     private org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node readConfigNode(final Node node) {
219         final InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node> nodeRef =
220                 InstanceIdentifier.builder(Nodes.class)
221                 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node.class, InventoryMapping.toNodeKey(node))
222                 .build();
223
224         return (org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node) startChange().readConfigurationData(nodeRef);
225     }
226
227     private org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector readConfigNodeConnector(final NodeConnector connector) {
228         final InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector> nodeConnectorRef =
229                 InstanceIdentifier.builder(Nodes.class)
230                 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node.class, InventoryMapping.toNodeKey(connector.getNode()))
231                 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector.class, InventoryMapping.toNodeConnectorKey(connector))
232                 .toInstance();
233
234         return((org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector) startChange().readConfigurationData(nodeConnectorRef));
235     }
236
237     /**
238      * Read a table of a node from configuration data store.
239      *
240      * @param node Node id
241      * @param id Table id
242      * @return Table contents, or null if not present
243      */
244     private Table readConfigTable(final Node node, final short id) {
245         final InstanceIdentifier<Table> tableRef = InstanceIdentifier.builder(Nodes.class)
246                 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node.class, InventoryMapping.toNodeKey(node))
247                 .augmentation(FlowCapableNode.class)
248                 .child(Table.class, new TableKey(id))
249                 .build();
250
251         return (Table) startChange().readConfigurationData(tableRef);
252     }
253
254     @Override
255     public List<FlowOnNode> readAllFlow(final Node node, final boolean cached) {
256         final ArrayList<FlowOnNode> output = new ArrayList<>();
257         final Table table = readConfigTable(node, OPENFLOWV10_TABLE_ID);
258         if (table != null) {
259             final List<Flow> flows = table.getFlow();
260             LOG.trace("Number of flows installed in table 0 of node {} : {}", node, flows.size());
261
262             for (final Flow flow : flows) {
263                 final FlowStatisticsData statsFromDataStore = flow.getAugmentation(FlowStatisticsData.class);
264                 if (statsFromDataStore != null) {
265                     final FlowOnNode it = new FlowOnNode(ToSalConversionsUtils.toFlow(flow, node));
266                     output.add(addFlowStats(it, statsFromDataStore.getFlowStatistics()));
267                 }
268             }
269         }
270
271         // TODO (main): Shall we send request to the switch? It will make async request to the switch.
272         // Once the plugin receives a response, it will let the adaptor know through onFlowStatisticsUpdate()
273         // If we assume that md-sal statistics manager will always be running, then it is not required
274         // But if not, then sending request will collect the latest data for adaptor at least.
275         getFlowStatisticsService().getAllFlowsStatisticsFromAllFlowTables(
276                 new GetAllFlowsStatisticsFromAllFlowTablesInputBuilder().setNode(NodeMapping.toNodeRef(node)).build());
277         return output;
278     }
279
280     @Override
281     public List<NodeConnectorStatistics> readAllNodeConnector(final Node node, final boolean cached) {
282         final ArrayList<NodeConnectorStatistics> ret = new ArrayList<>();
283
284         final org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node dsNode = readConfigNode(node);
285         if (dsNode != null) {
286             for (final org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector dsNodeConnector : dsNode.getNodeConnector()) {
287                 final FlowCapableNodeConnectorStatistics stats = (dsNodeConnector.getAugmentation(FlowCapableNodeConnectorStatisticsData.class));
288                 if (stats != null) {
289                     try {
290                         ret.add(toNodeConnectorStatistics(stats.getFlowCapableNodeConnectorStatistics(), dsNode.getId(), dsNodeConnector.getId()));
291                     } catch (ConstructionException e) {
292                         LOG.warn("Failed to instantiate node connector statistics for node {} connector {}, ignoring it",
293                                 dsNode.getId(), dsNodeConnector.getId(), e);
294                     }
295                 }
296             }
297         }
298
299         //TODO: Refer TODO (main)
300         getNodeConnectorStatisticsService().getAllNodeConnectorsStatistics(
301                 new GetAllNodeConnectorsStatisticsInputBuilder().setNode(NodeMapping.toNodeRef(node)).build());
302         return ret;
303     }
304
305     @Override
306     public List<NodeTableStatistics> readAllNodeTable(final Node node, final boolean cached) {
307         final NodeRef nodeRef = NodeMapping.toNodeRef(node);
308
309         final ArrayList<NodeTableStatistics> ret = new ArrayList<>();
310         final FlowCapableNode dsFlowCapableNode = this.readOperFlowCapableNode(nodeRef);
311         if (dsFlowCapableNode != null) {
312             for (final Table table : dsFlowCapableNode.getTable()) {
313                 final FlowTableStatisticsData tableStats = table.getAugmentation(FlowTableStatisticsData.class);
314                 if (tableStats != null) {
315                     try {
316                         ret.add(toNodeTableStatistics(tableStats.getFlowTableStatistics(), table.getId(), node));
317                     } catch (ConstructionException e) {
318                         LOG.warn("Failed to instantiate table statistics for node {} table {}, ignoring it", node, table.getId(), e);
319                     }
320                 }
321             }
322         }
323
324         //TODO: Refer TODO (main)
325         getFlowTableStatisticsService().getFlowTablesStatistics(new GetFlowTablesStatisticsInputBuilder().setNode(nodeRef).build());
326         return ret;
327     }
328
329     @Override
330     public NodeDescription readDescription(final Node node, final boolean cached) {
331         return this.toNodeDescription(NodeMapping.toNodeRef(node));
332     }
333
334     @Override
335     public FlowOnNode readFlow(final Node node, final org.opendaylight.controller.sal.flowprogrammer.Flow targetFlow, final boolean cached) {
336         FlowOnNode ret = null;
337         final Table table = readConfigTable(node, OPENFLOWV10_TABLE_ID);
338         if (table != null) {
339             final List<Flow> flows = table.getFlow();
340             InventoryAndReadAdapter.LOG.trace("Number of flows installed in table 0 of node {} : {}", node, flows.size());
341
342             for (final Flow mdsalFlow : flows) {
343                 if(FromSalConversionsUtils.flowEquals(mdsalFlow, MDFlowMapping.toMDSalflow(targetFlow))) {
344                     final FlowStatisticsData statsFromDataStore = mdsalFlow.getAugmentation(FlowStatisticsData.class);
345                     if (statsFromDataStore != null) {
346                         InventoryAndReadAdapter.LOG.debug("Found matching flow in the data store flow table ");
347                         ret = addFlowStats(new FlowOnNode(targetFlow), statsFromDataStore.getFlowStatistics());
348
349                         // FIXME: break; ?
350                     }
351                 }
352             }
353         }
354
355         //TODO: Refer TODO (main)
356         final GetFlowStatisticsFromFlowTableInputBuilder input = new GetFlowStatisticsFromFlowTableInputBuilder().setNode(NodeMapping.toNodeRef(node));
357         input.fieldsFrom(MDFlowMapping.toMDSalflow(targetFlow));
358         getFlowStatisticsService().getFlowStatisticsFromFlowTable(input.build());
359         return ret;
360     }
361
362     @Override
363     public NodeConnectorStatistics readNodeConnector(final NodeConnector connector, final boolean cached) {
364         final NodeConnectorId ncId = InventoryMapping.toNodeConnectorKey(connector).getId();
365
366         NodeConnectorStatistics ret = null;
367         final org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector nodeConnectorFromDS = readConfigNodeConnector(connector);
368         if (nodeConnectorFromDS != null) {
369             final FlowCapableNodeConnectorStatistics stats = nodeConnectorFromDS.getAugmentation(FlowCapableNodeConnectorStatisticsData.class);
370             if (stats != null) {
371                 try {
372                     ret = toNodeConnectorStatistics(stats.getFlowCapableNodeConnectorStatistics(),
373                             InventoryMapping.toNodeKey(connector.getNode()).getId(), ncId);
374                 } catch (ConstructionException e) {
375                     LOG.warn("Failed to instantiate node connector statistics for connector {}, ignoring it",
376                             connector, e);
377                 }
378             }
379         }
380
381         getNodeConnectorStatisticsService().getNodeConnectorStatistics(
382                 new GetNodeConnectorStatisticsInputBuilder().setNode(NodeMapping.toNodeRef(connector.getNode())).setNodeConnectorId(ncId).build());
383         return ret;
384     }
385
386     @Override
387     public NodeTableStatistics readNodeTable(final NodeTable nodeTable, final boolean cached) {
388         NodeTableStatistics nodeStats = null;
389         final Table table = readConfigTable(nodeTable.getNode(), (short) nodeTable.getID());
390         if (table != null) {
391             final FlowTableStatisticsData tableStats = table.getAugmentation(FlowTableStatisticsData.class);
392             if (tableStats != null) {
393                 try {
394                     nodeStats = toNodeTableStatistics(tableStats.getFlowTableStatistics(), table.getId(), nodeTable.getNode());
395                 } catch (ConstructionException e) {
396                     LOG.warn("Failed to instantiate table statistics for node {} table {}, ignoring it",
397                             nodeTable.getNode(), table.getId(), e);
398                 }
399             }
400         }
401
402         //TODO: Refer TODO (main)
403         getFlowTableStatisticsService().getFlowTablesStatistics(
404                 new GetFlowTablesStatisticsInputBuilder().setNode(NodeMapping.toNodeRef(nodeTable.getNode())).build());
405         return nodeStats;
406     }
407
408     @Override
409     public void onNodeConnectorRemoved(final NodeConnectorRemoved update) {
410         // Never received
411     }
412
413     @Override
414     public void onNodeRemoved(final NodeRemoved notification) {
415         this.removeNodeConnectors(notification.getNodeRef().getValue());
416         try {
417             final Node aDNode = NodeMapping.toADNode(notification.getNodeRef());
418             this.publishNodeUpdate(aDNode, UpdateType.REMOVED, Collections.<Property>emptySet());
419         } catch (ConstructionException e) {
420             LOG.warn("Failed to construct node for {}, not propagating update", notification.getNodeRef(), e);
421         }
422     }
423
424     @Override
425     public void onNodeConnectorUpdated(final NodeConnectorUpdated update) {
426         final NodeConnectorRef ref = update.getNodeConnectorRef();
427         final UpdateType updateType;
428         if (!this.isKnownNodeConnector(ref.getValue())) {
429             this.recordNodeConnector(ref.getValue());
430             updateType = UpdateType.ADDED;
431         } else {
432             updateType = UpdateType.CHANGED;
433         }
434
435         try {
436             final NodeConnector nodeConnector;
437             nodeConnector = NodeMapping.toADNodeConnector(ref);
438             this.publishNodeConnectorUpdate(nodeConnector, updateType, NodeMapping.toADNodeConnectorProperties(update));
439         } catch (ConstructionException e) {
440             LOG.warn("Failed to construct node connector for {}, not reporting the update", ref, e);
441         }
442     }
443
444     @Override
445     public void onNodeUpdated(final NodeUpdated notification) {
446         final NodeRef ref = notification.getNodeRef();
447
448         final UpdateType updateType;
449         if (dataService.readOperationalData(ref.getValue()) == null) {
450             updateType = UpdateType.ADDED;
451         } else {
452             updateType = UpdateType.CHANGED;
453         }
454
455         final Node aDNode;
456         try {
457             aDNode = NodeMapping.toADNode(ref);
458         } catch (ConstructionException e) {
459             LOG.warn("Failed to construct node for {}, not reporting the update", ref, e);
460             return;
461         }
462
463         this.publishNodeUpdate(aDNode, updateType, NodeMapping.toADNodeProperties(notification));
464         for (final IPluginOutReadService statsPublisher : getStatisticsPublisher()) {
465             final NodeDescription description = this.toNodeDescription(ref);
466             if (description != null) {
467                 final InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node> nodeRef =
468                         InstanceIdentifier.builder(Nodes.class)
469                         .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node.class, new NodeKey(notification.getId()))
470                         .toInstance();
471                 try {
472                     statsPublisher.descriptionStatisticsUpdated(NodeMapping.toADNode(nodeRef), description);
473                 } catch (ConstructionException e) {
474                     LOG.warn("Failed to construct node for {}, not reporting the update to publisher {}", nodeRef, statsPublisher, e);
475                 }
476             }
477         }
478     }
479
480     @Override
481     public ConcurrentMap<Node,Map<String,Property>> getNodeProps() {
482         final ConcurrentHashMap<Node,Map<String,Property>> props = new ConcurrentHashMap<>();
483         final Nodes nodes = this.readOperAllMDNodes();
484         for (final org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node node : nodes.getNode()) {
485             final FlowCapableNode fcn = node.getAugmentation(FlowCapableNode.class);
486             if (fcn != null) {
487                 final ConcurrentHashMap<String,Property> perNodePropMap = new ConcurrentHashMap<String, Property>();
488                 final HashSet<Property> perNodeProps = NodeMapping.toADNodeProperties(fcn, node.getId());
489                 if (perNodeProps != null) {
490                     for (final Property perNodeProp : perNodeProps) {
491                         perNodePropMap.put(perNodeProp.getName(), perNodeProp);
492                     }
493                 }
494
495                 try {
496                     final Node adNode = NodeMapping.toADNode(node.getId());
497                     props.put(adNode, perNodePropMap);
498                 } catch (ConstructionException e) {
499                     LOG.warn("Failed to construct node for {}, skipping it", node, e);
500                 }
501             }
502         }
503         return props;
504     }
505
506     private Nodes readOperAllMDNodes() {
507         final TypeSafeDataReader reader = TypeSafeDataReader.forReader(getDataService());
508         return reader.readOperationalData(InstanceIdentifier.builder(Nodes.class).build());
509     }
510
511     @Override
512     public ConcurrentMap<NodeConnector,Map<String,Property>> getNodeConnectorProps(final Boolean refresh) {
513         final ConcurrentHashMap<NodeConnector,Map<String,Property>> props = new ConcurrentHashMap<>();
514         for (final org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node node : this.readOperAllMDNodes().getNode()) {
515             for (final org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector nc : node.getNodeConnector()) {
516                 final FlowCapableNodeConnector fcnc = nc.getAugmentation(FlowCapableNodeConnector.class);
517                 if (fcnc != null) {
518                     final ConcurrentHashMap<String,Property> ncpsm = new ConcurrentHashMap<>();
519                     final HashSet<Property> ncps = NodeMapping.toADNodeConnectorProperties(fcnc);
520                     if (ncps != null) {
521                         for (final Property p : ncps) {
522                             ncpsm.put(p.getName(), p);
523                         }
524                     }
525
526                     try {
527                         props.put(NodeMapping.toADNodeConnector(nc.getId(), node.getId()), ncpsm);
528                     } catch (ConstructionException e) {
529                         LOG.warn("Failed to instantiate node {} connector {}, not reporting it", node.getId(), nc.getId(), e);
530                     }
531                 }
532             }
533         }
534         return props;
535     }
536
537     private FlowCapableNodeConnector readOperFlowCapableNodeConnector(final NodeConnectorRef ref) {
538         final org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector nc =
539                 (org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector)
540                 getDataService().readOperationalData(ref.getValue());
541         return nc.getAugmentation(FlowCapableNodeConnector.class);
542     }
543
544     private static NodeConnectorStatistics toNodeConnectorStatistics(final org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.NodeConnectorStatistics nodeConnectorStatistics, final NodeId nodeId, final NodeConnectorId nodeConnectorId) throws ConstructionException {
545         final NodeConnectorStatistics it = new NodeConnectorStatistics();
546
547         final Packets packets = nodeConnectorStatistics.getPackets();
548         it.setReceivePacketCount(packets.getReceived().longValue());
549         it.setTransmitPacketCount(packets.getTransmitted().longValue());
550
551         final Bytes bytes = nodeConnectorStatistics.getBytes();
552         it.setReceiveByteCount(bytes.getReceived().longValue());
553         it.setTransmitByteCount(bytes.getTransmitted().longValue());
554
555         it.setReceiveDropCount(nodeConnectorStatistics.getReceiveDrops().longValue());
556         it.setTransmitDropCount(nodeConnectorStatistics.getTransmitDrops().longValue());
557         it.setReceiveErrorCount(nodeConnectorStatistics.getReceiveErrors().longValue());
558         it.setTransmitErrorCount(nodeConnectorStatistics.getTransmitErrors().longValue());
559         it.setReceiveFrameErrorCount(nodeConnectorStatistics.getReceiveFrameError().longValue());
560         it.setReceiveOverRunErrorCount(nodeConnectorStatistics.getReceiveOverRunError().longValue());
561         it.setReceiveCRCErrorCount(nodeConnectorStatistics.getReceiveCrcError().longValue());
562         it.setCollisionCount(nodeConnectorStatistics.getCollisionCount().longValue());
563
564         final InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector> nodeConnectorRef =
565                 InstanceIdentifier.builder(Nodes.class)
566                 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node.class, new NodeKey(nodeId))
567                 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector.class, new NodeConnectorKey(nodeConnectorId))
568                 .build();
569         it.setNodeConnector(NodeMapping.toADNodeConnector(new NodeConnectorRef(nodeConnectorRef)));
570         return it;
571     }
572
573     private static NodeTableStatistics toNodeTableStatistics(final FlowTableStatistics tableStats, final Short tableId, final Node node) throws ConstructionException {
574         final NodeTableStatistics it = new NodeTableStatistics();
575         it.setActiveCount(tableStats.getActiveFlows().getValue().intValue());
576         it.setLookupCount(tableStats.getPacketsLookedUp().getValue().longValue());
577         it.setMatchedCount(tableStats.getPacketsMatched().getValue().longValue());
578         it.setName(tableId.toString());
579         it.setNodeTable(new NodeTable(NodeTableIDType.OPENFLOW, tableId.byteValue(), node));
580         return it;
581     }
582
583     private NodeDescription toNodeDescription(final NodeRef nodeRef) {
584         final FlowCapableNode capableNode = this.readOperFlowCapableNode(nodeRef);
585         if (capableNode == null) {
586             return null;
587         }
588
589         final NodeDescription it = new NodeDescription();
590         it.setManufacturer(capableNode.getManufacturer());
591         it.setSerialNumber(capableNode.getSerialNumber());
592         it.setSoftware(capableNode.getSoftware());
593         it.setDescription(capableNode.getDescription());
594         return it;
595     }
596
597     public Edge toADEdge(final Link link) throws ConstructionException {
598         NodeConnectorRef _source = link.getSource();
599         NodeConnector _aDNodeConnector = NodeMapping.toADNodeConnector(_source);
600         NodeConnectorRef _destination = link.getDestination();
601         NodeConnector _aDNodeConnector_1 = NodeMapping.toADNodeConnector(_destination);
602         Edge _edge = new Edge(_aDNodeConnector, _aDNodeConnector_1);
603         return _edge;
604     }
605
606     /**
607      * OpendaylightFlowStatisticsListener interface implementation
608      */
609     @Override
610     public void onAggregateFlowStatisticsUpdate(final AggregateFlowStatisticsUpdate notification) {
611         // Ignoring this notification as there does not seem to be a way to bubble this up to AD-SAL
612     }
613
614     @Override
615     public void onFlowsStatisticsUpdate(final FlowsStatisticsUpdate notification) {
616         final ArrayList<FlowOnNode> adsalFlowsStatistics = new ArrayList<>();
617         final InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node> nodeRef =
618                 InstanceIdentifier.builder(Nodes.class)
619                 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node.class, new NodeKey(notification.getId()))
620                 .build();
621
622         final Node aDNode;
623         try {
624             aDNode = NodeMapping.toADNode(nodeRef);
625         } catch (ConstructionException e) {
626             LOG.warn("Failed to construct node for {}, ignoring it", notification.getId(), e);
627             return;
628         }
629
630         for (final FlowAndStatisticsMapList flowStats : notification.getFlowAndStatisticsMapList()) {
631             if (flowStats.getTableId() == 0) {
632                 adsalFlowsStatistics.add(InventoryAndReadAdapter.toFlowOnNode(flowStats, aDNode));
633             }
634         }
635         for (final IPluginOutReadService statsPublisher : getStatisticsPublisher()) {
636             statsPublisher.nodeFlowStatisticsUpdated(aDNode, adsalFlowsStatistics);
637         }
638     }
639
640     /**
641      * OpendaylightFlowTableStatisticsListener interface implementation
642      */
643     @Override
644     public void onFlowTableStatisticsUpdate(final FlowTableStatisticsUpdate notification) {
645         ArrayList<NodeTableStatistics> adsalFlowTableStatistics = new ArrayList<>();
646         for (final FlowTableAndStatisticsMap stats : notification.getFlowTableAndStatisticsMap()) {
647             if (stats.getTableId().getValue() == 0) {
648                 final NodeTableStatistics it = new NodeTableStatistics();
649                 it.setActiveCount(stats.getActiveFlows().getValue().intValue());
650                 it.setLookupCount(stats.getPacketsLookedUp().getValue().longValue());
651                 it.setMatchedCount(stats.getPacketsMatched().getValue().longValue());
652                 adsalFlowTableStatistics.add(it);
653             }
654         }
655
656         final InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node> nodeRef =
657                 InstanceIdentifier.builder(Nodes.class)
658                 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node.class, new NodeKey(notification.getId()))
659                 .build();
660
661         final Node aDNode;
662         try {
663             aDNode = NodeMapping.toADNode(nodeRef);
664         } catch (ConstructionException e) {
665             LOG.warn("Failed to construct node for {}, ignoring it", notification.getId(), e);
666             return;
667         }
668
669         for (final IPluginOutReadService statsPublisher : getStatisticsPublisher()) {
670             statsPublisher.nodeTableStatisticsUpdated(aDNode, adsalFlowTableStatistics);
671         }
672     }
673
674     /**
675      * OpendaylightPortStatisticsUpdate interface implementation
676      */
677     @Override
678     public void onNodeConnectorStatisticsUpdate(final NodeConnectorStatisticsUpdate notification) {
679         final ArrayList<NodeConnectorStatistics> adsalPortStatistics = new ArrayList<NodeConnectorStatistics>();
680         for (final NodeConnectorStatisticsAndPortNumberMap nodeConnectorStatistics : notification.getNodeConnectorStatisticsAndPortNumberMap()) {
681             try {
682                 adsalPortStatistics.add(toNodeConnectorStatistics(
683                         nodeConnectorStatistics, notification.getId(), nodeConnectorStatistics.getNodeConnectorId()));
684             } catch (ConstructionException e) {
685                 LOG.warn("Failed to create statistics for node {} connector {}, not updating them",
686                         notification.getId(), nodeConnectorStatistics.getNodeConnectorId(), e);
687             }
688         }
689
690         final InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node> nodeRef =
691                 InstanceIdentifier.builder(Nodes.class)
692                 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node.class, new NodeKey(notification.getId()))
693                 .build();
694
695         final Node aDNode;
696         try {
697             aDNode = NodeMapping.toADNode(nodeRef);
698         } catch (ConstructionException e) {
699             LOG.warn("Failed to construct node for {}, ignoring it", notification.getId(), e);
700             return;
701         }
702
703         for (final IPluginOutReadService statsPublisher : getStatisticsPublisher()) {
704             statsPublisher.nodeConnectorStatisticsUpdated(aDNode, adsalPortStatistics);
705         }
706     }
707
708     private static FlowOnNode toFlowOnNode(final FlowAndStatisticsMapList flowAndStatsMap, final Node node) {
709         final FlowOnNode it = new FlowOnNode(ToSalConversionsUtils.toFlow(flowAndStatsMap, node));
710         return addFlowStats(it, flowAndStatsMap);
711     }
712
713     private static FlowOnNode addFlowStats(final FlowOnNode node, final GenericStatistics stats) {
714         node.setByteCount(stats.getByteCount().getValue().longValue());
715         node.setPacketCount(stats.getPacketCount().getValue().longValue());
716         node.setDurationSeconds(stats.getDuration().getSecond().getValue().intValue());
717         node.setDurationNanoseconds(stats.getDuration().getNanosecond().getValue().intValue());
718         return node;
719     }
720
721     @Override
722     public Set<Node> getConfiguredNotConnectedNodes() {
723         return Collections.emptySet();
724     }
725
726     private void publishNodeUpdate(final Node node, final UpdateType updateType, final Set<Property> properties) {
727         for (final IPluginOutInventoryService publisher : getInventoryPublisher()) {
728             publisher.updateNode(node, updateType, properties);
729         }
730     }
731
732     private void publishNodeConnectorUpdate(final NodeConnector nodeConnector, final UpdateType updateType, final Set<Property> properties) {
733         for (final IPluginOutInventoryService publisher : getInventoryPublisher()) {
734             publisher.updateNodeConnector(nodeConnector, updateType, properties);
735         }
736     }
737
738     private boolean isKnownNodeConnector(final InstanceIdentifier<? extends Object> nodeConnectorIdentifier) {
739         final Iterator<PathArgument> it = nodeConnectorIdentifier.getPathArguments().iterator();
740
741         if (!it.hasNext()) {
742             return false;
743         }
744         it.next();
745
746         if (!it.hasNext()) {
747             return false;
748         }
749         final PathArgument nodePath = it.next();
750
751         if (!it.hasNext()) {
752             return false;
753         }
754         final PathArgument nodeConnectorPath = it.next();
755
756         final List<PathArgument> nodeConnectors = nodeToNodeConnectorsMap.get(nodePath);
757         return nodeConnectors == null ? false :
758             nodeConnectors.contains(nodeConnectorPath);
759     }
760
761     private boolean recordNodeConnector(final InstanceIdentifier<? extends Object> nodeConnectorIdentifier) {
762         final Iterator<PathArgument> it = nodeConnectorIdentifier.getPathArguments().iterator();
763
764         if (!it.hasNext()) {
765             return false;
766         }
767         it.next();
768
769         if (!it.hasNext()) {
770             return false;
771         }
772         final PathArgument nodePath = it.next();
773
774         if (!it.hasNext()) {
775             return false;
776         }
777         final PathArgument nodeConnectorPath = it.next();
778
779         synchronized (this) {
780             List<PathArgument> nodeConnectors = this.nodeToNodeConnectorsMap.get(nodePath);
781             if (nodeConnectors == null) {
782                 nodeConnectors = new ArrayList<>();
783                 this.nodeToNodeConnectorsMap.put(nodePath, nodeConnectors);
784             }
785
786             return nodeConnectors.add(nodeConnectorPath);
787         }
788     }
789
790     private List<PathArgument> removeNodeConnectors(final InstanceIdentifier<? extends Object> nodeIdentifier) {
791         return this.nodeToNodeConnectorsMap.remove(Iterables.get(nodeIdentifier.getPathArguments(), 1));
792     }
793 }