MRI version bumpup for Aluminium
[netvirt.git] / aclservice / impl / src / main / java / org / opendaylight / netvirt / aclservice / listeners / AclEventListener.java
index f97fa81a4716caae9f3f48394ad99d457fd8da9c..c8a40472855f2b88ac730daddc2ba4b3bb6d2a4d 100644 (file)
@@ -8,22 +8,24 @@
 package org.opendaylight.netvirt.aclservice.listeners;
 
 import com.google.common.collect.ImmutableSet;
+import java.math.BigInteger;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Objects;
 import java.util.Set;
 import java.util.SortedSet;
-import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
 import javax.inject.Inject;
 import javax.inject.Singleton;
-import org.opendaylight.controller.md.sal.binding.api.ClusteredDataTreeChangeListener;
-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.srm.RecoverableListener;
-import org.opendaylight.genius.srm.ServiceRecoveryRegistry;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.infrautils.utils.concurrent.Executors;
+import org.opendaylight.mdsal.binding.api.ClusteredDataTreeChangeListener;
+import org.opendaylight.mdsal.binding.api.DataBroker;
+import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
 import org.opendaylight.netvirt.aclservice.api.AclInterfaceCache;
 import org.opendaylight.netvirt.aclservice.api.AclServiceManager;
 import org.opendaylight.netvirt.aclservice.api.utils.AclInterface;
@@ -31,6 +33,9 @@ import org.opendaylight.netvirt.aclservice.utils.AclClusterUtil;
 import org.opendaylight.netvirt.aclservice.utils.AclConstants;
 import org.opendaylight.netvirt.aclservice.utils.AclDataUtil;
 import org.opendaylight.netvirt.aclservice.utils.AclServiceUtils;
