3308797b9808d728a8d401366b1928ab4af0a62f
[nemo.git] / nemo-impl / src / main / java / org / opendaylight / nemo / intent / computation / PNResourcesTracker.java
1 /*\r
2  * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved.\r
3  *\r
4  * This program and the accompanying materials are made available under the\r
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
6  * and is available at http://www.eclipse.org/legal/epl-v10.html\r
7  */\r
8 \r
9 package org.opendaylight.nemo.intent.computation;\r
10 \r
11 import org.opendaylight.controller.md.sal.binding.api.DataBroker;\r
12 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;\r
13 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;\r
14 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;\r
15 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;\r
16 import org.opendaylight.nemo.intent.IntentResolver;\r
17 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.PhysicalNetwork;\r
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.PhysicalLinks;\r
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.PhysicalNodes;\r
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.physical.links.PhysicalLink;\r
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.physical.nodes.PhysicalNode;\r
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.physical.paths.PhysicalPath;\r
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.node.instance.PhysicalPort;\r
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.UserId;\r
25 import org.opendaylight.yangtools.concepts.ListenerRegistration;\r
26 import org.opendaylight.yangtools.yang.binding.DataObject;\r
27 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;\r
28 import org.slf4j.Logger;\r
29 import org.slf4j.LoggerFactory;\r
30 \r
31 import java.util.*;\r
32 import java.util.concurrent.ConcurrentHashMap;\r
33 import java.util.concurrent.CopyOnWriteArraySet;\r
34 \r
35 /**\r
36  * The virtual network mapping unit implements the following functions:\r
37  * (1) Automatically perform the virtual network mapping when the user's\r
38  * virtual network changed, which is subscribed from the data store.\r
39  * (2) Automatically perform the remapping for the virtual networks that\r
40  * are influenced by the changes of the underlying physical network\r
41  * which are also subscribed from the data store.\r
42  *\r
43  * @author Zhigang Ji\r
44  */\r
45 public class PNResourcesTracker {\r
46     private static final Logger log = LoggerFactory.getLogger(PNResourcesTracker.class);\r
47 \r
48     private final ConcurrentHashMap<UserId, CopyOnWriteArraySet<String>/*physical resources*/> physicalResourceMap;\r
49 \r
50     private final DataBroker dataBroker;\r
51     private final IntentResolver intentResolver;\r
52 \r
53     /**\r
54      * The registration for the physical node change listener.\r
55      */\r
56     private ListenerRegistration<DataChangeListener> physicalNodeChangeListenerReg;\r
57 \r
58     /**\r
59      * The registration for the physical link change listener.\r
60      */\r
61     private ListenerRegistration<DataChangeListener> physicalLinkChangeListenerReg;\r
62 \r
63     public PNResourcesTracker(DataBroker dataBroker, IntentResolver intentResolver) {\r
64         super();\r
65 \r
66         this.dataBroker = dataBroker;\r
67         this.intentResolver = intentResolver;\r
68         physicalResourceMap = new ConcurrentHashMap<UserId, CopyOnWriteArraySet<String>>();\r
69 \r
70         InstanceIdentifier<PhysicalNode> nodeInstanceIdentifier = InstanceIdentifier\r
71                 .builder(PhysicalNetwork.class)\r
72                 .child(PhysicalNodes.class)\r
73                 .child(PhysicalNode.class)\r
74                 .build();\r
75         InstanceIdentifier<PhysicalLink> linkInstanceIdentifier = InstanceIdentifier\r
76                 .builder(PhysicalNetwork.class)\r
77                 .child(PhysicalLinks.class)\r
78                 .child(PhysicalLink.class)\r
79                 .build();\r
80 \r
81         physicalNodeChangeListenerReg = dataBroker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,\r
82                 nodeInstanceIdentifier, new PhysicalNodeChangeListener(), DataChangeScope.BASE);\r
83         physicalLinkChangeListenerReg = dataBroker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,\r
84                 linkInstanceIdentifier, new PhysicalLinkChangeListener(), DataChangeScope.BASE);\r
85 \r
86         return;\r
87     }\r
88     public void close(){\r
89         if(physicalLinkChangeListenerReg!=null){\r
90             physicalLinkChangeListenerReg.close();\r
91         }\r
92         if(physicalNodeChangeListenerReg!=null){\r
93             physicalNodeChangeListenerReg.close();\r
94         }\r
95         physicalResourceMap.clear();\r
96     }\r
97     protected synchronized void resetResource(UserId userId) {\r
98         physicalResourceMap.remove(userId);\r
99     }\r
100 \r
101     protected void addPhysicalNode(UserId userId, PhysicalNode physicalNode) {\r
102         addPhysicalResource(userId, physicalNode.getKey().toString());\r
103     }\r
104 \r
105     protected void addPhysicalPort(UserId userId, PhysicalPort physicalPort) {\r
106         addPhysicalResource(userId, physicalPort.getKey().toString());\r
107     }\r
108 \r
109     protected void addPhysicalPath(UserId userId, PhysicalPath physicalPath) {\r
110         List<org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.path.instance.PhysicalLink>\r
111                 physicalLinkList = physicalPath.getPhysicalLink();\r
112         for (org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.path.instance.PhysicalLink physicalLink :\r
113                 physicalLinkList) {\r
114             addPhysicalResource(userId, physicalLink.getKey().toString());\r
115         }\r
116     }\r
117 \r
118     private synchronized void addPhysicalResource(UserId userId, String resourceId) {\r
119         if (!physicalResourceMap.containsKey(userId)) {\r
120             physicalResourceMap.put(userId, new CopyOnWriteArraySet<String>());\r
121         }\r
122         physicalResourceMap.get(userId).add(resourceId);\r
123     }\r
124 \r
125     private synchronized void physicalResourceDown(String resourceId) {\r
126         Map<UserId, CopyOnWriteArraySet<String>> tmpMap = new HashMap<UserId, CopyOnWriteArraySet<String>>(physicalResourceMap);\r
127         for (UserId userId : tmpMap.keySet()) {\r
128             Set<String> physicalResources = tmpMap.get(userId);\r
129             if (physicalResources.contains(resourceId)) {\r
130                 physicalResourceMap.remove(userId);\r
131                 try {\r
132                     intentResolver.resolveIntent(userId);\r
133                 } catch (Exception e) {\r
134                     e.printStackTrace();\r
135                 }\r
136             }\r
137         }\r
138     }\r
139 \r
140     /**\r
141      * A listener to ch ange events related to physical nodes being\r
142      * added, removed or updated.\r
143      *\r
144      * @author Zhigang Ji\r
145      */\r
146     private class PhysicalNodeChangeListener implements DataChangeListener {\r
147         @Override\r
148         public void onDataChanged(AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {\r
149             if (null == change) {\r
150                 return;\r
151             }\r
152 \r
153             Map<InstanceIdentifier<?>, DataObject> originalData = change.getOriginalData();\r
154             Map<InstanceIdentifier<?>, DataObject> updatedData = change.getUpdatedData();\r
155 \r
156             if (null != updatedData && !updatedData.isEmpty()) {\r
157                 for (InstanceIdentifier<?> identifier : updatedData.keySet()) {\r
158                     DataObject originData = originalData.get(identifier);\r
159                     DataObject currentData = updatedData.get(identifier);\r
160                     if (originData != null && originData instanceof PhysicalNode) {\r
161                         handleNodeUpdate((PhysicalNode) originData, (PhysicalNode) currentData);\r
162                     }\r
163                 }\r
164             }\r
165 \r
166             Set<InstanceIdentifier<?>> removedPaths = change.getRemovedPaths();\r
167 \r
168             if (null != removedPaths && !removedPaths.isEmpty()) {\r
169                 DataObject dataObject;\r
170                 for (InstanceIdentifier<?> instanceId : removedPaths) {\r
171                     dataObject = originalData.get(instanceId);\r
172                     if (dataObject != null && dataObject instanceof PhysicalNode) {\r
173                         String resourceId = ((PhysicalNode) dataObject).getKey().toString();\r
174                         log.debug("Physical node {} removed.", resourceId);\r
175                         physicalResourceDown(resourceId);\r
176                     }\r
177 \r
178                 }\r
179             }\r
180         }\r
181 \r
182         private void handleNodeUpdate(PhysicalNode originNode, PhysicalNode currentNode) {\r
183             log.debug("Handle node {} update.", originNode.getNodeId().getValue());\r
184             List<PhysicalPort> originPorts = originNode.getPhysicalPort();\r
185             List<PhysicalPort> currentPorts = currentNode.getPhysicalPort() == null ? new ArrayList<PhysicalPort>() : currentNode.getPhysicalPort();\r
186             if (originPorts != null)\r
187                 for (PhysicalPort physicalPort : originPorts) {\r
188                     if (!currentPorts.contains(physicalPort)) {\r
189                         log.debug("Physical port {} removed.", physicalPort.getPortId().getValue());\r
190                         physicalResourceDown(physicalPort.getKey().toString());\r
191                     }\r
192                 }\r
193         }\r
194     }\r
195 \r
196     /**\r
197      * A listener to change events related to physical links being\r
198      * added, removed or updated.\r
199      *\r
200      * @author Zhigang Ji\r
201      */\r
202     private class PhysicalLinkChangeListener implements DataChangeListener {\r
203         @Override\r
204         public void onDataChanged(AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {\r
205             if (null == change) {\r
206                 return;\r
207             }\r
208 \r
209             Map<InstanceIdentifier<?>, DataObject> originalData = change.getOriginalData();\r
210             Map<InstanceIdentifier<?>, DataObject> updatedData = change.getUpdatedData();\r
211 \r
212             if (null != updatedData && !updatedData.isEmpty()) {\r
213                 for (InstanceIdentifier<?> identifier : updatedData.keySet()) {\r
214                     DataObject originData = originalData.get(identifier);\r
215                     DataObject currentDate = updatedData.get(identifier);\r
216                     if (originData != null && originData instanceof PhysicalLink) {\r
217                         handleLinkUpdate((PhysicalLink) originalData, (PhysicalLink) currentDate);\r
218                     }\r
219                 }\r
220             }\r
221 \r
222             Set<InstanceIdentifier<?>> removedPaths = change.getRemovedPaths();\r
223 \r
224             if (null != removedPaths && !removedPaths.isEmpty()) {\r
225                 DataObject dataObject;\r
226 \r
227                 for (InstanceIdentifier<?> instanceId : removedPaths) {\r
228                     dataObject = originalData.get(instanceId);\r
229                     if (dataObject != null && dataObject instanceof PhysicalLink) {\r
230                         String resourceId = ((PhysicalLink) dataObject).getKey().toString();\r
231                         log.debug("Physical link {} removed.", resourceId);\r
232                         physicalResourceDown(resourceId);\r
233                     }\r
234                 }\r
235             }\r
236         }\r
237 \r
238         private void handleLinkUpdate(PhysicalLink originLink, PhysicalLink currentLink) {\r
239             log.debug("Handle physical link {} update.", originLink.getLinkId().getValue());\r
240             //TODO\r
241         }\r
242     }\r
243 \r
244 \r
245 }\r