From 500bb7ab0d5b63f1acfb86328bc93140c31c33a9 Mon Sep 17 00:00:00 2001 From: Abhinav Gupta Date: Fri, 8 Jan 2016 17:24:42 +0530 Subject: [PATCH] Initial commit for NeutronVpn 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 --- commons/config-parent/pom.xml | 1 + features/pom.xml | 23 + features/src/main/features/features.xml | 4 + neutronvpn/neutronvpn-api/pom.xml | 54 + .../interfaces/INeutronVpnManager.java | 40 + .../src/main/yang/neutronvpn-api.yang | 20 + .../src/main/yang/neutronvpn.yang | 274 ++++ neutronvpn/neutronvpn-impl/pom.xml | 52 + .../src/main/config/default-config.xml | 55 + .../NeutronBgpvpnChangeListener.java | 152 ++ .../NeutronNetworkChangeListener.java | 90 ++ .../neutronvpn/NeutronPortChangeListener.java | 108 ++ .../NeutronRouterChangeListener.java | 144 ++ .../NeutronSubnetChangeListener.java | 89 + .../neutronvpn/NeutronvpnManager.java | 1430 +++++++++++++++++ .../neutronvpn/NeutronvpnProvider.java | 142 ++ .../neutronvpn/NeutronvpnUtils.java | 301 ++++ .../impl/rev150325/NeutronvpnImplModule.java | 44 + .../NeutronvpnImplModuleFactory.java | 13 + .../src/main/yang/neutronvpn-impl.yang | 54 + neutronvpn/neutronvpn-shell/pom.xml | 37 + .../shell/ConfigureL3VpnCommand.java | 251 +++ .../shell/ShowNeutronPortsCommand.java | 30 + .../shell/ShowVpnConfigCommand.java | 42 + .../OSGI-INF/blueprint/blueprint.xml | 38 + neutronvpn/pom.xml | 51 + pom.xml | 1 + 27 files changed, 3540 insertions(+) create mode 100644 neutronvpn/neutronvpn-api/pom.xml create mode 100644 neutronvpn/neutronvpn-api/src/main/java/org/opendaylight/vpnservice/neutronvpn/interfaces/INeutronVpnManager.java create mode 100644 neutronvpn/neutronvpn-api/src/main/yang/neutronvpn-api.yang create mode 100644 neutronvpn/neutronvpn-api/src/main/yang/neutronvpn.yang create mode 100644 neutronvpn/neutronvpn-impl/pom.xml create mode 100644 neutronvpn/neutronvpn-impl/src/main/config/default-config.xml create mode 100644 neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/vpnservice/neutronvpn/NeutronBgpvpnChangeListener.java create mode 100644 neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/vpnservice/neutronvpn/NeutronNetworkChangeListener.java create mode 100644 neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/vpnservice/neutronvpn/NeutronPortChangeListener.java create mode 100644 neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/vpnservice/neutronvpn/NeutronRouterChangeListener.java create mode 100644 neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/vpnservice/neutronvpn/NeutronSubnetChangeListener.java create mode 100644 neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/vpnservice/neutronvpn/NeutronvpnManager.java create mode 100644 neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/vpnservice/neutronvpn/NeutronvpnProvider.java create mode 100644 neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/vpnservice/neutronvpn/NeutronvpnUtils.java create mode 100644 neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/neutronvpn/impl/rev150325/NeutronvpnImplModule.java create mode 100644 neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/neutronvpn/impl/rev150325/NeutronvpnImplModuleFactory.java create mode 100644 neutronvpn/neutronvpn-impl/src/main/yang/neutronvpn-impl.yang create mode 100644 neutronvpn/neutronvpn-shell/pom.xml create mode 100644 neutronvpn/neutronvpn-shell/src/main/java/org/opendaylight/vpnservice/neutronvpn/shell/ConfigureL3VpnCommand.java create mode 100644 neutronvpn/neutronvpn-shell/src/main/java/org/opendaylight/vpnservice/neutronvpn/shell/ShowNeutronPortsCommand.java create mode 100644 neutronvpn/neutronvpn-shell/src/main/java/org/opendaylight/vpnservice/neutronvpn/shell/ShowVpnConfigCommand.java create mode 100644 neutronvpn/neutronvpn-shell/src/main/resources/OSGI-INF/blueprint/blueprint.xml create mode 100644 neutronvpn/pom.xml diff --git a/commons/config-parent/pom.xml b/commons/config-parent/pom.xml index a3fff3a8..1d357538 100644 --- a/commons/config-parent/pom.xml +++ b/commons/config-parent/pom.xml @@ -31,6 +31,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html 0.2.0-SNAPSHOT 1.2.1-SNAPSHOT 0.10.0-SNAPSHOT + 3.0.3 0.6.0-SNAPSHOT diff --git a/features/pom.xml b/features/pom.xml index 569c136b..87365a79 100644 --- a/features/pom.xml +++ b/features/pom.xml @@ -39,6 +39,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL ${vpnservices.version} ${vpnservices.version} ${vpnservices.version} + ${vpnservices.version} @@ -318,6 +319,28 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL dhcpservice-api ${vpnservices.version} + + ${project.groupId} + neutronvpn-api + ${neutronvpn.version} + + + ${project.groupId} + neutronvpn-impl + ${neutronvpn.version} + + + ${project.groupId} + neutronvpn-impl + ${neutronvpn.version} + config + xml + + + ${project.groupId} + neutronvpn-shell + ${neutronvpn.version} + org.apache.thrift libthrift diff --git a/features/src/main/features/features.xml b/features/src/main/features/features.xml index 7268183e..92e6865b 100644 --- a/features/src/main/features/features.xml +++ b/features/src/main/features/features.xml @@ -34,6 +34,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html mvn:org.opendaylight.vpnservice/vpnmanager-api/${vpnmanager.version} mvn:org.opendaylight.vpnservice/fibmanager-api/${fibmanager.version} mvn:org.opendaylight.vpnservice/itm-api/${itm.version} + mvn:org.opendaylight.vpnservice/neutronvpn-api/${neutronvpn.version} mvn:org.opendaylight.vpnservice/dhcpservice-api/${vpnservices.version} @@ -56,6 +57,8 @@ and is available at http://www.eclipse.org/legal/epl-v10.html mvn:org.opendaylight.vpnservice/vpnmanager-impl/${vpnmanager.version} mvn:org.opendaylight.vpnservice/fibmanager-impl/${fibmanager.version} mvn:org.opendaylight.vpnservice/itm-impl/${itm.version} + mvn:org.opendaylight.vpnservice/neutronvpn-impl/${neutronvpn.version} + mvn:org.opendaylight.vpnservice/neutronvpn-shell/${neutronvpn.version} mvn:org.opendaylight.vpnservice/dhcpservice-impl/${vpnservices.version} @@ -72,6 +75,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html mvn:org.opendaylight.vpnservice/vpnmanager-impl/${vpnmanager.version}/xml/config mvn:org.opendaylight.vpnservice/fibmanager-impl/${fibmanager.version}/xml/config mvn:org.opendaylight.vpnservice/itm-impl/${itm.version}/xml/config + mvn:org.opendaylight.vpnservice/neutronvpn-impl/${neutronvpn.version}/xml/config mvn:org.opendaylight.vpnservice/dhcpservice-impl/${vpnservices.version}/xml/config diff --git a/neutronvpn/neutronvpn-api/pom.xml b/neutronvpn/neutronvpn-api/pom.xml new file mode 100644 index 00000000..16d28cb8 --- /dev/null +++ b/neutronvpn/neutronvpn-api/pom.xml @@ -0,0 +1,54 @@ + + + + + org.opendaylight.vpnservice + config-parent + 0.2.0-SNAPSHOT + ../../commons/config-parent + + + 4.0.0 + org.opendaylight.vpnservice + neutronvpn-api + ${vpnservices.version} + bundle + + + + org.opendaylight.mdsal + yang-binding + ${yangtools.version} + + + org.opendaylight.yangtools + yang-common + ${yangtools.version} + + + org.opendaylight.neutron + model + ${neutron.version} + + + org.opendaylight.mdsal.model + ietf-yang-types + + + org.opendaylight.vpnservice + mdsalutil-api + ${vpns.mdsalutil.version} + + + org.opendaylight.controller + config-api + + + diff --git a/neutronvpn/neutronvpn-api/src/main/java/org/opendaylight/vpnservice/neutronvpn/interfaces/INeutronVpnManager.java b/neutronvpn/neutronvpn-api/src/main/java/org/opendaylight/vpnservice/neutronvpn/interfaces/INeutronVpnManager.java new file mode 100644 index 00000000..8da26707 --- /dev/null +++ b/neutronvpn/neutronvpn-api/src/main/java/org/opendaylight/vpnservice/neutronvpn/interfaces/INeutronVpnManager.java @@ -0,0 +1,40 @@ +/* + * 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 getSubnetsforVpn(Uuid vpnid); + + List showVpnConfigCLI(Uuid vuuid); + + List 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); + +} diff --git a/neutronvpn/neutronvpn-api/src/main/yang/neutronvpn-api.yang b/neutronvpn/neutronvpn-api/src/main/yang/neutronvpn-api.yang new file mode 100644 index 00000000..ae6935d4 --- /dev/null +++ b/neutronvpn/neutronvpn-api/src/main/yang/neutronvpn-api.yang @@ -0,0 +1,20 @@ +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"; + } +} diff --git a/neutronvpn/neutronvpn-api/src/main/yang/neutronvpn.yang b/neutronvpn/neutronvpn-api/src/main/yang/neutronvpn.yang new file mode 100644 index 00000000..c1785340 --- /dev/null +++ b/neutronvpn/neutronvpn-api/src/main/yang/neutronvpn.yang @@ -0,0 +1,274 @@ + +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 diff --git a/neutronvpn/neutronvpn-impl/pom.xml b/neutronvpn/neutronvpn-impl/pom.xml new file mode 100644 index 00000000..8f9e42a9 --- /dev/null +++ b/neutronvpn/neutronvpn-impl/pom.xml @@ -0,0 +1,52 @@ + + + + + + org.opendaylight.vpnservice + config-parent + 0.2.0-SNAPSHOT + ../../commons/config-parent + + + 4.0.0 + org.opendaylight.vpnservice + neutronvpn-impl + ${vpnservices.version} + bundle + + + org.opendaylight.neutron + model + ${neutron.version} + + + org.opendaylight.vpnservice + neutronvpn-api + ${vpnservices.version} + + + org.opendaylight.vpnservice + vpnmanager-api + ${vpnservices.version} + + + org.opendaylight.vpnservice + mdsalutil-api + ${vpnservices.version} + + + org.opendaylight.vpnservice + lockmanager-api + ${vpnservices.version} + + + + diff --git a/neutronvpn/neutronvpn-impl/src/main/config/default-config.xml b/neutronvpn/neutronvpn-impl/src/main/config/default-config.xml new file mode 100644 index 00000000..89820424 --- /dev/null +++ b/neutronvpn/neutronvpn-impl/src/main/config/default-config.xml @@ -0,0 +1,55 @@ + + + + + + urn:opendaylight:params:xml:ns:yang:neutronvpn:impl?module=neutronvpn-impl&revision=2015-03-25 + urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding?module=opendaylight-md-sal-binding&revision=2013-10-28 + urn:opendaylight:params:xml:ns:yang:mdsalutil:api?module=odl-mdsalutil&revision=2015-04-10 + + + + + + + prefix:neutronvpn-impl + + neutronvpn-default + + + binding:binding-broker-osgi-registry + + binding-osgi-broker + + + + binding:binding-rpc-registry + + binding-rpc-broker + + + + mdsalutil:odl-mdsalutil + + mdsalutil-service + + + + + + prefix:neutronvpn-api + + neutronvpn + /modules/module[type='neutronvpn-impl'][name='neutronvpn-default'] + + + + + + diff --git a/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/vpnservice/neutronvpn/NeutronBgpvpnChangeListener.java b/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/vpnservice/neutronvpn/NeutronBgpvpnChangeListener.java new file mode 100644 index 00000000..d413a321 --- /dev/null +++ b/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/vpnservice/neutronvpn/NeutronBgpvpnChangeListener.java @@ -0,0 +1,152 @@ +/* + * 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 implements AutoCloseable { + private static final Logger LOG = LoggerFactory.getLogger(NeutronBgpvpnChangeListener.class); + + private ListenerRegistration 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 identifier, Bgpvpn input) { + if (LOG.isTraceEnabled()) { + LOG.trace("Adding Bgpvpn : key: " + identifier + ", value=" + input); + } + // Create internal VPN + // handle route-target + List irt = new ArrayList(); + List ert = new ArrayList(); + List inrt = input.getRouteTargets(); + List inirt = input.getImportTargets(); + List 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 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 identifier, Bgpvpn input) { + if (LOG.isTraceEnabled()) { + LOG.trace("Removing Bgpvpn : key: " + identifier + ", value=" + input); + } + nvpnManager.removeL3Vpn(input.getUuid()); + + } + + @Override + protected void update(InstanceIdentifier identifier, Bgpvpn original, Bgpvpn update) { + List oldNetworks = original.getNetworks(); + List 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 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 diff --git a/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/vpnservice/neutronvpn/NeutronNetworkChangeListener.java b/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/vpnservice/neutronvpn/NeutronNetworkChangeListener.java new file mode 100644 index 00000000..e5bc67ef --- /dev/null +++ b/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/vpnservice/neutronvpn/NeutronNetworkChangeListener.java @@ -0,0 +1,90 @@ +/* + * 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 implements AutoCloseable { + private static final Logger LOG = LoggerFactory.getLogger(NeutronNetworkChangeListener.class); + + private ListenerRegistration 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 identifier, Network input) { + if (LOG.isTraceEnabled()) { + LOG.trace("Adding Network : key: " + identifier + ", value=" + input); + } + } + + @Override + protected void remove(InstanceIdentifier identifier, Network input) { + if (LOG.isTraceEnabled()) { + LOG.trace("Removing Network : key: " + identifier + ", value=" + input); + } + } + + @Override + protected void update(InstanceIdentifier identifier, Network original, Network update) { + if (LOG.isTraceEnabled()) { + LOG.trace("Updating Network : key: " + identifier + ", original value=" + original + ", update value=" + + update); + } + } + +} diff --git a/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/vpnservice/neutronvpn/NeutronPortChangeListener.java b/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/vpnservice/neutronvpn/NeutronPortChangeListener.java new file mode 100644 index 00000000..a615600a --- /dev/null +++ b/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/vpnservice/neutronvpn/NeutronPortChangeListener.java @@ -0,0 +1,108 @@ +/* + * 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 implements AutoCloseable { + private static final Logger LOG = LoggerFactory.getLogger(NeutronPortChangeListener.class); + + private ListenerRegistration 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 identifier, Port input) { + if (LOG.isTraceEnabled()) { + LOG.trace("Adding Port : key: " + identifier + ", value=" + input); + } + nvpnManager.handleNeutronPortCreated(input); + + } + + @Override + protected void remove(InstanceIdentifier identifier, Port input) { + if (LOG.isTraceEnabled()) { + LOG.trace("Removing Port : key: " + identifier + ", value=" + input); + } + nvpnManager.handleNeutronPortDeleted(input); + + } + + @Override + protected void update(InstanceIdentifier identifier, Port original, Port update) { + if (LOG.isTraceEnabled()) { + LOG.trace("Updating Port : key: " + identifier + ", original value=" + original + ", update value=" + + update); + } + List oldIPs = (original.getFixedIps() != null) ? original.getFixedIps() : new ArrayList(); + List newIPs = (update.getFixedIps() != null) ? update.getFixedIps() : new ArrayList(); + + if (!oldIPs.equals(newIPs)) { + Iterator iterator = newIPs.iterator(); + while (iterator.hasNext()) { + FixedIps ip = iterator.next(); + if (oldIPs.remove(ip)) { + iterator.remove(); + } + } + nvpnManager.handleNeutronPortUpdated(original, update); + } + } +} diff --git a/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/vpnservice/neutronvpn/NeutronRouterChangeListener.java b/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/vpnservice/neutronvpn/NeutronRouterChangeListener.java new file mode 100644 index 00000000..6d644851 --- /dev/null +++ b/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/vpnservice/neutronvpn/NeutronRouterChangeListener.java @@ -0,0 +1,144 @@ +/* + * 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 implements AutoCloseable { + private static final Logger LOG = LoggerFactory.getLogger(NeutronRouterChangeListener.class); + + private ListenerRegistration 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 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 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 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 oldInterfaces = (original.getInterfaces() != null) ? original.getInterfaces() : new + ArrayList(); + List newInterfaces = (update.getInterfaces() != null) ? update.getInterfaces() : new + ArrayList(); + List oldRoutes = (original.getRoutes() != null) ? original.getRoutes() : new ArrayList(); + List newRoutes = (update.getRoutes() != null) ? update.getRoutes() : new ArrayList(); + + 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 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); + } + } + } +} diff --git a/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/vpnservice/neutronvpn/NeutronSubnetChangeListener.java b/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/vpnservice/neutronvpn/NeutronSubnetChangeListener.java new file mode 100644 index 00000000..5eceab30 --- /dev/null +++ b/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/vpnservice/neutronvpn/NeutronSubnetChangeListener.java @@ -0,0 +1,89 @@ +/* + * 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 implements AutoCloseable { + private static final Logger LOG = LoggerFactory.getLogger(NeutronSubnetChangeListener.class); + + private ListenerRegistration 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 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 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 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); + } +} diff --git a/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/vpnservice/neutronvpn/NeutronvpnManager.java b/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/vpnservice/neutronvpn/NeutronvpnManager.java new file mode 100644 index 00000000..3a591375 --- /dev/null +++ b/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/vpnservice/neutronvpn/NeutronvpnManager.java @@ -0,0 +1,1430 @@ +/* + * 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 id = InstanceIdentifier.builder(Subnetmaps.class). + child(Subnetmap.class, new SubnetmapKey(subnetId)).build(); + Optional 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 portList = builder.getPortList(); + if (portList == null) { + portList = new ArrayList(); + } + 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 id = InstanceIdentifier.builder(Subnetmaps.class). + child(Subnetmap.class, new SubnetmapKey(subnetId)).build(); + Optional 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 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 rd, List irt, List ert) { + + try { + VpnInstanceBuilder builder = null; + List vpnTargetList = new ArrayList(); + InstanceIdentifier vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class). + child(VpnInstance.class, new VpnInstanceKey(name)).build(); + Optional 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 commonRT = new ArrayList(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 vpnMapsIdentifier = InstanceIdentifier.builder(VpnMaps.class).build(); + VpnMapsBuilder vpnMaps = new VpnMapsBuilder(); + MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, vpnMapsIdentifier, vpnMaps.build()); + InstanceIdentifier subnetmapsId = InstanceIdentifier.builder(Subnetmaps.class).build(); + SubnetmapsBuilder subnetmaps = new SubnetmapsBuilder(); + MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, subnetmapsId, subnetmaps.build()); + } + + private void deleteVpnMapsNode(Uuid vpnid) { + InstanceIdentifier 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 networks) { + VpnMapBuilder builder; + InstanceIdentifier vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class) + .child(VpnMap.class, new VpnMapKey(vpnId)).build(); + Optional 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 nwList = builder.getNetworkIds(); + if (nwList == null) { + nwList = new ArrayList(); + } + 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 networks) { + InstanceIdentifier vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class) + .child(VpnMap.class, new VpnMapKey(id)).build(); + Optional 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 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 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 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 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 adjList = new ArrayList(); + InstanceIdentifier 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 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 routeList = rtr.getRoutes(); + List 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 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 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 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 rd, List irt, List ert, + Uuid router, List 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> createL3VPN(CreateL3VPNInput input) { + + CreateL3VPNOutputBuilder opBuilder = new CreateL3VPNOutputBuilder(); + SettableFuture> result = SettableFuture.create(); + List errorList = new ArrayList(); + int failurecount = 0; + int warningcount = 0; + + List 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.failed().withRpcErrors(errorList).build()); + } else { + List 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.success().withResult(opBuilder.build()).build()); + } + return result; + } + + @Override + public Future> getL3VPN(GetL3VPNInput input) { + + GetL3VPNOutputBuilder opBuilder = new GetL3VPNOutputBuilder(); + SettableFuture> result = SettableFuture.create(); + Uuid inputVpnId = input.getId(); + List vpns = new ArrayList(); + + try { + if (inputVpnId == null) { + // get all vpns + InstanceIdentifier vpnsIdentifier = + InstanceIdentifier.builder(VpnInstances.class).build(); + Optional optionalVpns = read(LogicalDatastoreType.CONFIGURATION, vpnsIdentifier); + if (optionalVpns.isPresent()) { + for (VpnInstance vpn : optionalVpns.get().getVpnInstance()) { + vpns.add(vpn); + } + } else { + // No VPN present + result.set(RpcResultBuilder.failed() + .withWarning(ErrorType.PROTOCOL, "", "No VPN is present").build()); + return result; + } + } else { + String name = inputVpnId.getValue(); + InstanceIdentifier vpnIdentifier = + InstanceIdentifier.builder(VpnInstances.class) + .child(VpnInstance.class, new VpnInstanceKey(name)).build(); + // read VpnInstance Info + Optional 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.failed() + .withWarning(ErrorType.PROTOCOL, "invalid-value", message).build()); + } + } + List l3vpnList = new ArrayList(); + for (VpnInstance vpnInstance : vpns) { + Uuid vpnId = new Uuid(vpnInstance.getVpnInstanceName()); + // create VpnMaps id + InstanceIdentifier vpnMapIdentifier = + InstanceIdentifier.builder(VpnMaps.class) + .child(VpnMap.class, new VpnMapKey(vpnId)).build(); + L3vpnInstancesBuilder l3vpn = new L3vpnInstancesBuilder(); + + List rd = Arrays.asList(vpnInstance.getIpv4Family().getRouteDistinguisher().split(",")); + List vpnTargetList = vpnInstance.getIpv4Family().getVpnTargets().getVpnTarget(); + + List ertList = new ArrayList(); + List irtList = new ArrayList(); + + 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 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.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.failed().withError(ErrorType.APPLICATION, message).build()); + } + + return result; + } + + @Override + public Future> deleteL3VPN(DeleteL3VPNInput input) { + + DeleteL3VPNOutputBuilder opBuilder = new DeleteL3VPNOutputBuilder(); + SettableFuture> result = SettableFuture.create(); + List errorList = new ArrayList(); + + int failurecount = 0; + int warningcount = 0; + List vpns = input.getId(); + for (Uuid vpn : vpns) { + RpcError error; + String msg; + try { + InstanceIdentifier vpnIdentifier = + InstanceIdentifier.builder(VpnInstances.class) + .child(VpnInstance.class, new VpnInstanceKey(vpn.getValue())).build(); + Optional 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.failed().withRpcErrors(errorList).build()); + } else { + List 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.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 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 addAdjacencyforExtraRoute(List routeList, boolean rtrUp, String vpnifname) { + try { + List adjList = new ArrayList(); + 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 vpnIfIdentifier = InstanceIdentifier.builder(VpnInterfaces.class). + child(VpnInterface.class, new VpnInterfaceKey(ifname)).build(); + Optional 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 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 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 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 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 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 associateNetworksToVpn(Uuid vpn, List networks) { + List failed = new ArrayList(); + 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 networkSubnets = NeutronvpnUtils.getNeutronNetworkSubnetIds(broker, nw); + logger.debug("Adding network subnets..."); + if (networkSubnets != null) { + for (Uuid subnet : networkSubnets) { + addSubnetToVpn(vpn, subnet); + } + } + } + } + } + return failed; + } + + protected List dissociateNetworksFromVpn(Uuid vpn, List networks) { + List failed = new ArrayList(); + 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 networkSubnets = NeutronvpnUtils.getNeutronNetworkSubnetIds(broker, nw); + logger.debug("Removing network subnets..."); + for (Uuid subnet : networkSubnets) { + removeSubnetFromVpn(vpn, subnet); + } + } + } + } + return failed; + } + + @Override + public Future> associateNetworks(AssociateNetworksInput input) { + + AssociateNetworksOutputBuilder opBuilder = new AssociateNetworksOutputBuilder(); + SettableFuture> result = SettableFuture.create(); + logger.debug("associateNetworks {}", input); + StringBuilder returnMsg = new StringBuilder(); + Uuid vpnId = input.getVpnId(); + + try { + if (NeutronvpnUtils.getVpnMap(broker, vpnId) != null) { + List netIds = input.getNetworkId(); + if (netIds != null && !netIds.isEmpty()) { + List 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.success().withResult(opBuilder.build()).build()); + } else { + result.set(RpcResultBuilder.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.failed().withError(ErrorType.APPLICATION, message) + .build()); + } + logger.debug("associateNetworks returns.."); + return result; + } + + @Override + public Future> associateRouter(AssociateRouterInput input) { + + SettableFuture> 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.failed().withWarning(ErrorType.PROTOCOL, "invalid-value", message) + .build()); + } else { + result.set(RpcResultBuilder.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.failed().withError(ErrorType.APPLICATION, message).build()); + } + logger.debug("associateRouter returns.."); + return result; + } + + @Override + public Future> dissociateNetworks(DissociateNetworksInput input) { + + DissociateNetworksOutputBuilder opBuilder = new DissociateNetworksOutputBuilder(); + SettableFuture> result = SettableFuture.create(); + + logger.debug("dissociateNetworks {}", input); + StringBuilder returnMsg = new StringBuilder(); + Uuid vpnId = input.getVpnId(); + + try { + if (NeutronvpnUtils.getVpnMap(broker, vpnId) != null) { + List netIds = input.getNetworkId(); + if (netIds != null && !netIds.isEmpty()) { + List 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.success().withResult(opBuilder.build()).build()); + } else { + result.set(RpcResultBuilder.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.failed().withError(ErrorType.APPLICATION, message) + .build()); + } + logger.debug("dissociateNetworks returns.."); + return result; + } + + @Override + public Future> dissociateRouter(DissociateRouterInput input) { + + SettableFuture> 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.failed().withWarning(ErrorType.PROTOCOL, "invalid-value", message) + .build()); + } else { + result.set(RpcResultBuilder.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.failed().withError(ErrorType.APPLICATION, message).build()); + } + logger.debug("dissociateRouter returns.."); + + return result; + } + + private Optional read(LogicalDatastoreType datastoreType, InstanceIdentifier path) { + + ReadOnlyTransaction tx = broker.newReadOnlyTransaction(); + + Optional 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 inst = InstanceIdentifier.create(Neutron.class). + child(Subnets.class).child(Subnet.class, new SubnetKey(subnetId)); + Optional 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 pid = InstanceIdentifier.create(Neutron.class). + child(Ports.class).child(Port.class, new PortKey(portId)); + Optional 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 pid = InstanceIdentifier.create(Neutron.class). + child(Ports.class).child(Port.class, new PortKey(portId)); + Optional optPort = read(LogicalDatastoreType.CONFIGURATION, pid); + if (optPort.isPresent()) { + return optPort.get(); + } + return null; + } + + protected List getSubnetsforVpn(Uuid vpnid) { + List subnets = new ArrayList(); + //read subnetmaps + InstanceIdentifier subnetmapsid = InstanceIdentifier.builder(Subnetmaps.class).build(); + Optional subnetmaps = read(LogicalDatastoreType.CONFIGURATION, subnetmapsid); + if (subnetmaps.isPresent()) { + Subnetmaps smaps = subnetmaps.get(); + List subnetMapList = smaps.getSubnetmap(); + for (Subnetmap subnetMap : subnetMapList) { + if (subnetMap.getVpnId() != null && subnetMap.getVpnId().equals(vpnid)) { + subnets.add(subnetMap.getId()); + } + } + } + return subnets; + } + + public List showNeutronPortsCLI() { + List result = new ArrayList(); + result.add(String.format(" %-22s %-22s %-22s %-6s ", "PortName", "Mac Address", "IP Address", + "Prefix Length")); + result.add("---------------------------------------------------------------------------------------"); + InstanceIdentifier portidentifier = InstanceIdentifier.create(Neutron.class).child(Ports.class); + try { + Optional ports = read(LogicalDatastoreType.CONFIGURATION, portidentifier); + if (ports.isPresent()) { + List 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 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 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 showVpnConfigCLI(Uuid vpnuuid) { + List result = new ArrayList(); + 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 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 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 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 ]"); + return help.toString(); + } + +} diff --git a/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/vpnservice/neutronvpn/NeutronvpnProvider.java b/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/vpnservice/neutronvpn/NeutronvpnProvider.java new file mode 100644 index 00000000..ccfc14e8 --- /dev/null +++ b/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/vpnservice/neutronvpn/NeutronvpnProvider.java @@ -0,0 +1,142 @@ +/* + * 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 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 showNeutronPortsCLI() { + return nvManager.showNeutronPortsCLI(); + } + + @Override + public List showVpnConfigCLI(Uuid vuuid) { + return nvManager.showVpnConfigCLI(vuuid); + } + + @Override + public void addSubnetToVpn(Uuid vpnId, Uuid subnet) { + nvManager.addSubnetToVpn(vpnId, subnet); + } + + @Override + public List 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); + } + +} diff --git a/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/vpnservice/neutronvpn/NeutronvpnUtils.java b/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/vpnservice/neutronvpn/NeutronvpnUtils.java new file mode 100644 index 00000000..12bd6583 --- /dev/null +++ b/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/vpnservice/neutronvpn/NeutronvpnUtils.java @@ -0,0 +1,301 @@ +/* + * 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 id = InstanceIdentifier.builder(Subnetmaps.class). + child(Subnetmap.class, new SubnetmapKey(subnetId)).build(); + Optional sn = read(broker, LogicalDatastoreType.CONFIGURATION, id); + + if (sn.isPresent()) { + return sn.get(); + } + return null; + } + + protected static VpnMap getVpnMap(DataBroker broker, Uuid id) { + InstanceIdentifier vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class) + .child(VpnMap.class, new VpnMapKey(id)).build(); + Optional 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 vpnMapsIdentifier = InstanceIdentifier.builder(VpnMaps.class).build(); + Optional optionalVpnMaps = read(broker, LogicalDatastoreType.CONFIGURATION, + vpnMapsIdentifier); + if (optionalVpnMaps.isPresent()) { + VpnMaps vpnMaps = optionalVpnMaps.get(); + List 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 vpnMapsIdentifier = InstanceIdentifier.builder(VpnMaps.class).build(); + Optional optionalVpnMaps = read(broker, LogicalDatastoreType.CONFIGURATION, + vpnMapsIdentifier); + if (optionalVpnMaps.isPresent()) { + VpnMaps vpnNets = optionalVpnMaps.get(); + List 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 vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class) + .child(VpnMap.class, new VpnMapKey(vpnId)).build(); + Optional 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 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 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 trunkportType = trunkportExt.getType(); + if (trunkportType != null && trunkportType.isAssignableFrom(TrunkportTypeSubport.class)) { + vlanId = trunkportExt.getVid(); + } + } + */ + return vlanId; + } + + protected static Router getNeutronRouter(DataBroker broker, Uuid routerId) { + + InstanceIdentifier inst = InstanceIdentifier.create(Neutron.class). + child(Routers.class).child(Router.class, new RouterKey(routerId)); + + Optional 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 inst = InstanceIdentifier.create(Neutron.class). + child(Networks.class).child(Network.class, new NetworkKey(networkId)); + + Optional net = read(broker, LogicalDatastoreType.CONFIGURATION, inst); + if (net.isPresent()) { + return net.get(); + } + return null; + } + + protected static List 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 getNeutronRouterSubnetIds(DataBroker broker, Uuid routerId) { + logger.info("getNeutronRouterSubnetIds for {}", routerId.getValue()); + + List subnetNames = new ArrayList(); + Router router = getNeutronRouter(broker, routerId); + if (router != null) { + List 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> 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> 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 buildPortNameToPortUuidIdentifier(String portname) { + InstanceIdentifier id = + InstanceIdentifier.builder(NeutronPortData.class).child(PortNameToPortUuid.class, new + PortNameToPortUuidKey(portname)).build(); + return id; + } + + static InstanceIdentifier buildFixedIpToPortNameIdentifier(String fixedIp) { + InstanceIdentifier id = + InstanceIdentifier.builder(NeutronPortData.class).child(PortFixedipToPortName.class, new + PortFixedipToPortNameKey(fixedIp)).build(); + return id; + } + + static InstanceIdentifier buildVlanInterfaceIdentifier(String interfaceName) { + InstanceIdentifier id = InstanceIdentifier.builder(Interfaces.class).child(Interface.class, new + InterfaceKey(interfaceName)).build(); + return id; + } + + static Optional read(DataBroker broker, LogicalDatastoreType datastoreType, + InstanceIdentifier path) { + + ReadOnlyTransaction tx = broker.newReadOnlyTransaction(); + + Optional result = Optional.absent(); + try { + result = tx.read(datastoreType, path).get(); + } catch (Exception e) { + throw new RuntimeException(e); + } + + return result; + } + +} diff --git a/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/neutronvpn/impl/rev150325/NeutronvpnImplModule.java b/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/neutronvpn/impl/rev150325/NeutronvpnImplModule.java new file mode 100644 index 00000000..c6b556df --- /dev/null +++ b/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/neutronvpn/impl/rev150325/NeutronvpnImplModule.java @@ -0,0 +1,44 @@ +/* + * 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; + } + +} diff --git a/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/neutronvpn/impl/rev150325/NeutronvpnImplModuleFactory.java b/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/neutronvpn/impl/rev150325/NeutronvpnImplModuleFactory.java new file mode 100644 index 00000000..d54bef15 --- /dev/null +++ b/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/neutronvpn/impl/rev150325/NeutronvpnImplModuleFactory.java @@ -0,0 +1,13 @@ +/* +* 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 { + +} diff --git a/neutronvpn/neutronvpn-impl/src/main/yang/neutronvpn-impl.yang b/neutronvpn/neutronvpn-impl/src/main/yang/neutronvpn-impl.yang new file mode 100644 index 00000000..dafd23ad --- /dev/null +++ b/neutronvpn/neutronvpn-impl/src/main/yang/neutronvpn-impl.yang @@ -0,0 +1,54 @@ +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; + } + } + } + } + } +} diff --git a/neutronvpn/neutronvpn-shell/pom.xml b/neutronvpn/neutronvpn-shell/pom.xml new file mode 100644 index 00000000..4be86556 --- /dev/null +++ b/neutronvpn/neutronvpn-shell/pom.xml @@ -0,0 +1,37 @@ + + + + + + org.opendaylight.vpnservice + config-parent + 0.2.0-SNAPSHOT + ../../commons/config-parent + + + 4.0.0 + org.opendaylight.vpnservice + neutronvpn-shell + ${vpnservices.version} + bundle + + + org.opendaylight.vpnservice + neutronvpn-api + ${vpnservices.version} + + + org.apache.karaf.shell + org.apache.karaf.shell.console + ${karaf.shell.console.version} + + + + diff --git a/neutronvpn/neutronvpn-shell/src/main/java/org/opendaylight/vpnservice/neutronvpn/shell/ConfigureL3VpnCommand.java b/neutronvpn/neutronvpn-shell/src/main/java/org/opendaylight/vpnservice/neutronvpn/shell/ConfigureL3VpnCommand.java new file mode 100644 index 00000000..01bfeb11 --- /dev/null +++ b/neutronvpn/neutronvpn-shell/src/main/java/org/opendaylight/vpnservice/neutronvpn/shell/ConfigureL3VpnCommand.java @@ -0,0 +1,251 @@ +/* + * 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 rdList = new ArrayList(Arrays.asList(rd.split(","))); + ArrayList irtList = new ArrayList(Arrays.asList(irt.split(","))); + ArrayList ertList = new ArrayList(Arrays.asList(ert.split(","))); + Uuid tuuid = null; + + if (tid != null) { + tuuid = new Uuid(tid); + } + + List l3vpns = new ArrayList(); + L3vpn l3vpn = new L3vpnBuilder().setId(vuuid).setName(name).setRouteDistinguisher(rdList).setImportRT + (irtList) + .setExportRT(ertList).setTenantId(tuuid).build(); + l3vpns.add(l3vpn); + Future> result = + neutronvpnService.createL3VPN(new CreateL3VPNInputBuilder().setL3vpn(l3vpns).build()); + RpcResult 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 sidList = new ArrayList(); + + 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 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 vpnIdList = new ArrayList(); + vpnIdList.add(vpnid); + + Future> result = + neutronvpnService.deleteL3VPN(new DeleteL3VPNInputBuilder().setId(vpnIdList).build()); + RpcResult 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 \n"); + help.append("-rd/--rd -irt/--import-rts -ert/--export-rts \n"); + help.append("[-sid/--subnet-uuid ]\n"); + break; + case "delete": + help.append("exec configure-vpn -op/--operation delete-l3-vpn -vid/--vpnid \n"); + break; + case "": + help.append("exec configure-vpn -op/--operation create-l3-vpn -vid/--vpnid \n"); + help.append("-rd/--rd -irt/--import-rts -ert/--export-rts \n"); + help.append("[-sid/--subnet-uuid ]\n"); + help.append("exec configure-vpn -op/--operation delete-l3-vpn -vid/--vpnid \n"); + } + return help.toString(); + } + +} diff --git a/neutronvpn/neutronvpn-shell/src/main/java/org/opendaylight/vpnservice/neutronvpn/shell/ShowNeutronPortsCommand.java b/neutronvpn/neutronvpn-shell/src/main/java/org/opendaylight/vpnservice/neutronvpn/shell/ShowNeutronPortsCommand.java new file mode 100644 index 00000000..cf4736e4 --- /dev/null +++ b/neutronvpn/neutronvpn-shell/src/main/java/org/opendaylight/vpnservice/neutronvpn/shell/ShowNeutronPortsCommand.java @@ -0,0 +1,30 @@ +/* + * 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; + } +} diff --git a/neutronvpn/neutronvpn-shell/src/main/java/org/opendaylight/vpnservice/neutronvpn/shell/ShowVpnConfigCommand.java b/neutronvpn/neutronvpn-shell/src/main/java/org/opendaylight/vpnservice/neutronvpn/shell/ShowVpnConfigCommand.java new file mode 100644 index 00000000..8801af35 --- /dev/null +++ b/neutronvpn/neutronvpn-shell/src/main/java/org/opendaylight/vpnservice/neutronvpn/shell/ShowVpnConfigCommand.java @@ -0,0 +1,42 @@ +/* + * 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; + } +} diff --git a/neutronvpn/neutronvpn-shell/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/neutronvpn/neutronvpn-shell/src/main/resources/OSGI-INF/blueprint/blueprint.xml new file mode 100644 index 00000000..80cff049 --- /dev/null +++ b/neutronvpn/neutronvpn-shell/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/neutronvpn/pom.xml b/neutronvpn/pom.xml new file mode 100644 index 00000000..18814e09 --- /dev/null +++ b/neutronvpn/pom.xml @@ -0,0 +1,51 @@ + + + + + + org.opendaylight.odlparent + odlparent + 1.6.0-SNAPSHOT + + + + org.opendaylight.vpnservice + neutronvpn-aggregator + 0.2.0-SNAPSHOT + neutronvpn + pom + 4.0.0 + + 3.1.1 + + + neutronvpn-api + neutronvpn-impl + neutronvpn-shell + + + + + + org.apache.maven.plugins + maven-deploy-plugin + + true + + + + org.apache.maven.plugins + maven-install-plugin + + true + + + + + diff --git a/pom.xml b/pom.xml index 19bcaaa3..0fdc1a45 100644 --- a/pom.xml +++ b/pom.xml @@ -28,6 +28,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL alivenessmonitor fibmanager bgpmanager + neutronvpn dhcpservice itm distribution/karaf -- 2.36.6