Use managed transactions in natservice-impl 71/71771/5
authorStephen Kitt <skitt@redhat.com>
Thu, 3 May 2018 15:09:02 +0000 (17:09 +0200)
committerSam Hague <shague@redhat.com>
Fri, 25 May 2018 17:12:55 +0000 (17:12 +0000)
This also enforces restrictions on newReadWriteTransaction and
newWriteOnlyTransaction calls, to prevent new code introducing
unmanaged transactions.

Change-Id: I37f377931cde7775aa744ea78fb88123f24e4b5a
Signed-off-by: Stephen Kitt <skitt@redhat.com>
13 files changed:
natservice/impl/pom.xml
natservice/impl/src/main/java/org/opendaylight/netvirt/natservice/ha/WeightedCentralizedSwitchScheduler.java
natservice/impl/src/main/java/org/opendaylight/netvirt/natservice/internal/EvpnDnatFlowProgrammer.java
natservice/impl/src/main/java/org/opendaylight/netvirt/natservice/internal/ExternalNetworksChangeListener.java
natservice/impl/src/main/java/org/opendaylight/netvirt/natservice/internal/ExternalRoutersListener.java
natservice/impl/src/main/java/org/opendaylight/netvirt/natservice/internal/FloatingIPListener.java
natservice/impl/src/main/java/org/opendaylight/netvirt/natservice/internal/NatInterfaceStateChangeListener.java
natservice/impl/src/main/java/org/opendaylight/netvirt/natservice/internal/NatRouterInterfaceListener.java
natservice/impl/src/main/java/org/opendaylight/netvirt/natservice/internal/NatTunnelInterfaceStateListener.java
natservice/impl/src/main/java/org/opendaylight/netvirt/natservice/internal/NatUtil.java
natservice/impl/src/main/java/org/opendaylight/netvirt/natservice/internal/RouterDpnChangeListener.java
natservice/impl/src/main/java/org/opendaylight/netvirt/natservice/internal/RouterToVpnListener.java
natservice/impl/src/main/java/org/opendaylight/netvirt/natservice/internal/VxlanGreConntrackBasedSnatService.java

index 92d4859af3955a96e549f4ef51150bda36e21134..db5cab36198277957958f0939f8b6b24a8b70210 100644 (file)
@@ -11,9 +11,9 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
 
     <parent>
         <groupId>org.opendaylight.netvirt</groupId>
-        <artifactId>binding-parent</artifactId>
+        <artifactId>managed-tx-parent</artifactId>
         <version>0.7.0-SNAPSHOT</version>
-        <relativePath>../../commons/binding-parent</relativePath>
+        <relativePath>../../commons/managed-tx-parent</relativePath>
     </parent>
 
     <artifactId>natservice-impl</artifactId>
index aff9c68e541644c4c7234938eaad47b5e927e6de..41d02b2cd669fa727dff3e6c83a6b0dc17f862d8 100644 (file)
@@ -18,11 +18,12 @@ import java.util.concurrent.ConcurrentHashMap;
 import javax.inject.Inject;
 import javax.inject.Singleton;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
+import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
+import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
+import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
 import org.opendaylight.netvirt.natservice.api.CentralizedSwitchScheduler;
 import org.opendaylight.netvirt.natservice.internal.NatUtil;
 import org.opendaylight.netvirt.vpnmanager.api.IVpnFootprintService;
@@ -48,6 +49,7 @@ public class WeightedCentralizedSwitchScheduler implements CentralizedSwitchSche
     private final Map<BigInteger,Integer> switchWeightsMap = new ConcurrentHashMap<>();
     private final Map<String,String> subnetIdToRouterPortMap = new ConcurrentHashMap<>();
     private final DataBroker dataBroker;
+    private final ManagedNewTransactionRunner txRunner;
     private final OdlInterfaceRpcService interfaceManager;
     private final IVpnFootprintService vpnFootprintService;
 
@@ -55,6 +57,7 @@ public class WeightedCentralizedSwitchScheduler implements CentralizedSwitchSche
     public WeightedCentralizedSwitchScheduler(DataBroker dataBroker, OdlInterfaceRpcService interfaceManager,
             IVpnFootprintService vpnFootprintService) {
         this.dataBroker = dataBroker;
+        this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
         this.interfaceManager = interfaceManager;
         this.vpnFootprintService = vpnFootprintService;
     }
@@ -110,25 +113,21 @@ public class WeightedCentralizedSwitchScheduler implements CentralizedSwitchSche
             LOG.debug("addToDpnMaps no subnets associated with {}", routerName);
             return;
         }
-        String primaryRd = NatUtil.getPrimaryRd(dataBroker, routerName);
-        WriteTransaction writeOperTxn = dataBroker.newWriteOnlyTransaction();
-        for (Uuid subnetUuid : addedSubnetIds) {
-            try {
-                Subnetmap subnetMapEntry = SingleTransactionDataBroker.syncRead(dataBroker,
-                        LogicalDatastoreType.CONFIGURATION, getSubnetMapIdentifier(subnetUuid));
+        ListenableFutures.addErrorLogging(txRunner.callWithNewReadWriteTransactionAndSubmit(tx -> {
+            for (Uuid subnetUuid : addedSubnetIds) {
+                String primaryRd = NatUtil.getPrimaryRd(routerName, tx);
+                Subnetmap subnetMapEntry = tx.read(LogicalDatastoreType.CONFIGURATION,
+                        getSubnetMapIdentifier(subnetUuid)).checkedGet().orNull();
                 Uuid routerPortUuid = subnetMapEntry.getRouterInterfacePortId();
                 subnetIdToRouterPortMap.put(subnetUuid.getValue(), routerPortUuid.getValue());
                 vpnFootprintService.updateVpnToDpnMapping(primarySwitchId, routerName, primaryRd,
                         routerPortUuid.getValue(), null, true);
                 NatUtil.addToNeutronRouterDpnsMap(dataBroker, routerName, routerPortUuid.getValue(),
-                        primarySwitchId, writeOperTxn);
+                        primarySwitchId, tx);
                 NatUtil.addToDpnRoutersMap(dataBroker, routerName, routerPortUuid.getValue(),
-                        primarySwitchId, writeOperTxn);
-            } catch (ReadFailedException e) {
-                LOG.error("addToDpnMaps failed for {}", routerName);
+                        primarySwitchId, tx);
             }
-        }
-        writeOperTxn.submit();
+        }), LOG, "Error adding subnets to DPN maps for {}", routerName);
     }
 
 
@@ -138,21 +137,20 @@ public class WeightedCentralizedSwitchScheduler implements CentralizedSwitchSche
             LOG.debug("deleteFromDpnMaps no subnets associated with {}", routerName);
             return;
         }
-        WriteTransaction writeOperTxn = dataBroker.newWriteOnlyTransaction();
-        String primaryRd = NatUtil.getPrimaryRd(dataBroker, routerName);
-        for (Uuid subnetUuid :deletedSubnetIds) {
-            String routerPort = subnetIdToRouterPortMap.remove(subnetUuid.getValue());
-            if (routerPort == null) {
-                LOG.error("The router port was not found for {}", subnetUuid.getValue());
-                continue;
+        ListenableFutures.addErrorLogging(txRunner.callWithNewReadWriteTransactionAndSubmit(tx -> {
+            String primaryRd = NatUtil.getPrimaryRd(routerName, tx);
+            for (Uuid subnetUuid : deletedSubnetIds) {
+                String routerPort = subnetIdToRouterPortMap.remove(subnetUuid.getValue());
+                if (routerPort == null) {
+                    LOG.error("The router port was not found for {}", subnetUuid.getValue());
+                    continue;
+                }
+                vpnFootprintService.updateVpnToDpnMapping(primarySwitchId, routerName, primaryRd,
+                        routerPort, null, false);
+                NatUtil.removeFromNeutronRouterDpnsMap(dataBroker, routerName, primarySwitchId, tx);
+                NatUtil.removeFromDpnRoutersMap(dataBroker, routerName, routerName, interfaceManager, tx);
             }
-            vpnFootprintService.updateVpnToDpnMapping(primarySwitchId, routerName, primaryRd,
-                    routerPort, null, false);
-            NatUtil.removeFromNeutronRouterDpnsMap(dataBroker, routerName, primarySwitchId, writeOperTxn);
-            NatUtil.removeFromDpnRoutersMap(dataBroker, routerName, routerName, interfaceManager,
-                    writeOperTxn);
-        }
-        writeOperTxn.submit();
+        }), LOG, "Error deleting subnets from DPN maps for {}", routerName);
     }
 
     @Override
index a1201b5c615394d5fc594758d31a780dcd84c391..453d43f3079864dbcc5bbac236b359df64353ae4 100644 (file)
@@ -24,6 +24,8 @@ import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
+import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
+import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
 import org.opendaylight.genius.mdsalutil.ActionInfo;
 import org.opendaylight.genius.mdsalutil.MDSALUtil;
 import org.opendaylight.genius.mdsalutil.MatchInfo;
@@ -75,6 +77,7 @@ public class EvpnDnatFlowProgrammer {
     private static final BigInteger COOKIE_TUNNEL = new BigInteger("9000000", 16);
 
     private final DataBroker dataBroker;
+    private final ManagedNewTransactionRunner txRunner;
     private final IMdsalApiManager mdsalManager;
     private final IBgpManager bgpManager;
     private final IFibManager fibManager;
@@ -90,6 +93,7 @@ public class EvpnDnatFlowProgrammer {
                            final IVpnManager vpnManager,
                            final IdManagerService idManager) {
         this.dataBroker = dataBroker;
+        this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
         this.mdsalManager = mdsalManager;
         this.bgpManager = bgpManager;
         this.fibManager = fibManager;
@@ -155,12 +159,12 @@ public class EvpnDnatFlowProgrammer {
         LOG.debug("onAddFloatingIp : Add Floating Ip {} , found associated to fixed port {}",
                 externalIp, interfaceName);
         if (floatingIpPortMacAddress != null) {
-            WriteTransaction writeTx = dataBroker.newWriteOnlyTransaction();
-            vpnManager.addSubnetMacIntoVpnInstance(vpnName, null, floatingIpPortMacAddress, dpnId, writeTx);
-            vpnManager.addArpResponderFlowsToExternalNetworkIps(routerName,
-                    Collections.singleton(externalIp),
-                    floatingIpPortMacAddress, dpnId, networkId, writeTx);
-            writeTx.submit();
+            ListenableFutures.addErrorLogging(txRunner.callWithNewReadWriteTransactionAndSubmit(tx -> {
+                vpnManager.addSubnetMacIntoVpnInstance(vpnName, null, floatingIpPortMacAddress, dpnId, tx);
+                vpnManager.addArpResponderFlowsToExternalNetworkIps(routerName,
+                        Collections.singleton(externalIp),
+                        floatingIpPortMacAddress, dpnId, networkId, tx);
+            }), LOG, "Error processing floating IP port with MAC address {}", floatingIpPortMacAddress);
         }
         final long finalL3Vni = l3Vni;
         Futures.addCallback(futureVxlan, new FutureCallback<RpcResult<CreateFibEntryOutput>>() {
@@ -208,41 +212,38 @@ public class EvpnDnatFlowProgrammer {
                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
                         LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier);
         if (optionalVpnInterface.isPresent()) {
-            WriteTransaction writeOperTxn = dataBroker.newWriteOnlyTransaction();
-            for (VpnInstanceNames vpnInstance : optionalVpnInterface.get().getVpnInstanceNames()) {
-                if (!vpnName.equals(vpnInstance.getVpnName())) {
-                    continue;
-                }
-                VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get());
-                Adjacencies adjs = vpnIfBuilder.getAugmentation(Adjacencies.class);
-                VpnInterfaceOpDataEntryBuilder vpnIfOpDataEntryBuilder = new VpnInterfaceOpDataEntryBuilder();
-                vpnIfOpDataEntryBuilder.setKey(new VpnInterfaceOpDataEntryKey(interfaceName, vpnName));
-
-                List<Adjacency> adjacencyList = adjs != null ? adjs.getAdjacency() : new ArrayList<>();
-                List<Adjacency> adjacencyListToImport = new ArrayList<>();
-                for (Adjacency adj : adjacencyList) {
-                    Subnetmap sn = VpnHelper.getSubnetmapFromItsUuid(dataBroker, adj.getSubnetId());
-                    if (!VpnHelper.isSubnetPartOfVpn(sn, vpnName)) {
+            ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
+                for (VpnInstanceNames vpnInstance : optionalVpnInterface.get().getVpnInstanceNames()) {
+                    if (!vpnName.equals(vpnInstance.getVpnName())) {
                         continue;
                     }
-                    adjacencyListToImport.add(adj);
-                }
-                AdjacenciesOp adjacenciesOp = new AdjacenciesOpBuilder()
-                        .setAdjacency(adjacencyListToImport).build();
-                vpnIfOpDataEntryBuilder.addAugmentation(AdjacenciesOp.class, adjacenciesOp);
+                    VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get());
+                    Adjacencies adjs = vpnIfBuilder.getAugmentation(Adjacencies.class);
+                    VpnInterfaceOpDataEntryBuilder vpnIfOpDataEntryBuilder = new VpnInterfaceOpDataEntryBuilder();
+                    vpnIfOpDataEntryBuilder.setKey(new VpnInterfaceOpDataEntryKey(interfaceName, vpnName));
 
-                LOG.debug("onAddFloatingIp : Add vpnInterface {} to Operational l3vpn:vpn-interfaces-op-data ",
-                        floatingIpInterface);
-                InstanceIdentifier<VpnInterfaceOpDataEntry> vpnIfIdentifierOpDataEntry =
-                                        NatUtil.getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
-                writeOperTxn.put(LogicalDatastoreType.OPERATIONAL, vpnIfIdentifierOpDataEntry,
-                              vpnIfOpDataEntryBuilder.build(), WriteTransaction.CREATE_MISSING_PARENTS);
-                break;
-            }
-            ListenableFuture<Void> futures = writeOperTxn.submit();
-            String errorText = "onAddFloatingIp : Could not write Interface " + interfaceName
-                  + " vpnName " + vpnName;
-            ListenableFutures.addErrorLogging(futures, LOG, errorText);
+                    List<Adjacency> adjacencyList = adjs != null ? adjs.getAdjacency() : new ArrayList<>();
+                    List<Adjacency> adjacencyListToImport = new ArrayList<>();
+                    for (Adjacency adj : adjacencyList) {
+                        Subnetmap sn = VpnHelper.getSubnetmapFromItsUuid(dataBroker, adj.getSubnetId());
+                        if (!VpnHelper.isSubnetPartOfVpn(sn, vpnName)) {
+                            continue;
+                        }
+                        adjacencyListToImport.add(adj);
+                    }
+                    AdjacenciesOp adjacenciesOp = new AdjacenciesOpBuilder()
+                            .setAdjacency(adjacencyListToImport).build();
+                    vpnIfOpDataEntryBuilder.addAugmentation(AdjacenciesOp.class, adjacenciesOp);
+
+                    LOG.debug("onAddFloatingIp : Add vpnInterface {} to Operational l3vpn:vpn-interfaces-op-data ",
+                            floatingIpInterface);
+                    InstanceIdentifier<VpnInterfaceOpDataEntry> vpnIfIdentifierOpDataEntry =
+                            NatUtil.getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
+                    tx.put(LogicalDatastoreType.OPERATIONAL, vpnIfIdentifierOpDataEntry,
+                            vpnIfOpDataEntryBuilder.build(), WriteTransaction.CREATE_MISSING_PARENTS);
+                    break;
+                }
+            }), LOG, "onAddFloatingIp : Could not write Interface {}, vpnName {}", interfaceName, vpnName);
         } else {
             LOG.debug("onAddFloatingIp : No vpnInterface {} found in Configuration l3vpn:vpn-interfaces ",
                            floatingIpInterface);
@@ -328,21 +329,18 @@ public class EvpnDnatFlowProgrammer {
                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
                         LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier);
         if (optionalVpnInterface.isPresent()) {
-            WriteTransaction writeOperTxn = dataBroker.newWriteOnlyTransaction();
-            for (VpnInstanceNames vpnInstance : optionalVpnInterface.get().getVpnInstanceNames()) {
-                if (!vpnName.equals(vpnInstance.getVpnName())) {
-                    continue;
+            ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
+                for (VpnInstanceNames vpnInstance : optionalVpnInterface.get().getVpnInstanceNames()) {
+                    if (!vpnName.equals(vpnInstance.getVpnName())) {
+                        continue;
+                    }
+                    InstanceIdentifier<VpnInterfaceOpDataEntry> vpnOpIfIdentifier = NatUtil
+                            .getVpnInterfaceOpDataEntryIdentifier(floatingIpInterface, vpnName);
+                    tx.delete(LogicalDatastoreType.OPERATIONAL, vpnOpIfIdentifier);
+                    break;
                 }
-                InstanceIdentifier<VpnInterfaceOpDataEntry> vpnOpIfIdentifier = NatUtil
-                           .getVpnInterfaceOpDataEntryIdentifier(floatingIpInterface, vpnName);
-                writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, vpnOpIfIdentifier);
-                break;
-            }
-            ListenableFuture<Void> futures = writeOperTxn.submit();
-            String errorText = "onRemoveFloatingIp : Could not remove vpnInterface " + floatingIpInterface
-                + " vpnName " + vpnName
-                + " from Operational odl-l3vpn:vpn-interface-op-data";
-            ListenableFutures.addErrorLogging(futures, LOG, errorText);
+            }), LOG, "onRemoveFloatingIp : Could not remove vpnInterface {}, vpnName {} from Operational "
+                    + "odl-l3vpn:vpn-interface-op-data", floatingIpInterface, vpnName);
 
             LOG.debug("onRemoveFloatingIp : Remove vpnInterface {} vpnName {} "
                      + "to Operational odl-l3vpn:vpn-interface-op-data", floatingIpInterface, vpnName);
