private void HandleNewFile(FileInfo fi)
 {
     try
     {
         bool success = false;
         while (!success)
         {
             try
             {
                 using (TextReader tr = new StreamReader(fi.FullName))
                 {
                     lock (IncomingQueueLock)
                     {
                         incoming.Enqueue(XMLSerializable.FromXML <AutomationMessage>(tr.ReadToEnd()));
                     }
                 }
                 success = true;
             }
             catch (IOException)
             {
                 //eat it
             }
             catch (System.UnauthorizedAccessException)
             {
                 //eat it
             }
         }
         if (success && fi.Exists)
         {
             fi.Delete();
         }
     }
     catch (Exception ex)
     {
         EventLog.WriteEntry(ex.ToString(), EventLogEntryType.Error);
         //invalid file, rename it
         try
         {
             fi.MoveTo(fi.FullName + ".bad");
         }
         catch (Exception ex2)
         {
             EventLog.WriteEntry(ex2.ToString(), EventLogEntryType.Error);
             //eat it
         }
     }
     lock (ExecuteLock)
     {
         Monitor.PulseAll(ExecuteLock);
     }
 }
        //void queue_ReceiveCompleted(object sender, ReceiveCompletedEventArgs e)
        //{
        //    //TODO catch MessageQueueException
        //    MessageQueue mq = (MessageQueue)sender;
        //    Message m = mq.EndReceive(e.AsyncResult);

        //    lock (IncomingQueueLock)
        //    {
        //        incoming.Enqueue(e.Message);
        //    }
        //    lock (ExecuteLock)
        //    {
        //        Monitor.PulseAll(ExecuteLock);
        //    }

        //    mq.BeginReceive();
        //}

        protected override void OnStart(string[] args)
        {
            #region Load VM Configs
            FileInfo vmConfigFile = new FileInfo(Path.Combine(AppConfig.ExecutingDir.FullName, "vm_list.txt"));
            if (vmConfigFile.Exists)
            {
                using (TextReader tr = new StreamReader(vmConfigFile.FullName))
                {
                    while (true)
                    {
                        string line = tr.ReadLine();
                        if (line == null)
                        {
                            break;
                        }
                        string[] parts = line.Split(',');
                        if (parts.Length != 4)
                        {
                            //skip the line
                            continue;
                        }
                        string         config = parts[0].Trim();
                        string         path   = parts[1].Trim();
                        VirtualMachine vm     = new VirtualMachine(parts[2].Trim(), parts[3].Trim(), vmHost.GetVMConnectionFromPath(path));
                        vmMap[config] = vm;
                    }
                }
            }
            #endregion

            #region Test Configuration
            //first check connection to ESX/vSphere
            try
            {
                vmHost.Login();
            }
            catch (System.Web.Services.Protocols.SoapException ex)
            {
                EventLog.WriteEntry("Error while logging in. Exception: " + Environment.NewLine + ex.ToString() + Environment.NewLine + ex.Detail.OuterXml, EventLogEntryType.Error);
                throw;
            }
            catch (System.Net.WebException ex)
            {
                EventLog.WriteEntry("Error while logging in. Exception: " + Environment.NewLine + ex.ToString() + Environment.NewLine + ex.Status, EventLogEntryType.Error);
                throw;
            }
            catch (Exception ex)
            {
                EventLog.WriteEntry("Error while logging in. Exception: " + Environment.NewLine + ex.ToString(), EventLogEntryType.Error);
                throw;
            }

            //now check each VM
            foreach (VirtualMachine vm in vmMap.Values)
            {
                if (!vm.HasValidConnection)
                {
                    EventLog.WriteEntry("Error: Could not find VM \"" + vm.Identifier + "\"", EventLogEntryType.Warning);
                }
            }
            #endregion

            #region Load Jobs
            DirectoryInfo import = new DirectoryInfo(Path.Combine(AppConfig.ExecutingDir.FullName, "jobs"));
            if (import.Exists)
            {
                foreach (FileInfo jobFile in import.GetFiles("*.job"))
                {
                    try
                    {
                        Job j = null;
                        using (TextReader tr = new StreamReader(jobFile.FullName))
                        {
                            j = XMLSerializable.FromXML <Job>(tr.ReadToEnd());
                        }
                        FileInfo  jobStatusFile = new FileInfo(Path.Combine(import.FullName, j.JobID + ".sta"));
                        JobStatus js            = null;
                        using (TextReader tr = new StreamReader(jobStatusFile.FullName))
                        {
                            js = XMLSerializable.FromXML <JobStatus>(tr.ReadToEnd());
                        }
                        jobs[j] = js;
                    }
                    catch (Exception ex)
                    {
                        EventLog.WriteEntry(ex.ToString(), EventLogEntryType.Error);
                        continue;
                    }
                }
                import.Delete(true);
            }
            #endregion

            #region Handle Messages
            //look for existing files (messages)
            FileInfo[] existingFiles = AppConfig.Inbox.GetFiles("*.xml");
            //start looking for new files
            StartWatchingDir();

            //handle existing files (messages)
            foreach (FileInfo fi in existingFiles)
            {
                HandleNewFile(fi);
            }
            #endregion

            //start worker loops
            mainLoopRunning = true;
            if (!mainLoop.IsAlive)
            {
                mainLoop.Start();
            }

            jobLoopRunning = true;
            if (!jobLoop.IsAlive)
            {
                jobLoop.Start();
            }

            //Set up background thread to periodically check jobs
            Thread backgroundChecker = new Thread(new ThreadStart(delegate
            {
                try
                {
                    while (mainLoopRunning)
                    {
                        CheckJobs();
                        Thread.Sleep(TimeSpan.FromMinutes(1));
                    }
                }
                catch (ThreadAbortException) { }    //eat it
            }));
            backgroundChecker.IsBackground = true;
            backgroundChecker.Start();

            EventLog.WriteEntry("JobManagerService started successfully.");
        }
