Integrating FAAS renderer with the faas fabric mapping services. Also, 19/29419/45
authorKhaldoon Al-zoubi <khalAlzoubi@gmail.com>
Sun, 8 Nov 2015 22:53:28 +0000 (17:53 -0500)
committerKhaldoon Al-zoubi <khalAlzoubi@gmail.com>
Thu, 7 Jan 2016 18:41:35 +0000 (13:41 -0500)
put tenants external explicit groups in resolved policies to be accessible
by renderers.

Change-Id: I41447bb41c71ca1e6cfb4fa001c4dd736b02a37e
Signed-off-by: Khaldoon Al-zoubi <khalAlzoubi@gmail.com>
20 files changed:
features/pom.xml
features/src/main/features/features.xml
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/resolver/PolicyResolver.java
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/util/IidFactory.java
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/util/InheritanceUtils.java
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/util/PolicyInfoUtils.java
renderers/faas/pom.xml
renderers/faas/src/main/config/default-config.xml
renderers/faas/src/main/java/org/opendaylight/controller/config/yang/config/faas_provider/impl/FaasProviderModule.java
renderers/faas/src/main/java/org/opendaylight/groupbasedpolicy/renderer/faas/FaasContractManagerListener.java [new file with mode: 0644]
renderers/faas/src/main/java/org/opendaylight/groupbasedpolicy/renderer/faas/FaasEndpointAug.java [new file with mode: 0644]
renderers/faas/src/main/java/org/opendaylight/groupbasedpolicy/renderer/faas/FaasEndpointManagerListener.java
renderers/faas/src/main/java/org/opendaylight/groupbasedpolicy/renderer/faas/FaasIidFactory.java [new file with mode: 0644]
renderers/faas/src/main/java/org/opendaylight/groupbasedpolicy/renderer/faas/FaasPolicyManager.java [new file with mode: 0644]
renderers/faas/src/main/java/org/opendaylight/groupbasedpolicy/renderer/faas/FaasRenderer.java
renderers/faas/src/main/java/org/opendaylight/groupbasedpolicy/renderer/faas/FaasSubnetManagerListener.java [new file with mode: 0644]
renderers/faas/src/main/java/org/opendaylight/groupbasedpolicy/renderer/faas/FaasTenantManagerListener.java [new file with mode: 0644]
renderers/faas/src/main/yang/faas-endpoint.yang
renderers/faas/src/main/yang/faas-provider-impl.yang
renderers/faas/src/main/yang/faas.yang

index 4f789f3c986ca5654baafe04d28b4f91f4b3c278..2b1d9e7cef6cbef06d12de42bcc203eee9b70378 100755 (executable)
@@ -31,6 +31,7 @@
     <openflowplugin.version>0.2.0-SNAPSHOT</openflowplugin.version>
     <ovsdb.southbound.version>1.2.1-SNAPSHOT</ovsdb.southbound.version>
     <neutron.version>0.6.0-SNAPSHOT</neutron.version>
+    <faas.version>1.0.0-SNAPSHOT</faas.version>
     <sfc.version>0.2.0-SNAPSHOT</sfc.version>
     <restconf.version>1.3.0-SNAPSHOT</restconf.version>
     <dlux.version>0.3.0-SNAPSHOT</dlux.version>
       <version>${neutron.version}</version>
       <type>xml</type>
     </dependency>
+    <!-- Faas -->
+    <dependency>
+      <groupId>org.opendaylight.faas</groupId>
+      <artifactId>features-faas</artifactId>
+      <classifier>features</classifier>
+      <version>${faas.version}</version>
+      <type>xml</type>
+    </dependency>
 
     <!-- SFC -->
     <dependency>
index 3d1ae992ad62aed999e8fe0fdf1760d1eafcb3fc..faa6dd88879077d9a493f3c194969b8859ed4d39 100755 (executable)
@@ -19,6 +19,8 @@
     <repository>mvn:org.opendaylight.openflowplugin/features-openflowplugin/{{VERSION}}/xml/features</repository>
     <repository>mvn:org.opendaylight.openflowplugin/features-openflowplugin-extension/{{VERSION}}/xml/features</repository>
     <repository>mvn:org.opendaylight.ovsdb/southbound-features/{{VERSION}}/xml/features</repository>
+    <!-- Repos needed by the Fabric As A Service (FAAS) renderer -->
+    <repository>mvn:org.opendaylight.faas/features-faas/{{VERSION}}/xml/features</repository>
     <!-- Repos needed by the Neutron Mapper -->
     <repository>mvn:org.opendaylight.neutron/features-neutron/{{VERSION}}/xml/features</repository>
     <!-- Repos needed by ofoverlay for SFC -->
@@ -84,7 +86,7 @@
     -->
     <feature name='odl-groupbasedpolicy-faas' version='${project.version}' description='OpenDaylight :: groupbasedpolicy :: Fabric As A Service Renderer'>
         <feature version="${project.version}">odl-groupbasedpolicy-base</feature>
-        <feature version='${openflowplugin.version}'>odl-openflowplugin-nxm-extensions</feature>
+        <feature version='${faas.version}'>odl-faas-uln-mapper</feature>
         <bundle>mvn:org.opendaylight.groupbasedpolicy/faas-renderer/{{VERSION}}</bundle>
         <configfile finalname="${config.configfile.directory}/15-groupbasedpolicy-faas.xml">mvn:org.opendaylight.groupbasedpolicy/faas-renderer/{{VERSION}}/xml/config</configfile>
     </feature>