index 1dce2ca9955c1b72f39f792a19b4ea861c320cf4..0f04056a856b0c840134e633745ca17380984819 100644 (file)
@@ -8,11 +8,11 @@
 package org.opendaylight.netvirt.natservice.internal;
 
 import com.google.common.base.Optional;
-import com.google.common.util.concurrent.ListenableFuture;
 import java.math.BigInteger;
-import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.List;
+import java.util.concurrent.ExecutionException;
 import javax.annotation.PostConstruct;
 import javax.inject.Inject;
 import javax.inject.Singleton;
@@ -20,6 +20,8 @@ import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
+import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
+import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
 import org.opendaylight.genius.mdsalutil.MDSALUtil;
 import org.opendaylight.genius.mdsalutil.NwConstants;
 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
@@ -45,6 +47,7 @@ public class ExternalNetworksChangeListener
         extends AsyncDataTreeChangeListenerBase<Networks, ExternalNetworksChangeListener> {
     private static final Logger LOG = LoggerFactory.getLogger(ExternalNetworksChangeListener.class);
     private final DataBroker dataBroker;
+    private final ManagedNewTransactionRunner txRunner;
     private final FloatingIPListener floatingIpListener;
     private final ExternalRoutersListener externalRouterListener;
     private final OdlInterfaceRpcService interfaceManager;
@@ -59,6 +62,7 @@ public class ExternalNetworksChangeListener
                                           final JobCoordinator coordinator) {
         super(Networks.class, ExternalNetworksChangeListener.class);
         this.dataBroker = dataBroker;
+        this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
         this.floatingIpListener = floatingIpListener;
         this.externalRouterListener = externalRouterListener;
         this.interfaceManager = interfaceManager;
@@ -117,21 +121,18 @@ public class ExternalNetworksChangeListener
         //Check for VPN disassociation
         Uuid originalVpn = original.getVpnid();
         Uuid updatedVpn = update.getVpnid();
-        coordinator.enqueueJob(NatConstants.NAT_DJC_PREFIX + update.getKey(), () -> {
-            WriteTransaction writeFlowInvTx = dataBroker.newWriteOnlyTransaction();
-            List<ListenableFuture<Void>> futures = new ArrayList<>();
-            if (originalVpn == null && updatedVpn != null) {
-                //external network is dis-associated from L3VPN instance
-                associateExternalNetworkWithVPN(update, writeFlowInvTx);
-            } else if (originalVpn != null && updatedVpn == null) {
-                //external network is associated with vpn
-                disassociateExternalNetworkFromVPN(update, originalVpn.getValue());
-                //Remove the SNAT entries
-                removeSnatEntries(original, original.getId(), writeFlowInvTx);
-            }
-            futures.add(NatUtil.waitForTransactionToComplete(writeFlowInvTx));
-            return futures;
-        }, NatConstants.NAT_DJC_MAX_RETRIES);
+        coordinator.enqueueJob(NatConstants.NAT_DJC_PREFIX + update.getKey(),
+            () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
+                if (originalVpn == null && updatedVpn != null) {
+                    //external network is dis-associated from L3VPN instance
+                    associateExternalNetworkWithVPN(update, tx);
+                } else if (originalVpn != null && updatedVpn == null) {
+                    //external network is associated with vpn
+                    disassociateExternalNetworkFromVPN(update, originalVpn.getValue());
+                    //Remove the SNAT entries
+                    removeSnatEntries(original, original.getId(), tx);
+                }
+            })), NatConstants.NAT_DJC_MAX_RETRIES);
     }
 
     private void removeSnatEntries(Networks original, Uuid networkUuid, WriteTransaction writeFlowInvTx) {
@@ -270,23 +271,26 @@ public class ExternalNetworksChangeListener
             }
             RouterPorts routerPorts = optRouterPorts.get();
             List<Ports> interfaces = routerPorts.getPorts();
-            WriteTransaction removeFlowInvTx = dataBroker.newWriteOnlyTransaction();
-            for (Ports port : interfaces) {
-                String portName = port.getPortName();
-                BigInteger dpnId = NatUtil.getDpnForInterface(interfaceManager, portName);
-                if (dpnId.equals(BigInteger.ZERO)) {
-                    LOG.debug("disassociateExternalNetworkFromVPN : DPN not found for {},"
-                            + "skip handling of ext nw {} disassociation", portName, network.getId());
-                    continue;
-                }
-                List<InternalToExternalPortMap> intExtPortMapList = port.getInternalToExternalPortMap();
-                for (InternalToExternalPortMap intExtPortMap : intExtPortMapList) {
-                    floatingIpListener.removeNATFlowEntries(dpnId, portName, vpnName, routerId.getValue(),
-                            intExtPortMap, removeFlowInvTx);
-                }
+            try {
+                txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
+                    for (Ports port : interfaces) {
+                        String portName = port.getPortName();
+                        BigInteger dpnId = NatUtil.getDpnForInterface(interfaceManager, portName);
+                        if (dpnId.equals(BigInteger.ZERO)) {
+                            LOG.debug("disassociateExternalNetworkFromVPN : DPN not found for {},"
+                                    + "skip handling of ext nw {} disassociation", portName, network.getId());
+                            continue;
+                        }
+                        List<InternalToExternalPortMap> intExtPortMapList = port.getInternalToExternalPortMap();
+                        for (InternalToExternalPortMap intExtPortMap : intExtPortMapList) {
+                            floatingIpListener.removeNATFlowEntries(dpnId, portName, vpnName, routerId.getValue(),
+                                    intExtPortMap, tx);
+                        }
+                    }
+                }).get();
+            } catch (ExecutionException | InterruptedException e) {
+                LOG.error("Error writing to datastore {}", e);
             }
-
-            NatUtil.waitForTransactionToComplete(removeFlowInvTx);
         }
     }
 }
index 1c1231dda1ec6fd21849c6ec7ab6bc80c8e3ee4c..2196fa43311a1517374279ee6ef41fe68289d7d4 100644 (file)
@@ -8,7 +8,6 @@
 package org.opendaylight.netvirt.natservice.internal;
 
 import com.google.common.base.Optional;
-import com.google.common.util.concurrent.AsyncFunction;
 import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
@@ -37,6 +36,8 @@ import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
+import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
+import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
 import org.opendaylight.genius.mdsalutil.ActionInfo;
 import org.opendaylight.genius.mdsalutil.BucketInfo;
@@ -63,6 +64,7 @@ import org.opendaylight.genius.mdsalutil.matches.MatchMetadata;
 import org.opendaylight.genius.mdsalutil.matches.MatchMplsLabel;
 import org.opendaylight.genius.mdsalutil.matches.MatchTunnelId;
 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
+import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
 import org.opendaylight.netvirt.elanmanager.api.IElanService;
 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
@@ -151,6 +153,7 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
     private static final BigInteger COOKIE_VM_LFIB_TABLE = new BigInteger("8000022", 16);
 
     private final DataBroker dataBroker;
+    private final ManagedNewTransactionRunner txRunner;
     private final IMdsalApiManager mdsalManager;
     private final ItmRpcService itmManager;
     private final OdlInterfaceRpcService odlInterfaceRpcService;
@@ -199,6 +202,7 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
                                    final IInterfaceManager interfaceManager) {
         super(Routers.class, ExternalRoutersListener.class);
         this.dataBroker = dataBroker;
+        this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
         this.mdsalManager = mdsalManager;
         this.itmManager = itmManager;
         this.odlInterfaceRpcService = odlInterfaceRpcService;
@@ -262,31 +266,27 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
             //snatServiceManger.notify(routers, null, Action.ADD);
         } else {
             try {
-                coordinator.enqueueJob(NatConstants.NAT_DJC_PREFIX + routers.getKey(), () -> {
-                    WriteTransaction writeFlowInvTx = dataBroker.newWriteOnlyTransaction();
-                    LOG.info("add : Installing NAT default route on all dpns part of router {}", routerName);
-                    long bgpVpnId = NatConstants.INVALID_ID;
-                    if (bgpVpnUuid != null) {
-                        bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnUuid.getValue());
-                    }
-                    addOrDelDefFibRouteToSNAT(routerName, routerId, bgpVpnId, bgpVpnUuid, true, writeFlowInvTx);
-                    List<ListenableFuture<Void>> futures = new ArrayList<>();
-                    // Allocate Primary Napt Switch for this router
-                    BigInteger primarySwitchId = getPrimaryNaptSwitch(routerName);
-                    if (primarySwitchId != null && !primarySwitchId.equals(BigInteger.ZERO)) {
-                        if (!routers.isEnableSnat()) {
-                            LOG.info("add : SNAT is disabled for external router {} ", routerName);
-                            /* If SNAT is disabled on ext-router though L3_FIB_TABLE(21) -> PSNAT_TABLE(26) flow
-                             * is required for DNAT. Hence writeFlowInvTx object submit is required.
-                             */
-                            return futures;
+                coordinator.enqueueJob(NatConstants.NAT_DJC_PREFIX + routers.getKey(),
+                    () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
+                        LOG.info("add : Installing NAT default route on all dpns part of router {}", routerName);
+                        long bgpVpnId = NatConstants.INVALID_ID;
+                        if (bgpVpnUuid != null) {
+                            bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnUuid.getValue());
                         }
-                        handleEnableSnat(routers, routerId, primarySwitchId, bgpVpnId, writeFlowInvTx);
-                    }
-                    //final submit call for writeFlowInvTx
-                    futures.add(NatUtil.waitForTransactionToComplete(writeFlowInvTx));
-                    return futures;
-                }, NatConstants.NAT_DJC_MAX_RETRIES);
+                        addOrDelDefFibRouteToSNAT(routerName, routerId, bgpVpnId, bgpVpnUuid, true, tx);
+                        // Allocate Primary Napt Switch for this router
+                        BigInteger primarySwitchId = getPrimaryNaptSwitch(routerName);
+                        if (primarySwitchId != null && !primarySwitchId.equals(BigInteger.ZERO)) {
+                            if (!routers.isEnableSnat()) {
+                                LOG.info("add : SNAT is disabled for external router {} ", routerName);
+                                /* If SNAT is disabled on ext-router though L3_FIB_TABLE(21) -> PSNAT_TABLE(26) flow
+                                 * is required for DNAT. Hence writeFlowInvTx object submit is required.
+                                 */
+                                return;
+                            }
+                            handleEnableSnat(routers, routerId, primarySwitchId, bgpVpnId, tx);
+                        }
+                    })), NatConstants.NAT_DJC_MAX_RETRIES);
             } catch (Exception ex) {
                 LOG.error("add : Exception while Installing NAT flows on all dpns as part of router {}",
                         routerName, ex);
@@ -993,9 +993,10 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
             return;
         }
         if (extNwProvType == ProviderTypes.VXLAN) {
-            WriteTransaction writeTx = dataBroker.newWriteOnlyTransaction();
-            evpnSnatFlowProgrammer.evpnAdvToBgpAndInstallFibAndTsFlows(dpnId, tableId, externalIp, vpnName, rd,
-                    nextHopIp, writeTx, routerId, routerName, writeFlowInvTx);
+            ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(
+                tx -> evpnSnatFlowProgrammer.evpnAdvToBgpAndInstallFibAndTsFlows(dpnId, tableId, externalIp,
+                        vpnName, rd, nextHopIp, tx, routerId, routerName, writeFlowInvTx)), LOG,
+                "Error installing FIB and TS flows");
             return;
         }
         //Generate VPN label for the external IP
@@ -1004,93 +1005,91 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
         ListenableFuture<RpcResult<GenerateVpnLabelOutput>> labelFuture = vpnService.generateVpnLabel(labelInput);
 
         //On successful generation of the VPN label, advertise the route to the BGP and install the FIB routes.
