Update MRI projects for Aluminium
[netconf.git] / netconf / netconf-topology-singleton / src / main / java / org / opendaylight / netconf / topology / singleton / impl / actors / NetconfNodeActor.java
index a3f73e1446d045c3a00d0320d859b67a4a442a14..cac94da1a19a86bfbe9538fad023b68d50c3d991 100644 (file)
@@ -18,6 +18,7 @@ import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.MoreExecutors;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 import java.io.IOException;
 import java.util.List;
 import java.util.stream.Collectors;
@@ -25,7 +26,10 @@ import org.opendaylight.controller.cluster.common.actor.AbstractUntypedActor;
 import org.opendaylight.controller.cluster.schema.provider.RemoteYangTextSourceProvider;
 import org.opendaylight.controller.cluster.schema.provider.impl.RemoteSchemaProvider;
 import org.opendaylight.controller.cluster.schema.provider.impl.YangTextSchemaSourceSerializationProxy;
+import org.opendaylight.mdsal.dom.api.DOMActionResult;
+import org.opendaylight.mdsal.dom.api.DOMActionService;
 import org.opendaylight.mdsal.dom.api.DOMDataBroker;
+import org.opendaylight.mdsal.dom.api.DOMDataTreeIdentifier;
 import org.opendaylight.mdsal.dom.api.DOMDataTreeReadTransaction;
 import org.opendaylight.mdsal.dom.api.DOMDataTreeReadWriteTransaction;
 import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteTransaction;
@@ -33,11 +37,13 @@ import org.opendaylight.mdsal.dom.api.DOMMountPointService;
 import org.opendaylight.mdsal.dom.api.DOMRpcResult;
 import org.opendaylight.mdsal.dom.api.DOMRpcService;
 import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
+import org.opendaylight.netconf.topology.singleton.impl.ProxyDOMActionService;
 import org.opendaylight.netconf.topology.singleton.impl.ProxyDOMRpcService;
 import org.opendaylight.netconf.topology.singleton.impl.ProxyYangTextSourceProvider;
 import org.opendaylight.netconf.topology.singleton.impl.SlaveSalFacade;
 import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologySetup;
 import org.opendaylight.netconf.topology.singleton.messages.AskForMasterMountPoint;
+import org.opendaylight.netconf.topology.singleton.messages.ContainerNodeMessage;
 import org.opendaylight.netconf.topology.singleton.messages.CreateInitialMasterActorData;
 import org.opendaylight.netconf.topology.singleton.messages.MasterActorDataInitialized;
 import org.opendaylight.netconf.topology.singleton.messages.NormalizedNodeMessage;
@@ -47,6 +53,8 @@ import org.opendaylight.netconf.topology.singleton.messages.RefreshSlaveActor;
 import org.opendaylight.netconf.topology.singleton.messages.RegisterMountPoint;
 import org.opendaylight.netconf.topology.singleton.messages.UnregisterSlaveMountPoint;
 import org.opendaylight.netconf.topology.singleton.messages.YangTextSchemaSourceRequest;
+import org.opendaylight.netconf.topology.singleton.messages.action.InvokeActionMessage;
+import org.opendaylight.netconf.topology.singleton.messages.action.InvokeActionMessageReply;
 import org.opendaylight.netconf.topology.singleton.messages.rpc.InvokeRpcMessage;
 import org.opendaylight.netconf.topology.singleton.messages.rpc.InvokeRpcMessageReply;
 import org.opendaylight.netconf.topology.singleton.messages.transactions.EmptyResultResponse;
@@ -55,7 +63,6 @@ import org.opendaylight.netconf.topology.singleton.messages.transactions.NewRead
 import org.opendaylight.netconf.topology.singleton.messages.transactions.NewWriteTransactionRequest;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
 import org.opendaylight.yangtools.yang.model.repo.api.EffectiveModelContextFactory;
 import org.opendaylight.yangtools.yang.model.repo.api.SchemaRepository;