+import org.opendaylight.serviceutils.srm.RecoverableListener;
+import org.opendaylight.serviceutils.srm.ServiceRecoveryRegistry;
+import org.opendaylight.serviceutils.tools.listener.AbstractAsyncDataTreeChangeListener;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.AccessLists;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.Acl;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.Ace;
@@ -44,7 +49,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 @Singleton
-public class AclEventListener extends AsyncDataTreeChangeListenerBase<Acl, AclEventListener> implements
+public class AclEventListener extends AbstractAsyncDataTreeChangeListener<Acl> implements
         ClusteredDataTreeChangeListener<Acl>, RecoverableListener {
 
     private static final Logger LOG = LoggerFactory.getLogger(AclEventListener.class);
@@ -60,7 +65,9 @@ public class AclEventListener extends AsyncDataTreeChangeListenerBase<Acl, AclEv
     public AclEventListener(AclServiceManager aclServiceManager, AclClusterUtil aclClusterUtil, DataBroker dataBroker,
             AclDataUtil aclDataUtil, AclServiceUtils aclServicUtils, AclInterfaceCache aclInterfaceCache,
             ServiceRecoveryRegistry serviceRecoveryRegistry) {
-        super(Acl.class, AclEventListener.class);
+        super(dataBroker, LogicalDatastoreType.CONFIGURATION,
+                InstanceIdentifier.create(AccessLists.class).child(Acl.class),
+                Executors.newListeningSingleThreadExecutor("AclEventListener", LOG));
         this.aclServiceManager = aclServiceManager;
         this.aclClusterUtil = aclClusterUtil;
         this.dataBroker = dataBroker;
@@ -70,48 +77,44 @@ public class AclEventListener extends AsyncDataTreeChangeListenerBase<Acl, AclEv
         serviceRecoveryRegistry.addRecoverableListener(AclServiceUtils.getRecoverServiceRegistryKey(), this);
     }
 
-    @Override
-    @PostConstruct
     public void init() {
         LOG.info("{} start", getClass().getSimpleName());
-        registerListener();
     }
 
     @Override
     public void registerListener() {
-        registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
+        super.register();
     }
 
     @Override
-    protected InstanceIdentifier<Acl> getWildCardPath() {
-        return InstanceIdentifier.create(AccessLists.class).child(Acl.class);
+    public void deregisterListener() {
+        super.close();
     }
 
     @Override
-    protected void remove(InstanceIdentifier<Acl> key, Acl acl) {
-        String aclName = acl.getAclName();
-        if (!AclServiceUtils.isOfAclInterest(acl)) {
-            LOG.trace("{} does not have SecurityRuleAttr augmentation", aclName);
-            return;
-        }
-
+    public void remove(InstanceIdentifier<Acl> key, Acl acl) {
         LOG.trace("On remove event, remove ACL: {}", acl);
+        String aclName = acl.getAclName();
         this.aclDataUtil.removeAcl(aclName);
         Integer aclTag = this.aclDataUtil.getAclTag(aclName);
         if (aclTag != null) {
             this.aclDataUtil.removeAclTag(aclName);
-            this.aclServiceUtils.releaseAclTag(aclName);
         }
-        updateRemoteAclCache(acl.getAccessListEntries().getAce(), aclName, AclServiceManager.Action.REMOVE);
+
+        updateRemoteAclCache(AclServiceUtils.getAceListFromAcl(acl), aclName, AclServiceManager.Action.REMOVE);
+        if (aclClusterUtil.isEntityOwner()) {
+            // Handle Rule deletion If SG Remove event is received before SG Rule delete event
+            List<Ace> aceList = AclServiceUtils.aceList(acl);
+            if (!aceList.isEmpty()) {
+                Collection<AclInterface> aclInterfaces =
+                        ImmutableSet.copyOf(aclDataUtil.getInterfaceList(new Uuid(aclName)));
+                updateAceRules(aclInterfaces, aclName, aceList, AclServiceManager.Action.REMOVE);
+            }
+        }
     }
 
     @Override
-    protected void update(InstanceIdentifier<Acl> key, Acl aclBefore, Acl aclAfter) {
-        if (!AclServiceUtils.isOfAclInterest(aclAfter) && !AclServiceUtils.isOfAclInterest(aclBefore)) {
-            LOG.trace("before {} and after {} does not have SecurityRuleAttr augmentation",
-                    aclBefore.getAclName(), aclAfter.getAclName());
-            return;
-        }
+    public void update(InstanceIdentifier<Acl> key, Acl aclBefore, Acl aclAfter) {
         String aclName = aclAfter.getAclName();
         Collection<AclInterface> interfacesBefore =
                 ImmutableSet.copyOf(aclDataUtil.getInterfaceList(new Uuid(aclName)));
@@ -119,15 +122,18 @@ public class AclEventListener extends AsyncDataTreeChangeListenerBase<Acl, AclEv
         List<Ace> addedAceRules = getChangedAceList(aclAfter, aclBefore);
 
         // Find and update deleted ace rules in acl
-        List<Ace> deletedAceRules = getChangedAceList(aclBefore, aclAfter);
+        List<Ace> deletedAceRules = getDeletedAceList(aclAfter);
 
-        if (interfacesBefore != null && aclClusterUtil.isEntityOwner()) {
+        if (aclClusterUtil.isEntityOwner()) {
             LOG.debug("On update event, remove Ace rules: {} for ACL: {}", deletedAceRules, aclName);
             updateAceRules(interfacesBefore, aclName, deletedAceRules, AclServiceManager.Action.REMOVE);
+            if (!deletedAceRules.isEmpty()) {
+                aclServiceUtils.deleteAcesFromConfigDS(aclName, deletedAceRules);
+            }
         }
         updateAclCaches(aclBefore, aclAfter, interfacesBefore);
 
-        if (interfacesBefore != null && aclClusterUtil.isEntityOwner()) {
+        if (aclClusterUtil.isEntityOwner()) {
             LOG.debug("On update event, add Ace rules: {} for ACL: {}", addedAceRules, aclName);
             updateAceRules(interfacesBefore, aclName, addedAceRules, AclServiceManager.Action.ADD);
 
@@ -137,33 +143,33 @@ public class AclEventListener extends AsyncDataTreeChangeListenerBase<Acl, AclEv
 
     private void updateAceRules(Collection<AclInterface> interfaceList, String aclName, List<Ace> aceList,
             AclServiceManager.Action action) {
-        if (null != aceList && !aceList.isEmpty()) {
-            LOG.trace("update ace rules - action: {} , ace rules: {}", action.name(), aceList);
-            for (AclInterface port : interfaceList) {
+        LOG.trace("update ace rules - action: {} , ace rules: {}", action.name(), aceList);
+        for (AclInterface port : interfaceList) {
+            BigInteger dpId = port.getDpId();
+            Long elanId = port.getElanId();
+            if (dpId != null && elanId != null) {
                 for (Ace aceRule : aceList) {
                     aclServiceManager.notifyAce(port, action, aclName, aceRule);
                 }
+            } else {
+                LOG.debug("Skip update ACE rules as DP ID or ELAN ID for interface {} is not present. "
+                        + "DP Id: {} ELAN ID: {}", port.getInterfaceId(), dpId, elanId);
             }
         }
     }
 
     @Override
-    protected void add(InstanceIdentifier<Acl> key, Acl acl) {
-        String aclName = acl.getAclName();
-        if (!AclServiceUtils.isOfAclInterest(acl)) {
-            LOG.trace("{} does not have SecurityRuleAttr augmentation", aclName);
-            return;
-        }
-
+    public void add(InstanceIdentifier<Acl> key, Acl acl) {
         LOG.trace("On add event, add ACL: {}", acl);
         this.aclDataUtil.addAcl(acl);
 
-        Integer aclTag = this.aclServiceUtils.allocateAclTag(aclName);
+        String aclName = acl.getAclName();
+        Integer aclTag = AclServiceUtils.getAclTag(acl);
         if (aclTag != null && aclTag != AclConstants.INVALID_ACL_TAG) {
             this.aclDataUtil.addAclTag(aclName, aclTag);
         }
 
-        updateRemoteAclCache(acl.getAccessListEntries().getAce(), aclName, AclServiceManager.Action.ADD);
+        updateRemoteAclCache(AclServiceUtils.getAceListFromAcl(acl), aclName, AclServiceManager.Action.ADD);
     }
 
     /**
@@ -173,10 +179,7 @@ public class AclEventListener extends AsyncDataTreeChangeListenerBase<Acl, AclEv
      * @param aclName the acl name
      * @param action the action
      */
-    private void updateRemoteAclCache(List<Ace> aceList, String aclName, AclServiceManager.Action action) {
-        if (null == aceList) {
-            return;
-        }
+    private void updateRemoteAclCache(@NonNull List<Ace> aceList, String aclName, AclServiceManager.Action action) {
         for (Ace ace : aceList) {
             SecurityRuleAttr aceAttributes = ace.augmentation(SecurityRuleAttr.class);
             if (AclServiceUtils.doesAceHaveRemoteGroupId(aceAttributes)) {
@@ -195,7 +198,7 @@ public class AclEventListener extends AsyncDataTreeChangeListenerBase<Acl, AclEv
         String aclName = aclAfter.getAclName();
         Integer aclTag = this.aclDataUtil.getAclTag(aclName);
         if (aclTag == null) {
-            aclTag = this.aclServiceUtils.allocateAclTag(aclName);
+            aclTag = AclServiceUtils.getAclTag(aclAfter);
             if (aclTag != null && aclTag != AclConstants.INVALID_ACL_TAG) {
                 this.aclDataUtil.addAclTag(aclName, aclTag);
             }
@@ -228,48 +231,62 @@ public class AclEventListener extends AsyncDataTreeChangeListenerBase<Acl, AclEv
             return;
         }
 
-        if (aclInterfaces != null) {
-            for (AclInterface aclInterface : aclInterfaces) {
-                AclInterface aclInterfaceInCache =
-                        aclInterfaceCache.addOrUpdate(aclInterface.getInterfaceId(), (prevAclInterface, builder) -> {
-                            SortedSet<Integer> remoteAclTags =
-                                    aclServiceUtils.getRemoteAclTags(aclInterface.getSecurityGroups(), direction);
-                            if (DirectionEgress.class.equals(direction)) {
-                                builder.egressRemoteAclTags(remoteAclTags);
-                            } else {
-                                builder.ingressRemoteAclTags(remoteAclTags);
-                            }
-                        });
-
-                aclDataUtil.addOrUpdateAclInterfaceMap(aclInterface.getSecurityGroups(), aclInterfaceInCache);
-            }
-        }
-    }
+        for (AclInterface aclInterface : aclInterfaces) {
+            AclInterface aclInterfaceInCache =
+                    aclInterfaceCache.addOrUpdate(aclInterface.getInterfaceId(), (prevAclInterface, builder) -> {
+                        SortedSet<Integer> remoteAclTags =
+                                aclServiceUtils.getRemoteAclTags(aclInterface.getSecurityGroups(), direction);
+                        if (DirectionEgress.class.equals(direction)) {
+                            builder.egressRemoteAclTags(remoteAclTags);
+                        } else {
+                            builder.ingressRemoteAclTags(remoteAclTags);
+                        }
+                    });
 
-    @Override
-    protected AclEventListener getDataTreeChangeListener() {
-        return this;
+            aclDataUtil.addOrUpdateAclInterfaceMap(aclInterface.getSecurityGroups(), aclInterfaceInCache);
+        }
     }
 
-    private List<Ace> getChangedAceList(Acl updatedAcl, Acl currentAcl) {
+    private static @NonNull List<Ace> getChangedAceList(Acl updatedAcl, Acl currentAcl) {
         if (updatedAcl == null) {
-            return null;
+            return Collections.emptyList();
         }
-        List<Ace> updatedAceList = updatedAcl.getAccessListEntries() == null ? new ArrayList<>()
-                : new ArrayList<>(updatedAcl.getAccessListEntries().getAce());
+        List<Ace> updatedAceList = AclServiceUtils.aceList(updatedAcl);
         if (currentAcl == null) {
             return updatedAceList;
         }
-        List<Ace> currentAceList = currentAcl.getAccessListEntries() == null ? new ArrayList<>()
-                : new ArrayList<>(currentAcl.getAccessListEntries().getAce());
+
+        List<Ace> currentAceList = AclServiceUtils.aceList(currentAcl);
+        updatedAceList = new ArrayList<>(updatedAceList);
         for (Iterator<Ace> iterator = updatedAceList.iterator(); iterator.hasNext();) {
             Ace ace1 = iterator.next();
             for (Ace ace2 : currentAceList) {
-                if (ace1.getRuleName().equals(ace2.getRuleName())) {
+                if (Objects.equals(ace1.getRuleName(), ace2.getRuleName())) {
                     iterator.remove();
                 }
             }
         }
         return updatedAceList;
     }
+
+    private List<Ace> getDeletedAceList(Acl acl) {
+        if (acl == null || acl.getAccessListEntries() == null || acl.getAccessListEntries().getAce() == null) {
+            return Collections.emptyList();
+        }
+        List<Ace> aceList = acl.getAccessListEntries().getAce();
+        List<Ace> deletedAceList = new ArrayList<>();
+        for (Ace ace: aceList) {
+            if (ace.augmentation(SecurityRuleAttr.class).isDeleted()) {
+                deletedAceList.add(ace);
+            }
+        }
+        return deletedAceList;
+    }
+
+    @Override
+    @PreDestroy
+    public void close() {
+        super.close();
+        Executors.shutdownAndAwaitTermination(getExecutorService());
+    }
 }