Neutron port removal fixed
[groupbasedpolicy.git] / neutron-mapper / src / main / java / org / opendaylight / groupbasedpolicy / neutron / mapper / NeutronMapper.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;
9
10 import java.util.ArrayList;
11 import java.util.Collection;
12 import java.util.List;
13 import java.util.Set;
14
15 import javax.annotation.Nonnull;
16 import javax.annotation.Nullable;
17
18 import org.opendaylight.controller.md.sal.binding.api.ClusteredDataTreeChangeListener;
19 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
20 import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
21 import org.opendaylight.controller.md.sal.binding.api.DataObjectModification.ModificationType;
22 import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
23 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
24 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
25 import org.opendaylight.groupbasedpolicy.neutron.mapper.mapping.NeutronAware;
26 import org.opendaylight.groupbasedpolicy.neutron.mapper.mapping.NeutronFloatingIpAware;
27 import org.opendaylight.groupbasedpolicy.neutron.mapper.mapping.NeutronNetworkAware;
28 import org.opendaylight.groupbasedpolicy.neutron.mapper.mapping.NeutronPortAware;
29 import org.opendaylight.groupbasedpolicy.neutron.mapper.mapping.NeutronRouterAware;
30 import org.opendaylight.groupbasedpolicy.neutron.mapper.mapping.NeutronSecurityGroupAware;
31 import org.opendaylight.groupbasedpolicy.neutron.mapper.mapping.NeutronSubnetAware;
32 import org.opendaylight.groupbasedpolicy.neutron.mapper.mapping.rule.NeutronSecurityRuleAware;
33 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.MappingUtils;
34 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.NetworkUtils;
35 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.BaseEndpointService;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.EndpointService;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.DirectionEgress;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.DirectionIngress;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.EthertypeV4;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.EthertypeV6;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.floatingips.attributes.floatingips.Floatingip;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.Router;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.NeutronBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.groups.attributes.SecurityGroups;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.groups.attributes.SecurityGroupsBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.groups.attributes.security.groups.SecurityGroup;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.groups.attributes.security.groups.SecurityGroupBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.rules.attributes.SecurityRules;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.rules.attributes.SecurityRulesBuilder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.rules.attributes.security.rules.SecurityRule;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.rules.attributes.security.rules.SecurityRuleBuilder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
57 import org.opendaylight.yangtools.concepts.ListenerRegistration;
58 import org.opendaylight.yangtools.yang.binding.DataObject;
59 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
60 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
61
62 import com.google.common.base.Function;
63 import com.google.common.base.Predicate;
64 import com.google.common.collect.FluentIterable;
65 import com.google.common.collect.Iterators;
66 import com.google.common.collect.PeekingIterator;
67
68 public class NeutronMapper implements ClusteredDataTreeChangeListener<Neutron>, AutoCloseable {
69
70     private static final String EXC_MSG_UNKNOWN_MODIFICATION_TYPE_WITHIN_DATA = "Unknown modification type within data ";
71
72     private final static SecurityRuleBuilder EIG_INGRESS_IPV4_SEC_RULE_BUILDER = new SecurityRuleBuilder()
73         .setUuid(new Uuid("0a629f80-2408-11e6-b67b-9e71128cae77"))
74         .setDirection(DirectionIngress.class)
75         .setEthertype(EthertypeV4.class)
76         .setSecurityGroupId(MappingUtils.EIG_UUID);
77     private final static SecurityRuleBuilder EIG_EGRESS_IPV4_SEC_RULE_BUILDER = new SecurityRuleBuilder()
78         .setUuid(new Uuid("0f1789be-2408-11e6-b67b-9e71128cae77"))
79         .setDirection(DirectionEgress.class)
80         .setEthertype(EthertypeV4.class)
81         .setSecurityGroupId(MappingUtils.EIG_UUID);
82     private final static SecurityRuleBuilder EIG_INGRESS_IPV6_SEC_RULE_BUILDER = new SecurityRuleBuilder()
83         .setUuid(new Uuid("139b7f90-2408-11e6-b67b-9e71128cae77"))
84         .setDirection(DirectionIngress.class)
85         .setEthertype(EthertypeV6.class)
86         .setSecurityGroupId(MappingUtils.EIG_UUID);
87     private final static SecurityRuleBuilder EIG_EGRESS_IPV6_SEC_RULE_BUILDER = new SecurityRuleBuilder()
88         .setUuid(new Uuid("17517202-2408-11e6-b67b-9e71128cae77"))
89         .setDirection(DirectionEgress.class)
90         .setEthertype(EthertypeV6.class)
91         .setSecurityGroupId(MappingUtils.EIG_UUID);
92     private final static SecurityGroupBuilder EIG_SEC_GROUP_BUILDER =
93             new SecurityGroupBuilder().setUuid(MappingUtils.EIG_UUID);
94
95     private final NeutronNetworkAware networkAware;
96     private final NeutronSecurityGroupAware securityGroupAware;
97     private final NeutronSecurityRuleAware securityRuleAware;
98     private final NeutronSubnetAware subnetAware;
99     private final NeutronPortAware portAware;
100     private final NeutronRouterAware routerAware;
101     private final NeutronFloatingIpAware floatingIpAware;
102
103     private final ListenerRegistration<NeutronMapper> registerDataTreeChangeListener;
104     private Neutron neutronBefore;
105     private Neutron neutronAfter;
106
107     public NeutronMapper(DataBroker dataProvider, EndpointService epService,
108             BaseEndpointService baseEpService) {
109         EndpointRegistrator epRegistrator = new EndpointRegistrator(epService, baseEpService);
110         networkAware = new NeutronNetworkAware(dataProvider);
111         securityGroupAware = new NeutronSecurityGroupAware(dataProvider);
112         securityRuleAware = new NeutronSecurityRuleAware(dataProvider);
113         subnetAware = new NeutronSubnetAware(dataProvider, epRegistrator);
114         portAware = new NeutronPortAware(dataProvider, epRegistrator);
115         routerAware = new NeutronRouterAware(dataProvider, epRegistrator);
116         floatingIpAware = new NeutronFloatingIpAware(dataProvider);
117         registerDataTreeChangeListener =
118                 dataProvider.registerDataTreeChangeListener(new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION,
119                         InstanceIdentifier.builder(Neutron.class).build()), this);
120     }
121
122     @Override
123     public void onDataTreeChanged(@Nonnull Collection<DataTreeModification<Neutron>> changes) {
124         for (DataTreeModification<Neutron> change : changes) {
125             DataObjectModification<Neutron> neutronModif = change.getRootNode();
126             resolveAndSetNeutron(neutronModif);
127             // network
128             List<DataObjectModification<Network>> networkModifs =
129                     findModifiedData(NeutronNetworkAware.NETWORK_WILDCARD_IID, neutronModif);
130             for (Uuid tenantFromCreatedRouterExternalNetwork : filterCreatedRouterExternalNetworksAndTransformToTenants(
131                     networkModifs)) {
132                 SecurityGroup eigSecGroup =
133                         EIG_SEC_GROUP_BUILDER.setTenantId(tenantFromCreatedRouterExternalNetwork).build();
134                 securityGroupAware.onCreated(eigSecGroup, neutronAfter);
135                 List<SecurityRule> eigSecRules = createEigSecurityRules(tenantFromCreatedRouterExternalNetwork);
136                 for (SecurityRule eigSecRule : eigSecRules) {
137                     securityRuleAware.onCreated(eigSecRule, neutronAfter);
138                 }
139             }
140             onDataObjectModification(networkModifs, networkAware);
141             // security group
142             List<DataObjectModification<SecurityGroup>> secGroupModifs =
143                     findModifiedData(NeutronSecurityGroupAware.SECURITY_GROUP_WILDCARD_IID, neutronModif);
144             onDataObjectModification(secGroupModifs, securityGroupAware);
145             // security rules
146             List<DataObjectModification<SecurityRule>> secRuleModifs =
147                     findModifiedData(NeutronSecurityRuleAware.SECURITY_RULE_WILDCARD_IID, neutronModif);
148             onDataObjectModification(secRuleModifs, securityRuleAware);
149             // subnet
150             List<DataObjectModification<Subnet>> subnetModifs = findModifiedData(NeutronSubnetAware.SUBNET_WILDCARD_IID, neutronModif);
151             onDataObjectModification(subnetModifs, subnetAware);
152             // port
153             List<DataObjectModification<Port>> portModifs = findModifiedData(NeutronPortAware.PORT_WILDCARD_IID, neutronModif);
154             onDataObjectModification(portModifs, portAware);
155             // router
156             List<DataObjectModification<Router>> routerModifs = findModifiedData(NeutronRouterAware.ROUTER_WILDCARD_IID, neutronModif);
157             onDataObjectModification(routerModifs, routerAware);
158             // floating IP
159             List<DataObjectModification<Floatingip>> floatingIpModifs = findModifiedData(NeutronFloatingIpAware.FLOATING_IP_WILDCARD_IID, neutronModif);
160             onDataObjectModification(floatingIpModifs, floatingIpAware);
161         }
162     }
163
164     private <T extends DataObject> void onDataObjectModification(List<DataObjectModification<T>> dataModifs,
165             NeutronAware<T> neutronAware) {
166         for (DataObjectModification<T> dataModif : dataModifs) {
167             final T dataBefore = dataModif.getDataBefore();
168             final T dataAfter = dataModif.getDataAfter();
169             if (dataBefore == null && dataAfter != null) {
170                 neutronAware.onCreated(dataAfter, neutronAfter);
171             }
172             else if (dataBefore != null && dataAfter != null) {
173                 neutronAware.onUpdated(dataBefore, dataAfter, neutronBefore, neutronAfter);
174             }
175             else if (dataBefore != null) {
176                 neutronAware.onDeleted(dataBefore, neutronBefore, neutronAfter);
177             }
178             else {
179                 throw new IllegalStateException(EXC_MSG_UNKNOWN_MODIFICATION_TYPE_WITHIN_DATA + dataModif);
180             }
181         }
182     }
183
184     private Set<Uuid> filterCreatedRouterExternalNetworksAndTransformToTenants(
185             List<DataObjectModification<Network>> modifiedNetworks) {
186         return FluentIterable.from(modifiedNetworks).filter(new Predicate<DataObjectModification<Network>>() {
187
188             @Override
189             public boolean apply(DataObjectModification<Network> modifiedNetwork) {
190                 return (ModificationType.WRITE == modifiedNetwork.getModificationType()
191                         && NetworkUtils.isRouterExternal(modifiedNetwork.getDataAfter()));
192             }
193         }).transform(new Function<DataObjectModification<Network>, Uuid>() {
194
195             @Override
196             public Uuid apply(DataObjectModification<Network> modifiedNetwork) {
197                 return modifiedNetwork.getDataAfter().getTenantId();
198             }
199         }).toSet();
200     }
201
202     private void resolveAndSetNeutron(DataObjectModification<Neutron> originalNeutron) {
203         Neutron oldNeutronBefore = originalNeutron.getDataBefore();
204         neutronBefore = resolveAndCreateNewNeutron(oldNeutronBefore);
205         Neutron oldNeutronAfter = originalNeutron.getDataAfter();
206         neutronAfter = resolveAndCreateNewNeutron(oldNeutronAfter);
207     }
208
209     private @Nullable Neutron resolveAndCreateNewNeutron(@Nullable Neutron originalNeutron) {
210         if (originalNeutron == null) {
211             return null;
212         }
213         NeutronBuilder newNeutronBuilder = new NeutronBuilder(originalNeutron);
214         resolveAndAddSecurityRulesAndGroups(originalNeutron, newNeutronBuilder);
215         return newNeutronBuilder.build();
216     }
217
218     private void resolveAndAddSecurityRulesAndGroups(Neutron originalNeutron, NeutronBuilder newNeutronBuilder) {
219         List<SecurityRule> eigSecRulesAndOriginalSecRules = new ArrayList<>();
220         List<SecurityGroup> eigSecGroupAndOriginalSecGroup = new ArrayList<>();
221         // resolve EIG sec rules and groups
222         List<Network> routerExternalNetworks = NetworkUtils.findRouterExternalNetworks(originalNeutron.getNetworks());
223         Set<Uuid> tenantsFromRouterExternalNetwork = resolveTenantsFromNetworks(routerExternalNetworks);
224         for (Uuid tenantFromRouterExternalNetwork : tenantsFromRouterExternalNetwork) {
225             eigSecRulesAndOriginalSecRules.addAll(createEigSecurityRules(tenantFromRouterExternalNetwork));
226             eigSecGroupAndOriginalSecGroup
227                 .add(EIG_SEC_GROUP_BUILDER.setTenantId(tenantFromRouterExternalNetwork).build());
228         }
229         // set new sec rules
230         SecurityRules newSecRules = null;
231         if (originalNeutron.getSecurityRules() != null) {
232             List<SecurityRule> originalSecRules = originalNeutron.getSecurityRules().getSecurityRule();
233             if (originalSecRules != null) {
234                 eigSecRulesAndOriginalSecRules.addAll(originalSecRules);
235             }
236             newSecRules = new SecurityRulesBuilder(originalNeutron.getSecurityRules())
237                 .setSecurityRule(eigSecRulesAndOriginalSecRules).build();
238         } else {
239             newSecRules = new SecurityRulesBuilder().setSecurityRule(eigSecRulesAndOriginalSecRules).build();
240         }
241         newNeutronBuilder.setSecurityRules(newSecRules);
242         // set new sec groups
243         SecurityGroups newSecGroups = null;
244         if (originalNeutron.getSecurityGroups() != null) {
245             List<SecurityGroup> originalSecGroups = originalNeutron.getSecurityGroups().getSecurityGroup();
246             if (originalSecGroups != null) {
247                 eigSecGroupAndOriginalSecGroup.addAll(originalSecGroups);
248             }
249             newSecGroups = new SecurityGroupsBuilder(originalNeutron.getSecurityGroups())
250                 .setSecurityGroup(eigSecGroupAndOriginalSecGroup).build();
251         } else {
252             newSecGroups = new SecurityGroupsBuilder().setSecurityGroup(eigSecGroupAndOriginalSecGroup).build();
253         }
254         newNeutronBuilder.setSecurityGroups(newSecGroups);
255     }
256
257     private Set<Uuid> resolveTenantsFromNetworks(List<Network> networks) {
258         return FluentIterable.from(networks).transform(new Function<Network, Uuid>() {
259
260             @Override
261             public Uuid apply(Network network) {
262                 return network.getTenantId();
263             }
264         }).toSet();
265     }
266
267     private List<SecurityRule> createEigSecurityRules(Uuid tenant) {
268         List<SecurityRule> eigSecRules = new ArrayList<>();
269         eigSecRules.add(EIG_INGRESS_IPV4_SEC_RULE_BUILDER.setTenantId(tenant).build());
270         eigSecRules.add(EIG_EGRESS_IPV4_SEC_RULE_BUILDER.setTenantId(tenant).build());
271         eigSecRules.add(EIG_INGRESS_IPV6_SEC_RULE_BUILDER.setTenantId(tenant).build());
272         eigSecRules.add(EIG_EGRESS_IPV6_SEC_RULE_BUILDER.setTenantId(tenant).build());
273         return eigSecRules;
274     }
275
276     /**
277      * Finds all modified subnodes of given type in {@link Neutron} node.
278      *
279      * @param <T>
280      * @param iid path to data in root node
281      * @param rootNode modified data of {@link Neutron} node
282      * @return {@link List} of modified subnodes
283      */
284     private <T extends DataObject> List<DataObjectModification<T>> findModifiedData(InstanceIdentifier<T> iid,
285             DataObjectModification<Neutron> rootNode) {
286         List<DataObjectModification<T>> modDtos = new ArrayList<>();
287         PeekingIterator<PathArgument> pathArgs = Iterators.peekingIterator(iid.getPathArguments().iterator());
288         DataObjectModification<? extends DataObject> modifDto = rootNode;
289         while (pathArgs.hasNext()) {
290             pathArgs.next();
291             for (DataObjectModification<? extends DataObject> childDto : modifDto.getModifiedChildren()) {
292                 if (pathArgs.hasNext() && childDto.getDataType().equals(pathArgs.peek().getType())) {
293                     if (childDto.getDataType().equals(iid.getTargetType())) {
294                         modDtos.add((DataObjectModification<T>) childDto);
295                     } else {
296                         modifDto = childDto;
297                         break;
298                     }
299                 }
300             }
301         }
302         return modDtos;
303     }
304
305     @Override
306     public void close() {
307         registerDataTreeChangeListener.close();
308     }
309
310 }