Use managed transactions in neutronvpn-impl 83/71583/3
authorStephen Kitt <skitt@redhat.com>
Mon, 30 Apr 2018 14:57:45 +0000 (16:57 +0200)
committerSam Hague <shague@redhat.com>
Tue, 1 May 2018 19:13:10 +0000 (19:13 +0000)
This also enforces restrictions on newReadWriteTransaction and
newWriteOnlyTransaction calls, to prevent new code introducing
unmanaged transactions.

Change-Id: Iaa7965e8d02327b2345151db62bd5ba847cc04ef
Signed-off-by: Stephen Kitt <skitt@redhat.com>
neutronvpn/impl/pom.xml
neutronvpn/impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronPortChangeListener.java
neutronvpn/impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronTrunkChangeListener.java
neutronvpn/impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronvpnManager.java
neutronvpn/impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronvpnUtils.java
neutronvpn/impl/src/main/java/org/opendaylight/netvirt/neutronvpn/evpn/utils/NeutronEvpnUtils.java
neutronvpn/impl/src/main/java/org/opendaylight/netvirt/neutronvpn/l2gw/L2GatewayListener.java

index e93e596f90fed7348827ea60e22772c158d81081..3f4dad3b9b76b34d8170e1439d003c661a1027fd 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>neutronvpn-impl</artifactId>
index bd08f41b001f538d4cd3c67f4afbb6c6cc65d71c..490de022c36d9758f8e8721ab99804ceb4271ab7 100644 (file)
@@ -11,7 +11,6 @@ import static org.opendaylight.netvirt.neutronvpn.NeutronvpnUtils.buildfloatingI
 
 import com.google.common.base.Optional;
 import com.google.common.base.Strings;
-import com.google.common.util.concurrent.ListenableFuture;
 import com.google.gson.Gson;
 import com.google.gson.JsonArray;
 import com.google.gson.JsonElement;
@@ -621,7 +620,6 @@ public class NeutronPortChangeListener extends AsyncDataTreeChangeListenerBase<P
         final List<FixedIps> portIpsList = port.getFixedIps();
         jobCoordinator.enqueueJob("PORT- " + portName,
             () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(confTx -> {
-                List<ListenableFuture<Void>> futures = new ArrayList<>();
                 if (!(NeutronUtils.isPortVnicTypeNormal(port) || isPortTypeSwitchdev(port))) {
                     for (FixedIps ip : portIpsList) {
                         // remove direct port from subnetMaps config DS
index 3ca35b6d8886f0877ef8c1b187d44e9140a8cebd..161565d822dbef1086355e7a3d60aea531f14ac2 100644 (file)
@@ -8,7 +8,6 @@
 package org.opendaylight.netvirt.neutronvpn;
 
 import com.google.common.base.Preconditions;
-import com.google.common.util.concurrent.ListenableFuture;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -16,9 +15,10 @@ 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.interfacemanager.interfaces.IInterfaceManager;
 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.L2vlan;
@@ -45,6 +45,7 @@ public class NeutronTrunkChangeListener extends AsyncDataTreeChangeListenerBase<
     private static final Logger LOG = LoggerFactory.getLogger(NeutronTrunkChangeListener.class);
 
     private final DataBroker dataBroker;
+    private final ManagedNewTransactionRunner txRunner;
     private final IInterfaceManager ifMgr;
     private final JobCoordinator jobCoordinator;
 
@@ -52,6 +53,7 @@ public class NeutronTrunkChangeListener extends AsyncDataTreeChangeListenerBase<
     public NeutronTrunkChangeListener(final DataBroker dataBroker, final IInterfaceManager ifMgr,
             final JobCoordinator jobCoordinator) {
         this.dataBroker = dataBroker;
+        this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
         this.ifMgr = ifMgr;
         this.jobCoordinator = jobCoordinator;
     }
@@ -125,7 +127,6 @@ public class NeutronTrunkChangeListener extends AsyncDataTreeChangeListenerBase<
         // Should we use parentName?
         jobCoordinator.enqueueJob("PORT- " + portName, () -> {
             Interface iface = ifMgr.getInterfaceInfoFromConfigDataStore(portName);
-            List<ListenableFuture<Void>> futures = new ArrayList<>();
             if (iface == null) {
                 /*
                  * Trunk creation requires NeutronPort to be present, by this time interface
@@ -135,7 +136,7 @@ public class NeutronTrunkChangeListener extends AsyncDataTreeChangeListenerBase<
                  *      node as this one. Use of DSJC helps ensure the order.
                  */
                 LOG.warn("Interface not present for Trunk SubPort: {}", subPort);
-                return futures;
+                return Collections.emptyList();
             }
             InterfaceBuilder interfaceBuilder = new InterfaceBuilder();
             IfL2vlan ifL2vlan = new IfL2vlanBuilder().setL2vlanMode(IfL2vlan.L2vlanMode.TrunkMember)
@@ -144,16 +145,15 @@ public class NeutronTrunkChangeListener extends AsyncDataTreeChangeListenerBase<
             SplitHorizon splitHorizon = new SplitHorizonBuilder().setOverrideSplitHorizonProtection(true).build();
             interfaceBuilder.setName(portName).setType(L2vlan.class).addAugmentation(IfL2vlan.class, ifL2vlan)
                 .addAugmentation(ParentRefs.class, parentRefs).addAugmentation(SplitHorizon.class, splitHorizon);
-            iface = interfaceBuilder.build();
+            Interface newIface = interfaceBuilder.build();
             /*
              * Interface is already created for parent NeutronPort. We're updating parent refs
              * and VLAN Information
              */
-            WriteTransaction txn = dataBroker.newWriteOnlyTransaction();
-            txn.merge(LogicalDatastoreType.CONFIGURATION, interfaceIdentifier, iface);
-            LOG.trace("Creating trunk member interface {}", iface);
-            futures.add(txn.submit());
-            return futures;
+            return Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
+                tx.merge(LogicalDatastoreType.CONFIGURATION, interfaceIdentifier, newIface);
+                LOG.trace("Creating trunk member interface {}", newIface);
+            }));
         });
     }
 
@@ -163,10 +163,9 @@ public class NeutronTrunkChangeListener extends AsyncDataTreeChangeListenerBase<
                         NeutronvpnUtils.buildVlanInterfaceIdentifier(subPort.getPortId().getValue());
         jobCoordinator.enqueueJob("PORT- " + portName, () -> {
             Interface iface = ifMgr.getInterfaceInfoFromConfigDataStore(portName);
-            List<ListenableFuture<Void>> futures = new ArrayList<>();
             if (iface == null) {
                 LOG.warn("Interface not present for SubPort {}", subPort);
-                return futures;
+                return Collections.emptyList();
             }
             /*
              * We'll reset interface back to way it was? Can IFM handle parentRef delete?
@@ -177,7 +176,7 @@ public class NeutronTrunkChangeListener extends AsyncDataTreeChangeListenerBase<
                 .removeAugmentation(SplitHorizon.class);
             IfL2vlan ifL2vlan = new IfL2vlanBuilder().setL2vlanMode(IfL2vlan.L2vlanMode.Trunk).build();
             interfaceBuilder.addAugmentation(IfL2vlan.class, ifL2vlan);
-            iface = interfaceBuilder.build();
+            Interface newIface = interfaceBuilder.build();
             /*
              * There is no means to do an update to remove elements from a node.
              * Our solution is to get existing iface, remove parentRef and VlanId,
@@ -187,11 +186,10 @@ public class NeutronTrunkChangeListener extends AsyncDataTreeChangeListenerBase<
              * and this being subport delete path, don't expect any significant changes to
              * corresponding Neutron Port. Deletion of NeutronPort should follow soon enough.
              */
-            WriteTransaction txn = dataBroker.newWriteOnlyTransaction();
-            txn.put(LogicalDatastoreType.CONFIGURATION, interfaceIdentifier, iface);
-            LOG.trace("Resetting trunk member interface {}", iface);
-            futures.add(txn.submit());
-            return futures;
+            return Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
+                tx.put(LogicalDatastoreType.CONFIGURATION, interfaceIdentifier, newIface);
+                LOG.trace("Resetting trunk member interface {}", newIface);
+            }));
         });
 
     }