@@ -77,6 +84,7 @@ public class NetconfNodeActor extends AbstractUntypedActor {
     private NetconfTopologySetup setup;
     private List<SourceIdentifier> sourceIdentifiers;
     private DOMRpcService deviceRpc;
+    private DOMActionService deviceAction;
     private SlaveSalFacade slaveSalManager;
     private DOMDataBroker deviceDataBroker;
     //readTxActor can be shared
@@ -114,23 +122,24 @@ public class NetconfNodeActor extends AbstractUntypedActor {
             final DOMDataTreeReadTransaction tx = deviceDataBroker.newReadOnlyTransaction();
             readTxActor = context().actorOf(ReadTransactionActor.props(tx));
             this.deviceRpc = masterActorData.getDeviceRpc();
+            this.deviceAction = masterActorData.getDeviceAction();
 
             sender().tell(new MasterActorDataInitialized(), self());
 
             LOG.debug("{}: Master is ready.", id);
 
-        } else if (message instanceof  RefreshSetupMasterActorData) {
+        } else if (message instanceof RefreshSetupMasterActorData) {
             setup = ((RefreshSetupMasterActorData) message).getNetconfTopologyDeviceSetup();
             id = ((RefreshSetupMasterActorData) message).getRemoteDeviceId();
             sender().tell(new MasterActorDataInitialized(), self());
         } else if (message instanceof AskForMasterMountPoint) { // master
-            AskForMasterMountPoint askForMasterMountPoint = (AskForMasterMountPoint)message;
+            AskForMasterMountPoint askForMasterMountPoint = (AskForMasterMountPoint) message;
 
             // only master contains reference to deviceDataBroker
             if (deviceDataBroker != null) {
                 LOG.debug("{}: Sending RegisterMountPoint reply to {}", id, askForMasterMountPoint.getSlaveActorRef());
                 askForMasterMountPoint.getSlaveActorRef().tell(new RegisterMountPoint(sourceIdentifiers, self()),
-                        sender());
+                    sender());
             } else {
                 LOG.warn("{}: Received {} but we don't appear to be the master", id, askForMasterMountPoint);
                 sender().tell(new Failure(new NotMasterException(self())), self());
@@ -163,9 +172,13 @@ public class NetconfNodeActor extends AbstractUntypedActor {
         } else if (message instanceof InvokeRpcMessage) { // master
             final InvokeRpcMessage invokeRpcMessage = (InvokeRpcMessage) message;
             invokeSlaveRpc(invokeRpcMessage.getSchemaPath(), invokeRpcMessage.getNormalizedNodeMessage(), sender());
-
+        } else if (message instanceof InvokeActionMessage) { // master
+            final InvokeActionMessage invokeActionMessage = (InvokeActionMessage) message;
+            LOG.info("InvokeActionMessage Details : {}", invokeActionMessage.toString());
+            invokeSlaveAction(invokeActionMessage.getSchemaPath(), invokeActionMessage.getContainerNodeMessage(),
+                invokeActionMessage.getDOMDataTreeIdentifier(), sender());
         } else if (message instanceof RegisterMountPoint) { //slaves
-            RegisterMountPoint registerMountPoint = (RegisterMountPoint)message;
+            RegisterMountPoint registerMountPoint = (RegisterMountPoint) message;
             sourceIdentifiers = registerMountPoint.getSourceIndentifiers();
             registerSlaveMountPoint(registerMountPoint.getMasterActorRef());
             sender().tell(new Success(null), self());
@@ -178,7 +191,6 @@ public class NetconfNodeActor extends AbstractUntypedActor {
             setup = ((RefreshSlaveActor) message).getSetup();
             schemaRepository = ((RefreshSlaveActor) message).getSchemaRepository();
         }
-
     }
 
     @Override
@@ -228,7 +240,7 @@ public class NetconfNodeActor extends AbstractUntypedActor {
         LOG.debug("{}: invokeSlaveRpc for {}, input: {} on rpc service {}", id, schemaPath, normalizedNodeMessage,
                 deviceRpc);
 
-        final ListenableFuture<DOMRpcResult> rpcResult = deviceRpc.invokeRpc(schemaPath,
+        final ListenableFuture<? extends DOMRpcResult> rpcResult = deviceRpc.invokeRpc(schemaPath,
                 normalizedNodeMessage != null ? normalizedNodeMessage.getNode() : null);
 
         Futures.addCallback(rpcResult, new FutureCallback<DOMRpcResult>() {
@@ -242,7 +254,7 @@ public class NetconfNodeActor extends AbstractUntypedActor {
                 }
                 NormalizedNodeMessage nodeMessageReply = null;
                 if (domRpcResult.getResult() != null) {
-                    nodeMessageReply = new NormalizedNodeMessage(YangInstanceIdentifier.EMPTY,
+                    nodeMessageReply = new NormalizedNodeMessage(YangInstanceIdentifier.empty(),
                             domRpcResult.getResult());
                 }
                 recipient.tell(new InvokeRpcMessageReply(nodeMessageReply, domRpcResult.getErrors()), getSelf());
@@ -255,6 +267,45 @@ public class NetconfNodeActor extends AbstractUntypedActor {
         }, MoreExecutors.directExecutor());
     }
 
+    /**
+     * Invoking Action on Slave Node in Odl Cluster Environment.
+     *
+     * @param schemaPath {@link SchemaPath}
+     * @param containerNodeMessage {@link ContainerNodeMessage}
+     * @param domDataTreeIdentifier {@link DOMDataTreeIdentifier}
+     * @param recipient {@link ActorRef}
+     */
+    private void invokeSlaveAction(final SchemaPath schemaPath, final ContainerNodeMessage containerNodeMessage,
+        final DOMDataTreeIdentifier domDataTreeIdentifier, final ActorRef recipient) {
+        LOG.info("{}: invokeSlaveAction for {}, input: {}, identifier: {} on action service {}", id, schemaPath,
+            containerNodeMessage, domDataTreeIdentifier, deviceAction);
+
+        final ListenableFuture<? extends DOMActionResult> actionResult = deviceAction.invokeAction(schemaPath,
+            domDataTreeIdentifier, containerNodeMessage != null ? containerNodeMessage.getNode() : null);
+
+        Futures.addCallback(actionResult, new FutureCallback<DOMActionResult>() {
+
+            @Override
+            public void onSuccess(final DOMActionResult domActionResult) {
+                LOG.debug("{}: invokeSlaveAction for {}, domActionResult: {}", id, schemaPath, domActionResult);
+                if (domActionResult == null) {
+                    recipient.tell(new EmptyResultResponse(), getSender());
+                    return;
+                }
+
+                //Check DomActionResult containing Ok onSuccess pass empty nodeMessageReply
+                ContainerNodeMessage nodeMessageReply = domActionResult.getOutput().map(ContainerNodeMessage::new)
+                        .orElse(null);
+                recipient.tell(new InvokeActionMessageReply(nodeMessageReply, domActionResult.getErrors()), getSelf());
+            }
+
+            @Override
+            public void onFailure(final Throwable throwable) {
+                recipient.tell(new Failure(throwable), getSelf());
+            }
+        }, MoreExecutors.directExecutor());
+    }
+
     private void registerSlaveMountPoint(final ActorRef masterReference) {
         unregisterSlaveMountPoint();
 
@@ -263,10 +314,18 @@ public class NetconfNodeActor extends AbstractUntypedActor {
         resolveSchemaContext(createSchemaContextFactory(masterReference), slaveSalManager, masterReference, 1);
     }
 
+    @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD",
+            justification = "https://github.com/spotbugs/spotbugs/issues/811")
     private DOMRpcService getDOMRpcService(final ActorRef masterReference) {
         return new ProxyDOMRpcService(setup.getActorSystem(), masterReference, id, actorResponseWaitTime);
     }
 
+    @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD",
+            justification = "https://github.com/spotbugs/spotbugs/issues/811")
+    private DOMActionService getDOMActionService(final ActorRef masterReference) {
+        return new ProxyDOMActionService(setup.getActorSystem(), masterReference, id, actorResponseWaitTime);
+    }
+
     private EffectiveModelContextFactory createSchemaContextFactory(final ActorRef masterReference) {
         final RemoteYangTextSourceProvider remoteYangTextSourceProvider =
                 new ProxyYangTextSourceProvider(masterReference, getContext().dispatcher(), actorResponseWaitTime);
@@ -286,9 +345,9 @@ public class NetconfNodeActor extends AbstractUntypedActor {
             final SlaveSalFacade localSlaveSalManager, final ActorRef masterReference, final int tries) {
         final ListenableFuture<EffectiveModelContext> schemaContextFuture =
                 schemaContextFactory.createEffectiveModelContext(sourceIdentifiers);
-        Futures.addCallback(schemaContextFuture, new FutureCallback<SchemaContext>() {
+        Futures.addCallback(schemaContextFuture, new FutureCallback<EffectiveModelContext>() {
             @Override
-            public void onSuccess(final SchemaContext result) {
+            public void onSuccess(final EffectiveModelContext result) {
                 executeInSelf(() -> {
                     // Make sure the slaveSalManager instance hasn't changed since we initiated the schema context
                     // resolution.
@@ -296,7 +355,7 @@ public class NetconfNodeActor extends AbstractUntypedActor {
                         LOG.info("{}: Schema context resolved: {} - registering slave mount point",
                                 id, result.getModules());
                         slaveSalManager.registerSlaveMountPoint(result, getDOMRpcService(masterReference),
-                                masterReference);
+                            getDOMActionService(masterReference), masterReference);
                     }
                 });
             }
@@ -330,4 +389,4 @@ public class NetconfNodeActor extends AbstractUntypedActor {
             registeredSchemas = null;
         }
     }
-}
+}
\ No newline at end of file