NETVIRT-1630 migrate to md-sal APIs
[netvirt.git] / vpnmanager / impl / src / main / java / org / opendaylight / netvirt / vpnmanager / InterfaceStateChangeListener.java
index c06fc1c2d6d30c1f292ac23e4ea429777ce978ce..9211bfcf865c4a717a0dfa9472ba6ca539981810 100644 (file)
@@ -9,50 +9,49 @@ package org.opendaylight.netvirt.vpnmanager;
 
 import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
 import static org.opendaylight.genius.infra.Datastore.OPERATIONAL;
-import static org.opendaylight.netvirt.vpnmanager.VpnUtil.requireNonNullElse;
 
-import com.google.common.base.Optional;
 import com.google.common.collect.HashBasedTable;
 import com.google.common.collect.Table;
 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.math.BigInteger;
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.Set;
-import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
 import javax.inject.Inject;
 import javax.inject.Singleton;
-
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-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.infrautils.jobcoordinator.JobCoordinator;
+import org.opendaylight.infrautils.utils.concurrent.Executors;
+import org.opendaylight.mdsal.binding.api.DataBroker;
+import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
 import org.opendaylight.netvirt.vpnmanager.api.InterfaceUtils;
-import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
-import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.vpn._interface.VpnInstanceNames;
+import org.opendaylight.serviceutils.tools.listener.AbstractAsyncDataTreeChangeListener;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev170119.L2vlan;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.data.LearntVpnVipToPort;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn._interface.op.data.VpnInterfaceOpDataEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.Adjacencies;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.adjacency.list.Adjacency;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.VpnInterface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.vpn._interface.VpnInstanceNames;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.Uint64;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 @Singleton
-public class InterfaceStateChangeListener
-    extends AsyncDataTreeChangeListenerBase<Interface, InterfaceStateChangeListener> {
+public class InterfaceStateChangeListener extends AbstractAsyncDataTreeChangeListener<Interface> {
 
     private static final Logger LOG = LoggerFactory.getLogger(InterfaceStateChangeListener.class);
     private static final short DJC_MAX_RETRIES = 3;
@@ -88,7 +87,9 @@ public class InterfaceStateChangeListener
     @Inject
     public InterfaceStateChangeListener(final DataBroker dataBroker, final VpnInterfaceManager vpnInterfaceManager,
             final VpnUtil vpnUtil, final JobCoordinator jobCoordinator, final IFibManager fibManager) {
-        super(Interface.class, InterfaceStateChangeListener.class);
+        super(dataBroker, LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.create(InterfacesState.class)
+                .child(Interface.class),
+                Executors.newListeningSingleThreadExecutor("InterfaceStateChangeListener", LOG));
         this.dataBroker = dataBroker;
         this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
         this.vpnInterfaceManager = vpnInterfaceManager;
@@ -98,28 +99,22 @@ public class InterfaceStateChangeListener
         initialize();
     }
 
-    @PostConstruct
     public void start() {
         LOG.info("{} start", getClass().getSimpleName());
-        registerListener(LogicalDatastoreType.OPERATIONAL, dataBroker);
-    }
-
-
-    @Override
-    protected InstanceIdentifier<Interface> getWildCardPath() {
-        return InstanceIdentifier.create(InterfacesState.class).child(Interface.class);
     }
 
     @Override
-    protected InterfaceStateChangeListener getDataTreeChangeListener() {
-        return InterfaceStateChangeListener.this;
+    @PreDestroy
+    public void close() {
+        super.close();
+        Executors.shutdownAndAwaitTermination(getExecutorService());
     }
 
 
     @Override
     // TODO Clean up the exception handling
     @SuppressWarnings("checkstyle:IllegalCatch")
-    protected void add(InstanceIdentifier<Interface> identifier, Interface intrf) {
+    public void add(InstanceIdentifier<Interface> identifier, Interface intrf) {
         try {
             if (L2vlan.class.equals(intrf.getType())) {
                 LOG.info("VPN Interface add event - intfName {} from InterfaceStateChangeListener",
@@ -140,8 +135,7 @@ public class InterfaceStateChangeListener
                                         final VpnInterface vpnIf = vpnUtil.getConfiguredVpnInterface(interfaceName);
                                         if (vpnIf != null) {
                                             for (VpnInstanceNames vpnInterfaceVpnInstance :
-                                                    requireNonNullElse(vpnIf.getVpnInstanceNames(),
-                                                        Collections.<VpnInstanceNames>emptyList())) {
+                                                    vpnIf.nonnullVpnInstanceNames()) {
                                                 String vpnName = vpnInterfaceVpnInstance.getVpnName();
                                                 String primaryRd = vpnUtil.getPrimaryRd(vpnName);
                                                 if (!vpnInterfaceManager.isVpnInstanceReady(vpnName)) {
@@ -153,7 +147,7 @@ public class InterfaceStateChangeListener
                                                             + " vpnInstance {} with primaryRd {} is already marked for"
                                                             + " deletion", interfaceName, vpnName, primaryRd);
                                                 } else {
-                                                    BigInteger intfDpnId = BigInteger.ZERO;
+                                                    Uint64 intfDpnId = Uint64.ZERO;
                                                     try {
                                                         intfDpnId = InterfaceUtils.getDpIdFromInterface(intrf);
                                                     } catch (Exception e) {
@@ -162,7 +156,10 @@ public class InterfaceStateChangeListener
                                                                 e);
                                                         return;
                                                     }
-                                                    final BigInteger dpnId = intfDpnId;
+                                                    LOG.error("InterfaceStateChangeListener- Processing ifState"
+                                                                    + " {} add event with dpnId {}",
+                                                            intrf.getName(), intfDpnId);
+                                                    final Uint64 dpnId = intfDpnId;
                                                     final int ifIndex = intrf.getIfIndex();
                                                     LOG.info("VPN Interface add event - intfName {} onto vpnName {}"
                                                             + " running oper-driven", vpnIf.getName(), vpnName);
@@ -185,7 +182,7 @@ public class InterfaceStateChangeListener
                         futures.add(configFuture);
                         //TODO: Allow immediateFailedFuture from writeCfgTxn to cancel writeInvTxn as well.
                         Futures.addCallback(configFuture, new PostVpnInterfaceThreadWorker(intrf.getName(), true,
-                                "Operational"));
+                                "Operational"), MoreExecutors.directExecutor());
                     }));
                     return futures;
                 });
@@ -198,9 +195,9 @@ public class InterfaceStateChangeListener
     @Override
     // TODO Clean up the exception handling
     @SuppressWarnings("checkstyle:IllegalCatch")
-    protected void remove(InstanceIdentifier<Interface> identifier, Interface intrf) {
+    public void remove(InstanceIdentifier<Interface> identifier, Interface intrf) {
         final String ifName = intrf.getName();
-        BigInteger dpId = BigInteger.ZERO;
+        Uint64 dpId = Uint64.ZERO;
         try {
             if (L2vlan.class.equals(intrf.getType())) {
                 LOG.info("VPN Interface remove event - intfName {} from InterfaceStateChangeListener",
@@ -211,7 +208,7 @@ public class InterfaceStateChangeListener
                     LOG.error("Unable to retrieve dpnId from interface operational data store for interface"
                             + " {}. Fetching from vpn interface op data store. ", ifName, e);
                 }
-                final BigInteger inputDpId = dpId;
+                final Uint64 inputDpId = dpId;
                 jobCoordinator.enqueueJob("VPNINTERFACE-" + ifName, () -> {
                     List<ListenableFuture<Void>> futures = new ArrayList<>(3);
                     ListenableFuture<Void> configFuture =
@@ -226,8 +223,7 @@ public class InterfaceStateChangeListener
                                             return;
                                         }
                                         for (VpnInstanceNames vpnInterfaceVpnInstance :
-                                                requireNonNullElse(cfgVpnInterface.getVpnInstanceNames(),
-                                                    Collections.<VpnInstanceNames>emptyList())) {
+                                                cfgVpnInterface.nonnullVpnInstanceNames()) {
                                             String vpnName = vpnInterfaceVpnInstance.getVpnName();
                                             Optional<VpnInterfaceOpDataEntry> optVpnInterface =
                                                 vpnUtil.getVpnInterfaceOpDataEntry(ifName, vpnName);
@@ -236,11 +232,12 @@ public class InterfaceStateChangeListener
                                                     + " triggered by northbound agent. ignoring.", ifName, vpnName);
                                                 continue;
                                             }
+                                            handleMipAdjRemoval(cfgVpnInterface, vpnName);
                                             final VpnInterfaceOpDataEntry vpnInterface = optVpnInterface.get();
                                             String gwMac = intrf.getPhysAddress() != null ? intrf.getPhysAddress()
                                                 .getValue() : vpnInterface.getGatewayMacAddress();
-                                            BigInteger dpnId = inputDpId;
-                                            if (dpnId == null || dpnId.equals(BigInteger.ZERO)) {
+                                            Uint64 dpnId = inputDpId;
+                                            if (dpnId == null || dpnId.equals(Uint64.ZERO)) {
                                                 dpnId = vpnInterface.getDpnId();
                                             }
                                             final int ifIndex = intrf.getIfIndex();
@@ -252,7 +249,7 @@ public class InterfaceStateChangeListener
                                     })))));
                     futures.add(configFuture);
                     Futures.addCallback(configFuture, new PostVpnInterfaceThreadWorker(intrf.getName(), false,
-                            "Operational"));
+                            "Operational"), MoreExecutors.directExecutor());
                     return futures;
                 }, DJC_MAX_RETRIES);
             }