-        ListenableFuture<RpcResult<CreateFibEntryOutput>> future =
-            Futures.transformAsync(labelFuture,
-                (AsyncFunction<RpcResult<GenerateVpnLabelOutput>, RpcResult<CreateFibEntryOutput>>) result -> {
-                    if (result.isSuccessful()) {
-                        LOG.debug("advToBgpAndInstallFibAndTsFlows : inside apply with result success");
-                        GenerateVpnLabelOutput output = result.getResult();
-                        final long label = output.getLabel();
-
-                        int externalIpInDsFlag = 0;
-                        //Get IPMaps from the DB for the router ID
-                        List<IpMap> dbIpMaps = NaptManager.getIpMapList(dataBroker, routerId);
-                        if (dbIpMaps != null) {
-                            for (IpMap dbIpMap : dbIpMaps) {
-                                String dbExternalIp = dbIpMap.getExternalIp();
-                                //Select the IPMap, whose external IP is the IP for which FIB is installed
-                                if (dbExternalIp.contains(externalIp)) {
-                                    String dbInternalIp = dbIpMap.getInternalIp();
-                                    IpMapKey dbIpMapKey = dbIpMap.getKey();
-                                    LOG.debug("advToBgpAndInstallFibAndTsFlows : Setting label {} for internalIp {} "
-                                            + "and externalIp {}", label, dbInternalIp, externalIp);
-                                    IpMap newIpm = new IpMapBuilder().setKey(dbIpMapKey).setInternalIp(dbInternalIp)
-                                        .setExternalIp(dbExternalIp).setLabel(label).build();
-                                    MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL,
-                                        naptManager.getIpMapIdentifier(routerId, dbInternalIp), newIpm);
-                                    externalIpInDsFlag++;
-                                }
-                            }
-                            if (externalIpInDsFlag <= 0) {
-                                LOG.debug("advToBgpAndInstallFibAndTsFlows : External Ip {} not found in DS, "
-                                        + "Failed to update label {} for routerId {} in DS",
-                                        externalIp, label, routerId);
-                                String errMsg = String.format("Failed to update label %s due to external Ip %s not"
-                                    + " found in DS for router %s", label, externalIp, routerId);
-                                return Futures.immediateFailedFuture(new Exception(errMsg));
-                            }
-                        } else {
-                            LOG.error("advToBgpAndInstallFibAndTsFlows : Failed to write label {} for externalIp {} for"
-                                    + " routerId {} in DS", label, externalIp, routerId);
-                        }
-                        //Inform BGP
-                        long l3vni = 0;
-                        if (NatUtil.isOpenStackVniSemanticsEnforcedForGreAndVxlan(elanManager, extNwProvType)) {
-                            l3vni = NatOverVxlanUtil.getInternetVpnVni(idManager, vpnName, l3vni).longValue();
-                        }
-                        Routers extRouter = router != null ? router :
-                            NatUtil.getRoutersFromConfigDS(dataBroker, routerName);
-                        Uuid externalSubnetId = NatUtil.getExternalSubnetForRouterExternalIp(externalIp,
-                                extRouter);
-                        NatUtil.addPrefixToBGP(dataBroker, bgpManager, fibManager, vpnName, rd, externalSubnetId,
-                            externalIp, nextHopIp, extRouter.getNetworkId().getValue(), null, label, l3vni,
-                            RouteOrigin.STATIC, dpnId);
-
-                        //Install custom FIB routes
-                        List<Instruction> tunnelTableCustomInstructions = new ArrayList<>();
-                        tunnelTableCustomInstructions.add(new InstructionGotoTable(tableId).buildInstruction(0));
-                        makeTunnelTableEntry(dpnId, label, l3vni, tunnelTableCustomInstructions, writeFlowInvTx,
-                                extNwProvType);
-                        makeLFibTableEntry(dpnId, label, tableId, writeFlowInvTx);
-
-                        //Install custom FIB routes - FIB table.
-                        List<Instruction> fibTableCustomInstructions = createFibTableCustomInstructions(tableId,
-                                routerName, externalIp);
-                        if (NatUtil.isOpenStackVniSemanticsEnforcedForGreAndVxlan(elanManager, extNwProvType)) {
-                            //Install the flow table 25->44 If there is no FIP Match on table 25 (PDNAT_TABLE)
-                            NatUtil.makePreDnatToSnatTableEntry(mdsalManager, dpnId,
-                                    NwConstants.INBOUND_NAPT_TABLE,writeFlowInvTx);
+        ListenableFuture<RpcResult<CreateFibEntryOutput>> future = Futures.transformAsync(labelFuture, result -> {
+            if (result.isSuccessful()) {
+                LOG.debug("advToBgpAndInstallFibAndTsFlows : inside apply with result success");
+                GenerateVpnLabelOutput output = result.getResult();
+                final long label = output.getLabel();
+
+                int externalIpInDsFlag = 0;
+                //Get IPMaps from the DB for the router ID
+                List<IpMap> dbIpMaps = NaptManager.getIpMapList(dataBroker, routerId);
+                if (dbIpMaps != null) {
+                    for (IpMap dbIpMap : dbIpMaps) {
+                        String dbExternalIp = dbIpMap.getExternalIp();
+                        //Select the IPMap, whose external IP is the IP for which FIB is installed
+                        if (dbExternalIp.contains(externalIp)) {
+                            String dbInternalIp = dbIpMap.getInternalIp();
+                            IpMapKey dbIpMapKey = dbIpMap.getKey();
+                            LOG.debug("advToBgpAndInstallFibAndTsFlows : Setting label {} for internalIp {} "
+                                    + "and externalIp {}", label, dbInternalIp, externalIp);
+                            IpMap newIpm = new IpMapBuilder().setKey(dbIpMapKey).setInternalIp(dbInternalIp)
+                                .setExternalIp(dbExternalIp).setLabel(label).build();
+                            MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL,
+                                naptManager.getIpMapIdentifier(routerId, dbInternalIp), newIpm);
+                            externalIpInDsFlag++;
                         }
-                        String fibExternalIp = NatUtil.validateAndAddNetworkMask(externalIp);
-                        Optional<Subnets> externalSubnet = NatUtil.getOptionalExternalSubnets(dataBroker,
-                                externalSubnetId);
-                        String externalVpn = vpnName;
-                        if (externalSubnet.isPresent()) {
-                            externalVpn =  externalSubnetId.getValue();
-                        }
-                        CreateFibEntryInput input = new CreateFibEntryInputBuilder()
-                            .setVpnName(externalVpn)
-                            .setSourceDpid(dpnId).setIpAddress(fibExternalIp).setServiceId(label)
-                            .setIpAddressSource(CreateFibEntryInput.IpAddressSource.ExternalFixedIP)
-                            .setInstruction(fibTableCustomInstructions).build();
-                        return fibService.createFibEntry(input);
-                    } else {
-                        LOG.error("advToBgpAndInstallFibAndTsFlows : inside apply with result failed");
-                        String errMsg = String.format("Could not retrieve the label for prefix %s in VPN %s, %s",
-                            externalIp, vpnName, result.getErrors());
-                        return Futures.immediateFailedFuture(new RuntimeException(errMsg));
                     }
-                }, MoreExecutors.directExecutor());
+                    if (externalIpInDsFlag <= 0) {
+                        LOG.debug("advToBgpAndInstallFibAndTsFlows : External Ip {} not found in DS, "
+                                + "Failed to update label {} for routerId {} in DS",
+                                externalIp, label, routerId);
+                        String errMsg = String.format("Failed to update label %s due to external Ip %s not"
+                            + " found in DS for router %s", label, externalIp, routerId);
+                        return Futures.immediateFailedFuture(new Exception(errMsg));
+                    }
+                } else {
+                    LOG.error("advToBgpAndInstallFibAndTsFlows : Failed to write label {} for externalIp {} for"
+                            + " routerId {} in DS", label, externalIp, routerId);
+                }
+                //Inform BGP
+                long l3vni = 0;
+                if (NatUtil.isOpenStackVniSemanticsEnforcedForGreAndVxlan(elanManager, extNwProvType)) {
+                    l3vni = NatOverVxlanUtil.getInternetVpnVni(idManager, vpnName, l3vni).longValue();
+                }
+                Routers extRouter = router != null ? router :
+                    NatUtil.getRoutersFromConfigDS(dataBroker, routerName);
+                Uuid externalSubnetId = NatUtil.getExternalSubnetForRouterExternalIp(externalIp,
+                        extRouter);
+                NatUtil.addPrefixToBGP(dataBroker, bgpManager, fibManager, vpnName, rd, externalSubnetId,
+                    externalIp, nextHopIp, extRouter.getNetworkId().getValue(), null, label, l3vni,
+                    RouteOrigin.STATIC, dpnId);
+
+                //Install custom FIB routes
+                List<Instruction> tunnelTableCustomInstructions = new ArrayList<>();
+                tunnelTableCustomInstructions.add(new InstructionGotoTable(tableId).buildInstruction(0));
+                makeTunnelTableEntry(dpnId, label, l3vni, tunnelTableCustomInstructions, writeFlowInvTx,
+                        extNwProvType);
+                makeLFibTableEntry(dpnId, label, tableId, writeFlowInvTx);
+
+                //Install custom FIB routes - FIB table.
+                List<Instruction> fibTableCustomInstructions = createFibTableCustomInstructions(tableId,
+                        routerName, externalIp);
+                if (NatUtil.isOpenStackVniSemanticsEnforcedForGreAndVxlan(elanManager, extNwProvType)) {
+                    //Install the flow table 25->44 If there is no FIP Match on table 25 (PDNAT_TABLE)
+                    NatUtil.makePreDnatToSnatTableEntry(mdsalManager, dpnId,
+                            NwConstants.INBOUND_NAPT_TABLE,writeFlowInvTx);
+                }
+                String fibExternalIp = NatUtil.validateAndAddNetworkMask(externalIp);
+                Optional<Subnets> externalSubnet = NatUtil.getOptionalExternalSubnets(dataBroker,
+                        externalSubnetId);
+                String externalVpn = vpnName;
+                if (externalSubnet.isPresent()) {
+                    externalVpn =  externalSubnetId.getValue();
+                }
+                CreateFibEntryInput input = new CreateFibEntryInputBuilder()
+                    .setVpnName(externalVpn)
+                    .setSourceDpid(dpnId).setIpAddress(fibExternalIp).setServiceId(label)
+                    .setIpAddressSource(CreateFibEntryInput.IpAddressSource.ExternalFixedIP)
+                    .setInstruction(fibTableCustomInstructions).build();
+                return fibService.createFibEntry(input);
+            } else {
+                LOG.error("advToBgpAndInstallFibAndTsFlows : inside apply with result failed");
+                String errMsg = String.format("Could not retrieve the label for prefix %s in VPN %s, %s",
+                    externalIp, vpnName, result.getErrors());
+                return Futures.immediateFailedFuture(new RuntimeException(errMsg));
+            }
+        }, MoreExecutors.directExecutor());
 
         Futures.addCallback(future, new FutureCallback<RpcResult<CreateFibEntryOutput>>() {
 
@@ -1234,68 +1233,72 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
             }
             final long finalBgpVpnId = bgpVpnId;
             coordinator.enqueueJob(NatConstants.NAT_DJC_PREFIX + update.getKey(), () -> {
-                WriteTransaction writeFlowInvTx = dataBroker.newWriteOnlyTransaction();
-                WriteTransaction removeFlowInvTx = dataBroker.newWriteOnlyTransaction();
-                Uuid networkId = original.getNetworkId();
-                if (originalSNATEnabled != updatedSNATEnabled) {
-                    if (originalSNATEnabled) {
-                        //SNAT disabled for the router
-                        Uuid networkUuid = original.getNetworkId();
-                        LOG.info("update : SNAT disabled for Router {}", routerName);
-                        Collection<String> externalIps = NatUtil.getExternalIpsForRouter(dataBroker, routerId);
-                        handleDisableSnat(original, networkUuid, externalIps, false, null, dpnId, routerId,
-                                removeFlowInvTx);
-                    } else {
-                        LOG.info("update : SNAT enabled for Router {}", original.getRouterName());
-                        handleEnableSnat(original, routerId, dpnId, finalBgpVpnId, removeFlowInvTx);
-                    }
-                }
-                if (!Objects.equals(original.getExtGwMacAddress(), update.getExtGwMacAddress())) {
-                    NatUtil.installRouterGwFlows(dataBroker, vpnManager, original, dpnId, NwConstants.DEL_FLOW);
-                    NatUtil.installRouterGwFlows(dataBroker, vpnManager, update, dpnId, NwConstants.ADD_FLOW);
-                }
+                List<ListenableFuture<Void>> futures = new ArrayList<>();
+                futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(writeFlowInvTx -> {
+                    futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(removeFlowInvTx -> {
+                        Uuid networkId = original.getNetworkId();
+                        if (originalSNATEnabled != updatedSNATEnabled) {
+                            if (originalSNATEnabled) {
+                                //SNAT disabled for the router
+                                Uuid networkUuid = original.getNetworkId();
+                                LOG.info("update : SNAT disabled for Router {}", routerName);
+                                Collection<String> externalIps = NatUtil.getExternalIpsForRouter(dataBroker, routerId);
+                                handleDisableSnat(original, networkUuid, externalIps, false, null, dpnId, routerId,
+                                        removeFlowInvTx);
+                            } else {
+                                LOG.info("update : SNAT enabled for Router {}", original.getRouterName());
+                                handleEnableSnat(original, routerId, dpnId, finalBgpVpnId, removeFlowInvTx);
+                            }
+                        }
+                        if (!Objects.equals(original.getExtGwMacAddress(), update.getExtGwMacAddress())) {
+                            NatUtil.installRouterGwFlows(txRunner, vpnManager, original, dpnId, NwConstants.DEL_FLOW);
+                            NatUtil.installRouterGwFlows(txRunner, vpnManager, update, dpnId, NwConstants.ADD_FLOW);
+                        }
 
-                //Check if the Update is on External IPs
-                LOG.debug("update : Checking if this is update on External IPs");
-                List<String> originalExternalIps = NatUtil.getIpsListFromExternalIps(original.getExternalIps());
-                List<String> updatedExternalIps = NatUtil.getIpsListFromExternalIps(update.getExternalIps());
-
-                //Check if the External IPs are added during the update.
-                Set<String> addedExternalIps = new HashSet<>(updatedExternalIps);
-                addedExternalIps.removeAll(originalExternalIps);
-                if (addedExternalIps.size() != 0) {
-                    LOG.debug("update : Start processing of the External IPs addition during the update operation");
-                    vpnManager.addArpResponderFlowsToExternalNetworkIps(routerName, addedExternalIps,
-                            update.getExtGwMacAddress(), dpnId,
-                            update.getNetworkId(), null);
-
-                    for (String addedExternalIp : addedExternalIps) {
+                        //Check if the Update is on External IPs
+                        LOG.debug("update : Checking if this is update on External IPs");
+                        List<String> originalExternalIps = NatUtil.getIpsListFromExternalIps(original.getExternalIps());
+                        List<String> updatedExternalIps = NatUtil.getIpsListFromExternalIps(update.getExternalIps());
+
+                        //Check if the External IPs are added during the update.
+                        Set<String> addedExternalIps = new HashSet<>(updatedExternalIps);
+                        addedExternalIps.removeAll(originalExternalIps);
+                        if (addedExternalIps.size() != 0) {
+                            LOG.debug("update : Start processing of the External IPs addition during the update "
+                                    + "operation");
+                            vpnManager.addArpResponderFlowsToExternalNetworkIps(routerName, addedExternalIps,
+                                    update.getExtGwMacAddress(), dpnId,
+                                    update.getNetworkId(), null);
+
+                            for (String addedExternalIp : addedExternalIps) {
                     /*
                         1) Do nothing in the IntExtIp model.
                         2) Initialise the count of the added external IP to 0 in the ExternalCounter model.
                      */
-                        String[] externalIpParts = NatUtil.getExternalIpAndPrefix(addedExternalIp);
-                        String externalIp = externalIpParts[0];
-                        String externalIpPrefix = externalIpParts[1];
-                        String externalpStr = externalIp + "/" + externalIpPrefix;
-                        LOG.debug("update : Initialise the count mapping of the external IP {} for the "
-                                        + "router ID {} in the ExternalIpsCounter model.",
-                                externalpStr, routerId);
-                        naptManager.initialiseNewExternalIpCounter(routerId, externalpStr);
-                    }
-                    LOG.debug("update : End processing of the External IPs addition during the update operation");
-                }
-
-                //Check if the External IPs are removed during the update.
-                Set<String> removedExternalIps = new HashSet<>(originalExternalIps);
-                removedExternalIps.removeAll(updatedExternalIps);
-                if (removedExternalIps.size() > 0) {
-                    LOG.debug("update : Start processing of the External IPs removal during the update operation");
-                    vpnManager.removeArpResponderFlowsToExternalNetworkIps(routerName,
-                            removedExternalIps, original.getExtGwMacAddress(),
-                            dpnId, networkId);
+                                String[] externalIpParts = NatUtil.getExternalIpAndPrefix(addedExternalIp);
+                                String externalIp = externalIpParts[0];
+                                String externalIpPrefix = externalIpParts[1];
+                                String externalpStr = externalIp + "/" + externalIpPrefix;
+                                LOG.debug("update : Initialise the count mapping of the external IP {} for the "
+                                                + "router ID {} in the ExternalIpsCounter model.",
+                                        externalpStr, routerId);
+                                naptManager.initialiseNewExternalIpCounter(routerId, externalpStr);
+                            }
+                            LOG.debug(
+                                    "update : End processing of the External IPs addition during the update operation");
+                        }
 
-                    for (String removedExternalIp : removedExternalIps) {
+                        //Check if the External IPs are removed during the update.
+                        Set<String> removedExternalIps = new HashSet<>(originalExternalIps);
+                        removedExternalIps.removeAll(updatedExternalIps);
+                        if (removedExternalIps.size() > 0) {
+                            LOG.debug("update : Start processing of the External IPs removal during the update "
+                                    + "operation");
+                            vpnManager.removeArpResponderFlowsToExternalNetworkIps(routerName,
+                                    removedExternalIps, original.getExtGwMacAddress(),
+                                    dpnId, networkId);
+
+                            for (String removedExternalIp : removedExternalIps) {
                     /*
                         1) Remove the mappings in the IntExt IP model which has external IP.
                         2) Remove the external IP in the ExternalCounter model.
@@ -1310,165 +1313,171 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
                         7) Advertise to the BGP for removing the route for the removed external IPs.
                      */
 
-                        String[] externalIpParts = NatUtil.getExternalIpAndPrefix(removedExternalIp);
-                        String externalIp = externalIpParts[0];
-                        String externalIpPrefix = externalIpParts[1];
-                        String externalIpAddrStr = externalIp + "/" + externalIpPrefix;
-
-                        LOG.debug("update : Clear the routes from the BGP and remove the FIB and TS "
-                                + "entries for removed external IP {}", externalIpAddrStr);
-                        Uuid vpnUuId = NatUtil.getVpnIdfromNetworkId(dataBroker, networkId);
-                        String vpnName = "";
-                        if (vpnUuId != null) {
-                            vpnName = vpnUuId.getValue();
-                        }
-                        clrRtsFromBgpAndDelFibTs(dpnId, routerId, externalIpAddrStr, vpnName, networkId,
-                                update.getExtGwMacAddress(), removeFlowInvTx);
-
-                        LOG.debug("update : Remove the mappings in the IntExtIP model which has external IP.");
-                        //Get the internal IPs which are associated to the removed external IPs
-                        List<IpMap> ipMaps = naptManager.getIpMapList(dataBroker, routerId);
-                        List<String> removedInternalIps = new ArrayList<>();
-                        for (IpMap ipMap : ipMaps) {
-                            if (ipMap.getExternalIp().equals(externalIpAddrStr)) {
-                                removedInternalIps.add(ipMap.getInternalIp());
-                            }
-                        }
+                                String[] externalIpParts = NatUtil.getExternalIpAndPrefix(removedExternalIp);
+                                String externalIp = externalIpParts[0];
+                                String externalIpPrefix = externalIpParts[1];
+                                String externalIpAddrStr = externalIp + "/" + externalIpPrefix;
+
+                                LOG.debug("update : Clear the routes from the BGP and remove the FIB and TS "
+                                        + "entries for removed external IP {}", externalIpAddrStr);
+                                Uuid vpnUuId = NatUtil.getVpnIdfromNetworkId(dataBroker, networkId);
+                                String vpnName = "";
+                                if (vpnUuId != null) {
+                                    vpnName = vpnUuId.getValue();
+                                }
+                                clrRtsFromBgpAndDelFibTs(dpnId, routerId, externalIpAddrStr, vpnName, networkId,
+                                        update.getExtGwMacAddress(), removeFlowInvTx);
+
+                                LOG.debug("update : Remove the mappings in the IntExtIP model which has external IP.");
+                                //Get the internal IPs which are associated to the removed external IPs
+                                List<IpMap> ipMaps = naptManager.getIpMapList(dataBroker, routerId);
+                                List<String> removedInternalIps = new ArrayList<>();
+                                for (IpMap ipMap : ipMaps) {
+                                    if (ipMap.getExternalIp().equals(externalIpAddrStr)) {
+                                        removedInternalIps.add(ipMap.getInternalIp());
+                                    }
+                                }
 
-                        LOG.debug("update : Remove the mappings of the internal IPs from the IntExtIP model.");
-                        for (String removedInternalIp : removedInternalIps) {
-                            LOG.debug("update : Remove the IP mapping of the internal IP {} for the "
-                                            + "router ID {} from the IntExtIP model",
-                                    removedInternalIp, routerId);
-                            naptManager.removeFromIpMapDS(routerId, removedInternalIp);
-                        }
+                                LOG.debug("update : Remove the mappings of the internal IPs from the IntExtIP model.");
+                                for (String removedInternalIp : removedInternalIps) {
+                                    LOG.debug("update : Remove the IP mapping of the internal IP {} for the "
+                                                    + "router ID {} from the IntExtIP model",
+                                            removedInternalIp, routerId);
+                                    naptManager.removeFromIpMapDS(routerId, removedInternalIp);
+                                }
 
-                        LOG.debug("update : Remove the count mapping of the external IP {} for the "
-                                        + "router ID {} from the ExternalIpsCounter model.",
-                                externalIpAddrStr, routerId);
-                        naptManager.removeExternalIpCounter(routerId, externalIpAddrStr);
+                                LOG.debug("update : Remove the count mapping of the external IP {} for the "
+                                                + "router ID {} from the ExternalIpsCounter model.",
+                                        externalIpAddrStr, routerId);
+                                naptManager.removeExternalIpCounter(routerId, externalIpAddrStr);
 
-                        LOG.debug("update : Allocate the least loaded external IPs to the subnets "
-                                + "whose external IPs were removed.");
-                        for (String removedInternalIp : removedInternalIps) {
-                            allocateExternalIp(dpnId, update, routerId, routerName, networkId, removedInternalIp,
-                                    writeFlowInvTx);
-                        }
+                                LOG.debug("update : Allocate the least loaded external IPs to the subnets "
+                                        + "whose external IPs were removed.");
+                                for (String removedInternalIp : removedInternalIps) {
+                                    allocateExternalIp(dpnId, update, routerId, routerName, networkId,
+                                            removedInternalIp, writeFlowInvTx);
+                                }
 
-                        LOG.debug("update : Remove the NAPT translation entries from "
-                                + "Inbound and Outbound NAPT tables for the removed external IPs.");
-                        //Get the internalIP and internal Port which were associated to the removed external IP.
-                        List<Integer> externalPorts = new ArrayList<>();
-                        Map<ProtocolTypes, List<String>> protoTypesIntIpPortsMap = new HashMap<>();
-                        InstanceIdentifier<IpPortMapping> ipPortMappingId = InstanceIdentifier
-                                .builder(IntextIpPortMap.class)
-                                .child(IpPortMapping.class, new IpPortMappingKey(routerId)).build();
-                        Optional<IpPortMapping> ipPortMapping =
-                                MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, ipPortMappingId);
-                        if (ipPortMapping.isPresent()) {
-                            List<IntextIpProtocolType> intextIpProtocolTypes = ipPortMapping.get()
-                                    .getIntextIpProtocolType();
-                            for (IntextIpProtocolType intextIpProtocolType : intextIpProtocolTypes) {
-                                ProtocolTypes protoType = intextIpProtocolType.getProtocol();
-                                List<IpPortMap> ipPortMaps = intextIpProtocolType.getIpPortMap();
-                                for (IpPortMap ipPortMap : ipPortMaps) {
-                                    IpPortExternal ipPortExternal = ipPortMap.getIpPortExternal();
-                                    if (ipPortExternal.getIpAddress().equals(externalIp)) {
-                                        externalPorts.add(ipPortExternal.getPortNum());
-                                        List<String> removedInternalIpPorts = protoTypesIntIpPortsMap.get(protoType);
-                                        if (removedInternalIpPorts != null) {
-                                            removedInternalIpPorts.add(ipPortMap.getIpPortInternal());
-                                            protoTypesIntIpPortsMap.put(protoType, removedInternalIpPorts);
-                                        } else {
-                                            removedInternalIpPorts = new ArrayList<>();
-                                            removedInternalIpPorts.add(ipPortMap.getIpPortInternal());
-                                            protoTypesIntIpPortsMap.put(protoType, removedInternalIpPorts);
+                                LOG.debug("update : Remove the NAPT translation entries from "
+                                        + "Inbound and Outbound NAPT tables for the removed external IPs.");
+                                //Get the internalIP and internal Port which were associated to the removed external IP.
+                                List<Integer> externalPorts = new ArrayList<>();
+                                Map<ProtocolTypes, List<String>> protoTypesIntIpPortsMap = new HashMap<>();
+                                InstanceIdentifier<IpPortMapping> ipPortMappingId = InstanceIdentifier
+                                        .builder(IntextIpPortMap.class)
+                                        .child(IpPortMapping.class, new IpPortMappingKey(routerId)).build();
+                                Optional<IpPortMapping> ipPortMapping =
+                                        MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, ipPortMappingId);
+                                if (ipPortMapping.isPresent()) {
+                                    List<IntextIpProtocolType> intextIpProtocolTypes = ipPortMapping.get()
+                                            .getIntextIpProtocolType();
+                                    for (IntextIpProtocolType intextIpProtocolType : intextIpProtocolTypes) {
+                                        ProtocolTypes protoType = intextIpProtocolType.getProtocol();
+                                        List<IpPortMap> ipPortMaps = intextIpProtocolType.getIpPortMap();
+                                        for (IpPortMap ipPortMap : ipPortMaps) {
+                                            IpPortExternal ipPortExternal = ipPortMap.getIpPortExternal();
+                                            if (ipPortExternal.getIpAddress().equals(externalIp)) {
+                                                externalPorts.add(ipPortExternal.getPortNum());
+                                                List<String> removedInternalIpPorts =
+                                                        protoTypesIntIpPortsMap.get(protoType);
+                                                if (removedInternalIpPorts != null) {
+                                                    removedInternalIpPorts.add(ipPortMap.getIpPortInternal());
+                                                    protoTypesIntIpPortsMap.put(protoType, removedInternalIpPorts);
+                                                } else {
+                                                    removedInternalIpPorts = new ArrayList<>();
+                                                    removedInternalIpPorts.add(ipPortMap.getIpPortInternal());
+                                                    protoTypesIntIpPortsMap.put(protoType, removedInternalIpPorts);
+                                                }
+                                            }
                                         }
                                     }
                                 }
-                            }
-                        }
 
-                        //Remove the IP port map from the intext-ip-port-map model, which were containing
-                        // the removed external IP.
-                        Set<Map.Entry<ProtocolTypes, List<String>>> protoTypesIntIpPorts = protoTypesIntIpPortsMap
-                                .entrySet();
-                        Map<String, List<String>> internalIpPortMap = new HashMap<>();
-                        for (Map.Entry protoTypesIntIpPort : protoTypesIntIpPorts) {
-                            ProtocolTypes protocolType = (ProtocolTypes) protoTypesIntIpPort.getKey();
-                            List<String> removedInternalIpPorts = (List<String>) protoTypesIntIpPort.getValue();
-                            for (String removedInternalIpPort : removedInternalIpPorts) {
-                                // Remove the IP port map from the intext-ip-port-map model,
-                                // which were containing the removed external IP
-                                naptManager.removeFromIpPortMapDS(routerId, removedInternalIpPort, protocolType);
-                                //Remove the IP port incomint packer map.
-                                naptPacketInHandler.removeIncomingPacketMap(routerId + NatConstants.COLON_SEPARATOR
-                                        + removedInternalIpPort);
-                                String[] removedInternalIpPortParts = removedInternalIpPort
-                                        .split(NatConstants.COLON_SEPARATOR);
-                                if (removedInternalIpPortParts.length == 2) {
-                                    String removedInternalIp = removedInternalIpPortParts[0];
-                                    String removedInternalPort = removedInternalIpPortParts[1];
-                                    List<String> removedInternalPortsList = internalIpPortMap.get(removedInternalPort);
-                                    if (removedInternalPortsList != null) {
-                                        removedInternalPortsList.add(removedInternalPort);
-                                        internalIpPortMap.put(removedInternalIp, removedInternalPortsList);
-                                    } else {
-                                        removedInternalPortsList = new ArrayList<>();
-                                        removedInternalPortsList.add(removedInternalPort);
-                                        internalIpPortMap.put(removedInternalIp, removedInternalPortsList);
+                                //Remove the IP port map from the intext-ip-port-map model, which were containing
+                                // the removed external IP.
+                                Set<Map.Entry<ProtocolTypes, List<String>>> protoTypesIntIpPorts =
+                                        protoTypesIntIpPortsMap.entrySet();
+                                Map<String, List<String>> internalIpPortMap = new HashMap<>();
+                                for (Map.Entry protoTypesIntIpPort : protoTypesIntIpPorts) {
+                                    ProtocolTypes protocolType = (ProtocolTypes) protoTypesIntIpPort.getKey();
+                                    List<String> removedInternalIpPorts = (List<String>) protoTypesIntIpPort.getValue();
+                                    for (String removedInternalIpPort : removedInternalIpPorts) {
+                                        // Remove the IP port map from the intext-ip-port-map model,
+                                        // which were containing the removed external IP
+                                        naptManager.removeFromIpPortMapDS(routerId, removedInternalIpPort,
+                                                protocolType);
+                                        //Remove the IP port incomint packer map.
+                                        naptPacketInHandler.removeIncomingPacketMap(
+                                                routerId + NatConstants.COLON_SEPARATOR + removedInternalIpPort);
+                                        String[] removedInternalIpPortParts = removedInternalIpPort
+                                                .split(NatConstants.COLON_SEPARATOR);
+                                        if (removedInternalIpPortParts.length == 2) {
+                                            String removedInternalIp = removedInternalIpPortParts[0];
+                                            String removedInternalPort = removedInternalIpPortParts[1];
+                                            List<String> removedInternalPortsList =
+                                                    internalIpPortMap.get(removedInternalPort);
+                                            if (removedInternalPortsList != null) {
+                                                removedInternalPortsList.add(removedInternalPort);
+                                                internalIpPortMap.put(removedInternalIp, removedInternalPortsList);
+                                            } else {
+                                                removedInternalPortsList = new ArrayList<>();
+                                                removedInternalPortsList.add(removedInternalPort);
+                                                internalIpPortMap.put(removedInternalIp, removedInternalPortsList);
+                                            }
+                                        }
                                     }
                                 }
-                            }
-                        }
 
-                        // Delete the entry from SnatIntIpPortMap DS
-                        Set<String> internalIps = internalIpPortMap.keySet();
-                        for (String internalIp : internalIps) {
-                            LOG.debug("update : Removing IpPort having the internal IP {} from the "
-                                    + "model SnatIntIpPortMap", internalIp);
-                            naptManager.removeFromSnatIpPortDS(routerId, internalIp);
-                        }
+                                // Delete the entry from SnatIntIpPortMap DS
+                                Set<String> internalIps = internalIpPortMap.keySet();
+                                for (String internalIp : internalIps) {
+                                    LOG.debug("update : Removing IpPort having the internal IP {} from the "
+                                            + "model SnatIntIpPortMap", internalIp);
+                                    naptManager.removeFromSnatIpPortDS(routerId, internalIp);
+                                }
 
-                        naptManager.removeNaptPortPool(externalIp);
+                                naptManager.removeNaptPortPool(externalIp);
 
-                        LOG.debug("update : Remove the NAPT translation entries from Inbound NAPT tables for the "
-                                + "removed external IP {}", externalIp);
-                        for (Integer externalPort : externalPorts) {
-                            //Remove the NAPT translation entries from Inbound NAPT table
-                            naptEventHandler.removeNatFlows(dpnId, NwConstants.INBOUND_NAPT_TABLE,
-                                    routerId, externalIp, externalPort);
-                        }
+                                LOG.debug("update : Remove the NAPT translation entries from Inbound NAPT tables for "
+                                        + "the removed external IP {}", externalIp);
+                                for (Integer externalPort : externalPorts) {
+                                    //Remove the NAPT translation entries from Inbound NAPT table
+                                    naptEventHandler.removeNatFlows(dpnId, NwConstants.INBOUND_NAPT_TABLE,
+                                            routerId, externalIp, externalPort);
+                                }
 
-                        Set<Map.Entry<String, List<String>>> internalIpPorts = internalIpPortMap.entrySet();
-                        for (Map.Entry<String, List<String>> internalIpPort : internalIpPorts) {
-                            String internalIp = internalIpPort.getKey();
-                            LOG.debug("update : Remove the NAPT translation entries from Outbound NAPT tables for "
-                                    + "the removed internal IP {}", internalIp);
-                            List<String> internalPorts = internalIpPort.getValue();
-                            for (String internalPort : internalPorts) {
-                                //Remove the NAPT translation entries from Outbound NAPT table
-                                naptPacketInHandler.removeIncomingPacketMap(routerId + NatConstants.COLON_SEPARATOR
-                                        + internalIp + NatConstants.COLON_SEPARATOR + internalPort);
-                                naptEventHandler.removeNatFlows(dpnId, NwConstants.OUTBOUND_NAPT_TABLE,
-                                        routerId, internalIp, Integer.parseInt(internalPort));
+                                Set<Map.Entry<String, List<String>>> internalIpPorts = internalIpPortMap.entrySet();
+                                for (Map.Entry<String, List<String>> internalIpPort : internalIpPorts) {
+                                    String internalIp = internalIpPort.getKey();
+                                    LOG.debug("update : Remove the NAPT translation entries from Outbound NAPT tables "
+                                            + "for the removed internal IP {}", internalIp);
+                                    List<String> internalPorts = internalIpPort.getValue();
+                                    for (String internalPort : internalPorts) {
+                                        //Remove the NAPT translation entries from Outbound NAPT table
+                                        naptPacketInHandler.removeIncomingPacketMap(
+                                                routerId + NatConstants.COLON_SEPARATOR + internalIp
+                                                        + NatConstants.COLON_SEPARATOR + internalPort);
+                                        naptEventHandler.removeNatFlows(dpnId, NwConstants.OUTBOUND_NAPT_TABLE,
+                                                routerId, internalIp, Integer.parseInt(internalPort));
+                                    }
+                                }
                             }
+                            LOG.debug(
+                                    "update : End processing of the External IPs removal during the update operation");
                         }
-                    }
-                    LOG.debug("update : End processing of the External IPs removal during the update operation");
-                }
 
-                //Check if its Update on subnets
-                LOG.debug("update : Checking if this is update on subnets");
-                List<Uuid> originalSubnetIds = original.getSubnetIds();
-                List<Uuid> updatedSubnetIds = update.getSubnetIds();
-                Set<Uuid> addedSubnetIds = new HashSet<>(updatedSubnetIds);
-                addedSubnetIds.removeAll(originalSubnetIds);
-
-                //Check if the Subnet IDs are added during the update.
-                if (addedSubnetIds.size() != 0) {
-                    LOG.debug("update : Start processing of the Subnet IDs addition during the update operation");
-                    for (Uuid addedSubnetId : addedSubnetIds) {
+                        //Check if its Update on subnets
+                        LOG.debug("update : Checking if this is update on subnets");
+                        List<Uuid> originalSubnetIds = original.getSubnetIds();
+                        List<Uuid> updatedSubnetIds = update.getSubnetIds();
+                        Set<Uuid> addedSubnetIds = new HashSet<>(updatedSubnetIds);
+                        addedSubnetIds.removeAll(originalSubnetIds);
+
+                        //Check if the Subnet IDs are added during the update.
+                        if (addedSubnetIds.size() != 0) {
+                            LOG.debug(
+                                    "update : Start processing of the Subnet IDs addition during the update operation");
+                            for (Uuid addedSubnetId : addedSubnetIds) {
                     /*
                         1) Select the least loaded external IP for the subnet and store the mapping of the
                         subnet IP and the external IP in the IntExtIp model.
@@ -1476,24 +1485,24 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
                         3) Advertise to the BGP if external IP is allocated for the first time for the
                         router i.e. the route for the external IP is absent.
                      */
-                        String subnetIp = NatUtil.getSubnetIp(dataBroker, addedSubnetId);
-                        if (subnetIp != null) {
-                            allocateExternalIp(dpnId, update, routerId, routerName, networkId, subnetIp,
-                                    writeFlowInvTx);
+                                String subnetIp = NatUtil.getSubnetIp(dataBroker, addedSubnetId);
+                                if (subnetIp != null) {
+                                    allocateExternalIp(dpnId, update, routerId, routerName, networkId, subnetIp,
+                                            writeFlowInvTx);
+                                }
+                            }
+                            LOG.debug("update : End processing of the Subnet IDs addition during the update operation");
                         }
-                    }
-                    LOG.debug("update : End processing of the Subnet IDs addition during the update operation");
-                }
 
-                //Check if the Subnet IDs are removed during the update.
-                Set<Uuid> removedSubnetIds = new HashSet<>(originalSubnetIds);
-                removedSubnetIds.removeAll(updatedSubnetIds);
-                List<ListenableFuture<Void>> futures = new ArrayList<>();
-                if (removedSubnetIds.size() != 0) {
-                    LOG.debug("update : Start processing of the Subnet IDs removal during the update operation");
-                    for (Uuid removedSubnetId : removedSubnetIds) {
-                        String[] subnetAddr = NatUtil.getSubnetIpAndPrefix(dataBroker, removedSubnetId);
-                        if (subnetAddr != null) {
+                        //Check if the Subnet IDs are removed during the update.
+                        Set<Uuid> removedSubnetIds = new HashSet<>(originalSubnetIds);
+                        removedSubnetIds.removeAll(updatedSubnetIds);
+                        if (removedSubnetIds.size() != 0) {
+                            LOG.debug(
+                                    "update : Start processing of the Subnet IDs removal during the update operation");
+                            for (Uuid removedSubnetId : removedSubnetIds) {
+                                String[] subnetAddr = NatUtil.getSubnetIpAndPrefix(dataBroker, removedSubnetId);
+                                if (subnetAddr != null) {
                         /*
                             1) Remove the subnet IP and the external IP in the IntExtIp map
                             2) Decrease the count of the coresponding external IP by one.
@@ -1501,39 +1510,37 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
                             IP if its not allocated to any other internal IP.
                         */
 
-                            String externalIp =
-                                    naptManager.getExternalIpAllocatedForSubnet(routerId, subnetAddr[0] + "/"
-                                            + subnetAddr[1]);
-                            if (externalIp == null) {
-                                LOG.error("update : No mapping found for router ID {} and internal IP {}",
-                                        routerId, subnetAddr[0]);
-                                futures.add(NatUtil.waitForTransactionToComplete(writeFlowInvTx));
-                                futures.add(NatUtil.waitForTransactionToComplete(removeFlowInvTx));
-                                return futures;
-                            }
+                                    String externalIp = naptManager.getExternalIpAllocatedForSubnet(routerId,
+                                            subnetAddr[0] + "/" + subnetAddr[1]);
+                                    if (externalIp == null) {
+                                        LOG.error("update : No mapping found for router ID {} and internal IP {}",
+                                                routerId, subnetAddr[0]);
+                                        return;
+                                    }
 
-                            naptManager.updateCounter(routerId, externalIp, false);
-                            // Traverse entire model of external-ip counter whether external ip is not
-                            // used by any other internal ip in any router
-                            if (!isExternalIpAllocated(externalIp)) {
-                                LOG.debug("update : external ip is not allocated to any other "
-                                        + "internal IP so proceeding to remove routes");
-                                clrRtsFromBgpAndDelFibTs(dpnId, routerId, networkId, Collections.singleton(externalIp),
-                                        null, update.getExtGwMacAddress(), removeFlowInvTx);
-                                LOG.debug("update : Successfully removed fib entries in switch {} for "
-                                                + "router {} with networkId {} and externalIp {}",
-                                        dpnId, routerId, networkId, externalIp);
-                            }
+                                    naptManager.updateCounter(routerId, externalIp, false);
+                                    // Traverse entire model of external-ip counter whether external ip is not
+                                    // used by any other internal ip in any router
+                                    if (!isExternalIpAllocated(externalIp)) {
+                                        LOG.debug("update : external ip is not allocated to any other "
+                                                + "internal IP so proceeding to remove routes");
+                                        clrRtsFromBgpAndDelFibTs(dpnId, routerId, networkId,
+                                                Collections.singleton(externalIp), null, update.getExtGwMacAddress(),
+                                                removeFlowInvTx);
+                                        LOG.debug("update : Successfully removed fib entries in switch {} for "
+                                                        + "router {} with networkId {} and externalIp {}",
+                                                dpnId, routerId, networkId, externalIp);
+                                    }
 
-                            LOG.debug("update : Remove the IP mapping for the router ID {} and "
-                                    + "internal IP {} external IP {}", routerId, subnetAddr[0], externalIp);
-                            naptManager.removeIntExtIpMapDS(routerId, subnetAddr[0] + "/" + subnetAddr[1]);
+                                    LOG.debug("update : Remove the IP mapping for the router ID {} and "
+                                            + "internal IP {} external IP {}", routerId, subnetAddr[0], externalIp);
+                                    naptManager.removeIntExtIpMapDS(routerId, subnetAddr[0] + "/" + subnetAddr[1]);
+                                }
+                            }
+                            LOG.debug("update : End processing of the Subnet IDs removal during the update operation");
                         }
-                    }
-                    LOG.debug("update : End processing of the Subnet IDs removal during the update operation");
-                }
-                futures.add(NatUtil.waitForTransactionToComplete(writeFlowInvTx));
-                futures.add(NatUtil.waitForTransactionToComplete(removeFlowInvTx));
+                    }));
+                }));
                 return futures;
             }, NatConstants.NAT_DJC_MAX_RETRIES);
         } //end of controller based SNAT
@@ -1670,40 +1677,43 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
                     centralizedSwitchScheduler.releaseCentralizedSwitch(router);
                 }
             } else {
-                coordinator.enqueueJob(NatConstants.NAT_DJC_PREFIX + router.getKey(), () -> {
-                    LOG.info("remove : Removing default NAT route from FIB on all dpns part of router {} ", routerName);
-                    List<ListenableFuture<Void>> futures = new ArrayList<>();
-                    Long routerId = NatUtil.getVpnId(dataBroker, routerName);
-                    if (routerId == NatConstants.INVALID_ID) {
-                        LOG.error("remove : Remove external router event - Invalid routerId for routerName {}",
+                coordinator.enqueueJob(NatConstants.NAT_DJC_PREFIX + router.getKey(),
+                    () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
+                        LOG.info("remove : Removing default NAT route from FIB on all dpns part of router {} ",
                                 routerName);
-                        return futures;
-                    }
-                    long bgpVpnId = NatConstants.INVALID_ID;
-                    Uuid bgpVpnUuid = NatUtil.getVpnForRouter(dataBroker, routerName);
-                    if (bgpVpnUuid != null) {
-                        bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnUuid.getValue());
-                    }
-                    WriteTransaction removeFlowInvTx = dataBroker.newWriteOnlyTransaction();
-                    addOrDelDefFibRouteToSNAT(routerName, routerId, bgpVpnId, bgpVpnUuid, false, removeFlowInvTx);
-                    Uuid networkUuid = router.getNetworkId();
-
-                    BigInteger primarySwitchId = NatUtil.getPrimaryNaptfromRouterName(dataBroker, routerName);
-                    if (primarySwitchId == null || primarySwitchId.equals(BigInteger.ZERO)) {
-                        // No NAPT switch for external router, probably because the router is not attached to any
-                        // internal networks
-                        LOG.debug("No NAPT switch for router {}, check if router is attached to any internal network",
-                                routerName);
-                        return futures;
-                    } else {
-                        Collection<String> externalIps = NatUtil.getExternalIpsForRouter(dataBroker, routerId);
-                        handleDisableSnat(router, networkUuid, externalIps, true, null, primarySwitchId,
-                                routerId, removeFlowInvTx);
-                    }
-                    NatOverVxlanUtil.releaseVNI(routerName, idManager);
-                    futures.add(NatUtil.waitForTransactionToComplete(removeFlowInvTx));
-                    return futures;
-                }, NatConstants.NAT_DJC_MAX_RETRIES);
+                        List<ListenableFuture<Void>> futures = new ArrayList<>();
+                        Long routerId = NatUtil.getVpnId(dataBroker, routerName);
+                        if (routerId == NatConstants.INVALID_ID) {
+                            LOG.error("remove : Remove external router event - Invalid routerId for routerName {}",
+                                    routerName);
+                            return;
+                        }
+                        long bgpVpnId = NatConstants.INVALID_ID;
+                        Uuid bgpVpnUuid = NatUtil.getVpnForRouter(dataBroker, routerName);
+                        if (bgpVpnUuid != null) {
+                            bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnUuid.getValue());
+                        }
+                        addOrDelDefFibRouteToSNAT(routerName, routerId, bgpVpnId, bgpVpnUuid, false,
+                                tx);
+                        Uuid networkUuid = router.getNetworkId();
+
+                        BigInteger primarySwitchId = NatUtil.getPrimaryNaptfromRouterName(dataBroker, routerName);
+                        if (primarySwitchId == null || primarySwitchId.equals(BigInteger.ZERO)) {
+                            // No NAPT switch for external router, probably because the router is not attached to
+                            // any
+                            // internal networks
+                            LOG.debug(
+                                    "No NAPT switch for router {}, check if router is attached to any internal "
+                                            + "network",
+                                    routerName);
+                            return;
+                        } else {
+                            Collection<String> externalIps = NatUtil.getExternalIpsForRouter(dataBroker, routerId);
+                            handleDisableSnat(router, networkUuid, externalIps, true, null, primarySwitchId,
+                                    routerId, tx);
+                        }
+                        NatOverVxlanUtil.releaseVNI(routerName, idManager);
+                    })), NatConstants.NAT_DJC_MAX_RETRIES);
             }
         }
     }
