Add subnet aware for vpp-mapper and vpp-renderer
[groupbasedpolicy.git] / neutron-vpp-mapper / src / main / java / org / opendaylight / groupbasedpolicy / neutron / vpp / mapper / processors / NeutronListener.java
1 /*\r
2  * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.\r
3  *\r
4  * This program and the accompanying materials are made available under the\r
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
6  * and is available at http://www.eclipse.org/legal/epl-v10.html\r
7  */\r
8 \r
9 package org.opendaylight.groupbasedpolicy.neutron.vpp.mapper.processors;\r
10 \r
11 import java.io.Closeable;\r
12 import java.util.ArrayList;\r
13 import java.util.Collection;\r
14 import java.util.LinkedHashSet;\r
15 import java.util.List;\r
16 import java.util.Set;\r
17 import java.util.concurrent.ExecutionException;\r
18 \r
19 import org.opendaylight.controller.md.sal.binding.api.ClusteredDataTreeChangeListener;\r
20 import org.opendaylight.controller.md.sal.binding.api.DataBroker;\r
21 import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;\r
22 import org.opendaylight.controller.md.sal.binding.api.DataObjectModification.ModificationType;\r
23 import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;\r
24 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;\r
25 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;\r
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;\r
27 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;\r
28 import org.opendaylight.yangtools.concepts.ListenerRegistration;\r
29 import org.opendaylight.yangtools.yang.binding.DataObject;\r
30 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;\r
31 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;\r
32 import org.slf4j.Logger;\r
33 import org.slf4j.LoggerFactory;\r
34 \r
35 import com.google.common.annotations.VisibleForTesting;\r
36 import com.google.common.collect.Iterators;\r
37 import com.google.common.collect.PeekingIterator;\r
38 \r
39 public class NeutronListener implements ClusteredDataTreeChangeListener<Neutron>, Closeable {\r
40 \r
41     private static final Logger LOG = LoggerFactory.getLogger(NeutronListener.class);\r
42 \r
43     private final Set<MappingProvider<? extends DataObject>> dataChangeProviders = new LinkedHashSet<>();\r
44     protected ListenerRegistration<NeutronListener> registeredListener;\r
45 \r
46     public NeutronListener(DataBroker dataBroker, NodeId routingNode) {\r
47         LOG.info("Routing node chosen in ODL is {}", routingNode);\r
48         registerHandlersAndListeners(dataBroker, routingNode);\r
49         registeredListener = dataBroker.registerDataTreeChangeListener(new DataTreeIdentifier<>(\r
50                 LogicalDatastoreType.CONFIGURATION, InstanceIdentifier.builder(Neutron.class).build()), this);\r
51     }\r
52 \r
53     private void registerHandlersAndListeners(DataBroker dataBroker, NodeId routingNode) {\r
54         PortHandler portHandler = new PortHandler(dataBroker, routingNode);\r
55         dataChangeProviders.add(new PortAware(portHandler, dataBroker));\r
56         dataChangeProviders.add(new NetworkAware(dataBroker));\r
57         dataChangeProviders.add(new SubnetAware(dataBroker));\r
58     }\r
59 \r
60     @Override\r
61     public void onDataTreeChanged(Collection<DataTreeModification<Neutron>> changes) {\r
62         for (DataTreeModification<Neutron> change : changes) {\r
63             DataObjectModification<Neutron> rootNode = change.getRootNode();\r
64             for (MappingProvider<? extends DataObject> provider : dataChangeProviders) {\r
65                 for (DataObjectModification<? extends DataObject> modDto : findModifiedData(provider, rootNode)) {\r
66                     try {\r
67                         processChangedData(modDto, modDto.getModificationType(), provider);\r
68                     } catch (InterruptedException | ExecutionException e) {\r
69                         LOG.error("Failed to process {} modification of node: {}. {}", modDto.getModificationType(),\r
70                                 modDto.getIdentifier(), e.getStackTrace());\r
71                     }\r
72                 }\r
73             }\r
74         }\r
75     }\r
76 \r
77     List<DataObjectModification<? extends DataObject>> findModifiedData(MappingProvider<? extends DataObject> provider,\r
78             DataObjectModification<Neutron> rootNode) {\r
79         List<DataObjectModification<? extends DataObject>> modDtos = new ArrayList<>();\r
80         PeekingIterator<PathArgument> pathArgs = Iterators.peekingIterator(provider.getNeutronDtoIid()\r
81             .getPathArguments()\r
82             .iterator());\r
83         DataObjectModification<? extends DataObject> modifDto = rootNode;\r
84         while (pathArgs.hasNext()) {\r
85             pathArgs.next();\r
86             for (DataObjectModification<? extends DataObject> childDto : modifDto.getModifiedChildren()) {\r
87                 if (pathArgs.hasNext() && childDto.getDataType().equals(pathArgs.peek().getType())) {\r
88                     if (childDto.getDataType().equals(provider.getNeutronDtoIid().getTargetType())) {\r
89                         modDtos.add(childDto);\r
90                     } else {\r
91                         modifDto = childDto;\r
92                         break;\r
93                     }\r
94                 }\r
95             }\r
96         }\r
97         return modDtos;\r
98     }\r
99 \r
100     @SuppressWarnings("unchecked")\r
101     <T extends DataObject> void processChangedData(DataObjectModification<?> dto, ModificationType m,\r
102             MappingProvider<T> processor) throws InterruptedException, ExecutionException {\r
103         switch (m) {\r
104             case WRITE: {\r
105                 if (dto.getDataBefore() != null) {\r
106                     processor.processUpdatedNeutronDto((T) dto.getDataBefore(), (T) dto.getDataAfter());\r
107                 } else {\r
108                     processor.processCreatedNeutronDto((T) dto.getDataAfter());\r
109                 }\r
110                 break;\r
111             }\r
112             case SUBTREE_MODIFIED: {\r
113                 processor.processUpdatedNeutronDto((T) dto.getDataBefore(), (T) dto.getDataAfter());\r
114                 break;\r
115             }\r
116             case DELETE: {\r
117                 processor.processDeletedNeutronDto((T) dto.getDataBefore());\r
118                 break;\r
119             }\r
120         }\r
121     }\r
122 \r
123     @VisibleForTesting\r
124     void clearDataChangeProviders() {\r
125         dataChangeProviders.clear();\r
126     }\r
127 \r
128     @VisibleForTesting\r
129     <T extends DataObject> void addDataChangeProvider(MappingProvider<T> t) {\r
130         dataChangeProviders.add(t);\r
131     }\r
132 \r
133     @Override\r
134     public void close() {\r
135         registeredListener.close();\r
136     }\r
137 }\r