EOS related changes for L2GW 04/84804/3
authormanojna v <manojna.vijayakrishna@ericsson.com>
Mon, 30 Sep 2019 09:12:25 +0000 (14:42 +0530)
committermanojna v <manojna.vijayakrishna@ericsson.com>
Wed, 9 Oct 2019 06:34:52 +0000 (12:04 +0530)
This change makes sure that whenever entity ownership change
occurs, l2gw connection and elan dpn interfaces information
is populated in the config datastore. A delay is specified
so that the 3 node odl cluster stablizes before EOS owner
for elan is selected.

This change covers a corner case where originally we could
have missed some updates that were triggered during eos
change.

Change-Id: Id1a6125edcf580f3621cd85c070e56fe09822f01
Signed-off-by: manojna v <manojna.vijayakrishna@ericsson.com>
elanmanager/impl/src/main/java/org/opendaylight/netvirt/elan/internal/ElanDpnInterfaceClusteredListener.java
elanmanager/impl/src/main/java/org/opendaylight/netvirt/elan/l2gw/listeners/ElanInstanceEntityOwnershipListener.java [new file with mode: 0644]
elanmanager/impl/src/main/java/org/opendaylight/netvirt/elan/l2gw/listeners/L2GatewayConnectionListener.java
elanmanager/impl/src/main/java/org/opendaylight/netvirt/elan/utils/ElanConstants.java

index f2bca580efa91899721edf82bf20c77e5b77e74a..d18882be9530f86219547c697fbb51ccc289f6c3 100644 (file)
@@ -151,7 +151,7 @@ public class ElanDpnInterfaceClusteredListener
     }
 
     @Override
