<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 -->
</pluginRepository>
</pluginRepositories>
</project>
+
<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>
+
<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>
+
<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>
<configfile finalname="${config.configfile.directory}/${config.groupbasedpolicy.openstackendpointconfigfile}">mvn:org.opendaylight.groupbasedpolicy/groupbasedpolicy-openstackendpoint-config/${project.version}/xml/config</configfile>
</feature>
</features>
+
--- /dev/null
+<?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>
--- /dev/null
+<?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&revision=2014-06-11</capability>
+ </required-capabilities>
+
+</snapshot>
+
<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>
+
--- /dev/null
+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());
+}
+
+}
--- /dev/null
+/*
+* 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 {
+
+}
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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());
+ }
+}
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*\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
--- /dev/null
+/*
+ * 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;
+ }
+ }
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * 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";
+ }
+}
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+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
<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>
</scm>
</project>
+