Add SfcClassifier to pipeline 14/29414/2
authorSam Hague <shague@redhat.com>
Sat, 7 Nov 2015 02:11:42 +0000 (21:11 -0500)
committerSam Hague <shague@redhat.com>
Sun, 8 Nov 2015 02:10:56 +0000 (21:10 -0500)
Change-Id: I7de504449435678020efc3aca290897adada42ab
Signed-off-by: Sam Hague <shague@redhat.com>
14 files changed:
openstack/net-virt-it/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/it/NetvirtIT.java
openstack/net-virt-providers/pom.xml
openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/PipelineOrchestrator.java
openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/PipelineOrchestratorImpl.java
openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/Service.java
openstack/net-virt-sfc/impl/pom.xml
openstack/net-virt-sfc/impl/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/NetvirtSfcProvider.java
openstack/net-virt-sfc/impl/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/openflow13/NetvirtSfcOF13Provider.java
openstack/net-virt-sfc/impl/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/openflow13/services/SfcClassifierService.java [new file with mode: 0644]
openstack/net-virt-sfc/impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/netvirt/sfc/rev141210/NetvirtSfcModule.java
openstack/net-virt-sfc/impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/netvirt/sfc/rev141210/NetvirtSfcModuleFactory.java
openstack/net-virt-sfc/impl/src/test/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/netvirt/sfc/rev141210/NetvirtSfcModuleTest.java
openstack/net-virt-sfc/it/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/NetvirtSfcIT.java
utils/mdsal-openflow/src/main/java/org/opendaylight/ovsdb/utils/mdsal/openflow/FlowUtils.java

index 5d29699642b10458b0e7754f1044735493faf472..c49173d9d6a6dc13a85089086641c1cb11ebae89 100644 (file)
@@ -7,11 +7,16 @@
  */
 package org.opendaylight.ovsdb.openstack.netvirt.it;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.fail;
 import static org.ops4j.pax.exam.CoreOptions.composite;
 import static org.ops4j.pax.exam.CoreOptions.maven;
+import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
 import static org.ops4j.pax.exam.CoreOptions.vmOption;
 import static org.ops4j.pax.exam.CoreOptions.when;
+import static org.ops4j.pax.exam.CoreOptions.wrappedBundle;
+import static org.ops4j.pax.exam.MavenUtils.asInProject;
 import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.editConfigurationFilePut;
 import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.karafDistributionConfiguration;
 import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.keepRuntimeFolder;
@@ -26,6 +31,7 @@ import java.net.UnknownHostException;
 import java.util.ArrayList;
 import java.util.Enumeration;
 import java.util.List;
+import java.util.Map;
 import java.util.Properties;
 import java.util.concurrent.atomic.AtomicBoolean;
 import javax.inject.Inject;
@@ -37,10 +43,17 @@ import org.junit.runner.RunWith;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.mdsal.it.base.AbstractMdsalTestBase;
+import org.opendaylight.ovsdb.openstack.netvirt.api.SecurityServicesManager;
 import org.opendaylight.ovsdb.openstack.netvirt.api.Southbound;
+import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.AbstractServiceInstance;
+import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.PipelineOrchestrator;
+import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.Service;
+import org.opendaylight.ovsdb.utils.mdsal.openflow.FlowUtils;
 import org.opendaylight.ovsdb.utils.servicehelper.ServiceHelper;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.*;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeExternalIds;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeOtherConfigs;
