Bug 6920 : Fix for ACL portSecurityUpdate to work with DjC + listed fixes 81/46781/2
authorAbhinav Gupta <abhinav.gupta@ericsson.com>
Tue, 11 Oct 2016 16:48:12 +0000 (22:18 +0530)
committerSam Hague <shague@redhat.com>
Tue, 11 Oct 2016 21:11:41 +0000 (21:11 +0000)
1. Fixes conflicting modification exceptions at interfaces/interface level
due to portVifType update and securityGroupUpdate writing at same time.

2. Includes fix for Lock API for sync in NeutronVpnUtils causing
concurrent modf exception : Bug 6902 :
https://git.opendaylight.org/gerrit/#/c/46663/

3. Synchronize on writes to router-interfaces map, not using DjC

Change-Id: I74bf6dd7bd80539e483bdf233a6d91ea39031190
Signed-off-by: Abhinav Gupta <abhinav.gupta@ericsson.com>
vpnservice/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronPortChangeListener.java
vpnservice/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronvpnManager.java
vpnservice/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronvpnUtils.java

index 50b92c1c9eb561e7c0084a9c55e1e88b2ca52ef8..efd2b061827c9315eed1f6815fd6c4a41a5fcf20 100644 (file)
@@ -186,18 +186,44 @@ public class NeutronPortChangeListener extends AsyncDataTreeChangeListenerBase<P
             }
         }
 
-        /* check if VIF type updated as part of port binding */
-        if(NeutronvpnUtils.isPortVifTypeUpdated(original, update)) {
+        // check if VIF type updated as part of port binding
+        // check if port security enabled/disabled as part of port update
+        boolean isPortVifTypeUpdated = NeutronvpnUtils.isPortVifTypeUpdated(original, update);
+        boolean origSecurityEnabled = NeutronvpnUtils.getPortSecurityEnabled(original);
+        boolean updatedSecurityEnabled = NeutronvpnUtils.getPortSecurityEnabled(update);
+
+        if (isPortVifTypeUpdated || origSecurityEnabled || updatedSecurityEnabled) {
+            InstanceIdentifier interfaceIdentifier = NeutronvpnUtils.buildVlanInterfaceIdentifier(portName);
             final DataStoreJobCoordinator portDataStoreCoordinator = DataStoreJobCoordinator.getInstance();
             portDataStoreCoordinator.enqueueJob("PORT- " + portName, new Callable<List<ListenableFuture<Void>>>() {
                 @Override
                 public List<ListenableFuture<Void>> call() throws Exception {
                     WriteTransaction wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
+                    try {
+                        Optional<Interface> optionalInf = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType
+                                .CONFIGURATION, interfaceIdentifier);
+                        if (optionalInf.isPresent()) {
+                            InterfaceBuilder interfaceBuilder = new InterfaceBuilder(optionalInf.get());
+                            if (isPortVifTypeUpdated && getParentRefsBuilder(update) != null) {
+                                interfaceBuilder.addAugmentation(ParentRefs.class, getParentRefsBuilder(update).build
+                                        ());
+                            }
+                            if (origSecurityEnabled || updatedSecurityEnabled) {
+                                InterfaceAcl infAcl = handlePortSecurityUpdated(original, update,
+                                        origSecurityEnabled, updatedSecurityEnabled, interfaceBuilder).build();
+                                interfaceBuilder.addAugmentation(InterfaceAcl.class, infAcl);
+                            }
+                            LOG.info("Of-port-interface updation for port {}", portName);
+                            // Update OFPort interface for this neutron port
+                            wrtConfigTxn.put(LogicalDatastoreType.CONFIGURATION, interfaceIdentifier,
+                                    interfaceBuilder.build());
+                        } else {
+                            LOG.error("Interface {} is not present", portName);
+                        }
+                    } catch (Exception e) {
+                        LOG.error("Failed to update interface {} due to the exception {}", portName, e);
+                    }
                     List<ListenableFuture<Void>> futures = new ArrayList<>();
-
-                    LOG.info("Of-port-interface updation for port {}", portName);
-                    // Update of-port interface for this neutron port
-                    updateOfPortInterface(original, update, wrtConfigTxn);
                     futures.add(wrtConfigTxn.submit());
                     return futures;
                 }
@@ -221,7 +247,6 @@ public class NeutronPortChangeListener extends AsyncDataTreeChangeListenerBase<P
             elanService.handleKnownL3DmacAddress(update.getMacAddress().getValue(), update.getNetworkId().getValue(),
                     NwConstants.ADD_FLOW);
         }
-        handlePortSecurityUpdated(original, update);
         // check for QoS updates
         QosPortExtension updateQos = update.getAugmentation(QosPortExtension.class);
         QosPortExtension originalQos = original.getAugmentation(QosPortExtension.class);
@@ -511,50 +536,38 @@ public class NeutronPortChangeListener extends AsyncDataTreeChangeListenerBase<P
                 });
     }
 
