Exemple #1
0
        /// <summary>
        /// Dumping Agent Azure VM extension logs to the support files folder.
        /// </summary>
        /// <param name="executionContext">Execution context to write debug messages.</param>
        /// <param name="supportFilesFolder">Destination folder for files to be dumped.</param>
        /// <param name="jobStartTimeUtc">Date and time to create timestamp.</param>
        /// <returns>true, if logs have been dumped successfully; otherwise returns false.</returns>
        private bool DumpAgentExtensionLogs(IExecutionContext executionContext, string supportFilesFolder, DateTime jobStartTimeUtc)
        {
            string pathToLogs  = String.Empty;
            string archiveName = String.Empty;
            string timestamp   = jobStartTimeUtc.ToString("yyyyMMdd-HHmmss");

            if (PlatformUtil.RunningOnWindows)
            {
                // the extension creates a subfolder with a version number on Windows, and we're taking the latest one
                string pathToExtensionVersions = ExtensionPaths.WindowsPathToExtensionVersions;
                if (!Directory.Exists(pathToExtensionVersions))
                {
                    executionContext.Debug("Path to subfolders with Agent Azure VM Windows extension logs (of its different versions) does not exist.");
                    executionContext.Debug($"(directory \"{pathToExtensionVersions}\" not found)");
                    return(false);
                }
                string[] subDirs = Directory.GetDirectories(pathToExtensionVersions).Select(dir => Path.GetFileName(dir)).ToArray();
                if (subDirs.Length == 0)
                {
                    executionContext.Debug("Path to Agent Azure VM Windows extension logs (of its different versions) does not contain subfolders.");
                    executionContext.Debug($"(directory \"{pathToExtensionVersions}\" does not contain subdirectories with logs)");
                    return(false);
                }
                Version[] versions   = subDirs.Select(dir => new Version(dir)).ToArray();
                Version   maxVersion = versions.Max();
                pathToLogs  = Path.Combine(pathToExtensionVersions, maxVersion.ToString());
                archiveName = $"AgentWindowsExtensionLogs-{timestamp}-utc.zip";
            }
            else if (PlatformUtil.RunningOnLinux)
            {
                // the extension does not create a subfolder with a version number on Linux, and we're just taking this folder
                pathToLogs = ExtensionPaths.LinuxPathToExtensionLogs;
                if (!Directory.Exists(pathToLogs))
                {
                    executionContext.Debug("Path to Agent Azure VM Linux extension logs does not exist.");
                    executionContext.Debug($"(directory \"{pathToLogs}\" not found)");
                    return(false);
                }
                archiveName = $"AgentLinuxExtensionLogs-{timestamp}-utc.zip";
            }
            else
            {
                executionContext.Debug("Dumping Agent Azure VM extension logs implemented for Windows and Linux only.");
                return(false);
            }

            executionContext.Debug($"Path to agent extension logs: {pathToLogs}");

            string archivePath = Path.Combine(HostContext.GetDiagDirectory(), archiveName);

            executionContext.Debug($"Archiving agent extension logs to: {archivePath}");
            ZipFile.CreateFromDirectory(pathToLogs, archivePath);

            string copyPath = Path.Combine(supportFilesFolder, archiveName);

            executionContext.Debug($"Copying archived agent extension logs to: {copyPath}");
            File.Copy(archivePath, copyPath);

            return(true);
        }
        private string GenerateUpdateScript(bool restartInteractiveAgent)
        {
            int    processId = Process.GetCurrentProcess().Id;
            string updateLog = Path.Combine(HostContext.GetDiagDirectory(), $"SelfUpdate-{DateTime.UtcNow.ToString("yyyyMMdd-HHmmss")}.log");
            string agentRoot = HostContext.GetDirectory(WellKnownDirectory.Root);

            string templateName = "update.sh.template";

            if (PlatformUtil.RunningOnWindows)
            {
                templateName = "update.cmd.template";
            }

            string templatePath = Path.Combine(agentRoot, $"bin.{_targetPackage.Version}", templateName);
            string template     = File.ReadAllText(templatePath);

            template = template.Replace("_PROCESS_ID_", processId.ToString());
            template = template.Replace("_AGENT_PROCESS_NAME_", $"Agent.Listener{IOUtil.ExeExtension}");
            template = template.Replace("_ROOT_FOLDER_", agentRoot);
            template = template.Replace("_EXIST_AGENT_VERSION_", BuildConstants.AgentPackage.Version);
            template = template.Replace("_DOWNLOAD_AGENT_VERSION_", _targetPackage.Version);
            template = template.Replace("_UPDATE_LOG_", updateLog);
            template = template.Replace("_RESTART_INTERACTIVE_AGENT_", restartInteractiveAgent ? "1" : "0");

            string scriptName = "_update.sh";

            if (PlatformUtil.RunningOnWindows)
            {
                scriptName = "_update.cmd";
            }

            string updateScript = Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Work), scriptName);

            if (File.Exists(updateScript))
            {
                IOUtil.DeleteFile(updateScript);
            }

            File.WriteAllText(updateScript, template);
            return(updateScript);
        }
