d92edd19666014b4fe059472cc34c11fa7f1888f
[groupbasedpolicy.git] / groupbasedpolicy / src / main / java / org / opendaylight / groupbasedpolicy / base_endpoint / BaseEndpointRpcRegistry.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 com.google.common.base.Function;
12 import com.google.common.util.concurrent.CheckedFuture;
13 import com.google.common.util.concurrent.FutureCallback;
14 import com.google.common.util.concurrent.Futures;
15 import com.google.common.util.concurrent.ListenableFuture;
16 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
17 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
18 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
19 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
20 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
21 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
22 import org.opendaylight.groupbasedpolicy.api.BaseEndpointRendererAugmentation;
23 import org.opendaylight.groupbasedpolicy.api.BaseEndpointRendererAugmentationRegistry;
24 import org.opendaylight.groupbasedpolicy.util.IidFactory;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.*;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpoint;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpointBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpointKey;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.containment.endpoints.ContainmentEndpoint;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.containment.endpoints.ContainmentEndpointBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.containment.endpoints.ContainmentEndpointKey;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.register.endpoint.input.AddressEndpointReg;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.register.endpoint.input.ContainmentEndpointReg;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.unregister.endpoint.input.AddressEndpointUnreg;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.unregister.endpoint.input.ContainmentEndpointUnreg;
36 import org.opendaylight.yangtools.yang.binding.Augmentation;
37 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
38 import org.opendaylight.yangtools.yang.common.RpcResult;
39 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
42
43 import javax.annotation.Nullable;
44 import java.util.Collections;
45 import java.util.List;
46 import java.util.Map;
47 import java.util.concurrent.ConcurrentHashMap;
48 import java.util.concurrent.ConcurrentMap;
49 import java.util.concurrent.Future;
50
51 public class BaseEndpointRpcRegistry
52     implements BaseEndpointService, BaseEndpointRendererAugmentationRegistry, AutoCloseable {
53
54     static final ConcurrentMap<String, BaseEndpointRendererAugmentation> registeredRenderers = new ConcurrentHashMap<>();
55     private static final Logger LOG = LoggerFactory.getLogger(BaseEndpointRpcRegistry.class);
56     private final DataBroker dataProvider;
57     private final BindingAwareBroker.RpcRegistration<BaseEndpointService> rpcRegistration;
58
59     private Function<Void, RpcResult<Void>> futureTrans = new Function<Void, RpcResult<Void>>() {
60
61         @Override
62         public RpcResult<Void> apply(Void input) {
63             return RpcResultBuilder.<Void>success().build();
64         }
65     };
66
67     public BaseEndpointRpcRegistry(DataBroker dataProvider, RpcProviderRegistry rpcRegistry) {
68         this.dataProvider = dataProvider;
69
70         if (rpcRegistry != null) {
71             rpcRegistration = rpcRegistry.addRpcImplementation(BaseEndpointService.class, this);
72             LOG.debug("Added Endpoints RPC Implementation Correctly");
73         } else {
74             rpcRegistration = null;
75         }
76
77         if (dataProvider != null) {
78             InstanceIdentifier<Endpoints> iid = InstanceIdentifier.builder(Endpoints.class).build();
79             WriteTransaction t = this.dataProvider.newWriteOnlyTransaction();
80             t.put(LogicalDatastoreType.OPERATIONAL, iid, new EndpointsBuilder().build());
81             CheckedFuture<Void, TransactionCommitFailedException> f = t.submit();
82             Futures.addCallback(f, new FutureCallback<Void>() {
83
84                 @Override
85                 public void onFailure(Throwable t) {
86                     LOG.error("Could not write Endpoints base container", t);
87                 }
88
89                 @Override
90                 public void onSuccess(Void result) {
91                     LOG.info("Endpoints container write successful");
92                 }
93             });
94         }
95     }
96
97     /**
98      * Registers renderer's endpoints augmentation.
99      *
100      * @param baseEndpointRendererAugmentation cannot be {@code null}
101      * @throws NullPointerException
102      */
103     @Override
104     public void register(BaseEndpointRendererAugmentation baseEndpointRendererAugmentation) {
105         if (baseEndpointRendererAugmentation != null) {
106             registeredRenderers.putIfAbsent(baseEndpointRendererAugmentation.getClass().getName(),
107                 baseEndpointRendererAugmentation);
108             LOG.info("Registered {}", baseEndpointRendererAugmentation.getClass().getName());
109         }
110     }
111
112     /**
113      * Unregisters renderer's endpoints augmentation.
114      *
115      * @param baseEndpointRendererAugmentation cannot be {@code null}
116      * @throws NullPointerException
117      */
118     @Override
119     public void unregister(BaseEndpointRendererAugmentation baseEndpointRendererAugmentation) {
120         if (baseEndpointRendererAugmentation == null
121                 || !registeredRenderers.containsKey(baseEndpointRendererAugmentation.getClass().getName())) {
122             return;
123         }
124         registeredRenderers.remove(baseEndpointRendererAugmentation.getClass().getName());
125         LOG.info("Unregistered {}", baseEndpointRendererAugmentation.getClass().getName());
126     }
127
128     /**
129      * Register a new endpoint into the registry. If there is already an existing
130      * endpoint with the same keys, they will be overwritten with the new information.
131      *
132      * @param input Endpoint to register
133      */
134     @Override
135     public Future<RpcResult<Void>> registerEndpoint(RegisterEndpointInput input) {
136         long timestamp = System.currentTimeMillis();
137
138         WriteTransaction t = dataProvider.newWriteOnlyTransaction();
139
140         List<ContainmentEndpointReg> endpoints = input.getContainmentEndpointReg();
141         for (ContainmentEndpointReg ce : nullToEmpty(endpoints)) {
142             long stamp = (ce.getTimestamp() == null || ce.getTimestamp() == 0) ? timestamp : ce.getTimestamp();
143             ContainmentEndpoint endpoint = buildContainmentEndpoint(ce).setTimestamp(stamp).build();
144             t.put(LogicalDatastoreType.OPERATIONAL, IidFactory.containmentEndpointIid(endpoint.getKey()), endpoint,
145                     true);
146         }
147
148         List<AddressEndpointReg> addressEndpoints = input.getAddressEndpointReg();
149         for (AddressEndpointReg ae : nullToEmpty(addressEndpoints)) {
150             long stamp = (ae.getTimestamp() == null || ae.getTimestamp() == 0) ? timestamp : ae.getTimestamp();
151             AddressEndpoint endpoint = buildAddressEndpoint(ae).setTimestamp(stamp).build();
152             t.put(LogicalDatastoreType.OPERATIONAL, IidFactory.addressEndpointIid(endpoint.getKey()), endpoint, true);
153         }
154
155         ListenableFuture<Void> r = t.submit();
156         return Futures.transform(r, futureTrans);
157     }
158
159     private ContainmentEndpointBuilder buildContainmentEndpoint(ContainmentEndpointReg input) {
160         ContainmentEndpointBuilder eb = new ContainmentEndpointBuilder().setChildEndpoint(input.getChildEndpoint())
161             .setCondition(input.getCondition())
162             .setContextType(input.getContextType())
163             .setContextId(input.getContextId())
164             .setEndpointGroup(input.getEndpointGroup())
165             .setKey(new ContainmentEndpointKey(input.getContextId(), input.getContextType()))
166             .setNetworkContainment(input.getNetworkContainment())
167             .setTenant(input.getTenant())
168             .setTimestamp(input.getTimestamp());
169
170         for (Map.Entry<String, BaseEndpointRendererAugmentation> entry : registeredRenderers.entrySet()) {
171             try {
172                 Map.Entry<Class<? extends Augmentation<ContainmentEndpoint>>, Augmentation<ContainmentEndpoint>> augmentationEntry =
173                         entry.getValue().buildContainmentEndpointAugmentation(input);
174                 if (augmentationEntry != null) {
175                     eb.addAugmentation(augmentationEntry.getKey(), augmentationEntry.getValue());
176                 }
177             } catch (Exception e) {
178                 LOG.warn("AddressEndpoint Augmentation error while processing " + entry.getKey() + ". Reason: ", e);
179             }
180         }
181         return eb;
182     }
183
184     private AddressEndpointBuilder buildAddressEndpoint(AddressEndpointReg ae) {
185         AddressEndpointBuilder builder = new AddressEndpointBuilder().setTenant(ae.getTenant())
186             .setNetworkContainment(ae.getNetworkContainment())
187             .setEndpointGroup(ae.getEndpointGroup())
188             .setAddress(ae.getAddress())
189             .setAddressType(ae.getAddressType())
190             .setChildEndpoint(ae.getChildEndpoint())
191             .setCondition(ae.getCondition())
192             .setKey(new AddressEndpointKey(ae.getAddress(), ae.getAddressType(), ae.getContextId(),
193                     ae.getContextType()))
194             .setParentEndpointChoice(ae.getParentEndpointChoice())
195             .setTimestamp(ae.getTimestamp())
196             .setContextId(ae.getContextId())
197             .setContextType(ae.getContextType())
198             .setTenant(ae.getTenant());
199
200         for (Map.Entry<String, BaseEndpointRendererAugmentation> entry : registeredRenderers.entrySet()) {
201             try {
202                 Map.Entry<Class<? extends Augmentation<AddressEndpoint>>, Augmentation<AddressEndpoint>> augmentationEntry =
203                         entry.getValue().buildAddressEndpointAugmentation(ae);
204                 if (augmentationEntry != null) {
205                     builder.addAugmentation(augmentationEntry.getKey(), augmentationEntry.getValue());
206                 }
207             } catch (Exception e) {
208                 LOG.warn("AddressEndpoint Augmentation error while processing " + entry.getKey() + ". Reason: ", e);
209             }
210         }
211         return builder;
212     }
213
214     /**
215      * Unregister an endpoint or endpoints from the registry.
216      *
217      * @param input Endpoint/endpoints to unregister
218      */
219     @Override
220     public Future<RpcResult<Void>> unregisterEndpoint(UnregisterEndpointInput input) {
221         WriteTransaction t = dataProvider.newWriteOnlyTransaction();
222
223         List<AddressEndpointUnreg> addressEndpoints = input.getAddressEndpointUnreg();
224         for (AddressEndpointUnreg ae : nullToEmpty(addressEndpoints)) {
225             AddressEndpointKey key = new AddressEndpointKey(ae.getAddress(), ae.getAddressType(), ae.getContextId(),
226                     ae.getContextType());
227             t.delete(LogicalDatastoreType.OPERATIONAL, IidFactory.addressEndpointIid(key));
228         }
229
230         List<ContainmentEndpointUnreg> endpoints = input.getContainmentEndpointUnreg();
231         for (ContainmentEndpointUnreg ce : nullToEmpty(endpoints)) {
232             ContainmentEndpointKey key = new ContainmentEndpointKey(ce.getContextId(), ce.getContextType());
233             t.delete(LogicalDatastoreType.OPERATIONAL, IidFactory.containmentEndpointIid(key));
234         }
235
236         ListenableFuture<Void> r = t.submit();
237         return Futures.transform(r, futureTrans);
238     }
239
240     @Override
241     public void close() throws Exception {
242         if (rpcRegistration != null) {
243             rpcRegistration.close();
244         }
245     }
246
247     private <T> List<T> nullToEmpty(@Nullable List<T> list) {
248         return list == null ? Collections.emptyList() : list;
249     }
250
251 }