This commit includes OpenContrail OC Renderer support. 76/14676/3
authorRajaniS <srivastava.rajani@tcs.com>
Wed, 18 Feb 2015 06:26:11 +0000 (11:56 +0530)
committerRajaniS <srivastava.rajani@tcs.com>
Wed, 18 Feb 2015 06:34:02 +0000 (12:04 +0530)
Change-Id: Ie650b1223fab200fe68229a91405ec7e54bc1157
Signed-off-by: RajaniS <srivastava.rajani@tcs.com>
20 files changed:
commons/parent/pom.xml
distribution-karaf/pom.xml
features/pom.xml
features/src/main/resources/features.xml
groupbasedpolicy-oc-config/pom.xml [new file with mode: 0644]
groupbasedpolicy-oc-config/src/main/resources/initial/15-groupbasedpolicy-oc.xml [new file with mode: 0644]
groupbasedpolicy/pom.xml
groupbasedpolicy/src/main/java/org/opendaylight/controller/config/yang/config/oc_provider/impl/OcProviderModule.java [new file with mode: 0644]
groupbasedpolicy/src/main/java/org/opendaylight/controller/config/yang/config/oc_provider/impl/OcProviderModuleFactory.java [new file with mode: 0644]
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/oc/L2DomainListener.java [new file with mode: 0644]
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/oc/L2DomainManager.java [new file with mode: 0644]
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/oc/OcRenderer.java [new file with mode: 0644]
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/oc/PolicyManager.java [new file with mode: 0644]
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/oc/Utils.java [new file with mode: 0644]
groupbasedpolicy/src/main/yang/renderer/oc/oc-provider-impl.yang [new file with mode: 0644]
groupbasedpolicy/src/main/yang/renderer/oc/oc-provider.yang [new file with mode: 0644]
groupbasedpolicy/src/main/yang/renderer/oc/oc.yang [new file with mode: 0644]
groupbasedpolicy/src/test/java/org/opendaylight/groupbasedpolicy/renderer/oc/TestL2DomainManager.java [new file with mode: 0644]
groupbasedpolicy/src/test/java/org/opendaylight/groupbasedpolicy/renderer/oc/TestUtilsStaticMethod.java [new file with mode: 0644]
pom.xml

index 493d423e4367d19f18e4aa25587ee26f5bee38aa..4e52ac2997a89130fbea09238b8ad81d98220683 100644 (file)
@@ -24,6 +24,7 @@
     <config.configfile.directory>etc/opendaylight/karaf</config.configfile.directory>
     <groupbasedpolicy.project.version>0.2.0-SNAPSHOT</groupbasedpolicy.project.version>
     <config.groupbasedpolicy.ofoverlayconfigfile>15-groupbasedpolicy-ofoverlay.xml</config.groupbasedpolicy.ofoverlayconfigfile>
+    <config.groupbasedpolicy.occonfigfile>15-groupbasedpolicy-oc.xml</config.groupbasedpolicy.occonfigfile>
     <config.groupbasedpolicy.openstackendpointconfigfile>15-groupbasedpolicy-openstackendpoint.xml</config.groupbasedpolicy.openstackendpointconfigfile>
     <karaf.version>3.0.1</karaf.version>
     <exam.version>4.4.0</exam.version> <!-- Needs to remain exported, as its used for dependencies, too -->
@@ -96,3 +97,4 @@
     </pluginRepository>
   </pluginRepositories>
 </project>
+
index 53242c6ff3d77faa28a89b49d8d0dca581506796..f05d32622a31850ff2a31f2f9dc8cd370ed2b5b7 100644 (file)
             <feature>standard</feature>
               <feature>standard</feature>
               <feature>odl-groupbasedpolicy-ofoverlay</feature>
+              <feature>odl-groupbasedpolicy-oc</feature>
               <feature>odl-restconf</feature>
           </bootFeatures>
         </configuration>
     <url>https://git.opendaylight.org/gerrit/gitweb?p=groupbasedpolicy.git;a=summary</url>
   </scm>
 </project>
+
index 45b973c40a388a40f7c180406744f03a372bad6e..305f84f86cc998f36d01d3127c70d8b36e073de4 100644 (file)
@@ -23,6 +23,7 @@
     <feature.test.version>0.7.0-SNAPSHOT</feature.test.version>
     <karaf.empty.version>1.5.0-SNAPSHOT</karaf.empty.version>
     <surefire.version>2.16</surefire.version>
+    <yangtools.version>0.7.0-SNAPSHOT</yangtools.version>
   </properties>
   <dependencies>
     <dependency>
       <version>${yangtools.version}</version>
       <classifier>features</classifier>
       <type>xml</type>
+    </dependency>
+     <dependency>
+       <groupId>org.opendaylight.controller</groupId>
+       <artifactId>features-nsf</artifactId>
+       <version>0.5.0-SNAPSHOT</version>
+       <classifier>features</classifier>
+       <type>xml</type>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>groupbasedpolicy</artifactId>
       <version>${project.version}</version>
     </dependency>
-
+    <dependency>
+       <groupId>org.opendaylight.controller</groupId>
+       <artifactId>features-base</artifactId>
+       <version>1.5.0-SNAPSHOT</version>
+       <classifier>features</classifier>
+       <type>xml</type>
+    </dependency>
     <dependency>
       <groupId>org.opendaylight.yangtools</groupId>
       <artifactId>features-test</artifactId>
       <type>xml</type>
       <classifier>config</classifier>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.groupbasedpolicy</groupId>
+      <artifactId>groupbasedpolicy-oc-config</artifactId>
+      <version>${project.version}</version>
+      <type>xml</type>
+      <classifier>config</classifier>
+    </dependency>
    <!-- dependency for opendaylight-karaf-empty for use by testing -->
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
     <url>https://git.opendaylight.org/gerrit/gitweb?p=groupbasedpolicy.git;a=summary</url>
   </scm>
 </project>
+
index 73ead5efaa70c699cd128fc2719ad944f39a63b6..5c776df3612e14934229521c0de7722612ca6bb0 100644 (file)
@@ -14,6 +14,8 @@
     <repository>mvn:org.opendaylight.controller/features-mdsal/${mdsal.version}/xml/features</repository>
     <repository>mvn:org.opendaylight.openflowplugin/features-openflowplugin/${openflowplugin.distribution.version}/xml/features</repository>
     <repository>mvn:org.opendaylight.openflowplugin/features-openflowplugin-extension/${openflowplugin.distribution.version}/xml/features</repository>
+    <repository>mvn:org.opendaylight.controller/features-base/1.5.0-SNAPSHOT/xml/features</repository>
+    <repository>mvn:org.opendaylight.controller/features-nsf/0.5.0-SNAPSHOT/xml/features</repository>
     <feature name='odl-groupbasedpolicy-ofoverlay' version='${project.version}' description='OpenDaylight :: groupbasedpolicy :: OpenFlow Overlay '>
         <feature version="${mdsal.version}">odl-mdsal-broker</feature>
         <feature version='${yangtools.version}'>odl-yangtools-binding</feature>
         <bundle start="true">mvn:com.fasterxml.jackson.core/jackson-databind/${jackson.version}</bundle>
         <configfile finalname="${config.configfile.directory}/${config.groupbasedpolicy.ofoverlayconfigfile}">mvn:org.opendaylight.groupbasedpolicy/groupbasedpolicy-ofoverlay-config/${project.version}/xml/config</configfile>
     </feature>
