2 * Copyright (C) 2019 Ericsson Software Technology AB. 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
8 package org.opendaylight.netconf.topology.singleton.impl;
10 import static java.util.Objects.requireNonNull;
12 import akka.actor.ActorRef;
13 import akka.actor.ActorSystem;
14 import akka.dispatch.OnComplete;
15 import akka.pattern.Patterns;
16 import akka.util.Timeout;
17 import com.google.common.collect.ClassToInstanceMap;
18 import com.google.common.collect.ImmutableClassToInstanceMap;
19 import com.google.common.collect.ImmutableList;
20 import com.google.common.util.concurrent.FluentFuture;
21 import com.google.common.util.concurrent.SettableFuture;
22 import java.util.Collection;
23 import org.opendaylight.mdsal.dom.api.DOMActionResult;
24 import org.opendaylight.mdsal.dom.api.DOMActionService;
25 import org.opendaylight.mdsal.dom.api.DOMActionServiceExtension;
26 import org.opendaylight.mdsal.dom.api.DOMDataTreeIdentifier;
27 import org.opendaylight.mdsal.dom.spi.SimpleDOMActionResult;
28 import org.opendaylight.netconf.client.mdsal.api.RemoteDeviceId;
29 import org.opendaylight.netconf.client.mdsal.api.RemoteDeviceServices.Actions;
30 import org.opendaylight.netconf.topology.singleton.impl.utils.ClusteringActionException;
31 import org.opendaylight.netconf.topology.singleton.messages.ContainerNodeMessage;
32 import org.opendaylight.netconf.topology.singleton.messages.SchemaPathMessage;
33 import org.opendaylight.netconf.topology.singleton.messages.action.InvokeActionMessage;
34 import org.opendaylight.netconf.topology.singleton.messages.action.InvokeActionMessageReply;
35 import org.opendaylight.netconf.topology.singleton.messages.transactions.EmptyResultResponse;
36 import org.opendaylight.yangtools.yang.common.RpcError;
37 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
38 import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
41 import scala.concurrent.Future;
44 * Implementation of {@link DOMActionService} provided by device in Odl-Cluster environment to invoke action.
45 * Communicates action message {@link InvokeActionMessage} to {@link ActorSystem} using {@link ActorRef} and transforms
46 * replied NETCONF message to action result, using {@link SimpleDOMActionResult}.
48 public class ProxyDOMActionService implements Actions.Normalized {
49 private static final Logger LOG = LoggerFactory.getLogger(ProxyDOMActionService.class);
51 private final RemoteDeviceId id;
52 private final ActorRef masterActorRef;
53 private final ActorSystem actorSystem;
54 private final Timeout actorResponseWaitTime;
57 * Constructor for {@code ProxyDOMActionService}.
59 * @param actorSystem ActorSystem
60 * @param masterActorRef ActorRef
61 * @param remoteDeviceId {@link RemoteDeviceId} ref
62 * @param actorResponseWaitTime Timeout
64 public ProxyDOMActionService(final ActorSystem actorSystem, final ActorRef masterActorRef,
65 final RemoteDeviceId remoteDeviceId, final Timeout actorResponseWaitTime) {
67 this.actorSystem = requireNonNull(actorSystem);
68 this.masterActorRef = requireNonNull(masterActorRef);
69 this.actorResponseWaitTime = requireNonNull(actorResponseWaitTime);
73 public FluentFuture<DOMActionResult> invokeAction(final Absolute type,
74 final DOMDataTreeIdentifier domDataTreeIdentifier, final ContainerNode input) {
76 requireNonNull(input);
77 requireNonNull(domDataTreeIdentifier);
79 LOG.info("{}: Action Operation invoked with schema type: {} and node: {}.", id, type, input);
80 final ContainerNodeMessage containerNodeMessage = new ContainerNodeMessage(input);
82 final Future<Object> scalaFuture = Patterns.ask(masterActorRef, new InvokeActionMessage(
83 new SchemaPathMessage(type), containerNodeMessage, domDataTreeIdentifier), actorResponseWaitTime);
85 final SettableFuture<DOMActionResult> settableFuture = SettableFuture.create();
87 scalaFuture.onComplete(new OnComplete<>() {
89 public void onComplete(final Throwable failure, final Object response) {
90 if (failure != null) {
91 if (failure instanceof ClusteringActionException) {
92 settableFuture.setException(failure);
94 settableFuture.setException(new ClusteringActionException(
95 id + ": Exception during remote Action invocation.", failure));
100 if (response instanceof EmptyResultResponse) {
101 settableFuture.set(null);
104 final Collection<? extends RpcError> errors = ((InvokeActionMessageReply) response).getRpcErrors();
106 final ContainerNodeMessage containerNodeMessage =
107 ((InvokeActionMessageReply) response).getContainerNodeMessage();
109 final DOMActionResult result;
111 if (containerNodeMessage == null) {
112 result = new SimpleDOMActionResult(ImmutableList.copyOf(errors));
114 result = new SimpleDOMActionResult(containerNodeMessage.getNode(), ImmutableList.copyOf(errors));
116 settableFuture.set(result);
118 }, actorSystem.dispatcher());
120 return FluentFuture.from(settableFuture);
124 public ClassToInstanceMap<DOMActionServiceExtension> getExtensions() {
125 return ImmutableClassToInstanceMap.of();