BUG:8232 updating BGPVPN with the List of RDs 26/55726/24
authorepgoraj <p.govinda.rajulu@ericsson.com>
Thu, 20 Apr 2017 11:59:50 +0000 (17:29 +0530)
committerSam Hague <shague@redhat.com>
Thu, 1 Jun 2017 22:26:30 +0000 (22:26 +0000)
       *Problem: When a new Extra-route is added and if there are not enough RDs
        for the VPN then the new extra-routes are not handled.
        These unprocessed extra-routes will be handled during vpninstance update
        (ie when new RDs are added(Update) to the existing VPN)

Change-Id: Ic380b6aaabdd0d44484c2ec1a33de7cde9c01366
Signed-off-by: epgoraj <p.govinda.rajulu@ericsson.com>
vpnservice/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronBgpvpnChangeListener.java
vpnservice/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronvpnManager.java
vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnInstanceListener.java
vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnInterfaceManager.java
vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnUtil.java

index 076f006f7cf970100105fe0b4f825a7e92b9a63e..0fed7216f5861f3011fab2515c3311aaf81d4a8f 100644 (file)
@@ -181,6 +181,13 @@ public class NeutronBgpvpnChangeListener extends AsyncDataTreeChangeListenerBase
     protected void update(InstanceIdentifier<Bgpvpn> identifier, Bgpvpn original, Bgpvpn update) {
         LOG.trace("Update Bgpvpn : key: {}, value={}", identifier, update);
         if (isBgpvpnTypeL3(update.getType())) {
+            try {
+                handleVpnInstanceUpdate(original.getUuid().getValue(), original.getRouteDistinguishers(),
+                        update.getRouteDistinguishers());
+            } catch (UnsupportedOperationException e) {
+                LOG.error("Error while processing Update Bgpvpn.", e);
+                return;
+            }
             List<Uuid> oldNetworks = original.getNetworks();
             List<Uuid> newNetworks = update.getNetworks();
             Uuid vpnId = update.getUuid();
@@ -191,6 +198,30 @@ public class NeutronBgpvpnChangeListener extends AsyncDataTreeChangeListenerBase
         }
     }
 
+    protected void handleVpnInstanceUpdate(String vpnInstanceName,final List<String> originalRds,
+                                           List<String> updateRDs) throws UnsupportedOperationException {
+        if (updateRDs == null || updateRDs.isEmpty()) {
+            return;
+        }
+        int oldRdsCount = originalRds.size();
+        Iterator<String> originalRdsInter = originalRds.iterator();
+
+        while (originalRdsInter.hasNext()) {
+            String rd = originalRdsInter.next();
+            //If the existing rd is not present in the updateRds list, not allow to process the updateRDs.
+            if (!updateRDs.contains(rd)) {
+                LOG.error("The existing RD:{} not present in the updatedRDsList:{}", rd, updateRDs);
+                throw new UnsupportedOperationException("The existing RD not present in the updatedRDsList");
+            }
+        }
+        if (updateRDs.size() == oldRdsCount) {
+            LOG.debug("There is no update in the List of Route Distinguisher for the VpnInstance:{}", vpnInstanceName);
+            return;
+        }
+        LOG.debug("update the VpnInstance:{} with the List of RDs: {}", vpnInstanceName, updateRDs);
+        nvpnManager.updateVpnInstanceWithRDs(vpnInstanceName, updateRDs);
+    }
+
     protected void handleNetworksUpdate(Uuid vpnId, List<Uuid> oldNetworks, List<Uuid> newNetworks) {
         if (newNetworks != null && !newNetworks.isEmpty()) {
             if (oldNetworks != null && !oldNetworks.isEmpty()) {
index 5f8a5bc188a5140296fd910b4eb2ac7b3c78ecb9..d59be9e0e7d20480acaacd9a4cb4450d73e2966a 100644 (file)
@@ -434,6 +434,28 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         }
     }
 
+    public void updateVpnInstanceWithRDs(String vpnInstanceId, final List<String> rds) {
+        InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
+            .child(VpnInstance.class, new VpnInstanceKey(vpnInstanceId)).build();
+        Optional<VpnInstance> vpnInstanceConfig =
+            NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier);
+        if (!vpnInstanceConfig.isPresent()) {
+            LOG.debug("No VpnInstance present under config vpnInstance:{}", vpnInstanceId);
+            return;
+        }
+        VpnInstance vpnInstance = vpnInstanceConfig.get();
+        VpnInstanceBuilder updateVpnInstanceBuilder = new VpnInstanceBuilder(vpnInstance);
+        Ipv4FamilyBuilder ipv4FamilyBuilder = new Ipv4FamilyBuilder(vpnInstance.getIpv4Family());
+        updateVpnInstanceBuilder.setIpv4Family(ipv4FamilyBuilder.setRouteDistinguisher(rds).build());
+        LOG.debug("Updating Config vpn-instance: {} with the list of RDs: {}", vpnInstanceId,rds);
+        try {
+            SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier,
+                    updateVpnInstanceBuilder.build());
+        } catch (TransactionCommitFailedException ex) {
+            LOG.warn("Error configuring feature ", ex);
+        }
+    }
+
     // TODO Clean up the exception handling
     @SuppressWarnings("checkstyle:IllegalCatch")
     private void updateVpnInstanceNode(String vpnName, List<String> rd, List<String> irt, List<String> ert,
index 5237554f9c8de7d697f18e8e1bd9c132ba116499..08bad4b40d88064bd162506c79255dd7a6040e6b 100644 (file)
@@ -304,6 +304,8 @@ public class VpnInstanceListener extends AsyncDataTreeChangeListenerBase<VpnInst
     protected void update(InstanceIdentifier<VpnInstance> identifier,
         VpnInstance original, VpnInstance update) {
         LOG.trace("Update VPN event key: {}, value: {}", identifier, update);
+        String vpnName = update.getVpnInstanceName();
+        vpnInterfaceManager.updateVpnInterfacesForUnProcessAdjancencies(dataBroker,vpnName);
     }
 
     @Override
index d51d6c7e533e84e125189594c0ea8f71d67cbdbe..e229cc5064f21d10e36edefdafe28337fdeb0546 100755 (executable)
@@ -98,6 +98,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neu
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface.vpn.ids.Prefixes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnTargets;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpntargets.VpnTarget;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.to.extraroutes.vpn.extra.routes.Routes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.Routers;
@@ -2080,4 +2081,67 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
             return true;
         }
     }