+
+    <feature name='odl-groupbasedpolicy-oc' version='${project.version}' description='OpenDaylight :: groupbasedpolicy :: Opencontrail'>
+        <feature version="${mdsal.version}">odl-mdsal-broker</feature>
+        <feature>odl-base-all</feature>
+        <feature>odl-nsf-all</feature>
+        <feature version='${yangtools.version}'>odl-yangtools-binding</feature>
+        <feature version='${yangtools.version}'>odl-yangtools-models</feature>
+        <bundle>mvn:org.opendaylight.groupbasedpolicy/groupbasedpolicy/${project.version}</bundle>
+        <bundle start="true">mvn:com.fasterxml.jackson.core/jackson-annotations/${jackson.version}</bundle>
+        <bundle start="true">mvn:com.fasterxml.jackson.core/jackson-core/${jackson.version}</bundle>
+        <bundle start="true">mvn:com.fasterxml.jackson.core/jackson-databind/${jackson.version}</bundle>
+        <configfile finalname="${config.configfile.directory}/${config.groupbasedpolicy.occonfigfile}">mvn:org.opendaylight.groupbasedpolicy/groupbasedpolicy-oc-config/${project.version}/xml/config
+       </configfile>
+    </feature>
+
     <feature name='odl-groupbasedpolicy-openstackgbp' version='${project.version}' description='OpenDaylight :: groupbasedpolicy :: Support OpenStack GBP Endpoints '>
         <feature version="${project.version}">odl-groupbasedpolicy-ofoverlay</feature>
         <feature version="${mdsal.version}">odl-mdsal-broker</feature>
@@ -36,3 +53,4 @@
         <configfile finalname="${config.configfile.directory}/${config.groupbasedpolicy.openstackendpointconfigfile}">mvn:org.opendaylight.groupbasedpolicy/groupbasedpolicy-openstackendpoint-config/${project.version}/xml/config</configfile>
     </feature>
 </features>
+
diff --git a/groupbasedpolicy-oc-config/pom.xml b/groupbasedpolicy-oc-config/pom.xml
new file mode 100644 (file)
index 0000000..d9d1a19
--- /dev/null
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2014 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
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+      <groupId>org.opendaylight.groupbasedpolicy</groupId>
+      <artifactId>commons.groupbasedpolicy</artifactId>
+      <version>0.2.0-SNAPSHOT</version>
+      <relativePath>../commons/parent</relativePath>
+    </parent>
+
+    <groupId>org.opendaylight.groupbasedpolicy</groupId>
+    <artifactId>groupbasedpolicy-oc-config</artifactId>
+    <description>Controller Configuration files for groupbasedpolicy</description>
+    <packaging>jar</packaging>
+    <build>
+      <plugins>
+          <plugin>
+          <groupId>org.codehaus.mojo</groupId>
+          <artifactId>build-helper-maven-plugin</artifactId>
+          <executions>
+            <execution>
+              <id>attach-artifacts</id>
+              <goals>
+                <goal>attach-artifact</goal>
+              </goals>
+              <phase>package</phase>
+              <configuration>
+                <artifacts>
+                  <artifact>
+                    <file>${project.build.directory}/classes/initial/15-groupbasedpolicy-oc.xml</file>
+                    <type>xml</type>
+                    <classifier>config</classifier>
+                  </artifact>
+                </artifacts>
+              </configuration>
+            </execution>
+          </executions>
+        </plugin>
+      </plugins>
+    </build>
+</project>
diff --git a/groupbasedpolicy-oc-config/src/main/resources/initial/15-groupbasedpolicy-oc.xml b/groupbasedpolicy-oc-config/src/main/resources/initial/15-groupbasedpolicy-oc.xml
new file mode 100644 (file)
index 0000000..ccc8f70
--- /dev/null
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+ Copyright (c) 2013 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
+-->
+<snapshot>
+    <configuration>
+        <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+            <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+                <module>
+                    <type xmlns:oc="urn:opendaylight:params:xml:ns:yang:controller:config:oc-provider:impl">
+                        oc:oc-provider-impl
+                    </type>
+                    <name>oc-provider-impl</name>
+
+                    <rpc-registry>
+                        <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-rpc-registry</type>
+                        <name>binding-rpc-broker</name>
+                    </rpc-registry>
+
+                    <data-broker>
+                      <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-async-data-broker</type>
+                      <name>binding-data-broker</name>
+                    </data-broker>
+                </module>
+            </modules>
+        </data>
+
+    </configuration>
+
+    <required-capabilities>
+        <capability>urn:opendaylight:params:xml:ns:yang:controller:config:oc-provider:impl?module=oc-provider-impl&amp;revision=2014-06-11</capability>
+    </required-capabilities>
+
+</snapshot>
+
index 375cf0a0918288c630f052c9125f8804171f2dea..34b225a945e0aba337104150dc9b4f14626ec5c3 100644 (file)
 
   <artifactId>groupbasedpolicy</artifactId>
   <packaging>bundle</packaging>
+  <repositories>
+  <repository>
+    <id>juniper-contrail</id>
+    <url>https://github.com/Juniper/contrail-maven/raw/master/releases</url>
+   </repository>
+  </repositories>
 
   <properties>
     <openflowplugin-nicira.version>0.1.0-SNAPSHOT</openflowplugin-nicira.version>
   </properties>
 
   <dependencies>
+   <dependency>
+    <groupId>net.juniper.contrail</groupId>
+    <artifactId>juniper-contrail-api</artifactId>
+    <version>1.2</version>
+    </dependency>
+    <dependency>
+     <groupId>org.apache.httpcomponents</groupId>
+      <artifactId>httpcore</artifactId>
+       <version>4.3.2</version>
+      </dependency>
+      <dependency>
+     <groupId>org.apache.httpcomponents</groupId>
+      <artifactId>httpclient</artifactId>
+      <version>4.3.2</version>
+     </dependency>
     <dependency>
       <groupId>ch.qos.logback</groupId>
       <artifactId>logback-classic</artifactId>
       <groupId>org.osgi</groupId>
       <artifactId>org.osgi.core</artifactId>
     </dependency>
-
+    <dependency>
+      <groupId>commons-lang</groupId>
+      <artifactId>commons-lang</artifactId>
+      <version>2.6</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.commons</groupId>
+      <artifactId>commons-exec</artifactId>
+      <version>1.1</version>
+    </dependency>
     <dependency>
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>
     <dependency>
       <groupId>org.mockito</groupId>
       <artifactId>mockito-all</artifactId>
+      <version>1.9.5</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.powermock</groupId>
+      <artifactId>powermock-module-junit4</artifactId>
+      <version>1.5.6</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.powermock</groupId>
+      <artifactId>powermock-api-mockito</artifactId>
+      <version>1.5.6</version>
       <scope>test</scope>
     </dependency>
   </dependencies>
         <extensions>true</extensions>
         <configuration>
           <instructions>
-            <Import-Package>*</Import-Package>
+            <Import-Package>
+             org.apache.http.*;version="4.3.2",
+             *;resolution:=optional</Import-Package>
+             <Embed-Dependency>httpclient,httpcore,commons-lang,commons-exec;type=!pom;inline=false</Embed-Dependency>
             <Export-Package>
              org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.*,
              org.opendaylight.controller.config.yang.config.endpoint_provider,
              org.opendaylight.groupbasedpolicy.endpoint,
-             org.opendaylight.groupbasedpolicy.resolver
+             org.opendaylight.groupbasedpolicy.resolver,
+             net.juniper.contrail.api.*;version="1.2"
            </Export-Package>
           </instructions>
           <manifestLocation>${project.basedir}/META-INF</manifestLocation>
     </plugins>
   </build>
 </project>
