Bug 5213 - Missing segmentation-id for physical networks
[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.HashSet;
13 import java.util.Set;
14 import java.util.UUID;
15
16 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
17 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
18 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
19 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
20 import org.opendaylight.groupbasedpolicy.neutron.gbp.util.NeutronGbpIidFactory;
21 import org.opendaylight.groupbasedpolicy.neutron.mapper.infrastructure.NetworkClient;
22 import org.opendaylight.groupbasedpolicy.neutron.mapper.infrastructure.NetworkService;
23 import org.opendaylight.groupbasedpolicy.neutron.mapper.mapping.group.NeutronSecurityGroupAware;
24 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.MappingUtils;
25 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.NeutronMapperIidFactory;
26 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.NeutronUtils;
27 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.Utils;
28 import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
29 import org.opendaylight.groupbasedpolicy.util.IidFactory;
30 import org.opendaylight.neutron.spi.INeutronNetworkAware;
31 import org.opendaylight.neutron.spi.NeutronNetwork;
32 import org.opendaylight.neutron.spi.NeutronSecurityGroup;
33 import org.opendaylight.neutron.spi.NeutronSecurityRule;
34 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2BridgeDomainId;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2FloodDomainId;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L3ContextId;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.Name;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.neutron.by.gbp.mappings.provider.physical.networks.as.l2.flood.domains.ProviderPhysicalNetworkAsL2FloodDomain;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.neutron.by.gbp.mappings.provider.physical.networks.as.l2.flood.domains.ProviderPhysicalNetworkAsL2FloodDomainBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.mapper.rev150223.mappings.network.mappings.NetworkMapping;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.mapper.rev150223.mappings.network.mappings.NetworkMappingBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L2BridgeDomain;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L2BridgeDomainBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L2FloodDomain;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L2FloodDomainBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L3Context;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L3ContextBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.ExternalImplicitGroup;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.ExternalImplicitGroupBuilder;
52 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
53 import org.slf4j.Logger;
54 import org.slf4j.LoggerFactory;
55
56 import com.google.common.base.Optional;
57 import com.google.common.base.Strings;
58 import com.google.common.collect.ImmutableList;
59
60 public class NeutronNetworkAware implements INeutronNetworkAware {
61
62     private static final Logger LOG = LoggerFactory.getLogger(NeutronNetworkAware.class);
63     private final DataBroker dataProvider;
64     private final Set<TenantId> tenantsWithRouterAndNetworkSeviceEntities = new HashSet<>();
65     private final NeutronSecurityGroupAware secGrpAware;
66     private final NeutronNetworkDao networkDao;
67
68     public NeutronNetworkAware(DataBroker dataProvider, NeutronSecurityGroupAware secGrpAware, NeutronNetworkDao networkDao) {
69         this.dataProvider = checkNotNull(dataProvider);
70         this.secGrpAware = checkNotNull(secGrpAware);
71         this.networkDao = checkNotNull(networkDao);
72     }
73
74     /**
75      * @see org.opendaylight.neutron.spi.INeutronNetworkAware#canCreateNetwork(org.opendaylight.neutron.spi.NeutronNetwork)
76      */
77     @Override
78     public int canCreateNetwork(NeutronNetwork network) {
79         LOG.trace("canCreateNetwork - {}", network);
80         // nothing to consider
81         return StatusCode.OK;
82     }
83
84     /**
85      * @see org.opendaylight.neutron.spi.INeutronNetworkAware#neutronNetworkCreated(org.opendaylight.neutron.spi.NeutronNetwork)
86      */
87     @Override
88     public void neutronNetworkCreated(NeutronNetwork network) {
89         LOG.trace("neutronNetworkCreated - {}", network);
90         ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
91         L2FloodDomainId l2FdId = new L2FloodDomainId(network.getID());
92         TenantId tenantId = new TenantId(Utils.normalizeUuid(network.getTenantID()));
93         Name name = null;
94         if (network.getNetworkName() != null) {
95             try {
96                 name = new Name(network.getNetworkName());
97             } catch (Exception e) {
98                 name = null;
99                 LOG.info("Name of Neutron Network '{}' is ignored.", network.getNetworkName());
100                 LOG.debug("Name exception", e);
101             }
102         }
103
104         L3ContextId l3ContextId = new L3ContextId(UUID.randomUUID().toString());
105         L3Context l3Context = new L3ContextBuilder().setId(l3ContextId).setName(name).build();
106         rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.l3ContextIid(tenantId, l3ContextId), l3Context, true);
107
108         L2BridgeDomainId l2BdId = new L2BridgeDomainId(UUID.randomUUID().toString());
109         L2BridgeDomain l2Bd = new L2BridgeDomainBuilder().setId(l2BdId).setParent(l3ContextId).setName(name).build();
110         rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.l2BridgeDomainIid(tenantId, l2BdId), l2Bd, true);
111
112         L2FloodDomain l2Fd = new L2FloodDomainBuilder().setId(l2FdId).setParent(l2BdId).setName(name).build();
113         rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.l2FloodDomainIid(tenantId, l2FdId), l2Fd, true);
114
115         NetworkMapping networkMapping = new NetworkMappingBuilder().setNetworkId(l2FdId)
116             .setL2BridgeDomainId(l2BdId)
117             .setL3ContextId(l3ContextId)
118             .build();
119         rwTx.put(LogicalDatastoreType.OPERATIONAL, NeutronMapperIidFactory.networkMappingIid(l2FdId), networkMapping,
120                 true);
121
122         if (!tenantsWithRouterAndNetworkSeviceEntities.contains(tenantId)) {
123             tenantsWithRouterAndNetworkSeviceEntities.add(tenantId);
124             NetworkService.writeNetworkServiceEntitiesToTenant(tenantId, rwTx);
125             NetworkService.writeDhcpClauseWithConsProvEic(tenantId, null, rwTx);
126             NetworkService.writeDnsClauseWithConsProvEic(tenantId, null, rwTx);
127             NetworkService.writeMgmtClauseWithConsProvEic(tenantId, null, rwTx);
128             NetworkClient.writeNetworkClientEntitiesToTenant(tenantId, rwTx);
129             NetworkClient.writeConsumerNamedSelector(tenantId, NetworkService.DHCP_CONTRACT_CONSUMER_SELECTOR, rwTx);
130             NetworkClient.writeConsumerNamedSelector(tenantId, NetworkService.DNS_CONTRACT_CONSUMER_SELECTOR, rwTx);
131             NetworkClient.writeConsumerNamedSelector(tenantId, NetworkService.MGMT_CONTRACT_CONSUMER_SELECTOR, rwTx);
132         }
133         networkDao.addNetwork(network);
134         if (network.getRouterExternal() != null && network.getRouterExternal() == true) {
135             addEigEpgExternalWithContracts(tenantId, rwTx);
136         }
137         if (!Strings.isNullOrEmpty(network.getProviderPhysicalNetwork())) {
138             String segmentationId = network.getProviderSegmentationID();
139             addProviderPhysicalNetworkMapping(tenantId, l2FdId, segmentationId, rwTx);
140         }
141         DataStoreHelper.submitToDs(rwTx);
142     }
143
144     private void addEigEpgExternalWithContracts(TenantId tenantId, ReadWriteTransaction rwTx) {
145         Uuid tenantUuid = new Uuid(tenantId.getValue());
146         NeutronSecurityRule inIpv4 = new NeutronSecurityRule();
147         inIpv4.setID("19b85ad2-bdfc-11e5-9912-ba0be0483c18");
148         inIpv4.setSecurityRuleDirection(NeutronUtils.INGRESS);
149         inIpv4.setSecurityRuleEthertype(NeutronUtils.IPv4);
150         inIpv4.setSecurityRuleGroupID(MappingUtils.EPG_EXTERNAL_ID.getValue());
151         inIpv4.setTenantID(tenantUuid);
152         NeutronSecurityRule outIpv4 = new NeutronSecurityRule();
153         outIpv4.setID("19b85eba-bdfc-11e5-9912-ba0be0483c18");
154         outIpv4.setSecurityRuleDirection(NeutronUtils.EGRESS);
155         outIpv4.setSecurityRuleEthertype(NeutronUtils.IPv4);
156         outIpv4.setSecurityRuleGroupID(MappingUtils.EPG_EXTERNAL_ID.getValue());
157         outIpv4.setTenantID(tenantUuid);
158         NeutronSecurityRule inIpv6 = new NeutronSecurityRule();
159         inIpv6.setID("19b86180-bdfc-11e5-9912-ba0be0483c18");
160         inIpv6.setSecurityRuleDirection(NeutronUtils.INGRESS);
161         inIpv6.setSecurityRuleEthertype(NeutronUtils.IPv6);
162         inIpv6.setSecurityRuleGroupID(MappingUtils.EPG_EXTERNAL_ID.getValue());
163         inIpv6.setTenantID(tenantUuid);
164         NeutronSecurityRule outIpv6 = new NeutronSecurityRule();
165         outIpv6.setID("19b86270-bdfc-11e5-9912-ba0be0483c18");
166         outIpv6.setSecurityRuleDirection(NeutronUtils.EGRESS);
167         outIpv6.setSecurityRuleEthertype(NeutronUtils.IPv6);
168         outIpv6.setSecurityRuleGroupID(MappingUtils.EPG_EXTERNAL_ID.getValue());
169         outIpv6.setTenantID(tenantUuid);
170         NeutronSecurityGroup externalSecGrp = new NeutronSecurityGroup();
171         externalSecGrp.setID(MappingUtils.EPG_EXTERNAL_ID.getValue());
172         externalSecGrp.setSecurityGroupName("EXTERNAL_group");
173         externalSecGrp.setTenantID(tenantUuid);
174         externalSecGrp.setSecurityRules(ImmutableList.of(inIpv4, outIpv4, inIpv6, outIpv6));
175         boolean isAddedNeutronSecurityGroup = secGrpAware.addNeutronSecurityGroup(externalSecGrp, rwTx);
176         if (!isAddedNeutronSecurityGroup) {
177             LOG.error("Problem with adding External Neutron Security Group representing External Implicit Group. {}", externalSecGrp);
178             return;
179         }
180         ExternalImplicitGroup eig = new ExternalImplicitGroupBuilder().setId(MappingUtils.EPG_EXTERNAL_ID).build();
181         rwTx.put(LogicalDatastoreType.CONFIGURATION,
182                 IidFactory.externalImplicitGroupIid(tenantId, eig.getId()), eig, true);
183     }
184
185     private void addProviderPhysicalNetworkMapping(TenantId tenantId, L2FloodDomainId l2FdId, String segmentationId,
186             WriteTransaction wTx) {
187         ProviderPhysicalNetworkAsL2FloodDomain provNetAsL2Fd = new ProviderPhysicalNetworkAsL2FloodDomainBuilder()
188             .setTenantId(tenantId).setL2FloodDomainId(l2FdId).setSegmentationId(segmentationId).build();
189         wTx.put(LogicalDatastoreType.OPERATIONAL,
190                 NeutronGbpIidFactory.providerPhysicalNetworkAsL2FloodDomainIid(tenantId, l2FdId), provNetAsL2Fd);
191     }
192
193     /**
194      * @see org.opendaylight.neutron.spi.INeutronNetworkAware#canUpdateNetwork(org.opendaylight.neutron.spi.NeutronNetwork,
195      *      org.opendaylight.neutron.spi.NeutronNetwork)
196      */
197     @Override
198     public int canUpdateNetwork(NeutronNetwork delta, NeutronNetwork original) {
199         LOG.trace("canUpdateNetwork - delta: {} original: {}", delta, original);
200         // nothing to consider
201         return StatusCode.OK;
202     }
203
204     /**
205      * @see org.opendaylight.neutron.spi.INeutronNetworkAware#neutronNetworkUpdated(org.opendaylight.neutron.spi.NeutronNetwork)
206      */
207     @Override
208     public void neutronNetworkUpdated(NeutronNetwork network) {
209         LOG.trace("neutronNetworkUpdated - {}", network);
210         // TODO we could update just name
211     }
212
213     /**
214      * @see org.opendaylight.neutron.spi.INeutronNetworkAware#canDeleteNetwork(org.opendaylight.neutron.spi.NeutronNetwork)
215      */
216     @Override
217     public int canDeleteNetwork(NeutronNetwork network) {
218         LOG.trace("canDeleteNetwork - {}", network);
219         // nothing to consider
220         return StatusCode.OK;
221     }
222
223     /**
224      * @see org.opendaylight.neutron.spi.INeutronNetworkAware#neutronNetworkDeleted(org.opendaylight.neutron.spi.NeutronNetwork)
225      */
226     @Override
227     public void neutronNetworkDeleted(NeutronNetwork network) {
228         LOG.trace("neutronNetworkDeleted - {}", network);
229         ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
230         TenantId tenantId = new TenantId(Utils.normalizeUuid(network.getTenantID()));
231         L2FloodDomainId l2FdId = new L2FloodDomainId(network.getID());
232         InstanceIdentifier<NetworkMapping> networkMappingIid = NeutronMapperIidFactory.networkMappingIid(l2FdId);
233         Optional<NetworkMapping> potentionalNetworkMapping =
234                 DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL, networkMappingIid, rwTx);
235         if (!potentionalNetworkMapping.isPresent()) {
236             LOG.warn("Illegal state - network-mapping {} does not exist.", l2FdId.getValue());
237             rwTx.cancel();
238             return;
239         }
240
241         NetworkMapping networkMapping = potentionalNetworkMapping.get();
242         L2BridgeDomainId l2BdId = networkMapping.getL2BridgeDomainId();
243         L3ContextId l3ContextId = networkMapping.getL3ContextId();
244         if (l2BdId == null || l3ContextId == null) {
245             LOG.warn("Illegal state - network-mapping {} is not valid.", networkMapping);
246             rwTx.cancel();
247             return;
248         }
249
250         Optional<L2FloodDomain> potentialL2Fd = DataStoreHelper.removeIfExists(LogicalDatastoreType.CONFIGURATION,
251                 IidFactory.l2FloodDomainIid(tenantId, l2FdId), rwTx);
252         if (!potentialL2Fd.isPresent()) {
253             LOG.warn("Illegal state - l2-flood-domain {} does not exist.", l2FdId.getValue());
254             rwTx.cancel();
255             return;
256         }
257
258         Optional<L2BridgeDomain> potentialL2Bd = DataStoreHelper.removeIfExists(LogicalDatastoreType.CONFIGURATION,
259                 IidFactory.l2BridgeDomainIid(tenantId, l2BdId), rwTx);
260         if (!potentialL2Bd.isPresent()) {
261             LOG.warn("Illegal state - l2-bridge-domain {} does not exist.", l2BdId.getValue());
262             rwTx.cancel();
263             return;
264         }
265
266         Optional<L3Context> potentialL3Context = DataStoreHelper.removeIfExists(LogicalDatastoreType.CONFIGURATION,
267                 IidFactory.l3ContextIid(tenantId, l3ContextId), rwTx);
268         if (!potentialL3Context.isPresent()) {
269             LOG.warn("Illegal state - l3-context {} does not exist.", l3ContextId.getValue());
270             rwTx.cancel();
271             return;
272         }
273
274         rwTx.delete(LogicalDatastoreType.OPERATIONAL, networkMappingIid);
275
276         DataStoreHelper.submitToDs(rwTx);
277     }
278 }