コード例 #1
0
        /// <summary>
        /// Called by schedulers to execute an action.
        /// </summary>
        /// <param name="action">The action to be executed.</param>
        /// <returns>An SMVActionResult object representing the result of executing the action.</returns>
        public static SMVActionResult ExecuteAction(SMVAction action, bool fromWorker)
        {
            // NOTE: The code in this function must be thread safe.
            if (action == null)
            {
                return(null);
            }

            // If there is a plugin, call PreAction first.
            if (plugin != null)
            {
                plugin.PreAction(action);
            }

            using (MemoryStream stream = new MemoryStream())
            {
                // We use a logger for writing messages since we can't output to the console in this function (As this
                // may be running in multiple threads).
                StreamWriter logger = new StreamWriter(stream);
                IDictionary <string, string> variables = action.variables;
                DateTime startTime          = DateTime.Now;
                string   actionPath         = variables["workingDir"];
                string   actionOutput       = string.Empty;
                int      cumulativeExitCode = 0;

                // Get the name of the action.
                string name = action.name;
                if (variables.ContainsKey("analysisProperty"))
                {
                    name = action.name + " - " + variables["analysisProperty"];
                }
                variables["name"] = action.name;
                Log.LogInfo("Running action: " + name, logger);

                // Get the path to the action.
                if (action.Path != null)
                {
                    actionPath = action.Path.value;
                }
                actionPath = ExpandVariables(actionPath, variables);
                variables["actionPath"] = actionPath;

                // Launch a cmd.exe process to run commands in.
                if (Console.InputEncoding.Equals(Encoding.UTF8))
                {
                    Console.InputEncoding = new UTF8Encoding(false);
                }


                // Run the commands.
                if (action.Command != null)
                {
                    foreach (SMVCommand cmd in action.Command)
                    {
                        JobObject jobObject = null;
                        if (useJobObject)
                        {
                            //Update maxTime and maxMemory allowed
                            int maxMemory = int.MaxValue;
                            int maxTime   = int.MaxValue;
                            updateAttribute(ref maxTime, cmd.maxTime, "Time");
                            Log.LogDebug("Maximum time allowed for this command = " + maxTime);
                            updateAttribute(ref maxMemory, cmd.maxMemory, "Memory");

                            //Converting memory from MB to bytes, if input is valid
                            if (maxMemory < int.MaxValue)
                            {
                                maxMemory *= (1024 * 1024);
                            }
                            Log.LogDebug("Maximum memory allowed for this command = " + maxMemory);
                            jobObject = new JobObject();
                            jobObject.setConstraints(maxMemory, maxTime);
                        }
                        Process process = LaunchProcess("cmd.exe", "", actionPath, action.Env, logger, jobObject);
                        process.OutputDataReceived += (sender, e) => { Log.LogMessage(e.Data, logger); };
                        process.ErrorDataReceived  += (sender, e) => { Log.LogMessage(e.Data, logger); };

                        // Get the command and arguments, and expand all environment as well as SMV variables.
                        string cmdAttr       = ExpandVariables(Environment.ExpandEnvironmentVariables(cmd.value), variables);
                        string argumentsAttr = string.Empty;
                        if (!string.IsNullOrEmpty(cmd.arguments))
                        {
                            argumentsAttr = ExpandVariables(Environment.ExpandEnvironmentVariables(cmd.arguments), variables);
                        }

                        try
                        {
                            Log.LogInfo(String.Format(CultureInfo.InvariantCulture, "Launching {0} with arguments: {1}", cmdAttr, argumentsAttr), logger);
                            process.StandardInput.WriteLine(String.Join(" ", new String[] { cmdAttr, argumentsAttr }));
                            process.StandardInput.WriteLine("Exit %errorlevel%");
                            process.StandardInput.Close();
                            process.BeginOutputReadLine();
                            process.BeginErrorReadLine();
                            process.WaitForExit();
                            TimeSpan span = process.ExitTime - process.StartTime;
                            Log.LogMessage(string.Format("Command Exit code: {0}", process.ExitCode), logger);
                            cumulativeExitCode += Math.Abs(process.ExitCode);
                            if (useDb)
                            {
                                try
                                {
                                    using (var database = new SmvDbEntities())
                                    {
                                        var masterEntry = new TaskAction
                                        {
                                            ActionID         = Guid.NewGuid().ToString(),
                                            TaskID           = taskId,
                                            ActionName       = action.name,
                                            Success          = cumulativeExitCode.ToString(),
                                            ActionTime       = span.ToString(),
                                            WorkingDirectory = variables["workingDir"]
                                        };
                                        database.TaskActions.Add(masterEntry);
                                        database.SaveChanges();
                                    }
                                }
                                catch (Exception e)
                                {
                                    if (fromWorker)
                                    {
                                        Log.LogError("Exception while updating database " + e);
                                    }
                                    else
                                    {
                                        Log.LogFatalError("Exception while updating database " + e);
                                    }
                                }
                            }
                            if (useJobObject)
                            {
                                jobObject.QueryExtendedLimitInformation();
                                jobObject.Close();
                                jobObject.Dispose();
                            }
                        }
                        catch (Exception e)
                        {
                            Log.LogInfo(e.ToString(), logger);
                            Log.LogInfo("Could not start process: " + cmdAttr, logger);
                            if (useJobObject)
                            {
                                jobObject.Close();
                                jobObject.Dispose();
                            }
                            return(null);
                        }
                    }
                }

                logger.Flush();
                stream.Position = 0;
                string output = new StreamReader(stream).ReadToEnd();

                if (debugMode)
                {
                    Log.WriteToFile(Path.Combine(actionPath, string.Format("smvexecute-{0}.log", action.name)), output, false);
                }
                Log.LogDebug("cumulative exit code is " + cumulativeExitCode);

                DateTime endTime = DateTime.Now;

                action.result = new SMVActionResult(action.name, output, (cumulativeExitCode == 0),
                                                    cumulativeExitCode != 0 && action.breakOnError, (int)(endTime - startTime).TotalSeconds);

                // Call plugin post action only if we were successful in executing the action.
                if (cumulativeExitCode == 0)
                {
                    // get the output directory and set the output of the action from the build log.
                    if (action.name.Equals("NormalBuild"))
                    {
                        string logPath = Path.Combine(variables["workingDir"], variables["smvLogFileNamePrefix"] + ".log");
                        action.result.output = Utility.ReadFile(logPath);

                        variables["outputDir"] = ExtractBuildPath(variables["workingDir"], action.result.output, logger);
                        Utility.SetSmvVar("outputDir", variables["outputDir"]);
                    }

                    // Get the output directory and the analysis directory.
                    if (action.name.Equals("InterceptedBuild"))
                    {
                        string logPath = Path.Combine(variables["workingDir"], variables["smvLogFileNamePrefix"] + ".log");
                        action.result.output = Utility.ReadFile(logPath);
                    }

                    // Call the plugin's post action.
                    if (plugin != null)
                    {
                        plugin.PostAction(action);
                    }
                }
                else
                {
                    // are we sure we want to exit here... the cloud worker instance becomes
                    // unhealthy after exiting here...
                    if (action.breakOnError)
                    {
                        if (fromWorker)
                        {
                            Log.LogError(String.Format("Action: {0}, failed.", name));
                        }
                        else
                        {
                            Log.LogFatalError(String.Format("Action: {0}, failed.", name));
                        }
                    }
                    else
                    {
                        Log.LogError(String.Format("Action: {0}, failed.", name));
                    }
                }

                return(action.result);
            }
        }
