/* * Copyright (c) 2015 Intel, Cisco Systems, Inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.groupbasedpolicy.neutron.mapper.mapping; import static com.google.common.base.Preconditions.checkNotNull; import java.util.Collections; import java.util.List; import javax.annotation.Nonnull; import org.opendaylight.controller.md.sal.binding.api.DataBroker; import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction; import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.groupbasedpolicy.domain_extension.l2_l3.util.L2L3IidFactory; import org.opendaylight.groupbasedpolicy.neutron.gbp.util.NeutronGbpIidFactory; import org.opendaylight.groupbasedpolicy.neutron.mapper.EndpointRegistrator; import org.opendaylight.groupbasedpolicy.neutron.mapper.util.MappingUtils; import org.opendaylight.groupbasedpolicy.neutron.mapper.util.NetworkUtils; import org.opendaylight.groupbasedpolicy.neutron.mapper.util.PortUtils; import org.opendaylight.groupbasedpolicy.neutron.mapper.util.SubnetUtils; import org.opendaylight.groupbasedpolicy.util.DataStoreHelper; import org.opendaylight.groupbasedpolicy.util.IidFactory; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.common.endpoint.fields.NetworkContainmentBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.common.endpoint.fields.network.containment.containment.NetworkDomainContainmentBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.register.endpoint.input.AddressEndpointRegBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.unregister.endpoint.input.AddressEndpointUnregBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContextId; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.Description; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2BridgeDomainId; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L3ContextId; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.Name; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.NetworkDomainId; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubnetId; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.Endpoints; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Key; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Prefix; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3PrefixKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.IpPrefixType; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.SubnetAugmentForwarding; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.SubnetAugmentForwardingBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.has.subnet.Subnet; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.has.subnet.SubnetBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.has.subnet.subnet.gateways.Prefixes; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.fields.Parent; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.has.subnet.subnet.Gateways; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.has.subnet.subnet.GatewaysBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.has.subnet.subnet.gateways.PrefixesBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.forwarding.by.tenant.ForwardingContext; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.forwarding.by.tenant.ForwardingContextBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.forwarding.by.tenant.NetworkDomain; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.forwarding.by.tenant.NetworkDomainBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.forwarding.by.tenant.NetworkDomainKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.neutron.by.gbp.mappings.external.gateways.as.endpoints.ExternalGatewayAsEndpoint; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.neutron.by.gbp.mappings.external.gateways.as.l3.endpoints.ExternalGatewayAsL3Endpoint; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L2BridgeDomain; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L2BridgeDomainBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L3Context; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L3ContextBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.Routers; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.Router; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.base.Optional; import com.google.common.base.Strings; import com.google.common.collect.ImmutableList; public class NeutronRouterAware implements NeutronAware<Router> { private static final Logger LOG = LoggerFactory.getLogger(NeutronRouterAware.class); public static final InstanceIdentifier<Router> ROUTER_WILDCARD_IID = InstanceIdentifier.builder(Neutron.class).child(Routers.class).child(Router.class).build(); private final DataBroker dataProvider; private final EndpointRegistrator epRegistrator; public NeutronRouterAware(DataBroker dataProvider, EndpointRegistrator epRegistrator) { this.dataProvider = checkNotNull(dataProvider); this.epRegistrator = checkNotNull(epRegistrator); } @Override public void onCreated(Router router, Neutron neutron) { LOG.trace("created router - {}", router); ContextId routerl3ContextId = new ContextId(router.getUuid().getValue()); TenantId tenantId = new TenantId(router.getTenantId().getValue()); InstanceIdentifier<ForwardingContext> routerL3CtxIid = L2L3IidFactory.l3ContextIid(tenantId, routerl3ContextId); ForwardingContextBuilder fwdCtxBuilder = new ForwardingContextBuilder(); Name routerName = null; if (!Strings.isNullOrEmpty(router.getName())) { try { routerName = new Name(router.getName()); fwdCtxBuilder.setName(routerName); } catch (Exception e) { LOG.info("Name '{}' of Neutron Subnet '{}' is ignored.", router.getName(), router.getUuid().getValue()); LOG.debug("Name exception", e); } } ForwardingContext routerl3Context = fwdCtxBuilder.setContextId(routerl3ContextId) .setContextType(MappingUtils.L3_CONTEXT) .build(); WriteTransaction wTx = dataProvider.newWriteOnlyTransaction(); wTx.put(LogicalDatastoreType.CONFIGURATION, routerL3CtxIid, routerl3Context, true); createTenantL3Context(new L3ContextId(routerl3ContextId), tenantId, routerName, wTx); DataStoreHelper.submitToDs(wTx); } @Deprecated private void createTenantL3Context(L3ContextId l3ContextId, TenantId tenantId, Name name, WriteTransaction wTx) { L3ContextBuilder l3ContextBuilder = new L3ContextBuilder(); if (name != null) { l3ContextBuilder.setName(name); } L3Context l3Context = l3ContextBuilder.setId(l3ContextId).build(); wTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.l3ContextIid(tenantId, l3ContextId), l3Context, true); } @Override public void onUpdated(Router oldRouter, Router newRouter, Neutron oldNeutron, Neutron newNeutron) { LOG.trace("updated router - OLD: {}\nNEW: {}", oldRouter, newRouter); ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction(); TenantId tenantId = new TenantId(newRouter.getTenantId().getValue()); ContextId routerL3CtxId = new ContextId(newRouter.getUuid().getValue()); if (newRouter.getGatewayPortId() != null && oldRouter.getGatewayPortId() == null) { // external network is attached to router Uuid gatewayPortId = newRouter.getGatewayPortId(); Optional<Port> potentialGwPort = PortUtils.findPort(gatewayPortId, newNeutron.getPorts()); if (!potentialGwPort.isPresent()) { LOG.warn("Illegal state - router gateway port {} does not exist for router {}.", gatewayPortId.getValue(), newRouter); rwTx.cancel(); return; } Port gwPort = potentialGwPort.get(); List<FixedIps> fixedIpsFromGwPort = gwPort.getFixedIps(); if (fixedIpsFromGwPort == null || fixedIpsFromGwPort.isEmpty()) { LOG.warn("Illegal state - router gateway port {} does not contain fixed IPs {}", gatewayPortId.getValue(), gwPort); rwTx.cancel(); return; } // router can have only one external network FixedIps ipWithSubnetFromGwPort = fixedIpsFromGwPort.get(0); Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet> potentialSubnet = SubnetUtils.findSubnet(ipWithSubnetFromGwPort.getSubnetId(), newNeutron.getSubnets()); if (!potentialSubnet.isPresent()) { LOG.warn("Illegal state - Subnet {} does not exist for router {}.", ipWithSubnetFromGwPort.getSubnetId(), newRouter); rwTx.cancel(); return; } tenantId = new TenantId(potentialSubnet.get().getTenantId().getValue()); IpAddress gwIp = potentialSubnet.get().getGatewayIp(); IpPrefix gatewayIp = MappingUtils.ipAddressToIpPrefix(gwIp); NetworkDomainId subnetId = new NetworkDomainId(ipWithSubnetFromGwPort.getSubnetId().getValue()); boolean registeredExternalGateway = registerExternalGateway(tenantId, gatewayIp, routerL3CtxId, subnetId); if (!registeredExternalGateway) { LOG.warn("Could not add L3Prefix as gateway of default route. Gateway port {}", gwPort); rwTx.cancel(); return; } addNeutronExtGwGbpMapping(routerL3CtxId, gatewayIp, rwTx); NetworkDomain subnetDomain; List<Prefixes> defaultPrefixes = Collections.singletonList(new PrefixesBuilder().setPrefix(MappingUtils.DEFAULT_ROUTE).build()); // if subnet is in external network then create subnet with IP from GW port as its virtual router IP // else use subnet gateway as virtual router IP. if (isSubnetInExternalNetwork(newNeutron.getNetworks().getNetwork(), potentialSubnet.get().getNetworkId())) { subnetDomain = createSubnetWithVirtualRouterIp( MappingUtils.ipAddressToIpPrefix(ipWithSubnetFromGwPort.getIpAddress()), subnetId, Collections.singletonList( new GatewaysBuilder().setGateway(gwIp).setPrefixes(defaultPrefixes).build())); } else { subnetDomain = createSubnetWithVirtualRouterIp(gatewayIp, subnetId, Collections.singletonList( new GatewaysBuilder().setGateway(gwIp).setPrefixes(defaultPrefixes).build())); } rwTx.merge(LogicalDatastoreType.CONFIGURATION, L2L3IidFactory.subnetIid(tenantId, subnetDomain.getNetworkDomainId()), subnetDomain); ContextId l2BdId = new ContextId(potentialSubnet.get().getNetworkId().getValue()); Optional<ForwardingContext> optBd = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION, L2L3IidFactory.l2BridgeDomainIid(tenantId, l2BdId), rwTx); if (!optBd.isPresent()) { LOG.warn( "Could not read L2-Bridge-Domain {}. Modification of its parent to L3-Context of router {} aborted.", l2BdId, newRouter.getUuid()); rwTx.cancel(); return; } ForwardingContext forwardingContext = optBd.get(); ForwardingContext l2BdWithGw = new ForwardingContextBuilder(forwardingContext) .setParent(MappingUtils.createParent(routerL3CtxId, MappingUtils.L3_CONTEXT)) .build(); rwTx.put(LogicalDatastoreType.CONFIGURATION, L2L3IidFactory.l2BridgeDomainIid(tenantId, l2BdId), l2BdWithGw); } updateTenantForwarding(newNeutron, oldRouter, newRouter, new L3ContextId(routerL3CtxId), tenantId, rwTx); DataStoreHelper.submitToDs(rwTx); } private boolean isSubnetInExternalNetwork(List<Network> networks, Uuid networkId) { return networks.stream().anyMatch(net -> net.getUuid().equals(networkId) && NetworkUtils.isRouterExternal(net)); } private boolean registerExternalGateway(TenantId tenantId, IpPrefix ipPrefix, ContextId routerl3ContextId, NetworkDomainId networkDomainId) { AddressEndpointRegBuilder addrEpBuilder = new AddressEndpointRegBuilder(); addrEpBuilder.setAddressType(IpPrefixType.class); addrEpBuilder.setAddress(MappingUtils.ipPrefixToStringIpAddress(ipPrefix)); addrEpBuilder.setContextId(routerl3ContextId); addrEpBuilder.setContextType(MappingUtils.L3_CONTEXT); addrEpBuilder.setTenant(tenantId); addrEpBuilder.setNetworkContainment(new NetworkContainmentBuilder().setContainment( new NetworkDomainContainmentBuilder().setNetworkDomainId(networkDomainId).build()).build()); addrEpBuilder.setEndpointGroup(ImmutableList.of(MappingUtils.EPG_EXTERNAL_ID)); addrEpBuilder.setTimestamp(System.currentTimeMillis()); return epRegistrator.registerEndpoint(addrEpBuilder.build()); } private boolean unregisterExternalGateway(IpPrefix ipPrefix, ContextId routerl3ContextId) { AddressEndpointUnregBuilder addrEpBuilder = new AddressEndpointUnregBuilder(); addrEpBuilder.setAddressType(IpPrefixType.class); addrEpBuilder.setAddress(MappingUtils.ipPrefixToStringIpAddress(ipPrefix)); addrEpBuilder.setContextId(routerl3ContextId); addrEpBuilder.setContextType(MappingUtils.L3_CONTEXT); return epRegistrator.unregisterEndpoint(addrEpBuilder.build()); } private NetworkDomain createSubnetWithVirtualRouterIp(IpPrefix gatewayIp, NetworkDomainId subnetId, List<Gateways> gateways) { Subnet subnet = new SubnetBuilder() .setVirtualRouterIp(MappingUtils.ipPrefixToIpAddress(gatewayIp.getValue())) .setGateways(gateways) .build(); return new NetworkDomainBuilder().setKey(new NetworkDomainKey(subnetId, MappingUtils.SUBNET)) .addAugmentation(SubnetAugmentForwarding.class, new SubnetAugmentForwardingBuilder().setSubnet(subnet).build()) .build(); } @Deprecated private void updateTenantForwarding(Neutron newNeutron, Router oldRouter, Router newRouter, L3ContextId l3ContextId, TenantId tenantId, ReadWriteTransaction rwTx) { InstanceIdentifier<L3Context> l3ContextIid = IidFactory.l3ContextIid(tenantId, l3ContextId); Optional<L3Context> optL3Context = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION, l3ContextIid, rwTx); L3Context l3Context; if (!optL3Context.isPresent()) { // add L3 context if missing l3Context = createL3CtxFromRouter(newRouter); rwTx.put(LogicalDatastoreType.CONFIGURATION, l3ContextIid, l3Context, true); } if (newRouter.getGatewayPortId() != null && oldRouter.getGatewayPortId() == null) { // external network is attached to router Uuid gatewayPortId = newRouter.getGatewayPortId(); Optional<Port> potentialGwPort = PortUtils.findPort(gatewayPortId, newNeutron.getPorts()); if (!potentialGwPort.isPresent()) { LOG.warn("Illegal state - router gateway port {} does not exist for router {}.", gatewayPortId.getValue(), newRouter); rwTx.cancel(); return; } Port gwPort = potentialGwPort.get(); List<FixedIps> fixedIpsFromGwPort = gwPort.getFixedIps(); if (fixedIpsFromGwPort == null || fixedIpsFromGwPort.isEmpty()) { LOG.warn("Illegal state - router gateway port {} does not contain fixed IPs {}", gatewayPortId.getValue(), gwPort); rwTx.cancel(); return; } // router can have only one external network FixedIps ipWithSubnetFromGwPort = fixedIpsFromGwPort.get(0); Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet> potentialSubnet = SubnetUtils.findSubnet(ipWithSubnetFromGwPort.getSubnetId(), newNeutron.getSubnets()); if (!potentialSubnet.isPresent()) { LOG.warn("Illegal state - Subnet {} does not exist for router {}.", ipWithSubnetFromGwPort.getSubnetId(), newRouter); rwTx.cancel(); return; } IpAddress gatewayIp = potentialSubnet.get().getGatewayIp(); NetworkDomainId networkContainment = new NetworkDomainId(ipWithSubnetFromGwPort.getSubnetId().getValue()); boolean registeredExternalGateway = epRegistrator.registerL3EpAsExternalGateway(tenantId, gatewayIp, l3ContextId, networkContainment); if (!registeredExternalGateway) { LOG.warn("Could not add L3Prefix as gateway of default route. Gateway port {}", gwPort); rwTx.cancel(); return; } EndpointL3Key epL3Key = new EndpointL3Key(gatewayIp, l3ContextId); addNeutronExtGwMapping(epL3Key, rwTx); boolean registeredDefaultRoute = epRegistrator.registerExternalL3PrefixEndpoint(MappingUtils.DEFAULT_ROUTE, l3ContextId, gatewayIp, tenantId); if (!registeredDefaultRoute) { LOG.warn("Could not add EndpointL3Prefix as default route. Gateway port {}", gwPort); rwTx.cancel(); return; } org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.Subnet subnetWithGw = new org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.SubnetBuilder().setId(new SubnetId(ipWithSubnetFromGwPort.getSubnetId().getValue())) .setVirtualRouterIp(gatewayIp) .build(); rwTx.merge(LogicalDatastoreType.CONFIGURATION, IidFactory.subnetIid(tenantId, subnetWithGw.getId()), subnetWithGw); L2BridgeDomainId l2BdId = new L2BridgeDomainId(potentialSubnet.get().getNetworkId().getValue()); Optional<L2BridgeDomain> optBd = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION, IidFactory.l2BridgeDomainIid(tenantId, l2BdId), rwTx); if (!optBd.isPresent()) { LOG.warn( "Could not read L2-Bridge-Domain {}. Modification of its parent to L3-Context of router {} aborted.", l2BdId, newRouter.getUuid()); rwTx.cancel(); return; } L2BridgeDomain l2BdWithGw = new L2BridgeDomainBuilder(optBd.get()) .setParent(new L3ContextId(l3ContextId.getValue())) .build(); rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.l2BridgeDomainIid(tenantId, l2BdId), l2BdWithGw); } } private void deleteTenantForwarding(Neutron newNeutron, Router oldRouter, L3ContextId l3ContextId, TenantId tenantId, ReadWriteTransaction rwTx) { InstanceIdentifier<L3Context> l3ContextIid = IidFactory.l3ContextIid(tenantId, l3ContextId); LOG.trace("Deleting router from TenantForwarding {}", l3ContextIid); DataStoreHelper.removeIfExists(LogicalDatastoreType.CONFIGURATION, l3ContextIid, rwTx); if (oldRouter.getGatewayPortId() != null) { // external network is attached to router Uuid gatewayPortId = oldRouter.getGatewayPortId(); Optional<Port> potentialGwPort = PortUtils.findPort(gatewayPortId, newNeutron.getPorts()); if (!potentialGwPort.isPresent()) { LOG.trace("Gateway port {} is not present. Skipping delete of extGW from TenantForwarding", gatewayPortId); return; } Port gwPort = potentialGwPort.get(); List<FixedIps> fixedIpsFromGwPort = gwPort.getFixedIps(); if (fixedIpsFromGwPort == null || fixedIpsFromGwPort.isEmpty()) { LOG.trace("Gateway port {} does not contain fixed IPs. Skipping delete of extGW from TenantForwarding", gatewayPortId); return; } // router can have only one external network FixedIps ipWithSubnetFromGwPort = fixedIpsFromGwPort.get(0); Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet> potentialSubnet = SubnetUtils.findSubnet(ipWithSubnetFromGwPort.getSubnetId(), newNeutron.getSubnets()); if (!potentialSubnet.isPresent()) { LOG.trace("Gateway port {} does not contain fixed IPs. Skipping delete of extGW from TenantForwarding", gatewayPortId); return; } IpAddress gatewayIp = potentialSubnet.get().getGatewayIp(); boolean registeredExternalGateway = epRegistrator.unregisterL3EpAsExternalGateway(gatewayIp, l3ContextId); if (!registeredExternalGateway) { LOG.trace("L3 Gateway endpoint {} with IP {} was not unregistered.", l3ContextId, gatewayIp); return; } else { LOG.trace("L3 Gateway endpoint {} with IP {} was unregistered successfully.", l3ContextId, gatewayIp); } EndpointL3Key epL3Key = new EndpointL3Key(gatewayIp, l3ContextId); DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL, NeutronGbpIidFactory.externalGatewayAsL3Endpoint(epL3Key.getL3Context(), epL3Key.getIpAddress()), rwTx); DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.builder(Endpoints.class) .child(EndpointL3Prefix.class, new EndpointL3PrefixKey(MappingUtils.DEFAULT_ROUTE, l3ContextId)) .build(), rwTx); Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.Subnet> subnetOptional = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION, IidFactory.subnetIid(tenantId, new SubnetId(ipWithSubnetFromGwPort.getSubnetId().getValue())), dataProvider.newReadOnlyTransaction()); org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.Subnet subnet = new org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.SubnetBuilder( subnetOptional.get()).setVirtualRouterIp(null).setGateways(null).build(); LOG.trace("Removing VirtualRouterIp from subnet {}.", subnetOptional.get()); rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.subnetIid(tenantId, new SubnetId(ipWithSubnetFromGwPort.getSubnetId().getValue())), subnet); L2BridgeDomainId l2BdId = new L2BridgeDomainId(potentialSubnet.get().getNetworkId().getValue()); L3ContextId l3Context = new L3ContextId( potentialSubnet.get().getNetworkId().getValue()); Optional<L2BridgeDomain> optBd = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION, IidFactory.l2BridgeDomainIid(tenantId, l2BdId), rwTx); if (optBd.isPresent()) { L2BridgeDomain l2BdWithGw = new L2BridgeDomainBuilder(optBd.get()).setParent(l3Context).build(); LOG.trace("Setting parent for L2BridgeDomain {} back to network {}.", l2BdWithGw, l3Context); rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.l2BridgeDomainIid(tenantId, l2BdId), l2BdWithGw); } } } private static @Nonnull ForwardingContext createL3ContextFromRouter( Router router) { Name l3ContextName = null; if (!Strings.isNullOrEmpty(router.getName())) { l3ContextName = new Name(router.getName()); } return new ForwardingContextBuilder().setContextId(new ContextId(router.getUuid().getValue())) .setContextType(MappingUtils.L3_CONTEXT) .setName(new Name(l3ContextName.getValue())) .build(); } @Deprecated private static @Nonnull L3Context createL3CtxFromRouter(Router router) { Name l3ContextName = null; if (!Strings.isNullOrEmpty(router.getName())) { l3ContextName = new Name(router.getName()); } return new L3ContextBuilder().setId(new L3ContextId(router.getUuid().getValue())) .setName(l3ContextName) .setDescription(new Description(MappingUtils.NEUTRON_ROUTER + router.getUuid().getValue())) .build(); } private static void addNeutronExtGwGbpMapping(ContextId contextId, IpPrefix ipPrefix, ReadWriteTransaction rwTx) { ExternalGatewayAsEndpoint externalGatewayL3Endpoint = MappingFactory.createEaxternalGatewayAsEndpoint( contextId, ipPrefix); rwTx.put(LogicalDatastoreType.OPERATIONAL, NeutronGbpIidFactory.externalGatewayAsEndpoint(contextId, ipPrefix, MappingUtils.L3_CONTEXT), externalGatewayL3Endpoint, true); } @Deprecated private static void addNeutronExtGwMapping(EndpointL3Key epL3Key, ReadWriteTransaction rwTx) { ExternalGatewayAsL3Endpoint externalGatewayL3Endpoint = MappingFactory.createExternalGatewayByL3Endpoint(epL3Key); rwTx.put(LogicalDatastoreType.OPERATIONAL, NeutronGbpIidFactory.externalGatewayAsL3Endpoint(epL3Key.getL3Context(), epL3Key.getIpAddress()), externalGatewayL3Endpoint, true); } @Override public void onDeleted(Router router, Neutron oldNeutron, Neutron newNeutron) { LOG.debug("deleted router - {}", router); ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction(); ContextId routerl3ContextId = new ContextId(router.getUuid().getValue()); TenantId tenantId = new TenantId(router.getTenantId().getValue()); deleteExtGw(router, tenantId, newNeutron, rwTx); InstanceIdentifier<ForwardingContext> routerL3CtxIid = L2L3IidFactory.l3ContextIid(tenantId, routerl3ContextId); LOG.trace("Removing router from forwardingByTenant. Router: {} Path: {}", router, routerL3CtxIid); DataStoreHelper.removeIfExists(LogicalDatastoreType.CONFIGURATION, routerL3CtxIid, rwTx); InstanceIdentifier<L3Context> l3ContextInstanceIdentifier = IidFactory.l3ContextIid(tenantId, new L3ContextId(routerl3ContextId)); LOG.trace("Removing router from Tenant`s forwarding context. Router: {} Path: {}", router, l3ContextInstanceIdentifier); DataStoreHelper.removeIfExists(LogicalDatastoreType.CONFIGURATION, l3ContextInstanceIdentifier, rwTx); DataStoreHelper.submitToDs(rwTx); } private void deleteExtGw(Router router, TenantId tenantId, Neutron newNeutron, ReadWriteTransaction rwTx) { ContextId routerL3CtxId = new ContextId(router.getUuid().getValue()); if (router.getGatewayPortId() != null) { // external network is attached to router Uuid gatewayPortId = router.getGatewayPortId(); Optional<Port> potentialGwPort = PortUtils.findPort(gatewayPortId, newNeutron.getPorts()); if (!potentialGwPort.isPresent()) { LOG.trace("Gateway port {} is not present. Skipping delete for external gateway", gatewayPortId); return; } Port gwPort = potentialGwPort.get(); List<FixedIps> fixedIpsFromGwPort = gwPort.getFixedIps(); if (fixedIpsFromGwPort == null || fixedIpsFromGwPort.isEmpty()) { LOG.trace("Gateway port {} with does not contain fixed IPs. Skipping delete for external gateway", gatewayPortId); return; } FixedIps ipWithSubnetFromGwPort = fixedIpsFromGwPort.get(0); Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet> potentialSubnet = SubnetUtils.findSubnet(ipWithSubnetFromGwPort.getSubnetId(), newNeutron.getSubnets()); if (!potentialSubnet.isPresent()) { LOG.trace("Subnet for GW port {} is not present. Skipping delete for external gateway", gatewayPortId); return; } IpPrefix gatewayIp = MappingUtils.ipAddressToIpPrefix(potentialSubnet.get().getGatewayIp()); if (!unregisterExternalGateway(gatewayIp, routerL3CtxId)) { LOG.warn("Could not unregister routerL3Prefix as gateway of default route. Gateway port {}", gwPort); return; } DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL, NeutronGbpIidFactory.externalGatewayAsEndpoint(routerL3CtxId, gatewayIp, MappingUtils.L3_CONTEXT), rwTx); NetworkDomainId domainId = new NetworkDomainId(ipWithSubnetFromGwPort.getSubnetId().getValue()); Optional<NetworkDomain> domainOptional = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION, L2L3IidFactory.subnetIid(tenantId, domainId), dataProvider.newReadWriteTransaction()); if (domainOptional.isPresent()) { Subnet originalSubnet = domainOptional.get().getAugmentation(SubnetAugmentForwarding.class).getSubnet(); if (originalSubnet != null) { LOG.trace("Deleting virtual router IP from Subnet {} in gateway {}", originalSubnet, gatewayPortId); SubnetBuilder subnetBuilder = new SubnetBuilder(originalSubnet).setVirtualRouterIp(null) .setGateways(null); rwTx.put(LogicalDatastoreType.CONFIGURATION, L2L3IidFactory.subnetIid(tenantId, domainId) .augmentation(SubnetAugmentForwarding.class) .child(Subnet.class), subnetBuilder.build()); } } ContextId l2BdId = new ContextId(potentialSubnet.get().getNetworkId().getValue()); Optional<ForwardingContext> optBd = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION, L2L3IidFactory.l2BridgeDomainIid(tenantId, l2BdId), rwTx); Parent parent = MappingUtils.createParent(l2BdId, MappingUtils.L3_CONTEXT); if (optBd.isPresent()) { ForwardingContext bridgeDomain = new ForwardingContextBuilder(optBd.get()).setParent(parent).build(); LOG.trace("Setting parent for L2BridgeDomain {} back to network {}.", bridgeDomain, parent); rwTx.put(LogicalDatastoreType.CONFIGURATION, L2L3IidFactory.l2BridgeDomainIid(tenantId, l2BdId), bridgeDomain); } } deleteTenantForwarding(newNeutron, router, new L3ContextId(routerL3CtxId), tenantId, rwTx); } }