Exemple #3
0
        public void LogFileChangedAccordingToEnvVariable()
        {
            try
            {
                var newPath = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), "logs");
                Environment.SetEnvironmentVariable("AGENT_DIAGLOGPATH", newPath);

                using (var _hc = new HostContext(HostType.Agent))
                {
                    // Act.
                    var diagFolder = _hc.GetDiagDirectory();

                    // Assert
                    Assert.Equal(Path.Combine(newPath, Constants.Path.DiagDirectory), diagFolder);
                    Directory.Exists(diagFolder);
                }
            }
            finally
            {
                Environment.SetEnvironmentVariable("AGENT_DIAGLOGPATH", null);
            }
        }
Exemple #4
0
        public async Task UploadDiagnosticLogsAsync(IExecutionContext executionContext,
                                                    Pipelines.AgentJobRequestMessage message,
                                                    DateTime jobStartTimeUtc)
        {
            ArgUtil.NotNull(executionContext, nameof(executionContext));
            ArgUtil.NotNull(message, nameof(message));

            executionContext.Debug("Starting diagnostic file upload.");

            // Setup folders
            // \_layout\_work\_temp\[jobname-support]
            executionContext.Debug("Setting up diagnostic log folders.");
            string tempDirectory = HostContext.GetDirectory(WellKnownDirectory.Temp);

            ArgUtil.Directory(tempDirectory, nameof(tempDirectory));

            string supportRootFolder = Path.Combine(tempDirectory, message.JobName + "-support");

            Directory.CreateDirectory(supportRootFolder);

            // \_layout\_work\_temp\[jobname-support]\files
            executionContext.Debug("Creating diagnostic log files folder.");
            string supportFilesFolder = Path.Combine(supportRootFolder, "files");

            Directory.CreateDirectory(supportFilesFolder);

            // Create the environment file
            // \_layout\_work\_temp\[jobname-support]\files\environment.txt
            var           configurationStore = HostContext.GetService <IConfigurationStore>();
            AgentSettings settings           = configurationStore.GetSettings();
            int           agentId            = settings.AgentId;
            string        agentName          = settings.AgentName;
            int           poolId             = settings.PoolId;

            executionContext.Debug("Creating diagnostic log environment file.");
            string environmentFile = Path.Combine(supportFilesFolder, "environment.txt");
            string content         = await GetEnvironmentContent(agentId, agentName, message.Steps);

            File.WriteAllText(environmentFile, content);

            // Create the capabilities file
            var capabilitiesManager = HostContext.GetService <ICapabilitiesManager>();
            Dictionary <string, string> capabilities = await capabilitiesManager.GetCapabilitiesAsync(configurationStore.GetSettings(), default(CancellationToken));

            executionContext.Debug("Creating capabilities file.");
            string capabilitiesFile    = Path.Combine(supportFilesFolder, "capabilities.txt");
            string capabilitiesContent = GetCapabilitiesContent(capabilities);

            File.WriteAllText(capabilitiesFile, capabilitiesContent);

            // Copy worker diag log files
            List <string> workerDiagLogFiles = GetWorkerDiagLogFiles(HostContext.GetDiagDirectory(), jobStartTimeUtc);

            executionContext.Debug($"Copying {workerDiagLogFiles.Count()} worker diag logs from {HostContext.GetDiagDirectory()}.");

            foreach (string workerLogFile in workerDiagLogFiles)
            {
                ArgUtil.File(workerLogFile, nameof(workerLogFile));

                string destination = Path.Combine(supportFilesFolder, Path.GetFileName(workerLogFile));
                File.Copy(workerLogFile, destination);
            }

            // Copy agent diag log files - we are using the worker Host Context and we need the diag folder form the Agent.
            List <string> agentDiagLogFiles = GetAgentDiagLogFiles(HostContext.GetDiagDirectory(HostType.Agent), jobStartTimeUtc);

            executionContext.Debug($"Copying {agentDiagLogFiles.Count()} agent diag logs from {HostContext.GetDiagDirectory(HostType.Agent)}.");

            foreach (string agentLogFile in agentDiagLogFiles)
            {
                ArgUtil.File(agentLogFile, nameof(agentLogFile));

                string destination = Path.Combine(supportFilesFolder, Path.GetFileName(agentLogFile));
                File.Copy(agentLogFile, destination);
            }

            // Read and add to logs waagent.conf settings on Linux
            if (PlatformUtil.RunningOnLinux)
            {
                executionContext.Debug("Dumping of waagent.conf file");
                string waagentDumpFile = Path.Combine(supportFilesFolder, "waagentConf.txt");

                string configFileName = "waagent.conf";
                try
                {
                    string filePath = Directory.GetFiles("/etc", configFileName).FirstOrDefault();
                    if (!string.IsNullOrWhiteSpace(filePath))
                    {
                        string waagentContent = File.ReadAllText(filePath);

                        File.AppendAllText(waagentDumpFile, "waagent.conf settings");
                        File.AppendAllText(waagentDumpFile, Environment.NewLine);
                        File.AppendAllText(waagentDumpFile, waagentContent);

                        executionContext.Debug("Dumping waagent.conf file is completed.");
                    }
                    else
                    {
                        executionContext.Debug("waagent.conf file wasn't found. Dumping was not done.");
                    }
                }
                catch (Exception ex)
                {
                    string warningMessage = $"Dumping of waagent.conf was not completed successfully. Error message: {ex.Message}";
                    executionContext.Warning(warningMessage);
                }
            }

            // Copy cloud-init log files from linux machines
            if (PlatformUtil.RunningOnLinux)
            {
                executionContext.Debug("Dumping cloud-init logs.");

                string logsFilePath = $"{HostContext.GetDiagDirectory()}/cloudinit-{jobStartTimeUtc.ToString("yyyyMMdd-HHmmss")}-logs.tar.gz";
                string resultLogs   = await DumpCloudInitLogs(logsFilePath);

                executionContext.Debug(resultLogs);

                if (File.Exists(logsFilePath))
                {
                    string destination = Path.Combine(supportFilesFolder, Path.GetFileName(logsFilePath));
                    File.Copy(logsFilePath, destination);
                    executionContext.Debug("Cloud-init logs added to the diagnostics archive.");
                }
                else
                {
                    executionContext.Debug("Cloud-init logs were not found.");
                }

                executionContext.Debug("Dumping cloud-init logs is ended.");
            }

            // Copy event logs for windows machines
            bool dumpJobEventLogs = AgentKnobs.DumpJobEventLogs.GetValue(executionContext).AsBoolean();

            if (dumpJobEventLogs && PlatformUtil.RunningOnWindows)
            {
                executionContext.Debug("Dumping event viewer logs for current job.");

                try
                {
                    string eventLogsFile = $"{HostContext.GetDiagDirectory()}/EventViewer-{ jobStartTimeUtc.ToString("yyyyMMdd-HHmmss") }.csv";
                    await DumpCurrentJobEventLogs(executionContext, eventLogsFile, jobStartTimeUtc);

                    string destination = Path.Combine(supportFilesFolder, Path.GetFileName(eventLogsFile));
                    File.Copy(eventLogsFile, destination);
                }
                catch (Exception ex)
                {
                    executionContext.Debug("Failed to dump event viewer logs. Skipping.");
                    executionContext.Debug($"Error message: {ex}");
                }
            }

            bool dumpPackagesVerificationResult = AgentKnobs.DumpPackagesVerificationResult.GetValue(executionContext).AsBoolean();

            if (dumpPackagesVerificationResult && PlatformUtil.RunningOnLinux && !PlatformUtil.RunningOnRHEL6)
            {
                executionContext.Debug("Dumping info about invalid MD5 sums of installed packages.");

                var debsums = WhichUtil.Which("debsums");
                if (debsums == null)
                {
                    executionContext.Debug("Debsums is not installed on the system. Skipping broken packages check.");
                }
                else
                {
                    try
                    {
                        string packageVerificationResults = await GetPackageVerificationResult(debsums);

                        IEnumerable <string> brokenPackagesInfo = packageVerificationResults
                                                                  .Split("\n")
                                                                  .Where((line) => !String.IsNullOrEmpty(line) && !line.EndsWith("OK"));

                        string brokenPackagesLogsPath = $"{HostContext.GetDiagDirectory()}/BrokenPackages-{ jobStartTimeUtc.ToString("yyyyMMdd-HHmmss") }.log";
                        File.AppendAllLines(brokenPackagesLogsPath, brokenPackagesInfo);

                        string destination = Path.Combine(supportFilesFolder, Path.GetFileName(brokenPackagesLogsPath));
                        File.Copy(brokenPackagesLogsPath, destination);
                    }
                    catch (Exception ex)
                    {
                        executionContext.Debug("Failed to dump broken packages logs. Skipping.");
                        executionContext.Debug($"Error message: {ex}");
                    }
                }
            }
            else
            {
                executionContext.Debug("The platform is not based on Debian - skipping debsums check.");
            }

            try
            {
                executionContext.Debug("Starting dumping Agent Azure VM extension logs.");
                bool logsSuccessfullyDumped = DumpAgentExtensionLogs(executionContext, supportFilesFolder, jobStartTimeUtc);
                if (logsSuccessfullyDumped)
                {
                    executionContext.Debug("Agent Azure VM extension logs successfully dumped.");
                }
                else
                {
                    executionContext.Debug("Agent Azure VM extension logs not found. Skipping.");
                }
            }
            catch (Exception ex)
            {
                executionContext.Debug("Failed to dump Agent Azure VM extension logs. Skipping.");
                executionContext.Debug($"Error message: {ex}");
            }

            executionContext.Debug("Zipping diagnostic files.");

            string buildNumber = executionContext.Variables.Build_Number ?? "UnknownBuildNumber";
            string buildName   = $"Build {buildNumber}";
            string phaseName   = executionContext.Variables.System_PhaseDisplayName ?? "UnknownPhaseName";

            // zip the files
            string diagnosticsZipFileName = $"{buildName}-{phaseName}.zip";
            string diagnosticsZipFilePath = Path.Combine(supportRootFolder, diagnosticsZipFileName);

            ZipFile.CreateFromDirectory(supportFilesFolder, diagnosticsZipFilePath);

            // upload the json metadata file
            executionContext.Debug("Uploading diagnostic metadata file.");
            string metadataFileName = $"diagnostics-{buildName}-{phaseName}.json";
            string metadataFilePath = Path.Combine(supportFilesFolder, metadataFileName);
            string phaseResult      = GetTaskResultAsString(executionContext.Result);

            IOUtil.SaveObject(new DiagnosticLogMetadata(agentName, agentId, poolId, phaseName, diagnosticsZipFileName, phaseResult), metadataFilePath);

            executionContext.QueueAttachFile(type: CoreAttachmentType.DiagnosticLog, name: metadataFileName, filePath: metadataFilePath);

            executionContext.QueueAttachFile(type: CoreAttachmentType.DiagnosticLog, name: diagnosticsZipFileName, filePath: diagnosticsZipFilePath);

            executionContext.Debug("Diagnostic file upload complete.");
        }