<openflowplugin.distribution.version>0.1.0-SNAPSHOT</openflowplugin.distribution.version>
<openflowplugin-nicira.version>0.1.0-SNAPSHOT</openflowplugin-nicira.version>
<openflowjava.distribution.version>0.6.0-SNAPSHOT</openflowjava.distribution.version>
+ <neutron.version>0.5.0-SNAPSHOT</neutron.version>
<restconf.project.version>1.2.0-SNAPSHOT</restconf.project.version>
<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.opflexconfigfile>15-groupbasedpolicy-opflex.xml</config.groupbasedpolicy.opflexconfigfile>
<config.groupbasedpolicy.openstackendpointconfigfile>15-groupbasedpolicy-openstackendpoint.xml</config.groupbasedpolicy.openstackendpointconfigfile>
+ <config.groupbasedpolicy.neutronmapperconfigfile>15-neutron-mapper.xml</config.groupbasedpolicy.neutronmapperconfigfile>
<karaf.version>3.0.1</karaf.version>
<exam.version>4.4.0</exam.version> <!-- Needs to remain exported, as its used for dependencies, too -->
<sfc.version>0.1.0-SNAPSHOT</sfc.version>
<classifier>features</classifier>
<type>xml</type>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.neutron</groupId>
+ <artifactId>features-neutron</artifactId>
+ <classifier>features</classifier>
+ <version>${neutron.version}</version>
+ <type>xml</type>
+ </dependency>
<dependency>
<groupId>org.opendaylight.groupbasedpolicy</groupId>
<artifactId>groupbasedpolicy</artifactId>
<type>xml</type>
<classifier>config</classifier>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.groupbasedpolicy</groupId>
+ <artifactId>neutron-mapper-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>
<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>
+ <!-- Repos needed by the Neutron Mapper -->
+ <repository>mvn:org.opendaylight.neutron/features-neutron/${neutron.version}/xml/features</repository>
+
<!-- The common GBP components -->
<feature name='odl-groupbasedpolicy-base' version='${project.version}' description='OpenDaylight :: groupbasedpolicy :: Base Copmonents'>
<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>
+
+ <!--
+ The Neutron provider
+ -->
+ <feature name='odl-groupbasedpolicy-neutronmapper' version='${project.version}' description='OpenDaylight :: groupbasedpolicy :: Neutron Mapper mapps neutron APIs to GBP APIs '>
+ <feature version="${mdsal.version}">odl-mdsal-broker</feature>
+ <feature version="${neutron.version}">odl-neutron-service</feature>
+ <feature version="${project.version}">odl-groupbasedpolicy-base</feature>
+ <feature version="${project.version}">odl-groupbasedpolicy-ofoverlay</feature>
+ <bundle>mvn:org.opendaylight.groupbasedpolicy/neutron-mapper/${project.version}</bundle>
+ <configfile finalname="${config.configfile.directory}/${config.groupbasedpolicy.neutronmapperconfigfile}">mvn:org.opendaylight.groupbasedpolicy/neutron-mapper-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>
+
+ <artifactId>neutron-mapper-config</artifactId>
+ <description>Controller Configuration files for neutron-mapper</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-neutron-mapper.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"?>
+<!--
+ 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
+-->
+<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:neutron-mapper="urn:opendaylight:params:xml:ns:yang:controller:config:neutron-mapper:impl">
+ neutron-mapper:neutron-mapper-impl
+ </type>
+ <name>neutron-mapper-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:neutron-mapper:impl?module=neutron-mapper-impl&revision=2015-02-19</capability>
+ </required-capabilities>
+
+</snapshot>
--- /dev/null
+<?xml version="1.0"?>
+<!--
+ 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
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
+ xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.opendaylight.groupbasedpolicy</groupId>
+ <artifactId>groupbasedpolicy.project</artifactId>
+ <version>0.2.0-SNAPSHOT</version>
+ <relativePath>../</relativePath>
+ </parent>
+ <artifactId>neutron-mapper</artifactId>
+ <packaging>bundle</packaging>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>groupbasedpolicy</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>ofoverlay-renderer</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.neutron</groupId>
+ <artifactId>neutron-spi</artifactId>
+ <version>0.5.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-config</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <configuration>
+ <instructions>
+ <Export-Package></Export-Package>
+ <Import-Package>*</Import-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>config</id>
+ <goals>
+ <goal>generate-sources</goal>
+ </goals>
+ <configuration>
+ <codeGenerators>
+ <generator>
+ <codeGeneratorClass>org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator</codeGeneratorClass>
+ <outputBaseDir>${project.build.directory}/generated-sources/config</outputBaseDir>
+ <additionalConfiguration>
+ <namespaceToPackage1>urn:opendaylight:params:xml:ns:yang:controller==org.opendaylight.controller.config.yang</namespaceToPackage1>
+ </additionalConfiguration>
+ </generator>
+ <generator>
+ <codeGeneratorClass>org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl</codeGeneratorClass>
+ <outputBaseDir>${project.build.directory}/generated-sources/sal</outputBaseDir>
+ </generator>
+ </codeGenerators>
+ <inspectDependencies>true</inspectDependencies>
+ </configuration>
+ </execution>
+ </executions>
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>yang-jmx-generator-plugin</artifactId>
+ <version>0.3.0-SNAPSHOT</version>
+ </dependency>
+ </dependencies>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <goals>
+ <goal>add-source</goal>
+ </goals>
+ <phase>generate-sources</phase>
+ <configuration>
+ <sources>
+ <source>target/generated-sources/sal</source>
+ <source>target/generated-sources/config</source>
+ <source>target/generated-resources/</source>
+ </sources>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
--- /dev/null
+/*
+ * 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
+ */
+
+package org.opendaylight.controller.config.yang.config.neutron_mapper.impl;
+
+import org.opendaylight.groupbasedpolicy.neutron.mapper.NeutronMapper;
+import org.osgi.framework.BundleContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class NeutronMapperModule extends org.opendaylight.controller.config.yang.config.neutron_mapper.impl.AbstractNeutronMapperModule {
+
+ private final Logger LOG = LoggerFactory.getLogger(NeutronMapperModule.class);
+ private BundleContext bundleContext;
+
+ public NeutronMapperModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+ super(identifier, dependencyResolver);
+ }
+
+ public NeutronMapperModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.controller.config.yang.config.neutron_mapper.impl.NeutronMapperModule 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() {
+ final NeutronMapper neutronMapper = new NeutronMapper(getDataBrokerDependency(), getRpcRegistryDependency(), bundleContext);
+ LOG.info("Neutron mapper started.");
+ return new AutoCloseable() {
+
+ @Override
+ public void close() throws Exception {
+ neutronMapper.close();
+ }
+ };
+ }
+
+ public void setBundleContext(BundleContext bundleContext) {
+ this.bundleContext = bundleContext;
+ }
+
+}
--- /dev/null
+/*
+* Generated file
+*
+* Generated from: yang module name: neutron-mapper-impl yang module local name: neutron-mapper-impl
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Thu Feb 19 12:58:22 CET 2015
+*
+* Do not modify this file unless it is present under src/main directory
+*/
+/*
+ * 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
+ */
+
+package org.opendaylight.controller.config.yang.config.neutron_mapper.impl;
+
+import org.opendaylight.controller.config.api.DependencyResolver;
+import org.opendaylight.controller.config.api.DynamicMBeanWithInstance;
+import org.opendaylight.controller.config.spi.Module;
+import org.osgi.framework.BundleContext;
+
+public class NeutronMapperModuleFactory extends org.opendaylight.controller.config.yang.config.neutron_mapper.impl.AbstractNeutronMapperModuleFactory {
+
+ /**
+ * @see org.opendaylight.controller.config.yang.config.neutron_mapper.impl.AbstractNeutronMapperModuleFactory#createModule(java.lang.String, org.opendaylight.controller.config.api.DependencyResolver, org.osgi.framework.BundleContext)
+ */
+ @Override
+ public Module createModule(String instanceName, DependencyResolver dependencyResolver, BundleContext bundleContext) {
+ NeutronMapperModule module = (NeutronMapperModule) super.createModule(instanceName, dependencyResolver, bundleContext);
+ module.setBundleContext(bundleContext);
+ return module;
+ }
+
+ /**
+ * @see org.opendaylight.controller.config.yang.config.neutron_mapper.impl.AbstractNeutronMapperModuleFactory#createModule(java.lang.String, org.opendaylight.controller.config.api.DependencyResolver, org.opendaylight.controller.config.api.DynamicMBeanWithInstance, org.osgi.framework.BundleContext)
+ */
+ @Override
+ public Module createModule(String instanceName, DependencyResolver dependencyResolver, DynamicMBeanWithInstance old,
+ BundleContext bundleContext) throws Exception {
+ NeutronMapperModule module = (NeutronMapperModule) super.createModule(instanceName, dependencyResolver, old, bundleContext);
+ module.setBundleContext(bundleContext);
+ return module;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.groupbasedpolicy.neutron.mapper;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.groupbasedpolicy.neutron.mapper.mapping.NeutronNetworkAware;
+import org.opendaylight.groupbasedpolicy.neutron.mapper.mapping.NeutronPortAware;
+import org.opendaylight.groupbasedpolicy.neutron.mapper.mapping.NeutronSecurityGroupAware;
+import org.opendaylight.groupbasedpolicy.neutron.mapper.mapping.NeutronSubnetAware;
+import org.opendaylight.neutron.spi.INeutronNetworkAware;
+import org.opendaylight.neutron.spi.INeutronPortAware;
+import org.opendaylight.neutron.spi.INeutronSecurityGroupAware;
+import org.opendaylight.neutron.spi.INeutronSubnetAware;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.EndpointService;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+
+public class NeutronMapper implements AutoCloseable {
+
+ private final List<ServiceRegistration<?>> registrations = new ArrayList<ServiceRegistration<?>>();
+
+ public NeutronMapper(DataBroker dataProvider, RpcProviderRegistry rpcProvider, BundleContext context) {
+ checkNotNull(dataProvider);
+ checkNotNull(rpcProvider);
+ checkNotNull(context);
+ EndpointService epService = rpcProvider.getRpcService(EndpointService.class);
+
+ registerAwareProviders(dataProvider, epService, context);
+ }
+
+ private void registerAwareProviders(DataBroker dataProvider, EndpointService epService, BundleContext context) {
+ ServiceRegistration<INeutronNetworkAware> neutronNetworkAwareRegistration = context.registerService(
+ INeutronNetworkAware.class, new NeutronNetworkAware(dataProvider), null);
+ registrations.add(neutronNetworkAwareRegistration);
+
+ ServiceRegistration<INeutronSubnetAware> neutronSubnetAwareRegistration = context.registerService(
+ INeutronSubnetAware.class, new NeutronSubnetAware(dataProvider), null);
+ registrations.add(neutronSubnetAwareRegistration);
+
+ ServiceRegistration<INeutronPortAware> neutronPortAwareRegistration = context.registerService(
+ INeutronPortAware.class, new NeutronPortAware(dataProvider, epService), null);
+ registrations.add(neutronPortAwareRegistration);
+
+ ServiceRegistration<INeutronSecurityGroupAware> neutronSecurityGroupAwareRegistration = context.registerService(
+ INeutronSecurityGroupAware.class, new NeutronSecurityGroupAware(dataProvider), null);
+ registrations.add(neutronSecurityGroupAwareRegistration);
+ }
+
+ /**
+ * @see java.lang.AutoCloseable#close()
+ */
+ @Override
+ public void close() throws Exception {
+ for (ServiceRegistration<?> registration : registrations) {
+ registration.unregister();
+ }
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.groupbasedpolicy.neutron.mapper.mapping;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.UUID;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.groupbasedpolicy.neutron.mapper.util.DataStoreHelper;
+import org.opendaylight.groupbasedpolicy.neutron.mapper.util.IidFactory;
+import org.opendaylight.groupbasedpolicy.neutron.mapper.util.MappingUtils;
+import org.opendaylight.groupbasedpolicy.neutron.mapper.util.Utils;
+import org.opendaylight.neutron.spi.INeutronNetworkAware;
+import org.opendaylight.neutron.spi.NeutronNetwork;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.Description;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2BridgeDomainId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2FloodDomainId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L3ContextId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.Name;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.mapper.rev150223.mappings.network.mappings.NetworkMapping;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.mapper.rev150223.mappings.network.mappings.NetworkMappingBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.EndpointGroup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.EndpointGroup.IntraGroupPolicy;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.EndpointGroupBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.L2BridgeDomain;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.L2BridgeDomainBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.L2FloodDomain;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.L2FloodDomainBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.L3Context;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.L3ContextBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+
+public class NeutronNetworkAware implements INeutronNetworkAware {
+
+ private static final Logger LOG = LoggerFactory.getLogger(NeutronNetworkAware.class);
+ private final DataBroker dataProvider;
+
+ public NeutronNetworkAware(DataBroker dataProvider) {
+ this.dataProvider = checkNotNull(dataProvider);
+ }
+
+ /**
+ * @see org.opendaylight.neutron.spi.INeutronNetworkAware#canCreateNetwork(org.opendaylight.neutron.spi.NeutronNetwork)
+ */
+ @Override
+ public int canCreateNetwork(NeutronNetwork network) {
+ LOG.trace("canCreateNetwork - {}", network);
+ // nothing to consider
+ return StatusCode.OK;
+ }
+
+ /**
+ * @see org.opendaylight.neutron.spi.INeutronNetworkAware#neutronNetworkCreated(org.opendaylight.neutron.spi.NeutronNetwork)
+ */
+ @Override
+ public void neutronNetworkCreated(NeutronNetwork network) {
+ LOG.trace("neutronNetworkCreated - {}", network);
+ ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
+ L2FloodDomainId l2FdId = new L2FloodDomainId(network.getID());
+ TenantId tenantId = new TenantId(Utils.normalizeUuid(network.getTenantID()));
+ addEpgDhcpIfMissing(tenantId, rwTx);
+ addEpgRouterIfMissing(tenantId, rwTx);
+ Description domainDescription = new Description(MappingUtils.NEUTRON_NETWORK__ + network.getID());
+ Name name = null;
+ if (network.getNetworkName() != null) {
+ name = new Name(network.getNetworkName());
+ }
+ L3ContextId l3ContextId = new L3ContextId(UUID.randomUUID().toString());
+ L3Context l3Context = new L3ContextBuilder().setId(l3ContextId)
+ .setDescription(domainDescription)
+ .setName(name)
+ .build();
+ rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.l3ContextIid(tenantId, l3ContextId), l3Context, true);
+
+ L2BridgeDomainId l2BdId = new L2BridgeDomainId(UUID.randomUUID().toString());
+ L2BridgeDomain l2Bd = new L2BridgeDomainBuilder().setId(l2BdId)
+ .setParent(l3ContextId)
+ .setDescription(domainDescription)
+ .setName(name)
+ .build();
+ rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.l2BridgeDomainIid(tenantId, l2BdId), l2Bd, true);
+
+ L2FloodDomain l2Fd = new L2FloodDomainBuilder().setId(l2FdId)
+ .setParent(l2BdId)
+ .setDescription(domainDescription)
+ .setName(name)
+ .build();
+ rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.l2FloodDomainIid(tenantId, l2FdId), l2Fd, true);
+
+ NetworkMapping networkMapping = new NetworkMappingBuilder().setNetworkId(l2FdId)
+ .setL2BridgeDomainId(l2BdId)
+ .setL3ContextId(l3ContextId)
+ .build();
+ rwTx.put(LogicalDatastoreType.OPERATIONAL, IidFactory.networkMappingIid(l2FdId), networkMapping, true);
+
+ DataStoreHelper.submitToDs(rwTx);
+ }
+
+ private void addEpgDhcpIfMissing(TenantId tenantId, ReadWriteTransaction rwTx) {
+ InstanceIdentifier<EndpointGroup> epgDhcpIid = IidFactory.endpointGroupIid(tenantId, MappingUtils.EPG_DHCP_ID);
+ Optional<EndpointGroup> potentialDhcpEpg = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
+ epgDhcpIid, rwTx);
+ if (!potentialDhcpEpg.isPresent()) {
+ EndpointGroup epgDhcp = new EndpointGroupBuilder().setId(MappingUtils.EPG_DHCP_ID)
+ .setName(new Name("DHCP_group"))
+ .setDescription(new Description("Group where are all DHCP endpoints."))
+ .build();
+ rwTx.put(LogicalDatastoreType.CONFIGURATION, epgDhcpIid, epgDhcp);
+ }
+ }
+
+ private void addEpgRouterIfMissing(TenantId tenantId, ReadWriteTransaction rwTx) {
+ Optional<EndpointGroup> potentialEpgRouter = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
+ IidFactory.endpointGroupIid(tenantId, MappingUtils.EPG_ROUTER_ID), rwTx);
+ if (potentialEpgRouter.isPresent()) {
+ EndpointGroup epgRouter = new EndpointGroupBuilder().setId(MappingUtils.EPG_ROUTER_ID)
+ .setDescription(new Description(MappingUtils.NEUTRON_ROUTER__ + "epg_routers"))
+ .setIntraGroupPolicy(IntraGroupPolicy.RequireContract)
+ .build();
+ rwTx.put(LogicalDatastoreType.CONFIGURATION,
+ IidFactory.endpointGroupIid(tenantId, MappingUtils.EPG_ROUTER_ID), epgRouter);
+ }
+ }
+
+ /**
+ * @see org.opendaylight.neutron.spi.INeutronNetworkAware#canUpdateNetwork(org.opendaylight.neutron.spi.NeutronNetwork,
+ * org.opendaylight.neutron.spi.NeutronNetwork)
+ */
+ @Override
+ public int canUpdateNetwork(NeutronNetwork delta, NeutronNetwork original) {
+ LOG.trace("canUpdateNetwork - delta: {} original: {}", delta, original);
+ // nothing to consider
+ return StatusCode.OK;
+ }
+
+ /**
+ * @see org.opendaylight.neutron.spi.INeutronNetworkAware#neutronNetworkUpdated(org.opendaylight.neutron.spi.NeutronNetwork)
+ */
+ @Override
+ public void neutronNetworkUpdated(NeutronNetwork network) {
+ LOG.trace("neutronNetworkUpdated - {}", network);
+ // TODO we could update just name
+ }
+
+ /**
+ * @see org.opendaylight.neutron.spi.INeutronNetworkAware#canDeleteNetwork(org.opendaylight.neutron.spi.NeutronNetwork)
+ */
+ @Override
+ public int canDeleteNetwork(NeutronNetwork network) {
+ LOG.trace("canDeleteNetwork - {}", network);
+ // nothing to consider
+ return StatusCode.OK;
+ }
+
+ /**
+ * @see org.opendaylight.neutron.spi.INeutronNetworkAware#neutronNetworkDeleted(org.opendaylight.neutron.spi.NeutronNetwork)
+ */
+ @Override
+ public void neutronNetworkDeleted(NeutronNetwork network) {
+ LOG.trace("neutronNetworkDeleted - {}", network);
+ ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
+ TenantId tenantId = new TenantId(Utils.normalizeUuid(network.getTenantID()));
+ L2FloodDomainId l2FdId = new L2FloodDomainId(network.getID());
+ Optional<NetworkMapping> potentionalNetworkMapping = DataStoreHelper.readFromDs(
+ LogicalDatastoreType.OPERATIONAL, IidFactory.networkMappingIid(l2FdId), rwTx);
+ if (!potentionalNetworkMapping.isPresent()) {
+ LOG.warn("Illegal state - network-mapping {} does not exist.", l2FdId.getValue());
+ rwTx.cancel();
+ return;
+ }
+
+ NetworkMapping networkMapping = potentionalNetworkMapping.get();
+ L2BridgeDomainId l2BdId = networkMapping.getL2BridgeDomainId();
+ L3ContextId l3ContextId = networkMapping.getL3ContextId();
+ if (l2BdId == null || l3ContextId == null) {
+ LOG.warn("Illegal state - network-mapping {} is not valid.", networkMapping);
+ rwTx.cancel();
+ return;
+ }
+
+ Optional<L2FloodDomain> potentialL2Fd = DataStoreHelper.removeIfExists(LogicalDatastoreType.CONFIGURATION,
+ IidFactory.l2FloodDomainIid(tenantId, l2FdId), rwTx);
+ if (!potentialL2Fd.isPresent()) {
+ LOG.warn("Illegal state - l2-flood-domain {} does not exist.", l2FdId.getValue());
+ rwTx.cancel();
+ return;
+ }
+
+ Optional<L2BridgeDomain> potentialL2Bd = DataStoreHelper.removeIfExists(LogicalDatastoreType.CONFIGURATION,
+ IidFactory.l2BridgeDomainIid(tenantId, l2BdId), rwTx);
+ if (!potentialL2Bd.isPresent()) {
+ LOG.warn("Illegal state - l2-bridge-domain {} does not exist.", l2BdId.getValue());
+ rwTx.cancel();
+ return;
+ }
+
+ Optional<L3Context> potentialL3Context = DataStoreHelper.removeIfExists(LogicalDatastoreType.CONFIGURATION,
+ IidFactory.l3ContextIid(tenantId, l3ContextId), rwTx);
+ if (!potentialL3Context.isPresent()) {
+ LOG.warn("Illegal state - l3-context {} does not exist.", l3ContextId.getValue());
+ rwTx.cancel();
+ return;
+ }
+
+ DataStoreHelper.submitToDs(rwTx);
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.groupbasedpolicy.neutron.mapper.mapping;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.ExecutionException;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.binding.api.ReadTransaction;
+import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.groupbasedpolicy.neutron.mapper.util.DataStoreHelper;
+import org.opendaylight.groupbasedpolicy.neutron.mapper.util.IidFactory;
+import org.opendaylight.groupbasedpolicy.neutron.mapper.util.MappingUtils;
+import org.opendaylight.groupbasedpolicy.neutron.mapper.util.NeutronUtils;
+import org.opendaylight.groupbasedpolicy.neutron.mapper.util.Utils;
+import org.opendaylight.groupbasedpolicy.neutron.mapper.util.MappingUtils.ForwardingCtx;
+import org.opendaylight.neutron.spi.INeutronPortAware;
+import org.opendaylight.neutron.spi.NeutronPort;
+import org.opendaylight.neutron.spi.NeutronSecurityGroup;
+import org.opendaylight.neutron.spi.NeutronSecurityRule;
+import org.opendaylight.neutron.spi.Neutron_IPs;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2FloodDomainId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L3ContextId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.Name;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubnetId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.EndpointService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.UnregisterEndpointInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.UnregisterEndpointInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.fields.L3Address;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.fields.L3AddressBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.unregister.endpoint.input.L2;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.unregister.endpoint.input.L2Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.unregister.endpoint.input.L3;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.unregister.endpoint.input.L3Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContextInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContextInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.EndpointGroup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.Subnet;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.base.Strings;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.ImmutableList;
+
+public class NeutronPortAware implements INeutronPortAware {
+
+ private static final Logger LOG = LoggerFactory.getLogger(NeutronPortAware.class);
+ private static final String DEVICE_OWNER_DHCP = "network:dhcp";
+ private static final String DEVICE_OWNER_ROUTER_IFACE = "network:router_interface";
+ private static final int DHCP_CLIENT_PORT = 68;
+ private static final int DHCP_SERVER_PORT = 67;
+ private final DataBroker dataProvider;
+ private final EndpointService epService;
+
+ public NeutronPortAware(DataBroker dataProvider, EndpointService epService) {
+ this.dataProvider = checkNotNull(dataProvider);
+ this.epService = checkNotNull(epService);
+ }
+
+ /**
+ * @see org.opendaylight.neutron.spi.INeutronPortAware#canCreatePort(org.opendaylight.neutron.spi.NeutronPort)
+ */
+ @Override
+ public int canCreatePort(NeutronPort port) {
+ LOG.trace("canCreatePort - {}", port);
+ // TODO Li msunal this has to be rewrite when OFOverlay renderer will support l3-endpoints.
+ List<Neutron_IPs> fixedIPs = port.getFixedIPs();
+ if (fixedIPs != null && fixedIPs.size() > 1) {
+ LOG.warn("Neutron mapper does not support multiple IPs on the same port.");
+ return StatusCode.BAD_REQUEST;
+ }
+ return StatusCode.OK;
+ }
+
+ /**
+ * @see org.opendaylight.neutron.spi.INeutronPortAware#neutronPortCreated(org.opendaylight.neutron.spi.NeutronPort)
+ */
+ @Override
+ public void neutronPortCreated(NeutronPort port) {
+ LOG.trace("neutronPortCreated - {}", port);
+ if (isRouterInterfacePort(port)) {
+ LOG.trace("Port is router interface - do nothing - NeutronRouterAware handles router iface");
+ return;
+ }
+ ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
+ TenantId tenantId = new TenantId(Utils.normalizeUuid(port.getTenantID()));
+
+ if (isDhcpPort(port)) {
+ List<NeutronSecurityRule> dhcpSecRules = createDhcpSecRules(port, null, rwTx);
+ if (dhcpSecRules == null) {
+ rwTx.cancel();
+ return;
+ }
+
+ for (NeutronSecurityRule dhcpSecRule : dhcpSecRules) {
+ boolean isDhcpSecRuleAdded = NeutronSecurityRuleAware.addNeutronSecurityRule(dhcpSecRule, rwTx);
+ if (!isDhcpSecRuleAdded) {
+ rwTx.cancel();
+ return;
+ }
+ }
+ } else {
+ List<NeutronSecurityGroup> secGroups = port.getSecurityGroups();
+ if (secGroups != null) {
+ for (NeutronSecurityGroup secGroup : secGroups) {
+ EndpointGroupId epgId = new EndpointGroupId(secGroup.getSecurityGroupUUID());
+ Optional<EndpointGroup> potentialEpg = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
+ IidFactory.endpointGroupIid(tenantId, epgId), rwTx);
+ if (!potentialEpg.isPresent()) {
+ boolean isSecGroupCreated = NeutronSecurityGroupAware.addNeutronSecurityGroup(secGroup, rwTx);
+ if (!isSecGroupCreated) {
+ rwTx.cancel();
+ return;
+ }
+ if (containsSecRuleWithRemoteSecGroup(secGroup)) {
+ List<NeutronSecurityRule> dhcpSecRules = createDhcpSecRules(port, epgId, rwTx);
+ if (dhcpSecRules == null) {
+ rwTx.cancel();
+ return;
+ }
+ List<NeutronSecurityRule> routerSecRules = NeutronRouterAware.createRouterSecRules(port, epgId, rwTx);
+ if (routerSecRules == null) {
+ rwTx.cancel();
+ return;
+ }
+ }
+ } else {
+ List<NeutronSecurityRule> secRules = secGroup.getSecurityRules();
+ if (secRules != null) {
+ for (NeutronSecurityRule secRule : secRules) {
+ NeutronSecurityRuleAware.addNeutronSecurityRule(secRule, rwTx);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ boolean isNeutronPortCreated = addNeutronPort(port, rwTx, epService);
+ if (!isNeutronPortCreated) {
+ rwTx.cancel();
+ return;
+ }
+
+ DataStoreHelper.submitToDs(rwTx);
+ }
+
+ public static boolean addNeutronPort(NeutronPort port, ReadWriteTransaction rwTx, EndpointService epService) {
+ TenantId tenantId = new TenantId(Utils.normalizeUuid(port.getTenantID()));
+ L2FloodDomainId l2FdId = new L2FloodDomainId(port.getNetworkUUID());
+ ForwardingCtx fwCtx = MappingUtils.createForwardingContext(tenantId, l2FdId, rwTx);
+ boolean isFwCtxValid = validateForwardingCtx(fwCtx);
+ if (!isFwCtxValid) {
+ return false;
+ }
+
+ try {
+ RegisterEndpointInput registerEpRpcInput = createRegisterEndpointInput(port, fwCtx);
+ RpcResult<Void> rpcResult = epService.registerEndpoint(registerEpRpcInput).get();
+ if (!rpcResult.isSuccessful()) {
+ LOG.warn("Illegal state - RPC registerEndpoint failed. Input of RPC: {}", registerEpRpcInput);
+ return false;
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.error("addPort - RPC invocation failed.", e);
+ return false;
+ }
+ return true;
+ }
+
+ private static boolean validateForwardingCtx(ForwardingCtx fwCtx) {
+ if (fwCtx.getL2FloodDomain() == null) {
+ LOG.warn("Illegal state - l2-flood-domain does not exist.");
+ return false;
+ }
+ if (fwCtx.getL2BridgeDomain() == null) {
+ LOG.warn("Illegal state - l2-bridge-domain does not exist.");
+ return false;
+ }
+ if (fwCtx.getL3Context() == null) {
+ LOG.warn("Illegal state - l3-context does not exist.");
+ return false;
+ }
+ return true;
+ }
+
+ private List<NeutronSecurityRule> createDhcpSecRules(NeutronPort port, EndpointGroupId consumerEpgId, ReadTransaction rTx) {
+ TenantId tenantId = new TenantId(Utils.normalizeUuid(port.getTenantID()));
+ Neutron_IPs firstIp = getFirstIp(port.getFixedIPs());
+ if (firstIp == null) {
+ LOG.warn("Illegal state - DHCP port does not have an IP address.");
+ return null;
+ }
+ SubnetId dhcpSubnetId = new SubnetId(firstIp.getSubnetUUID());
+ Optional<Subnet> potentialSubnet = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
+ IidFactory.subnetIid(tenantId, dhcpSubnetId), rTx);
+ if (!potentialSubnet.isPresent()) {
+ LOG.warn("Illegal state - Subnet {} where is DHCP port does not exist.", dhcpSubnetId.getValue());
+ return null;
+ }
+ IpPrefix ipSubnet = potentialSubnet.get().getIpPrefix();
+ NeutronSecurityRule dhcpRuleEgress = createDhcpSecRule(port.getID(), tenantId, ipSubnet, consumerEpgId, true);
+ NeutronSecurityRule dhcpRuleIngress = createDhcpSecRule(port.getID(), tenantId, ipSubnet, consumerEpgId, false);
+ return ImmutableList.of(dhcpRuleEgress, dhcpRuleIngress);
+ }
+
+ private NeutronSecurityRule createDhcpSecRule(String ruleUuid, TenantId tenantId, IpPrefix ipSubnet, EndpointGroupId consumerEpgId,
+ boolean isEgress) {
+ NeutronSecurityRule dhcpSecRule = new NeutronSecurityRule();
+ dhcpSecRule.setSecurityRuleGroupID(MappingUtils.EPG_DHCP_ID.getValue());
+ dhcpSecRule.setSecurityRuleTenantID(tenantId.getValue());
+ dhcpSecRule.setSecurityRuleRemoteIpPrefix(Utils.getStringIpPrefix(ipSubnet));
+ if (consumerEpgId != null) {
+ dhcpSecRule.setSecurityRemoteGroupID(consumerEpgId.getValue());
+ }
+ if (isEgress) {
+ dhcpSecRule.setSecurityRuleUUID(NeutronUtils.EGRESS + "__" + ruleUuid);
+ dhcpSecRule.setSecurityRuleDirection(NeutronUtils.EGRESS);
+ dhcpSecRule.setSecurityRulePortMin(DHCP_CLIENT_PORT);
+ dhcpSecRule.setSecurityRulePortMax(DHCP_CLIENT_PORT);
+ } else {
+ dhcpSecRule.setSecurityRuleUUID(NeutronUtils.INGRESS + "__" + ruleUuid);
+ dhcpSecRule.setSecurityRuleDirection(NeutronUtils.INGRESS);
+ dhcpSecRule.setSecurityRulePortMin(DHCP_SERVER_PORT);
+ dhcpSecRule.setSecurityRulePortMax(DHCP_SERVER_PORT);
+ }
+ dhcpSecRule.setSecurityRuleProtocol(NeutronUtils.UDP);
+ if (ipSubnet.getIpv4Prefix() != null) {
+ dhcpSecRule.setSecurityRuleEthertype(NeutronUtils.IPv4);
+ } else {
+ dhcpSecRule.setSecurityRuleEthertype(NeutronUtils.IPv6);
+ }
+ return dhcpSecRule;
+ }
+
+ /**
+ * @see org.opendaylight.neutron.spi.INeutronPortAware#canUpdatePort(org.opendaylight.neutron.spi.NeutronPort,
+ * org.opendaylight.neutron.spi.NeutronPort)
+ */
+ @Override
+ public int canUpdatePort(NeutronPort delta, NeutronPort original) {
+ LOG.trace("canUpdatePort - delta: {} original: {}", delta, original);
+ if (delta.getFixedIPs() == null || delta.getFixedIPs().isEmpty()) {
+ return StatusCode.OK;
+ }
+ // TODO Li msunal this has to be rewrite when OFOverlay renderer will support l3-endpoints.
+ List<Neutron_IPs> fixedIPs = delta.getFixedIPs();
+ if (fixedIPs != null && fixedIPs.size() > 1) {
+ LOG.warn("Neutron mapper does not support multiple IPs on the same port.");
+ return StatusCode.BAD_REQUEST;
+ }
+ return StatusCode.OK;
+ }
+
+ /**
+ * @see org.opendaylight.neutron.spi.INeutronPortAware#neutronPortUpdated(org.opendaylight.neutron.spi.NeutronPort)
+ */
+ @Override
+ public void neutronPortUpdated(NeutronPort port) {
+ LOG.trace("neutronPortUpdated - {}", port);
+ if (isRouterInterfacePort(port)) {
+ LOG.trace("Port is router interface - do nothing - NeutronRouterAware handles router iface");
+ return;
+ }
+ ReadOnlyTransaction rTx = dataProvider.newReadOnlyTransaction();
+ TenantId tenantId = new TenantId(Utils.normalizeUuid(port.getTenantID()));
+ MacAddress macAddress = new MacAddress(port.getMacAddress());
+ L2FloodDomainId l2FdId = new L2FloodDomainId(port.getNetworkUUID());
+ ForwardingCtx fwCtx = MappingUtils.createForwardingContext(tenantId, l2FdId, rTx);
+ boolean isFwCtxValid = validateForwardingCtx(fwCtx);
+ if (!isFwCtxValid) {
+ rTx.close();
+ return;
+ }
+
+ Optional<Endpoint> potentionalEp = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
+ IidFactory.endpointIid(fwCtx.getL2BridgeDomain().getId(), macAddress), rTx);
+ if (!potentionalEp.isPresent()) {
+ LOG.warn("Illegal state - endpoint {} does not exist.", new EndpointKey(fwCtx.getL2BridgeDomain().getId(),
+ macAddress));
+ rTx.close();
+ return;
+ }
+
+ Endpoint ep = potentionalEp.get();
+ if (isEpIpDifferentThanPortFixedIp(ep, port) || isEpgDifferentThanSecGrp(ep, port)) {
+ UnregisterEndpointInput unregisterEpRpcInput = createUnregisterEndpointInput(ep);
+ RegisterEndpointInput registerEpRpcInput = createRegisterEndpointInput(port, fwCtx);
+ try {
+ RpcResult<Void> rpcResult = epService.unregisterEndpoint(unregisterEpRpcInput).get();
+ if (!rpcResult.isSuccessful()) {
+ LOG.warn("Illegal state - RPC unregisterEndpoint failed. Input of RPC: {}", unregisterEpRpcInput);
+ rTx.close();
+ return;
+ }
+ rpcResult = epService.registerEndpoint(registerEpRpcInput).get();
+ if (!rpcResult.isSuccessful()) {
+ LOG.warn("Illegal state - RPC registerEndpoint failed. Input of RPC: {}", registerEpRpcInput);
+ rTx.close();
+ return;
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.error("addPort - RPC invocation failed.", e);
+ rTx.close();
+ return;
+ }
+ }
+ rTx.close();
+ }
+
+ private boolean isEpIpDifferentThanPortFixedIp(Endpoint ep, NeutronPort port) {
+ List<L3Address> l3Addresses = ep.getL3Address();
+ List<Neutron_IPs> fixedIPs = port.getFixedIPs();
+ if ((l3Addresses == null || l3Addresses.isEmpty()) && (fixedIPs == null || fixedIPs.isEmpty())) {
+ return false;
+ }
+ if (l3Addresses != null && !l3Addresses.isEmpty() && fixedIPs != null && !fixedIPs.isEmpty()) {
+ if (fixedIPs.get(0).getIpAddress().equals(Utils.getStringIpAddress(l3Addresses.get(0).getIpAddress()))) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private boolean isEpgDifferentThanSecGrp(Endpoint ep, NeutronPort port) {
+ List<EndpointGroupId> epgIds = ep.getEndpointGroups();
+ List<NeutronSecurityGroup> secGroups = port.getSecurityGroups();
+ if ((epgIds == null || epgIds.isEmpty()) && (secGroups == null || secGroups.isEmpty())) {
+ return false;
+ }
+ if (epgIds != null && !epgIds.isEmpty() && secGroups != null && !secGroups.isEmpty()) {
+ if (epgIds.size() != secGroups.size()) {
+ return true;
+ }
+ Collection<EndpointGroupId> epgIdsFromSecGroups = Collections2.transform(secGroups,
+ new Function<NeutronSecurityGroup, EndpointGroupId>() {
+
+ @Override
+ public EndpointGroupId apply(NeutronSecurityGroup input) {
+ return new EndpointGroupId(input.getSecurityGroupUUID());
+ }
+ });
+ // order independent equals
+ Set<EndpointGroupId> one = new HashSet<>(epgIds);
+ Set<EndpointGroupId> two = new HashSet<>(epgIdsFromSecGroups);
+ if (one.equals(two)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * @see org.opendaylight.neutron.spi.INeutronPortAware#canDeletePort(org.opendaylight.neutron.spi.NeutronPort)
+ */
+ @Override
+ public int canDeletePort(NeutronPort port) {
+ LOG.trace("canDeletePort - {}", port);
+ // nothing to consider
+ return StatusCode.OK;
+ }
+
+ /**
+ * @see org.opendaylight.neutron.spi.INeutronPortAware#neutronPortDeleted(org.opendaylight.neutron.spi.NeutronPort)
+ */
+ @Override
+ public void neutronPortDeleted(NeutronPort port) {
+ LOG.trace("neutronPortDeleted - {}", port);
+ if (isRouterInterfacePort(port)) {
+ LOG.trace("Port is router interface - do nothing - NeutronRouterAware handles router iface");
+ return;
+ }
+ ReadOnlyTransaction rTx = dataProvider.newReadOnlyTransaction();
+ TenantId tenantId = new TenantId(Utils.normalizeUuid(port.getTenantID()));
+ L2FloodDomainId l2FdId = new L2FloodDomainId(port.getNetworkUUID());
+ ForwardingCtx fwCtx = MappingUtils.createForwardingContext(tenantId, l2FdId, rTx);
+ boolean isFwCtxValid = validateForwardingCtx(fwCtx);
+ if (!isFwCtxValid) {
+ rTx.close();
+ return;
+ }
+
+ UnregisterEndpointInput unregisterEpRpcInput = createUnregisterEndpointInput(port, fwCtx);
+ try {
+ RpcResult<Void> rpcResult = epService.unregisterEndpoint(unregisterEpRpcInput).get();
+ if (!rpcResult.isSuccessful()) {
+ LOG.warn("Illegal state - RPC unregisterEndpoint failed. Input of RPC: {}", unregisterEpRpcInput);
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.error("addPort - RPC invocation failed.", e);
+ } finally {
+ rTx.close();
+ }
+ }
+
+ private static RegisterEndpointInput createRegisterEndpointInput(NeutronPort port, ForwardingCtx fwCtx) {
+ List<EndpointGroupId> epgIds = new ArrayList<>();
+ // each EP has to be in EPG ANY, except dhcp and router
+ if (isDhcpPort(port)) {
+ epgIds.add(MappingUtils.EPG_DHCP_ID);
+ } else if (isRouterInterfacePort(port)) {
+ epgIds.add(MappingUtils.EPG_ROUTER_ID);
+ } else if (!containsSecRuleWithRemoteSecGroup(port.getSecurityGroups())) {
+ epgIds.add(MappingUtils.EPG_ANY_ID);
+ }
+
+ List<NeutronSecurityGroup> securityGroups = port.getSecurityGroups();
+ if ((securityGroups == null || securityGroups.isEmpty())) {
+ if (!isDhcpPort(port) && !isRouterInterfacePort(port)) {
+ LOG.warn(
+ "Port {} does not contain any security group. The port should belong to 'default' security group at least.",
+ port.getPortUUID());
+ }
+ } else {
+ for (NeutronSecurityGroup secGrp : securityGroups) {
+ epgIds.add(new EndpointGroupId(secGrp.getSecurityGroupUUID()));
+ }
+ }
+ RegisterEndpointInputBuilder inputBuilder = new RegisterEndpointInputBuilder().setL2Context(
+ fwCtx.getL2BridgeDomain().getId())
+ .setMacAddress(new MacAddress(port.getMacAddress()))
+ .setTenant(new TenantId(Utils.normalizeUuid(port.getTenantID())))
+ .setEndpointGroups(epgIds)
+ .addAugmentation(OfOverlayContextInput.class,
+ new OfOverlayContextInputBuilder().setPortName(createTapPortName(port)).build())
+ .setTimestamp(System.currentTimeMillis());
+ List<Neutron_IPs> fixedIPs = port.getFixedIPs();
+ // TODO Li msunal this getting of just first IP has to be rewrite when OFOverlay renderer
+ // will support l3-endpoints. Then we will register L2 and L3 endpoints separately.
+ Neutron_IPs firstIp = getFirstIp(fixedIPs);
+ if (firstIp != null) {
+ inputBuilder.setNetworkContainment(new SubnetId(firstIp.getSubnetUUID()));
+ L3Address l3Address = new L3AddressBuilder().setIpAddress(Utils.createIpAddress(firstIp.getIpAddress()))
+ .setL3Context(fwCtx.getL3Context().getId())
+ .build();
+ inputBuilder.setL3Address(ImmutableList.of(l3Address));
+ }
+ if (!Strings.isNullOrEmpty(port.getName())) {
+
+ }
+ return inputBuilder.build();
+ }
+
+ private static boolean containsSecRuleWithRemoteSecGroup(List<NeutronSecurityGroup> secGroups) {
+ if (secGroups == null) {
+ return false;
+ }
+ for (NeutronSecurityGroup secGroup : secGroups) {
+ boolean containsSecRuleWithRemoteSecGroup = containsSecRuleWithRemoteSecGroup(secGroup);
+ if (containsSecRuleWithRemoteSecGroup) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static boolean containsSecRuleWithRemoteSecGroup(NeutronSecurityGroup secGroup) {
+ List<NeutronSecurityRule> secRules = secGroup.getSecurityRules();
+ if (secRules == null) {
+ return false;
+ }
+ for (NeutronSecurityRule secRule : secRules) {
+ if (!Strings.isNullOrEmpty(secRule.getSecurityRemoteGroupID())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static Name createTapPortName(NeutronPort port) {
+ return new Name("tap" + port.getID().substring(0, 11));
+ }
+
+ private static Neutron_IPs getFirstIp(List<Neutron_IPs> fixedIPs) {
+ if (fixedIPs == null || fixedIPs.isEmpty()) {
+ return null;
+ }
+ Neutron_IPs neutron_Ip = fixedIPs.get(0);
+ if (fixedIPs.size() > 1) {
+ LOG.warn("Neutron mapper does not support multiple IPs on the same port. Only first IP is selected {}",
+ neutron_Ip);
+ }
+ return neutron_Ip;
+ }
+
+ private static boolean isDhcpPort(NeutronPort port) {
+ return DEVICE_OWNER_DHCP.equals(port.getDeviceOwner());
+ }
+
+ private static boolean isRouterInterfacePort(NeutronPort port) {
+ return DEVICE_OWNER_ROUTER_IFACE.equals(port.getDeviceOwner());
+ }
+
+ private UnregisterEndpointInput createUnregisterEndpointInput(Endpoint ep) {
+ UnregisterEndpointInputBuilder inputBuilder = new UnregisterEndpointInputBuilder();
+ L2 l2Ep = new L2Builder().setL2Context(ep.getL2Context()).setMacAddress(ep.getMacAddress()).build();
+ inputBuilder.setL2(ImmutableList.of(l2Ep));
+ // TODO Li msunal this has to be rewrite when OFOverlay renderer will support l3-endpoints.
+ // Endpoint probably will not have l3-addresses anymore, because L2 and L3 endpoints should
+ // be registered separately.
+ if (ep.getL3Address() != null && !ep.getL3Address().isEmpty()) {
+ List<L3> l3Eps = new ArrayList<>();
+ for (L3Address ip : ep.getL3Address()) {
+ l3Eps.add(new L3Builder().setL3Context(ip.getL3Context()).setIpAddress(ip.getIpAddress()).build());
+ }
+ inputBuilder.setL3(l3Eps);
+ }
+ return inputBuilder.build();
+ }
+
+ private UnregisterEndpointInput createUnregisterEndpointInput(NeutronPort port, ForwardingCtx fwCtx) {
+ UnregisterEndpointInputBuilder inputBuilder = new UnregisterEndpointInputBuilder();
+ L2 l2Ep = new L2Builder().setL2Context(fwCtx.getL2BridgeDomain().getId())
+ .setMacAddress(new MacAddress(port.getMacAddress()))
+ .build();
+ inputBuilder.setL2(ImmutableList.of(l2Ep));
+ // TODO Li msunal this has to be rewrite when OFOverlay renderer will support l3-endpoints.
+ // Endpoint probably will not have l3-addresses anymore, because L2 and L3 endpoints should
+ // be registered separately.
+ if (port.getFixedIPs() != null && !port.getFixedIPs().isEmpty()) {
+ inputBuilder.setL3(createL3s(port.getFixedIPs(), fwCtx.getL3Context().getId()));
+ }
+ return inputBuilder.build();
+ }
+
+ private List<L3> createL3s(List<Neutron_IPs> neutronIps, L3ContextId l3ContextId) {
+ List<L3> l3s = new ArrayList<>();
+ for (Neutron_IPs fixedIp : neutronIps) {
+ String ip = fixedIp.getIpAddress();
+ L3 l3 = new L3Builder().setIpAddress(Utils.createIpAddress(ip)).setL3Context(l3ContextId).build();
+ l3s.add(l3);
+ }
+ return l3s;
+ }
+
+}
--- /dev/null
+package org.opendaylight.groupbasedpolicy.neutron.mapper.mapping;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.List;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.binding.api.ReadTransaction;
+import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.groupbasedpolicy.neutron.mapper.util.DataStoreHelper;
+import org.opendaylight.groupbasedpolicy.neutron.mapper.util.IidFactory;
+import org.opendaylight.groupbasedpolicy.neutron.mapper.util.MappingUtils;
+import org.opendaylight.groupbasedpolicy.neutron.mapper.util.NeutronUtils;
+import org.opendaylight.groupbasedpolicy.neutron.mapper.util.Utils;
+import org.opendaylight.groupbasedpolicy.neutron.mapper.util.MappingUtils.ForwardingCtx;
+import org.opendaylight.neutron.spi.INeutronPortCRUD;
+import org.opendaylight.neutron.spi.INeutronRouterAware;
+import org.opendaylight.neutron.spi.INeutronRouterCRUD;
+import org.opendaylight.neutron.spi.INeutronSubnetCRUD;
+import org.opendaylight.neutron.spi.NeutronCRUDInterfaces;
+import org.opendaylight.neutron.spi.NeutronPort;
+import org.opendaylight.neutron.spi.NeutronRouter;
+import org.opendaylight.neutron.spi.NeutronRouter_Interface;
+import org.opendaylight.neutron.spi.NeutronSecurityRule;
+import org.opendaylight.neutron.spi.NeutronSubnet;
+import org.opendaylight.neutron.spi.Neutron_IPs;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.Description;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2FloodDomainId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L3ContextId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.Name;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubnetId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.EndpointService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.mapper.rev150223.mappings.network.mappings.NetworkMapping;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.EndpointGroup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.L2BridgeDomain;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.L2BridgeDomainBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.L3Context;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.L3ContextBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.Subnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.SubnetBuilder;
+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.collect.ImmutableList;
+
+public class NeutronRouterAware implements INeutronRouterAware {
+
+ private static final Logger LOG = LoggerFactory.getLogger(NeutronRouterAware.class);
+ private final DataBroker dataProvider;
+ private final EndpointService epService;
+
+ public NeutronRouterAware(DataBroker dataProvider, EndpointService epService) {
+ this.dataProvider = checkNotNull(dataProvider);
+ this.epService = checkNotNull(epService);
+ }
+
+ @Override
+ public int canCreateRouter(NeutronRouter router) {
+ LOG.trace("canCreateRouter - {}", router);
+ INeutronRouterCRUD routerInterface = NeutronCRUDInterfaces.getINeutronRouterCRUD(this);
+ if (routerInterface == null) {
+ LOG.warn("Illegal state - No provider for {}", INeutronSubnetCRUD.class.getName());
+ return StatusCode.INTERNAL_SERVER_ERROR;
+ }
+
+ List<NeutronRouter> allRouters = routerInterface.getAllRouters();
+ if (allRouters != null && !allRouters.isEmpty()) {
+ LOG.warn("Illegal state - Neutron mapper does not support multiple routers yet.");
+ return StatusCode.FORBIDDEN;
+ }
+ return StatusCode.OK;
+ }
+
+ @Override
+ public void neutronRouterCreated(NeutronRouter router) {
+ LOG.trace("neutronRouterCreated - {}", router);
+ // TODO Li msunal external gateway
+ }
+
+ @Override
+ public int canUpdateRouter(NeutronRouter delta, NeutronRouter original) {
+ LOG.trace("canUpdateRouter - delta: {} original: {}", delta, original);
+ // TODO Li msunal external gateway
+ return StatusCode.OK;
+ }
+
+ @Override
+ public void neutronRouterUpdated(NeutronRouter router) {
+ LOG.trace("neutronRouterUpdated - {}", router);
+ // TODO Li msunal external gateway
+ }
+
+ @Override
+ public int canDeleteRouter(NeutronRouter router) {
+ LOG.trace("canDeleteRouter - {}", router);
+ // nothing to consider
+ return StatusCode.OK;
+ }
+
+ @Override
+ public void neutronRouterDeleted(NeutronRouter router) {
+ LOG.trace("neutronRouterDeleted - {}", router);
+ ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
+ TenantId tenantId = new TenantId(Utils.normalizeUuid(router.getTenantID()));
+ Optional<EndpointGroup> potentialEpg = DataStoreHelper.removeIfExists(LogicalDatastoreType.CONFIGURATION,
+ IidFactory.endpointGroupIid(tenantId, MappingUtils.EPG_ROUTER_ID), rwTx);
+ if (!potentialEpg.isPresent()) {
+ LOG.warn("Illegal state - Endpoint group {} does not exist.", MappingUtils.EPG_ROUTER_ID.getValue());
+ rwTx.cancel();
+ return;
+ }
+ DataStoreHelper.submitToDs(rwTx);
+ }
+
+ @Override
+ public int canAttachInterface(NeutronRouter router, NeutronRouter_Interface routerInterface) {
+ LOG.trace("canAttachInterface - router: {} interface: {}", router, routerInterface);
+ try (ReadOnlyTransaction rTx = dataProvider.newReadOnlyTransaction()) {
+ L3ContextId l3ContextId = new L3ContextId(router.getID());
+ TenantId tenantId = new TenantId(Utils.normalizeUuid(router.getTenantID()));
+ SubnetId subnetId = new SubnetId(routerInterface.getSubnetUUID());
+ Optional<Subnet> potentialSubnet = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
+ IidFactory.subnetIid(tenantId, subnetId), rTx);
+ if (!potentialSubnet.isPresent()) {
+ LOG.warn("Illegal state - subnet {} does not exist.", subnetId.getValue());
+ return StatusCode.NOT_FOUND;
+ }
+ Subnet subnet = potentialSubnet.get();
+ L2FloodDomainId l2FdId = new L2FloodDomainId(subnet.getParent().getValue());
+ ForwardingCtx fwCtx = MappingUtils.createForwardingContext(tenantId, l2FdId, rTx);
+ if (fwCtx.getL3Context() != null && fwCtx.getL3Context().equals(l3ContextId)) {
+ // TODO Be msunal
+ LOG.warn("Illegal state - Neutron mapper does not support multiple router interfaces in the same subnet yet.");
+ return StatusCode.FORBIDDEN;
+ }
+ return StatusCode.OK;
+ }
+ }
+
+ @Override
+ public void neutronRouterInterfaceAttached(NeutronRouter router, NeutronRouter_Interface routerInterface) {
+ LOG.trace("neutronRouterInterfaceAttached - router: {} interface: {}", router, routerInterface);
+ INeutronPortCRUD portInterface = NeutronCRUDInterfaces.getINeutronPortCRUD(this);
+ if (portInterface == null) {
+ LOG.warn("Illegal state - No provider for {}", INeutronPortCRUD.class.getName());
+ return;
+ }
+
+ INeutronSubnetCRUD subnetInterface = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this);
+ if (subnetInterface == null) {
+ LOG.warn("Illegal state - No provider for {}", INeutronSubnetCRUD.class.getName());
+ return;
+ }
+
+ ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
+ TenantId tenantId = new TenantId(Utils.normalizeUuid(router.getTenantID()));
+ L3ContextId l3ContextId = new L3ContextId(router.getID());
+ InstanceIdentifier<L3Context> l3ContextIid = IidFactory.l3ContextIid(tenantId, l3ContextId);
+ Optional<L3Context> potentialL3Context = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
+ l3ContextIid, rwTx);
+ // add L3 context if missing
+ if (!potentialL3Context.isPresent()) {
+ Name l3ContextName = null;
+ if (router.getName() != null) {
+ l3ContextName = new Name(router.getName());
+ }
+ L3Context l3Context = new L3ContextBuilder().setId(l3ContextId)
+ .setName(l3ContextName)
+ .setDescription(new Description(MappingUtils.NEUTRON_ROUTER__ + router.getID()))
+ .build();
+ rwTx.put(LogicalDatastoreType.CONFIGURATION, l3ContextIid, l3Context);
+ }
+
+ SubnetId subnetId = new SubnetId(routerInterface.getSubnetUUID());
+ Optional<Subnet> potentialSubnet = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
+ IidFactory.subnetIid(tenantId, subnetId), rwTx);
+ if (!potentialSubnet.isPresent()) {
+ LOG.warn("Illegal state - subnet {} does not exist.", subnetId.getValue());
+ rwTx.cancel();
+ return;
+ }
+
+ // Based on Neutron Northbound - Port representing router interface contains exactly on
+ // fixed IP
+ NeutronPort routerPort = portInterface.getPort(routerInterface.getPortUUID());
+ Subnet subnet = new SubnetBuilder(potentialSubnet.get()).setVirtualRouterIp(
+ Utils.createIpAddress(routerPort.getFixedIPs().get(0).getIpAddress())).build();
+ rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.subnetIid(tenantId, subnetId), subnet);
+ if (subnet.getParent() == null) {
+ LOG.warn("Illegal state - subnet {} does not have a parent.", subnetId.getValue());
+ rwTx.cancel();
+ return;
+ }
+
+ L2FloodDomainId l2FdId = new L2FloodDomainId(subnet.getParent().getValue());
+ ForwardingCtx fwCtx = MappingUtils.createForwardingContext(tenantId, l2FdId, rwTx);
+ if (fwCtx.getL2BridgeDomain() == null) {
+ LOG.warn("Illegal state - l2-flood-domain {} does not have a parent.", l2FdId.getValue());
+ rwTx.cancel();
+ return;
+ }
+
+ L2BridgeDomain l2BridgeDomain = new L2BridgeDomainBuilder(fwCtx.getL2BridgeDomain()).setParent(l3ContextId)
+ .build();
+ rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.l2BridgeDomainIid(tenantId, l2BridgeDomain.getId()),
+ l2BridgeDomain);
+
+ // create security rules for router
+ List<NeutronSecurityRule> routerSecRules = createRouterSecRules(routerPort, null, rwTx);
+ if (routerSecRules == null) {
+ rwTx.cancel();
+ return;
+ }
+ for (NeutronSecurityRule routerSecRule : routerSecRules) {
+ boolean isRouterSecRuleAdded = NeutronSecurityRuleAware.addNeutronSecurityRule(routerSecRule, rwTx);
+ if (!isRouterSecRuleAdded) {
+ rwTx.cancel();
+ return;
+ }
+ }
+
+ NeutronSubnet neutronSubnet = subnetInterface.getSubnet(subnetId.getValue());
+ List<NeutronPort> portsInNeutronSubnet = neutronSubnet.getPortsInSubnet();
+ for (NeutronPort port : portsInNeutronSubnet) {
+ boolean isPortAdded = NeutronPortAware.addNeutronPort(port, rwTx, epService);
+ if (!isPortAdded) {
+ rwTx.cancel();
+ return;
+ }
+ }
+
+ DataStoreHelper.submitToDs(rwTx);
+ }
+
+ public static List<NeutronSecurityRule> createRouterSecRules(NeutronPort port, EndpointGroupId consumerEpgId,
+ ReadTransaction rTx) {
+ TenantId tenantId = new TenantId(Utils.normalizeUuid(port.getTenantID()));
+ Neutron_IPs firstIp = getFirstIp(port.getFixedIPs());
+ if (firstIp == null) {
+ LOG.warn("Illegal state - Router port does not have an IP address.");
+ return null;
+ }
+ SubnetId routerSubnetId = new SubnetId(firstIp.getSubnetUUID());
+ Optional<Subnet> potentialSubnet = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
+ IidFactory.subnetIid(tenantId, routerSubnetId), rTx);
+ if (!potentialSubnet.isPresent()) {
+ LOG.warn("Illegal state - Subnet {} where is router port does not exist.", routerSubnetId.getValue());
+ return null;
+ }
+ IpPrefix ipSubnet = potentialSubnet.get().getIpPrefix();
+ NeutronSecurityRule routerRuleEgress = createRouterSecRule(port.getID(), tenantId, ipSubnet, consumerEpgId,
+ true);
+ NeutronSecurityRule routerRuleIngress = createRouterSecRule(port.getID(), tenantId, ipSubnet, consumerEpgId,
+ false);
+ return ImmutableList.of(routerRuleEgress, routerRuleIngress);
+ }
+
+ private static Neutron_IPs getFirstIp(List<Neutron_IPs> fixedIPs) {
+ if (fixedIPs == null || fixedIPs.isEmpty()) {
+ return null;
+ }
+ Neutron_IPs neutron_Ip = fixedIPs.get(0);
+ if (fixedIPs.size() > 1) {
+ LOG.warn("Neutron mapper does not support multiple IPs on the same port. Only first IP is selected {}",
+ neutron_Ip);
+ }
+ return neutron_Ip;
+ }
+
+ private static NeutronSecurityRule createRouterSecRule(String ruleUuid, TenantId tenantId, IpPrefix ipSubnet,
+ EndpointGroupId consumerEpgId, boolean isEgress) {
+ NeutronSecurityRule dhcpSecRule = new NeutronSecurityRule();
+ dhcpSecRule.setSecurityRuleGroupID(MappingUtils.EPG_ROUTER_ID.getValue());
+ dhcpSecRule.setSecurityRuleTenantID(tenantId.getValue());
+ dhcpSecRule.setSecurityRuleRemoteIpPrefix(Utils.getStringIpPrefix(ipSubnet));
+ if (isEgress) {
+ dhcpSecRule.setSecurityRuleUUID(NeutronUtils.EGRESS + "__" + ruleUuid);
+ dhcpSecRule.setSecurityRuleDirection(NeutronUtils.EGRESS);
+ } else {
+ dhcpSecRule.setSecurityRuleUUID(NeutronUtils.INGRESS + "__" + ruleUuid);
+ dhcpSecRule.setSecurityRuleDirection(NeutronUtils.INGRESS);
+ }
+ if (ipSubnet.getIpv4Prefix() != null) {
+ dhcpSecRule.setSecurityRuleEthertype(NeutronUtils.IPv4);
+ } else {
+ dhcpSecRule.setSecurityRuleEthertype(NeutronUtils.IPv6);
+ }
+ return dhcpSecRule;
+ }
+
+ @Override
+ public int canDetachInterface(NeutronRouter router, NeutronRouter_Interface routerInterface) {
+ LOG.trace("canDetachInterface - router: {} interface: {}", router, routerInterface);
+ // nothing to consider
+ return StatusCode.OK;
+ }
+
+ @Override
+ public void neutronRouterInterfaceDetached(NeutronRouter router, NeutronRouter_Interface routerInterface) {
+ LOG.trace("neutronRouterInterfaceDetached - router: {} interface: {}", router, routerInterface);
+ INeutronSubnetCRUD subnetInterface = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this);
+ if (subnetInterface == null) {
+ LOG.warn("Illegal state - No provider for {}", INeutronSubnetCRUD.class.getName());
+ return;
+ }
+
+ ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
+ TenantId tenantId = new TenantId(Utils.normalizeUuid(router.getTenantID()));
+ L3ContextId l3ContextId = new L3ContextId(router.getID());
+ SubnetId subnetId = new SubnetId(routerInterface.getSubnetUUID());
+ InstanceIdentifier<L3Context> l3ContextIid = IidFactory.l3ContextIid(tenantId, l3ContextId);
+ DataStoreHelper.removeIfExists(LogicalDatastoreType.CONFIGURATION,
+ IidFactory.l3ContextIid(tenantId, l3ContextId), rwTx);
+
+ Optional<Subnet> potentialSubnet = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
+ IidFactory.subnetIid(tenantId, subnetId), rwTx);
+ if (!potentialSubnet.isPresent()) {
+ LOG.warn("Illegal state - subnet {} does not exist.", subnetId.getValue());
+ rwTx.cancel();
+ return;
+ }
+
+ Subnet subnet = new SubnetBuilder(potentialSubnet.get()).setVirtualRouterIp(null).build();
+ rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.subnetIid(tenantId, subnetId), subnet);
+
+ L2FloodDomainId l2FdId = new L2FloodDomainId(subnet.getParent().getValue());
+ ForwardingCtx fwCtx = MappingUtils.createForwardingContext(tenantId, l2FdId, rwTx);
+ if (fwCtx.getL2BridgeDomain() == null) {
+ LOG.warn("Illegal state - l2-flood-domain {} does not have a parent.", l2FdId.getValue());
+ rwTx.cancel();
+ return;
+ }
+
+ Optional<NetworkMapping> potentialNetworkMapping = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
+ IidFactory.networkMappingIid(l2FdId), rwTx);
+ if (!potentialNetworkMapping.isPresent()) {
+ LOG.warn("Illegal state - network-mapping {} does not exist.", l2FdId.getValue());
+ rwTx.cancel();
+ return;
+ }
+
+ L2BridgeDomain l2BridgeDomain = new L2BridgeDomainBuilder(fwCtx.getL2BridgeDomain()).setParent(
+ potentialNetworkMapping.get().getL3ContextId()).build();
+ rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.l2BridgeDomainIid(tenantId, l2BridgeDomain.getId()),
+ l2BridgeDomain);
+
+ NeutronSubnet neutronSubnet = subnetInterface.getSubnet(subnetId.getValue());
+ List<NeutronPort> portsInNeutronSubnet = neutronSubnet.getPortsInSubnet();
+ for (NeutronPort port : portsInNeutronSubnet) {
+ boolean isPortAdded = NeutronPortAware.addNeutronPort(port, rwTx, epService);
+ if (!isPortAdded) {
+ rwTx.cancel();
+ return;
+ }
+ }
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.groupbasedpolicy.neutron.mapper.mapping;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.groupbasedpolicy.neutron.mapper.util.DataStoreHelper;
+import org.opendaylight.groupbasedpolicy.neutron.mapper.util.IidFactory;
+import org.opendaylight.groupbasedpolicy.neutron.mapper.util.MappingUtils;
+import org.opendaylight.groupbasedpolicy.neutron.mapper.util.Utils;
+import org.opendaylight.neutron.spi.INeutronSecurityGroupAware;
+import org.opendaylight.neutron.spi.NeutronSecurityGroup;
+import org.opendaylight.neutron.spi.NeutronSecurityRule;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.Description;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.Name;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.EndpointGroup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.EndpointGroupBuilder;
+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.base.Preconditions;
+import com.google.common.base.Strings;
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableListMultimap;
+import com.google.common.collect.ListMultimap;
+
+public class NeutronSecurityGroupAware implements INeutronSecurityGroupAware {
+
+ private static final Logger LOG = LoggerFactory.getLogger(NeutronSecurityGroupAware.class);
+ private final DataBroker dataProvider;
+
+ public NeutronSecurityGroupAware(DataBroker dataProvider) {
+ this.dataProvider = checkNotNull(dataProvider);
+ }
+
+ /**
+ * @see org.opendaylight.neutron.spi.INeutronSecurityGroupAware#canCreateNeutronSecurityGroup(org.opendaylight.neutron.spi.NeutronSecurityGroup)
+ */
+ @Override
+ public int canCreateNeutronSecurityGroup(NeutronSecurityGroup securityGroup) {
+ LOG.trace("canCreateNeutronSecurityGroup - {}", securityGroup);
+ // nothing to consider
+ return StatusCode.OK;
+ }
+
+ /**
+ * @see org.opendaylight.neutron.spi.INeutronSecurityGroupAware#neutronSecurityGroupCreated(org.opendaylight.neutron.spi.NeutronSecurityGroup)
+ */
+ @Override
+ public void neutronSecurityGroupCreated(NeutronSecurityGroup secGroup) {
+ LOG.trace("neutronSecurityGroupCreated - {}", secGroup);
+ ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
+ boolean isSecGroupCreated = addNeutronSecurityGroup(secGroup, rwTx);
+ if (isSecGroupCreated) {
+ DataStoreHelper.submitToDs(rwTx);
+ } else {
+ rwTx.cancel();
+ }
+ }
+
+ public static boolean addNeutronSecurityGroup(NeutronSecurityGroup secGroup, ReadWriteTransaction rwTx) {
+ TenantId tenantId = new TenantId(Utils.normalizeUuid(secGroup.getSecurityGroupTenantID()));
+ EndpointGroupId providerEpgId = new EndpointGroupId(secGroup.getSecurityGroupUUID());
+ EndpointGroupBuilder providerEpgBuilder = new EndpointGroupBuilder().setId(providerEpgId);
+ providerEpgBuilder.setName(new Name(MappingUtils.NEUTRON_GROUP__ + Strings.nullToEmpty(secGroup.getSecurityGroupName())));
+ providerEpgBuilder.setDescription(new Description(MappingUtils.NEUTRON_GROUP__
+ + Strings.nullToEmpty(secGroup.getSecurityGroupDescription())));
+ rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.endpointGroupIid(tenantId, providerEpgId),
+ providerEpgBuilder.build(), true);
+ List<NeutronSecurityRule> secRules = secGroup.getSecurityRules();
+ SortedSecurityGroupRules sortedSecGrpRules = new SortedSecurityGroupRules(secRules);
+ ListMultimap<EndpointGroupId, NeutronSecurityRule> secRuleByRemoteSecGrpId = sortedSecGrpRules.secRuleByRemoteSecGrpId;
+ for (EndpointGroupId consumerEpgId : secRuleByRemoteSecGrpId.keySet()) {
+ addEpgIfMissing(tenantId, consumerEpgId, rwTx);
+ boolean areSecRulesAdded = addNeutronSecurityRule(secRuleByRemoteSecGrpId.get(consumerEpgId), rwTx);
+ if (!areSecRulesAdded) {
+ return false;
+ }
+ }
+ ListMultimap<IpPrefix, NeutronSecurityRule> secRuleByRemoteIpPrefix = sortedSecGrpRules.secRuleByRemoteIpPrefix;
+ for (IpPrefix remoteIpPrefex : secRuleByRemoteIpPrefix.keySet()) {
+ boolean areSecRulesAdded = addNeutronSecurityRule(secRuleByRemoteIpPrefix.get(remoteIpPrefex), rwTx);
+ if (!areSecRulesAdded) {
+ return false;
+ }
+ }
+ boolean areSecRulesAdded = addNeutronSecurityRule(sortedSecGrpRules.secRulesWithoutRemote, rwTx);
+ if (!areSecRulesAdded) {
+ return false;
+ }
+ return true;
+ }
+
+ public static void addEpgIfMissing(TenantId tenantId, EndpointGroupId epgId, ReadWriteTransaction rwTx) {
+ InstanceIdentifier<EndpointGroup> epgIid = IidFactory.endpointGroupIid(tenantId, epgId);
+ Optional<EndpointGroup> potentialConsumerEpg = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
+ epgIid, rwTx);
+ if (!potentialConsumerEpg.isPresent()) {
+ EndpointGroup epg = new EndpointGroupBuilder().setId(epgId)
+ .setName(new Name(MappingUtils.NEUTRON_GROUP__))
+ .setDescription(new Description(MappingUtils.NEUTRON_GROUP__ + "EPG was created just based on remote group ID from a security rule."))
+ .build();
+ rwTx.put(LogicalDatastoreType.CONFIGURATION, epgIid, epg);
+ }
+ }
+
+ private static boolean addNeutronSecurityRule(List<NeutronSecurityRule> secRules, ReadWriteTransaction rwTx) {
+ for (NeutronSecurityRule secRule : secRules) {
+ boolean isSecRuleAdded = NeutronSecurityRuleAware.addNeutronSecurityRule(secRule, rwTx);
+ if (!isSecRuleAdded) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * @see org.opendaylight.neutron.spi.INeutronSecurityGroupAware#canUpdateNeutronSecurityGroup(org.opendaylight.neutron.spi.NeutronSecurityGroup,
+ * org.opendaylight.neutron.spi.NeutronSecurityGroup)
+ */
+ @Override
+ public int canUpdateNeutronSecurityGroup(NeutronSecurityGroup delta, NeutronSecurityGroup original) {
+ LOG.warn("canUpdateNeutronSecurityGroup - Never should be called "
+ + "- neutron API does not allow UPDATE on neutron security group. \nDelta: {} \nOriginal: {}", delta,
+ original);
+ return StatusCode.BAD_REQUEST;
+ }
+
+ /**
+ * @see org.opendaylight.neutron.spi.INeutronSecurityGroupAware#neutronSecurityGroupUpdated(org.opendaylight.neutron.spi.NeutronSecurityGroup)
+ */
+ @Override
+ public void neutronSecurityGroupUpdated(NeutronSecurityGroup securityGroup) {
+ LOG.warn("neutronSecurityGroupUpdated - Never should be called "
+ + "- neutron API does not allow UPDATE on neutron security group. \nSecurity group: {}", securityGroup);
+ }
+
+ /**
+ * @see org.opendaylight.neutron.spi.INeutronSecurityGroupAware#canDeleteNeutronSecurityGroup(org.opendaylight.neutron.spi.NeutronSecurityGroup)
+ */
+ @Override
+ public int canDeleteNeutronSecurityGroup(NeutronSecurityGroup securityGroup) {
+ LOG.trace("canDeleteNeutronSecurityGroup - {}", securityGroup);
+ // nothing to consider
+ return StatusCode.OK;
+ }
+
+ /**
+ * @see org.opendaylight.neutron.spi.INeutronSecurityGroupAware#neutronSecurityGroupDeleted(org.opendaylight.neutron.spi.NeutronSecurityGroup)
+ */
+ @Override
+ public void neutronSecurityGroupDeleted(NeutronSecurityGroup secGroup) {
+ LOG.trace("neutronSecurityGroupDeleted - {}", secGroup);
+ ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
+ List<NeutronSecurityRule> secRules = secGroup.getSecurityRules();
+ if (secRules != null) {
+ boolean areSecRulesAdded = deleteNeutronSecurityRules(secRules, rwTx);
+ if (!areSecRulesAdded) {
+ rwTx.cancel();
+ return;
+ }
+ }
+ TenantId tenantId = new TenantId(Utils.normalizeUuid(secGroup.getSecurityGroupTenantID()));
+ EndpointGroupId epgId = new EndpointGroupId(secGroup.getSecurityGroupUUID());
+ Optional<EndpointGroup> potentialEpg = DataStoreHelper.removeIfExists(LogicalDatastoreType.CONFIGURATION,
+ IidFactory.endpointGroupIid(tenantId, epgId), rwTx);
+ if (!potentialEpg.isPresent()) {
+ LOG.warn("Illegal state - Endpoint group {} does not exist.", epgId.getValue());
+ rwTx.cancel();
+ return;
+ }
+
+ DataStoreHelper.submitToDs(rwTx);
+ }
+
+ private boolean deleteNeutronSecurityRules(List<NeutronSecurityRule> secRules, ReadWriteTransaction rwTx) {
+ for (NeutronSecurityRule secRule : secRules) {
+ boolean isSecRuleDeleted = NeutronSecurityRuleAware.deleteNeutronSecurityRule(secRule, rwTx);
+ if (!isSecRuleDeleted) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private static final class SortedSecurityGroupRules {
+
+ private final ListMultimap<EndpointGroupId, NeutronSecurityRule> secRuleByRemoteSecGrpId;
+ private final ListMultimap<IpPrefix, NeutronSecurityRule> secRuleByRemoteIpPrefix;
+ private final List<NeutronSecurityRule> secRulesWithoutRemote;
+
+ private SortedSecurityGroupRules(List<NeutronSecurityRule> securityRules) {
+ Preconditions.checkNotNull(securityRules);
+ ListMultimap<EndpointGroupId, NeutronSecurityRule> tmpSecRuleByRemoteSecGrpId = ArrayListMultimap.create();
+ ListMultimap<IpPrefix, NeutronSecurityRule> tmpSecRuleByRemoteIpPrefix = ArrayListMultimap.create();
+ List<NeutronSecurityRule> tmpSecRulesWithoutRemote = new ArrayList<>();
+ for (NeutronSecurityRule securityRule : securityRules) {
+ String remoteSecGroupId = securityRule.getSecurityRemoteGroupID();
+ String remoteIpPrefix = securityRule.getSecurityRuleRemoteIpPrefix();
+ boolean isRemoteSecGroupId = remoteSecGroupId != null && !"null".equals(remoteSecGroupId);
+ boolean isRemoteIpPrefix = remoteIpPrefix != null && !"null".equals(remoteIpPrefix);
+ if (isRemoteSecGroupId && isRemoteIpPrefix) {
+ throw new IllegalArgumentException("Either remote group id or ip prefix "
+ + "must be speciefied in neutron security group rule." + securityRule.toString());
+ }
+ if (isRemoteSecGroupId) {
+ tmpSecRuleByRemoteSecGrpId.put(new EndpointGroupId(remoteSecGroupId), securityRule);
+ } else if (isRemoteIpPrefix) {
+ tmpSecRuleByRemoteIpPrefix.put(Utils.createIpPrefix(remoteIpPrefix), securityRule);
+ } else {
+ tmpSecRulesWithoutRemote.add(securityRule);
+ }
+ }
+ secRuleByRemoteSecGrpId = ImmutableListMultimap.copyOf(tmpSecRuleByRemoteSecGrpId);
+ secRuleByRemoteIpPrefix = ImmutableListMultimap.copyOf(tmpSecRuleByRemoteIpPrefix);
+ secRulesWithoutRemote = ImmutableList.copyOf(tmpSecRulesWithoutRemote);
+ }
+ }
+
+}
--- /dev/null
+package org.opendaylight.groupbasedpolicy.neutron.mapper.mapping;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.UUID;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadTransaction;
+import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.groupbasedpolicy.neutron.mapper.util.DataStoreHelper;
+import org.opendaylight.groupbasedpolicy.neutron.mapper.util.IidFactory;
+import org.opendaylight.groupbasedpolicy.neutron.mapper.util.MappingUtils;
+import org.opendaylight.neutron.spi.INeutronSecurityRuleAware;
+import org.opendaylight.neutron.spi.NeutronSecurityRule;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClassifierName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClauseName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContractId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.Description;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.RuleName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SelectorName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubjectName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.mapper.rev150223.mappings.endpoint.group.pair.to.contract.mappings.EndpointGroupPairToContractMapping;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.mapper.rev150223.mappings.endpoint.group.pair.to.contract.mappings.EndpointGroupPairToContractMappingBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.Contract;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.ContractBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.EndpointGroup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.EndpointGroup.IntraGroupPolicy;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.EndpointGroupBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.Clause;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.Subject;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.subject.Rule;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ConsumerNamedSelector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ConsumerNamedSelectorBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ProviderNamedSelector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ProviderNamedSelectorBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.subject.feature.instances.ActionInstance;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.subject.feature.instances.ClassifierInstance;
+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.collect.ImmutableList;
+
+public class NeutronSecurityRuleAware implements INeutronSecurityRuleAware {
+
+ private static final Logger LOG = LoggerFactory.getLogger(NeutronSecurityRuleAware.class);
+ private final DataBroker dataProvider;
+
+ public NeutronSecurityRuleAware(DataBroker dataProvider) {
+ this.dataProvider = checkNotNull(dataProvider);
+ }
+
+ @Override
+ public int canCreateNeutronSecurityRule(NeutronSecurityRule securityRule) {
+ LOG.trace("canCreateNeutronSecurityRule - {}", securityRule);
+ // nothing to consider
+ return StatusCode.OK;
+ }
+
+ @Override
+ public void neutronSecurityRuleCreated(NeutronSecurityRule securityRule) {
+ LOG.trace("neutronSecurityRuleCreated - {}", securityRule);
+ ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
+ boolean isNeutronSecurityRuleAdded = addNeutronSecurityRule(securityRule, rwTx);
+ if (isNeutronSecurityRuleAdded) {
+ DataStoreHelper.submitToDs(rwTx);
+ } else {
+ rwTx.cancel();
+ }
+ }
+
+ /**
+ * <b>ASSUMPTION</b>: Endpoint group with id
+ * {@link NeutronSecurityRule#getSecurityRuleGroupID()} and
+ * endpoint group with id {@link NeutronSecurityRule#getSecurityRemoteGroupID()} already exist
+ * in transaction.
+ *
+ * @param secRule neutron security rule from which GBP entities are created
+ * @param rwTx GBP entities are stored to this transaction. This method NEVER submits or cancel
+ * the transaction.
+ * @return {@code true} if operation was successful; {@code false} if an illegal state occurs -
+ * the transaction may contain just partial result
+ */
+ public static boolean addNeutronSecurityRule(NeutronSecurityRule secRule, ReadWriteTransaction rwTx) {
+ TransformSecRule transform = new TransformSecRule(secRule);
+ TenantId tenantId = transform.getTenantId();
+ EndpointGroupId providerEpgId = transform.getProviderEpgId();
+ EndpointGroupId consumerEpgId = transform.getConsumerEpgId();
+ SubjectName subjectName = transform.getSubjectName();
+
+ Optional<ContractId> potentialContractId = readContractIdFromEpgPairToContractMapping(providerEpgId,
+ consumerEpgId, rwTx);
+ ContractId contractId = null;
+ if (potentialContractId.isPresent()) {
+ contractId = potentialContractId.get();
+ Optional<Subject> potentialSubject = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
+ IidFactory.subjectIid(tenantId, contractId, subjectName), rwTx);
+ if (!potentialSubject.isPresent()) {
+ // it also means that clause for this subject does not exist
+ rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.subjectIid(tenantId, contractId, subjectName),
+ transform.createSubject());
+ rwTx.put(LogicalDatastoreType.CONFIGURATION,
+ IidFactory.clauseIid(tenantId, contractId, transform.getClauseName()), transform.createClause());
+ }
+ } else {
+ // check assumption that provider EPG exists
+ Optional<EndpointGroup> potentialProviderEpg = DataStoreHelper.readFromDs(
+ LogicalDatastoreType.CONFIGURATION, IidFactory.endpointGroupIid(tenantId, providerEpgId), rwTx);
+ if (!potentialProviderEpg.isPresent()) {
+ LOG.warn("Illegal state - Endpoint group {} does not exist.", providerEpgId.getValue());
+ return false;
+ }
+
+ if (providerEpgId.equals(consumerEpgId)) {
+ EndpointGroup providerConsumerEpg = potentialProviderEpg.get();
+ if (providerConsumerEpg.getIntraGroupPolicy() == null
+ || !providerConsumerEpg.getIntraGroupPolicy().equals(IntraGroupPolicy.RequireContract)) {
+ EndpointGroup newProviderConsumerEpg = new EndpointGroupBuilder(providerConsumerEpg).setIntraGroupPolicy(
+ IntraGroupPolicy.RequireContract)
+ .build();
+ rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.endpointGroupIid(tenantId, providerEpgId),
+ newProviderConsumerEpg);
+ }
+ } else {
+ Optional<EndpointGroup> potentialConsumerEpg = DataStoreHelper.readFromDs(
+ LogicalDatastoreType.CONFIGURATION, IidFactory.endpointGroupIid(tenantId, consumerEpgId), rwTx);
+ if (!potentialConsumerEpg.isPresent()) {
+ if (MappingUtils.EPG_ANY_ID.equals(consumerEpgId)) {
+ EndpointGroup epgAny = createEpgAny();
+ rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.endpointGroupIid(tenantId, MappingUtils.EPG_ANY_ID),
+ epgAny);
+ } else {
+ LOG.warn("Illegal state - Endpoint group {} does not exist.", consumerEpgId.getValue());
+ return false;
+ }
+ }
+ }
+ // creates and stores contract with clause and subject
+ Subject subject = transform.createSubject();
+ Clause clause = transform.createClause();
+ Contract contract = createContract(clause, subject);
+ contractId = contract.getId();
+ rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.contractIid(tenantId, contractId), contract);
+ putEpgPairToContractMapping(providerEpgId, consumerEpgId, contractId, rwTx);
+
+ // adds provider and consumer named selectors
+ ProviderNamedSelector providerSelector = createProviderNamedSelector(contractId);
+ rwTx.put(LogicalDatastoreType.CONFIGURATION,
+ IidFactory.providerNamedSelectorIid(tenantId, providerEpgId, providerSelector.getName()),
+ providerSelector);
+ ConsumerNamedSelector consumerSelector = createConsumerNamedSelector(contractId);
+ rwTx.put(LogicalDatastoreType.CONFIGURATION,
+ IidFactory.consumerNamedSelectorIid(tenantId, consumerEpgId, consumerSelector.getName()),
+ consumerSelector);
+ }
+
+ // create classifier-instance
+ ClassifierName classifierName = transform.getClassifierName();
+ ClassifierInstance classifier = transform.createClassifier();
+ rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.classifierInstanceIid(tenantId, classifierName),
+ classifier, true);
+ // create action-instance if it does not exist yet
+ Optional<ActionInstance> potentialAction = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
+ IidFactory.actionInstanceIid(tenantId, MappingUtils.ACTION_ALLOW.getName()), rwTx);
+ if (!potentialAction.isPresent()) {
+ rwTx.put(LogicalDatastoreType.CONFIGURATION,
+ IidFactory.actionInstanceIid(tenantId, MappingUtils.ACTION_ALLOW.getName()),
+ MappingUtils.ACTION_ALLOW, true);
+ }
+
+ // create rule
+ Rule rule = transform.createRule(0);
+ rwTx.put(LogicalDatastoreType.CONFIGURATION,
+ IidFactory.ruleIid(tenantId, contractId, subjectName, rule.getName()), rule);
+ return true;
+ }
+
+ private static EndpointGroup createEpgAny() {
+ return new EndpointGroupBuilder().setId(MappingUtils.EPG_ANY_ID)
+ .setDescription(new Description(MappingUtils.NEUTRON_RULE__ + "epg_any"))
+ .setIntraGroupPolicy(IntraGroupPolicy.RequireContract)
+ .build();
+ }
+
+ @Override
+ public int canUpdateNeutronSecurityRule(NeutronSecurityRule delta, NeutronSecurityRule original) {
+ LOG.warn("canUpdateNeutronSecurityRule - Never should be called "
+ + "- neutron API does not allow UPDATE on neutron security group rule. \nDelta: {} \nOriginal: {}",
+ delta, original);
+ return StatusCode.BAD_REQUEST;
+ }
+
+ @Override
+ public void neutronSecurityRuleUpdated(NeutronSecurityRule securityRule) {
+ LOG.warn("neutronSecurityRuleUpdated - Never should be called "
+ + "- neutron API does not allow UPDATE on neutron security group rule. \nSecurity group rule: {}",
+ securityRule);
+ }
+
+ @Override
+ public int canDeleteNeutronSecurityRule(NeutronSecurityRule securityRule) {
+ LOG.trace("canDeleteNeutronSecurityRule - {}", securityRule);
+ // nothing to consider
+ return StatusCode.OK;
+ }
+
+ @Override
+ public void neutronSecurityRuleDeleted(NeutronSecurityRule secRule) {
+ LOG.trace("neutronSecurityRuleCreated - {}", secRule);
+ ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
+ boolean isNeutronSecurityRuleDelete = deleteNeutronSecurityRule(secRule, rwTx);
+ if (isNeutronSecurityRuleDelete) {
+ DataStoreHelper.submitToDs(rwTx);
+ } else {
+ DataStoreHelper.submitToDs(rwTx);
+ }
+ }
+
+ /**
+ * @param secRule neutron security rule from which GBP entities are deleted
+ * @param rwTx GBP entities are stored to this transaction. This method NEVER submits or cancel
+ * the transaction.
+ * @return {@code true} if operation was successful; {@code false} if an illegal state occurs -
+ * the transaction may contain just partial result
+ */
+ public static boolean deleteNeutronSecurityRule(NeutronSecurityRule secRule, ReadWriteTransaction rwTx) {
+ TransformSecRule transform = new TransformSecRule(secRule);
+ TenantId tenantId = transform.getTenantId();
+ EndpointGroupId providerEpgId = transform.getProviderEpgId();
+ EndpointGroupId consumerEpgId = transform.getConsumerEpgId();
+
+ Optional<ContractId> potentialContractId = readContractIdFromEpgPairToContractMapping(providerEpgId,
+ consumerEpgId, rwTx);
+ if (!potentialContractId.isPresent()) {
+ LOG.warn("Illegal state - mapping EPG pair (provider EPG {} consumer EPG {}) does not exist.",
+ providerEpgId.getValue(), consumerEpgId.getValue());
+ return false;
+ }
+
+ ContractId contractId = potentialContractId.get();
+ ClassifierName classifierName = transform.getClassifierName();
+ InstanceIdentifier<ClassifierInstance> classifierIid = IidFactory.classifierInstanceIid(tenantId,
+ classifierName);
+ Optional<ClassifierInstance> potentialClassifier = DataStoreHelper.removeIfExists(
+ LogicalDatastoreType.CONFIGURATION, classifierIid, rwTx);
+ if (!potentialClassifier.isPresent()) {
+ LOG.warn("Illegal state - classifier-instance {} does not exist. {}", classifierName.getValue(),
+ classifierIid);
+ return false;
+ }
+
+ RuleName ruleName = transform.getRuleName();
+ SubjectName subjectName = transform.getSubjectName();
+ InstanceIdentifier<Rule> ruleIid = IidFactory.ruleIid(tenantId, contractId, subjectName, ruleName);
+ Optional<Rule> potentionalRule = DataStoreHelper.removeIfExists(LogicalDatastoreType.CONFIGURATION, ruleIid,
+ rwTx);
+ if (!potentionalRule.isPresent()) {
+ LOG.warn("Illegal state - rule {} does not exist. {}", ruleName.getValue(), ruleIid);
+ return false;
+ }
+
+ InstanceIdentifier<Subject> subjectIid = IidFactory.subjectIid(tenantId, contractId, subjectName);
+ Optional<Subject> potentionalSubject = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
+ subjectIid, rwTx);
+ if (!potentionalSubject.isPresent()) {
+ LOG.warn("Illegal state - subject {} does not exist. {}", subjectName.getValue(), subjectName);
+ return false;
+ }
+
+ ClauseName clauseName = transform.getClauseName();
+ InstanceIdentifier<Clause> clauseIid = IidFactory.clauseIid(tenantId, contractId, clauseName);
+ Optional<Clause> potentialClause = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION, clauseIid,
+ rwTx);
+ if (!potentialClause.isPresent()) {
+ LOG.warn("Illegal state - clause {} does not exist. {}", clauseName.getValue(), clauseIid);
+ return false;
+ }
+
+ Subject subject = potentionalSubject.get();
+ if (subject.getRule() == null || subject.getRule().isEmpty()) {
+ rwTx.delete(LogicalDatastoreType.CONFIGURATION, clauseIid);
+ rwTx.delete(LogicalDatastoreType.CONFIGURATION, subjectIid);
+ }
+
+ InstanceIdentifier<Contract> contractIid = IidFactory.contractIid(tenantId, contractId);
+ Optional<Contract> potentialContract = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
+ contractIid, rwTx);
+ if (!potentialContract.isPresent()) {
+ LOG.warn("Illegal state - contract {} does not exist. {}", contractId.getValue(), contractIid);
+ return false;
+ }
+
+ Contract contract = potentialContract.get();
+ if (contract.getSubject() == null || contract.getSubject().isEmpty()) {
+ // remove contract and named selectors from EPGs
+ rwTx.delete(LogicalDatastoreType.CONFIGURATION, contractIid);
+ SelectorName providerSelectorName = createNameOfNamedSelector(contractId);
+ InstanceIdentifier<ProviderNamedSelector> providerSelectorIid = IidFactory.providerNamedSelectorIid(
+ tenantId, providerEpgId, providerSelectorName);
+ Optional<ProviderNamedSelector> potentialProviderSelector = DataStoreHelper.removeIfExists(
+ LogicalDatastoreType.CONFIGURATION, providerSelectorIid, rwTx);
+ if (!potentialProviderSelector.isPresent()) {
+ LOG.warn("Illegal state - provider-name-selector {} does not exist. {}",
+ providerSelectorName.getValue(), providerSelectorIid);
+ return false;
+ }
+ SelectorName consumerSelectorName = createNameOfNamedSelector(contractId);
+ InstanceIdentifier<ConsumerNamedSelector> consumerSelectorIid = IidFactory.consumerNamedSelectorIid(
+ tenantId, consumerEpgId, consumerSelectorName);
+ Optional<ConsumerNamedSelector> potentialConsuemrSelector = DataStoreHelper.removeIfExists(
+ LogicalDatastoreType.CONFIGURATION, consumerSelectorIid, rwTx);
+ if (!potentialConsuemrSelector.isPresent()) {
+ LOG.warn("Illegal state - consumer-name-selector {} does not exist. {}",
+ consumerSelectorName.getValue(), consumerSelectorIid);
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static Optional<ContractId> readContractIdFromEpgPairToContractMapping(EndpointGroupId providerEpgId,
+ EndpointGroupId consumerEpgId, ReadTransaction rTx) {
+ Optional<EndpointGroupPairToContractMapping> potentialMapping = DataStoreHelper.readFromDs(
+ LogicalDatastoreType.OPERATIONAL,
+ IidFactory.endpointGroupPairToContractMappingIid(providerEpgId, consumerEpgId), rTx);
+ if (potentialMapping.isPresent()) {
+ return Optional.of(potentialMapping.get().getContractId());
+ }
+ return Optional.absent();
+ }
+
+ private static void putEpgPairToContractMapping(EndpointGroupId providerEpgId, EndpointGroupId consumerEpgId,
+ ContractId contractId, WriteTransaction wTx) {
+ EndpointGroupPairToContractMapping epgPairToContractMapping = new EndpointGroupPairToContractMappingBuilder().setProviderEpgId(
+ providerEpgId)
+ .setConsumerEpgId(consumerEpgId)
+ .setContractId(contractId)
+ .build();
+ wTx.put(LogicalDatastoreType.OPERATIONAL, IidFactory.endpointGroupPairToContractMappingIid(
+ epgPairToContractMapping.getProviderEpgId(), epgPairToContractMapping.getConsumerEpgId()),
+ epgPairToContractMapping, true);
+ }
+
+ private static Contract createContract(Clause clause, Subject subject) {
+ ContractId contractId = new ContractId(UUID.randomUUID().toString());
+ return new ContractBuilder().setId(contractId)
+ .setClause(ImmutableList.of(clause))
+ .setSubject(ImmutableList.of(subject))
+ .build();
+ }
+
+ private static ProviderNamedSelector createProviderNamedSelector(ContractId contractId) {
+ return new ProviderNamedSelectorBuilder().setName(createNameOfNamedSelector(contractId))
+ .setContract(ImmutableList.of(contractId))
+ .build();
+ }
+
+ private static ConsumerNamedSelector createConsumerNamedSelector(ContractId contractId) {
+ return new ConsumerNamedSelectorBuilder().setName(createNameOfNamedSelector(contractId))
+ .setContract(ImmutableList.of(contractId))
+ .build();
+ }
+
+ private static SelectorName createNameOfNamedSelector(ContractId contractId) {
+ return new SelectorName(MappingUtils.NEUTRON_RULE__ + contractId.getValue());
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.groupbasedpolicy.neutron.mapper.mapping;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.groupbasedpolicy.neutron.mapper.util.DataStoreHelper;
+import org.opendaylight.groupbasedpolicy.neutron.mapper.util.IidFactory;
+import org.opendaylight.groupbasedpolicy.neutron.mapper.util.Utils;
+import org.opendaylight.neutron.spi.INeutronSubnetAware;
+import org.opendaylight.neutron.spi.NeutronSubnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContextId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.Name;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubnetId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.Subnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.SubnetBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+
+public class NeutronSubnetAware implements INeutronSubnetAware {
+
+ private final static Logger LOG = LoggerFactory.getLogger(NeutronSubnetAware.class);
+ private final DataBroker dataProvider;
+
+ public NeutronSubnetAware(DataBroker dataProvider) {
+ this.dataProvider = checkNotNull(dataProvider);
+ }
+
+ /**
+ * @see org.opendaylight.neutron.spi.INeutronSubnetAware#canCreateSubnet(org.opendaylight.neutron.spi.NeutronSubnet)
+ */
+ @Override
+ public int canCreateSubnet(NeutronSubnet subnet) {
+ LOG.trace("canCreateSubnet - {}", subnet);
+ // nothing to consider
+ return StatusCode.OK;
+ }
+
+ /**
+ * @see org.opendaylight.neutron.spi.INeutronSubnetAware#neutronSubnetCreated(org.opendaylight.neutron.spi.NeutronSubnet)
+ */
+ @Override
+ public void neutronSubnetCreated(NeutronSubnet neutronSubnet) {
+ LOG.trace("neutronSubnetCreated - {}", neutronSubnet);
+ ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
+ SubnetId subnetId = new SubnetId(Utils.normalizeUuid(neutronSubnet.getID()));
+ TenantId tenantId = new TenantId(Utils.normalizeUuid(neutronSubnet.getTenantID()));
+ Subnet subnet = createSubnet(neutronSubnet);
+ rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.subnetIid(tenantId, subnetId), subnet, true);
+
+ DataStoreHelper.submitToDs(rwTx);
+ }
+
+ private Subnet createSubnet(NeutronSubnet neutronSubnet) {
+ SubnetBuilder subnetBuilder = new SubnetBuilder();
+ subnetBuilder.setId(new SubnetId(neutronSubnet.getID()));
+ subnetBuilder.setParent(new ContextId(neutronSubnet.getNetworkUUID()));
+ if (neutronSubnet.getName() != null) {
+ subnetBuilder.setName(new Name(neutronSubnet.getName()));
+ }
+ subnetBuilder.setIpPrefix(Utils.createIpPrefix(neutronSubnet.getCidr()));
+ return subnetBuilder.build();
+ }
+
+ /**
+ * @see org.opendaylight.neutron.spi.INeutronSubnetAware#canUpdateSubnet(org.opendaylight.neutron.spi.NeutronSubnet,
+ * org.opendaylight.neutron.spi.NeutronSubnet)
+ */
+ @Override
+ public int canUpdateSubnet(NeutronSubnet delta, NeutronSubnet original) {
+ LOG.trace("canUpdateSubnet - delta: {} original: {}", delta, original);
+ // nothing to consider
+ return StatusCode.OK;
+ }
+
+ /**
+ * @see org.opendaylight.neutron.spi.INeutronSubnetAware#neutronSubnetUpdated(org.opendaylight.neutron.spi.NeutronSubnet)
+ */
+ @Override
+ public void neutronSubnetUpdated(NeutronSubnet subnet) {
+ LOG.trace("neutronSubnetUpdated - {}", subnet);
+ neutronSubnetCreated(subnet);
+ }
+
+ /**
+ * @see org.opendaylight.neutron.spi.INeutronSubnetAware#canDeleteSubnet(org.opendaylight.neutron.spi.NeutronSubnet)
+ */
+ @Override
+ public int canDeleteSubnet(NeutronSubnet subnet) {
+ LOG.trace("canDeleteSubnet - {}", subnet);
+ // nothing to consider
+ return StatusCode.OK;
+ }
+
+ /**
+ * @see org.opendaylight.neutron.spi.INeutronSubnetAware#neutronSubnetDeleted(org.opendaylight.neutron.spi.NeutronSubnet)
+ */
+ @Override
+ public void neutronSubnetDeleted(NeutronSubnet neutronSubnet) {
+ LOG.trace("neutronSubnetDeleted - {}", neutronSubnet);
+ ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
+ SubnetId subnetId = new SubnetId(Utils.normalizeUuid(neutronSubnet.getID()));
+ TenantId tenantId = new TenantId(Utils.normalizeUuid(neutronSubnet.getTenantID()));
+ Optional<Subnet> potentialSubnet = DataStoreHelper.removeIfExists(LogicalDatastoreType.CONFIGURATION,
+ IidFactory.subnetIid(tenantId, subnetId), rwTx);
+ if (!potentialSubnet.isPresent()) {
+ LOG.warn("Illegal state - subnet {} does not exist.", subnetId.getValue());
+ rwTx.cancel();
+ return;
+ }
+
+ DataStoreHelper.submitToDs(rwTx);
+ }
+
+}
--- /dev/null
+package org.opendaylight.groupbasedpolicy.neutron.mapper.mapping;
+
+/**
+ * HTTP status codes
+ */
+public final class StatusCode {
+
+ public static final int OK = 200;
+ public static final int BAD_REQUEST = 400;
+ public static final int FORBIDDEN = 403;
+ public static final int NOT_FOUND = 404;
+ public static final int INTERNAL_SERVER_ERROR = 500;
+
+ private StatusCode() {
+ throw new UnsupportedOperationException("Cannot create an instance.");
+ }
+}
--- /dev/null
+package org.opendaylight.groupbasedpolicy.neutron.mapper.mapping;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.opendaylight.groupbasedpolicy.neutron.mapper.util.MappingUtils;
+import org.opendaylight.groupbasedpolicy.neutron.mapper.util.NeutronUtils;
+import org.opendaylight.groupbasedpolicy.neutron.mapper.util.Utils;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.EtherTypeClassifier;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.IpProtoClassifier;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.L4Classifier;
+import org.opendaylight.neutron.spi.NeutronSecurityRule;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClassifierName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClauseName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ParameterName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.RuleName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubjectName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.HasDirection.Direction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.action.refs.ActionRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.action.refs.ActionRefBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.classifier.refs.ClassifierRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.classifier.refs.ClassifierRef.ConnectionTracking;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.classifier.refs.ClassifierRefBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.instance.ParameterValue;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.instance.ParameterValueBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.instance.parameter.value.RangeValueBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.Clause;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.ClauseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.Subject;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.SubjectBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.ConsumerMatchersBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.ProviderMatchersBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.consumer.matchers.EndpointIdentificationConstraintsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.consumer.matchers.endpoint.identification.constraints.L3EndpointIdentificationConstraintsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.consumer.matchers.endpoint.identification.constraints.l3.endpoint.identification.constraints.PrefixConstraint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.consumer.matchers.endpoint.identification.constraints.l3.endpoint.identification.constraints.PrefixConstraintBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.subject.Rule;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.subject.RuleBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.subject.feature.instances.ClassifierInstance;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.subject.feature.instances.ClassifierInstanceBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableList;
+
+public class TransformSecRule {
+
+ private static final Logger LOG = LoggerFactory.getLogger(TransformSecRule.class);
+ private static final List<ActionRef> ACTION_REF_ALLOW = ImmutableList.of(new ActionRefBuilder().setName(
+ MappingUtils.ACTION_ALLOW.getName())
+ .setOrder(0)
+ .build());
+ private final NeutronSecurityRule secRule;
+ private final TenantId tenantId;
+ private final EndpointGroupId providerEpgId;
+ private final EndpointGroupId consumerEpgId;
+ private final SubjectName subjectName;
+ private final ClauseName clauseName;
+ private final IpPrefix ipPrefix;
+ private final int subjectOrder;
+ private final ClassifierName classifierName;
+ private final RuleName ruleName;
+
+ /**
+ * If a {@link NeutronSecurityRule#getSecurityRuleGroupID()} is {@link MappingUtils#EPG_DHCP_ID}
+ * or {@link MappingUtils#EPG_ROUTER_ID} then the neutron security rule can contain remote ip
+ * prefix besides remote ip security group. I this case {@link #getConsumerEpgId()} returns remote security group id.
+ *
+ * @param secRule
+ */
+ public TransformSecRule(NeutronSecurityRule secRule) {
+ this.secRule = checkNotNull(secRule);
+ tenantId = new TenantId(Utils.normalizeUuid(secRule.getSecurityRuleTenantID()));
+ providerEpgId = new EndpointGroupId(secRule.getSecurityRuleGroupID());
+ if (!Strings.isNullOrEmpty(secRule.getSecurityRemoteGroupID())) {
+ consumerEpgId = new EndpointGroupId(secRule.getSecurityRemoteGroupID());
+ if (isEpgIdRouterOrDhcp(providerEpgId) && !Strings.isNullOrEmpty(secRule.getSecurityRuleRemoteIpPrefix())) {
+ ipPrefix = Utils.createIpPrefix(secRule.getSecurityRuleRemoteIpPrefix());
+ } else {
+ ipPrefix = null;
+ }
+ subjectOrder = 0;
+ } else if (!Strings.isNullOrEmpty(secRule.getSecurityRuleRemoteIpPrefix())) {
+ consumerEpgId = MappingUtils.EPG_ANY_ID;
+ ipPrefix = Utils.createIpPrefix(secRule.getSecurityRuleRemoteIpPrefix());
+ subjectOrder = 0;
+ } else {
+ consumerEpgId = MappingUtils.EPG_ANY_ID;
+ ipPrefix = null;
+ subjectOrder = 1;
+ }
+ subjectName = createSubjectName();
+ clauseName = new ClauseName(subjectName.getValue());
+ classifierName = new ClassifierName(MappingUtils.NEUTRON_RULE__ + secRule.getSecurityRuleUUID());
+ ruleName = new RuleName(MappingUtils.NEUTRON_RULE__ + "Allow--" + classifierName.getValue());
+ }
+
+ private SubjectName createSubjectName() {
+ if (ipPrefix == null) {
+ return new SubjectName(MappingUtils.NEUTRON_RULE__ + providerEpgId.getValue() + "__"
+ + consumerEpgId.getValue());
+ }
+ String prefix = Utils.getStringIpPrefix(ipPrefix).replace('/', '_');
+ return new SubjectName(MappingUtils.NEUTRON_RULE__ + providerEpgId.getValue() + "__" + prefix + "__"
+ + consumerEpgId.getValue());
+ }
+
+ public Clause createClause() {
+ ClauseBuilder clauseBuilder = new ClauseBuilder().setName(clauseName).setSubjectRefs(
+ ImmutableList.of(subjectName));
+ if (ipPrefix != null) {
+ clauseBuilder.setConsumerMatchers(new ConsumerMatchersBuilder().setEndpointIdentificationConstraints(
+ new EndpointIdentificationConstraintsBuilder().setL3EndpointIdentificationConstraints(
+ new L3EndpointIdentificationConstraintsBuilder().setPrefixConstraint(
+ ImmutableList.<PrefixConstraint>of(new PrefixConstraintBuilder().setIpPrefix(
+ ipPrefix).build())).build()).build()).build());
+ if (isEpgIdRouterOrDhcp(providerEpgId)) {
+ clauseBuilder.setProviderMatchers(new ProviderMatchersBuilder().setEndpointIdentificationConstraints(
+ new org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.provider.matchers.EndpointIdentificationConstraintsBuilder().setL3EndpointIdentificationConstraints(
+ new org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.provider.matchers.endpoint.identification.constraints.L3EndpointIdentificationConstraintsBuilder().setPrefixConstraint(
+ ImmutableList.<org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.provider.matchers.endpoint.identification.constraints.l3.endpoint.identification.constraints.PrefixConstraint>of(new org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.provider.matchers.endpoint.identification.constraints.l3.endpoint.identification.constraints.PrefixConstraintBuilder().setIpPrefix(
+ ipPrefix)
+ .build()))
+ .build())
+ .build())
+ .build());
+ }
+ }
+ return clauseBuilder.build();
+ }
+
+ private static boolean isEpgIdRouterOrDhcp(EndpointGroupId epgId) {
+ return (MappingUtils.EPG_ROUTER_ID.equals(epgId) || MappingUtils.EPG_DHCP_ID.equals(epgId));
+ }
+
+ public ClassifierInstance createClassifier() {
+ ClassifierInstanceBuilder classifierBuilder = new ClassifierInstanceBuilder().setName(classifierName);
+ List<ParameterValue> params = new ArrayList<>();
+ Integer portMin = secRule.getSecurityRulePortMin();
+ Integer portMax = secRule.getSecurityRulePortMax();
+ if (portMin != null && portMax != null) {
+ classifierBuilder.setClassifierDefinitionId(L4Classifier.DEFINITION.getId());
+ if (portMin.equals(portMax)) {
+ params.add(new ParameterValueBuilder().setName(new ParameterName(L4Classifier.DST_PORT_PARAM))
+ .setIntValue(portMin.longValue())
+ .build());
+ } else {
+ params.add(new ParameterValueBuilder().setName(new ParameterName(L4Classifier.DST_PORT_RANGE_PARAM))
+ .setRangeValue(
+ new RangeValueBuilder().setMin(portMin.longValue()).setMax(portMax.longValue()).build())
+ .build());
+ }
+ }
+ String protocol = secRule.getSecurityRuleProtocol();
+ if (!Strings.isNullOrEmpty(protocol)) {
+ if (classifierBuilder.getClassifierDefinitionId() == null) {
+ classifierBuilder.setClassifierDefinitionId(IpProtoClassifier.DEFINITION.getId());
+ }
+ if (NeutronUtils.TCP.equals(protocol)) {
+ params.add(new ParameterValueBuilder().setName(new ParameterName(IpProtoClassifier.PROTO_PARAM))
+ .setIntValue(IpProtoClassifier.TCP_VALUE)
+ .build());
+ } else if (NeutronUtils.UDP.equals(protocol)) {
+ params.add(new ParameterValueBuilder().setName(new ParameterName(IpProtoClassifier.PROTO_PARAM))
+ .setIntValue(IpProtoClassifier.UDP_VALUE)
+ .build());
+ } else if (NeutronUtils.ICMP.equals(protocol)) {
+ params.add(new ParameterValueBuilder().setName(new ParameterName(IpProtoClassifier.PROTO_PARAM))
+ .setIntValue(1L)
+ .build());
+ } else if (NeutronUtils.NULL.equals(protocol)) {
+ LOG.debug("Protocol is not specified in security group rule {}", secRule.getSecurityRuleUUID());
+ } else {
+ throw new IllegalArgumentException("Protocol " + protocol + " is not supported.");
+ }
+ }
+ String ethertype = secRule.getSecurityRuleEthertype();
+ if (!Strings.isNullOrEmpty(ethertype)) {
+ if (classifierBuilder.getClassifierDefinitionId() == null) {
+ classifierBuilder.setClassifierDefinitionId(EtherTypeClassifier.DEFINITION.getId());
+ }
+ if (NeutronUtils.IPv4.equals(ethertype)) {
+ params.add(new ParameterValueBuilder().setName(new ParameterName(EtherTypeClassifier.ETHERTYPE_PARAM))
+ .setIntValue(EtherTypeClassifier.IPv4_VALUE)
+ .build());
+ } else if (NeutronUtils.IPv6.equals(ethertype)) {
+ params.add(new ParameterValueBuilder().setName(new ParameterName(EtherTypeClassifier.ETHERTYPE_PARAM))
+ .setIntValue(EtherTypeClassifier.IPv6_VALUE)
+ .build());
+ } else {
+ throw new IllegalArgumentException("Ethertype " + ethertype + " is not supported.");
+ }
+ }
+ return classifierBuilder.setParameterValue(params).build();
+ }
+
+ public Rule createRule(int order) {
+ return new RuleBuilder().setName(ruleName)
+ .setOrder(order)
+ .setActionRef(ACTION_REF_ALLOW)
+ .setClassifierRef(ImmutableList.of(createClassifierRef()))
+ .build();
+ }
+
+ public Subject createSubject() {
+ return new SubjectBuilder().setName(subjectName).setOrder(subjectOrder).build();
+ }
+
+ private ClassifierRef createClassifierRef() {
+ ClassifierRefBuilder classifierRefBuilder = new ClassifierRefBuilder().setName(classifierName)
+ .setConnectionTracking(ConnectionTracking.Reflexive)
+ .setInstanceName(classifierName);
+ String direction = secRule.getSecurityRuleDirection();
+ if (NeutronUtils.INGRESS.equals(direction)) {
+ classifierRefBuilder.setDirection(Direction.In);
+ } else if (NeutronUtils.EGRESS.equals(direction)) {
+ classifierRefBuilder.setDirection(Direction.Out);
+ } else {
+ throw new IllegalArgumentException("Direction " + direction + " from security group rule "
+ + secRule.getSecurityRuleUUID() + " is not supported. Direction can be only 'ingress' or 'egress'.");
+ }
+ return classifierRefBuilder.build();
+ }
+
+ public TenantId getTenantId() {
+ return tenantId;
+ }
+
+ public EndpointGroupId getProviderEpgId() {
+ return providerEpgId;
+ }
+
+ public EndpointGroupId getConsumerEpgId() {
+ return consumerEpgId;
+ }
+
+ public SubjectName getSubjectName() {
+ return subjectName;
+ }
+
+ public ClauseName getClauseName() {
+ return clauseName;
+ }
+
+ public IpPrefix getIpPrefix() {
+ return ipPrefix;
+ }
+
+ public ClassifierName getClassifierName() {
+ return classifierName;
+ }
+
+ public RuleName getRuleName() {
+ return ruleName;
+ }
+
+}
--- /dev/null
+/*
+ * 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
+ */
+
+package org.opendaylight.groupbasedpolicy.neutron.mapper.util;
+
+import org.opendaylight.controller.md.sal.binding.api.ReadTransaction;
+import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+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;
+
+/**
+ * @author Martin Sunal
+ */
+public class DataStoreHelper {
+
+ private static final Logger LOG = LoggerFactory.getLogger(DataStoreHelper.class);
+
+ /**
+ * Reads data from datastore as synchrone call.
+ * @return {@link Optional#isPresent()} is {@code true} if reading was successful and data exists in datastore; {@link Optional#isPresent()} is {@code false} otherwise
+ */
+ public static <T extends DataObject> Optional<T> readFromDs(LogicalDatastoreType store, InstanceIdentifier<T> path, ReadTransaction rTx) {
+ CheckedFuture<Optional<T>, ReadFailedException> resultFuture = rTx.read(store, path);
+ try {
+ return resultFuture.checkedGet();
+ } catch (ReadFailedException e) {
+ LOG.warn("Read failed from DS.", e);
+ return Optional.absent();
+ }
+ }
+
+ /**
+ * Calls {@link WriteTransaction#submit()} on write transaction.
+ * @param wTx write transaction
+ * @return {@code true} if transaction commit was successful; {@code false} otherwise
+ */
+ public static boolean submitToDs(WriteTransaction wTx) {
+ CheckedFuture<Void, TransactionCommitFailedException> submitFuture = wTx.submit();
+ try {
+ submitFuture.checkedGet();
+ return true;
+ } catch (TransactionCommitFailedException e) {
+ LOG.warn("Transaction commit failed to DS.", e);
+ return false;
+ }
+ }
+
+ /**
+ * If an element on the path exists in datastore the element is removed and returned as a result.
+ * {@link Optional#isPresent()} is {@code false} in case that element on path does not exist.
+ * @return removed element in {@link Optional#get()}; otherwise {@link Optional#absent()}
+ */
+ public static <T extends DataObject> Optional<T> removeIfExists(LogicalDatastoreType store, InstanceIdentifier<T> path,
+ ReadWriteTransaction rwTx) {
+ Optional<T> potentialResult = readFromDs(store, path, rwTx);
+ if (potentialResult.isPresent()) {
+ rwTx.delete(store, path);
+ }
+ return potentialResult;
+ }
+
+}
--- /dev/null
+/*
+ * 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
+ */
+
+package org.opendaylight.groupbasedpolicy.neutron.mapper.util;
+
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ActionName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClassifierName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClauseName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContractId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2BridgeDomainId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2FloodDomainId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L3ContextId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.RuleName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SelectorName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubjectName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubnetId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.UniqueId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.Endpoints;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Key;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.mapper.rev150223.Mappings;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.mapper.rev150223.mappings.EndpointGroupPairToContractMappings;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.mapper.rev150223.mappings.NetworkMappings;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.mapper.rev150223.mappings.endpoint.group.pair.to.contract.mappings.EndpointGroupPairToContractMapping;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.mapper.rev150223.mappings.endpoint.group.pair.to.contract.mappings.EndpointGroupPairToContractMappingKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.mapper.rev150223.mappings.network.mappings.NetworkMapping;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.mapper.rev150223.mappings.network.mappings.NetworkMappingKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.Tenants;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.classifier.refs.ClassifierRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.classifier.refs.ClassifierRefKey;
+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.TenantKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.Contract;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.ContractKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.EndpointGroup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.EndpointGroupKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.L2BridgeDomain;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.L2BridgeDomainKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.L2FloodDomain;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.L2FloodDomainKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.L3Context;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.L3ContextKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.SubjectFeatureInstances;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.Subnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.SubnetKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.Clause;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.ClauseKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.Subject;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.SubjectKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.subject.Rule;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.subject.RuleKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ConsumerNamedSelector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ConsumerNamedSelectorKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ProviderNamedSelector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ProviderNamedSelectorKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.subject.feature.instances.ActionInstance;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.subject.feature.instances.ActionInstanceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.subject.feature.instances.ClassifierInstance;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.subject.feature.instances.ClassifierInstanceKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class IidFactory {
+
+ private IidFactory() {
+ throw new UnsupportedOperationException();
+ }
+
+ public static InstanceIdentifier<Tenant> tenantIid(TenantId id) {
+ return InstanceIdentifier.builder(Tenants.class).child(Tenant.class, new TenantKey(id)).build();
+ }
+
+ public static InstanceIdentifier<EndpointGroup> endpointGroupIid(TenantId tenantId, EndpointGroupId epgId) {
+ return InstanceIdentifier.builder(Tenants.class)
+ .child(Tenant.class, new TenantKey(tenantId))
+ .child(EndpointGroup.class, new EndpointGroupKey(epgId))
+ .build();
+ }
+
+ public static InstanceIdentifier<Contract> contractIid(TenantId tenantId, ContractId contractId) {
+ return InstanceIdentifier.builder(Tenants.class)
+ .child(Tenant.class, new TenantKey(tenantId))
+ .child(Contract.class, new ContractKey(contractId))
+ .build();
+ }
+
+ public static InstanceIdentifier<Subject> subjectIid(TenantId tenantId, ContractId contractId,
+ SubjectName subjectName) {
+ return InstanceIdentifier.builder(Tenants.class)
+ .child(Tenant.class, new TenantKey(tenantId))
+ .child(Contract.class, new ContractKey(contractId))
+ .child(Subject.class, new SubjectKey(subjectName))
+ .build();
+ }
+
+ public static InstanceIdentifier<ProviderNamedSelector> providerNamedSelectorIid(TenantId tenantId,
+ EndpointGroupId epgId, SelectorName providerSelectorName) {
+ return InstanceIdentifier.builder(Tenants.class)
+ .child(Tenant.class, new TenantKey(tenantId))
+ .child(EndpointGroup.class, new EndpointGroupKey(epgId))
+ .child(ProviderNamedSelector.class, new ProviderNamedSelectorKey(providerSelectorName))
+ .build();
+ }
+
+ public static InstanceIdentifier<ConsumerNamedSelector> consumerNamedSelectorIid(TenantId tenantId,
+ EndpointGroupId epgId, SelectorName consumerSelectorName) {
+ return InstanceIdentifier.builder(Tenants.class)
+ .child(Tenant.class, new TenantKey(tenantId))
+ .child(EndpointGroup.class, new EndpointGroupKey(epgId))
+ .child(ConsumerNamedSelector.class, new ConsumerNamedSelectorKey(consumerSelectorName))
+ .build();
+ }
+
+ public static InstanceIdentifier<Clause> clauseIid(TenantId tenantId, ContractId contractId, ClauseName clauseName) {
+ return InstanceIdentifier.builder(Tenants.class)
+ .child(Tenant.class, new TenantKey(tenantId))
+ .child(Contract.class, new ContractKey(contractId))
+ .child(Clause.class, new ClauseKey(clauseName))
+ .build();
+ }
+
+ public static InstanceIdentifier<Rule> ruleIid(TenantId tenantId, ContractId contractId, SubjectName subjectName,
+ RuleName ruleName) {
+ return InstanceIdentifier.builder(Tenants.class)
+ .child(Tenant.class, new TenantKey(tenantId))
+ .child(Contract.class, new ContractKey(contractId))
+ .child(Subject.class, new SubjectKey(subjectName))
+ .child(Rule.class, new RuleKey(ruleName))
+ .build();
+ }
+
+ public static InstanceIdentifier<ActionInstance> actionInstanceIid(TenantId tenantId, ActionName actionName) {
+ return InstanceIdentifier.builder(Tenants.class)
+ .child(Tenant.class, new TenantKey(tenantId))
+ .child(SubjectFeatureInstances.class)
+ .child(ActionInstance.class, new ActionInstanceKey(actionName))
+ .build();
+ }
+
+ public static InstanceIdentifier<ClassifierInstance> classifierInstanceIid(TenantId tenantId,
+ ClassifierName classifierName) {
+ return InstanceIdentifier.builder(Tenants.class)
+ .child(Tenant.class, new TenantKey(tenantId))
+ .child(SubjectFeatureInstances.class)
+ .child(ClassifierInstance.class, new ClassifierInstanceKey(classifierName))
+ .build();
+ }
+
+ public static InstanceIdentifier<ClassifierRef> classifierRefIid(TenantId tenantId, ContractId contractId,
+ SubjectName subjectName, RuleName ruleName, ClassifierName classifierRefName) {
+ return InstanceIdentifier.builder(Tenants.class)
+ .child(Tenant.class, new TenantKey(tenantId))
+ .child(Contract.class, new ContractKey(contractId))
+ .child(Subject.class, new SubjectKey(subjectName))
+ .child(Rule.class, new RuleKey(ruleName))
+ .child(ClassifierRef.class, new ClassifierRefKey(classifierRefName))
+ .build();
+ }
+
+ public static InstanceIdentifier<NetworkMapping> networkMappingIid(UniqueId networkId) {
+ return InstanceIdentifier.builder(Mappings.class)
+ .child(NetworkMappings.class)
+ .child(NetworkMapping.class, new NetworkMappingKey(networkId))
+ .build();
+ }
+
+ public static InstanceIdentifier<EndpointGroupPairToContractMapping> endpointGroupPairToContractMappingIid(
+ EndpointGroupId providerEpg, EndpointGroupId consumerEpg) {
+ return InstanceIdentifier.builder(Mappings.class)
+ .child(EndpointGroupPairToContractMappings.class)
+ .child(EndpointGroupPairToContractMapping.class,
+ new EndpointGroupPairToContractMappingKey(consumerEpg, providerEpg))
+ .build();
+ }
+
+ public static InstanceIdentifier<L2FloodDomain> l2FloodDomainIid(TenantId tenantId, L2FloodDomainId l2FloodDomainId) {
+ return InstanceIdentifier.builder(Tenants.class)
+ .child(Tenant.class, new TenantKey(tenantId))
+ .child(L2FloodDomain.class, new L2FloodDomainKey(l2FloodDomainId))
+ .build();
+ }
+
+ public static InstanceIdentifier<L2BridgeDomain> l2BridgeDomainIid(TenantId tenantId,
+ L2BridgeDomainId l2BridgeDomainId) {
+ return InstanceIdentifier.builder(Tenants.class)
+ .child(Tenant.class, new TenantKey(tenantId))
+ .child(L2BridgeDomain.class, new L2BridgeDomainKey(l2BridgeDomainId))
+ .build();
+ }
+
+ public static InstanceIdentifier<L3Context> l3ContextIid(TenantId tenantId, L3ContextId l3ContextId) {
+ return InstanceIdentifier.builder(Tenants.class)
+ .child(Tenant.class, new TenantKey(tenantId))
+ .child(L3Context.class, new L3ContextKey(l3ContextId))
+ .build();
+ }
+
+ public static InstanceIdentifier<Endpoint> endpointIid(L2BridgeDomainId l2Context, MacAddress macAddress) {
+ return InstanceIdentifier.builder(Endpoints.class)
+ .child(Endpoint.class, new EndpointKey(l2Context, macAddress))
+ .build();
+ }
+
+ public static InstanceIdentifier<EndpointL3> endpointL3Iid(L3ContextId l3Context, IpAddress ipAddress) {
+ return InstanceIdentifier.builder(Endpoints.class)
+ .child(EndpointL3.class, new EndpointL3Key(ipAddress, l3Context))
+ .build();
+ }
+
+ public static InstanceIdentifier<Subnet> subnetIid(TenantId tenantId, SubnetId subnetId) {
+ return InstanceIdentifier.builder(Tenants.class)
+ .child(Tenant.class, new TenantKey(tenantId))
+ .child(Subnet.class, new SubnetKey(subnetId))
+ .build();
+ }
+}
--- /dev/null
+package org.opendaylight.groupbasedpolicy.neutron.mapper.util;
+
+import org.opendaylight.controller.md.sal.binding.api.ReadTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.AllowAction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ActionName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2BridgeDomainId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2FloodDomainId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L3ContextId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.L2BridgeDomain;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.L2FloodDomain;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.L3Context;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.subject.feature.instances.ActionInstance;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.subject.feature.instances.ActionInstanceBuilder;
+
+import com.google.common.base.Optional;
+
+public final class MappingUtils {
+
+ public static final String NEUTRON_RULE__ = "neutron_rule__";
+ public static final String NEUTRON_NETWORK__ = "neutron_network__";
+ public static final String NEUTRON_ROUTER__ = "neutron_router__";
+ public static final String NEUTRON_GROUP__ = "neutron_group__";
+ public static final ActionInstance ACTION_ALLOW = new ActionInstanceBuilder().setName(
+ new ActionName(NEUTRON_RULE__ + "allow"))
+ .setActionDefinitionId(AllowAction.DEFINITION.getId())
+ .build();
+ public static final EndpointGroupId EPG_ANY_ID = new EndpointGroupId("aaaec0ce-dd5a-11e4-b9d6-1681e6b88ec1");
+ public static final EndpointGroupId EPG_DHCP_ID = new EndpointGroupId("ddd6cfe6-dfe5-11e4-8a00-1681e6b88ec1");
+ public static final EndpointGroupId EPG_ROUTER_ID = new EndpointGroupId("1118172e-cd84-4933-a35f-749f9a651de9");
+
+ private MappingUtils() {
+ throw new UnsupportedOperationException("Cannot create an instance.");
+ }
+
+ public static ForwardingCtx createForwardingContext(TenantId tenantId, L2FloodDomainId l2FdId, ReadTransaction rTx) {
+ Optional<L2FloodDomain> potentialL2Fd = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
+ IidFactory.l2FloodDomainIid(tenantId, l2FdId), rTx);
+ if (!potentialL2Fd.isPresent()) {
+ return new ForwardingCtx(null, null, null);
+ }
+ L2BridgeDomainId l2BdId = potentialL2Fd.get().getParent();
+ if (l2BdId == null) {
+ return new ForwardingCtx(potentialL2Fd.get(), null, null);
+ }
+ Optional<L2BridgeDomain> potentialL2Bd = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
+ IidFactory.l2BridgeDomainIid(tenantId, l2BdId), rTx);
+ if (!potentialL2Bd.isPresent()) {
+ return new ForwardingCtx(potentialL2Fd.get(), null, null);
+ }
+ L3ContextId l3ContextId = potentialL2Bd.get().getParent();
+ if (l3ContextId == null) {
+ return new ForwardingCtx(potentialL2Fd.get(), potentialL2Bd.get(), null);
+ }
+ Optional<L3Context> potentialL3Context = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
+ IidFactory.l3ContextIid(tenantId, l3ContextId), rTx);
+ if (!potentialL3Context.isPresent()) {
+ return new ForwardingCtx(potentialL2Fd.get(), potentialL2Bd.get(), null);
+ }
+ return new ForwardingCtx(potentialL2Fd.get(), potentialL2Bd.get(), potentialL3Context.get());
+ }
+
+ public static final class ForwardingCtx {
+
+ private final L2FloodDomain l2FloodDomain;
+ private final L2BridgeDomain l2BridgeDomain;
+ private final L3Context l3Context;
+
+ private ForwardingCtx(L2FloodDomain l2Fd, L2BridgeDomain l2Bd, L3Context l3Context) {
+ this.l2FloodDomain = l2Fd;
+ this.l2BridgeDomain = l2Bd;
+ this.l3Context = l3Context;
+ }
+
+ public L2FloodDomain getL2FloodDomain() {
+ return l2FloodDomain;
+ }
+
+ public L2BridgeDomain getL2BridgeDomain() {
+ return l2BridgeDomain;
+ }
+
+ public L3Context getL3Context() {
+ return l3Context;
+ }
+
+ }
+}
--- /dev/null
+package org.opendaylight.groupbasedpolicy.neutron.mapper.util;
+
+public final class NeutronUtils {
+
+ public static final String EGRESS = "egress";
+ public static final String INGRESS = "ingress";
+ public static final String IPv6 = "IPv6";
+ public static final String IPv4 = "IPv4";
+ public static final String NULL = "null";
+ public static final String UDP = "udp";
+ public static final String TCP = "tcp";
+ public static final String ICMP = "icmp";
+
+ private NeutronUtils() {
+ throw new UnsupportedOperationException("Cannot create an instance.");
+ }
+}
--- /dev/null
+/*
+ * 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
+ */
+package org.opendaylight.groupbasedpolicy.neutron.mapper.util;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+import org.apache.commons.net.util.SubnetUtils;
+import org.apache.commons.net.util.SubnetUtils.SubnetInfo;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Prefix;
+
+import com.google.common.base.Strings;
+import com.google.common.net.InetAddresses;
+
+/**
+ * @author Martin Sunal
+ */
+public class Utils {
+
+ private Utils() {}
+
+ /**
+ * This implementation does not use nameservice lookups (e.g. no DNS).
+ *
+ * @param cidr - format must be valid for regex in {@link Ipv4Prefix} or {@link Ipv6Prefix}
+ * @return the {@link IpPrefix} having the given cidr string representation
+ * @throws IllegalArgumentException - if the argument is not a valid CIDR string
+ */
+ public static IpPrefix createIpPrefix(String cidr) {
+ checkArgument(!Strings.isNullOrEmpty(cidr), "Cannot be null or empty.");
+ String[] ipAndPrefix = cidr.split("/");
+ checkArgument(ipAndPrefix.length == 2, "Bad format.");
+ InetAddress ip = InetAddresses.forString(ipAndPrefix[0]);
+ if (ip instanceof Inet4Address) {
+ return new IpPrefix(new Ipv4Prefix(cidr));
+ }
+ return new IpPrefix(new Ipv6Prefix(cidr));
+ }
+
+ /**
+ * This implementation does not use nameservice lookups (e.g. no DNS).
+ *
+ * @param ipAddress - format must be valid for regex in {@link Ipv4Address} or
+ * {@link Ipv6Address}
+ * @return the {@link IpAddress} having the given ipAddress string representation
+ * @throws IllegalArgumentException - if the argument is not a valid IP address string
+ */
+ public static IpAddress createIpAddress(String ipAddress) {
+ checkArgument(!Strings.isNullOrEmpty(ipAddress), "Cannot be null or empty.");
+ InetAddress ip = InetAddresses.forString(ipAddress);
+ if (ip instanceof Inet4Address) {
+ return new IpAddress(new Ipv4Address(ipAddress));
+ }
+ return new IpAddress(new Ipv6Address(ipAddress));
+ }
+
+ public static String getStringIpPrefix(IpPrefix ipPrefix) {
+ if (ipPrefix.getIpv4Prefix() != null) {
+ return ipPrefix.getIpv4Prefix().getValue();
+ }
+ return ipPrefix.getIpv6Prefix().getValue();
+ }
+
+ public static String getStringIpAddress(IpAddress ipAddress) {
+ if (ipAddress.getIpv4Address() != null) {
+ return ipAddress.getIpv4Address().getValue();
+ }
+ return ipAddress.getIpv6Address().getValue();
+ }
+
+ public static boolean isHostInIpPrefix(IpAddress host, IpPrefix ipPrefix) {
+ String ipAddress = "";
+ int ipVersion = 0;
+ if (host.getIpv4Address() != null) {
+ ipAddress = host.getIpv4Address().getValue();
+ ipVersion = 4;
+ } else {
+ ipAddress = host.getIpv6Address().getValue();
+ ipVersion = 6;
+ }
+ String cidr = getStringIpPrefix(ipPrefix);
+
+ if (ipVersion == 4) {
+ try {
+ SubnetUtils util = new SubnetUtils(cidr);
+ SubnetInfo info = util.getInfo();
+ return info.isInRange(ipAddress);
+ } catch (IllegalArgumentException e) {
+ return false;
+ }
+ }
+
+ if (ipVersion == 6) {
+ String[] parts = cidr.split("/");
+ try {
+ int length = Integer.parseInt(parts[1]);
+ byte[] cidrBytes = ((Inet6Address) InetAddress.getByName(parts[0])).getAddress();
+ byte[] ipBytes = ((Inet6Address) InetAddress.getByName(ipAddress)).getAddress();
+ int i;
+ for (i = 0; i < length; i++) { // offset is to ensure proper comparison
+ if ((((cidrBytes[i / 8]) & 0x000000FF) & (1 << (7 - (i % 8)))) != (((ipBytes[i / 8]) & 0x000000FF) & (1 << (7 - (i % 8))))) {
+ return false;
+ }
+ }
+ return true;
+ } catch (UnknownHostException e) {
+ return false;
+ }
+ }
+ return false;
+ }
+
+ public static String normalizeUuid(String string) {
+ return string.replaceFirst("([0-9a-fA-F]{8})([0-9a-fA-F]{4})([0-9a-fA-F]{4})([0-9a-fA-F]{4})([0-9a-fA-F]+)",
+ "$1-$2-$3-$4-$5");
+ }
+
+}
--- /dev/null
+module neutron-mapper {
+ yang-version 1;
+
+ namespace "urn:opendaylight:groupbasedpolicy:neutron-mapper";
+ prefix "gbp-neutron-mapper";
+
+ import gbp-common {prefix gbp-common;}
+ import endpoint {prefix gbp-endpoint;}
+ import ietf-inet-types {prefix inet;}
+
+ description
+ "This module defines the mapping model between Neutron IDs and GBP IDs.";
+
+ revision "2015-02-23" {
+ description
+ "Initial revision.";
+ }
+
+ grouping tenant-id-fields {
+ leaf tenant-id {
+ description "A unique ID for the tenant";
+ mandatory true;
+ type gbp-common:tenant-id;
+ }
+ }
+
+ grouping endpoint-group-pair-fields {
+ leaf provider-epg-id {
+ type gbp-common:endpoint-group-id;
+ }
+ leaf consumer-epg-id {
+ type gbp-common:endpoint-group-id;
+ }
+ leaf contract-id {
+ type gbp-common:contract-id;
+ }
+ }
+
+ container mappings {
+ config false;
+ container network-mappings {
+ list network-mapping {
+ key network-id;
+ leaf network-id {
+ description "A unique ID for the neutron network == gbp l2-flood-domain";
+ type gbp-common:unique-id;
+ }
+ leaf l2-bridge-domain-id {
+ description "A unique ID of l2-bridge-domain generated for neutron network";
+ type gbp-common:l2-bridge-domain-id;
+ }
+ leaf l3-context-id {
+ description "A unique ID of l3-context generated for neutron network";
+ type gbp-common:l3-context-id;
+ }
+ }
+ }
+ container endpoint-group-pair-to-contract-mappings {
+ list endpoint-group-pair-to-contract-mapping {
+ key "provider-epg-id consumer-epg-id";
+ uses endpoint-group-pair-fields;
+ }
+ }
+ }
+
+}
\ No newline at end of file
--- /dev/null
+module neutron-mapper-impl {
+
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:controller:config:neutron-mapper:impl";
+ prefix "neutron-mapper-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
+ neutron-mapper implementation.";
+
+ revision "2015-02-19" {
+ description
+ "Initial revision.";
+ }
+
+ // This is the definition of the service implementation as a module identity.
+ identity neutron-mapper-impl {
+ base config:module-type;
+
+ // Specifies the prefix for generated java classes.
+ config:java-name-prefix NeutronMapper;
+ }
+
+ // Augments the 'configuration' choice node under modules/module.
+ augment "/config:modules/config:module/config:configuration" {
+ case neutron-mapper-impl {
+ when "/config:modules/config:module/config:type = 'neutron-mapper-impl'";
+
+ container data-broker {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity mdsal:binding-async-data-broker;
+ }
+ }
+ }
+
+ container rpc-registry {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity mdsal:binding-rpc-registry;
+ }
+ }
+ }
+
+ }
+ }
+}
\ No newline at end of file
<module>groupbasedpolicy-ofoverlay-config</module>
<module>groupbasedpolicy-opflex-config</module>
<module>groupbasedpolicy-openstackendpoint-config</module>
+ <module>neutron-mapper</module>
+ <module>neutron-mapper-config</module>
<module>distribution-karaf</module>
<module>features</module>
</modules>
</scm>
</project>
-