Neutron-mapper uses only DTOs from neutron.yang
[groupbasedpolicy.git] / neutron-mapper / src / main / java / org / opendaylight / groupbasedpolicy / neutron / mapper / NeutronMapper.java
index f514f00164b940a7dae148ab2ce836b2c5cfb608..ece7573cd272c1e04d7555b5294acf9babd63b0d 100644 (file)
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
-
 package org.opendaylight.groupbasedpolicy.neutron.mapper;
 
-import static com.google.common.base.Preconditions.checkNotNull;
-
+import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
+import java.util.Set;
+
+import javax.annotation.Nullable;
 
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RpcRegistration;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification.ModificationType;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.groupbasedpolicy.neutron.mapper.mapping.NeutronAware;
 import org.opendaylight.groupbasedpolicy.neutron.mapper.mapping.NeutronFloatingIpAware;
-import org.opendaylight.groupbasedpolicy.neutron.mapper.mapping.NeutronListener;
 import org.opendaylight.groupbasedpolicy.neutron.mapper.mapping.NeutronNetworkAware;
-import org.opendaylight.groupbasedpolicy.neutron.mapper.mapping.NeutronNetworkDao;
 import org.opendaylight.groupbasedpolicy.neutron.mapper.mapping.NeutronPortAware;
 import org.opendaylight.groupbasedpolicy.neutron.mapper.mapping.NeutronRouterAware;
+import org.opendaylight.groupbasedpolicy.neutron.mapper.mapping.NeutronSecurityGroupAware;
 import org.opendaylight.groupbasedpolicy.neutron.mapper.mapping.NeutronSubnetAware;
-import org.opendaylight.groupbasedpolicy.neutron.mapper.mapping.group.NeutronSecurityGroupAware;
-import org.opendaylight.groupbasedpolicy.neutron.mapper.mapping.group.SecGroupDao;
-import org.opendaylight.groupbasedpolicy.neutron.mapper.mapping.rule.NeutronGbpMapperServiceImpl;
 import org.opendaylight.groupbasedpolicy.neutron.mapper.mapping.rule.NeutronSecurityRuleAware;