index 87839c88725aafa176deddb5b10c27a95adb8b8e..4267deacda0734f733a2dbfb2f236ae114c06c33 100644 (file)
@@ -8,11 +8,11 @@
 package org.opendaylight.netvirt.natservice.internal;
 
 import com.google.common.base.Optional;
-import com.google.common.util.concurrent.ListenableFuture;
 import java.math.BigInteger;
 import java.net.InetAddress;
 import java.net.UnknownHostException;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 import javax.annotation.PostConstruct;
 import javax.inject.Inject;
@@ -22,6 +22,8 @@ import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
+import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
+import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
 import org.opendaylight.genius.mdsalutil.ActionInfo;
 import org.opendaylight.genius.mdsalutil.FlowEntity;
 import org.opendaylight.genius.mdsalutil.InstructionInfo;
@@ -43,6 +45,7 @@ import org.opendaylight.genius.mdsalutil.matches.MatchIpv4Destination;
 import org.opendaylight.genius.mdsalutil.matches.MatchIpv4Source;
 import org.opendaylight.genius.mdsalutil.matches.MatchMetadata;
 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
+import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
 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.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
@@ -66,6 +69,7 @@ import org.slf4j.LoggerFactory;
 public class FloatingIPListener extends AsyncDataTreeChangeListenerBase<InternalToExternalPortMap, FloatingIPListener> {
     private static final Logger LOG = LoggerFactory.getLogger(FloatingIPListener.class);
     private final DataBroker dataBroker;
+    private final ManagedNewTransactionRunner txRunner;
     private final IMdsalApiManager mdsalManager;
     private final OdlInterfaceRpcService interfaceManager;
     private final FloatingIPHandler floatingIPHandler;
@@ -80,6 +84,7 @@ public class FloatingIPListener extends AsyncDataTreeChangeListenerBase<Internal
                               final JobCoordinator coordinator) {
         super(InternalToExternalPortMap.class, FloatingIPListener.class);
         this.dataBroker = dataBroker;
+        this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
         this.mdsalManager = mdsalManager;
         this.interfaceManager = interfaceManager;
         this.floatingIPHandler = floatingIPHandler;
@@ -380,14 +385,10 @@ public class FloatingIPListener extends AsyncDataTreeChangeListenerBase<Internal
         String interfaceName = pKey.getPortName();
 
         InstanceIdentifier<RouterPorts> portIid = identifier.firstIdentifierOf(RouterPorts.class);
-        coordinator.enqueueJob(NatConstants.NAT_DJC_PREFIX + mapping.getKey(), () -> {
-            WriteTransaction writeFlowInvTx = dataBroker.newWriteOnlyTransaction();
-            List<ListenableFuture<Void>> futures = new ArrayList<>();
-            createNATFlowEntries(interfaceName, mapping, portIid, routerId, writeFlowInvTx);
-            //final submit call for writeFlowInvTx
-            futures.add(NatUtil.waitForTransactionToComplete(writeFlowInvTx));
-            return futures;
-        }, NatConstants.NAT_DJC_MAX_RETRIES);
+        coordinator.enqueueJob(NatConstants.NAT_DJC_PREFIX + mapping.getKey(), () -> Collections.singletonList(
+                txRunner.callWithNewWriteOnlyTransactionAndSubmit(
+                    tx -> createNATFlowEntries(interfaceName, mapping, portIid, routerId, tx))),
+                NatConstants.NAT_DJC_MAX_RETRIES);
     }
 
     private void processFloatingIPDel(final InstanceIdentifier<InternalToExternalPortMap> identifier,
@@ -399,14 +400,10 @@ public class FloatingIPListener extends AsyncDataTreeChangeListenerBase<Internal
         String interfaceName = pKey.getPortName();
 
         InstanceIdentifier<RouterPorts> portIid = identifier.firstIdentifierOf(RouterPorts.class);
-        coordinator.enqueueJob(NatConstants.NAT_DJC_PREFIX + mapping.getKey(), () -> {
-            WriteTransaction removeFlowInvTx = dataBroker.newWriteOnlyTransaction();
-            List<ListenableFuture<Void>> futures = new ArrayList<>();
-            removeNATFlowEntries(interfaceName, mapping, portIid, routerId, null, removeFlowInvTx);
-            //final submit call for removeFlowInvTx
-            futures.add(NatUtil.waitForTransactionToComplete(removeFlowInvTx));
-            return futures;
-        }, NatConstants.NAT_DJC_MAX_RETRIES);
+        coordinator.enqueueJob(NatConstants.NAT_DJC_PREFIX + mapping.getKey(), () -> Collections.singletonList(
+                txRunner.callWithNewWriteOnlyTransactionAndSubmit(
+                    tx -> removeNATFlowEntries(interfaceName, mapping, portIid, routerId, null, tx))),
+                NatConstants.NAT_DJC_MAX_RETRIES);
     }
 
     private InetAddress getInetAddress(String ipAddr) {
@@ -772,10 +769,11 @@ public class FloatingIPListener extends AsyncDataTreeChangeListenerBase<Internal
 
     private void addOrDelDefaultFibRouteForDnat(BigInteger dpnId, String routerName,
                                                 long routerId, WriteTransaction tx, boolean create) {
-        Boolean wrTxPresent = true;
         if (tx == null) {
-            wrTxPresent = false;
-            tx = dataBroker.newWriteOnlyTransaction();
+            ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(
+                newTx -> addOrDelDefaultFibRouteForDnat(dpnId, routerName, routerId, newTx, create)), LOG,
+                "Error handling default FIB route for DNAT");
+            return;
         }
         //Check if the router to bgp-vpn association is present
         long associatedVpnId = NatConstants.INVALID_ID;
@@ -804,8 +802,5 @@ public class FloatingIPListener extends AsyncDataTreeChangeListenerBase<Internal
                 defaultRouteProgrammer.removeDefNATRouteInDPN(dpnId, routerId, tx);
             }
         }
