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