index d4a2887069aaf049dd3a0e2240bf866c01c1c43f..7986020796dbb99e683768f8b10bcf2869ac0ac8 100644 (file)
@@ -14,8 +14,11 @@ import static org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker
 
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.JdkFutureAdapters;
 import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.MoreExecutors;
 import com.google.common.util.concurrent.SettableFuture;
 
 import java.util.ArrayList;
@@ -182,7 +185,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
     private static long LOCK_WAIT_TIME = 10L;
 
     private final DataBroker dataBroker;
-    private final ManagedNewTransactionRunner managedNewTransactionRunner;
+    private final ManagedNewTransactionRunner txRunner;
     private final NotificationPublishService notificationPublishService;
     private final VpnRpcService vpnRpcService;
     private final NeutronFloatingToFixedIpMappingChangeListener floatingIpMapListener;
@@ -205,7 +208,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             final NeutronvpnConfig neutronvpnConfig, final IVpnManager vpnManager,
             final JobCoordinator jobCoordinator, final NeutronvpnUtils neutronvpnUtils) {
         this.dataBroker = dataBroker;
-        this.managedNewTransactionRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
+        this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
         notificationPublishService = notiPublishService;
         vpnRpcService = vpnRpcSrv;
         this.elanService = elanService;
@@ -904,26 +907,28 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
 
     // TODO Clean up the exception handling
     @SuppressWarnings("checkstyle:IllegalCatch")
-    protected boolean deleteVpnInterface(String infName, @Nullable String vpnId, WriteTransaction wrtConfigTxn) {
+    protected void deleteVpnInterface(String infName, @Nullable String vpnId, WriteTransaction wrtConfigTxn) {
+        if (wrtConfigTxn == null) {
+            ListenableFutures.addErrorLogging(
+                    txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> deleteVpnInterface(infName, vpnId, tx)),
+                    LOG, "Error deleting VPN interface {} {}", infName, vpnId);
+            return;
+        }
+
         InstanceIdentifier<VpnInterface> vpnIfIdentifier =
             NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
-        Optional<VpnInterface> optionalVpnInterface = null;
+        Optional<VpnInterface> optionalVpnInterface;
         try {
             optionalVpnInterface =
                 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
                             vpnIfIdentifier);
         } catch (ReadFailedException ex) {
             LOG.error("Error during deletion of vpninterface {}", infName, ex);
-            return false;
+            return;
         }
         if (!optionalVpnInterface.isPresent()) {
             LOG.warn("Deletion of vpninterface {}, optionalVpnInterface is not present()", infName);
-            return false;
-        }
-        boolean wrtConfigTxnPresent = true;
-        if (wrtConfigTxn == null) {
-            wrtConfigTxnPresent = false;
-            wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
+            return;
         }
         if (vpnId != null) {
             VpnInterface vpnInterface = optionalVpnInterface.get();
@@ -932,12 +937,9 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId, vpnList)) {
                 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(vpnId, vpnList);
                 if (!vpnList.isEmpty()) {
-                    if (!wrtConfigTxnPresent) {
-                        wrtConfigTxn.submit();
-                    }
                     LOG.debug("Deleting vpn interface {} not immediately since vpnInstanceName "
                             + "List not empty", infName);
-                    return false;
+                    return;
                 }
                 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
                         .setVpnInstanceNames(vpnList);
@@ -947,10 +949,6 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         }
         LOG.debug("Deleting vpn interface {}", infName);
         wrtConfigTxn.delete(LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier);
