update deprecated transform and addCallback methods
[groupbasedpolicy.git] / groupbasedpolicy / src / main / java / org / opendaylight / groupbasedpolicy / base_endpoint / BaseEndpointServiceImpl.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.base_endpoint;
10
11 import java.util.Collections;
12 import java.util.List;
13 import java.util.Map;
14 import java.util.concurrent.Future;
15
16 import javax.annotation.Nullable;
17
18 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
19 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
20 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
21 import org.opendaylight.groupbasedpolicy.api.EndpointAugmentor;
22 import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
23 import org.opendaylight.groupbasedpolicy.util.EndpointUtils;
24 import org.opendaylight.groupbasedpolicy.util.IidFactory;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.BaseEndpointService;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.RegisterEndpointInput;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.UnregisterEndpointInput;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpoint;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpointBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpointKey;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.containment.endpoints.ContainmentEndpoint;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.containment.endpoints.ContainmentEndpointBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.containment.endpoints.ContainmentEndpointKey;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.child.endpoints.ChildEndpoint;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.child.endpoints.ChildEndpointBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.child.endpoints.ChildEndpointKey;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.ParentEndpointChoice;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.parent.containment.endpoint._case.ParentContainmentEndpoint;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.parent.containment.endpoint._case.ParentContainmentEndpointBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.parent.containment.endpoint._case.ParentContainmentEndpointKey;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.parent.endpoint._case.ParentEndpoint;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.parent.endpoint._case.ParentEndpointBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.parent.endpoint._case.ParentEndpointKey;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.register.endpoint.input.AddressEndpointReg;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.register.endpoint.input.ContainmentEndpointReg;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.unregister.endpoint.input.AddressEndpointUnreg;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.unregister.endpoint.input.ContainmentEndpointUnreg;
48 import org.opendaylight.yangtools.yang.binding.Augmentation;
49 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
50 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
51 import org.opendaylight.yangtools.yang.common.RpcResult;
52 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
53 import org.slf4j.Logger;
54 import org.slf4j.LoggerFactory;
55
56 import com.google.common.base.Function;
57 import com.google.common.base.Optional;
58 import com.google.common.base.Preconditions;
59 import com.google.common.util.concurrent.Futures;
60 import com.google.common.util.concurrent.ListenableFuture;
61 import com.google.common.util.concurrent.MoreExecutors;
62
63 public class BaseEndpointServiceImpl implements BaseEndpointService, AutoCloseable {
64
65     private static final Logger LOG = LoggerFactory.getLogger(BaseEndpointServiceImpl.class);
66     private final DataBroker dataProvider;
67     private final EndpointAugmentorRegistryImpl epAugRegistry;
68
69     private static final Function<Void, RpcResult<Void>> TO_SUCCESS_RPC_RESULT =
70         input -> RpcResultBuilder.<Void>success().build();
71
72     public BaseEndpointServiceImpl(DataBroker dataProvider, EndpointAugmentorRegistryImpl epAugRegistry) {
73         this.epAugRegistry = Preconditions.checkNotNull(epAugRegistry);
74         this.dataProvider = Preconditions.checkNotNull(dataProvider);
75     }
76
77     /**
78      * Register a new endpoint into the registry. If there is already an existing
79      * endpoint with the same keys, they will be overwritten with the new information.
80      *
81      * @param input Endpoint to register
82      */
83     @Override
84     public Future<RpcResult<Void>> registerEndpoint(RegisterEndpointInput input) {
85         long timestamp = System.currentTimeMillis();
86
87         ReadWriteTransaction t = dataProvider.newReadWriteTransaction();
88
89         ListenableFuture<RpcResult<Void>> failResult =
90                 RegisterEndpointInputVerificator.verifyRegisterEndpointInput(input, t);
91         if (failResult != null) {
92             t.cancel();
93             return failResult;
94         }
95
96         List<ContainmentEndpointReg> endpoints = input.getContainmentEndpointReg();
97         for (ContainmentEndpointReg ce : nullToEmpty(endpoints)) {
98             long stamp = (ce.getTimestamp() == null || ce.getTimestamp() == 0) ? timestamp : ce.getTimestamp();
99             ContainmentEndpoint endpoint = buildContainmentEndpoint(ce).setTimestamp(stamp).build();
100             t.put(LogicalDatastoreType.OPERATIONAL, IidFactory.containmentEndpointIid(endpoint.getKey()), endpoint,
101                     true);
102             addContainmentEndpointToChilds(t, endpoint);
103         }
104
105         List<AddressEndpointReg> addressEndpoints = input.getAddressEndpointReg();
106         for (AddressEndpointReg ae : nullToEmpty(addressEndpoints)) {
107             long stamp = (ae.getTimestamp() == null || ae.getTimestamp() == 0) ? timestamp : ae.getTimestamp();
108             AddressEndpoint endpoint = buildAddressEndpoint(ae).setTimestamp(stamp).build();
109             t.put(LogicalDatastoreType.OPERATIONAL, IidFactory.addressEndpointIid(endpoint.getKey()), endpoint, true);
110             addAddressEndpointToChilds(t, endpoint);
111             addAddressEndpointToParents(t, endpoint);
112         }
113
114         return Futures.transform(t.submit(), TO_SUCCESS_RPC_RESULT, MoreExecutors.directExecutor());
115     }
116
117     private void addContainmentEndpointToChilds(ReadWriteTransaction t, ContainmentEndpoint endpoint) {
118         ParentContainmentEndpoint epAsParent = new ParentContainmentEndpointBuilder(endpoint).build();
119         for (ChildEndpoint child : nullToEmpty(endpoint.getChildEndpoint())) {
120             InstanceIdentifier<AddressEndpoint> childIid =
121                     IidFactory.addressEndpointIid(EndpointUtils.createAddressEndpointKey(child));
122             Optional<AddressEndpoint> childAddrEpOptional =
123                     DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL, childIid, t);
124             if (childAddrEpOptional.isPresent()) {
125                 KeyedInstanceIdentifier<ParentContainmentEndpoint, ParentContainmentEndpointKey> parentInChildIid =
126                         childIid.child(ParentContainmentEndpoint.class, epAsParent.getKey());
127                 t.put(LogicalDatastoreType.OPERATIONAL, parentInChildIid, epAsParent, true);
128             }
129         }
130     }
131
132     private void addAddressEndpointToChilds(ReadWriteTransaction t, AddressEndpoint endpoint) {
133         ParentEndpoint epAsParent = new ParentEndpointBuilder(endpoint).build();
134         for (ChildEndpoint child : nullToEmpty(endpoint.getChildEndpoint())) {
135             InstanceIdentifier<AddressEndpoint> childIid =
136                     IidFactory.addressEndpointIid(EndpointUtils.createAddressEndpointKey(child));
137             Optional<AddressEndpoint> childAddrEpOptional =
138                     DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL, childIid, t);
139             if (childAddrEpOptional.isPresent()) {
140                 KeyedInstanceIdentifier<ParentEndpoint, ParentEndpointKey> parentInChildIid =
141                         childIid.child(ParentEndpoint.class, epAsParent.getKey());
142                 t.put(LogicalDatastoreType.OPERATIONAL, parentInChildIid, epAsParent, true);
143             }
144         }
145     }
146
147     private void addAddressEndpointToParents(ReadWriteTransaction t, AddressEndpoint endpoint) {
148         ChildEndpoint epAsChild = new ChildEndpointBuilder(endpoint).build();
149         for (ParentEndpoint parent : EndpointUtils.getParentEndpoints(endpoint.getParentEndpointChoice())) {
150             InstanceIdentifier<AddressEndpoint> parentIid =
151                     IidFactory.addressEndpointIid(EndpointUtils.createAddressEndpointKey(parent));
152             Optional<AddressEndpoint> parentAddrEpOptional =
153                     DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL, parentIid, t);
154             if (parentAddrEpOptional.isPresent()) {
155                 KeyedInstanceIdentifier<ChildEndpoint, ChildEndpointKey> childInParentIid =
156                         parentIid.child(ChildEndpoint.class, epAsChild.getKey());
157                 t.put(LogicalDatastoreType.OPERATIONAL, childInParentIid, epAsChild, true);
158             }
159         }
160         for (ParentContainmentEndpoint parent : EndpointUtils.getParentContainmentEndpoints(endpoint.getParentEndpointChoice())) {
161             InstanceIdentifier<ContainmentEndpoint> parentIid = IidFactory
162                 .containmentEndpointIid(new ContainmentEndpointKey(parent.getContextId(), parent.getContextType()));
163             Optional<ContainmentEndpoint> parentContEpOptional =
164                     DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL, parentIid, t);
165             if (parentContEpOptional.isPresent()) {
166                 KeyedInstanceIdentifier<ChildEndpoint, ChildEndpointKey> childInParentIid =
167                         parentIid.child(ChildEndpoint.class, epAsChild.getKey());
168                 t.put(LogicalDatastoreType.OPERATIONAL, childInParentIid, epAsChild, true);
169             }
170         }
171     }
172
173     private ContainmentEndpointBuilder buildContainmentEndpoint(ContainmentEndpointReg input) {
174
175         ContainmentEndpointBuilder eb = new ContainmentEndpointBuilder().setChildEndpoint(input.getChildEndpoint())
176             .setCondition(input.getCondition())
177             .setContextType(input.getContextType())
178             .setContextId(input.getContextId())
179             .setEndpointGroup(input.getEndpointGroup())
180             .setKey(new ContainmentEndpointKey(input.getContextId(), input.getContextType()))
181             .setNetworkContainment(input.getNetworkContainment())
182             .setTenant(input.getTenant())
183             .setTimestamp(input.getTimestamp())
184             .setChildEndpoint(input.getChildEndpoint());
185
186         for (EndpointAugmentor epAugmentor : epAugRegistry.getEndpointAugmentors()) {
187             try {
188                 Map.Entry<Class<? extends Augmentation<ContainmentEndpoint>>, Augmentation<ContainmentEndpoint>> augmentationEntry =
189                         epAugmentor.buildContainmentEndpointAugmentation(input);
190                 if (augmentationEntry != null) {
191                     eb.addAugmentation(augmentationEntry.getKey(), augmentationEntry.getValue());
192                 }
193             } catch (Exception e) {
194                 LOG.warn("AddressEndpoint Augmentation error while {} was processing {}",
195                         epAugmentor.getClass().getSimpleName(), input, e);
196             }
197         }
198         return eb;
199     }
200
201     private AddressEndpointBuilder buildAddressEndpoint(AddressEndpointReg ae) {
202         AddressEndpointBuilder builder = new AddressEndpointBuilder().setTenant(ae.getTenant())
203             .setNetworkContainment(ae.getNetworkContainment())
204             .setEndpointGroup(ae.getEndpointGroup())
205             .setAddress(ae.getAddress())
206             .setAddressType(ae.getAddressType())
207             .setChildEndpoint(ae.getChildEndpoint())
208             .setCondition(ae.getCondition())
209             .setKey(new AddressEndpointKey(ae.getAddress(), ae.getAddressType(), ae.getContextId(),
210                     ae.getContextType()))
211             .setParentEndpointChoice(ae.getParentEndpointChoice())
212             .setTimestamp(ae.getTimestamp())
213             .setContextId(ae.getContextId())
214             .setContextType(ae.getContextType())
215             .setTenant(ae.getTenant());
216
217         for (EndpointAugmentor epAugmentor : epAugRegistry.getEndpointAugmentors()) {
218             try {
219                 Map.Entry<Class<? extends Augmentation<AddressEndpoint>>, Augmentation<AddressEndpoint>> augmentationEntry =
220                         epAugmentor.buildAddressEndpointAugmentation(ae);
221                 if (augmentationEntry != null) {
222                     builder.addAugmentation(augmentationEntry.getKey(), augmentationEntry.getValue());
223                 }
224             } catch (Exception e) {
225                 LOG.warn("AddressEndpoint Augmentation error while {} was processing {}",
226                         epAugmentor.getClass().getSimpleName(), ae, e);
227             }
228         }
229         return builder;
230     }
231
232     /**
233      * Unregister an endpoint or endpoints from the registry.
234      *
235      * @param input Endpoint/endpoints to unregister
236      */
237     @Override
238     public Future<RpcResult<Void>> unregisterEndpoint(UnregisterEndpointInput input) {
239         ReadWriteTransaction t = dataProvider.newReadWriteTransaction();
240
241         List<AddressEndpointUnreg> addrEndpoints = input.getAddressEndpointUnreg();
242         for (AddressEndpointUnreg aeUnreg : nullToEmpty(addrEndpoints)) {
243             AddressEndpointKey key = new AddressEndpointKey(aeUnreg.getAddress(), aeUnreg.getAddressType(),
244                     aeUnreg.getContextId(), aeUnreg.getContextType());
245             Optional<AddressEndpoint> aeOptional = DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
246                     IidFactory.addressEndpointIid(key), t);
247             if (aeOptional.isPresent()) {
248                 deleteAddressEndpointFromParents(t, aeOptional.get());
249                 deleteAddressEndpointFromChilds(t, aeOptional.get());
250             }
251         }
252
253         List<ContainmentEndpointUnreg> contEndpoints = input.getContainmentEndpointUnreg();
254         for (ContainmentEndpointUnreg ceUnreg : nullToEmpty(contEndpoints)) {
255             ContainmentEndpointKey key = new ContainmentEndpointKey(ceUnreg.getContextId(), ceUnreg.getContextType());
256             Optional<ContainmentEndpoint> ceOptional = DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
257                     IidFactory.containmentEndpointIid(key), t);
258             if (ceOptional.isPresent()) {
259                 deleteContainmentEndpointFromChilds(t, ceOptional.get());
260             }
261         }
262
263         ListenableFuture<Void> r = t.submit();
264         return Futures.transform(r, TO_SUCCESS_RPC_RESULT, MoreExecutors.directExecutor());
265     }
266
267     private void deleteAddressEndpointFromParents(ReadWriteTransaction t, AddressEndpoint endpoint) {
268         ParentEndpointChoice parentEndpointChoice = endpoint.getParentEndpointChoice();
269         for (ParentEndpoint parentEndpoint : EndpointUtils.getParentEndpoints(parentEndpointChoice)) {
270             KeyedInstanceIdentifier<ChildEndpoint, ChildEndpointKey> childEp =
271                     IidFactory.addressEndpointIid(EndpointUtils.createAddressEndpointKey(parentEndpoint)).child(ChildEndpoint.class,
272                             new ChildEndpointKey(endpoint.getAddress(), endpoint.getAddressType(),
273                                     endpoint.getContextId(), endpoint.getContextType()));
274             DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL, childEp, t);
275         }
276         for (ParentContainmentEndpoint parentContEndpoint : EndpointUtils.getParentContainmentEndpoints(parentEndpointChoice)) {
277             KeyedInstanceIdentifier<ChildEndpoint, ChildEndpointKey> childEp = IidFactory
278                 .containmentEndpointIid(new ContainmentEndpointKey(parentContEndpoint.getContextId(),
279                         parentContEndpoint.getContextType()))
280                 .child(ChildEndpoint.class, new ChildEndpointKey(endpoint.getAddress(), endpoint.getAddressType(),
281                         endpoint.getContextId(), endpoint.getContextType()));
282             DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL, childEp, t);
283         }
284     }
285
286     private void deleteAddressEndpointFromChilds(ReadWriteTransaction t, AddressEndpoint endpoint) {
287         for (ChildEndpoint childEndpoint : nullToEmpty(endpoint.getChildEndpoint())) {
288             KeyedInstanceIdentifier<ParentEndpoint, ParentEndpointKey> parentEp =
289                     IidFactory.addressEndpointIid(EndpointUtils.createAddressEndpointKey(childEndpoint)).child(ParentEndpoint.class,
290                             new ParentEndpointKey(endpoint.getAddress(), endpoint.getAddressType(),
291                                     endpoint.getContextId(), endpoint.getContextType()));
292             DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL, parentEp, t);
293         }
294     }
295
296     private void deleteContainmentEndpointFromChilds(ReadWriteTransaction t, ContainmentEndpoint endpoint) {
297         for (ChildEndpoint child : nullToEmpty(endpoint.getChildEndpoint())) {
298             AddressEndpointKey aeKey = new AddressEndpointKey(child.getAddress(), child.getAddressType(),
299                     child.getContextId(), child.getContextType());
300             KeyedInstanceIdentifier<ParentContainmentEndpoint, ParentContainmentEndpointKey> parentEp =
301                     IidFactory.addressEndpointIid(aeKey).child(ParentContainmentEndpoint.class,
302                             new ParentContainmentEndpointKey(endpoint.getContextId(), endpoint.getContextType()));
303             DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL, parentEp, t);
304         }
305     }
306
307     @Override
308     public void close() {
309     }
310
311     private <T> List<T> nullToEmpty(@Nullable List<T> list) {
312         return list == null ? Collections.emptyList() : list;
313     }
314
315 }