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