-        if (!wrTxPresent) {
-            tx.submit();
-        }
     }
 }
index f71235e30671298e38d4897bcbebde14b21b7306..277cf06c9301957254b74d78d409a8bc42ddb00a 100644 (file)
@@ -26,6 +26,8 @@ import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
+import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
+import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
 import org.opendaylight.genius.mdsalutil.FlowEntity;
 import org.opendaylight.genius.mdsalutil.NwConstants;
 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
@@ -64,6 +66,7 @@ public class NatInterfaceStateChangeListener
     private static final Logger LOG = LoggerFactory.getLogger(NatInterfaceStateChangeListener.class);
     private static final String NAT_DS = "NATDS";
     private final DataBroker dataBroker;
+    private final ManagedNewTransactionRunner txRunner;
     private final OdlInterfaceRpcService odlInterfaceRpcService;
     private final JobCoordinator coordinator;
     private final FloatingIPListener floatingIPListener;
@@ -99,6 +102,7 @@ public class NatInterfaceStateChangeListener
             final IMdsalApiManager mdsalManager, final NaptManager naptManager) {
         super(Interface.class, NatInterfaceStateChangeListener.class);
         this.dataBroker = dataBroker;
+        this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
         this.odlInterfaceRpcService = odlInterfaceRpcService;
         this.coordinator = coordinator;
         this.floatingIPListener = floatingIPListener;
@@ -315,9 +319,8 @@ public class NatInterfaceStateChangeListener
             List<ListenableFuture<Void>> futures = new ArrayList<>();
             try {
                 LOG.trace("call : Received interface {} PORT UP OR ADD event ", interfaceName);
-                WriteTransaction writeOperTxn = dataBroker.newWriteOnlyTransaction();
-                handleRouterInterfacesUpEvent(routerName, interfaceName, intfDpnId, writeOperTxn);
-                futures.add(writeOperTxn.submit());
+                futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx ->
+                    handleRouterInterfacesUpEvent(routerName, interfaceName, intfDpnId, tx)));
             } catch (Exception e) {
                 LOG.error("call : Exception caught in Interface {} Operational State Up event",
                         interfaceName, e);
@@ -343,9 +346,8 @@ public class NatInterfaceStateChangeListener
             List<ListenableFuture<Void>> futures = new ArrayList<>();
             try {
                 LOG.trace("call : Received interface {} PORT DOWN or REMOVE event", interfaceName);
-                WriteTransaction writeOperTxn = dataBroker.newWriteOnlyTransaction();
-                handleRouterInterfacesDownEvent(routerName, interfaceName, intfDpnId, writeOperTxn);
-                futures.add(writeOperTxn.submit());
+                futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx ->
+                        handleRouterInterfacesDownEvent(routerName, interfaceName, intfDpnId, tx)));
             } catch (Exception e) {
                 LOG.error("call : Exception observed in handling deletion of VPN Interface {}.", interfaceName, e);
             }