-        if (!wrtConfigTxnPresent) {
-            wrtConfigTxn.submit();
-        }
-        return true;
     }
 
     protected void removeVpnFromVpnInterface(Uuid vpnId, Port port,
@@ -1528,7 +1526,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 final Boolean isRouterInterface = port.getDeviceOwner()
                         .equals(NeutronConstants.DEVICE_OWNER_ROUTER_INF) ? true : false;
                 jobCoordinator.enqueueJob("PORT-" + portId.getValue(), () -> singletonList(
-                    managedNewTransactionRunner.callWithNewWriteOnlyTransactionAndSubmit(wrtConfigTxn -> {
+                    txRunner.callWithNewWriteOnlyTransactionAndSubmit(wrtConfigTxn -> {
                         Adjacencies portAdj = createPortIpAdjacencies(port, isRouterInterface, wrtConfigTxn, sn,
                                 vpnIface);
                         if (vpnIface == null) {
@@ -1617,18 +1615,17 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             for (final Uuid portId : portList) {
                 LOG.debug("withdrawing subnet IP {} from vpn-interface {}", sn.getSubnetIp(), portId.getValue());
                 final Port port = neutronvpnUtils.getNeutronPort(portId);
-                jobCoordinator.enqueueJob("PORT-" + portId.getValue(), () -> {
-                    WriteTransaction wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
-                    List<ListenableFuture<Void>> futures = new ArrayList<>();
-                    if (port != null) {
-                        withdrawPortIpFromVpnIface(vpnId, internetId, port, sn, wrtConfigTxn);
-                    } else {
-                        LOG.warn("Cannot proceed with withdrawPortIpFromVpnIface for port {} in subnet {} since "
-                                 + "port is absent in Neutron config DS", portId.getValue(), subnet.getValue());
-                    }
-                    futures.add(wrtConfigTxn.submit());
-                    return futures;
-                });
+                jobCoordinator.enqueueJob("PORT-" + portId.getValue(),
+                    () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
+                        if (port != null) {
+                            withdrawPortIpFromVpnIface(vpnId, internetId, port, sn, tx);
+                        } else {
+                            LOG.warn(
+                                    "Cannot proceed with withdrawPortIpFromVpnIface for port {} in subnet {} since "
+                                            + "port is absent in Neutron config DS", portId.getValue(),
+                                    subnet.getValue());
+                        }
+                    })));
             }
         }
         //update subnet-vpn association
@@ -1652,7 +1649,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         }
 
         jobCoordinator.enqueueJob("VPN-" + vpn.getValue(), () -> singletonList(
-            managedNewTransactionRunner.callWithNewWriteOnlyTransactionAndSubmit(wrtConfigTxn -> {
+            txRunner.callWithNewWriteOnlyTransactionAndSubmit(wrtConfigTxn -> {
                 if (isBeingAssociated) {
                     updateVpnInterface(vpn, null, neutronvpnUtils.getNeutronPort(sm.getRouterInterfacePortId()),
                                     true, true, wrtConfigTxn);
@@ -1670,19 +1667,15 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             for (Uuid port : portList) {
                 LOG.debug("Updating vpn-interface for port {} isBeingAssociated {}",
                     port.getValue(), isBeingAssociated);
-                jobCoordinator.enqueueJob("PORT-" + port.getValue(), () -> {
-                    WriteTransaction wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
-                    List<ListenableFuture<Void>> futures = new ArrayList<>();
-                    if (isBeingAssociated) {
-                        updateVpnInterface(vpn, null, neutronvpnUtils.getNeutronPort(port),
-                                 isBeingAssociated, false, wrtConfigTxn);
-                    } else {
-                        removeVpnFromVpnInterface(vpn,
-                              neutronvpnUtils.getNeutronPort(port), wrtConfigTxn, sm);
-                    }
-                    futures.add(wrtConfigTxn.submit());
-                    return futures;
-                });
+                jobCoordinator.enqueueJob("PORT-" + port.getValue(),
+                    () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
+                        if (isBeingAssociated) {
+                            updateVpnInterface(vpn, null, neutronvpnUtils.getNeutronPort(port),
+                                    true, false, tx);
+                        } else {
+                            removeVpnFromVpnInterface(vpn, neutronvpnUtils.getNeutronPort(port), tx, sm);
+                        }
+                    })));
             }
         }
     }
@@ -1703,35 +1696,38 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
 
         //Update Router Interface first synchronously.
         //CAUTION:  Please DONOT make the router interface VPN Movement as an asynchronous commit again !
-        try {
-            WriteTransaction wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
-            updateVpnInterface(newVpnId, oldVpnId,
-                    neutronvpnUtils.getNeutronPort(sn.getRouterInterfacePortId()),
-                    isBeingAssociated, true, wrtConfigTxn);
-            wrtConfigTxn.submit().checkedGet();
-        } catch (TransactionCommitFailedException e) {
-            LOG.error("Failed to update router interface {} in subnet {} from oldVpnId {} to newVpnId {}, returning",
-                    sn.getRouterInterfacePortId().getValue(), subnet.getValue(), oldVpnId, newVpnId);
-            return sn;
-        }
+        ListenableFuture<Void> future =
+                txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> updateVpnInterface(newVpnId, oldVpnId,
+                        neutronvpnUtils.getNeutronPort(sn.getRouterInterfacePortId()),
+                        isBeingAssociated, true, tx));
+        Futures.addCallback(future, new FutureCallback<Void>() {
+            @Override
+            public void onSuccess(Void result) {
+                // Check for ports on this subnet and update association of
+                // corresponding vpn-interfaces to external vpn
+                List<Uuid> portList = sn.getPortList();
+                if (portList != null) {
+                    for (Uuid port : portList) {
+                        LOG.debug("Updating vpn-interface for port {} isBeingAssociated {}",
+                                port.getValue(), isBeingAssociated);
+                        jobCoordinator.enqueueJob("PORT-" + port.getValue(), () -> Collections.singletonList(
+                                txRunner.callWithNewWriteOnlyTransactionAndSubmit(
+                                    tx -> updateVpnInterface(newVpnId, oldVpnId,
+                                            neutronvpnUtils.getNeutronPort(port), isBeingAssociated, false,
+                                            tx))));
+                    }
+                }
+            }
 
-        // Check for ports on this subnet and update association of
-        // corresponding vpn-interfaces to external vpn
-        List<Uuid> portList = sn.getPortList();
-        if (portList != null) {
-            for (Uuid port : portList) {
-                LOG.debug("Updating vpn-interface for port {} isBeingAssociated {}",
-                    port.getValue(), isBeingAssociated);
-                jobCoordinator.enqueueJob("PORT-" + port.getValue(), () -> {
-                    WriteTransaction wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
-                    List<ListenableFuture<Void>> futures = new ArrayList<>();
-                    updateVpnInterface(newVpnId, oldVpnId, neutronvpnUtils.getNeutronPort(port),
-                            isBeingAssociated, false, wrtConfigTxn);
-                    futures.add(wrtConfigTxn.submit());
-                    return futures;
-                });
+            @Override
+            public void onFailure(Throwable throwable) {
+                LOG.error(
+                        "Failed to update router interface {} in subnet {} from oldVpnId {} to newVpnId {}, "
+                                + "returning",
+                        sn.getRouterInterfacePortId().getValue(), subnet.getValue(), oldVpnId, newVpnId, throwable);
             }
-        }
+        }, MoreExecutors.directExecutor());
+
         return sn;
     }
 
@@ -2895,11 +2891,11 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             return;
         }
 
-        WriteTransaction wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
-        for (String elanInterface : extElanInterfaces) {
-            createExternalVpnInterface(extNetId, elanInterface, wrtConfigTxn);
-        }
-        wrtConfigTxn.submit();
+        ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
+            for (String elanInterface : extElanInterfaces) {
+                createExternalVpnInterface(extNetId, elanInterface, tx);
+            }
+        }), LOG, "Error creating external VPN interfaces for {}", extNetId);
     }
 
     // TODO Clean up the exception handling
