Implement vn automatic remapping. 43/30543/1
authorFengkai Li <lifengkai@huawei.com>
Thu, 3 Dec 2015 10:42:05 +0000 (18:42 +0800)
committerFengkai Li <lifengkai@huawei.com>
Thu, 3 Dec 2015 10:51:32 +0000 (18:51 +0800)
Change-Id: Id0c28e70546be5092ab26cdec7ab3ed8e8953d14
Signed-off-by: Fengkai Li <lifengkai@huawei.com>
nemo-impl/src/main/java/org/opendaylight/nemo/intent/IntentResolver.java
nemo-impl/src/main/java/org/opendaylight/nemo/intent/computation/PNResourcesTracker.java [new file with mode: 0644]
nemo-impl/src/main/java/org/opendaylight/nemo/intent/computation/VNMappingUnit.java

index 7767f37ecdbe3f82c0ccb699235e186682f72ebf..1ed17fbab4e82da577182b6920c86948015c2f25 100644 (file)
@@ -13,6 +13,7 @@ import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;\r
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;\r
 import org.opendaylight.nemo.intent.computation.PNComputationUnit;\r
+import org.opendaylight.nemo.intent.computation.PNResourcesTracker;\r
 import org.opendaylight.nemo.intent.computation.VNComputationUnit;\r
 import org.opendaylight.nemo.intent.computation.VNMappingUnit;\r
 import org.opendaylight.nemo.intent.condition.ConditionManager;\r