-    private void handlePortSecurityUpdated(Port portOriginal, Port portUpdated) {
-        Boolean origSecurityEnabled = NeutronvpnUtils.getPortSecurityEnabled(portOriginal);
-        Boolean updatedSecurityEnabled = NeutronvpnUtils.getPortSecurityEnabled(portUpdated);
+    private static InterfaceAclBuilder handlePortSecurityUpdated(Port portOriginal, Port portUpdated, boolean
+            origSecurityEnabled, boolean updatedSecurityEnabled, InterfaceBuilder interfaceBuilder) {
         String interfaceName = portUpdated.getUuid().getValue();
-        Interface portInterface = NeutronvpnUtils.getOfPortInterface(dataBroker, portUpdated);
-        if (portInterface != null) {
-            InterfaceAclBuilder interfaceAclBuilder = null;
-            if (origSecurityEnabled != updatedSecurityEnabled) {
-                interfaceAclBuilder = new InterfaceAclBuilder();
-                interfaceAclBuilder.setPortSecurityEnabled(updatedSecurityEnabled);
-                if (updatedSecurityEnabled) {
-                    // Handle security group enabled
-                    NeutronvpnUtils.populateInterfaceAclBuilder(interfaceAclBuilder, portUpdated);
-                } else {
-                    // Handle security group disabled
-                    interfaceAclBuilder.setSecurityGroups(Lists.newArrayList());
-                    interfaceAclBuilder.setAllowedAddressPairs(Lists.newArrayList());
-                }
+        InterfaceAclBuilder interfaceAclBuilder = null;
+        if (origSecurityEnabled != updatedSecurityEnabled) {
+            interfaceAclBuilder = new InterfaceAclBuilder();
+            interfaceAclBuilder.setPortSecurityEnabled(updatedSecurityEnabled);
+            if (updatedSecurityEnabled) {
+                // Handle security group enabled
+                NeutronvpnUtils.populateInterfaceAclBuilder(interfaceAclBuilder, portUpdated);
             } else {
-                if (updatedSecurityEnabled) {
-                    // handle SG add/delete delta
-                    InterfaceAcl interfaceAcl = portInterface.getAugmentation(InterfaceAcl.class);
-                    interfaceAclBuilder = new InterfaceAclBuilder(interfaceAcl);
-                    interfaceAclBuilder.setSecurityGroups(
-                            NeutronvpnUtils.getUpdatedSecurityGroups(interfaceAcl.getSecurityGroups(),
-                                    portOriginal.getSecurityGroups(), portUpdated.getSecurityGroups()));
-                    List<AllowedAddressPairs> updatedAddressPairs = NeutronvpnUtils.getUpdatedAllowedAddressPairs(
-                            interfaceAcl.getAllowedAddressPairs(), portOriginal.getAllowedAddressPairs(),
-                            portUpdated.getAllowedAddressPairs());
-                    interfaceAclBuilder.setAllowedAddressPairs(NeutronvpnUtils.getAllowedAddressPairsForFixedIps(
-                            updatedAddressPairs, portOriginal.getMacAddress(), portOriginal.getFixedIps(),
-                            portUpdated.getFixedIps()));
-                }
-            }
-
-            if (interfaceAclBuilder != null) {
-                InterfaceBuilder builder = new InterfaceBuilder(portInterface).addAugmentation(InterfaceAcl.class,
-                        interfaceAclBuilder.build());
-                InstanceIdentifier interfaceIdentifier = NeutronvpnUtils.buildVlanInterfaceIdentifier(interfaceName);
-                MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, interfaceIdentifier, builder.build());
+                // Handle security group disabled
+                interfaceAclBuilder.setSecurityGroups(Lists.newArrayList());
+                interfaceAclBuilder.setAllowedAddressPairs(Lists.newArrayList());
             }
         } else {
-            LOG.error("Interface {} is not present", interfaceName);
+            if (updatedSecurityEnabled) {
+                // handle SG add/delete delta
+                InterfaceAcl interfaceAcl = interfaceBuilder.getAugmentation(InterfaceAcl.class);
+                interfaceAclBuilder = new InterfaceAclBuilder(interfaceAcl);
+                interfaceAclBuilder.setSecurityGroups(
+                        NeutronvpnUtils.getUpdatedSecurityGroups(interfaceAcl.getSecurityGroups(),
+                                portOriginal.getSecurityGroups(), portUpdated.getSecurityGroups()));
+                List<AllowedAddressPairs> updatedAddressPairs = NeutronvpnUtils.getUpdatedAllowedAddressPairs(
+                        interfaceAcl.getAllowedAddressPairs(), portOriginal.getAllowedAddressPairs(),
+                        portUpdated.getAllowedAddressPairs());
+                interfaceAclBuilder.setAllowedAddressPairs(NeutronvpnUtils.getAllowedAddressPairsForFixedIps(
+                        updatedAddressPairs, portOriginal.getMacAddress(), portOriginal.getFixedIps(),
+                        portUpdated.getFixedIps()));
+            }
         }
+        return interfaceAclBuilder;
     }
 
     private String createOfPortInterface(Port port, WriteTransaction wrtConfigTxn) {
@@ -621,38 +634,12 @@ public class NeutronPortChangeListener extends AsyncDataTreeChangeListenerBase<P
         }
     }
 
-    private Interface updateInterface(Port original, Port update) {
+    private ParentRefsBuilder getParentRefsBuilder(Port update) {
         String parentRefName = NeutronvpnUtils.getVifPortName(update);
-        String interfaceName = original.getUuid().getValue();
-        InterfaceBuilder interfaceBuilder = new InterfaceBuilder();
-
-        if(parentRefName != null) {
-            ParentRefsBuilder parentRefsBuilder = new ParentRefsBuilder().setParentInterface(parentRefName);
-            interfaceBuilder.addAugmentation(ParentRefs.class, parentRefsBuilder.build());
+        if (parentRefName != null) {
+            return new ParentRefsBuilder().setParentInterface(parentRefName);
         }
-
-        interfaceBuilder.setName(interfaceName);
-        return interfaceBuilder.build();
-    }
-
-    private String updateOfPortInterface(Port original, Port updated, WriteTransaction wrtConfigTxn) {
-        Interface inf = updateInterface(original, updated);
-        String infName = inf.getName();
-
-        LOG.debug("Updating OFPort Interface {}", infName);
-        InstanceIdentifier interfaceIdentifier = NeutronvpnUtils.buildVlanInterfaceIdentifier(infName);
-        try {
-            Optional<Interface> optionalInf = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
-                    interfaceIdentifier);
-            if (optionalInf.isPresent()) {
-                wrtConfigTxn.merge(LogicalDatastoreType.CONFIGURATION, interfaceIdentifier, inf);
-            } else {
-                LOG.error("Interface {} doesn't exist", infName);
-            }
-        } catch (Exception e) {
-            LOG.error("failed to update interface {} due to the exception {} ", infName, e.getMessage());
-        }
-        return infName;
+        return null;
     }
 
     private void createElanInterface(Port port, String name, WriteTransaction wrtConfigTxn) {
index 6761c27d4a9e6f5f45018d7bebab121f60bde35d..f58f8f9637c1b1c17e5cd7fa95571226b80d4ae8 100644 (file)
@@ -647,7 +647,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             LOG.error("Creation of vpninterface {} failed due to {}", infName, ex);
         }
         if (routerId != null) {
-            addToNeutronRouterInterfacesMap(routerId, infName, wrtConfigTxn);
+            addToNeutronRouterInterfacesMap(routerId, infName);
         }
         if (!wrtConfigTxnPresent) {
             wrtConfigTxn.submit();
@@ -675,7 +675,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             LOG.error("Deletion of vpninterface {} failed due to {}", infName, ex);
         }
         if (routerId != null) {
-            removeFromNeutronRouterInterfacesMap(routerId, infName, wrtConfigTxn);
+            removeFromNeutronRouterInterfacesMap(routerId, infName);
         }
         if (!wrtConfigTxnPresent) {
             wrtConfigTxn.submit();
@@ -1194,59 +1194,46 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 .child(RouterInterfaces.class, new RouterInterfacesKey(routerId)).build();
     }
 
-    protected void addToNeutronRouterInterfacesMap(Uuid routerId, String interfaceName, WriteTransaction wrtConfigTxn) {
-        Boolean wrtConfigTxnPresent = true;
-        if (wrtConfigTxn == null) {
-            wrtConfigTxnPresent = false;
-            wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
-        }
-        InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
-        Optional<RouterInterfaces> optRouterInterfaces = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType
-                .CONFIGURATION, routerInterfacesId);
-        Interfaces routerInterface = new InterfacesBuilder().setKey(new InterfacesKey(interfaceName)).setInterfaceId
-                (interfaceName).build();
-        if (optRouterInterfaces.isPresent()) {
-            wrtConfigTxn.put(LogicalDatastoreType.CONFIGURATION, routerInterfacesId.child(Interfaces
-                    .class, new InterfacesKey(interfaceName)), routerInterface);
-        } else {
-            RouterInterfacesBuilder builder = new RouterInterfacesBuilder().setRouterId(routerId);
-            List<Interfaces> interfaces = new ArrayList<>();
-            interfaces.add(routerInterface);
-            wrtConfigTxn.put(LogicalDatastoreType.CONFIGURATION, routerInterfacesId, builder
-                    .setInterfaces(interfaces).build());
-        }
-        if (!wrtConfigTxnPresent) {
-            wrtConfigTxn.submit();
+    protected void addToNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
+        synchronized (routerId.getValue().intern()) {
+            InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
+            Optional<RouterInterfaces> optRouterInterfaces = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType
+                    .CONFIGURATION, routerInterfacesId);
+            Interfaces routerInterface = new InterfacesBuilder().setKey(new InterfacesKey(interfaceName)).setInterfaceId
+                    (interfaceName).build();
+            if (optRouterInterfaces.isPresent()) {
+                MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, routerInterfacesId.child(Interfaces
+                        .class, new InterfacesKey(interfaceName)), routerInterface);
+            } else {
+                RouterInterfacesBuilder builder = new RouterInterfacesBuilder().setRouterId(routerId);
+                List<Interfaces> interfaces = new ArrayList<>();
+                interfaces.add(routerInterface);
+                MDSALUtil.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, routerInterfacesId.child(Interfaces
+                        .class, new InterfacesKey(interfaceName)), routerInterface);
+            }
         }
     }
 