Ejemplo n.º 3
0
        public void Run()
        {
            try
            {
                FileInfo mapNetBatchFile = new FileInfo(Path.Combine(Utilities.ExecutingAssembly.Directory.FullName, "map.bat"));
                //if the network drive is disconected, then we will be unable to get to the server inbox, in which case we should try to remap
                if (!AppConfig.ServerInbox.Exists && mapNetBatchFile.Exists)
                {
                    using (System.Diagnostics.Process p = new System.Diagnostics.Process())
                    {
                        p.StartInfo.WorkingDirectory = mapNetBatchFile.Directory.FullName;
                        p.StartInfo.FileName         = mapNetBatchFile.Name;
                        p.StartInfo.CreateNoWindow   = true;
                        p.StartInfo.UseShellExecute  = true;
                        p.Start();
                        p.WaitForExit();
                    }
                }
                int       packageToRun = 0;
                JobResult result       = new JobResult();
                result.Completed = true;

                //string sendQueueName = @"FormatName:DIRECT=OS:hammerbuildvm\Private$\jobmanager";
                //string sendQueueName = @"FormatName:DIRECT=OS:ryanadams2\Private$\test2";
                //jci.LogString("Connecting to Job Manager receive queue (" + sendQueueName + ")");
                MessageSendRecieve msr = new MessageSendRecieve(AppConfig.ServerInbox, AppConfig.ServerOutbox);
                //jci.LogString("Permission = " + msr.RemoteMessageQueue.AccessMode.ToString());

                //look for an existing job to run/continue before getting a new job from the server
                FileInfo jobXML = new FileInfo(Path.Combine(Utilities.ExecutingAssembly.Directory.FullName, "job.xml"));
                if (jobXML.Exists)
                {
                    using (TextReader tr = new StreamReader(jobXML.FullName))
                    {
                        j = XMLSerializable.FromXML <Job>(tr.ReadToEnd());
                        if (j.Properties.ContainsKey("PackageToRun"))
                        {
                            packageToRun = Int32.Parse(j.Properties["PackageToRun"]);
                        }
                    }
                    try
                    {
                        //rename the job file so the next run doesn't automatically use it.  The job.xml file will be put back
                        //as part of jci.StartupOnNextRun if it is meant to be continued after a restart
                        string lastFile = jobXML.FullName + ".old";
                        if (File.Exists(lastFile))
                        {
                            File.Delete(lastFile);
                        }
                        File.Move(jobXML.FullName, lastFile);
                    }
                    catch (Exception ex)
                    {
                        //if the delete fails lets log it, but it isn't critical so let's eat the exception
                        LogString("Could not delete existing job.xml file: " + ex.ToString());
                    }
                    //look for an existing JobResult to pull in
                    FileInfo jobResultXML = new FileInfo(Path.Combine(Utilities.ExecutingAssembly.Directory.FullName, "jobresult.xml"));
                    if (jobResultXML.Exists)
                    {
                        try
                        {
                            using (TextReader tr = new StreamReader(jobResultXML.FullName))
                            {
                                result = XMLSerializable.FromXML <JobResult>(tr.ReadToEnd());
                            }
                        }
                        catch (Exception ex)
                        {
                            //log, but eat it
                            LogString(ex.ToString());
                        }
                    }
                }
                else
                {
                    LogString("Requesting Jobs from Job Manager");
                    string messageID = msr.RequestJob();
                    LogString("Sent request with message id: " + messageID);

                    LogString("Waiting for Job response from Job Manager");
                    j = msr.WaitForJob(messageID, DEFAULT_JOB_WAIT);
                    if (j == null)
                    {
                        LogString("No Jobs Available");
                        return;
                    }
                    try
                    {
                        LogString("Found Job: " + j.JobID);

                        if (baseDir.Exists)
                        {
                            baseDir.Delete(true);
                            //TODO wait for files to be deleted?
                        }
                        baseDir.Create();

                        List <string> keys = new List <string>(j.ISOs.Keys);
                        foreach (string isoName in keys)
                        {
                            FileInfo isoPath  = new FileInfo(j.ISOs[isoName]);
                            string   destPath = Path.Combine(Utilities.ExecutingAssembly.Directory.FullName, isoPath.Name);
                            LogString("Copying ISO from \"" + isoPath.Directory.FullName + "\" to \"" + destPath + "\"");
                            isoPath.CopyTo(destPath);
                            j.ISOs[isoName] = destPath;
                        }

                        if (j.Properties == null)
                        {
                            j.Properties = new SerializableDictionary <string, string>();
                        }
                    }
                    catch (Exception ex)
                    {
                        LogString(ex.ToString());
                        result.Completed = false;
                        ExecutionResult er = new ExecutionResult(ex.ToString(), null);
                        result.ExecutionResults.Add(er);
                        Logger.Instance.Pause();
                        result.Logs.Add(FileData.FromFile(new FileInfo(Logger.Instance.FileName)));
                        Logger.Instance.Resume();
                        LogString("Sending Job Result");
                        msr.ReportJobStatus(new JobCompleted(j, result));
                        LogString("Job Result Sent");
                        return;
                    }
                }
                if (j.Packages.Count == 0)
                {
                    Logger.Instance.Pause();
                    result.Logs.Add(FileData.FromFile(new FileInfo(Logger.Instance.FileName)));
                    Logger.Instance.Resume();
                }
                while (packageToRun < j.Packages.Count)
                {
                    runningPackageDir = new DirectoryInfo(Path.Combine(baseDir.FullName, packageToRun.ToString()));

                    ExecutablePackage ep = j.Packages[packageToRun];
                    runningPackage = ep;
                    ExecutionResult er = new ExecutionResult();
                    try
                    {
                        if (!ep.ContentDirectory.ToLower().Equals(runningPackageDir.FullName.ToLower()))
                        {
                            if (runningPackageDir.Exists)
                            {
                                runningPackageDir.Delete(true);
                            }
                            runningPackageDir.Create();

                            LogString("Copying data from \"" + ep.ContentDirectory + "\" to \"" + runningPackageDir.FullName + "\"");
                            DirectoryData.FromDirectory(new DirectoryInfo(ep.ContentDirectory)).DumpContentsToDir(runningPackageDir);
                            ep.ContentDirectory = runningPackageDir.FullName;
                        }
                        LogString("Loading external test DLL: " + ep.JobRunnerDLLName + " , " + ep.JobRunnerClassName);
                        JobRunner jr = LoadJobRunner(ep.JobRunnerClassName, Path.Combine(runningPackageDir.FullName, ep.JobRunnerDLLName));

                        LogString("Executing Execute() method on external DLL");

                        er = jr.Execute(this);
                    }
                    catch (Exception ex)
                    {
                        LogString(ex.ToString());
                        result.Completed = false;
                        er = new ExecutionResult(ex.ToString(), null);
                    }

                    Logger.Instance.Pause();
                    result.Logs.Add(FileData.FromFile(new FileInfo(Logger.Instance.FileName)));
                    Logger.Instance.Resume();

                    if (er != null)
                    {
                        result.ExecutionResults.Add(er);
                    }

                    //lets save the current job result
                    using (TextWriter tw = new StreamWriter(Path.Combine(Utilities.ExecutingAssembly.Directory.FullName, "jobresult.xml"), false))
                    {
                        tw.Write(result.ToXML());
                    }

                    if (er == null)
                    {
                        //The automation is likely not finished, the computer is likely going to reboot and
                        //we want this execution to continue after reboot so we should exit now instead of going to the next package.
                        //the executable package should have already called startuponnextrun
                        return;
                    }


                    if (!er.Success)
                    {
                        //stop on first error
                        break;
                    }

                    packageToRun++;
                    j.Properties["PackageToRun"] = packageToRun.ToString();
                    if (er.Success && er.RestartAfter)
                    {
                        StartupOnNextRun();
                        LogString("Restarting ...");
                        system.Shutdown(true);
                        return;
                    }
                }
                LogString("Sending Job Result");
                msr.ReportJobStatus(new JobCompleted(j, result));
                LogString("Job Result Sent");
                //cleanup
                if (File.Exists(Path.Combine(Utilities.ExecutingAssembly.Directory.FullName, "jobresult.xml")))
                {
                    File.Delete(Path.Combine(Utilities.ExecutingAssembly.Directory.FullName, "jobresult.xml"));
                }
                if (ShutdownOnCompletion)
                {
                    LogString("Shuting Down ...");
                    system.Shutdown(false);

                    //so, lets exit the program
                    System.Windows.Forms.Application.Exit();
                }
            }
            catch (ThreadAbortException)
            {
                //eat it, get out right away.  Program is exiting or user has stopped automation
                return;
            }
            catch (Exception e)
            {
                LogString("Exception in thread: " + e.ToString());
                return;
            }
        }