2 * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved.
\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
9 package org.opendaylight.nemo.intent.computation;
\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
32 import java.util.concurrent.ConcurrentHashMap;
\r
33 import java.util.concurrent.CopyOnWriteArraySet;
\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
43 * @author Zhigang Ji
\r
45 public class PNResourcesTracker {
\r
46 private static final Logger log = LoggerFactory.getLogger(PNResourcesTracker.class);
\r
48 private final ConcurrentHashMap<UserId, CopyOnWriteArraySet<String>/*physical resources*/> physicalResourceMap;
\r
50 private final DataBroker dataBroker;
\r
51 private final IntentResolver intentResolver;
\r
54 * The registration for the physical node change listener.
\r
56 private ListenerRegistration<DataChangeListener> physicalNodeChangeListenerReg;
\r
59 * The registration for the physical link change listener.
\r
61 private ListenerRegistration<DataChangeListener> physicalLinkChangeListenerReg;
\r
63 public PNResourcesTracker(DataBroker dataBroker, IntentResolver intentResolver) {
\r
66 this.dataBroker = dataBroker;
\r
67 this.intentResolver = intentResolver;
\r
68 physicalResourceMap = new ConcurrentHashMap<UserId, CopyOnWriteArraySet<String>>();
\r
70 InstanceIdentifier<PhysicalNode> nodeInstanceIdentifier = InstanceIdentifier
\r
71 .builder(PhysicalNetwork.class)
\r
72 .child(PhysicalNodes.class)
\r
73 .child(PhysicalNode.class)
\r
75 InstanceIdentifier<PhysicalLink> linkInstanceIdentifier = InstanceIdentifier
\r
76 .builder(PhysicalNetwork.class)
\r
77 .child(PhysicalLinks.class)
\r
78 .child(PhysicalLink.class)
\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
88 public void close(){
\r
89 if(physicalLinkChangeListenerReg!=null){
\r
90 physicalLinkChangeListenerReg.close();
\r
92 if(physicalNodeChangeListenerReg!=null){
\r
93 physicalNodeChangeListenerReg.close();
\r
95 physicalResourceMap.clear();
\r
97 protected synchronized void resetResource(UserId userId) {
\r
98 physicalResourceMap.remove(userId);
\r
101 protected void addPhysicalNode(UserId userId, PhysicalNode physicalNode) {
\r
102 addPhysicalResource(userId, physicalNode.getKey().toString());
\r
105 protected void addPhysicalPort(UserId userId, PhysicalPort physicalPort) {
\r
106 addPhysicalResource(userId, physicalPort.getKey().toString());
\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
118 private synchronized void addPhysicalResource(UserId userId, String resourceId) {
\r
119 if (!physicalResourceMap.containsKey(userId)) {
\r
120 physicalResourceMap.put(userId, new CopyOnWriteArraySet<String>());
\r
122 physicalResourceMap.get(userId).add(resourceId);
\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
132 log.info("Physical network changed and affected the virtual network of " +
\r
133 "user {}, start remapping.", userId.getValue());
\r
135 intentResolver.resolveIntent(userId);
\r
136 } catch (Exception e) {
\r
137 // TODO Auto-generated catch block
\r
138 log.error("Exception:",e);
\r
145 * A listener to ch ange events related to physical nodes being
\r
146 * added, removed or updated.
\r
148 * @author Zhigang Ji
\r
150 private class PhysicalNodeChangeListener implements DataChangeListener {
\r
152 public void onDataChanged(AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
\r
153 if (null == change) {
\r
157 Map<InstanceIdentifier<?>, DataObject> originalData = change.getOriginalData();
\r
158 Map<InstanceIdentifier<?>, DataObject> updatedData = change.getUpdatedData();
\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
170 Set<InstanceIdentifier<?>> removedPaths = change.getRemovedPaths();
\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
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
201 * A listener to change events related to physical links being
\r
202 * added, removed or updated.
\r
204 * @author Zhigang Ji
\r
206 private class PhysicalLinkChangeListener implements DataChangeListener {
\r
208 public void onDataChanged(AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
\r
209 if (null == change) {
\r
213 Map<InstanceIdentifier<?>, DataObject> originalData = change.getOriginalData();
\r
214 Map<InstanceIdentifier<?>, DataObject> updatedData = change.getUpdatedData();
\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
226 Set<InstanceIdentifier<?>> removedPaths = change.getRemovedPaths();
\r
228 if (null != removedPaths && !removedPaths.isEmpty()) {
\r
229 DataObject dataObject;
\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
242 private void handleLinkUpdate(PhysicalLink originLink, PhysicalLink currentLink) {
\r
243 log.debug("Handle physical link {} update.", originLink.getLinkId().getValue());
\r