BGPVPN optional RD,L3 Type and Union of routelist 96/41696/6
authorsathish kumar B T <sathish.kumar.tippeshappa@ericsson.com>
Tue, 12 Jul 2016 07:03:07 +0000 (12:33 +0530)
committerSam Hague <shague@redhat.com>
Sat, 16 Jul 2016 15:34:04 +0000 (11:34 -0400)
Update to use idmanager form genius

Change-Id: I11c258d8f58ac6531b26f0f979dd93a863895da9
Signed-off-by: sathish kumar B T <sathish.kumar.tippeshappa@ericsson.com>
Signed-off-by: Sam Hague <shague@redhat.com>
vpnservice/neutronvpn/neutronvpn-impl/pom.xml
vpnservice/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronBgpvpnChangeListener.java
vpnservice/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronConstants.java
vpnservice/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronvpnProvider.java
vpnservice/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronvpnUtils.java

index e901e17082adfe65f8d4a050e60da05c92d72d04..57069d71eea4254d852ec6368f5e2f15f585fd7b 100644 (file)
@@ -72,6 +72,11 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
             <artifactId>aclservice-api</artifactId>
             <version>${vpnservices.version}</version>
         </dependency>
+        <dependency>
+            <groupId>org.opendaylight.genius</groupId>
+            <artifactId>idmanager-api</artifactId>
+            <version>${genius.version}</version>
+        </dependency>
     </dependencies>
 
     <!--
index 818fd8710a0abdcc48d31bc2142d9214a07d89b6..55a53f989f0d59067f5df947e353785e7a240046 100644 (file)
@@ -17,15 +17,30 @@ import org.opendaylight.genius.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.bgpvpns.rev150903.BgpvpnTypeBase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.bgpvpns.rev150903.BgpvpnTypeL3;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMap;
 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.opendaylight.yangtools.yang.common.RpcResult;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
+import java.math.BigInteger;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
 
 
 public class NeutronBgpvpnChangeListener extends AbstractDataChangeListener<Bgpvpn> implements AutoCloseable {
@@ -33,12 +48,18 @@ public class NeutronBgpvpnChangeListener extends AbstractDataChangeListener<Bgpv
 
     private ListenerRegistration<DataChangeListener> listenerRegistration;
     private NeutronvpnManager nvpnManager;
+    private IdManagerService idManager;
+    private String adminRDValue;
+    private DataBroker dbroker;
 
 
     public NeutronBgpvpnChangeListener(final DataBroker db, NeutronvpnManager nVpnMgr) {
         super(Bgpvpn.class);
         nvpnManager = nVpnMgr;
+        dbroker = db;
         registerListener(db);
+        BundleContext bundleContext=FrameworkUtil.getBundle(NeutronBgpvpnChangeListener.class).getBundleContext();
+        adminRDValue = bundleContext.getProperty(NeutronConstants.RD_PROPERTY_KEY);
     }
 
     @Override
@@ -66,40 +87,80 @@ public class NeutronBgpvpnChangeListener extends AbstractDataChangeListener<Bgpv
         }
     }
 