コード例 #2
0
        /// <summary>
        /// Launches a process and executes the given command with the args provided.
        /// </summary>
        /// <param name="cmd">Command to execute.</param>
        /// <param name="args">Arguments to pass.</param>
        /// <param name="startDirectory">Directory in which to start the process</param>
        /// <param name="env">Environment variables</param>
        /// <returns>The process on success, null on failure.</returns>
        public static Process LaunchProcess(String cmd, String args, string startDirectory, SMVEnvVar[] env, TextWriter logger, JobObject jobObject)
        {
            try
            {
                var psi = new ProcessStartInfo(cmd, args);
                psi.RedirectStandardError  = true;
                psi.RedirectStandardInput  = true;
                psi.RedirectStandardOutput = true;
                psi.UseShellExecute        = false;

                // Set environment variables for this process.
                SetEnvironmentVariables(psi, env, logger);

                Log.LogInfo(String.Format(CultureInfo.InvariantCulture, "Launching {0} with arguments: {1} ", cmd, args), logger);

                if (!String.IsNullOrEmpty(startDirectory))
                {
                    psi.WorkingDirectory = startDirectory;
                    Log.LogInfo("PATH: " + startDirectory, logger);
                }

                Process process = Process.Start(psi);
                if (process == null)
                {
                    Log.LogFatalError(String.Format(CultureInfo.InvariantCulture, "Could not create process: {0} with args {1}, working directory: {2}", cmd, args, startDirectory));
                }
                if (jobObject != null)
                {
                    jobObject.AddProcess(process.Id);
                }
                return(process);
            }
            catch (Exception e)
            {
                Log.LogError(e.ToString());
                Log.LogFatalError(String.Format(CultureInfo.InvariantCulture, "Could not start process: {0} with args {1}, working directory: {2}", cmd, args, startDirectory));
                return(null);
            }
        }