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 java.util.List;
14 import java.util.concurrent.ExecutionException;
16 import javax.annotation.Nonnull;
18 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
19 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
20 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
21 import org.opendaylight.groupbasedpolicy.dto.IndexedTenant;
22 import org.opendaylight.groupbasedpolicy.neutron.gbp.util.NeutronGbpIidFactory;
23 import org.opendaylight.groupbasedpolicy.neutron.mapper.EndpointRegistrator;
24 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.MappingUtils;
25 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.PortUtils;
26 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.SubnetUtils;
27 import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
28 import org.opendaylight.groupbasedpolicy.util.IidFactory;
29 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
30 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.Description;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2BridgeDomainId;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L3ContextId;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.Name;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.NetworkDomainId;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubnetId;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Key;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.neutron.by.gbp.mappings.external.gateways.as.l3.endpoints.ExternalGatewayAsL3Endpoint;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.TenantBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.ForwardingContext;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L2BridgeDomain;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L2BridgeDomainBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L2FloodDomain;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L3Context;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L3ContextBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.Subnet;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.SubnetBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.Routers;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.Router;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
54 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
55 import org.slf4j.Logger;
56 import org.slf4j.LoggerFactory;
58 import com.google.common.base.Optional;
59 import com.google.common.base.Strings;
61 public class NeutronRouterAware implements NeutronAware<Router> {
63 private static final Logger LOG = LoggerFactory.getLogger(NeutronRouterAware.class);
64 public static final InstanceIdentifier<Router> ROUTER_WILDCARD_IID =
65 InstanceIdentifier.builder(Neutron.class).child(Routers.class).child(Router.class).build();
66 private final DataBroker dataProvider;
67 private final EndpointRegistrator epRegistrator;
69 public NeutronRouterAware(DataBroker dataProvider, EndpointRegistrator epRegistrator) {
70 this.dataProvider = checkNotNull(dataProvider);
71 this.epRegistrator = checkNotNull(epRegistrator);
75 public void onCreated(Router router, Neutron neutron) {
76 LOG.trace("created router - {}", router);
80 public void onUpdated(Router oldRouter, Router newRouter, Neutron oldNeutron, Neutron newNeutron) {
81 LOG.trace("updated router - OLD: {}\nNEW: {}", oldRouter, newRouter);
83 ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
84 TenantId tenantId = new TenantId(newRouter.getTenantId().getValue());
85 L3ContextId l3ContextIdFromRouterId = new L3ContextId(newRouter.getUuid().getValue());
86 InstanceIdentifier<L3Context> l3ContextIidForRouterId =
87 IidFactory.l3ContextIid(tenantId, l3ContextIdFromRouterId);
88 Optional<L3Context> potentialL3ContextForRouter =
89 DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION, l3ContextIidForRouterId, rwTx);
90 L3Context l3Context = null;
91 if (potentialL3ContextForRouter.isPresent()) {
92 l3Context = potentialL3ContextForRouter.get();
93 } else { // add L3 context if missing
94 l3Context = createL3ContextFromRouter(newRouter);
95 rwTx.put(LogicalDatastoreType.CONFIGURATION, l3ContextIidForRouterId, l3Context);
98 if (newRouter.getGatewayPortId() != null && oldRouter.getGatewayPortId() == null) {
99 // external network is attached to router
100 Uuid gatewayPortId = newRouter.getGatewayPortId();
101 Optional<Port> potentialGwPort = PortUtils.findPort(gatewayPortId, newNeutron.getPorts());
102 if (!potentialGwPort.isPresent()) {
103 LOG.warn("Illegal state - router gateway port {} does not exist for router {}.",
104 gatewayPortId.getValue(), newRouter);
109 Port gwPort = potentialGwPort.get();
110 List<FixedIps> fixedIpsFromGwPort = gwPort.getFixedIps();
111 if (fixedIpsFromGwPort == null || fixedIpsFromGwPort.isEmpty()) {
112 LOG.warn("Illegal state - router gateway port {} does not contain fixed IPs {}",
113 gatewayPortId.getValue(), gwPort);
118 // router can have only one external network
119 FixedIps ipWithSubnetFromGwPort = fixedIpsFromGwPort.get(0);
120 Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet> potentialSubnet = SubnetUtils.findSubnet(ipWithSubnetFromGwPort.getSubnetId(), newNeutron.getSubnets());
121 if (!potentialSubnet.isPresent()) {
122 LOG.warn("Illegal state - Subnet {} does not exist for router {}.",
123 ipWithSubnetFromGwPort.getSubnetId(), newRouter);
127 IpAddress gatewayIp = potentialSubnet.get().getGatewayIp();
128 boolean registeredExternalGateway = epRegistrator.registerL3EndpointAsExternalGateway(tenantId, gatewayIp,
129 l3ContextIdFromRouterId, new NetworkDomainId(ipWithSubnetFromGwPort.getSubnetId().getValue()));
130 if (!registeredExternalGateway) {
131 LOG.warn("Could not add L3Prefix as gateway of default route. Gateway port {}", gwPort);
135 EndpointL3Key epL3Key = new EndpointL3Key(gatewayIp, l3ContextIdFromRouterId);
136 addNeutronExtGwGbpMapping(epL3Key, rwTx);
138 boolean registeredDefaultRoute = epRegistrator.registerExternalL3PrefixEndpoint(MappingUtils.DEFAULT_ROUTE,
139 l3ContextIdFromRouterId, gatewayIp, tenantId);
140 if (!registeredDefaultRoute) {
141 LOG.warn("Could not add EndpointL3Prefix as default route. Gateway port {}", gwPort);
145 Subnet subnetWithGw =
146 new SubnetBuilder().setId(new SubnetId(ipWithSubnetFromGwPort.getSubnetId().getValue()))
147 .setVirtualRouterIp(gatewayIp)
149 rwTx.merge(LogicalDatastoreType.CONFIGURATION, IidFactory.subnetIid(tenantId, subnetWithGw.getId()),
151 L2BridgeDomainId l2BdId = new L2BridgeDomainId(potentialSubnet.get().getNetworkId().getValue());
152 Optional<L2BridgeDomain> optBd = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
153 IidFactory.l2BridgeDomainIid(tenantId, l2BdId), rwTx);
154 if (!optBd.isPresent()) {
156 "Could not read L2-Bridge-Domain {} Modifiaction of it's parent to L3-Context of router {} aborted.",
157 l2BdId, newRouter.getUuid());
161 L2BridgeDomain l2BdWithGw = new L2BridgeDomainBuilder(optBd.get())
162 .setParent(new L3ContextId(l3ContextIdFromRouterId.getValue()))
164 rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.l2BridgeDomainIid(tenantId, l2BdId),
167 DataStoreHelper.submitToDs(rwTx);
170 private static @Nonnull L3Context createL3ContextFromRouter(Router router) {
171 Name l3ContextName = null;
172 if (!Strings.isNullOrEmpty(router.getName())) {
173 l3ContextName = new Name(router.getName());
175 return new L3ContextBuilder().setId(new L3ContextId(router.getUuid().getValue()))
176 .setName(l3ContextName)
177 .setDescription(new Description(MappingUtils.NEUTRON_ROUTER + router.getUuid().getValue()))
181 private static void addNeutronExtGwGbpMapping(EndpointL3Key epL3Key, ReadWriteTransaction rwTx) {
182 ExternalGatewayAsL3Endpoint externalGatewayL3Endpoint =
183 MappingFactory.createExternalGatewayByL3Endpoint(epL3Key);
184 rwTx.put(LogicalDatastoreType.OPERATIONAL,
185 NeutronGbpIidFactory.externalGatewayAsL3Endpoint(epL3Key.getL3Context(), epL3Key.getIpAddress()),
186 externalGatewayL3Endpoint, true);
190 public void onDeleted(Router router, Neutron oldNeutron, Neutron newNeutron) {
191 LOG.trace("deleted router - {}", router);