index 1d260fc5f219c8a5699ee557af182aac3a838d9e..255e90a5e002f948c0169ad51aad11f9fb62e544 100755 (executable)
@@ -224,7 +224,7 @@ public class PolicyResolver implements PolicyValidatorRegistry, AutoCloseable {
         Table<EgKey, EgKey, org.opendaylight.groupbasedpolicy.dto.Policy> policyMap =
                 PolicyResolverUtils.resolvePolicy(indexedTenants);
         ResolvedPolicies resolvedPolicies =
-                new ResolvedPoliciesBuilder().setResolvedPolicy(PolicyInfoUtils.buildResolvedPolicy(policyMap)).build();
+                new ResolvedPoliciesBuilder().setResolvedPolicy(PolicyInfoUtils.buildResolvedPolicy(policyMap, resolvedTenants)).build();
 
         wTx.put(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.builder(ResolvedPolicies.class).build(),
                 resolvedPolicies, true);
index e588d7432dbf415878807c01b673d2b123e8e68e..4d0a4289f1b7bf691ead39386416186230c17134 100644 (file)
@@ -116,6 +116,14 @@ public class IidFactory {
             .build();
     }
 
+    public static InstanceIdentifier<Contract> contractWildcardIid(TenantId tenantId) {
+        return InstanceIdentifier.builder(Tenants.class)
+            .child(Tenant.class, new TenantKey(tenantId))
+            .child(Policy.class)
+            .child(Contract.class)
+            .build();
+    }
+
     public static InstanceIdentifier<Subject> subjectIid(TenantId tenantId, ContractId contractId,
             SubjectName subjectName) {
         return InstanceIdentifier.builder(Tenants.class)
@@ -281,6 +289,14 @@ public class IidFactory {
             .build();
     }
 
+    public static InstanceIdentifier<Subnet> subnetWildcardIid(TenantId tenantId) {
+        return InstanceIdentifier.builder(Tenants.class)
+            .child(Tenant.class, new TenantKey(tenantId))
+            .child(ForwardingContext.class)
+            .child(Subnet.class)
+            .build();
+    }
+
     public static InstanceIdentifier<FollowedEndpointGroup> followedEndpointgroupIid(RendererName rendererName,
             TenantId tenantId, EndpointGroupId epgId) {
         return InstanceIdentifier.builder(Renderers.class)
@@ -307,4 +323,21 @@ public class IidFactory {
             .child(SupportedClassifierDefinition.class)
             .build();
     }
+
+    public static InstanceIdentifier<FollowedTenant> followedTenantIid(RendererName rendererName, TenantId tenantId) {
+        return InstanceIdentifier.builder(Renderers.class)
+            .child(Renderer.class, new RendererKey(rendererName))
+            .child(Interests.class)
+            .child(FollowedTenants.class)
+            .child(FollowedTenant.class, new FollowedTenantKey(tenantId))
+            .build();
+    }
+
+    public static InstanceIdentifier<Renderer> rendererIid(RendererName rendererName) {
+        return InstanceIdentifier.builder(Renderers.class).child(Renderer.class, new RendererKey(rendererName)).build();
+    }
+
+    public static InstanceIdentifier<Renderers> renderersIid() {
+        return InstanceIdentifier.builder(Renderers.class).build();
+    }
 }
index 5bf27a6a2ecb6af1036ba455b1c2f6a477272cf7..f7b46864c58ece24e90126dfb6ba6644109ac496 100644 (file)
@@ -134,6 +134,7 @@ public class InheritanceUtils {
             .setPolicy(new PolicyBuilder().setEndpointGroup(ImmutableList.copyOf(resolvedEgs.values()))
                 .setContract(ImmutableList.copyOf(resolvedContracts.values()))
                 .setContractRef(unresolvedPolicy.getContractRef())
+                .setExternalImplicitGroup(unresolvedPolicy.getExternalImplicitGroup())
                 .setSubjectFeatureInstances(unresolvedPolicy.getSubjectFeatureInstances())
                 .build());
         }
index 94e2c678039e05d48a1b9b1bb5c4d5dcfe0fec17..100c54f30612396317f036caecdf1ec9daea27fc 100644 (file)
@@ -12,15 +12,19 @@ import java.util.Collection;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
+import java.util.concurrent.ConcurrentMap;
 
 import org.opendaylight.groupbasedpolicy.dto.ConditionSet;
 import org.opendaylight.groupbasedpolicy.dto.EgKey;
 import org.opendaylight.groupbasedpolicy.dto.EndpointConstraint;
+import org.opendaylight.groupbasedpolicy.dto.IndexedTenant;
 import org.opendaylight.groupbasedpolicy.dto.Policy;
 import org.opendaylight.groupbasedpolicy.dto.RuleGroup;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ActionName;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClassifierName;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ConditionName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.action.refs.ActionRef;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.classifier.refs.ClassifierRef;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.classifier.refs.ClassifierRef.ConnectionTracking;
@@ -50,6 +54,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.p
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.has.resolved.rules.ResolvedRuleBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.has.resolved.rules.ResolvedRuleKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.resolved.policies.ResolvedPolicy;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.resolved.policies.ResolvedPolicy.ExternalImplicitGroup;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.resolved.policies.ResolvedPolicyBuilder;
 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.PolicyRuleGroupWithEndpointConstraintsBuilder;
@@ -57,17 +62,20 @@ 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.policy.rule.group.with.endpoint.constraints.PolicyRuleGroup;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.resolved.policies.resolved.policy.policy.rule.group.with.endpoint.constraints.PolicyRuleGroupBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.resolved.policies.resolved.policy.policy.rule.group.with.endpoint.constraints.ProviderEndpointConstraintsBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import com.google.common.collect.Table;
 import com.google.common.collect.Table.Cell;
 
 public class PolicyInfoUtils {
-
+    private static final Logger LOG = LoggerFactory.getLogger(PolicyInfoUtils.class);
     private PolicyInfoUtils() {
         throw new UnsupportedOperationException("Cannot create an instance");
     }
 
-    public static List<ResolvedPolicy> buildResolvedPolicy(Table<EgKey, EgKey, Policy> policyMap) {
+    public static List<ResolvedPolicy> buildResolvedPolicy(Table<EgKey, EgKey, Policy> policyMap,
+            ConcurrentMap<TenantId, IndexedTenant> resolvedTenants) {
         List<ResolvedPolicy> resolvedPolicies = new ArrayList<>();
         for (Cell<EgKey, EgKey, Policy> policyCell : policyMap.cellSet()) {
             ResolvedPolicyBuilder resolvedPolicyBuilder = new ResolvedPolicyBuilder();
@@ -77,11 +85,35 @@ public class PolicyInfoUtils {
             resolvedPolicyBuilder.setProviderTenantId(policyCell.getColumnKey().getTenantId());
             resolvedPolicyBuilder.setPolicyRuleGroupWithEndpointConstraints(
                     buildPolicyRuleGroupWithEndpointConstraints(policyCell.getValue()));
+            Tenant consTenant = resolvedTenants.get(policyCell.getRowKey().getTenantId()).getTenant();
+            Tenant provTenant = resolvedTenants.get(policyCell.getColumnKey().getTenantId()).getTenant();
+            if (isExternalImplicitGroup(consTenant, policyCell.getRowKey().getEgId())) {
+                resolvedPolicyBuilder.setExternalImplicitGroup(ExternalImplicitGroup.ConsumerEpg);
+            } else if (isExternalImplicitGroup(provTenant, policyCell.getColumnKey().getEgId())) {
+                resolvedPolicyBuilder.setExternalImplicitGroup(ExternalImplicitGroup.ProviderEpg);
+            }
             resolvedPolicies.add(resolvedPolicyBuilder.build());
         }
         return resolvedPolicies;
     }
 
+    private static boolean isExternalImplicitGroup(Tenant tenant, EndpointGroupId epgId) {
+        if (tenant == null || epgId == null || tenant.getPolicy() == null
+                || tenant.getPolicy().getExternalImplicitGroup() == null) {
+            return false;
+        }
+        LOG.trace("Found External EPGs in Tenant {}", tenant.getId().getValue());
+        for (org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.ExternalImplicitGroup eig : tenant.getPolicy()
+            .getExternalImplicitGroup()) {
+            if (eig.getId().equals(epgId)) {
+                LOG.trace("EPG {} is External Implicit Group", epgId.getValue());
+                return true;
+            }
+        }
+        LOG.trace("EPG {} is NOT External Implicit Group", epgId.getValue());
+        return false;
+    }
+
     private static List<PolicyRuleGroupWithEndpointConstraints> buildPolicyRuleGroupWithEndpointConstraints(
             Policy policy) {
         List<PolicyRuleGroupWithEndpointConstraints> policyRuleGroupWithEndpointConstraintsList = new ArrayList<>();
index a99a73b861d0dcc00a6ea55bd39abeb08d134eea..4b75906e69d3487e6cf1a992ff27923cdc183b77 100644 (file)
 
   <properties>
     <openflowplugin.version>0.2.0-SNAPSHOT</openflowplugin.version>
+    <faas.version>1.0.0-SNAPSHOT</faas.version>
   </properties>
 
   <dependencies>
     <dependency>
-      <groupId>org.opendaylight.openflowplugin</groupId>
-      <artifactId>openflowplugin-extension-nicira</artifactId>
-      <version>${openflowplugin.version}</version>
+      <groupId>org.opendaylight.faas</groupId>
+      <artifactId>uln-mapper-model</artifactId>
+      <version>${faas.version}</version>
     </dependency>
     <!-- testing dependencies -->
     <dependency>
@@ -57,4 +58,4 @@
       </plugin>
     </plugins>
   </build>
-</project>
\ No newline at end of file
+</project>
index 670e8514490edf9168cbbf579c6c0d987e3e7696..4da9c6b0af2e837acb48dd6c2223148d0e4b2a5b 100644 (file)
                     </type>
                     <name>faas-provider-impl</name>
 
-                    <rpc-registry>
-                        <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-rpc-registry</type>
-                        <name>binding-rpc-broker</name>
-                    </rpc-registry>
-
                     <data-broker>
                       <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-async-data-broker</type>
                       <name>binding-data-broker</name>
                     </data-broker>
-
-                    <notification-adapter>
-                        <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">binding:binding-new-notification-service</type>
-                        <name>binding-notification-adapter</name>
-                    </notification-adapter>
+                    
+                    <ep-renderer-augmentation-registry>
+                        <type xmlns:epr="urn:opendaylight:params:xml:ns:yang:controller:config:groupbasedpolicy">epr:ep-renderer-augmentation-registry</type>
+                        <name>ep-renderer-augmentation-registry</name>
+                    </ep-renderer-augmentation-registry>
+                    
                 </module>
             </modules>
         </data>
index 553910055d7fdc9be12435ae001d6c62d18da469..3909c975bcdba135a2ee67433d05b77906db6bfa 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
@@ -32,8 +32,7 @@ public class FaasProviderModule extends
 
     @Override
     public java.lang.AutoCloseable createInstance() {
-        return new FaasRenderer(getDataBrokerDependency(), getRpcRegistryDependency(),
-                getNotificationAdapterDependency());
+        return new FaasRenderer(getDataBrokerDependency(), getEpRendererAugmentationRegistryDependency());
     }
 
 }
diff --git a/renderers/faas/src/main/java/org/opendaylight/groupbasedpolicy/renderer/faas/FaasContractManagerListener.java b/renderers/faas/src/main/java/org/opendaylight/groupbasedpolicy/renderer/faas/FaasContractManagerListener.java
new file mode 100644 (file)
index 0000000..f4311e3
--- /dev/null
@@ -0,0 +1,422 @@
+/*
+ * 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
+ */
+
+package org.opendaylight.groupbasedpolicy.renderer.faas;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ScheduledExecutorService;
+
+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.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.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.faas.uln.datastore.api.UlnDatastoreApi;
+import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.common.rev151013.Name;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.common.rev151013.Text;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.common.rev151013.Uuid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.security.rules.rev151013.parameter.values.grouping.ParameterValue;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.security.rules.rev151013.parameter.values.grouping.ParameterValueBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.security.rules.rev151013.parameter.values.grouping.parameter.value.RangeValueBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.security.rules.rev151013.security.rule.groups.attributes.security.rule.groups.container.SecurityRuleGroupsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.security.rules.rev151013.security.rule.groups.attributes.security.rule.groups.container.security.rule.groups.SecurityRuleGroup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.security.rules.rev151013.security.rule.groups.attributes.security.rule.groups.container.security.rule.groups.SecurityRuleGroupBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.security.rules.rev151013.security.rule.groups.attributes.security.rule.groups.container.security.rule.groups.security.rule.group.SecurityRule;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.security.rules.rev151013.security.rule.groups.attributes.security.rule.groups.container.security.rule.groups.security.rule.group.SecurityRuleBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.security.rules.rev151013.security.rule.groups.attributes.security.rule.groups.container.security.rule.groups.security.rule.group.security.rule.RuleAction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.security.rules.rev151013.security.rule.groups.attributes.security.rule.groups.container.security.rule.groups.security.rule.group.security.rule.RuleActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.security.rules.rev151013.security.rule.groups.attributes.security.rule.groups.container.security.rule.groups.security.rule.group.security.rule.RuleClassifier;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.security.rules.rev151013.security.rule.groups.attributes.security.rule.groups.container.security.rule.groups.security.rule.group.security.rule.RuleClassifier.Direction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.security.rules.rev151013.security.rule.groups.attributes.security.rule.groups.container.security.rule.groups.security.rule.group.security.rule.RuleClassifierBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ActionName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClassifierName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContractId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubjectName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.mapped.tenants.entities.mapped.entity.MappedContract;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.mapped.tenants.entities.mapped.entity.MappedContractBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.Tenants;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.action.refs.ActionRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.classifier.refs.ClassifierRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.Tenant;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.TenantKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.Policy;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.Contract;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.SubjectFeatureInstances;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.contract.Clause;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.contract.Subject;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.contract.subject.Rule;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.subject.feature.instances.ActionInstance;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.subject.feature.instances.ActionInstanceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.subject.feature.instances.ClassifierInstance;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.subject.feature.instances.ClassifierInstanceKey;
+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 FaasContractManagerListener implements DataChangeListener {
+
+    private static final Logger LOG = LoggerFactory.getLogger(FaasContractManagerListener.class);
+    private ConcurrentHashMap<ContractId, Uuid> mappedContracts = new ConcurrentHashMap<>();
+    private final ScheduledExecutorService executor;
+    private final DataBroker dataProvider;
+    private final TenantId gbpTenantId;
+    private final Uuid faasTenantId;
+
+    public FaasContractManagerListener(DataBroker dataProvider, TenantId gbpTenantId, Uuid faasTenantId,
+            ScheduledExecutorService executor) {
+        this.executor = executor;
+        this.gbpTenantId = gbpTenantId;
+        this.faasTenantId = faasTenantId;
+        this.dataProvider = dataProvider;
+    }
+
+    @Override
+    public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+        executor.execute(new Runnable() {
+
+            public void run() {
+                executeEvent(change);
+            }
+        });
+    }
+
+    private void executeEvent(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+        // Create
+        for (DataObject dao : change.getCreatedData().values()) {
+            if (dao instanceof Contract) {
+                Contract contract = (Contract) dao;
+                LOG.debug("Contract {} is Created.", contract.getId().getValue());
+                UlnDatastoreApi.submitSecurityGroupsToDs(initSecurityGroupBuilder(contract).build());
+            }
+        }
+        // Update
+        Map<InstanceIdentifier<?>, DataObject> dao = change.getUpdatedData();
+        for (Map.Entry<InstanceIdentifier<?>, DataObject> entry : dao.entrySet()) {
+            if (entry.getValue() instanceof Contract) {
+                Contract contract = (Contract) dao;
+                LOG.debug("Contract {} is Updated.", contract.getId().getValue());
+                UlnDatastoreApi.submitSecurityGroupsToDs(initSecurityGroupBuilder(contract).build());
+            }
+        }
+        // Remove
+        for (InstanceIdentifier<?> iid : change.getRemovedPaths()) {
+            DataObject old = change.getOriginalData().get(iid);
+            if (old == null) {
+                continue;
+            }
+            if (old instanceof Contract) {
+                Contract contract = (Contract) old;
+                LOG.debug("Contract {} is removed.", contract.getId().getValue());
+                ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
+                Optional<MappedContract> op = DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
+                        FaasIidFactory.mappedContractIid(gbpTenantId, contract.getId()), rwTx);
+                if (op.isPresent()) {
+                    DataStoreHelper.submitToDs(rwTx);
+                }
+                Uuid val = mappedContracts.remove(contract.getId());
+                if (val != null) {
+                    UlnDatastoreApi.removeSecurityGroupsFromDsIfExists(faasTenantId, val);
+                }
+            }
+        }
+    }
+
+    public void loadAll(List<Contract> contracts, List<MappedContract> mpContracts) {
+        if (mpContracts != null) {
+            for (MappedContract mpContract : mpContracts) {
+                mappedContracts.putIfAbsent(mpContract.getGbpContractId(), mpContract.getFaasSecurityRulesId());
+            }
+        }
+        if (contracts != null) {
+            for (Contract contract : contracts) {
+                LOG.debug("Loading Contract {}", contract.getId().getValue());
+                UlnDatastoreApi.submitSecurityGroupsToDs(initSecurityGroupBuilder(contract).build());
+            }
+        }
+    }
+
+    private SecurityRuleGroupsBuilder initSecurityGroupBuilder(Contract contract) {
+        LOG.trace("Start initSecurityGroupBuilder");
+        SecurityRuleGroupsBuilder builder = new SecurityRuleGroupsBuilder();
+        builder.setUuid(getFaasSecurityRulesId(contract.getId()));
+        builder.setName(new Text(contract.getId().getValue()));
+        if (contract.getDescription() != null)
+            builder.setDescription(new Text("gbp-contract: " + contract.getDescription().getValue()));
+        else
+            builder.setDescription(new Text("gbp-contract"));
+        builder.setTenantId(faasTenantId);
+        builder.setSecurityRuleGroup(buildSecurityRuleGroup(contract));
+        LOG.trace("Contract {} is mapped to Faas Security Rules {} ", contract.getId().getValue(), builder.getUuid()
+            .getValue());
+        return builder;
+    }
+
+    private Uuid getFaasSecurityRulesId(ContractId contractId) {
+        Uuid val = mappedContracts.get(contractId);
+        if (val != null) {
+            return val;
+        }
+        Uuid faasContractId = null;
+        if (FaasPolicyManager.isUUid(contractId.getValue())) {
+            faasContractId = new Uuid(contractId.getValue());
+        } else {
+            faasContractId = new Uuid(UUID.randomUUID().toString());
+        }
+        mappedContracts.putIfAbsent(contractId, faasContractId);
+        val = mappedContracts.get(contractId);
+        MappedContractBuilder builder = new MappedContractBuilder();
+        builder.setFaasSecurityRulesId(val);
+        builder.setGbpContractId(contractId);
+        WriteTransaction wTx = dataProvider.newWriteOnlyTransaction();
+        MappedContract result = builder.build();
+        wTx.put(LogicalDatastoreType.OPERATIONAL,
+                FaasIidFactory.mappedContractIid(gbpTenantId, contractId), result);
+        if (DataStoreHelper.submitToDs(wTx)) {
+            LOG.debug("Cached in Datastore Mapped Contract {}", result);
+        } else {
+            LOG.error("Couldn't Cache in Datastore Mapped Contract {}", result);
+        }
+        return val;
+    }
+
+    private List<SecurityRuleGroup> buildSecurityRuleGroup(Contract contract) {
+        LOG.trace("Start buildSecurityRuleGroup for contract {}", contract.getId().getValue());
+        List<SecurityRuleGroup> securityRuleGroups = new ArrayList<>();
+        if (contract.getClause() == null) {
+            LOG.debug("contract {} has no Clause", contract.getId().getValue());
+            return null;
+        }
+        for (Clause clause : contract.getClause()) {
+            if (clause.getSubjectRefs() == null) {
+                LOG.debug("Clause {} in contract {} has no Subject Ref", clause.getName().getValue(), contract.getId()
+                    .getValue());
+                continue;
+            }
+            if (contract.getSubject() == null) {
+                LOG.warn("Couldn't find in Contract {} the expected subject references", contract.getId().getValue());
+                continue;
+            }
+            for (SubjectName subjectRef : clause.getSubjectRefs()) {
+                LOG.trace("Start Parsing Subject Ref {} in Contract {}", subjectRef, contract.getId().getValue());
+                for (Subject sub : contract.getSubject()) {
+                    if (subjectRef.equals(sub.getName())) {
+                        SecurityRuleGroupBuilder securityRuleGroupBuilder = new SecurityRuleGroupBuilder();
+                        securityRuleGroupBuilder.setName(new Name(subjectRef.getValue()));
+                        List<Rule> subRules = sub.getRule();
+                        if (subRules == null) {
+                            LOG.warn("Subject {} in Contract {} doesn't have rules", subjectRef.getValue(),
+                                    contract.getId().getValue());
+                        } else {
+                            List<SecurityRule> securityRules = getSecurityRules(contract, subjectRef, subRules);
+                            LOG.debug("Subject {} in Contract {} has {} rules", subjectRef.getValue(), contract.getId()
+                                .getValue(), securityRules.size());
+                            securityRuleGroupBuilder.setSecurityRule(securityRules);
+                        }
+                        LOG.debug("Added Rule {} to Subject {} in Contract {}", securityRuleGroupBuilder.getName()
+                            .getValue(), subjectRef.getValue(), contract.getId().getValue());
+                        securityRuleGroups.add(securityRuleGroupBuilder.build());
+                    }
+                }
+            }
+        }
+        LOG.trace("Done with buildSecurityRuleGroup for contract {}", contract.getId().getValue());
+        return securityRuleGroups;
+    }
+
+    private List<SecurityRule> getSecurityRules(Contract contract, SubjectName subjectRef, List<Rule> subRules) {
+        List<SecurityRule> securityRules = new ArrayList<>();
+        for (Rule rule : subRules) {
+            List<ClassifierRef> classifierRefs = rule.getClassifierRef();
+            List<RuleClassifier> pClassifiers = null;
+            if (classifierRefs == null || classifierRefs.isEmpty()) {
+                LOG.warn("Rule {} in Subject {} in Contract {} doesn't have classifiers", rule.getName(), subjectRef,
+                        contract.getId());
+            } else {
+                pClassifiers = getClassifiers(gbpTenantId, contract, classifierRefs, dataProvider);
+                if (pClassifiers == null || pClassifiers.isEmpty()) {
+                    LOG.warn("Rule {} in Subject {} in Contract {} doesn't have classifiers -- Will ignore this rule",
+                            rule.getName(), subjectRef, contract.getId());
+                }
+            }
+            List<ActionRef> actionRefs = rule.getActionRef();
+            List<RuleAction> pActions = null;
+            if (actionRefs == null || actionRefs.isEmpty()) {
+                LOG.warn("Rule {} in Subject {} in Contract {} doesn't have actions", rule.getName(), subjectRef,
+                        contract.getId());
+            } else {
+                pActions = getActions(contract, actionRefs);
+                if (pActions == null || pActions.isEmpty()) {
+                    LOG.warn("Rule {} in Subject {} in Contract {} doesn't have actions", rule.getName(), subjectRef,
+                            contract.getId());
+                }
+            }
+
+            securityRules.add(new SecurityRuleBuilder().setName(new Name(rule.getName().getValue()))
+                .setOrder(rule.getOrder())
+                .setRuleClassifier(pClassifiers)
+                .setRuleAction(pActions)
+                .build());
+        } // for rules
+        return securityRules;
+    }
+
+    private List<RuleAction> getActions(Contract contract, List<ActionRef> actionRefs) {
+        LOG.trace("Start Parsing Actions for actionRefs count {} in Contract {}", actionRefs.size(), contract.getId()
+            .getValue());
+        List<RuleAction> pActions = new ArrayList<>();
+        for (ActionRef actionRef : actionRefs) {
+            if (actionRef.getName() == null) {
+                LOG.warn("Couldn't find an Action in Contract {} -- ignored Action", contract.getId().getValue());
+                continue;
+            }
+            RuleActionBuilder ruleActionBuilder = new RuleActionBuilder();
+            ruleActionBuilder.setName(new Name(actionRef.getName().getValue()));
+            ruleActionBuilder.setOrder(actionRef.getOrder());
+            ActionInstance actionInstance = getActionInstance(actionRef.getName());
+            if (actionInstance == null) {
+                LOG.warn("Action instance {} is not found -- will only use the Action ref info", actionRef.getName());
+            } else {
+                if (actionInstance.getActionDefinitionId() != null) {
+                    ruleActionBuilder.setAdditionalInfo(new Text(actionInstance.getActionDefinitionId().getValue()));
+                }
+                List<ParameterValue> parms = null;
+                if (actionInstance.getParameterValue() != null) {
+                    LOG.trace("Action Instance {} has {} parameters", actionInstance.getName().getValue(),
+                            actionInstance.getParameterValue().size());
+                    parms = new ArrayList<>();
+                    for (org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.instance.ParameterValue instance : actionInstance.getParameterValue()) {
+                        ParameterValueBuilder pBuilder = new ParameterValueBuilder();
+                        pBuilder.setIntValue(instance.getIntValue());
+                        if (instance.getName() != null) {
+                            pBuilder.setName(new Name(instance.getName().getValue()));
+                        }
+                        pBuilder.setStringValue(instance.getStringValue());
+                        if (instance.getRangeValue() != null) {
+                            RangeValueBuilder rBuilder = new RangeValueBuilder().setMax(
+                                    instance.getRangeValue().getMax()).setMin(instance.getRangeValue().getMin());
+                            pBuilder.setRangeValue(rBuilder.build());
+                        }
+                        ParameterValue parm = pBuilder.build();
+                        LOG.trace("Added Parm {} from Action Instance {}", parm, actionInstance.getName().getValue());
+                        parms.add(parm);
+                    }
+                } else {
+                    LOG.trace("Action Instance {} has no parameters", actionInstance.getName().getValue());
+                }
+                ruleActionBuilder.setParameterValue(parms);
+            }
+            pActions.add(ruleActionBuilder.build());
+        }
+
+        return pActions;
+    }
+
+    private ActionInstance getActionInstance(ActionName name) {
+        ReadOnlyTransaction trans = dataProvider.newReadOnlyTransaction();
+        InstanceIdentifier<ActionInstance> ciId = InstanceIdentifier.builder(Tenants.class)
+            .child(Tenant.class, new TenantKey(gbpTenantId))
+            .child(Policy.class)
+            .child(SubjectFeatureInstances.class)
+            .child(ActionInstance.class, new ActionInstanceKey(name))
+            .build();
+        try {
+            Optional<ActionInstance> data = trans.read(LogicalDatastoreType.CONFIGURATION, ciId).get();
+            if (data.isPresent()) {
+                return data.get();
+            }
+        } catch (Exception e) {
+            LOG.error("Couldn't read Action instance from datastore. Exception: ", e);
+        }
+        return null;
+    }
+
+    private List<RuleClassifier> getClassifiers(TenantId tenantId, Contract contract,
+            List<ClassifierRef> classifierRefs, DataBroker dataProvider) {
+        List<RuleClassifier> fClassifiers = new ArrayList<>();
+        for (ClassifierRef classifierRef : classifierRefs) {
+            if (classifierRef.getName() == null) {
+                LOG.warn("Found a Classifer without name in Contract {} ", contract.getId().getValue());
+                continue;
+            }
+            RuleClassifierBuilder ruleClassifierBuilder = new RuleClassifierBuilder();
+            ruleClassifierBuilder.setName(new Name(classifierRef.getName().getValue()));
+            ClassifierInstance classifierInstance = getClassifierInstance(tenantId, classifierRef.getName(),
+                    dataProvider);
+            if (classifierInstance == null) {
+                LOG.warn("Classifer instance {} is not found -- will only use the classifier Ref info",
+                        classifierRef.getName());
+            } else {
+                if (classifierInstance.getClassifierDefinitionId() != null) {
+                    ruleClassifierBuilder.setAdditionalInfo(new Text(classifierInstance.getClassifierDefinitionId()
+                        .getValue()));
+                }
+                List<ParameterValue> parms = null;
+                if (classifierInstance.getParameterValue() != null) {
+                    LOG.trace("Calssifier Instance {} has {} parameters", classifierInstance.getName().getValue(),
+                            classifierInstance.getParameterValue().size());
+                    parms = new ArrayList<>();
+                    for (org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.instance.ParameterValue instance : classifierInstance.getParameterValue()) {
+                        ParameterValueBuilder pBuilder = new ParameterValueBuilder();
+                        pBuilder.setIntValue(instance.getIntValue());
+                        pBuilder.setName(new Name(instance.getName().getValue()));
+                        pBuilder.setStringValue(instance.getStringValue());
+                        if (instance.getRangeValue() != null) {
+                            RangeValueBuilder rBuilder = new RangeValueBuilder().setMax(
+                                    instance.getRangeValue().getMax()).setMin(instance.getRangeValue().getMin());
+                            pBuilder.setRangeValue(rBuilder.build());
+                        }
+                        ParameterValue parm = pBuilder.build();
+                        LOG.trace("Added parm {} from Classifier Instance {}", parm, classifierInstance.getName()
+                            .getValue());
+                        parms.add(parm);
+                    }
+                } else {
+                    LOG.trace("Classifier Instance {} has no parameters", classifierInstance.getName().getValue());
+                }
+                ruleClassifierBuilder.setParameterValue(parms);
+            }
+            if (classifierRef.getDirection() != null) {
+                ruleClassifierBuilder.setDirection(Direction.forValue(classifierRef.getDirection().getIntValue()));
+            } else {
+                ruleClassifierBuilder.setDirection(Direction.Bidirectional);
+            }
+            fClassifiers.add(ruleClassifierBuilder.build());
+        }
+        return fClassifiers;
+    }
+
+    private ClassifierInstance getClassifierInstance(TenantId tenantId, ClassifierName name, DataBroker dataProvider) {
+        ReadOnlyTransaction trans = dataProvider.newReadOnlyTransaction();
+        InstanceIdentifier<ClassifierInstance> ciId = InstanceIdentifier.builder(Tenants.class)
+            .child(Tenant.class, new TenantKey(tenantId))
+            .child(Policy.class)
+            .child(SubjectFeatureInstances.class)
+            .child(ClassifierInstance.class, new ClassifierInstanceKey(name))
+            .build();
+        try {
+            Optional<ClassifierInstance> data = trans.read(LogicalDatastoreType.CONFIGURATION, ciId).get();
+            if (data.isPresent()) {
+                return data.get();
+            }
+        } catch (Exception e) {
+            LOG.error("Couldn't read Action instance from datastore. Exception: ", e);
+        }
+        return null;
+    }
+}
diff --git a/renderers/faas/src/main/java/org/opendaylight/groupbasedpolicy/renderer/faas/FaasEndpointAug.java b/renderers/faas/src/main/java/org/opendaylight/groupbasedpolicy/renderer/faas/FaasEndpointAug.java
new file mode 100644 (file)
index 0000000..fec6b90
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * 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
+ */
+package org.opendaylight.groupbasedpolicy.renderer.faas;
+
+import java.util.AbstractMap.SimpleImmutableEntry;
+import java.util.Map;
+
+import org.opendaylight.groupbasedpolicy.api.EpRendererAugmentation;
+import org.opendaylight.groupbasedpolicy.api.EpRendererAugmentationRegistry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.faas.endpoint.rev151009.FaasEndpointContext;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.faas.endpoint.rev151009.FaasEndpointContextBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.faas.endpoint.rev151009.FaasEndpointContextInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterL3PrefixEndpointInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Prefix;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+
+public class FaasEndpointAug implements EpRendererAugmentation, AutoCloseable {
+
+    private EpRendererAugmentationRegistry epRendererAugmentationRegistry;
+
+    public FaasEndpointAug(EpRendererAugmentationRegistry epRendererAugmentationRegistry) {
+
+        this.epRendererAugmentationRegistry = epRendererAugmentationRegistry;
+        epRendererAugmentationRegistry.register(this);
+    }
+
+    @Override
+    public Map.Entry<Class<? extends Augmentation<Endpoint>>, Augmentation<Endpoint>> buildEndpointAugmentation(
+            RegisterEndpointInput input) {
+        FaasEndpointContextBuilder pb;
+        FaasEndpointContextInput pix = input.getAugmentation(FaasEndpointContextInput.class);
+        if (pix == null) {
+            pb = new FaasEndpointContextBuilder();
+        } else {
+            pb = new FaasEndpointContextBuilder(pix);
+        }
+        return new SimpleImmutableEntry<Class<? extends Augmentation<Endpoint>>, Augmentation<Endpoint>>(
+                FaasEndpointContext.class, pb.build());
+
+    }
+
+    @Override
+    public Map.Entry<Class<? extends Augmentation<EndpointL3>>, Augmentation<EndpointL3>> buildEndpointL3Augmentation(
+            RegisterEndpointInput input) {
+        return null;
+    }
+
+    @Override
+    public Map.Entry<Class<? extends Augmentation<EndpointL3Prefix>>, Augmentation<EndpointL3Prefix>> buildL3PrefixEndpointAugmentation(
+            RegisterL3PrefixEndpointInput input) {
+        return null;
+    }
+
+    @Override
+    public void close() throws Exception {
+        epRendererAugmentationRegistry.unregister(this);
+    }
+}
index ea574641927c907831fce985cedb91ca7576dfbb..f78fb56378ae3ee8e1854d63cf30d42e19f4ab62 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
@@ -10,55 +10,112 @@ package org.opendaylight.groupbasedpolicy.renderer.faas;
 
 import static com.google.common.base.Preconditions.checkNotNull;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.ScheduledExecutorService;
 
 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.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.AsyncDataChangeEvent;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.faas.uln.datastore.api.UlnDatastoreApi;
+import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
 import org.opendaylight.groupbasedpolicy.util.IidFactory;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.faas.endpoint.rev151009.FaasEndpointContext;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.common.rev151013.Text;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.common.rev151013.Uuid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.endpoints.locations.rev151013.endpoints.locations.container.endpoints.locations.EndpointLocationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.ports.rev151013.ports.container.ports.port.PrivateIps;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.ports.rev151013.ports.container.ports.port.PrivateIpsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2BridgeDomainId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubnetId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.fields.L3Address;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Prefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.mapped.tenants.entities.mapped.entity.MappedEndpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.mapped.tenants.entities.mapped.entity.MappedEndpointBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.mapped.tenants.entities.mapped.entity.MappedEndpointKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.mapped.tenants.entities.mapped.entity.MappedSubnet;
 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 FaasEndpointManagerListener implements DataChangeListener, AutoCloseable {
 
     private static final Logger LOG = LoggerFactory.getLogger(FaasEndpointManagerListener.class);
-
+    private final ScheduledExecutorService executor;
     private final ListenerRegistration<DataChangeListener> registerListener;
+    private final FaasPolicyManager policyManager;
+    private final DataBroker dataProvider;
 
-    public FaasEndpointManagerListener(DataBroker dataProvider) {
+    public FaasEndpointManagerListener(FaasPolicyManager policyManager, DataBroker dataProvider,
+            ScheduledExecutorService executor) {
+        this.executor = executor;
+        this.policyManager = policyManager;
+        this.dataProvider = dataProvider;
         this.registerListener = checkNotNull(dataProvider).registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
                 IidFactory.endpointsIidWildcard(), this, AsyncDataBroker.DataChangeScope.SUBTREE);
     }
 
     @Override
-    public void onDataChanged(AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+    public void close() throws Exception {
+        if (registerListener != null)
+            registerListener.close();
+    }
+
+    @Override
+    public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+        executor.execute(new Runnable() {
+
+            public void run() {
+                executeEvent(change);
+            }
+        });
+    }
+
+    private void executeEvent(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+
         // Create
         for (DataObject dao : change.getCreatedData().values()) {
             if (dao instanceof Endpoint) {
-                LOG.debug("Created Endpoint {}", (Endpoint) dao);
+                Endpoint endpoint = (Endpoint) dao;
+                LOG.debug("Created Endpoint {}", endpoint);
+                if (validate(endpoint)) {
+                    policyManager.registerTenant(endpoint.getTenant(), endpoint.getEndpointGroup());
+                    processEndpoint(endpoint);
+                }
             } else if (dao instanceof EndpointL3) {
                 LOG.debug("Created EndpointL3 {}", (EndpointL3) dao);
             } else if (dao instanceof EndpointL3Prefix) {
-                LOG.debug("Created EndpointL3Prefix {}", (EndpointL3Prefix) dao);
+                LOG.warn("Not Handled Event Yet by Faas Renderer. Created EndpointL3Prefix {}", (EndpointL3Prefix) dao);
             }
         }
         // Update
         Map<InstanceIdentifier<?>, DataObject> dao = change.getUpdatedData();
         for (Map.Entry<InstanceIdentifier<?>, DataObject> entry : dao.entrySet()) {
             if (entry.getValue() instanceof Endpoint) {
-                LOG.debug("Updated Endpoint {}", (Endpoint) dao);
+                Endpoint endpoint = (Endpoint) dao;
+                LOG.debug("Updated Endpoint {}", endpoint);
+                if (validate(endpoint)) {
+                    policyManager.registerTenant(endpoint.getTenant(), endpoint.getEndpointGroup());
+                    processEndpoint(endpoint);
+                }
             } else if (entry.getValue() instanceof EndpointL3) {
                 LOG.debug("Updated EndpointL3 {}", (EndpointL3) dao);
             } else if (entry.getValue() instanceof EndpointL3Prefix) {
-                LOG.debug("Updated EndpointL3Prefix {}", (EndpointL3Prefix) dao);
+                LOG.warn("Not Handled Event Yet by Faas Renderer. Updated EndpointL3Prefix {}", (EndpointL3Prefix) dao);
             }
         }
         // Remove
@@ -68,18 +125,162 @@ public class FaasEndpointManagerListener implements DataChangeListener, AutoClos
                 continue;
             }
             if (old instanceof Endpoint) {
-                LOG.debug("Removed Endpoint {}", (Endpoint) old);
+                Endpoint endpoint = (Endpoint) dao;
+                LOG.debug("Removed Endpoint {}", endpoint);
+                removeFaasEndpointLocationIfExist(endpoint.getTenant(), endpoint.getL2Context(),
+                        endpoint.getMacAddress());
             } else if (old instanceof EndpointL3) {
-                LOG.debug("Removed EndpointL3 {}", (EndpointL3) old);
+                EndpointL3 endpoint = (EndpointL3) dao;
+                LOG.debug("Removed EndpointL3 {}", endpoint);
+                removeFaasEndpointLocationIfExist(endpoint.getTenant(), endpoint.getL2Context(),
+                        endpoint.getMacAddress());
             } else if (old instanceof EndpointL3Prefix) {
-                LOG.debug("Removed EndpointL3Prefix {}", (EndpointL3Prefix) old);
+                LOG.warn("Not Handled Event Yet by Faas Renderer. Removed EndpointL3Prefix {}", (EndpointL3Prefix) old);
             }
         }
     }
 
-    @Override
-    public void close() throws Exception {
-        if (registerListener != null)
-            registerListener.close();
+    private void processEndpoint(Endpoint endpoint) {
+        Uuid tenantId = policyManager.getFaasTenantId(endpoint.getTenant());
+        if (tenantId == null) {
+            LOG.error("Failed Endpoint Registration. Couldn't find faas tenant Id. Endpoint {}", endpoint);
+            return;
+        }
+        EndpointLocationBuilder epLocBuilder = new EndpointLocationBuilder();
+        epLocBuilder.setDescription(new Text("gbp-endpoint"));
+        epLocBuilder.setName(new Text(endpoint.getL2Context().getValue()));
+        epLocBuilder.setTenantId(tenantId);
+        epLocBuilder.setFaasPortRefId(endpoint.getAugmentation(FaasEndpointContext.class).getFaasPortRefId());
+        Uuid epId = getFaasEndpointId(endpoint);
+        if (epId == null) {
+            LOG.error("Failed Endpoint registration. Couldn't Create Faas Endpoint Id");
+            return;
+        }
+        epLocBuilder.setUuid(epId);
+        Uuid faasSubnetId = getFaasSubnetId(endpoint);
+        List<PrivateIps> privateIpAddresses = new ArrayList<PrivateIps>();
+        for (L3Address ip : endpoint.getL3Address()) {
+            PrivateIpsBuilder ipBuilder = new PrivateIpsBuilder();
+            ipBuilder.setIpAddress(ip.getIpAddress());
+            ipBuilder.setSubnetId(faasSubnetId);
+            privateIpAddresses.add(ipBuilder.build());
+        }
+        if (!UlnDatastoreApi.attachEndpointToSubnet(epLocBuilder, faasSubnetId, endpoint.getMacAddress(),
+                privateIpAddresses, null)) {
+            LOG.error("Failed Endpoint Registration. Failed to Attach Endpoint to Faas Logical Network. Endpoint {}",
+                    endpoint);
+        }
+    }
+
+    private Uuid getFaasEndpointId(Endpoint endpoint) {
+        MappedEndpoint mEndpoint1 = getMappedEndpoint(endpoint);
+        if (mEndpoint1 != null) {
+            return mEndpoint1.getEndpointLocation();
+        }
+        synchronized (this) {// must be atomic
+            MappedEndpoint mEndpoint2 = getMappedEndpoint(endpoint);
+            if (mEndpoint2 != null) {
+                return mEndpoint2.getEndpointLocation();
+            }
+            MappedEndpointBuilder mBuilder = new MappedEndpointBuilder();
+            mBuilder.setL2Context(endpoint.getL2Context());
+            mBuilder.setMacAddress(endpoint.getMacAddress());
+            mBuilder.setEndpointLocation(new Uuid(UUID.randomUUID().toString()));
+            MappedEndpoint mEndpoint = mBuilder.build();
+            WriteTransaction wTx = dataProvider.newWriteOnlyTransaction();
+            wTx.put(LogicalDatastoreType.OPERATIONAL, FaasIidFactory.mappedEndpointIid(
+                    endpoint.getTenant(), new MappedEndpointKey(endpoint.getL2Context(), endpoint.getMacAddress())),
+                    mEndpoint);
+            if (DataStoreHelper.submitToDs(wTx)) {
+                LOG.debug("Cached in Datastore Mapped Endpoint {}", mEndpoint);
+                return mEndpoint.getEndpointLocation();
+            } else {
+                LOG.error("Couldn't Cache in Datastore Mapped Endpoint {}", mEndpoint);
+                return null;
+            }
+        }
+    }
+
+    private Uuid getFaasSubnetId(Endpoint endpoint) {
+        if (endpoint.getEndpointGroup() == null) {
+            LOG.error("Failed Endpoint registration -- No Endpoint-Group Id in endpoint {}", endpoint);
+            return null;
+        }
+        SubnetId subnetId = null;
+        if (endpoint.getNetworkContainment() != null) {
+            LOG.trace("Subnet is defined based on endpoint containment value {}", endpoint.getNetworkContainment()
+                .getValue());
+            subnetId = new SubnetId(endpoint.getNetworkContainment());
+        }
+        if (subnetId == null) {
+            LOG.error("Failed Endpoint registration -- Couldn't find a subnet for endpoint {}", endpoint.getKey());
+            return null;
+        }
+        LOG.debug("Using subnetId {} for endpoint {}", subnetId, endpoint.getKey());
+        policyManager.registerSubnetWithEpg(endpoint.getEndpointGroup(), endpoint.getTenant(), subnetId);
+
+        Optional<MappedSubnet> subnetOp = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
+                FaasIidFactory.mappedSubnetIid(endpoint.getTenant(), subnetId),
+                dataProvider.newReadWriteTransaction());
+        if (subnetOp.isPresent()) {
+            return subnetOp.get().getFaasSubnetId();
+        }
+        LOG.error("Failed Endpoint registration -- Couldn't find Mapped Subnet Id based on GBP Subnet Id {}", subnetId);
+        return null;
+    }
+
+    private boolean validate(Endpoint endpoint) {
+        if (endpoint.getL2Context() == null) {
+            LOG.error("Endpoint Failed Validation -- Missing L2 Context. Endpoint {}", endpoint);
+            return false;
+        }
+        if (endpoint.getL3Address() == null) {
+            LOG.error("Endpoint Failed Validation -- Missing L3 Address. Endpoint {}", endpoint);
+            return false;
+        }
+        if (endpoint.getMacAddress() == null) {
+            LOG.error("Endpoint Failed Validation -- Missing Mac Address. Endpoint {}", endpoint);
+            return false;
+        }
+        if (endpoint.getTenant() == null) {
+            LOG.error("Endpoint Failed Validation -- Missing Tenant Id. Endpoint {}", endpoint);
+            return false;
+        }
+        if (endpoint.getEndpointGroup() == null) {
+            LOG.error("Endpoint Failed Validation -- Missing Endpoint-Group. Endpoint {}", endpoint);
+            return false;
+        }
+        FaasEndpointContext faasEpAug = endpoint.getAugmentation(FaasEndpointContext.class);
+        if (faasEpAug == null || faasEpAug.getFaasPortRefId() == null) {
+            LOG.error("Endpoint Failed Validation -- Missing Required Faas Info. Endpoint {}", endpoint);
+            return false;
+        }
+        return true;
+    }
+
+    private void removeFaasEndpointLocationIfExist(TenantId tenantId, L2BridgeDomainId l2BridgeDomainId,
+            MacAddress macAddress) {
+        synchronized (this) {
+            MappedEndpointKey mappedEndpointKey = new MappedEndpointKey(l2BridgeDomainId, macAddress);
+            ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
+            Optional<MappedEndpoint> endpointOp = DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
+                    FaasIidFactory.mappedEndpointIid(tenantId, mappedEndpointKey), rwTx);
+            DataStoreHelper.submitToDs(rwTx);
+            if (endpointOp.isPresent()) {
+                UlnDatastoreApi.removeEndpointLocationFromDsIfExists(policyManager.getFaasTenantId(tenantId),
+                        endpointOp.get().getEndpointLocation());
+            }
+        }
+    }
+
+    private MappedEndpoint getMappedEndpoint(Endpoint endpoint) {
+        MappedEndpointKey mappedEndpointKey = new MappedEndpointKey(endpoint.getL2Context(), endpoint.getMacAddress());
+        Optional<MappedEndpoint> endpointOp = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
+                FaasIidFactory.mappedEndpointIid(endpoint.getTenant(), mappedEndpointKey),
+                dataProvider.newReadWriteTransaction());
+        if (endpointOp.isPresent()) {
+            return endpointOp.get();
+        }
+        return null;
     }
 }
