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.groupbasedpolicy.api.EpRendererAugmentation;
24 import org.opendaylight.groupbasedpolicy.api.EpRendererAugmentationRegistry;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.EndpointService;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.Endpoints;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.EndpointsBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInput;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterL3PrefixEndpointInput;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.SetEndpointGroupConditionsInput;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.UnregisterEndpointInput;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.UnsetEndpointGroupConditionsInput;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.fields.L3Address;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.ConditionMapping;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.ConditionMappingKey;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointKey;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Builder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Key;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Prefix;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3PrefixBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3PrefixKey;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.has.endpoint.group.conditions.EndpointGroupCondition;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.has.endpoint.group.conditions.EndpointGroupConditionKey;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.unregister.endpoint.input.L2;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.unregister.endpoint.input.L3;
49 import org.opendaylight.yangtools.yang.binding.Augmentation;
50 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
51 import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
52 import org.opendaylight.yangtools.yang.common.RpcResult;
53 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
54 import org.slf4j.Logger;
55 import org.slf4j.LoggerFactory;
57 import com.google.common.base.Function;
58 import com.google.common.util.concurrent.CheckedFuture;
59 import com.google.common.util.concurrent.FutureCallback;
60 import com.google.common.util.concurrent.Futures;
61 import com.google.common.util.concurrent.ListenableFuture;
64 * Endpoint registry provides a scalable store for accessing and updating
65 * information about endpoints.
67 public class EndpointRpcRegistry implements EndpointService, EpRendererAugmentationRegistry, AutoCloseable {
68 private static final Logger LOG =
69 LoggerFactory.getLogger(EndpointRpcRegistry.class);
71 private final DataBroker dataProvider;
72 private final RpcProviderRegistry rpcRegistry;
74 private final BindingAwareBroker.RpcRegistration<EndpointService> rpcRegistration;
76 final static ConcurrentMap<String, EpRendererAugmentation> registeredRenderers = new ConcurrentHashMap<String, EpRendererAugmentation>();
79 * This method registers a renderer for endpoint RPC API. This method
80 * ensures single RPC registration for all renderers since a single RPC
81 * registration is only allowed.
83 * @param epRendererAugmentation
84 * - specific implementation RPC augmentation, if any. Otherwise
88 public void register(EpRendererAugmentation epRendererAugmentation) {
89 if (epRendererAugmentation != null) {
90 registeredRenderers.putIfAbsent(epRendererAugmentation.getClass().getName(), epRendererAugmentation);
91 LOG.info("Registered {}", epRendererAugmentation.getClass().getName());
97 * @param regImp the endpoint augmentation
100 public void unregister(EpRendererAugmentation regImp) {
101 if (regImp == null || !registeredRenderers.containsKey(regImp.getClass().getName())) {
104 registeredRenderers.remove(regImp.getClass().getName());
105 LOG.info("Unregistered {}", regImp.getClass().getName());
111 * @param dataProvider the {@link DataBroker}
112 * @param rpcRegistry the {@link RpcProviderRegistry}
114 public EndpointRpcRegistry(DataBroker dataProvider, RpcProviderRegistry rpcRegistry) {
115 this.dataProvider = dataProvider;
116 this.rpcRegistry = rpcRegistry;
117 if (this.rpcRegistry != null) {
119 this.rpcRegistry.addRpcImplementation(EndpointService.class, this);
120 LOG.debug("Added RPC Implementation Correctly");
122 rpcRegistration = null;
125 if (dataProvider != null) {
126 InstanceIdentifier<Endpoints> iid =
127 InstanceIdentifier.builder(Endpoints.class).build();
128 WriteTransaction t = this.dataProvider.newWriteOnlyTransaction();
129 t.put(LogicalDatastoreType.OPERATIONAL,
130 iid, new EndpointsBuilder().build());
131 CheckedFuture<Void, TransactionCommitFailedException> f = t.submit();
132 Futures.addCallback(f, new FutureCallback<Void>() {
134 public void onFailure(Throwable t) {
135 LOG.error("Could not write endpoint base container", t);
139 public void onSuccess(Void result) {
145 // TODO Be alagalah - age out endpoint data and remove
146 // endpoint group/condition mappings with no conditions
150 public void close() throws Exception {
151 if (rpcRegistration != null) {
152 rpcRegistration.close();
157 * Construct an endpoint with the appropriate augmentations from the
158 * endpoint input. Each concrete implementation can provides its specifics
164 private EndpointBuilder buildEndpoint(RegisterEndpointInput input) {
165 EndpointBuilder eb = new EndpointBuilder(input);
166 for (Entry<String, EpRendererAugmentation> entry : registeredRenderers
169 Map.Entry<Class<? extends Augmentation<Endpoint>>, Augmentation<Endpoint>> augmentationEntry =
170 entry.getValue().buildEndpointAugmentation(input);
171 if (augmentationEntry != null) {
172 eb.addAugmentation(augmentationEntry.getKey(), augmentationEntry.getValue());
174 } catch (Exception e) {
175 LOG.warn("Endpoint Augmentation error while processing "
176 + entry.getKey() + ". Reason: ", e);
183 * Construct an L3 endpoint with the appropriate augmentations from the
184 * endpoint input. Each concrete implementation can provides its specifics
190 private EndpointL3Builder buildEndpointL3(RegisterEndpointInput input) {
191 EndpointL3Builder eb = new EndpointL3Builder(input);
192 for (Entry<String, EpRendererAugmentation> entry : registeredRenderers
195 Map.Entry<Class<? extends Augmentation<EndpointL3>>, Augmentation<EndpointL3>> augmentationEntry =
196 entry.getValue().buildEndpointL3Augmentation(input);
197 if (augmentationEntry != null) {
198 eb.addAugmentation(augmentationEntry.getKey(), augmentationEntry.getValue());
200 } catch (Exception e) {
201 LOG.warn("L3 endpoint Augmentation error while processing "
202 + entry.getKey() + ". Reason: ", e);
209 * Construct an L3 endpoint with the appropriate augmentations from the
210 * endpoint input. Each concrete implementation can provides its specifics
216 private EndpointL3PrefixBuilder buildL3PrefixEndpoint(RegisterL3PrefixEndpointInput input) {
217 EndpointL3PrefixBuilder eb = new EndpointL3PrefixBuilder(input);
218 for (Entry<String, EpRendererAugmentation> entry : registeredRenderers
221 Map.Entry<Class<? extends Augmentation<EndpointL3Prefix>>, Augmentation<EndpointL3Prefix>> augmentationEntry =
222 entry.getValue().buildL3PrefixEndpointAugmentation(input);
223 if (augmentationEntry != null) {
224 eb.addAugmentation(augmentationEntry.getKey(), augmentationEntry.getValue());
226 } catch (Exception e) {
227 LOG.warn("L3 endpoint Augmentation error while processing "
228 + entry.getKey() + ". Reason: ", e);
235 public Future<RpcResult<Void>>
236 registerEndpoint(RegisterEndpointInput input) {
237 long timestamp = System.currentTimeMillis();
239 // TODO: Replicate RPC feedback implemented in L3Prefix register for
240 // unmet requirements.
241 WriteTransaction t = dataProvider.newWriteOnlyTransaction();
243 if (input.getL2Context() != null &&
244 input.getMacAddress() != null) {
245 Endpoint ep = buildEndpoint(input)
246 .setTimestamp(timestamp)
250 new EndpointKey(ep.getL2Context(), ep.getMacAddress());
251 InstanceIdentifier<Endpoint> iid =
252 InstanceIdentifier.builder(Endpoints.class)
253 .child(Endpoint.class, key)
255 t.put(LogicalDatastoreType.OPERATIONAL, iid, ep, true);
257 if (input.getL3Address() != null) {
258 for (L3Address l3addr : input.getL3Address()) {
259 EndpointL3Key key3 = new EndpointL3Key(l3addr.getIpAddress(),
260 l3addr.getL3Context());
261 EndpointL3 ep3 = buildEndpointL3(input)
262 .setIpAddress(key3.getIpAddress())
263 .setL3Context(key3.getL3Context())
264 .setTimestamp(timestamp)
266 InstanceIdentifier<EndpointL3> iid_l3 =
267 InstanceIdentifier.builder(Endpoints.class)
268 .child(EndpointL3.class, key3)
270 t.put(LogicalDatastoreType.OPERATIONAL, iid_l3, ep3, true);
273 ListenableFuture<Void> r = t.submit();
274 return Futures.transform(r, futureTrans);
278 public Future<RpcResult<Void>> registerL3PrefixEndpoint(RegisterL3PrefixEndpointInput input) {
280 if (input.getL3Context() == null) {
281 return Futures.immediateFuture(RpcResultBuilder.<Void> failed()
282 .withError(ErrorType.RPC, "L3 Prefix Endpoint must have L3Context.").build());
284 if (input.getIpPrefix() == null) {
285 return Futures.immediateFuture(RpcResultBuilder.<Void> failed()
286 .withError(ErrorType.RPC, "L3 Prefix Endpoint must have ip-prefix.").build());
289 if (input.getTenant() == null) {
290 return Futures.immediateFuture(RpcResultBuilder.<Void> failed()
291 .withError(ErrorType.RPC, "L3 Prefix Endpoint must have tenant.").build());
294 WriteTransaction t = dataProvider.newWriteOnlyTransaction();
296 long timestamp = System.currentTimeMillis();
298 // TODO: Convert IPPrefix into it's IPv4/IPv6 canonical form.
299 // See org.apache.commons.net.util.SubnetUtils.SubnetInfo
301 EndpointL3PrefixKey epL3PrefixKey = new EndpointL3PrefixKey(input.getIpPrefix(), input.getL3Context());
303 EndpointL3Prefix epL3Prefix = buildL3PrefixEndpoint(input).setTimestamp(timestamp).build();
304 InstanceIdentifier<EndpointL3Prefix> iid_l3prefix =
305 InstanceIdentifier.builder(Endpoints.class)
306 .child(EndpointL3Prefix.class, epL3PrefixKey)
308 t.put(LogicalDatastoreType.OPERATIONAL, iid_l3prefix, epL3Prefix);
310 ListenableFuture<Void> r = t.submit();
311 return Futures.transform(r, futureTrans);
315 public Future<RpcResult<Void>>
316 unregisterEndpoint(UnregisterEndpointInput input) {
317 WriteTransaction t = dataProvider.newWriteOnlyTransaction();
318 if (input.getL2() != null) {
319 for (L2 l2a : input.getL2()) {
321 new EndpointKey(l2a.getL2Context(),
322 l2a.getMacAddress());
323 InstanceIdentifier<Endpoint> iid =
324 InstanceIdentifier.builder(Endpoints.class)
325 .child(Endpoint.class, key).build();
326 t.delete(LogicalDatastoreType.OPERATIONAL, iid);
329 if (input.getL3() != null) {
330 for (L3 l3addr : input.getL3()) {
332 new EndpointL3Key(l3addr.getIpAddress(),
333 l3addr.getL3Context());
334 InstanceIdentifier<EndpointL3> iid_l3 =
335 InstanceIdentifier.builder(Endpoints.class)
336 .child(EndpointL3.class, key3)
338 t.delete(LogicalDatastoreType.OPERATIONAL, iid_l3);
341 // TODO: Implement L3Prefix
343 ListenableFuture<Void> r = t.submit();
344 return Futures.transform(r, futureTrans);
348 public Future<RpcResult<Void>>
349 setEndpointGroupConditions(SetEndpointGroupConditionsInput input) {
350 WriteTransaction t = dataProvider.newWriteOnlyTransaction();
352 ConditionMappingKey key =
353 new ConditionMappingKey(input.getEndpointGroup());
355 for (EndpointGroupCondition condition : input.getEndpointGroupCondition()) {
356 EndpointGroupConditionKey ckey =
357 new EndpointGroupConditionKey(condition.getCondition());
358 InstanceIdentifier<EndpointGroupCondition> iid =
359 InstanceIdentifier.builder(Endpoints.class)
360 .child(ConditionMapping.class, key)
361 .child(EndpointGroupCondition.class, ckey)
363 t.put(LogicalDatastoreType.OPERATIONAL, iid, condition);
366 ListenableFuture<Void> r = t.submit();
367 return Futures.transform(r, futureTrans);
371 public Future<RpcResult<Void>>
372 unsetEndpointGroupConditions(UnsetEndpointGroupConditionsInput input) {
373 WriteTransaction t = dataProvider.newWriteOnlyTransaction();
375 ConditionMappingKey key =
376 new ConditionMappingKey(input.getEndpointGroup());
378 for (EndpointGroupCondition condition : input.getEndpointGroupCondition()) {
379 EndpointGroupConditionKey ckey =
380 new EndpointGroupConditionKey(condition.getCondition());
381 InstanceIdentifier<EndpointGroupCondition> iid =
382 InstanceIdentifier.builder(Endpoints.class)
383 .child(ConditionMapping.class, key)
384 .child(EndpointGroupCondition.class, ckey)
387 t.delete(LogicalDatastoreType.OPERATIONAL, iid);
390 ListenableFuture<Void> r = t.submit();
391 return Futures.transform(r, futureTrans);
394 Function<Void, RpcResult<Void>> futureTrans =
395 new Function<Void, RpcResult<Void>>() {
397 public RpcResult<Void> apply(Void input) {
398 return RpcResultBuilder.<Void> success().build();