ELAN integration to be done once ELAN is in.
VLAN transparency integration to be done iff trunkport extensions are in.
Change-Id: I6db2f9b654c3146f4514c994e4f8654b1a6c7d18
Signed-off-by: Abhinav Gupta <abhinav.gupta@ericsson.com>
<openflowplugin.version>0.2.0-SNAPSHOT</openflowplugin.version>
<vpns.ovsdb.version>1.2.1-SNAPSHOT</vpns.ovsdb.version>
<liblldp.version>0.10.0-SNAPSHOT</liblldp.version>
+ <karaf.shell.console.version>3.0.3</karaf.shell.console.version>
<neutron.version>0.6.0-SNAPSHOT</neutron.version>
</properties>
<lockmanager.version>${vpnservices.version}</lockmanager.version>
<idmanager.version>${vpnservices.version}</idmanager.version>
<itm.version>${vpnservices.version}</itm.version>
+ <neutronvpn.version>${vpnservices.version}</neutronvpn.version>
</properties>
<dependencyManagement>
<dependencies>
<artifactId>dhcpservice-api</artifactId>
<version>${vpnservices.version}</version>
</dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>neutronvpn-api</artifactId>
+ <version>${neutronvpn.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>neutronvpn-impl</artifactId>
+ <version>${neutronvpn.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>neutronvpn-impl</artifactId>
+ <version>${neutronvpn.version}</version>
+ <classifier>config</classifier>
+ <type>xml</type>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>neutronvpn-shell</artifactId>
+ <version>${neutronvpn.version}</version>
+ </dependency>
<dependency>
<groupId>org.apache.thrift</groupId>
<artifactId>libthrift</artifactId>
<bundle>mvn:org.opendaylight.vpnservice/vpnmanager-api/${vpnmanager.version}</bundle>
<bundle>mvn:org.opendaylight.vpnservice/fibmanager-api/${fibmanager.version}</bundle>
<bundle>mvn:org.opendaylight.vpnservice/itm-api/${itm.version}</bundle>
+ <bundle>mvn:org.opendaylight.vpnservice/neutronvpn-api/${neutronvpn.version}</bundle>
<bundle>mvn:org.opendaylight.vpnservice/dhcpservice-api/${vpnservices.version}</bundle>
</feature>
<feature name='odl-vpnservice-impl' version='${project.version}' description='OpenDaylight :: vpnservice :: impl '>
<bundle>mvn:org.opendaylight.vpnservice/vpnmanager-impl/${vpnmanager.version}</bundle>
<bundle>mvn:org.opendaylight.vpnservice/fibmanager-impl/${fibmanager.version}</bundle>
<bundle>mvn:org.opendaylight.vpnservice/itm-impl/${itm.version}</bundle>
+ <bundle>mvn:org.opendaylight.vpnservice/neutronvpn-impl/${neutronvpn.version}</bundle>
+ <bundle>mvn:org.opendaylight.vpnservice/neutronvpn-shell/${neutronvpn.version}</bundle>
<bundle>mvn:org.opendaylight.vpnservice/dhcpservice-impl/${vpnservices.version}</bundle>
<!--<bundle>mvn:org.opendaylight.vpnservice.third-party/org.apache.thriftlib/1.0.1-SNAPSHOT</bundle>-->
<configfile finalname="vpnmanager-impl-default-config.xml">mvn:org.opendaylight.vpnservice/vpnmanager-impl/${vpnmanager.version}/xml/config</configfile>
<configfile finalname="fibmanager-impl-default-config.xml">mvn:org.opendaylight.vpnservice/fibmanager-impl/${fibmanager.version}/xml/config</configfile>
<configfile finalname="itm-impl-default-config.xml">mvn:org.opendaylight.vpnservice/itm-impl/${itm.version}/xml/config</configfile>
+ <configfile finalname="neutronvpn-impl-default-config.xml">mvn:org.opendaylight.vpnservice/neutronvpn-impl/${neutronvpn.version}/xml/config</configfile>
<configfile finalname="dhcpservice-impl-default-config.xml">mvn:org.opendaylight.vpnservice/dhcpservice-impl/${vpnservices.version}/xml/config</configfile>
</feature>
<feature name='odl-vpnservice-impl-rest' version='${project.version}' description='OpenDaylight :: vpnservice :: impl :: REST '>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2015 - 2016 Ericsson India Global Services Pvt Ltd. 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">
+ <parent>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>config-parent</artifactId>
+ <version>0.2.0-SNAPSHOT</version>
+ <relativePath>../../commons/config-parent</relativePath>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>neutronvpn-api</artifactId>
+ <version>${vpnservices.version}</version>
+ <packaging>bundle</packaging>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.mdsal</groupId>
+ <artifactId>yang-binding</artifactId>
+ <version>${yangtools.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-common</artifactId>
+ <version>${yangtools.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.neutron</groupId>
+ <artifactId>model</artifactId>
+ <version>${neutron.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.mdsal.model</groupId>
+ <artifactId>ietf-yang-types</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>mdsalutil-api</artifactId>
+ <version>${vpns.mdsalutil.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-api</artifactId>
+ </dependency>
+ </dependencies>
+</project>
--- /dev/null
+/*
+ * Copyright (c) 2015 - 2016 Ericsson India Global Services Pvt Ltd. 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.vpnservice.neutronvpn.interfaces;
+
+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.rev130715.Uuid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
+
+import java.util.List;
+
+public interface INeutronVpnManager {
+
+ public void addSubnetToVpn(Uuid vpnId, Uuid subnet);
+
+ public void removeSubnetFromVpn(Uuid vpnId, Uuid subnet);
+
+ public List<Uuid> getSubnetsforVpn(Uuid vpnid);
+
+ List<String> showVpnConfigCLI(Uuid vuuid);
+
+ List<String> showNeutronPortsCLI();
+
+ public Port getNeutronPort(String name);
+
+ public Subnet getNeutronSubnet(Uuid subnetId);
+
+ public String uuidToTapPortName(Uuid id);
+
+ public Port getNeutronPort(Uuid portId);
+
+ public IpAddress getNeutronSubnetGateway(Uuid subnetId);
+
+}
--- /dev/null
+module neutronvpn-api {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:neutronvpn:api";
+ prefix "neutronvpn-api";
+
+ import config { prefix config; revision-date 2013-04-05; }
+
+ description
+ "Service definition for neutronvpn project";
+
+ revision "2015-08-12" {
+ description
+ "Initial revision";
+ }
+
+ identity neutronvpn-api {
+ base "config:service-type";
+ config:java-class "org.opendaylight.vpnservice.neutronvpn.interfaces.INeutronVpnManager";
+ }
+}
--- /dev/null
+
+module neutronvpn {
+
+ namespace "urn:opendaylight:vpnservice:neutronvpn";
+ prefix neutronvpn;
+
+ import ietf-yang-types { prefix "yang"; }
+
+ revision "2015-06-02" {
+ description "Neutron based L3Service Module, provides integration of ODL VPN service with Neutron NSF";
+ }
+
+ container subnetmaps{
+ list subnetmap {
+ key id;
+ leaf id {
+ type yang:uuid;
+ description "UUID representing the subnet ";
+ }
+
+ leaf tenant-id {
+ type yang:uuid;
+ description "The UUID of the tenant that will own the subnet.";
+ }
+
+ leaf network-id {
+ type yang:uuid;
+ description "UUID representing the network ";
+ }
+
+ leaf router-id {
+ type yang:uuid;
+ description "router to which this subnet belongs";
+ }
+
+ leaf vpn-id {
+ type yang:uuid;
+ description "VPN to which this subnet belongs";
+ }
+
+ leaf-list port-list {
+ type yang:uuid;
+ }
+ }
+ }
+
+ container networkMaps{
+ list networkMap {
+ key network-id;
+
+ leaf network-id {
+ type yang:uuid;
+ description "UUID representing the network";
+ }
+
+ leaf-list subnet-id-list {
+ type yang:uuid;
+ description "List of UUIDs representing the subnets associated to the network";
+ }
+ }
+ }
+
+ grouping l3vpn-instance{
+
+ leaf id {
+ mandatory "true";
+ type yang:uuid;
+ description "vpn-id";
+ }
+
+ leaf name {
+ type string;
+ description "VPN name";
+ }
+
+ leaf tenant-id {
+ type yang:uuid;
+ description "The UUID of the tenant that will own the subnet.";
+ }
+
+ leaf-list route-distinguisher {
+ type string;
+ description
+ "configures a route distinguisher (RD) for the VPN instance.
+ Format is ASN:nn or IP-address:nn.";
+ }
+
+ leaf-list import-RT {
+ type string;
+ description
+ "configures a list of import route target.
+ Format is ASN:nn or IP-address:nn.";
+ }
+
+ leaf-list export-RT{
+ type string;
+ description
+ "configures a list of export route targets.
+ Format is ASN:nn or IP-address:nn.";
+ }
+
+ leaf router-id {
+ type yang:uuid;
+ description "UUID of router ";
+ }
+
+ leaf-list network-ids {
+ type yang:uuid;
+ description "UUID representing the network ";
+ }
+ }
+
+ container vpnMaps {
+ list vpnMap {
+ key vpn-id;
+ leaf vpn-id {
+ type yang:uuid;
+ description "vpn-id";
+ }
+ leaf name {
+ type string;
+ description "vpn name";
+ }
+ leaf tenant-id {
+ type yang:uuid;
+ description "The UUID of the tenant that will own the subnet.";
+ }
+
+ leaf router-id {
+ type yang:uuid;
+ description "UUID of router ";
+ }
+ leaf-list network_ids {
+ type yang:uuid;
+ description "UUID representing the network ";
+ }
+ }
+ }
+
+ /* Data models to adhere to restart requirements */
+ container neutron-port-data {
+ list port-name-to-port-uuid {
+ key port-name;
+ leaf port-id { type yang:uuid;}
+ leaf port-name { type string;}
+ }
+ list port-fixedip-to-port-name {
+ key port-fixedip;
+ leaf port-name { type string;}
+ leaf port-fixedip { type string;}
+ }
+ }
+
+ rpc createL3VPN{
+ description "Create one or more L3 VPN";
+ input {
+ list l3vpn {
+ uses l3vpn-instance;
+ }
+ }
+ output {
+ leaf-list response {
+ type string;
+ description "Status response for createVPN RPC";
+ }
+ }
+ }
+
+ rpc associateRouter {
+ description "associates a router with L3VPN";
+ input {
+ leaf vpn-id {
+ type yang:uuid;
+ mandatory "true";
+ description "vpn-id";
+ }
+ leaf router-id {
+ type yang:uuid;
+ mandatory "true";
+ description "vpn-id";
+ }
+ }
+ }
+
+ rpc dissociateRouter {
+ description "dissociates a router with L3VPN";
+ input {
+ leaf vpn-id {
+ type yang:uuid;
+ mandatory "true";
+ description "vpn-id";
+ }
+ leaf router-id {
+ type yang:uuid;
+ mandatory "true";
+ description "router-id";
+ }
+ }
+ }
+
+ rpc associateNetworks {
+ description "associates a list of networks with L3VPN";
+ input {
+ leaf vpn-id {
+ type yang:uuid;
+ mandatory "true";
+ description "vpn-id";
+ }
+ leaf-list network-id {
+ type yang:uuid;
+ description "network-id";
+ }
+ }
+ output {
+ leaf response {
+ type string;
+ description "Status response for associateNetworks RPC";
+ }
+ }
+ }
+
+ rpc dissociateNetworks{
+ description "dissociates a list of networks with L3VPN";
+ input {
+ leaf vpn-id {
+ type yang:uuid;
+ mandatory "true";
+ description "vpn-id";
+ }
+ leaf-list network-id {
+ type yang:uuid;
+ description "network-id";
+ }
+ }
+ output {
+ leaf response {
+ type string;
+ description "Status response for dissociateNetworks RPC";
+ }
+ }
+ }
+
+ rpc deleteL3VPN{
+ description "delete VPNs for specified Id list";
+ input {
+ leaf-list id {
+ type yang:uuid;
+ description "vpn-id";
+ }
+ }
+ output {
+ leaf-list response {
+ type string;
+ description "Status response for deleteL3VPN RPC";
+ }
+ }
+ }
+
+ rpc getL3VPN{
+ description "returns VPN configuration";
+ input {
+ leaf id {
+ type yang:uuid;
+ description "vpn-id";
+ }
+ }
+ output {
+ list l3vpn-instances {
+ uses l3vpn-instance;
+ }
+ }
+ }
+
+}
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: --><!--
+Copyright (c) 2015 - 2016 Ericsson India Global Services Pvt Ltd. 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">
+
+ <parent>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>config-parent</artifactId>
+ <version>0.2.0-SNAPSHOT</version>
+ <relativePath>../../commons/config-parent</relativePath>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>neutronvpn-impl</artifactId>
+ <version>${vpnservices.version}</version>
+ <packaging>bundle</packaging>
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.neutron</groupId>
+ <artifactId>model</artifactId>
+ <version>${neutron.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>neutronvpn-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>vpnmanager-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>mdsalutil-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>lockmanager-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ </dependencies>
+
+</project>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. 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>
+ <required-capabilities>
+ <capability>urn:opendaylight:params:xml:ns:yang:neutronvpn:impl?module=neutronvpn-impl&revision=2015-03-25</capability>
+ <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding?module=opendaylight-md-sal-binding&revision=2013-10-28</capability>
+ <capability>urn:opendaylight:params:xml:ns:yang:mdsalutil:api?module=odl-mdsalutil&revision=2015-04-10</capability>
+ </required-capabilities>
+ <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:prefix="urn:opendaylight:params:xml:ns:yang:neutronvpn:impl">prefix:neutronvpn-impl
+ </type>
+ <name>neutronvpn-default</name>
+ <broker>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">
+ binding:binding-broker-osgi-registry
+ </type>
+ <name>binding-osgi-broker</name>
+ </broker>
+ <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>
+ <mdsalutil>
+ <type xmlns:mdsalutil="urn:opendaylight:params:xml:ns:yang:mdsalutil:api">
+ mdsalutil:odl-mdsalutil
+ </type>
+ <name>mdsalutil-service</name>
+ </mdsalutil>
+ </module>
+ </modules>
+ <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+ <service>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:neutronvpn:api">prefix:neutronvpn-api</type>
+ <instance>
+ <name>neutronvpn</name>
+ <provider>/modules/module[type='neutronvpn-impl'][name='neutronvpn-default']</provider>
+ </instance>
+ </service>
+ </services>
+ </data>
+ </configuration>
+</snapshot>
--- /dev/null
+/*
+ * Copyright (c) 2015 - 2016 Ericsson India Global Services Pvt Ltd. 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.vpnservice.neutronvpn;
+
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.mdsalutil.AbstractDataChangeListener;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.bgpvpns.rev150903.bgpvpns.attributes.Bgpvpns;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.bgpvpns.rev150903.bgpvpns.attributes.bgpvpns.Bgpvpn;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+
+public class NeutronBgpvpnChangeListener extends AbstractDataChangeListener<Bgpvpn> implements AutoCloseable {
+ private static final Logger LOG = LoggerFactory.getLogger(NeutronBgpvpnChangeListener.class);
+
+ private ListenerRegistration<DataChangeListener> listenerRegistration;
+ private NeutronvpnManager nvpnManager;
+
+
+ public NeutronBgpvpnChangeListener(final DataBroker db, NeutronvpnManager nVpnMgr) {
+ super(Bgpvpn.class);
+ nvpnManager = nVpnMgr;
+ registerListener(db);
+ }
+
+ @Override
+ public void close() throws Exception {
+ if (listenerRegistration != null) {
+ try {
+ listenerRegistration.close();
+ } catch (final Exception e) {
+ LOG.error("Error when cleaning up DataChangeListener.", e);
+ }
+ listenerRegistration = null;
+ }
+ LOG.info("N_Bgpvpn listener Closed");
+ }
+
+
+ private void registerListener(final DataBroker db) {
+ try {
+ listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
+ InstanceIdentifier.create(Neutron.class).child(Bgpvpns.class).child(Bgpvpn.class),
+ NeutronBgpvpnChangeListener.this, DataChangeScope.SUBTREE);
+ } catch (final Exception e) {
+ LOG.error("Neutron Manager Bgpvpn DataChange listener registration fail!", e);
+ throw new IllegalStateException("Neutron Manager Bgpvpn DataChange listener registration failed.", e);
+ }
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<Bgpvpn> identifier, Bgpvpn input) {
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Adding Bgpvpn : key: " + identifier + ", value=" + input);
+ }
+ // Create internal VPN
+ // handle route-target
+ List<String> irt = new ArrayList<String>();
+ List<String> ert = new ArrayList<String>();
+ List<String> inrt = input.getRouteTargets();
+ List<String> inirt = input.getImportTargets();
+ List<String> inert = input.getExportTargets();
+ if (inrt != null && !inrt.isEmpty()) {
+ irt.addAll(inrt);
+ ert.addAll(inrt);
+ }
+ if (inirt != null && !inirt.isEmpty()) {
+ irt.addAll(inirt);
+ }
+ if (inert != null && !inert.isEmpty()) {
+ ert.addAll(inert);
+ }
+ List<String> rd = input.getRouteDistinguishers();
+
+ if (rd == null || rd.isEmpty()) {
+ // generate new RD
+ }
+ Uuid router = null;
+ if (input.getRouters() != null) {
+ // currently only one router
+ router = input.getRouters().get(0);
+ }
+ nvpnManager.createL3Vpn(input.getUuid(), input.getName(), input.getTenantId(),
+ rd, irt, ert, router, input.getNetworks());
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<Bgpvpn> identifier, Bgpvpn input) {
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Removing Bgpvpn : key: " + identifier + ", value=" + input);
+ }
+ nvpnManager.removeL3Vpn(input.getUuid());
+
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<Bgpvpn> identifier, Bgpvpn original, Bgpvpn update) {
+ List<Uuid> oldNetworks = original.getNetworks();
+ List<Uuid> newNetworks = update.getNetworks();
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Update Bgpvpn : key: " + identifier + ", value=" + update);
+ }
+ if (newNetworks != null && !newNetworks.isEmpty()) {
+ if (oldNetworks != null && !oldNetworks.isEmpty()) {
+ if (oldNetworks != newNetworks) {
+ Iterator<Uuid> iter = newNetworks.iterator();
+ while (iter.hasNext()) {
+ Object net = iter.next();
+ if (oldNetworks.contains(net)) {
+ oldNetworks.remove(net);
+ iter.remove();
+ }
+ }
+ //clear removed networks
+ if (!oldNetworks.isEmpty()) {
+ LOG.trace("Removing old networks {} ", oldNetworks);
+ nvpnManager.dissociateNetworksFromVpn(update.getUuid(), oldNetworks);
+ }
+ //add new (Delta) Networks
+ if (!newNetworks.isEmpty()) {
+ LOG.trace("Adding delta New networks {} ", newNetworks);
+ nvpnManager.associateNetworksToVpn(update.getUuid(), newNetworks);
+ }
+ }
+ } else {
+ //add new Networks
+ LOG.trace("Adding New networks {} ", newNetworks);
+ nvpnManager.associateNetworksToVpn(update.getUuid(), newNetworks);
+ }
+ }
+ // ### TBD : Handle routers
+ }
+
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2015 - 2016 Ericsson India Global Services Pvt Ltd. 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.vpnservice.neutronvpn;
+
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.mdsalutil.AbstractDataChangeListener;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.Networks;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+public class NeutronNetworkChangeListener extends AbstractDataChangeListener<Network> implements AutoCloseable {
+ private static final Logger LOG = LoggerFactory.getLogger(NeutronNetworkChangeListener.class);
+
+ private ListenerRegistration<DataChangeListener> listenerRegistration;
+ private final DataBroker broker;
+ private NeutronvpnManager nvpnManager;
+
+
+ public NeutronNetworkChangeListener(final DataBroker db, NeutronvpnManager nVpnMgr) {
+ super(Network.class);
+ broker = db;
+ nvpnManager = nVpnMgr;
+ registerListener(db);
+ }
+
+ @Override
+ public void close() throws Exception {
+ if (listenerRegistration != null) {
+ try {
+ listenerRegistration.close();
+ } catch (final Exception e) {
+ LOG.error("Error when cleaning up DataChangeListener.", e);
+ }
+ listenerRegistration = null;
+ }
+ LOG.info("N_Network listener Closed");
+ }
+
+
+ private void registerListener(final DataBroker db) {
+ try {
+ listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
+ InstanceIdentifier.create(Neutron.class).
+ child(Networks.class).child(Network.class),
+ NeutronNetworkChangeListener.this, DataChangeScope.SUBTREE);
+ LOG.info("Neutron Manager Network DataChange listener registration Success!");
+ } catch (final Exception e) {
+ LOG.error("Neutron Manager Network DataChange listener registration fail!", e);
+ throw new IllegalStateException("Neutron Manager Network DataChange listener registration failed.", e);
+ }
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<Network> identifier, Network input) {
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Adding Network : key: " + identifier + ", value=" + input);
+ }
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<Network> identifier, Network input) {
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Removing Network : key: " + identifier + ", value=" + input);
+ }
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<Network> identifier, Network original, Network update) {
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Updating Network : key: " + identifier + ", original value=" + original + ", update value=" +
+ update);
+ }
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 - 2016 Ericsson India Global Services Pvt Ltd. 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.vpnservice.neutronvpn;
+
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.mdsalutil.AbstractDataChangeListener;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+
+public class NeutronPortChangeListener extends AbstractDataChangeListener<Port> implements AutoCloseable {
+ private static final Logger LOG = LoggerFactory.getLogger(NeutronPortChangeListener.class);
+
+ private ListenerRegistration<DataChangeListener> listenerRegistration;
+ private final DataBroker broker;
+ private NeutronvpnManager nvpnManager;
+
+
+ public NeutronPortChangeListener(final DataBroker db, NeutronvpnManager nVpnMgr) {
+ super(Port.class);
+ broker = db;
+ nvpnManager = nVpnMgr;
+ registerListener(db);
+ }
+
+ @Override
+ public void close() throws Exception {
+ if (listenerRegistration != null) {
+ try {
+ listenerRegistration.close();
+ } catch (final Exception e) {
+ LOG.error("Error when cleaning up DataChangeListener.", e);
+ }
+ listenerRegistration = null;
+ }
+ LOG.info("N_Port listener Closed");
+ }
+
+
+ private void registerListener(final DataBroker db) {
+ try {
+ listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
+ InstanceIdentifier.create(Neutron.class).child(Ports.class).child(Port.class),
+ NeutronPortChangeListener.this, DataChangeScope.SUBTREE);
+ } catch (final Exception e) {
+ LOG.error("Neutron Manager Port DataChange listener registration fail!", e);
+ throw new IllegalStateException("Neutron Manager Port DataChange listener registration failed.", e);
+ }
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<Port> identifier, Port input) {
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Adding Port : key: " + identifier + ", value=" + input);
+ }
+ nvpnManager.handleNeutronPortCreated(input);
+
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<Port> identifier, Port input) {
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Removing Port : key: " + identifier + ", value=" + input);
+ }
+ nvpnManager.handleNeutronPortDeleted(input);
+
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<Port> identifier, Port original, Port update) {
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Updating Port : key: " + identifier + ", original value=" + original + ", update value=" +
+ update);
+ }
+ List<FixedIps> oldIPs = (original.getFixedIps() != null) ? original.getFixedIps() : new ArrayList<FixedIps>();
+ List<FixedIps> newIPs = (update.getFixedIps() != null) ? update.getFixedIps() : new ArrayList<FixedIps>();
+
+ if (!oldIPs.equals(newIPs)) {
+ Iterator<FixedIps> iterator = newIPs.iterator();
+ while (iterator.hasNext()) {
+ FixedIps ip = iterator.next();
+ if (oldIPs.remove(ip)) {
+ iterator.remove();
+ }
+ }
+ nvpnManager.handleNeutronPortUpdated(original, update);
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 - 2016 Ericsson India Global Services Pvt Ltd. 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.vpnservice.neutronvpn;
+
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.mdsalutil.AbstractDataChangeListener;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.Routers;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.Router;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.router.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.vpnmaps.VpnMap;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+
+public class NeutronRouterChangeListener extends AbstractDataChangeListener<Router> implements AutoCloseable {
+ private static final Logger LOG = LoggerFactory.getLogger(NeutronRouterChangeListener.class);
+
+ private ListenerRegistration<DataChangeListener> listenerRegistration;
+ private final DataBroker broker;
+ private NeutronvpnManager nvpnManager;
+
+
+ public NeutronRouterChangeListener(final DataBroker db, NeutronvpnManager nVpnMgr) {
+ super(Router.class);
+ broker = db;
+ nvpnManager = nVpnMgr;
+ registerListener(db);
+ }
+
+ @Override
+ public void close() throws Exception {
+ if (listenerRegistration != null) {
+ try {
+ listenerRegistration.close();
+ } catch (final Exception e) {
+ LOG.error("Error when cleaning up DataChangeListener.", e);
+ }
+ listenerRegistration = null;
+ }
+ LOG.info("N_Router listener Closed");
+ }
+
+
+ private void registerListener(final DataBroker db) {
+ try {
+ listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
+ InstanceIdentifier.create(Neutron.class).child(Routers.class).child(Router.class),
+ NeutronRouterChangeListener.this, DataChangeScope.SUBTREE);
+ } catch (final Exception e) {
+ LOG.error("Neutron Manager Router DataChange listener registration fail!", e);
+ throw new IllegalStateException("Neutron Manager Router DataChange listener registration failed.", e);
+ }
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<Router> identifier, Router input) {
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Adding Router : key: " + identifier + ", value=" + input);
+ }
+ // Create internal VPN
+ nvpnManager.createL3Vpn(input.getUuid(), null, null, null, null, null, input.getUuid(), null);
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<Router> identifier, Router input) {
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Removing router : key: " + identifier + ", value=" + input);
+ }
+ // check if this router has internal-VPN
+ Uuid routerId = input.getUuid();
+ VpnMap vpnmap = NeutronvpnUtils.getVpnMap(broker, routerId);
+ if (vpnmap != null) {
+ // if yes, remove corresponding internal vpn
+ LOG.trace("removing internal-vpn for router {}", routerId);
+ nvpnManager.removeL3Vpn(routerId);
+ } else {
+ // if not, it is associated with some VPN
+ // remove VPN-router association
+ Uuid vpnId = NeutronvpnUtils.getVpnForRouter(broker, routerId);
+ LOG.trace("dissociating router {} from vpn {}", routerId, vpnId);
+ nvpnManager.dissociateRouterFromVpn(vpnId, routerId);
+ }
+
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<Router> identifier, Router original, Router update) {
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Updating Router : key: " + identifier + ", original value=" + original + ", update value=" +
+ update);
+ }
+ Uuid routerId = update.getUuid();
+ Uuid vpnId = NeutronvpnUtils.getVpnForRouter(broker, routerId);
+ List<Interfaces> oldInterfaces = (original.getInterfaces() != null) ? original.getInterfaces() : new
+ ArrayList<Interfaces>();
+ List<Interfaces> newInterfaces = (update.getInterfaces() != null) ? update.getInterfaces() : new
+ ArrayList<Interfaces>();
+ List<String> oldRoutes = (original.getRoutes() != null) ? original.getRoutes() : new ArrayList<String>();
+ List<String> newRoutes = (update.getRoutes() != null) ? update.getRoutes() : new ArrayList<String>();
+
+ if (!oldInterfaces.equals(newInterfaces)) {
+ for (Interfaces intrf : newInterfaces) {
+ if (!oldInterfaces.remove(intrf)) {
+ // add new subnet
+ nvpnManager.addSubnetToVpn(vpnId, intrf.getSubnetId());
+ }
+ }
+ //clear remaining old subnets
+ for (Interfaces intrf : oldInterfaces) {
+ nvpnManager.removeSubnetFromVpn(vpnId, intrf.getSubnetId());
+ }
+ }
+ if (!oldRoutes.equals(newRoutes)) {
+ Iterator<String> iterator = newRoutes.iterator();
+ while (iterator.hasNext()) {
+ String route = iterator.next();
+ if (oldRoutes.remove(route)) {
+ iterator.remove();
+ }
+ }
+ nvpnManager.addAdjacencyforExtraRoute(newRoutes, true, null);
+ if (!oldRoutes.isEmpty()) {
+ nvpnManager.removeAdjacencyforExtraRoute(oldRoutes);
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 - 2016 Ericsson India Global Services Pvt Ltd. 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.vpnservice.neutronvpn;
+
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.mdsalutil.AbstractDataChangeListener;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.Subnets;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+public class NeutronSubnetChangeListener extends AbstractDataChangeListener<Subnet> implements AutoCloseable {
+ private static final Logger LOG = LoggerFactory.getLogger(NeutronSubnetChangeListener.class);
+
+ private ListenerRegistration<DataChangeListener> listenerRegistration;
+ private final DataBroker broker;
+ private NeutronvpnManager nvpnManager;
+
+
+ public NeutronSubnetChangeListener(final DataBroker db, NeutronvpnManager nVpnMgr) {
+ super(Subnet.class);
+ broker = db;
+ nvpnManager = nVpnMgr;
+ registerListener(db);
+ }
+
+ @Override
+ public void close() throws Exception {
+ if (listenerRegistration != null) {
+ try {
+ listenerRegistration.close();
+ } catch (final Exception e) {
+ LOG.error("Error when cleaning up DataChangeListener.", e);
+ }
+ listenerRegistration = null;
+ }
+ LOG.info("N_Subnet listener Closed");
+ }
+
+
+ private void registerListener(final DataBroker db) {
+ try {
+ listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
+ InstanceIdentifier.create(Neutron.class).child(Subnets.class).child(Subnet.class),
+ NeutronSubnetChangeListener.this, DataChangeScope.SUBTREE);
+ } catch (final Exception e) {
+ LOG.error("Neutron Manager Subnet DataChange listener registration fail!", e);
+ throw new IllegalStateException("Neutron Manager Subnet DataChange listener registration failed.", e);
+ }
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<Subnet> identifier, Subnet input) {
+ LOG.trace("Adding Subnet : key: " + identifier + ", value=" + input);
+ nvpnManager.updateSubnetNode(input.getUuid(), input.getTenantId(), input.getNetworkId(), null, null, null);
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<Subnet> identifier, Subnet input) {
+ LOG.trace("Removing subnet : key: " + identifier + ", value=" + input);
+ Uuid vpnId = NeutronvpnUtils.getVpnForNetwork(broker, input.getNetworkId());
+ if (vpnId != null) {
+ nvpnManager.removeSubnetFromVpn(vpnId, input.getUuid());
+ }
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<Subnet> identifier, Subnet original, Subnet update) {
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Updating Subnet : key: " + identifier + ", original value=" + original + ", update value=" +
+ update);
+ }
+ nvpnManager.updateSubnetNode(update.getUuid(), update.getTenantId(), update.getNetworkId(), null, null, null);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 - 2016 Ericsson India Global Services Pvt Ltd. 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.vpnservice.neutronvpn;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.SettableFuture;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.VpnTargets;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.VpnTargetsBuilder;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTarget;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets
+ .VpnTargetBuilder;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTargetKey;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceBuilder;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceKey;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.vpn.instance
+ .Ipv4FamilyBuilder;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceBuilder;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.L2vlan;
+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.interfaces.rev140508.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.Adjacencies;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.AdjacenciesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.adjacency.list.Adjacency;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.adjacency.list.AdjacencyBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.adjacency.list.AdjacencyKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.Router;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.PortKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.Subnets;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.SubnetKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.LockManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.AssociateNetworksInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.AssociateNetworksOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.AssociateNetworksOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.AssociateRouterInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.CreateL3VPNInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.CreateL3VPNOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.CreateL3VPNOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.DeleteL3VPNInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.DeleteL3VPNOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.DeleteL3VPNOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.DissociateNetworksInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.DissociateNetworksOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.DissociateNetworksOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.DissociateRouterInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.GetL3VPNInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.GetL3VPNInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.GetL3VPNOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.GetL3VPNOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.L3vpnInstance;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.NeutronvpnService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.Subnetmaps;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.SubnetmapsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.VpnMaps;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.VpnMapsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.createl3vpn.input.L3vpn;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.getl3vpn.output.L3vpnInstances;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.getl3vpn.output
+ .L3vpnInstancesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.neutron.port.data
+ .PortFixedipToPortNameBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.neutron.port.data
+ .PortNameToPortUuidBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.subnetmaps.Subnetmap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.subnetmaps.SubnetmapBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.subnetmaps.SubnetmapKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.vpnmaps.VpnMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.vpnmaps.VpnMapBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.vpnmaps.VpnMapKey;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+public class NeutronvpnManager implements NeutronvpnService, AutoCloseable {
+
+ private static final Logger logger = LoggerFactory.getLogger(NeutronvpnManager.class);
+ private final DataBroker broker;
+ private LockManagerService lockManager;
+ IMdsalApiManager mdsalUtil;
+
+ /**
+ * @param db - dataBroker reference
+ * @param mdsalManager - MDSAL Util API access
+ */
+ public NeutronvpnManager(final DataBroker db, IMdsalApiManager mdsalManager) {
+ broker = db;
+ mdsalUtil = mdsalManager;
+ }
+
+ public void setLockManager(LockManagerService lockManager) {
+ this.lockManager = lockManager;
+ }
+
+ @Override
+ public void close() throws Exception {
+ logger.info("Neutron VPN Manager Closed");
+ }
+
+ protected Subnetmap updateSubnetNode(Uuid subnetId, Uuid tenantId, Uuid networkId, Uuid routerId, Uuid vpnId,
+ Uuid portId) {
+
+ try {
+ SubnetmapBuilder builder = null;
+
+ InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).
+ child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
+ Optional<Subnetmap> sn = read(LogicalDatastoreType.CONFIGURATION, id);
+ logger.debug("updating Subnet :read: ");
+ if (sn.isPresent()) {
+ builder = new SubnetmapBuilder(sn.get());
+ logger.debug("updating Subnet :existing: ");
+ } else {
+ builder = new SubnetmapBuilder().setKey(new SubnetmapKey(subnetId)).setId(subnetId);
+ logger.debug("updating Subnet :new: ");
+ }
+
+ if (routerId != null) {
+ builder.setRouterId(routerId);
+ }
+ if (networkId != null) {
+ builder.setNetworkId(networkId);
+ }
+ if (vpnId != null) {
+ builder.setVpnId(vpnId);
+ }
+ if (tenantId != null) {
+ builder.setTenantId(tenantId);
+ }
+
+ if (portId != null) {
+ List<Uuid> portList = builder.getPortList();
+ if (portList == null) {
+ portList = new ArrayList<Uuid>();
+ }
+ portList.add(portId);
+ builder.setPortList(portList);
+ }
+
+ Subnetmap subnetmap = builder.build();
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
+ logger.debug("Created/Updated subnetmap node: {} ", subnetId.getValue());
+
+ return subnetmap;
+ } catch (Exception e) {
+ logger.error("Update local subnetmap failed for node: {} {} {} {} {} {} ",
+ subnetId.getValue(), tenantId.getValue(), networkId.getValue(), routerId.getValue(), vpnId
+ .getValue(), portId.getValue());
+ throw new RuntimeException(e);
+ }
+
+ }
+
+ protected Subnetmap removeFromSubnetNode(Uuid subnetId, Uuid networkId, Uuid routerId, Uuid vpnId, Uuid portId) {
+ Subnetmap subnetmap = null;
+ try {
+ InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).
+ child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
+ Optional<Subnetmap> sn = read(LogicalDatastoreType.CONFIGURATION, id);
+
+ if (sn.isPresent()) {
+ SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
+
+ if (routerId != null) {
+ builder.setRouterId(null);
+ }
+ if (networkId != null) {
+ builder.setNetworkId(null);
+ }
+ if (vpnId != null) {
+ builder.setVpnId(null);
+ }
+ if (portId != null && builder.getPortList() != null) {
+ List<Uuid> portList = builder.getPortList();
+ portList.remove(portId);
+ builder.setPortList(portList);
+ }
+
+ subnetmap = builder.build();
+ logger.debug("Removing from existing subnetmap node: {} ", subnetId.getValue());
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
+ } else {
+ logger.warn("remove from non-existing subnetmap node: {} ", subnetId.getValue());
+ }
+ } catch (Exception e) {
+ logger.error("Remove from subnetmap failed for node: {} {} {} {} {} {} ", subnetId.getValue(), networkId
+ .getValue(), routerId.getValue(), vpnId.getValue(), portId.getValue());
+ throw new RuntimeException(e);
+ }
+
+ return subnetmap;
+ }
+
+ private void updateVpnInstanceNode(String name, List<String> rd, List<String> irt, List<String> ert) {
+
+ try {
+ VpnInstanceBuilder builder = null;
+ List<VpnTarget> vpnTargetList = new ArrayList<VpnTarget>();
+ InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class).
+ child(VpnInstance.class, new VpnInstanceKey(name)).build();
+ Optional<VpnInstance> optionalVpn = read(LogicalDatastoreType.CONFIGURATION, vpnIdentifier);
+ logger.debug("Creating/Updating a new vpn-instance node: {} ", name);
+ if (optionalVpn.isPresent()) {
+ builder = new VpnInstanceBuilder(optionalVpn.get());
+ logger.debug("updating existing vpninstance node");
+ } else {
+ builder = new VpnInstanceBuilder().setKey(new VpnInstanceKey(name)).setVpnInstanceName(name);
+ }
+
+ if (irt != null && !irt.isEmpty()) {
+ if (ert != null && !ert.isEmpty()) {
+ List<String> commonRT = new ArrayList<String>(irt);
+ commonRT.retainAll(ert);
+
+ for (String common : commonRT) {
+ irt.remove(common);
+ ert.remove(common);
+ VpnTarget vpnTarget = new VpnTargetBuilder().setKey(new VpnTargetKey(common)).setVrfRTValue
+ (common).setVrfRTType(VpnTarget.VrfRTType.Both).build();
+ vpnTargetList.add(vpnTarget);
+ }
+ }
+ for (String importRT : irt) {
+ VpnTarget vpnTarget = new VpnTargetBuilder().setKey(new VpnTargetKey(importRT)).setVrfRTValue
+ (importRT).setVrfRTType(VpnTarget.VrfRTType.ImportExtcommunity).build();
+ vpnTargetList.add(vpnTarget);
+ }
+ }
+
+ if (ert != null && !ert.isEmpty()) {
+ for (String exportRT : ert) {
+ VpnTarget vpnTarget = new VpnTargetBuilder().setKey(new VpnTargetKey(exportRT)).setVrfRTValue
+ (exportRT).setVrfRTType(VpnTarget.VrfRTType.ExportExtcommunity).build();
+ vpnTargetList.add(vpnTarget);
+ }
+ }
+
+ VpnTargets vpnTargets = new VpnTargetsBuilder().setVpnTarget(vpnTargetList).build();
+
+ Ipv4FamilyBuilder ipv4vpnBuilder = new Ipv4FamilyBuilder().setVpnTargets(vpnTargets);
+
+ if (rd != null && !rd.isEmpty()) {
+ ipv4vpnBuilder.setRouteDistinguisher(rd.get(0));
+ }
+
+ VpnInstance newVpn = builder.setIpv4Family(ipv4vpnBuilder.build()).build();
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier, newVpn);
+ logger.debug("Created/Updated vpn-instance for {} ", name);
+ } catch (Exception e) {
+ logger.error("Update VPN Instance node failed for node: {} {} {} {}", name, rd, irt, ert);
+ throw new RuntimeException(e);
+ }
+ }
+
+ private void createVpnMapsNode() {
+ InstanceIdentifier<VpnMaps> vpnMapsIdentifier = InstanceIdentifier.builder(VpnMaps.class).build();
+ VpnMapsBuilder vpnMaps = new VpnMapsBuilder();
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, vpnMapsIdentifier, vpnMaps.build());
+ InstanceIdentifier<Subnetmaps> subnetmapsId = InstanceIdentifier.builder(Subnetmaps.class).build();
+ SubnetmapsBuilder subnetmaps = new SubnetmapsBuilder();
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, subnetmapsId, subnetmaps.build());
+ }
+
+ private void deleteVpnMapsNode(Uuid vpnid) {
+ InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
+ .child(VpnMap.class, new VpnMapKey(vpnid)).build();
+ logger.debug("removing vpnMaps node: {} ", vpnid.getValue());
+ MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier);
+ }
+
+ private void updateVpnMaps(Uuid vpnId, String name, Uuid router, Uuid tenantId, List<Uuid> networks) {
+ VpnMapBuilder builder;
+ InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
+ .child(VpnMap.class, new VpnMapKey(vpnId)).build();
+ Optional<VpnMap> optionalVpnMap = read(LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier);
+ if (optionalVpnMap.isPresent()) {
+ builder = new VpnMapBuilder(optionalVpnMap.get());
+ } else {
+ builder = new VpnMapBuilder().setKey(new VpnMapKey(vpnId)).setVpnId(vpnId);
+ }
+
+ if (name != null) {
+ builder.setName(name);
+ }
+ if (tenantId != null) {
+ builder.setTenantId(tenantId);
+ }
+ if (router != null) {
+ builder.setRouterId(router);
+ }
+ if (networks != null) {
+ List<Uuid> nwList = builder.getNetworkIds();
+ if (nwList == null) {
+ nwList = new ArrayList<Uuid>();
+ }
+ nwList.addAll(networks);
+ builder.setNetworkIds(nwList);
+ }
+
+ logger.debug("Creating/Updating vpnMaps node: {} ", vpnId.getValue());
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier, builder.build());
+ logger.debug("VPNMaps DS updated for VPN {} ", vpnId.getValue());
+ }
+
+ private void clearFromVpnMaps(Uuid id, Uuid router, List<Uuid> networks) {
+ InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
+ .child(VpnMap.class, new VpnMapKey(id)).build();
+ Optional<VpnMap> optionalVpnMap = read(LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier);
+ if (optionalVpnMap.isPresent()) {
+ VpnMap vpnMap = optionalVpnMap.get();
+ VpnMapBuilder vpnMapBuilder = new VpnMapBuilder(vpnMap);
+ if (router != null) {
+ if (vpnMap.getNetworkIds() == null && router.equals(vpnMap.getVpnId())) {
+ // remove entire node in case of internal VPN
+ logger.debug("removing vpnMaps node: {} ", id);
+ MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier);
+ return;
+ }
+ vpnMapBuilder.setRouterId(null);
+ }
+ if (networks != null) {
+ List<Uuid> vpnNw = vpnMap.getNetworkIds();
+ for (Uuid nw : networks) {
+ vpnNw.remove(nw);
+ }
+ if (vpnNw.isEmpty()) {
+ logger.debug("setting networks null in vpnMaps node: {} ", id.getValue());
+ vpnMapBuilder.setNetworkIds(null);
+ } else {
+ vpnMapBuilder.setNetworkIds(vpnNw);
+ }
+ }
+
+ logger.debug("clearing from vpnMaps node: {} ", id.getValue());
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier, vpnMapBuilder.build());
+ } else {
+ logger.error("VPN : {} not found", id.getValue());
+ }
+ logger.debug("VPNMaps DS clear success for VPN {} ", id.getValue());
+ }
+
+ private void createOfPortInterface(Port port, int portVlanId) {
+ String name = NeutronvpnUtils.uuidToTapPortName(port.getUuid());
+ //String ifname = new StringBuilder(name).append(":").append(Integer.toString(portVlanId)).toString();
+ //Network network = NeutronvpnUtils.getNeutronNetwork(broker, port.getNetworkId());
+ //Boolean isVlanTransparent = network.isVlanTransparent();
+
+ logger.debug("Creating OFPort Interface {}", name);
+ InstanceIdentifier interfaceIdentifier = NeutronvpnUtils.buildVlanInterfaceIdentifier(name);
+ try {
+ Optional<Interface> optionalInf = read(LogicalDatastoreType.CONFIGURATION, interfaceIdentifier);
+ if (!optionalInf.isPresent()) {
+ // handle these for trunkport extensions : portVlanId, isVlanTransparent
+ Interface inf = new InterfaceBuilder().setEnabled(true).setName(name).setType(L2vlan.class).build();
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, interfaceIdentifier, inf);
+ } else {
+ logger.error("Interface {} is already present", name);
+ }
+ } catch (Exception e) {
+ logger.error("failed to create interface {} due to the exception {} ", name, e.getMessage());
+ }
+
+ InstanceIdentifier portIdentifier = NeutronvpnUtils.buildPortNameToPortUuidIdentifier(name);
+ PortNameToPortUuidBuilder builder = new PortNameToPortUuidBuilder().setPortName(name).setPortId(port.getUuid());
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, portIdentifier, builder.build());
+ logger.debug("name-uuid map for port with name: {}, uuid: {} added to NeutronPortData DS", name, port.getUuid
+ ());
+ }
+
+ private void deleteOfPortInterface(Port port, int portVlanId) {
+ String name = NeutronvpnUtils.uuidToTapPortName(port.getUuid());
+ //String ifname = new StringBuilder(name).append(":").append(Integer.toString(portVlanId)).toString();
+ logger.debug("Removing OFPort Interface {}", name);
+ InstanceIdentifier interfaceIdentifier = NeutronvpnUtils.buildVlanInterfaceIdentifier(name);
+ try {
+ Optional<Interface> optionalInf = read(LogicalDatastoreType.CONFIGURATION, interfaceIdentifier);
+ if (optionalInf.isPresent()) {
+ MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, interfaceIdentifier);
+ } else {
+ logger.error("Interface {} is not present", name);
+ }
+ } catch (Exception e) {
+ logger.error("Failed to delete interface {} due to the exception {}", name, e.getMessage());
+ }
+
+ InstanceIdentifier id = NeutronvpnUtils.buildPortNameToPortUuidIdentifier(name);
+ MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, id);
+ logger.debug("name-uuid map for port with name: {}, uuid: {} deleted from NeutronPortData DS", name, port
+ .getUuid());
+ }
+
+ private void deleteVpnInstance(Uuid vpnId) {
+
+ InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class).
+ child(VpnInstance.class, new VpnInstanceKey(vpnId.getValue())).build();
+ logger.debug("removing vpn Instance {}", vpnId.getValue());
+ MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier);
+ }
+
+
+ private void createVpnInterface(Uuid vpnId, Port port) {
+
+ if (vpnId == null || port == null) {
+ return;
+ }
+ String portname = NeutronvpnUtils.uuidToTapPortName(port.getUuid());
+ String name = new StringBuilder(portname).append(":0").toString();
+ List<Adjacency> adjList = new ArrayList<Adjacency>();
+ InstanceIdentifier<VpnInterface> vpnIfIdentifier = InstanceIdentifier.builder(VpnInterfaces.class).
+ child(VpnInterface.class, new VpnInterfaceKey(name)).build();
+ // find router associated to vpn
+ Uuid routerId = NeutronvpnUtils.getRouterforVpn(broker, vpnId);
+ Router rtr = null;
+ if (routerId != null) {
+ rtr = NeutronvpnUtils.getNeutronRouter(broker, routerId);
+ }
+ // find all Subnets to which this port is associated
+ List<FixedIps> ips = port.getFixedIps();
+ // create adjacency list
+ for (FixedIps ip : ips) {
+ // create vm adjacency
+ StringBuilder IpPrefixBuild = new StringBuilder(ip.getIpAddress().getIpv4Address().getValue());
+ String IpPrefix = IpPrefixBuild.append("/32").toString();
+ Adjacency vmAdj = new AdjacencyBuilder().setKey(new AdjacencyKey(IpPrefix)).setIpAddress(IpPrefix)
+ .setMacAddress(port.getMacAddress()).build();
+ adjList.add(vmAdj);
+ // create extra route adjacency
+ if (rtr != null && rtr.getRoutes() != null) {
+ List<String> routeList = rtr.getRoutes();
+ List<Adjacency> erAdjList = addAdjacencyforExtraRoute(routeList, false, name);
+ if (erAdjList != null) {
+ adjList.addAll(erAdjList);
+ }
+ }
+ }
+ // create vpn-interface on this neutron port
+ Adjacencies adjs = new AdjacenciesBuilder().setAdjacency(adjList).build();
+ VpnInterfaceBuilder vpnb = new VpnInterfaceBuilder().setKey(new VpnInterfaceKey(name)).
+ setName(name).setVpnInstanceName(vpnId.getValue()).addAugmentation(Adjacencies.class, adjs);
+ VpnInterface vpnIf = vpnb.build();
+
+ NeutronvpnUtils.lockVpnInterface(lockManager, name);
+ try {
+ logger.debug("Creating vpn interface {}", vpnIf);
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier, vpnIf);
+ } catch (Exception ex) {
+ logger.error("Creation of vpninterface {} failed due to {}", name, ex);
+ } finally {
+ NeutronvpnUtils.unlockVpnInterface(lockManager, name);
+ }
+ }
+
+ private void deleteVpnInterface(Port port) {
+
+ if (port != null) {
+ String pname = NeutronvpnUtils.uuidToTapPortName(port.getUuid());
+ String name = new StringBuilder(pname).append(":0").toString();
+ InstanceIdentifier<VpnInterface> vpnIfIdentifier = InstanceIdentifier.builder(VpnInterfaces.class).
+ child(VpnInterface.class, new VpnInterfaceKey(name)).build();
+
+ NeutronvpnUtils.lockVpnInterface(lockManager, name);
+ try {
+ logger.debug("Deleting vpn interface {}", name);
+ MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier);
+ } catch (Exception ex) {
+ logger.error("Deletion of vpninterface {} failed due to {}", name, ex);
+ } finally {
+ NeutronvpnUtils.unlockVpnInterface(lockManager, name);
+ }
+ }
+ }
+
+ // adds port to subnet list and creates vpnInterface
+ private Uuid addPortToSubnets(Port port) {
+ Uuid subnetId = null;
+ Uuid vpnId = null;
+ String name = NeutronvpnUtils.uuidToTapPortName(port.getUuid());
+
+ // find all Subnets to which this port is associated,
+ List<FixedIps> ips = port.getFixedIps();
+ for (FixedIps ip : ips) {
+ String ipValue = ip.getIpAddress().getIpv4Address().getValue();
+
+ InstanceIdentifier id = NeutronvpnUtils.buildFixedIpToPortNameIdentifier(ipValue);
+ PortFixedipToPortNameBuilder builder = new PortFixedipToPortNameBuilder().setPortFixedip(ipValue)
+ .setPortName(name);
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, id, builder.build());
+ logger.debug("fixedIp-name map for neutron port with fixedIp: {}, name: {} added to NeutronPortData DS",
+ ipValue, name);
+
+ subnetId = ip.getSubnetId();
+ Subnetmap subnetmap = updateSubnetNode(subnetId, null, null, null, null, port.getUuid());
+ if (vpnId == null && subnetmap != null) {
+ vpnId = subnetmap.getVpnId();
+ }
+ }
+ return vpnId;
+ }
+
+ private Uuid removePortFromSubnets(Port port) {
+ Uuid subnetId = null;
+ Uuid vpnId = null;
+
+ // find all Subnets to which this port is associated,
+ List<FixedIps> ips = port.getFixedIps();
+ for (FixedIps ip : ips) {
+ String ipValue = ip.getIpAddress().getIpv4Address().getValue();
+
+ InstanceIdentifier id = NeutronvpnUtils.buildFixedIpToPortNameIdentifier(ipValue);
+ MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, id);
+ logger.debug("fixedIp-name map for neutron port with fixedIp: {} deleted from NeutronPortData DS",
+ ipValue);
+
+ subnetId = ip.getSubnetId();
+ Subnetmap subnetmap = removeFromSubnetNode(subnetId, null, null, null, port.getUuid());
+ if (vpnId == null && subnetmap != null) {
+ vpnId = subnetmap.getVpnId();
+ }
+ }
+ return vpnId;
+ }
+
+ protected void handleNeutronPortCreated(Port port) {
+ logger.info("Of-port-interface creation");
+ int portVlanId = NeutronvpnUtils.getVlanFromNeutronPort(port);
+ // Create of-port interface for this neutron port
+ createOfPortInterface(port, portVlanId);
+ logger.debug("Add port to subnet");
+ // add port to local Subnets DS
+ Uuid vpnId = addPortToSubnets(port);
+
+ if (vpnId != null) {
+ // create vpn-interface on this neutron port
+ logger.debug("Adding VPN Interface");
+ createVpnInterface(vpnId, port);
+ }
+ }
+
+ protected void handleNeutronPortDeleted(Port port) {
+ logger.debug("Of-port-interface removal");
+ logger.debug("Remove port from subnet");
+ // remove port from local Subnets DS
+ Uuid vpnId = removePortFromSubnets(port);
+
+ if (vpnId != null) {
+ // remove vpn-interface for this neutron port
+ logger.debug("removing VPN Interface");
+ deleteVpnInterface(port);
+ }
+ int portVlanId = NeutronvpnUtils.getVlanFromNeutronPort(port);
+ // Remove of-port interface for this neutron port
+ deleteOfPortInterface(port, portVlanId);
+
+ }
+
+ protected void handleNeutronPortUpdated(Port portoriginal, Port portupdate) {
+ logger.debug("Add port to subnet");
+ // add port FixedIPs to local Subnets DS
+ Uuid vpnIdup = addPortToSubnets(portupdate);
+
+ if (vpnIdup != null) {
+ createVpnInterface(vpnIdup, portupdate);
+ }
+
+ // remove port FixedIPs from local Subnets DS
+ Uuid vpnIdor = removePortFromSubnets(portoriginal);
+
+ if (vpnIdor != null) {
+ deleteVpnInterface(portoriginal);
+ }
+ }
+
+ public void createL3Vpn(Uuid vpn, String name, Uuid tenant, List<String> rd, List<String> irt, List<String> ert,
+ Uuid router, List<Uuid> networks) {
+
+ // Update VPN Instance node
+ updateVpnInstanceNode(vpn.getValue(), rd, irt, ert);
+
+ // Update local vpn-subnet DS
+ updateVpnMaps(vpn, name, router, tenant, networks);
+
+ if (router != null) {
+ associateRouterToVpn(vpn, router);
+ }
+ if (networks != null) {
+ associateNetworksToVpn(vpn, networks);
+ }
+ }
+
+ @Override
+ public Future<RpcResult<CreateL3VPNOutput>> createL3VPN(CreateL3VPNInput input) {
+
+ CreateL3VPNOutputBuilder opBuilder = new CreateL3VPNOutputBuilder();
+ SettableFuture<RpcResult<CreateL3VPNOutput>> result = SettableFuture.create();
+ List<RpcError> errorList = new ArrayList<RpcError>();
+ int failurecount = 0;
+ int warningcount = 0;
+
+ List<L3vpn> vpns = input.getL3vpn();
+ for (L3vpn vpn : vpns) {
+ RpcError error;
+ String msg;
+ if (vpn.getRouteDistinguisher() == null || vpn.getImportRT() == null || vpn.getExportRT() == null) {
+ msg = String.format("Creation of L3VPN failed for VPN %s due to absence of RD/iRT/eRT input",
+ vpn.getId().getValue());
+ logger.warn(msg);
+ error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
+ errorList.add(error);
+ warningcount++;
+ continue;
+ }
+ if (vpn.getRouteDistinguisher().size() > 1) {
+ msg = String.format("Creation of L3VPN failed for VPN %s due to multiple RD input %s",
+ vpn.getId().getValue(), vpn.getRouteDistinguisher());
+ logger.warn(msg);
+ error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
+ errorList.add(error);
+ warningcount++;
+ continue;
+ }
+ try {
+ createL3Vpn(vpn.getId(), vpn.getName(), vpn.getTenantId(), vpn.getRouteDistinguisher(),
+ vpn.getImportRT(), vpn.getExportRT(), vpn.getRouterId(), vpn.getNetworkIds());
+ } catch (Exception ex) {
+ msg = String.format("Creation of L3VPN failed for VPN %s", vpn.getId().getValue());
+ logger.error(msg, ex.getMessage());
+ error = RpcResultBuilder.newError(ErrorType.APPLICATION, msg, ex.getMessage());
+ errorList.add(error);
+ failurecount++;
+ }
+ }
+ // if at least one succeeds; result is success
+ // if none succeeds; result is failure
+ if (failurecount + warningcount == vpns.size()) {
+ result.set(RpcResultBuilder.<CreateL3VPNOutput>failed().withRpcErrors(errorList).build());
+ } else {
+ List<String> errorResponseList = new ArrayList<>();
+ if (!errorList.isEmpty()) {
+ for (RpcError rpcError : errorList) {
+ String errorResponse = String.format("ErrorType: " + rpcError.getErrorType() + ", " + "ErrorTag: " +
+ rpcError.getTag() + ", " + "ErrorMessage: " + rpcError.getMessage());
+ errorResponseList.add(errorResponse);
+ }
+ } else {
+ errorResponseList.add("Operation successful with no errors");
+ }
+ opBuilder.setResponse(errorResponseList);
+ result.set(RpcResultBuilder.<CreateL3VPNOutput>success().withResult(opBuilder.build()).build());
+ }
+ return result;
+ }
+
+ @Override
+ public Future<RpcResult<GetL3VPNOutput>> getL3VPN(GetL3VPNInput input) {
+
+ GetL3VPNOutputBuilder opBuilder = new GetL3VPNOutputBuilder();
+ SettableFuture<RpcResult<GetL3VPNOutput>> result = SettableFuture.create();
+ Uuid inputVpnId = input.getId();
+ List<VpnInstance> vpns = new ArrayList<VpnInstance>();
+
+ try {
+ if (inputVpnId == null) {
+ // get all vpns
+ InstanceIdentifier<VpnInstances> vpnsIdentifier =
+ InstanceIdentifier.builder(VpnInstances.class).build();
+ Optional<VpnInstances> optionalVpns = read(LogicalDatastoreType.CONFIGURATION, vpnsIdentifier);
+ if (optionalVpns.isPresent()) {
+ for (VpnInstance vpn : optionalVpns.get().getVpnInstance()) {
+ vpns.add(vpn);
+ }
+ } else {
+ // No VPN present
+ result.set(RpcResultBuilder.<GetL3VPNOutput>failed()
+ .withWarning(ErrorType.PROTOCOL, "", "No VPN is present").build());
+ return result;
+ }
+ } else {
+ String name = inputVpnId.getValue();
+ InstanceIdentifier<VpnInstance> vpnIdentifier =
+ InstanceIdentifier.builder(VpnInstances.class)
+ .child(VpnInstance.class, new VpnInstanceKey(name)).build();
+ // read VpnInstance Info
+ Optional<VpnInstance> optionalVpn = read(LogicalDatastoreType.CONFIGURATION, vpnIdentifier);
+ if (optionalVpn.isPresent()) {
+ vpns.add(optionalVpn.get());
+ } else {
+ String message = String.format("GetL3VPN failed because VPN %s is not present", name);
+ logger.error(message);
+ result.set(RpcResultBuilder.<GetL3VPNOutput>failed()
+ .withWarning(ErrorType.PROTOCOL, "invalid-value", message).build());
+ }
+ }
+ List<L3vpnInstances> l3vpnList = new ArrayList<L3vpnInstances>();
+ for (VpnInstance vpnInstance : vpns) {
+ Uuid vpnId = new Uuid(vpnInstance.getVpnInstanceName());
+ // create VpnMaps id
+ InstanceIdentifier<VpnMap> vpnMapIdentifier =
+ InstanceIdentifier.builder(VpnMaps.class)
+ .child(VpnMap.class, new VpnMapKey(vpnId)).build();
+ L3vpnInstancesBuilder l3vpn = new L3vpnInstancesBuilder();
+
+ List<String> rd = Arrays.asList(vpnInstance.getIpv4Family().getRouteDistinguisher().split(","));
+ List<VpnTarget> vpnTargetList = vpnInstance.getIpv4Family().getVpnTargets().getVpnTarget();
+
+ List<String> ertList = new ArrayList<String>();
+ List<String> irtList = new ArrayList<String>();
+
+ for (VpnTarget vpnTarget : vpnTargetList) {
+ if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ExportExtcommunity) {
+ ertList.add(vpnTarget.getVrfRTValue());
+ }
+ if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ImportExtcommunity) {
+ irtList.add(vpnTarget.getVrfRTValue());
+ }
+ if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.Both) {
+ ertList.add(vpnTarget.getVrfRTValue());
+ irtList.add(vpnTarget.getVrfRTValue());
+ }
+ }
+
+ l3vpn.setId(vpnId).setRouteDistinguisher(rd).setImportRT(irtList).setExportRT(ertList);
+ Optional<VpnMap> optionalVpnMap =
+ read(LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier);
+ if (optionalVpnMap.isPresent()) {
+ VpnMap vpnMap = optionalVpnMap.get();
+ l3vpn.setRouterId(vpnMap.getRouterId()).setNetworkIds(vpnMap.getNetworkIds())
+ .setTenantId(vpnMap.getTenantId()).setName(vpnMap.getName());
+ }
+ l3vpnList.add(l3vpn.build());
+ }
+
+ opBuilder.setL3vpnInstances(l3vpnList);
+ result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
+
+ } catch (Exception ex) {
+ String message = String.format("GetL3VPN failed due to %s", ex.getMessage());
+ logger.error(message);
+ result.set(RpcResultBuilder.<GetL3VPNOutput>failed().withError(ErrorType.APPLICATION, message).build());
+ }
+
+ return result;
+ }
+
+ @Override
+ public Future<RpcResult<DeleteL3VPNOutput>> deleteL3VPN(DeleteL3VPNInput input) {
+
+ DeleteL3VPNOutputBuilder opBuilder = new DeleteL3VPNOutputBuilder();
+ SettableFuture<RpcResult<DeleteL3VPNOutput>> result = SettableFuture.create();
+ List<RpcError> errorList = new ArrayList<RpcError>();
+
+ int failurecount = 0;
+ int warningcount = 0;
+ List<Uuid> vpns = input.getId();
+ for (Uuid vpn : vpns) {
+ RpcError error;
+ String msg;
+ try {
+ InstanceIdentifier<VpnInstance> vpnIdentifier =
+ InstanceIdentifier.builder(VpnInstances.class)
+ .child(VpnInstance.class, new VpnInstanceKey(vpn.getValue())).build();
+ Optional<VpnInstance> optionalVpn = read(LogicalDatastoreType.CONFIGURATION, vpnIdentifier);
+ if (optionalVpn.isPresent()) {
+ removeL3Vpn(vpn);
+ } else {
+ msg = String.format("VPN with vpnid: %s does not exist", vpn.getValue());
+ logger.warn(msg);
+ error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-value", msg);
+ errorList.add(error);
+ warningcount++;
+ }
+ } catch (Exception ex) {
+ msg = String.format("Deletion of L3VPN failed when deleting for uuid %s", vpn.getValue());
+ logger.error(msg, ex.getMessage());
+ error = RpcResultBuilder.newError(ErrorType.APPLICATION, msg, ex.getMessage());
+ errorList.add(error);
+ failurecount++;
+ }
+ }
+ // if at least one succeeds; result is success
+ // if none succeeds; result is failure
+ if (failurecount + warningcount == vpns.size()) {
+ result.set(RpcResultBuilder.<DeleteL3VPNOutput>failed().withRpcErrors(errorList).build());
+ } else {
+ List<String> errorResponseList = new ArrayList<>();
+ if (!errorList.isEmpty()) {
+ for (RpcError rpcError : errorList) {
+ String errorResponse = String.format("ErrorType: " + rpcError.getErrorType() + ", " + "ErrorTag: " +
+ rpcError.getTag() + ", " + "ErrorMessage: " + rpcError.getMessage());
+ errorResponseList.add(errorResponse);
+ }
+ } else {
+ errorResponseList.add("Operation successful with no errors");
+ }
+ opBuilder.setResponse(errorResponseList);
+ result.set(RpcResultBuilder.<DeleteL3VPNOutput>success().withResult(opBuilder.build()).build());
+ }
+ return result;
+ }
+
+ protected void addSubnetToVpn(Uuid vpnId, Uuid subnet) {
+ logger.debug("Adding subnet {} to vpn {}", subnet.getValue(), vpnId.getValue());
+ Subnetmap sn = updateSubnetNode(subnet, null, null, null, vpnId, null);
+ // Check if there are ports on this subnet and add corresponding vpn-interfaces
+ List<Uuid> portList = sn.getPortList();
+ if (portList != null) {
+ for (Uuid port : sn.getPortList()) {
+ logger.debug("adding vpn-interface for port {}", port.getValue());
+ createVpnInterface(vpnId, getNeutronPort(port));
+ }
+ }
+ }
+
+ protected List<Adjacency> addAdjacencyforExtraRoute(List<String> routeList, boolean rtrUp, String vpnifname) {
+ try {
+ List<Adjacency> adjList = new ArrayList<Adjacency>();
+ for (String route : routeList) {
+ // assuming extra route is strictly in the format "nexthop destination" > "10.1.1.10 40.0.1.0/24"
+ String[] parts = route.split(" ");
+ if (parts.length == 2) {
+ String nextHop = parts[0];
+ String destination = parts[1];
+
+ String tapPortName = NeutronvpnUtils.getNeutronPortNamefromPortFixedIp(broker, nextHop);
+ String ifname = new StringBuilder(tapPortName).append(":0").toString();
+ logger.trace("Adding extra route with nexthop {}, destination {}, ifName {}", nextHop,
+ destination, ifname);
+ Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination).setNextHopIp(nextHop).setKey
+ (new AdjacencyKey(destination)).build();
+ if (rtrUp == false) {
+ if (ifname.equals(vpnifname)) {
+ adjList.add(erAdj);
+ }
+ continue;
+ }
+ InstanceIdentifier<VpnInterface> vpnIfIdentifier = InstanceIdentifier.builder(VpnInterfaces.class).
+ child(VpnInterface.class, new VpnInterfaceKey(ifname)).build();
+ Optional<VpnInterface> optionalVpnInterface = read(LogicalDatastoreType.CONFIGURATION,
+ vpnIfIdentifier);
+ if (optionalVpnInterface.isPresent()) {
+ Adjacencies erAdjs = new AdjacenciesBuilder().setAdjacency(Arrays.asList(erAdj)).build();
+ VpnInterface vpnIf = new VpnInterfaceBuilder().setKey(new VpnInterfaceKey(ifname))
+ .addAugmentation(Adjacencies.class, erAdjs).build();
+ MDSALUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier, vpnIf);
+ logger.trace("extra route {} added successfully", route);
+ } else {
+ logger.error("VM adjacency for interface {} not present ; cannot add extra route adjacency",
+ ifname);
+ }
+ } else {
+ logger.error("Incorrect input received for extra route. {}", parts);
+ }
+ }
+ return adjList;
+ } catch (Exception e) {
+ logger.error("exception in adding extra route: {}" + e);
+ }
+ return null;
+ }
+
+ protected void removeAdjacencyforExtraRoute(List<String> routeList) {
+ try {
+ for (String route : routeList) {
+ // assuming extra route is strictly in the format "nexthop destination" > "10.1.1.10 40.0.1.0/24"
+ String[] parts = route.split(" ");
+ if (parts.length == 2) {
+ String nextHop = parts[0];
+ String destination = parts[1];
+
+ String tapPortName = NeutronvpnUtils.getNeutronPortNamefromPortFixedIp(broker, nextHop);
+ String ifname = new StringBuilder(tapPortName).append(":0").toString();
+ logger.trace("Removing extra route with nexthop {}, destination {}, ifName {}", nextHop,
+ destination, ifname);
+ InstanceIdentifier<Adjacency> adjacencyIdentifier = InstanceIdentifier.builder(VpnInterfaces.class).
+ child(VpnInterface.class, new VpnInterfaceKey(ifname)).augmentation(Adjacencies.class)
+ .child(Adjacency.class, new AdjacencyKey(destination)).build();
+ MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, adjacencyIdentifier);
+ logger.trace("extra route {} deleted successfully", route);
+ } else {
+ logger.error("Incorrect input received for extra route. {}", parts);
+ }
+ }
+ } catch (Exception e) {
+ logger.error("exception in deleting extra route: {}" + e);
+ }
+ }
+
+ protected void addPortToVpn(Uuid vpnId, Uuid port) {
+ logger.debug("Adding Port to vpn node...");
+ createVpnInterface(vpnId, getNeutronPort(port));
+ }
+
+ protected void removeL3Vpn(Uuid id) {
+ // read VPN networks
+ VpnMap vpnMap = NeutronvpnUtils.getVpnMap(broker, id);
+ Uuid router = vpnMap.getRouterId();
+ // dissociate router
+ if (router != null) {
+ dissociateRouterFromVpn(id, router);
+ }
+ // dissociate networks
+ if (!id.equals(router)) {
+ dissociateNetworksFromVpn(id, vpnMap.getNetworkIds());
+ }
+ // remove entire vpnMaps node
+ deleteVpnMapsNode(id);
+
+ // remove vpn-instance
+ deleteVpnInstance(id);
+ }
+
+ protected void removePortFromVpn(Uuid vpnId, Uuid port) {
+ logger.debug("Removing Port from vpn node...");
+ deleteVpnInterface(getNeutronPort(port));
+ }
+
+ protected void removeSubnetFromVpn(Uuid vpnId, Uuid subnet) {
+ logger.debug("Removing subnet {} from vpn {}", subnet.getValue(), vpnId.getValue());
+ Subnetmap sn = NeutronvpnUtils.getSubnetmap(broker, subnet);
+ if (sn != null) {
+ // Check if there are ports on this subnet; remove corresponding vpn-interfaces
+ List<Uuid> portList = sn.getPortList();
+ if (portList != null) {
+ for (Uuid port : sn.getPortList()) {
+ logger.debug("removing vpn-interface for port {}", port.getValue());
+ deleteVpnInterface(getNeutronPort(port));
+ }
+ }
+ // update subnet-vpn association
+ removeFromSubnetNode(subnet, null, null, vpnId, null);
+ } else {
+ logger.warn("Subnetmap for subnet {} not found", subnet.getValue());
+ }
+ }
+
+ protected void associateRouterToVpn(Uuid vpn, Uuid router) {
+
+ // remove existing Router-VPN
+ if (!vpn.equals(router)) {
+ removeL3Vpn(router);
+ }
+ updateVpnMaps(vpn, null, router, null, null);
+
+ List<Uuid> routerSubnets = NeutronvpnUtils.getNeutronRouterSubnetIds(broker, router);
+ logger.debug("Adding subnets...");
+ for (Uuid subnet : routerSubnets) {
+ addSubnetToVpn(vpn, subnet);
+ }
+ }
+
+ protected void dissociateRouterFromVpn(Uuid vpn, Uuid router) {
+ clearFromVpnMaps(vpn, router, null);
+
+ // fetching sn from SubnetmapDS for internal VPN because sn already deleted from RouterIf DS on router deletion
+ List<Uuid> routerSubnets = (vpn.equals(router)) ? getSubnetsforVpn(vpn) :
+ NeutronvpnUtils.getNeutronRouterSubnetIds(broker, router);
+
+ logger.debug("dissociateRouter vpn {} router {} Removing subnets...", vpn.getValue(), router.getValue());
+ if (routerSubnets != null) {
+ for (Uuid subnet : routerSubnets) {
+ removeSubnetFromVpn(vpn, subnet);
+ }
+ }
+ // create Router-VPN for this router
+ if (!vpn.equals(router)) {
+ logger.debug("Re-creating vpn-router...");
+ createL3Vpn(router, null, null, null, null, null, router, null);
+ }
+ }
+
+ protected List<String> associateNetworksToVpn(Uuid vpn, List<Uuid> networks) {
+ List<String> failed = new ArrayList<String>();
+ if (!networks.isEmpty()) {
+ // store in Data Base
+ updateVpnMaps(vpn, null, null, null, networks);
+ // process corresponding subnets for VPN
+ for (Uuid nw : networks) {
+ if (NeutronvpnUtils.getNeutronNetwork(broker, nw) == null) {
+ failed.add(nw.getValue());
+ } else {
+ List<Uuid> networkSubnets = NeutronvpnUtils.getNeutronNetworkSubnetIds(broker, nw);
+ logger.debug("Adding network subnets...");
+ if (networkSubnets != null) {
+ for (Uuid subnet : networkSubnets) {
+ addSubnetToVpn(vpn, subnet);
+ }
+ }
+ }
+ }
+ }
+ return failed;
+ }
+
+ protected List<String> dissociateNetworksFromVpn(Uuid vpn, List<Uuid> networks) {
+ List<String> failed = new ArrayList<String>();
+ if (networks != null && !networks.isEmpty()) {
+ // store in Data Base
+ clearFromVpnMaps(vpn, null, networks);
+ // process corresponding subnets for VPN
+ for (Uuid nw : networks) {
+ if (NeutronvpnUtils.getNeutronNetwork(broker, nw) == null) {
+ failed.add(nw.getValue());
+ } else {
+ List<Uuid> networkSubnets = NeutronvpnUtils.getNeutronNetworkSubnetIds(broker, nw);
+ logger.debug("Removing network subnets...");
+ for (Uuid subnet : networkSubnets) {
+ removeSubnetFromVpn(vpn, subnet);
+ }
+ }
+ }
+ }
+ return failed;
+ }
+
+ @Override
+ public Future<RpcResult<AssociateNetworksOutput>> associateNetworks(AssociateNetworksInput input) {
+
+ AssociateNetworksOutputBuilder opBuilder = new AssociateNetworksOutputBuilder();
+ SettableFuture<RpcResult<AssociateNetworksOutput>> result = SettableFuture.create();
+ logger.debug("associateNetworks {}", input);
+ StringBuilder returnMsg = new StringBuilder();
+ Uuid vpnId = input.getVpnId();
+
+ try {
+ if (NeutronvpnUtils.getVpnMap(broker, vpnId) != null) {
+ List<Uuid> netIds = input.getNetworkId();
+ if (netIds != null && !netIds.isEmpty()) {
+ List<String> failed = associateNetworksToVpn(vpnId, netIds);
+ if (!failed.isEmpty()) {
+ returnMsg.append("network(s) not found : ").append(failed);
+ }
+ }
+ } else {
+ returnMsg.append("VPN not found : ").append(vpnId.getValue());
+ }
+ if (returnMsg.length() != 0) {
+ String message = String.format("associate Networks to vpn %s failed due to %s", vpnId.getValue(),
+ returnMsg);
+ logger.error(message);
+ String errorResponse = String.format("ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " +
+ message);
+ opBuilder.setResponse(errorResponse);
+ result.set(RpcResultBuilder.<AssociateNetworksOutput>success().withResult(opBuilder.build()).build());
+ } else {
+ result.set(RpcResultBuilder.<AssociateNetworksOutput>success().build());
+ }
+ } catch (Exception ex) {
+ String message = String.format("associate Networks to vpn %s failed due to %s", input.getVpnId().getValue(),
+ ex.getMessage());
+ logger.error(message);
+ result.set(RpcResultBuilder.<AssociateNetworksOutput>failed().withError(ErrorType.APPLICATION, message)
+ .build());
+ }
+ logger.debug("associateNetworks returns..");
+ return result;
+ }
+
+ @Override
+ public Future<RpcResult<Void>> associateRouter(AssociateRouterInput input) {
+
+ SettableFuture<RpcResult<Void>> result = SettableFuture.create();
+ logger.debug("associateRouter {}", input);
+ StringBuilder returnMsg = new StringBuilder();
+ Uuid vpnId = input.getVpnId();
+ Uuid routerId = input.getRouterId();
+ try {
+ if (routerId != null && vpnId != null) {
+ Router rtr = NeutronvpnUtils.getNeutronRouter(broker, routerId);
+ VpnMap vpnMap = NeutronvpnUtils.getVpnMap(broker, vpnId);
+ if (rtr != null && vpnMap != null) {
+ if (vpnMap.getRouterId() != null) {
+ returnMsg.append("vpn ").append(vpnId.getValue()).append(" already associated to router ")
+ .append(vpnMap.getRouterId().getValue());
+ } else {
+ associateRouterToVpn(vpnId, routerId);
+ }
+ } else {
+ returnMsg.append("router not found : ").append(routerId.getValue());
+ }
+ } else {
+ returnMsg.append("VPN not found : ").append(vpnId.getValue());
+ }
+ if (returnMsg.length() != 0) {
+ String message = String.format("associate router to vpn %s failed due to %s", routerId.getValue(),
+ returnMsg);
+ logger.error(message);
+ result.set(RpcResultBuilder.<Void>failed().withWarning(ErrorType.PROTOCOL, "invalid-value", message)
+ .build());
+ } else {
+ result.set(RpcResultBuilder.<Void>success().build());
+ }
+ } catch (Exception ex) {
+ String message = String.format("associate router %s to vpn %s failed due to %s", routerId.getValue(),
+ vpnId.getValue(), ex.getMessage());
+ logger.error(message);
+ result.set(RpcResultBuilder.<Void>failed().withError(ErrorType.APPLICATION, message).build());
+ }
+ logger.debug("associateRouter returns..");
+ return result;
+ }
+
+ @Override
+ public Future<RpcResult<DissociateNetworksOutput>> dissociateNetworks(DissociateNetworksInput input) {
+
+ DissociateNetworksOutputBuilder opBuilder = new DissociateNetworksOutputBuilder();
+ SettableFuture<RpcResult<DissociateNetworksOutput>> result = SettableFuture.create();
+
+ logger.debug("dissociateNetworks {}", input);
+ StringBuilder returnMsg = new StringBuilder();
+ Uuid vpnId = input.getVpnId();
+
+ try {
+ if (NeutronvpnUtils.getVpnMap(broker, vpnId) != null) {
+ List<Uuid> netIds = input.getNetworkId();
+ if (netIds != null && !netIds.isEmpty()) {
+ List<String> failed = dissociateNetworksFromVpn(vpnId, netIds);
+ if (!failed.isEmpty()) {
+ returnMsg.append("netowrk(s) not found : ").append(failed);
+ }
+ }
+ } else {
+ returnMsg.append("VPN not found : ").append(vpnId.getValue());
+ }
+ if (returnMsg.length() != 0) {
+ String message = String.format("disssociate Networks to vpn %s failed due to %s", vpnId.getValue(),
+ returnMsg);
+ logger.error(message);
+ String errorResponse = String.format("ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " +
+ message);
+ opBuilder.setResponse(errorResponse);
+ result.set(RpcResultBuilder.<DissociateNetworksOutput>success().withResult(opBuilder.build()).build());
+ } else {
+ result.set(RpcResultBuilder.<DissociateNetworksOutput>success().build());
+ }
+ } catch (Exception ex) {
+ String message = String.format("dissociate Networks to vpn %s failed due to %s", input.getVpnId().
+ getValue(), ex.getMessage());
+ logger.error(message);
+ result.set(RpcResultBuilder.<DissociateNetworksOutput>failed().withError(ErrorType.APPLICATION, message)
+ .build());
+ }
+ logger.debug("dissociateNetworks returns..");
+ return result;
+ }
+
+ @Override
+ public Future<RpcResult<Void>> dissociateRouter(DissociateRouterInput input) {
+
+ SettableFuture<RpcResult<Void>> result = SettableFuture.create();
+
+ logger.debug("dissociateRouter {}", input);
+ StringBuilder returnMsg = new StringBuilder();
+ Uuid vpnId = input.getVpnId();
+ Uuid routerId = input.getRouterId();
+ try {
+ if (NeutronvpnUtils.getVpnMap(broker, vpnId) != null) {
+ if (routerId != null) {
+ Router rtr = NeutronvpnUtils.getNeutronRouter(broker, routerId);
+ if (rtr != null) {
+ dissociateRouterFromVpn(vpnId, routerId);
+ } else {
+ returnMsg.append("router not found : ").append(routerId.getValue());
+ }
+ }
+ } else {
+ returnMsg.append("VPN not found : ").append(vpnId.getValue());
+ }
+ if (returnMsg.length() != 0) {
+ String message = String.format("disssociate router %s to vpn %s failed due to %s", routerId.getValue(),
+ vpnId.getValue(), returnMsg);
+ logger.error(message);
+ String errorResponse = String.format("ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " +
+ message);
+ result.set(RpcResultBuilder.<Void>failed().withWarning(ErrorType.PROTOCOL, "invalid-value", message)
+ .build());
+ } else {
+ result.set(RpcResultBuilder.<Void>success().build());
+ }
+ } catch (Exception ex) {
+ String message = String.format("disssociate router %s to vpn %s failed due to %s", routerId.getValue(),
+ vpnId.getValue(), ex.getMessage());
+ logger.error(message);
+ result.set(RpcResultBuilder.<Void>failed().withError(ErrorType.APPLICATION, message).build());
+ }
+ logger.debug("dissociateRouter returns..");
+
+ return result;
+ }
+
+ private <T extends DataObject> Optional<T> read(LogicalDatastoreType datastoreType, InstanceIdentifier<T> path) {
+
+ ReadOnlyTransaction tx = broker.newReadOnlyTransaction();
+
+ Optional<T> result = Optional.absent();
+ try {
+ result = tx.read(datastoreType, path).get();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+
+ return result;
+ }
+
+ protected Subnet getNeutronSubnet(Uuid subnetId) {
+ InstanceIdentifier<Subnet> inst = InstanceIdentifier.create(Neutron.class).
+ child(Subnets.class).child(Subnet.class, new SubnetKey(subnetId));
+ Optional<Subnet> sn = read(LogicalDatastoreType.CONFIGURATION, inst);
+
+ if (sn.isPresent()) {
+ return sn.get();
+ }
+ return null;
+ }
+
+ protected IpAddress getNeutronSubnetGateway(Uuid subnetId) {
+ Subnet sn = getNeutronSubnet(subnetId);
+ if (null != sn) {
+ return sn.getGatewayIp();
+ }
+ return null;
+ }
+
+ protected Port getNeutronPort(String name) {
+ Uuid portId = NeutronvpnUtils.getNeutronPortIdfromPortName(broker, name);
+ if (portId != null) {
+ InstanceIdentifier<Port> pid = InstanceIdentifier.create(Neutron.class).
+ child(Ports.class).child(Port.class, new PortKey(portId));
+ Optional<Port> optPort = read(LogicalDatastoreType.CONFIGURATION, pid);
+ if (optPort.isPresent()) {
+ return optPort.get();
+ }
+ } else {
+ logger.error("Port {} not Found!!", name);
+ }
+ return null;
+ }
+
+ protected Port getNeutronPort(Uuid portId) {
+ InstanceIdentifier<Port> pid = InstanceIdentifier.create(Neutron.class).
+ child(Ports.class).child(Port.class, new PortKey(portId));
+ Optional<Port> optPort = read(LogicalDatastoreType.CONFIGURATION, pid);
+ if (optPort.isPresent()) {
+ return optPort.get();
+ }
+ return null;
+ }
+
+ protected List<Uuid> getSubnetsforVpn(Uuid vpnid) {
+ List<Uuid> subnets = new ArrayList<Uuid>();
+ //read subnetmaps
+ InstanceIdentifier<Subnetmaps> subnetmapsid = InstanceIdentifier.builder(Subnetmaps.class).build();
+ Optional<Subnetmaps> subnetmaps = read(LogicalDatastoreType.CONFIGURATION, subnetmapsid);
+ if (subnetmaps.isPresent()) {
+ Subnetmaps smaps = subnetmaps.get();
+ List<Subnetmap> subnetMapList = smaps.getSubnetmap();
+ for (Subnetmap subnetMap : subnetMapList) {
+ if (subnetMap.getVpnId() != null && subnetMap.getVpnId().equals(vpnid)) {
+ subnets.add(subnetMap.getId());
+ }
+ }
+ }
+ return subnets;
+ }
+
+ public List<String> showNeutronPortsCLI() {
+ List<String> result = new ArrayList<String>();
+ result.add(String.format(" %-22s %-22s %-22s %-6s ", "PortName", "Mac Address", "IP Address",
+ "Prefix Length"));
+ result.add("---------------------------------------------------------------------------------------");
+ InstanceIdentifier<Ports> portidentifier = InstanceIdentifier.create(Neutron.class).child(Ports.class);
+ try {
+ Optional<Ports> ports = read(LogicalDatastoreType.CONFIGURATION, portidentifier);
+ if (ports.isPresent()) {
+ List<Port> portList = ports.get().getPort();
+ for (Port port : portList) {
+ result.add(String.format(" %-22s %-22s %-22s %-6s ", NeutronvpnUtils.uuidToTapPortName(port
+ .getUuid()), port.getMacAddress(), port.getFixedIps().get(0).getIpAddress().getIpv4Address()
+ .getValue(), getIPPrefixFromPort(port)));
+ }
+ }
+ } catch (Exception e) {
+ logger.trace("Failed to retrieve neutronPorts info : ", e);
+ System.out.println("Failed to retrieve neutronPorts info : " + e.getMessage());
+ }
+ return result;
+ }
+
+ private Short getIPPrefixFromPort(Port port) {
+ Short prefix = new Short((short) 0);
+ String cidr = "";
+ try {
+ Uuid subnetUUID = port.getFixedIps().get(0).getSubnetId();
+
+ org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets
+ .SubnetKey subnetkey = new org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets
+ .rev150712.subnets.attributes.subnets.SubnetKey(subnetUUID);
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets
+ .attributes.subnets.Subnet> subnetidentifier = InstanceIdentifier.create(Neutron.class).child(org
+ .opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.Subnets
+ .class).child(org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets
+ .attributes.subnets.Subnet.class, subnetkey);
+ Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes
+ .subnets.Subnet> subnet = read(LogicalDatastoreType.CONFIGURATION, subnetidentifier);
+
+ if (subnet.isPresent()) {
+ cidr = subnet.get().getCidr();
+ // Extract the prefix length from cidr
+ String[] parts = cidr.split("/");
+ if ((parts.length == 2)) {
+ prefix = Short.valueOf(parts[1]);
+ return prefix;
+ } else {
+ logger.trace("Could not retrieve prefix from subnet CIDR");
+ System.out.println("Could not retrieve prefix from subnet CIDR");
+ }
+ } else {
+ logger.trace("Unable to read on subnet datastore");
+ }
+ } catch (Exception e) {
+ logger.trace("Failed to retrieve IP prefix from port : ", e);
+ System.out.println("Failed to retrieve IP prefix from port : " + e.getMessage());
+ }
+ return null;
+ }
+
+ public List<String> showVpnConfigCLI(Uuid vpnuuid) {
+ List<String> result = new ArrayList<String>();
+ if (vpnuuid == null) {
+ System.out.println("");
+ System.out.println("Displaying VPN config for all VPNs");
+ System.out.println("To display VPN config for a particular VPN, use the following syntax");
+ System.out.println(getshowVpnConfigCLIHelp());
+ }
+ try {
+ RpcResult<GetL3VPNOutput> rpcResult = getL3VPN(new GetL3VPNInputBuilder().setId(vpnuuid).build()).get();
+ if (rpcResult.isSuccessful()) {
+ result.add("");
+ result.add(String.format(" %-37s %-37s %-7s ", "VPN ID", "Tenant ID", "RD"));
+ result.add("");
+ result.add(String.format(" %-80s ", "Import-RTs"));
+ result.add("");
+ result.add(String.format(" %-80s ", "Export-RTs"));
+ result.add("");
+ result.add(String.format(" %-76s ", "Subnet IDs"));
+ result.add("");
+ result.add("------------------------------------------------------------------------------------");
+ result.add("");
+ List<L3vpnInstances> VpnList = rpcResult.getResult().getL3vpnInstances();
+ for (L3vpnInstance Vpn : VpnList) {
+ String tenantId = Vpn.getTenantId() != null ? Vpn.getTenantId().getValue() : "\" " +
+ " \"";
+ result.add(String.format(" %-37s %-37s %-7s ", Vpn.getId().getValue(), tenantId, Vpn
+ .getRouteDistinguisher()));
+ result.add("");
+ result.add(String.format(" %-80s ", Vpn.getImportRT()));
+ result.add("");
+ result.add(String.format(" %-80s ", Vpn.getExportRT()));
+ result.add("");
+
+ Uuid vpnid = Vpn.getId();
+ List<Uuid> subnetList = getSubnetsforVpn(vpnid);
+ if (!subnetList.isEmpty()) {
+ for (Uuid subnetuuid : subnetList) {
+ result.add(String.format(" %-76s ", subnetuuid.getValue()));
+ }
+ } else {
+ result.add(String.format(" %-76s ", "\" \""));
+ }
+ result.add("");
+ result.add("----------------------------------------");
+ result.add("");
+ }
+ } else {
+ String errortag = rpcResult.getErrors().iterator().next().getTag();
+ if (errortag == "") {
+ System.out.println("");
+ System.out.println("No VPN has been configured yet");
+ } else if (errortag == "invalid-value") {
+ System.out.println("");
+ System.out.println("VPN " + vpnuuid.getValue() + " is not present");
+ } else {
+ System.out.println("error getting VPN info : " + rpcResult.getErrors());
+ System.out.println(getshowVpnConfigCLIHelp());
+ }
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ logger.trace("error getting VPN info : ", e);
+ System.out.println("error getting VPN info : " + e.getMessage());
+ }
+ return result;
+ }
+
+ private String getshowVpnConfigCLIHelp() {
+ StringBuilder help = new StringBuilder("Usage:");
+ help.append("display vpn-config [-vid/--vpnid <id>]");
+ return help.toString();
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 - 2016 Ericsson India Global Services Pvt Ltd. 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.vpnservice.neutronvpn;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
+import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.vpnservice.neutronvpn.interfaces.INeutronVpnManager;
+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.rev130715.Uuid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.LockManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.NeutronvpnService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+
+public class NeutronvpnProvider implements BindingAwareProvider, INeutronVpnManager, AutoCloseable {
+
+ private static final Logger LOG = LoggerFactory.getLogger(NeutronvpnProvider.class);
+ private NeutronvpnManager nvManager;
+ private IMdsalApiManager mdsalManager;
+ private LockManagerService lockManager;
+ private NeutronBgpvpnChangeListener bgpvpnListener;
+ private NeutronNetworkChangeListener networkListener;
+ private NeutronSubnetChangeListener subnetListener;
+ private NeutronRouterChangeListener routerListener;
+ private NeutronPortChangeListener portListener;
+ private RpcProviderRegistry rpcProviderRegistry;
+
+ public NeutronvpnProvider(RpcProviderRegistry rpcRegistry) {
+ this.rpcProviderRegistry = rpcRegistry;
+ }
+
+ public RpcProviderRegistry getRpcProviderRegistry() {
+ return rpcProviderRegistry;
+ }
+
+ public void setRpcProviderRegistry(RpcProviderRegistry rpcProviderRegistry) {
+ this.rpcProviderRegistry = rpcProviderRegistry;
+ }
+
+ public void setMdsalManager(IMdsalApiManager mdsalManager) {
+ this.mdsalManager = mdsalManager;
+ }
+
+ public void setLockManager(LockManagerService lockManager) {
+ this.lockManager = lockManager;
+ }
+
+ @Override
+ public void onSessionInitiated(ProviderContext session) {
+ try {
+ final DataBroker dbx = session.getSALService(DataBroker.class);
+ nvManager = new NeutronvpnManager(dbx, mdsalManager);
+ final BindingAwareBroker.RpcRegistration<NeutronvpnService> rpcRegistration =
+ getRpcProviderRegistry().addRpcImplementation(NeutronvpnService.class, nvManager);
+ bgpvpnListener = new NeutronBgpvpnChangeListener(dbx, nvManager);
+ networkListener = new NeutronNetworkChangeListener(dbx, nvManager);
+ subnetListener = new NeutronSubnetChangeListener(dbx, nvManager);
+ routerListener = new NeutronRouterChangeListener(dbx, nvManager);
+ portListener = new NeutronPortChangeListener(dbx, nvManager);
+ nvManager.setLockManager(lockManager);
+
+ LOG.info("NeutronvpnProvider Session Initiated");
+ } catch (Exception e) {
+ LOG.error("Error initializing services", e);
+ }
+ }
+
+ @Override
+ public void close() throws Exception {
+ portListener.close();
+ subnetListener.close();
+ routerListener.close();
+ networkListener.close();
+ bgpvpnListener.close();
+ nvManager.close();
+ LOG.info("NeutronvpnProvider Closed");
+ }
+
+ @Override
+ public List<String> showNeutronPortsCLI() {
+ return nvManager.showNeutronPortsCLI();
+ }
+
+ @Override
+ public List<String> showVpnConfigCLI(Uuid vuuid) {
+ return nvManager.showVpnConfigCLI(vuuid);
+ }
+
+ @Override
+ public void addSubnetToVpn(Uuid vpnId, Uuid subnet) {
+ nvManager.addSubnetToVpn(vpnId, subnet);
+ }
+
+ @Override
+ public List<Uuid> getSubnetsforVpn(Uuid vpnid) {
+ return nvManager.getSubnetsforVpn(vpnid);
+ }
+
+ @Override
+ public void removeSubnetFromVpn(Uuid vpnId, Uuid subnet) {
+ nvManager.removeSubnetFromVpn(vpnId, subnet);
+ }
+
+ @Override
+ public Port getNeutronPort(String name) {
+ return nvManager.getNeutronPort(name);
+ }
+
+ @Override
+ public Subnet getNeutronSubnet(Uuid subnetId) {
+ return nvManager.getNeutronSubnet(subnetId);
+ }
+
+ @Override
+ public String uuidToTapPortName(Uuid id) {
+ return NeutronvpnUtils.uuidToTapPortName(id);
+ }
+
+ @Override
+ public Port getNeutronPort(Uuid portId) {
+ return nvManager.getNeutronPort(portId);
+ }
+
+ @Override
+ public IpAddress getNeutronSubnetGateway(Uuid subnetId) {
+ return nvManager.getNeutronSubnetGateway(subnetId);
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 - 2016 Ericsson India Global Services Pvt Ltd. 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.vpnservice.neutronvpn;
+
+import com.google.common.base.Optional;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.Routers;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.Router;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.RouterKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.Networks;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.NetworkKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.LockManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.TimeUnits;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.TryLockInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.TryLockInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.UnlockInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.UnlockInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.NeutronPortData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.Subnetmaps;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.VpnMaps;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.neutron.port.data
+ .PortFixedipToPortName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.neutron.port.data
+ .PortFixedipToPortNameKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.neutron.port.data
+ .PortNameToPortUuid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.neutron.port.data
+ .PortNameToPortUuidKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.subnetmaps.Subnetmap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.subnetmaps.SubnetmapKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.vpnmaps.VpnMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.vpnmaps.VpnMapKey;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+//import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.port.ext.rev151125.TrunkportExt;
+//import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.port.ext.rev151125.TrunkportTypeBase;
+//import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.port.ext.rev151125.TrunkportTypeSubport;
+
+public class NeutronvpnUtils {
+
+ private static final Logger logger = LoggerFactory.getLogger(NeutronvpnUtils.class);
+
+ protected static Subnetmap getSubnetmap(DataBroker broker, Uuid subnetId) {
+ InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).
+ child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
+ Optional<Subnetmap> sn = read(broker, LogicalDatastoreType.CONFIGURATION, id);
+
+ if (sn.isPresent()) {
+ return sn.get();
+ }
+ return null;
+ }
+
+ protected static VpnMap getVpnMap(DataBroker broker, Uuid id) {
+ InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
+ .child(VpnMap.class, new VpnMapKey(id)).build();
+ Optional<VpnMap> optionalVpnMap = read(broker, LogicalDatastoreType.CONFIGURATION,
+ vpnMapIdentifier);
+ if (optionalVpnMap.isPresent()) {
+ return optionalVpnMap.get();
+ }
+ logger.error("getVpnMap failed, VPN {} not present", id.getValue());
+ return null;
+ }
+
+ protected static Uuid getVpnForNetwork(DataBroker broker, Uuid network) {
+ InstanceIdentifier<VpnMaps> vpnMapsIdentifier = InstanceIdentifier.builder(VpnMaps.class).build();
+ Optional<VpnMaps> optionalVpnMaps = read(broker, LogicalDatastoreType.CONFIGURATION,
+ vpnMapsIdentifier);
+ if (optionalVpnMaps.isPresent()) {
+ VpnMaps vpnMaps = optionalVpnMaps.get();
+ List<VpnMap> allMaps = vpnMaps.getVpnMap();
+ for (VpnMap vpnMap : allMaps) {
+ if (vpnMap.getNetworkIds().contains(network)) {
+ return vpnMap.getVpnId();
+ }
+ }
+ }
+ return null;
+ }
+
+ protected static Uuid getVpnForRouter(DataBroker broker, Uuid router) {
+ InstanceIdentifier<VpnMaps> vpnMapsIdentifier = InstanceIdentifier.builder(VpnMaps.class).build();
+ Optional<VpnMaps> optionalVpnMaps = read(broker, LogicalDatastoreType.CONFIGURATION,
+ vpnMapsIdentifier);
+ if (optionalVpnMaps.isPresent()) {
+ VpnMaps vpnNets = optionalVpnMaps.get();
+ List<VpnMap> allMaps = vpnNets.getVpnMap();
+ if (router != null) {
+ for (VpnMap vpnMap : allMaps) {
+ if (router.equals(vpnMap.getRouterId())) {
+ return vpnMap.getVpnId();
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ protected static Uuid getRouterforVpn(DataBroker broker, Uuid vpnId) {
+ InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
+ .child(VpnMap.class, new VpnMapKey(vpnId)).build();
+ Optional<VpnMap> optionalVpnMap = read(broker, LogicalDatastoreType.CONFIGURATION,
+ vpnMapIdentifier);
+ if (optionalVpnMap.isPresent()) {
+ VpnMap vpnMap = optionalVpnMap.get();
+ return vpnMap.getRouterId();
+ }
+ return null;
+ }
+
+ protected static Uuid getNeutronPortIdfromPortName(DataBroker broker, String portname) {
+ InstanceIdentifier id = buildPortNameToPortUuidIdentifier(portname);
+ Optional<PortNameToPortUuid> portNameToPortUuidData = read(broker, LogicalDatastoreType.CONFIGURATION, id);
+ if (portNameToPortUuidData.isPresent()) {
+ return portNameToPortUuidData.get().getPortId();
+ }
+ return null;
+ }
+
+ protected static String getNeutronPortNamefromPortFixedIp(DataBroker broker, String fixedIp) {
+ InstanceIdentifier id = buildFixedIpToPortNameIdentifier(fixedIp);
+ Optional<PortFixedipToPortName> portFixedipToPortNameData = read(broker, LogicalDatastoreType.CONFIGURATION,
+ id);
+ if (portFixedipToPortNameData.isPresent()) {
+ return portFixedipToPortNameData.get().getPortName();
+ }
+ return null;
+ }
+
+ //TODO
+ //Will be done once integrated with TrunkPort Extensions
+ protected static int getVlanFromNeutronPort(Port port) {
+ int vlanId = 0;
+ /*
+ TrunkportExt trunkportExt = port.getAugmentation(TrunkportExt.class);
+ if (trunkportExt != null) {
+ Class<? extends TrunkportTypeBase> trunkportType = trunkportExt.getType();
+ if (trunkportType != null && trunkportType.isAssignableFrom(TrunkportTypeSubport.class)) {
+ vlanId = trunkportExt.getVid();
+ }
+ }
+ */
+ return vlanId;
+ }
+
+ protected static Router getNeutronRouter(DataBroker broker, Uuid routerId) {
+
+ InstanceIdentifier<Router> inst = InstanceIdentifier.create(Neutron.class).
+ child(Routers.class).child(Router.class, new RouterKey(routerId));
+
+ Optional<Router> rtr = read(broker, LogicalDatastoreType.CONFIGURATION, inst);
+ if (rtr.isPresent()) {
+ return rtr.get();
+ }
+ return null;
+ }
+
+ protected static Network getNeutronNetwork(DataBroker broker, Uuid networkId) {
+ logger.debug("getNeutronNetwork for {}", networkId.getValue());
+ InstanceIdentifier<Network> inst = InstanceIdentifier.create(Neutron.class).
+ child(Networks.class).child(Network.class, new NetworkKey(networkId));
+
+ Optional<Network> net = read(broker, LogicalDatastoreType.CONFIGURATION, inst);
+ if (net.isPresent()) {
+ return net.get();
+ }
+ return null;
+ }
+
+ protected static List<Uuid> getNeutronNetworkSubnetIds(DataBroker broker, Uuid networkId) {
+
+ logger.debug("getNeutronNetworkSubnetIds for {}", networkId.getValue());
+ Network network = getNeutronNetwork(broker, networkId);
+ if (network != null) {
+ //TODO
+ //return network.getSubnets();
+ }
+ logger.debug("returning from getNeutronNetworkSubnetIds for {}", networkId.getValue());
+
+ return null;
+ }
+
+ protected static List<Uuid> getNeutronRouterSubnetIds(DataBroker broker, Uuid routerId) {
+ logger.info("getNeutronRouterSubnetIds for {}", routerId.getValue());
+
+ List<Uuid> subnetNames = new ArrayList<Uuid>();
+ Router router = getNeutronRouter(broker, routerId);
+ if (router != null) {
+ List<org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.router
+ .Interfaces> ifs = router.getInterfaces();
+ if (!ifs.isEmpty()) {
+ for (org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers
+ .router.Interfaces iff : ifs) {
+ subnetNames.add(iff.getSubnetId());
+ }
+ }
+ }
+ logger.info("returning from getNeutronRouterSubnetIds for {}", routerId.getValue());
+ return subnetNames;
+ }
+
+ protected static String uuidToTapPortName(Uuid id) {
+ String tapId = id.getValue().substring(0, 11);
+ return new StringBuilder().append("tap").append(tapId).toString();
+ }
+
+ protected static void lockVpnInterface(LockManagerService lockManager, String vpnInterfaceName) {
+ TryLockInput input = new TryLockInputBuilder().setLockName(vpnInterfaceName).setTime(5L).setTimeUnit
+ (TimeUnits.Milliseconds).build();
+ Future<RpcResult<Void>> result = lockManager.tryLock(input);
+ try {
+ if ((result != null) && (result.get().isSuccessful())) {
+ logger.debug("Acquired lock for vpninterface {}", vpnInterfaceName);
+ } else {
+ throw new RuntimeException(String.format("Unable to getLock for vpninterface %s", vpnInterfaceName));
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ logger.error("Unable to getLock for vpninterface {}", vpnInterfaceName);
+ throw new RuntimeException(String.format("Unable to getLock for vpninterface %s", vpnInterfaceName), e
+ .getCause());
+ }
+ }
+
+ protected static void unlockVpnInterface(LockManagerService lockManager, String vpnInterfaceName) {
+ UnlockInput input = new UnlockInputBuilder().setLockName(vpnInterfaceName).build();
+ Future<RpcResult<Void>> result = lockManager.unlock(input);
+ try {
+ if ((result != null) && (result.get().isSuccessful())) {
+ logger.debug("Unlocked vpninterface{}", vpnInterfaceName);
+ } else {
+ logger.debug("Unable to unlock vpninterface {}", vpnInterfaceName);
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ logger.error("Unable to unlock vpninterface {}", vpnInterfaceName);
+ throw new RuntimeException(String.format("Unable to unlock vpninterface %s", vpnInterfaceName), e
+ .getCause());
+ }
+ }
+
+ static InstanceIdentifier<PortNameToPortUuid> buildPortNameToPortUuidIdentifier(String portname) {
+ InstanceIdentifier<PortNameToPortUuid> id =
+ InstanceIdentifier.builder(NeutronPortData.class).child(PortNameToPortUuid.class, new
+ PortNameToPortUuidKey(portname)).build();
+ return id;
+ }
+
+ static InstanceIdentifier<PortFixedipToPortName> buildFixedIpToPortNameIdentifier(String fixedIp) {
+ InstanceIdentifier<PortFixedipToPortName> id =
+ InstanceIdentifier.builder(NeutronPortData.class).child(PortFixedipToPortName.class, new
+ PortFixedipToPortNameKey(fixedIp)).build();
+ return id;
+ }
+
+ static InstanceIdentifier<Interface> buildVlanInterfaceIdentifier(String interfaceName) {
+ InstanceIdentifier<Interface> id = InstanceIdentifier.builder(Interfaces.class).child(Interface.class, new
+ InterfaceKey(interfaceName)).build();
+ return id;
+ }
+
+ static <T extends DataObject> Optional<T> read(DataBroker broker, LogicalDatastoreType datastoreType,
+ InstanceIdentifier<T> path) {
+
+ ReadOnlyTransaction tx = broker.newReadOnlyTransaction();
+
+ Optional<T> result = Optional.absent();
+ try {
+ result = tx.read(datastoreType, path).get();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+
+ return result;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2015-2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.neutronvpn.impl.rev150325;
+
+import org.opendaylight.vpnservice.neutronvpn.NeutronvpnProvider;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.LockManagerService;
+
+public class NeutronvpnImplModule extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.neutronvpn
+ .impl.rev150325.AbstractNeutronvpnImplModule {
+ public NeutronvpnImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight
+ .controller.config.api.DependencyResolver dependencyResolver) {
+ super(identifier, dependencyResolver);
+ }
+
+ public NeutronvpnImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight
+ .controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.yang.gen.v1.urn
+ .opendaylight.params.xml.ns.yang.neutronvpn.impl.rev150325.NeutronvpnImplModule 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() {
+ // TODO:implement
+ LockManagerService lockManagerService = getRpcRegistryDependency().getRpcService(LockManagerService.class);
+ NeutronvpnProvider provider = new NeutronvpnProvider(getRpcRegistryDependency());
+ provider.setMdsalManager(getMdsalutilDependency());
+ provider.setLockManager(lockManagerService);
+ getBrokerDependency().registerProvider(provider);
+ return provider;
+ }
+
+}
--- /dev/null
+/*
+* Generated file
+*
+* Generated from: yang module name: neutronvpn-impl yang module local name: neutronvpn-impl
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Thu Jan 06 10:51:12 IST 2015
+*
+* Do not modify this file unless it is present under src/main directory
+*/
+package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.neutronvpn.impl.rev150325;
+public class NeutronvpnImplModuleFactory extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.neutronvpn.impl.rev150325.AbstractNeutronvpnImplModuleFactory {
+
+}
--- /dev/null
+module neutronvpn-impl {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:neutronvpn:impl";
+ prefix "neutronvpn-impl";
+
+ import config { prefix config; revision-date 2013-04-05; }
+ import neutronvpn-api { prefix neutronvpn-api; revision-date 2015-08-12;}
+ import opendaylight-md-sal-binding { prefix md-sal-binding; revision-date 2013-10-28;}
+ import odl-mdsalutil { prefix odl-mdsal; revision-date 2015-04-10;}
+
+ description
+ "Service definition for neutronvpn project";
+
+ revision "2015-03-25" {
+ description
+ "Initial revision";
+ }
+
+ identity neutronvpn-impl {
+ base config:module-type;
+ config:provided-service neutronvpn-api:neutronvpn-api;
+ config:java-name-prefix NeutronvpnImpl;
+ }
+
+ augment "/config:modules/config:module/config:configuration" {
+ case neutronvpn-impl {
+ when "/config:modules/config:module/config:type = 'neutronvpn-impl'";
+ container broker {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity md-sal-binding:binding-broker-osgi-registry;
+ }
+ }
+ }
+ container rpc-registry {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity md-sal-binding:binding-rpc-registry;
+ }
+ }
+ }
+ container mdsalutil {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity odl-mdsal:odl-mdsalutil;
+ }
+ }
+ }
+ }
+ }
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: --><!--
+Copyright (c) 2015 - 2016 Ericsson India Global Services Pvt Ltd. 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">
+
+ <parent>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>config-parent</artifactId>
+ <version>0.2.0-SNAPSHOT</version>
+ <relativePath>../../commons/config-parent</relativePath>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>neutronvpn-shell</artifactId>
+ <version>${vpnservices.version}</version>
+ <packaging>bundle</packaging>
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>neutronvpn-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.karaf.shell</groupId>
+ <artifactId>org.apache.karaf.shell.console</artifactId>
+ <version>${karaf.shell.console.version}</version>
+ </dependency>
+ </dependencies>
+
+</project>
--- /dev/null
+/*
+ * Copyright (c) 2015 - 2016 Ericsson India Global Services Pvt Ltd. 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.vpnservice.neutronvpn.shell;
+
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+import org.apache.karaf.shell.console.OsgiCommandSupport;
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.vpnservice.neutronvpn.interfaces.INeutronVpnManager;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.CreateL3VPNInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.CreateL3VPNOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.DeleteL3VPNInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.DeleteL3VPNOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.NeutronvpnService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.createl3vpn.input.L3vpn;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.createl3vpn.input.L3vpnBuilder;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+@Command(scope = "vpnservice", name = "configure-l3vpn", description = "Create/Delete Neutron L3VPN")
+public class ConfigureL3VpnCommand extends OsgiCommandSupport {
+
+ final Logger Logger = LoggerFactory.getLogger(ConfigureL3VpnCommand.class);
+
+ private INeutronVpnManager neutronVpnManager;
+ private RpcProviderRegistry rpcProviderRegistry;
+ private NeutronvpnService neutronvpnService;
+
+ public void setNeutronVpnManager(INeutronVpnManager neutronVpnManager) {
+ this.neutronVpnManager = neutronVpnManager;
+ }
+
+ public void setRpcRegistry(RpcProviderRegistry rpcProviderRegistry) {
+ this.rpcProviderRegistry = rpcProviderRegistry;
+ }
+
+ @Option(name = "-op", aliases = {"--operation"}, description = "create-l3-vpn/delete-l3-vpn",
+ required = false, multiValued = false)
+ String op;
+
+ @Option(name = "-vid", aliases = {"--vpnid"}, description = "VPN ID", required = false, multiValued = false)
+ String vid;
+
+ @Option(name = "-n", aliases = {"--name"}, description = "VPN Name", required = false, multiValued = false)
+ String name;
+
+ @Option(name = "-tid", aliases = {"--tenantid"}, description = "Tenant ID", required = false, multiValued = false)
+ String tid;
+
+ @Option(name = "-rd", aliases = {"--rd"}, description = "Route Distinguisher", required = false, multiValued =
+ false)
+ String rd;
+
+ @Option(name = "-irt", aliases = {"--import-rts"}, description = "List of Import RTs", required = false,
+ multiValued = false)
+ String irt;
+
+ @Option(name = "-ert", aliases = {"--export-rts"}, description = "List of Export RTs", required = false,
+ multiValued = false)
+ String ert;
+
+ @Option(name = "-sid", aliases = {"--subnet-uuid"}, description = "List of Subnet IDs", required = false,
+ multiValued = false)
+ String sid;
+
+ @Override
+ protected Object doExecute() throws Exception {
+
+ if (rpcProviderRegistry != null) {
+ neutronvpnService = rpcProviderRegistry.getRpcService(NeutronvpnService.class);
+ if (neutronvpnService != null) {
+ if (op != null) {
+ switch (op) {
+ case "create-l3-vpn":
+ createL3VpnCLI();
+ break;
+ case "delete-l3-vpn":
+ deleteL3VpnCLI();
+ break;
+ default:
+ System.out.println("Invalid argument.");
+ System.out.println(getHelp(""));
+ break;
+ }
+ } else {
+ System.out.println("Too few arguments");
+ System.out.println(getHelp(""));
+ }
+ } else {
+ System.out.println("neutronvpnservice not initialized");
+ }
+ } else {
+ System.out.println("rpcProviderRegistryService not initialized");
+ }
+ return null;
+ }
+
+ public void createL3VpnCLI() {
+
+ if (vid == null) {
+ System.out.println("Please supply a valid VPN ID");
+ System.out.println(getHelp("create"));
+ return;
+ }
+
+ if (rd == null) {
+ System.out.println("Please supply a valid RD");
+ System.out.println(getHelp("create"));
+ return;
+ }
+
+ if (irt == null) {
+ System.out.println("Please supply a valid list of import RTs separated by {,}");
+ System.out.println(getHelp("create"));
+ return;
+ }
+
+ if (ert == null) {
+ System.out.println("Please supply a valid list of export RTs separated by {,}");
+ System.out.println(getHelp("create"));
+ return;
+ }
+
+ Uuid vuuid = new Uuid(vid);
+
+ try {
+ ArrayList<String> rdList = new ArrayList<String>(Arrays.asList(rd.split(",")));
+ ArrayList<String> irtList = new ArrayList<String>(Arrays.asList(irt.split(",")));
+ ArrayList<String> ertList = new ArrayList<String>(Arrays.asList(ert.split(",")));
+ Uuid tuuid = null;
+
+ if (tid != null) {
+ tuuid = new Uuid(tid);
+ }
+
+ List<L3vpn> l3vpns = new ArrayList<L3vpn>();
+ L3vpn l3vpn = new L3vpnBuilder().setId(vuuid).setName(name).setRouteDistinguisher(rdList).setImportRT
+ (irtList)
+ .setExportRT(ertList).setTenantId(tuuid).build();
+ l3vpns.add(l3vpn);
+ Future<RpcResult<CreateL3VPNOutput>> result =
+ neutronvpnService.createL3VPN(new CreateL3VPNInputBuilder().setL3vpn(l3vpns).build());
+ RpcResult<CreateL3VPNOutput> rpcResult = result.get();
+ if (rpcResult.isSuccessful()) {
+ System.out.println("L3VPN created successfully");
+ Logger.trace("createl3vpn: {}", result);
+ } else {
+ System.out.println("error populating createL3VPN : " + result.get().getErrors());
+ System.out.println(getHelp("create"));
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ Logger.trace("error populating createL3VPN", e);
+ System.out.println("error populating createL3VPN : " + e.getMessage());
+ System.out.println(getHelp("create"));
+ }
+
+ try {
+ List<Uuid> sidList = new ArrayList<Uuid>();
+
+ if (sid != null) {
+ for (String sidStr : sid.split(",")) {
+ Uuid suuid = new Uuid(sidStr);
+ sidList.add(suuid);
+ }
+ }
+ for (Uuid subnet : sidList) {
+ neutronVpnManager.addSubnetToVpn(vuuid, subnet);
+ }
+
+ } catch (Exception e) {
+ Logger.trace("error in adding subnet to VPN", e);
+ System.out.println("error in adding subnet to VPN : " + e.getMessage());
+ }
+ }
+
+ public void deleteL3VpnCLI() {
+
+ if (vid == null) {
+ System.out.println("Please supply a valid VPN ID");
+ System.out.println(getHelp("delete"));
+ return;
+ }
+ Uuid vpnid = new Uuid(vid);
+ try {
+ List<Uuid> sidList = neutronVpnManager.getSubnetsforVpn(vpnid);
+ if (sidList != null) {
+ for (Uuid subnet : sidList) {
+ neutronVpnManager.removeSubnetFromVpn(vpnid, subnet);
+ }
+ }
+ } catch (Exception e) {
+ Logger.trace("error in deleting subnet from VPN", e);
+ System.out.println("error in deleting subnet from VPN : " + e.getMessage());
+ }
+
+ try {
+ List<Uuid> vpnIdList = new ArrayList<Uuid>();
+ vpnIdList.add(vpnid);
+
+ Future<RpcResult<DeleteL3VPNOutput>> result =
+ neutronvpnService.deleteL3VPN(new DeleteL3VPNInputBuilder().setId(vpnIdList).build());
+ RpcResult<DeleteL3VPNOutput> rpcResult = result.get();
+ if (rpcResult.isSuccessful()) {
+ System.out.println("L3VPN deleted successfully");
+ Logger.trace("deletel3vpn: {}", result);
+ } else {
+ System.out.println("error populating deleteL3VPN : " + result.get().getErrors());
+ System.out.println(getHelp("delete"));
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ Logger.trace("error populating deleteL3VPN", e);
+ System.out.println("error populating deleteL3VPN : " + e.getMessage());
+ System.out.println(getHelp("delete"));
+ }
+ }
+
+ private String getHelp(String cmd) {
+ StringBuilder help = new StringBuilder("Usage:");
+ switch (cmd) {
+ case "create":
+ help.append("exec configure-vpn -op/--operation create-l3-vpn -vid/--vpnid <id>\n");
+ help.append("-rd/--rd <rd> -irt/--import-rts <irt1,irt2,..> -ert/--export-rts <ert1,ert2,..>\n");
+ help.append("[-sid/--subnet-uuid <subnet1,subnet2,..>]\n");
+ break;
+ case "delete":
+ help.append("exec configure-vpn -op/--operation delete-l3-vpn -vid/--vpnid <id> \n");
+ break;
+ case "":
+ help.append("exec configure-vpn -op/--operation create-l3-vpn -vid/--vpnid <id>\n");
+ help.append("-rd/--rd <rd> -irt/--import-rts <irt1,irt2,..> -ert/--export-rts <ert1,ert2,..>\n");
+ help.append("[-sid/--subnet-uuid <subnet1,subnet2,..>]\n");
+ help.append("exec configure-vpn -op/--operation delete-l3-vpn -vid/--vpnid <id> \n");
+ }
+ return help.toString();
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 - 2016 Ericsson India Global Services Pvt Ltd. 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.vpnservice.neutronvpn.shell;
+
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.console.OsgiCommandSupport;
+import org.opendaylight.vpnservice.neutronvpn.interfaces.INeutronVpnManager;
+
+@Command(scope = "vpnservice", name = "neutron-ports-show", description = "Displays neutron ports")
+public class ShowNeutronPortsCommand extends OsgiCommandSupport {
+ private INeutronVpnManager neutronVpnManager;
+
+ public void setNeutronVpnManager(INeutronVpnManager neutronVpnManager) {
+ this.neutronVpnManager = neutronVpnManager;
+ }
+
+ @Override
+ protected Object doExecute() throws Exception {
+ for (String p : neutronVpnManager.showNeutronPortsCLI()) {
+ System.out.println(p);
+ }
+ return null;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 - 2016 Ericsson India Global Services Pvt Ltd. 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.vpnservice.neutronvpn.shell;
+
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+import org.apache.karaf.shell.console.OsgiCommandSupport;
+import org.opendaylight.vpnservice.neutronvpn.interfaces.INeutronVpnManager;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
+
+@Command(scope = "vpnservice", name = "l3vpn-config-show", description = "Displays Neutron L3VPN configuration")
+public class ShowVpnConfigCommand extends OsgiCommandSupport {
+
+ @Option(name = "-vid", aliases = {"--vpnid"}, description = "VPN ID", required = false, multiValued = false)
+ String vid;
+
+ private INeutronVpnManager neutronVpnManager;
+
+ public void setNeutronVpnManager(INeutronVpnManager neutronVpnManager) {
+ this.neutronVpnManager = neutronVpnManager;
+ }
+
+ @Override
+ protected Object doExecute() throws Exception {
+
+ Uuid vuuid = null;
+ if (vid != null) {
+ vuuid = new Uuid(vid);
+ }
+
+ for (String p : neutronVpnManager.showVpnConfigCLI(vuuid)) {
+ System.out.println(p);
+ }
+ return null;
+ }
+}
--- /dev/null
+<!-- * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. 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
+-->
+
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
+
+ <reference id="neutronVpnManagerRef"
+ interface="org.opendaylight.vpnservice.neutronvpn.interfaces.INeutronVpnManager"
+ availability="optional"/>
+ <reference id="rpcRegistryRef" interface="org.opendaylight.controller.sal.binding.api.RpcProviderRegistry"
+ availability="optional"/>
+ <command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0">
+
+ <command>
+ <action class="org.opendaylight.vpnservice.neutronvpn.shell.ConfigureL3VpnCommand">
+ <property name="neutronVpnManager" ref="neutronVpnManagerRef"/>
+ <property name="rpcRegistry" ref="rpcRegistryRef"/>
+ </action>
+ </command>
+
+ <command>
+ <action class="org.opendaylight.vpnservice.neutronvpn.shell.ShowVpnConfigCommand">
+ <property name="neutronVpnManager" ref="neutronVpnManagerRef"/>
+ </action>
+ </command>
+
+ <command>
+ <action class="org.opendaylight.vpnservice.neutronvpn.shell.ShowNeutronPortsCommand">
+ <property name="neutronVpnManager" ref="neutronVpnManagerRef"/>
+ </action>
+ </command>
+
+ </command-bundle>
+
+</blueprint>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2015 - 2016 Ericsson India Global Services Pvt Ltd. 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 INTERNAL
+-->
+<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">
+
+ <parent>
+ <groupId>org.opendaylight.odlparent</groupId>
+ <artifactId>odlparent</artifactId>
+ <version>1.6.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>neutronvpn-aggregator</artifactId>
+ <version>0.2.0-SNAPSHOT</version>
+ <name>neutronvpn</name>
+ <packaging>pom</packaging>
+ <modelVersion>4.0.0</modelVersion>
+ <prerequisites>
+ <maven>3.1.1</maven>
+ </prerequisites>
+ <modules>
+ <module>neutronvpn-api</module>
+ <module>neutronvpn-impl</module>
+ <module>neutronvpn-shell</module>
+ </modules>
+ <!-- DO NOT install or deploy the repo root pom as it's only needed to initiate a build -->
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-deploy-plugin</artifactId>
+ <configuration>
+ <skip>true</skip>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-install-plugin</artifactId>
+ <configuration>
+ <skip>true</skip>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
<module>alivenessmonitor</module>
<module>fibmanager</module>
<module>bgpmanager</module>
+ <module>neutronvpn</module>
<module>dhcpservice</module>
<module>itm</module>
<module>distribution/karaf</module>