2 * Copyright (c) 2015 Intel, Cisco Systems, Inc. and others. All rights reserved.
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
9 package org.opendaylight.groupbasedpolicy.neutron.mapper.mapping;
11 import static com.google.common.base.Preconditions.checkNotNull;
13 import com.google.common.base.Optional;
14 import com.google.common.base.Strings;
15 import com.google.common.collect.ImmutableList;
17 import java.util.Collections;
18 import java.util.List;
20 import javax.annotation.Nonnull;
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;
85 public class NeutronRouterAware implements NeutronAware<Router> {
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;
93 public NeutronRouterAware(DataBroker dataProvider, EndpointRegistrator epRegistrator) {
94 this.dataProvider = checkNotNull(dataProvider);
95 this.epRegistrator = checkNotNull(epRegistrator);
99 public void onCreated(Router router, Neutron neutron) {
100 LOG.trace("created router - {}", router);
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())) {
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);
117 ForwardingContext routerl3Context = fwdCtxBuilder.setContextId(routerl3ContextId)
118 .setContextType(MappingUtils.L3_CONTEXT)
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);
127 private void createTenantL3Context(L3ContextId l3ContextId, TenantId tenantId, Name name,
128 WriteTransaction writeTx) {
129 L3ContextBuilder l3ContextBuilder = new L3ContextBuilder();
131 l3ContextBuilder.setName(name);
133 L3Context l3Context = l3ContextBuilder.setId(l3ContextId).build();
134 writeTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.l3ContextIid(tenantId, l3ContextId), l3Context,
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);
144 ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
145 TenantId tenantId = new TenantId(newRouter.getTenantId().getValue());
146 ContextId routerL3CtxId = new ContextId(newRouter.getUuid().getValue());
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);
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);
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);
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);
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()));
201 subnetDomain = createSubnetWithVirtualRouterIp(gatewayIp, subnetId, Collections.singletonList(
202 new GatewaysBuilder().setGateway(gwIp).setPrefixes(defaultPrefixes).build()));
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()) {
211 "Could not read L2BridgeDomain {}. Modification of its parent to L3Context of router {} aborted.",
212 l2BdId, newRouter.getUuid());
216 ForwardingContext forwardingContext = optBd.get();
217 ForwardingContext l2BdWithGw = new ForwardingContextBuilder(forwardingContext)
218 .setParent(MappingUtils.createParent(routerL3CtxId, MappingUtils.L3_CONTEXT))
220 rwTx.put(LogicalDatastoreType.CONFIGURATION, L2L3IidFactory.l2BridgeDomainIid(tenantId, l2BdId),
223 updateTenantForwarding(newNeutron, oldRouter, newRouter, new L3ContextId(routerL3CtxId), tenantId, rwTx);
224 DataStoreHelper.submitToDs(rwTx);
227 private boolean isSubnetInExternalNetwork(List<Network> networks, Uuid networkId) {
228 return networks.stream().anyMatch(net -> net.getUuid().equals(networkId) && NetworkUtils.isRouterExternal(net));
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);
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());
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());
256 private NetworkDomain createSubnetWithVirtualRouterIp(IpPrefix gatewayIp, NetworkDomainId subnetId,
257 List<Gateways> gateways) {
260 new SubnetBuilder().setVirtualRouterIp(MappingUtils.ipPrefixToIpAddress(gatewayIp.getValue()))
261 .setGateways(gateways)
263 return new NetworkDomainBuilder().setKey(new NetworkDomainKey(subnetId, MappingUtils.SUBNET))
264 .addAugmentation(SubnetAugmentForwarding.class,
265 new SubnetAugmentForwardingBuilder().setSubnet(subnet).build())
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) {
275 InstanceIdentifier<L3Context> l3ContextIid = IidFactory.l3ContextIid(tenantId, l3ContextId);
276 Optional<L3Context> optL3Context = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION, l3ContextIid,
279 if (!optL3Context.isPresent()) { // add L3 context if missing
280 l3Context = createL3CtxFromRouter(newRouter);
281 rwTx.put(LogicalDatastoreType.CONFIGURATION, l3ContextIid, l3Context, true);
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);
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);
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);
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);
323 EndpointL3Key epL3Key = new EndpointL3Key(gatewayIp, l3ContextId);
324 addNeutronExtGwMapping(epL3Key, rwTx);
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);
333 org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.Subnet
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)
339 rwTx.merge(LogicalDatastoreType.CONFIGURATION, IidFactory.subnetIid(tenantId, subnetWithGw.getId()),
341 L2BridgeDomainId l2BdId = new L2BridgeDomainId(potentialSubnet.get().getNetworkId().getValue());
342 Optional<L2BridgeDomain> optBd =
343 DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION, IidFactory.l2BridgeDomainIid(tenantId,
345 if (!optBd.isPresent()) {
347 "Could not read L2BridgeDomain {}. Modification of its parent to L3Context of router {} aborted.",
348 l2BdId, newRouter.getUuid());
354 new L2BridgeDomainBuilder(optBd.get()).setParent(new L3ContextId(l3ContextId.getValue())).build();
355 rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.l2BridgeDomainIid(tenantId, l2BdId), l2BdWithGw);
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) {
364 InstanceIdentifier<L3Context> l3ContextIid = IidFactory.l3ContextIid(tenantId, l3ContextId);
366 LOG.trace("Deleting router from TenantForwarding {}", l3ContextIid);
367 DataStoreHelper.removeIfExists(LogicalDatastoreType.CONFIGURATION, l3ContextIid, rwTx);
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",
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",
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>
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",
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);
403 LOG.trace("L3 Gateway endpoint {} with IP {} was unregistered successfully.", l3ContextId, gatewayIp);
405 EndpointL3Key epL3Key = new EndpointL3Key(gatewayIp, l3ContextId);
407 DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
408 NeutronGbpIidFactory.externalGatewayAsL3Endpoint(epL3Key.getL3Context(), epL3Key.getIpAddress()), rwTx);
410 DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.builder(Endpoints.class)
411 .child(EndpointL3Prefix.class, new EndpointL3PrefixKey(MappingUtils.DEFAULT_ROUTE, l3ContextId))
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());
419 org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.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);
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),
440 private static @Nonnull ForwardingContext createL3ContextFromRouter(
442 Name l3ContextName = null;
443 if (!Strings.isNullOrEmpty(router.getName())) {
444 l3ContextName = new Name(router.getName());
446 return new ForwardingContextBuilder().setContextId(new ContextId(router.getUuid().getValue()))
447 .setContextType(MappingUtils.L3_CONTEXT)
448 .setName(new Name(l3ContextName.getValue()))
453 private static @Nonnull L3Context createL3CtxFromRouter(Router router) {
454 Name l3ContextName = null;
455 if (!Strings.isNullOrEmpty(router.getName())) {
456 l3ContextName = new Name(router.getName());
458 return new L3ContextBuilder().setId(new L3ContextId(router.getUuid().getValue()))
459 .setName(l3ContextName)
460 .setDescription(new Description(MappingUtils.NEUTRON_ROUTER + router.getUuid().getValue()))
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);
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);
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);
489 LOG.trace("Removing router from forwardingByTenant. Router: {} Path: {}", router, routerL3CtxIid);
490 DataStoreHelper.removeIfExists(LogicalDatastoreType.CONFIGURATION, routerL3CtxIid, rwTx);
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);
498 DataStoreHelper.submitToDs(rwTx);
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);
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",
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",
530 IpPrefix gatewayIp = MappingUtils.ipAddressToIpPrefix(potentialSubnet.get().getGatewayIp());
532 if (!unregisterExternalGateway(gatewayIp, routerL3CtxId)) {
533 LOG.warn("Could not unregister routerL3Prefix as gateway of default route. Gateway port {}", gwPort);
536 DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
537 NeutronGbpIidFactory.externalGatewayAsEndpoint(routerL3CtxId, gatewayIp, MappingUtils.L3_CONTEXT),
539 NetworkDomainId domainId = new NetworkDomainId(ipWithSubnetFromGwPort.getSubnetId().getValue());
540 Optional<NetworkDomain> domainOptional =
541 DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
542 L2L3IidFactory.subnetIid(tenantId, domainId), dataProvider.newReadWriteTransaction());
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)
550 rwTx.put(LogicalDatastoreType.CONFIGURATION,
551 L2L3IidFactory.subnetIid(tenantId, domainId)
552 .augmentation(SubnetAugmentForwarding.class)
553 .child(Subnet.class),
554 subnetBuilder.build());
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),
568 deleteTenantForwarding(newNeutron, router, new L3ContextId(routerL3CtxId), tenantId, rwTx);