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.ImmutableList;
18 import com.google.common.util.concurrent.FluentFuture;
19 import com.google.common.util.concurrent.SettableFuture;
20 import java.util.Collection;
21 import org.opendaylight.mdsal.dom.api.DOMActionResult;
22 import org.opendaylight.mdsal.dom.api.DOMActionService;
23 import org.opendaylight.mdsal.dom.api.DOMDataTreeIdentifier;
24 import org.opendaylight.mdsal.dom.spi.SimpleDOMActionResult;
25 import org.opendaylight.netconf.client.mdsal.api.RemoteDeviceId;
26 import org.opendaylight.netconf.client.mdsal.api.RemoteDeviceServices.Actions;
27 import org.opendaylight.netconf.topology.singleton.impl.utils.ClusteringActionException;
28 import org.opendaylight.netconf.topology.singleton.messages.ContainerNodeMessage;
29 import org.opendaylight.netconf.topology.singleton.messages.SchemaPathMessage;
30 import org.opendaylight.netconf.topology.singleton.messages.action.InvokeActionMessage;
31 import org.opendaylight.netconf.topology.singleton.messages.action.InvokeActionMessageReply;
32 import org.opendaylight.netconf.topology.singleton.messages.transactions.EmptyResultResponse;
33 import org.opendaylight.yangtools.yang.common.RpcError;
34 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
35 import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
38 import scala.concurrent.Future;
41 * Implementation of {@link DOMActionService} provided by device in Odl-Cluster environment to invoke action.
42 * Communicates action message {@link InvokeActionMessage} to {@link ActorSystem} using {@link ActorRef} and transforms
43 * replied NETCONF message to action result, using {@link SimpleDOMActionResult}.
45 public class ProxyDOMActionService implements Actions.Normalized {
46 private static final Logger LOG = LoggerFactory.getLogger(ProxyDOMActionService.class);
48 private final RemoteDeviceId id;
49 private final ActorRef masterActorRef;
50 private final ActorSystem actorSystem;
51 private final Timeout actorResponseWaitTime;
54 * Constructor for {@code ProxyDOMActionService}.
56 * @param actorSystem ActorSystem
57 * @param masterActorRef ActorRef
58 * @param remoteDeviceId {@link RemoteDeviceId} ref
59 * @param actorResponseWaitTime Timeout
61 public ProxyDOMActionService(final ActorSystem actorSystem, final ActorRef masterActorRef,
62 final RemoteDeviceId remoteDeviceId, final Timeout actorResponseWaitTime) {
64 this.actorSystem = requireNonNull(actorSystem);
65 this.masterActorRef = requireNonNull(masterActorRef);
66 this.actorResponseWaitTime = requireNonNull(actorResponseWaitTime);
70 public FluentFuture<DOMActionResult> invokeAction(final Absolute type,
71 final DOMDataTreeIdentifier domDataTreeIdentifier, final ContainerNode input) {
73 requireNonNull(input);
74 requireNonNull(domDataTreeIdentifier);
76 LOG.info("{}: Action Operation invoked with schema type: {} and node: {}.", id, type, input);
77 final ContainerNodeMessage containerNodeMessage = new ContainerNodeMessage(input);
79 final Future<Object> scalaFuture = Patterns.ask(masterActorRef, new InvokeActionMessage(
80 new SchemaPathMessage(type), containerNodeMessage, domDataTreeIdentifier), actorResponseWaitTime);
82 final SettableFuture<DOMActionResult> settableFuture = SettableFuture.create();
84 scalaFuture.onComplete(new OnComplete<>() {
86 public void onComplete(final Throwable failure, final Object response) {
87 if (failure != null) {
88 if (failure instanceof ClusteringActionException) {
89 settableFuture.setException(failure);
91 settableFuture.setException(new ClusteringActionException(
92 id + ": Exception during remote Action invocation.", failure));
97 if (response instanceof EmptyResultResponse) {
98 settableFuture.set(null);
101 final Collection<? extends RpcError> errors = ((InvokeActionMessageReply) response).getRpcErrors();
103 final ContainerNodeMessage containerNodeMessage =
104 ((InvokeActionMessageReply) response).getContainerNodeMessage();
106 final DOMActionResult result;
108 if (containerNodeMessage == null) {
109 result = new SimpleDOMActionResult(ImmutableList.copyOf(errors));
111 result = new SimpleDOMActionResult(containerNodeMessage.getNode(), ImmutableList.copyOf(errors));
113 settableFuture.set(result);
115 }, actorSystem.dispatcher());
117 return FluentFuture.from(settableFuture);