@@ -374,27 +376,27 @@ public class NatInterfaceStateChangeListener
                 final String interfaceName = update.getName();
                 LOG.trace("call : Received interface {} state change event", interfaceName);
                 LOG.debug("call : DPN ID {} for the interface {} ", intfDpnId, interfaceName);
-                WriteTransaction writeOperTxn = dataBroker.newWriteOnlyTransaction();
                 IntfTransitionState state = getTransitionState(original.getOperStatus(), update.getOperStatus());
                 if (state.equals(IntfTransitionState.STATE_IGNORE)) {
                     LOG.info("NAT Service: Interface {} state original {} updated {} not handled",
                             interfaceName, original.getOperStatus(), update.getOperStatus());
                     return futures;
                 }
-                if (state.equals(IntfTransitionState.STATE_DOWN)) {
-                    LOG.debug("call : DPN {} connnected to the interface {} has gone down."
-                            + "Hence clearing the dpn-vpninterfaces-list entry from the"
-                            + " neutron-router-dpns model in the ODL:L3VPN", intfDpnId, interfaceName);
-                    // If the interface state is unknown, it means that the corresponding DPN has gone down.
-                    // So remove the dpn-vpninterfaces-list from the neutron-router-dpns model.
-                    NatUtil.removeFromNeutronRouterDpnsMap(dataBroker, routerName, intfDpnId, writeOperTxn);
-                } else if (state.equals(IntfTransitionState.STATE_UP)) {
-                    LOG.debug("call : DPN {} connnected to the interface {} has come up. Hence adding"
-                            + " the dpn-vpninterfaces-list entry from the neutron-router-dpns model"
-                            + " in the ODL:L3VPN", intfDpnId, interfaceName);
-                    handleRouterInterfacesUpEvent(routerName, interfaceName, intfDpnId, writeOperTxn);
-                }
-                futures.add(writeOperTxn.submit());
+                futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
+                    if (state.equals(IntfTransitionState.STATE_DOWN)) {
+                        LOG.debug("call : DPN {} connnected to the interface {} has gone down."
+                                + "Hence clearing the dpn-vpninterfaces-list entry from the"
+                                + " neutron-router-dpns model in the ODL:L3VPN", intfDpnId, interfaceName);
+                        // If the interface state is unknown, it means that the corresponding DPN has gone down.
+                        // So remove the dpn-vpninterfaces-list from the neutron-router-dpns model.
+                        NatUtil.removeFromNeutronRouterDpnsMap(dataBroker, routerName, intfDpnId, tx);
+                    } else if (state.equals(IntfTransitionState.STATE_UP)) {
+                        LOG.debug("call : DPN {} connnected to the interface {} has come up. Hence adding"
+                                + " the dpn-vpninterfaces-list entry from the neutron-router-dpns model"
+                                + " in the ODL:L3VPN", intfDpnId, interfaceName);
+                        handleRouterInterfacesUpEvent(routerName, interfaceName, intfDpnId, tx);
+                    }
+                }));
             } catch (Exception e) {
                 LOG.error("call : Exception observed in handling updation of VPN Interface {}.", update.getName(), e);
             }
@@ -410,12 +412,17 @@ public class NatInterfaceStateChangeListener
             return;
         }
         InstanceIdentifier<RouterPorts> portIid = NatUtil.buildRouterPortsIdentifier(routerId);
-        WriteTransaction installFlowInvTx = dataBroker.newWriteOnlyTransaction();
-        for (InternalToExternalPortMap intExtPortMap : intExtPortMapList) {
-            floatingIPListener.createNATFlowEntries(portName, intExtPortMap, portIid, routerId, installFlowInvTx);
+        ListenableFuture<Void> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
+            for (InternalToExternalPortMap intExtPortMap : intExtPortMapList) {
+                floatingIPListener.createNATFlowEntries(portName, intExtPortMap, portIid, routerId, tx);
+            }
+        });
+        futures.add(future);
+        try {
+            future.get();
+        } catch (InterruptedException | ExecutionException e) {
+            LOG.error("Error processing interface addition", e);
         }
-        //final submit call for installFlowInvTx
-        futures.add(NatUtil.waitForTransactionToComplete(installFlowInvTx));
     }
 
     private List<InternalToExternalPortMap> getIntExtPortMapListForPortName(String portName, String routerId) {
@@ -484,13 +491,18 @@ public class NatInterfaceStateChangeListener
             return;
         }
         InstanceIdentifier<RouterPorts> portIid = NatUtil.buildRouterPortsIdentifier(routerId);
-        WriteTransaction removeFlowInvTx = dataBroker.newWriteOnlyTransaction();
-        for (InternalToExternalPortMap intExtPortMap : intExtPortMapList) {
-            LOG.trace("processInterfaceRemoved : Removing DNAT Flow entries for dpnId {} ", dpnId);
-            floatingIPListener.removeNATFlowEntries(portName, intExtPortMap, portIid, routerId, dpnId, removeFlowInvTx);
+        ListenableFuture<Void> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
+            for (InternalToExternalPortMap intExtPortMap : intExtPortMapList) {
+                LOG.trace("processInterfaceRemoved : Removing DNAT Flow entries for dpnId {} ", dpnId);
+                floatingIPListener.removeNATFlowEntries(portName, intExtPortMap, portIid, routerId, dpnId, tx);
+            }
+        });
+        futures.add(future);
+        try {
+            future.get();
+        } catch (InterruptedException | ExecutionException e) {
+            LOG.error("Error processing interface removal", e);
         }
-        // final submit call for removeFlowInvTx
-        futures.add(NatUtil.waitForTransactionToComplete(removeFlowInvTx));
     }
 
     // TODO Clean up the exception handling
index 5d398329f25f745564add88a8af45f44f58c3864..ce7ea592b596f023ca7f4c74b3e821dc1953ac42 100644 (file)
@@ -12,10 +12,12 @@ import javax.annotation.PostConstruct;
 import javax.inject.Inject;
 import javax.inject.Singleton;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
+import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
+import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
 import org.opendaylight.genius.mdsalutil.MDSALUtil;
+import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.router.interfaces.RouterInterface;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.router.interfaces.RouterInterfaceBuilder;
@@ -33,12 +35,14 @@ public class NatRouterInterfaceListener
 
     private static final Logger LOG = LoggerFactory.getLogger(NatRouterInterfaceListener.class);
     private final DataBroker dataBroker;
+    private final ManagedNewTransactionRunner txRunner;
     private final OdlInterfaceRpcService interfaceManager;
 
     @Inject
     public NatRouterInterfaceListener(final DataBroker dataBroker, final OdlInterfaceRpcService interfaceManager) {
         super(Interfaces.class, NatRouterInterfaceListener.class);
         this.dataBroker = dataBroker;
+        this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
         this.interfaceManager = interfaceManager;
     }
 
@@ -77,7 +81,6 @@ public class NatRouterInterfaceListener
 
         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces
             .state.Interface interfaceState = NatUtil.getInterfaceStateFromOperDS(dataBroker, interfaceName);
-        WriteTransaction writeOperTxn = dataBroker.newWriteOnlyTransaction();
         if (interfaceState != null) {
             BigInteger dpId = NatUtil.getDpnForInterface(interfaceManager, interfaceName);
             if (dpId.equals(BigInteger.ZERO)) {
@@ -85,14 +88,14 @@ public class NatRouterInterfaceListener
                         interfaceName, routerId);
                 return;
             }
-            NatUtil.addToNeutronRouterDpnsMap(dataBroker, routerId, interfaceName, dpId, writeOperTxn);
-            NatUtil.addToDpnRoutersMap(dataBroker, routerId, interfaceName, dpId, writeOperTxn);
+            ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(operTx -> {
+                NatUtil.addToNeutronRouterDpnsMap(dataBroker, routerId, interfaceName, dpId, operTx);
+                NatUtil.addToDpnRoutersMap(dataBroker, routerId, interfaceName, dpId, operTx);
+            }), LOG, "Error processing NAT router interface addition");
         } else {
             LOG.info("add : Interface {} not yet operational to handle router interface add event in router {}",
                     interfaceName, routerId);
         }
-
-        writeOperTxn.submit();
     }
 
     @Override
@@ -102,15 +105,17 @@ public class NatRouterInterfaceListener
         final String interfaceName = interfaceInfo.getInterfaceId();
 
         //Delete the RouterInterfaces maintained in the ODL:L3VPN configuration model
-        WriteTransaction writeTxn = dataBroker.newWriteOnlyTransaction();
-        writeTxn.delete(LogicalDatastoreType.CONFIGURATION, NatUtil.getRouterInterfaceId(interfaceName));
+        ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(confTx -> {
+            confTx.delete(LogicalDatastoreType.CONFIGURATION, NatUtil.getRouterInterfaceId(interfaceName));
+        }), LOG, "Error handling NAT router interface removal");
 