+
diff --git a/groupbasedpolicy/src/main/java/org/opendaylight/controller/config/yang/config/oc_provider/impl/OcProviderModule.java b/groupbasedpolicy/src/main/java/org/opendaylight/controller/config/yang/config/oc_provider/impl/OcProviderModule.java
new file mode 100644 (file)
index 0000000..e44e691
--- /dev/null
@@ -0,0 +1,25 @@
+package org.opendaylight.controller.config.yang.config.oc_provider.impl;
+
+import org.opendaylight.groupbasedpolicy.renderer.oc.OcRenderer;
+
+public class OcProviderModule extends org.opendaylight.controller.config.yang.config.oc_provider.impl.AbstractOcProviderModule {
+    public OcProviderModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+        super(identifier, dependencyResolver);
+    }
+
+    public OcProviderModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.controller.config.yang.config.oc_provider.impl.OcProviderModule oldModule, java.lang.AutoCloseable oldInstance) {
+        super(identifier, dependencyResolver, oldModule, oldInstance);
+    }
+
+    @Override
+    public void customValidation() {
+        // add custom validation form module attributes here.
+    }
+
+    @Override
+    public java.lang.AutoCloseable createInstance() {
+        return new OcRenderer(getDataBrokerDependency(),
+                getRpcRegistryDependency());
+}
+
+}
diff --git a/groupbasedpolicy/src/main/java/org/opendaylight/controller/config/yang/config/oc_provider/impl/OcProviderModuleFactory.java b/groupbasedpolicy/src/main/java/org/opendaylight/controller/config/yang/config/oc_provider/impl/OcProviderModuleFactory.java
new file mode 100644 (file)
index 0000000..baabae4
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+* Generated file
+*
+* Generated from: yang module name: oc-provider-impl yang module local name: oc-provider-impl
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Thu Jan 22 14:49:56 IST 2015
+*
+* Do not modify this file unless it is present under src/main directory
+*/
+package org.opendaylight.controller.config.yang.config.oc_provider.impl;
+public class OcProviderModuleFactory extends org.opendaylight.controller.config.yang.config.oc_provider.impl.AbstractOcProviderModuleFactory {
+
+}
diff --git a/groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/oc/L2DomainListener.java b/groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/oc/L2DomainListener.java
new file mode 100644 (file)
index 0000000..71844b0
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2015 Juniper Networks, Inc.  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.groupbasedpolicy.renderer.oc;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2FloodDomainId;
+
+
+/**
+ * A listener to events related to L2 flood domain being added, removed or updated.
+ */
+public interface L2DomainListener {
+    /**
+     * The L2 Flood Domain has been added or updated
+     * @param L2FloodDomainId L2 Flood domain id
+     */
+    public void L2DomainUpdated(L2FloodDomainId l2domainid);
+}
diff --git a/groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/oc/L2DomainManager.java b/groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/oc/L2DomainManager.java
new file mode 100644 (file)
index 0000000..b9ccefc
--- /dev/null
@@ -0,0 +1,380 @@
+/*
+ * Copyright (c) 2015 Juniper Networks, Inc.  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.groupbasedpolicy.renderer.oc;
+
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.UUID;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.ScheduledExecutorService;
+
+import net.juniper.contrail.api.ApiConnector;
+import net.juniper.contrail.api.types.Project;
+import net.juniper.contrail.api.types.VirtualNetwork;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.Tenants;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.Tenant;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.L2FloodDomain;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+public class L2DomainManager implements AutoCloseable, DataChangeListener {
+       private static final Logger LOG = LoggerFactory
+                       .getLogger(L2DomainManager.class);
+       static ApiConnector apiConnector;
+       private static final InstanceIdentifier<Tenant> TenantIid = InstanceIdentifier
+                       .builder(Tenants.class).child(Tenant.class).build();
+       private ListenerRegistration<DataChangeListener> listenerReg;
+
+       private final DataBroker dataProvider;
+       private List<L2DomainListener> listeners = new CopyOnWriteArrayList<>();
+
+       public L2DomainManager(DataBroker dataProvider,
+                       RpcProviderRegistry rpcRegistry, ScheduledExecutorService executor) {
+
+               super();
+               this.dataProvider = dataProvider;
+               if (dataProvider != null) {
+                       listenerReg = dataProvider.registerDataChangeListener(
+                                       LogicalDatastoreType.CONFIGURATION, TenantIid, this,
+                                       DataChangeScope.ONE);
+               } else
+                       listenerReg = null;
+
+               LOG.debug("Initialized L2 Domain manager");
+       }
+
+    public void registerListener(L2DomainListener listener) {
+        listeners.add(listener);
+    }
+
+       // ******************
+       // DataChangeListener
+       // ******************
+
+       @Override
+       public void onDataChanged(
+                       AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+               for (DataObject dao : change.getCreatedData().values()) {
+                       if (dao instanceof Tenant)
+                       try {
+                               createL2FloodDomain((Tenant)dao);
+                       } catch (IOException e) {
+                               // TODO Auto-generated catch block
+                               e.printStackTrace();
+                       }
+               }
+               Map<InstanceIdentifier<?>,DataObject> d = change.getUpdatedData();
+        for (Entry<InstanceIdentifier<?>, DataObject> entry : d.entrySet()) {
+            if (!(entry.getValue() instanceof Tenant)) continue;
+            DataObject old = change.getOriginalData().get(entry.getKey());
+            Tenant olddata = null;
+            if (old != null && old instanceof Tenant)
+                olddata = (Tenant)old;
+                try {
+                       updateL2FloodDomain(olddata, (Tenant)entry.getValue());
+                       } catch (IOException e) {
+                               // TODO Auto-generated catch block
+                               e.printStackTrace();
+                       }
+        }
+       }
+
+       @Override
+       public void close() throws Exception {
+               // TODO Auto-generated method stub
+       }
+
+        /**
+     * Invoked when a L2FloodDomain create is requested
+     *
+     *@param  tenant
+     *                An instance of tenant data
+     */
+
+       public void createL2FloodDomain(Tenant tenant) throws IOException{
+               String tenantID = tenant.getId().toString();
+               if (tenant.getL2FloodDomain() != null){
+                       for(L2FloodDomain l2FloodDomain : tenant.getL2FloodDomain()) {
+                               canCreateFloodDomain(l2FloodDomain, tenantID);
+                               createFloodDomain(l2FloodDomain, tenantID);
+                       }
+               }
+       }
+
+        /**
+     * Invoked when a L2FloodDomain create is requested to indicate if the specified
+     * L2FloodDomain can be created using the specified delta.
+     *
+     *@param  l2FloodDomain
+     *                An instance of l2FloodDomain
+     *@param  tenantid
+     *                Tenant id
+     */
+
+       public int canCreateFloodDomain(L2FloodDomain l2FloodDomain, String tenantID) {
+        apiConnector = OcRenderer.apiConnector;
+
+        if (l2FloodDomain.getId() == null || l2FloodDomain.getName() == null
+                       || l2FloodDomain.getId().equals("") || l2FloodDomain.getName().equals("")) {
+            LOG.error("l2FloodDomain id or name can't be null/empty...");
+            return HttpURLConnection.HTTP_BAD_REQUEST;
+        }
+
+        try {
+            String l2FloodDomainUUID = Utils.uuidNameFormat(l2FloodDomain.getId().toString());
+            String projectUUID = Utils.uuidNameFormat(tenantID);
+            try {
+                if (!(l2FloodDomainUUID.contains("-"))) {
+                       l2FloodDomainUUID = Utils.uuidFormater(l2FloodDomainUUID);
+                }
+                if (!(projectUUID.contains("-"))) {
+                    projectUUID = Utils.uuidFormater(projectUUID);
+                }
+                boolean isValidl2FloodDomainUUID = Utils.isValidHexNumber(l2FloodDomainUUID);
+                boolean isValidprojectUUID = Utils.isValidHexNumber(projectUUID);
+                if (!isValidl2FloodDomainUUID || !isValidprojectUUID) {
+                    LOG.info("Badly formed Hexadecimal UUID...");
+                    return HttpURLConnection.HTTP_BAD_REQUEST;
+                }
+                projectUUID = UUID.fromString(projectUUID).toString();
+                l2FloodDomainUUID = UUID.fromString(l2FloodDomainUUID).toString();
+            } catch (Exception ex) {
+                LOG.error("UUID input incorrect", ex);
+                return HttpURLConnection.HTTP_BAD_REQUEST;
+            }
+
+            Project project = (Project) apiConnector.findById(Project.class, projectUUID);
+            if (project == null) {
+                try {
+                    Thread.currentThread();
+                    Thread.sleep(3000);
+                } catch (InterruptedException e) {
+                    LOG.error("InterruptedException :    ", e);
+                    return HttpURLConnection.HTTP_BAD_REQUEST;
+                }
+               project = (Project) apiConnector.findById(Project.class, projectUUID);
+                if (project == null) {
+                    LOG.error("Could not find projectUUID...");
+                    return HttpURLConnection.HTTP_NOT_FOUND;
+                }
+           }
+           VirtualNetwork virtualNetworkById = (VirtualNetwork) apiConnector.findById(VirtualNetwork.class, l2FloodDomainUUID);
+            if (virtualNetworkById != null) {
+                LOG.warn("l2FloodDomain already exists with UUID" + l2FloodDomainUUID);
+                return HttpURLConnection.HTTP_FORBIDDEN;
+            }
+            return HttpURLConnection.HTTP_OK;
+        } catch (Exception e) {
+            LOG.error("Exception :   " + e);
+            return HttpURLConnection.HTTP_INTERNAL_ERROR;
+        }
+    }
+
+    /**
+     * Invoked to create the specified L2FloodDomain.
+     *
+     * @param L2FloodDomain
+     *            An instance of new L2FloodDomain object.
+     *
+     * @param  tenantid
+     *            Tenant id
+     */
+    private void createFloodDomain(L2FloodDomain l2FloodDomain, String tenantid) throws IOException {
+        VirtualNetwork virtualNetwork = new VirtualNetwork();
+        virtualNetwork = mapNetworkProperties(l2FloodDomain, virtualNetwork, tenantid);
+        boolean l2FloodDomainCreated;
+        try {
+               l2FloodDomainCreated = apiConnector.create(virtualNetwork);
+            if (!l2FloodDomainCreated) {
+                LOG.warn("l2FloodDomain creation failed..");
+            }
+        } catch (IOException ioEx) {
+            LOG.error("Exception : " + ioEx);
+        }
+        LOG.info("l2FloodDomain : " + virtualNetwork.getName() + "  having UUID : " + virtualNetwork.getUuid() + "  sucessfully created...");
+    }
+
+    /**
+     * Invoked to map the L2FloodDomain object properties to the virtualNetwork
+     * object.
+     *
+     * @param L2FloodDomain
+     *            An instance of L2FloodDomain object.
+     * @param virtualNetwork
+     *            An instance of new virtualNetwork object.
+     *
+     * @param tenantid
+     *            tenant id
+     * @return {@link VirtualNetwork}
+     */
+    private VirtualNetwork mapNetworkProperties(L2FloodDomain l2FloodDomain, VirtualNetwork virtualNetwork, String tenantid) {
+        String l2FloodDomainUUID = Utils.uuidNameFormat(l2FloodDomain.getId().toString());
+        String projectUUID = Utils.uuidNameFormat(tenantid);
+        String l2FloodDomainName = Utils.uuidNameFormat(l2FloodDomain.getName().toString());
+        try {
+            if (!(l2FloodDomainUUID.contains("-"))) {
+               l2FloodDomainUUID = Utils.uuidFormater(l2FloodDomainUUID);
+            }
+            l2FloodDomainUUID = UUID.fromString(l2FloodDomainUUID).toString();
+            if (!(projectUUID.contains("-"))) {
+                projectUUID = Utils.uuidFormater(projectUUID);
+            }
+            projectUUID = UUID.fromString(projectUUID).toString();
+            Project project = (Project) apiConnector.findById(Project.class, projectUUID);
+            virtualNetwork.setParent(project);
+        } catch (Exception ex) {
+            LOG.error("UUID input incorrect", ex);
+        }
+        virtualNetwork.setName(l2FloodDomainName);
+        virtualNetwork.setUuid(l2FloodDomainUUID);
+        virtualNetwork.setDisplayName(l2FloodDomainName);
+        return virtualNetwork;
+    }
+
+    /**
+     * Invoked when a L2FloodDomain update is requested
+     *
+     *@param  oldData
+     *                An instance of Old tenant data
+     *@param  newData
+     *                An instance of New tenant data
+     */
+
+    public void updateL2FloodDomain(Tenant oldData, Tenant newData) throws IOException{
+               String tenantID = newData.getId().toString();
+               if (newData.getL2FloodDomain() != null){
+                       if(oldData.getL2FloodDomain() == null){
+                               for(L2FloodDomain l2FloodDomain : newData.getL2FloodDomain()) {
+                                       canCreateFloodDomain(l2FloodDomain, tenantID);
+                                       createFloodDomain(l2FloodDomain, tenantID);
+                               }
+                       }
+                       else {
+                               for(L2FloodDomain l2FloodDomainNew : newData.getL2FloodDomain()) {
+                                       for(L2FloodDomain l2FloodDomainOld : oldData.getL2FloodDomain()) {
+                                               String l2FloodDomainNewId = Utils.uuidNameFormat(l2FloodDomainNew.getId().toString());
+                                               String l2FloodDomainOldId = Utils.uuidNameFormat(l2FloodDomainOld.getId().toString());
+                                               if(l2FloodDomainNewId.equals(l2FloodDomainOldId)){
+                                                       canUpdateFloodDomain(l2FloodDomainNew, l2FloodDomainOld, tenantID);
+                                                       updateFloodDomain(l2FloodDomainNew, tenantID);
+                                               }
+                                               else{
+                                                       canCreateFloodDomain(l2FloodDomainNew, tenantID);
+                                                       createFloodDomain(l2FloodDomainNew, tenantID);
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+
+    /**
+     * Invoked when a L2FloodDomain update is requested to indicate if the specified
+     * L2FloodDomain can be changed using the specified delta.
+     *
+     *@param  l2FloodDomainNew
+     *                An instance of updated l2FloodDomain
+     *@param  l2FloodDomainOld
+     *                An instance of old l2FloodDomain
+     *@param  tenantid
+     *                Tenant id
+     */
+
+    public int canUpdateFloodDomain(L2FloodDomain l2FloodDomainNew, L2FloodDomain l2FloodDomainOld, String tenantID ) {
+        VirtualNetwork virtualnetwork;
+        apiConnector = OcRenderer.apiConnector;
+
+        String l2FloodDomainUUID = Utils.uuidNameFormat(l2FloodDomainOld.getId().toString());
+        String projectUUID = Utils.uuidNameFormat(tenantID);
+        try {
+            if (!(l2FloodDomainUUID.contains("-"))) {
+               l2FloodDomainUUID = Utils.uuidFormater(l2FloodDomainUUID);
+               l2FloodDomainUUID = UUID.fromString(l2FloodDomainUUID).toString();
+            }
+            if (!(projectUUID.contains("-"))) {
+                projectUUID = Utils.uuidFormater(projectUUID);
+                projectUUID = UUID.fromString(projectUUID).toString();
+            }
+        } catch (Exception ex) {
+            LOG.error("UUID input incorrect", ex);
+        }
+        if(l2FloodDomainNew.getName() == null){
+            LOG.error("L2 flood domain Name to be update can't be empty..");
+            return HttpURLConnection.HTTP_BAD_REQUEST;
+        }
+        try {
+            Project project = (Project) apiConnector.findById(Project.class, projectUUID);
+            String virtualNetworkByName = apiConnector.findByName(VirtualNetwork.class, project, l2FloodDomainNew.getName().toString());
+            if (virtualNetworkByName != null) {
+                LOG.warn("L2 flood domain with name  " + l2FloodDomainNew.getName() + "  already exists with UUID : " + virtualNetworkByName);
+                return HttpURLConnection.HTTP_FORBIDDEN;
+            }
+        } catch (IOException ioEx) {
+            LOG.error("IOException :     " + ioEx);
+            return HttpURLConnection.HTTP_INTERNAL_ERROR;
+        }
+        try {
+            virtualnetwork = (VirtualNetwork) apiConnector.findById(VirtualNetwork.class, l2FloodDomainUUID);
+        } catch (IOException ex) {
+            LOG.error("Exception :     " + ex);
+            return HttpURLConnection.HTTP_INTERNAL_ERROR;
+        }
+        if (virtualnetwork == null) {
+            LOG.error("No L2 flood domain exists for the specified UUID...");
+            return HttpURLConnection.HTTP_FORBIDDEN;
+        }
+        return HttpURLConnection.HTTP_OK;
+    }
+
+    /**
+     * Invoked to update the L2 Flood Domain
+     *
+     *@param  l2FloodDomain
+     *                An instance of updated l2FloodDomain
+     *@param  tenantid
+     *                Tenant id
+     */
+    private void updateFloodDomain(L2FloodDomain l2FloodDomain, String tenantid) throws IOException {
+        String l2FloodDomainUUID = Utils.uuidNameFormat(l2FloodDomain.getId().toString());
+        try {
+            if (!(l2FloodDomainUUID.contains("-"))) {
+               l2FloodDomainUUID = Utils.uuidFormater(l2FloodDomainUUID);
+            }
+            l2FloodDomainUUID = UUID.fromString(l2FloodDomainUUID).toString();
+        } catch (Exception ex) {
+            LOG.error("UUID input incorrect", ex);
+        }
+        VirtualNetwork virtualNetwork = (VirtualNetwork) apiConnector.findById(VirtualNetwork.class, l2FloodDomainUUID);
+        virtualNetwork.setDisplayName(Utils.uuidNameFormat(l2FloodDomain.getName().toString()));
+        boolean l2FloodDomainUpdate;
+        try {
+               l2FloodDomainUpdate = apiConnector.update(virtualNetwork);
+            if (!l2FloodDomainUpdate) {
+                LOG.warn("L2 flood domain Updation failed..");
+            }
+        } catch (IOException e) {
+            LOG.warn("L2 flood domain Updation failed..");
+        }
+        LOG.info("L2 flood domain having UUID : " + virtualNetwork.getUuid() + "  has been sucessfully updated...");
+    }
+}
\ No newline at end of file
diff --git a/groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/oc/OcRenderer.java b/groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/oc/OcRenderer.java
new file mode 100644 (file)
index 0000000..3787b11
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2015 Juniper Networks, Inc.  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.groupbasedpolicy.renderer.oc;
+
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+
+import net.juniper.contrail.api.ApiConnector;
+import net.juniper.contrail.api.ApiConnectorFactory;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.groupbasedpolicy.resolver.PolicyResolver;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.oc.rev140528.OcConfig;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+
+/**
+ * Renderer that uses OpenContrail
+ */
+public class OcRenderer implements AutoCloseable, DataChangeListener {
+    private static final Logger LOG =
+            LoggerFactory.getLogger(OcRenderer.class);
+    static ApiConnector apiConnector = null;
+    private final DataBroker dataBroker;
+    private final PolicyResolver policyResolver;
+    private final L2DomainManager l2domainManager;
+    private final PolicyManager policyManager;
+
+    private final ScheduledExecutorService executor;
+
+    private static final InstanceIdentifier<OcConfig> configIid =
+            InstanceIdentifier.builder(OcConfig.class).build();
+    private OcConfig config;
+    ListenerRegistration<DataChangeListener> configReg;
+
+    public OcRenderer(DataBroker dataProvider,
+                             RpcProviderRegistry rpcRegistry) {
+        super();
+        this.dataBroker = dataProvider;
+        apiConnector = getApiConnection();
+
+        int numCPU = Runtime.getRuntime().availableProcessors();
+        executor = Executors.newScheduledThreadPool(numCPU * 2);
+
+        l2domainManager = new L2DomainManager(dataProvider,rpcRegistry,executor);
+        policyResolver = new PolicyResolver(dataProvider, executor);
+
+        policyManager = new PolicyManager(dataProvider,
+                                          policyResolver,
+                                          l2domainManager,
+                                          rpcRegistry,
+                                          executor);
+
+        configReg =
+                dataProvider.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
+                                                        configIid,
+                                                        this,
+                                                        DataChangeScope.SUBTREE);
+        readConfig();
+        LOG.info("Initialized OC renderer");
+
+    }
+
+    public ApiConnector getApiConnection() {
+       String ipAddress = System.getProperty("plugin2oc.apiserver.ipaddress");
+       String port = System.getProperty("plugin2oc.apiserver.port");
+
+       int portNumber = 0;
+        try {
+            portNumber = Integer.parseInt(port.toString());
+        } catch (Exception ex) {
+            LOG.error("Missing entry in Config file of Opendaylight", ex);
+        }
+        apiConnector = ApiConnectorFactory.build(ipAddress, portNumber);
+        return apiConnector;
+    }
+
+    // *************
+    // AutoCloseable
+    // *************
+
+    @Override
+    public void close() throws Exception {
+        executor.shutdownNow();
+        if (configReg != null) configReg.close();
+        if (policyResolver != null) policyResolver.close();
+        if (l2domainManager != null) l2domainManager.close();
+    }
+
+    // ******************
+    // DataChangeListener
+    // ******************
+
+    @Override
+    public void onDataChanged(AsyncDataChangeEvent<InstanceIdentifier<?>,
+                                                   DataObject> change) {
+        readConfig();
+    }
+
+    // **************
+    // Implementation
+    // **************
+
+    private void readConfig() {
+        ListenableFuture<Optional<OcConfig>> dao =
+                dataBroker.newReadOnlyTransaction()
+                    .read(LogicalDatastoreType.CONFIGURATION, configIid);
+        Futures.addCallback(dao, new FutureCallback<Optional<OcConfig>>() {
+            @Override
+            public void onSuccess(final Optional<OcConfig> result) {
+                if (!result.isPresent()) return;
+                if (result.get() instanceof OcConfig) {
+                    config = (OcConfig)result.get();
+                    applyConfig();
+                }
+            }
+
+            @Override
+            public void onFailure(Throwable t) {
+                LOG.error("Failed to read configuration", t);
+            }
+        }, executor);
+    }
+
+    private void applyConfig() {
+        policyManager.setLearningMode(config.getLearningMode());
+    }
+}
diff --git a/groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/oc/PolicyManager.java b/groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/oc/PolicyManager.java
new file mode 100644 (file)
index 0000000..aa07582
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2015 Juniper Networks, Inc.  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.groupbasedpolicy.renderer.oc;
+
+import java.util.Set;
+import java.util.concurrent.ScheduledExecutorService;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.groupbasedpolicy.resolver.EgKey;
+import org.opendaylight.groupbasedpolicy.resolver.PolicyListener;
+import org.opendaylight.groupbasedpolicy.resolver.PolicyResolver;
+import org.opendaylight.groupbasedpolicy.resolver.PolicyScope;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2FloodDomainId;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Manage policies
+ */
+public class PolicyManager implements PolicyListener, L2DomainListener {
+    private static final Logger LOG =
+            LoggerFactory.getLogger(PolicyManager.class);
+
+    private final PolicyResolver policyResolver;
+    private final PolicyScope policyScope;
+    private final ScheduledExecutorService executor;
+
+    public PolicyManager(DataBroker dataBroker,
+                         PolicyResolver policyResolver,
+                         L2DomainManager l2domainManager,
+                         RpcProviderRegistry rpcRegistry,
+                         ScheduledExecutorService executor) {
+        super();
+        this.executor = executor;
+        this.policyResolver = policyResolver;
+
+       policyScope = policyResolver.registerListener(this);
+       l2domainManager.registerListener((L2DomainListener) this);
+        LOG.debug("Initialized OC policy manager");
+    }
+
+    /**
+     * Set the learning mode to the specified value
+     * @param learningMode the learning mode to set
+     */
+    public void setLearningMode(org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.oc.rev140528.OcConfig.LearningMode learningMode) {
+        // No-op for now
+    }
+
+    public void L2DomainUpdated(L2FloodDomainId id) {
+               // TODO Auto-generated method stub
+       }
+
+       @Override
+       public void policyUpdated(Set<EgKey> updatedGroups) {
+               // TODO Auto-generated method stub
+       }
+}
\ No newline at end of file
diff --git a/groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/oc/Utils.java b/groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/oc/Utils.java
new file mode 100644 (file)
index 0000000..74da664
--- /dev/null
@@ -0,0 +1,80 @@
+/*\r
+ * Copyright (c) 2015 Juniper Networks, Inc.  All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+\r
+package org.opendaylight.groupbasedpolicy.renderer.oc;\r
+\r
+import java.util.regex.Pattern;\r
+\r
+import org.slf4j.Logger;\r
+import org.slf4j.LoggerFactory;\r
+\r
+public class Utils {\r
+\r
+    static final Logger LOGGER = LoggerFactory.getLogger(Utils.class);\r
+\r
+    /**\r
+     * Invoked to format the UUID if UUID is not in correct format.\r
+     *\r
+     * @param String\r
+     *            An instance of UUID string.\r
+     *\r
+     * @return Correctly formated UUID string.\r
+     */\r
+    public static String uuidFormater(String uuid) {\r
+        String uuidPattern = null;\r
+        String id1 = uuid.substring(0, 8);\r
+        String id2 = uuid.substring(8, 12);\r
+        String id3 = uuid.substring(12, 16);\r
+        String id4 = uuid.substring(16, 20);\r
+        String id5 = uuid.substring(20, 32);\r
+        uuidPattern = (id1 + "-" + id2 + "-" + id3 + "-" + id4 + "-" + id5);\r
+        return uuidPattern;\r
+    }\r
+\r
+    /**\r
+     * Invoked to check the UUID if UUID is not a valid hexa-decimal number.\r
+     *\r
+     * @param String\r
+     *            An instance of UUID string.\r
+     *\r
+     * @return boolean value.\r
+     */\r
+    public static boolean isValidHexNumber(String uuid) {\r
+        try {\r
+            Pattern hex = Pattern.compile("^[0-9a-f]+$");\r
+            uuid = uuid.replaceAll("-", "");\r
+            boolean valid = hex.matcher(uuid).matches();\r
+            if (uuid.length() != 32) {\r
+                return false;\r
+            }\r
+            if (valid) {\r
+                return true;\r
+            } else {\r
+                return false;\r
+            }\r
+        } catch (NumberFormatException ex) {\r
+            LOGGER.error("Exception :  " + ex);\r
+            return false;\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Invoked to format the UUID/Name in correct format.\r
+     *\r
+     * @param String\r
+     *            An instance of UUID/Name string.\r
+     *\r
+     * @return Correctly formated UUID/name string.\r
+     */\r
+\r
+    public static String uuidNameFormat(String value){\r
+       String[] pattern = value.split("=");\r
+       value = pattern[1].replace("]", "");\r
+       return value;\r
+    }\r
+}
\ No newline at end of file
diff --git a/groupbasedpolicy/src/main/yang/renderer/oc/oc-provider-impl.yang b/groupbasedpolicy/src/main/yang/renderer/oc/oc-provider-impl.yang
new file mode 100644 (file)
index 0000000..d2fb9c8
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2015 Juniper Networks, Inc.  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
+ */
+
+module oc-provider-impl {
+    yang-version 1;
+    namespace "urn:opendaylight:params:xml:ns:yang:controller:config:oc-provider:impl";
+    prefix "oc-provider-impl";
+
+    import config { prefix config; revision-date 2013-04-05; }
+    import opendaylight-md-sal-binding { prefix mdsal; revision-date 2013-10-28; }
+
+    description
+        "This module contains the base YANG definitions for
+          oc-provider impl implementation.";
+
+    revision "2014-06-11" {
+        description
+            "Initial revision.";
+    }
+
+    identity oc-provider-impl {
+        base "config:module-type";
+
+        config:java-name-prefix OcProvider;
+    }
+
+    // Augments the 'configuration' choice node under modules/module.
+    augment "/config:modules/config:module/config:configuration" {
+        case oc-provider-impl {
+            when "/config:modules/config:module/config:type = 'oc-provider-impl'";
+
+            //wires in the data-broker service
+            container data-broker {
+                uses config:service-ref {
+                    refine type {
+                        mandatory true;
+                        config:required-identity mdsal:binding-async-data-broker;
+                    }
+                }
+            }
+            // RPC Registry
+            container rpc-registry {
+                uses config:service-ref {
+                    refine type {
+                        mandatory true;
+                        config:required-identity mdsal:binding-rpc-registry;
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/groupbasedpolicy/src/main/yang/renderer/oc/oc-provider.yang b/groupbasedpolicy/src/main/yang/renderer/oc/oc-provider.yang
new file mode 100644 (file)
index 0000000..153ca04
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2015 Juniper Networks, Inc.  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
+ */
+
+module oc-provider {
+     yang-version 1;
+     namespace "urn:opendaylight:params:xml:ns:yang:controller:config:oc-provider";
+     prefix "oc-provider";
+
+     import config { prefix config; revision-date 2013-04-05; }
+
+     description
+         "This module contains the base YANG definitions for
+          oc-provider services.";
+
+     revision "2014-04-21" {
+         description
+             "Initial revision.";
+     }
+
+     identity oc-provider {
+         base "config:service-type";
+         config:java-class "org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.oc.rev140528.OcData";
+     }
+}
diff --git a/groupbasedpolicy/src/main/yang/renderer/oc/oc.yang b/groupbasedpolicy/src/main/yang/renderer/oc/oc.yang
new file mode 100644 (file)
index 0000000..43a9cd3
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2015 Juniper Networks, Inc.  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
+ */
+
+module oc {
+    yang-version 1;
+
+    namespace "urn:opendaylight:groupbasedpolicy:oc";
+    prefix "oc";
+
+    import ietf-inet-types { prefix "inet"; revision-date 2010-09-24; }
+
+    import yang-ext {prefix ext; revision-date "2013-07-09";}
+
+    import gbp-common {prefix gbp-common;}
+    import endpoint {prefix endpoint;}
+
+    description
+        "This module defines the group-based policy oc renderer model.";
+
+    revision "2014-05-28" {
+        description
+            "Initial revision.";
+    }
+
+    // ******************
+    // Configuration Data
+    // ******************
+    container oc-config {
+        description
+            "Configuration for the OC renderer";
+        config true;
+
+           leaf learning-mode {
+            description
+                "Selects how and whether we learn endpoints";
+            type enumeration {
+                enum orchestrated {
+                    description
+                        "An external orchestration system will provide
+                         information about all endpoints, and no
+                         direct learning will occur.";
+                }
+            }
+        }
+    }
+
+    grouping endpoint-location {
+        description
+            "The location for this endpoint in the overlay network";
+
+        leaf location-type {
+            default internal;
+
+            type enumeration {
+                enum internal {
+                    description
+                    "The endpoint is located on a port that is part of
+                     the network.  You must include the node
+                     ID and port number for this endpoint.";
+                }
+                enum external {
+                    description "This endpoint is not inside the network.";
+                }
+            }
+        }
+        leaf port-id {
+            description
+                "The port where the endpoint is located.";
+            type string;
+        }
+    }
+
+    augment "/endpoint:endpoints/endpoint:endpoint" {
+        ext:augment-identifier "oc-context";
+        uses endpoint-location;
+    }
+
+    augment "/endpoint:register-endpoint/endpoint:input" {
+        ext:augment-identifier "oc-context-input";
+        uses endpoint-location;
+    }
+}
\ No newline at end of file
diff --git a/groupbasedpolicy/src/test/java/org/opendaylight/groupbasedpolicy/renderer/oc/TestL2DomainManager.java b/groupbasedpolicy/src/test/java/org/opendaylight/groupbasedpolicy/renderer/oc/TestL2DomainManager.java
new file mode 100644 (file)
index 0000000..083fc5c
--- /dev/null
@@ -0,0 +1,221 @@
+/*
+ * Copyright (C) 2015 Juniper Networks, Inc.
+ *
+ * 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.groupbasedpolicy.renderer.oc;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ScheduledExecutorService;
+
+import net.juniper.contrail.api.ApiConnector;
+import net.juniper.contrail.api.types.FloatingIpPool;
+import net.juniper.contrail.api.types.Project;
+import net.juniper.contrail.api.types.VirtualNetwork;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.groupbasedpolicy.jsonrpc.JsonRpcEndpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2FloodDomainId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.Name;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.L2FloodDomain;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.CheckedFuture;
+
+/**
+ * Test Class for L2 Flood Domain.
+ */
+
+public class TestL2DomainManager {
+    L2DomainManager domainmanager;
+    ApiConnector apiconnector;
+    ApiConnector mockedApiConnector = mock(ApiConnector.class);
+    VirtualNetwork mockedVirtualNetwork = mock(VirtualNetwork.class);
+    Project mockedProject = mock(Project.class);
+    FloatingIpPool mockedFloatingIpPool = mock(FloatingIpPool.class);
+    L2FloodDomain mockFd = mock(L2FloodDomain.class);
+    L2FloodDomain mockFdNew = mock(L2FloodDomain.class);
+    @Mock
+    private DataBroker mockBroker;
+    @Mock
+    private RpcProviderRegistry mockRpcRegistry;
+    @Mock
+    private ScheduledExecutorService mockExecutor;
+    @Mock
+    private ListenerRegistration<DataChangeListener> mockListener;
+    @Mock
+    private ListenerRegistration<DataChangeListener> mockL3Listener;
+    @Mock
+    private CheckedFuture<Optional<L2FloodDomain>,ReadFailedException> mockReadFuture;
+    @Mock
+    private JsonRpcEndpoint mockAgent;
+    @Mock
+    private OcRenderer mockOcRenderer;
+    @Mock
+    private WriteTransaction mockWriteTransaction;
+    @Mock
+    private ReadOnlyTransaction mockReadTransaction;
+    @Mock
+    private CheckedFuture<Void, TransactionCommitFailedException> mockWriteFuture;
+    @Mock
+    private AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> mockChange;
+    @Mock
+    private Map<InstanceIdentifier<?>, DataObject> mockDaoMap;
+    @Mock
+    private Set<InstanceIdentifier<?>> mockDaoSet;
+    @Mock
+    private DataObject mockDao;
+    @Mock
+    private InstanceIdentifier<?> mockIid;
+    protected static final Logger logger = LoggerFactory.getLogger(L2DomainManager.class);
+    private static final String TENANT_ID = "22282cca-9a13-4d0c-a67e-a933ebb0b0ae";
+    private static final String TENANT_ID_VALUE = "[_value=22282cca-9a13-4d0c-a67e-a933ebb0b0ae]";
+    private static final L2FloodDomainId FLOOD_DOMAIN_ID = new L2FloodDomainId("08e3904c-7850-41c0-959a-1a646a83598a");
+    private static final Name FLOOD_DOMAIN_NAME = new Name("MOCK_DOMAIN");
+
+    List<DataObject> daoList =
+            new ArrayList<DataObject>();
+
+    @Before
+    public void beforeTest() {
+       domainmanager = new L2DomainManager(mockBroker, mockRpcRegistry, mockExecutor);
+        assertNotNull(mockedApiConnector);
+        assertNotNull(mockedVirtualNetwork);
+        assertNotNull(mockedProject);
+        assertNotNull(mockedFloatingIpPool);
+    }
+
+    @After
+    public void AfterTest() {
+       domainmanager = null;
+        apiconnector = null;
+    }
+
+   /*  Test method to check if flood domain id is null*/
+    @Test
+    public void testCanCreateFloodDomainIDNull() {
+       OcRenderer.apiConnector = mockedApiConnector;
+       when(mockFd.getId()).thenReturn(null);
+        assertEquals(HttpURLConnection.HTTP_BAD_REQUEST,domainmanager.canCreateFloodDomain(mockFd, TENANT_ID));
+    }
+
+    /* Test method to check if flood domain name is null*/
+    @Test
+    public void testCanCreateFloodDomainNameNull() {
+       OcRenderer.apiConnector = mockedApiConnector;
+       when(mockFd.getName()).thenReturn(null);
+        assertEquals(HttpURLConnection.HTTP_BAD_REQUEST,domainmanager.canCreateFloodDomain(mockFd, TENANT_ID));
+    }
+
+     /*Test method to check if FloodDomain ProjctUUID is not found */
+    @Test
+    public void testCanCreateFloodDomainProjctUUIDNotFound() throws IOException {
+       OcRenderer.apiConnector = mockedApiConnector;
+       when(mockFd.getId()).thenReturn(FLOOD_DOMAIN_ID);
+       when(mockFd.getName()).thenReturn(FLOOD_DOMAIN_NAME);
+       when(mockedApiConnector.findById(Project.class, TENANT_ID)).thenReturn(null);
+       assertEquals(HttpURLConnection.HTTP_NOT_FOUND,domainmanager.canCreateFloodDomain(mockFd ,TENANT_ID_VALUE));
+    }
+
+    /*Test method to check if FloodDomain ProjctUUID is forbidden */
+    @Test
+    public void testCanCreateFloodDomainForbidden() throws IOException {
+       OcRenderer.apiConnector = mockedApiConnector;
+       when(mockFd.getId()).thenReturn(FLOOD_DOMAIN_ID);
+       when(mockFd.getName()).thenReturn(FLOOD_DOMAIN_NAME);
+       String mockL2FloodDomainUUID = "08e3904c-7850-41c0-959a-1a646a83598a";
+       when(mockedApiConnector.findById(Project.class, TENANT_ID)).thenReturn(mockedProject);
+       when(mockedApiConnector.findById(VirtualNetwork.class, mockL2FloodDomainUUID)).thenReturn(mockedVirtualNetwork);
+       assertEquals(HttpURLConnection.HTTP_FORBIDDEN,domainmanager.canCreateFloodDomain(mockFd ,TENANT_ID_VALUE));
+    }
+
+    /*Test method to check if FloodDomain is created ok. */
+    @Test
+    public void testCanCreateFloodDomainOk() throws IOException {
+       OcRenderer.apiConnector = mockedApiConnector;
+       when(mockFd.getId()).thenReturn(FLOOD_DOMAIN_ID);
+       when(mockFd.getName()).thenReturn(FLOOD_DOMAIN_NAME);
+       String mockL2FloodDomainUUID = "08e3904c-7850-41c0-959a-1a646a83598a";
+       when(mockedApiConnector.findById(Project.class, TENANT_ID)).thenReturn(mockedProject);
+       when(mockedApiConnector.findById(VirtualNetwork.class, mockL2FloodDomainUUID)).thenReturn(null);
+       assertEquals(HttpURLConnection.HTTP_OK,domainmanager.canCreateFloodDomain(mockFd ,TENANT_ID_VALUE));
+    }
+
+    /*Test method to check if FloodDomain Name is null */
+    @Test
+    public void testCanUpdateFloodDomainNameisNull(){
+       OcRenderer.apiConnector = mockedApiConnector;
+       when(mockFd.getId()).thenReturn(FLOOD_DOMAIN_ID);
+       when(mockFdNew.getName()).thenReturn(null);
+       assertEquals(HttpURLConnection.HTTP_BAD_REQUEST, domainmanager.canUpdateFloodDomain(mockFdNew, mockFd, TENANT_ID_VALUE));
+    }
+
+    /*Test method to check if FloodDomainName already exists */
+    @Test
+    public void testCanUpdateFloodDomainNameALreadyExist() throws IOException{
+       OcRenderer.apiConnector = mockedApiConnector;
+       String mockL2FloodDomainUUID = "08e3904c-7850-41c0-959a-1a646a83598a";
+       String name = "MOCK_DOMAIN";
+       when(mockFd.getId()).thenReturn(FLOOD_DOMAIN_ID);
+       when(mockFdNew.getName()).thenReturn(FLOOD_DOMAIN_NAME);
+       when(mockedApiConnector.findById(Project.class, TENANT_ID)).thenReturn(mockedProject);
+       when(mockedApiConnector.findById(VirtualNetwork.class, mockL2FloodDomainUUID)).thenReturn(mockedVirtualNetwork);
+       when(mockedApiConnector.findByName(VirtualNetwork.class, mockedProject, mockFdNew.getName().toString())).thenReturn(name);
+       assertEquals(HttpURLConnection.HTTP_FORBIDDEN, domainmanager.canUpdateFloodDomain(mockFdNew, mockFd, TENANT_ID_VALUE));
+    }
+
+    /*Test method to check if FloodDomain ID is null */
+    @Test
+    public void testCanUpdateFloodDomainIDisNull() throws IOException{
+       OcRenderer.apiConnector = mockedApiConnector;
+       String mockL2FloodDomainUUID = "08e3904c-7850-41c0-959a-1a646a83598a";
+       when(mockFd.getId()).thenReturn(FLOOD_DOMAIN_ID);
+       when(mockFdNew.getName()).thenReturn(FLOOD_DOMAIN_NAME);
+       when(mockedApiConnector.findById(Project.class, TENANT_ID)).thenReturn(mockedProject);
+       when(mockedApiConnector.findById(VirtualNetwork.class, mockL2FloodDomainUUID)).thenReturn(null);
+       when(mockedApiConnector.findByName(VirtualNetwork.class, mockedProject, mockFdNew.getName().toString())).thenReturn(null);
+       assertEquals(HttpURLConnection.HTTP_FORBIDDEN, domainmanager.canUpdateFloodDomain(mockFdNew, mockFd, TENANT_ID_VALUE));
+    }
+
+    /*Test method to check if FloodDomain Name can be updated */
+    @Test
+    public void testCanUpdateFloodDomainOK() throws IOException{
+       OcRenderer.apiConnector = mockedApiConnector;
+       String mockL2FloodDomainUUID = "08e3904c-7850-41c0-959a-1a646a83598a";
+       when(mockFd.getId()).thenReturn(FLOOD_DOMAIN_ID);
+       when(mockFdNew.getName()).thenReturn(FLOOD_DOMAIN_NAME);
+       when(mockedApiConnector.findById(Project.class, TENANT_ID)).thenReturn(mockedProject);
+       when(mockedApiConnector.findById(VirtualNetwork.class, mockL2FloodDomainUUID)).thenReturn(mockedVirtualNetwork);
+       when(mockedApiConnector.findByName(VirtualNetwork.class, mockedProject, mockFdNew.getName().toString())).thenReturn(null);
+       assertEquals(HttpURLConnection.HTTP_OK, domainmanager.canUpdateFloodDomain(mockFdNew, mockFd, TENANT_ID_VALUE));
+    }
+}
\ No newline at end of file
diff --git a/groupbasedpolicy/src/test/java/org/opendaylight/groupbasedpolicy/renderer/oc/TestUtilsStaticMethod.java b/groupbasedpolicy/src/test/java/org/opendaylight/groupbasedpolicy/renderer/oc/TestUtilsStaticMethod.java
new file mode 100644 (file)
index 0000000..14410ab
--- /dev/null
@@ -0,0 +1,61 @@
+package org.opendaylight.groupbasedpolicy.renderer.oc;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.net.HttpURLConnection;
+import java.util.concurrent.ScheduledExecutorService;
+
+import net.juniper.contrail.api.ApiConnector;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2FloodDomainId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.Name;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.L2FloodDomain;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+@RunWith(PowerMockRunner.class)
+@PrepareForTest( Utils.class )
+public class TestUtilsStaticMethod{
+       L2DomainManager domainmanager;
+       ApiConnector mockedApiConnector = mock(ApiConnector.class);
+    L2FloodDomain mockFd = mock(L2FloodDomain.class);
+    Utils mockUtils = mock(Utils.class);
+    private static final L2FloodDomainId FLOOD_DOMAIN_ID = new L2FloodDomainId("08e3904c-7850-41c0-959a-1a646a83598a");
+    private static final Name FLOOD_DOMAIN_NAME = new Name("MOCK_NETWORK");
+    private static final String TENANT_ID = "22282cca-9a13-4d0c-a67e-a933ebb0b0ae";
+    private static final String TENANT_ID_VALUE = "[_value=22282cca-9a13-4d0c-a67e-a933ebb0b0ae]";
+    @Mock
+    private DataBroker mockBroker;
+    @Mock
+    private RpcProviderRegistry mockRpcRegistry;
+    @Mock
+    private ScheduledExecutorService mockExecutor;
+
+    @Before
+    public void beforeTest() {
+       domainmanager = new L2DomainManager(mockBroker, mockRpcRegistry, mockExecutor);
+    }
+
+    /*Test method to check if FloodDomain id is invalid */
+    @Test
+    public void testCanCreateInvalidFloodDomainId(){
+       OcRenderer.apiConnector = mockedApiConnector;
+       String InvalidFloodDOmainID = "08e3904c-7850-41c0-9";
+       when(mockFd.getId()).thenReturn(FLOOD_DOMAIN_ID);
+       when(mockFd.getName()).thenReturn(FLOOD_DOMAIN_NAME);
+        PowerMockito.mockStatic(Utils.class);
+        PowerMockito.when(Utils.uuidNameFormat(mockFd.getId().toString())).thenReturn(InvalidFloodDOmainID);
+        PowerMockito.when(Utils.uuidNameFormat(TENANT_ID_VALUE)).thenReturn(TENANT_ID);
+        PowerMockito.when(Utils.isValidHexNumber(InvalidFloodDOmainID)).thenReturn(false);
+       assertEquals(HttpURLConnection.HTTP_BAD_REQUEST, domainmanager.canCreateFloodDomain(mockFd, TENANT_ID_VALUE));
+    }
+}
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 3f5d4261a46a9e44644a05f88034b1b2203940e6..e38882dd85db0bcf4e2c604cd4bb1432409ab295 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -20,6 +20,7 @@
     <module>commons/parent</module>
     <module>groupbasedpolicy</module>
     <module>groupbasedpolicy-ofoverlay-config</module>
+    <module>groupbasedpolicy-oc-config</module>
     <module>groupbasedpolicy-openstackendpoint-config</module>
     <module>distribution-karaf</module>
     <module>features</module>
@@ -46,3 +47,4 @@
   </scm>
 
 </project>
+