@@ -2910,20 +2906,14 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             LOG.error("No external ports attached for external network {}", extNetId.getValue());
             return;
         }
-        try {
-
-            WriteTransaction wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
+        ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
             for (String elanInterface : extElanInterfaces) {
                 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils
                         .buildVpnInterfaceIdentifier(elanInterface);
                 LOG.info("Removing vpn interface {}", elanInterface);
-                wrtConfigTxn.delete(LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier);
+                tx.delete(LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier);
             }
-            wrtConfigTxn.submit();
-
-        } catch (Exception ex) {
-            LOG.error("Removal of vpninterfaces {} failed", extElanInterfaces, ex);
-        }
+        }), LOG, "Error removing external VPN interfaces for {}", extNetId);
     }
 
     private void createExternalVpnInterface(Uuid vpnId, String infName, WriteTransaction wrtConfigTxn) {
@@ -2939,17 +2929,18 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             LOG.error("vpn id or interface is null");
             return;
         }
+        if (wrtConfigTxn == null) {
+            ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(
+                tx -> writeVpnInterfaceToDs(vpnIdList, infName, adjacencies, isRouterInterface, tx)), LOG,
+                "Error writing VPN interface");
+            return;
+        }
         List<VpnInstanceNames> vpnIdListStruct = new ArrayList<>();
         for (Uuid vpnId: vpnIdList) {
             VpnInstanceNames vpnInstance = VpnHelper.getVpnInterfaceVpnInstanceNames(vpnId.getValue(),
                                    AssociatedSubnetType.V4AndV6Subnets);
             vpnIdListStruct.add(vpnInstance);
         }
-        Boolean wrtConfigTxnPresent = true;
-        if (wrtConfigTxn == null) {
-            wrtConfigTxnPresent = false;
-            wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
-        }
 
         InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
         VpnInterfaceBuilder vpnb = new VpnInterfaceBuilder().setKey(new VpnInterfaceKey(infName))