-        //Delete the NeutronRouterDpnMap from the ODL:L3VPN operational model
-        NatUtil.removeFromNeutronRouterDpnsMap(dataBroker, routerId, interfaceName, interfaceManager, writeTxn);
+        ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(operTx -> {
+            //Delete the NeutronRouterDpnMap from the ODL:L3VPN operational model
+            NatUtil.removeFromNeutronRouterDpnsMap(dataBroker, routerId, interfaceName, interfaceManager, operTx);
 
-        //Delete the DpnRouterMap from the ODL:L3VPN operational model
-        NatUtil.removeFromDpnRoutersMap(dataBroker, routerId, interfaceName, interfaceManager, writeTxn);
-        writeTxn.submit();
+            //Delete the DpnRouterMap from the ODL:L3VPN operational model
+            NatUtil.removeFromDpnRoutersMap(dataBroker, routerId, interfaceName, interfaceManager, operTx);
+        }), LOG, "Error handling NAT router interface removal");
     }
 
     @Override
index ce2d8dade40baa0c7254278b755816704aa21ba7..ab77e9a5569731088f51372060a1a4f25d407ef6 100644 (file)
@@ -20,6 +20,7 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.ExecutionException;
 import javax.annotation.Nonnull;
 import javax.annotation.PostConstruct;
 import javax.inject.Inject;
@@ -29,6 +30,8 @@ import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
+import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
+import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
 import org.opendaylight.genius.mdsalutil.BucketInfo;
 import org.opendaylight.genius.mdsalutil.FlowEntity;
@@ -85,6 +88,7 @@ public class NatTunnelInterfaceStateListener
 
     private static final Logger LOG = LoggerFactory.getLogger(NatTunnelInterfaceStateListener.class);
     private final DataBroker dataBroker;
+    private final ManagedNewTransactionRunner txRunner;
     private final IFibManager fibManager;
     private final SNATDefaultRouteProgrammer defaultRouteProgrammer;
     private final NaptSwitchHA naptSwitchHA;
@@ -143,6 +147,7 @@ public class NatTunnelInterfaceStateListener
                                            final IInterfaceManager interfaceManager) {
         super(StateTunnelList.class, NatTunnelInterfaceStateListener.class);
         this.dataBroker = dataBroker;
+        this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
         this.bgpManager = bgpManager;
         this.fibManager = fibManager;
         this.defaultRouteProgrammer = defaultRouteProgrammer;
@@ -343,21 +348,30 @@ public class NatTunnelInterfaceStateListener
 
             switch (tunnelAction) {
                 case TUNNEL_EP_ADD:
-                    WriteTransaction writeFlowInvTx = dataBroker.newWriteOnlyTransaction();
-                    if (isTunnelInLogicalGroup(stateTunnelList)
-                            || !hndlTepAddForAllRtrs(srcDpnId, tunnelType, tunnelName, srcTepIp, destTepIp,
-                            writeFlowInvTx)) {
-                        LOG.debug("hndlTepEvntsForDpn : Unable to process TEP ADD");
+                    try {
+                        txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
+                            if (isTunnelInLogicalGroup(stateTunnelList)
+                                    || !hndlTepAddForAllRtrs(srcDpnId, tunnelType, tunnelName, srcTepIp, destTepIp,
+                                    tx)) {
+                                LOG.debug("hndlTepEvntsForDpn : Unable to process TEP ADD");
+                            }
+                        }).get();
+                    } catch (InterruptedException | ExecutionException e) {
+                        LOG.error("Error processing tunnel endpoint addition", e);
                     }
-                    NatUtil.waitForTransactionToComplete(writeFlowInvTx);
                     break;
                 case TUNNEL_EP_DELETE:
-                    WriteTransaction writeFlowRemovetx = dataBroker.newWriteOnlyTransaction();
-                    if (!handleTepDelForAllRtrs(srcDpnId, tunnelType, tunnelName, srcTepIp, destTepIp,
-                            writeFlowRemovetx)) {
-                        LOG.debug("hndlTepEvntsForDpn : Unable to process TEP DEL");
+                    try {
+                        txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
+                            if (!handleTepDelForAllRtrs(srcDpnId, tunnelType, tunnelName, srcTepIp, destTepIp, tx)) {
+                                LOG.debug("hndlTepEvntsForDpn : Unable to process TEP DEL");
+                            }
+                        }).get();
+                    } catch (InterruptedException | ExecutionException e) {
+                        LOG.error("Error processing tunnel endpoint removal", e);
                     }
-                    NatUtil.waitForTransactionToComplete(writeFlowRemovetx);
+                    break;
+                case TUNNEL_EP_UPDATE:
                     break;
                 default:
                     LOG.warn("hndlTepEvntsForDpn: unknown tunnelAction: {}", tunnelAction);
@@ -365,7 +379,6 @@ public class NatTunnelInterfaceStateListener
             }
         } catch (Exception e) {
             LOG.error("hndlTepEvntsForDpn : Unable to handle the TEP event.", e);
-            return;
         }
     }
 
index bbe0e8cd529cec746e5c3b8a16ab561849b1cbfb..bc528356d9ca62f0ae9e544bc4dae38f035de2cb 100644 (file)
@@ -28,10 +28,13 @@ import java.util.stream.Collectors;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadTransaction;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
+import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
 import org.opendaylight.genius.mdsalutil.ActionInfo;
 import org.opendaylight.genius.mdsalutil.FlowEntity;
@@ -52,6 +55,7 @@ import org.opendaylight.genius.mdsalutil.instructions.InstructionGotoTable;
 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
 import org.opendaylight.genius.mdsalutil.matches.MatchEthernetType;
 import org.opendaylight.genius.mdsalutil.matches.MatchMetadata;
+import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
 import org.opendaylight.netvirt.elanmanager.api.IElanService;
 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
@@ -1838,6 +1842,12 @@ public final class NatUtil {
                 .child(VpnToDpnList.class, new VpnToDpnListKey(dpnId)).build();
     }
 
+    @Nullable
+    public static String getPrimaryRd(String vpnName, ReadTransaction tx) throws ReadFailedException {
+        return tx.read(LogicalDatastoreType.CONFIGURATION,
+                getVpnInstanceIdentifier(vpnName)).checkedGet().toJavaUtil().map(NatUtil::getPrimaryRd).orElse(null);
+    }
+
     public static String getPrimaryRd(DataBroker dataBroker, String vpnName) {
         InstanceIdentifier<VpnInstance> id  = getVpnInstanceIdentifier(vpnName);
         Optional<VpnInstance> vpnInstance =
@@ -1923,34 +1933,34 @@ public final class NatUtil {
         return false;
     }
 
-    public static void installRouterGwFlows(DataBroker dataBroker, IVpnManager vpnManager, Routers router,
-            BigInteger primarySwitchId, int addOrRemove) {
-        WriteTransaction writeTx = dataBroker.newWriteOnlyTransaction();
-        List<ExternalIps> externalIps = router.getExternalIps();
-        List<String> externalIpsSting = new ArrayList<>();
+    public static void installRouterGwFlows(ManagedNewTransactionRunner txRunner, IVpnManager vpnManager,
+            Routers router, BigInteger primarySwitchId, int addOrRemove) {
+        ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
+            List<ExternalIps> externalIps = router.getExternalIps();
+            List<String> externalIpsSting = new ArrayList<>();
 
-        if (externalIps.isEmpty()) {
-            LOG.error("installRouterGwFlows: setupRouterGwFlows no externalIP present");
-            return;
-        }
-        for (ExternalIps externalIp : externalIps) {
-            externalIpsSting.add(externalIp.getIpAddress());
-        }
-        Uuid subnetVpnName = externalIps.get(0).getSubnetId();
-        if (addOrRemove == NwConstants.ADD_FLOW) {
-            vpnManager.addRouterGwMacFlow(router.getRouterName(), router.getExtGwMacAddress(), primarySwitchId,
-                    router.getNetworkId(), subnetVpnName.getValue(), writeTx);
-            vpnManager.addArpResponderFlowsToExternalNetworkIps(router.getRouterName(), externalIpsSting,
-                    router.getExtGwMacAddress(), primarySwitchId,
-                    router.getNetworkId(), writeTx);
-        } else {
-            vpnManager.removeRouterGwMacFlow(router.getRouterName(), router.getExtGwMacAddress(), primarySwitchId,
-                    router.getNetworkId(), subnetVpnName.getValue(), writeTx);
-            vpnManager.removeArpResponderFlowsToExternalNetworkIps(router.getRouterName(), externalIpsSting,
-                    router.getExtGwMacAddress(), primarySwitchId,
-                    router.getNetworkId());
-        }
-        writeTx.submit();
+            if (externalIps.isEmpty()) {
+                LOG.error("installRouterGwFlows: setupRouterGwFlows no externalIP present");
+                return;
+            }
+            for (ExternalIps externalIp : externalIps) {
+                externalIpsSting.add(externalIp.getIpAddress());
+            }
+            Uuid subnetVpnName = externalIps.get(0).getSubnetId();
+            if (addOrRemove == NwConstants.ADD_FLOW) {
+                vpnManager.addRouterGwMacFlow(router.getRouterName(), router.getExtGwMacAddress(), primarySwitchId,
+                        router.getNetworkId(), subnetVpnName.getValue(), tx);
+                vpnManager.addArpResponderFlowsToExternalNetworkIps(router.getRouterName(), externalIpsSting,
+                        router.getExtGwMacAddress(), primarySwitchId,
+                        router.getNetworkId(), tx);
+            } else {
+                vpnManager.removeRouterGwMacFlow(router.getRouterName(), router.getExtGwMacAddress(), primarySwitchId,
+                        router.getNetworkId(), subnetVpnName.getValue(), tx);
+                vpnManager.removeArpResponderFlowsToExternalNetworkIps(router.getRouterName(), externalIpsSting,
+                        router.getExtGwMacAddress(), primarySwitchId,
+                        router.getNetworkId());
+            }
+        }), LOG, "Error installing router gateway flows");
     }
 
     public static CheckedFuture<Void, TransactionCommitFailedException> waitForTransactionToComplete(
index eeeef374138886dfdfee761bf287913707c69f71..f600a89429a17de7c52e13376afc0d738ca488f3 100644 (file)
@@ -23,6 +23,8 @@ import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
+import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
+import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
 import org.opendaylight.genius.mdsalutil.BucketInfo;
 import org.opendaylight.genius.mdsalutil.FlowEntity;
 import org.opendaylight.genius.mdsalutil.GroupEntity;
@@ -52,6 +54,7 @@ public class RouterDpnChangeListener
 
     private static final Logger LOG = LoggerFactory.getLogger(RouterDpnChangeListener.class);
     private final DataBroker dataBroker;
+    private final ManagedNewTransactionRunner txRunner;
     private final IMdsalApiManager mdsalManager;
     private final SNATDefaultRouteProgrammer snatDefaultRouteProgrammer;
     private final NaptSwitchHA naptSwitchHA;
@@ -76,6 +79,7 @@ public class RouterDpnChangeListener
                                    final JobCoordinator coordinator) {
         super(DpnVpninterfacesList.class, RouterDpnChangeListener.class);
         this.dataBroker = dataBroker;
+        this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
         this.mdsalManager = mdsalManager;
         this.snatDefaultRouteProgrammer = snatDefaultRouteProgrammer;
         this.naptSwitchHA = naptSwitchHA;
@@ -135,74 +139,66 @@ public class RouterDpnChangeListener
                             SnatServiceManager.Action.SNAT_ROUTER_ENBL);
                 } else {
                     coordinator.enqueueJob(NatConstants.NAT_DJC_PREFIX + dpnInfo.getKey(), () -> {
-                        WriteTransaction writeFlowInvTx = dataBroker.newWriteOnlyTransaction();
-                        WriteTransaction removeFlowInvTx = dataBroker.newWriteOnlyTransaction();
+                        List<ListenableFuture<Void>> futures = new ArrayList<>(2);
                         LOG.debug("add : Router {} is associated with ext nw {}", routerUuid, networkId);
                         Uuid vpnName = NatUtil.getVpnForRouter(dataBroker, routerUuid);
                         Long routerId = NatUtil.getVpnId(dataBroker, routerUuid);
-                        List<ListenableFuture<Void>> futures = new ArrayList<>();
                         if (routerId == NatConstants.INVALID_ID) {
                             LOG.error("add : Invalid routerId returned for routerName {}", routerUuid);
-                            writeFlowInvTx.cancel();
-                            removeFlowInvTx.cancel();
                             return futures;
                         }
                         extNetGroupInstaller.installExtNetGroupEntries(networkId, dpnId);
-                        Long vpnId;
-                        if (vpnName == null) {
-                            LOG.debug("add : Internal vpn associated to router {}", routerUuid);
-                            vpnId = routerId;
-                            if (vpnId == NatConstants.INVALID_ID) {
-                                LOG.error("add : Invalid vpnId returned for routerName {}", routerUuid);
-                                writeFlowInvTx.cancel();
-                                removeFlowInvTx.cancel();
-                                return futures;
-                            }
-                            LOG.debug("add : Retrieved vpnId {} for router {}", vpnId, routerUuid);
-                            //Install default entry in FIB to SNAT table
-                            LOG.info("add : Installing default route in FIB on dpn {} for router {} with vpn {}",
-                                    dpnId, routerUuid, vpnId);
-                            installDefaultNatRouteForRouterExternalSubnets(dpnId,
-                                    NatUtil.getExternalSubnetIdsFromExternalIps(router.getExternalIps()));
-                            snatDefaultRouteProgrammer.installDefNATRouteInDPN(dpnId, vpnId, writeFlowInvTx);
-                        } else {
-                            LOG.debug("add : External BGP vpn associated to router {}", routerUuid);
-                            vpnId = NatUtil.getVpnId(dataBroker, vpnName.getValue());
-                            if (vpnId == NatConstants.INVALID_ID) {
-                                LOG.error("add : Invalid vpnId returned for routerName {}", routerUuid);
-                                writeFlowInvTx.cancel();
-                                removeFlowInvTx.cancel();
-                                return futures;
-                            }
-
-                            LOG.debug("add : Retrieved vpnId {} for router {}", vpnId, routerUuid);
-                            //Install default entry in FIB to SNAT table
-                            LOG.debug("add : Installing default route in FIB on dpn {} for routerId {} with "
-                                    + "vpnId {}...", dpnId, routerUuid, vpnId);
-                            installDefaultNatRouteForRouterExternalSubnets(dpnId,
-                                    NatUtil.getExternalSubnetIdsFromExternalIps(router.getExternalIps()));
-                            snatDefaultRouteProgrammer.installDefNATRouteInDPN(dpnId, vpnId, routerId, writeFlowInvTx);
-                        }
+                        futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(writeFlowInvTx -> {
+                            Long vpnId;
+                            if (vpnName == null) {
+                                LOG.debug("add : Internal vpn associated to router {}", routerUuid);
+                                vpnId = routerId;
+                                if (vpnId == NatConstants.INVALID_ID) {
+                                    LOG.error("add : Invalid vpnId returned for routerName {}", routerUuid);
+                                    return;
+                                }
+                                LOG.debug("add : Retrieved vpnId {} for router {}", vpnId, routerUuid);
+                                //Install default entry in FIB to SNAT table
+                                LOG.info("add : Installing default route in FIB on dpn {} for router {} with vpn {}",
+                                        dpnId, routerUuid, vpnId);
+                                installDefaultNatRouteForRouterExternalSubnets(dpnId,
+                                        NatUtil.getExternalSubnetIdsFromExternalIps(router.getExternalIps()));
+                                snatDefaultRouteProgrammer.installDefNATRouteInDPN(dpnId, vpnId, writeFlowInvTx);
+                            } else {
+                                LOG.debug("add : External BGP vpn associated to router {}", routerUuid);
+                                vpnId = NatUtil.getVpnId(dataBroker, vpnName.getValue());
+                                if (vpnId == NatConstants.INVALID_ID) {
+                                    LOG.error("add : Invalid vpnId returned for routerName {}", routerUuid);
+                                    return;
+                                }
 
+                                LOG.debug("add : Retrieved vpnId {} for router {}", vpnId, routerUuid);
+                                //Install default entry in FIB to SNAT table
+                                LOG.debug("add : Installing default route in FIB on dpn {} for routerId {} with "
+                                        + "vpnId {}...", dpnId, routerUuid, vpnId);
+                                installDefaultNatRouteForRouterExternalSubnets(dpnId,
+                                        NatUtil.getExternalSubnetIdsFromExternalIps(router.getExternalIps()));
+                                snatDefaultRouteProgrammer.installDefNATRouteInDPN(dpnId, vpnId, routerId,
+                                        writeFlowInvTx);
+                            }
 
-                        if (router.isEnableSnat()) {
-                            LOG.info("add : SNAT enabled for router {}", routerUuid);
-                            ProviderTypes extNwProvType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker,
-                                    routerUuid, networkId);
-                            if (extNwProvType == null) {
-                                LOG.error("add : External Network Provider Type missing");
-                                writeFlowInvTx.cancel();
-                                removeFlowInvTx.cancel();
-                                return futures;
+                            if (router.isEnableSnat()) {
+                                LOG.info("add : SNAT enabled for router {}", routerUuid);
+                                ProviderTypes extNwProvType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker,
+                                        routerUuid, networkId);
+                                if (extNwProvType == null) {
+                                    LOG.error("add : External Network Provider Type missing");
+                                    return;
+                                }
+                                futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(removeFlowInvTx -> {
+                                    handleSNATForDPN(dpnId, routerUuid, routerId, vpnId, writeFlowInvTx,
+                                            removeFlowInvTx, extNwProvType);
+                                }));
+                            } else {
+                                LOG.info("add : SNAT is not enabled for router {} to handle addDPN event {}",
+                                        routerUuid, dpnId);
                             }
-                            handleSNATForDPN(dpnId, routerUuid, routerId, vpnId, writeFlowInvTx, removeFlowInvTx,
-                                    extNwProvType);
-                        } else {
-                            LOG.info("add : SNAT is not enabled for router {} to handle addDPN event {}",
-                                    routerUuid, dpnId);
-                        }
-                        futures.add(NatUtil.waitForTransactionToComplete(writeFlowInvTx));
-                        futures.add(NatUtil.waitForTransactionToComplete(removeFlowInvTx));
+                        }));
                         return futures;
                     }, NatConstants.NAT_DJC_MAX_RETRIES);
                 } // end of controller based SNAT
