Fix copyright header
[groupbasedpolicy.git] / neutron-mapper / src / main / java / org / opendaylight / groupbasedpolicy / neutron / mapper / mapping / NeutronRouterAware.java
1 /*
2  * Copyright (c) 2015 Intel, Cisco Systems, Inc. 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
9 package org.opendaylight.groupbasedpolicy.neutron.mapper.mapping;
10
11 import static com.google.common.base.Preconditions.checkNotNull;
12
13 import java.util.ArrayList;
14 import java.util.List;
15
16 import javax.annotation.Nonnull;
17 import javax.annotation.Nullable;
18
19 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
20 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
21 import org.opendaylight.controller.md.sal.binding.api.ReadTransaction;
22 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
23 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
24 import org.opendaylight.groupbasedpolicy.neutron.mapper.infrastructure.Router;
25 import org.opendaylight.groupbasedpolicy.neutron.mapper.mapping.rule.NeutronSecurityRuleAware;
26 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.MappingUtils;
27 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.MappingUtils.ForwardingCtx;
28 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.NeutronMapperIidFactory;
29 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.Utils;
30 import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
31 import org.opendaylight.groupbasedpolicy.util.IidFactory;
32 import org.opendaylight.neutron.spi.INeutronPortCRUD;
33 import org.opendaylight.neutron.spi.INeutronRouterAware;
34 import org.opendaylight.neutron.spi.INeutronSubnetCRUD;
35 import org.opendaylight.neutron.spi.NeutronCRUDInterfaces;
36 import org.opendaylight.neutron.spi.NeutronPort;
37 import org.opendaylight.neutron.spi.NeutronRouter;
38 import org.opendaylight.neutron.spi.NeutronRouter_Interface;
39 import org.opendaylight.neutron.spi.NeutronSubnet;
40 import org.opendaylight.neutron.spi.Neutron_IPs;
41 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
42 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.Description;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2FloodDomainId;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L3ContextId;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.Name;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.NetworkDomainId;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubnetId;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.EndpointService;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.UnregisterEndpointInputBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.unregister.endpoint.input.L3;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.unregister.endpoint.input.L3Builder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.mapper.rev150223.mappings.network.mappings.NetworkMapping;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.EndpointGroup;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.L2BridgeDomain;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.L2BridgeDomainBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.L3Context;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.L3ContextBuilder;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.Subnet;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.SubnetBuilder;
62 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
63 import org.slf4j.Logger;
64 import org.slf4j.LoggerFactory;
65
66 import com.google.common.base.Optional;
67 import com.google.common.base.Strings;
68 import com.google.common.collect.ImmutableList;
69
70 public class NeutronRouterAware implements INeutronRouterAware {
71
72     private static final Logger LOG = LoggerFactory.getLogger(NeutronRouterAware.class);
73     private final DataBroker dataProvider;
74     private final  EndpointService epService;
75     private final NeutronSecurityRuleAware secRuleAware;
76
77     public NeutronRouterAware(DataBroker dataProvider, EndpointService epService, NeutronSecurityRuleAware secRuleAware) {
78         this.dataProvider = checkNotNull(dataProvider);
79         this.epService = checkNotNull(epService);
80         this.secRuleAware = checkNotNull(secRuleAware);
81     }
82
83     @Override
84     public int canCreateRouter(NeutronRouter router) {
85         LOG.trace("canCreateRouter - {}", router);
86         // nothing to consider
87         return StatusCode.OK;
88     }
89
90     @Override
91     public void neutronRouterCreated(NeutronRouter router) {
92         LOG.trace("neutronRouterCreated - {}", router);
93         // TODO Li msunal external gateway
94     }
95
96     @Override
97     public int canUpdateRouter(NeutronRouter delta, NeutronRouter original) {
98         LOG.trace("canUpdateRouter - delta: {} original: {}", delta, original);
99         // TODO Li msunal external gateway
100         return StatusCode.OK;
101     }
102
103     @Override
104     public void neutronRouterUpdated(NeutronRouter router) {
105         LOG.trace("neutronRouterUpdated - {}", router);
106         if (router.getExternalGatewayInfo() == null || router.getExternalGatewayInfo().getExternalFixedIPs() == null) {
107             LOG.trace("neutronRouterUpdated - not an external Gateway");
108             return;
109         }
110
111         NeutronCRUDInterfaces neutronCRUDInterface = new NeutronCRUDInterfaces().fetchINeutronPortCRUD(this);
112         INeutronPortCRUD portInterface = neutronCRUDInterface.getPortInterface();
113         if (portInterface == null) {
114             LOG.warn("Illegal state - No provider for {}", INeutronPortCRUD.class.getName());
115             return;
116         }
117
118         ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
119         TenantId tenantId = new TenantId(Utils.normalizeUuid(router.getTenantID()));
120         L3ContextId l3ContextIdFromRouterId = new L3ContextId(router.getID());
121         InstanceIdentifier<L3Context> l3ContextIidForRouterId = IidFactory.l3ContextIid(tenantId,
122                 l3ContextIdFromRouterId);
123         Optional<L3Context> potentialL3ContextForRouter = DataStoreHelper.readFromDs(
124                 LogicalDatastoreType.CONFIGURATION, l3ContextIidForRouterId, rwTx);
125         L3Context l3Context = null;
126         if (potentialL3ContextForRouter.isPresent()) {
127             l3Context = potentialL3ContextForRouter.get();
128         } else { // add L3 context if missing
129             l3Context = createL3ContextFromRouter(router);
130             rwTx.put(LogicalDatastoreType.CONFIGURATION, l3ContextIidForRouterId, l3Context);
131         }
132
133         neutronCRUDInterface = neutronCRUDInterface.fetchINeutronSubnetCRUD(this);
134         INeutronSubnetCRUD subnetInterface = neutronCRUDInterface.getSubnetInterface();
135         if (subnetInterface == null) {
136             LOG.warn("Illegal state - No provider for {}", INeutronSubnetCRUD.class.getName());
137             return;
138         }
139         NeutronSubnet defaultSubnet = subnetInterface.getSubnet(router.getExternalGatewayInfo()
140             .getExternalFixedIPs()
141             .get(0)
142             .getSubnetUUID());
143         IpAddress defaultGateway = null;
144         if (defaultSubnet != null) {
145             defaultGateway = Utils.createIpAddress(defaultSubnet.getGatewayIP());
146             //Create L3Endpoint for defaultGateway and write to externalGateways to L3Endpoints in neutron-gbp datastore
147             NetworkDomainId containment = new NetworkDomainId(defaultSubnet.getID());
148             NeutronPortAware.addL3EndpointForExternalGateway(tenantId, l3Context.getId(), defaultGateway, containment ,rwTx);
149         }
150         // Create L3Prefix Endpoints for all routes
151         if (router.getRoutes().isEmpty()) {
152             List<String> defaultRoute = ImmutableList.of("0.0.0.0/0");
153             router.setRoutes(defaultRoute);
154
155         }
156         if (l3ContextIdFromRouterId != null) {
157             for (String route : router.getRoutes()) {
158                 IpPrefix ipPrefix = Utils.createIpPrefix(route);
159                 boolean addedL3Prefix = NeutronPortAware.addL3PrefixEndpoint(l3ContextIdFromRouterId, ipPrefix,
160                         defaultGateway, tenantId, epService);
161                 if (!addedL3Prefix) {
162                     LOG.warn("Could not add EndpointL3Prefix for Neutron route {} for router {}", route, router.getID());
163                     rwTx.cancel();
164                     return;
165                 }
166             }
167         }
168         for (Neutron_IPs externalFixedIp : router.getExternalGatewayInfo().getExternalFixedIPs()) {
169             NeutronPort routerPort = portInterface.getPort(router.getGatewayPortId());
170             IpAddress ipAddress = Utils.createIpAddress(routerPort.getFixedIPs().get(0).getIpAddress());
171             // External subnet associated with gateway port should use the gateway IP not router IP.
172             NeutronSubnet neutronSubnet = subnetInterface.getSubnet(externalFixedIp.getSubnetUUID());
173             ipAddress = Utils.createIpAddress(neutronSubnet.getGatewayIP());
174             SubnetId subnetId = new SubnetId(externalFixedIp.getSubnetUUID());
175             Subnet subnet = resolveSubnetWithVirtualRouterIp(tenantId, subnetId, ipAddress, rwTx);
176             if (subnet == null) {
177                 rwTx.cancel();
178                 return;
179             }
180             rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.subnetIid(tenantId, subnet.getId()), subnet);
181
182             if (Strings.isNullOrEmpty(routerPort.getTenantID())) {
183                 routerPort.setTenantID(router.getTenantID());
184             }
185
186             boolean isSuccessful = setNewL3ContextToEpsFromSubnet(tenantId, l3Context, subnet, rwTx);
187             if (!isSuccessful) {
188                 rwTx.cancel();
189                 return;
190             }
191         }
192
193         DataStoreHelper.submitToDs(rwTx);
194     }
195
196     @Override
197     public int canDeleteRouter(NeutronRouter router) {
198         LOG.trace("canDeleteRouter - {}", router);
199         // nothing to consider
200         return StatusCode.OK;
201     }
202
203     @Override
204     public void neutronRouterDeleted(NeutronRouter router) {
205         LOG.trace("neutronRouterDeleted - {}", router);
206         ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
207         TenantId tenantId = new TenantId(Utils.normalizeUuid(router.getTenantID()));
208         Optional<EndpointGroup> potentialEpg = DataStoreHelper.removeIfExists(LogicalDatastoreType.CONFIGURATION,
209                 IidFactory.endpointGroupIid(tenantId, Router.EPG_ID), rwTx);
210         if (!potentialEpg.isPresent()) {
211             LOG.warn("Illegal state - Endpoint group {} does not exist.", Router.EPG_ID.getValue());
212             rwTx.cancel();
213             return;
214         }
215         DataStoreHelper.submitToDs(rwTx);
216     }
217
218     @Override
219     public int canAttachInterface(NeutronRouter router, NeutronRouter_Interface routerInterface) {
220         LOG.trace("canAttachInterface - router: {} interface: {}", router, routerInterface);
221         try (ReadOnlyTransaction rTx = dataProvider.newReadOnlyTransaction()) {
222             L3ContextId l3ContextIdFromRouterId = new L3ContextId(router.getID());
223             TenantId tenantId = new TenantId(Utils.normalizeUuid(router.getTenantID()));
224             SubnetId subnetId = new SubnetId(routerInterface.getSubnetUUID());
225             Optional<Subnet> potentialSubnet = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
226                     IidFactory.subnetIid(tenantId, subnetId), rTx);
227             if (!potentialSubnet.isPresent()) {
228                 LOG.warn("Illegal state - subnet {} does not exist.", subnetId.getValue());
229                 return StatusCode.NOT_FOUND;
230             }
231             Subnet subnet = potentialSubnet.get();
232             L2FloodDomainId l2FdId = new L2FloodDomainId(subnet.getParent().getValue());
233             ForwardingCtx fwCtx = MappingUtils.createForwardingContext(tenantId, l2FdId, rTx);
234             if (fwCtx.getL3Context() != null && fwCtx.getL3Context().getId().equals(l3ContextIdFromRouterId)) {
235                 // TODO Be msunal
236                 LOG.warn("Illegal state - Neutron mapper does not support multiple router interfaces in the same subnet yet.");
237                 return StatusCode.FORBIDDEN;
238             }
239             return StatusCode.OK;
240         }
241     }
242
243     @Override
244     public void neutronRouterInterfaceAttached(NeutronRouter router, NeutronRouter_Interface routerInterface) {
245         LOG.trace("neutronRouterInterfaceAttached - router: {} interface: {}", router, routerInterface);
246         NeutronCRUDInterfaces neutronCRUDInterface = new NeutronCRUDInterfaces().fetchINeutronPortCRUD(this);
247         INeutronPortCRUD portInterface = neutronCRUDInterface.getPortInterface();
248         if (portInterface == null) {
249             LOG.warn("Illegal state - No provider for {}", INeutronPortCRUD.class.getName());
250             return;
251         }
252
253         ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
254         TenantId tenantId = new TenantId(Utils.normalizeUuid(router.getTenantID()));
255         L3ContextId l3ContextIdFromRouterId = new L3ContextId(router.getID());
256         InstanceIdentifier<L3Context> l3ContextIidForRouterId = IidFactory.l3ContextIid(tenantId,
257                 l3ContextIdFromRouterId);
258         Optional<L3Context> potentialL3ContextForRouter = DataStoreHelper.readFromDs(
259                 LogicalDatastoreType.CONFIGURATION, l3ContextIidForRouterId, rwTx);
260         L3Context l3Context = null;
261         if (potentialL3ContextForRouter.isPresent()) {
262             l3Context = potentialL3ContextForRouter.get();
263         } else { // add L3 context if missing
264             l3Context = createL3ContextFromRouter(router);
265             rwTx.put(LogicalDatastoreType.CONFIGURATION, l3ContextIidForRouterId, l3Context);
266         }
267
268         // Based on Neutron Northbound - Port representing router interface
269         // contains exactly on fixed IP
270         NeutronPort routerPort = portInterface.getPort(routerInterface.getPortUUID());
271         SubnetId subnetId = new SubnetId(routerInterface.getSubnetUUID());
272         IpAddress ipAddress = Utils.createIpAddress(routerPort.getFixedIPs().get(0).getIpAddress());
273         Subnet subnet = resolveSubnetWithVirtualRouterIp(tenantId, subnetId, ipAddress, rwTx);
274         if (subnet == null) {
275             rwTx.cancel();
276             return;
277         }
278         rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.subnetIid(tenantId, subnet.getId()), subnet);
279
280         boolean isSuccessful = setNewL3ContextToEpsFromSubnet(tenantId, l3Context, subnet, rwTx);
281         if (!isSuccessful) {
282             rwTx.cancel();
283             return;
284         }
285
286         DataStoreHelper.submitToDs(rwTx);
287     }
288
289     private static @Nonnull L3Context createL3ContextFromRouter(NeutronRouter router) {
290         Name l3ContextName = null;
291         if (!Strings.isNullOrEmpty(router.getName())) {
292             l3ContextName = new Name(router.getName());
293         }
294         return new L3ContextBuilder().setId(new L3ContextId(router.getID()))
295             .setName(l3ContextName)
296             .setDescription(new Description(MappingUtils.NEUTRON_ROUTER + router.getID()))
297             .build();
298     }
299
300     private @Nullable Subnet resolveSubnetWithVirtualRouterIp(TenantId tenantId, SubnetId subnetId,
301             IpAddress ipAddress, ReadTransaction rTx) {
302         Optional<Subnet> potentialSubnet = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
303                 IidFactory.subnetIid(tenantId, subnetId), rTx);
304         if (!potentialSubnet.isPresent()) {
305             LOG.warn("Illegal state - subnet {} does not exist.", subnetId.getValue());
306             return null;
307         }
308
309         // TODO: Li alagalah: Add gateways and prefixes instead of
310         // VirtualRouterID
311         return new SubnetBuilder(potentialSubnet.get()).setVirtualRouterIp(ipAddress).build();
312     }
313
314     /**
315      * @return {@code false} if illegal state occurred; {@code true} otherwise
316      */
317     public boolean setNewL3ContextToEpsFromSubnet(TenantId tenantId, L3Context l3Context, Subnet subnet,
318             ReadWriteTransaction rwTx) {
319         if (subnet.getParent() == null) {
320             LOG.warn("Illegal state - subnet {} does not have a parent.", subnet.getId().getValue());
321             return false;
322         }
323
324         L2FloodDomainId l2FdId = new L2FloodDomainId(subnet.getParent().getValue());
325         ForwardingCtx fwCtx = MappingUtils.createForwardingContext(tenantId, l2FdId, rwTx);
326         if (fwCtx.getL2BridgeDomain() == null) {
327             LOG.warn("Illegal state - l2-flood-domain {} does not have a parent.", l2FdId.getValue());
328             return false;
329         }
330
331         L2BridgeDomain l2BridgeDomain = new L2BridgeDomainBuilder(fwCtx.getL2BridgeDomain()).setParent(
332                 l3Context.getId()).build();
333         rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.l2BridgeDomainIid(tenantId, l2BridgeDomain.getId()),
334                 l2BridgeDomain);
335
336         NeutronCRUDInterfaces neutronCRUDInterface = new NeutronCRUDInterfaces().fetchINeutronSubnetCRUD(this);
337         INeutronSubnetCRUD subnetInterface = neutronCRUDInterface.getSubnetInterface();
338         if (subnetInterface == null) {
339             LOG.warn("Illegal state - No provider for {}", INeutronSubnetCRUD.class.getName());
340             return false;
341         }
342
343         List<L3> l3Eps = new ArrayList<>();
344         L3ContextId oldL3ContextId = fwCtx.getL3Context().getId();
345         NeutronSubnet neutronSubnet = subnetInterface.getSubnet(subnet.getId().getValue());
346         List<NeutronPort> portsInNeutronSubnet = neutronSubnet.getPortsInSubnet();
347         for (NeutronPort port : portsInNeutronSubnet) {
348             boolean isPortAdded = NeutronPortAware.addNeutronPort(port, rwTx, epService);
349             if (!isPortAdded) {
350                 return false;
351             }
352             // TODO Li msunal this has to be rewrite when OFOverlay renderer
353             // will support l3-endpoints.
354             Neutron_IPs firstIp = MappingUtils.getFirstIp(port.getFixedIPs());
355             if (firstIp != null) {
356                 l3Eps.add(new L3Builder().setL3Context(oldL3ContextId)
357                     .setIpAddress(Utils.createIpAddress(firstIp.getIpAddress()))
358                     .build());
359             }
360         }
361         if (neutronSubnet.getGatewayIP() != null) {
362             l3Eps.add(new L3Builder().setL3Context(oldL3ContextId)
363                     .setIpAddress(Utils.createIpAddress(neutronSubnet.getGatewayIP()))
364                     .build());
365         }
366
367         if (!l3Eps.isEmpty()) {
368             epService.unregisterEndpoint(new UnregisterEndpointInputBuilder().setL3(l3Eps).build());
369         }
370         return true;
371     }
372
373     @Override
374     public int canDetachInterface(NeutronRouter router, NeutronRouter_Interface routerInterface) {
375         LOG.trace("canDetachInterface - router: {} interface: {}", router, routerInterface);
376         // nothing to consider
377         return StatusCode.OK;
378     }
379
380     @Override
381     public void neutronRouterInterfaceDetached(NeutronRouter router, NeutronRouter_Interface routerInterface) {
382         LOG.trace("neutronRouterInterfaceDetached - router: {} interface: {}", router, routerInterface);
383         NeutronCRUDInterfaces neutronCRUDInterface = new NeutronCRUDInterfaces().fetchINeutronSubnetCRUD(this);
384         INeutronSubnetCRUD subnetInterface = neutronCRUDInterface.getSubnetInterface();
385         if (subnetInterface == null) {
386             LOG.warn("Illegal state - No provider for {}", INeutronSubnetCRUD.class.getName());
387             return;
388         }
389
390         ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
391         TenantId tenantId = new TenantId(Utils.normalizeUuid(router.getTenantID()));
392         L3ContextId l3ContextId = new L3ContextId(router.getID());
393         SubnetId subnetId = new SubnetId(routerInterface.getSubnetUUID());
394         InstanceIdentifier<L3Context> l3ContextIid = IidFactory.l3ContextIid(tenantId, l3ContextId);
395         DataStoreHelper.removeIfExists(LogicalDatastoreType.CONFIGURATION,
396                 IidFactory.l3ContextIid(tenantId, l3ContextId), rwTx);
397
398         Optional<Subnet> potentialSubnet = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
399                 IidFactory.subnetIid(tenantId, subnetId), rwTx);
400         if (!potentialSubnet.isPresent()) {
401             LOG.warn("Illegal state - subnet {} does not exist.", subnetId.getValue());
402             rwTx.cancel();
403             return;
404         }
405
406         Subnet subnet = new SubnetBuilder(potentialSubnet.get()).setVirtualRouterIp(null).build();
407         rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.subnetIid(tenantId, subnetId), subnet);
408
409         L2FloodDomainId l2FdId = new L2FloodDomainId(subnet.getParent().getValue());
410         ForwardingCtx fwCtx = MappingUtils.createForwardingContext(tenantId, l2FdId, rwTx);
411         if (fwCtx.getL2BridgeDomain() == null) {
412             LOG.warn("Illegal state - l2-flood-domain {} does not have a parent.", l2FdId.getValue());
413             rwTx.cancel();
414             return;
415         }
416
417         Optional<NetworkMapping> potentialNetworkMapping = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
418                 NeutronMapperIidFactory.networkMappingIid(l2FdId), rwTx);
419         if (!potentialNetworkMapping.isPresent()) {
420             LOG.warn("Illegal state - network-mapping {} does not exist.", l2FdId.getValue());
421             rwTx.cancel();
422             return;
423         }
424
425         L2BridgeDomain l2BridgeDomain = new L2BridgeDomainBuilder(fwCtx.getL2BridgeDomain()).setParent(
426                 potentialNetworkMapping.get().getL3ContextId()).build();
427         rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.l2BridgeDomainIid(tenantId, l2BridgeDomain.getId()),
428                 l2BridgeDomain);
429
430         NeutronSubnet neutronSubnet = subnetInterface.getSubnet(subnetId.getValue());
431         List<NeutronPort> portsInNeutronSubnet = neutronSubnet.getPortsInSubnet();
432         for (NeutronPort port : portsInNeutronSubnet) {
433             boolean isPortAdded = NeutronPortAware.addNeutronPort(port, rwTx, epService);
434             if (!isPortAdded) {
435                 rwTx.cancel();
436                 return;
437             }
438         }
439     }
440
441 }