2 * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
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
9 package org.opendaylight.groupbasedpolicy.endpoint;
11 import java.util.Map.Entry;
12 import java.util.concurrent.ConcurrentHashMap;
13 import java.util.concurrent.ConcurrentMap;
14 import java.util.concurrent.Future;
15 import java.util.concurrent.ScheduledExecutorService;
17 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
18 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
19 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
20 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
21 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
22 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.EndpointService;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.Endpoints;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.EndpointsBuilder;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInput;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterL3PrefixEndpointInput;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.SetEndpointGroupConditionsInput;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.UnregisterEndpointInput;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.UnsetEndpointGroupConditionsInput;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.fields.L3Address;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.ConditionMapping;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.ConditionMappingKey;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointKey;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Builder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Key;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Prefix;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3PrefixBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3PrefixKey;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.has.endpoint.group.conditions.EndpointGroupCondition;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.has.endpoint.group.conditions.EndpointGroupConditionKey;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.unregister.endpoint.input.L2;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.unregister.endpoint.input.L3;
47 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
48 import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
49 import org.opendaylight.yangtools.yang.common.RpcResult;
50 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
51 import org.slf4j.Logger;
52 import org.slf4j.LoggerFactory;
54 import com.google.common.base.Function;
55 import com.google.common.util.concurrent.CheckedFuture;
56 import com.google.common.util.concurrent.FutureCallback;
57 import com.google.common.util.concurrent.Futures;
58 import com.google.common.util.concurrent.ListenableFuture;
61 * Endpoint registry provides a scalable store for accessing and updating
62 * information about endpoints.
64 public class EndpointRpcRegistry implements EndpointService {
65 private static final Logger LOG =
66 LoggerFactory.getLogger(EndpointRpcRegistry.class);
68 private final DataBroker dataProvider;
69 private final ScheduledExecutorService executor;
70 private final RpcProviderRegistry rpcRegistry;
71 private static EndpointRpcRegistry endpointRpcRegistry;
73 final BindingAwareBroker.RpcRegistration<EndpointService> rpcRegistration;
75 private final static ConcurrentMap<String, EpRendererAugmentation> registeredRenderers = new ConcurrentHashMap<String, EpRendererAugmentation>();
78 * This method registers a renderer for endpoint RPC API. This method
79 * ensures single RPC registration for all renderers since a single RPC
80 * registration is only allowed.
87 * - thread pool executor
88 * @param epRendererAugmentation
89 * - specific implementation RPC augmentation, if any. Otherwise
92 public static void register(DataBroker dataProvider,
93 RpcProviderRegistry rpcRegistry, ScheduledExecutorService executor,
94 EpRendererAugmentation epRendererAugmentation) {
95 if (dataProvider == null || rpcRegistry == null || executor == null) {
96 if (epRendererAugmentation != null) {
97 LOG.warn("Couldn't register class {} for endpoint RPC because of missing required info");
101 if (endpointRpcRegistry == null) {
102 synchronized (EndpointRpcRegistry.class) {
103 if (endpointRpcRegistry == null) {
104 endpointRpcRegistry = new EndpointRpcRegistry(dataProvider,
105 rpcRegistry, executor);
109 if (epRendererAugmentation != null) {
110 registeredRenderers.putIfAbsent(epRendererAugmentation.getClass()
111 .getName(), epRendererAugmentation);
120 public static void unregister(EpRendererAugmentation regImp)
123 || !registeredRenderers
124 .containsKey(regImp.getClass().getName())) {
127 registeredRenderers.remove(regImp.getClass().getName());
128 LOG.info("Unregistered {}", regImp.getClass().getName());
129 if (registeredRenderers.isEmpty() && endpointRpcRegistry != null) {
130 synchronized (EndpointRpcRegistry.class) {
131 if (registeredRenderers.isEmpty()
132 && endpointRpcRegistry != null) {
133 endpointRpcRegistry.rpcRegistration.close();
134 endpointRpcRegistry = null;
143 * @param dataProvider
147 private EndpointRpcRegistry(DataBroker dataProvider,
148 RpcProviderRegistry rpcRegistry,
149 ScheduledExecutorService executor) {
150 this.dataProvider = dataProvider;
151 this.executor = executor;
152 this.rpcRegistry = rpcRegistry;
154 if (this.rpcRegistry != null) {
156 this.rpcRegistry.addRpcImplementation(EndpointService.class, this);
157 LOG.debug("Added RPC Implementation Correctly");
159 rpcRegistration = null;
161 if (dataProvider != null) {
162 InstanceIdentifier<Endpoints> iid =
163 InstanceIdentifier.builder(Endpoints.class).build();
164 WriteTransaction t = this.dataProvider.newWriteOnlyTransaction();
165 t.put(LogicalDatastoreType.OPERATIONAL,
166 iid, new EndpointsBuilder().build());
167 CheckedFuture<Void, TransactionCommitFailedException> f = t.submit();
168 Futures.addCallback(f, new FutureCallback<Void>() {
170 public void onFailure(Throwable t) {
171 LOG.error("Could not write endpoint base container", t);
175 public void onSuccess(Void result) {
181 // XXX TODO - age out endpoint data and remove
182 // endpoint group/condition mappings with no conditions
186 * Construct an endpoint with the appropriate augmentations from the
187 * endpoint input. Each concrete implementation can provides its specifics
193 private EndpointBuilder buildEndpoint(RegisterEndpointInput input) {
194 EndpointBuilder eb = new EndpointBuilder(input);
195 for (Entry<String, EpRendererAugmentation> entry : registeredRenderers
198 entry.getValue().buildEndpointAugmentation(eb, input);
199 } catch (Throwable t) {
200 LOG.warn("Endpoint Augmentation error while processing "
201 + entry.getKey() + ". Reason: ", t);
208 * Construct an L3 endpoint with the appropriate augmentations from the
209 * endpoint input. Each concrete implementation can provides its specifics
215 private EndpointL3Builder buildEndpointL3(RegisterEndpointInput input) {
216 EndpointL3Builder eb = new EndpointL3Builder(input);
217 for (Entry<String, EpRendererAugmentation> entry : registeredRenderers
220 entry.getValue().buildEndpointL3Augmentation(eb, input);
221 } catch (Throwable t) {
222 LOG.warn("L3 endpoint Augmentation error while processing "
223 + entry.getKey() + ". Reason: ", t);
230 * Construct an L3 endpoint with the appropriate augmentations from the
231 * endpoint input. Each concrete implementation can provides its specifics
237 private EndpointL3PrefixBuilder buildL3PrefixEndpoint(RegisterL3PrefixEndpointInput input) {
238 EndpointL3PrefixBuilder eb = new EndpointL3PrefixBuilder(input);
239 for (Entry<String, EpRendererAugmentation> entry : registeredRenderers
242 entry.getValue().buildL3PrefixEndpointAugmentation(eb, input);
243 } catch (Throwable t) {
244 LOG.warn("L3 endpoint Augmentation error while processing "
245 + entry.getKey() + ". Reason: ", t);
252 public Future<RpcResult<Void>>
253 registerEndpoint(RegisterEndpointInput input) {
254 long timestamp = System.currentTimeMillis();
256 // TODO: Replicate RPC feedback implemented in L3Prefix register for
257 // unmet requirements.
258 WriteTransaction t = dataProvider.newWriteOnlyTransaction();
260 if (input.getL2Context() != null &&
261 input.getMacAddress() != null) {
262 Endpoint ep = buildEndpoint(input)
263 .setTimestamp(timestamp)
267 new EndpointKey(ep.getL2Context(), ep.getMacAddress());
268 InstanceIdentifier<Endpoint> iid =
269 InstanceIdentifier.builder(Endpoints.class)
270 .child(Endpoint.class, key)
272 t.put(LogicalDatastoreType.OPERATIONAL, iid, ep);
274 if (input.getL3Address() != null) {
275 for (L3Address l3addr : input.getL3Address()) {
276 EndpointL3Key key3 = new EndpointL3Key(l3addr.getIpAddress(),
277 l3addr.getL3Context());
278 EndpointL3 ep3 = buildEndpointL3(input)
279 .setIpAddress(key3.getIpAddress())
280 .setL3Context(key3.getL3Context())
281 .setTimestamp(timestamp)
283 InstanceIdentifier<EndpointL3> iid_l3 =
284 InstanceIdentifier.builder(Endpoints.class)
285 .child(EndpointL3.class, key3)
287 t.put(LogicalDatastoreType.OPERATIONAL, iid_l3, ep3);
290 ListenableFuture<Void> r = t.submit();
291 return Futures.transform(r, futureTrans, executor);
295 public Future<RpcResult<Void>> registerL3PrefixEndpoint(RegisterL3PrefixEndpointInput input) {
297 if (input.getL3Context() == null) {
298 return Futures.immediateFuture(RpcResultBuilder.<Void> failed()
299 .withError(ErrorType.RPC, "L3 Prefix Endpoint must have L3Context.").build());
301 if (input.getIpPrefix() == null) {
302 return Futures.immediateFuture(RpcResultBuilder.<Void> failed()
303 .withError(ErrorType.RPC, "L3 Prefix Endpoint must have ip-prefix.").build());
306 if (input.getTenant() == null) {
307 return Futures.immediateFuture(RpcResultBuilder.<Void> failed()
308 .withError(ErrorType.RPC, "L3 Prefix Endpoint must have tenant.").build());
311 WriteTransaction t = dataProvider.newWriteOnlyTransaction();
313 long timestamp = System.currentTimeMillis();
315 // TODO: Convert IPPrefix into it's IPv4/IPv6 canonical form.
316 // See org.apache.commons.net.util.SubnetUtils.SubnetInfo
318 EndpointL3PrefixKey epL3PrefixKey = new EndpointL3PrefixKey(input.getIpPrefix(), input.getL3Context());
320 EndpointL3Prefix epL3Prefix = buildL3PrefixEndpoint(input).setTimestamp(timestamp).build();
321 InstanceIdentifier<EndpointL3Prefix> iid_l3prefix =
322 InstanceIdentifier.builder(Endpoints.class)
323 .child(EndpointL3Prefix.class, epL3PrefixKey)
325 t.put(LogicalDatastoreType.OPERATIONAL, iid_l3prefix, epL3Prefix);
327 ListenableFuture<Void> r = t.submit();
328 return Futures.transform(r, futureTrans, executor);
332 public Future<RpcResult<Void>>
333 unregisterEndpoint(UnregisterEndpointInput input) {
334 WriteTransaction t = dataProvider.newWriteOnlyTransaction();
335 if (input.getL2() != null) {
336 for (L2 l2a : input.getL2()) {
338 new EndpointKey(l2a.getL2Context(),
339 l2a.getMacAddress());
340 InstanceIdentifier<Endpoint> iid =
341 InstanceIdentifier.builder(Endpoints.class)
342 .child(Endpoint.class, key).build();
343 t.delete(LogicalDatastoreType.OPERATIONAL, iid);
346 if (input.getL3() != null) {
347 for (L3 l3addr : input.getL3()) {
349 new EndpointL3Key(l3addr.getIpAddress(),
350 l3addr.getL3Context());
351 InstanceIdentifier<EndpointL3> iid_l3 =
352 InstanceIdentifier.builder(Endpoints.class)
353 .child(EndpointL3.class, key3)
355 t.delete(LogicalDatastoreType.OPERATIONAL, iid_l3);
358 // TODO: Implement L3Prefix
360 ListenableFuture<Void> r = t.submit();
361 return Futures.transform(r, futureTrans, executor);
365 public Future<RpcResult<Void>>
366 setEndpointGroupConditions(SetEndpointGroupConditionsInput input) {
367 WriteTransaction t = dataProvider.newWriteOnlyTransaction();
369 ConditionMappingKey key =
370 new ConditionMappingKey(input.getEndpointGroup());
372 for (EndpointGroupCondition condition : input.getEndpointGroupCondition()) {
373 EndpointGroupConditionKey ckey =
374 new EndpointGroupConditionKey(condition.getCondition());
375 InstanceIdentifier<EndpointGroupCondition> iid =
376 InstanceIdentifier.builder(Endpoints.class)
377 .child(ConditionMapping.class, key)
378 .child(EndpointGroupCondition.class, ckey)
380 t.put(LogicalDatastoreType.OPERATIONAL, iid, condition);
383 ListenableFuture<Void> r = t.submit();
384 return Futures.transform(r, futureTrans, executor);
388 public Future<RpcResult<Void>>
389 unsetEndpointGroupConditions(UnsetEndpointGroupConditionsInput input) {
390 WriteTransaction t = dataProvider.newWriteOnlyTransaction();
392 ConditionMappingKey key =
393 new ConditionMappingKey(input.getEndpointGroup());
395 for (EndpointGroupCondition condition : input.getEndpointGroupCondition()) {
396 EndpointGroupConditionKey ckey =
397 new EndpointGroupConditionKey(condition.getCondition());
398 InstanceIdentifier<EndpointGroupCondition> iid =
399 InstanceIdentifier.builder(Endpoints.class)
400 .child(ConditionMapping.class, key)
401 .child(EndpointGroupCondition.class, ckey)
404 t.delete(LogicalDatastoreType.OPERATIONAL, iid);
407 ListenableFuture<Void> r = t.submit();
408 return Futures.transform(r, futureTrans, executor);
411 Function<Void, RpcResult<Void>> futureTrans =
412 new Function<Void, RpcResult<Void>>() {
414 public RpcResult<Void> apply(Void input) {
415 return RpcResultBuilder.<Void> success().build();