apply checkstyle check during build for neutron-mapper
[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 com.google.common.base.Optional;
14 import com.google.common.base.Strings;
15 import com.google.common.collect.ImmutableList;
16
17 import java.util.Collections;
18 import java.util.List;
19
20 import javax.annotation.Nonnull;
21
22 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
23 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
24 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
25 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
26 import org.opendaylight.groupbasedpolicy.domain_extension.l2_l3.util.L2L3IidFactory;
27 import org.opendaylight.groupbasedpolicy.neutron.gbp.util.NeutronGbpIidFactory;
28 import org.opendaylight.groupbasedpolicy.neutron.mapper.EndpointRegistrator;
29 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.MappingUtils;
30 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.NetworkUtils;
31 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.PortUtils;
32 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.SubnetUtils;
33 import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
34 import org.opendaylight.groupbasedpolicy.util.IidFactory;
35 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
36 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
37 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.common.endpoint.fields.NetworkContainmentBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.common.endpoint.fields.network.containment.containment.NetworkDomainContainmentBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.register.endpoint.input.AddressEndpointRegBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.unregister.endpoint.input.AddressEndpointUnregBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContextId;
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.L2BridgeDomainId;
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.Endpoints;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Key;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Prefix;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3PrefixKey;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev170511.IpPrefixType;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev170511.SubnetAugmentForwarding;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev170511.SubnetAugmentForwardingBuilder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev170511.has.subnet.Subnet;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev170511.has.subnet.SubnetBuilder;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev170511.has.subnet.subnet.Gateways;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev170511.has.subnet.subnet.GatewaysBuilder;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev170511.has.subnet.subnet.gateways.Prefixes;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev170511.has.subnet.subnet.gateways.PrefixesBuilder;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.fields.Parent;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.forwarding.by.tenant.ForwardingContext;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.forwarding.by.tenant.ForwardingContextBuilder;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.forwarding.by.tenant.NetworkDomain;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.forwarding.by.tenant.NetworkDomainBuilder;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.forwarding.by.tenant.NetworkDomainKey;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.neutron.by.gbp.mappings.external.gateways.as.endpoints.ExternalGatewayAsEndpoint;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.neutron.by.gbp.mappings.external.gateways.as.l3.endpoints.ExternalGatewayAsL3Endpoint;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L2BridgeDomain;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L2BridgeDomainBuilder;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L3Context;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L3ContextBuilder;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.Routers;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.Router;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
81 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
82 import org.slf4j.Logger;
83 import org.slf4j.LoggerFactory;
84
85 public class NeutronRouterAware implements NeutronAware<Router> {
86
87     private static final Logger LOG = LoggerFactory.getLogger(NeutronRouterAware.class);
88     public static final InstanceIdentifier<Router> ROUTER_WILDCARD_IID =
89             InstanceIdentifier.builder(Neutron.class).child(Routers.class).child(Router.class).build();
90     private final DataBroker dataProvider;
91     private final EndpointRegistrator epRegistrator;
92
93     public NeutronRouterAware(DataBroker dataProvider, EndpointRegistrator epRegistrator) {
94         this.dataProvider = checkNotNull(dataProvider);
95         this.epRegistrator = checkNotNull(epRegistrator);
96     }
97
98     @Override
99     public void onCreated(Router router, Neutron neutron) {
100         LOG.trace("created router - {}", router);
101
102         ContextId routerl3ContextId = new ContextId(router.getUuid().getValue());
103         TenantId tenantId = new TenantId(router.getTenantId().getValue());
104         InstanceIdentifier<ForwardingContext> routerL3CtxIid = L2L3IidFactory.l3ContextIid(tenantId, routerl3ContextId);
105         ForwardingContextBuilder fwdCtxBuilder = new ForwardingContextBuilder();
106         Name routerName = null;
107         if (!Strings.isNullOrEmpty(router.getName())) {
108             try {
109                 routerName = new Name(router.getName());
110                 fwdCtxBuilder.setName(routerName);
111             } catch (NullPointerException | IllegalArgumentException e) {
112                 LOG.info("Name '{}' of Neutron Subnet '{}' is ignored.", router.getName(),
113                         router.getUuid().getValue());
114                 LOG.debug("Name exception", e);
115             }
116         }
117         ForwardingContext routerl3Context = fwdCtxBuilder.setContextId(routerl3ContextId)
118             .setContextType(MappingUtils.L3_CONTEXT)
119             .build();
120         WriteTransaction writeTx = dataProvider.newWriteOnlyTransaction();
121         writeTx.put(LogicalDatastoreType.CONFIGURATION, routerL3CtxIid, routerl3Context, true);
122         createTenantL3Context(new L3ContextId(routerl3ContextId), tenantId, routerName, writeTx);
123         DataStoreHelper.submitToDs(writeTx);
124     }
125
126     @Deprecated
127     private void createTenantL3Context(L3ContextId l3ContextId, TenantId tenantId, Name name,
128         WriteTransaction writeTx) {
129         L3ContextBuilder l3ContextBuilder = new L3ContextBuilder();
130         if (name != null) {
131             l3ContextBuilder.setName(name);
132         }
133         L3Context l3Context = l3ContextBuilder.setId(l3ContextId).build();
134         writeTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.l3ContextIid(tenantId, l3ContextId), l3Context,
135             true);
136     }
137
138     @Override
139     @SuppressWarnings("checkstyle:LineLength") // Longer lines in this method are caused by long package names,
140                                                // this will be removed when deprecated classes will be cleared.
141     public void onUpdated(Router oldRouter, Router newRouter, Neutron oldNeutron, Neutron newNeutron) {
142         LOG.trace("updated router - OLD: {}\nNEW: {}", oldRouter, newRouter);
143
144         ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
145         TenantId tenantId = new TenantId(newRouter.getTenantId().getValue());
146         ContextId routerL3CtxId = new ContextId(newRouter.getUuid().getValue());
147
148         if (newRouter.getGatewayPortId() != null && oldRouter.getGatewayPortId() == null) {
149             // external network is attached to router
150             Uuid gatewayPortId = newRouter.getGatewayPortId();
151             Optional<Port> potentialGwPort = PortUtils.findPort(gatewayPortId, newNeutron.getPorts());
152             if (!potentialGwPort.isPresent()) {
153                 LOG.warn("Illegal state - router gateway port {} does not exist for router {}.",
154                         gatewayPortId.getValue(), newRouter);
155                 rwTx.cancel();
156                 return;
157             }
158
159             Port gwPort = potentialGwPort.get();
160             List<FixedIps> fixedIpsFromGwPort = gwPort.getFixedIps();
161             if (fixedIpsFromGwPort == null || fixedIpsFromGwPort.isEmpty()) {
162                 LOG.warn("Illegal state - router gateway port {} does not contain fixed IPs {}",
163                         gatewayPortId.getValue(), gwPort);
164                 rwTx.cancel();
165                 return;
166             }
167
168             // router can have only one external network
169             FixedIps ipWithSubnetFromGwPort = fixedIpsFromGwPort.get(0);
170             Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet>
171                 potentialSubnet = SubnetUtils.findSubnet(ipWithSubnetFromGwPort.getSubnetId(), newNeutron.getSubnets());
172             if (!potentialSubnet.isPresent()) {
173                 LOG.warn("Illegal state - Subnet {} does not exist for router {}.",
174                         ipWithSubnetFromGwPort.getSubnetId(), newRouter);
175                 rwTx.cancel();
176                 return;
177             }
178             tenantId = new TenantId(potentialSubnet.get().getTenantId().getValue());
179             IpAddress gwIp = potentialSubnet.get().getGatewayIp();
180             IpPrefix gatewayIp =  MappingUtils.ipAddressToIpPrefix(gwIp);
181             NetworkDomainId subnetId = new NetworkDomainId(ipWithSubnetFromGwPort.getSubnetId().getValue());
182             boolean registeredExternalGateway = registerExternalGateway(tenantId, gatewayIp, routerL3CtxId, subnetId);
183             if (!registeredExternalGateway) {
184                 LOG.warn("Could not add L3Prefix as gateway of default route. Gateway port {}", gwPort);
185                 rwTx.cancel();
186                 return;
187             }
188             addNeutronExtGwGbpMapping(routerL3CtxId, gatewayIp, rwTx);
189             NetworkDomain subnetDomain;
190             List<Prefixes> defaultPrefixes =
191                 Collections.singletonList(new PrefixesBuilder().setPrefix(MappingUtils.DEFAULT_ROUTE).build());
192             // if subnet is in external network then create subnet with IP from GW port as its virtual router IP
193             // else use subnet gateway as virtual router IP.
194             if (isSubnetInExternalNetwork(newNeutron.getNetworks().getNetwork(),
195                 potentialSubnet.get().getNetworkId())) {
196                 subnetDomain = createSubnetWithVirtualRouterIp(
197                         MappingUtils.ipAddressToIpPrefix(ipWithSubnetFromGwPort.getIpAddress()), subnetId,
198                         Collections.singletonList(
199                             new GatewaysBuilder().setGateway(gwIp).setPrefixes(defaultPrefixes).build()));
200             } else {
201                 subnetDomain = createSubnetWithVirtualRouterIp(gatewayIp, subnetId, Collections.singletonList(
202                     new GatewaysBuilder().setGateway(gwIp).setPrefixes(defaultPrefixes).build()));
203             }
204             rwTx.merge(LogicalDatastoreType.CONFIGURATION,
205                 L2L3IidFactory.subnetIid(tenantId, subnetDomain.getNetworkDomainId()), subnetDomain);
206             ContextId l2BdId = new ContextId(potentialSubnet.get().getNetworkId().getValue());
207             Optional<ForwardingContext> optBd = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
208                     L2L3IidFactory.l2BridgeDomainIid(tenantId, l2BdId), rwTx);
209             if (!optBd.isPresent()) {
210                 LOG.warn(
211                     "Could not read L2BridgeDomain {}. Modification of its parent to L3Context of router {} aborted.",
212                         l2BdId, newRouter.getUuid());
213                 rwTx.cancel();
214                 return;
215             }
216             ForwardingContext forwardingContext = optBd.get();
217             ForwardingContext l2BdWithGw = new ForwardingContextBuilder(forwardingContext)
218                 .setParent(MappingUtils.createParent(routerL3CtxId, MappingUtils.L3_CONTEXT))
219                 .build();
220             rwTx.put(LogicalDatastoreType.CONFIGURATION, L2L3IidFactory.l2BridgeDomainIid(tenantId, l2BdId),
221                     l2BdWithGw);
222         }
223         updateTenantForwarding(newNeutron, oldRouter, newRouter, new L3ContextId(routerL3CtxId), tenantId, rwTx);
224         DataStoreHelper.submitToDs(rwTx);
225     }
226
227     private boolean isSubnetInExternalNetwork(List<Network> networks, Uuid networkId) {
228         return networks.stream().anyMatch(net -> net.getUuid().equals(networkId) && NetworkUtils.isRouterExternal(net));
229     }
230
231     private boolean registerExternalGateway(TenantId tenantId, IpPrefix ipPrefix, ContextId routerl3ContextId,
232             NetworkDomainId networkDomainId) {
233         AddressEndpointRegBuilder addrEpBuilder = new AddressEndpointRegBuilder();
234         addrEpBuilder.setAddressType(IpPrefixType.class);
235         addrEpBuilder.setAddress(MappingUtils.ipPrefixToStringIpAddress(ipPrefix));
236         addrEpBuilder.setContextId(routerl3ContextId);
237         addrEpBuilder.setContextType(MappingUtils.L3_CONTEXT);
238         addrEpBuilder.setTenant(tenantId);
239         addrEpBuilder
240             .setNetworkContainment(new NetworkContainmentBuilder().setContainment(new NetworkDomainContainmentBuilder()
241                 .setNetworkDomainId(networkDomainId).setNetworkDomainType(MappingUtils.SUBNET).build()).build());
242         addrEpBuilder.setEndpointGroup(ImmutableList.of(MappingUtils.EPG_EXTERNAL_ID));
243         addrEpBuilder.setTimestamp(System.currentTimeMillis());
244         return epRegistrator.registerEndpoint(addrEpBuilder.build());
245     }
246
247     private boolean unregisterExternalGateway(IpPrefix ipPrefix, ContextId routerl3ContextId) {
248         AddressEndpointUnregBuilder addrEpBuilder = new AddressEndpointUnregBuilder();
249         addrEpBuilder.setAddressType(IpPrefixType.class);
250         addrEpBuilder.setAddress(MappingUtils.ipPrefixToStringIpAddress(ipPrefix));
251         addrEpBuilder.setContextId(routerl3ContextId);
252         addrEpBuilder.setContextType(MappingUtils.L3_CONTEXT);
253         return epRegistrator.unregisterEndpoint(addrEpBuilder.build());
254     }
255
256     private NetworkDomain createSubnetWithVirtualRouterIp(IpPrefix gatewayIp, NetworkDomainId subnetId,
257         List<Gateways> gateways) {
258
259         Subnet subnet =
260             new SubnetBuilder().setVirtualRouterIp(MappingUtils.ipPrefixToIpAddress(gatewayIp.getValue()))
261                 .setGateways(gateways)
262                 .build();
263         return new NetworkDomainBuilder().setKey(new NetworkDomainKey(subnetId, MappingUtils.SUBNET))
264             .addAugmentation(SubnetAugmentForwarding.class,
265                 new SubnetAugmentForwardingBuilder().setSubnet(subnet).build())
266             .build();
267     }
268
269     @Deprecated
270     @SuppressWarnings("checkstyle:LineLength") // Longer lines in this method are caused by long package names,
271                                                // this will be removed when deprecated classes will be cleared.
272     private void updateTenantForwarding(Neutron newNeutron, Router oldRouter, Router newRouter, L3ContextId l3ContextId,
273         TenantId tenantId, ReadWriteTransaction rwTx) {
274
275         InstanceIdentifier<L3Context> l3ContextIid = IidFactory.l3ContextIid(tenantId, l3ContextId);
276         Optional<L3Context> optL3Context = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION, l3ContextIid,
277             rwTx);
278         L3Context l3Context;
279         if (!optL3Context.isPresent()) { // add L3 context if missing
280             l3Context = createL3CtxFromRouter(newRouter);
281             rwTx.put(LogicalDatastoreType.CONFIGURATION, l3ContextIid, l3Context, true);
282         }
283
284         if (newRouter.getGatewayPortId() != null && oldRouter.getGatewayPortId() == null) {
285             // external network is attached to router
286             Uuid gatewayPortId = newRouter.getGatewayPortId();
287             Optional<Port> potentialGwPort = PortUtils.findPort(gatewayPortId, newNeutron.getPorts());
288             if (!potentialGwPort.isPresent()) {
289                 LOG.warn("Illegal state - router gateway port {} does not exist for router {}.",
290                      gatewayPortId.getValue(), newRouter);
291                 rwTx.cancel();
292                 return;
293             }
294
295             Port gwPort = potentialGwPort.get();
296             List<FixedIps> fixedIpsFromGwPort = gwPort.getFixedIps();
297             if (fixedIpsFromGwPort == null || fixedIpsFromGwPort.isEmpty()) {
298                 LOG.warn("Illegal state - router gateway port {} does not contain fixed IPs {}",
299                      gatewayPortId.getValue(), gwPort);
300                 rwTx.cancel();
301                 return;
302             }
303
304             // router can have only one external network
305             FixedIps ipWithSubnetFromGwPort = fixedIpsFromGwPort.get(0);
306             Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet>
307                 potentialSubnet = SubnetUtils.findSubnet(ipWithSubnetFromGwPort.getSubnetId(), newNeutron.getSubnets());
308             if (!potentialSubnet.isPresent()) {
309                 LOG.warn("Illegal state - Subnet {} does not exist for router {}.",
310                     ipWithSubnetFromGwPort.getSubnetId(), newRouter);
311                 rwTx.cancel();
312                 return;
313             }
314             IpAddress gatewayIp = potentialSubnet.get().getGatewayIp();
315             NetworkDomainId networkContainment = new NetworkDomainId(ipWithSubnetFromGwPort.getSubnetId().getValue());
316             boolean registeredExternalGateway =
317                 epRegistrator.registerL3EpAsExternalGateway(tenantId, gatewayIp, l3ContextId, networkContainment);
318             if (!registeredExternalGateway) {
319                 LOG.warn("Could not add L3Prefix as gateway of default route. Gateway port {}", gwPort);
320                 rwTx.cancel();
321                 return;
322             }
323             EndpointL3Key epL3Key = new EndpointL3Key(gatewayIp, l3ContextId);
324             addNeutronExtGwMapping(epL3Key, rwTx);
325
326             boolean registeredDefaultRoute = epRegistrator.registerExternalL3PrefixEndpoint(MappingUtils.DEFAULT_ROUTE,
327                 l3ContextId, gatewayIp, tenantId);
328             if (!registeredDefaultRoute) {
329                 LOG.warn("Could not add EndpointL3Prefix as default route. Gateway port {}", gwPort);
330                 rwTx.cancel();
331                 return;
332             }
333             org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.Subnet
334                 subnetWithGw =
335                 new org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.SubnetBuilder()
336                     .setId(new SubnetId(ipWithSubnetFromGwPort.getSubnetId().getValue()))
337                     .setVirtualRouterIp(gatewayIp)
338                     .build();
339             rwTx.merge(LogicalDatastoreType.CONFIGURATION, IidFactory.subnetIid(tenantId, subnetWithGw.getId()),
340                 subnetWithGw);
341             L2BridgeDomainId l2BdId = new L2BridgeDomainId(potentialSubnet.get().getNetworkId().getValue());
342             Optional<L2BridgeDomain> optBd =
343                 DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION, IidFactory.l2BridgeDomainIid(tenantId,
344                     l2BdId), rwTx);
345             if (!optBd.isPresent()) {
346                 LOG.warn(
347                     "Could not read L2BridgeDomain {}. Modification of its parent to L3Context of router {} aborted.",
348                     l2BdId, newRouter.getUuid());
349                 rwTx.cancel();
350                 return;
351             }
352             L2BridgeDomain
353                 l2BdWithGw =
354                 new L2BridgeDomainBuilder(optBd.get()).setParent(new L3ContextId(l3ContextId.getValue())).build();
355             rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.l2BridgeDomainIid(tenantId, l2BdId), l2BdWithGw);
356         }
357     }
358
359     @SuppressWarnings("checkstyle:LineLength") // Longer lines in this method are caused by long package names,
360                                                // this will be removed when deprecated classes will be cleared.
361     private void deleteTenantForwarding(Neutron newNeutron, Router oldRouter, L3ContextId l3ContextId,
362         TenantId tenantId, ReadWriteTransaction rwTx) {
363
364         InstanceIdentifier<L3Context> l3ContextIid = IidFactory.l3ContextIid(tenantId, l3ContextId);
365
366         LOG.trace("Deleting router from TenantForwarding {}", l3ContextIid);
367         DataStoreHelper.removeIfExists(LogicalDatastoreType.CONFIGURATION, l3ContextIid, rwTx);
368
369         if (oldRouter.getGatewayPortId() != null) {
370             // external network is attached to router
371             Uuid gatewayPortId = oldRouter.getGatewayPortId();
372             Optional<Port> potentialGwPort = PortUtils.findPort(gatewayPortId, newNeutron.getPorts());
373             if (!potentialGwPort.isPresent()) {
374                 LOG.trace("Gateway port {} is not present. Skipping delete of extGW from TenantForwarding",
375                     gatewayPortId);
376                 return;
377             }
378
379             Port gwPort = potentialGwPort.get();
380             List<FixedIps> fixedIpsFromGwPort = gwPort.getFixedIps();
381             if (fixedIpsFromGwPort == null || fixedIpsFromGwPort.isEmpty()) {
382                 LOG.trace("Gateway port {} does not contain fixed IPs. Skipping delete of extGW from TenantForwarding",
383                     gatewayPortId);
384                 return;
385             }
386
387             // router can have only one external network
388             FixedIps ipWithSubnetFromGwPort = fixedIpsFromGwPort.get(0);
389             Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet>
390                 potentialSubnet =
391                 SubnetUtils.findSubnet(ipWithSubnetFromGwPort.getSubnetId(), newNeutron.getSubnets());
392             if (!potentialSubnet.isPresent()) {
393                 LOG.trace("Gateway port {} does not contain fixed IPs. Skipping delete of extGW from TenantForwarding",
394                     gatewayPortId);
395                 return;
396             }
397             IpAddress gatewayIp = potentialSubnet.get().getGatewayIp();
398             boolean registeredExternalGateway = epRegistrator.unregisterL3EpAsExternalGateway(gatewayIp, l3ContextId);
399             if (!registeredExternalGateway) {
400                 LOG.trace("L3 Gateway endpoint {} with IP {} was not unregistered.", l3ContextId, gatewayIp);
401                 return;
402             } else {
403                 LOG.trace("L3 Gateway endpoint {} with IP {} was unregistered successfully.", l3ContextId, gatewayIp);
404             }
405             EndpointL3Key epL3Key = new EndpointL3Key(gatewayIp, l3ContextId);
406
407             DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
408                 NeutronGbpIidFactory.externalGatewayAsL3Endpoint(epL3Key.getL3Context(), epL3Key.getIpAddress()), rwTx);
409
410             DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.builder(Endpoints.class)
411                 .child(EndpointL3Prefix.class, new EndpointL3PrefixKey(MappingUtils.DEFAULT_ROUTE, l3ContextId))
412                 .build(), rwTx);
413
414             Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.Subnet>
415                 subnetOptional = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
416                 IidFactory.subnetIid(tenantId, new SubnetId(ipWithSubnetFromGwPort.getSubnetId().getValue())),
417                 dataProvider.newReadOnlyTransaction());
418
419             org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.Subnet
420                 subnet =
421                 new org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.SubnetBuilder(
422                     subnetOptional.get()).setVirtualRouterIp(null).setGateways(null).build();
423             LOG.trace("Removing VirtualRouterIp from subnet {}.", subnetOptional.get());
424             rwTx.put(LogicalDatastoreType.CONFIGURATION,
425                 IidFactory.subnetIid(tenantId, new SubnetId(ipWithSubnetFromGwPort.getSubnetId().getValue())), subnet);
426
427             L2BridgeDomainId l2BdId = new L2BridgeDomainId(potentialSubnet.get().getNetworkId().getValue());
428             L3ContextId l3Context = new L3ContextId(potentialSubnet.get().getNetworkId().getValue());
429             Optional<L2BridgeDomain> optBd = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
430                     IidFactory.l2BridgeDomainIid(tenantId, l2BdId), rwTx);
431             if (optBd.isPresent()) {
432                 L2BridgeDomain l2BdWithGw = new L2BridgeDomainBuilder(optBd.get()).setParent(l3Context).build();
433                 LOG.trace("Setting parent for L2BridgeDomain {} back to network {}.", l2BdWithGw, l3Context);
434                 rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.l2BridgeDomainIid(tenantId, l2BdId),
435                     l2BdWithGw);
436             }
437         }
438     }
439
440     private static @Nonnull ForwardingContext createL3ContextFromRouter(
441             Router router) {
442         Name l3ContextName = null;
443         if (!Strings.isNullOrEmpty(router.getName())) {
444             l3ContextName = new Name(router.getName());
445         }
446         return new ForwardingContextBuilder().setContextId(new ContextId(router.getUuid().getValue()))
447             .setContextType(MappingUtils.L3_CONTEXT)
448             .setName(new Name(l3ContextName.getValue()))
449             .build();
450     }
451
452     @Deprecated
453     private static @Nonnull L3Context createL3CtxFromRouter(Router router) {
454         Name l3ContextName = null;
455         if (!Strings.isNullOrEmpty(router.getName())) {
456             l3ContextName = new Name(router.getName());
457         }
458         return new L3ContextBuilder().setId(new L3ContextId(router.getUuid().getValue()))
459             .setName(l3ContextName)
460             .setDescription(new Description(MappingUtils.NEUTRON_ROUTER + router.getUuid().getValue()))
461             .build();
462     }
463
464     private static void addNeutronExtGwGbpMapping(ContextId contextId, IpPrefix ipPrefix, ReadWriteTransaction rwTx) {
465         ExternalGatewayAsEndpoint externalGatewayL3Endpoint = MappingFactory.createEaxternalGatewayAsEndpoint(
466                 contextId, ipPrefix);
467         rwTx.put(LogicalDatastoreType.OPERATIONAL, NeutronGbpIidFactory.externalGatewayAsEndpoint(contextId,
468             ipPrefix, MappingUtils.L3_CONTEXT), externalGatewayL3Endpoint, true);
469     }
470
471     @Deprecated
472     private static void addNeutronExtGwMapping(EndpointL3Key epL3Key, ReadWriteTransaction rwTx) {
473         ExternalGatewayAsL3Endpoint externalGatewayL3Endpoint =
474                 MappingFactory.createExternalGatewayByL3Endpoint(epL3Key);
475         rwTx.put(LogicalDatastoreType.OPERATIONAL,
476                 NeutronGbpIidFactory.externalGatewayAsL3Endpoint(epL3Key.getL3Context(), epL3Key.getIpAddress()),
477                 externalGatewayL3Endpoint, true);
478     }
479
480     @Override
481     public void onDeleted(Router router, Neutron oldNeutron, Neutron newNeutron) {
482         LOG.debug("deleted router - {}", router);
483         ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
484         ContextId routerl3ContextId = new ContextId(router.getUuid().getValue());
485         TenantId tenantId = new TenantId(router.getTenantId().getValue());
486         deleteExtGw(router, tenantId, newNeutron, rwTx);
487         InstanceIdentifier<ForwardingContext> routerL3CtxIid = L2L3IidFactory.l3ContextIid(tenantId, routerl3ContextId);
488
489         LOG.trace("Removing router from forwardingByTenant. Router: {} Path: {}", router, routerL3CtxIid);
490         DataStoreHelper.removeIfExists(LogicalDatastoreType.CONFIGURATION, routerL3CtxIid, rwTx);
491
492         InstanceIdentifier<L3Context> l3ContextInstanceIdentifier =
493             IidFactory.l3ContextIid(tenantId, new L3ContextId(routerl3ContextId));
494         LOG.trace("Removing router from Tenant`s forwarding context. Router: {} Path: {}", router,
495             l3ContextInstanceIdentifier);
496         DataStoreHelper.removeIfExists(LogicalDatastoreType.CONFIGURATION, l3ContextInstanceIdentifier, rwTx);
497
498         DataStoreHelper.submitToDs(rwTx);
499     }
500
501     @SuppressWarnings("checkstyle:LineLength") // Longer lines in this method are caused by long package names,
502                                                // this will be removed when deprecated classes will be cleared.
503     private void deleteExtGw(Router router, TenantId tenantId, Neutron newNeutron, ReadWriteTransaction rwTx) {
504         ContextId routerL3CtxId = new ContextId(router.getUuid().getValue());
505         if (router.getGatewayPortId() != null) {
506             // external network is attached to router
507             Uuid gatewayPortId = router.getGatewayPortId();
508             Optional<Port> potentialGwPort = PortUtils.findPort(gatewayPortId, newNeutron.getPorts());
509             if (potentialGwPort == null || !potentialGwPort.isPresent()) {
510                 LOG.trace("Gateway port {} is not present. Skipping delete for external gateway", gatewayPortId);
511                 return;
512             }
513
514             Port gwPort = potentialGwPort.get();
515             List<FixedIps> fixedIpsFromGwPort = gwPort.getFixedIps();
516             if (fixedIpsFromGwPort == null || fixedIpsFromGwPort.isEmpty()) {
517                 LOG.trace("Gateway port {} with does not contain fixed IPs. Skipping delete for external gateway",
518                     gatewayPortId);
519                 return;
520             }
521
522             FixedIps ipWithSubnetFromGwPort = fixedIpsFromGwPort.get(0);
523             Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet>
524                 potentialSubnet = SubnetUtils.findSubnet(ipWithSubnetFromGwPort.getSubnetId(), newNeutron.getSubnets());
525             if (!potentialSubnet.isPresent()) {
526                 LOG.trace("Subnet for GW port {} is not present. Skipping delete for external gateway",
527                     gatewayPortId);
528                 return;
529             }
530             IpPrefix gatewayIp = MappingUtils.ipAddressToIpPrefix(potentialSubnet.get().getGatewayIp());
531
532             if (!unregisterExternalGateway(gatewayIp, routerL3CtxId)) {
533                 LOG.warn("Could not unregister routerL3Prefix as gateway of default route. Gateway port {}", gwPort);
534                 return;
535             }
536             DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
537                 NeutronGbpIidFactory.externalGatewayAsEndpoint(routerL3CtxId, gatewayIp, MappingUtils.L3_CONTEXT),
538                 rwTx);
539             NetworkDomainId domainId = new NetworkDomainId(ipWithSubnetFromGwPort.getSubnetId().getValue());
540             Optional<NetworkDomain> domainOptional =
541                 DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
542                     L2L3IidFactory.subnetIid(tenantId, domainId), dataProvider.newReadWriteTransaction());
543
544             if (domainOptional.isPresent()) {
545                 Subnet originalSubnet = domainOptional.get().getAugmentation(SubnetAugmentForwarding.class).getSubnet();
546                 if (originalSubnet != null) {
547                     LOG.trace("Deleting virtual router IP from Subnet {} in gateway {}", originalSubnet, gatewayPortId);
548                     SubnetBuilder subnetBuilder = new SubnetBuilder(originalSubnet).setVirtualRouterIp(null)
549                         .setGateways(null);
550                     rwTx.put(LogicalDatastoreType.CONFIGURATION,
551                         L2L3IidFactory.subnetIid(tenantId, domainId)
552                             .augmentation(SubnetAugmentForwarding.class)
553                             .child(Subnet.class),
554                         subnetBuilder.build());
555                 }
556             }
557             ContextId l2BdId = new ContextId(potentialSubnet.get().getNetworkId().getValue());
558             Optional<ForwardingContext> optBd = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
559                 L2L3IidFactory.l2BridgeDomainIid(tenantId, l2BdId), rwTx);
560             Parent parent = MappingUtils.createParent(l2BdId, MappingUtils.L3_CONTEXT);
561             if (optBd.isPresent()) {
562                 ForwardingContext bridgeDomain = new ForwardingContextBuilder(optBd.get()).setParent(parent).build();
563                 LOG.trace("Setting parent for L2BridgeDomain {} back to network {}.", bridgeDomain, parent);
564                 rwTx.put(LogicalDatastoreType.CONFIGURATION, L2L3IidFactory.l2BridgeDomainIid(tenantId, l2BdId),
565                     bridgeDomain);
566             }
567         }
568         deleteTenantForwarding(newNeutron, router, new L3ContextId(routerL3CtxId), tenantId, rwTx);
569     }
570
571 }