Upgrade+conntrack, default FIB flow missing 25/66825/12
authorJosh <jhershbe@redhat.com>
Tue, 2 Jan 2018 03:47:46 +0000 (05:47 +0200)
committerSam Hague <shague@redhat.com>
Wed, 24 Jan 2018 18:48:13 +0000 (18:48 +0000)
N.B.: Depends on https://git.opendaylight.org/gerrit/#/c/65894/

The default fib route can not be configured before
the VpnInstanceOpDataEntry's dpn<->vpn mapping exists.
I've added code that waits for that to show up.

Change-Id: I7a4e75b04b171b5a6c80c74e75a410312ef3dee6
Signed-off-by: Josh <jhershbe@redhat.com>
vpnservice/natservice/natservice-impl/src/main/java/org/opendaylight/netvirt/natservice/internal/ExternalSubnetVpnInstanceListener.java
vpnservice/natservice/natservice-impl/src/main/java/org/opendaylight/netvirt/natservice/internal/SNATDefaultRouteProgrammer.java
vpnservice/natservice/natservice-impl/src/main/resources/org/opendaylight/blueprint/natservice.xml

index 40947911121be6ba23b61f2452dadf1f08b32b34..1e3f3c52968bca6ed3410a56a380e049712b5730 100644 (file)
@@ -8,18 +8,25 @@
 package org.opendaylight.netvirt.natservice.internal;
 
 import com.google.common.base.Optional;
+import java.util.List;
 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.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
+import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
+import org.opendaylight.genius.datastoreutils.listeners.DataTreeEventCallbackRegistrar;
 import org.opendaylight.genius.mdsalutil.NwConstants;
+import org.opendaylight.genius.mdsalutil.UpgradeState;
 import org.opendaylight.netvirt.elanmanager.api.IElanService;
 import org.opendaylight.netvirt.vpnmanager.api.IVpnManager;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInstanceToVpnId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.subnets.Subnets;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
@@ -35,15 +42,20 @@ public class ExternalSubnetVpnInstanceListener extends AsyncDataTreeChangeListen
     private final SNATDefaultRouteProgrammer snatDefaultRouteProgrammer;
     private final IElanService elanService;
     private final IVpnManager vpnManager;
+    private final UpgradeState upgradeState;
+    private final DataTreeEventCallbackRegistrar dataTreeEventCallbackRegistrar;
 
     @Inject
     public ExternalSubnetVpnInstanceListener(final DataBroker dataBroker,
-            final SNATDefaultRouteProgrammer snatDefaultRouteProgrammer,
-            final IElanService elanService, final IVpnManager vpnManager) {
+                     final SNATDefaultRouteProgrammer snatDefaultRouteProgrammer,
+                     final IElanService elanService, final IVpnManager vpnManager,
+                     final UpgradeState upgradeState, DataTreeEventCallbackRegistrar dataTreeEventCallbackRegistrar) {
         this.dataBroker = dataBroker;
         this.snatDefaultRouteProgrammer = snatDefaultRouteProgrammer;
         this.elanService = elanService;
         this.vpnManager = vpnManager;
+        this.upgradeState = upgradeState;
+        this.dataTreeEventCallbackRegistrar = dataTreeEventCallbackRegistrar;
     }
 
     @Override
@@ -117,6 +129,48 @@ public class ExternalSubnetVpnInstanceListener extends AsyncDataTreeChangeListen
         LOG.debug("addOrDelDefaultFibRouteToSNATFlow : VpnInstance {} for external subnet {}.",
                 vpnInstanceName, subnet);
         Long vpnId = vpnInstance.getVpnId();
+
+        if (upgradeState.isUpgradeInProgress()) {
+            LOG.info("Upgrade in process, checking for existence of VpnInstanceOpDataEntry's vpn->dpn list");
+            InstanceIdentifier<VpnInstanceOpDataEntry> vpnOpDataIid =
+                    NatUtil.getVpnInstanceOpDataIdentifier(subnet.getExternalNetworkId().getValue());
+
+            Optional<VpnInstanceOpDataEntry> networkVpnInstanceOp;
+            try {
+                networkVpnInstanceOp = SingleTransactionDataBroker.syncReadOptional(
+                                            dataBroker, LogicalDatastoreType.OPERATIONAL, vpnOpDataIid);
+            } catch (ReadFailedException e) {
+                LOG.error("Exception while attempting to read VpnInstanceOpDataEntry", e);
+                return;
+            }
+
+            List<VpnToDpnList> dpnListInVpn = null;
+            if (networkVpnInstanceOp.isPresent()) {
+                dpnListInVpn = networkVpnInstanceOp.get().getVpnToDpnList();
+            }
+
+            if (dpnListInVpn == null) {
+                LOG.info("VpnInstanceOpDataEntry's vpn->dpn list not present, wait for it");
+                dataTreeEventCallbackRegistrar.onAddOrUpdate(LogicalDatastoreType.OPERATIONAL, vpnOpDataIid,
+                    (beforeOpData, afterOpData) -> {
+                        LOG.info("VpnInstanceOpDataEntry added/updated {}", afterOpData);
+                        if (afterOpData.getVpnToDpnList() == null) {
+                            if (upgradeState.isUpgradeInProgress()) {
+                                return DataTreeEventCallbackRegistrar.NextAction.CALL_AGAIN;
+                            } else {
+                                return DataTreeEventCallbackRegistrar.NextAction.UNREGISTER;
+                            }
+                        }
+                        snatDefaultRouteProgrammer.addOrDelDefaultFibRouteToSNATForSubnet(subnet,
+                                subnet.getExternalNetworkId().getValue(), flowAction, vpnId);
+                        return DataTreeEventCallbackRegistrar.NextAction.UNREGISTER;
+                    });
+                return;
+            }
+            LOG.info("VpnInstanceOpDataEntry's vpn->dpn list present, continue with regular scheduled programming");
+
+        }
+
         snatDefaultRouteProgrammer.addOrDelDefaultFibRouteToSNATForSubnet(subnet,
                 subnet.getExternalNetworkId().getValue(), flowAction, vpnId);
     }
