2 * Copyright (c) 2016 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
9 package org.opendaylight.groupbasedpolicy.ne.location.provider;
11 import java.util.ArrayList;
12 import java.util.Collection;
13 import java.util.Collections;
14 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.DataTreeChangeListener;
21 import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
22 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
23 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
24 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
25 import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
26 import org.opendaylight.groupbasedpolicy.util.IidFactory;
27 import org.opendaylight.groupbasedpolicy.util.NetUtils;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpoint;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.AbsoluteLocation;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.AbsoluteLocationBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.location.type.ExternalLocationCaseBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.network.elements.rev160407.NetworkElements;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.network.elements.rev160407.NetworkElementsBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.network.elements.rev160407.network.elements.NetworkElement;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.network.elements.rev160407.network.elements.network.element.Interface;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.network.elements.rev160407.network.elements.network.element._interface.EndpointNetwork;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.IpPrefixType;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.L3Context;
40 import org.opendaylight.yangtools.concepts.ListenerRegistration;
41 import org.opendaylight.yangtools.yang.binding.DataObject;
42 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
46 import com.google.common.annotations.VisibleForTesting;
48 public class NeLocationProvider implements DataTreeChangeListener<NetworkElements>, AutoCloseable {
50 private static final Logger LOG = LoggerFactory.getLogger(NeLocationProvider.class);
51 public static final String NE_LOCATION_PROVIDER_NAME = "ne-location-provider";
53 private List<AddressEndpoint> endpoints;
54 private NetworkElements networkElements;
55 private DataBroker dataBroker;
56 private ListenerRegistration<NeLocationProvider> listenerRegistration;
57 private EndpointsListener endpointsListener;
59 public NeLocationProvider(DataBroker dataBroker) {
60 this.listenerRegistration =
61 dataBroker.registerDataTreeChangeListener(new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION,
62 InstanceIdentifier.builder(NetworkElements.class).build()), this);
63 this.endpoints = new ArrayList<>();
64 this.networkElements = new NetworkElementsBuilder().build();
65 this.dataBroker = dataBroker;
66 this.endpointsListener = new EndpointsListener(dataBroker, this);
67 LOG.info("NE location provider created");
72 this.listenerRegistration.close();
73 this.endpointsListener.close();
76 public synchronized void onEndpointsChange(Collection<DataTreeModification<AddressEndpoint>> changes) {
77 WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
78 for (DataTreeModification<AddressEndpoint> change : changes) {
79 switch (change.getRootNode().getModificationType()) {
81 AddressEndpoint endpoint = change.getRootNode().getDataBefore();
82 removeLocationForEndpoint(endpoint, wtx);
83 this.endpoints.remove(endpoint);
87 AddressEndpoint endpoint = change.getRootNode().getDataBefore();
88 if (endpoint != null) {
89 this.endpoints.remove(endpoint);
90 this.endpoints.add(change.getRootNode().getDataAfter());
93 endpoint = change.getRootNode().getDataAfter();
94 createLocationForEndpoint(endpoint, wtx);
95 this.endpoints.add(endpoint);
98 case SUBTREE_MODIFIED: {
99 this.endpoints.remove(change.getRootNode().getDataBefore());
100 this.endpoints.add(change.getRootNode().getDataAfter());
105 DataStoreHelper.submitToDs(wtx);
108 private void createLocationForEndpoint(AddressEndpoint endpoint, WriteTransaction wtx) {
109 for (NetworkElement ne : nullToEmpty(networkElements.getNetworkElement())) {
110 for (Interface iface : nullToEmpty(ne.getInterface())) {
111 for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
112 if (endpoint.getContextType().isAssignableFrom(L3Context.class)
113 && endpoint.getContextId().equals(en.getL3ContextId())
114 && endpoint.getAddressType().isAssignableFrom(IpPrefixType.class) && NetUtils
115 .samePrefix(new IpPrefix(endpoint.getAddress().toCharArray()), en.getIpPrefix())) {
116 InstanceIdentifier<AbsoluteLocation> iid = IidFactory
117 .providerAddressEndpointLocationIid(NE_LOCATION_PROVIDER_NAME, IpPrefixType.class,
118 endpoint.getAddress(), endpoint.getContextType(), endpoint.getContextId())
119 .child(AbsoluteLocation.class);
120 wtx.put(LogicalDatastoreType.CONFIGURATION, iid, createRealLocation(ne.getIid(), iface.getIid()),
122 LOG.debug("New location created for endpoint {}", endpoint);
130 private void removeLocationForEndpoint(AddressEndpoint endpoint, WriteTransaction wtx) {
131 for (NetworkElement ne : nullToEmpty(networkElements.getNetworkElement())) {
132 for (Interface iface : nullToEmpty(ne.getInterface())) {
133 for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
134 if (endpoint.getContextType().isAssignableFrom(L3Context.class)
135 && endpoint.getContextId().equals(en.getL3ContextId())
136 && endpoint.getAddressType().isAssignableFrom(IpPrefixType.class) && NetUtils
137 .samePrefix(new IpPrefix(endpoint.getAddress().toCharArray()), en.getIpPrefix())) {
138 InstanceIdentifier<AbsoluteLocation> iid = IidFactory
139 .providerAddressEndpointLocationIid(NE_LOCATION_PROVIDER_NAME, IpPrefixType.class,
140 endpoint.getAddress(), endpoint.getContextType(), endpoint.getContextId())
141 .child(AbsoluteLocation.class);
142 wtx.delete(LogicalDatastoreType.CONFIGURATION, iid);
143 LOG.debug("Location deleted for endpoint {}", endpoint);
152 public synchronized void onDataTreeChanged(Collection<DataTreeModification<NetworkElements>> changes) {
153 WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
154 for (DataTreeModification<NetworkElements> change : changes) {
155 switch (change.getRootNode().getModificationType()) {
157 NetworkElements nes = change.getRootNode().getDataBefore();
158 for (NetworkElement ne : nullToEmpty(nes.getNetworkElement())) {
159 for (Interface iface : nullToEmpty(ne.getInterface())) {
160 for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
161 processDeletedEN(en, wtx);
165 networkElements = new NetworkElementsBuilder().build();
166 LOG.debug("Network elements removed");
170 NetworkElements nes = change.getRootNode().getDataBefore();
172 for (NetworkElement ne : nullToEmpty(nes.getNetworkElement())) {
173 for (Interface iface : nullToEmpty(ne.getInterface())) {
174 for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
175 processDeletedEN(en, wtx);
180 nes = change.getRootNode().getDataAfter();
181 for (NetworkElement ne : nullToEmpty(nes.getNetworkElement())) {
182 for (Interface iface : nullToEmpty(ne.getInterface())) {
183 for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
184 processCreatedEN(en, ne.getIid(), iface.getIid(), wtx);
188 networkElements = nes;
189 LOG.debug("New Network elements created {}", change.getRootNode().getDataAfter());
192 case SUBTREE_MODIFIED: {
193 List<DataObjectModification<NetworkElement>> modifiedNetworkElements =
194 getModifiedNetworkElements(change.getRootNode());
195 for (DataObjectModification<NetworkElement> netElement : modifiedNetworkElements) {
196 processNetworkElementChange(netElement, wtx);
202 DataStoreHelper.submitToDs(wtx);
205 private List<DataObjectModification<NetworkElement>> getModifiedNetworkElements(
206 DataObjectModification<NetworkElements> modifiedNEs) {
207 Collection<DataObjectModification<? extends DataObject>> potentialModifiedNetworkElements =
208 modifiedNEs.getModifiedChildren();
209 if (potentialModifiedNetworkElements == null) {
210 return Collections.emptyList();
212 List<DataObjectModification<NetworkElement>> nes = new ArrayList<>();
213 for (DataObjectModification<? extends DataObject> potentialModifiedNetworkElement : potentialModifiedNetworkElements) {
214 if (potentialModifiedNetworkElement.getDataType().isAssignableFrom(NetworkElement.class)) {
215 nes.add((DataObjectModification<NetworkElement>) potentialModifiedNetworkElement);
221 private void processNetworkElementChange(DataObjectModification<NetworkElement> netElement, WriteTransaction wtx) {
222 switch (netElement.getModificationType()) {
224 NetworkElement ne = netElement.getDataBefore();
225 for (Interface iface : nullToEmpty(ne.getInterface())) {
226 for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
227 processDeletedEN(en, wtx);
230 networkElements.getNetworkElement().remove(ne);
231 LOG.debug("Netowrk element {} removed", netElement.getDataBefore());
235 NetworkElement ne = netElement.getDataBefore();
237 for (Interface iface : nullToEmpty(ne.getInterface())) {
238 for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
239 processDeletedEN(en, wtx);
242 networkElements.getNetworkElement().remove(ne);
244 ne = netElement.getDataAfter();
245 for (Interface iface : nullToEmpty(ne.getInterface())) {
246 for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
247 processCreatedEN(en, ne.getIid(), iface.getIid(), wtx);
250 networkElements.getNetworkElement().add(ne);
251 LOG.debug("Created new Network element {}", netElement.getDataAfter());
254 case SUBTREE_MODIFIED: {
255 List<DataObjectModification<Interface>> modifiedInterfaces = getModifiedInterfaces(netElement);
256 for (DataObjectModification<Interface> modifiedInterface : modifiedInterfaces) {
257 processInterfaceChange(modifiedInterface, netElement.getDataBefore(), wtx);
264 private List<DataObjectModification<Interface>> getModifiedInterfaces(
265 DataObjectModification<NetworkElement> netElement) {
266 Collection<DataObjectModification<? extends DataObject>> potentialModifiedInterfaces =
267 netElement.getModifiedChildren();
268 if (potentialModifiedInterfaces == null) {
269 return Collections.emptyList();
271 List<DataObjectModification<Interface>> interfaces = new ArrayList<>();
272 for (DataObjectModification<? extends DataObject> potentialModifiedInterface : potentialModifiedInterfaces) {
273 if (potentialModifiedInterface.getDataType().isAssignableFrom(Interface.class)) {
274 interfaces.add((DataObjectModification<Interface>) potentialModifiedInterface);
280 private void processInterfaceChange(DataObjectModification<Interface> modifiedInterface,
281 NetworkElement nodeBefore, WriteTransaction wtx) {
282 switch (modifiedInterface.getModificationType()) {
284 Interface iface = modifiedInterface.getDataBefore();
285 for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
286 processDeletedEN(en, wtx);
288 int nodeIndex = getIndexOf(nodeBefore);
289 networkElements.getNetworkElement().get(nodeIndex).getInterface().remove(iface);
290 LOG.debug("Interface {} removed", modifiedInterface.getDataBefore());
294 Interface iface = modifiedInterface.getDataBefore();
295 int nodeIndex = getIndexOf(nodeBefore);
297 for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
298 processDeletedEN(en, wtx);
300 networkElements.getNetworkElement().get(nodeIndex).getInterface().remove(iface);
302 iface = modifiedInterface.getDataAfter();
303 for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
304 processCreatedEN(en, nodeBefore.getIid(), iface.getIid(), wtx);
306 networkElements.getNetworkElement().get(nodeIndex).getInterface().add(iface);
307 LOG.debug("Created new Interface {}", modifiedInterface.getDataAfter());
310 case SUBTREE_MODIFIED: {
311 List<DataObjectModification<EndpointNetwork>> modifiedENs =
312 getModifiedEndpointNetworks(modifiedInterface);
313 for (DataObjectModification<EndpointNetwork> modifiedEN : modifiedENs) {
314 processEndpointNetworkChange(modifiedEN, nodeBefore, modifiedInterface.getDataBefore(), wtx);
321 private List<DataObjectModification<EndpointNetwork>> getModifiedEndpointNetworks(
322 DataObjectModification<Interface> modifiedInterface) {
323 Collection<DataObjectModification<? extends DataObject>> potentialModifiedEPs =
324 modifiedInterface.getModifiedChildren();
325 if (potentialModifiedEPs == null) {
326 return Collections.emptyList();
328 List<DataObjectModification<EndpointNetwork>> eps = new ArrayList<>();
329 for (DataObjectModification<? extends DataObject> potentialModifiedEP : potentialModifiedEPs) {
330 if (potentialModifiedEP.getDataType().isAssignableFrom(EndpointNetwork.class)) {
331 eps.add((DataObjectModification<EndpointNetwork>) potentialModifiedEP);
337 private void processEndpointNetworkChange(DataObjectModification<EndpointNetwork> modifiedEN,
338 NetworkElement nodeBefore, Interface ifaceBefore, WriteTransaction wtx) {
339 switch (modifiedEN.getModificationType()) {
341 processDeletedEN(modifiedEN.getDataBefore(), wtx);
342 int nodeIndex = getIndexOf(nodeBefore);
343 int ifaceIndex = getIndexOf(ifaceBefore, nodeIndex);
344 networkElements.getNetworkElement()
348 .getEndpointNetwork()
349 .remove(modifiedEN.getDataBefore());
350 LOG.debug("Endpoint network {} removed", modifiedEN.getDataBefore());
354 processCreatedEN(modifiedEN.getDataAfter(), nodeBefore.getIid(), ifaceBefore.getIid(), wtx);
355 int nodeIndex = getIndexOf(nodeBefore);
356 int ifaceIndex = getIndexOf(ifaceBefore, nodeIndex);
357 networkElements.getNetworkElement()
361 .getEndpointNetwork()
362 .add(modifiedEN.getDataAfter());
363 LOG.debug("Created new Endpoint network {}", modifiedEN.getDataAfter());
366 case SUBTREE_MODIFIED: {
367 LOG.debug("EndpointNetwork {} changed", modifiedEN.getDataAfter().getKey());
373 private void processCreatedEN(EndpointNetwork en, InstanceIdentifier<?> nodeIID,
374 String connectorIID, WriteTransaction wtx) {
375 for (AddressEndpoint endpoint : endpoints) {
376 if (endpoint.getContextType().isAssignableFrom(L3Context.class)
377 && endpoint.getContextId().equals(en.getL3ContextId())
378 && endpoint.getAddressType().isAssignableFrom(IpPrefixType.class)
379 && NetUtils.samePrefix(new IpPrefix(endpoint.getAddress().toCharArray()), en.getIpPrefix())) {
380 InstanceIdentifier<AbsoluteLocation> iid = IidFactory
381 .providerAddressEndpointLocationIid(NE_LOCATION_PROVIDER_NAME, IpPrefixType.class,
382 endpoint.getAddress(), endpoint.getContextType(), endpoint.getContextId())
383 .child(AbsoluteLocation.class);
384 wtx.put(LogicalDatastoreType.CONFIGURATION, iid, createRealLocation(nodeIID, connectorIID), true);
385 LOG.debug("New location created for endpoint {}", endpoint);
391 private void processDeletedEN(EndpointNetwork en, WriteTransaction wtx) {
392 for (AddressEndpoint endpoint : endpoints) {
393 if (endpoint.getContextType().isAssignableFrom(L3Context.class)
394 && endpoint.getContextId().equals(en.getL3ContextId())
395 && endpoint.getAddressType().isAssignableFrom(IpPrefixType.class)
396 && NetUtils.samePrefix(new IpPrefix(endpoint.getAddress().toCharArray()), en.getIpPrefix())) {
397 InstanceIdentifier<AbsoluteLocation> iid = IidFactory
398 .providerAddressEndpointLocationIid(NE_LOCATION_PROVIDER_NAME, IpPrefixType.class,
399 endpoint.getAddress(), endpoint.getContextType(), endpoint.getContextId())
400 .child(AbsoluteLocation.class);
401 wtx.delete(LogicalDatastoreType.CONFIGURATION, iid);
402 LOG.debug("Location deleted for endpoint {}", endpoint);
408 private AbsoluteLocation createRealLocation(InstanceIdentifier<?> node, String iface) {
409 return new AbsoluteLocationBuilder()
410 .setLocationType(new ExternalLocationCaseBuilder().setExternalNodeMountPoint(node)
411 .setExternalNodeConnector(iface).build()).build();
414 private <T> List<T> nullToEmpty(@Nullable List<T> list) {
415 return list == null ? Collections.emptyList() : list;
418 private int getIndexOf(NetworkElement ne) {
419 for (NetworkElement listNE : networkElements.getNetworkElement()) {
420 if (ne.getIid().equals(listNE.getIid())) {
421 return networkElements.getNetworkElement().indexOf(listNE);
427 private int getIndexOf(Interface iface, int nodeIndex) {
428 for (Interface listIface : networkElements.getNetworkElement().get(nodeIndex).getInterface()) {
429 if (iface.getIid().equals(listIface.getIid())) {
430 return networkElements.getNetworkElement().get(nodeIndex).getInterface().indexOf(listIface);
437 synchronized List<AddressEndpoint> getEndpoints() {
442 synchronized NetworkElements getNetworkElements() {
443 return networkElements;