Bug 5077: Codes break the security rules
[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                     log.info("Physical network changed and affected the virtual network of " +\r
133                             "user {}, start remapping.", userId.getValue());\r
134 \r
135                     intentResolver.resolveIntent(userId);\r
136                 } catch (Exception e) {\r
137                     // TODO Auto-generated catch block\r
138                     log.error("Exception:",e);\r
139                 }\r
140             }\r
141         }\r
142     }\r
143 \r
144     /**\r
145      * A listener to ch ange events related to physical nodes being\r
146      * added, removed or updated.\r
147      *\r
148      * @author Zhigang Ji\r
149      */\r
150     private class PhysicalNodeChangeListener implements DataChangeListener {\r
151         @Override\r
152         public void onDataChanged(AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {\r
153             if (null == change) {\r
154                 return;\r
155             }\r
156 \r
157             Map<InstanceIdentifier<?>, DataObject> originalData = change.getOriginalData();\r
158             Map<InstanceIdentifier<?>, DataObject> updatedData = change.getUpdatedData();\r
159 \r
160             if (null != updatedData && !updatedData.isEmpty()) {\r
161                 for (InstanceIdentifier<?> identifier : updatedData.keySet()) {\r
162                     DataObject originData = originalData.get(identifier);\r
163                     DataObject currentData = updatedData.get(identifier);\r
164                     if (originData != null && originData instanceof PhysicalNode) {\r
165                         handleNodeUpdate((PhysicalNode) originData, (PhysicalNode) currentData);\r
166                     }\r
167                 }\r
168             }\r
169 \r
170             Set<InstanceIdentifier<?>> removedPaths = change.getRemovedPaths();\r
171 \r
172             if (null != removedPaths && !removedPaths.isEmpty()) {\r
173                 DataObject dataObject;\r
174                 for (InstanceIdentifier<?> instanceId : removedPaths) {\r
175                     dataObject = originalData.get(instanceId);\r
176                     if (dataObject != null && dataObject instanceof PhysicalNode) {\r
177                         String resourceId = ((PhysicalNode) dataObject).getKey().toString();\r
178                         log.debug("Physical node {} removed.", resourceId);\r
179                         physicalResourceDown(resourceId);\r
180                     }\r
181 \r
182                 }\r
183             }\r
184         }\r
185 \r
186         private void handleNodeUpdate(PhysicalNode originNode, PhysicalNode currentNode) {\r
187             log.debug("Handle node {} update.", originNode.getNodeId().getValue());\r
188             List<PhysicalPort> originPorts = originNode.getPhysicalPort();\r
189             List<PhysicalPort> currentPorts = currentNode.getPhysicalPort() == null ? new ArrayList<PhysicalPort>() : currentNode.getPhysicalPort();\r
190             if (originPorts != null)\r
191                 for (PhysicalPort physicalPort : originPorts) {\r
192                     if (!currentPorts.contains(physicalPort)) {\r
193                         log.debug("Physical port {} removed.", physicalPort.getPortId().getValue());\r
194                         physicalResourceDown(physicalPort.getKey().toString());\r
195                     }\r
196                 }\r
197         }\r
198     }\r
199 \r
200     /**\r
201      * A listener to change events related to physical links being\r
202      * added, removed or updated.\r
203      *\r
204      * @author Zhigang Ji\r
205      */\r
206     private class PhysicalLinkChangeListener implements DataChangeListener {\r
207         @Override\r
208         public void onDataChanged(AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {\r
209             if (null == change) {\r
210                 return;\r
211             }\r
212 \r
213             Map<InstanceIdentifier<?>, DataObject> originalData = change.getOriginalData();\r
214             Map<InstanceIdentifier<?>, DataObject> updatedData = change.getUpdatedData();\r
215 \r
216             if (null != updatedData && !updatedData.isEmpty()) {\r
217                 for (InstanceIdentifier<?> identifier : updatedData.keySet()) {\r
218                     DataObject originData = originalData.get(identifier);\r
219                     DataObject currentDate = updatedData.get(identifier);\r
220                     if (originData != null && originData instanceof PhysicalLink) {\r
221                         handleLinkUpdate((PhysicalLink) originalData, (PhysicalLink) currentDate);\r
222                     }\r
223                 }\r
224             }\r
225 \r
226             Set<InstanceIdentifier<?>> removedPaths = change.getRemovedPaths();\r
227 \r
228             if (null != removedPaths && !removedPaths.isEmpty()) {\r
229                 DataObject dataObject;\r
230 \r
231                 for (InstanceIdentifier<?> instanceId : removedPaths) {\r
232                     dataObject = originalData.get(instanceId);\r
233                     if (dataObject != null && dataObject instanceof PhysicalLink) {\r
234                         String resourceId = ((PhysicalLink) dataObject).getKey().toString();\r
235                         log.debug("Physical link {} removed.", resourceId);\r
236                         physicalResourceDown(resourceId);\r
237                     }\r
238                 }\r
239             }\r
240         }\r
241 \r
242         private void handleLinkUpdate(PhysicalLink originLink, PhysicalLink currentLink) {\r
243             log.debug("Handle physical link {} update.", originLink.getLinkId().getValue());\r
244             //TODO\r
245         }\r
246     }\r
247 \r
248 \r
249 }\r