index 5c978d0f4adfc6328efca567f1d7b1b7aab2ad92..cd4c149ceabfab24fcfb4f7c4d666ce2ae52b774 100644 (file)
@@ -183,30 +183,34 @@ public class SNATDefaultRouteProgrammer {
         Optional<VpnInstanceOpDataEntry> networkVpnInstanceOp =
                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
                         LogicalDatastoreType.OPERATIONAL, networkVpnInstanceIdentifier);
-        if (networkVpnInstanceOp.isPresent()) {
-            List<VpnToDpnList> dpnListInVpn = networkVpnInstanceOp.get().getVpnToDpnList();
-            if (dpnListInVpn != null) {
-                for (VpnToDpnList dpn : dpnListInVpn) {
-                    FlowEntity flowEntity = NatUtil.buildDefaultNATFlowEntityForExternalSubnet(dpn.getDpnId(),
-                            vpnId, subnetId, idManager);
-                    if (flowAction == NwConstants.ADD_FLOW || flowAction == NwConstants.MOD_FLOW) {
-                        LOG.info("addOrDelDefaultFibRouteToSNATForSubnet : Installing flow {} for subnetId {},"
-                                + "vpnId {} on dpn {}", flowEntity, subnetId, vpnId, dpn.getDpnId());
-                        mdsalManager.installFlow(flowEntity);
-                    } else {
-                        LOG.info("addOrDelDefaultFibRouteToSNATForSubnet : Removing flow for subnetId {},"
-                                + "vpnId {} with dpn {}", subnetId, vpnId, dpn);
-                        mdsalManager.removeFlow(flowEntity);
-                    }
-                }
+
+        if (!networkVpnInstanceOp.isPresent()) {
+            LOG.debug("addOrDelDefaultFibRouteToSNATForSubnet : Cannot create/remove default FIB route to SNAT flow "
+                            + "for subnet {} vpn-instance-op-data entry for network {} does not exist",
+                    subnetId, networkId);
+            return;
+        }
+
+        List<VpnToDpnList> dpnListInVpn = networkVpnInstanceOp.get().getVpnToDpnList();
+        if (dpnListInVpn == null) {
+            LOG.debug("addOrDelDefaultFibRouteToSNATForSubnet : Will not add/remove default NAT flow for subnet {} "
+                    + "no dpn set for vpn instance {}", subnetId, networkVpnInstanceOp.get());
+
+            return;
+        }
+
+        for (VpnToDpnList dpn : dpnListInVpn) {
+            FlowEntity flowEntity = NatUtil.buildDefaultNATFlowEntityForExternalSubnet(dpn.getDpnId(),
+                    vpnId, subnetId, idManager);
+            if (flowAction == NwConstants.ADD_FLOW || flowAction == NwConstants.MOD_FLOW) {
+                LOG.info("addOrDelDefaultFibRouteToSNATForSubnet : Installing flow {} for subnetId {},"
+                        + "vpnId {} on dpn {}", flowEntity, subnetId, vpnId, dpn.getDpnId());
+                mdsalManager.installFlow(flowEntity);
             } else {
-                LOG.debug("addOrDelDefaultFibRouteToSNATForSubnet : Will not add/remove default NAT flow for subnet {} "
-                        + "no dpn set for vpn instance {}", subnetId, networkVpnInstanceOp.get());
+                LOG.info("addOrDelDefaultFibRouteToSNATForSubnet : Removing flow for subnetId {},"
+                        + "vpnId {} with dpn {}", subnetId, vpnId, dpn);
+                mdsalManager.removeFlow(flowEntity);
             }
-        } else {
-            LOG.debug("addOrDelDefaultFibRouteToSNATForSubnet : Cannot create/remove default FIB route to SNAT flow "
-                    + "for subnet {} vpn-instance-op-data entry for network {} does not exist",
-                subnetId, networkId);
         }
     }
 }
index 4cf4a820eb1b96be2f9ed8d5787d9b66e4e57249..7b5c4c8f925a26388371c9a359a6930af66e2538 100644 (file)
@@ -28,6 +28,8 @@
              interface="org.opendaylight.infrautils.jobcoordinator.JobCoordinator"/>
   <reference id="upgradeState"
              interface="org.opendaylight.genius.mdsalutil.UpgradeState"/>
+  <reference id="dataTreeEventCallbackRegistrar"
+             interface="org.opendaylight.genius.datastoreutils.listeners.DataTreeEventCallbackRegistrar"/>
 
   <odl:rpc-service id="idManagerService"
                    interface="org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService" />