@@ -2966,10 +2957,6 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         } catch (Exception ex) {
             LOG.error("Creation of vpninterface {} failed", infName, ex);
         }
-
-        if (!wrtConfigTxnPresent) {
-            wrtConfigTxn.submit();
-        }
     }
 
     private void updateVpnInterfaceWithAdjacencies(Uuid vpnId, String infName, Adjacencies adjacencies,
@@ -2978,10 +2965,13 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             LOG.error("vpn id or interface is null");
             return;
         }
-
         if (wrtConfigTxn == null) {
-            wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
+            ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
+                updateVpnInterfaceWithAdjacencies(vpnId, infName, adjacencies, tx);
+            }), LOG, "Error updating VPN interface with adjacencies");
+            return;
         }
+
         InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
         boolean isLockAcquired = false;
         try {
index e70bc013778ad117e50f0565d38843fe44b7163d..2d1c9a272ab64e6dcb15bd8b369973e3a86b6c37 100644 (file)
@@ -39,8 +39,11 @@ 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.genius.mdsalutil.MDSALUtil;
 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
+import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
 import org.opendaylight.netvirt.neutronvpn.api.enums.IpVersionChoice;
 import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronUtils;
 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
@@ -183,6 +186,7 @@ public class NeutronvpnUtils {
     private final ConcurrentMap<Uuid, HashMap<Uuid, Network>> qosNetworksMap = new ConcurrentHashMap<>();
 
     private final DataBroker dataBroker;
+    private final ManagedNewTransactionRunner txRunner;
     private final IdManagerService idManager;
     private final JobCoordinator jobCoordinator;
     private IPV6InternetDefaultRouteProgrammer ipV6InternetDefRt;
@@ -191,6 +195,7 @@ public class NeutronvpnUtils {
     public NeutronvpnUtils(final DataBroker dataBroker, final IdManagerService idManager,
             final JobCoordinator jobCoordinator, final IPV6InternetDefaultRouteProgrammer ipV6InternetDefRt) {
         this.dataBroker = dataBroker;
+        this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
         this.idManager = idManager;
         this.jobCoordinator = jobCoordinator;
         this.ipV6InternetDefRt = ipV6InternetDefRt;
@@ -1498,17 +1503,16 @@ public class NeutronvpnUtils {
             if (isFinalVpnInstanceIpv6Changed) {
                 builder.setIpv6Configured(finalIsIpv6Configured);
             }
-            WriteTransaction writeTxn = dataBroker.newWriteOnlyTransaction();
-            InstanceIdentifier<VpnInstanceOpDataEntry> id = InstanceIdentifier.builder(VpnInstanceOpData.class)
-                    .child(VpnInstanceOpDataEntry.class,
-                            new VpnInstanceOpDataEntryKey(vpnInstanceOpDataEntry.getVrfId())).build();
-            writeTxn.merge(LogicalDatastoreType.OPERATIONAL, id, builder.build(), false);
-            LOG.info("updateVpnInstanceWithIpFamily: Successfully {} {} to Vpn {}",
-                    add ? "added" : "removed",
-                    ipVersion.toString(), vpnName);
-            return Collections.singletonList(writeTxn.submit());
+            return Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
+                InstanceIdentifier<VpnInstanceOpDataEntry> id = InstanceIdentifier.builder(VpnInstanceOpData.class)
+                        .child(VpnInstanceOpDataEntry.class,
+                                new VpnInstanceOpDataEntryKey(vpnInstanceOpDataEntry.getVrfId())).build();
+                tx.merge(LogicalDatastoreType.OPERATIONAL, id, builder.build(), false);
+                LOG.info("updateVpnInstanceWithIpFamily: Successfully {} {} to Vpn {}",
+                        add ? "added" : "removed",
+                        ipVersion.toString(), vpnName);
+            }));
         });
