ovs-driver refactored to support new TAPI-based presto NRP model. 69/58169/1
authormarek.ryznar <marek.ryznar@amartus.com>
Thu, 1 Jun 2017 14:27:56 +0000 (16:27 +0200)
committermarek.ryznar <marek.ryznar@amartus.com>
Fri, 2 Jun 2017 07:16:53 +0000 (09:16 +0200)
Change-Id: Iee76b62274ef1ef174b963cc93357c0785ec5cfc
Signed-off-by: marek.ryznar <marek.ryznar@amartus.com>
16 files changed:
ovs-driver/src/main/java/org/opendaylight/unimgr/mef/nrp/ovs/activator/OvsActivator.java
ovs-driver/src/main/java/org/opendaylight/unimgr/mef/nrp/ovs/activator/OvsActivatorHelper.java
ovs-driver/src/main/java/org/opendaylight/unimgr/mef/nrp/ovs/driver/OvsDriver.java
ovs-driver/src/main/java/org/opendaylight/unimgr/mef/nrp/ovs/tapi/DataObjectModificationQualifier.java [new file with mode: 0644]
ovs-driver/src/main/java/org/opendaylight/unimgr/mef/nrp/ovs/tapi/TopologyDataHandler.java [new file with mode: 0644]
ovs-driver/src/main/java/org/opendaylight/unimgr/mef/nrp/ovs/transaction/TopologyTransaction.java
ovs-driver/src/main/java/org/opendaylight/unimgr/mef/nrp/ovs/util/OpenFlowUtils.java
ovs-driver/src/main/java/org/opendaylight/unimgr/mef/nrp/ovs/util/VlanUtils.java
ovs-driver/src/main/resources/org/opendaylight/blueprint/ovs-driver.xml
ovs-driver/src/test/java/org/opendaylight/unimgr/mef/nrp/ovs/DataStoreTestUtils.java [new file with mode: 0644]
ovs-driver/src/test/java/org/opendaylight/unimgr/mef/nrp/ovs/FlowTopologyTestUtils.java [new file with mode: 0644]
ovs-driver/src/test/java/org/opendaylight/unimgr/mef/nrp/ovs/OpenFlowTopologyTestUtils.java [new file with mode: 0644]
ovs-driver/src/test/java/org/opendaylight/unimgr/mef/nrp/ovs/OvsdbTopologyTestUtils.java [new file with mode: 0644]
ovs-driver/src/test/java/org/opendaylight/unimgr/mef/nrp/ovs/activator/OvsActivatorTest.java [new file with mode: 0644]
ovs-driver/src/test/java/org/opendaylight/unimgr/mef/nrp/ovs/tapi/TopologyDataHandlerTest.java [new file with mode: 0644]
ovs-driver/src/test/java/org/opendaylight/unimgr/mef/nrp/ovs/tapi/TopologyDataHandlerTestUtils.java [new file with mode: 0644]

index e3f4dd51108925d07d45d76d0ae7b406735b2892..0462143fd45287236cac09386f5687fbee3952f4 100644 (file)
@@ -11,12 +11,10 @@ import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
 import org.opendaylight.unimgr.mef.nrp.api.EndPoint;
 import org.opendaylight.unimgr.mef.nrp.common.ResourceActivator;
-import org.opendaylight.unimgr.mef.nrp.common.ResourceActivatorException;
 import org.opendaylight.unimgr.mef.nrp.common.ResourceNotAvailableException;
 import org.opendaylight.unimgr.mef.nrp.ovs.transaction.TableTransaction;
 import org.opendaylight.unimgr.mef.nrp.ovs.transaction.TopologyTransaction;
 import org.opendaylight.unimgr.mef.nrp.ovs.util.OpenFlowUtils;