@@ -107,6 +108,11 @@ public class IntentResolver implements AutoCloseable {
      */\r
     private Map<UserId, VNComputationUnit> vnComputationUnits;\r
 \r
+    /**\r
+     * Track the physical resource, re-resolve intent if related physical resource removed.\r
+     */\r
+    private PNResourcesTracker pnResourcesTracker;\r
+\r
     /**\r
      * The virtual network mapping unit.\r
      */\r
@@ -124,7 +130,8 @@ public class IntentResolver implements AutoCloseable {
 \r
         pnComputationUnit = new PNComputationUnit(dataBroker);\r
         vnComputationUnits = new HashMap<UserId, VNComputationUnit>();\r
-        vnMappingUnit = new VNMappingUnit(dataBroker, pnComputationUnit);\r
+        pnResourcesTracker = new PNResourcesTracker(dataBroker, this);\r
+        vnMappingUnit = new VNMappingUnit(dataBroker, pnComputationUnit, pnResourcesTracker);\r
 \r
         operationResolver = new OperationResolver(dataBroker, conditionManager, vnComputationUnits);\r
 \r
@@ -439,6 +446,10 @@ public class IntentResolver implements AutoCloseable {
             }\r
         }\r
 \r
+        if ( null != pnResourcesTracker ) {\r
+            pnResourcesTracker.close();\r
+        }\r
+\r
         if ( null != vnMappingUnit ) {\r
             vnMappingUnit.close();\r
         }\r
diff --git a/nemo-impl/src/main/java/org/opendaylight/nemo/intent/computation/PNResourcesTracker.java b/nemo-impl/src/main/java/org/opendaylight/nemo/intent/computation/PNResourcesTracker.java
new file mode 100644 (file)
index 0000000..3308797
--- /dev/null
@@ -0,0 +1,245 @@
+/*\r
+ * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+\r
+package org.opendaylight.nemo.intent.computation;\r
+\r
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;\r
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;\r
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;\r
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;\r
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;\r
+import org.opendaylight.nemo.intent.IntentResolver;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.PhysicalNetwork;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.PhysicalLinks;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.PhysicalNodes;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.physical.links.PhysicalLink;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.physical.nodes.PhysicalNode;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.physical.paths.PhysicalPath;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.node.instance.PhysicalPort;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.UserId;\r
+import org.opendaylight.yangtools.concepts.ListenerRegistration;\r
+import org.opendaylight.yangtools.yang.binding.DataObject;\r
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;\r
+import org.slf4j.Logger;\r
+import org.slf4j.LoggerFactory;\r
+\r
+import java.util.*;\r
+import java.util.concurrent.ConcurrentHashMap;\r
+import java.util.concurrent.CopyOnWriteArraySet;\r
+\r
+/**\r
+ * The virtual network mapping unit implements the following functions:\r
+ * (1) Automatically perform the virtual network mapping when the user's\r
+ * virtual network changed, which is subscribed from the data store.\r
+ * (2) Automatically perform the remapping for the virtual networks that\r
+ * are influenced by the changes of the underlying physical network\r
+ * which are also subscribed from the data store.\r
+ *\r
+ * @author Zhigang Ji\r
+ */\r
+public class PNResourcesTracker {\r
+    private static final Logger log = LoggerFactory.getLogger(PNResourcesTracker.class);\r
+\r
+    private final ConcurrentHashMap<UserId, CopyOnWriteArraySet<String>/*physical resources*/> physicalResourceMap;\r
+\r
+    private final DataBroker dataBroker;\r
+    private final IntentResolver intentResolver;\r
+\r
+    /**\r
+     * The registration for the physical node change listener.\r
+     */\r
+    private ListenerRegistration<DataChangeListener> physicalNodeChangeListenerReg;\r
+\r
+    /**\r
+     * The registration for the physical link change listener.\r
+     */\r
+    private ListenerRegistration<DataChangeListener> physicalLinkChangeListenerReg;\r
+\r
+    public PNResourcesTracker(DataBroker dataBroker, IntentResolver intentResolver) {\r
+        super();\r
+\r
+        this.dataBroker = dataBroker;\r
+        this.intentResolver = intentResolver;\r
+        physicalResourceMap = new ConcurrentHashMap<UserId, CopyOnWriteArraySet<String>>();\r
+\r
+        InstanceIdentifier<PhysicalNode> nodeInstanceIdentifier = InstanceIdentifier\r
+                .builder(PhysicalNetwork.class)\r
+                .child(PhysicalNodes.class)\r
+                .child(PhysicalNode.class)\r
+                .build();\r
+        InstanceIdentifier<PhysicalLink> linkInstanceIdentifier = InstanceIdentifier\r
+                .builder(PhysicalNetwork.class)\r
+                .child(PhysicalLinks.class)\r
+                .child(PhysicalLink.class)\r
+                .build();\r
+\r
+        physicalNodeChangeListenerReg = dataBroker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,\r
+                nodeInstanceIdentifier, new PhysicalNodeChangeListener(), DataChangeScope.BASE);\r
+        physicalLinkChangeListenerReg = dataBroker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,\r
+                linkInstanceIdentifier, new PhysicalLinkChangeListener(), DataChangeScope.BASE);\r
+\r
+        return;\r
+    }\r
+    public void close(){\r
+        if(physicalLinkChangeListenerReg!=null){\r
+            physicalLinkChangeListenerReg.close();\r
+        }\r
+        if(physicalNodeChangeListenerReg!=null){\r
+            physicalNodeChangeListenerReg.close();\r
+        }\r
+        physicalResourceMap.clear();\r
+    }\r
+    protected synchronized void resetResource(UserId userId) {\r
+        physicalResourceMap.remove(userId);\r
+    }\r
+\r
+    protected void addPhysicalNode(UserId userId, PhysicalNode physicalNode) {\r
+        addPhysicalResource(userId, physicalNode.getKey().toString());\r
+    }\r
+\r
+    protected void addPhysicalPort(UserId userId, PhysicalPort physicalPort) {\r
+        addPhysicalResource(userId, physicalPort.getKey().toString());\r
+    }\r
+\r
+    protected void addPhysicalPath(UserId userId, PhysicalPath physicalPath) {\r
+        List<org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.path.instance.PhysicalLink>\r
+                physicalLinkList = physicalPath.getPhysicalLink();\r
+        for (org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.path.instance.PhysicalLink physicalLink :\r
+                physicalLinkList) {\r
+            addPhysicalResource(userId, physicalLink.getKey().toString());\r
+        }\r
+    }\r
+\r
+    private synchronized void addPhysicalResource(UserId userId, String resourceId) {\r
+        if (!physicalResourceMap.containsKey(userId)) {\r
+            physicalResourceMap.put(userId, new CopyOnWriteArraySet<String>());\r
+        }\r
+        physicalResourceMap.get(userId).add(resourceId);\r
+    }\r
+\r
+    private synchronized void physicalResourceDown(String resourceId) {\r
+        Map<UserId, CopyOnWriteArraySet<String>> tmpMap = new HashMap<UserId, CopyOnWriteArraySet<String>>(physicalResourceMap);\r
+        for (UserId userId : tmpMap.keySet()) {\r
+            Set<String> physicalResources = tmpMap.get(userId);\r
+            if (physicalResources.contains(resourceId)) {\r
+                physicalResourceMap.remove(userId);\r
+                try {\r
+                    intentResolver.resolveIntent(userId);\r
+                } catch (Exception e) {\r
+                    e.printStackTrace();\r
+                }\r
+            }\r
+        }\r
+    }\r
+\r
+    /**\r
+     * A listener to ch ange events related to physical nodes being\r
+     * added, removed or updated.\r
+     *\r
+     * @author Zhigang Ji\r
+     */\r
+    private class PhysicalNodeChangeListener implements DataChangeListener {\r
+        @Override\r
+        public void onDataChanged(AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {\r
+            if (null == change) {\r
+                return;\r
+            }\r
+\r
+            Map<InstanceIdentifier<?>, DataObject> originalData = change.getOriginalData();\r
+            Map<InstanceIdentifier<?>, DataObject> updatedData = change.getUpdatedData();\r
+\r
+            if (null != updatedData && !updatedData.isEmpty()) {\r
+                for (InstanceIdentifier<?> identifier : updatedData.keySet()) {\r
+                    DataObject originData = originalData.get(identifier);\r
+                    DataObject currentData = updatedData.get(identifier);\r
+                    if (originData != null && originData instanceof PhysicalNode) {\r
+                        handleNodeUpdate((PhysicalNode) originData, (PhysicalNode) currentData);\r
+                    }\r
+                }\r
+            }\r
+\r
+            Set<InstanceIdentifier<?>> removedPaths = change.getRemovedPaths();\r
+\r
+            if (null != removedPaths && !removedPaths.isEmpty()) {\r
+                DataObject dataObject;\r
+                for (InstanceIdentifier<?> instanceId : removedPaths) {\r
+                    dataObject = originalData.get(instanceId);\r
+                    if (dataObject != null && dataObject instanceof PhysicalNode) {\r
+                        String resourceId = ((PhysicalNode) dataObject).getKey().toString();\r
+                        log.debug("Physical node {} removed.", resourceId);\r
+                        physicalResourceDown(resourceId);\r
+                    }\r
+\r
+                }\r
+            }\r
+        }\r
+\r
+        private void handleNodeUpdate(PhysicalNode originNode, PhysicalNode currentNode) {\r
+            log.debug("Handle node {} update.", originNode.getNodeId().getValue());\r
+            List<PhysicalPort> originPorts = originNode.getPhysicalPort();\r
+            List<PhysicalPort> currentPorts = currentNode.getPhysicalPort() == null ? new ArrayList<PhysicalPort>() : currentNode.getPhysicalPort();\r
+            if (originPorts != null)\r
+                for (PhysicalPort physicalPort : originPorts) {\r
+                    if (!currentPorts.contains(physicalPort)) {\r
+                        log.debug("Physical port {} removed.", physicalPort.getPortId().getValue());\r
+                        physicalResourceDown(physicalPort.getKey().toString());\r
+                    }\r
+                }\r
+        }\r
+    }\r
+\r
+    /**\r
+     * A listener to change events related to physical links being\r
+     * added, removed or updated.\r
+     *\r
+     * @author Zhigang Ji\r
+     */\r
+    private class PhysicalLinkChangeListener implements DataChangeListener {\r
+        @Override\r
+        public void onDataChanged(AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {\r
+            if (null == change) {\r
+                return;\r
+            }\r
+\r
+            Map<InstanceIdentifier<?>, DataObject> originalData = change.getOriginalData();\r
+            Map<InstanceIdentifier<?>, DataObject> updatedData = change.getUpdatedData();\r
+\r
+            if (null != updatedData && !updatedData.isEmpty()) {\r
+                for (InstanceIdentifier<?> identifier : updatedData.keySet()) {\r
+                    DataObject originData = originalData.get(identifier);\r
+                    DataObject currentDate = updatedData.get(identifier);\r
+                    if (originData != null && originData instanceof PhysicalLink) {\r
+                        handleLinkUpdate((PhysicalLink) originalData, (PhysicalLink) currentDate);\r
+                    }\r
+                }\r
+            }\r
+\r
+            Set<InstanceIdentifier<?>> removedPaths = change.getRemovedPaths();\r
+\r
+            if (null != removedPaths && !removedPaths.isEmpty()) {\r
+                DataObject dataObject;\r
+\r
+                for (InstanceIdentifier<?> instanceId : removedPaths) {\r
+                    dataObject = originalData.get(instanceId);\r
+                    if (dataObject != null && dataObject instanceof PhysicalLink) {\r
+                        String resourceId = ((PhysicalLink) dataObject).getKey().toString();\r
+                        log.debug("Physical link {} removed.", resourceId);\r
+                        physicalResourceDown(resourceId);\r
+                    }\r
+                }\r
+            }\r
+        }\r
+\r
+        private void handleLinkUpdate(PhysicalLink originLink, PhysicalLink currentLink) {\r
+            log.debug("Handle physical link {} update.", originLink.getLinkId().getValue());\r
+            //TODO\r
+        }\r
+    }\r
+\r
+\r
+}\r
index 4458e5fdfe811384925b362a1ef79004d8a58612..95a9efd01471dcb63913e5632bc9e4dfdcca094e 100644 (file)
@@ -8,29 +8,16 @@
 \r
 package org.opendaylight.nemo.intent.computation;\r
 \r
-import java.util.ArrayList;\r
-import java.util.HashMap;\r
-import java.util.LinkedList;\r
-import java.util.List;\r
-import java.util.Map;\r
-import java.util.Set;\r
-import java.util.UUID;\r
-import java.util.concurrent.ExecutionException;\r
-\r
+import com.google.common.base.Optional;\r
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;\r
-import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;\r
 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;\r
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;\r
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;\r
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.PhysicalNetwork;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.PhysicalNodeAttributeDefinitions;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.PhysicalPortAttributeDefinitions;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.attribute.definition.AttributeMatchPatterns;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.attribute.instance.attribute.value.RangeValue;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.PhysicalLinks;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.PhysicalNodes;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.physical.links.PhysicalLink;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.physical.nodes.PhysicalNode;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.physical.paths.PhysicalPath;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.physical.paths.PhysicalPathBuilder;\r
@@ -51,23 +38,17 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.intent.m
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.intent.mapping.result.rev151010.vn.pn.mapping.results.UserVnPnMapping;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.intent.mapping.result.rev151010.vn.pn.mapping.results.user.vn.pn.mapping.VnPnMappingResult;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.intent.mapping.result.rev151010.vn.pn.mapping.results.user.vn.pn.mapping.VnPnMappingResultBuilder;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.engine.common.rev151010.AttributeName;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.engine.common.rev151010.PhysicalNodeId;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.engine.common.rev151010.PhysicalPathId;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.engine.common.rev151010.PhysicalPortId;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.engine.common.rev151010.PhysicalResourceEntityId;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.engine.common.rev151010.PhysicalResourceId;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.engine.common.rev151010.VirtualNetworkId;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.engine.common.rev151010.VirtualNodeId;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.engine.common.rev151010.VirtualResourceEntityId;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.engine.common.rev151010.VirtualResourceId;\r
-import org.opendaylight.yangtools.concepts.ListenerRegistration;\r
-import org.opendaylight.yangtools.yang.binding.DataObject;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.UserId;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.engine.common.rev151010.*;\r
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;\r
 import org.slf4j.Logger;\r
 import org.slf4j.LoggerFactory;\r
 \r
-import com.google.common.base.Optional;\r
+import java.util.ArrayList;\r
+import java.util.LinkedList;\r
+import java.util.List;\r
+import java.util.UUID;\r
+import java.util.concurrent.ExecutionException;\r
 \r
 /**\r
  * The virtual network mapping unit implements the following functions:\r
@@ -90,44 +71,18 @@ public class VNMappingUnit implements AutoCloseable {
     private PNComputationUnit pnComputationUnit;\r
 \r
     /**\r
-     * The registrations for the physical port change listeners.\r
-     */\r
-    private Map<PhysicalNodeId, Map<PhysicalPortId, ListenerRegistration<DataChangeListener>>> physicalPortChangeListenerRegs;\r
-\r
-    /**\r
-     * The registration for the physical node change listener.\r
+     * The physical network resource tracker.\r
      */\r
-    private ListenerRegistration<DataChangeListener> physicalNodeChangeListenerReg;\r
+    private PNResourcesTracker pnResourcesTracker;\r
 \r
-    /**\r
-     * The registration for the physical link change listener.\r
-     */\r
-    private ListenerRegistration<DataChangeListener> physicalLinkChangeListenerReg;\r
-\r
-    public VNMappingUnit(DataBroker dataBroker, PNComputationUnit pnComputationUnit) {\r
+    public VNMappingUnit(DataBroker dataBroker,\r
+                         PNComputationUnit pnComputationUnit,\r
+                         PNResourcesTracker pnResourcesTracker) {\r
         super();\r
 \r
         this.dataBroker = dataBroker;\r
         this.pnComputationUnit = pnComputationUnit;\r
-\r
-        physicalPortChangeListenerRegs =\r
-                new HashMap<PhysicalNodeId, Map<PhysicalPortId, ListenerRegistration<DataChangeListener>>>();\r
-\r
-        InstanceIdentifier<PhysicalNode> physicalNodeIid = InstanceIdentifier\r
-                .builder(PhysicalNetwork.class)\r
-                .child(PhysicalNodes.class)\r
-                .child(PhysicalNode.class)\r
-                .build();\r
-        InstanceIdentifier<PhysicalLink> physicalLinkIid = InstanceIdentifier\r
-                .builder(PhysicalNetwork.class)\r
-                .child(PhysicalLinks.class)\r
-                .child(PhysicalLink.class)\r
-                .build();\r
-\r
-        physicalNodeChangeListenerReg = dataBroker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,\r
-                physicalNodeIid, new PhysicalNodeChangeListener(), DataChangeScope.BASE);\r
-        physicalLinkChangeListenerReg = dataBroker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,\r
-                physicalLinkIid, new PhysicalLinkChangeListener(), DataChangeScope.BASE);\r
+        this.pnResourcesTracker = pnResourcesTracker;\r
 \r
         LOG.debug("Initialized the virtual network mapping unit.");\r
 \r
@@ -161,6 +116,7 @@ public class VNMappingUnit implements AutoCloseable {
         PhysicalNodes physicalNodes = result.get();\r
         List<PhysicalNode> physicalNodeList = physicalNodes.getPhysicalNode();\r
 \r
+        UserId userId = virtualNetwork.getUserId();\r
         List<VnPnMappingResult> vnPnMappingResults = userVnPnMapping.getVnPnMappingResult();\r
         List<VirtualNode> virtualNodes = virtualNetwork.getVirtualNodes().getVirtualNode();\r
         List<VirtualPort> virtualPorts;\r
@@ -172,11 +128,17 @@ public class VNMappingUnit implements AutoCloseable {
             physicalNode = virtualNodeMapping(virtualNetwork.getNetworkId(), virtualNode, physicalNodeList);\r
 \r
             if ( null == physicalNode ) {\r
+                // If mapping failed, reset the user physical resources.\r
+                pnResourcesTracker.resetResource(userId);\r
+\r
                 throw new VNMappingException("Failed mapping for the virtual node " +\r
                         virtualNode.getNodeId().getValue() + " in the virtual network " +\r
                         virtualNetwork.getNetworkId().getValue());\r
             }\r
 \r
+            // Keep physical resource.\r
+            pnResourcesTracker.addPhysicalNode(userId, physicalNode);\r
+\r
             virtualPorts = virtualNode.getVirtualPort();\r
 \r
             for ( VirtualPort virtualPort : virtualPorts ) {\r
@@ -185,12 +147,18 @@ public class VNMappingUnit implements AutoCloseable {
                             virtualNode.getNodeId(), virtualPort, physicalNode);\r
 \r
                     if ( null == physicalPort ) {\r
+                        // If mapping failed, reset the user physical resources.\r
+                        pnResourcesTracker.resetResource(userId);\r
+\r
                         throw new VNMappingException("Failed mapping for the virtual port " +\r
                                 virtualPort.getPortId().getValue() + " of the virtual node " +\r
                                 virtualNode.getNodeId().getValue() + " in the virtual network " +\r
                                 virtualNetwork.getNetworkId().getValue());\r
                     }\r
 \r
+                    // Keep physical resource.\r
+                    pnResourcesTracker.addPhysicalPort(userId, physicalPort);\r
+\r
                     vnPnMappingResult = new VnPnMappingResultBuilder()\r
                             .setVirtualResourceId(new VirtualResourceId(UUID.randomUUID().toString()))\r
                             .setVirtualResourceType(VirtualResourceInstance.VirtualResourceType.Vport)\r
@@ -227,11 +195,17 @@ public class VNMappingUnit implements AutoCloseable {
             physicalPath = virtualLinkMapping(virtualNetwork.getNetworkId(), virtualLink, userVnPnMapping);\r
 \r
             if ( null == physicalPath ) {\r
+                // If mapping failed, reset the user physical resources.\r
+                pnResourcesTracker.resetResource(userId);\r
+\r
                 throw new VNMappingException("Failed mapping for the virtual link " +\r
                         virtualLink.getLinkId().getValue() + " in the virtual network " +\r
                         virtualNetwork.getNetworkId().getValue());\r
             }\r
 \r
+            // Keep physical resource.\r
+            pnResourcesTracker.addPhysicalPath(userId, physicalPath);\r
+\r
             physicalPaths.add(physicalPath);\r
 \r
             newVirtualLink = new VirtualLinkBuilder(virtualLink)\r
@@ -1073,125 +1047,4 @@ public class VNMappingUnit implements AutoCloseable {
 //            }\r
 //        }\r
 //    }\r
-\r
-    /**\r
-     * A listener to change events related to physical ports being\r
-     * added, removed or updated.\r
-     *\r
-     * @author Zhigang Ji\r
-     */\r
-    private class PhysicalPortChangeListener implements DataChangeListener {\r
-        /**\r
-         * The physical node that the physical port belongs to.\r
-         */\r
-        private PhysicalNodeId physicalNodeId;\r
-\r
-        public PhysicalPortChangeListener(PhysicalNodeId physicalNodeId) {\r
-            super();\r
-\r
-            this.physicalNodeId = physicalNodeId;\r
-\r
-            return;\r
-        }\r
-\r
-        @Override\r
-        public void onDataChanged(AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {\r
-            if ( null == change ) {\r
-                return;\r
-            }\r
-\r
-            Map<InstanceIdentifier<?>, DataObject> originalData = change.getOriginalData();\r
-            Map<InstanceIdentifier<?>, DataObject> updatedData = change.getUpdatedData();\r
-\r
-            if ( null != updatedData && !updatedData.isEmpty() ) {\r
-                for ( DataObject dataObject : updatedData.values() ) {\r
-                    // TODO\r
-                }\r
-            }\r
-\r
-            Set<InstanceIdentifier<?>> removedPaths = change.getRemovedPaths();\r
-\r
-            if ( null != removedPaths && !removedPaths.isEmpty() ) {\r
-                DataObject dataObject;\r
-\r
-                for ( InstanceIdentifier<?> instanceId : removedPaths ) {\r
-                    dataObject = originalData.get(instanceId);\r
-\r
-                    // TODO\r
-                }\r
-            }\r
-        }\r
-    }\r
-\r
-    /**\r
-     * A listener to change events related to physical nodes being\r
-     * added, removed or updated.\r
-     *\r
-     * @author Zhigang Ji\r
-     */\r
-    private class PhysicalNodeChangeListener implements DataChangeListener {\r
-        @Override\r
-        public void onDataChanged(AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {\r
-            if ( null == change ) {\r
-                return;\r
-            }\r
-\r
-            Map<InstanceIdentifier<?>, DataObject> originalData = change.getOriginalData();\r
-            Map<InstanceIdentifier<?>, DataObject> updatedData = change.getUpdatedData();\r
-\r
-            if ( null != updatedData && !updatedData.isEmpty() ) {\r
-                for ( DataObject dataObject : updatedData.values() ) {\r
-                    // TODO\r
-                }\r
-            }\r
-\r
-            Set<InstanceIdentifier<?>> removedPaths = change.getRemovedPaths();\r
-\r
-            if ( null != removedPaths && !removedPaths.isEmpty() ) {\r
-                DataObject dataObject;\r
-\r
-                for ( InstanceIdentifier<?> instanceId : removedPaths ) {\r
-                    dataObject = originalData.get(instanceId);\r
-\r
-                    // TODO\r
-                }\r
-            }\r
-        }\r
-    }\r
-\r
-    /**\r
-     * A listener to change events related to physical links being\r
-     * added, removed or updated.\r
-     *\r
-     * @author Zhigang Ji\r
-     */\r
-    private class PhysicalLinkChangeListener implements DataChangeListener {\r
-        @Override\r
-        public void onDataChanged(AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {\r
-            if ( null == change ) {\r
-                return;\r
-            }\r
-\r
-            Map<InstanceIdentifier<?>, DataObject> originalData = change.getOriginalData();\r
-            Map<InstanceIdentifier<?>, DataObject> updatedData = change.getUpdatedData();\r
-\r
-            if ( null != updatedData && !updatedData.isEmpty() ) {\r
-                for ( DataObject dataObject : updatedData.values() ) {\r
-                    // TODO\r
-                }\r
-            }\r
-\r
-            Set<InstanceIdentifier<?>> removedPaths = change.getRemovedPaths();\r
-\r
-            if ( null != removedPaths && !removedPaths.isEmpty() ) {\r
-                DataObject dataObject;\r
-\r
-                for ( InstanceIdentifier<?> instanceId : removedPaths ) {\r
-                    dataObject = originalData.get(instanceId);\r
-\r
-                    // TODO\r
-                }\r
-            }\r
-        }\r
-    }\r
 }\r