@@ -124,6 +137,10 @@ public class NetvirtIT extends AbstractMdsalTestBase {
 
     private Option[] getOtherOptions() {
         return new Option[] {
+                wrappedBundle(
+                        mavenBundle("org.opendaylight.ovsdb", "utils.mdsal-openflow")
+                                .version(asInProject())
+                                .type("jar")),
                 vmOption("-javaagent:../jars/org.jacoco.agent.jar=destfile=../../jacoco-it.exec"),
                 keepRuntimeFolder()
         };
@@ -677,8 +694,34 @@ public class NetvirtIT extends AbstractMdsalTestBase {
     @Test
     public void testNetVirt() throws InterruptedException {
         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
-        connectOvsdbNode(connectionInfo);
+        Node ovsdbNode = connectOvsdbNode(connectionInfo);
+
         Thread.sleep(10000);
+        // Verify the pipeline flows were installed
+        PipelineOrchestrator pipelineOrchestrator =
+                (PipelineOrchestrator) ServiceHelper.getGlobalInstance(PipelineOrchestrator.class, this);
+        assertNotNull("Could not find PipelineOrchestrator Service", pipelineOrchestrator);
+        Node bridgeNode = southbound.getBridgeNode(ovsdbNode, NetvirtITConstants.INTEGRATION_BRIDGE_NAME);
+        assertNotNull("bridge " + NetvirtITConstants.INTEGRATION_BRIDGE_NAME + " was not found", bridgeNode);
+        long datapathId = southbound.getDataPathId(bridgeNode);
+        org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder nodeBuilder =
+                FlowUtils.createNodeBuilder(datapathId);
+
+        List<Service> staticPipeline = pipelineOrchestrator.getStaticPipeline();
+        List<Service> staticPipelineFound = Lists.newArrayList();
+        for (Service service : pipelineOrchestrator.getServiceRegistry().keySet()) {
+            if (staticPipeline.contains(service)) {
+                staticPipelineFound.add(service);
+            }
+            FlowBuilder flowBuilder = FlowUtils.getPipelineFlow(service.getTable(), (short)0);
+            Flow flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.CONFIGURATION);
+            assertNotNull("Could not find flow in config", flow);
+            flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.OPERATIONAL);
+            assertNotNull("Could not find flow in operational", flow);
+        }
+        assertEquals("did not find all expected flows in static pipeline",
+                staticPipeline.size(), staticPipelineFound.size());
+
         netVirtAddPort(connectionInfo);
         Thread.sleep(10000);
         Assert.assertTrue(deleteBridge(connectionInfo, NetvirtITConstants.INTEGRATION_BRIDGE_NAME));
@@ -700,4 +743,22 @@ public class NetvirtIT extends AbstractMdsalTestBase {
             LOG.info(">>>>> node: {}", node);
         }
     }
+
+    private Flow getFlow (
+            FlowBuilder flowBuilder,
+            org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder nodeBuilder,
+            LogicalDatastoreType store)
+            throws InterruptedException {
+
+        Flow flow = null;
+        for (int i = 0; i < 10; i++) {
+            flow = FlowUtils.getFlow(flowBuilder, nodeBuilder, dataBroker.newReadOnlyTransaction(), store);
+            if (flow != null) {
+                LOG.info("getFlow: flow({}): {}", store, flow);
+                break;
+            }
+            Thread.sleep(1000);
+        }
+        return flow;
+    }
 }
index 76ca876bdd34368c4b7c57b54e54730bf4038838..dfef38d55431f8a6c579369b2f1f57ce9b3381d7 100644 (file)
@@ -259,7 +259,8 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
             <Embed-Dependency>utils.config,utils.mdsal-openflow;type=!pom;inline=false</Embed-Dependency>
             <Embed-Transitive>true</Embed-Transitive>
             <Export-Package>
-              org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.*
+              org.opendaylight.ovsdb.openstack.netvirt.providers,
+              org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13
             </Export-Package>
           </instructions>
         </configuration>
index e6e0fd0396bf0a638685381f762206ec73d015ec..6f8a19728298cec71d23d9fdeb0e77af6ad60d2d 100644 (file)
@@ -8,6 +8,8 @@
 
 package org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13;
 
+import java.util.List;
+import java.util.Map;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
 import org.osgi.framework.ServiceReference;
 
