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