2 * Copyright (c) 2015 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
8 package org.opendaylight.groupbasedpolicy.neutron.mapper;
10 import java.io.IOException;
11 import java.util.ArrayList;
12 import java.util.Collection;
13 import java.util.List;
16 import javax.annotation.Nullable;
18 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
19 import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
20 import org.opendaylight.controller.md.sal.binding.api.DataObjectModification.ModificationType;
21 import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
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.controller.sal.binding.api.RpcProviderRegistry;
26 import org.opendaylight.groupbasedpolicy.neutron.mapper.mapping.NeutronAware;
27 import org.opendaylight.groupbasedpolicy.neutron.mapper.mapping.NeutronFloatingIpAware;
28 import org.opendaylight.groupbasedpolicy.neutron.mapper.mapping.NeutronNetworkAware;
29 import org.opendaylight.groupbasedpolicy.neutron.mapper.mapping.NeutronPortAware;
30 import org.opendaylight.groupbasedpolicy.neutron.mapper.mapping.NeutronRouterAware;
31 import org.opendaylight.groupbasedpolicy.neutron.mapper.mapping.NeutronSecurityGroupAware;
32 import org.opendaylight.groupbasedpolicy.neutron.mapper.mapping.NeutronSubnetAware;
33 import org.opendaylight.groupbasedpolicy.neutron.mapper.mapping.rule.NeutronSecurityRuleAware;
34 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.MappingUtils;
35 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.NetworkUtils;
36 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.BaseEndpointService;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.EndpointService;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.DirectionEgress;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.DirectionIngress;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.EthertypeV4;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.EthertypeV6;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.floatingips.attributes.floatingips.Floatingip;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.Router;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.NeutronBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.groups.attributes.SecurityGroups;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.groups.attributes.SecurityGroupsBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.groups.attributes.security.groups.SecurityGroup;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.groups.attributes.security.groups.SecurityGroupBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.rules.attributes.SecurityRules;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.rules.attributes.SecurityRulesBuilder;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.rules.attributes.security.rules.SecurityRule;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.rules.attributes.security.rules.SecurityRuleBuilder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
58 import org.opendaylight.yangtools.concepts.ListenerRegistration;
59 import org.opendaylight.yangtools.yang.binding.DataObject;
60 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
61 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
63 import com.google.common.base.Function;
64 import com.google.common.base.Predicate;
65 import com.google.common.collect.FluentIterable;
66 import com.google.common.collect.Iterators;
67 import com.google.common.collect.PeekingIterator;
69 public class NeutronMapper implements DataTreeChangeListener<Neutron>, AutoCloseable {
71 private final static SecurityRuleBuilder EIG_INGRESS_IPV4_SEC_RULE_BUILDER = new SecurityRuleBuilder()
72 .setId(new Uuid("19b85ad2-bdfc-11e5-9912-ba0be0483c18"))
73 .setDirection(DirectionIngress.class)
74 .setEthertype(EthertypeV4.class)
75 .setSecurityGroupId(MappingUtils.EIG_UUID);
76 private final static SecurityRuleBuilder EIG_EGRESS_IPV4_SEC_RULE_BUILDER = new SecurityRuleBuilder()
77 .setId(new Uuid("19b85ad2-bdfc-11e5-9912-ba0be0483c18"))
78 .setDirection(DirectionEgress.class)
79 .setEthertype(EthertypeV4.class)
80 .setSecurityGroupId(MappingUtils.EIG_UUID);
81 private final static SecurityRuleBuilder EIG_INGRESS_IPV6_SEC_RULE_BUILDER = new SecurityRuleBuilder()
82 .setId(new Uuid("19b85ad2-bdfc-11e5-9912-ba0be0483c18"))
83 .setDirection(DirectionIngress.class)
84 .setEthertype(EthertypeV6.class)
85 .setSecurityGroupId(MappingUtils.EIG_UUID);
86 private final static SecurityRuleBuilder EIG_EGRESS_IPV6_SEC_RULE_BUILDER = new SecurityRuleBuilder()
87 .setId(new Uuid("19b85ad2-bdfc-11e5-9912-ba0be0483c18"))
88 .setDirection(DirectionEgress.class)
89 .setEthertype(EthertypeV6.class)
90 .setSecurityGroupId(MappingUtils.EIG_UUID);
91 private final static SecurityGroupBuilder EIG_SEC_GROUP_BUILDER =
92 new SecurityGroupBuilder().setUuid(MappingUtils.EIG_UUID).setDescription("EXTERNAL_group");
94 private final NeutronNetworkAware networkAware;
95 private final NeutronSecurityGroupAware securityGroupAware;
96 private final NeutronSecurityRuleAware securityRuleAware;
97 private final NeutronSubnetAware subnetAware;
98 private final NeutronPortAware portAware;
99 private final NeutronRouterAware routerAware;
100 private final NeutronFloatingIpAware floatingIpAware;
102 private final ListenerRegistration<NeutronMapper> registerDataTreeChangeListener;
103 private Neutron neutronBefore;
104 private Neutron neutronAfter;
106 public NeutronMapper(DataBroker dataProvider, RpcProviderRegistry rpcProvider) {
107 EndpointService epService = rpcProvider.getRpcService(EndpointService.class);
108 BaseEndpointService baseEpService = rpcProvider.getRpcService(BaseEndpointService.class);
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);
123 public void onDataTreeChanged(Collection<DataTreeModification<Neutron>> changes) {
124 for (DataTreeModification<Neutron> change : changes) {
125 DataObjectModification<Neutron> neutronModif = change.getRootNode();
126 resolveAndSetNeutron(neutronModif);
128 List<DataObjectModification<Network>> networkModifs =
129 findModifiedData(NeutronNetworkAware.NETWORK_WILDCARD_IID, neutronModif);
130 for (Uuid tenantFromCreatedRouterExternalNetwork : filterCreatedRouterExternalNetworksAndTransformToTenants(
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);
140 onDataObjectModification(networkModifs, networkAware);
142 List<DataObjectModification<SecurityGroup>> secGroupModifs =
143 findModifiedData(NeutronSecurityGroupAware.SECURITY_GROUP_WILDCARD_IID, neutronModif);
144 onDataObjectModification(secGroupModifs, securityGroupAware);
146 List<DataObjectModification<SecurityRule>> secRuleModifs =
147 findModifiedData(NeutronSecurityRuleAware.SECURITY_RULE_WILDCARD_IID, neutronModif);
148 onDataObjectModification(secRuleModifs, securityRuleAware);
150 List<DataObjectModification<Subnet>> subnetModifs = findModifiedData(NeutronSubnetAware.SUBNET_WILDCARD_IID, neutronModif);
151 onDataObjectModification(subnetModifs, subnetAware);
153 List<DataObjectModification<Port>> portModifs = findModifiedData(NeutronPortAware.PORT_WILDCARD_IID, neutronModif);
154 onDataObjectModification(portModifs, portAware);
156 List<DataObjectModification<Router>> routerModifs = findModifiedData(NeutronRouterAware.ROUTER_WILDCARD_IID, neutronModif);
157 onDataObjectModification(routerModifs, routerAware);
159 List<DataObjectModification<Floatingip>> floatingIpModifs = findModifiedData(NeutronFloatingIpAware.FLOATING_IP_WILDCARD_IID, neutronModif);
160 onDataObjectModification(floatingIpModifs, floatingIpAware);
164 private <T extends DataObject> void onDataObjectModification(List<DataObjectModification<T>> dataModifs,
165 NeutronAware<T> neutronAware) {
166 for (DataObjectModification<T> dataModif : dataModifs) {
167 switch (dataModif.getModificationType()) {
169 neutronAware.onDeleted(dataModif.getDataBefore(), neutronBefore, neutronAfter);
171 case SUBTREE_MODIFIED:
172 neutronAware.onUpdated(dataModif.getDataBefore(), dataModif.getDataAfter(), neutronBefore,
176 if (dataModif.getDataBefore() == null) {
177 neutronAware.onCreated(dataModif.getDataAfter(), neutronAfter);
179 neutronAware.onUpdated(dataModif.getDataBefore(), dataModif.getDataAfter(), neutronBefore,
184 throw new IllegalStateException("Unknown modification type within data " + dataModif);
189 private Set<Uuid> filterCreatedRouterExternalNetworksAndTransformToTenants(
190 List<DataObjectModification<Network>> modifiedNetworks) {
191 return FluentIterable.from(modifiedNetworks).filter(new Predicate<DataObjectModification<Network>>() {
194 public boolean apply(DataObjectModification<Network> modifiedNetwork) {
195 return (ModificationType.WRITE == modifiedNetwork.getModificationType()
196 && NetworkUtils.isRouterExternal(modifiedNetwork.getDataAfter()));
198 }).transform(new Function<DataObjectModification<Network>, Uuid>() {
201 public Uuid apply(DataObjectModification<Network> modifiedNetwork) {
202 return modifiedNetwork.getDataAfter().getTenantId();
207 private void resolveAndSetNeutron(DataObjectModification<Neutron> originalNeutron) {
208 Neutron oldNeutronBefore = originalNeutron.getDataBefore();
209 neutronBefore = resolveAndCreateNewNeutron(oldNeutronBefore);
210 Neutron oldNeutronAfter = originalNeutron.getDataAfter();
211 neutronAfter = resolveAndCreateNewNeutron(oldNeutronAfter);
214 private @Nullable Neutron resolveAndCreateNewNeutron(@Nullable Neutron originalNeutron) {
215 if (originalNeutron == null) {
218 NeutronBuilder newNeutronBuilder = new NeutronBuilder(originalNeutron);
219 resolveAndAddSecurityRulesAndGroups(originalNeutron, newNeutronBuilder);
220 return newNeutronBuilder.build();
223 private void resolveAndAddSecurityRulesAndGroups(Neutron originalNeutron, NeutronBuilder newNeutronBuilder) {
224 List<SecurityRule> eigSecRulesAndOriginalSecRules = new ArrayList<>();
225 List<SecurityGroup> eigSecGroupAndOriginalSecGroup = new ArrayList<>();
226 // resolve EIG sec rules and groups
227 List<Network> routerExternalNetworks = NetworkUtils.findRouterExternalNetworks(originalNeutron.getNetworks());
228 Set<Uuid> tenantsFromRouterExternalNetwork = resolveTenantsFromNetworks(routerExternalNetworks);
229 for (Uuid tenantFromRouterExternalNetwork : tenantsFromRouterExternalNetwork) {
230 eigSecRulesAndOriginalSecRules.addAll(createEigSecurityRules(tenantFromRouterExternalNetwork));
231 eigSecGroupAndOriginalSecGroup
232 .add(EIG_SEC_GROUP_BUILDER.setTenantId(tenantFromRouterExternalNetwork).build());
235 SecurityRules newSecRules = null;
236 if (originalNeutron.getSecurityRules() != null) {
237 List<SecurityRule> originalSecRules = originalNeutron.getSecurityRules().getSecurityRule();
238 if (originalSecRules != null) {
239 eigSecRulesAndOriginalSecRules.addAll(originalSecRules);
241 newSecRules = new SecurityRulesBuilder(originalNeutron.getSecurityRules())
242 .setSecurityRule(eigSecRulesAndOriginalSecRules).build();
244 newSecRules = new SecurityRulesBuilder().setSecurityRule(eigSecRulesAndOriginalSecRules).build();
246 newNeutronBuilder.setSecurityRules(newSecRules);
247 // set new sec groups
248 SecurityGroups newSecGroups = null;
249 if (originalNeutron.getSecurityGroups() != null) {
250 List<SecurityGroup> originalSecGroups = originalNeutron.getSecurityGroups().getSecurityGroup();
251 if (originalSecGroups != null) {
252 eigSecGroupAndOriginalSecGroup.addAll(originalSecGroups);
254 newSecGroups = new SecurityGroupsBuilder(originalNeutron.getSecurityGroups())
255 .setSecurityGroup(eigSecGroupAndOriginalSecGroup).build();
257 newSecGroups = new SecurityGroupsBuilder().setSecurityGroup(eigSecGroupAndOriginalSecGroup).build();
259 newNeutronBuilder.setSecurityGroups(newSecGroups);
262 private Set<Uuid> resolveTenantsFromNetworks(List<Network> networks) {
263 return FluentIterable.from(networks).transform(new Function<Network, Uuid>() {
266 public Uuid apply(Network network) {
267 return network.getTenantId();
272 private List<SecurityRule> createEigSecurityRules(Uuid tenant) {
273 List<SecurityRule> eigSecRules = new ArrayList<>();
274 eigSecRules.add(EIG_INGRESS_IPV4_SEC_RULE_BUILDER.setTenantId(tenant).build());
275 eigSecRules.add(EIG_EGRESS_IPV4_SEC_RULE_BUILDER.setTenantId(tenant).build());
276 eigSecRules.add(EIG_INGRESS_IPV6_SEC_RULE_BUILDER.setTenantId(tenant).build());
277 eigSecRules.add(EIG_EGRESS_IPV6_SEC_RULE_BUILDER.setTenantId(tenant).build());
282 * Finds all modified subnodes of given type in {@link Neutron} node.
285 * @param iid path to data in root node
286 * @param rootNode modified data of {@link Neutron} node
287 * @return {@link List} of modified subnodes
289 private <T extends DataObject> List<DataObjectModification<T>> findModifiedData(InstanceIdentifier<T> iid,
290 DataObjectModification<Neutron> rootNode) {
291 List<DataObjectModification<T>> modDtos = new ArrayList<>();
292 PeekingIterator<PathArgument> pathArgs = Iterators.peekingIterator(iid.getPathArguments().iterator());
293 DataObjectModification<? extends DataObject> modifDto = rootNode;
294 while (pathArgs.hasNext()) {
296 for (DataObjectModification<? extends DataObject> childDto : modifDto.getModifiedChildren()) {
297 if (pathArgs.hasNext() && childDto.getDataType().equals(pathArgs.peek().getType())) {
298 if (childDto.getDataType().equals(iid.getTargetType())) {
299 modDtos.add((DataObjectModification<T>) childDto);
311 public void close() throws IOException {
312 registerDataTreeChangeListener.close();