-    protected void removeFromNeutronRouterInterfacesMap(Uuid routerId, String interfaceName, WriteTransaction
-            wrtConfigTxn) {
-        Boolean wrtConfigTxnPresent = true;
-        if (wrtConfigTxn == null) {
-            wrtConfigTxnPresent = false;
-            wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
-        }
-        InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
-        Optional<RouterInterfaces> optRouterInterfaces = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType
-                .CONFIGURATION, routerInterfacesId);
-        Interfaces routerInterface = new InterfacesBuilder().setKey(new InterfacesKey(interfaceName)).setInterfaceId
-                (interfaceName).build();
-        if (optRouterInterfaces.isPresent()) {
-            RouterInterfaces routerInterfaces = optRouterInterfaces.get();
-            List<Interfaces> interfaces = routerInterfaces.getInterfaces();
-            if (interfaces != null && interfaces.remove(routerInterface)) {
-                if (interfaces.isEmpty()) {
-                    wrtConfigTxn.delete(LogicalDatastoreType.CONFIGURATION, routerInterfacesId);
-                } else {
-                    wrtConfigTxn.delete(LogicalDatastoreType.CONFIGURATION,
-                            routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)));
+    protected void removeFromNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
+        synchronized (routerId.getValue().intern()) {
+            InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
+            Optional<RouterInterfaces> optRouterInterfaces = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType
+                    .CONFIGURATION, routerInterfacesId);
+            Interfaces routerInterface = new InterfacesBuilder().setKey(new InterfacesKey(interfaceName)).setInterfaceId
+                    (interfaceName).build();
+            if (optRouterInterfaces.isPresent()) {
+                RouterInterfaces routerInterfaces = optRouterInterfaces.get();
+                List<Interfaces> interfaces = routerInterfaces.getInterfaces();
+                if (interfaces != null && interfaces.remove(routerInterface)) {
+                    if (interfaces.isEmpty()) {
+                        MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, routerInterfacesId);
+                    } else {
+                        MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
+                                routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)));
+                    }
                 }
             }
         }
