From 5e6060f0834cf79e32f8fa1dda72ef5a9f3b1ec8 Mon Sep 17 00:00:00 2001 From: nalini Date: Fri, 28 Feb 2025 11:37:43 +0530 Subject: [PATCH] PR Commit: PRODUCT BACKLOG ITEM 30293542 --- .../PSCPInstallation.cs | 157 ++++++++++++++++++ .../VirtualClient.Main/profiles/PSCP.json | 33 ++++ 2 files changed, 190 insertions(+) create mode 100644 src/VirtualClient/VirtualClient.Dependencies/PSCPInstallation.cs create mode 100644 src/VirtualClient/VirtualClient.Main/profiles/PSCP.json diff --git a/src/VirtualClient/VirtualClient.Dependencies/PSCPInstallation.cs b/src/VirtualClient/VirtualClient.Dependencies/PSCPInstallation.cs new file mode 100644 index 0000000000..be7d729198 --- /dev/null +++ b/src/VirtualClient/VirtualClient.Dependencies/PSCPInstallation.cs @@ -0,0 +1,157 @@ +namespace VirtualClient.Dependencies +{ + using System; + using System.Collections.Generic; + using System.IO; + using System.IO.Abstractions; + using System.Threading; + using System.Threading.Tasks; + using global::VirtualClient; + using global::VirtualClient.Common; + using global::VirtualClient.Common.Extensions; + using global::VirtualClient.Common.Telemetry; + using global::VirtualClient.Contracts; + using Microsoft.Extensions.DependencyInjection; + + /// + /// Installation component for the PSCP + /// + public class PSCPInstallation : VirtualClientComponent + { + private IFileSystem fileSystem; + private IPackageManager packageManager; + private ProcessManager processManager; + private ISystemManagement systemManagement; + + /// + /// Initializes a new instance of the class. + /// + /// An enumeration of dependencies that can be used for dependency injection. + /// A series of key value pairs that dictate runtime execution. + public PSCPInstallation(IServiceCollection dependencies, IDictionary parameters) + : base(dependencies, parameters) + { + this.fileSystem = dependencies.GetService(); + this.packageManager = dependencies.GetService(); + this.processManager = dependencies.GetService(); + this.systemManagement = dependencies.GetService(); + this.SupportingExecutables = new List(); + } + + /// + /// The path to the pscp executable. + /// + public string ExecutablePath { get; set; } + + /// + /// The path where the pscp JSON results file should be output. + /// + public string ResultsFilePath { get; set; } + + /// + /// path to store pscp.exe + /// + public string PscpPath + { + get + { + return this.Parameters.GetValue(nameof(PSCPInstallation.PscpPath)); + } + } + + /// + /// A set of paths for supporting executables of the main process + /// (e.g. pscp_x86_64, pscp_aarch64). These typically need to + /// be cleaned up/terminated at the end of each round of processing. + /// + protected IList SupportingExecutables { get; } + + /// + /// Executes Geek bench + /// + protected override async Task ExecuteAsync(EventContext telemetryContext, CancellationToken cancellationToken) + { + this.DeleteResultsFile(telemetryContext); + + string commandLineArguments = string.Empty; + + using (BackgroundOperations profiling = BackgroundOperations.BeginProfiling(this, cancellationToken)) + { + string pscpPath = Path.Combine(this.PscpPath, "pscp.exe"); + if (!Directory.Exists(this.PscpPath)) + { + // If it doesn't exist, create dir + Directory.CreateDirectory(this.PscpPath); + } + + await Task.Run(() => + { + this.systemManagement.FileSystem.File.Copy(this.ExecutablePath, pscpPath); + }); + } + } + + /// + /// Initializes the environment and dependencies for running the pscp workload. + /// + protected override async Task InitializeAsync(EventContext telemetryContext, CancellationToken cancellationToken) + { + DependencyPath workloadPackage = await this.packageManager.GetPackageAsync(this.PackageName, CancellationToken.None); + + if (workloadPackage == null) + { + throw new DependencyException( + $"The expected package '{this.PackageName}' does not exist on the system or is not registered.", + ErrorReason.WorkloadDependencyMissing); + } + + workloadPackage = this.PlatformSpecifics.ToPlatformSpecificPath(workloadPackage, this.Platform, this.CpuArchitecture); + + switch (this.PlatformArchitectureName) + { + case "win-x64": + this.ExecutablePath = this.PlatformSpecifics.Combine(workloadPackage.Path, "pscp.exe"); + ConsoleLogger.Default.LogMessage($"win-x64 path {this.ExecutablePath}", telemetryContext); + this.SupportingExecutables.Add("pscp.exe"); + break; + + case "win-arm64": + this.ExecutablePath = this.PlatformSpecifics.Combine(workloadPackage.Path, "pscp.exe"); + ConsoleLogger.Default.LogMessage($"win-arm64 path {this.ExecutablePath}", telemetryContext); + this.SupportingExecutables.Add("pscp.exe"); + break; + + case "win-x32": + this.ExecutablePath = this.PlatformSpecifics.Combine(workloadPackage.Path, "pscp.exe"); + ConsoleLogger.Default.LogMessage($"win-x32 path {this.ExecutablePath}", telemetryContext); + this.SupportingExecutables.Add("pscp.exe"); + + break; + } + + this.ResultsFilePath = this.PlatformSpecifics.Combine(workloadPackage.Path, $"{this.PackageName}-output.txt"); + + if (!this.fileSystem.File.Exists(this.ExecutablePath)) + { + throw new DependencyException( + $"PSCP executable not found at path '{this.ExecutablePath}'", + ErrorReason.WorkloadDependencyMissing); + } + } + + private void DeleteResultsFile(EventContext telemetryContext) + { + try + { + if (this.fileSystem.File.Exists(this.ResultsFilePath)) + { + this.fileSystem.File.Delete(this.ResultsFilePath); + } + } + catch (IOException exc) + { + this.Logger.LogErrorMessage(exc, telemetryContext); + } + } + } +} diff --git a/src/VirtualClient/VirtualClient.Main/profiles/PSCP.json b/src/VirtualClient/VirtualClient.Main/profiles/PSCP.json new file mode 100644 index 0000000000..9046ad4833 --- /dev/null +++ b/src/VirtualClient/VirtualClient.Main/profiles/PSCP.json @@ -0,0 +1,33 @@ +{ + "Description": "PSCP Installation Workload", + "Metadata": { + "RecommendedMinimumExecutionTime": "00:05:00", + "SupportedPlatforms": "win-x64,win-arm64,,win-arm32", + "SupportedOperatingSystems": "Windows" + }, + "Parameters": { + "PscpPath": "C:\\ToolkitUserFiles\\Binaries\\Putty" + }, + "Actions": [ + { + "Type": "PSCPInstallation", + "Parameters": { + "Scenario": "PSCPInstallation", + "PackageName": "pscp", + "PscpPath": "$.Parameters.PscpPath" + } + } + ], + "Dependencies": [ + { + "Type": "DependencyPackageInstallation", + "Parameters": { + "Scenario": "PSCPInstallation", + "BlobContainer": "packages", + "BlobName": "pscp.zip", + "PackageName": "pscp", + "Extract": true + } + } + ] +} \ No newline at end of file