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;
12 import java.util.Map.Entry;
13 import java.util.concurrent.ConcurrentHashMap;
14 import java.util.concurrent.ConcurrentMap;
15 import java.util.concurrent.Future;
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.Augmentation;
48 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
49 import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
50 import org.opendaylight.yangtools.yang.common.RpcResult;
51 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
52 import org.slf4j.Logger;
53 import org.slf4j.LoggerFactory;
55 import com.google.common.base.Function;
56 import com.google.common.util.concurrent.CheckedFuture;
57 import com.google.common.util.concurrent.FutureCallback;
58 import com.google.common.util.concurrent.Futures;
59 import com.google.common.util.concurrent.ListenableFuture;
62 * Endpoint registry provides a scalable store for accessing and updating
63 * information about endpoints.
65 public class EndpointRpcRegistry implements EndpointService, AutoCloseable {
66 private static final Logger LOG =
67 LoggerFactory.getLogger(EndpointRpcRegistry.class);
69 private final DataBroker dataProvider;
70 private final RpcProviderRegistry rpcRegistry;
72 private final BindingAwareBroker.RpcRegistration<EndpointService> rpcRegistration;
74 final static ConcurrentMap<String, EpRendererAugmentation> registeredRenderers = new ConcurrentHashMap<String, EpRendererAugmentation>();
77 * This method registers a renderer for endpoint RPC API. This method
78 * ensures single RPC registration for all renderers since a single RPC
79 * registration is only allowed.
81 * @param epRendererAugmentation
82 * - specific implementation RPC augmentation, if any. Otherwise
85 public static void register(EpRendererAugmentation epRendererAugmentation) {
86 if (epRendererAugmentation != null) {
87 registeredRenderers.putIfAbsent(epRendererAugmentation.getClass().getName(), epRendererAugmentation);
88 LOG.info("Registered {}", epRendererAugmentation.getClass().getName());
94 * @param regImp the endpoint augmentation
97 public static void unregister(EpRendererAugmentation regImp) throws Exception {
98 if (regImp == null || !registeredRenderers.containsKey(regImp.getClass().getName())) {
101 registeredRenderers.remove(regImp.getClass().getName());
102 LOG.info("Unregistered {}", regImp.getClass().getName());
108 * @param dataProvider the {@link DataBroker}
109 * @param rpcRegistry the {@link RpcProviderRegistry}
111 public EndpointRpcRegistry(DataBroker dataProvider, RpcProviderRegistry rpcRegistry) {
112 this.dataProvider = dataProvider;
113 this.rpcRegistry = rpcRegistry;
114 if (this.rpcRegistry != null) {
116 this.rpcRegistry.addRpcImplementation(EndpointService.class, this);
117 LOG.debug("Added RPC Implementation Correctly");
119 rpcRegistration = null;
121 if (dataProvider != null) {
122 InstanceIdentifier<Endpoints> iid =
123 InstanceIdentifier.builder(Endpoints.class).build();
124 WriteTransaction t = this.dataProvider.newWriteOnlyTransaction();
125 t.put(LogicalDatastoreType.OPERATIONAL,
126 iid, new EndpointsBuilder().build());
127 CheckedFuture<Void, TransactionCommitFailedException> f = t.submit();
128 Futures.addCallback(f, new FutureCallback<Void>() {
130 public void onFailure(Throwable t) {
131 LOG.error("Could not write endpoint base container", t);
135 public void onSuccess(Void result) {
141 // TODO Be alagalah - age out endpoint data and remove
142 // endpoint group/condition mappings with no conditions
146 public void close() throws Exception {
147 if (rpcRegistration != null) {
148 rpcRegistration.close();
153 * Construct an endpoint with the appropriate augmentations from the
154 * endpoint input. Each concrete implementation can provides its specifics
160 private EndpointBuilder buildEndpoint(RegisterEndpointInput input) {
161 EndpointBuilder eb = new EndpointBuilder(input);
162 for (Entry<String, EpRendererAugmentation> entry : registeredRenderers
165 Map.Entry<Class<? extends Augmentation<Endpoint>>, Augmentation<Endpoint>> augmentationEntry =
166 entry.getValue().buildEndpointAugmentation(input);
167 if (augmentationEntry != null) {
168 eb.addAugmentation(augmentationEntry.getKey(), augmentationEntry.getValue());
170 } catch (Exception e) {
171 LOG.warn("Endpoint Augmentation error while processing "
172 + entry.getKey() + ". Reason: ", e);
179 * Construct an L3 endpoint with the appropriate augmentations from the
180 * endpoint input. Each concrete implementation can provides its specifics
186 private EndpointL3Builder buildEndpointL3(RegisterEndpointInput input) {
187 EndpointL3Builder eb = new EndpointL3Builder(input);
188 for (Entry<String, EpRendererAugmentation> entry : registeredRenderers
191 Map.Entry<Class<? extends Augmentation<EndpointL3>>, Augmentation<EndpointL3>> augmentationEntry =
192 entry.getValue().buildEndpointL3Augmentation(input);
193 if (augmentationEntry != null) {
194 eb.addAugmentation(augmentationEntry.getKey(), augmentationEntry.getValue());
196 } catch (Exception e) {
197 LOG.warn("L3 endpoint Augmentation error while processing "
198 + entry.getKey() + ". Reason: ", e);
205 * Construct an L3 endpoint with the appropriate augmentations from the
206 * endpoint input. Each concrete implementation can provides its specifics
212 private EndpointL3PrefixBuilder buildL3PrefixEndpoint(RegisterL3PrefixEndpointInput input) {
213 EndpointL3PrefixBuilder eb = new EndpointL3PrefixBuilder(input);
214 for (Entry<String, EpRendererAugmentation> entry : registeredRenderers
217 Map.Entry<Class<? extends Augmentation<EndpointL3Prefix>>, Augmentation<EndpointL3Prefix>> augmentationEntry =
218 entry.getValue().buildL3PrefixEndpointAugmentation(input);
219 if (augmentationEntry != null) {
220 eb.addAugmentation(augmentationEntry.getKey(), augmentationEntry.getValue());
222 } catch (Exception e) {
223 LOG.warn("L3 endpoint Augmentation error while processing "
224 + entry.getKey() + ". Reason: ", e);
231 public Future<RpcResult<Void>>
232 registerEndpoint(RegisterEndpointInput input) {
233 long timestamp = System.currentTimeMillis();
235 // TODO: Replicate RPC feedback implemented in L3Prefix register for
236 // unmet requirements.
237 WriteTransaction t = dataProvider.newWriteOnlyTransaction();
239 if (input.getL2Context() != null &&
240 input.getMacAddress() != null) {
241 Endpoint ep = buildEndpoint(input)
242 .setTimestamp(timestamp)
246 new EndpointKey(ep.getL2Context(), ep.getMacAddress());
247 InstanceIdentifier<Endpoint> iid =
248 InstanceIdentifier.builder(Endpoints.class)
249 .child(Endpoint.class, key)
251 t.put(LogicalDatastoreType.OPERATIONAL, iid, ep, true);
253 if (input.getL3Address() != null) {
254 for (L3Address l3addr : input.getL3Address()) {
255 EndpointL3Key key3 = new EndpointL3Key(l3addr.getIpAddress(),
256 l3addr.getL3Context());
257 EndpointL3 ep3 = buildEndpointL3(input)
258 .setIpAddress(key3.getIpAddress())
259 .setL3Context(key3.getL3Context())
260 .setTimestamp(timestamp)
262 InstanceIdentifier<EndpointL3> iid_l3 =
263 InstanceIdentifier.builder(Endpoints.class)
264 .child(EndpointL3.class, key3)
266 t.put(LogicalDatastoreType.OPERATIONAL, iid_l3, ep3, true);
269 ListenableFuture<Void> r = t.submit();
270 return Futures.transform(r, futureTrans);
274 public Future<RpcResult<Void>> registerL3PrefixEndpoint(RegisterL3PrefixEndpointInput input) {
276 if (input.getL3Context() == null) {
277 return Futures.immediateFuture(RpcResultBuilder.<Void> failed()
278 .withError(ErrorType.RPC, "L3 Prefix Endpoint must have L3Context.").build());
280 if (input.getIpPrefix() == null) {
281 return Futures.immediateFuture(RpcResultBuilder.<Void> failed()
282 .withError(ErrorType.RPC, "L3 Prefix Endpoint must have ip-prefix.").build());
285 if (input.getTenant() == null) {
286 return Futures.immediateFuture(RpcResultBuilder.<Void> failed()
287 .withError(ErrorType.RPC, "L3 Prefix Endpoint must have tenant.").build());
290 WriteTransaction t = dataProvider.newWriteOnlyTransaction();
292 long timestamp = System.currentTimeMillis();
294 // TODO: Convert IPPrefix into it's IPv4/IPv6 canonical form.
295 // See org.apache.commons.net.util.SubnetUtils.SubnetInfo
297 EndpointL3PrefixKey epL3PrefixKey = new EndpointL3PrefixKey(input.getIpPrefix(), input.getL3Context());
299 EndpointL3Prefix epL3Prefix = buildL3PrefixEndpoint(input).setTimestamp(timestamp).build();
300 InstanceIdentifier<EndpointL3Prefix> iid_l3prefix =
301 InstanceIdentifier.builder(Endpoints.class)
302 .child(EndpointL3Prefix.class, epL3PrefixKey)
304 t.put(LogicalDatastoreType.OPERATIONAL, iid_l3prefix, epL3Prefix);
306 ListenableFuture<Void> r = t.submit();
307 return Futures.transform(r, futureTrans);
311 public Future<RpcResult<Void>>
312 unregisterEndpoint(UnregisterEndpointInput input) {
313 WriteTransaction t = dataProvider.newWriteOnlyTransaction();
314 if (input.getL2() != null) {
315 for (L2 l2a : input.getL2()) {
317 new EndpointKey(l2a.getL2Context(),
318 l2a.getMacAddress());
319 InstanceIdentifier<Endpoint> iid =
320 InstanceIdentifier.builder(Endpoints.class)
321 .child(Endpoint.class, key).build();
322 t.delete(LogicalDatastoreType.OPERATIONAL, iid);
325 if (input.getL3() != null) {
326 for (L3 l3addr : input.getL3()) {
328 new EndpointL3Key(l3addr.getIpAddress(),
329 l3addr.getL3Context());
330 InstanceIdentifier<EndpointL3> iid_l3 =
331 InstanceIdentifier.builder(Endpoints.class)
332 .child(EndpointL3.class, key3)
334 t.delete(LogicalDatastoreType.OPERATIONAL, iid_l3);
337 // TODO: Implement L3Prefix
339 ListenableFuture<Void> r = t.submit();
340 return Futures.transform(r, futureTrans);
344 public Future<RpcResult<Void>>
345 setEndpointGroupConditions(SetEndpointGroupConditionsInput input) {
346 WriteTransaction t = dataProvider.newWriteOnlyTransaction();
348 ConditionMappingKey key =
349 new ConditionMappingKey(input.getEndpointGroup());
351 for (EndpointGroupCondition condition : input.getEndpointGroupCondition()) {
352 EndpointGroupConditionKey ckey =
353 new EndpointGroupConditionKey(condition.getCondition());
354 InstanceIdentifier<EndpointGroupCondition> iid =
355 InstanceIdentifier.builder(Endpoints.class)
356 .child(ConditionMapping.class, key)
357 .child(EndpointGroupCondition.class, ckey)
359 t.put(LogicalDatastoreType.OPERATIONAL, iid, condition);
362 ListenableFuture<Void> r = t.submit();
363 return Futures.transform(r, futureTrans);
367 public Future<RpcResult<Void>>
368 unsetEndpointGroupConditions(UnsetEndpointGroupConditionsInput input) {
369 WriteTransaction t = dataProvider.newWriteOnlyTransaction();
371 ConditionMappingKey key =
372 new ConditionMappingKey(input.getEndpointGroup());
374 for (EndpointGroupCondition condition : input.getEndpointGroupCondition()) {
375 EndpointGroupConditionKey ckey =
376 new EndpointGroupConditionKey(condition.getCondition());
377 InstanceIdentifier<EndpointGroupCondition> iid =
378 InstanceIdentifier.builder(Endpoints.class)
379 .child(ConditionMapping.class, key)
380 .child(EndpointGroupCondition.class, ckey)
383 t.delete(LogicalDatastoreType.OPERATIONAL, iid);
386 ListenableFuture<Void> r = t.submit();
387 return Futures.transform(r, futureTrans);
390 Function<Void, RpcResult<Void>> futureTrans =
391 new Function<Void, RpcResult<Void>>() {
393 public RpcResult<Void> apply(Void input) {
394 return RpcResultBuilder.<Void> success().build();