@@ -246,48 +242,44 @@ public class RouterDpnChangeListener
                             SnatServiceManager.Action.SNAT_ROUTER_DISBL);
                 } else {
                     coordinator.enqueueJob(NatConstants.NAT_DJC_PREFIX + dpnInfo.getKey(), () -> {
-                        WriteTransaction removeFlowInvTx = dataBroker.newWriteOnlyTransaction();
                         LOG.debug("remove : Router {} is associated with ext nw {}", routerUuid, networkId);
                         Uuid vpnName = NatUtil.getVpnForRouter(dataBroker, routerUuid);
-                        Long vpnId;
-                        List<ListenableFuture<Void>> futures = new ArrayList<>();
-                        if (vpnName == null) {
-                            LOG.debug("remove : Internal vpn associated to router {}", routerUuid);
-                            vpnId = routerId;
-                            if (vpnId == NatConstants.INVALID_ID) {
-                                LOG.error("remove : Invalid vpnId returned for routerName {}", routerUuid);
-                                removeFlowInvTx.cancel();
-                                return futures;
+                        return Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
+                            Long vpnId;
+                            if (vpnName == null) {
+                                LOG.debug("remove : Internal vpn associated to router {}", routerUuid);
+                                vpnId = routerId;
+                                if (vpnId == NatConstants.INVALID_ID) {
+                                    LOG.error("remove : Invalid vpnId returned for routerName {}", routerUuid);
+                                    return;
+                                }
+                                LOG.debug("remove : Retrieved vpnId {} for router {}", vpnId, routerUuid);
+                                //Remove default entry in FIB
+                                LOG.debug("remove : Removing default route in FIB on dpn {} for vpn {} ...", dpnId,
+                                        vpnName);
+                                snatDefaultRouteProgrammer.removeDefNATRouteInDPN(dpnId, vpnId, tx);
+                            } else {
+                                LOG.debug("remove : External vpn associated to router {}", routerUuid);
+                                vpnId = NatUtil.getVpnId(dataBroker, vpnName.getValue());
+                                if (vpnId == NatConstants.INVALID_ID) {
+                                    LOG.error("remove : Invalid vpnId returned for routerName {}", routerUuid);
+                                    return;
+                                }
+                                LOG.debug("remove : Retrieved vpnId {} for router {}", vpnId, routerUuid);
+                                //Remove default entry in FIB
+                                LOG.debug("remove : Removing default route in FIB on dpn {} for vpn {} ...", dpnId,
+                                        vpnName);
+                                snatDefaultRouteProgrammer.removeDefNATRouteInDPN(dpnId, vpnId, routerId, tx);
                             }
-                            LOG.debug("remove : Retrieved vpnId {} for router {}", vpnId, routerUuid);
-                            //Remove default entry in FIB
-                            LOG.debug("remove : Removing default route in FIB on dpn {} for vpn {} ...", dpnId,
-                                    vpnName);
-                            snatDefaultRouteProgrammer.removeDefNATRouteInDPN(dpnId, vpnId, removeFlowInvTx);
-                        } else {
-                            LOG.debug("remove : External vpn associated to router {}", routerUuid);
-                            vpnId = NatUtil.getVpnId(dataBroker, vpnName.getValue());
-                            if (vpnId == NatConstants.INVALID_ID) {
-                                LOG.error("remove : Invalid vpnId returned for routerName {}", routerUuid);
-                                removeFlowInvTx.cancel();
-                                return futures;
-                            }
-                            LOG.debug("remove : Retrieved vpnId {} for router {}", vpnId, routerUuid);
-                            //Remove default entry in FIB
-                            LOG.debug("remove : Removing default route in FIB on dpn {} for vpn {} ...", dpnId,
-                                    vpnName);
-                            snatDefaultRouteProgrammer.removeDefNATRouteInDPN(dpnId, vpnId, routerId, removeFlowInvTx);
-                        }
 
-                        if (router.isEnableSnat()) {
-                            LOG.info("remove : SNAT enabled for router {}", routerUuid);
-                            removeSNATFromDPN(dpnId, routerUuid, routerId, vpnId, networkId, removeFlowInvTx);
-                        } else {
-                            LOG.info("remove : SNAT is not enabled for router {} to handle removeDPN event {}",
-                                    routerUuid, dpnId);
-                        }
-                        futures.add(NatUtil.waitForTransactionToComplete(removeFlowInvTx));
-                        return futures;
+                            if (router.isEnableSnat()) {
+                                LOG.info("remove : SNAT enabled for router {}", routerUuid);
+                                removeSNATFromDPN(dpnId, routerUuid, routerId, vpnId, networkId, tx);
+                            } else {
+                                LOG.info("remove : SNAT is not enabled for router {} to handle removeDPN event {}",
+                                        routerUuid, dpnId);
+                            }
+                        }));
                     }, NatConstants.NAT_DJC_MAX_RETRIES);
                 } // end of controller based SNAT
             }
index de48cc1fdfe8df12f794f1d0b6ee4fb243818ebc..25ae71b13a41cd5fb3a20b1d1306b7d4396ff156 100644 (file)
@@ -10,11 +10,13 @@ package org.opendaylight.netvirt.natservice.internal;
 import com.google.common.base.Optional;
 import java.math.BigInteger;
 import java.util.List;
+import java.util.concurrent.ExecutionException;
 import javax.inject.Inject;
 import javax.inject.Singleton;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
+import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
 import org.opendaylight.genius.mdsalutil.MDSALUtil;
 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.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
@@ -33,6 +35,7 @@ import org.slf4j.LoggerFactory;
 public class RouterToVpnListener implements NeutronvpnListener {
     private static final Logger LOG = LoggerFactory.getLogger(RouterToVpnListener.class);
     private final DataBroker dataBroker;
+    private final ManagedNewTransactionRunner txRunner;
     private final FloatingIPListener floatingIpListener;
     private final OdlInterfaceRpcService interfaceManager;
     private final ExternalRoutersListener externalRoutersListener;
@@ -43,6 +46,7 @@ public class RouterToVpnListener implements NeutronvpnListener {
                                final OdlInterfaceRpcService interfaceManager,
                                final ExternalRoutersListener externalRoutersListener) {
         this.dataBroker = dataBroker;
+        this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
         this.floatingIpListener = floatingIpListener;
         this.interfaceManager = interfaceManager;
         this.externalRoutersListener = externalRoutersListener;
@@ -55,7 +59,6 @@ public class RouterToVpnListener implements NeutronvpnListener {
     public void onRouterAssociatedToVpn(RouterAssociatedToVpn notification) {
         String routerName = notification.getRouterId().getValue();
         String vpnName = notification.getVpnId().getValue();
-        WriteTransaction writeFlowInvTx = dataBroker.newWriteOnlyTransaction();
         //check router is associated to external network
         String extNetwork = NatUtil.getAssociatedExternalNetwork(dataBroker, routerName);
         if (extNetwork != null) {
@@ -74,14 +77,17 @@ public class RouterToVpnListener implements NeutronvpnListener {
                 return;
             }
             long routerId = NatUtil.getVpnId(dataBroker, routerName);
-            externalRoutersListener.changeLocalVpnIdToBgpVpnId(routerName, routerId, vpnName, writeFlowInvTx,
-                    extNwProvType);
+            try {
+                txRunner.callWithNewWriteOnlyTransactionAndSubmit(
+                    tx -> externalRoutersListener.changeLocalVpnIdToBgpVpnId(routerName, routerId, vpnName, tx,
+                            extNwProvType)).get();
+            } catch (InterruptedException | ExecutionException e) {
+                LOG.error("Error changling local VPN identifier to BGP VPN identifier", e);
+            }
         } else {
             LOG.debug("onRouterAssociatedToVpn : Ignoring the Router {} association with VPN {} "
                     + "since it is not external router", routerName, vpnName);
         }
-
-        NatUtil.waitForTransactionToComplete(writeFlowInvTx);
     }
 
     /**
@@ -91,7 +97,6 @@ public class RouterToVpnListener implements NeutronvpnListener {
     public void onRouterDisassociatedFromVpn(RouterDisassociatedFromVpn notification) {
         String routerName = notification.getRouterId().getValue();
         String vpnName = notification.getVpnId().getValue();
-        WriteTransaction writeFlowInvTx = dataBroker.newWriteOnlyTransaction();
         //check router is associated to external network
         String extNetwork = NatUtil.getAssociatedExternalNetwork(dataBroker, routerName);
         if (extNetwork != null) {
@@ -110,14 +115,17 @@ public class RouterToVpnListener implements NeutronvpnListener {
                 return;
             }
             long routerId = NatUtil.getVpnId(dataBroker, routerName);
-            externalRoutersListener.changeBgpVpnIdToLocalVpnId(routerName, routerId, vpnName, writeFlowInvTx,
-                    extNwProvType);
+            try {
+                txRunner.callWithNewWriteOnlyTransactionAndSubmit(
+                    tx -> externalRoutersListener.changeBgpVpnIdToLocalVpnId(routerName, routerId, vpnName, tx,
+                            extNwProvType)).get();
+            } catch (InterruptedException | ExecutionException e) {
+                LOG.error("Error changing BGP VPN identifier to local VPN identifier", e);
+            }
         } else {
             LOG.debug("onRouterDisassociatedFromVpn : Ignoring the Router {} association with VPN {} "
                     + "since it is not external router", routerName, vpnName);
         }
-
-        NatUtil.waitForTransactionToComplete(writeFlowInvTx);
     }
 
     void handleDNATConfigurationForRouterAssociation(String routerName, String vpnName, String externalNetwork) {
index d62987328aa438b71cbca5cf61cf2ab8affe1ecf..15cf6b2d7b72054b33342126a5375e30e222c24e 100644 (file)
@@ -13,7 +13,8 @@ import java.util.Collections;
 import java.util.List;
 
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
+import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
 import org.opendaylight.genius.mdsalutil.ActionInfo;
 import org.opendaylight.genius.mdsalutil.BucketInfo;
@@ -38,6 +39,7 @@ import org.opendaylight.genius.mdsalutil.matches.MatchIpv4Destination;
 import org.opendaylight.genius.mdsalutil.matches.MatchMetadata;
 import org.opendaylight.genius.mdsalutil.matches.MatchTunnelId;
 import org.opendaylight.genius.mdsalutil.nxmatches.NxMatchCtState;
+import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
 import org.opendaylight.netvirt.elanmanager.api.IElanService;
 import org.opendaylight.netvirt.vpnmanager.api.IVpnFootprintService;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
@@ -59,6 +61,7 @@ public class VxlanGreConntrackBasedSnatService extends ConntrackBasedSnatService
     private static final Logger LOG = LoggerFactory.getLogger(VxlanGreConntrackBasedSnatService.class);
     private final ExternalRoutersListener externalRouterListener;
     private final IElanService elanManager;
+    private final ManagedNewTransactionRunner txRunner;
 
     public VxlanGreConntrackBasedSnatService(DataBroker dataBroker, IMdsalApiManager mdsalManager,
                                              ItmRpcService itmManager, OdlInterfaceRpcService odlInterfaceRpcService,
@@ -70,6 +73,7 @@ public class VxlanGreConntrackBasedSnatService extends ConntrackBasedSnatService
                 interfaceManager, vpnFootprintService);
         this.externalRouterListener = externalRouterListener;
         this.elanManager = elanManager;
+        this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
     }
 
     @Override
@@ -134,16 +138,15 @@ public class VxlanGreConntrackBasedSnatService extends ConntrackBasedSnatService
             return;
         }
         //The logic now handle only one external IP per router, others if present will be ignored.
-        String externalIp = externalIps.get(0).getIpAddress();
-        externalIp = NatUtil.validateAndAddNetworkMask(externalIp);
-        WriteTransaction writeFlowInvTx = dataBroker.newWriteOnlyTransaction();
-        if (addOrRemove == NwConstants.ADD_FLOW) {
-            externalRouterListener.handleSnatReverseTraffic(dpnId, routers, routerId, routerName, externalIp,
-                    writeFlowInvTx);
-        } else {
-            externalRouterListener.clearFibTsAndReverseTraffic(dpnId, routerId, routers.getNetworkId(),
-                    Collections.singletonList(externalIp), null, routers.getExtGwMacAddress(), writeFlowInvTx);
-        }
+        String externalIp = NatUtil.validateAndAddNetworkMask(externalIps.get(0).getIpAddress());
+        ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
+            if (addOrRemove == NwConstants.ADD_FLOW) {
+                externalRouterListener.handleSnatReverseTraffic(dpnId, routers, routerId, routerName, externalIp, tx);
+            } else {
+                externalRouterListener.clearFibTsAndReverseTraffic(dpnId, routerId, routers.getNetworkId(),
+                        Collections.singletonList(externalIp), null, routers.getExtGwMacAddress(), tx);
+            }
+        }), LOG, "Error installing SNAT-specific entries for NAPT switch");
     }
 
     protected void createOutboundTblTrackEntryForVxlanGre(BigInteger dpnId, Long routerId, Long extNetVpnId,