a84e7423fd6eeeb1ac68eaff4e69478a60e02e8d
[groupbasedpolicy.git] / neutron-mapper / src / main / java / org / opendaylight / groupbasedpolicy / neutron / mapper / mapping / NeutronNetworkAware.java
1 /*
2  * Copyright (c) 2015 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 package org.opendaylight.groupbasedpolicy.neutron.mapper.mapping;
9
10 import static com.google.common.base.Preconditions.checkNotNull;
11
12 import java.util.UUID;
13
14 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
15 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
16 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
17 import org.opendaylight.groupbasedpolicy.neutron.gbp.util.NeutronGbpIidFactory;
18 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.MappingUtils;
19 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.NeutronMapperIidFactory;
20 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.Utils;
21 import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
22 import org.opendaylight.groupbasedpolicy.util.IidFactory;
23 import org.opendaylight.neutron.spi.INeutronNetworkAware;
24 import org.opendaylight.neutron.spi.NeutronNetwork;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.Description;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2BridgeDomainId;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2FloodDomainId;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L3ContextId;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.Name;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.neutron.by.gbp.mappings.external.networks.by.l2.flood.domains.ExternalNetworkByL2FloodDomain;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.neutron.by.gbp.mappings.external.networks.by.l2.flood.domains.ExternalNetworkByL2FloodDomainBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.mapper.rev150223.mappings.network.mappings.NetworkMapping;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.mapper.rev150223.mappings.network.mappings.NetworkMappingBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.EndpointGroup;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.EndpointGroup.IntraGroupPolicy;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.EndpointGroupBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.L2BridgeDomain;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.L2BridgeDomainBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.L2FloodDomain;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.L2FloodDomainBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.L3Context;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.L3ContextBuilder;
44 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
45 import org.slf4j.Logger;
46 import org.slf4j.LoggerFactory;
47
48 import com.google.common.base.Optional;
49
50 public class NeutronNetworkAware implements INeutronNetworkAware {
51
52     private static final Logger LOG = LoggerFactory.getLogger(NeutronNetworkAware.class);
53     private final DataBroker dataProvider;
54
55     public NeutronNetworkAware(DataBroker dataProvider) {
56         this.dataProvider = checkNotNull(dataProvider);
57     }
58
59     /**
60      * @see org.opendaylight.neutron.spi.INeutronNetworkAware#canCreateNetwork(org.opendaylight.neutron.spi.NeutronNetwork)
61      */
62     @Override
63     public int canCreateNetwork(NeutronNetwork network) {
64         LOG.trace("canCreateNetwork - {}", network);
65         // nothing to consider
66         return StatusCode.OK;
67     }
68
69     /**
70      * @see org.opendaylight.neutron.spi.INeutronNetworkAware#neutronNetworkCreated(org.opendaylight.neutron.spi.NeutronNetwork)
71      */
72     @Override
73     public void neutronNetworkCreated(NeutronNetwork network) {
74         LOG.trace("neutronNetworkCreated - {}", network);
75         ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
76         L2FloodDomainId l2FdId = new L2FloodDomainId(network.getID());
77         TenantId tenantId = new TenantId(Utils.normalizeUuid(network.getTenantID()));
78         addEpgDhcpIfMissing(tenantId, rwTx);
79         addEpgRouterIfMissing(tenantId, rwTx);
80         // Note that Router External doesn't mean the router exists yet, it simply means it will connect to one.
81         if(network.getRouterExternal()) {
82             addEpgExternalIfMissing(tenantId, rwTx);
83         }
84         Description domainDescription = new Description(MappingUtils.NEUTRON_NETWORK__ + network.getID());
85         Name name = null;
86         if (network.getNetworkName() != null) {
87             name = new Name(network.getNetworkName());
88         }
89         L3ContextId l3ContextId = new L3ContextId(UUID.randomUUID().toString());
90         L3Context l3Context = new L3ContextBuilder().setId(l3ContextId)
91             .setDescription(domainDescription)
92             .setName(name)
93             .build();
94         rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.l3ContextIid(tenantId, l3ContextId), l3Context, true);
95
96         L2BridgeDomainId l2BdId = new L2BridgeDomainId(UUID.randomUUID().toString());
97         L2BridgeDomain l2Bd = new L2BridgeDomainBuilder().setId(l2BdId)
98             .setParent(l3ContextId)
99             .setDescription(domainDescription)
100             .setName(name)
101             .build();
102         rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.l2BridgeDomainIid(tenantId, l2BdId), l2Bd, true);
103
104         L2FloodDomain l2Fd = new L2FloodDomainBuilder().setId(l2FdId)
105             .setParent(l2BdId)
106             .setDescription(domainDescription)
107             .setName(name)
108             .build();
109         rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.l2FloodDomainIid(tenantId, l2FdId), l2Fd, true);
110
111         NetworkMapping networkMapping = new NetworkMappingBuilder().setNetworkId(l2FdId)
112             .setL2BridgeDomainId(l2BdId)
113             .setL3ContextId(l3ContextId)
114             .build();
115         rwTx.put(LogicalDatastoreType.OPERATIONAL, NeutronMapperIidFactory.networkMappingIid(l2FdId), networkMapping, true);
116
117         if (network.getRouterExternal() != null
118                 && network.getRouterExternal() == true) {
119             addExternalNetworkIfMissing(l2Fd.getId(), rwTx);
120         }
121         DataStoreHelper.submitToDs(rwTx);
122     }
123
124     private void addExternalNetworkIfMissing(L2FloodDomainId l2FdId, ReadWriteTransaction rwTx) {
125         InstanceIdentifier<ExternalNetworkByL2FloodDomain> iid = NeutronGbpIidFactory.externalNetworkByL2FloodDomain(l2FdId);
126         Optional<ExternalNetworkByL2FloodDomain> externalPresent = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
127                 iid, rwTx);
128         if (!externalPresent.isPresent()) {
129             ExternalNetworkByL2FloodDomainBuilder builder = new ExternalNetworkByL2FloodDomainBuilder()
130                 .setL2FloodDomainId(l2FdId);
131             rwTx.put(LogicalDatastoreType.OPERATIONAL,
132                     NeutronGbpIidFactory.externalNetworkByL2FloodDomain(l2FdId), builder.build(), true);
133         }
134     }
135
136     private void addEpgExternalIfMissing(TenantId tenantId, ReadWriteTransaction rwTx) {
137         Optional<EndpointGroup> potentialEpgExternal = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
138                 IidFactory.endpointGroupIid(tenantId, MappingUtils.EPG_EXTERNAL_ID), rwTx);
139         if (!potentialEpgExternal.isPresent()) {
140             EndpointGroup epgExternal = new EndpointGroupBuilder().setId(MappingUtils.EPG_EXTERNAL_ID)
141                 .setDescription(new Description(MappingUtils.NEUTRON_EXTERNAL__ + "epg_external_networks"))
142                 .setIntraGroupPolicy(IntraGroupPolicy.RequireContract)
143                 .build();
144             rwTx.put(LogicalDatastoreType.CONFIGURATION,
145                     IidFactory.endpointGroupIid(tenantId, MappingUtils.EPG_EXTERNAL_ID), epgExternal, true);
146         }
147     }
148
149     private void addEpgDhcpIfMissing(TenantId tenantId, ReadWriteTransaction rwTx) {
150         InstanceIdentifier<EndpointGroup> epgDhcpIid = IidFactory.endpointGroupIid(tenantId, MappingUtils.EPG_DHCP_ID);
151         Optional<EndpointGroup> potentialDhcpEpg = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
152                 epgDhcpIid, rwTx);
153         if (!potentialDhcpEpg.isPresent()) {
154             EndpointGroup epgDhcp = new EndpointGroupBuilder().setId(MappingUtils.EPG_DHCP_ID)
155                 .setName(new Name("DHCP_group"))
156                 .setDescription(new Description("Group where are all DHCP endpoints."))
157                 .setIntraGroupPolicy(IntraGroupPolicy.RequireContract)
158                 .build();
159             rwTx.put(LogicalDatastoreType.CONFIGURATION, epgDhcpIid, epgDhcp);
160         }
161     }
162
163     private void addEpgRouterIfMissing(TenantId tenantId, ReadWriteTransaction rwTx) {
164         Optional<EndpointGroup> potentialEpgRouter = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
165                 IidFactory.endpointGroupIid(tenantId, MappingUtils.EPG_ROUTER_ID), rwTx);
166         if (!potentialEpgRouter.isPresent()) {
167             EndpointGroup epgRouter = new EndpointGroupBuilder().setId(MappingUtils.EPG_ROUTER_ID)
168                 .setDescription(new Description(MappingUtils.NEUTRON_ROUTER__ + "epg_routers"))
169                 .setIntraGroupPolicy(IntraGroupPolicy.RequireContract)
170                 .build();
171             rwTx.put(LogicalDatastoreType.CONFIGURATION,
172                     IidFactory.endpointGroupIid(tenantId, MappingUtils.EPG_ROUTER_ID), epgRouter);
173         }
174     }
175
176     /**
177      * @see org.opendaylight.neutron.spi.INeutronNetworkAware#canUpdateNetwork(org.opendaylight.neutron.spi.NeutronNetwork,
178      *      org.opendaylight.neutron.spi.NeutronNetwork)
179      */
180     @Override
181     public int canUpdateNetwork(NeutronNetwork delta, NeutronNetwork original) {
182         LOG.trace("canUpdateNetwork - delta: {} original: {}", delta, original);
183         // nothing to consider
184         return StatusCode.OK;
185     }
186
187     /**
188      * @see org.opendaylight.neutron.spi.INeutronNetworkAware#neutronNetworkUpdated(org.opendaylight.neutron.spi.NeutronNetwork)
189      */
190     @Override
191     public void neutronNetworkUpdated(NeutronNetwork network) {
192         LOG.trace("neutronNetworkUpdated - {}", network);
193         // TODO we could update just name
194     }
195
196     /**
197      * @see org.opendaylight.neutron.spi.INeutronNetworkAware#canDeleteNetwork(org.opendaylight.neutron.spi.NeutronNetwork)
198      */
199     @Override
200     public int canDeleteNetwork(NeutronNetwork network) {
201         LOG.trace("canDeleteNetwork - {}", network);
202         // nothing to consider
203         return StatusCode.OK;
204     }
205
206     /**
207      * @see org.opendaylight.neutron.spi.INeutronNetworkAware#neutronNetworkDeleted(org.opendaylight.neutron.spi.NeutronNetwork)
208      */
209     @Override
210     public void neutronNetworkDeleted(NeutronNetwork network) {
211         LOG.trace("neutronNetworkDeleted - {}", network);
212         ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
213         TenantId tenantId = new TenantId(Utils.normalizeUuid(network.getTenantID()));
214         L2FloodDomainId l2FdId = new L2FloodDomainId(network.getID());
215         Optional<NetworkMapping> potentionalNetworkMapping = DataStoreHelper.readFromDs(
216                 LogicalDatastoreType.OPERATIONAL, NeutronMapperIidFactory.networkMappingIid(l2FdId), rwTx);
217         if (!potentionalNetworkMapping.isPresent()) {
218             LOG.warn("Illegal state - network-mapping {} does not exist.", l2FdId.getValue());
219             rwTx.cancel();
220             return;
221         }
222
223         NetworkMapping networkMapping = potentionalNetworkMapping.get();
224         L2BridgeDomainId l2BdId = networkMapping.getL2BridgeDomainId();
225         L3ContextId l3ContextId = networkMapping.getL3ContextId();
226         if (l2BdId == null || l3ContextId == null) {
227             LOG.warn("Illegal state - network-mapping {} is not valid.", networkMapping);
228             rwTx.cancel();
229             return;
230         }
231
232         Optional<L2FloodDomain> potentialL2Fd = DataStoreHelper.removeIfExists(LogicalDatastoreType.CONFIGURATION,
233                 IidFactory.l2FloodDomainIid(tenantId, l2FdId), rwTx);
234         if (!potentialL2Fd.isPresent()) {
235             LOG.warn("Illegal state - l2-flood-domain {} does not exist.", l2FdId.getValue());
236             rwTx.cancel();
237             return;
238         }
239
240         Optional<L2BridgeDomain> potentialL2Bd = DataStoreHelper.removeIfExists(LogicalDatastoreType.CONFIGURATION,
241                 IidFactory.l2BridgeDomainIid(tenantId, l2BdId), rwTx);
242         if (!potentialL2Bd.isPresent()) {
243             LOG.warn("Illegal state - l2-bridge-domain {} does not exist.", l2BdId.getValue());
244             rwTx.cancel();
245             return;
246         }
247
248         Optional<L3Context> potentialL3Context = DataStoreHelper.removeIfExists(LogicalDatastoreType.CONFIGURATION,
249                 IidFactory.l3ContextIid(tenantId, l3ContextId), rwTx);
250         if (!potentialL3Context.isPresent()) {
251             LOG.warn("Illegal state - l3-context {} does not exist.", l3ContextId.getValue());
252             rwTx.cancel();
253             return;
254         }
255
256         DataStoreHelper.submitToDs(rwTx);
257     }
258
259 }