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