+
+    public void updateVpnInterfacesForUnProcessAdjancencies(DataBroker dataBroker,
+                                                                   String vpnName) {
+        String primaryRd = VpnUtil.getVpnRd(dataBroker, vpnName);
+        VpnInstanceOpDataEntry vpnInstanceOpData = VpnUtil.getVpnInstanceOpData(dataBroker, primaryRd);
+        if (vpnInstanceOpData == null) {
+            return;
+        }
+        List<VpnToDpnList> vpnToDpnLists = vpnInstanceOpData.getVpnToDpnList();
+        if (vpnToDpnLists == null || vpnToDpnLists.isEmpty()) {
+            return;
+        }
+        LOG.debug("Update the VpnInterfaces for Unprocessed Adjancencies for vpnName:{}", vpnName);
+        vpnToDpnLists.forEach(vpnToDpnList -> {
+            vpnToDpnList.getVpnInterfaces().forEach(vpnInterface -> {
+                InstanceIdentifier<VpnInterface> existingVpnInterfaceId =
+                        VpnUtil.getVpnInterfaceIdentifier(vpnInterface.getInterfaceName());
+                Optional<VpnInterface> vpnInterfaceOptional = VpnUtil.read(dataBroker,
+                        LogicalDatastoreType.OPERATIONAL, existingVpnInterfaceId);
+                if (!vpnInterfaceOptional.isPresent()) {
+                    return;
+                }
+                List<Adjacency> configVpnAdjacencies = VpnUtil.getAdjacenciesForVpnInterfaceFromConfig(dataBroker,
+                        vpnInterface.getInterfaceName());
+                if (configVpnAdjacencies == null) {
+                    LOG.debug("There is no adjacency available for vpnInterface:{}", vpnInterface);
+                    return;
+                }
+                List<Adjacency> operationVpnAdjacencies = vpnInterfaceOptional.get()
+                        .getAugmentation(Adjacencies.class).getAdjacency();
+                // Due to insufficient rds,  some of the extra route wont get processed when it is added.
+                // The unprocessed adjacencies will be present in config vpn interface DS but will be missing
+                // in operational DS. These unprocessed adjacencies will be handled below.
+                // To obtain unprocessed adjacencies, filtering is done by which the missing adjacencies in operational
+                // DS are retrieved which is used to call addNewAdjToVpnInterface method.
+                configVpnAdjacencies.stream()
+                        .filter(adjacency -> operationVpnAdjacencies.stream()
+                                .noneMatch(operationalAdjacency ->
+                                        operationalAdjacency.getIpAddress().equals(adjacency.getIpAddress())))
+                        .forEach(adjacency -> {
+                            LOG.debug("Processing the vpnInterface{} for the Ajacency:{}", vpnInterface, adjacency);
+                            DataStoreJobCoordinator dataStoreJobCoordinator = DataStoreJobCoordinator.getInstance();
+                            dataStoreJobCoordinator.enqueueJob("VPNINTERFACE-" + vpnInterface.getInterfaceName(),
+                                () -> {
+                                    WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
+                                    WriteTransaction writeOperTxn = dataBroker.newWriteOnlyTransaction();
+                                    addNewAdjToVpnInterface(existingVpnInterfaceId, adjacency,
+                                                vpnInterfaceOptional.get().getDpnId(), writeConfigTxn, writeOperTxn);
+                                    List<ListenableFuture<Void>> futures = new ArrayList<>();
+                                    ListenableFuture<Void> operFuture = writeOperTxn.submit();
+                                    try {
+                                        operFuture.get();
+                                    } catch (ExecutionException | InterruptedException e) {
+                                        LOG.error("Exception encountered while submitting operational"
+                                                + " future for vpnInterface {}: " + "{}", vpnInterface, e);
+                                    }
+                                    futures.add(writeConfigTxn.submit());
+                                    return futures;
+                                });
+                        });
+            });
+        });
+    }
 }
index 4aeb1efa1280ea722882689a367253616fc01314..e96dcfa2b6842e24487fd4624a4870411d659d9c 100755 (executable)
@@ -1489,6 +1489,11 @@ public class VpnUtil {
      * @return the primary rd of the VPN
      */
     public static String getPrimaryRd(DataBroker dataBroker, String vpnName) {
+        // Retrieves the VPN Route Distinguisher by its Vpn instance name
+        String rd = getVpnRd(dataBroker, vpnName);
+        if (rd != null) {
+            return rd;
+        }
         InstanceIdentifier<VpnInstance> id  = getVpnInstanceIdentifier(vpnName);
         Optional<VpnInstance> vpnInstance = VpnUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
         if (vpnInstance.isPresent()) {