@@ -264,7 +261,7 @@ public class InterfaceStateChangeListener
     // TODO Clean up the exception handling
     @SuppressWarnings("checkstyle:IllegalCatch")
     @Override
-    protected void update(InstanceIdentifier<Interface> identifier,
+    public void update(InstanceIdentifier<Interface> identifier,
                     Interface original, Interface update) {
         final String ifName = update.getName();
         try {
@@ -288,7 +285,7 @@ public class InterfaceStateChangeListener
                                             final VpnInterface vpnIf = vpnUtil.getConfiguredVpnInterface(ifName);
                                             if (vpnIf != null) {
                                                 final int ifIndex = update.getIfIndex();
-                                                BigInteger dpnId;
+                                                Uint64 dpnId;
                                                 try {
                                                     dpnId = InterfaceUtils.getDpIdFromInterface(update);
                                                 } catch (Exception e) {
@@ -304,10 +301,14 @@ public class InterfaceStateChangeListener
                                                          original.getOperStatus(), update.getOperStatus());
                                                     return;
                                                 }
-                                                if (state.equals(IntfTransitionState.STATE_UP)) {
+                                                LOG.error("InterfaceStateChangeListener- Processing ifState {} "
+                                                                + "update event "
+                                                                + "with dpnId {} operstate {}",
+                                                        ifName, dpnId, update.getOperStatus());
+                                                if (state.equals(IntfTransitionState.STATE_UP)
+                                                        && vpnIf.getVpnInstanceNames() != null) {
                                                     for (VpnInstanceNames vpnInterfaceVpnInstance :
-                                                        requireNonNullElse(vpnIf.getVpnInstanceNames(),
-                                                        Collections.<VpnInstanceNames>emptyList())) {
+                                                            vpnIf.getVpnInstanceNames()) {
                                                         String vpnName = vpnInterfaceVpnInstance.getVpnName();
                                                         String primaryRd = vpnUtil.getPrimaryRd(vpnName);
                                                         Set<String> prefixes = new HashSet<>();
@@ -328,10 +329,10 @@ public class InterfaceStateChangeListener
                                                             mapOfRdAndPrefixesForRefreshFib.put(primaryRd, prefixes);
                                                         }
                                                     }
-                                                } else if (state.equals(IntfTransitionState.STATE_DOWN)) {
+                                                } else if (state.equals(IntfTransitionState.STATE_DOWN)
+                                                        && vpnIf.getVpnInstanceNames() != null) {
                                                     for (VpnInstanceNames vpnInterfaceVpnInstance :
-                                                        requireNonNullElse(vpnIf.getVpnInstanceNames(),
-                                                        Collections.<VpnInstanceNames>emptyList())) {
+                                                            vpnIf.getVpnInstanceNames()) {
                                                         String vpnName = vpnInterfaceVpnInstance.getVpnName();
                                                         LOG.info("VPN Interface update event - intfName {} "
                                                             + " onto vpnName {} running oper-driven DOWN",
@@ -341,6 +342,7 @@ public class InterfaceStateChangeListener
                                                         if (optVpnInterface.isPresent()) {
                                                             VpnInterfaceOpDataEntry vpnOpInterface =
                                                                 optVpnInterface.get();
+                                                            handleMipAdjRemoval(vpnIf, vpnName);
                                                             vpnInterfaceManager.processVpnInterfaceDown(dpnId,
                                                                 vpnIf.getName(), ifIndex, update.getPhysAddress()
                                                                 .getValue(), vpnOpInterface, true,
@@ -370,6 +372,29 @@ public class InterfaceStateChangeListener
         }
     }
 
+    private void handleMipAdjRemoval(VpnInterface cfgVpnInterface, String vpnName) {
+        String interfaceName = cfgVpnInterface.getName();
+        Adjacencies adjacencies = cfgVpnInterface.augmentation(Adjacencies.class);
+        if (adjacencies != null) {
+            List<Adjacency> adjacencyList = adjacencies.getAdjacency();
+            if (!adjacencyList.isEmpty()) {
+                for (Adjacency adj : adjacencyList) {
+                    if (adj.getAdjacencyType() != Adjacency.AdjacencyType.PrimaryAdjacency) {
+                        String ipAddress = adj.getIpAddress();
+                        String prefix = ipAddress.split("/")[0];
+                        LearntVpnVipToPort vpnVipToPort = vpnUtil.getLearntVpnVipToPort(vpnName, prefix);
+                        if (vpnVipToPort != null && vpnVipToPort.getPortName().equals(interfaceName)) {
+                            vpnUtil.removeMipAdjacency(vpnName, interfaceName, ipAddress, null);
+                        } else {
+                            LOG.debug("IP {} could be extra-route or learnt-ip on different interface"
+                                    + "than oper-vpn-interface {}", ipAddress, interfaceName);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
     private class PostVpnInterfaceThreadWorker implements FutureCallback<Void> {
         private final String interfaceName;
         private final boolean add;
@@ -430,7 +455,7 @@ public class InterfaceStateChangeListener
 
         @Override
         public void onFailure(Throwable throwable) {
-            LOG.debug("write Tx config operation failed {}", throwable);
+            LOG.debug("write Tx config operation failedTunnelEndPointChangeListener", throwable);
         }
     }
 }