Bug 8965 - L2gw update is not suported 26/61426/4
authoreaksahu <a.k.sahu@ericsson.com>
Wed, 9 Aug 2017 14:22:09 +0000 (19:52 +0530)
committerVivekanandan Narasimhan <n.vivekanandan@ericsson.com>
Mon, 21 Aug 2017 09:55:56 +0000 (09:55 +0000)
Currently l2gw once created , no update are on that are supported.
With this patch following use case has been supported.
Update existing l2gw vlanbindings
Update existing l2gw with new ports / device .

It takes care of configuring w.r.t associated l2gwconnection .

Change-Id: I37dda9cf366b1fe59ccf95f64f0574448f156d47
Signed-off-by: eaksahu <a.k.sahu@ericsson.com>
vpnservice/elanmanager/elanmanager-api/src/main/java/org/opendaylight/netvirt/elanmanager/api/IL2gwService.java
vpnservice/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/netvirt/elan/l2gw/utils/L2GatewayConnectionUtils.java
vpnservice/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/netvirt/elan/l2gw/utils/L2gwServiceProvider.java
vpnservice/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/netvirt/neutronvpn/l2gw/L2GatewayListener.java

index d8fae28f701187ace13418db3cb6e46bd2d07120..deb6c2ccf543ace131513edf60011799848109fa 100644 (file)
@@ -9,14 +9,26 @@
 package org.opendaylight.netvirt.elanmanager.api;
 
 import java.util.List;
+import java.util.Set;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.netvirt.neutronvpn.api.l2gw.L2GatewayDevice;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
 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.neutron.l2gateways.rev150712.l2gateway.connections.attributes.l2gatewayconnections.L2gatewayConnection;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l2gateways.rev150712.l2gateways.attributes.l2gateways.L2gateway;
 
 public interface IL2gwService {
     void provisionItmAndL2gwConnection(L2GatewayDevice l2GwDevice, String psName,
-                                              String hwvtepNodeId, IpAddress tunnelIpAddr) ;
+                                       String hwvtepNodeId, IpAddress tunnelIpAddr);
 
     List<L2gatewayConnection> getL2GwConnectionsByL2GatewayId(Uuid l2GatewayId);
+
+    void addL2GatewayConnection(L2gatewayConnection input);
+
+    void addL2GatewayConnection(L2gatewayConnection input,
+                                String l2GwDeviceName,
+                                L2gateway l2Gateway);
+
+    List<L2gatewayConnection> getAssociatedL2GwConnections(DataBroker broker, Set<Uuid> l2GatewayIds);
 }
index 887adbd0667006e63baaceda51e5555e1d057461..4d16986501e047171a18f25be26ab2c037c53c61 100644 (file)
@@ -146,10 +146,17 @@ public class L2GatewayConnectionUtils {
     }
 
     public void addL2GatewayConnection(L2gatewayConnection input) {
-        addL2GatewayConnection(input, null/*deviceName*/);
+        addL2GatewayConnection(input, null/*deviceName*/, null);
     }
 
