コード例 #1
0
        /// <summary>
        /// Runs the commands on the PlanetLab node at the specified index.
        /// </summary>
        /// <param name="state">The state.</param>
        /// <param name="index">The node state index.</param>
        private void OnRunNode(PlManagerState state, int index)
        {
            lock (state.Sync)
            {
                // If the operation has been canceled, return.
                if (state.IsStopped) return;

                // Get the node state.
                PlManagerNodeState nodeState = state.GetNode(index);

                // Execute the secure shell connection on the thread pool.
                ThreadPool.QueueUserWorkItem((object threadState) =>
                    {
                        // Raise a node started event.
                        if (null != this.NodeStarted) this.NodeStarted(this, new PlManagerNodeEventArgs(state, nodeState.Node));

                        try
                        {
                            // Create the private key connection information.
                            ConnectionInfo connectionInfo;
                            // Create a memory stream with the key data.
                            using (MemoryStream memoryStream = new MemoryStream(state.Slice.Key))
                            {
                                // Create the private key file.
                                using (PrivateKeyFile keyFile = new PrivateKeyFile(memoryStream))
                                {
                                    // Create a key connection info.
                                    connectionInfo = new PrivateKeyConnectionInfo(nodeState.Node.Hostname, state.Slice.Name, keyFile);
                                }
                            }

                            // Open an SSH client to the PlanetLab node.
                            using (SshClient sshClient = new SshClient(connectionInfo))
                            {
                                // Connect the client.
                                sshClient.Connect();

                                // For all the slice commands.
                                foreach (PlCommand command in state.Slice.Commands)
                                {
                                    // If the command has parameters.
                                    if (command.HasParameters)
                                    {
                                        // Format the command with all parameter sets.
                                        for (int indexSet = 0; indexSet < command.SetsCount; indexSet++)
                                        {
                                            // If the operation has been paused, wait for resume.
                                            if (state.IsPaused)
                                            {
                                                state.WaitPause();
                                            }

                                            // If the operation has been canceled, return.
                                            if (state.IsStopped)
                                            {
                                                // Remove the node from the running list.
                                                state.UpdateNodeRunningToSkipped(index);
                                                // Cancel all nodes in the pending list.
                                                state.CancelPendingNodes();
                                                // Raise the canceled event.
                                                if (null != this.NodeCanceled) this.NodeCanceled(this, new PlManagerNodeEventArgs(state, nodeState.Node));
                                                // Return.
                                                return;
                                            }

                                            // Run the command with the current parameters set.
                                            this.OnRunCommand(state, nodeState, command, indexSet, sshClient);
                                        }
                                    }
                                    else
                                    {
                                        // Run the command without parameters.
                                        this.OnRunCommand(state, nodeState, command, -1, sshClient);
                                    }
                                }

                                // Disconnect the client.
                                sshClient.Disconnect();
                            }

                            // Remove the node from the running list.
                            state.UpdateNodeRunningToCompleted(index);

                            // Raise the success event.
                            if (null != this.NodeFinishedSuccess) this.NodeFinishedSuccess(this, new PlManagerNodeEventArgs(state, nodeState.Node));
                        }
                        catch (Exception exception)
                        {
                            // Remove the node from the running list.
                            state.UpdateNodeRunningToSkipped(index);

                            // Raise the fail event.
                            if (null != this.NodeFinishedFail) this.NodeFinishedFail(this, new PlManagerNodeEventArgs(state, nodeState.Node, exception));
                        }
                        finally
                        {
                            lock (state.Sync)
                            {
                                // If the operation has not been canceled.
                                if (!state.IsStopped)
                                {

                                    // If the list of pending nodes and running nodes is empty, stop.
                                    if ((0 == state.PendingCount) && (0 == state.RunningCount))
                                    {
                                        this.Stop(state);
                                    }

                                    // Get a cached copy of all the pending PlanetLab nodes.
                                    int[] pendingCache = state.PendingNodes.ToArray();

                                    // Find the next pending node to execute commands.
                                    foreach (int newIndex in pendingCache)
                                    {
                                        // Get the node state corresponding to the pending node.
                                        PlManagerNodeState newNode = state.GetNode(newIndex);

                                        // If the slice configuration only allows one node per site.
                                        if (state.Slice.OnlyRunOneNodePerSite)
                                        {
                                            // If the node site is completed.
                                            if (state.IsSiteCompleted(newNode.Node.SiteId.Value))
                                            {
                                                // Change the node from the pending to the skipped state.
                                                state.UpdateNodePendingToSkipped(newIndex);
                                                // Raise an event indicating that the node has been skipped.
                                                if (null != this.NodeSkipped) this.NodeSkipped(this, new PlManagerNodeEventArgs(state, newNode.Node));
                                                // Skip the loop to the next node.
                                                continue;
                                            }
                                            // If the node site is running.
                                            if (state.IsSiteRunning(newNode.Node.SiteId.Value))
                                            {
                                                // Postpone the node for later, and skip the loop to the next node.
                                                continue;
                                            }
                                        }

                                        // Change the node from the pending to the running state.
                                        state.UpdateNodePendingToRunning(newIndex);

                                        // Execute the commands on specified node.
                                        this.OnRunNode(state, newIndex);

                                        // Exit the loop.
                                        break;
                                    }
                                }
                            }
                        }
                    });
            }
        }