Convert DataChangeListeners to DataTreeChangeListeners
[groupbasedpolicy.git] / renderers / faas / src / main / java / org / opendaylight / groupbasedpolicy / renderer / faas / FaasPolicyManager.java
index 3c2e86189307658fa4001373e3db237ab869a5da..9ac9d8a86a46057f3915193cafdb3edf1acaf759 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2015 Huawei Technologies 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
@@ -9,7 +9,10 @@ package org.opendaylight.groupbasedpolicy.renderer.faas;
 
 import static com.google.common.base.Preconditions.checkNotNull;
 
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Optional;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -17,16 +20,15 @@ import java.util.Map;
 import java.util.Set;
 import java.util.UUID;
 import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ScheduledExecutorService;
-
+import java.util.concurrent.Executor;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.faas.uln.datastore.api.Pair;
 import org.opendaylight.faas.uln.datastore.api.UlnDatastoreApi;
@@ -77,30 +79,28 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.p
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.resolved.policies.resolved.policy.PolicyRuleGroupWithEndpointConstraints;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.resolved.policies.resolved.policy.policy.rule.group.with.endpoint.constraints.PolicyRuleGroup;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Optional;
-
-public class FaasPolicyManager implements DataChangeListener, AutoCloseable {
+public class FaasPolicyManager implements DataTreeChangeListener<ResolvedPolicy>, AutoCloseable {
 
     private static final Logger LOG = LoggerFactory.getLogger(FaasPolicyManager.class);
     private static final RendererName rendererName = new RendererName("faas");
-    private final ListenerRegistration<DataChangeListener> registerListener;
-    private final ScheduledExecutorService executor;
+    private final ListenerRegistration<?> registerListener;
+    private final Executor executor;
     private final DataBroker dataProvider;
-    protected final Map<Pair<EndpointGroupId, TenantId>, List<SubnetId>> epgSubnetsMap = new HashMap<>();
+    final Map<Pair<EndpointGroupId, TenantId>, List<SubnetId>> epgSubnetsMap = new HashMap<>();
     private final ConcurrentHashMap<TenantId, Uuid> mappedTenants = new ConcurrentHashMap<>();
-    protected final ConcurrentHashMap<TenantId, ArrayList<ListenerRegistration<DataChangeListener>>> registeredTenants = new ConcurrentHashMap<TenantId, ArrayList<ListenerRegistration<DataChangeListener>>>();
+    final ConcurrentHashMap<TenantId, ArrayList<ListenerRegistration<?>>> registeredTenants =
+            new ConcurrentHashMap<>();
 
-    public FaasPolicyManager(DataBroker dataBroker, ScheduledExecutorService executor) {
+    public FaasPolicyManager(DataBroker dataBroker, Executor executor) {
         this.dataProvider = dataBroker;
         this.executor = executor;
-        this.registerListener = checkNotNull(dataProvider).registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
-                InstanceIdentifier.builder(ResolvedPolicies.class).child(ResolvedPolicy.class).build(), this,
-                AsyncDataBroker.DataChangeScope.SUBTREE);
+        this.registerListener = checkNotNull(dataProvider).registerDataTreeChangeListener(new DataTreeIdentifier<>(
+                LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.builder(ResolvedPolicies.class)
+                    .child(ResolvedPolicy.class).build()), this);
 
         RendererBuilder rendBuilder = new RendererBuilder();
         rendBuilder.setName(rendererName);
@@ -116,66 +116,48 @@ public class FaasPolicyManager implements DataChangeListener, AutoCloseable {
     @Override
     public void close() throws Exception {
         synchronized (registeredTenants) {
-            for (ArrayList<ListenerRegistration<DataChangeListener>> list : registeredTenants.values()) {
-                for (ListenerRegistration<DataChangeListener> reg : list) {
-                    reg.close();
-                }
+            for (ArrayList<ListenerRegistration<?>> list : registeredTenants.values()) {
+                list.forEach(ListenerRegistration::close);
             }
             registeredTenants.clear();
 
             LOG.debug("Closed All Tenant Registerations");
         }
-        if (registerListener != null)
+        if (registerListener != null) {
             registerListener.close();
+        }
     }
 
     @Override
-    public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
-        executor.execute(new Runnable() {
-
-            public void run() {
-                executeEvent(change);
-            }
-        });
+    public void onDataTreeChanged(Collection<DataTreeModification<ResolvedPolicy>> changes) {
+        executor.execute(() -> executeEvent(changes));
     }
 
-    private void executeEvent(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
-        // Create
-        for (DataObject dao : change.getCreatedData().values()) {
-            if (dao instanceof ResolvedPolicy) {
-                ResolvedPolicy newPolicy = (ResolvedPolicy) dao;
-                if (handledPolicy(newPolicy)) {
-                    LOG.debug("Created Policy: Consumer EPG {}, Provider EPG {}", newPolicy.getConsumerEpgId(),
-                            newPolicy.getProviderEpgId());
-                    updateLogicalNetwork(newPolicy);
-                }
-            }
-        }
-        // Update
-        Map<InstanceIdentifier<?>, DataObject> d = change.getUpdatedData();
-        for (Map.Entry<InstanceIdentifier<?>, DataObject> entry : d.entrySet()) {
-            if (entry.getValue() instanceof ResolvedPolicy) {
-                ResolvedPolicy newPolicy = (ResolvedPolicy) entry.getValue();
-                ResolvedPolicy oldPolicy = (ResolvedPolicy) change.getOriginalData().get(entry.getKey());
-                if (!isEqualService(newPolicy, oldPolicy)) {
-                    removeLogicalNetwork(oldPolicy);
-                }
-                if (handledPolicy(newPolicy)) {
-                    LOG.debug("Updated Policy: Consumer EPG {}, Provider EPG {}", newPolicy.getConsumerEpgId(),
-                            newPolicy.getProviderEpgId());
-                    updateLogicalNetwork(newPolicy);
-                }
-            }
-        }
+    private void executeEvent(final Collection<DataTreeModification<ResolvedPolicy>> changes) {
+        for (DataTreeModification<ResolvedPolicy> change: changes) {
+            DataObjectModification<ResolvedPolicy> rootNode = change.getRootNode();
+            ResolvedPolicy oldPolicy = rootNode.getDataBefore();
+            switch (rootNode.getModificationType()) {
+                case SUBTREE_MODIFIED:
+                case WRITE:
+                    ResolvedPolicy newPolicy = rootNode.getDataAfter();
+                    if (!isEqualService(newPolicy, oldPolicy)) {
+                        removeLogicalNetwork(oldPolicy);
+                    }
 
-        // Remove
-        for (InstanceIdentifier<?> iid : change.getRemovedPaths()) {
-            DataObject old = change.getOriginalData().get(iid);
-            if (old != null && old instanceof ResolvedPolicy) {
-                ResolvedPolicy oldPolicy = (ResolvedPolicy) old;
-                LOG.debug("Removed Policy: Consumer EPG {}, Provider EPG {}", oldPolicy.getConsumerEpgId(),
-                        oldPolicy.getProviderEpgId());
-                removeLogicalNetwork(oldPolicy);
+                    if (handledPolicy(newPolicy)) {
+                        LOG.debug("Updated Policy: Consumer EPG {}, Provider EPG {}", newPolicy.getConsumerEpgId(),
+                                newPolicy.getProviderEpgId());
+                        updateLogicalNetwork(newPolicy);
+                    }
+                    break;
+                case DELETE:
+                    LOG.debug("Removed Policy: Consumer EPG {}, Provider EPG {}", oldPolicy.getConsumerEpgId(),
+                            oldPolicy.getProviderEpgId());
+                    removeLogicalNetwork(oldPolicy);
+                    break;
+                default:
+                    break;
             }
         }
     }
@@ -250,21 +232,23 @@ public class FaasPolicyManager implements DataChangeListener, AutoCloseable {
             /*
              * tenant registrations
              */
-            ArrayList<ListenerRegistration<DataChangeListener>> list = new ArrayList<ListenerRegistration<DataChangeListener>>();
-            ListenerRegistration<DataChangeListener> reg;
+            ArrayList<ListenerRegistration<?>> list = new ArrayList<>();
+            ListenerRegistration<?> reg;
             // contracts
-            reg = dataProvider.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
-                    IidFactory.contractWildcardIid(gbpTenantId), faasContractManagerListener, DataChangeScope.SUBTREE);
+            reg = dataProvider.registerDataTreeChangeListener(new DataTreeIdentifier<>(
+                    LogicalDatastoreType.CONFIGURATION, IidFactory.contractWildcardIid(gbpTenantId)),
+                    faasContractManagerListener);
             list.add(reg);
             // subnets
-            reg = dataProvider.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
-                    IidFactory.subnetWildcardIid(gbpTenantId), faasSubnetManagerListener, DataChangeScope.SUBTREE);
+            reg = dataProvider.registerDataTreeChangeListener(new DataTreeIdentifier<>(
+                    LogicalDatastoreType.CONFIGURATION, IidFactory.subnetWildcardIid(gbpTenantId)),
+                    faasSubnetManagerListener);
             list.add(reg);
 
             // tenant
-            reg = dataProvider.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
-                    IidFactory.tenantIid(gbpTenantId), new FaasTenantManagerListener(this, gbpTenantId, faasTenantId,
-                            executor), DataChangeScope.BASE);
+            reg = dataProvider.registerDataTreeChangeListener(new DataTreeIdentifier<>(
+                    LogicalDatastoreType.CONFIGURATION, IidFactory.tenantIid(gbpTenantId)),
+                    new FaasTenantManagerListener(this, gbpTenantId, faasTenantId, executor));
             list.add(reg);
 
             // Map previously resolved policy for this tenant
@@ -286,6 +270,7 @@ public class FaasPolicyManager implements DataChangeListener, AutoCloseable {
         if (!resolvedPoliciesOptional.isPresent() || resolvedPoliciesOptional.get().getResolvedPolicy() == null) {
             return;
         }
+        //TODO forEach possible?
         List<ResolvedPolicy> resolvedPolicies = resolvedPoliciesOptional.get().getResolvedPolicy();
         for (ResolvedPolicy policy : resolvedPolicies) {
             if (policy.getConsumerTenantId().equals(gbpTenantId)) {
@@ -316,7 +301,8 @@ public class FaasPolicyManager implements DataChangeListener, AutoCloseable {
         }
     }
 
-    private void registerFollowedEndpointgroup(TenantId gbpTenantId, EndpointGroupId epgId) {
+    @VisibleForTesting
+    void registerFollowedEndpointgroup(TenantId gbpTenantId, EndpointGroupId epgId) {
         if (epgId == null) {
             return;
         }
@@ -339,7 +325,7 @@ public class FaasPolicyManager implements DataChangeListener, AutoCloseable {
         if (val != null) {
             return val;
         }
-        Uuid faasTenantId = null;
+        Uuid faasTenantId;
         if (isUUid(tenantId.getValue())) {
             faasTenantId = new Uuid(tenantId.getValue());
         } else {
@@ -362,15 +348,17 @@ public class FaasPolicyManager implements DataChangeListener, AutoCloseable {
     }
 
     public static boolean isUUid(String value) {
-        return (value != null && value.matches("[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}"));
+        return value != null && value.matches("[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}");
     }
 
     public void unregisterTenant(TenantId tenantId) {
 
-        ArrayList<ListenerRegistration<DataChangeListener>> list = registeredTenants.remove(tenantId);
+        ArrayList<ListenerRegistration<?>> list = registeredTenants.remove(tenantId);
         if (list != null) {
-            for (ListenerRegistration<DataChangeListener> reg : list) {
-                reg.close();
+            for (ListenerRegistration<?> reg : list) {
+                if (reg != null) {
+                    reg.close();
+                }
             }
             LOG.debug("Unregistered tenant {}", tenantId);
         }
@@ -385,7 +373,8 @@ public class FaasPolicyManager implements DataChangeListener, AutoCloseable {
         return registeredTenants.containsKey(tenantId);
     }
 
-    private boolean handledPolicy(ResolvedPolicy policy) {
+    @VisibleForTesting
+    boolean handledPolicy(ResolvedPolicy policy) {
         if (!policy.getConsumerTenantId().equals(policy.getProviderTenantId())) {
             // FAAS always assumes consumer and provider EPGs belong to the same tenant
             LOG.warn(
@@ -393,10 +382,7 @@ public class FaasPolicyManager implements DataChangeListener, AutoCloseable {
                     policy.getConsumerTenantId().getValue(), policy.getProviderTenantId().getValue());
             return false;
         }
-        if (!isTenantRegistered(policy.getConsumerTenantId())) {
-            return false;
-        }
-        return true;
+        return isTenantRegistered(policy.getConsumerTenantId());
     }
 
     private boolean isEqualService(ResolvedPolicy newPolicy, ResolvedPolicy oldPolicy) {
@@ -413,10 +399,8 @@ public class FaasPolicyManager implements DataChangeListener, AutoCloseable {
     private void registerSubnetWithEpg(EndpointGroupId epgId, TenantId tenantId, SubnetId subnetId, boolean updateLn) {
         synchronized (this) {
             List<SubnetId> subnets = cloneAndGetEpgSubnets(epgId, tenantId);
-            for (SubnetId id : subnets) {
-                if (id.equals(subnetId)) {
-                    return;
-                }
+            if(subnets.contains(subnetId)){
+                return;
             }
             subnets.add(subnetId);
             epgSubnetsMap.put(new Pair<>(epgId, tenantId), subnets);
@@ -427,7 +411,8 @@ public class FaasPolicyManager implements DataChangeListener, AutoCloseable {
         }
     }
 
-    private void removeLogicalNetwork(ResolvedPolicy oldPolicy) {
+    @VisibleForTesting
+    void removeLogicalNetwork(ResolvedPolicy oldPolicy) {
         if (oldPolicy == null) {
             return;
         }
@@ -565,7 +550,7 @@ public class FaasPolicyManager implements DataChangeListener, AutoCloseable {
         LogicalRouterBuilder provLR = initLogicalRouterBuilder(provEpg, faasTenantId,
                 isProviderPublic(externalImplicitGroup));
 
-        if (!UlnDatastoreApi.attachAndSubmitToDs(consLR, provLR, new Pair<Uuid, Uuid>(null, privateSecRulesId), null)) {
+        if (!UlnDatastoreApi.attachAndSubmitToDs(consLR, provLR, new Pair<>(null, privateSecRulesId), null)) {
             LOG.error("Failed to join Logical Routers in a Logical Network");
             return;
         }
@@ -789,10 +774,11 @@ public class FaasPolicyManager implements DataChangeListener, AutoCloseable {
         LogicalRouterBuilder builder = new LogicalRouterBuilder();
         builder.setAdminStateUp(true);
         builder.setName(new Text(epg.getId().getValue()));
-        if (epg.getDescription() != null)
+        if (epg.getDescription() != null) {
             builder.setDescription(new Text("gbp-epg: " + epg.getDescription().getValue()));
-        else
+        } else {
             builder.setDescription(new Text("gbp-epg"));
+        }
         builder.setPublic(isPublic);
         builder.setTenantId(tenantId);
         builder.setUuid(new Uuid(UUID.randomUUID().toString()));
@@ -803,16 +789,18 @@ public class FaasPolicyManager implements DataChangeListener, AutoCloseable {
         LogicalSwitchBuilder builder = new LogicalSwitchBuilder();
         builder.setAdminStateUp(true);
         builder.setName(new Text(epg.getId().getValue()));
-        if (epg.getDescription() != null)
+        if (epg.getDescription() != null) {
             builder.setDescription(new Text("gbp-epg: " + epg.getDescription().getValue()));
-        else
+        } else {
             builder.setDescription(new Text("gbp-epg"));
+        }
         builder.setTenantId(tenantId);
         builder.setUuid(new Uuid(UUID.randomUUID().toString()));
         return builder;
     }
 
-    protected boolean needToCreateLogicalNetwork(ServiceCommunicationLayer comLayer, List<SubnetId> consSubnetIds,
+    @VisibleForTesting
+    boolean needToCreateLogicalNetwork(ServiceCommunicationLayer comLayer, List<SubnetId> consSubnetIds,
             List<SubnetId> provSubnetIds, TenantId tenantId, ContractId contractId, EndpointGroup providerEpg,
             EndpointGroup consumerEpg, ExternalImplicitGroup externalImplicitGroup) {
         Optional<LogicalNetwork> lnOp = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
@@ -841,10 +829,8 @@ public class FaasPolicyManager implements DataChangeListener, AutoCloseable {
             return true;
         }
         Set<SubnetId> lnProvSubnets = new HashSet<>(logicalNet.getProviderNetwork().getGbpSubnetId());
-        if (lnProvSubnets.size() != provSubnetIds.size() || !lnProvSubnets.containsAll(provSubnetIds)) {
-            return true;
-        }
-        return false;
+        return lnProvSubnets.size() != provSubnetIds.size() || !lnProvSubnets.containsAll(
+                provSubnetIds);
     }
 
     private ServiceCommunicationLayer findLayerNetwork(TenantId tenantId, List<SubnetId> consSubnetIds,
@@ -950,7 +936,8 @@ public class FaasPolicyManager implements DataChangeListener, AutoCloseable {
         return null;
     }
 
-    protected L3Context readL3ContextInstance(TenantId tenantId, L3ContextId l3cId) {
+    @VisibleForTesting
+    L3Context readL3ContextInstance(TenantId tenantId, L3ContextId l3cId) {
         ReadOnlyTransaction rTx = dataProvider.newReadOnlyTransaction();
         InstanceIdentifier<L3Context> iid = IidFactory.l3ContextIid(tenantId, l3cId);
         Optional<L3Context> l2Op = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION, iid, rTx);
@@ -962,7 +949,8 @@ public class FaasPolicyManager implements DataChangeListener, AutoCloseable {
         return l2Op.get();
     }
 
-    protected L2BridgeDomain readL2BridgeDomainInstance(TenantId tenantId, L2BridgeDomainId l2bId) {
+    @VisibleForTesting
+    L2BridgeDomain readL2BridgeDomainInstance(TenantId tenantId, L2BridgeDomainId l2bId) {
         ReadOnlyTransaction rTx = dataProvider.newReadOnlyTransaction();
         InstanceIdentifier<L2BridgeDomain> iid = IidFactory.l2BridgeDomainIid(tenantId, l2bId);
         Optional<L2BridgeDomain> l2Op = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION, iid, rTx);
@@ -974,7 +962,8 @@ public class FaasPolicyManager implements DataChangeListener, AutoCloseable {
         return l2Op.get();
     }
 
-    protected L2FloodDomain readL2FloodDomain(L2FloodDomainId l2fId, TenantId tenantId) {
+    @VisibleForTesting
+    L2FloodDomain readL2FloodDomain(L2FloodDomainId l2fId, TenantId tenantId) {
         ReadOnlyTransaction rTx = dataProvider.newReadOnlyTransaction();
         InstanceIdentifier<L2FloodDomain> iid = IidFactory.l2FloodDomainIid(tenantId, l2fId);
         Optional<L2FloodDomain> l2Op = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION, iid, rTx);
@@ -1023,7 +1012,8 @@ public class FaasPolicyManager implements DataChangeListener, AutoCloseable {
         removeTenantLogicalNetwork(gbpTenantId, faasTenantId, true);
     }
 
-    private void removeTenantLogicalNetwork(TenantId gbpTenantId, Uuid faasTenantId, boolean unregister) {
+    @VisibleForTesting
+    void removeTenantLogicalNetwork(TenantId gbpTenantId, Uuid faasTenantId, boolean unregister) {
         UlnDatastoreApi.removeTenantFromDsIfExists(faasTenantId);
         synchronized (this) {
             mappedTenants.remove(gbpTenantId);