Migrate elanmanager to use LoggingFutures
[netvirt.git] / elanmanager / impl / src / main / java / org / opendaylight / netvirt / elan / l2gw / utils / ElanL2GatewayUtils.java
index ed64743430cebe529fb610951e99b28a86a1425c..bb53847f45060b574491dbabfd2f96b950a196ea 100644 (file)
@@ -7,6 +7,8 @@
  */
 package org.opendaylight.netvirt.elan.l2gw.utils;
 
+import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
+
 import com.google.common.base.Optional;
 import com.google.common.collect.Lists;
 import com.google.common.util.concurrent.FutureCallback;
@@ -19,7 +21,6 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
-import java.util.Locale;
 import java.util.Objects;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
@@ -30,12 +31,13 @@ import java.util.concurrent.ScheduledFuture;
 import java.util.concurrent.TimeUnit;
 import java.util.function.Function;
 import java.util.stream.Collectors;
-import javax.annotation.Nonnull;
 import javax.annotation.PreDestroy;
 import javax.inject.Inject;
 import javax.inject.Singleton;
 import org.apache.commons.lang3.tuple.ImmutablePair;
 import org.apache.commons.lang3.tuple.Pair;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
@@ -48,9 +50,10 @@ import org.opendaylight.genius.utils.hwvtep.HwvtepSouthboundConstants;
 import org.opendaylight.genius.utils.hwvtep.HwvtepSouthboundUtils;
 import org.opendaylight.genius.utils.hwvtep.HwvtepUtils;
 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
-import org.opendaylight.netvirt.elan.ElanException;
+import org.opendaylight.infrautils.utils.concurrent.LoggingFutures;
 import org.opendaylight.netvirt.elan.cache.ElanInstanceCache;
 import org.opendaylight.netvirt.elan.cache.ElanInstanceDpnsCache;
+import org.opendaylight.netvirt.elan.l2gw.ha.HwvtepHAUtil;
 import org.opendaylight.netvirt.elan.l2gw.jobs.DeleteL2GwDeviceMacsFromElanJob;
 import org.opendaylight.netvirt.elan.l2gw.jobs.DeleteLogicalSwitchJob;
 import org.opendaylight.netvirt.elan.utils.ElanClusterUtils;
@@ -65,18 +68,24 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.IetfYangUtil;
 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.PhysAddress;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.TransportZones;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.subnets.DeviceVteps;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.AddL2GwDeviceInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.AddL2GwDeviceOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.config.rev150710.ElanConfig;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInstances;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan._interface.forwarding.entries.ElanInterfaceMac;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.elan.dpn.interfaces.list.DpnInterfaces;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.forwarding.tables.MacTable;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.elan.instance.ExternalTeps;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.forwarding.entries.MacEntry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l2gateways.rev150712.l2gateway.attributes.Devices;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentation;