-import org.opendaylight.yang.gen.v1.urn.onf.core.network.module.rev160630.g_forwardingconstruct.FcPort;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
@@ -33,54 +31,72 @@ import java.util.List;
 public class OvsActivator implements ResourceActivator {
 
     private final DataBroker dataBroker;
+    private String serviceName;
     private static final Logger LOG = LoggerFactory.getLogger(OvsActivator.class);
 
     public OvsActivator(DataBroker dataBroker) {
         this.dataBroker = dataBroker;
     }
 
+    /**
+     * Set state for the driver for a (de)activation transaction.
+     * @param endPoints list of endpoint to interconnect
+     */
     @Override
-    public void activate(List<EndPoint> endPoints, String serviceName) throws ResourceActivatorException, TransactionCommitFailedException {
-//        // Transaction - Get Open vSwitch node and its flow table
-//        String portName = flowPoint.getTp().getValue();
-//        TopologyTransaction topologyTransaction = new TopologyTransaction(dataBroker);
-//        Node node = topologyTransaction.readNode(portName);
-//        Table table = OpenFlowUtils.getTable(node);
-//
-//        // Prepare list of flows to be added/removed
-//        List<Flow> flowsToWrite = new ArrayList<>();
-//        List<Flow> flowsToDelete = new ArrayList<>();
-//        List<Link> interswitchLinks = topologyTransaction.readInterswitchLinks(node);
-//        if (!OpenFlowUtils.isTablePreconfigured(table)) {
-//            LOG.debug("Table is not preconfigured. Adding base flows.");
-//            flowsToWrite.addAll(OpenFlowUtils.getBaseFlows(interswitchLinks));
-//            flowsToDelete.addAll(OpenFlowUtils.getExistingFlows(table));
-//        }
-//        OvsActivatorHelper ovsActivatorHelper = new OvsActivatorHelper(topologyTransaction, flowPoint);
-//        String openFlowPortName = ovsActivatorHelper.getOpenFlowPortName();
-//        int externalVlanId = ovsActivatorHelper.getServiceVlanId();
-//        int internalVlanId = ovsActivatorHelper.getInternalVlanId();
-//        flowsToWrite.addAll(OpenFlowUtils.getVlanFlows(openFlowPortName, externalVlanId, internalVlanId, interswitchLinks, outerName));
-//
-//        // Transaction - Add flows related to service to table and remove unnecessary flows
-//        TableTransaction tableTransaction = new TableTransaction(dataBroker, node, table);
-//        tableTransaction.deleteFlows(flowsToDelete, true);
-//        tableTransaction.writeFlows(flowsToWrite);
+    public void activate(List<EndPoint> endPoints, String serviceName) throws ResourceNotAvailableException, TransactionCommitFailedException {
+        this.serviceName = serviceName;
+        for (EndPoint endPoint:endPoints)
+            activateEndpoint(endPoint);
+    }
+
+    private void activateEndpoint(EndPoint endPoint) throws ResourceNotAvailableException, TransactionCommitFailedException {
+        // Transaction - Get Open vSwitch node and its flow table
+        String portName = OvsActivatorHelper.getPortName(endPoint.getEndpoint().getServiceInterfacePoint().getValue());
+        TopologyTransaction topologyTransaction = new TopologyTransaction(dataBroker);
+        Node node = topologyTransaction.readNode(portName);
+        Table table = OpenFlowUtils.getTable(node);
+
+        // Prepare list of flows to be added/removed
+        List<Flow> flowsToWrite = new ArrayList<>();
+        List<Flow> flowsToDelete = new ArrayList<>();
+        List<Link> interswitchLinks = topologyTransaction.readInterswitchLinks(node);
+        if (!OpenFlowUtils.isTablePreconfigured(table)) {
+            LOG.debug("Table is not preconfigured. Adding base flows.");
+            flowsToWrite.addAll(OpenFlowUtils.getBaseFlows(interswitchLinks));
+            flowsToDelete.addAll(OpenFlowUtils.getExistingFlows(table));
+        }
+
+        OvsActivatorHelper ovsActivatorHelper = new OvsActivatorHelper(topologyTransaction, endPoint);
+        String openFlowPortName = ovsActivatorHelper.getOpenFlowPortName();
+        int externalVlanId = ovsActivatorHelper.getCeVlanId();
+        int internalVlanId = ovsActivatorHelper.getInternalVlanId();
+        flowsToWrite.addAll(OpenFlowUtils.getVlanFlows(openFlowPortName, externalVlanId, internalVlanId, interswitchLinks, serviceName));
+
+        // Transaction - Add flows related to service to table and remove unnecessary flows
+        TableTransaction tableTransaction = new TableTransaction(dataBroker, node, table);
+        tableTransaction.deleteFlows(flowsToDelete, true);
+        tableTransaction.writeFlows(flowsToWrite);
     }
 
     @Override
-    public void deactivate(List<EndPoint> endPoints, String serviceName) throws TransactionCommitFailedException, ResourceActivatorException {
-//        // Transaction - Get Open vSwitch node and its flow table
-//        String portName = flowPoint.getTp().getValue();
-//        TopologyTransaction topologyTransaction = new TopologyTransaction(dataBroker);
-//        Node node = topologyTransaction.readNode(portName);
-//        Table table = OpenFlowUtils.getTable(node);
-//
-//        // Get list of flows to be removed
-//        List<Flow> flowsToDelete = OpenFlowUtils.getServiceFlows(table, outerName);
-//
-//        // Transaction - Remove flows related to service from table
-//        TableTransaction tableTransaction = new TableTransaction(dataBroker, node, table);
-//        tableTransaction.deleteFlows(flowsToDelete, false);
+    public void deactivate(List<EndPoint> endPoints, String serviceName) throws TransactionCommitFailedException, ResourceNotAvailableException {
+        for (EndPoint endPoint:endPoints)
+            deactivateEndpoint(endPoint);
     }
+
+    private void deactivateEndpoint(EndPoint endPoint) throws ResourceNotAvailableException, TransactionCommitFailedException {
+        // Transaction - Get Open vSwitch node and its flow table
+        TopologyTransaction topologyTransaction = new TopologyTransaction(dataBroker);
+        OvsActivatorHelper ovsActivatorHelper = new OvsActivatorHelper(topologyTransaction,endPoint);
+
+        Node node = topologyTransaction.readNodeOF(ovsActivatorHelper.getOpenFlowPortName());
+        Table table = OpenFlowUtils.getTable(node);
+        // Get list of flows to be removed
+        List<Flow> flowsToDelete = OpenFlowUtils.getServiceFlows(table, serviceName);
+
+        // Transaction - Remove flows related to service from table
+        TableTransaction tableTransaction = new TableTransaction(dataBroker, node, table);
+        tableTransaction.deleteFlows(flowsToDelete, false);
+    }
+
 }
index dcedb2d19a2b8fd1d24d5300ef7338d16b40b971..55d9c840f0ea1b538fb6fa16eae09b7ae55716ab 100644 (file)
@@ -7,13 +7,13 @@
  */
 package org.opendaylight.unimgr.mef.nrp.ovs.activator;
 
+import org.opendaylight.unimgr.mef.nrp.api.EndPoint;
 import org.opendaylight.unimgr.mef.nrp.common.ResourceNotAvailableException;
 import org.opendaylight.unimgr.mef.nrp.ovs.exception.VlanNotSetException;
 import org.opendaylight.unimgr.mef.nrp.ovs.transaction.TopologyTransaction;
 import org.opendaylight.unimgr.mef.nrp.ovs.util.VlanUtils;
 import org.opendaylight.unimgr.utils.NullAwareDatastoreGetter;
-import org.opendaylight.yang.gen.v1.urn.mef.unimgr.ext.rev160725.FcPort1;
-import org.opendaylight.yang.gen.v1.urn.onf.core.network.module.rev160630.g_forwardingconstruct.FcPort;
+import org.opendaylight.yang.gen.v1.urn.mef.yang.nrp_interface.rev170227.nrp.create.connectivity.service.end.point.attrs.NrpCgEthFrameFlowCpaAspec;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
@@ -31,17 +31,20 @@ import java.util.Map;
  */
 class OvsActivatorHelper {
     private List<NullAwareDatastoreGetter<Node>> nodes;
-    private FcPort flowPoint;
+    private EndPoint endPoint;
+    private String tpName;
     private Map<String, String> portMap;
 
-    private static final String CTAG_VLAN_ID_NOT_SET_ERROR_MESSAGE = "C-Tag VLAN Id not set for termination point '%s'.";
-    private static final String FC_PORT_NOT_AUGMENTED_ERROR_MESSAGE = "Forwarding Construct port '%s' does not have '%s' augmentation.";
+    private static final String CTAG_VLAN_ID_NOT_SET_ERROR_MESSAGE = "C-Tag VLAN Id not set for End Point '%s'.";
+    private static final String ATTRS_NOT_SET_ERROR_MESSAGE = "End Point '%s' does not have '%s' set.";
+
 
     private static final Logger LOG = LoggerFactory.getLogger(OvsActivatorHelper.class);
 
-    OvsActivatorHelper(TopologyTransaction topologyTransaction, FcPort flowPoint) {
+    OvsActivatorHelper(TopologyTransaction topologyTransaction, EndPoint endPoint) {
         this.nodes = topologyTransaction.readNodes();
-        this.flowPoint = flowPoint;
+        this.endPoint = endPoint;
+        tpName = getPortName(endPoint.getEndpoint().getServiceInterfacePoint().getValue());
         this.portMap = createPortMap(nodes);
     }
 
@@ -50,21 +53,21 @@ class OvsActivatorHelper {
      *
      * @return Integer with VLAN Id
      */
-    int getServiceVlanId() throws ResourceNotAvailableException {
-        FcPort1 fcPort1 = flowPoint.getAugmentation(FcPort1.class);
-        String tpName = flowPoint.getTp().getValue();
+    int getCeVlanId() throws ResourceNotAvailableException {
 
-        if (fcPort1 != null) {
-            if (fcPort1.getCTagVlanId() != null) {
-                return fcPort1.getCTagVlanId().getValue().intValue();
+        if( (endPoint.getAttrs() != null) && (endPoint.getAttrs().getNrpCgEthFrameFlowCpaAspec()!=null) ){
+            NrpCgEthFrameFlowCpaAspec attr = endPoint.getAttrs().getNrpCgEthFrameFlowCpaAspec();
+            if( (attr.getCeVlanIdList()!=null) && !(attr.getCeVlanIdList().getVlanIdList().isEmpty()) ){
+                //for now we support only one CE VLAN
+                return attr.getCeVlanIdList().getVlanIdList().get(0).getVlanId().getValue().intValue();
             } else {
                 LOG.warn(String.format(CTAG_VLAN_ID_NOT_SET_ERROR_MESSAGE, tpName));
                 throw new VlanNotSetException(String.format(CTAG_VLAN_ID_NOT_SET_ERROR_MESSAGE, tpName));
             }
         } else {
-            String fcPort1ClassName = FcPort1.class.toString();
-            LOG.warn(String.format(FC_PORT_NOT_AUGMENTED_ERROR_MESSAGE, tpName, fcPort1ClassName));
-            throw new ResourceNotAvailableException(String.format(FC_PORT_NOT_AUGMENTED_ERROR_MESSAGE, tpName, fcPort1ClassName));
+            String className = NrpCgEthFrameFlowCpaAspec.class.toString();
+            LOG.warn(String.format(ATTRS_NOT_SET_ERROR_MESSAGE, tpName, className));
+            throw new ResourceNotAvailableException(String.format(ATTRS_NOT_SET_ERROR_MESSAGE, tpName, className));
         }
     }
 
@@ -75,7 +78,7 @@ class OvsActivatorHelper {
      */
     int getInternalVlanId() throws ResourceNotAvailableException {
         VlanUtils vlanUtils = new VlanUtils(nodes);
-        int serviceVlanId = getServiceVlanId();
+        int serviceVlanId = getCeVlanId();
 
         if (vlanUtils.isVlanInUse(serviceVlanId)) {
             LOG.debug("VLAN ID = '" + serviceVlanId + "' already in use.");
@@ -92,7 +95,7 @@ class OvsActivatorHelper {
      * @return String with port name
      */
     String getOpenFlowPortName() {
-        return portMap.get(flowPoint.getTp().getValue());
+        return portMap.get(tpName);
     }
 
     private Map<String, String> createPortMap(List<NullAwareDatastoreGetter<Node>> nodes) {
@@ -109,4 +112,9 @@ class OvsActivatorHelper {
         }
         return portMap;
     }
+
+    protected static String getPortName(String sip){
+        String[] tab = sip.split(":");
+        return tab[tab.length-1];
+    }
 }
index c6f147714b5c69a4589f7e52e0128698967d7b0e..1eb0f2bbb6d45c924db04f35a353a1315de96498 100644 (file)
@@ -12,11 +12,11 @@ import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFaile
 import org.opendaylight.unimgr.mef.nrp.api.ActivationDriver;
 import org.opendaylight.unimgr.mef.nrp.api.ActivationDriverBuilder;
 import org.opendaylight.unimgr.mef.nrp.api.EndPoint;
-import org.opendaylight.unimgr.mef.nrp.common.ResourceActivatorException;
+import org.opendaylight.unimgr.mef.nrp.common.ResourceNotAvailableException;
 import org.opendaylight.unimgr.mef.nrp.ovs.activator.OvsActivator;
+import org.opendaylight.unimgr.mef.nrp.ovs.tapi.TopologyDataHandler;
 import org.opendaylight.yang.gen.v1.urn.mef.yang.nrp_interface.rev170227.NrpCreateConnectivityServiceAttrs;
 import org.opendaylight.yang.gen.v1.urn.mef.yang.tapicommon.rev170227.UniversalId;
-import org.opendaylight.yang.gen.v1.urn.onf.core.network.module.rev160630.g_forwardingconstruct.FcPort;
 
 import java.util.List;
 import java.util.Optional;
@@ -27,20 +27,16 @@ import java.util.Optional;
 public class OvsDriver implements ActivationDriverBuilder {
 
     private OvsActivator activator;
-    private final DataBroker dataBroker;
-    private static final String GROUP_NAME = "local";
-    private static final long MTU_VALUE = 1522;
 
     public OvsDriver(DataBroker dataBroker){
-        this.dataBroker = dataBroker;
         activator = new OvsActivator(dataBroker);
     }
 
+
     private ActivationDriver getDriver() {
         return new ActivationDriver() {
-            private FcPort aEnd;
-            private FcPort zEnd;
-            private String uuid;
+            List<EndPoint> endPoints;
+            String serviceId;
 
             @Override
             public void commit() {
@@ -54,17 +50,18 @@ public class OvsDriver implements ActivationDriverBuilder {
 
             @Override
             public void initialize(List<EndPoint> endPoints, String serviceId, NrpCreateConnectivityServiceAttrs context) {
-
+                this.endPoints = endPoints;
+                this.serviceId = serviceId;
             }
 
             @Override
-            public void activate() throws TransactionCommitFailedException, ResourceActivatorException {
-                activator.activate(null,null);
+            public void activate() throws TransactionCommitFailedException, ResourceNotAvailableException {
+                activator.activate(endPoints,serviceId);
             }
 
             @Override
-            public void deactivate() throws TransactionCommitFailedException, ResourceActivatorException {
-                activator.deactivate(null,null);
+            public void deactivate() throws TransactionCommitFailedException, ResourceNotAvailableException {
+                activator.deactivate(endPoints,serviceId);
             }
 
             @Override
@@ -81,6 +78,6 @@ public class OvsDriver implements ActivationDriverBuilder {
 
     @Override
     public UniversalId getNodeUuid() {
-        return null;
+        return new UniversalId(TopologyDataHandler.getOvsNode());
     }
 }
diff --git a/ovs-driver/src/main/java/org/opendaylight/unimgr/mef/nrp/ovs/tapi/DataObjectModificationQualifier.java b/ovs-driver/src/main/java/org/opendaylight/unimgr/mef/nrp/ovs/tapi/DataObjectModificationQualifier.java
new file mode 100644 (file)
index 0000000..c5d0abe
--- /dev/null
@@ -0,0 +1,98 @@
+package org.opendaylight.unimgr.mef.nrp.ovs.tapi;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
+import org.opendaylight.unimgr.utils.CapabilitiesService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+
+import static org.opendaylight.unimgr.utils.CapabilitiesService.Capability.Mode.AND;
+import static org.opendaylight.unimgr.utils.CapabilitiesService.NodeContext.NodeCapability.OVSDB;
+
+/**
+ * Class created to classify object according to its modification types.
+ *
+ * @author marek.ryznar@amartus.com
+ */
+public class DataObjectModificationQualifier {
+    private static final Logger LOG = LoggerFactory.getLogger(DataObjectModificationQualifier.class);
+    private CapabilitiesService capabilitiesService;
+
+    public DataObjectModificationQualifier(DataBroker dataBroker){
+        capabilitiesService = new CapabilitiesService(dataBroker);
+    }
+
+    private Function<Node,Boolean> isOvs = node -> capabilitiesService.node(node).isSupporting(AND, OVSDB);
+
+    protected void checkNodes(List<DataObjectModification> nodes, Map<TerminationPoint,String> toAddMap, Map<TerminationPoint,String> toUpdateMap, Map<TerminationPoint,String> toDeleteMap){
+        Node n;
+        for(DataObjectModification node: nodes){
+            switch(node.getModificationType()){
+                //new ovs node
+                case WRITE :{
+                    n = (Node) node.getDataAfter();
+                    if(!isOvs.apply(n) || n.getTerminationPoint()==null)
+                        break;
+                    String bridgeName = n.getAugmentation(OvsdbBridgeAugmentation.class).getBridgeName().getValue();
+                    n.getTerminationPoint().forEach(tp -> toAddMap.put(tp,bridgeName));
+                } break;
+                case SUBTREE_MODIFIED:{
+                    checkTerminationPoints(node, toAddMap, toUpdateMap, toDeleteMap);
+                } break;
+                //whole ovs-node eg. s1 deleted
+                case DELETE:{
+                    n = (Node) node.getDataBefore();
+                    if(!isOvs.apply(n) || n.getTerminationPoint()==null)
+                        break;
+                    String bridgeName = n.getAugmentation(OvsdbBridgeAugmentation.class).getBridgeName().getValue();
+                    n.getTerminationPoint().forEach(tp -> toDeleteMap.put(tp,bridgeName));
+                } break;
+                default:{
+                    LOG.debug("Not supported modification type: {}",node.getModificationType());
+                } break;
+            }
+        }
+    }
+
+    private void checkTerminationPoints(DataObjectModification node, Map<TerminationPoint,String> toAddMap, Map<TerminationPoint,String> toUpdateMap, Map<TerminationPoint,String> toDeleteMap){
+        Node n = (Node) node.getDataAfter();
+        if(!isOvs.apply(n))
+            return ;
+        String bridgeName = n.getAugmentation(OvsdbBridgeAugmentation.class).getBridgeName().getValue();
+        Collection<DataObjectModification<? extends DataObject>> modifiedChildren = node.getModifiedChildren();
+
+        TerminationPoint terminationPoint;
+        for(DataObjectModification tp: modifiedChildren) {
+            if(!tp.getDataType().equals(TerminationPoint.class))
+                continue;
+            switch (tp.getModificationType()) {
+                //new port added eg. s1-eth7
+                case WRITE: {
+                    terminationPoint = (TerminationPoint) tp.getDataAfter();
+                    toAddMap.put(terminationPoint,bridgeName);
+                } break;
+                case SUBTREE_MODIFIED: {
+                    terminationPoint = (TerminationPoint) tp.getDataAfter();
+                    if (!tp.getDataBefore().equals(tp.getDataAfter()))
+                        toUpdateMap.put(terminationPoint,bridgeName);
+                } break;
+                case DELETE: {
+                    terminationPoint = (TerminationPoint) tp.getDataBefore();
+                    toDeleteMap.put(terminationPoint,bridgeName);
+                } break;
+                default: {
+                    LOG.debug("Not supported modification type: SUBTREE_MODIFIED.{}",tp.getModificationType());
+                } break;
+            }
+        }
+    }
+}
diff --git a/ovs-driver/src/main/java/org/opendaylight/unimgr/mef/nrp/ovs/tapi/TopologyDataHandler.java b/ovs-driver/src/main/java/org/opendaylight/unimgr/mef/nrp/ovs/tapi/TopologyDataHandler.java
new file mode 100644 (file)
index 0000000..8309409
--- /dev/null
@@ -0,0 +1,260 @@
+/*
+ * Copyright (c) 2017 Cisco Systems Inc and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.unimgr.mef.nrp.ovs.tapi;
+
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import org.opendaylight.controller.md.sal.binding.api.*;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.unimgr.mef.nrp.common.NrpDao;
+import org.opendaylight.unimgr.mef.nrp.common.ResourceNotAvailableException;
+import org.opendaylight.unimgr.mef.nrp.ovs.transaction.TopologyTransaction;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
+import org.opendaylight.yang.gen.v1.urn.mef.yang.tapicommon.rev170227.LifecycleState;
+import org.opendaylight.yang.gen.v1.urn.mef.yang.tapicommon.rev170227.TerminationDirection;
+import org.opendaylight.yang.gen.v1.urn.mef.yang.tapicommon.rev170227.UniversalId;
+import org.opendaylight.yang.gen.v1.urn.mef.yang.tapicommon.rev170227.context.attrs.ServiceInterfacePoint;
+import org.opendaylight.yang.gen.v1.urn.mef.yang.tapicommon.rev170227.context.attrs.ServiceInterfacePointBuilder;
+import org.opendaylight.yang.gen.v1.urn.mef.yang.tapicommon.rev170227.context.attrs.ServiceInterfacePointKey;
+import org.opendaylight.yang.gen.v1.urn.mef.yang.tapicommon.rev170227.service._interface.point.StateBuilder;
+import org.opendaylight.yang.gen.v1.urn.mef.yang.tapitopology.rev170227.node.OwnedNodeEdgePoint;
+import org.opendaylight.yang.gen.v1.urn.mef.yang.tapitopology.rev170227.node.OwnedNodeEdgePointBuilder;
+import org.opendaylight.yang.gen.v1.urn.mef.yang.tapitopology.rev170227.node.OwnedNodeEdgePointKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeInternal;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import java.util.*;
+import java.util.function.BiConsumer;
+import java.util.stream.Collectors;
+
+/**
+ * TopologyDataHandler listens to ovsdb topology and propagate significant changes to presto ext topology.
+ *
+ * @author bartosz.michalik@amartus.com
+ */
+public class TopologyDataHandler implements DataTreeChangeListener<Node> {
+    private static final Logger LOG = LoggerFactory.getLogger(TopologyDataHandler.class);
+    private static final String OVS_NODE = "ovs-node";
+    private static final String DELIMETER = ":";
+    private static final InstanceIdentifier<Topology> OVSDB_TOPO_IID = InstanceIdentifier
+            .create(NetworkTopology.class)
+            .child(Topology.class, new TopologyKey(new TopologyId(new Uri("ovsdb:1"))));
+    private ListenerRegistration<TopologyDataHandler> registration;
+    private TopologyTransaction topologyTransaction;
+    private DataObjectModificationQualifier dataObjectModificationQualifier;
+
+    private final DataBroker dataBroker;
+
+    public TopologyDataHandler(DataBroker dataBroker) {
+        Objects.requireNonNull(dataBroker);
+        this.dataBroker = dataBroker;
+        topologyTransaction = new TopologyTransaction(dataBroker);
+    }
+
+    public void init() {
+        ReadWriteTransaction tx = dataBroker.newReadWriteTransaction();
+
+        NrpDao dao = new NrpDao(tx);
+        dao.createSystemNode(OVS_NODE, null);
+
+        Futures.addCallback(tx.submit(), new FutureCallback<Void>() {
+            @Override
+            public void onSuccess(@Nullable Void result) {
+                LOG.info("Node {} created", OVS_NODE);
+            }
+
+            @Override
+            public void onFailure(Throwable t) {
+                LOG.error("No node created due to the error", t);
+            }
+        });
+
+        dataObjectModificationQualifier = new DataObjectModificationQualifier(dataBroker);
+        registerOvsdbTreeListener();
+    }
+
+    private void registerOvsdbTreeListener(){
+        InstanceIdentifier<Node> nodeId = OVSDB_TOPO_IID.child(Node.class);
+        registration = dataBroker.registerDataTreeChangeListener(new DataTreeIdentifier<>(LogicalDatastoreType.OPERATIONAL, nodeId), this);
+    }
+
+    public void close() {
+        ReadWriteTransaction tx = dataBroker.newReadWriteTransaction();
+
+        NrpDao dao = new NrpDao(tx);
+        dao.removeNode(OVS_NODE, true);
+
+        Futures.addCallback(tx.submit(), new FutureCallback<Void>() {
+            @Override
+            public void onSuccess(@Nullable Void result) {
+                LOG.info("Node {} deleted", OVS_NODE);
+            }
+
+            @Override
+            public void onFailure(Throwable t) {
+                LOG.error("No node deleted due to the error", t);
+            }
+        });
+
+        if(registration != null) {
+            LOG.info("closing netconf tree listener");
+            registration.close();
+        }
+    }
+
+    @Override
+    public void onDataTreeChanged(@Nonnull Collection<DataTreeModification<Node>> collection) {
+        final Map<TerminationPoint,String> toAddMap = new HashMap<>();
+        final Map<TerminationPoint,String> toDeleteMap = new HashMap<>();
+        final Map<TerminationPoint,String> toUpdateMap = new HashMap<>();
+
+        List<DataObjectModification> nodes = collection.stream()
+                .map(DataTreeModification::getRootNode)
+                .collect(Collectors.toList());
+
+        dataObjectModificationQualifier.checkNodes(nodes,toAddMap,toUpdateMap,toDeleteMap);
+
+        executeDbAction(addAction,toAddMap);
+        executeDbAction(updateAction,toUpdateMap);
+        executeDbAction(deleteAction,toDeleteMap);
+    }
+
+    BiConsumer<Map<TerminationPoint,String>,NrpDao> updateAction = (map,dao) -> {
+        map.entrySet()
+                .forEach(entry -> {
+                    String nepId = OVS_NODE + DELIMETER + getFullPortName(entry.getValue(), entry.getKey().getTpId().getValue());
+                    OwnedNodeEdgePoint nep;
+                    if(dao.hasSip(nepId)){
+                        nep = createNep(nepId);
+                        dao.updateNep(OVS_NODE,nep);
+                    } else {
+                        addEndpoint(dao,nepId);
+                    }
+                });
+    };
+
+    BiConsumer<Map<TerminationPoint,String>,NrpDao> deleteAction = (map,dao) -> {
+        map.entrySet()
+                .forEach(entry -> {
+                    String nepId = OVS_NODE + DELIMETER + getFullPortName(entry.getValue(), entry.getKey().getTpId().getValue());
+                    dao.removeNep(OVS_NODE,nepId,true);
+                });
+    };
+
+    BiConsumer<Map<TerminationPoint,String>,NrpDao> addAction = (map,dao) -> {
+        List<OwnedNodeEdgePoint> newNeps = getNewNeps(map);
+        newNeps.forEach(nep -> addEndpoint(dao,nep.getKey().getUuid().getValue()));
+    };
+
+    private void executeDbAction(BiConsumer<Map<TerminationPoint,String>,NrpDao> action,Map<TerminationPoint,String> map){
+        if(map.isEmpty())
+            return ;
+        final ReadWriteTransaction topoTx = dataBroker.newReadWriteTransaction();
+        NrpDao dao = new NrpDao(topoTx);
+
+        action.accept(map,dao);
+
+        Futures.addCallback(topoTx.submit(), new FutureCallback<Void>() {
+
+            @Override
+            public void onSuccess(@Nullable Void result) {
+                LOG.debug("Ovs TAPI node action executed successfully");
+            }
+
+            @Override
+            public void onFailure(Throwable t) {
+                LOG.warn("Ovs TAPI node action execution failed due to an error", t);
+            }
+        });
+    }
+
+    private String getFullPortName(String switchName, String portName){
+        return switchName + DELIMETER + portName;
+    }
+
+    private void addEndpoint(NrpDao dao, String nepName) {
+        ServiceInterfacePoint sip = createSip(nepName);
+
+        dao.addSip(sip);
+        dao.updateNep(OVS_NODE, nep(nepName, sip.getUuid()));
+    }
+
+    private OwnedNodeEdgePoint nep(String nepName, UniversalId sipUuid) {
+        UniversalId uuid = new UniversalId(nepName);
+        return new OwnedNodeEdgePointBuilder()
+                .setUuid(uuid)
+                .setKey(new OwnedNodeEdgePointKey(uuid))
+                .setMappedServiceInterfacePoint(Collections.singletonList(sipUuid))
+                .build();
+    }
+
+    private ServiceInterfacePoint createSip(String nep) {
+        UniversalId uuid = new UniversalId( "sip" + DELIMETER + nep);
+        return new ServiceInterfacePointBuilder()
+                .setUuid(uuid)
+                .setKey(new ServiceInterfacePointKey(uuid))
+                .setState(new StateBuilder().setLifecycleState(LifecycleState.Installed).build())
+                .setDirection(TerminationDirection.Bidirectional)
+                .build();
+    }
+
+    private OwnedNodeEdgePoint createNep(String nepId){
+        OwnedNodeEdgePointBuilder tpBuilder = new OwnedNodeEdgePointBuilder();
+        UniversalId tpId = new UniversalId(OVS_NODE + DELIMETER + nepId);
+        return tpBuilder
+                .setUuid(tpId)
+                .setKey(new OwnedNodeEdgePointKey(tpId))
+                .build();
+    }
+
+    private List<OwnedNodeEdgePoint> getNewNeps(Map<TerminationPoint,String> toAddMap){
+        return toAddMap.entrySet().stream()
+                .map(entry -> createNep(getFullPortName(entry.getValue(),entry.getKey().getTpId().getValue())) )
+                .collect(Collectors.toList());
+    }
+
+    //TODO: write better implementation
+    private boolean isNep(TerminationPoint terminationPoint){
+        OvsdbTerminationPointAugmentation ovsdbTerminationPoint = terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class);
+        if( ovsdbTerminationPoint==null || (ovsdbTerminationPoint.getInterfaceType()!=null && ovsdbTerminationPoint.getInterfaceType().equals(InterfaceTypeInternal.class))) {
+            return false;
+        }
+
+        if( ovsdbTerminationPoint.getOfport() == null )
+            return false;
+
+        String ofPortNumber = ovsdbTerminationPoint.getOfport().toString();
+        try {
+            org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node node = topologyTransaction.readNode(terminationPoint.getTpId().getValue());
+            String ofPortName = node.getId().getValue()+":"+ofPortNumber;
+            List<Link> links = topologyTransaction.readLinks(node);
+            return !links.stream()
+                    .anyMatch(link -> link.getSource().getSourceTp().getValue().equals(ofPortName));
+        } catch (ResourceNotAvailableException e) {
+            LOG.warn(e.getMessage());
+        }
+        return false;
+    }
+
+    public static String getOvsNode() {
+        return OVS_NODE;
+    }
+}
\ No newline at end of file
index 18ed0f508ddaaaf04cfaa0892004d4d98c07de7f..1f27b69261cb8a2c41be9d90445ef5ff8ac621ff 100644 (file)
@@ -86,6 +86,24 @@ public class TopologyTransaction {
         throw new ResourceNotAvailableException(String.format(NODE_NOT_FOUND_ERROR_MESSAGE, portName));
     }
 
+    public Node readNodeOF(String ofportName) throws ResourceNotAvailableException {
+        String ofNodeName = ofportName.split(":")[0]+":"+ofportName.split(":")[1];
+        Nodes nodes = readOpenFLowTopology(dataBroker);
+        if(nodes != null){
+            for(Node node: nodes.getNode()){
+                if(node.getId().getValue().equals(ofNodeName)){
+                    return node;
+                }
+            }
+        } else {
+            LOG.warn(String.format(NODE_NOT_FOUND_ERROR_MESSAGE, "OpenFlow"));
+            throw new ResourceNotAvailableException(String.format(NODE_NOT_FOUND_ERROR_MESSAGE, "OpenFlow"));
+        }
+
+        LOG.warn(String.format(NODE_NOT_FOUND_ERROR_MESSAGE, ofportName));
+        throw new ResourceNotAvailableException(String.format(NODE_NOT_FOUND_ERROR_MESSAGE, ofportName));
+    }
+
     /**
      * Returns links associated with specified node
      *
@@ -132,4 +150,9 @@ public class TopologyTransaction {
     private InstanceIdentifier<Nodes> getNodesInstanceId() {
         return InstanceIdentifier.builder(Nodes.class).build();
     }
+
+    public static Nodes readOpenFLowTopology(DataBroker dataBroker){
+        InstanceIdentifier instanceIdentifier = InstanceIdentifier.builder(Nodes.class).build();
+        return (Nodes) MdsalUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION,instanceIdentifier);
+    }
 }
index 3da24ea52e34a3744d77f080434da06389610590..dde3067da47cdf192d04c665d36e4155c715ee52 100644 (file)
@@ -21,7 +21,10 @@ import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Optional;
 import java.util.stream.Collectors;
 
 /**
index 0251a5cfd00c85a0c2e009f692705a9dbec3fe43..0ea0ae5424f3d5e1d20673ba443ee0cecef3535a 100644 (file)
@@ -23,7 +23,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
index 2a74a6678fc5679dd1cf3a903e227d9cb2e18666..41b69a12d7cbf7400aecfe9a26aea8772f086338 100644 (file)
@@ -16,4 +16,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL
             <argument ref="dataBroker" />
         </bean>
     </service>
+    <bean id="topologyHandler" class="org.opendaylight.unimgr.mef.nrp.ovs.tapi.TopologyDataHandler" init-method="init" destroy-method="close">
+        <argument ref="dataBroker" />
+    </bean>
 </blueprint>
diff --git a/ovs-driver/src/test/java/org/opendaylight/unimgr/mef/nrp/ovs/DataStoreTestUtils.java b/ovs-driver/src/test/java/org/opendaylight/unimgr/mef/nrp/ovs/DataStoreTestUtils.java
new file mode 100644 (file)
index 0000000..513bd7a
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2017 Cisco Systems Inc and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.unimgr.mef.nrp.ovs;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.annotation.Nullable;
+
+import static org.junit.Assert.fail;
+
+/**
+ * @author marek.ryznar@amartus.com
+ */
+public class DataStoreTestUtils {
+    private static final Logger LOG = LoggerFactory.getLogger(DataStoreTestUtils.class);
+
+    public static <T extends DataObject> T read(InstanceIdentifier instanceIdentifier, DataBroker dataBroker){
+        return read(instanceIdentifier,dataBroker,LogicalDatastoreType.OPERATIONAL);
+    }
+
+    public static <T extends DataObject> T readConfig(InstanceIdentifier instanceIdentifier, DataBroker dataBroker){
+        return read(instanceIdentifier,dataBroker,LogicalDatastoreType.CONFIGURATION);
+    }
+
+    public static <T extends DataObject> void write(T object, InstanceIdentifier<T> instanceIdentifier, DataBroker dataBroker){
+        ReadWriteTransaction transaction = dataBroker.newReadWriteTransaction();
+        transaction.put(LogicalDatastoreType.OPERATIONAL,instanceIdentifier,object,true);
+
+        Futures.addCallback(transaction.submit(), new FutureCallback<Void>() {
+            @Override
+            public void onSuccess(@Nullable Void result) {
+                LOG.debug("Object: {} created.",object.toString());
+            }
+
+            @Override
+            public void onFailure(Throwable t) {
+                LOG.debug("Object: {} wasn't created due to a error: {}",object.toString(), t.getMessage());
+                fail("Object  wasn't created due to a error: "+ t.getMessage());
+            }
+        });
+    }
+
+    public static void delete(InstanceIdentifier instanceIdentifier, DataBroker dataBroker){
+        ReadWriteTransaction transaction = dataBroker.newReadWriteTransaction();
+        transaction.delete(LogicalDatastoreType.OPERATIONAL, instanceIdentifier);
+
+        Futures.addCallback(transaction.submit(), new FutureCallback<Void>() {
+            @Override
+            public void onSuccess(@Nullable Void result) {
+                LOG.debug("Object: {} deleted.",instanceIdentifier.toString());
+            }
+
+            @Override
+            public void onFailure(Throwable t) {
+                LOG.debug("Object: {} wasn't deleted due to a error: {}",instanceIdentifier.toString(), t.getMessage());
+                fail("Object wasn't deleted due to a error: "+ t.getMessage());
+            }
+        });
+    }
+
+    private static <T extends DataObject> T read(InstanceIdentifier instanceIdentifier, DataBroker dataBroker, LogicalDatastoreType type){
+        ReadOnlyTransaction transaction = dataBroker.newReadOnlyTransaction();
+        try {
+            Optional<T> opt = (Optional<T>) transaction.read(type,instanceIdentifier).checkedGet();
+            if (opt.isPresent()){
+                return opt.get();
+            } else {
+                fail("Could not find object");
+            }
+        } catch (Exception e) {
+            fail("Could not find object, "+e.getMessage());
+        }
+        return null;
+    }
+}
diff --git a/ovs-driver/src/test/java/org/opendaylight/unimgr/mef/nrp/ovs/FlowTopologyTestUtils.java b/ovs-driver/src/test/java/org/opendaylight/unimgr/mef/nrp/ovs/FlowTopologyTestUtils.java
new file mode 100644 (file)
index 0000000..547db49
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2017 Cisco Systems Inc and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.unimgr.mef.nrp.ovs;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.*;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.link.attributes.DestinationBuilder;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.link.attributes.SourceBuilder;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyBuilder;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.LinkBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import java.util.List;
+
+/**
+ * @author marek.ryznar@amartus.com
+ */
+public class FlowTopologyTestUtils {
+    private static final TopologyId flowTopologyId = new TopologyId(new Uri("flow:1"));
+    private static final InstanceIdentifier<Topology> FLOW_TOPO_IID = InstanceIdentifier
+            .create(NetworkTopology.class)
+            .child(Topology.class, new TopologyKey(flowTopologyId));
+    private static final String prefix = "openflow:";
+
+    /**
+     * Creates flow topology with link nodes (Links between ovs).
+     */
+    public static void createFlowTopology(DataBroker dataBroker, List<Link> links){
+        TopologyBuilder topologyBuilder = new TopologyBuilder();
+        topologyBuilder.setTopologyId(flowTopologyId);
+        topologyBuilder.setLink(links);
+        Topology topology = topologyBuilder.build();
+        DataStoreTestUtils.write(topology,FLOW_TOPO_IID,dataBroker);
+    }
+
+    public static Link createLink(String sourceNode, Long sourcePort, String destNode, Long destPort){
+        LinkBuilder linkBuilder = new LinkBuilder();
+        String sourcePortName = prefix + sourceNode + ":" + sourcePort.toString();
+        String destPortName =  prefix + destNode + ":" + destPort;
+
+        linkBuilder.setLinkId(new LinkId(sourcePortName));
+
+        SourceBuilder sourceBuilder = new SourceBuilder();
+        sourceBuilder.setSourceTp(new TpId(sourcePortName));
+        sourceBuilder.setSourceNode(new NodeId(prefix+sourceNode));
+        linkBuilder.setSource(sourceBuilder.build());
+
+        DestinationBuilder destinationBuilder = new DestinationBuilder();
+        destinationBuilder.setDestTp(new TpId(destPortName));
+        destinationBuilder.setDestNode(new NodeId(prefix+destNode));
+        linkBuilder.setDestination(destinationBuilder.build());
+
+        return linkBuilder.build();
+    }
+
+}
diff --git a/ovs-driver/src/test/java/org/opendaylight/unimgr/mef/nrp/ovs/OpenFlowTopologyTestUtils.java b/ovs-driver/src/test/java/org/opendaylight/unimgr/mef/nrp/ovs/OpenFlowTopologyTestUtils.java
new file mode 100644 (file)
index 0000000..581c473
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2017 Cisco Systems Inc and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.unimgr.mef.nrp.ovs;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.unimgr.utils.MdsalUtils;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnectorBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.PortNumberUni;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author marek.ryznar@amartus.com
+ */
+public class OpenFlowTopologyTestUtils {
+
+    public static void createOpenFlowNodes(List<Node> nodeList, DataBroker dataBroker){
+        NodesBuilder nodesBuilder = new NodesBuilder();
+        nodesBuilder.setNode(nodeList);
+        Nodes nodes = nodesBuilder.build();
+        InstanceIdentifier<Nodes> nodesIId = InstanceIdentifier.builder(Nodes.class).build();
+        DataStoreTestUtils.write(nodes,nodesIId,dataBroker);
+    }
+
+    public static org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node createOpenFlowNode(String oFName, List<NodeConnector> nodeConnectorList){
+        org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder nodeBuilder =
+                new org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder();
+        org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId nodeId =
+                new org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId(oFName);
+        nodeBuilder.setId(nodeId);
+        nodeBuilder.setKey(new org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey(nodeId));
+        nodeBuilder.setNodeConnector(nodeConnectorList);
+        nodeBuilder.addAugmentation(FlowCapableNode.class,createFlowCapableNode());
+        return nodeBuilder.build();
+    }
+
+    public static NodeConnector createNodeConnector(String ofBridgeName, Long portNumber, String ovsdbPortName){
+        NodeConnectorBuilder nodeConnectorBuilder = new NodeConnectorBuilder();
+        String ofPortName = ofBridgeName + ":" + portNumber.toString();
+        NodeConnectorId nodeConnectorId = new NodeConnectorId(ofPortName);
+        nodeConnectorBuilder.setId(nodeConnectorId);
+        nodeConnectorBuilder.setKey(new NodeConnectorKey(nodeConnectorId));
+        nodeConnectorBuilder.addAugmentation(FlowCapableNodeConnector.class,createFlowCapableNodeConnector(ovsdbPortName,portNumber));
+        return nodeConnectorBuilder.build();
+    }
+
+    private static FlowCapableNodeConnector createFlowCapableNodeConnector(String ovsdbName, Long portNumber){
+        FlowCapableNodeConnectorBuilder flowCapableNodeConnectorBuilder = new FlowCapableNodeConnectorBuilder();
+        flowCapableNodeConnectorBuilder.setName(ovsdbName);
+        flowCapableNodeConnectorBuilder.setPortNumber(new PortNumberUni(portNumber));
+        return flowCapableNodeConnectorBuilder.build();
+    }
+
+    public static FlowCapableNode createFlowCapableNode(){
+        FlowCapableNodeBuilder flowCapableNodeBuilder = new FlowCapableNodeBuilder();
+
+        flowCapableNodeBuilder.setTable(createOfTable());
+        return flowCapableNodeBuilder.build();
+    }
+
+    private static List<Table> createOfTable(){
+        List<Table> tables = new ArrayList<>();
+        TableBuilder tableBuilder = new TableBuilder();
+        tableBuilder.setId(Short.valueOf("0"));
+        List<Flow> flows = new ArrayList<>();
+        tableBuilder.setFlow(flows);
+        tables.add(tableBuilder.build());
+        return tables;
+    }
+
+    public static InstanceIdentifier<NodeConnector> getNodeConnectorInstanceIdentifier(String ofBridgeName, String nodeConnectorId){
+        return InstanceIdentifier.builder(Nodes.class)
+                .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node.class,
+                        new org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey(
+                                new org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId(ofBridgeName)))
+                .child(NodeConnector.class, new NodeConnectorKey(new NodeConnectorId(nodeConnectorId)))
+                .build();
+    }
+}
diff --git a/ovs-driver/src/test/java/org/opendaylight/unimgr/mef/nrp/ovs/OvsdbTopologyTestUtils.java b/ovs-driver/src/test/java/org/opendaylight/unimgr/mef/nrp/ovs/OvsdbTopologyTestUtils.java
new file mode 100644 (file)
index 0000000..be69813
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2017 Cisco Systems Inc and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.unimgr.mef.nrp.ovs;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.*;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyBuilder;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointBuilder;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import java.util.List;
+
+/**
+ * @author marek.ryznar@amartus.com
+ */
+public class OvsdbTopologyTestUtils {
+    private static final TopologyId ovsdbTopologyId = new TopologyId(new Uri("ovsdb:1"));
+    private static final InstanceIdentifier ovsdbTopology =
+            InstanceIdentifier
+                    .create(NetworkTopology.class)
+                    .child(Topology.class, new TopologyKey(ovsdbTopologyId));
+
+    /**
+     * Ovsdb topology initializator.
+     */
+    public static void createOvsdbTopology(DataBroker dataBroker){
+        TopologyBuilder topologyBuilder = new TopologyBuilder();
+        topologyBuilder.setTopologyId(ovsdbTopologyId);
+        Topology topology = topologyBuilder.build();
+        DataStoreTestUtils.write(topology,ovsdbTopology, dataBroker);
+    }
+
+    public static void writeBridge(Node node, DataBroker dataBroker){
+        InstanceIdentifier bridgeIid = getNodeInstanceIdentifier(node.getNodeId());
+        DataStoreTestUtils.write(node,bridgeIid,dataBroker);
+    }
+
+    public static Node createBridge(String nodeId, List<TerminationPoint> tps){
+        NodeBuilder nodeBuilder = new NodeBuilder();
+        nodeBuilder.setNodeId(new NodeId(nodeId));
+        nodeBuilder.setTerminationPoint(tps);
+        nodeBuilder.addAugmentation(OvsdbBridgeAugmentation.class,createOvsdbBridgeAugmentation(nodeId));
+        return nodeBuilder.build();
+    }
+
+    public static InstanceIdentifier getNodeInstanceIdentifier(NodeId nodeId){
+        return InstanceIdentifier
+                .builder(NetworkTopology.class)
+                .child(Topology.class,
+                        new TopologyKey(ovsdbTopologyId))
+                .child(Node.class,
+                        new NodeKey(nodeId))
+                .build();
+    }
+
+    public static InstanceIdentifier getPortInstanceIdentifier(String nodeName, String portName){
+        return getNodeInstanceIdentifier(new NodeId(nodeName))
+                .child(TerminationPoint.class,
+                        new TerminationPointKey(new TpId(portName)));
+    }
+
+    private static OvsdbBridgeAugmentation createOvsdbBridgeAugmentation(String ovsdbBridgeName){
+        OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder = new OvsdbBridgeAugmentationBuilder();
+        ovsdbBridgeAugmentationBuilder.setBridgeName(new OvsdbBridgeName(ovsdbBridgeName));
+        return ovsdbBridgeAugmentationBuilder.build();
+    }
+
+    public static TerminationPoint createTerminationPoint(String tpId, Long ofName) {
+        TerminationPointBuilder terminationPointBuilder = new TerminationPointBuilder();
+        terminationPointBuilder.setTpId(new TpId(tpId));
+        terminationPointBuilder.setKey(new TerminationPointKey(new TpId(tpId)));
+        terminationPointBuilder.addAugmentation(OvsdbTerminationPointAugmentation.class, createOvsdbTerminationPointAugmentation(ofName));
+        TerminationPoint terminationPoint = terminationPointBuilder.build();
+        return terminationPoint;
+    }
+
+    private static OvsdbTerminationPointAugmentation createOvsdbTerminationPointAugmentation(Long ofPort) {
+        OvsdbTerminationPointAugmentationBuilder ovsdbTerminationPointAugmentationBuilder = new OvsdbTerminationPointAugmentationBuilder();
+        ovsdbTerminationPointAugmentationBuilder.setOfport(ofPort);
+        return ovsdbTerminationPointAugmentationBuilder.build();
+    }
+}
diff --git a/ovs-driver/src/test/java/org/opendaylight/unimgr/mef/nrp/ovs/activator/OvsActivatorTest.java b/ovs-driver/src/test/java/org/opendaylight/unimgr/mef/nrp/ovs/activator/OvsActivatorTest.java
new file mode 100644 (file)
index 0000000..989551f
--- /dev/null
@@ -0,0 +1,290 @@
+/*
+ * Copyright (c) 2017 Cisco Systems Inc and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.unimgr.mef.nrp.ovs.activator;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.test.AbstractDataBrokerTest;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.unimgr.mef.nrp.api.EndPoint;
+import org.opendaylight.unimgr.mef.nrp.common.ResourceNotAvailableException;
+import org.opendaylight.unimgr.mef.nrp.ovs.FlowTopologyTestUtils;
+import org.opendaylight.unimgr.mef.nrp.ovs.OpenFlowTopologyTestUtils;
+import org.opendaylight.unimgr.mef.nrp.ovs.OvsdbTopologyTestUtils;
+import org.opendaylight.unimgr.mef.nrp.ovs.util.OpenFlowUtils;
+import org.opendaylight.unimgr.utils.MdsalUtils;
+import org.opendaylight.yang.gen.v1.urn.mef.yang.nrm_connectivity.rev170227.PositiveInteger;
+import org.opendaylight.yang.gen.v1.urn.mef.yang.nrm_connectivity.rev170227.cg.eth.frame.flow.cpa.aspec.CeVlanIdList;
+import org.opendaylight.yang.gen.v1.urn.mef.yang.nrm_connectivity.rev170227.vlan.id.listing.VlanIdList;
+import org.opendaylight.yang.gen.v1.urn.mef.yang.nrp_interface.rev170227.NrpCreateConnectivityServiceEndPointAttrs;
+import org.opendaylight.yang.gen.v1.urn.mef.yang.nrp_interface.rev170227.nrp.create.connectivity.service.end.point.attrs.NrpCgEthFrameFlowCpaAspec;
+import org.opendaylight.yang.gen.v1.urn.mef.yang.tapicommon.rev170227.UniversalId;
+import org.opendaylight.yang.gen.v1.urn.mef.yang.tapiconnectivity.rev170227.ConnectivityServiceEndPoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.function.BiConsumer;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+/**
+ * @author marek.ryznar@amartus.com
+ */
+public class OvsActivatorTest extends AbstractDataBrokerTest{
+
+    private DataBroker dataBroker;
+    private OvsActivator ovsActivator;
+    private static final String port1Name = "sip:ovs-node:s1:s1-eth1";
+    private static final String port2Name = "sip:ovs-node:s5:s5-eth1";
+    private static final String ofPort1Name = "openflow:1";
+    private static final String ofPort2Name = "openflow:5";
+    private static final Integer expectedVlanId = 200;
+    private static final String serviceId = "serviceId";
+
+    private static final String interswitchName = "interswitch-openflow";
+    private static final String vlanName = "vlan-openflow";
+    private static final String dropName = "default-DROP";
+
+    List<String> of1InterwitchPorts = Arrays.asList("openflow:1:3", "openflow:1:4", "openflow:1:5");
+    List<String> of2InterwitchPorts = Arrays.asList("openflow:5:3", "openflow:5:4");
+
+    @Before
+    public void setUp(){
+        //given
+        dataBroker = getDataBroker();
+        ovsActivator = new OvsActivator(dataBroker);
+        OvsdbTopologyTestUtils.createOvsdbTopology(dataBroker);
+        initTopologies();
+        FlowTopologyTestUtils.createFlowTopology(dataBroker, getLinkList());
+    }
+
+    @Test
+    public void testActivate(){
+        //given
+        List<EndPoint> endPoints = prepareEndpoints();
+
+        //when
+        try {
+            ovsActivator.activate(endPoints,serviceId);
+        } catch (ResourceNotAvailableException e) {
+            fail(e.getMessage());
+        } catch (TransactionCommitFailedException e) {
+            fail(e.getMessage());
+        }
+
+        //then
+        Nodes nodes = readOpenFLowTopology(dataBroker);
+        checkTable(nodes,activated);
+        System.out.println("Before deactivation: "+ nodes.toString());
+
+        //when
+        try {
+            ovsActivator.deactivate(endPoints, serviceId);
+        } catch (TransactionCommitFailedException e) {
+            fail(e.getMessage());
+        } catch (ResourceNotAvailableException e) {
+            fail(e.getMessage());
+        }
+        nodes = readOpenFLowTopology(dataBroker);
+        checkTable(nodes,deactivated);
+        System.out.println("After deactivation: "+ nodes.toString());
+    }
+
+    BiConsumer<Table,List<String>> activated = (table,interswitchPorts) -> {
+        List<Flow> flows = table.getFlow();
+        int interswitchPortCount = interswitchPorts.size();
+        //vlan & interwitch + 1 vlan + 1 drop
+        int flowCount = interswitchPortCount * 2 + 2;
+        assertEquals(flowCount,flows.size());
+        List<Flow> interswitchFlows = flows.stream()
+                .filter(flow -> flow.getId().getValue().contains(interswitchName))
+                .collect(Collectors.toList());
+        assertEquals(interswitchPortCount,interswitchFlows.size());
+
+        List<Flow> vlanFlows = flows.stream()
+                .filter(flow -> flow.getId().getValue().contains(vlanName))
+                .filter(flow -> flow.getMatch().getVlanMatch().getVlanId().getVlanId().getValue().equals(expectedVlanId))
+                .collect(Collectors.toList());
+        assertEquals(interswitchPortCount+1,vlanFlows.size());
+
+        assertTrue(flows.stream().anyMatch(flow -> flow.getId().getValue().equals(dropName)));
+    };
+
+    BiConsumer<Table,List<String>> deactivated = (table,interswitchPorts) -> {
+        List<Flow> flows = table.getFlow();
+        boolean hasVlanFlows = flows.stream()
+                .filter(flow -> flow.getId().getValue().contains(serviceId+"-"+vlanName))
+                .anyMatch(this::hasVlanMatch);
+        assertFalse(hasVlanFlows);
+    };
+
+    private boolean hasVlanMatch(Flow flow){
+        if(flow.getMatch().getVlanMatch().getVlanId().getVlanId().getValue().equals(expectedVlanId)){
+            return true;
+        }
+        return false;
+    }
+
+    private void checkTable(Nodes nodes, BiConsumer<Table,List<String>> checkTable){
+        nodes.getNode()
+                .forEach(node -> {
+                    try {
+                        Table t = OpenFlowUtils.getTable(node);
+                        if(node.getKey().getId().getValue().equals(ofPort1Name)){
+                            checkTable.accept(t,of1InterwitchPorts);
+                        } else if(node.getKey().getId().getValue().equals(ofPort2Name)){
+                            checkTable.accept(t,of2InterwitchPorts);
+                        }
+                    } catch (ResourceNotAvailableException e) {
+                        fail(e.getMessage());
+                    }
+                });
+    }
+
+    private List<EndPoint> prepareEndpoints(){
+        List<EndPoint> endPoints = new ArrayList<>();
+        endPoints.add(mockEndPoint(port1Name));
+        endPoints.add(mockEndPoint(port2Name));
+        return endPoints;
+    }
+
+    private EndPoint mockEndPoint(String portName){
+        ConnectivityServiceEndPoint connectivityServiceEndPoint = mock(ConnectivityServiceEndPoint.class);
+        NrpCreateConnectivityServiceEndPointAttrs attrs = mock(NrpCreateConnectivityServiceEndPointAttrs.class);
+        //UNI port mock
+        when(connectivityServiceEndPoint.getServiceInterfacePoint())
+                .thenReturn(new UniversalId(portName));
+
+        //Vlan Id mock
+        VlanIdList vlanIdList = mock(VlanIdList.class);
+        when(vlanIdList.getVlanId())
+                .thenReturn(PositiveInteger.getDefaultInstance(expectedVlanId.toString()));
+
+        List<VlanIdList> vlanIds = new ArrayList<>();
+        vlanIds.add(vlanIdList);
+
+        CeVlanIdList ceVlanIdList = mock(CeVlanIdList.class);
+        when(ceVlanIdList.getVlanIdList())
+                .thenReturn(vlanIds);
+
+        NrpCgEthFrameFlowCpaAspec nrpCgEthFrameFlowCpaAspec = mock(NrpCgEthFrameFlowCpaAspec.class);
+        when(nrpCgEthFrameFlowCpaAspec.getCeVlanIdList())
+                .thenReturn(ceVlanIdList);
+
+        when(attrs.getNrpCgEthFrameFlowCpaAspec())
+                .thenReturn(nrpCgEthFrameFlowCpaAspec);
+
+        return new EndPoint(connectivityServiceEndPoint,attrs);
+    }
+
+    /**
+     * Add 5 ovsdb bridges and suitable openflow nodes
+     */
+    private void initTopologies(){
+        List<Node> bridges = new ArrayList<>();
+        List<org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node> ofNodes = new ArrayList<>();
+        bridges.add(createBridge("s1",5));
+        bridges.add(createBridge("s2",2));
+        bridges.add(createBridge("s3",4));
+        bridges.add(createBridge("s4",3));
+        bridges.add(createBridge("s5",4));
+
+        bridges.forEach(node -> {
+            OvsdbTopologyTestUtils.writeBridge(node,dataBroker);
+            ofNodes.add(createOpenFlowNode(node));
+        });
+
+        OpenFlowTopologyTestUtils.createOpenFlowNodes(ofNodes,dataBroker);
+    }
+
+    private Node createBridge(String name, int portCount){
+        List<TerminationPoint> tps = new ArrayList<>();
+        IntStream.range(1,portCount+1)
+                .forEach(i -> tps.add(OvsdbTopologyTestUtils.createTerminationPoint(name+"-eth"+i,Long.valueOf(i))));
+        return OvsdbTopologyTestUtils.createBridge(name, tps);
+    }
+
+    private org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node createOpenFlowNode(Node node){
+        String ovsdbName = node.getKey().getNodeId().getValue();
+        String ofBridgeName = getOfName(ovsdbName);
+
+        List<NodeConnector> nodeConnectors = new ArrayList<>();
+        node.getTerminationPoint()
+                .forEach(tp -> nodeConnectors.add(OpenFlowTopologyTestUtils.createNodeConnector(ofBridgeName, tp.getAugmentation(OvsdbTerminationPointAugmentation.class).getOfport(), ovsdbName+"-eth"+tp.getAugmentation(OvsdbTerminationPointAugmentation.class).getOfport())));
+
+        return OpenFlowTopologyTestUtils.createOpenFlowNode(ofBridgeName,nodeConnectors);
+    }
+
+    private String getOfName(String ovsdbName){
+        String bridgeNumber = ovsdbName.substring(1,ovsdbName.length());
+        return "openflow:"+bridgeNumber;
+    }
+
+    public static Nodes readOpenFLowTopology(DataBroker dataBroker){
+        InstanceIdentifier instanceIdentifier = InstanceIdentifier.builder(Nodes.class).build();
+        return (Nodes) MdsalUtils.read(dataBroker,LogicalDatastoreType.CONFIGURATION,instanceIdentifier);
+    }
+
+    /**
+     * @return List of links between ovswitches
+     */
+    private static List<Link> getLinkList(){
+        List<Link> linkList = new ArrayList<>();
+
+        //openflow nodes
+        String of1 = "1";
+        String of2 = "2";
+        String of3 = "3";
+        String of4 = "4";
+        String of5 = "5";
+        //ports
+        Long p1 = 1L;
+        Long p2 = 2L;
+        Long p3 = 3L;
+        Long p4 = 4L;
+        Long p5 = 5L;
+
+        //openflow:1
+        linkList.add(FlowTopologyTestUtils.createLink(of1,p3,of2,p1));
+        linkList.add(FlowTopologyTestUtils.createLink(of1,p5,of4,p1));
+        linkList.add(FlowTopologyTestUtils.createLink(of1,p4,of3,p1));
+        //openflow:2
+        linkList.add(FlowTopologyTestUtils.createLink(of2,p2,of3,p2));
+        linkList.add(FlowTopologyTestUtils.createLink(of2,p1,of1,p3));
+        //openflow:3
+        linkList.add(FlowTopologyTestUtils.createLink(of3,p4,of5,p3));
+        linkList.add(FlowTopologyTestUtils.createLink(of3,p1,of1,p4));
+        linkList.add(FlowTopologyTestUtils.createLink(of3,p3,of4,p2));
+        linkList.add(FlowTopologyTestUtils.createLink(of3,p2,of2,p2));
+        //openflow:4
+        linkList.add(FlowTopologyTestUtils.createLink(of4,p3,of5,p4));
+        linkList.add(FlowTopologyTestUtils.createLink(of4,p2,of3,p3));
+        linkList.add(FlowTopologyTestUtils.createLink(of4,p1,of1,p5));
+        //openflow:5
+        linkList.add(FlowTopologyTestUtils.createLink(of5,p3,of3,p4));
+        linkList.add(FlowTopologyTestUtils.createLink(of5,p4,of4,p3));
+
+        return linkList;
+    }
+}
diff --git a/ovs-driver/src/test/java/org/opendaylight/unimgr/mef/nrp/ovs/tapi/TopologyDataHandlerTest.java b/ovs-driver/src/test/java/org/opendaylight/unimgr/mef/nrp/ovs/tapi/TopologyDataHandlerTest.java
new file mode 100644 (file)
index 0000000..5508036
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2017 Cisco Systems Inc and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.unimgr.mef.nrp.ovs.tapi;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.test.AbstractDataBrokerTest;
+import org.opendaylight.unimgr.mef.nrp.ovs.FlowTopologyTestUtils;
+import org.opendaylight.unimgr.mef.nrp.ovs.OvsdbTopologyTestUtils;
+import org.opendaylight.yang.gen.v1.urn.mef.yang.tapicommon.rev170227.UniversalId;
+import org.opendaylight.yang.gen.v1.urn.mef.yang.tapitopology.rev170227.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.function.BiFunction;
+
+import static junit.framework.TestCase.assertNotNull;
+import static org.junit.Assert.*;
+
+/**
+ * @author marek.ryznar@amartus.com
+ */
+public class TopologyDataHandlerTest extends AbstractDataBrokerTest{
+
+    private TopologyDataHandler topologyDataHandler;
+    private DataBroker dataBroker;
+    private TopologyDataHandlerTestUtils helper;
+    private static final String ovs_nep_prefix = "ovs-node:";
+    private static final String sip_prefix = "sip:";
+    private static final String bridgeName = "br1";
+    private static final String expectedNep1 = "br1:br1-eth1";
+    private static final String expectedNep2 = "br1:br1-eth2";
+    private static String tp1Name = "br1-eth1";
+    private static int initialBridgePortCount = 3;
+
+    @Before
+    public void setUp(){
+        //given
+        dataBroker = getDataBroker();
+        helper = new TopologyDataHandlerTestUtils(dataBroker);
+
+        //helper.createOvsdbTopology();
+        OvsdbTopologyTestUtils.createOvsdbTopology(dataBroker);
+        helper.createOpenFlowNodes();
+        FlowTopologyTestUtils.createFlowTopology(dataBroker,getLinkList());
+        helper.createPrestoSystemTopology();
+
+        topologyDataHandler = new TopologyDataHandler(dataBroker);
+        topologyDataHandler.init();
+    }
+
+    @Test
+    public void testBridgeAddition(){
+        //when
+        helper.createTestBridge();
+
+        //then
+        Node ovsNode = helper.readOvsNode();
+        assertNotNull(ovsNode);
+        checkNeps(ovsNode,expectedNep1,expectedNep2);
+        checkSips(helper.readSips(),expectedNep1,expectedNep2);
+    }
+
+    @Test
+    public void testPortAddition(){
+        //given
+        String newPortName = "br1-eth4";
+        Long ofPortNumber = 4L;
+        helper.createTestBridge();
+        Node ovsNode = helper.readOvsNode();
+        assertEquals(initialBridgePortCount,ovsNode.getOwnedNodeEdgePoint().size());
+
+        //when
+        helper.addPort(bridgeName,newPortName,ofPortNumber);
+
+        //then
+        ovsNode = helper.readOvsNode();
+        assertEquals(initialBridgePortCount+1,ovsNode.getOwnedNodeEdgePoint().size());
+        checkNeps(ovsNode,"br1:"+newPortName,expectedNep1,expectedNep2);
+        checkSips(helper.readSips(),"br1:"+newPortName,expectedNep1,expectedNep2);
+    }
+
+    @Test
+    public void testBridgeRemoval(){
+        //given
+        helper.createTestBridge();
+        Node ovsNode = helper.readOvsNode();
+        assertEquals(initialBridgePortCount,ovsNode.getOwnedNodeEdgePoint().size());
+
+        //when
+        helper.deleteTestBridge();
+
+        //then
+        ovsNode = helper.readOvsNode();
+        assertEquals(0,ovsNode.getOwnedNodeEdgePoint().size());
+    }
+
+    @Test
+    public void testPortRemoval(){
+        //given
+        String fullPortNameToRemove = bridgeName+tp1Name;
+        //helper.createTestBridge();
+        helper.createTestBridge();
+        Node ovsNode = helper.readOvsNode();
+        assertEquals(initialBridgePortCount,ovsNode.getOwnedNodeEdgePoint().size());
+
+        //when
+        helper.deletePort(tp1Name);
+
+        //then
+        ovsNode = helper.readOvsNode();
+        assertEquals(initialBridgePortCount-1,ovsNode.getOwnedNodeEdgePoint().size());
+        assertFalse(checkNep.apply(ovsNode,fullPortNameToRemove));
+        assertFalse(checkSip.apply(helper.readSips(), fullPortNameToRemove));
+    }
+
+    private BiFunction<Node, String, Boolean> checkNep = (node,nepName) ->
+            node.getOwnedNodeEdgePoint().stream()
+                    .anyMatch(ownedNep -> ownedNep.getMappedServiceInterfacePoint().contains(new UniversalId(sip_prefix + ovs_nep_prefix + nepName))
+                                && ownedNep.getUuid().getValue().equals(ovs_nep_prefix + nepName)
+                    );
+
+    private void checkNeps(Node node,String ... neps){
+        Arrays.stream(neps)
+                .forEach(nep -> assertTrue(checkNep.apply(node,nep)));
+    }
+
+    private BiFunction<List<org.opendaylight.yang.gen.v1.urn.mef.yang.tapicommon.rev170227.context.attrs.ServiceInterfacePoint>, String, Boolean> checkSip =
+            (sips, nep) -> sips.stream()
+                .anyMatch(sip -> sip.getUuid().getValue().equals(sip_prefix + ovs_nep_prefix + nep));
+
+    private void checkSips(List<org.opendaylight.yang.gen.v1.urn.mef.yang.tapicommon.rev170227.context.attrs.ServiceInterfacePoint> sips, String ... neps){
+        Arrays.stream(neps)
+                .forEach(nep -> assertTrue(checkSip.apply(sips,nep)));
+    }
+
+    private List<Link> getLinkList(){
+        List<Link> linkList = new ArrayList<>();
+
+        //For testing purposes only - can't be find anywhere else in DataStore
+        String of1NodeName = "1";
+        String of2NodeName = "2";
+        Long of2PortNumber = 1L;
+        Long of1PortNumber = 3L;
+
+        //openflow:1:3 -> <- openflow:2:1
+        linkList.add(FlowTopologyTestUtils.createLink(of1NodeName,of1PortNumber,of2NodeName,of2PortNumber));
+        linkList.add(FlowTopologyTestUtils.createLink(of2NodeName,of2PortNumber,of1NodeName,of1PortNumber));
+
+        return linkList;
+    }
+
+
+
+}
diff --git a/ovs-driver/src/test/java/org/opendaylight/unimgr/mef/nrp/ovs/tapi/TopologyDataHandlerTestUtils.java b/ovs-driver/src/test/java/org/opendaylight/unimgr/mef/nrp/ovs/tapi/TopologyDataHandlerTestUtils.java
new file mode 100644 (file)
index 0000000..785365c
--- /dev/null
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2017 Cisco Systems Inc and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.unimgr.mef.nrp.ovs.tapi;
+
+import com.google.common.base.Optional;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
+import org.opendaylight.unimgr.mef.nrp.impl.NrpInitializer;
+import org.opendaylight.unimgr.mef.nrp.ovs.DataStoreTestUtils;
+import org.opendaylight.unimgr.mef.nrp.ovs.OpenFlowTopologyTestUtils;
+import org.opendaylight.unimgr.mef.nrp.ovs.OvsdbTopologyTestUtils;
+import org.opendaylight.yang.gen.v1.urn.mef.yang.tapicommon.rev170227.Context;
+import org.opendaylight.yang.gen.v1.urn.mef.yang.tapicommon.rev170227.UniversalId;
+import org.opendaylight.yang.gen.v1.urn.mef.yang.tapitopology.rev170227.Context1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnectorBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.PortNumberUni;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+
+import static org.junit.Assert.fail;
+
+/**
+ * @author marek.ryznar@amartus.com
+ */
+public class TopologyDataHandlerTestUtils {
+    private static String bridgeName = "br1";
+    private static String ofBridgeName = "openflow:1";
+    private static String tp1Name = "br1-eth1";
+    private static String tp2Name = "br1-eth2";
+    private static String tp3Name = "br1-eth3";
+    private static Long tp1OFport = 1L;
+    private static Long tp2OFport = 2L;
+    private static Long tp3OFport = 3L;
+
+    private static final String prestoNrpTopoId = "mef:presto-nrp-topology-system";
+    private static final String ovsNodeId = "ovs-node";
+
+    private final DataBroker dataBroker;
+
+    protected TopologyDataHandlerTestUtils(DataBroker dataBroker){
+        this.dataBroker = dataBroker;
+    }
+
+    /**
+     * Creates ovsdb bridge "br1" with 3 ports:
+     *  1. tp1 - nep
+     *  2. tp2 - nep
+     *  3. tp3 - not nep, becouse it is connected to other switch
+     */
+    public void createTestBridge(){
+        List<TerminationPoint> tps = new LinkedList<>();
+
+        tps.add(OvsdbTopologyTestUtils.createTerminationPoint(tp1Name,tp1OFport));
+        tps.add(OvsdbTopologyTestUtils.createTerminationPoint(tp2Name,tp2OFport));
+        tps.add(OvsdbTopologyTestUtils.createTerminationPoint(tp3Name,tp3OFport));
+
+        org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node node = OvsdbTopologyTestUtils.createBridge(bridgeName,tps);
+        InstanceIdentifier instanceIdentifier = OvsdbTopologyTestUtils.getNodeInstanceIdentifier(node.getNodeId());
+        DataStoreTestUtils.write(node,instanceIdentifier,dataBroker);
+    }
+
+    protected void deleteTestBridge(){
+        InstanceIdentifier instanceIdentifier = OvsdbTopologyTestUtils.getNodeInstanceIdentifier(new NodeId(bridgeName));
+        DataStoreTestUtils.delete(instanceIdentifier,dataBroker);
+    }
+
+    protected void deletePort(String port){
+        InstanceIdentifier<TerminationPoint> tpIid = OvsdbTopologyTestUtils.getPortInstanceIdentifier(bridgeName,port);
+        DataStoreTestUtils.delete(tpIid,dataBroker);
+    }
+
+    protected void addPort(String bridgeName, String portName, Long ofNumber){
+        String bridgeId = bridgeName;
+        //openflow init
+        NodeConnector nodeConnector = OpenFlowTopologyTestUtils.createNodeConnector(ofBridgeName,ofNumber,portName);
+        InstanceIdentifier<NodeConnector> nodeConnectorInstanceIdentifier =
+                OpenFlowTopologyTestUtils.getNodeConnectorInstanceIdentifier(ofBridgeName,ofBridgeName+":"+ofNumber.toString());
+        DataStoreTestUtils.write(nodeConnector,nodeConnectorInstanceIdentifier,dataBroker);
+        //ovsdb init
+        TerminationPoint terminationPoint = OvsdbTopologyTestUtils.createTerminationPoint(portName,ofNumber);
+        InstanceIdentifier<TerminationPoint> tpIid = OvsdbTopologyTestUtils.getPortInstanceIdentifier(bridgeId,portName);
+        DataStoreTestUtils.write(terminationPoint,tpIid,dataBroker);
+    }
+
+    /**
+     * Creates OpenFlow Nodes with one Node ("openflow:1" openflow equivalent of ovsdb's "br1"), which consist of 3 NodeConnectors:
+     *  1. id:"openflow:1:1", name: "br1-eth1", portNumber: "1"
+     *  2. id:"openflow:1:2", name: "br1-eth2", portNumber: "2"
+     *  3. id:"openflow:1:3", name: "br1-eth3", portNumber: "3"
+     */
+    protected void createOpenFlowNodes(){
+        NodesBuilder nodesBuilder = new NodesBuilder();
+        List<org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node> nodeList = new ArrayList<>();
+        nodeList.add(createOpenFlowNode(ofBridgeName));
+        nodesBuilder.setNode(nodeList);
+        Nodes nodes = nodesBuilder.build();
+        InstanceIdentifier<Nodes> nodesIId = InstanceIdentifier.builder(Nodes.class).build();
+
+        ReadWriteTransaction transaction = dataBroker.newReadWriteTransaction();
+        transaction.put(LogicalDatastoreType.OPERATIONAL,nodesIId,nodes);
+        transaction.submit();
+    }
+
+    private org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node createOpenFlowNode(String oFName){
+        org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder nodeBuilder =
+                new org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder();
+        org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId nodeId =
+                new org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId(oFName);
+        nodeBuilder.setId(nodeId);
+        nodeBuilder.setKey(new org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey(nodeId));
+        List<NodeConnector> nodeConnectorList = new ArrayList<>();
+        nodeConnectorList.add(createNodeConnector(oFName,tp1OFport,tp1Name));
+        nodeConnectorList.add(createNodeConnector(oFName,tp2OFport,tp2Name));
+        nodeConnectorList.add(createNodeConnector(oFName,tp3OFport,tp3Name));
+        nodeBuilder.setNodeConnector(nodeConnectorList);
+        return nodeBuilder.build();
+    }
+
+    private NodeConnector createNodeConnector(String ofBridgeName, Long portNumber, String ovsdbPortName){
+        NodeConnectorBuilder nodeConnectorBuilder = new NodeConnectorBuilder();
+        String ofPortName = ofBridgeName + ":" + portNumber.toString();
+        NodeConnectorId nodeConnectorId = new NodeConnectorId(ofPortName);
+        nodeConnectorBuilder.setId(nodeConnectorId);
+        nodeConnectorBuilder.setKey(new NodeConnectorKey(nodeConnectorId));
+        nodeConnectorBuilder.addAugmentation(FlowCapableNodeConnector.class,createFlowCapableNodeConnector(ovsdbPortName,portNumber));
+        return nodeConnectorBuilder.build();
+    }
+
+    private FlowCapableNodeConnector createFlowCapableNodeConnector(String ovsdbName, Long portNumber){
+        FlowCapableNodeConnectorBuilder flowCapableNodeConnectorBuilder = new FlowCapableNodeConnectorBuilder();
+        flowCapableNodeConnectorBuilder.setName(ovsdbName);
+        flowCapableNodeConnectorBuilder.setPortNumber(new PortNumberUni(portNumber));
+        return flowCapableNodeConnectorBuilder.build();
+    }
+
+    protected void createPrestoSystemTopology(){
+        NrpInitializer nrpInitializer = new NrpInitializer(dataBroker);
+        try {
+            nrpInitializer.init();
+        } catch (Exception e) {
+            fail("Could not initialize NRP topology.");
+        }
+    }
+
+    protected org.opendaylight.yang.gen.v1.urn.mef.yang.tapitopology.rev170227.topology.Node readOvsNode(){
+        return DataStoreTestUtils.read(getNodeIid(),dataBroker);
+    }
+
+    protected List<org.opendaylight.yang.gen.v1.urn.mef.yang.tapicommon.rev170227.context.attrs.ServiceInterfacePoint> readSips(){
+        ReadWriteTransaction readWriteTransaction = dataBroker.newReadWriteTransaction();
+        try {
+            Optional<Context> opt = readWriteTransaction.read(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.create(Context.class)).checkedGet();
+            if(opt.isPresent()){
+                return opt.get().getServiceInterfacePoint();
+            } else {
+                fail("There are no sips.");
+            }
+        } catch (ReadFailedException e) {
+            fail(e.getMessage());
+        }
+        return null;
+    }
+
+    private static InstanceIdentifier getNodeIid(){
+        return getTopoIid()
+                .child(org.opendaylight.yang.gen.v1.urn.mef.yang.tapitopology.rev170227.topology.Node.class,
+                        new org.opendaylight.yang.gen.v1.urn.mef.yang.tapitopology.rev170227.topology.NodeKey(new UniversalId(ovsNodeId)));
+    }
+
+    private static InstanceIdentifier getTopoIid(){
+        return InstanceIdentifier.create(Context.class)
+                .augmentation(Context1.class)
+                .child(org.opendaylight.yang.gen.v1.urn.mef.yang.tapitopology.rev170227.topology.context.Topology.class,
+                        new org.opendaylight.yang.gen.v1.urn.mef.yang.tapitopology.rev170227.topology.context.TopologyKey(new UniversalId(prestoNrpTopoId)));
+    }
+}
\ No newline at end of file