Add INFO.yaml for nemo
[nemo.git] / nemo-impl / src / main / java / org / opendaylight / nemo / intent / computation / PNResourcesTracker.java
1 /*
2  * Copyright (c) 2015 Huawei, 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
9 package org.opendaylight.nemo.intent.computation;
10
11 import java.util.ArrayList;
12 import java.util.Collection;
13 import java.util.HashMap;
14 import java.util.List;
15 import java.util.Map;
16 import java.util.Set;
17 import java.util.concurrent.ConcurrentHashMap;
18 import java.util.concurrent.CopyOnWriteArraySet;
19 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
20 import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
21 import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
22 import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
23 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
24 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
25 import org.opendaylight.nemo.intent.IntentResolver;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.PhysicalNetwork;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.PhysicalLinks;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.PhysicalNodes;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.physical.links.PhysicalLink;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.physical.nodes.PhysicalNode;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.physical.paths.PhysicalPath;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.node.instance.PhysicalPort;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.UserId;
34 import org.opendaylight.yangtools.concepts.ListenerRegistration;
35 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
38
39 /**
40  * The virtual network mapping unit implements the following functions:
41  * (1) Automatically perform the virtual network mapping when the user's
42  * virtual network changed, which is subscribed from the data store.
43  * (2) Automatically perform the remapping for the virtual networks that
44  * are influenced by the changes of the underlying physical network
45  * which are also subscribed from the data store.
46  *
47  * @author Zhigang Ji
48  */
49 public class PNResourcesTracker {
50     private static final Logger log = LoggerFactory.getLogger(PNResourcesTracker.class);
51
52     private final ConcurrentHashMap<UserId, CopyOnWriteArraySet<String>/*physical resources*/> physicalResourceMap;
53
54     private final DataBroker dataBroker;
55     private final IntentResolver intentResolver;
56
57     /**
58      * The registration for the physical node change listener.
59      */
60     private ListenerRegistration<?> physicalNodeChangeListenerReg;
61
62     /**
63      * The registration for the physical link change listener.
64      */
65     private ListenerRegistration<?> physicalLinkChangeListenerReg;
66
67     public PNResourcesTracker(DataBroker dataBroker, IntentResolver intentResolver) {
68         super();
69
70         this.dataBroker = dataBroker;
71         this.intentResolver = intentResolver;
72         physicalResourceMap = new ConcurrentHashMap<>();
73
74         InstanceIdentifier<PhysicalNode> nodeInstanceIdentifier = InstanceIdentifier
75                 .builder(PhysicalNetwork.class)
76                 .child(PhysicalNodes.class)
77                 .child(PhysicalNode.class)
78                 .build();
79         InstanceIdentifier<PhysicalLink> linkInstanceIdentifier = InstanceIdentifier
80                 .builder(PhysicalNetwork.class)
81                 .child(PhysicalLinks.class)
82                 .child(PhysicalLink.class)
83                 .build();
84
85         physicalNodeChangeListenerReg = dataBroker.registerDataTreeChangeListener(new DataTreeIdentifier<>(
86                 LogicalDatastoreType.OPERATIONAL, nodeInstanceIdentifier), new PhysicalNodeChangeListener());
87         physicalLinkChangeListenerReg = dataBroker.registerDataTreeChangeListener(new DataTreeIdentifier<>(
88                 LogicalDatastoreType.OPERATIONAL, linkInstanceIdentifier), new PhysicalLinkChangeListener());
89
90         return;
91     }
92     public void close(){
93         if(physicalLinkChangeListenerReg!=null){
94             physicalLinkChangeListenerReg.close();
95         }
96         if(physicalNodeChangeListenerReg!=null){
97             physicalNodeChangeListenerReg.close();
98         }
99         physicalResourceMap.clear();
100     }
101     protected synchronized void resetResource(UserId userId) {
102         physicalResourceMap.remove(userId);
103     }
104
105     protected void addPhysicalNode(UserId userId, PhysicalNode physicalNode) {
106         addPhysicalResource(userId, physicalNode.getKey().toString());
107     }
108
109     protected void addPhysicalPort(UserId userId, PhysicalPort physicalPort) {
110         addPhysicalResource(userId, physicalPort.getKey().toString());
111     }
112
113     protected void addPhysicalPath(UserId userId, PhysicalPath physicalPath) {
114         List<org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.path.instance.PhysicalLink>
115                 physicalLinkList = physicalPath.getPhysicalLink();
116         for (org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.path.instance.PhysicalLink physicalLink :
117                 physicalLinkList) {
118             addPhysicalResource(userId, physicalLink.getKey().toString());
119         }
120     }
121
122     private synchronized void addPhysicalResource(UserId userId, String resourceId) {
123         if (!physicalResourceMap.containsKey(userId)) {
124             physicalResourceMap.put(userId, new CopyOnWriteArraySet<String>());
125         }
126         physicalResourceMap.get(userId).add(resourceId);
127     }
128
129     private synchronized void physicalResourceDown(String resourceId) {
130         Map<UserId, CopyOnWriteArraySet<String>> tmpMap = new HashMap<>(physicalResourceMap);
131         for (UserId userId : tmpMap.keySet()) {
132             Set<String> physicalResources = tmpMap.get(userId);
133             if (physicalResources.contains(resourceId)) {
134                 physicalResourceMap.remove(userId);
135                 try {
136                     log.info("Physical network changed and affected the virtual network of " +
137                             "user {}, start remapping.", userId.getValue());
138
139                     intentResolver.resolveIntent(userId);
140                 } catch (Exception e) {
141                     // TODO Auto-generated catch block
142                     log.error("Exception:",e);
143                 }
144             }
145         }
146     }
147
148     /**
149      * A listener to ch ange events related to physical nodes being
150      * added, removed or updated.
151      *
152      * @author Zhigang Ji
153      */
154     private class PhysicalNodeChangeListener implements DataTreeChangeListener<PhysicalNode> {
155         private void handleNodeUpdate(PhysicalNode originNode, PhysicalNode currentNode) {
156             log.debug("Handle node {} update.", originNode.getNodeId().getValue());
157             List<PhysicalPort> originPorts = originNode.getPhysicalPort();
158             List<PhysicalPort> currentPorts = currentNode.getPhysicalPort() == null ? new ArrayList<>() : currentNode.getPhysicalPort();
159             if (originPorts != null) {
160                 for (PhysicalPort physicalPort : originPorts) {
161                     if (!currentPorts.contains(physicalPort)) {
162                         log.debug("Physical port {} removed.", physicalPort.getPortId().getValue());
163                         physicalResourceDown(physicalPort.getKey().toString());
164                     }
165                 }
166             }
167         }
168
169         @Override
170         public void onDataTreeChanged(Collection<DataTreeModification<PhysicalNode>> changes) {
171             for (DataTreeModification<PhysicalNode> change: changes) {
172                 DataObjectModification<PhysicalNode> rootNode = change.getRootNode();
173                 PhysicalNode originalNode = rootNode.getDataBefore();
174                 switch (rootNode.getModificationType()) {
175                     case WRITE:
176                         if (originalNode != null) {
177                             handleNodeUpdate(originalNode, rootNode.getDataAfter());
178                         }
179                         break;
180                     case DELETE:
181                         String resourceId = originalNode.getKey().toString();
182                         log.debug("Physical node {} removed.", resourceId);
183                         physicalResourceDown(resourceId);
184                         break;
185                     default:
186                         break;
187                 }
188             }
189         }
190     }
191
192     /**
193      * A listener to change events related to physical links being
194      * added, removed or updated.
195      *
196      * @author Zhigang Ji
197      */
198     private class PhysicalLinkChangeListener implements DataTreeChangeListener<PhysicalLink> {
199         private void handleLinkUpdate(PhysicalLink originLink, PhysicalLink currentLink) {
200             log.debug("Handle physical link {} update.", originLink.getLinkId().getValue());
201             //TODO
202         }
203
204         @Override
205         public void onDataTreeChanged(Collection<DataTreeModification<PhysicalLink>> changes) {
206             for (DataTreeModification<PhysicalLink> change: changes) {
207                 DataObjectModification<PhysicalLink> rootNode = change.getRootNode();
208                 PhysicalLink originalLink = rootNode.getDataBefore();
209                 switch (rootNode.getModificationType()) {
210                     case WRITE:
211                         if (originalLink != null) {
212                             handleLinkUpdate(originalLink, rootNode.getDataAfter());
213                         }
214                         break;
215                     case DELETE:
216                         String resourceId = originalLink.getKey().toString();
217                         log.debug("Physical link {} removed.", resourceId);
218                         physicalResourceDown(resourceId);
219                         break;
220                     default:
221                         break;
222                 }
223             }
224         }
225     }
226 }