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