@@ -21,6 +23,8 @@ import org.osgi.framework.ServiceReference;
 public interface PipelineOrchestrator {
     Service getNextServiceInPipeline(Service service);
     AbstractServiceInstance getServiceInstance(Service service);
+    Map<Service, AbstractServiceInstance> getServiceRegistry();
+    List<Service> getStaticPipeline();
     void enqueue(Node node);
     void registerService(final ServiceReference ref, AbstractServiceInstance serviceInstance);
     void unregisterService(final ServiceReference ref);
index edea48c26cdc122d5e2c6cbd29dd478f62e90075..299ab21a08b76f4261a5fceee18f5e49cf8c7046 100644 (file)
@@ -8,6 +8,7 @@
 
 package org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13;
 
+import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.BlockingQueue;
@@ -32,6 +33,11 @@ import com.google.common.collect.Maps;
 
 public class PipelineOrchestratorImpl implements ConfigInterface, NodeCacheListener, PipelineOrchestrator {
     private static final Logger LOG = LoggerFactory.getLogger(PipelineOrchestratorImpl.class);
+
+    public List<Service> getStaticPipeline() {
+        return staticPipeline;
+    }
+
     private List<Service> staticPipeline = Lists.newArrayList(
             Service.CLASSIFIER,
             Service.ARP_RESPONDER,
@@ -45,6 +51,11 @@ public class PipelineOrchestratorImpl implements ConfigInterface, NodeCacheListe
             Service.OUTBOUND_NAT,
             Service.L2_FORWARDING
     );
+
+    public Map<Service, AbstractServiceInstance> getServiceRegistry() {
+        return serviceRegistry;
+    }
+
     Map<Service, AbstractServiceInstance> serviceRegistry = Maps.newConcurrentMap();
     private volatile BlockingQueue<Node> queue;
     private ExecutorService eventHandler;
@@ -61,6 +72,23 @@ public class PipelineOrchestratorImpl implements ConfigInterface, NodeCacheListe
         Service service = (Service)ref.getProperty(AbstractServiceInstance.SERVICE_PROPERTY);
         LOG.info("registerService {} - {}", serviceInstance, service);
         serviceRegistry.put(service, serviceInstance);
+        // insert the service if not already there. The list is ordered based of table ID.
+        if (!staticPipeline.contains(service) && !isTableInPipeline(service.getTable())) {
+            staticPipeline.add(service);
+            Collections.sort(staticPipeline, Service.insertComparator);
+        }
+        LOG.info("registerService: {}", staticPipeline);
+    }
+
+    private boolean isTableInPipeline (short tableId) {
+        boolean found = false;
+        for (Service service : staticPipeline) {
+            if (service.getTable() == tableId) {
+                found = true;
+                break;
+            }
+        }
+        return found;
     }
 
     public void unregisterService(final ServiceReference ref) {
index badde08175e9c141537f22272ccfa90165642459..25177441218ed005b4c4788254738b7c1bb0608a 100644 (file)
@@ -8,11 +8,14 @@
 
 package org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13;
 
+import java.util.Comparator;
+
 public enum Service {
 
     CLASSIFIER ((short) 0, "Classifier"),
     GATEWAY_RESOLVER((short) 0, "External Network Gateway Resolver"),
     DIRECTOR ((short) 10, "Director"),
+    SFC_CLASSIFIER ((short) 10, "SFC Classifier"),
     ARP_RESPONDER ((short) 20, "Distributed ARP Responder"),
     INBOUND_NAT ((short) 30, "DNAT for inbound floating-ip traffic"),
     EGRESS_ACL ((short) 40, "Egress Acces-control"),
@@ -39,4 +42,12 @@ public enum Service {
     public String getDescription() {
         return description;
     }
+
+    public static Comparator<Service> insertComparator = new Comparator<Service>() {
+
+        @Override
+        public int compare(Service service1, Service service2) {
+            return service1.getTable() - service2.getTable();
+        }
+    };
 }
index 690626c9b060fb9350f9e07a8474b08e0f79b320..3bd7e21e281bd2e596bdbc28b6cdf25f711f93d8 100644 (file)
@@ -27,6 +27,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
   <properties>
     <networkconfig.neutron.version>0.6.0-SNAPSHOT</networkconfig.neutron.version>
     <openflowplugin.version>0.2.0-SNAPSHOT</openflowplugin.version>
+    <powermock.version>1.5.2</powermock.version>
     <sonar.jacoco.itReportPath>../it/target/jacoco-it.exec</sonar.jacoco.itReportPath>
     <sfc.project.version>0.2.0-SNAPSHOT</sfc.project.version>
   </properties>
@@ -91,6 +92,20 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal-common-api</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller.model</groupId>
+      <artifactId>model-inventory</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.openflowplugin</groupId>
+      <artifactId>openflowplugin-extension-nicira</artifactId>
+      <version>${openflowplugin.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.openflowplugin</groupId>
+      <artifactId>openflowjava-extension-nicira</artifactId>
+      <version>${openflowplugin.version}</version>
+    </dependency>
     <dependency>
       <groupId>org.opendaylight.openflowplugin.model</groupId>
       <artifactId>model-flow-base</artifactId>
@@ -110,11 +125,6 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
       <artifactId>sfc-model</artifactId>
       <version>${sfc.project.version}</version>
     </dependency>
-    <dependency>
-      <groupId>org.opendaylight.sfc</groupId>
-      <artifactId>sfc-ovs</artifactId>
-      <version>${sfc.project.version}</version>
-    </dependency>
     <dependency>
       <groupId>org.opendaylight.sfc</groupId>
       <artifactId>sfc-provider</artifactId>
@@ -139,6 +149,24 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
       <artifactId>mockito-all</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.powermock</groupId>
+      <artifactId>powermock-core</artifactId>
+      <version>${powermock.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.powermock</groupId>
+      <artifactId>powermock-module-junit4</artifactId>
+      <version>${powermock.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.powermock</groupId>
+      <artifactId>powermock-api-mockito</artifactId>
+      <version>${powermock.version}</version>
+      <scope>test</scope>
+    </dependency>
     <dependency>
       <groupId>org.codehaus.sonar-plugins.java</groupId>
       <artifactId>sonar-jacoco-listeners</artifactId>
index 57dece3e31e912f2409786ee35c88a33c12192c7..b967b759aaab1906912be4df60cf904dd37d5a42 100644 (file)
@@ -8,11 +8,20 @@
 
 package org.opendaylight.ovsdb.openstack.netvirt.sfc;
 
+import java.util.Dictionary;
+import java.util.Hashtable;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
 import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
+import org.opendaylight.ovsdb.openstack.netvirt.api.Constants;
+import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.AbstractServiceInstance;
+import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.OF13Provider;
+import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.Service;
 import org.opendaylight.ovsdb.openstack.netvirt.sfc.openflow13.INetvirtSfcOF13Provider;
 import org.opendaylight.ovsdb.openstack.netvirt.sfc.openflow13.NetvirtSfcOF13Provider;
+import org.opendaylight.ovsdb.openstack.netvirt.sfc.openflow13.services.SfcClassifierService;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -21,6 +30,18 @@ public class NetvirtSfcProvider implements BindingAwareProvider, AutoCloseable {
     private NetvirtSfcAclListener aclListener;
     private NetvirtSfcClassifierListener classfierListener;
 
+    public void setBundleContext(BundleContext bundleContext) {
+        this.bundleContext = bundleContext;
+        LOG.info("bundleContext is: {}", bundleContext);
+    }
+
+    private BundleContext bundleContext;
+
+    public NetvirtSfcProvider(BundleContext bundleContext) {
+        LOG.info("NetvirtSfcProvider: bundleContext: {}", bundleContext);
+        this.bundleContext = bundleContext;
+    }
+
     @Override
     public void onSessionInitiated(ProviderContext session) {
         LOG.info("NetvirtSfcProvider Session Initiated");
@@ -29,6 +50,8 @@ public class NetvirtSfcProvider implements BindingAwareProvider, AutoCloseable {
         INetvirtSfcOF13Provider provider = new NetvirtSfcOF13Provider(dataBroker);
         aclListener = new NetvirtSfcAclListener(provider, dataBroker);
         classfierListener = new NetvirtSfcClassifierListener(provider, dataBroker);
+
+        addToPipeline();
     }
 
     @Override
@@ -37,4 +60,27 @@ public class NetvirtSfcProvider implements BindingAwareProvider, AutoCloseable {
         aclListener.close();
         classfierListener.close();
     }
+
+    private void addToPipeline() {
+        SfcClassifierService sfcClassifierService = new SfcClassifierService();
+        registerService(bundleContext, SfcClassifierService.class.getName(),
+                        sfcClassifierService, Service.SFC_CLASSIFIER);
+        sfcClassifierService.setDependencies(bundleContext, null);
+        }
+
+    private ServiceRegistration<?> registerService(BundleContext bundleContext, String[] interfaces,
+                                                   Dictionary<String, Object> properties, Object impl) {
+        ServiceRegistration<?> serviceRegistration = bundleContext.registerService(interfaces, impl, properties);
+        return serviceRegistration;
+    }
+
+    private ServiceRegistration<?> registerService(BundleContext bundleContext, String interfaceClassName,
+                                                       Object impl, Object serviceProperty) {
+        Dictionary<String, Object> properties = new Hashtable<>();
+        properties.put(AbstractServiceInstance.SERVICE_PROPERTY, serviceProperty);
+        properties.put(Constants.PROVIDER_NAME_PROPERTY, OF13Provider.NAME);
+        return registerService(bundleContext,
+                new String[] {AbstractServiceInstance.class.getName(),
+                interfaceClassName}, properties, impl);
+    }
 }
index 5b2d94e2cb0abcfae78cb566f1fc20f55ca1a139..1c83d5370bb6ddfdbb30cbc7f4ce79752c874cec 100644 (file)
@@ -38,8 +38,6 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.cont
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.access.list.entries.ace.matches.ace.type.AceIp;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.access.list.entries.ace.matches.ace.type.ace.ip.ace.ip.version.AceIpv4;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg0;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.acl.rev150105.RedirectToSfc;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.classifiers.classifier.Bridges;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.classifiers.classifier.bridges.Bridge;
diff --git a/openstack/net-virt-sfc/impl/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/openflow13/services/SfcClassifierService.java b/openstack/net-virt-sfc/impl/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/openflow13/services/SfcClassifierService.java
new file mode 100644 (file)
index 0000000..b05c6f5
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright © 2015 Red Hat, 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.ovsdb.openstack.netvirt.sfc.openflow13.services;
+
+import org.opendaylight.ovsdb.openstack.netvirt.providers.ConfigInterface;
+import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.AbstractServiceInstance;
+import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.Service;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+
+public class SfcClassifierService extends AbstractServiceInstance implements ConfigInterface {
+    public SfcClassifierService(Service service) {
+        super(service);
+    }
+
+    public SfcClassifierService() {
+        super(Service.SFC_CLASSIFIER);
+    }
+
+    @Override
+    public void setDependencies(BundleContext bundleContext, ServiceReference serviceReference) {
+        super.setDependencies(bundleContext.getServiceReference(SfcClassifierService.class.getName()), this);
+    }
+
+    @Override
+    public void setDependencies(Object impl) {}
+}
index 4709be3238d78a71c6d3ed8b5b5d4a52e905c76d..278a47cfe68dc81e914ac7d0824e521fff9949bd 100644 (file)
@@ -1,18 +1,30 @@
+/*
+ * Copyright © 2015 Red Hat, 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.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.rev141210;
 
+import org.opendaylight.controller.config.api.DependencyResolver;
+import org.opendaylight.controller.config.api.ModuleIdentifier;
 import org.opendaylight.ovsdb.openstack.netvirt.sfc.NetvirtSfcProvider;
+import org.osgi.framework.BundleContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class NetvirtSfcModule extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.rev141210.AbstractNetvirtSfcModule {
-
+public class NetvirtSfcModule extends AbstractNetvirtSfcModule {
     private static final Logger LOG = LoggerFactory.getLogger(NetvirtSfcModule.class);
+    private BundleContext bundleContext;
 
-    public NetvirtSfcModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+    public NetvirtSfcModule(ModuleIdentifier identifier, DependencyResolver dependencyResolver) {
         super(identifier, dependencyResolver);
     }
 
-    public NetvirtSfcModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.rev141210.NetvirtSfcModule oldModule, java.lang.AutoCloseable oldInstance) {
+    public NetvirtSfcModule(ModuleIdentifier identifier, DependencyResolver dependencyResolver,
+                            NetvirtSfcModule oldModule, java.lang.AutoCloseable oldInstance) {
         super(identifier, dependencyResolver, oldModule, oldInstance);
     }
 
@@ -24,8 +36,12 @@ public class NetvirtSfcModule extends org.opendaylight.yang.gen.v1.urn.opendayli
     @Override
     public java.lang.AutoCloseable createInstance() {
         LOG.info("Netvirt SFC module initialization.");
-        NetvirtSfcProvider sfcProvider = new NetvirtSfcProvider();
+        NetvirtSfcProvider sfcProvider = new NetvirtSfcProvider(bundleContext);
         getBrokerDependency().registerProvider(sfcProvider);
         return sfcProvider;
     }
+
+    public void setBundleContext(BundleContext bundleContext) {
+        this.bundleContext = bundleContext;
+    }
 }
index 60b6cddc04b7505de015da0b32008d1d1cd35a29..276a14aa20b5561f3a20ab37114fdf3c03a1b4c3 100644 (file)
@@ -1,13 +1,32 @@
 /*
-* Generated file
-*
-* Generated from: yang module name: netvirt-sfc yang module local name: netvirt-sfc
-* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
-* Generated at: Wed Sep 23 15:18:24 EDT 2015
-*
-* Do not modify this file unless it is present under src/main directory
-*/
+ * Copyright © 2015 Red Hat, 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.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.rev141210;
 
-public class NetvirtSfcModuleFactory extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.rev141210.AbstractNetvirtSfcModuleFactory {
+import org.opendaylight.controller.config.api.DependencyResolver;
+import org.osgi.framework.BundleContext;
+
+public class NetvirtSfcModuleFactory extends AbstractNetvirtSfcModuleFactory {
+    @Override
+    public NetvirtSfcModule instantiateModule(String instanceName, DependencyResolver dependencyResolver,
+                                              BundleContext bundleContext) {
+        NetvirtSfcModule module = super.instantiateModule(instanceName, dependencyResolver, bundleContext);
+        module.setBundleContext(bundleContext);
+        return module;
+    }
+
+    @Override
+    public NetvirtSfcModule instantiateModule(String instanceName, DependencyResolver dependencyResolver,
+                                              NetvirtSfcModule oldModule, AutoCloseable oldInstance,
+                                              BundleContext bundleContext) {
+        NetvirtSfcModule module = super.instantiateModule(instanceName, dependencyResolver,
+                oldModule, oldInstance, bundleContext);
+        module.setBundleContext(bundleContext);
+        return module;
+    }
 }
index 7b6f065a38badcb0119e3372e5ca12e27d287b90..1704c1a97753b3b2a0e91983479d9e04d6aa479e 100644 (file)
@@ -5,25 +5,42 @@
  * 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.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.rev141210;
 
+import java.util.Dictionary;
 import org.junit.Test;
+import org.junit.runner.RunWith;
 import org.opendaylight.controller.config.api.DependencyResolver;
 import org.opendaylight.controller.config.api.JmxAttribute;
 import org.opendaylight.controller.config.api.ModuleIdentifier;
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.ovsdb.openstack.netvirt.api.Southbound;
+import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.AbstractServiceInstance;
+import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.PipelineOrchestrator;
 import org.opendaylight.ovsdb.openstack.netvirt.sfc.NetvirtSfcProvider;
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
 
 import javax.management.ObjectName;
+import org.opendaylight.ovsdb.openstack.netvirt.sfc.openflow13.services.SfcClassifierService;
+import org.opendaylight.ovsdb.utils.servicehelper.ServiceHelper;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
 
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+@PrepareForTest(ServiceHelper.class)
+@RunWith(PowerMockRunner.class)
 public class NetvirtSfcModuleTest {
     @Test
     public void testCustomValidation() {
@@ -33,6 +50,7 @@ public class NetvirtSfcModuleTest {
         module.customValidation();
     }
 
+    @SuppressWarnings("unchecked")
     @Test
     public void testCreateInstance() throws Exception {
         // configure mocks
@@ -40,13 +58,32 @@ public class NetvirtSfcModuleTest {
         BindingAwareBroker broker = mock(BindingAwareBroker.class);
         ProviderContext session = mock(ProviderContext.class);
         DataBroker dataBroker = mock(DataBroker.class);
-        when(dependencyResolver.resolveInstance(eq(BindingAwareBroker.class), any(ObjectName.class), any(JmxAttribute.class))).thenReturn(broker);
+        when(dependencyResolver.resolveInstance(eq(BindingAwareBroker.class),
+                any(ObjectName.class), any(JmxAttribute.class))).thenReturn(broker);
         when(session.getSALService(eq(DataBroker.class))).thenReturn(dataBroker);
 
         // create instance of module with injected mocks
         NetvirtSfcModule module = new NetvirtSfcModule(mock(ModuleIdentifier.class), dependencyResolver);
         // getInstance calls resolveInstance to get the broker dependency and then calls createInstance
+        BundleContext bundleContext = mock(BundleContext.class);
+        PowerMockito.mockStatic(ServiceHelper.class);
+        PipelineOrchestrator pipelineOrchestrator = mock(PipelineOrchestrator.class);
+        PowerMockito.when(ServiceHelper.getGlobalInstance(eq(PipelineOrchestrator.class), any(AbstractServiceInstance.class)))
+                .thenReturn(pipelineOrchestrator);
+        PowerMockito.when(ServiceHelper.getGlobalInstance(eq(Southbound.class), any(AbstractServiceInstance.class)))
+                .thenReturn(mock(Southbound.class));
+
+        doNothing().when(pipelineOrchestrator).registerService(any(ServiceReference.class),
+                any(AbstractServiceInstance.class));
+        when(bundleContext.registerService(
+                eq(new String[]{AbstractServiceInstance.class.getName(), SfcClassifierService.class.getName()}),
+                any(),
+                any(Dictionary.class)))
+                .thenReturn(mock(ServiceRegistration.class));
+        when(bundleContext.getServiceReference(SfcClassifierService.class.getName()))
+                .thenReturn(mock(ServiceReference.class));
         AutoCloseable closeable = module.getInstance();
+        ((NetvirtSfcProvider)closeable).setBundleContext(bundleContext);
         ((NetvirtSfcProvider)closeable).onSessionInitiated(session);
         // verify that the module registered the returned provider with the broker
         verify(broker).registerProvider((NetvirtSfcProvider)closeable);
index f59ca24f59190e6d14c389d2ba83a192b235634d..87cdaa5df867187388f7a13aa7e277a386909a6e 100644 (file)
@@ -37,6 +37,8 @@ import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.mdsal.it.base.AbstractMdsalTestBase;
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
 import org.opendaylight.ovsdb.openstack.netvirt.api.Southbound;
+import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.PipelineOrchestrator;
+import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.Service;
 import org.opendaylight.ovsdb.openstack.netvirt.sfc.openflow13.NshUtils;
 import org.opendaylight.ovsdb.openstack.netvirt.sfc.openflow13.SfcClassifier;
 import org.opendaylight.ovsdb.openstack.netvirt.sfc.utils.AclUtils;
@@ -89,6 +91,7 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.ops4j.pax.exam.Configuration;
 import org.ops4j.pax.exam.Option;
 import org.ops4j.pax.exam.junit.PaxExam;
+import org.ops4j.pax.exam.karaf.options.LogLevelOption;
 import org.ops4j.pax.exam.karaf.options.LogLevelOption.LogLevel;
 import org.ops4j.pax.exam.options.MavenUrlReference;
 import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
@@ -187,9 +190,9 @@ public class NetvirtSfcIT extends AbstractMdsalTestBase {
                 editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG,
                         "log4j.logger.org.opendaylight.ovsdb.openstack.netvirt.sfc",
                         LogLevel.TRACE.name()),
-                /*editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG,
+                editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG,
                         "log4j.logger.org.opendaylight.ovsdb",
-                        LogLevelOption.LogLevel.TRACE.name()),*/
+                        LogLevelOption.LogLevel.TRACE.name()),
                 super.getLoggingOption());
     }
 
@@ -360,7 +363,7 @@ public class NetvirtSfcIT extends AbstractMdsalTestBase {
      * and program the pipeline flows.
      */
     @Test
-    public void testDoIt() throws InterruptedException {
+    public void testNetvirtSfc() throws InterruptedException {
         String bridgeName = INTEGRATION_BRIDGE_NAME;
         ConnectionInfo connectionInfo = southboundUtils.getConnectionInfo(addressStr, portStr);
         assertNotNull("connection failed", southboundUtils.connectOvsdbNode(connectionInfo));
@@ -371,25 +374,38 @@ public class NetvirtSfcIT extends AbstractMdsalTestBase {
         for (int i = 0; i < 10; i++) {
             ovsdbNode = southboundUtils.getOvsdbNode(connectionInfo);
             assertNotNull("ovsdb node not found", ovsdbNode);
-            String controllerTarget = "tcp:192.168.50.1:6653";//SouthboundUtil.getControllerTarget(ovsdbNode);
+            String controllerTarget = SouthboundUtil.getControllerTarget(ovsdbNode);
             assertNotNull("Failed to get controller target", controllerTarget);
             OvsdbBridgeAugmentation bridge = southboundUtils.getBridge(connectionInfo, bridgeName);
-            assertNotNull(bridge);
-            assertNotNull(bridge.getControllerEntry());
-            controllerEntry = bridge.getControllerEntry().iterator().next();
-            assertEquals(controllerTarget, controllerEntry.getTarget().getValue());
-            if (controllerEntry.isIsConnected()) {
-                Assert.assertTrue(controllerEntry.isIsConnected());
-                break;
+            if (bridge != null) {
+                assertNotNull("Failed to read bridge", bridge);
+                assertNotNull("Failed to extract controllerEntry", bridge.getControllerEntry());
+                controllerEntry = bridge.getControllerEntry().iterator().next();
+                assertEquals(controllerTarget, controllerEntry.getTarget().getValue());
+                if (controllerEntry.isIsConnected()) {
+                    Assert.assertTrue("switch is not connected to the controller", controllerEntry.isIsConnected());
+                    break;
+                }
             }
             Thread.sleep(1000);
         }
 
+        Node bridgeNode = southbound.getBridgeNode(ovsdbNode, bridgeName);
+        assertNotNull("bridge " + bridgeName + " was not found", bridgeNode);
+        long datapathId = southbound.getDataPathId(bridgeNode);
+
         /* TODO: add code to write to mdsal to exercise the sfc dataChangeListener */
         /* allow some time to let the impl code do it's work to push flows */
         /* or just comment out below lines and just manually verify on the bridges and reset them */
         //Thread.sleep(10000);
 
+        NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(datapathId);
+        FlowBuilder flowBuilder = FlowUtils.getPipelineFlow(Service.SFC_CLASSIFIER.getTable(), (short)0);
+        Flow flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.CONFIGURATION);
+        assertNotNull("Could not find flow in config", flow);
+        flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.OPERATIONAL);
+        assertNotNull("Could not find flow in operational", flow);
+
         assertTrue(southboundUtils.deleteBridge(connectionInfo, bridgeName));
         Thread.sleep(1000);
         assertTrue(southboundUtils.disconnectOvsdbNode(connectionInfo));
@@ -600,7 +616,7 @@ public class NetvirtSfcIT extends AbstractMdsalTestBase {
         for (int i = 0; i < 10; i++) {
             flow = FlowUtils.getFlow(flowBuilder, nodeBuilder, dataBroker.newReadOnlyTransaction(), store);
             if (flow != null) {
-                LOG.info("flow({}): {}", store, flow);
+                LOG.info("getFlow: flow({}): {}", store, flow);
                 break;
             }
             Thread.sleep(1000);
index 475c0739e4ab90d1b040db3d629b00fb32c0dcf4..2ab09e90799eb2e192a4360a4a32ae9434e32c99 100644 (file)
@@ -13,10 +13,13 @@ import java.util.concurrent.ExecutionException;
 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
 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.TableKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
@@ -80,4 +83,22 @@ public class FlowUtils {
         LOG.info("Cannot find data for Flow {}", flowBuilder.getFlowName());
         return null;
     }
+
+    public static FlowBuilder getPipelineFlow(short table, short gotoTable) {
+        FlowBuilder flowBuilder = new FlowBuilder();
+        flowBuilder.setMatch(new MatchBuilder().build());
+
+        String flowId = "DEFAULT_PIPELINE_FLOW_" + table;
+        flowBuilder.setId(new FlowId(flowId));
+        FlowKey key = new FlowKey(new FlowId(flowId));
+        flowBuilder.setStrict(true);
+        flowBuilder.setBarrier(false);
+        flowBuilder.setTableId(table);
+        flowBuilder.setKey(key);
+        flowBuilder.setFlowName(flowId);
+        flowBuilder.setHardTimeout(0);
+        flowBuilder.setIdleTimeout(0);
+        flowBuilder.setPriority(0);
+        return flowBuilder;
+    }
 }