Add blueprint wiring for address tracker
[l2switch.git] / arphandler / src / main / java / org / opendaylight / l2switch / arphandler / inventory / InventoryReader.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.l2switch.arphandler.inventory;
9
10 import com.google.common.base.Optional;
11 import java.util.ArrayList;
12 import java.util.HashMap;
13 import java.util.List;
14 import java.util.concurrent.ExecutionException;
15 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
16 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
17 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
18 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.address.tracker.rev140617.AddressCapableNodeConnector;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.address.tracker.rev140617.address.node.connector.Addresses;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2switch.loopremover.rev140714.StpStatus;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2switch.loopremover.rev140714.StpStatusAwareNodeConnector;
30 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
33
34 /**
35  * InventoryReader reads the opendaylight-inventory tree in MD-SAL data store.
36  */
37 public class InventoryReader {
38
39     private static final Logger LOG = LoggerFactory.getLogger(InventoryReader.class);
40     private DataBroker dataService;
41     // Key: SwitchId, Value: NodeConnectorRef that corresponds to NC between
42     // controller & switch
43     private HashMap<String, NodeConnectorRef> controllerSwitchConnectors;
44     // Key: SwitchId, Value: List of node connectors on this switch
45     private HashMap<String, List<NodeConnectorRef>> switchNodeConnectors;
46
47     public void setRefreshData(boolean refreshData) {
48         this.refreshData = refreshData;
49     }
50
51     private boolean refreshData = false;
52
53     /**
54      * Construct an InventoryService object with the specified inputs.
55      *
56      * @param dataService
57      *            The DataBrokerService associated with the InventoryService.
58      */
59     public InventoryReader(DataBroker dataService) {
60         this.dataService = dataService;
61         controllerSwitchConnectors = new HashMap<String, NodeConnectorRef>();
62         switchNodeConnectors = new HashMap<String, List<NodeConnectorRef>>();
63     }
64
65     public HashMap<String, NodeConnectorRef> getControllerSwitchConnectors() {
66         return controllerSwitchConnectors;
67     }
68
69     public HashMap<String, List<NodeConnectorRef>> getSwitchNodeConnectors() {
70         return switchNodeConnectors;
71     }
72
73     /**
74      * Read the Inventory data tree to find information about the Nodes and
75      * NodeConnectors. Create the list of NodeConnectors for a given switch.
76      * Also determine the STP status of each NodeConnector.
77      */
78     public void readInventory() {
79         // Only run once for now
80         if (!refreshData) {
81             return;
82         }
83         synchronized (this) {
84             if (!refreshData)
85                 return;
86             // Read Inventory
87             InstanceIdentifier.InstanceIdentifierBuilder<Nodes> nodesInsIdBuilder = InstanceIdentifier
88                     .<Nodes>builder(Nodes.class);
89             Nodes nodes = null;
90             ReadOnlyTransaction readOnlyTransaction = dataService.newReadOnlyTransaction();
91
92             try {
93                 Optional<Nodes> dataObjectOptional = null;
94                 dataObjectOptional = readOnlyTransaction
95                         .read(LogicalDatastoreType.OPERATIONAL, nodesInsIdBuilder.build()).get();
96                 if (dataObjectOptional.isPresent())
97                     nodes = (Nodes) dataObjectOptional.get();
98             } catch (InterruptedException e) {
99                 LOG.error("Failed to read nodes from Operation data store.");
100                 readOnlyTransaction.close();
101                 throw new RuntimeException("Failed to read nodes from Operation data store.", e);
102             } catch (ExecutionException e) {
103                 LOG.error("Failed to read nodes from Operation data store.");
104                 readOnlyTransaction.close();
105                 throw new RuntimeException("Failed to read nodes from Operation data store.", e);
106             }
107
108             if (nodes != null) {
109                 // Get NodeConnectors for each node
110                 for (Node node : nodes.getNode()) {
111                     ArrayList<NodeConnectorRef> nodeConnectorRefs = new ArrayList<NodeConnectorRef>();
112                     List<NodeConnector> nodeConnectors = node.getNodeConnector();
113                     if (nodeConnectors != null) {
114                         for (NodeConnector nodeConnector : nodeConnectors) {
115                             // Read STP status for this NodeConnector
116                             StpStatusAwareNodeConnector saNodeConnector = nodeConnector
117                                     .getAugmentation(StpStatusAwareNodeConnector.class);
118                             if (saNodeConnector != null && StpStatus.Discarding.equals(saNodeConnector.getStatus())) {
119                                 continue;
120                             }
121                             if (nodeConnector.getKey().toString().contains("LOCAL")) {
122                                 continue;
123                             }
124                             NodeConnectorRef ncRef = new NodeConnectorRef(InstanceIdentifier.<Nodes>builder(Nodes.class)
125                                     .<Node, NodeKey>child(Node.class, node.getKey())
126                                     .<NodeConnector, NodeConnectorKey>child(NodeConnector.class, nodeConnector.getKey())
127                                     .build());
128                             nodeConnectorRefs.add(ncRef);
129                         }
130                     }
131
132                     switchNodeConnectors.put(node.getId().getValue(), nodeConnectorRefs);
133                     NodeConnectorRef ncRef = new NodeConnectorRef(InstanceIdentifier.<Nodes>builder(Nodes.class)
134                             .<Node, NodeKey>child(Node.class, node.getKey())
135                             .<NodeConnector, NodeConnectorKey>child(NodeConnector.class,
136                                     new NodeConnectorKey(new NodeConnectorId(node.getId().getValue() + ":LOCAL")))
137                             .build());
138                     LOG.debug("Local port for node {} is {}", node.getKey(), ncRef);
139                     controllerSwitchConnectors.put(node.getId().getValue(), ncRef);
140                 }
141             }
142             readOnlyTransaction.close();
143             refreshData = false;
144         }
145     }
146
147     /**
148      * Get the NodeConnector on the specified node with the specified MacAddress
149      * observation.
150      *
151      * @param nodeInsId
152      *            InstanceIdentifier for the node on which to search for.
153      * @param macAddress
154      *            MacAddress to be searched for.
155      * @return NodeConnectorRef that pertains to the NodeConnector containing
156      *         the MacAddress observation.
157      */
158     public NodeConnectorRef getNodeConnector(InstanceIdentifier<Node> nodeInsId, MacAddress macAddress) {
159         if (nodeInsId == null || macAddress == null) {
160             return null;
161         }
162
163         NodeConnectorRef destNodeConnector = null;
164         long latest = -1;
165         ReadOnlyTransaction readOnlyTransaction = dataService.newReadOnlyTransaction();
166         try {
167             Optional<Node> dataObjectOptional = null;
168             dataObjectOptional = readOnlyTransaction.read(LogicalDatastoreType.OPERATIONAL, nodeInsId).get();
169             if (dataObjectOptional.isPresent()) {
170                 Node node = (Node) dataObjectOptional.get();
171                 LOG.debug("Looking address{} in node : {}", macAddress, nodeInsId);
172                 if (node.getNodeConnector() != null) {
173                     for (NodeConnector nc : node.getNodeConnector()) {
174                         // Don't look for mac in discarding node connectors
175                         StpStatusAwareNodeConnector saNodeConnector = nc
176                                 .getAugmentation(StpStatusAwareNodeConnector.class);
177                         if (saNodeConnector != null && StpStatus.Discarding.equals(saNodeConnector.getStatus())) {
178                             continue;
179                         }
180                         LOG.debug("Looking address{} in nodeconnector : {}", macAddress, nc.getKey());
181                         AddressCapableNodeConnector acnc = nc.getAugmentation(AddressCapableNodeConnector.class);
182                         if (acnc != null) {
183                             List<Addresses> addressesList = acnc.getAddresses();
184                             for (Addresses add : addressesList) {
185                                 if (macAddress.equals(add.getMac())) {
186                                     if (add.getLastSeen() > latest) {
187                                         destNodeConnector = new NodeConnectorRef(
188                                                 nodeInsId.child(NodeConnector.class, nc.getKey()));
189                                         latest = add.getLastSeen();
190                                         LOG.debug("Found address{} in nodeconnector : {}", macAddress, nc.getKey());
191                                         break;
192                                     }
193                                 }
194                             }
195                         }
196                     }
197                 } else {
198                     LOG.debug("Node connectors data is not present for node {}", node.getId());
199                 }
200             }
201         } catch (InterruptedException e) {
202             LOG.error("Failed to read nodes from Operation data store.");
203             readOnlyTransaction.close();
204             throw new RuntimeException("Failed to read nodes from Operation data store.", e);
205         } catch (ExecutionException e) {
206             LOG.error("Failed to read nodes from Operation data store.");
207             readOnlyTransaction.close();
208             throw new RuntimeException("Failed to read nodes from Operation data store.", e);
209         }
210         readOnlyTransaction.close();
211         return destNodeConnector;
212     }
213
214 }