Add session-id to the operational datastore
[netconf.git] / apps / netconf-topology-singleton / src / main / java / org / opendaylight / netconf / topology / singleton / impl / ProxyDOMActionService.java
1 /*
2  * Copyright (C) 2019 Ericsson Software Technology AB. All rights reserved.
3  *
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
7  */
8 package org.opendaylight.netconf.topology.singleton.impl;
9
10 import static java.util.Objects.requireNonNull;
11
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.sal.connect.api.RemoteDeviceId;
29 import org.opendaylight.netconf.sal.connect.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;
42
43 /**
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}.
47  */
48 public class ProxyDOMActionService implements Actions.Normalized {
49     private static final Logger LOG = LoggerFactory.getLogger(ProxyDOMActionService.class);
50
51     private final RemoteDeviceId id;
52     private final ActorRef masterActorRef;
53     private final ActorSystem actorSystem;
54     private final Timeout actorResponseWaitTime;
55
56     /**
57      * Constructor for {@code ProxyDOMActionService}.
58      *
59      * @param actorSystem ActorSystem
60      * @param masterActorRef ActorRef
61      * @param remoteDeviceId {@link org.opendaylight.netconf.sal.connect.api.RemoteDeviceId} ref
62      * @param actorResponseWaitTime Timeout
63      */
64     public ProxyDOMActionService(final ActorSystem actorSystem, final ActorRef masterActorRef,
65         final RemoteDeviceId remoteDeviceId, final Timeout actorResponseWaitTime) {
66         id = remoteDeviceId;
67         this.actorSystem = requireNonNull(actorSystem);
68         this.masterActorRef = requireNonNull(masterActorRef);
69         this.actorResponseWaitTime = requireNonNull(actorResponseWaitTime);
70     }
71
72     @Override
73     public FluentFuture<DOMActionResult> invokeAction(final Absolute type,
74             final DOMDataTreeIdentifier domDataTreeIdentifier, final ContainerNode input) {
75         requireNonNull(type);
76         requireNonNull(input);
77         requireNonNull(domDataTreeIdentifier);
78
79         LOG.info("{}: Action Operation invoked with schema type: {} and node: {}.", id, type, input);
80         final ContainerNodeMessage containerNodeMessage = new ContainerNodeMessage(input);
81
82         final Future<Object> scalaFuture = Patterns.ask(masterActorRef, new InvokeActionMessage(
83             new SchemaPathMessage(type), containerNodeMessage, domDataTreeIdentifier), actorResponseWaitTime);
84
85         final SettableFuture<DOMActionResult> settableFuture = SettableFuture.create();
86
87         scalaFuture.onComplete(new OnComplete<>() {
88             @Override
89             public void onComplete(final Throwable failure, final Object response) {
90                 if (failure != null) {
91                     if (failure instanceof ClusteringActionException) {
92                         settableFuture.setException(failure);
93                     } else {
94                         settableFuture.setException(new ClusteringActionException(
95                             id + ": Exception during remote Action invocation.", failure));
96                     }
97                     return;
98                 }
99
100                 if (response instanceof EmptyResultResponse) {
101                     settableFuture.set(null);
102                     return;
103                 }
104                 final Collection<? extends RpcError> errors = ((InvokeActionMessageReply) response).getRpcErrors();
105
106                 final ContainerNodeMessage containerNodeMessage =
107                     ((InvokeActionMessageReply) response).getContainerNodeMessage();
108
109                 final DOMActionResult result;
110
111                 if (containerNodeMessage == null) {
112                     result = new SimpleDOMActionResult(ImmutableList.copyOf(errors));
113                 } else {
114                     result = new SimpleDOMActionResult(containerNodeMessage.getNode(), ImmutableList.copyOf(errors));
115                 }
116                 settableFuture.set(result);
117             }
118         }, actorSystem.dispatcher());
119
120         return FluentFuture.from(settableFuture);
121     }
122
123     @Override
124     public ClassToInstanceMap<DOMActionServiceExtension> getExtensions() {
125         return ImmutableClassToInstanceMap.of();
126     }
127 }