-        return;
     }
 
     /**
@@ -1648,15 +1652,10 @@ public class NeutronvpnUtils {
         }
         VpnInstanceOpDataEntryBuilder builder = new VpnInstanceOpDataEntryBuilder(vpnInstanceOpDataEntry);
         builder.setBgpvpnType(choice);
-        WriteTransaction writeTxn = dataBroker.newWriteOnlyTransaction();
-        writeTxn.merge(LogicalDatastoreType.OPERATIONAL, id, builder.build(), false);
-        LOG.debug("updateVpnInstanceOpWithType: sent merge to operDS BgpvpnType {} for {}", choice, vpn.getValue());
-        try {
-            writeTxn.submit().get();
-        } catch (InterruptedException | ExecutionException e) {
-            LOG.error("updateVpnInstanceOpWithType: on merge execution, error:  {}", e);
-        }
-        return;
+        ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
+            tx.merge(LogicalDatastoreType.OPERATIONAL, id, builder.build(), false);
+            LOG.debug("updateVpnInstanceOpWithType: sent merge to operDS BgpvpnType {} for {}", choice, vpn.getValue());
+        }), LOG, "Error updating VPN instance op {} with type {}", vpn, choice);
     }
 
     @Nonnull
index 99c07eaa346999a5b07db99a7cc2349094d0ce4d..d4a06370a4dced8af50ea8bc3bf4452a0f1e8e55 100644 (file)
@@ -8,16 +8,16 @@
 package org.opendaylight.netvirt.neutronvpn.evpn.utils;
 
 import com.google.common.base.Optional;
-import com.google.common.util.concurrent.ListenableFuture;
-import java.util.ArrayList;
-import java.util.List;
+import java.util.Collections;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
 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.genius.datastoreutils.SingleTransactionDataBroker;
+import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
+import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
+import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
 import org.opendaylight.netvirt.elanmanager.api.ElanHelper;
 import org.opendaylight.netvirt.vpnmanager.api.IVpnManager;
 import org.opendaylight.netvirt.vpnmanager.api.VpnHelper;
@@ -45,11 +45,13 @@ public class NeutronEvpnUtils {
     }
 
     private final DataBroker dataBroker;
+    private final ManagedNewTransactionRunner txRunner;
     private final IVpnManager vpnManager;
     private final JobCoordinator jobCoordinator;
 
     public NeutronEvpnUtils(DataBroker broker, IVpnManager vpnManager, JobCoordinator jobCoordinator) {
         this.dataBroker = broker;
+        this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
         this.vpnManager = vpnManager;
         this.jobCoordinator = jobCoordinator;
     }
@@ -79,35 +81,31 @@ public class NeutronEvpnUtils {
     public void updateElanWithVpnInfo(String elanInstanceName, VpnInstance vpnInstance, Operation operation) {
         String vpnName = vpnInstance.getVpnInstanceName();
         InstanceIdentifier<ElanInstance> elanIid = ElanHelper.getElanInstanceConfigurationDataPath(elanInstanceName);
-        ReadWriteTransaction transaction = dataBroker.newReadWriteTransaction();
-        Optional<ElanInstance> elanInstanceOptional = Optional.absent();
-        try {
-            elanInstanceOptional = transaction.read(LogicalDatastoreType.CONFIGURATION, elanIid).checkedGet();
-        } catch (ReadFailedException e) {
-            LOG.error("updateElanWithVpnInfo throws ReadFailedException e {}", e);
-        }
-        if (!elanInstanceOptional.isPresent()) {
-            return;
-        }
+        ListenableFutures.addErrorLogging(txRunner.callWithNewReadWriteTransactionAndSubmit(tx -> {
+            Optional<ElanInstance> elanInstanceOptional =
+                    tx.read(LogicalDatastoreType.CONFIGURATION, elanIid).checkedGet();
+            if (!elanInstanceOptional.isPresent()) {
+                return;
+            }
 
-        EvpnAugmentationBuilder evpnAugmentationBuilder = new EvpnAugmentationBuilder();
-        ElanInstanceBuilder elanInstanceBuilder = new ElanInstanceBuilder(elanInstanceOptional.get());
-        if (elanInstanceBuilder.getAugmentation(EvpnAugmentation.class) != null) {
-            evpnAugmentationBuilder =
-                    new EvpnAugmentationBuilder(elanInstanceBuilder.getAugmentation(EvpnAugmentation.class));
-        }
-        if (operation == Operation.ADD) {
-            evpnAugmentationBuilder.setEvpnName(vpnName);
-            LOG.debug("Writing Elan-EvpnAugmentation with key {}", elanInstanceName);
-        } else {
-            evpnAugmentationBuilder.setEvpnName(null);
-            LOG.debug("Deleting Elan-EvpnAugmentation with key {}", elanInstanceName);
-        }
+            EvpnAugmentationBuilder evpnAugmentationBuilder = new EvpnAugmentationBuilder();
+            ElanInstanceBuilder elanInstanceBuilder = new ElanInstanceBuilder(elanInstanceOptional.get());
+            if (elanInstanceBuilder.getAugmentation(EvpnAugmentation.class) != null) {
+                evpnAugmentationBuilder =
+                        new EvpnAugmentationBuilder(elanInstanceBuilder.getAugmentation(EvpnAugmentation.class));
+            }
+            if (operation == Operation.ADD) {
+                evpnAugmentationBuilder.setEvpnName(vpnName);
+                LOG.debug("Writing Elan-EvpnAugmentation with key {}", elanInstanceName);
+            } else {
+                evpnAugmentationBuilder.setEvpnName(null);
+                LOG.debug("Deleting Elan-EvpnAugmentation with key {}", elanInstanceName);
+            }
 
-        elanInstanceBuilder.addAugmentation(EvpnAugmentation.class, evpnAugmentationBuilder.build());
-        transaction.put(LogicalDatastoreType.CONFIGURATION, elanIid, elanInstanceBuilder.build(),
-                WriteTransaction.CREATE_MISSING_PARENTS);
-        transaction.submit();
+            elanInstanceBuilder.addAugmentation(EvpnAugmentation.class, evpnAugmentationBuilder.build());
+            tx.put(LogicalDatastoreType.CONFIGURATION, elanIid, elanInstanceBuilder.build(),
+                    WriteTransaction.CREATE_MISSING_PARENTS);
+        }), LOG, "Error updating ELAN with VPN info {}, {}, {}", elanInstanceName, vpnInstance, operation);
     }
 
     public void updateVpnWithElanInfo(VpnInstance vpnInstance, String elanInstanceName, Operation operation) {
@@ -115,25 +113,22 @@ public class NeutronEvpnUtils {
 
         InstanceIdentifier<EvpnRdToNetwork> rdToNetworkIdentifier = getRdToNetworkIdentifier(rd);
 
-        jobCoordinator.enqueueJob("EVPN_ASSOCIATE-" + rd, () -> {
-            ReadWriteTransaction transaction = dataBroker.newReadWriteTransaction();
-            List<ListenableFuture<Void>> futures = new ArrayList<>();
-            if (operation == Operation.DELETE) {
-                LOG.debug("Deleting Evpn-Network with key {}", rd);
-                transaction.delete(LogicalDatastoreType.CONFIGURATION, rdToNetworkIdentifier);
-            } else {
-                EvpnRdToNetworkBuilder evpnRdToNetworkBuilder = new EvpnRdToNetworkBuilder().setKey(
-                        new EvpnRdToNetworkKey(rd));
-                evpnRdToNetworkBuilder.setRd(rd);
-                evpnRdToNetworkBuilder.setNetworkId(elanInstanceName);
-                LOG.info("updating Evpn {} with elaninstance {} and rd {}",
-                        vpnInstance.getVpnInstanceName(), elanInstanceName, rd);
-                transaction.put(LogicalDatastoreType.CONFIGURATION, rdToNetworkIdentifier,
-                        evpnRdToNetworkBuilder.build(), WriteTransaction.CREATE_MISSING_PARENTS);
-            }
-            futures.add(transaction.submit());
-            return futures;
-        });
+        jobCoordinator.enqueueJob("EVPN_ASSOCIATE-" + rd,
+            () -> Collections.singletonList(txRunner.callWithNewReadWriteTransactionAndSubmit(tx -> {
+                if (operation == Operation.DELETE) {
+                    LOG.debug("Deleting Evpn-Network with key {}", rd);
+                    tx.delete(LogicalDatastoreType.CONFIGURATION, rdToNetworkIdentifier);
+                } else {
+                    EvpnRdToNetworkBuilder evpnRdToNetworkBuilder = new EvpnRdToNetworkBuilder().setKey(
+                            new EvpnRdToNetworkKey(rd));
+                    evpnRdToNetworkBuilder.setRd(rd);
+                    evpnRdToNetworkBuilder.setNetworkId(elanInstanceName);
+                    LOG.info("updating Evpn {} with elaninstance {} and rd {}",
+                            vpnInstance.getVpnInstanceName(), elanInstanceName, rd);
+                    tx.put(LogicalDatastoreType.CONFIGURATION, rdToNetworkIdentifier,
+                            evpnRdToNetworkBuilder.build(), WriteTransaction.CREATE_MISSING_PARENTS);
+                }
+            })));
     }
 
     public void updateElanAndVpn(VpnInstance vpnInstance, String subnetVpn, Operation operation) {
index 4953122d8d5677a33188327ee065e8fcba2fe618..b6e517a18d6dd2fc1904f4efb1a706747c03a4f5 100644 (file)
@@ -12,7 +12,7 @@ import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.MoreExecutors;
-import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -21,10 +21,10 @@ 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.ReadWriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
 import org.opendaylight.genius.datastoreutils.AsyncClusteredDataTreeChangeListenerBase;
+import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
+import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
 import org.opendaylight.genius.mdsalutil.MDSALUtil;
 import org.opendaylight.genius.utils.SystemPropertyReader;
 import org.opendaylight.genius.utils.clustering.EntityOwnershipUtils;
@@ -54,6 +54,7 @@ import org.slf4j.LoggerFactory;
 public class L2GatewayListener extends AsyncClusteredDataTreeChangeListenerBase<L2gateway, L2GatewayListener> {
     private static final Logger LOG = LoggerFactory.getLogger(L2GatewayListener.class);
     private final DataBroker dataBroker;
+    private final ManagedNewTransactionRunner txRunner;
     private final ItmRpcService itmRpcService;
     private final IL2gwService l2gwService;
     private final EntityOwnershipUtils entityOwnershipUtils;
@@ -65,6 +66,7 @@ public class L2GatewayListener extends AsyncClusteredDataTreeChangeListenerBase<
                              final ItmRpcService itmRpcService, final IL2gwService l2gwService,
                              final JobCoordinator jobCoordinator, final L2GatewayCache l2GatewayCache) {
         this.dataBroker = dataBroker;
+        this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
         this.entityOwnershipUtils = new EntityOwnershipUtils(entityOwnershipService);
         this.itmRpcService = itmRpcService;
         this.l2gwService = l2gwService;
@@ -99,24 +101,28 @@ public class L2GatewayListener extends AsyncClusteredDataTreeChangeListenerBase<
         LOG.info("Removing L2gateway with ID: {}", input.getUuid());
         List<L2gatewayConnection> connections = l2gwService
                 .getL2GwConnectionsByL2GatewayId(input.getUuid());
-        try {
-            ReadWriteTransaction tx = this.dataBroker.newReadWriteTransaction();
+        Futures.addCallback(txRunner.callWithNewReadWriteTransactionAndSubmit(tx -> {
             for (L2gatewayConnection connection : connections) {
                 InstanceIdentifier<L2gatewayConnection> iid = InstanceIdentifier.create(Neutron.class)
                         .child(L2gatewayConnections.class).child(L2gatewayConnection.class, connection.getKey());
                 tx.delete(LogicalDatastoreType.CONFIGURATION, iid);
             }
-            tx.submit().checkedGet();
-        } catch (TransactionCommitFailedException e) {
-            LOG.error("Failed to delete associated l2gwconnection while deleting l2gw {} with id beacause of {}",
-                    input.getUuid(), e.getLocalizedMessage());
-            //TODO :retry
-        }
-        List<Devices> l2Devices = input.getDevices();
-        for (Devices l2Device : l2Devices) {
-            LOG.trace("Removing L2gateway device: {}", l2Device);
-            removeL2Device(l2Device, input);
-        }
+        }), new FutureCallback<Void>() {
+            @Override
+            public void onSuccess(Void result) {
+                List<Devices> l2Devices = input.getDevices();
+                for (Devices l2Device : l2Devices) {
+                    LOG.trace("Removing L2gateway device: {}", l2Device);
+                    removeL2Device(l2Device, input);
+                }
+            }
+
+            @Override
+            public void onFailure(Throwable throwable) {
+                LOG.error("Failed to delete associated l2gwconnection while deleting l2gw {} with id",
+                        input.getUuid(), throwable);
+            }
+        }, MoreExecutors.directExecutor());
     }
 
     @Override
@@ -134,39 +140,38 @@ public class L2GatewayListener extends AsyncClusteredDataTreeChangeListenerBase<
             return;
         }
         jobCoordinator.enqueueJob("l2gw.update", () -> {
-            ReadWriteTransaction transaction = dataBroker.newReadWriteTransaction();
-            DeviceInterfaces updatedDeviceInterfaces = new DeviceInterfaces(update);
-            List<ListenableFuture<Void>> fts = new ArrayList<>();
-            original.getDevices()
-                    .stream()
-                    .filter((originalDevice) -> originalDevice.getInterfaces() != null)
-                    .forEach((originalDevice) -> {
-                        String deviceName = originalDevice.getDeviceName();
-                        L2GatewayDevice l2GwDevice = l2GatewayCache.get(deviceName);
-                        NodeId physicalSwitchNodeId = HwvtepSouthboundUtils.createManagedNodeId(
-                                new NodeId(l2GwDevice.getHwvtepNodeId()), deviceName);
-                        originalDevice.getInterfaces()
-                                .stream()
-                                .filter((intf) -> !updatedDeviceInterfaces.containsInterface(
-                                        deviceName, intf.getInterfaceName()))
-                                .forEach((intf) -> connections.forEach((connection) -> {
-                                    Integer vlanId = connection.getSegmentId();
-                                    if (intf.getSegmentationIds() != null
-                                            && !intf.getSegmentationIds().isEmpty()) {
-                                        for (Integer vlan : intf.getSegmentationIds()) {
-                                            HwvtepUtils.deleteVlanBinding(transaction,
-                                                    physicalSwitchNodeId, intf.getInterfaceName(), vlan);
+            ListenableFuture<Void> future = txRunner.callWithNewReadWriteTransactionAndSubmit(tx -> {
+                DeviceInterfaces updatedDeviceInterfaces = new DeviceInterfaces(update);
+                original.getDevices()
+                        .stream()
+                        .filter((originalDevice) -> originalDevice.getInterfaces() != null)
+                        .forEach((originalDevice) -> {
+                            String deviceName = originalDevice.getDeviceName();
+                            L2GatewayDevice l2GwDevice = l2GatewayCache.get(deviceName);
+                            NodeId physicalSwitchNodeId = HwvtepSouthboundUtils.createManagedNodeId(
+                                    new NodeId(l2GwDevice.getHwvtepNodeId()), deviceName);
+                            originalDevice.getInterfaces()
+                                    .stream()
+                                    .filter((intf) -> !updatedDeviceInterfaces.containsInterface(
+                                            deviceName, intf.getInterfaceName()))
+                                    .forEach((intf) -> connections.forEach((connection) -> {
+                                        Integer vlanId = connection.getSegmentId();
+                                        if (intf.getSegmentationIds() != null
+                                                && !intf.getSegmentationIds().isEmpty()) {
+                                            for (Integer vlan : intf.getSegmentationIds()) {
+                                                HwvtepUtils.deleteVlanBinding(tx,
+                                                        physicalSwitchNodeId, intf.getInterfaceName(), vlan);
+                                            }
+                                        } else {
+                                            LOG.debug("Deleting vlan binding {} {} {}",
+                                                    physicalSwitchNodeId, intf.getInterfaceName(), vlanId);
+                                            HwvtepUtils.deleteVlanBinding(tx, physicalSwitchNodeId,
+                                                    intf.getInterfaceName(), vlanId);
                                         }
-                                    } else {
-                                        LOG.debug("Deleting vlan binding {} {} {}",
-                                                physicalSwitchNodeId, intf.getInterfaceName(), vlanId);
-                                        HwvtepUtils.deleteVlanBinding(transaction, physicalSwitchNodeId,
-                                                intf.getInterfaceName(), vlanId);
-                                    }
-                                }));
-                    });
-            fts.add(transaction.submit());
-            Futures.addCallback(fts.get(0), new FutureCallback<Void>() {
+                                    }));
+                        });
+            });
+            Futures.addCallback(future, new FutureCallback<Void>() {
                 @Override
                 public void onSuccess(Void success) {
                     LOG.debug("Successfully deleted vlan bindings for l2gw update {}", update);
@@ -179,7 +184,7 @@ public class L2GatewayListener extends AsyncClusteredDataTreeChangeListenerBase<
                     LOG.error("Failed to delete vlan bindings as part of l2gw udpate {}", update);
                 }
             }, MoreExecutors.directExecutor());
-            return fts;
+            return Collections.singletonList(future);
         }, SystemPropertyReader.getDataStoreJobCoordinatorMaxRetries());
     }