-import org.opendaylight.groupbasedpolicy.neutron.mapper.mapping.rule.SecRuleDao;
+import org.opendaylight.groupbasedpolicy.neutron.mapper.util.MappingUtils;
+import org.opendaylight.groupbasedpolicy.neutron.mapper.util.NetworkUtils;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.EndpointService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.NeutronGbpMapperService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.floatingips.attributes.Floatingips;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.DirectionEgress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.DirectionIngress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.EthertypeV4;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.EthertypeV6;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.floatingips.attributes.floatingips.Floatingip;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.Routers;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.Router;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.Networks;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.NeutronBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.groups.attributes.SecurityGroups;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.groups.attributes.SecurityGroupsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.groups.attributes.security.groups.SecurityGroup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.groups.attributes.security.groups.SecurityGroupBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.rules.attributes.SecurityRules;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.rules.attributes.SecurityRulesBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.rules.attributes.security.rules.SecurityRule;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.Subnets;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.rules.attributes.security.rules.SecurityRuleBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.osgi.framework.ServiceRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
+
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.Iterators;
+import com.google.common.collect.PeekingIterator;
+
+public class NeutronMapper implements DataTreeChangeListener<Neutron>, AutoCloseable {
 
-public class NeutronMapper implements AutoCloseable {
+    private final static SecurityRuleBuilder EIG_INGRESS_IPV4_SEC_RULE_BUILDER = new SecurityRuleBuilder()
+        .setId(new Uuid("19b85ad2-bdfc-11e5-9912-ba0be0483c18"))
+        .setDirection(DirectionIngress.class)
+        .setEthertype(EthertypeV4.class)
+        .setSecurityGroupId(MappingUtils.EIG_UUID);
+    private final static SecurityRuleBuilder EIG_EGRESS_IPV4_SEC_RULE_BUILDER = new SecurityRuleBuilder()
+        .setId(new Uuid("19b85ad2-bdfc-11e5-9912-ba0be0483c18"))
+        .setDirection(DirectionEgress.class)
+        .setEthertype(EthertypeV4.class)
+        .setSecurityGroupId(MappingUtils.EIG_UUID);
+    private final static SecurityRuleBuilder EIG_INGRESS_IPV6_SEC_RULE_BUILDER = new SecurityRuleBuilder()
+        .setId(new Uuid("19b85ad2-bdfc-11e5-9912-ba0be0483c18"))
+        .setDirection(DirectionIngress.class)
+        .setEthertype(EthertypeV6.class)
+        .setSecurityGroupId(MappingUtils.EIG_UUID);
+    private final static SecurityRuleBuilder EIG_EGRESS_IPV6_SEC_RULE_BUILDER = new SecurityRuleBuilder()
+        .setId(new Uuid("19b85ad2-bdfc-11e5-9912-ba0be0483c18"))
+        .setDirection(DirectionEgress.class)
+        .setEthertype(EthertypeV6.class)
+        .setSecurityGroupId(MappingUtils.EIG_UUID);
+    private final static SecurityGroupBuilder EIG_SEC_GROUP_BUILDER =
+            new SecurityGroupBuilder().setUuid(MappingUtils.EIG_UUID).setDescription("EXTERNAL_group");
 
-    private final List<ServiceRegistration<?>> registrations = new ArrayList<ServiceRegistration<?>>();
-    private final DataBroker dataProvider;
-    private final RpcProviderRegistry providerRegistry;
-    private final EndpointService epService;
-    private RpcRegistration<NeutronGbpMapperService> rpcRegistration;
-    private NeutronListener neutronListener;
+    private final NeutronNetworkAware networkAware;
+    private final NeutronSecurityGroupAware securityGroupAware;
+    private final NeutronSecurityRuleAware securityRuleAware;
+    private final NeutronSubnetAware subnetAware;
+    private final NeutronPortAware portAware;
+    private final NeutronRouterAware routerAware;
+    private final NeutronFloatingIpAware floatingIpAware;
+
+    private final ListenerRegistration<NeutronMapper> registerDataTreeChangeListener;
+    private Neutron neutronBefore;
+    private Neutron neutronAfter;
 
     public NeutronMapper(DataBroker dataProvider, RpcProviderRegistry rpcProvider) {
-        this.dataProvider = checkNotNull(dataProvider);
-        this.providerRegistry = checkNotNull(rpcProvider);
-        this.epService = rpcProvider.getRpcService(EndpointService.class);
-        neutronListener = new NeutronListener(dataProvider);
-        registerAwareProviders();
+        EndpointService epService = rpcProvider.getRpcService(EndpointService.class);
+        EndpointRegistrator epRegistrator = new EndpointRegistrator(epService);
+        networkAware = new NeutronNetworkAware(dataProvider);
+        securityGroupAware = new NeutronSecurityGroupAware(dataProvider);
+        securityRuleAware = new NeutronSecurityRuleAware(dataProvider);
+        subnetAware = new NeutronSubnetAware(dataProvider, epRegistrator);
+        portAware = new NeutronPortAware(dataProvider, epRegistrator);
+        routerAware = new NeutronRouterAware(dataProvider, epRegistrator);
+        floatingIpAware = new NeutronFloatingIpAware(dataProvider);
+        registerDataTreeChangeListener =
+                dataProvider.registerDataTreeChangeListener(new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION,
+                        InstanceIdentifier.builder(Neutron.class).build()), this);
+    }
+
+    @Override
+    public void onDataTreeChanged(Collection<DataTreeModification<Neutron>> changes) {
+        for (DataTreeModification<Neutron> change : changes) {
+            DataObjectModification<Neutron> neutronModif = change.getRootNode();
+            resolveAndSetNeutron(neutronModif);
+            // network
+            List<DataObjectModification<Network>> networkModifs =
+                    findModifiedData(NeutronNetworkAware.NETWORK_WILDCARD_IID, neutronModif);
+            for (Uuid tenantFromCreatedRouterExternalNetwork : filterCreatedRouterExternalNetworksAndTransformToTenants(
+                    networkModifs)) {
+                SecurityGroup eigSecGroup =
+                        EIG_SEC_GROUP_BUILDER.setTenantId(tenantFromCreatedRouterExternalNetwork).build();
+                securityGroupAware.onCreated(eigSecGroup, neutronAfter);
+                List<SecurityRule> eigSecRules = createEigSecurityRules(tenantFromCreatedRouterExternalNetwork);
+                for (SecurityRule eigSecRule : eigSecRules) {
+                    securityRuleAware.onCreated(eigSecRule, neutronAfter);
+                }
+            }
+            onDataObjectModification(networkModifs, networkAware);
+            // security group
+            List<DataObjectModification<SecurityGroup>> secGroupModifs =
+                    findModifiedData(NeutronSecurityGroupAware.SECURITY_GROUP_WILDCARD_IID, neutronModif);
+            onDataObjectModification(secGroupModifs, securityGroupAware);
+            // security rules
+            List<DataObjectModification<SecurityRule>> secRuleModifs =
+                    findModifiedData(NeutronSecurityRuleAware.SECURITY_RULE_WILDCARD_IID, neutronModif);
+            onDataObjectModification(secRuleModifs, securityRuleAware);
+            // subnet
+            List<DataObjectModification<Subnet>> subnetModifs = findModifiedData(NeutronSubnetAware.SUBNET_WILDCARD_IID, neutronModif);
+            onDataObjectModification(subnetModifs, subnetAware);
+            // port
+            List<DataObjectModification<Port>> portModifs = findModifiedData(NeutronPortAware.PORT_WILDCARD_IID, neutronModif);
+            onDataObjectModification(portModifs, portAware);
+            // router
+            List<DataObjectModification<Router>> routerModifs = findModifiedData(NeutronRouterAware.ROUTER_WILDCARD_IID, neutronModif);
+            onDataObjectModification(routerModifs, routerAware);
+            // floating IP
+            List<DataObjectModification<Floatingip>> floatingIpModifs = findModifiedData(NeutronFloatingIpAware.FLOATING_IP_WILDCARD_IID, neutronModif);
+            onDataObjectModification(floatingIpModifs, floatingIpAware);
+        }
     }
 
-    private void registerAwareProviders() {
-        SecGroupDao secGroupDao = new SecGroupDao();
-        SecRuleDao secRuleDao = new SecRuleDao();
-        NeutronNetworkDao networkDao = new NeutronNetworkDao();
-        NeutronSecurityRuleAware securityRuleAware = new NeutronSecurityRuleAware(dataProvider, secRuleDao, secGroupDao);
-        NeutronSecurityGroupAware securityGroupAware = new NeutronSecurityGroupAware(dataProvider, securityRuleAware, secGroupDao);
-        neutronListener.registerMappingProviders(
-                InstanceIdentifier.builder(Neutron.class).child(Floatingips.class).child(Floatingip.class).build(),
-                new NeutronFloatingIpAware(dataProvider));
-        neutronListener.registerMappingProviders(
-                InstanceIdentifier.builder(Neutron.class).child(Ports.class).child(Port.class).build(),
-                new NeutronPortAware(dataProvider, epService, securityRuleAware, securityGroupAware));
-        neutronListener.registerMappingProviders(
-                InstanceIdentifier.builder(Neutron.class).child(Routers.class).child(Router.class).build(),
-                new NeutronRouterAware(dataProvider, epService));
-        neutronListener.registerMappingProviders(
-                InstanceIdentifier.builder(Neutron.class).child(SecurityRules.class).child(SecurityRule.class).build(),
-                securityRuleAware);
-        neutronListener.registerMappingProviders(
-                InstanceIdentifier.builder(Neutron.class).child(SecurityGroups.class).child(SecurityGroup.class).build(),
-                securityGroupAware);
-        neutronListener.registerMappingProviders(
-                InstanceIdentifier.builder(Neutron.class).child(Subnets.class).child(Subnet.class).build(),
-                new NeutronSubnetAware(dataProvider, networkDao));
-        neutronListener.registerMappingProviders(
-                InstanceIdentifier.builder(Neutron.class).child(Networks.class).child(Network.class).build(),
-                new NeutronNetworkAware(dataProvider, securityGroupAware, networkDao));
-        NeutronGbpMapperService neutronGbpMapperService = new NeutronGbpMapperServiceImpl(dataProvider, securityRuleAware);
-        rpcRegistration = providerRegistry.addRpcImplementation(NeutronGbpMapperService.class, neutronGbpMapperService);
+    private <T extends DataObject> void onDataObjectModification(List<DataObjectModification<T>> dataModifs,
+            NeutronAware<T> neutronAware) {
+        for (DataObjectModification<T> dataModif : dataModifs) {
+            switch (dataModif.getModificationType()) {
+                case DELETE:
+                    neutronAware.onDeleted(dataModif.getDataBefore(), neutronBefore, neutronAfter);
+                    break;
+                case SUBTREE_MODIFIED:
+                    neutronAware.onUpdated(dataModif.getDataBefore(), dataModif.getDataAfter(), neutronBefore,
+                            neutronAfter);
+                    break;
+                case WRITE:
+                    if (dataModif.getDataBefore() == null) {
+                        neutronAware.onCreated(dataModif.getDataAfter(), neutronAfter);
+                    } else {
+                        neutronAware.onUpdated(dataModif.getDataBefore(), dataModif.getDataAfter(), neutronBefore,
+                                neutronAfter);
+                    }
+                    break;
+                default:
+                    throw new IllegalStateException("Unknown modification type within data " + dataModif);
+            }
+        }
+    }
+
+    private Set<Uuid> filterCreatedRouterExternalNetworksAndTransformToTenants(
+            List<DataObjectModification<Network>> modifiedNetworks) {
+        return FluentIterable.from(modifiedNetworks).filter(new Predicate<DataObjectModification<Network>>() {
+
+            @Override
+            public boolean apply(DataObjectModification<Network> modifiedNetwork) {
+                return (ModificationType.WRITE == modifiedNetwork.getModificationType()
+                        && NetworkUtils.isRouterExternal(modifiedNetwork.getDataAfter()));
+            }
+        }).transform(new Function<DataObjectModification<Network>, Uuid>() {
+
+            @Override
+            public Uuid apply(DataObjectModification<Network> modifiedNetwork) {
+                return modifiedNetwork.getDataAfter().getTenantId();
+            }
+        }).toSet();
+    }
+
+    private void resolveAndSetNeutron(DataObjectModification<Neutron> originalNeutron) {
+        Neutron oldNeutronBefore = originalNeutron.getDataBefore();
+        neutronBefore = resolveAndCreateNewNeutron(oldNeutronBefore);
+        Neutron oldNeutronAfter = originalNeutron.getDataAfter();
+        neutronAfter = resolveAndCreateNewNeutron(oldNeutronAfter);
+    }
+
+    private @Nullable Neutron resolveAndCreateNewNeutron(@Nullable Neutron originalNeutron) {
+        if (originalNeutron == null) {
+            return null;
+        }
+        NeutronBuilder newNeutronBuilder = new NeutronBuilder(originalNeutron);
+        resolveAndAddSecurityRulesAndGroups(originalNeutron, newNeutronBuilder);
+        return newNeutronBuilder.build();
+    }
+
+    private void resolveAndAddSecurityRulesAndGroups(Neutron originalNeutron, NeutronBuilder newNeutronBuilder) {
+        List<SecurityRule> eigSecRulesAndOriginalSecRules = new ArrayList<>();
+        List<SecurityGroup> eigSecGroupAndOriginalSecGroup = new ArrayList<>();
+        // resolve EIG sec rules and groups
+        List<Network> routerExternalNetworks = NetworkUtils.findRouterExternalNetworks(originalNeutron.getNetworks());
+        Set<Uuid> tenantsFromRouterExternalNetwork = resolveTenantsFromNetworks(routerExternalNetworks);
+        for (Uuid tenantFromRouterExternalNetwork : tenantsFromRouterExternalNetwork) {
+            eigSecRulesAndOriginalSecRules.addAll(createEigSecurityRules(tenantFromRouterExternalNetwork));
+            eigSecGroupAndOriginalSecGroup
+                .add(EIG_SEC_GROUP_BUILDER.setTenantId(tenantFromRouterExternalNetwork).build());
+        }
+        // set new sec rules
+        SecurityRules newSecRules = null;
+        if (originalNeutron.getSecurityRules() != null) {
+            List<SecurityRule> originalSecRules = originalNeutron.getSecurityRules().getSecurityRule();
+            if (originalSecRules != null) {
+                eigSecRulesAndOriginalSecRules.addAll(originalSecRules);
+            }
+            newSecRules = new SecurityRulesBuilder(originalNeutron.getSecurityRules())
+                .setSecurityRule(eigSecRulesAndOriginalSecRules).build();
+        } else {
+            newSecRules = new SecurityRulesBuilder().setSecurityRule(eigSecRulesAndOriginalSecRules).build();
+        }
+        newNeutronBuilder.setSecurityRules(newSecRules);
+        // set new sec groups
+        SecurityGroups newSecGroups = null;
+        if (originalNeutron.getSecurityGroups() != null) {
+            List<SecurityGroup> originalSecGroups = originalNeutron.getSecurityGroups().getSecurityGroup();
+            if (originalSecGroups != null) {
+                eigSecGroupAndOriginalSecGroup.addAll(originalSecGroups);
+            }
+            newSecGroups = new SecurityGroupsBuilder(originalNeutron.getSecurityGroups())
+                .setSecurityGroup(eigSecGroupAndOriginalSecGroup).build();
+        } else {
+            newSecGroups = new SecurityGroupsBuilder().setSecurityGroup(eigSecGroupAndOriginalSecGroup).build();
+        }
+        newNeutronBuilder.setSecurityGroups(newSecGroups);
+    }
+
+    private Set<Uuid> resolveTenantsFromNetworks(List<Network> networks) {
+        return FluentIterable.from(networks).transform(new Function<Network, Uuid>() {
+
+            @Override
+            public Uuid apply(Network network) {
+                return network.getTenantId();
+            }
+        }).toSet();
+    }
+
+    private List<SecurityRule> createEigSecurityRules(Uuid tenant) {
+        List<SecurityRule> eigSecRules = new ArrayList<>();
+        eigSecRules.add(EIG_INGRESS_IPV4_SEC_RULE_BUILDER.setTenantId(tenant).build());
+        eigSecRules.add(EIG_EGRESS_IPV4_SEC_RULE_BUILDER.setTenantId(tenant).build());
+        eigSecRules.add(EIG_INGRESS_IPV6_SEC_RULE_BUILDER.setTenantId(tenant).build());
+        eigSecRules.add(EIG_EGRESS_IPV6_SEC_RULE_BUILDER.setTenantId(tenant).build());
+        return eigSecRules;
     }
 
     /**
-     * @see java.lang.AutoCloseable#close()
+     * Finds all modified subnodes of given type in {@link Neutron} node.
+     *
+     * @param <T>
+     * @param iid path to data in root node
+     * @param rootNode modified data of {@link Neutron} node
+     * @return {@link List} of modified subnodes
      */
-    @Override
-    public void close() throws Exception {
-        for (ServiceRegistration<?> registration : registrations) {
-            registration.unregister();
+    private <T extends DataObject> List<DataObjectModification<T>> findModifiedData(InstanceIdentifier<T> iid,
+            DataObjectModification<Neutron> rootNode) {
+        List<DataObjectModification<T>> modDtos = new ArrayList<>();
+        PeekingIterator<PathArgument> pathArgs = Iterators.peekingIterator(iid.getPathArguments().iterator());
+        DataObjectModification<? extends DataObject> modifDto = rootNode;
+        while (pathArgs.hasNext()) {
+            pathArgs.next();
+            for (DataObjectModification<? extends DataObject> childDto : modifDto.getModifiedChildren()) {
+                if (pathArgs.hasNext() && childDto.getDataType().equals(pathArgs.peek().getType())) {
+                    if (childDto.getDataType().equals(iid.getTargetType())) {
+                        modDtos.add((DataObjectModification<T>) childDto);
+                    } else {
+                        modifDto = childDto;
+                        break;
+                    }
+                }
+            }
         }
-        if (neutronListener != null) {
-            neutronListener.close();
-            neutronListener = null;
-        }
-        rpcRegistration.close();
+        return modDtos;
+    }
+
+    @Override
+    public void close() throws IOException {
+        registerDataTreeChangeListener.close();
     }
 
 }