-        if (!wrtConfigTxnPresent) {
-            wrtConfigTxn.submit();
-        }
     }
 
     /**
index 962ad7268795f2d626d25b84bfd6672280a87b1f..539a0071e58c66b3d1a2106929a70e1f03df2447 100644 (file)
@@ -605,23 +605,6 @@ public class NeutronvpnUtils {
         interfaceAclBuilder.setAllowedAddressPairs(aclAllowedAddressPairs);
     }
 
-    protected static Interface getOfPortInterface(DataBroker broker, Port port) {
-        String name = port.getUuid().getValue();
-        InstanceIdentifier interfaceIdentifier = NeutronvpnUtils.buildVlanInterfaceIdentifier(name);
-        try {
-            Optional<Interface> optionalInf = NeutronvpnUtils.read(broker, LogicalDatastoreType.CONFIGURATION,
-                    interfaceIdentifier);
-            if (optionalInf.isPresent()) {
-                return optionalInf.get();
-            } else {
-                logger.error("Interface {} is not present", name);
-            }
-        } catch (Exception e) {
-            logger.error("Failed to get interface {} due to the exception {}", name, e.getMessage());
-        }
-        return null;
-    }
-
     protected static Subnet getNeutronSubnet(DataBroker broker, Uuid subnetId) {
         Subnet subnet = null;
         subnet = subnetMap.get(subnetId);
@@ -694,50 +677,54 @@ public class NeutronvpnUtils {
     }
 
     protected static boolean lock(String lockName) {
-            if (locks.get(lockName) != null) {
-                synchronized(locks) {
-                    if (locks.get(lockName) != null) {
-                        locks.get(lockName).getRight().incrementAndGet();
-                    } else {
-                        locks.putIfAbsent(lockName, new ImmutablePair<ReadWriteLock, AtomicInteger>(
-                            new ReentrantReadWriteLock(), new AtomicInteger(0)));
-                    }
+        if (locks.get(lockName) != null) {
+            synchronized (locks) {
+                if (locks.get(lockName) == null) {
+                    locks.putIfAbsent(lockName, new ImmutablePair<ReadWriteLock, AtomicInteger>(new
+                            ReentrantReadWriteLock(), new AtomicInteger(0)));
                 }
-                try {
-                    locks.get(lockName).getLeft().writeLock().tryLock(LOCK_WAIT_TIME, secUnit);
-                } catch (InterruptedException e) {
-                    locks.get(lockName).getRight().decrementAndGet();
-                    logger.error("Unable to acquire lock for  {}", lockName);
-                    throw new RuntimeException(String.format("Unable to acquire lock for %s", lockName), e.getCause());
-                }
-            } else {
-                locks.putIfAbsent(lockName, new ImmutablePair<ReadWriteLock, AtomicInteger>(new ReentrantReadWriteLock(), new AtomicInteger(0)));
                 locks.get(lockName).getRight().incrementAndGet();
-                try {
+            }
+            try {
+                if (locks.get(lockName) != null) {
                     locks.get(lockName).getLeft().writeLock().tryLock(LOCK_WAIT_TIME, secUnit);
-                } catch (Exception e) {
-                    locks.get(lockName).getRight().decrementAndGet();
-                    logger.error("Unable to acquire lock for  {}", lockName);
-                    throw new RuntimeException(String.format("Unable to acquire lock for %s", lockName), e.getCause());
                 }
+            } catch (InterruptedException e) {
+                locks.get(lockName).getRight().decrementAndGet();
+                logger.error("Unable to acquire lock for  {}", lockName);
+                throw new RuntimeException(String.format("Unable to acquire lock for %s", lockName), e.getCause());
+            }
+        } else {
+            locks.putIfAbsent(lockName, new ImmutablePair<ReadWriteLock, AtomicInteger>(new ReentrantReadWriteLock(),
+                    new AtomicInteger(0)));
+            locks.get(lockName).getRight().incrementAndGet();
+            try {
+                locks.get(lockName).getLeft().writeLock().tryLock(LOCK_WAIT_TIME, secUnit);
+            } catch (Exception e) {
+                locks.get(lockName).getRight().decrementAndGet();
+                logger.error("Unable to acquire lock for  {}", lockName);
+                throw new RuntimeException(String.format("Unable to acquire lock for %s", lockName), e.getCause());
             }
+        }
         return true;
     }
 
     protected static boolean unlock(String lockName) {
-            if (locks.get(lockName) != null) {
-                try {
-                    locks.get(lockName).getLeft().writeLock().unlock();
-                } catch (Exception e) {
-                    logger.error("Unable to un-lock ", e);
-                    return false;
-                }
-                if (0 == locks.get(lockName).getRight().decrementAndGet()) {
-                    synchronized(locks) {
+        if (locks.get(lockName) != null) {
+            try {
+                locks.get(lockName).getLeft().writeLock().unlock();
+            } catch (Exception e) {
+                logger.error("Unable to un-lock for " + lockName, e);
+                return false;
+            }
+            if (0 == locks.get(lockName).getRight().decrementAndGet()) {
+                synchronized (locks) {
+                    if (locks.get(lockName).getRight().get() == 0) {
                         locks.remove(lockName);
                     }
                 }
             }
+        }
         return true;
     }