e4b00dc8b14b245b3a6476ff227685e9fe939d60
[groupbasedpolicy.git] / groupbasedpolicy / src / main / java / org / opendaylight / groupbasedpolicy / location / resolver / LocationResolver.java
1 /*
2  * Copyright (c) 2016 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
9 package org.opendaylight.groupbasedpolicy.location.resolver;
10
11 import java.util.Collection;
12 import java.util.Collections;
13 import java.util.HashMap;
14 import java.util.List;
15 import java.util.Map;
16
17 import javax.annotation.Nullable;
18
19 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
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.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoint.locations.AddressEndpointLocation;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoint.locations.AddressEndpointLocationBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoint.locations.AddressEndpointLocationKey;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoint.locations.ContainmentEndpointLocation;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoint.locations.ContainmentEndpointLocationBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoint.locations.ContainmentEndpointLocationKey;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.AbsoluteLocation;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.relative.location.relative.locations.ExternalLocation;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.relative.location.relative.locations.InternalLocation;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint_location_provider.rev160419.LocationProviders;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint_location_provider.rev160419.location.providers.LocationProvider;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint_location_provider.rev160419.location.providers.location.provider.ProviderAddressEndpointLocation;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint_location_provider.rev160419.location.providers.location.provider.ProviderAddressEndpointLocationKey;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint_location_provider.rev160419.location.providers.location.provider.ProviderContainmentEndpointLocation;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint_location_provider.rev160419.location.providers.location.provider.ProviderContainmentEndpointLocationKey;
42 import org.opendaylight.yangtools.concepts.ListenerRegistration;
43 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
44 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory;
46
47 public class LocationResolver implements DataTreeChangeListener<LocationProvider>, AutoCloseable {
48
49     private static final Logger LOG = LoggerFactory.getLogger(LocationResolver.class);
50     private Map<AddressEndpointLocationKey, Map<Long, AbsoluteLocation>> realLocations;
51     private DataBroker dataBroker;
52     private ListenerRegistration<LocationResolver> listenerRegistation;
53
54     public LocationResolver(DataBroker dataBroker) {
55         this.dataBroker = dataBroker;
56         this.realLocations = new HashMap<>();
57         this.listenerRegistation = dataBroker.registerDataTreeChangeListener(
58                 new DataTreeIdentifier<>(LogicalDatastoreType.OPERATIONAL,
59                         InstanceIdentifier.builder(LocationProviders.class).child(LocationProvider.class).build()),
60                 this);
61     }
62
63     @Override
64     public synchronized void onDataTreeChanged(Collection<DataTreeModification<LocationProvider>> changes) {
65         for (DataTreeModification<LocationProvider> change : changes) {
66             WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
67             switch (change.getRootNode().getModificationType()) {
68                 case DELETE: {
69                     processRemovedLocationProviderData(change.getRootNode().getDataBefore(), wtx);
70                     LOG.debug("Data from location provider {} has been removed",
71                             change.getRootNode().getDataBefore().getProvider().getValue());
72                     break;
73                 }
74                 case WRITE: {
75                     if (change.getRootNode().getDataBefore() != null) {
76                         processRemovedLocationProviderData(change.getRootNode().getDataBefore(), wtx);
77                     }
78                     processCreatedLocationProviderData(change.getRootNode().getDataAfter(), wtx);
79                     LOG.debug("Data from location provider {} has been created",
80                             change.getRootNode().getDataAfter().getProvider().getValue());
81                     break;
82                 }
83                 case SUBTREE_MODIFIED: {
84                     processRemovedLocationProviderData(change.getRootNode().getDataBefore(), wtx);
85                     processCreatedLocationProviderData(change.getRootNode().getDataAfter(), wtx);
86                     LOG.debug("Data from location provider {} has been changed",
87                             change.getRootNode().getDataAfter().getProvider().getValue());
88                     break;
89                 }
90             }
91             LOG.debug("Writing endpoint location changes to DS");
92             DataStoreHelper.submitToDs(wtx);
93         }
94     }
95
96     private void processRemovedLocationProviderData(LocationProvider provider, WriteTransaction wtx) {
97         for (ProviderAddressEndpointLocation addressEndpointLocation : nullToEmpty(
98                 provider.getProviderAddressEndpointLocation())) {
99             AddressEndpointLocationKey epKey = createAddressEndpointLocationKey(addressEndpointLocation.getKey());
100             long priority;
101             if (provider.getPriority() == null) {
102                 priority = 0;
103                 LOG.debug("{} provider doesn't provide priority. Using 0 as priority instead.",
104                         provider.getProvider().getValue());
105             } else {
106                 priority = provider.getPriority();
107             }
108             realLocations.get(epKey).remove(priority);
109             AbsoluteLocation newAbsoluteLocation = getBestAbsoluteLocation(epKey);
110             if (newAbsoluteLocation == null) {
111                 InstanceIdentifier<AbsoluteLocation> iid = IidFactory.absoluteLocationIid(epKey);
112                 wtx.delete(LogicalDatastoreType.OPERATIONAL, iid);
113             } else {
114                 AddressEndpointLocationBuilder newEP =
115                         new AddressEndpointLocationBuilder().setKey(epKey).setAbsoluteLocation(newAbsoluteLocation);
116                 InstanceIdentifier<AddressEndpointLocation> iid = IidFactory.addressEndpointLocationIid(newEP.getKey());
117                 wtx.merge(LogicalDatastoreType.OPERATIONAL, iid, newEP.build(), true);
118             }
119             if (addressEndpointLocation.getRelativeLocations() != null) {
120                 for (InternalLocation location : nullToEmpty(
121                         addressEndpointLocation.getRelativeLocations().getInternalLocation())) {
122                     InstanceIdentifier<InternalLocation> iid = IidFactory.internalLocationIid(epKey, location.getKey());
123                     wtx.delete(LogicalDatastoreType.OPERATIONAL, iid);
124                 }
125                 for (ExternalLocation location : nullToEmpty(
126                         addressEndpointLocation.getRelativeLocations().getExternalLocation())) {
127                     InstanceIdentifier<ExternalLocation> iid = IidFactory.externalLocationIid(epKey, location.getKey());
128                     wtx.delete(LogicalDatastoreType.OPERATIONAL, iid);
129                 }
130             }
131         }
132         for (ProviderContainmentEndpointLocation containmentEndpoint : nullToEmpty(
133                 provider.getProviderContainmentEndpointLocation())) {
134             ContainmentEndpointLocationKey epKey = createContainmentEndpointLocationKey(containmentEndpoint.getKey());
135             if (containmentEndpoint.getRelativeLocations() != null) {
136                 for (InternalLocation location : nullToEmpty(
137                         containmentEndpoint.getRelativeLocations().getInternalLocation())) {
138                     InstanceIdentifier<InternalLocation> iid = IidFactory.internalLocationIid(epKey, location.getKey());
139                     wtx.delete(LogicalDatastoreType.OPERATIONAL, iid);
140                 }
141                 for (ExternalLocation location : nullToEmpty(
142                         containmentEndpoint.getRelativeLocations().getExternalLocation())) {
143                     InstanceIdentifier<ExternalLocation> iid = IidFactory.externalLocationIid(epKey, location.getKey());
144                     wtx.delete(LogicalDatastoreType.OPERATIONAL, iid);
145                 }
146             }
147         }
148     }
149
150     private void processCreatedLocationProviderData(LocationProvider provider, WriteTransaction wtx) {
151         for (ProviderAddressEndpointLocation addressEndpointLocation : nullToEmpty(
152                 provider.getProviderAddressEndpointLocation())) {
153             AddressEndpointLocationKey epKey = createAddressEndpointLocationKey(addressEndpointLocation.getKey());
154             AddressEndpointLocationBuilder newEP = new AddressEndpointLocationBuilder().setKey(epKey);
155             if (addressEndpointLocation.getAbsoluteLocation() != null) {
156                 if (realLocations.get(epKey) == null) {
157                     realLocations.put(epKey, new HashMap<>());
158                 }
159                 long priority;
160                 if (provider.getPriority() == null) {
161                     priority = 0;
162                     LOG.debug("{} provider doesnt provide priority. Using 0 as priority instead.",
163                             provider.getProvider().getValue());
164                 } else {
165                     priority = provider.getPriority();
166                 }
167                 realLocations.get(epKey).put(priority, addressEndpointLocation.getAbsoluteLocation());
168             }
169             AbsoluteLocation bestLocation = getBestAbsoluteLocation(epKey);
170             if (bestLocation != null) {
171                 newEP.setAbsoluteLocation(bestLocation);
172             }
173             if (addressEndpointLocation.getRelativeLocations() != null) {
174                 newEP.setRelativeLocations(addressEndpointLocation.getRelativeLocations());
175             }
176             InstanceIdentifier<AddressEndpointLocation> iid = IidFactory.addressEndpointLocationIid(newEP.getKey());
177             wtx.merge(LogicalDatastoreType.OPERATIONAL, iid, newEP.build(), true);
178         }
179         for (ProviderContainmentEndpointLocation containmentEndpointLocation : nullToEmpty(
180                 provider.getProviderContainmentEndpointLocation())) {
181             if (containmentEndpointLocation.getRelativeLocations() != null) {
182                 ContainmentEndpointLocationKey key =
183                         createContainmentEndpointLocationKey(containmentEndpointLocation.getKey());
184                 ContainmentEndpointLocationBuilder newEP = new ContainmentEndpointLocationBuilder().setKey(key);
185                 newEP.setRelativeLocations(containmentEndpointLocation.getRelativeLocations());
186                 InstanceIdentifier<ContainmentEndpointLocation> iid =
187                         IidFactory.containmentEndpointLocationIid(newEP.getKey());
188                 wtx.merge(LogicalDatastoreType.OPERATIONAL, iid, newEP.build(), true);
189             }
190         }
191     }
192
193     private AbsoluteLocation getBestAbsoluteLocation(AddressEndpointLocationKey epKey) {
194         if (realLocations.get(epKey) == null) {
195             return null;
196         }
197         long bestPriority = -1;
198         for (long priority : realLocations.get(epKey).keySet()) {
199             bestPriority = bestPriority > priority ? bestPriority : priority;
200         };
201         if (bestPriority == -1) {
202             return null;
203         }
204         return (realLocations.get(epKey).get(new Long(bestPriority)));
205     }
206
207     private AddressEndpointLocationKey createAddressEndpointLocationKey(ProviderAddressEndpointLocationKey key) {
208         return new AddressEndpointLocationKey(key.getAddress(), key.getAddressType(), key.getContextId(),
209                 key.getContextType());
210     }
211
212     private ContainmentEndpointLocationKey createContainmentEndpointLocationKey(
213             ProviderContainmentEndpointLocationKey key) {
214         return new ContainmentEndpointLocationKey(key.getContextId(), key.getContextType());
215     }
216
217     private <T> List<T> nullToEmpty(@Nullable List<T> list) {
218         return list == null ? Collections.emptyList() : list;
219     }
220
221     @Override
222     public void close() throws Exception {
223         listenerRegistation.close();
224     }
225 }