-    protected void add(InstanceIdentifier<DpnInterfaces> identifier, final DpnInterfaces dpnInterfaces) {
+    public void add(InstanceIdentifier<DpnInterfaces> identifier, final DpnInterfaces dpnInterfaces) {
         final String elanName = getElanName(identifier);
 
         jobCoordinator.enqueueJob(elanName + ":l2gw", () -> {
diff --git a/elanmanager/impl/src/main/java/org/opendaylight/netvirt/elan/l2gw/listeners/ElanInstanceEntityOwnershipListener.java b/elanmanager/impl/src/main/java/org/opendaylight/netvirt/elan/l2gw/listeners/ElanInstanceEntityOwnershipListener.java
new file mode 100644 (file)
index 0000000..b71598b
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2019 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.netvirt.elan.l2gw.listeners;
+
+import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.OPERATIONAL;
+import static org.opendaylight.netvirt.elan.utils.ElanConstants.ELAN_EOS_DELAY;
+
+import com.google.common.base.Optional;
+
+import java.util.List;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.genius.mdsalutil.MDSALUtil;
+import org.opendaylight.genius.utils.hwvtep.HwvtepSouthboundConstants;
+import org.opendaylight.mdsal.eos.binding.api.EntityOwnershipChange;
+import org.opendaylight.mdsal.eos.binding.api.EntityOwnershipListener;
+import org.opendaylight.mdsal.eos.binding.api.EntityOwnershipService;
+import org.opendaylight.netvirt.elan.internal.ElanDpnInterfaceClusteredListener;
+import org.opendaylight.netvirt.elan.utils.Scheduler;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanDpnInterfaces;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.ElanDpnInterfacesList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.ElanDpnInterfacesListKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.elan.dpn.interfaces.list.DpnInterfaces;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Singleton
+public class ElanInstanceEntityOwnershipListener implements EntityOwnershipListener {
+
+    private static final Logger LOG = LoggerFactory.getLogger(ElanInstanceEntityOwnershipListener.class);
+
+    private final L2GatewayConnectionListener l2GatewayConnectionListener;
+    private final ElanDpnInterfaceClusteredListener elanDpnInterfaceClusteredListener;
+    private final Scheduler scheduler;
+    private final DataBroker dataBroker;
+    volatile ScheduledFuture<?> ft;
+
+    @Inject
+    public ElanInstanceEntityOwnershipListener(L2GatewayConnectionListener l2GatewayConnectionListener,
+                                               ElanDpnInterfaceClusteredListener elanDpnInterfaceClusteredListener,
+                                               Scheduler scheduler, DataBroker dataBroker,
+                                               EntityOwnershipService entityOwnershipService) {
+        this.l2GatewayConnectionListener = l2GatewayConnectionListener;
+        this.elanDpnInterfaceClusteredListener = elanDpnInterfaceClusteredListener;
+        this.scheduler = scheduler;
+        this.dataBroker = dataBroker;
+        entityOwnershipService.registerListener(HwvtepSouthboundConstants.ELAN_ENTITY_TYPE, this);
+    }
+
+    @SuppressWarnings("checkstyle:IllegalCatch")
+    @Override
+    public void ownershipChanged(EntityOwnershipChange ownershipChange) {
+        LOG.info("Entity Ownership changed for the entity: {}" , ownershipChange);
+        if (!ownershipChange.getState().isOwner()) {
+            if (ft != null) {
+                ft.cancel(false);
+                ft = null;
+            }
+            return;
+        }
+
+        if (!ownershipChange.getState().wasOwner() && ownershipChange.getState().isOwner()) {
+            if (ft != null) {
+                ft.cancel(false);
+                ft = null;
+            }
+            ft = scheduler.getScheduledExecutorService().schedule(() -> {
+                try {
+                    //check if i'm the owner
+                    if (ownershipChange.getState().isOwner()) {
+                        LOG.info("Elan Entity owner is: {}", ownershipChange);
+                        l2GatewayConnectionListener.loadL2GwConnectionCache();
+
+                        InstanceIdentifier<ElanDpnInterfaces> elanDpnInterfacesInstanceIdentifier = InstanceIdentifier
+                                .builder(ElanDpnInterfaces.class).build();
+
+                        Optional<ElanDpnInterfaces> optional = MDSALUtil.read(dataBroker, OPERATIONAL,
+                                elanDpnInterfacesInstanceIdentifier);
+                        if (optional.isPresent() && optional.get().getElanDpnInterfacesList() != null) {
+                            LOG.debug("Found elan dpn interfaces list");
+                            optional.get().getElanDpnInterfacesList().forEach(elanDpnInterfacesList -> {
+                                List<DpnInterfaces> dpnInterfaces = elanDpnInterfacesList.getDpnInterfaces();
+                                InstanceIdentifier<ElanDpnInterfacesList> parentIid = InstanceIdentifier
+                                        .builder(ElanDpnInterfaces.class).child(ElanDpnInterfacesList.class,
+                                                new ElanDpnInterfacesListKey(elanDpnInterfacesList
+                                                        .getElanInstanceName())).build();
+                                for (DpnInterfaces dpnInterface : dpnInterfaces) {
+                                    LOG.debug("Found elan dpn interfaces");
+                                    elanDpnInterfaceClusteredListener.add(parentIid
+                                                    .child(DpnInterfaces.class, dpnInterface.key()),
+                                            dpnInterface);
+                                }
+                            });
+                        }
+                    } else {
+                        LOG.info("Not the owner for Elan entity {}", ownershipChange);
+                    }
+                    ft = null;
+                } catch (Exception e) {
+                    LOG.error("Failed to read mdsal ", e);
+                }
+            }, ELAN_EOS_DELAY, TimeUnit.MINUTES);
+        }
+    }
+}
\ No newline at end of file
index a4f528bcdfff4dd3781056b8ea46da84bd767275..7268a3b54c91428dd9b70b2bfc5dc8ce0ca68340 100644 (file)
@@ -31,6 +31,7 @@ import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
 import org.opendaylight.genius.datastoreutils.AsyncClusteredDataTreeChangeListenerBase;
+import org.opendaylight.genius.mdsalutil.MDSALUtil;
 import org.opendaylight.genius.utils.hwvtep.HwvtepSouthboundUtils;
 import org.opendaylight.infrautils.metrics.Counter;
 import org.opendaylight.infrautils.metrics.Labeled;
@@ -105,6 +106,8 @@ public class L2GatewayConnectionListener extends AsyncClusteredDataTreeChangeLis
     @PostConstruct
     public void init() {
         loadL2GwDeviceCache(1);
+        LOG.trace("Loading l2gw connection cache");
+        loadL2GwConnectionCache();
     }
 
     @Override
@@ -211,6 +214,21 @@ public class L2GatewayConnectionListener extends AsyncClusteredDataTreeChangeLis
                 });
     }
 
+    public void loadL2GwConnectionCache() {
+        InstanceIdentifier<L2gatewayConnections> parentIid = InstanceIdentifier
+                .create(Neutron.class)
+                .child(L2gatewayConnections.class);
+
+        Optional<L2gatewayConnections> optional = MDSALUtil.read(broker, CONFIGURATION, parentIid);
+        if (optional.isPresent() && optional.get().getL2gatewayConnection() != null) {
+            LOG.trace("Found some connections to fill in l2gw connection cache");
+            optional.get().getL2gatewayConnection()
+                    .forEach(connection -> {
+                        add(parentIid.child(L2gatewayConnection.class, connection.key()), connection);
+                    });
+        }
+    }
+
     void addL2DeviceToCache(InstanceIdentifier<Node> psIid, Node globalNode, Node psNode) {
         LOG.trace("Adding device to cache {}", psNode.getNodeId().getValue());
         String deviceName = HwvtepHAUtil.getPsName(psIid);
index ad8aceb4b2c64c3e5c78cd4c3b7cef25db553816..41021ba38b6717a3a1cd80fe9a8a75b5f9dd86b5 100755 (executable)
@@ -23,6 +23,7 @@ public interface ElanConstants {
     long DELAY_TIME_IN_MILLISECOND = 5000;
     int ELAN_GID_MIN = 200000;
     int ELAN_SERVICE_PRIORITY = 5;
+    int ELAN_EOS_DELAY = 5;
     int STATIC_MAC_TIMEOUT = 0;
     int ELAN_TAG_LENGTH = 16;
     int INTERFACE_TAG_LENGTH = 20;