-    public void addL2GatewayConnection(L2gatewayConnection input, String l2GwDeviceName) {
+    public void addL2GatewayConnection(final L2gatewayConnection input,
+                                       final String l2GwDeviceName) {
+        addL2GatewayConnection(input, l2GwDeviceName, null);
+    }
+
+    public void addL2GatewayConnection(final L2gatewayConnection input,
+                                       final String l2GwDeviceName ,
+                                       L2gateway l2Gateway) {
         LOG.info("Adding L2gateway Connection with ID: {}", input.getKey().getUuid());
 
         Uuid networkUuid = input.getNetworkId();
@@ -167,7 +174,9 @@ public class L2GatewayConnectionUtils {
             LOG.error("Neutron network with id {} is not VxlanNetwork", networkUuid.getValue());
         } else {
             Uuid l2GatewayId = input.getL2gatewayId();
-            L2gateway l2Gateway = getNeutronL2gateway(broker, l2GatewayId);
+            if (l2Gateway == null) {
+                l2Gateway = getNeutronL2gateway(broker, l2GatewayId);
+            }
             if (l2Gateway == null) {
                 LOG.error("L2Gateway with id {} is not present", l2GatewayId.getValue());
             } else {
index 9f5478b2156f6e63f70c1da8b8876a6e8cdc7d8b..95e5bdb70ddc8f3bfb55dc33daf147329edbbaca 100644 (file)
@@ -10,6 +10,8 @@ package org.opendaylight.netvirt.elan.l2gw.utils;
 
 import java.util.Collections;
 import java.util.List;
+import java.util.Set;
+
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
 import org.opendaylight.infrautils.inject.AbstractLifecycle;
@@ -21,6 +23,7 @@ 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.yang.types.rev130715.Uuid;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l2gateways.rev150712.l2gateway.connections.attributes.l2gatewayconnections.L2gatewayConnection;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l2gateways.rev150712.l2gateways.attributes.l2gateways.L2gateway;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -69,6 +72,23 @@ public class L2gwServiceProvider extends AbstractLifecycle implements IL2gwServi
                 this.dataBroker, l2GatewayId);
     }
 
+    @Override
+    public void addL2GatewayConnection(L2gatewayConnection input) {
+        this.elanUtils.getL2GatewayConnectionUtils().addL2GatewayConnection(input);
+    }
+
+    @Override
+    public void addL2GatewayConnection(L2gatewayConnection input,
+                                       String l2GwDeviceName,
+                                       L2gateway l2Gateway) {
+        this.elanUtils.getL2GatewayConnectionUtils().addL2GatewayConnection(input, l2GwDeviceName, l2Gateway);
+    }
+
+    @Override
+    public List<L2gatewayConnection> getAssociatedL2GwConnections(DataBroker broker, Set<Uuid> l2GatewayIds) {
+        return L2GatewayConnectionUtils.getAssociatedL2GwConnections(dataBroker, l2GatewayIds);
+    }
+
     @Override
     protected void start() throws Exception {
         LOG.info("Starting L2gwServiceProvider");
index 5f44670f32b5f2e097013d48d05c44e57e2dbe28..d2c9c89518d4838297d532536cfd2c8c915e9f2a 100644 (file)
@@ -7,10 +7,15 @@
  */
 package org.opendaylight.netvirt.neutronvpn.l2gw;
 
+import com.google.common.collect.Sets;
 import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
+
+import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 import javax.annotation.PostConstruct;
 import javax.inject.Inject;
@@ -21,16 +26,20 @@ import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipS
 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.datastoreutils.DataStoreJobCoordinator;
 import org.opendaylight.genius.mdsalutil.MDSALUtil;
+import org.opendaylight.genius.utils.SystemPropertyReader;
 import org.opendaylight.genius.utils.clustering.ClusteringUtils;
 import org.opendaylight.genius.utils.hwvtep.HwvtepSouthboundConstants;
 import org.opendaylight.genius.utils.hwvtep.HwvtepSouthboundUtils;
+import org.opendaylight.genius.utils.hwvtep.HwvtepUtils;
 import org.opendaylight.netvirt.elanmanager.api.IL2gwService;
 import org.opendaylight.netvirt.neutronvpn.api.l2gw.L2GatewayDevice;
 import org.opendaylight.netvirt.neutronvpn.api.l2gw.utils.L2GatewayCacheUtils;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l2gateways.rev150712.l2gateway.attributes.Devices;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l2gateways.rev150712.l2gateway.attributes.devices.Interfaces;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l2gateways.rev150712.l2gateway.connections.attributes.L2gatewayConnections;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l2gateways.rev150712.l2gateway.connections.attributes.l2gatewayconnections.L2gatewayConnection;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l2gateways.rev150712.l2gateways.attributes.L2gateways;
@@ -111,6 +120,68 @@ public class L2GatewayListener extends AsyncClusteredDataTreeChangeListenerBase<
     @Override
     protected void update(InstanceIdentifier<L2gateway> identifier, L2gateway original, L2gateway update) {
         LOG.trace("Updating L2gateway : key: {}, original value={}, update value={}", identifier, original, update);
+        List<L2gatewayConnection> connections = l2gwService.getAssociatedL2GwConnections(
+                dataBroker, Sets.newHashSet(update.getUuid()));
+        if (connections == null) {
+            LOG.warn("There are no connections associated with l2 gateway uuid {} name {}",
+                    update.getUuid(), update.getName());
+            return;
+        }
+        if (original.getDevices() == null) {
+            connections.forEach(
+                (connection) -> l2gwService.addL2GatewayConnection(connection));
+            return;
+        }
+        DataStoreJobCoordinator.getInstance().enqueueJob("l2gw.update", () -> {
+            ReadWriteTransaction transaction = dataBroker.newReadWriteTransaction();
+            DeviceInterfaces updatedDeviceInterfaces = new DeviceInterfaces(update);
+            List<ListenableFuture<Void>> fts = new ArrayList<ListenableFuture<Void>>();
+            original.getDevices()
+                    .stream()
+                    .filter((originalDevice) -> originalDevice.getInterfaces() != null)
+                    .forEach((originalDevice) -> {
+                        String deviceName = originalDevice.getDeviceName();
+                        L2GatewayDevice l2GwDevice = L2GatewayCacheUtils.getL2DeviceFromCache(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);
+                                            }
+                                        } 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>() {
+                @Override
+                public void onSuccess(Void success) {
+                    LOG.debug("Successfully deleted vlan bindings for l2gw update {}", update);
+                        connections.forEach((l2GwConnection) ->
+                                l2gwService.addL2GatewayConnection(l2GwConnection, null, update));
+                }
+
+                @Override
+                public void onFailure(Throwable throwable) {
+                    LOG.error("Failed to delete vlan bindings as part of l2gw udpate {}", update);
+                }
+            });
+            return fts;
+        }, SystemPropertyReader.getDataStoreJobCoordinatorMaxRetries());
     }
 
     private synchronized void addL2Device(Devices l2Device, L2gateway input) {
@@ -186,4 +257,27 @@ public class L2GatewayListener extends AsyncClusteredDataTreeChangeListenerBase<
     protected L2GatewayListener getDataTreeChangeListener() {
         return this;
     }
+
+    static class DeviceInterfaces {
+        Map<String, Map<String, Interfaces>> deviceInterfacesMap = new HashMap<>();
+
+        DeviceInterfaces(L2gateway l2gateway) {
+            if (l2gateway.getDevices() != null) {
+                l2gateway.getDevices().forEach((device) -> {
+                    deviceInterfacesMap.putIfAbsent(device.getDeviceName(), new HashMap<>());
+                    if (device.getInterfaces() != null) {
+                        device.getInterfaces().forEach((intf) ->
+                                deviceInterfacesMap.get(device.getDeviceName()).put(intf.getInterfaceName(), intf));
+                    }
+                });
+            }
+        }
+
+        boolean containsInterface(String deviceName, String interfaceName) {
+            if (deviceInterfacesMap.containsKey(deviceName)) {
+                return deviceInterfacesMap.get(deviceName).containsKey(interfaceName);
+            }
+            return false;
+        }
+    }
 }