+    public void setIdManager(IdManagerService idManager) {
+        this.idManager = idManager;
+        createIdPool();
+    }
+
+    private boolean isBgpvpnTypeL3(Class<? extends BgpvpnTypeBase> bgpvpnType) {
+        if (BgpvpnTypeL3.class.equals(bgpvpnType)) {
+            return true;
+        } else {
+            LOG.warn("CRUD operations supported only for L3 type Bgpvpn");
+            return false;
+        }
+    }
+
     @Override
     protected void add(InstanceIdentifier<Bgpvpn> identifier, Bgpvpn input) {
         if (LOG.isTraceEnabled()) {
             LOG.trace("Adding Bgpvpn : key: " + identifier + ", value=" + input);
         }
-        // Create internal VPN
-        // handle route-target
-        List<String> irt = new ArrayList<>();
-        List<String> ert = new ArrayList<>();
-        List<String> inrt = input.getRouteTargets();
-        List<String> inirt = input.getImportTargets();
-        List<String> inert = input.getExportTargets();
-        if (inrt != null && !inrt.isEmpty()) {
-            irt.addAll(inrt);
-            ert.addAll(inrt);
-        }
-        if (inirt != null && !inirt.isEmpty()) {
-            irt.addAll(inirt);
-        }
-        if (inert != null && !inert.isEmpty()) {
-            ert.addAll(inert);
-        }
-        List<String> rd = input.getRouteDistinguishers();
+        if (isBgpvpnTypeL3(input.getType())) {
+            // Create internal VPN
+            // handle route-target
+            List<String> importRouteTargets = new ArrayList<>();
+            List<String> exportRouteTargets = new ArrayList<>();
+            List<String> inputRouteList = input.getRouteTargets();
+            List<String> inputImportRouteList = input.getImportTargets();
+            List<String> inputExportRouteList = input.getExportTargets();
+            if (inputRouteList != null && !inputRouteList.isEmpty()) {
+                importRouteTargets.addAll(inputRouteList);
+                exportRouteTargets.addAll(inputRouteList);
+            }
+            if (inputImportRouteList != null && !inputImportRouteList.isEmpty()) {
+                importRouteTargets.addAll(inputImportRouteList);
+            }
+            if (inputExportRouteList != null && !inputExportRouteList.isEmpty()) {
+                exportRouteTargets.addAll(inputExportRouteList);
+            }
+            List<String> rd = input.getRouteDistinguishers();
 
-        if (rd == null || rd.isEmpty()) {
-            // generate new RD
+            if (rd == null || rd.isEmpty()) {
+                // generate new RD
+                rd = generateNewRD(input.getUuid());
+            }else {
+                String[] rdParams = rd.get(0).split(":");
+                if (rdParams[0].trim().equals(adminRDValue)) {
+                    LOG.error("AS specific part of RD should not be same as that defined by DC Admin");
+                    return;
+                }
+            }
+            Uuid router = null;
+            if (input.getRouters() != null && !input.getRouters().isEmpty()) {
+                // currently only one router
+                router = input.getRouters().get(0);
+            }
+            if (rd != null) {
+                nvpnManager.createL3Vpn(input.getUuid(), input.getName(), input.getTenantId(), rd,
+                        importRouteTargets, exportRouteTargets, router, input.getNetworks());
+            }else {
+                LOG.error("Create BgpVPN with id " + input.getUuid() + " failed due to missing/invalid RD value.");
+            }
         }
-        Uuid router = null;
-        if (input.getRouters() != null && !input.getRouters().isEmpty()) {
-            // currently only one router
-            router = input.getRouters().get(0);
+
+    }
+
+    private List<String> generateNewRD(Uuid vpn) {
+        List<String> rd = null;
+        if (adminRDValue != null) {
+            Integer rdId = NeutronvpnUtils.getUniqueRDId(idManager, NeutronConstants.RD_IDPOOL_NAME, vpn.toString());
+            if (rdId != null) {
+                rd = new ArrayList<>(Arrays.asList(adminRDValue + ":" + rdId));
+            }
+            LOG.debug("Generated RD " + rd.get(0) + " for L3VPN " + vpn);
         }
-        nvpnManager.createL3Vpn(input.getUuid(), input.getName(), input.getTenantId(),
-                rd, irt, ert, router, input.getNetworks());
+        return rd;
     }
 
     @Override
@@ -107,17 +168,32 @@ public class NeutronBgpvpnChangeListener extends AbstractDataChangeListener<Bgpv
         if (LOG.isTraceEnabled()) {
             LOG.trace("Removing Bgpvpn : key: " + identifier + ", value=" + input);
         }
-        nvpnManager.removeL3Vpn(input.getUuid());
+        if (isBgpvpnTypeL3(input.getType())) {
+            nvpnManager.removeL3Vpn(input.getUuid());
+            NeutronvpnUtils.releaseRDId(idManager, NeutronConstants.RD_IDPOOL_NAME, input.getUuid().toString());
+        }
+
 
     }
 
     @Override
     protected void update(InstanceIdentifier<Bgpvpn> identifier, Bgpvpn original, Bgpvpn update) {
-        List<Uuid> oldNetworks = original.getNetworks();
-        List<Uuid> newNetworks = update.getNetworks();
         if (LOG.isTraceEnabled()) {
             LOG.trace("Update Bgpvpn : key: " + identifier + ", value=" + update);
         }
+        if (isBgpvpnTypeL3(update.getType())) {
+            List<Uuid> oldNetworks = original.getNetworks();
+            List<Uuid> newNetworks = update.getNetworks();
+            List<Uuid> oldRouters = original.getRouters();
+            List<Uuid> newRouters = update.getRouters();
+            Uuid vpnId = update.getUuid();
+            handleNetworksUpdate(vpnId, oldNetworks, newNetworks);
+            handleRoutersUpdate(vpnId, oldRouters, newRouters);
+
+        }
+    }
+
+    protected void handleNetworksUpdate(Uuid vpnId, List<Uuid> oldNetworks, List<Uuid> newNetworks) {
         if (newNetworks != null && !newNetworks.isEmpty()) {
             if (oldNetworks != null && !oldNetworks.isEmpty()) {
                 if (oldNetworks != newNetworks) {
@@ -132,26 +208,72 @@ public class NeutronBgpvpnChangeListener extends AbstractDataChangeListener<Bgpv
                     //clear removed networks
                     if (!oldNetworks.isEmpty()) {
                         LOG.trace("Removing old networks {} ", oldNetworks);
-                        nvpnManager.dissociateNetworksFromVpn(update.getUuid(), oldNetworks);
+                        nvpnManager.dissociateNetworksFromVpn(vpnId, oldNetworks);
                     }
+
                     //add new (Delta) Networks
                     if (!newNetworks.isEmpty()) {
                         LOG.trace("Adding delta New networks {} ", newNetworks);
-                        nvpnManager.associateNetworksToVpn(update.getUuid(), newNetworks);
+                        nvpnManager.associateNetworksToVpn(vpnId, newNetworks);
                     }
                 }
             } else {
                 //add new Networks
                 LOG.trace("Adding New networks {} ", newNetworks);
-                nvpnManager.associateNetworksToVpn(update.getUuid(), newNetworks);
+                nvpnManager.associateNetworksToVpn(vpnId, newNetworks);
             }
-        } else {
-            if (oldNetworks != null && !oldNetworks.isEmpty()) {
-                LOG.trace("Removing old networks {} ", oldNetworks);
-                nvpnManager.dissociateNetworksFromVpn(update.getUuid(), oldNetworks);
+        } else if (oldNetworks != null && !oldNetworks.isEmpty()) {
+            LOG.trace("Removing old networks {} ", oldNetworks);
+            nvpnManager.dissociateNetworksFromVpn(vpnId, oldNetworks);
+
+        }
+    }
+
+    protected void handleRoutersUpdate(Uuid vpnId, List<Uuid> oldRouters, List<Uuid> newRouters) {
+        if (newRouters != null && !newRouters.isEmpty()) {
+            if (oldRouters != null && !oldRouters.isEmpty()) {
+                if (oldRouters.size() > 1 || newRouters.size() > 1) {
+                    VpnMap vpnMap = NeutronvpnUtils.getVpnMap(dbroker, vpnId);
+                    if (vpnMap.getRouterId() != null) {
+                        LOG.warn("Only Single Router association  to a given bgpvpn is allowed .Kindly de-associate " +
+                                "router " + vpnMap.getRouterId().getValue() + " from vpn " + vpnId + " before " +
+                                "proceeding with associate");
+                    }
+                    return;
+                }
+            } else if (validateRouteInfo(newRouters.get(0))) {
+                nvpnManager.associateRouterToVpn(vpnId, newRouters.get(0));
             }
+
+        } else if (oldRouters != null && !oldRouters.isEmpty()) {
+                /* dissociate old router */
+            Uuid oldRouter = oldRouters.get(0);
+            nvpnManager.dissociateRouterFromVpn(vpnId, oldRouter);
+        }
+    }
+
+    private void createIdPool() {
+        CreateIdPoolInput createPool = new CreateIdPoolInputBuilder().setPoolName(NeutronConstants.RD_IDPOOL_NAME)
+                .setLow(NeutronConstants.RD_IDPOOL_START)
+                .setHigh(new BigInteger(NeutronConstants.RD_IDPOOL_SIZE).longValue()).build();
+        try {
+            Future<RpcResult<Void>> result = idManager.createIdPool(createPool);
+            if ((result != null) && (result.get().isSuccessful())) {
+                LOG.info("Created IdPool for Bgpvpn RD");
+            }
+        } catch (InterruptedException | ExecutionException e) {
+            LOG.error("Failed to create idPool for Bgpvpn RD", e);
+        }
+    }
+
+    private boolean validateRouteInfo(Uuid routerID) {
+        Uuid assocVPNId;
+        if ((assocVPNId = NeutronvpnUtils.getVpnForRouter(dbroker, routerID, true)) != null) {
+            LOG.warn("VPN router association failed  due to router " + routerID.getValue()
+                    + " already associated to another VPN " + assocVPNId.getValue());
+            return false;
         }
-        // ### TBD : Handle routers
+        return true;
     }
 
-}
\ No newline at end of file
+}
index b84ea1fac69bded19bba59b0cb93cd3235faa785..6186b0c20e76fadf2401b4435af35b7f115fb6fa 100644 (file)
@@ -22,5 +22,9 @@ public class NeutronConstants {
     public static final String VIF_TYPE_MACVTAP = "macvtap";
     public static final String PREFIX_TAP = "tap";
     public static final String PREFIX_VHOSTUSER = "vhu";
+    public static final String RD_IDPOOL_NAME = "RouteDistinguisherPool";
+    public static final long RD_IDPOOL_START = 1L;
+    public static final String RD_IDPOOL_SIZE = "65535";// 16 bit AS specific part of RD
+    public static final String RD_PROPERTY_KEY = "vpnservice.admin.rdvalue";//stored in etc/custom.propertie
 
 }