@@ -194,12 +203,12 @@ public class ElanL2GatewayUtils {
             RemoteMcastMacs remoteMcastMac, IpAddress expectedPhyLocatorIp) {
         if (remoteMcastMac != null) {
             HwvtepPhysicalLocatorAugmentation expectedPhyLocatorAug = HwvtepSouthboundUtils
-                    .createHwvtepPhysicalLocatorAugmentation(String.valueOf(expectedPhyLocatorIp.getValue()));
+                    .createHwvtepPhysicalLocatorAugmentation(expectedPhyLocatorIp);
             HwvtepPhysicalLocatorRef expectedPhyLocRef = new HwvtepPhysicalLocatorRef(
                     HwvtepSouthboundUtils.createPhysicalLocatorInstanceIdentifier(nodeId, expectedPhyLocatorAug));
             if (remoteMcastMac.getLocatorSet() != null) {
                 for (LocatorSet locatorSet : remoteMcastMac.getLocatorSet()) {
-                    if (locatorSet.getLocatorRef().equals(expectedPhyLocRef)) {
+                    if (Objects.equals(locatorSet.getLocatorRef(), expectedPhyLocRef)) {
                         LOG.trace("matched phyLocRef: {}", expectedPhyLocRef);
                         return true;
                     }
@@ -266,18 +275,6 @@ public class ElanL2GatewayUtils {
         return HwvtepUtils.deleteRemoteUcastMacs(broker, nodeId, logicalSwitchName, lstMac);
     }
 
-    public ElanInstance getElanInstanceForUcastLocalMac(LocalUcastMacs localUcastMac) {
-        Optional<LogicalSwitches> lsOpc = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL,
-                (InstanceIdentifier<LogicalSwitches>) localUcastMac.getLogicalSwitchRef().getValue());
-        if (lsOpc.isPresent()) {
-            LogicalSwitches ls = lsOpc.get();
-            // Logical switch name is Elan name
-            String elanName = getElanFromLogicalSwitch(ls.getHwvtepNodeName().getValue());
-            return elanInstanceCache.get(elanName).orNull();
-        }
-        return null;
-    }
-
     /**
      * Install external device local macs in dpn.
      *
@@ -289,10 +286,9 @@ public class ElanL2GatewayUtils {
      *            the elan
      * @param interfaceName
      *            the interface name
-     * @throws ElanException in case of issues creating the flow objects
      */
     public void installL2gwDeviceMacsInDpn(BigInteger dpnId, NodeId l2gwDeviceNodeId, ElanInstance elan,
-            String interfaceName) throws ElanException {
+            String interfaceName) {
         L2GatewayDevice l2gwDevice = ElanL2GwCacheUtils.getL2GatewayDeviceFromCache(elan.getElanInstanceName(),
                 l2gwDeviceNodeId.getValue());
         if (l2gwDevice == null) {
@@ -314,10 +310,9 @@ public class ElanL2GatewayUtils {
      *            the elan
      * @param interfaceName
      *            the interface name
-     * @throws ElanException in case of issues creating the flow objects
      */
     public void installDmacFlowsOnDpn(BigInteger dpnId, L2GatewayDevice l2gwDevice, ElanInstance elan,
-            String interfaceName) throws ElanException {
+            String interfaceName) {
         String elanName = elan.getElanInstanceName();
 
         Collection<LocalUcastMacs> l2gwDeviceLocalMacs = l2gwDevice.getUcastLocalMacs();
@@ -341,10 +336,8 @@ public class ElanL2GatewayUtils {
      *            the elan
      * @param interfaceName
      *            the interface name
-     * @throws ElanException in case of issues creating the flow objects
      */
-    public void installElanL2gwDevicesLocalMacsInDpn(BigInteger dpnId, ElanInstance elan, String interfaceName)
-            throws ElanException {
+    public void installElanL2gwDevicesLocalMacsInDpn(BigInteger dpnId, ElanInstance elan, String interfaceName) {
         ConcurrentMap<String, L2GatewayDevice> elanL2GwDevicesFromCache = ElanL2GwCacheUtils
                 .getInvolvedL2GwDevices(elan.getElanInstanceName());
         if (elanL2GwDevicesFromCache != null) {
@@ -357,7 +350,7 @@ public class ElanL2GatewayUtils {
     }
 
     public void installL2GwUcastMacInElan(final ElanInstance elan, final L2GatewayDevice extL2GwDevice,
-            final String macToBeAdded, final LocalUcastMacs localUcastMacs, String interfaceName) {
+            final String macToBeAdded, final LocalUcastMacs localUcastMacs, @Nullable String interfaceName) {
         final String extDeviceNodeId = extL2GwDevice.getHwvtepNodeId();
         final String elanInstanceName = elan.getElanInstanceName();
         final Collection<DpnInterfaces> elanDpns = getElanDpns(elanInstanceName);
@@ -464,7 +457,8 @@ public class ElanL2GatewayUtils {
                     for (DpnInterfaces elanDpn : elanDpns) {
                         BigInteger dpnId = elanDpn.getDpId();
                         result.addAll(elanDmacUtils.deleteDmacFlowsToExternalMac(elan.getElanTag(), dpnId,
-                                l2GwDevice.getHwvtepNodeId(), mac.getValue().toLowerCase(Locale.getDefault())));
+                                l2GwDevice.getHwvtepNodeId(),
+                                IetfYangUtil.INSTANCE.canonizeMacAddress(mac).getValue()));
                     }
                     return result;
                 });
@@ -478,10 +472,8 @@ public class ElanL2GatewayUtils {
      *            the elan name
      * @param dpnId
      *            the dpn id
-     * @throws ReadFailedException if a read fails throws ReadFailedException
      */
-    public void deleteElanL2GwDevicesUcastLocalMacsFromDpn(final String elanName, final BigInteger dpnId)
-            throws ReadFailedException {
+    public void deleteElanL2GwDevicesUcastLocalMacsFromDpn(final String elanName, final BigInteger dpnId) {
         ConcurrentMap<String, L2GatewayDevice> elanL2GwDevices = ElanL2GwCacheUtils.getInvolvedL2GwDevices(elanName);
         if (elanL2GwDevices == null || elanL2GwDevices.isEmpty()) {
             LOG.trace("No L2 gateway devices in Elan [{}] cache.", elanName);
@@ -528,12 +520,12 @@ public class ElanL2GatewayUtils {
                     @Override
                     public void onSuccess(Optional<Node> configNode) {
                         if (configNode != null && configNode.isPresent()) {
-                            HwvtepGlobalAugmentation augmentation = configNode.get().getAugmentation(
+                            HwvtepGlobalAugmentation augmentation = configNode.get().augmentation(
                                     HwvtepGlobalAugmentation.class);
                             if (augmentation != null && augmentation.getLocalUcastMacs() != null) {
                                 macs.addAll(augmentation.getLocalUcastMacs().stream()
                                         .filter(mac -> getLogicalSwitchName(mac).equals(elanName))
-                                        .map(mac -> mac.getMacEntryKey())
+                                        .map(HwvtepMacTableGenericAttributes::getMacEntryKey)
                                         .collect(Collectors.toSet()));
                             }
                             function.apply(macs);
@@ -542,7 +534,7 @@ public class ElanL2GatewayUtils {
 
                     @Override
                     public void onFailure(Throwable throwable) {
-                        LOG.error("Failed to read config topology node ", nodeIid);
+                        LOG.error("Failed to read config topology node {}", nodeIid);
                     }
                 }, MoreExecutors.directExecutor());
     }
@@ -580,8 +572,8 @@ public class ElanL2GatewayUtils {
 
             @Override
             public void onFailure(Throwable error) {
-                LOG.warn(String.format("Failed during batch delete of elan [%s] macs from l2gw device [%s]. "
-                        + "Retrying with sequential deletes.", elanName, hwvtepNodeId), error);
+                LOG.warn("Failed during batch delete of elan {} macs from l2gw device {}. "
+                        + "Retrying with sequential deletes.", elanName, hwvtepNodeId, error);
                 if (lstElanMacs != null && !lstElanMacs.isEmpty()) {
                     for (MacAddress mac : lstElanMacs) {
                         HwvtepUtils.deleteRemoteUcastMac(broker, new NodeId(hwvtepNodeId), logicalSwitch, mac);
@@ -614,7 +606,7 @@ public class ElanL2GatewayUtils {
         List<MacAddress> lstMacs = Collections.emptyList();
         Node hwvtepNode = HwvtepUtils.getHwVtepNode(broker, datastoreType, hwvtepNodeId);
         if (hwvtepNode != null) {
-            List<RemoteUcastMacs> remoteUcastMacs = hwvtepNode.getAugmentation(HwvtepGlobalAugmentation.class)
+            List<RemoteUcastMacs> remoteUcastMacs = hwvtepNode.augmentation(HwvtepGlobalAugmentation.class)
                     .getRemoteUcastMacs();
             if (remoteUcastMacs != null && !remoteUcastMacs.isEmpty()) {
                 // Filtering remoteUcastMacs based on the logical switch and
@@ -646,7 +638,7 @@ public class ElanL2GatewayUtils {
 
         List<RemoteUcastMacs> lstL2GatewayDevicesMacs = getOtherDevicesMacs(elanName, l2GatewayDevice, hwVtepNodeId,
                 logicalSwitchName);
-        List<RemoteUcastMacs> lstElanMacTableEntries = getElanMacTableEntriesMacs(elanName, l2GatewayDevice,
+        List<RemoteUcastMacs> lstElanMacTableEntries = getElanMacTableEntriesMacs(elanName,
                 hwVtepNodeId, logicalSwitchName);
 
         List<RemoteUcastMacs> lstRemoteUcastMacs = new ArrayList<>(lstL2GatewayDevicesMacs);
@@ -686,11 +678,10 @@ public class ElanL2GatewayUtils {
                 if (!areMLAGDevices(l2GatewayDeviceToBeConfigured, otherDevice)) {
                     for (LocalUcastMacs localUcastMac : otherDevice.getUcastLocalMacs()) {
                         HwvtepPhysicalLocatorAugmentation physLocatorAug = HwvtepSouthboundUtils
-                                .createHwvtepPhysicalLocatorAugmentation(
-                                        String.valueOf(otherDevice.getTunnelIp().getValue()));
+                                .createHwvtepPhysicalLocatorAugmentation(otherDevice.getTunnelIp());
                         RemoteUcastMacs remoteUcastMac = HwvtepSouthboundUtils.createRemoteUcastMac(hwVtepNodeId,
-                                localUcastMac.getMacEntryKey().getValue().toLowerCase(Locale.getDefault()),
-                                localUcastMac.getIpaddr(), logicalSwitchName, physLocatorAug);
+                            IetfYangUtil.INSTANCE.canonizeMacAddress(localUcastMac.getMacEntryKey()).getValue(),
+                            localUcastMac.getIpaddr(), logicalSwitchName, physLocatorAug);
                         lstRemoteUcastMacs.add(remoteUcastMac);
                     }
                 }
@@ -721,8 +712,6 @@ public class ElanL2GatewayUtils {
      *
      * @param elanName
      *            the elan name
-     * @param l2GatewayDeviceToBeConfigured
-     *            the l2 gateway device to be configured
      * @param hwVtepNodeId
      *            the hw vtep node id
      * @param logicalSwitchName
@@ -730,7 +719,7 @@ public class ElanL2GatewayUtils {
      * @return the elan mac table entries as remote ucast macs
      */
     public List<RemoteUcastMacs> getElanMacTableEntriesMacs(String elanName,
-            L2GatewayDevice l2GatewayDeviceToBeConfigured, NodeId hwVtepNodeId, String logicalSwitchName) {
+            NodeId hwVtepNodeId, String logicalSwitchName) {
         List<RemoteUcastMacs> lstRemoteUcastMacs = new ArrayList<>();
 
         MacTable macTable = ElanUtils.getElanMacTable(broker, elanName);
@@ -753,11 +742,11 @@ public class ElanL2GatewayUtils {
                 continue;
             }
             HwvtepPhysicalLocatorAugmentation physLocatorAug = HwvtepSouthboundUtils
-                    .createHwvtepPhysicalLocatorAugmentation(String.valueOf(dpnTepIp.getValue()));
+                    .createHwvtepPhysicalLocatorAugmentation(dpnTepIp);
             // TODO: Query ARP cache to get IP address corresponding to the
             // MAC
             RemoteUcastMacs remoteUcastMac = HwvtepSouthboundUtils.createRemoteUcastMac(hwVtepNodeId,
-                    macEntry.getMacAddress().getValue().toLowerCase(Locale.getDefault()), null /*IpAddress*/,
+                IetfYangUtil.INSTANCE.canonizePhysAddress(macEntry.getMacAddress()).getValue(), null /*IpAddress*/,
                     logicalSwitchName, physLocatorAug);
             lstRemoteUcastMacs.add(remoteUcastMac);
         }
@@ -771,6 +760,7 @@ public class ElanL2GatewayUtils {
      *            the interface name
      * @return the dpid from interface
      */
+    @Nullable
     public BigInteger getDpidFromInterface(String interfaceName) {
         BigInteger dpId = null;
         Future<RpcResult<GetDpidFromInterfaceOutput>> output = interfaceManagerRpcService
@@ -781,7 +771,7 @@ public class ElanL2GatewayUtils {
                 dpId = rpcResult.getResult().getDpid();
             }
         } catch (InterruptedException | ExecutionException e) {
-            LOG.error("Failed to get the DPN ID for interface {}: {} ", interfaceName, e);
+            LOG.error("Failed to get the DPN ID for interface {}", interfaceName, e);
         }
         return dpId;
     }
@@ -807,7 +797,7 @@ public class ElanL2GatewayUtils {
             return Futures.immediateFailedFuture(new RuntimeException(errMsg));
         }
 
-        return txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
+        return txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
             for (org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l2gateways.rev150712
                     .l2gateway.attributes.devices.Interfaces deviceInterface : hwVtepDevice.getInterfaces()) {
                 //Removed the check for checking terminationPoint present in OP or not
@@ -847,7 +837,7 @@ public class ElanL2GatewayUtils {
      */
     public ListenableFuture<Void> updateVlanBindingsInL2GatewayDevice(NodeId nodeId, String psName,
             String interfaceName, List<VlanBindings> vlanBindings) {
-        return txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
+        return txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
             HwvtepUtils.mergeVlanBindings(tx, nodeId, psName, interfaceName, vlanBindings);
             LOG.info("Updated Hwvtep VlanBindings in config DS. NodeID: {}", nodeId.getValue());
         });
@@ -873,7 +863,7 @@ public class ElanL2GatewayUtils {
         }
         NodeId physicalSwitchNodeId = HwvtepSouthboundUtils.createManagedNodeId(nodeId, hwVtepDevice.getDeviceName());
 
-        return txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
+        return txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
             for (org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l2gateways.rev150712
                     .l2gateway.attributes.devices.Interfaces deviceInterface : hwVtepDevice.getInterfaces()) {
                 String phyPortName = deviceInterface.getInterfaceName();
@@ -892,19 +882,6 @@ public class ElanL2GatewayUtils {
         });
     }
 
-    /**
-     * Gets the elan name from logical switch name.
-     *
-     * @param logicalSwitchName
-     *            the logical switch name
-     * @return the elan name from logical switch name
-     */
-    public static String getElanFromLogicalSwitch(String logicalSwitchName) {
-        // Assuming elan name is same as logical switch name
-        String elanName = logicalSwitchName;
-        return elanName;
-    }
-
     /**
      * Gets the logical switch name from elan name.
      *
@@ -921,13 +898,11 @@ public class ElanL2GatewayUtils {
     /**
      * Gets the l2 gateway connection job key.
      *
-     * @param nodeId
-     *            the node id
      * @param logicalSwitchName
      *            the logical switch name
      * @return the l2 gateway connection job key
      */
-    public static String getL2GatewayConnectionJobKey(String nodeId, String logicalSwitchName) {
+    public static String getL2GatewayConnectionJobKey(String logicalSwitchName) {
         return logicalSwitchName;
     }
 
@@ -937,6 +912,7 @@ public class ElanL2GatewayUtils {
         return interfaceInstanceIdentifierBuilder.build();
     }
 
+    @Nullable
     public static Interface getInterfaceFromConfigDS(InterfaceKey interfaceKey, DataBroker dataBroker) {
         InstanceIdentifier<Interface> interfaceId = getInterfaceIdentifier(interfaceKey);
         try {
@@ -959,10 +935,9 @@ public class ElanL2GatewayUtils {
      *            from elan
      * @param elanName
      *            the elan name
-     * @throws ReadFailedException if a read fails
      */
     public void deleteL2GwDeviceUcastLocalMacsFromElan(L2GatewayDevice l2GatewayDevice,
-            String elanName) throws ReadFailedException {
+            String elanName) {
         LOG.info("Deleting L2GatewayDevice [{}] UcastLocalMacs from elan [{}]", l2GatewayDevice.getHwvtepNodeId(),
                 elanName);
 
@@ -977,27 +952,91 @@ public class ElanL2GatewayUtils {
         unInstallL2GwUcastMacFromElanDpns(elan, l2GatewayDevice, localMacs);
     }
 
-    public static void createItmTunnels(ItmRpcService itmRpcService, String hwvtepId, String psName,
-            IpAddress tunnelIp) {
+    public static void createItmTunnels(DataBroker dataBroker, ItmRpcService itmRpcService,
+                                        String hwvtepId, String psName, IpAddress tunnelIp) {
         AddL2GwDeviceInputBuilder builder = new AddL2GwDeviceInputBuilder();
         builder.setTopologyId(HwvtepSouthboundConstants.HWVTEP_TOPOLOGY_ID.getValue());
         builder.setNodeId(HwvtepSouthboundUtils.createManagedNodeId(new NodeId(hwvtepId), psName).getValue());
         builder.setIpAddress(tunnelIp);
         try {
-            Future<RpcResult<Void>> result = itmRpcService.addL2GwDevice(builder.build());
-            RpcResult<Void> rpcResult = result.get();
+            deleteStaleTunnelsOfHwvtepInITM(dataBroker, itmRpcService, hwvtepId, psName, tunnelIp);
+            RpcResult<AddL2GwDeviceOutput> rpcResult = itmRpcService.addL2GwDevice(builder.build()).get();
             if (rpcResult.isSuccessful()) {
                 LOG.info("Created ITM tunnels for {}", hwvtepId);
             } else {
-                LOG.error("Failed to create ITM Tunnels: ", rpcResult.getErrors());
+                LOG.error("Failed to create ITM Tunnels: {}", rpcResult.getErrors());
             }
         } catch (InterruptedException | ExecutionException e) {
             LOG.error("RPC to create ITM tunnels failed", e);
         }
     }
 
-    public static String getNodeIdFromDpnId(BigInteger dpnId) {
-        return MDSALUtil.NODE_PREFIX + MDSALUtil.SEPARATOR + dpnId.toString();
+    private static void deleteStaleTunnelsOfHwvtepInITM(DataBroker dataBroker,
+                                                        ItmRpcService itmRpcService,
+                                                        String globalNodeId,
+                                                        String psName,
+                                                        IpAddress tunnelIp) {
+        try {
+            Optional<TransportZones> tzonesoptional = readTransportZone(dataBroker);
+            if (!tzonesoptional.isPresent() || tzonesoptional.get().getTransportZone() == null) {
+                return;
+            }
+            String psNodeId = globalNodeId + HwvtepHAUtil.PHYSICALSWITCH + psName;
+            tzonesoptional.get().nonnullTransportZone().stream()
+                .filter(transportZone -> transportZone.getSubnets() != null)
+                .flatMap(transportZone -> transportZone.getSubnets().stream())
+                .filter(subnet -> subnet.getDeviceVteps() != null)
+                .flatMap(subnet -> subnet.getDeviceVteps().stream())
+                .filter(deviceVteps -> Objects.equals(getPsName(deviceVteps), psName)) //get device with same ps name
+                .filter(deviceVteps -> !Objects.equals(psNodeId, deviceVteps.getNodeId())
+                        || !Objects.equals(tunnelIp, deviceVteps.getIpAddress()))//node id or tunnel ip is changed
+                .forEach(deviceVteps -> deleteStaleL2gwTep(dataBroker, itmRpcService, deviceVteps));
+        } catch (ReadFailedException e) {
+            LOG.error("Failed delete stale tunnels for {}", globalNodeId);
+        }
+    }
+
+    private static Optional<TransportZones> readTransportZone(DataBroker dataBroker) throws ReadFailedException {
+        return new SingleTransactionDataBroker(dataBroker).syncReadOptional(LogicalDatastoreType.CONFIGURATION,
+                InstanceIdentifier.builder(TransportZones.class).build());
+    }
+
+    private static Optional<ElanInstances> readElanInstances(DataBroker dataBroker) throws ReadFailedException {
+        return new SingleTransactionDataBroker(dataBroker).syncReadOptional(LogicalDatastoreType.CONFIGURATION,
+                InstanceIdentifier.builder(ElanInstances.class).build());
+    }
+
+    private static String getPsName(DeviceVteps deviceVteps) {
+        return HwvtepHAUtil.getPsName(HwvtepHAUtil.convertToInstanceIdentifier(deviceVteps.getNodeId()));
+    }
+
+    private static void deleteStaleL2gwTep(DataBroker dataBroker,
+                                           ItmRpcService itmRpcService,
+                                           DeviceVteps deviceVteps) {
+        String psName = HwvtepHAUtil.getPsName(HwvtepHAUtil.convertToInstanceIdentifier(deviceVteps.getNodeId()));
+        String globalNodeId = HwvtepHAUtil.convertToGlobalNodeId(deviceVteps.getNodeId());
+        try {
+            LOG.info("Deleting stale tep {} ", deviceVteps);
+            L2GatewayUtils.deleteItmTunnels(itmRpcService, globalNodeId, psName, deviceVteps.getIpAddress());
+            Optional<ElanInstances> optionalElan = readElanInstances(dataBroker);
+            if (!optionalElan.isPresent()) {
+                return;
+            }
+            LoggingFutures.addErrorLogging(
+                new ManagedNewTransactionRunnerImpl(dataBroker).callWithNewReadWriteTransactionAndSubmit(CONFIGURATION,
+                    tx -> optionalElan.get().nonnullElanInstance().stream()
+                        .flatMap(elan -> elan.nonnullExternalTeps().stream()
+                            .map(externalTep -> ElanL2GatewayMulticastUtils.buildExternalTepPath(
+                                elan.getElanInstanceName(), externalTep.getTepIp())))
+                        .filter(externalTepIid -> Objects.equals(
+                            deviceVteps.getIpAddress(), externalTepIid.firstKeyOf(ExternalTeps.class).getTepIp()))
+                        .peek(externalTepIid -> LOG.info("Deleting stale external tep {}", externalTepIid))
+                        .forEach(tx::delete)), LOG,
+                "Failed to delete stale external teps {}", deviceVteps);
+            Thread.sleep(10000);//TODO remove the sleep currently it waits for interfacemgr to finish the cleanup
+        } catch (ReadFailedException | InterruptedException e) {
+            LOG.error("Failed to delete stale l2gw tep {}", deviceVteps, e);
+        }
     }
 
     public void scheduleAddDpnMacInExtDevices(String elanName, BigInteger dpId,
@@ -1028,16 +1067,15 @@ public class ElanL2GatewayUtils {
 
     public void scheduleDeleteLogicalSwitch(final NodeId hwvtepNodeId, final String lsName, final boolean clearUcast) {
         final Pair<NodeId, String> nodeIdLogicalSwitchNamePair = new ImmutablePair<>(hwvtepNodeId, lsName);
-        logicalSwitchDeletedTasks.computeIfAbsent(nodeIdLogicalSwitchNamePair, (key) -> {
-            return scheduler.getScheduledExecutorService().schedule(() -> {
+        logicalSwitchDeletedTasks.computeIfAbsent(nodeIdLogicalSwitchNamePair,
+            (key) -> scheduler.getScheduledExecutorService().schedule(() -> {
                 DeleteLogicalSwitchJob deleteLsJob = new DeleteLogicalSwitchJob(broker,
                         ElanL2GatewayUtils.this, hwvtepNodeId, lsName, clearUcast);
                 jobCoordinator.enqueueJob(deleteLsJob.getJobKey(), deleteLsJob,
                         SystemPropertyReader.getDataStoreJobCoordinatorMaxRetries());
                 deleteJobs.put(nodeIdLogicalSwitchNamePair, deleteLsJob);
                 logicalSwitchDeletedTasks.remove(nodeIdLogicalSwitchNamePair);
-            }, getLogicalSwitchDeleteDelaySecs(), TimeUnit.SECONDS);
-        });
+            }, getLogicalSwitchDeleteDelaySecs(), TimeUnit.SECONDS));
     }
 
     public void cancelDeleteLogicalSwitch(final NodeId hwvtepNodeId, final String lsName) {
@@ -1053,7 +1091,7 @@ public class ElanL2GatewayUtils {
         }
     }
 
-    @Nonnull
+    @NonNull
     public Collection<DpnInterfaces> getElanDpns(String elanName) {
         Collection<DpnInterfaces> dpnInterfaces = elanInstanceDpnsCache.get(elanName);
         if (!dpnInterfaces.isEmpty()) {
@@ -1085,11 +1123,11 @@ public class ElanL2GatewayUtils {
         Optional<Node> configNode = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION,
                 HwvtepSouthboundUtils.createInstanceIdentifier(new NodeId(l2gwDevice.getHwvtepNodeId())));
         if (configNode.isPresent()) {
-            HwvtepGlobalAugmentation augmentation = configNode.get().getAugmentation(HwvtepGlobalAugmentation.class);
+            HwvtepGlobalAugmentation augmentation = configNode.get().augmentation(HwvtepGlobalAugmentation.class);
             if (augmentation != null && augmentation.getLocalUcastMacs() != null) {
                 macs.addAll(augmentation.getLocalUcastMacs().stream()
                         .filter(mac -> getLogicalSwitchName(mac).equals(elanName))
-                        .map(mac -> mac.getMacEntryKey())
+                        .map(HwvtepMacTableGenericAttributes::getMacEntryKey)
                         .collect(Collectors.toSet()));
             }
         }