diff --git a/renderers/faas/src/main/java/org/opendaylight/groupbasedpolicy/renderer/faas/FaasIidFactory.java b/renderers/faas/src/main/java/org/opendaylight/groupbasedpolicy/renderer/faas/FaasIidFactory.java
new file mode 100644 (file)
index 0000000..634e778
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * 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
+ */
+package org.opendaylight.groupbasedpolicy.renderer.faas;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContractId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubnetId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.LogicalNetworks;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.MappedTenantsEntities;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.logical.networks.LogicalNetwork;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.logical.networks.LogicalNetworkKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.mapped.tenants.entities.MappedEntity;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.mapped.tenants.entities.MappedEntityKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.mapped.tenants.entities.MappedTenant;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.mapped.tenants.entities.MappedTenantKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.mapped.tenants.entities.mapped.entity.MappedContract;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.mapped.tenants.entities.mapped.entity.MappedContractKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.mapped.tenants.entities.mapped.entity.MappedEndpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.mapped.tenants.entities.mapped.entity.MappedEndpointKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.mapped.tenants.entities.mapped.entity.MappedSubnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.mapped.tenants.entities.mapped.entity.MappedSubnetKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class FaasIidFactory {
+
+    public static InstanceIdentifier<LogicalNetworks> logicalNetworksIid() {
+        return InstanceIdentifier.builder(LogicalNetworks.class).build();
+    }
+
+    public static InstanceIdentifier<LogicalNetwork> logicalNetworkIid(EndpointGroupId consumerEpgId,
+            TenantId consumerTenantId, ContractId contractId, EndpointGroupId providerEpgId, TenantId providerTenantId) {
+        return InstanceIdentifier.builder(LogicalNetworks.class)
+            .child(LogicalNetwork.class,
+                    new LogicalNetworkKey(consumerEpgId, consumerTenantId, contractId, providerEpgId, providerTenantId))
+            .build();
+    }
+
+    public static InstanceIdentifier<MappedTenantsEntities> mappedTenantsEntitiesIid() {
+        return InstanceIdentifier.builder(MappedTenantsEntities.class).build();
+    }
+
+    public static InstanceIdentifier<MappedSubnet> mappedSubnetIid(TenantId gbpTenantId, SubnetId subnetId) {
+        return InstanceIdentifier.builder(MappedTenantsEntities.class)
+            .child(MappedEntity.class, new MappedEntityKey(gbpTenantId))
+            .child(MappedSubnet.class, new MappedSubnetKey(subnetId))
+            .build();
+    }
+
+    public static InstanceIdentifier<MappedTenant> mappedTenantIid(TenantId gbpTenantId) {
+        return InstanceIdentifier.builder(MappedTenantsEntities.class)
+            .child(MappedTenant.class, new MappedTenantKey(gbpTenantId))
+            .build();
+    }
+
+    public static InstanceIdentifier<MappedEntity> mappedEntityIid(TenantId gbpTenantId) {
+        return InstanceIdentifier.builder(MappedTenantsEntities.class)
+            .child(MappedEntity.class, new MappedEntityKey(gbpTenantId))
+            .build();
+    }
+
+    public static InstanceIdentifier<MappedContract> mappedContractIid(TenantId gbpTenantId, ContractId contractId) {
+        return InstanceIdentifier.builder(MappedTenantsEntities.class)
+            .child(MappedEntity.class, new MappedEntityKey(gbpTenantId))
+            .child(MappedContract.class, new MappedContractKey(contractId))
+            .build();
+    }
+
+    public static InstanceIdentifier<MappedEndpoint> mappedEndpointIid(TenantId gbpTenantId,
+            MappedEndpointKey mappedEndpointKey) {
+        return InstanceIdentifier.builder(MappedTenantsEntities.class)
+            .child(MappedEntity.class, new MappedEntityKey(gbpTenantId))
+            .child(MappedEndpoint.class, mappedEndpointKey)
+            .build();
+    }
+}
diff --git a/renderers/faas/src/main/java/org/opendaylight/groupbasedpolicy/renderer/faas/FaasPolicyManager.java b/renderers/faas/src/main/java/org/opendaylight/groupbasedpolicy/renderer/faas/FaasPolicyManager.java
new file mode 100644 (file)
index 0000000..17a57c4
--- /dev/null
@@ -0,0 +1,1062 @@
+/*
+ * 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
+ */
+package org.opendaylight.groupbasedpolicy.renderer.faas;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ScheduledExecutorService;
+
+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.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;
+import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
+import org.opendaylight.groupbasedpolicy.util.IidFactory;
+import org.opendaylight.groupbasedpolicy.util.TenantUtils;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.common.rev151013.Text;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.common.rev151013.Uuid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.logical.routers.rev151013.logical.routers.container.logical.routers.LogicalRouterBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.logical.switches.rev151013.logical.switches.container.logical.switches.LogicalSwitchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.ports.rev151013.PortLocationAttributes.LocationType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContextId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContractId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2BridgeDomainId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2FloodDomainId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L3ContextId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubnetId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.LogicalNetworks;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.ScopeType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.ServiceCommunicationLayer;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.logical.networks.LogicalNetwork;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.logical.networks.LogicalNetworkBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.logical.networks.logical.network.ConsumerNetworkBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.logical.networks.logical.network.ProviderNetworkBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.mapped.tenants.entities.MappedEntity;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.mapped.tenants.entities.MappedEntityBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.mapped.tenants.entities.MappedTenant;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.mapped.tenants.entities.MappedTenantBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.mapped.tenants.entities.mapped.entity.MappedContract;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.mapped.tenants.entities.mapped.entity.MappedSubnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.Tenant;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L2BridgeDomain;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L2FloodDomain;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L3Context;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.Subnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.Contract;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.EndpointGroup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.RendererName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.RendererBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.interests.followed.tenants.FollowedTenantBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.interests.followed.tenants.followed.tenant.FollowedEndpointGroup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.interests.followed.tenants.followed.tenant.FollowedEndpointGroupBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.ResolvedPolicies;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.resolved.policies.ResolvedPolicy;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.resolved.policies.ResolvedPolicy.ExternalImplicitGroup;
+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 {
+
+    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 DataBroker dataProvider;
+    private final Map<Pair<EndpointGroupId, TenantId>, List<SubnetId>> epgSubnetsMap = new HashMap<>();
+    private final ConcurrentHashMap<TenantId, Uuid> mappedTenants = new ConcurrentHashMap<>();
+    private final ConcurrentHashMap<TenantId, ArrayList<ListenerRegistration<DataChangeListener>>> registeredTenants = new ConcurrentHashMap<TenantId, ArrayList<ListenerRegistration<DataChangeListener>>>();
+
+    public FaasPolicyManager(DataBroker dataBroker, ScheduledExecutorService 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);
+
+        RendererBuilder rendBuilder = new RendererBuilder();
+        rendBuilder.setName(rendererName);
+        WriteTransaction wTx = dataProvider.newWriteOnlyTransaction();
+        wTx.put(LogicalDatastoreType.OPERATIONAL, IidFactory.rendererIid(rendererName), rendBuilder.build());
+        if (DataStoreHelper.submitToDs(wTx)) {
+            LOG.debug("{} renderer registered with the multi-renderer manager", rendererName.getValue());
+        } else {
+            LOG.error("{} renderer Failed to register with the multi-renderer manager", rendererName.getValue());
+        }
+    }
+
+    @Override
+    public void close() throws Exception {
+        synchronized (registeredTenants) {
+            for (ArrayList<ListenerRegistration<DataChangeListener>> list : registeredTenants.values()) {
+                for (ListenerRegistration<DataChangeListener> reg : list) {
+                    reg.close();
+                }
+            }
+            registeredTenants.clear();
+
+            LOG.debug("Closed All Tenant Registerations");
+        }
+        if (registerListener != null)
+            registerListener.close();
+    }
+
+    @Override
+    public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+        executor.execute(new Runnable() {
+
+            public void run() {
+                executeEvent(change);
+            }
+        });
+    }
+
+    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);
+                }
+            }
+        }
+
+        // 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);
+            }
+        }
+    }
+
+    public void registerTenant(TenantId gbpTenantId) {
+        registerTenant(gbpTenantId, null);
+    }
+
+    public void registerTenant(TenantId gbpTenantId, EndpointGroupId epgId) {
+        if (registeredTenants.get(gbpTenantId) != null) {
+            registerFollowedEndpointgroup(gbpTenantId, epgId);
+            return; // already registered
+        }
+        synchronized (this) {
+            if (registeredTenants.get(gbpTenantId) != null) {
+                return; // already registered
+            }
+            /*
+             * map tenant's required elements to faas logical networks
+             */
+            Optional<MappedTenant> mTenantOptional = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
+                    FaasIidFactory.mappedTenantIid(gbpTenantId), dataProvider.newReadOnlyTransaction());
+            Uuid faasTenantId;
+            if (mTenantOptional.isPresent()) {
+                faasTenantId = mTenantOptional.get().getFaasTenantId();
+            } else {
+                faasTenantId = getFaasTenantId(gbpTenantId);
+            }
+            // load tenant datastore info
+            Tenant tenant = null;
+            Optional<Tenant> tenantOptional = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
+                    TenantUtils.tenantIid(gbpTenantId), dataProvider.newReadOnlyTransaction());
+            if (tenantOptional.isPresent()) {
+                tenant = tenantOptional.get();
+            }
+            List<Contract> contracts = null;
+            List<Subnet> subnets = null;
+            if (tenant != null) {
+                contracts = tenant.getPolicy().getContract();
+                subnets = tenant.getForwardingContext().getSubnet();
+            }
+            Optional<MappedEntity> mEntityOptional = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
+                    FaasIidFactory.mappedEntityIid(gbpTenantId),
+                    dataProvider.newReadOnlyTransaction());
+            MappedEntity mappedEntity;
+            if (mEntityOptional.isPresent()) {
+                mappedEntity = mEntityOptional.get();
+            } else {
+                // This is needed as a workaround of a datastore problem
+                MappedEntityBuilder builder = new MappedEntityBuilder();
+                builder.setGbpTenantId(gbpTenantId);
+                mappedEntity = builder.build();
+                WriteTransaction wTx = dataProvider.newWriteOnlyTransaction();
+                wTx.put(LogicalDatastoreType.OPERATIONAL,
+                        FaasIidFactory.mappedEntityIid(gbpTenantId), mappedEntity);
+                if (DataStoreHelper.submitToDs(wTx)) {
+                    LOG.debug("Initailized Mapped Entry in Datastore for tenant {}", gbpTenantId);
+                } else {
+                    LOG.error("Couldn't Initailized Mapped Entry in Datastore for tenant {}", gbpTenantId);
+                }
+            }
+
+            // contracts
+            FaasContractManagerListener faasContractManagerListener = new FaasContractManagerListener(dataProvider,
+                    gbpTenantId, faasTenantId, executor);
+            faasContractManagerListener.loadAll(contracts, mappedEntity.getMappedContract());
+            // subnets
+            FaasSubnetManagerListener faasSubnetManagerListener = new FaasSubnetManagerListener(dataProvider,
+                    gbpTenantId, faasTenantId, executor);
+            faasSubnetManagerListener.loadAll(subnets, mappedEntity.getMappedSubnet());
+
+            /*
+             * tenant registrations
+             */
+            ArrayList<ListenerRegistration<DataChangeListener>> list = new ArrayList<ListenerRegistration<DataChangeListener>>();
+            ListenerRegistration<DataChangeListener> reg;
+            // contracts
+            reg = dataProvider.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
+                    IidFactory.contractWildcardIid(gbpTenantId), faasContractManagerListener, DataChangeScope.SUBTREE);
+            list.add(reg);
+            // subnets
+            reg = dataProvider.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
+                    IidFactory.subnetWildcardIid(gbpTenantId), faasSubnetManagerListener, DataChangeScope.SUBTREE);
+            list.add(reg);
+
+            // tenant
+            reg = dataProvider.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
+                    IidFactory.tenantIid(gbpTenantId), new FaasTenantManagerListener(this, gbpTenantId, faasTenantId,
+                            executor), DataChangeScope.BASE);
+            list.add(reg);
+
+            // Map previously resolved policy for this tenant
+            mapAllTenantResolvedPolicies(gbpTenantId, null);
+
+            registerFollowedTenant(gbpTenantId, epgId);
+
+            // track all registrations
+            registeredTenants.put(gbpTenantId, list);
+
+            LOG.debug("Registered tenant {}", gbpTenantId);
+        }
+    }
+
+    private void mapAllTenantResolvedPolicies(TenantId gbpTenantId, EndpointGroupId epgId) {
+        Optional<ResolvedPolicies> resolvedPoliciesOptional = DataStoreHelper.readFromDs(
+                LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.builder(ResolvedPolicies.class).build(),
+                dataProvider.newReadOnlyTransaction());
+        if (!resolvedPoliciesOptional.isPresent() || resolvedPoliciesOptional.get().getResolvedPolicy() == null) {
+            return;
+        }
+        List<ResolvedPolicy> resolvedPolicies = resolvedPoliciesOptional.get().getResolvedPolicy();
+        for (ResolvedPolicy policy : resolvedPolicies) {
+            if (policy.getConsumerTenantId().equals(gbpTenantId)) {
+                if (epgId == null || epgId.equals(policy.getConsumerEpgId()) || epgId.equals(policy.getProviderEpgId())) {
+                    // if any epg or a specific epg policy
+                    updateLogicalNetwork(policy);
+                }
+            }
+        }
+    }
+
+    private void registerFollowedTenant(TenantId gbpTenantId, EndpointGroupId epgId) {
+        FollowedTenantBuilder fTenantBuilder = new FollowedTenantBuilder();
+        fTenantBuilder.setId(gbpTenantId);
+        if (epgId != null) {
+            List<FollowedEndpointGroup> epgs = new ArrayList<>();
+            epgs.add(new FollowedEndpointGroupBuilder().setId(epgId).build());
+            fTenantBuilder.setFollowedEndpointGroup(epgs);
+        }
+        WriteTransaction wTx = dataProvider.newWriteOnlyTransaction();
+        wTx.put(LogicalDatastoreType.OPERATIONAL, IidFactory.followedTenantIid(rendererName, gbpTenantId),
+                fTenantBuilder.build());
+        if (DataStoreHelper.submitToDs(wTx)) {
+            LOG.info("Tenant {} is followed by renderer {}", gbpTenantId.getValue(), rendererName.getValue());
+        } else {
+            LOG.info("Couldn't register Tenant {} that is followed by renderer {}", gbpTenantId.getValue(),
+                    rendererName.getValue());
+        }
+    }
+
+    private void registerFollowedEndpointgroup(TenantId gbpTenantId, EndpointGroupId epgId) {
+        if (epgId == null) {
+            return;
+        }
+        FollowedEndpointGroupBuilder fEpgBuilder = new FollowedEndpointGroupBuilder();
+        fEpgBuilder.setId(epgId);
+        WriteTransaction wTx = dataProvider.newWriteOnlyTransaction();
+        wTx.put(LogicalDatastoreType.OPERATIONAL,
+                IidFactory.followedEndpointgroupIid(rendererName, gbpTenantId, epgId), fEpgBuilder.build());
+        if (DataStoreHelper.submitToDs(wTx)) {
+            LOG.trace("EPG {} in Tenant {} is followed by renderer {}", epgId.getValue(), gbpTenantId.getValue(),
+                    rendererName.getValue());
+        } else {
+            LOG.info("Couldn't register EPG {} in Tenant {} that is followed by renderer {}", epgId.getValue(),
+                    gbpTenantId.getValue(), rendererName.getValue());
+        }
+    }
+
+    public Uuid getFaasTenantId(TenantId tenantId) {
+        Uuid val = mappedTenants.get(tenantId);
+        if (val != null) {
+            return val;
+        }
+        Uuid faasTenantId = null;
+        if (isUUid(tenantId.getValue())) {
+            faasTenantId = new Uuid(tenantId.getValue());
+        } else {
+            faasTenantId = new Uuid(UUID.randomUUID().toString());
+        }
+        mappedTenants.putIfAbsent(tenantId, faasTenantId);
+        val = mappedTenants.get(tenantId);
+        MappedTenantBuilder builder = new MappedTenantBuilder();
+        builder.setFaasTenantId(val);
+        builder.setGbpTenantId(tenantId);
+        WriteTransaction wTx = dataProvider.newWriteOnlyTransaction();
+        MappedTenant result = builder.build();
+        wTx.put(LogicalDatastoreType.OPERATIONAL, FaasIidFactory.mappedTenantIid(tenantId), result);
+        if (DataStoreHelper.submitToDs(wTx)) {
+            LOG.debug("Cached in Datastore Mapped Tenant {}", result);
+        } else {
+            LOG.error("Couldn't Cache in Datastore Mapped Tenant {}", result);
+        }
+        return val;
+    }
+
+    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}"));
+    }
+
+    public void unregisterTenant(TenantId tenantId) {
+
+        ArrayList<ListenerRegistration<DataChangeListener>> list = registeredTenants.remove(tenantId);
+        if (list != null) {
+            for (ListenerRegistration<DataChangeListener> reg : list) {
+                reg.close();
+            }
+            LOG.debug("Unregistered tenant {}", tenantId);
+        }
+        registeredTenants.remove(tenantId);
+        Uuid faasTenantId = mappedTenants.get(tenantId);
+        if (faasTenantId != null) {
+            removeTenantLogicalNetwork(tenantId, faasTenantId, false);
+        }
+    }
+
+    public boolean isTenantRegistered(TenantId tenantId) {
+        return registeredTenants.containsKey(tenantId);
+    }
+
+    private boolean handledPolicy(ResolvedPolicy policy) {
+        if (!policy.getConsumerTenantId().equals(policy.getProviderTenantId())) {
+            // FAAS always assumes consumer and provider EPGs belong to the same tenant
+            LOG.warn(
+                    "Ignore Resolved Policy between Consumer EPG {} and Provider EPG {} becuase they belong to different Tenants",
+                    policy.getConsumerTenantId().getValue(), policy.getProviderTenantId().getValue());
+            return false;
+        }
+        if (!isTenantRegistered(policy.getConsumerTenantId())) {
+            return false;
+        }
+        return true;
+    }
+
+    private boolean isEqualService(ResolvedPolicy newPolicy, ResolvedPolicy oldPolicy) {
+        return oldPolicy != null && newPolicy.getConsumerEpgId().equals(oldPolicy.getConsumerEpgId())
+                && newPolicy.getProviderEpgId().equals(oldPolicy.getProviderEpgId())
+                && newPolicy.getConsumerTenantId().equals(oldPolicy.getConsumerTenantId())
+                && newPolicy.getProviderTenantId().equals(oldPolicy.getProviderTenantId());
+    }
+
+    public void registerSubnetWithEpg(EndpointGroupId epgId, TenantId tenantId, SubnetId subnetId) {
+        registerSubnetWithEpg(epgId, tenantId, subnetId, true);
+    }
+
+    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;
+                }
+            }
+            subnets.add(subnetId);
+            epgSubnetsMap.put(new Pair<>(epgId, tenantId), subnets);
+            LOG.debug("Registered Subnet {} with EPG {}", subnetId, epgId);
+            if (updateLn) {
+                mapAllTenantResolvedPolicies(tenantId, epgId);
+            }
+        }
+    }
+
+    private void removeLogicalNetwork(ResolvedPolicy oldPolicy) {
+        if (oldPolicy == null) {
+            return;
+        }
+        removeLogicalNetwork(oldPolicy.getConsumerEpgId(), oldPolicy.getConsumerTenantId(), getContractId(oldPolicy),
+                oldPolicy.getProviderEpgId(), oldPolicy.getProviderTenantId());
+    }
+
+    private void removeLogicalNetwork(EndpointGroupId consumerEpgId, TenantId consumerTenantId, ContractId contractId,
+            EndpointGroupId providerEpgId, TenantId providerTenantId) {
+        ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
+        Optional<LogicalNetwork> lnOp = DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
+                FaasIidFactory.logicalNetworkIid(consumerEpgId, consumerTenantId, contractId,
+                        providerEpgId, providerTenantId), rwTx);
+        if (lnOp.isPresent()) {
+            DataStoreHelper.submitToDs(rwTx);
+            LogicalNetwork logicalNetwork = lnOp.get();
+            Uuid consTenantId = getFaasTenantId(logicalNetwork.getConsumerTenantId());
+            Uuid provTenantId = getFaasTenantId(logicalNetwork.getProviderTenantId());
+
+            UlnDatastoreApi.removeLogicalSwitchFromDsIfExists(consTenantId, logicalNetwork.getConsumerNetwork()
+                .getLogicalSwitchId());
+            UlnDatastoreApi.removeLogicalSwitchFromDsIfExists(provTenantId, logicalNetwork.getProviderNetwork()
+                .getLogicalSwitchId());
+            if (logicalNetwork.getConsumerNetwork().getLogicalRouterId() != null) {
+                UlnDatastoreApi.removeLogicalRouterFromDsIfExists(consTenantId, logicalNetwork.getConsumerNetwork()
+                    .getLogicalRouterId());
+            }
+            if (logicalNetwork.getProviderNetwork().getLogicalRouterId() != null) {
+                UlnDatastoreApi.removeLogicalRouterFromDsIfExists(provTenantId, logicalNetwork.getProviderNetwork()
+                    .getLogicalRouterId());
+            }
+        }
+    }
+
+    private synchronized void updateLogicalNetwork(ResolvedPolicy policy) {
+        updateLogicalNetwork(policy.getConsumerEpgId(), getContractId(policy), policy.getProviderEpgId(),
+                policy.getConsumerTenantId(), policy.getExternalImplicitGroup());
+    }
+
+    private synchronized void updateLogicalNetwork(EndpointGroupId consumerEpgId, ContractId contractId,
+            EndpointGroupId providerEpgId, TenantId tenantId, ExternalImplicitGroup externalImplicitGroup) {
+
+        LOG.trace("Start updateLogicalNetwork: Consumer EPG {}   Provider Epg {}   Contract {}", consumerEpgId,
+                providerEpgId, contractId);
+
+        // Create Logical network
+        EndpointGroup consEpg = readEndpointGroup(consumerEpgId, tenantId);
+        if (consEpg == null) {
+            LOG.error("Couldn't Creat Logical Network. Missing EPG {}", consumerEpgId);
+            return;
+        }
+        List<SubnetId> consSubnetIds = cloneAndGetEpgSubnets(consEpg.getId(), tenantId);
+        if (consSubnetIds.isEmpty()) {
+            LOG.info("Couldn't Creat Logical Network. Missing Subnets for Consumer EPG {}", consumerEpgId);
+            return;
+        }
+        EndpointGroup provEpg = readEndpointGroup(providerEpgId, tenantId);
+        if (provEpg == null) {
+            LOG.error("Couldn't Creat Logical Network. Missing EPG {}", providerEpgId);
+            return;
+        }
+        List<SubnetId> provSubnetIds = cloneAndGetEpgSubnets(provEpg.getId(), tenantId);
+        if (provSubnetIds.isEmpty()) {
+            LOG.info("Couldn't Creat Logical Network. Missing Subnets for Provider EPG {}", providerEpgId);
+            return;
+        }
+
+        ServiceCommunicationLayer comLayer = findLayerNetwork(tenantId, consSubnetIds, provSubnetIds);
+        if (comLayer == null) {
+            LOG.error(
+                    "Couldn't determine forwarding Context. Couldn't Process Logical Network for Consumer EPG {}   Provider Epg {}   Contract {}",
+                    consumerEpgId, providerEpgId, contractId);
+            return;
+        }
+
+        if (needToCreateLogicalNetwork(comLayer, consSubnetIds, provSubnetIds, tenantId, contractId, provEpg, consEpg,
+                externalImplicitGroup)) {
+            if (comLayer == ServiceCommunicationLayer.Layer2) {
+                createLayer2LogicalNetwork(consEpg, contractId, provEpg, tenantId, comLayer, externalImplicitGroup);
+            } else if (comLayer == ServiceCommunicationLayer.Layer3) {
+                createLayer3LogicalNetwork(consEpg, contractId, provEpg, tenantId, comLayer, externalImplicitGroup);
+            } else {
+                LOG.error("Couldn't find the communication layer.Consumer EPG {}   Provider Epg {}   Contract {}",
+                        consumerEpgId, providerEpgId, contractId);
+            }
+        } else {
+            LOG.debug("No need to Create the Logical Network. Consumer EPG {}   Provider Epg {}   Contract {}",
+                    consumerEpgId, providerEpgId, contractId);
+        }
+    }
+
+    private boolean isConsumerPublic(ExternalImplicitGroup externalImplicitGroup) {
+        return externalImplicitGroup != null && externalImplicitGroup == ExternalImplicitGroup.ConsumerEpg;
+    }
+
+    private boolean isProviderPublic(ExternalImplicitGroup externalImplicitGroup) {
+        return externalImplicitGroup != null && externalImplicitGroup == ExternalImplicitGroup.ProviderEpg;
+    }
+
+    private List<SubnetId> cloneAndGetEpgSubnets(EndpointGroupId epgId, TenantId tenantId) {
+        synchronized (this) {
+            List<SubnetId> list1 = epgSubnetsMap.get(new Pair<>(epgId, tenantId));
+            if (list1 == null) {
+                return new ArrayList<>();
+            }
+            List<SubnetId> list2 = new ArrayList<>();
+            for (SubnetId id : list1) {
+                list2.add(new SubnetId(id));
+            }
+            return list2;
+        }
+    }
+
+    private void createLayer3LogicalNetwork(EndpointGroup consEpg, ContractId contractId, EndpointGroup provEpg,
+            TenantId gbpTenantId, ServiceCommunicationLayer comLayer, ExternalImplicitGroup externalImplicitGroup) {
+        LOG.trace("Start createLayer3LogicalNetwork: Consumer EPG {}   Provider Epg {}   Contract {}", consEpg.getId()
+            .getValue(), provEpg.getId().getValue(), contractId);
+        LogicalNetworkBuilder lNetbuilder = buildLayer2LogicalNetwork(consEpg, provEpg, gbpTenantId, null,
+                externalImplicitGroup);
+        if (lNetbuilder == null) {
+            LOG.error("Failed to create Logical Switchs layer on the Logical network");
+            return;
+        }
+        Uuid privateSecRulesId = getFaasSecRulesId(contractId, gbpTenantId);
+        if (privateSecRulesId == null) {
+            LOG.error(
+                    "Couldn't Create Logical Network because unable to find FAAS Security Rules Id based on GBP Contract {}",
+                    contractId);
+            return;
+        }
+
+        Uuid faasTenantId = getFaasTenantId(gbpTenantId);
+        LogicalRouterBuilder consLR = initLogicalRouterBuilder(consEpg, faasTenantId,
+                isConsumerPublic(externalImplicitGroup));
+        LogicalRouterBuilder provLR = initLogicalRouterBuilder(provEpg, faasTenantId,
+                isProviderPublic(externalImplicitGroup));
+
+        if (!UlnDatastoreApi.attachAndSubmitToDs(consLR, provLR, new Pair<Uuid, Uuid>(null, privateSecRulesId), null)) {
+            LOG.error("Failed to join Logical Routers in a Logical Network");
+            return;
+        }
+
+        if (!UlnDatastoreApi.attachAndSubmitToDs(consLR.getUuid(), lNetbuilder.getConsumerNetwork()
+            .getLogicalSwitchId(), faasTenantId, new Pair<>(LocationType.RouterType, LocationType.SwitchType))) {
+            LOG.error("Failed to join Consumer Logical Router to Logical Switch in a Logical Network");
+            return;
+        }
+        LOG.debug("Attached Consumer Router {} to Consumer Switch {}", consLR.getUuid().getValue(),
+                lNetbuilder.getConsumerNetwork().getLogicalSwitchId().getValue());
+        if (!UlnDatastoreApi.attachAndSubmitToDs(provLR.getUuid(), lNetbuilder.getProviderNetwork()
+            .getLogicalSwitchId(), faasTenantId, new Pair<>(LocationType.RouterType, LocationType.SwitchType))) {
+            LOG.error("Failed to join Provider Logical Router to Logical Switch in a Logical Network");
+            return;
+        }
+        LOG.debug("Attached Provider Router {} to Provider Switch {}", provLR.getUuid().getValue(),
+                lNetbuilder.getProviderNetwork().getLogicalSwitchId().getValue());
+        ConsumerNetworkBuilder cNetBuilder = new ConsumerNetworkBuilder(lNetbuilder.getConsumerNetwork());
+        cNetBuilder.setLogicalRouterId(consLR.getUuid());
+        lNetbuilder.setConsumerNetwork(cNetBuilder.build());
+        ProviderNetworkBuilder pNetBuilder = new ProviderNetworkBuilder(lNetbuilder.getProviderNetwork());
+        pNetBuilder.setLogicalRouterId(provLR.getUuid());
+        lNetbuilder.setProviderNetwork(pNetBuilder.build());
+        lNetbuilder.setContractId(contractId);
+        lNetbuilder.setContractTenantId(gbpTenantId);
+        LogicalNetwork result = lNetbuilder.build();
+        WriteTransaction wTx = dataProvider.newWriteOnlyTransaction();
+        InstanceIdentifier<LogicalNetwork> iid = FaasIidFactory.logicalNetworkIid(
+                consEpg.getId(), gbpTenantId, contractId, provEpg.getId(), gbpTenantId);
+        wTx.put(LogicalDatastoreType.OPERATIONAL, iid, result);
+        if (DataStoreHelper.submitToDs(wTx)) {
+            LOG.debug("Cached in Datastore Mapped Logical Network {}", result);
+        } else {
+            LOG.error("Couldn't Cache in Datastore Mapped Logical Network {}", result);
+        }
+        LOG.debug("Created Layer 3 Logical network consEpg {}, contractId {}, provEpg {}", consEpg.getId().getValue(),
+                contractId.getValue(), provEpg.getId().getValue());
+    }
+
+    private void createLayer2LogicalNetwork(EndpointGroup consEpg, ContractId contractId, EndpointGroup provEpg,
+            TenantId gbpTenantId, ServiceCommunicationLayer comLayer, ExternalImplicitGroup externalImplicitGroup) {
+        LOG.trace("Start createLayer2LogicalNetwork: Consumer EPG {}   Provider Epg {}   Contract {}", consEpg.getId()
+            .getValue(), provEpg.getId().getValue(), contractId);
+        Uuid secRulesId = getFaasSecRulesId(contractId, gbpTenantId);
+        if (secRulesId == null) {
+            LOG.error(
+                    "Couldn't Create Logical Network because unable to find FAAS Security Rules Id based on GBP Contract {}",
+                    contractId);
+            return;
+        }
+        LogicalNetworkBuilder lNetbuilder = buildLayer2LogicalNetwork(consEpg, provEpg, gbpTenantId, secRulesId,
+                externalImplicitGroup);
+        if (lNetbuilder == null) {
+            LOG.error("Failed to create Logical Switchs layer on the Logical network");
+            return;
+        }
+
+        if (isConsumerPublic(externalImplicitGroup)) {
+            Uuid faasTenantId = getFaasTenantId(gbpTenantId);
+            LogicalRouterBuilder consLR = initLogicalRouterBuilder(consEpg, faasTenantId, true);
+            UlnDatastoreApi.submitLogicalRouterToDs(consLR.build());
+            ConsumerNetworkBuilder cNetBuilder = new ConsumerNetworkBuilder(lNetbuilder.getConsumerNetwork());
+            cNetBuilder.setLogicalRouterId(consLR.getUuid());
+            lNetbuilder.setConsumerNetwork(cNetBuilder.build());
+            if (!UlnDatastoreApi.attachAndSubmitToDs(consLR.getUuid(), lNetbuilder.getConsumerNetwork()
+                .getLogicalSwitchId(), faasTenantId, new Pair<>(LocationType.RouterType, LocationType.SwitchType),
+                    null, null)) {
+                LOG.error("Failed to join Consumer Public Logical Router to Logical Switch in a Logical Network");
+            }
+            LOG.debug("Attached Consumer Public Router {} to Consumer Switch {}", consLR.getUuid().getValue(),
+                    lNetbuilder.getConsumerNetwork().getLogicalSwitchId().getValue());
+        }
+        if (isProviderPublic(externalImplicitGroup)) {
+            Uuid faasTenantId = getFaasTenantId(gbpTenantId);
+            LogicalRouterBuilder provLR = initLogicalRouterBuilder(provEpg, faasTenantId, true);
+            provLR.setPublic(true);
+            UlnDatastoreApi.submitLogicalRouterToDs(provLR.build());
+            ProviderNetworkBuilder cNetBuilder = new ProviderNetworkBuilder(lNetbuilder.getProviderNetwork());
+            cNetBuilder.setLogicalRouterId(provLR.getUuid());
+            lNetbuilder.setProviderNetwork(cNetBuilder.build());
+            if (!UlnDatastoreApi.attachAndSubmitToDs(provLR.getUuid(), lNetbuilder.getProviderNetwork()
+                .getLogicalSwitchId(), faasTenantId, new Pair<>(LocationType.RouterType, LocationType.SwitchType),
+                    null, null)) {
+                LOG.error("Failed to join Provider Public Logical Router to Logical Switch in a Logical Network");
+            }
+            LOG.debug("Attached Provider Public Router {} to Provider Switch {}", provLR.getUuid().getValue(),
+                    lNetbuilder.getProviderNetwork().getLogicalSwitchId().getValue());
+        }
+
+        lNetbuilder.setContractId(contractId);
+        lNetbuilder.setContractTenantId(gbpTenantId);
+        LogicalNetwork result = lNetbuilder.build();
+        WriteTransaction wTx = dataProvider.newWriteOnlyTransaction();
+        InstanceIdentifier<LogicalNetwork> iid = FaasIidFactory.logicalNetworkIid(
+                consEpg.getId(), gbpTenantId, contractId, provEpg.getId(), gbpTenantId);
+        wTx.put(LogicalDatastoreType.OPERATIONAL, iid, result);
+        if (DataStoreHelper.submitToDs(wTx)) {
+            LOG.debug("Cached in Datastore Mapped Logical Network {}", result);
+        } else {
+            LOG.error("Couldn't Cache in Datastore Mapped Logical Network {}", result);
+        }
+        LOG.debug("Created Layer 2 Logical network consEpg {}, contractId {}, provEpg {}", consEpg.getId().getValue(),
+                contractId.getValue(), provEpg.getId().getValue());
+    }
+
+    private LogicalNetworkBuilder buildLayer2LogicalNetwork(EndpointGroup consEpg, EndpointGroup provEpg,
+            TenantId gbpTenantId, Uuid layer2SecRulesId, ExternalImplicitGroup externalImplicitGroup) {
+        LOG.trace("Start buildLayer2LogicalNetwork: Consumer EPG {}   Provider Epg {}", consEpg.getId().getValue(),
+                provEpg.getId().getValue());
+        List<SubnetId> consSubnetIds = cloneAndGetEpgSubnets(consEpg.getId(), gbpTenantId);
+        List<Uuid> consFaasSubnetIds = new ArrayList<>();
+        for (SubnetId subnetId : consSubnetIds) {
+            Uuid id = getFaasSubnetId(subnetId, gbpTenantId);
+            if (id != null) {
+                LOG.trace("Added to Consumer Network Faas Subnet {}", id.getValue());
+                consFaasSubnetIds.add(id);
+            }
+        }
+        if (consFaasSubnetIds.isEmpty()) {
+            LOG.error("Couldn't find Faas subnets based on EPG {} -- Unable to create Layer2 Logical Network",
+                    consEpg.getId().getValue());
+            return null;
+        }
+        List<SubnetId> provSubnetIds = cloneAndGetEpgSubnets(provEpg.getId(), gbpTenantId);
+        List<Uuid> provFaasSubnetIds = new ArrayList<>();
+        for (SubnetId subnetId : provSubnetIds) {
+            Uuid id = getFaasSubnetId(subnetId, gbpTenantId);
+            if (id != null) {
+                LOG.trace("Added to Provider Network Faas Subnet {}", id.getValue());
+                provFaasSubnetIds.add(id);
+            }
+        }
+        if (provFaasSubnetIds.isEmpty()) {
+            LOG.error("Couldn't find Faas subnets based on EPG {} -- Unable to create Layer2 Logical Network",
+                    provEpg.getId().getValue());
+            return null;
+        }
+        Uuid faasTenantId = getFaasTenantId(gbpTenantId);
+        LogicalSwitchBuilder consLS = initLogicalSwitchBuilder(consEpg, faasTenantId);
+        LogicalSwitchBuilder provLS = initLogicalSwitchBuilder(provEpg, faasTenantId);
+        if (layer2SecRulesId != null) {
+            if (!UlnDatastoreApi.attachAndSubmitToDs(consLS, provLS, new Pair<Uuid, Uuid>(null, layer2SecRulesId))) {
+                LOG.error("Failed to join Logical Switches in a Logical Network");
+                return null;
+            }
+        } else {
+            UlnDatastoreApi.submitLogicalSwitchToDs(consLS.build());
+            UlnDatastoreApi.submitLogicalSwitchToDs(provLS.build());
+        }
+        for (Uuid subnetId : consFaasSubnetIds) {
+            if (!UlnDatastoreApi.attachAndSubmitToDs(consLS.getUuid(), subnetId, consLS.getTenantId(), new Pair<>(
+                    LocationType.SwitchType, LocationType.SubnetType))) {
+                LOG.error("Failed to join Consumer Logical Switch with Subnet {} in a Logical Network", subnetId);
+                return null;
+            }
+            LOG.debug("Attached Consumer Switch {} to Subnet {}", consLS.getUuid().getValue(), subnetId.getValue());
+        }
+        for (Uuid subnetId : provFaasSubnetIds) {
+            if (!UlnDatastoreApi.attachAndSubmitToDs(provLS.getUuid(), subnetId, provLS.getTenantId(), new Pair<>(
+                    LocationType.SwitchType, LocationType.SubnetType))) {
+                LOG.error("Failed to join Provider Logical Switch with Subnet {} in a Logical Network", subnetId);
+                return null;
+            }
+            LOG.debug("Attached Provider Switch {} to Subnet {}", provLS.getUuid().getValue(), subnetId.getValue());
+        }
+        LogicalNetworkBuilder lNetbuilder = new LogicalNetworkBuilder();
+        lNetbuilder.setConsumerEpgId(consEpg.getId());
+        lNetbuilder.setConsumerTenantId(gbpTenantId);
+        lNetbuilder.setContractTenantId(gbpTenantId);
+        lNetbuilder.setProviderEpgId(provEpg.getId());
+        lNetbuilder.setProviderTenantId(gbpTenantId);
+        ConsumerNetworkBuilder cNetBuilder = new ConsumerNetworkBuilder();
+        cNetBuilder.setLogicalSwitchId(consLS.getUuid());
+        cNetBuilder.setGbpSubnetId(consSubnetIds);
+        if (isConsumerPublic(externalImplicitGroup)) {
+            cNetBuilder.setNetworkScopeType(ScopeType.Public);
+        } else {
+            cNetBuilder.setNetworkScopeType(ScopeType.Private);
+        }
+        lNetbuilder.setConsumerNetwork(cNetBuilder.build());
+        ProviderNetworkBuilder pNetBuilder = new ProviderNetworkBuilder();
+        pNetBuilder.setLogicalSwitchId(provLS.getUuid());
+        pNetBuilder.setGbpSubnetId(provSubnetIds);
+        if (isProviderPublic(externalImplicitGroup)) {
+            pNetBuilder.setNetworkScopeType(ScopeType.Public);
+        } else {
+            pNetBuilder.setNetworkScopeType(ScopeType.Private);
+        }
+        lNetbuilder.setProviderNetwork(pNetBuilder.build());
+
+        return lNetbuilder;
+
+    }
+
+    private Uuid getFaasSubnetId(SubnetId subnetId, TenantId gbpTenantId) {
+        if (subnetId != null) {
+            Optional<MappedSubnet> mSubnetOp = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
+                    FaasIidFactory.mappedSubnetIid(gbpTenantId, subnetId),
+                    dataProvider.newReadOnlyTransaction());
+            if (mSubnetOp.isPresent()) {
+                return mSubnetOp.get().getFaasSubnetId();
+            }
+        }
+        return null;
+    }
+
+    private Uuid getFaasSecRulesId(ContractId contractId, TenantId gbpTenantId) {
+        if (contractId != null) {
+            Optional<MappedContract> mContractOp = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
+                    FaasIidFactory.mappedContractIid(gbpTenantId, contractId),
+                    dataProvider.newReadOnlyTransaction());
+            if (mContractOp.isPresent()) {
+                return mContractOp.get().getFaasSecurityRulesId();
+            }
+        }
+        return null;
+    }
+
+    private LogicalRouterBuilder initLogicalRouterBuilder(EndpointGroup epg, Uuid tenantId, boolean isPublic) {
+        LogicalRouterBuilder builder = new LogicalRouterBuilder();
+        builder.setAdminStateUp(true);
+        builder.setName(new Text(epg.getId().getValue()));
+        if (epg.getDescription() != null)
+            builder.setDescription(new Text("gbp-epg: " + epg.getDescription().getValue()));
+        else
+            builder.setDescription(new Text("gbp-epg"));
+        builder.setPublic(isPublic);
+        builder.setTenantId(tenantId);
+        builder.setUuid(new Uuid(UUID.randomUUID().toString()));
+        return builder;
+    }
+
+    private LogicalSwitchBuilder initLogicalSwitchBuilder(EndpointGroup epg, Uuid tenantId) {
+        LogicalSwitchBuilder builder = new LogicalSwitchBuilder();
+        builder.setAdminStateUp(true);
+        builder.setName(new Text(epg.getId().getValue()));
+        if (epg.getDescription() != null)
+            builder.setDescription(new Text("gbp-epg: " + epg.getDescription().getValue()));
+        else
+            builder.setDescription(new Text("gbp-epg"));
+        builder.setTenantId(tenantId);
+        builder.setUuid(new Uuid(UUID.randomUUID().toString()));
+        return builder;
+    }
+
+    private 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,
+                FaasIidFactory.logicalNetworkIid(consumerEpg.getId(), tenantId, contractId,
+                        providerEpg.getId(), tenantId), dataProvider.newReadOnlyTransaction());
+        if (!lnOp.isPresent()) {
+            return true;
+        }
+        LogicalNetwork logicalNet = lnOp.get();
+        if (!comLayer.equals(logicalNet.getCommunicationLayer())) {
+            return true;
+        }
+
+        boolean isConsPublic = logicalNet.getConsumerNetwork().getNetworkScopeType() != null
+                && logicalNet.getConsumerNetwork().getNetworkScopeType() == ScopeType.Public;
+        if (isConsumerPublic(externalImplicitGroup) != isConsPublic) {
+            return true;
+        }
+        boolean isProvPublic = logicalNet.getProviderNetwork().getNetworkScopeType() != null
+                && logicalNet.getProviderNetwork().getNetworkScopeType() == ScopeType.Public;
+        if (isProviderPublic(externalImplicitGroup) != isProvPublic) {
+            return true;
+        }
+        Set<SubnetId> lnConsSubnets = new HashSet<>(logicalNet.getConsumerNetwork().getGbpSubnetId());
+        if (lnConsSubnets.size() != consSubnetIds.size() || !lnConsSubnets.containsAll(consSubnetIds)) {
+            return true;
+        }
+        Set<SubnetId> lnProvSubnets = new HashSet<>(logicalNet.getProviderNetwork().getGbpSubnetId());
+        if (lnProvSubnets.size() != provSubnetIds.size() || !lnProvSubnets.containsAll(provSubnetIds)) {
+            return true;
+        }
+        return false;
+    }
+
+    private ServiceCommunicationLayer findLayerNetwork(TenantId tenantId, List<SubnetId> consSubnetIds,
+            List<SubnetId> provSubnetIds) {
+        Subnet consSubnet = null;
+        Subnet provSubnet = null;
+        ContextId contextId = null;
+        for (SubnetId subnetId : consSubnetIds) {
+            consSubnet = readSubnet(subnetId, tenantId);
+            if (consSubnet == null) {
+                LOG.error("Couldn't find subnet {} in datastore", subnetId);
+                return null;
+            }
+            if (consSubnet.getParent() == null) {
+                LOG.error("Flood domain is set to NULL in subnet " + consSubnet.getId());
+                return null;
+            }
+            if (contextId == null) {
+                contextId = consSubnet.getParent();
+            } else if (!contextId.equals(consSubnet.getParent())) {
+                LOG.error("Flood domain is not the same for all Network domains in the Consumer EPG ");
+                return null;
+            }
+        }
+
+        contextId = null;
+        for (SubnetId subnetId : provSubnetIds) {
+            provSubnet = readSubnet(subnetId, tenantId);
+            if (provSubnet == null) {
+                LOG.error("Couldn't find subnet {} in datastore", subnetId);
+                return null;
+            }
+            if (provSubnet.getParent() == null) {
+                LOG.error("Flood domain is set to NULL in subnet " + provSubnet.getId());
+                return null;
+            }
+            if (contextId == null) {
+                contextId = provSubnet.getParent();
+            } else if (!contextId.equals(provSubnet.getParent())) {
+                LOG.error("Flood domain is not the same for all Network domains in the Provider EPG ");
+                return null;
+            }
+        }
+
+        if (consSubnet == null || provSubnet == null) {
+            LOG.error("Couldn't find Consumer and/or Provider subnets");
+            return null;
+        }
+
+        L2FloodDomainId consL2FldId = new L2FloodDomainId(consSubnet.getParent().getValue());
+        L2FloodDomain consFloodDomain = readL2FloodDomain(consL2FldId, tenantId);
+        if (consFloodDomain == null) {
+            LOG.error("Couldn't find flood domain instance in datastore with id " + consL2FldId);
+            return null;
+        }
+        L2FloodDomainId provL2FldId = new L2FloodDomainId(provSubnet.getParent().getValue());
+        L2FloodDomain provFloodDomain = readL2FloodDomain(provL2FldId, tenantId);
+        if (provFloodDomain == null) {
+            LOG.error("Couldn't find flood domain instance in datastore with id " + provL2FldId);
+            return null;
+        }
+
+        if (consFloodDomain.equals(provFloodDomain)) {
+            return ServiceCommunicationLayer.Layer2;
+        }
+
+        if (consFloodDomain.getParent() == null) {
+            LOG.error("Bridge domain is set to NULL in flood domain " + consFloodDomain.getId());
+            return null;
+        }
+        if (provFloodDomain.getParent() == null) {
+            LOG.error("Bridge domain is set to NULL in flood domain " + provFloodDomain.getId());
+            return null;
+        }
+
+        L2BridgeDomain consBridgeDomain = readL2BridgeDomainInstance(tenantId, consFloodDomain.getParent());
+        if (consBridgeDomain == null) {
+            LOG.error("Couldn't find bridge domain instance in datastore with id " + consFloodDomain.getParent());
+            return null;
+        }
+        L2BridgeDomain provBridgeDomain = readL2BridgeDomainInstance(tenantId, provFloodDomain.getParent());
+        if (provBridgeDomain == null) {
+            LOG.error("Couldn't find bridge domain instance in datastore with id " + provFloodDomain.getParent());
+            return null;
+        }
+        if (consBridgeDomain.equals(provBridgeDomain)) {
+            return ServiceCommunicationLayer.Layer2;
+        }
+
+        L3Context consL3ContextDomain = readL3ContextInstance(tenantId, consBridgeDomain.getParent());
+        if (consL3ContextDomain == null) {
+            LOG.error("Couldn't find L3 context instance in datastore with id " + consBridgeDomain.getParent());
+            return null;
+        }
+        L3Context provL3ContextDomain = readL3ContextInstance(tenantId, provBridgeDomain.getParent());
+        if (provL3ContextDomain == null) {
+            LOG.error("Couldn't find L3 context instance in datastore with id " + provBridgeDomain.getParent());
+            return null;
+        }
+        if (consL3ContextDomain.equals(provL3ContextDomain)) {
+            return ServiceCommunicationLayer.Layer3;
+        }
+        return null;
+    }
+
+    private 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);
+        if (!l2Op.isPresent()) {
+            LOG.error("Couldn't find L3 Context Domain {} which belongs to Tenant {}", l3cId, tenantId);
+            rTx.close();
+            return null;
+        }
+        return l2Op.get();
+    }
+
+    private 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);
+        if (!l2Op.isPresent()) {
+            LOG.error("Couldn't find L2 Brdge Domain {} which belongs to Tenant {}", l2bId, tenantId);
+            rTx.close();
+            return null;
+        }
+        return l2Op.get();
+    }
+
+    private 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);
+        if (!l2Op.isPresent()) {
+            LOG.error("Couldn't find L2 Flood Domain {} which belongs to Tenant {}", l2fId, tenantId);
+            rTx.close();
+            return null;
+        }
+        return l2Op.get();
+    }
+
+    public Subnet readSubnet(SubnetId subnetId, TenantId tenantId) {
+        ReadOnlyTransaction rTx = dataProvider.newReadOnlyTransaction();
+        InstanceIdentifier<Subnet> iid = IidFactory.subnetIid(tenantId, subnetId);
+        Optional<Subnet> subnetOp = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION, iid, rTx);
+        if (!subnetOp.isPresent()) {
+            LOG.warn("Couldn't find Subnet {} which belongs to Tenant {}", subnetId, tenantId);
+            rTx.close();
+            return null;
+        }
+        return subnetOp.get();
+    }
+
+    public EndpointGroup readEndpointGroup(EndpointGroupId epgId, TenantId tenantId) {
+        ReadOnlyTransaction rTx = dataProvider.newReadOnlyTransaction();
+        InstanceIdentifier<EndpointGroup> iid = IidFactory.endpointGroupIid(tenantId, epgId);
+        Optional<EndpointGroup> epgOp = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION, iid, rTx);
+        if (!epgOp.isPresent()) {
+            LOG.warn("Couldn't find EPG {} which belongs to Tenant {}", epgId, tenantId);
+            rTx.close();
+            return null;
+        }
+        return epgOp.get();
+    }
+
+    private ContractId getContractId(ResolvedPolicy policy) {
+        for (PolicyRuleGroupWithEndpointConstraints prgwec : policy.getPolicyRuleGroupWithEndpointConstraints()) {
+            for (PolicyRuleGroup prg : prgwec.getPolicyRuleGroup()) {
+                return prg.getContractId();
+            }
+        }
+        return null;
+    }
+
+    public void removeTenantLogicalNetwork(TenantId gbpTenantId, Uuid faasTenantId) {
+        removeTenantLogicalNetwork(gbpTenantId, faasTenantId, true);
+    }
+
+    private void removeTenantLogicalNetwork(TenantId gbpTenantId, Uuid faasTenantId, boolean unregister) {
+        UlnDatastoreApi.removeTenantFromDsIfExists(faasTenantId);
+        synchronized (this) {
+            mappedTenants.remove(gbpTenantId);
+            Optional<LogicalNetworks> op3 = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
+                    FaasIidFactory.logicalNetworksIid(), dataProvider.newReadOnlyTransaction());
+            if (op3.isPresent()) {
+                LogicalNetworks logicalNetworks = op3.get();
+                for (LogicalNetwork ln : logicalNetworks.getLogicalNetwork()) {
+                    if (ln.getConsumerTenantId().equals(gbpTenantId) || ln.getProviderTenantId().equals(gbpTenantId)) {
+                        removeLogicalNetwork(ln.getConsumerEpgId(), ln.getConsumerTenantId(), ln.getContractId(),
+                                ln.getProviderEpgId(), ln.getProviderTenantId());
+                    }
+                }
+            }
+            boolean toSubmit = false;
+            ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
+            Optional<MappedEntity> op1 = DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
+                    FaasIidFactory.mappedEntityIid(gbpTenantId), rwTx);
+            if (op1.isPresent()) {
+                toSubmit = true;
+            }
+            Optional<MappedTenant> op2 = DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
+                    FaasIidFactory.mappedTenantIid(gbpTenantId), rwTx);
+            if (op2.isPresent()) {
+                toSubmit = true;
+            }
+            if (toSubmit) {
+                DataStoreHelper.submitToDs(rwTx);
+            }
+
+            if (unregister) {
+                unregisterTenant(gbpTenantId);
+            }
+        }
+    }
+}
index 3e1807e0c5e86b965c611ba3cd6125d6c5ea6359..694ab7c486818865b0f1ca3de2a1a5ef0e068027 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
@@ -12,8 +12,7 @@ import java.util.concurrent.Executors;
 import java.util.concurrent.ScheduledExecutorService;
 
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.binding.api.NotificationService;
-import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.groupbasedpolicy.api.EpRendererAugmentationRegistry;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -25,21 +24,17 @@ public class FaasRenderer implements AutoCloseable {
 
     private static final Logger LOG = LoggerFactory.getLogger(FaasRenderer.class);
 
-    private final DataBroker dataBroker;
     private final ScheduledExecutorService executor;
-
     private final FaasEndpointManagerListener endpointListner;
+    private final FaasPolicyManager policyManager;
+    private final FaasEndpointAug faasEndpointAug;
 
-    public FaasRenderer(final DataBroker dataProvider, RpcProviderRegistry rpcRegistry,
-            NotificationService notificationService) {
-        super();
-        this.dataBroker = dataProvider;
-
+    public FaasRenderer(final DataBroker dataProvider, EpRendererAugmentationRegistry epRendererAugmentationRegistry) {
         int numCPU = Runtime.getRuntime().availableProcessors();
         executor = Executors.newScheduledThreadPool(numCPU * 2);
-
-        endpointListner = new FaasEndpointManagerListener(dataProvider);
-
+        policyManager = new FaasPolicyManager(dataProvider, executor);
+        endpointListner = new FaasEndpointManagerListener(policyManager, dataProvider, executor);
+        faasEndpointAug = new FaasEndpointAug(epRendererAugmentationRegistry);
         LOG.info("FAAS Renderer has Started");
     }
 
@@ -47,6 +42,7 @@ public class FaasRenderer implements AutoCloseable {
     public void close() throws Exception {
         executor.shutdownNow();
         endpointListner.close();
+        policyManager.close();
+        faasEndpointAug.close();
     }
-
 }
diff --git a/renderers/faas/src/main/java/org/opendaylight/groupbasedpolicy/renderer/faas/FaasSubnetManagerListener.java b/renderers/faas/src/main/java/org/opendaylight/groupbasedpolicy/renderer/faas/FaasSubnetManagerListener.java
new file mode 100644 (file)
index 0000000..75f14e3
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+ * 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
+ */
+package org.opendaylight.groupbasedpolicy.renderer.faas;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ScheduledExecutorService;
+
+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.ReadWriteTransaction;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+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.UlnDatastoreApi;
+import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.common.rev151013.Text;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.common.rev151013.Uuid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.subnets.rev151013.subnets.container.subnets.SubnetBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.subnets.rev151013.subnets.container.subnets.subnet.ExternalGateways;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.subnets.rev151013.subnets.container.subnets.subnet.ExternalGatewaysBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubnetId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.mapped.tenants.entities.mapped.entity.MappedSubnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.mapped.tenants.entities.mapped.entity.MappedSubnetBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.Subnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.subnet.Gateways;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.subnet.gateways.Prefixes;
+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 FaasSubnetManagerListener implements DataChangeListener {
+
+    private static final Logger LOG = LoggerFactory.getLogger(FaasSubnetManagerListener.class);
+    private ConcurrentHashMap<SubnetId, Uuid> mappedSubnets = new ConcurrentHashMap<>();
+    private final ScheduledExecutorService executor;
+    private final DataBroker dataProvider;
+    private final TenantId gbpTenantId;
+    private final Uuid faasTenantId;
+
+    public FaasSubnetManagerListener(DataBroker dataProvider, TenantId gbpTenantId, Uuid faasTenantId,
+            ScheduledExecutorService executor) {
+        this.executor = executor;
+        this.faasTenantId = faasTenantId;
+        this.gbpTenantId = gbpTenantId;
+        this.dataProvider = dataProvider;
+    }
+
+    @Override
+    public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+        executor.execute(new Runnable() {
+
+            public void run() {
+                executeEvent(change);
+            }
+        });
+    }
+
+    private void executeEvent(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+        // Create
+        for (DataObject dao : change.getCreatedData().values()) {
+            if (dao instanceof Subnet) {
+                Subnet subnet = (Subnet) dao;
+                LOG.debug("Subnet {} is Created.", subnet.getId().getValue());
+                UlnDatastoreApi.submitSubnetToDs(initSubnetBuilder(subnet).build());
+            }
+        }
+        // Update
+        Map<InstanceIdentifier<?>, DataObject> dao = change.getUpdatedData();
+        for (Map.Entry<InstanceIdentifier<?>, DataObject> entry : dao.entrySet()) {
+            if (entry.getValue() instanceof Subnet) {
+                Subnet subnet = (Subnet) dao;
+                LOG.debug("Subnet {} is Updated.", subnet.getId().getValue());
+                UlnDatastoreApi.submitSubnetToDs(initSubnetBuilder(subnet).build());
+            }
+        }
+        // Remove
+        for (InstanceIdentifier<?> iid : change.getRemovedPaths()) {
+            DataObject old = change.getOriginalData().get(iid);
+            if (old == null) {
+                continue;
+            }
+            if (old instanceof Subnet) {
+                Subnet subnet = (Subnet) old;
+                ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
+                Optional<MappedSubnet> op = DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
+                        FaasIidFactory.mappedSubnetIid(gbpTenantId, subnet.getId()), rwTx);
+                if (op.isPresent()) {
+                    DataStoreHelper.submitToDs(rwTx);
+                }
+                Uuid faasSubnetId = mappedSubnets.remove(subnet.getId());
+                if (faasSubnetId != null) {
+                    UlnDatastoreApi.removeSubnetFromDsIfExists(faasTenantId, faasSubnetId);
+                }
+            }
+        }
+    }
+
+    public void loadAll(List<Subnet> subnets, List<MappedSubnet> mpSubnets) {
+        if (mpSubnets != null) {
+            for (MappedSubnet mpSubnet : mpSubnets) {
+                mappedSubnets.putIfAbsent(mpSubnet.getGbpSubnetId(), mpSubnet.getFaasSubnetId());
+            }
+        }
+        if (subnets != null) {
+            for (Subnet subnet : subnets) {
+                LOG.debug("Loading Subnet {}", subnet.getId().getValue());
+                UlnDatastoreApi.submitSubnetToDs(initSubnetBuilder(subnet).build());
+            }
+        }
+    }
+
+    private SubnetBuilder initSubnetBuilder(Subnet gbpSubnet) {
+        SubnetBuilder builder = new SubnetBuilder();
+        if (gbpSubnet.getGateways() != null) {
+            List<ExternalGateways> gateways = new ArrayList<>();
+            for (Gateways gw : gbpSubnet.getGateways()) {
+                ExternalGatewaysBuilder eb = new ExternalGatewaysBuilder();
+                eb.setExternalGateway(gw.getGateway());
+                if (gw.getPrefixes() != null) {
+                    List<IpPrefix> ipPrefixes = new ArrayList<>();
+                    for (Prefixes px : gw.getPrefixes()) {
+                        ipPrefixes.add(px.getPrefix());
+                    }
+                    eb.setPrefixes(ipPrefixes);
+                }
+                gateways.add(eb.build());
+            }
+            builder.setExternalGateways(gateways);
+        }
+
+        builder.setIpPrefix(gbpSubnet.getIpPrefix());
+        builder.setUuid(getFaasSubnetId(gbpSubnet.getId()));
+        builder.setName(new Text(gbpSubnet.getId().getValue()));
+        if (gbpSubnet.getDescription() != null)
+            builder.setDescription(new Text("gbp-subnet: " + gbpSubnet.getDescription().getValue()));
+        else
+            builder.setDescription(new Text("gbp-subnet"));
+        builder.setTenantId(faasTenantId);
+        builder.setVirtualRouterIp(gbpSubnet.getVirtualRouterIp());
+        // TODO DNS servers
+        builder.setDnsNameservers(null);
+        // TODO DHCP server
+        builder.setEnableDhcp(false);
+        return builder;
+    }
+
+    private Uuid getFaasSubnetId(SubnetId subnetId) {
+        Uuid val = mappedSubnets.get(subnetId);
+        if (val != null) {
+            return val;
+        }
+        Uuid faasSubnetId = null;
+        if (FaasPolicyManager.isUUid(subnetId.getValue())) {
+            faasSubnetId = new Uuid(subnetId.getValue());
+        } else {
+            faasSubnetId = new Uuid(UUID.randomUUID().toString());
+        }
+        mappedSubnets.putIfAbsent(subnetId, faasSubnetId);
+        val = mappedSubnets.get(subnetId);
+        MappedSubnetBuilder builder = new MappedSubnetBuilder();
+        builder.setFaasSubnetId(val);
+        builder.setGbpSubnetId(subnetId);
+        WriteTransaction wTx = dataProvider.newWriteOnlyTransaction();
+        MappedSubnet result = builder.build();
+        wTx.put(LogicalDatastoreType.OPERATIONAL,
+                FaasIidFactory.mappedSubnetIid(gbpTenantId, subnetId), result);
+        if (DataStoreHelper.submitToDs(wTx)) {
+            LOG.debug("Cached in Datastore Mapped Subnet {}", result);
+        } else {
+            LOG.error("Couldn't Cache in Datastore Mapped Subnet {}", result);
+        }
+        return val;
+    }
+
+}
diff --git a/renderers/faas/src/main/java/org/opendaylight/groupbasedpolicy/renderer/faas/FaasTenantManagerListener.java b/renderers/faas/src/main/java/org/opendaylight/groupbasedpolicy/renderer/faas/FaasTenantManagerListener.java
new file mode 100644 (file)
index 0000000..c7a9179
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * 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
+ */
+package org.opendaylight.groupbasedpolicy.renderer.faas;
+
+import java.util.concurrent.ScheduledExecutorService;
+
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.common.rev151013.Uuid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.Tenant;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class FaasTenantManagerListener implements DataChangeListener {
+
+    private static final Logger LOG = LoggerFactory.getLogger(FaasTenantManagerListener.class);
+    private final ScheduledExecutorService executor;
+    private final TenantId gbpTenantId;
+    private final Uuid faasTenantId;
+    private final FaasPolicyManager policyManager;
+
+    public FaasTenantManagerListener(FaasPolicyManager policyManager, TenantId gbpTenantId, Uuid faasTenantId,
+            ScheduledExecutorService executor) {
+        this.executor = executor;
+        this.faasTenantId = faasTenantId;
+        this.gbpTenantId = gbpTenantId;
+        this.policyManager = policyManager;
+    }
+
+    @Override
+    public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+        executor.execute(new Runnable() {
+
+            public void run() {
+                executeEvent(change);
+            }
+        });
+    }
+
+    private void executeEvent(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+        // Remove
+        for (InstanceIdentifier<?> iid : change.getRemovedPaths()) {
+            DataObject old = change.getOriginalData().get(iid);
+            if (old == null) {
+                continue;
+            }
+            if (old instanceof Tenant) {
+                Tenant tenant = (Tenant) old;
+                if (tenant.getId().equals(gbpTenantId)) {
+                    LOG.info("Removed gbp Tenant {}  -- faas Tenant {}", gbpTenantId.getValue(),
+                            faasTenantId.getValue());
+                    this.policyManager.removeTenantLogicalNetwork(gbpTenantId, faasTenantId);
+                }
+            }
+        }
+    }
+}
index 1ac4a231d45c8ac7022eb48b0eb290eec746d1f1..04b78fa18b0535b71228934b6fd607ab77dca344 100644 (file)
@@ -12,44 +12,26 @@ module faas-endpoint {
     prefix "faas-endpoint";
 
     import yang-ext { prefix ext; revision-date "2013-07-09"; }
-    import opendaylight-inventory { prefix inv; revision-date "2013-08-19"; }
-    import gbp-common { prefix gbp-common; }
-    import endpoint { prefix endpoint; }
+    import endpoint { prefix endpoint; revision-date 2014-04-21; }
+    import faas-common { prefix faas-common; revision-date 2015-10-13; }
 
     revision 2015-10-09 {
         description "Initial revision";
     }
 
-    grouping switch-attach-location {
-        description
-                "The switch attachment for this endpoint";
-
-        leaf node-id {
-            description "The switch for this attached point";
-            type inv:node-id;
-        }
-
-        leaf node-connector-id {
-            description "The node connector that this point is attached to";
-            type inv:node-connector-id;
+    grouping faas-port-ref {
+        leaf faas-port-ref-id {
+            description "faas port cross reference";
+            type faas-common:uuid;
         }
     }
-
-    grouping endpoint-ext-fields {
-        leaf subnet-id {
-            description "The subnet Id";
-            type gbp-common:unique-id;
-        }
-        uses switch-attach-location;
-    }
-
     augment "/endpoint:endpoints/endpoint:endpoint" {
         ext:augment-identifier "faas-endpoint-context";
-        uses endpoint-ext-fields;
+        uses faas-port-ref;
     }
 
     augment "/endpoint:register-endpoint/endpoint:input" {
         ext:augment-identifier "faas-endpoint-context-input";
-        uses endpoint-ext-fields;
+        uses faas-port-ref;
     }
 }
index df5b2d08cb1a5508427cc23fddb3f1b47eddf4b0..d41bf78c42608121566233aa666fbe7f7a4d19c5 100644 (file)
@@ -14,6 +14,7 @@ module faas-provider-impl {
     import config { prefix config; revision-date 2013-04-05; }
     import opendaylight-md-sal-binding { prefix mdsal; revision-date 2013-10-28; }
     import opendaylight-sal-binding-broker-impl { prefix sal-broker; revision-date 2013-10-28; }
+    import groupbasedpolicy-cfg { prefix gbpcfg; revision-date 2015-11-06; }
 
     description
         "This module contains the base YANG definitions for faas-provider
@@ -35,7 +36,7 @@ module faas-provider-impl {
         case faas-provider-impl {
             when "/config:modules/config:module/config:type = 'faas-provider-impl'";
 
-            //wires in the data-broker service 
+            //wires in the data-broker service
             container data-broker {
                 uses config:service-ref {
                     refine type {
@@ -44,21 +45,12 @@ module faas-provider-impl {
                     }
                 }
             }
-            // RPC Registry
-            container rpc-registry {
+            // EpRendererAugmentationRegistry service
+            container ep-renderer-augmentation-registry {
                 uses config:service-ref {
                     refine type {
                         mandatory true;
-                        config:required-identity mdsal:binding-rpc-registry;
-                    }
-                }
-            }
-            // Notification service
-            container notification-adapter {
-                uses config:service-ref {
-                    refine type {
-                        mandatory true;
-                        config:required-identity sal-broker:binding-new-notification-service;
+                        config:required-identity gbpcfg:ep-renderer-augmentation-registry;
                     }
                 }
             }
index e8fcd48d281f513d6c1071c879107bfc0b9aa863..0e786f600edc5dd92cac449f2b006ed72d2e74f2 100644 (file)
@@ -12,9 +12,10 @@ module faas {
     namespace "urn:opendaylight:groupbasedpolicy:faas";
     prefix "faas";
 
-    import gbp-common { prefix gbp-common; }
-    import endpoint { prefix endpoint; }
-    import resolved-policy { prefix resolved-policy; }
+    import gbp-common { prefix gbp-common; revision-date 2014-04-21; }
+    import faas-common { prefix faas-common; revision-date 2015-10-13; }
+    import endpoint { prefix endpoint; revision-date 2014-04-21; }
+    import resolved-policy { prefix resolved-policy; revision-date 2015-08-28; }
 
     description
         "This module defines the group-based policy faas renderer model.";
@@ -24,6 +25,29 @@ module faas {
                 "Initial revision.";
     }
 
+    typedef scope-type {
+        type enumeration {
+            enum private {
+                description "private scope within a tenant domain";
+            }
+            enum public {
+                description "public scope that is exposed outside the tenant domain such as the Internet";
+            }
+        }
+    }
+    typedef service-communication-layer {
+        type enumeration {
+            enum layer-undefined {
+                description "Undefined layer";
+            }
+            enum layer-2 {
+                description "layer 2";
+            }
+            enum layer-3 {
+                description "layer 3";
+            }
+        }
+    }
     grouping has-contract-key {
         leaf contract-tenant-id {
             description "Related tenant id";
@@ -36,45 +60,99 @@ module faas {
         }
     }
 
-    container mapped-service-profiles {
-        description "The list of mapped services";
+    grouping has-logical-entity {
+        leaf logical-router-id {
+            type faas-common:uuid;
+        }
+        leaf logical-switch-id {
+            type faas-common:uuid;
+        }
+        leaf-list gbp-subnet-id {
+            type gbp-common:subnet-id;
+        }
+    }
+
+    container logical-networks {
+        description "The mapped logical networks based on GBP resolved services";
 
         config false;
 
-        list mapped-service-profile {
-            description "a service is an EPG-Contract-EPG";
+        list logical-network {
+            description "Mapped logical network for an EPG-Contract-EPG service";
 
-            key "consumer-epg-id contract-id provider-epg-id";
+            key "consumer-epg-id contract-id provider-epg-id consumer-tenant-id provider-tenant-id";
 
             uses resolved-policy:has-consumer-epg-key;
             uses has-contract-key;
             uses resolved-policy:has-provider-epg-key;
-            leaf faas-security-rules-groups {
-                description "Faas rules generated from GBP contract";
-                type gbp-common:uuid;
+            leaf communication-layer {
+                description "logical network communication layer";
+                type service-communication-layer;
             }
-            leaf-list faas-routers {
-                description "Faas logical routers";
-                type gbp-common:uuid;
+            container consumer-network {
+                uses has-logical-entity;
+                leaf network-scope-type {
+                    description "if public, it means the router has a public access port";
+                    default private;
+                    type scope-type;
+                }
             }
-            leaf-list faas-switches {
-                description "Faas logical switches";
-                type gbp-common:uuid;
+            container provider-network {
+                uses has-logical-entity;
+                leaf network-scope-type {
+                    description "if public, it means the router has a public access port";
+                    default private;
+                    type scope-type;
+                }
             }
-            leaf-list faas-ports {
-                description "Faas logical ports";
-                type gbp-common:uuid;
+        }
+    }
+
+    grouping tenant-pair-id {
+        leaf gbp-tenant-id {
+            type gbp-common:tenant-id;
+        }
+        leaf faas-tenant-id {
+            type faas-common:uuid;
+        }
+    }
+    container mapped-tenants-entities {
+
+        config false;
+
+        list mapped-tenant {
+            key "gbp-tenant-id";
+            uses tenant-pair-id;
+        }
+        list mapped-entity {
+            key "gbp-tenant-id";
+            leaf gbp-tenant-id {
+                type gbp-common:tenant-id;
             }
-            leaf-list faas-subnets {
-                description "Faas subnets";
-                type gbp-common:uuid;
+            list mapped-contract {
+                key "gbp-contract-id";
+                leaf gbp-contract-id {
+                    type gbp-common:contract-id;
+                }
+                leaf faas-security-rules-id {
+                    type faas-common:uuid;
+                }
             }
-        }
-        list mapped-endpoints {
-            uses endpoint:l2-key;
-            leaf-list faas-ports {
-                description "Faas logical ports";
-                type gbp-common:uuid;
+            list mapped-subnet {
+                key "gbp-subnet-id";
+                leaf gbp-subnet-id {
+                    type gbp-common:subnet-id;
+                }
+                leaf faas-subnet-id {
+                    type faas-common:uuid;
+                }
+            }
+            list mapped-endpoint {
+                key "l2-context mac-address";
+                uses endpoint:l2-key;
+                leaf endpoint-location {
+                    type faas-common:uuid;
+                }
             }
         }
     }