index bde75fc798ea83d5d1978e82bc8b9a735554c133..45f5e56c9d45275f2b041a7128c81fb9c703a668 100644 (file)
@@ -23,7 +23,9 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.LockManagerService;
 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.genius.idmanager.rev160406.IdManagerService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronvpnService;
+import org.opendaylight.yangtools.binding.data.codec.api.BindingNormalizedNodeSerializer;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -48,6 +50,7 @@ public class NeutronvpnProvider implements BindingAwareProvider, INeutronVpnMana
     private NotificationPublishService notificationPublishService;
     private NotificationService notificationService;
     private EntityOwnershipService entityOwnershipService;
+    private IdManagerService idManager;
 
     public NeutronvpnProvider(RpcProviderRegistry rpcRegistry,NotificationPublishService notificationPublishService,
                               NotificationService notificationService) {
@@ -80,6 +83,7 @@ public class NeutronvpnProvider implements BindingAwareProvider, INeutronVpnMana
     public void onSessionInitiated(ProviderContext session) {
         try {
             final DataBroker dbx = session.getSALService(DataBroker.class);
+            idManager = getRpcProviderRegistry().getRpcService(IdManagerService.class);
             nvNatManager = new NeutronvpnNatManager(dbx, mdsalManager);
             floatingIpMapListener = new NeutronFloatingToFixedIpMappingChangeListener(dbx);
             nvManager = new NeutronvpnManager(dbx, mdsalManager,notificationPublishService,notificationService,
@@ -100,6 +104,7 @@ public class NeutronvpnProvider implements BindingAwareProvider, INeutronVpnMana
             l2GatewayProvider = new L2GatewayProvider(dbx, rpcProviderRegistry, entityOwnershipService);
             securityRuleListener = new NeutronSecurityRuleListener(dbx);
             securityRuleListener.registerListener();
+            bgpvpnListener.setIdManager(idManager);
             LOG.info("NeutronvpnProvider Session Initiated");
         } catch (Exception e) {
             LOG.error("Error initializing services", e);
index 054154083d373a75e1d115c8b44279bb920a4eca..694c6bc27a48526968b418d6d7e25e89bbbb00ef 100644 (file)
@@ -41,6 +41,12 @@ 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.genius.idmanager.rev160406.AllocateIdInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.LockManagerService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.TimeUnits;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.TryLockInput;
@@ -521,4 +527,36 @@ public class NeutronvpnUtils {
         }
         return false;
     }
+
+    protected static Integer getUniqueRDId(IdManagerService idManager, String poolName, String idKey) {
+        AllocateIdInput getIdInput = new AllocateIdInputBuilder().setPoolName(poolName).setIdKey(idKey).build();
+        try {
+            Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput);
+            RpcResult<AllocateIdOutput> rpcResult = result.get();
+            if (rpcResult.isSuccessful()) {
+                return rpcResult.getResult().getIdValue().intValue();
+            } else {
+                logger.debug("RPC Call to Get Unique Id returned with Errors", rpcResult.getErrors());
+            }
+        } catch (InterruptedException | ExecutionException e) {
+            logger.debug("Exception when getting Unique Id", e);
+        }
+        return null;
+    }
+
+    protected static void releaseRDId(IdManagerService idManager, String poolName, String idKey) {
+        ReleaseIdInput idInput = new ReleaseIdInputBuilder().setPoolName(poolName).setIdKey(idKey).build();
+        try {
+            Future<RpcResult<Void>> result = idManager.releaseId(idInput);
+            RpcResult<Void> rpcResult = result.get();
+            if (!rpcResult.isSuccessful()) {
+                logger.debug("RPC Call to Get Unique Id returned with Errors", rpcResult.getErrors());
+            } else {
+                logger.info("ID for RD " + idKey + " released successfully");
+            }
+        } catch (InterruptedException | ExecutionException e) {
+            logger.debug("Exception when trying to release ID into the pool", idKey, e);
+        }
+    }
+
 }