2dc43f4accc798d60763870bd7f1a7aa1bc3c857
[groupbasedpolicy.git] / renderers / faas / src / main / java / org / opendaylight / groupbasedpolicy / renderer / faas / FaasPolicyManager.java
1 /*
2  * Copyright (c) 2015 Huawei Technologies and others. All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.groupbasedpolicy.renderer.faas;
9
10 import static com.google.common.base.Preconditions.checkNotNull;
11
12 import java.util.ArrayList;
13 import java.util.HashMap;
14 import java.util.HashSet;
15 import java.util.List;
16 import java.util.Map;
17 import java.util.Set;
18 import java.util.UUID;
19 import java.util.concurrent.ConcurrentHashMap;
20 import java.util.concurrent.ScheduledExecutorService;
21
22 import com.google.common.annotations.VisibleForTesting;
23 import com.google.common.base.Optional;
24 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
25 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
26 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
27 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
28 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
29 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
30 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
31 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
32 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
33 import org.opendaylight.faas.uln.datastore.api.Pair;
34 import org.opendaylight.faas.uln.datastore.api.UlnDatastoreApi;
35 import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
36 import org.opendaylight.groupbasedpolicy.util.IidFactory;
37 import org.opendaylight.groupbasedpolicy.util.TenantUtils;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.common.rev151013.Text;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.common.rev151013.Uuid;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.logical.routers.rev151013.logical.routers.container.logical.routers.LogicalRouterBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.logical.switches.rev151013.logical.switches.container.logical.switches.LogicalSwitchBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.ports.rev151013.PortLocationAttributes.LocationType;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContextId;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContractId;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2BridgeDomainId;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2FloodDomainId;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L3ContextId;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubnetId;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.LogicalNetworks;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.ScopeType;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.ServiceCommunicationLayer;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.logical.networks.LogicalNetwork;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.logical.networks.LogicalNetworkBuilder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.logical.networks.logical.network.ConsumerNetworkBuilder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.logical.networks.logical.network.ProviderNetworkBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.mapped.tenants.entities.MappedEntity;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.mapped.tenants.entities.MappedEntityBuilder;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.mapped.tenants.entities.MappedTenant;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.mapped.tenants.entities.MappedTenantBuilder;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.mapped.tenants.entities.mapped.entity.MappedContract;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.mapped.tenants.entities.mapped.entity.MappedSubnet;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.Tenant;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L2BridgeDomain;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L2FloodDomain;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L3Context;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.Subnet;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.Contract;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.EndpointGroup;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.RendererName;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.RendererBuilder;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.interests.followed.tenants.FollowedTenantBuilder;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.interests.followed.tenants.followed.tenant.FollowedEndpointGroup;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.interests.followed.tenants.followed.tenant.FollowedEndpointGroupBuilder;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.ResolvedPolicies;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.resolved.policies.ResolvedPolicy;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.resolved.policies.ResolvedPolicy.ExternalImplicitGroup;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.resolved.policies.resolved.policy.PolicyRuleGroupWithEndpointConstraints;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.resolved.policies.resolved.policy.policy.rule.group.with.endpoint.constraints.PolicyRuleGroup;
81 import org.opendaylight.yangtools.concepts.ListenerRegistration;
82 import org.opendaylight.yangtools.yang.binding.DataObject;
83 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
84 import org.slf4j.Logger;
85 import org.slf4j.LoggerFactory;
86
87 public class FaasPolicyManager implements DataChangeListener, AutoCloseable {
88
89     private static final Logger LOG = LoggerFactory.getLogger(FaasPolicyManager.class);
90     private static final RendererName rendererName = new RendererName("faas");
91     private final ListenerRegistration<DataChangeListener> registerListener;
92     private final ScheduledExecutorService executor;
93     private final DataBroker dataProvider;
94     final Map<Pair<EndpointGroupId, TenantId>, List<SubnetId>> epgSubnetsMap = new HashMap<>();
95     private final ConcurrentHashMap<TenantId, Uuid> mappedTenants = new ConcurrentHashMap<>();
96     final ConcurrentHashMap<TenantId, ArrayList<ListenerRegistration<DataChangeListener>>> registeredTenants =
97             new ConcurrentHashMap<>();
98
99     public FaasPolicyManager(DataBroker dataBroker, ScheduledExecutorService executor) {
100         this.dataProvider = dataBroker;
101         this.executor = executor;
102         this.registerListener = checkNotNull(dataProvider).registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
103                 InstanceIdentifier.builder(ResolvedPolicies.class).child(ResolvedPolicy.class).build(), this,
104                 AsyncDataBroker.DataChangeScope.SUBTREE);
105
106         RendererBuilder rendBuilder = new RendererBuilder();
107         rendBuilder.setName(rendererName);
108         WriteTransaction wTx = dataProvider.newWriteOnlyTransaction();
109         wTx.put(LogicalDatastoreType.OPERATIONAL, IidFactory.rendererIid(rendererName), rendBuilder.build());
110         if (DataStoreHelper.submitToDs(wTx)) {
111             LOG.debug("{} renderer registered with the multi-renderer manager", rendererName.getValue());
112         } else {
113             LOG.error("{} renderer Failed to register with the multi-renderer manager", rendererName.getValue());
114         }
115     }
116
117     @Override
118     public void close() throws Exception {
119         synchronized (registeredTenants) {
120             for (ArrayList<ListenerRegistration<DataChangeListener>> list : registeredTenants.values()) {
121                 list.forEach(ListenerRegistration::close);
122             }
123             registeredTenants.clear();
124
125             LOG.debug("Closed All Tenant Registerations");
126         }
127         if (registerListener != null)
128             registerListener.close();
129     }
130
131     @Override
132     public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
133         executor.execute(new Runnable() {
134
135             public void run() {
136                 executeEvent(change);
137             }
138         });
139     }
140
141     private void executeEvent(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
142         // Create
143         for (DataObject dao : change.getCreatedData().values()) {
144             if (dao instanceof ResolvedPolicy) {
145                 ResolvedPolicy newPolicy = (ResolvedPolicy) dao;
146                 if (handledPolicy(newPolicy)) {
147                     LOG.debug("Created Policy: Consumer EPG {}, Provider EPG {}", newPolicy.getConsumerEpgId(),
148                             newPolicy.getProviderEpgId());
149                     updateLogicalNetwork(newPolicy);
150                 }
151             }
152         }
153         // Update
154         Map<InstanceIdentifier<?>, DataObject> d = change.getUpdatedData();
155         for (Map.Entry<InstanceIdentifier<?>, DataObject> entry : d.entrySet()) {
156             if (entry.getValue() instanceof ResolvedPolicy) {
157                 ResolvedPolicy newPolicy = (ResolvedPolicy) entry.getValue();
158                 ResolvedPolicy oldPolicy = (ResolvedPolicy) change.getOriginalData().get(entry.getKey());
159                 if (!isEqualService(newPolicy, oldPolicy)) {
160                     removeLogicalNetwork(oldPolicy);
161                 }
162                 if (handledPolicy(newPolicy)) {
163                     LOG.debug("Updated Policy: Consumer EPG {}, Provider EPG {}", newPolicy.getConsumerEpgId(),
164                             newPolicy.getProviderEpgId());
165                     updateLogicalNetwork(newPolicy);
166                 }
167             }
168         }
169
170         // Remove
171         for (InstanceIdentifier<?> iid : change.getRemovedPaths()) {
172             DataObject old = change.getOriginalData().get(iid);
173             if (old != null && old instanceof ResolvedPolicy) {
174                 ResolvedPolicy oldPolicy = (ResolvedPolicy) old;
175                 LOG.debug("Removed Policy: Consumer EPG {}, Provider EPG {}", oldPolicy.getConsumerEpgId(),
176                         oldPolicy.getProviderEpgId());
177                 removeLogicalNetwork(oldPolicy);
178             }
179         }
180     }
181
182     public void registerTenant(TenantId gbpTenantId) {
183         registerTenant(gbpTenantId, null);
184     }
185
186     public void registerTenant(TenantId gbpTenantId, EndpointGroupId epgId) {
187         if (registeredTenants.get(gbpTenantId) != null) {
188             registerFollowedEndpointgroup(gbpTenantId, epgId);
189             return; // already registered
190         }
191         synchronized (this) {
192             if (registeredTenants.get(gbpTenantId) != null) {
193                 return; // already registered
194             }
195             /*
196              * map tenant's required elements to faas logical networks
197              */
198             Optional<MappedTenant> mTenantOptional = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
199                     FaasIidFactory.mappedTenantIid(gbpTenantId), dataProvider.newReadOnlyTransaction());
200             Uuid faasTenantId;
201             if (mTenantOptional.isPresent()) {
202                 faasTenantId = mTenantOptional.get().getFaasTenantId();
203             } else {
204                 faasTenantId = getFaasTenantId(gbpTenantId);
205             }
206             // load tenant datastore info
207             Tenant tenant = null;
208             Optional<Tenant> tenantOptional = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
209                     TenantUtils.tenantIid(gbpTenantId), dataProvider.newReadOnlyTransaction());
210             if (tenantOptional.isPresent()) {
211                 tenant = tenantOptional.get();
212             }
213             List<Contract> contracts = null;
214             List<Subnet> subnets = null;
215             if (tenant != null) {
216                 contracts = tenant.getPolicy().getContract();
217                 subnets = tenant.getForwardingContext().getSubnet();
218             }
219             Optional<MappedEntity> mEntityOptional = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
220                     FaasIidFactory.mappedEntityIid(gbpTenantId),
221                     dataProvider.newReadOnlyTransaction());
222             MappedEntity mappedEntity;
223             if (mEntityOptional.isPresent()) {
224                 mappedEntity = mEntityOptional.get();
225             } else {
226                 // This is needed as a workaround of a datastore problem
227                 MappedEntityBuilder builder = new MappedEntityBuilder();
228                 builder.setGbpTenantId(gbpTenantId);
229                 mappedEntity = builder.build();
230                 WriteTransaction wTx = dataProvider.newWriteOnlyTransaction();
231                 wTx.put(LogicalDatastoreType.OPERATIONAL,
232                         FaasIidFactory.mappedEntityIid(gbpTenantId), mappedEntity);
233                 if (DataStoreHelper.submitToDs(wTx)) {
234                     LOG.debug("Initailized Mapped Entry in Datastore for tenant {}", gbpTenantId);
235                 } else {
236                     LOG.error("Couldn't Initailized Mapped Entry in Datastore for tenant {}", gbpTenantId);
237                 }
238             }
239
240             // contracts
241             FaasContractManagerListener faasContractManagerListener = new FaasContractManagerListener(dataProvider,
242                     gbpTenantId, faasTenantId, executor);
243             faasContractManagerListener.loadAll(contracts, mappedEntity.getMappedContract());
244             // subnets
245             FaasSubnetManagerListener faasSubnetManagerListener = new FaasSubnetManagerListener(dataProvider,
246                     gbpTenantId, faasTenantId, executor);
247             faasSubnetManagerListener.loadAll(subnets, mappedEntity.getMappedSubnet());
248
249             /*
250              * tenant registrations
251              */
252             ArrayList<ListenerRegistration<DataChangeListener>> list = new ArrayList<>();
253             ListenerRegistration<DataChangeListener> reg;
254             // contracts
255             reg = dataProvider.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
256                     IidFactory.contractWildcardIid(gbpTenantId), faasContractManagerListener, DataChangeScope.SUBTREE);
257             list.add(reg);
258             // subnets
259             reg = dataProvider.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
260                     IidFactory.subnetWildcardIid(gbpTenantId), faasSubnetManagerListener, DataChangeScope.SUBTREE);
261             list.add(reg);
262
263             // tenant
264             reg = dataProvider.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
265                     IidFactory.tenantIid(gbpTenantId), new FaasTenantManagerListener(this, gbpTenantId, faasTenantId,
266                             executor), DataChangeScope.BASE);
267             list.add(reg);
268
269             // Map previously resolved policy for this tenant
270             mapAllTenantResolvedPolicies(gbpTenantId, null);
271
272             registerFollowedTenant(gbpTenantId, epgId);
273
274             // track all registrations
275             registeredTenants.put(gbpTenantId, list);
276
277             LOG.debug("Registered tenant {}", gbpTenantId);
278         }
279     }
280
281     private void mapAllTenantResolvedPolicies(TenantId gbpTenantId, EndpointGroupId epgId) {
282         Optional<ResolvedPolicies> resolvedPoliciesOptional = DataStoreHelper.readFromDs(
283                 LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.builder(ResolvedPolicies.class).build(),
284                 dataProvider.newReadOnlyTransaction());
285         if (!resolvedPoliciesOptional.isPresent() || resolvedPoliciesOptional.get().getResolvedPolicy() == null) {
286             return;
287         }
288         //TODO forEach possible?
289         List<ResolvedPolicy> resolvedPolicies = resolvedPoliciesOptional.get().getResolvedPolicy();
290         for (ResolvedPolicy policy : resolvedPolicies) {
291             if (policy.getConsumerTenantId().equals(gbpTenantId)) {
292                 if (epgId == null || epgId.equals(policy.getConsumerEpgId()) || epgId.equals(policy.getProviderEpgId())) {
293                     // if any epg or a specific epg policy
294                     updateLogicalNetwork(policy);
295                 }
296             }
297         }
298     }
299
300     private void registerFollowedTenant(TenantId gbpTenantId, EndpointGroupId epgId) {
301         FollowedTenantBuilder fTenantBuilder = new FollowedTenantBuilder();
302         fTenantBuilder.setId(gbpTenantId);
303         if (epgId != null) {
304             List<FollowedEndpointGroup> epgs = new ArrayList<>();
305             epgs.add(new FollowedEndpointGroupBuilder().setId(epgId).build());
306             fTenantBuilder.setFollowedEndpointGroup(epgs);
307         }
308         WriteTransaction wTx = dataProvider.newWriteOnlyTransaction();
309         wTx.put(LogicalDatastoreType.OPERATIONAL, IidFactory.followedTenantIid(rendererName, gbpTenantId),
310                 fTenantBuilder.build());
311         if (DataStoreHelper.submitToDs(wTx)) {
312             LOG.info("Tenant {} is followed by renderer {}", gbpTenantId.getValue(), rendererName.getValue());
313         } else {
314             LOG.info("Couldn't register Tenant {} that is followed by renderer {}", gbpTenantId.getValue(),
315                     rendererName.getValue());
316         }
317     }
318
319     @VisibleForTesting
320     void registerFollowedEndpointgroup(TenantId gbpTenantId, EndpointGroupId epgId) {
321         if (epgId == null) {
322             return;
323         }
324         FollowedEndpointGroupBuilder fEpgBuilder = new FollowedEndpointGroupBuilder();
325         fEpgBuilder.setId(epgId);
326         WriteTransaction wTx = dataProvider.newWriteOnlyTransaction();
327         wTx.put(LogicalDatastoreType.OPERATIONAL,
328                 IidFactory.followedEndpointgroupIid(rendererName, gbpTenantId, epgId), fEpgBuilder.build());
329         if (DataStoreHelper.submitToDs(wTx)) {
330             LOG.trace("EPG {} in Tenant {} is followed by renderer {}", epgId.getValue(), gbpTenantId.getValue(),
331                     rendererName.getValue());
332         } else {
333             LOG.info("Couldn't register EPG {} in Tenant {} that is followed by renderer {}", epgId.getValue(),
334                     gbpTenantId.getValue(), rendererName.getValue());
335         }
336     }
337
338     public Uuid getFaasTenantId(TenantId tenantId) {
339         Uuid val = mappedTenants.get(tenantId);
340         if (val != null) {
341             return val;
342         }
343         Uuid faasTenantId;
344         if (isUUid(tenantId.getValue())) {
345             faasTenantId = new Uuid(tenantId.getValue());
346         } else {
347             faasTenantId = new Uuid(UUID.randomUUID().toString());
348         }
349         mappedTenants.putIfAbsent(tenantId, faasTenantId);
350         val = mappedTenants.get(tenantId);
351         MappedTenantBuilder builder = new MappedTenantBuilder();
352         builder.setFaasTenantId(val);
353         builder.setGbpTenantId(tenantId);
354         WriteTransaction wTx = dataProvider.newWriteOnlyTransaction();
355         MappedTenant result = builder.build();
356         wTx.put(LogicalDatastoreType.OPERATIONAL, FaasIidFactory.mappedTenantIid(tenantId), result);
357         if (DataStoreHelper.submitToDs(wTx)) {
358             LOG.debug("Cached in Datastore Mapped Tenant {}", result);
359         } else {
360             LOG.error("Couldn't Cache in Datastore Mapped Tenant {}", result);
361         }
362         return val;
363     }
364
365     public static boolean isUUid(String value) {
366         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}"));
367     }
368
369     public void unregisterTenant(TenantId tenantId) {
370
371         ArrayList<ListenerRegistration<DataChangeListener>> list = registeredTenants.remove(tenantId);
372         if (list != null) {
373             for (ListenerRegistration<DataChangeListener> reg : list) {
374                 if (reg != null)
375                     reg.close();
376             }
377             LOG.debug("Unregistered tenant {}", tenantId);
378         }
379         registeredTenants.remove(tenantId);
380         Uuid faasTenantId = mappedTenants.get(tenantId);
381         if (faasTenantId != null) {
382             removeTenantLogicalNetwork(tenantId, faasTenantId, false);
383         }
384     }
385
386     public boolean isTenantRegistered(TenantId tenantId) {
387         return registeredTenants.containsKey(tenantId);
388     }
389
390     @VisibleForTesting
391     boolean handledPolicy(ResolvedPolicy policy) {
392         if (!policy.getConsumerTenantId().equals(policy.getProviderTenantId())) {
393             // FAAS always assumes consumer and provider EPGs belong to the same tenant
394             LOG.warn(
395                     "Ignore Resolved Policy between Consumer EPG {} and Provider EPG {} becuase they belong to different Tenants",
396                     policy.getConsumerTenantId().getValue(), policy.getProviderTenantId().getValue());
397             return false;
398         }
399         return isTenantRegistered(policy.getConsumerTenantId());
400     }
401
402     private boolean isEqualService(ResolvedPolicy newPolicy, ResolvedPolicy oldPolicy) {
403         return oldPolicy != null && newPolicy.getConsumerEpgId().equals(oldPolicy.getConsumerEpgId())
404                 && newPolicy.getProviderEpgId().equals(oldPolicy.getProviderEpgId())
405                 && newPolicy.getConsumerTenantId().equals(oldPolicy.getConsumerTenantId())
406                 && newPolicy.getProviderTenantId().equals(oldPolicy.getProviderTenantId());
407     }
408
409     public void registerSubnetWithEpg(EndpointGroupId epgId, TenantId tenantId, SubnetId subnetId) {
410         registerSubnetWithEpg(epgId, tenantId, subnetId, true);
411     }
412
413     private void registerSubnetWithEpg(EndpointGroupId epgId, TenantId tenantId, SubnetId subnetId, boolean updateLn) {
414         synchronized (this) {
415             List<SubnetId> subnets = cloneAndGetEpgSubnets(epgId, tenantId);
416             if(subnets.contains(subnetId)){
417                 return;
418             }
419             subnets.add(subnetId);
420             epgSubnetsMap.put(new Pair<>(epgId, tenantId), subnets);
421             LOG.debug("Registered Subnet {} with EPG {}", subnetId, epgId);
422             if (updateLn) {
423                 mapAllTenantResolvedPolicies(tenantId, epgId);
424             }
425         }
426     }
427
428     @VisibleForTesting
429     void removeLogicalNetwork(ResolvedPolicy oldPolicy) {
430         if (oldPolicy == null) {
431             return;
432         }
433         removeLogicalNetwork(oldPolicy.getConsumerEpgId(), oldPolicy.getConsumerTenantId(), getContractId(oldPolicy),
434                 oldPolicy.getProviderEpgId(), oldPolicy.getProviderTenantId());
435     }
436
437     private void removeLogicalNetwork(EndpointGroupId consumerEpgId, TenantId consumerTenantId, ContractId contractId,
438             EndpointGroupId providerEpgId, TenantId providerTenantId) {
439         ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
440         Optional<LogicalNetwork> lnOp = DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
441                 FaasIidFactory.logicalNetworkIid(consumerEpgId, consumerTenantId, contractId,
442                         providerEpgId, providerTenantId), rwTx);
443         if (lnOp.isPresent()) {
444             DataStoreHelper.submitToDs(rwTx);
445             LogicalNetwork logicalNetwork = lnOp.get();
446             Uuid consTenantId = getFaasTenantId(logicalNetwork.getConsumerTenantId());
447             Uuid provTenantId = getFaasTenantId(logicalNetwork.getProviderTenantId());
448
449             UlnDatastoreApi.removeLogicalSwitchFromDsIfExists(consTenantId, logicalNetwork.getConsumerNetwork()
450                 .getLogicalSwitchId());
451             UlnDatastoreApi.removeLogicalSwitchFromDsIfExists(provTenantId, logicalNetwork.getProviderNetwork()
452                 .getLogicalSwitchId());
453             if (logicalNetwork.getConsumerNetwork().getLogicalRouterId() != null) {
454                 UlnDatastoreApi.removeLogicalRouterFromDsIfExists(consTenantId, logicalNetwork.getConsumerNetwork()
455                     .getLogicalRouterId());
456             }
457             if (logicalNetwork.getProviderNetwork().getLogicalRouterId() != null) {
458                 UlnDatastoreApi.removeLogicalRouterFromDsIfExists(provTenantId, logicalNetwork.getProviderNetwork()
459                     .getLogicalRouterId());
460             }
461         }
462     }
463
464     private synchronized void updateLogicalNetwork(ResolvedPolicy policy) {
465         updateLogicalNetwork(policy.getConsumerEpgId(), getContractId(policy), policy.getProviderEpgId(),
466                 policy.getConsumerTenantId(), policy.getExternalImplicitGroup());
467     }
468
469     private synchronized void updateLogicalNetwork(EndpointGroupId consumerEpgId, ContractId contractId,
470             EndpointGroupId providerEpgId, TenantId tenantId, ExternalImplicitGroup externalImplicitGroup) {
471
472         LOG.trace("Start updateLogicalNetwork: Consumer EPG {}   Provider Epg {}   Contract {}", consumerEpgId,
473                 providerEpgId, contractId);
474
475         // Create Logical network
476         EndpointGroup consEpg = readEndpointGroup(consumerEpgId, tenantId);
477         if (consEpg == null) {
478             LOG.error("Couldn't Creat Logical Network. Missing EPG {}", consumerEpgId);
479             return;
480         }
481         List<SubnetId> consSubnetIds = cloneAndGetEpgSubnets(consEpg.getId(), tenantId);
482         if (consSubnetIds.isEmpty()) {
483             LOG.info("Couldn't Creat Logical Network. Missing Subnets for Consumer EPG {}", consumerEpgId);
484             return;
485         }
486         EndpointGroup provEpg = readEndpointGroup(providerEpgId, tenantId);
487         if (provEpg == null) {
488             LOG.error("Couldn't Creat Logical Network. Missing EPG {}", providerEpgId);
489             return;
490         }
491         List<SubnetId> provSubnetIds = cloneAndGetEpgSubnets(provEpg.getId(), tenantId);
492         if (provSubnetIds.isEmpty()) {
493             LOG.info("Couldn't Creat Logical Network. Missing Subnets for Provider EPG {}", providerEpgId);
494             return;
495         }
496
497         ServiceCommunicationLayer comLayer = findLayerNetwork(tenantId, consSubnetIds, provSubnetIds);
498         if (comLayer == null) {
499             LOG.error(
500                     "Couldn't determine forwarding Context. Couldn't Process Logical Network for Consumer EPG {}   Provider Epg {}   Contract {}",
501                     consumerEpgId, providerEpgId, contractId);
502             return;
503         }
504
505         if (needToCreateLogicalNetwork(comLayer, consSubnetIds, provSubnetIds, tenantId, contractId, provEpg, consEpg,
506                 externalImplicitGroup)) {
507             if (comLayer == ServiceCommunicationLayer.Layer2) {
508                 createLayer2LogicalNetwork(consEpg, contractId, provEpg, tenantId, comLayer, externalImplicitGroup);
509             } else if (comLayer == ServiceCommunicationLayer.Layer3) {
510                 createLayer3LogicalNetwork(consEpg, contractId, provEpg, tenantId, comLayer, externalImplicitGroup);
511             } else {
512                 LOG.error("Couldn't find the communication layer.Consumer EPG {}   Provider Epg {}   Contract {}",
513                         consumerEpgId, providerEpgId, contractId);
514             }
515         } else {
516             LOG.debug("No need to Create the Logical Network. Consumer EPG {}   Provider Epg {}   Contract {}",
517                     consumerEpgId, providerEpgId, contractId);
518         }
519     }
520
521     private boolean isConsumerPublic(ExternalImplicitGroup externalImplicitGroup) {
522         return externalImplicitGroup != null && externalImplicitGroup == ExternalImplicitGroup.ConsumerEpg;
523     }
524
525     private boolean isProviderPublic(ExternalImplicitGroup externalImplicitGroup) {
526         return externalImplicitGroup != null && externalImplicitGroup == ExternalImplicitGroup.ProviderEpg;
527     }
528
529     private List<SubnetId> cloneAndGetEpgSubnets(EndpointGroupId epgId, TenantId tenantId) {
530         synchronized (this) {
531             List<SubnetId> list1 = epgSubnetsMap.get(new Pair<>(epgId, tenantId));
532             if (list1 == null) {
533                 return new ArrayList<>();
534             }
535             List<SubnetId> list2 = new ArrayList<>();
536             for (SubnetId id : list1) {
537                 list2.add(new SubnetId(id));
538             }
539             return list2;
540         }
541     }
542
543     protected void createLayer3LogicalNetwork(EndpointGroup consEpg, ContractId contractId, EndpointGroup provEpg,
544             TenantId gbpTenantId, ServiceCommunicationLayer comLayer, ExternalImplicitGroup externalImplicitGroup) {
545         LOG.trace("Start createLayer3LogicalNetwork: Consumer EPG {}   Provider Epg {}   Contract {}", consEpg.getId()
546             .getValue(), provEpg.getId().getValue(), contractId);
547         LogicalNetworkBuilder lNetbuilder = buildLayer2LogicalNetwork(consEpg, provEpg, gbpTenantId, null,
548                 externalImplicitGroup);
549         if (lNetbuilder == null) {
550             LOG.error("Failed to create Logical Switchs layer on the Logical network");
551             return;
552         }
553         Uuid privateSecRulesId = getFaasSecRulesId(contractId, gbpTenantId);
554         if (privateSecRulesId == null) {
555             LOG.error(
556                     "Couldn't Create Logical Network because unable to find FAAS Security Rules Id based on GBP Contract {}",
557                     contractId);
558             return;
559         }
560
561         Uuid faasTenantId = getFaasTenantId(gbpTenantId);
562         LogicalRouterBuilder consLR = initLogicalRouterBuilder(consEpg, faasTenantId,
563                 isConsumerPublic(externalImplicitGroup));
564         LogicalRouterBuilder provLR = initLogicalRouterBuilder(provEpg, faasTenantId,
565                 isProviderPublic(externalImplicitGroup));
566
567         if (!UlnDatastoreApi.attachAndSubmitToDs(consLR, provLR, new Pair<>(null, privateSecRulesId), null)) {
568             LOG.error("Failed to join Logical Routers in a Logical Network");
569             return;
570         }
571
572         if (!UlnDatastoreApi.attachAndSubmitToDs(consLR.getUuid(), lNetbuilder.getConsumerNetwork()
573             .getLogicalSwitchId(), faasTenantId, new Pair<>(LocationType.RouterType, LocationType.SwitchType))) {
574             LOG.error("Failed to join Consumer Logical Router to Logical Switch in a Logical Network");
575             return;
576         }
577         LOG.debug("Attached Consumer Router {} to Consumer Switch {}", consLR.getUuid().getValue(),
578                 lNetbuilder.getConsumerNetwork().getLogicalSwitchId().getValue());
579         if (!UlnDatastoreApi.attachAndSubmitToDs(provLR.getUuid(), lNetbuilder.getProviderNetwork()
580             .getLogicalSwitchId(), faasTenantId, new Pair<>(LocationType.RouterType, LocationType.SwitchType))) {
581             LOG.error("Failed to join Provider Logical Router to Logical Switch in a Logical Network");
582             return;
583         }
584         LOG.debug("Attached Provider Router {} to Provider Switch {}", provLR.getUuid().getValue(),
585                 lNetbuilder.getProviderNetwork().getLogicalSwitchId().getValue());
586         ConsumerNetworkBuilder cNetBuilder = new ConsumerNetworkBuilder(lNetbuilder.getConsumerNetwork());
587         cNetBuilder.setLogicalRouterId(consLR.getUuid());
588         lNetbuilder.setConsumerNetwork(cNetBuilder.build());
589         ProviderNetworkBuilder pNetBuilder = new ProviderNetworkBuilder(lNetbuilder.getProviderNetwork());
590         pNetBuilder.setLogicalRouterId(provLR.getUuid());
591         lNetbuilder.setProviderNetwork(pNetBuilder.build());
592         lNetbuilder.setContractId(contractId);
593         lNetbuilder.setContractTenantId(gbpTenantId);
594         LogicalNetwork result = lNetbuilder.build();
595         WriteTransaction wTx = dataProvider.newWriteOnlyTransaction();
596         InstanceIdentifier<LogicalNetwork> iid = FaasIidFactory.logicalNetworkIid(
597                 consEpg.getId(), gbpTenantId, contractId, provEpg.getId(), gbpTenantId);
598         wTx.put(LogicalDatastoreType.OPERATIONAL, iid, result);
599         if (DataStoreHelper.submitToDs(wTx)) {
600             LOG.debug("Cached in Datastore Mapped Logical Network {}", result);
601         } else {
602             LOG.error("Couldn't Cache in Datastore Mapped Logical Network {}", result);
603         }
604         LOG.debug("Created Layer 3 Logical network consEpg {}, contractId {}, provEpg {}", consEpg.getId().getValue(),
605                 contractId.getValue(), provEpg.getId().getValue());
606     }
607
608     protected void createLayer2LogicalNetwork(EndpointGroup consEpg, ContractId contractId, EndpointGroup provEpg,
609             TenantId gbpTenantId, ServiceCommunicationLayer comLayer, ExternalImplicitGroup externalImplicitGroup) {
610         LOG.trace("Start createLayer2LogicalNetwork: Consumer EPG {}   Provider Epg {}   Contract {}", consEpg.getId()
611             .getValue(), provEpg.getId().getValue(), contractId);
612         Uuid secRulesId = getFaasSecRulesId(contractId, gbpTenantId);
613         if (secRulesId == null) {
614             LOG.error(
615                     "Couldn't Create Logical Network because unable to find FAAS Security Rules Id based on GBP Contract {}",
616                     contractId);
617             return;
618         }
619         LogicalNetworkBuilder lNetbuilder = buildLayer2LogicalNetwork(consEpg, provEpg, gbpTenantId, secRulesId,
620                 externalImplicitGroup);
621         if (lNetbuilder == null) {
622             LOG.error("Failed to create Logical Switchs layer on the Logical network");
623             return;
624         }
625
626         if (isConsumerPublic(externalImplicitGroup)) {
627             Uuid faasTenantId = getFaasTenantId(gbpTenantId);
628             LogicalRouterBuilder consLR = initLogicalRouterBuilder(consEpg, faasTenantId, true);
629             UlnDatastoreApi.submitLogicalRouterToDs(consLR.build());
630             ConsumerNetworkBuilder cNetBuilder = new ConsumerNetworkBuilder(lNetbuilder.getConsumerNetwork());
631             cNetBuilder.setLogicalRouterId(consLR.getUuid());
632             lNetbuilder.setConsumerNetwork(cNetBuilder.build());
633             if (!UlnDatastoreApi.attachAndSubmitToDs(consLR.getUuid(), lNetbuilder.getConsumerNetwork()
634                 .getLogicalSwitchId(), faasTenantId, new Pair<>(LocationType.RouterType, LocationType.SwitchType),
635                     null, null)) {
636                 LOG.error("Failed to join Consumer Public Logical Router to Logical Switch in a Logical Network");
637             }
638             LOG.debug("Attached Consumer Public Router {} to Consumer Switch {}", consLR.getUuid().getValue(),
639                     lNetbuilder.getConsumerNetwork().getLogicalSwitchId().getValue());
640         }
641         if (isProviderPublic(externalImplicitGroup)) {
642             Uuid faasTenantId = getFaasTenantId(gbpTenantId);
643             LogicalRouterBuilder provLR = initLogicalRouterBuilder(provEpg, faasTenantId, true);
644             provLR.setPublic(true);
645             UlnDatastoreApi.submitLogicalRouterToDs(provLR.build());
646             ProviderNetworkBuilder cNetBuilder = new ProviderNetworkBuilder(lNetbuilder.getProviderNetwork());
647             cNetBuilder.setLogicalRouterId(provLR.getUuid());
648             lNetbuilder.setProviderNetwork(cNetBuilder.build());
649             if (!UlnDatastoreApi.attachAndSubmitToDs(provLR.getUuid(), lNetbuilder.getProviderNetwork()
650                 .getLogicalSwitchId(), faasTenantId, new Pair<>(LocationType.RouterType, LocationType.SwitchType),
651                     null, null)) {
652                 LOG.error("Failed to join Provider Public Logical Router to Logical Switch in a Logical Network");
653             }
654             LOG.debug("Attached Provider Public Router {} to Provider Switch {}", provLR.getUuid().getValue(),
655                     lNetbuilder.getProviderNetwork().getLogicalSwitchId().getValue());
656         }
657
658         lNetbuilder.setContractId(contractId);
659         lNetbuilder.setContractTenantId(gbpTenantId);
660         LogicalNetwork result = lNetbuilder.build();
661         WriteTransaction wTx = dataProvider.newWriteOnlyTransaction();
662         InstanceIdentifier<LogicalNetwork> iid = FaasIidFactory.logicalNetworkIid(
663                 consEpg.getId(), gbpTenantId, contractId, provEpg.getId(), gbpTenantId);
664         wTx.put(LogicalDatastoreType.OPERATIONAL, iid, result);
665         if (DataStoreHelper.submitToDs(wTx)) {
666             LOG.debug("Cached in Datastore Mapped Logical Network {}", result);
667         } else {
668             LOG.error("Couldn't Cache in Datastore Mapped Logical Network {}", result);
669         }
670         LOG.debug("Created Layer 2 Logical network consEpg {}, contractId {}, provEpg {}", consEpg.getId().getValue(),
671                 contractId.getValue(), provEpg.getId().getValue());
672     }
673
674     private LogicalNetworkBuilder buildLayer2LogicalNetwork(EndpointGroup consEpg, EndpointGroup provEpg,
675             TenantId gbpTenantId, Uuid layer2SecRulesId, ExternalImplicitGroup externalImplicitGroup) {
676         LOG.trace("Start buildLayer2LogicalNetwork: Consumer EPG {}   Provider Epg {}", consEpg.getId().getValue(),
677                 provEpg.getId().getValue());
678         List<SubnetId> consSubnetIds = cloneAndGetEpgSubnets(consEpg.getId(), gbpTenantId);
679         List<Uuid> consFaasSubnetIds = new ArrayList<>();
680         for (SubnetId subnetId : consSubnetIds) {
681             Uuid id = getFaasSubnetId(subnetId, gbpTenantId);
682             if (id != null) {
683                 LOG.trace("Added to Consumer Network Faas Subnet {}", id.getValue());
684                 consFaasSubnetIds.add(id);
685             }
686         }
687         if (consFaasSubnetIds.isEmpty()) {
688             LOG.error("Couldn't find Faas subnets based on EPG {} -- Unable to create Layer2 Logical Network",
689                     consEpg.getId().getValue());
690             return null;
691         }
692         List<SubnetId> provSubnetIds = cloneAndGetEpgSubnets(provEpg.getId(), gbpTenantId);
693         List<Uuid> provFaasSubnetIds = new ArrayList<>();
694         for (SubnetId subnetId : provSubnetIds) {
695             Uuid id = getFaasSubnetId(subnetId, gbpTenantId);
696             if (id != null) {
697                 LOG.trace("Added to Provider Network Faas Subnet {}", id.getValue());
698                 provFaasSubnetIds.add(id);
699             }
700         }
701         if (provFaasSubnetIds.isEmpty()) {
702             LOG.error("Couldn't find Faas subnets based on EPG {} -- Unable to create Layer2 Logical Network",
703                     provEpg.getId().getValue());
704             return null;
705         }
706         Uuid faasTenantId = getFaasTenantId(gbpTenantId);
707         LogicalSwitchBuilder consLS = initLogicalSwitchBuilder(consEpg, faasTenantId);
708         LogicalSwitchBuilder provLS = initLogicalSwitchBuilder(provEpg, faasTenantId);
709         if (layer2SecRulesId != null) {
710             if (!UlnDatastoreApi.attachAndSubmitToDs(consLS, provLS, new Pair<Uuid, Uuid>(null, layer2SecRulesId))) {
711                 LOG.error("Failed to join Logical Switches in a Logical Network");
712                 return null;
713             }
714         } else {
715             UlnDatastoreApi.submitLogicalSwitchToDs(consLS.build());
716             UlnDatastoreApi.submitLogicalSwitchToDs(provLS.build());
717         }
718         for (Uuid subnetId : consFaasSubnetIds) {
719             if (!UlnDatastoreApi.attachAndSubmitToDs(consLS.getUuid(), subnetId, consLS.getTenantId(), new Pair<>(
720                     LocationType.SwitchType, LocationType.SubnetType))) {
721                 LOG.error("Failed to join Consumer Logical Switch with Subnet {} in a Logical Network", subnetId);
722                 return null;
723             }
724             LOG.debug("Attached Consumer Switch {} to Subnet {}", consLS.getUuid().getValue(), subnetId.getValue());
725         }
726         for (Uuid subnetId : provFaasSubnetIds) {
727             if (!UlnDatastoreApi.attachAndSubmitToDs(provLS.getUuid(), subnetId, provLS.getTenantId(), new Pair<>(
728                     LocationType.SwitchType, LocationType.SubnetType))) {
729                 LOG.error("Failed to join Provider Logical Switch with Subnet {} in a Logical Network", subnetId);
730                 return null;
731             }
732             LOG.debug("Attached Provider Switch {} to Subnet {}", provLS.getUuid().getValue(), subnetId.getValue());
733         }
734         LogicalNetworkBuilder lNetbuilder = new LogicalNetworkBuilder();
735         lNetbuilder.setConsumerEpgId(consEpg.getId());
736         lNetbuilder.setConsumerTenantId(gbpTenantId);
737         lNetbuilder.setContractTenantId(gbpTenantId);
738         lNetbuilder.setProviderEpgId(provEpg.getId());
739         lNetbuilder.setProviderTenantId(gbpTenantId);
740         ConsumerNetworkBuilder cNetBuilder = new ConsumerNetworkBuilder();
741         cNetBuilder.setLogicalSwitchId(consLS.getUuid());
742         cNetBuilder.setGbpSubnetId(consSubnetIds);
743         if (isConsumerPublic(externalImplicitGroup)) {
744             cNetBuilder.setNetworkScopeType(ScopeType.Public);
745         } else {
746             cNetBuilder.setNetworkScopeType(ScopeType.Private);
747         }
748         lNetbuilder.setConsumerNetwork(cNetBuilder.build());
749         ProviderNetworkBuilder pNetBuilder = new ProviderNetworkBuilder();
750         pNetBuilder.setLogicalSwitchId(provLS.getUuid());
751         pNetBuilder.setGbpSubnetId(provSubnetIds);
752         if (isProviderPublic(externalImplicitGroup)) {
753             pNetBuilder.setNetworkScopeType(ScopeType.Public);
754         } else {
755             pNetBuilder.setNetworkScopeType(ScopeType.Private);
756         }
757         lNetbuilder.setProviderNetwork(pNetBuilder.build());
758
759         return lNetbuilder;
760
761     }
762
763     private Uuid getFaasSubnetId(SubnetId subnetId, TenantId gbpTenantId) {
764         if (subnetId != null) {
765             Optional<MappedSubnet> mSubnetOp = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
766                     FaasIidFactory.mappedSubnetIid(gbpTenantId, subnetId),
767                     dataProvider.newReadOnlyTransaction());
768             if (mSubnetOp.isPresent()) {
769                 return mSubnetOp.get().getFaasSubnetId();
770             }
771         }
772         return null;
773     }
774
775     protected Uuid getFaasSecRulesId(ContractId contractId, TenantId gbpTenantId) {
776         if (contractId != null) {
777             Optional<MappedContract> mContractOp = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
778                     FaasIidFactory.mappedContractIid(gbpTenantId, contractId),
779                     dataProvider.newReadOnlyTransaction());
780             if (mContractOp.isPresent()) {
781                 return mContractOp.get().getFaasSecurityRulesId();
782             }
783         }
784         return null;
785     }
786
787     private LogicalRouterBuilder initLogicalRouterBuilder(EndpointGroup epg, Uuid tenantId, boolean isPublic) {
788         LogicalRouterBuilder builder = new LogicalRouterBuilder();
789         builder.setAdminStateUp(true);
790         builder.setName(new Text(epg.getId().getValue()));
791         if (epg.getDescription() != null)
792             builder.setDescription(new Text("gbp-epg: " + epg.getDescription().getValue()));
793         else
794             builder.setDescription(new Text("gbp-epg"));
795         builder.setPublic(isPublic);
796         builder.setTenantId(tenantId);
797         builder.setUuid(new Uuid(UUID.randomUUID().toString()));
798         return builder;
799     }
800
801     private LogicalSwitchBuilder initLogicalSwitchBuilder(EndpointGroup epg, Uuid tenantId) {
802         LogicalSwitchBuilder builder = new LogicalSwitchBuilder();
803         builder.setAdminStateUp(true);
804         builder.setName(new Text(epg.getId().getValue()));
805         if (epg.getDescription() != null)
806             builder.setDescription(new Text("gbp-epg: " + epg.getDescription().getValue()));
807         else
808             builder.setDescription(new Text("gbp-epg"));
809         builder.setTenantId(tenantId);
810         builder.setUuid(new Uuid(UUID.randomUUID().toString()));
811         return builder;
812     }
813
814     @VisibleForTesting
815     boolean needToCreateLogicalNetwork(ServiceCommunicationLayer comLayer, List<SubnetId> consSubnetIds,
816             List<SubnetId> provSubnetIds, TenantId tenantId, ContractId contractId, EndpointGroup providerEpg,
817             EndpointGroup consumerEpg, ExternalImplicitGroup externalImplicitGroup) {
818         Optional<LogicalNetwork> lnOp = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
819                 FaasIidFactory.logicalNetworkIid(consumerEpg.getId(), tenantId, contractId,
820                         providerEpg.getId(), tenantId), dataProvider.newReadOnlyTransaction());
821         if (!lnOp.isPresent()) {
822             return true;
823         }
824         LogicalNetwork logicalNet = lnOp.get();
825         if (!comLayer.equals(logicalNet.getCommunicationLayer())) {
826             return true;
827         }
828
829         boolean isConsPublic = logicalNet.getConsumerNetwork().getNetworkScopeType() != null
830                 && logicalNet.getConsumerNetwork().getNetworkScopeType() == ScopeType.Public;
831         if (isConsumerPublic(externalImplicitGroup) != isConsPublic) {
832             return true;
833         }
834         boolean isProvPublic = logicalNet.getProviderNetwork().getNetworkScopeType() != null
835                 && logicalNet.getProviderNetwork().getNetworkScopeType() == ScopeType.Public;
836         if (isProviderPublic(externalImplicitGroup) != isProvPublic) {
837             return true;
838         }
839         Set<SubnetId> lnConsSubnets = new HashSet<>(logicalNet.getConsumerNetwork().getGbpSubnetId());
840         if (lnConsSubnets.size() != consSubnetIds.size() || !lnConsSubnets.containsAll(consSubnetIds)) {
841             return true;
842         }
843         Set<SubnetId> lnProvSubnets = new HashSet<>(logicalNet.getProviderNetwork().getGbpSubnetId());
844         return lnProvSubnets.size() != provSubnetIds.size() || !lnProvSubnets.containsAll(
845                 provSubnetIds);
846     }
847
848     private ServiceCommunicationLayer findLayerNetwork(TenantId tenantId, List<SubnetId> consSubnetIds,
849             List<SubnetId> provSubnetIds) {
850         Subnet consSubnet = null;
851         Subnet provSubnet = null;
852         ContextId contextId = null;
853         for (SubnetId subnetId : consSubnetIds) {
854             consSubnet = readSubnet(subnetId, tenantId);
855             if (consSubnet == null) {
856                 LOG.error("Couldn't find subnet {} in datastore", subnetId);
857                 return null;
858             }
859             if (consSubnet.getParent() == null) {
860                 LOG.error("Flood domain is set to NULL in subnet " + consSubnet.getId());
861                 return null;
862             }
863             if (contextId == null) {
864                 contextId = consSubnet.getParent();
865             } else if (!contextId.equals(consSubnet.getParent())) {
866                 LOG.error("Flood domain is not the same for all Network domains in the Consumer EPG ");
867                 return null;
868             }
869         }
870
871         contextId = null;
872         for (SubnetId subnetId : provSubnetIds) {
873             provSubnet = readSubnet(subnetId, tenantId);
874             if (provSubnet == null) {
875                 LOG.error("Couldn't find subnet {} in datastore", subnetId);
876                 return null;
877             }
878             if (provSubnet.getParent() == null) {
879                 LOG.error("Flood domain is set to NULL in subnet " + provSubnet.getId());
880                 return null;
881             }
882             if (contextId == null) {
883                 contextId = provSubnet.getParent();
884             } else if (!contextId.equals(provSubnet.getParent())) {
885                 LOG.error("Flood domain is not the same for all Network domains in the Provider EPG ");
886                 return null;
887             }
888         }
889
890         if (consSubnet == null || provSubnet == null) {
891             LOG.error("Couldn't find Consumer and/or Provider subnets");
892             return null;
893         }
894
895         L2FloodDomainId consL2FldId = new L2FloodDomainId(consSubnet.getParent().getValue());
896         L2FloodDomain consFloodDomain = readL2FloodDomain(consL2FldId, tenantId);
897         if (consFloodDomain == null) {
898             LOG.error("Couldn't find flood domain instance in datastore with id " + consL2FldId);
899             return null;
900         }
901         L2FloodDomainId provL2FldId = new L2FloodDomainId(provSubnet.getParent().getValue());
902         L2FloodDomain provFloodDomain = readL2FloodDomain(provL2FldId, tenantId);
903         if (provFloodDomain == null) {
904             LOG.error("Couldn't find flood domain instance in datastore with id " + provL2FldId);
905             return null;
906         }
907
908         if (consFloodDomain.equals(provFloodDomain)) {
909             return ServiceCommunicationLayer.Layer2;
910         }
911
912         if (consFloodDomain.getParent() == null) {
913             LOG.error("Bridge domain is set to NULL in flood domain " + consFloodDomain.getId());
914             return null;
915         }
916         if (provFloodDomain.getParent() == null) {
917             LOG.error("Bridge domain is set to NULL in flood domain " + provFloodDomain.getId());
918             return null;
919         }
920
921         L2BridgeDomain consBridgeDomain = readL2BridgeDomainInstance(tenantId, consFloodDomain.getParent());
922         if (consBridgeDomain == null) {
923             LOG.error("Couldn't find bridge domain instance in datastore with id " + consFloodDomain.getParent());
924             return null;
925         }
926         L2BridgeDomain provBridgeDomain = readL2BridgeDomainInstance(tenantId, provFloodDomain.getParent());
927         if (provBridgeDomain == null) {
928             LOG.error("Couldn't find bridge domain instance in datastore with id " + provFloodDomain.getParent());
929             return null;
930         }
931         if (consBridgeDomain.equals(provBridgeDomain)) {
932             return ServiceCommunicationLayer.Layer2;
933         }
934
935         L3Context consL3ContextDomain = readL3ContextInstance(tenantId, consBridgeDomain.getParent());
936         if (consL3ContextDomain == null) {
937             LOG.error("Couldn't find L3 context instance in datastore with id " + consBridgeDomain.getParent());
938             return null;
939         }
940         L3Context provL3ContextDomain = readL3ContextInstance(tenantId, provBridgeDomain.getParent());
941         if (provL3ContextDomain == null) {
942             LOG.error("Couldn't find L3 context instance in datastore with id " + provBridgeDomain.getParent());
943             return null;
944         }
945         if (consL3ContextDomain.equals(provL3ContextDomain)) {
946             return ServiceCommunicationLayer.Layer3;
947         }
948         return null;
949     }
950
951     @VisibleForTesting
952     L3Context readL3ContextInstance(TenantId tenantId, L3ContextId l3cId) {
953         ReadOnlyTransaction rTx = dataProvider.newReadOnlyTransaction();
954         InstanceIdentifier<L3Context> iid = IidFactory.l3ContextIid(tenantId, l3cId);
955         Optional<L3Context> l2Op = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION, iid, rTx);
956         if (!l2Op.isPresent()) {
957             LOG.error("Couldn't find L3 Context Domain {} which belongs to Tenant {}", l3cId, tenantId);
958             rTx.close();
959             return null;
960         }
961         return l2Op.get();
962     }
963
964     @VisibleForTesting
965     L2BridgeDomain readL2BridgeDomainInstance(TenantId tenantId, L2BridgeDomainId l2bId) {
966         ReadOnlyTransaction rTx = dataProvider.newReadOnlyTransaction();
967         InstanceIdentifier<L2BridgeDomain> iid = IidFactory.l2BridgeDomainIid(tenantId, l2bId);
968         Optional<L2BridgeDomain> l2Op = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION, iid, rTx);
969         if (!l2Op.isPresent()) {
970             LOG.error("Couldn't find L2 Brdge Domain {} which belongs to Tenant {}", l2bId, tenantId);
971             rTx.close();
972             return null;
973         }
974         return l2Op.get();
975     }
976
977     @VisibleForTesting
978     L2FloodDomain readL2FloodDomain(L2FloodDomainId l2fId, TenantId tenantId) {
979         ReadOnlyTransaction rTx = dataProvider.newReadOnlyTransaction();
980         InstanceIdentifier<L2FloodDomain> iid = IidFactory.l2FloodDomainIid(tenantId, l2fId);
981         Optional<L2FloodDomain> l2Op = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION, iid, rTx);
982         if (!l2Op.isPresent()) {
983             LOG.error("Couldn't find L2 Flood Domain {} which belongs to Tenant {}", l2fId, tenantId);
984             rTx.close();
985             return null;
986         }
987         return l2Op.get();
988     }
989
990     public Subnet readSubnet(SubnetId subnetId, TenantId tenantId) {
991         ReadOnlyTransaction rTx = dataProvider.newReadOnlyTransaction();
992         InstanceIdentifier<Subnet> iid = IidFactory.subnetIid(tenantId, subnetId);
993         Optional<Subnet> subnetOp = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION, iid, rTx);
994         if (!subnetOp.isPresent()) {
995             LOG.warn("Couldn't find Subnet {} which belongs to Tenant {}", subnetId, tenantId);
996             rTx.close();
997             return null;
998         }
999         return subnetOp.get();
1000     }
1001
1002     public EndpointGroup readEndpointGroup(EndpointGroupId epgId, TenantId tenantId) {
1003         ReadOnlyTransaction rTx = dataProvider.newReadOnlyTransaction();
1004         InstanceIdentifier<EndpointGroup> iid = IidFactory.endpointGroupIid(tenantId, epgId);
1005         Optional<EndpointGroup> epgOp = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION, iid, rTx);
1006         if (!epgOp.isPresent()) {
1007             LOG.warn("Couldn't find EPG {} which belongs to Tenant {}", epgId, tenantId);
1008             rTx.close();
1009             return null;
1010         }
1011         return epgOp.get();
1012     }
1013
1014     private ContractId getContractId(ResolvedPolicy policy) {
1015         for (PolicyRuleGroupWithEndpointConstraints prgwec : policy.getPolicyRuleGroupWithEndpointConstraints()) {
1016             for (PolicyRuleGroup prg : prgwec.getPolicyRuleGroup()) {
1017                 return prg.getContractId();
1018             }
1019         }
1020         return null;
1021     }
1022
1023     public void removeTenantLogicalNetwork(TenantId gbpTenantId, Uuid faasTenantId) {
1024         removeTenantLogicalNetwork(gbpTenantId, faasTenantId, true);
1025     }
1026
1027     @VisibleForTesting
1028     void removeTenantLogicalNetwork(TenantId gbpTenantId, Uuid faasTenantId, boolean unregister) {
1029         UlnDatastoreApi.removeTenantFromDsIfExists(faasTenantId);
1030         synchronized (this) {
1031             mappedTenants.remove(gbpTenantId);
1032             Optional<LogicalNetworks> op3 = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
1033                     FaasIidFactory.logicalNetworksIid(), dataProvider.newReadOnlyTransaction());
1034             if (op3.isPresent()) {
1035                 LogicalNetworks logicalNetworks = op3.get();
1036                 for (LogicalNetwork ln : logicalNetworks.getLogicalNetwork()) {
1037                     if (ln.getConsumerTenantId().equals(gbpTenantId) || ln.getProviderTenantId().equals(gbpTenantId)) {
1038                         removeLogicalNetwork(ln.getConsumerEpgId(), ln.getConsumerTenantId(), ln.getContractId(),
1039                                 ln.getProviderEpgId(), ln.getProviderTenantId());
1040                     }
1041                 }
1042             }
1043             boolean toSubmit = false;
1044             ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
1045             Optional<MappedEntity> op1 = DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
1046                     FaasIidFactory.mappedEntityIid(gbpTenantId), rwTx);
1047             if (op1.isPresent()) {
1048                 toSubmit = true;
1049             }
1050             Optional<MappedTenant> op2 = DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
1051                     FaasIidFactory.mappedTenantIid(gbpTenantId), rwTx);
1052             if (op2.isPresent()) {
1053                 toSubmit = true;
1054             }
1055             if (toSubmit) {
1056                 DataStoreHelper.submitToDs(rwTx);
1057             }
1058
1059             if (unregister) {
1060                 unregisterTenant(gbpTenantId);
1061             }
1062         }
1063     }
1064 }