diff --git a/src/VirtualClient/VirtualClient.Actions.UnitTests/FIO/FioExecutorTests.cs b/src/VirtualClient/VirtualClient.Actions.UnitTests/FIO/FioExecutorTests.cs index a12f7797f..b0e49b711 100644 --- a/src/VirtualClient/VirtualClient.Actions.UnitTests/FIO/FioExecutorTests.cs +++ b/src/VirtualClient/VirtualClient.Actions.UnitTests/FIO/FioExecutorTests.cs @@ -216,39 +216,6 @@ public void FioExecutorAppliesConfigurationParametersCorrectly_DiskFillScenario( } } - [Test] - public async Task FioExecutorCreatesExpectedMountPointsForDisksUnderTest_RemoteDiskScenario() - { - // Clear any access points out. - this.disks.ToList().ForEach(disk => disk.Volumes.ToList().ForEach(vol => (vol.AccessPaths as List).Clear())); - - List> mountPointsCreated = new List>(); - - this.DiskManager - .Setup(mgr => mgr.CreateMountPointAsync(It.IsAny(), It.IsAny(), It.IsAny())) - .Callback((volume, mountPoint, token) => - { - (volume.AccessPaths as List).Add(mountPoint); - }) - .Returns(Task.CompletedTask); - - using (TestFioExecutor workloadExecutor = new TestFioExecutor(this.Dependencies, this.profileParameters)) - { - await workloadExecutor.ExecuteAsync(CancellationToken.None); - - Assert.IsTrue(this.disks.Skip(1).All(d => d.Volumes.First().AccessPaths?.Any() == true)); - - string expectedMountPoint1 = Path.Combine(MockFixture.TestAssemblyDirectory, "vcmnt_dev_sdd1"); - Assert.AreEqual(expectedMountPoint1, this.disks.ElementAt(1).Volumes.First().AccessPaths.First()); - - string expectedMountPoint2 = Path.Combine(MockFixture.TestAssemblyDirectory, "vcmnt_dev_sde1"); - Assert.AreEqual(expectedMountPoint2, this.disks.ElementAt(2).Volumes.First().AccessPaths.First()); - - string expectedMountPoint3 = Path.Combine(MockFixture.TestAssemblyDirectory, "vcmnt_dev_sdf1"); - Assert.AreEqual(expectedMountPoint3, this.disks.ElementAt(3).Volumes.First().AccessPaths.First()); - } - } - [Test] public void FioExecutorCreatesTheExpectedWorkloadProcess_Scenario1() { diff --git a/src/VirtualClient/VirtualClient.Actions/FIO/FioExecutor.cs b/src/VirtualClient/VirtualClient.Actions/FIO/FioExecutor.cs index dcccd8126..74e1abec1 100644 --- a/src/VirtualClient/VirtualClient.Actions/FIO/FioExecutor.cs +++ b/src/VirtualClient/VirtualClient.Actions/FIO/FioExecutor.cs @@ -303,7 +303,9 @@ protected override async Task ExecuteAsync(EventContext telemetryContext, Cancel string ioEngine = FioExecutor.GetIOEngine(Environment.OSVersion.Platform); - IEnumerable disks = await this.SystemManagement.DiskManager.GetDisksAsync(cancellationToken) + this.DiskFilter = string.IsNullOrWhiteSpace(this.DiskFilter) ? DiskFilters.DefaultDiskFilter : this.DiskFilter; + + IEnumerable disks = await this.SystemManagement.DiskManager.GetFilteredDisksAsync(this.Platform, this.DiskFilter, cancellationToken) .ConfigureAwait(false); if (disks?.Any() != true) @@ -313,37 +315,15 @@ protected override async Task ExecuteAsync(EventContext telemetryContext, Cancel ErrorReason.WorkloadUnexpectedAnomaly); } - IEnumerable disksToTest = this.GetDisksToTest(disks); - - if (disksToTest?.Any() != true) - { - throw new WorkloadException( - "Expected disks to test not found. Given the parameters defined for the profile action/step or those passed " + - "in on the command line, the requisite disks do not exist on the system or could not be identified based on the properties " + - "of the existing disks.", - ErrorReason.DependencyNotFound); - } - - if (await this.CreateMountPointsAsync(disksToTest, cancellationToken).ConfigureAwait(false)) - { - // Refresh the disks to pickup the mount point changes. - await Task.Delay(1000).ConfigureAwait(false); - IEnumerable updatedDisks = await this.SystemManagement.DiskManager.GetDisksAsync(cancellationToken) - .ConfigureAwait(false); - - disksToTest = this.GetDisksToTest(updatedDisks); - } - telemetryContext.AddContext(nameof(this.DiskFilter), this.DiskFilter); telemetryContext.AddContext("executable", this.ExecutablePath); telemetryContext.AddContext(nameof(ioEngine), ioEngine); telemetryContext.AddContext(nameof(disks), disks); - telemetryContext.AddContext(nameof(disksToTest), disksToTest); this.WorkloadProcesses.Clear(); List fioProcessTasks = new List(); - this.WorkloadProcesses.AddRange(this.CreateWorkloadProcesses(this.ExecutablePath, this.CommandLine, disksToTest, this.ProcessModel)); + this.WorkloadProcesses.AddRange(this.CreateWorkloadProcesses(this.ExecutablePath, this.CommandLine, disks, this.ProcessModel)); using (BackgroundOperations profiling = BackgroundOperations.BeginProfiling(this, cancellationToken)) { @@ -386,48 +366,6 @@ await this.DeleteTestFilesAsync(workload.TestFiles) } } - /// - /// Creates mount points for any disks that do not have them already. - /// - /// This disks on which to create the mount points. - /// A token that can be used to cancel the operation. - protected async Task CreateMountPointsAsync(IEnumerable disks, CancellationToken cancellationToken) - { - bool mountPointsCreated = false; - - // Don't mount any partition in OS drive. - foreach (Disk disk in disks.Where(d => !d.IsOperatingSystem())) - { - // mount every volume that doesn't have an accessPath. - foreach (DiskVolume volume in disk.Volumes.Where(v => v.AccessPaths?.Any() != true)) - { - string newMountPoint = volume.GetDefaultMountPoint(); - this.Logger.LogTraceMessage($"Create Mount Point: {newMountPoint}"); - - EventContext relatedContext = EventContext.Persisted().Clone() - .AddContext(nameof(volume), volume) - .AddContext("mountPoint", newMountPoint); - - await this.Logger.LogMessageAsync($"{this.TypeName}.CreateMountPoint", relatedContext, async () => - { - string newMountPoint = volume.GetDefaultMountPoint(); - if (!this.SystemManagement.FileSystem.Directory.Exists(newMountPoint)) - { - this.SystemManagement.FileSystem.Directory.CreateDirectory(newMountPoint).Create(); - } - - await this.SystemManagement.DiskManager.CreateMountPointAsync(volume, newMountPoint, cancellationToken) - .ConfigureAwait(false); - - mountPointsCreated = true; - - }).ConfigureAwait(false); - } - } - - return mountPointsCreated; - } - /// /// Creates a process to run FIO targeting the disks specified. /// diff --git a/src/VirtualClient/VirtualClient.Core.UnitTests/UnixDiskManagerTests.cs b/src/VirtualClient/VirtualClient.Core.UnitTests/UnixDiskManagerTests.cs index ee4728693..1ff5d8427 100644 --- a/src/VirtualClient/VirtualClient.Core.UnitTests/UnixDiskManagerTests.cs +++ b/src/VirtualClient/VirtualClient.Core.UnitTests/UnixDiskManagerTests.cs @@ -349,6 +349,20 @@ public void UnixDiskManagerAppliesRetriesOnFailedAttemptsToCreateMountPoints() Assert.IsTrue(attempts == 4); } + [Test] + public async Task UnixDiskManagerReturnsListofFilteredDisks() + { + this.testProcess.OnHasExited = () => true; + this.testProcess.OnStart = () => true; + this.testProcess.StandardOutput.Append(Resources.lshw_disk_storage_results); + + + IEnumerable disks = await this.diskManager.GetFilteredDisksAsync(PlatformID.Unix, "osdisk:false", CancellationToken.None) + .ConfigureAwait(false); + + Assert.AreEqual(disks.Count(), 3); + } + private class TestUnixDiskManager : UnixDiskManager { public TestUnixDiskManager(ProcessManager processManager) diff --git a/src/VirtualClient/VirtualClient.Core.UnitTests/WindowsDiskManagerTests.cs b/src/VirtualClient/VirtualClient.Core.UnitTests/WindowsDiskManagerTests.cs index 9f9695f19..578e0e8bf 100644 --- a/src/VirtualClient/VirtualClient.Core.UnitTests/WindowsDiskManagerTests.cs +++ b/src/VirtualClient/VirtualClient.Core.UnitTests/WindowsDiskManagerTests.cs @@ -1483,6 +1483,89 @@ public async Task WindowsDiskManagerGetsTheExpectedDisks_Scenario1() actualDisks.ToList().ForEach(disk => Assert.IsTrue(disk.Volumes.Count() == 2)); } + [Test] + public async Task WindowsDiskManagerReturnsListofFilteredDisks() + { + this.testProcess.OnHasExited = () => true; + this.testProcess.OnStart = () => true; + + this.standardInput.BytesWritten += (sender, data) => + { + string input = data.ToString().Trim(); + if (input.Contains($"select disk")) + { + int diskIndex = int.Parse(Regex.Match(input, "[0-9]+").Value); + this.testProcess.StandardOutput.Append($"Disk {diskIndex} is now the selected disk."); + } + else if (input.Contains($"select partition")) + { + int partitionIndex = int.Parse(Regex.Match(input, "[0-9]+").Value); + this.testProcess.StandardOutput.Append($"Partition {partitionIndex} is now the selected partition."); + } + else if (input.Contains("list disk")) + { + StringBuilder listDiskResults = new StringBuilder() + .AppendLine(" ") + .AppendLine(" Disk ### Status Size Free Dyn Gpt") + .AppendLine(" -------- ------------- ------- ------- --- ---") + .AppendLine(" Disk 0 Online 127 GB 1024 KB "); + + this.testProcess.StandardOutput.Append(listDiskResults.ToString()); + } + else if (input.Contains("list partition")) + { + StringBuilder listPartitionResults = new StringBuilder() + .AppendLine(" ") + .AppendLine(" Partition ### Type Size Offset") + .AppendLine(" ------------- ---------------- ------- -------") + .AppendLine(" Partition 1 Primary 500 MB 1024 KB") + .AppendLine(" Partition 2 Primary 126 GB 501 MB"); + + this.testProcess.StandardOutput.Append(listPartitionResults.ToString()); + } + else if (input.Contains($"detail disk")) + { + StringBuilder detailDiskResults = new StringBuilder() + .AppendLine(" ") + .AppendLine("Virtual HD ATA Device") + .AppendLine("Disk ID: EF349D83") + .AppendLine("Type : ATA") + .AppendLine("Status : Online") + .AppendLine("Path : 0") + .AppendLine("Target : 0") + .AppendLine("LUN ID : 0") + .AppendLine(" ") + .AppendLine(" Volume ### Ltr Label Fs Type Size Status Info ") + .AppendLine(" ---------- --- ----------- ----- ---------- ------- --------- --------") + .AppendLine(" Volume 0 System Rese NTFS Partition 500 MB Healthy System ") + .AppendLine(" Volume 1 C Windows NTFS Partition 126 GB Healthy Boot "); + + this.testProcess.StandardOutput.Append(detailDiskResults.ToString()); + } + else if (input.Contains($"detail partition")) + { + StringBuilder detailPartitionResults = new StringBuilder() + .AppendLine(" ") + .AppendLine("Partition 1") + .AppendLine("Type : 07") + .AppendLine("Hidden: No") + .AppendLine("Active: Yes") + .AppendLine("Offset in Bytes: 525336576") + .AppendLine(" ") + .AppendLine(" Volume ### Ltr Label Fs Type Size Status Info ") + .AppendLine(" ---------- --- ----------- ----- ---------- ------- --------- --------") + .AppendLine(" Volume 1 C Windows NTFS Partition 126 GB Healthy Boot "); + + this.testProcess.StandardOutput.Append(detailPartitionResults.ToString()); + } + }; + + IEnumerable disks = await this.diskManager.GetFilteredDisksAsync(PlatformID.Win32NT, DiskFilters.DefaultDiskFilter, CancellationToken.None) + .ConfigureAwait(false); + + Assert.AreEqual(disks.Count(), 1); + } + private class TestWindowsDiskManager : WindowsDiskManager { public TestWindowsDiskManager(ProcessManager processManager) diff --git a/src/VirtualClient/VirtualClient.Core/DiskManagerExtensions.cs b/src/VirtualClient/VirtualClient.Core/DiskManagerExtensions.cs new file mode 100644 index 000000000..1971783f3 --- /dev/null +++ b/src/VirtualClient/VirtualClient.Core/DiskManagerExtensions.cs @@ -0,0 +1,42 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace VirtualClient +{ + using System; + using System.Collections; + using System.Collections.Generic; + using System.IO; + using System.IO.Abstractions; + using System.Linq; + using System.Text.RegularExpressions; + using System.Threading; + using System.Threading.Tasks; + using Polly; + using VirtualClient.Common.Extensions; + using VirtualClient.Contracts; + + /// + /// Methods for extending the functionality of the + /// disk manager class, and related classes. + /// + public static class DiskManagerExtensions + { + /// + /// Gets a filtered set of physical disks that exist on the system. + /// + /// + /// + /// A token that can be used to cancel the operation. + /// The filter to apply to the disks. + public static async Task> GetFilteredDisksAsync(this IDiskManager diskManager, PlatformID platform, string diskFilter, CancellationToken cancellationToken) + { + IEnumerable disks = await diskManager.GetDisksAsync(cancellationToken) + .ConfigureAwait(false); + + IEnumerable filteredDisks = DiskFilters.FilterDisks(disks, diskFilter, platform).ToList(); + + return filteredDisks; + } + } +} diff --git a/src/VirtualClient/VirtualClient.Main/profiles/PERF-IO-FIO.json b/src/VirtualClient/VirtualClient.Main/profiles/PERF-IO-FIO.json index f3d098128..b5ab75305 100644 --- a/src/VirtualClient/VirtualClient.Main/profiles/PERF-IO-FIO.json +++ b/src/VirtualClient/VirtualClient.Main/profiles/PERF-IO-FIO.json @@ -500,6 +500,12 @@ "Scenario": "InitializeDisks" } }, + { + "Type": "MountDisks", + "Parameters": { + "Scenario": "CreateMountPoints" + } + }, { "Type": "DependencyPackageInstallation", "Parameters": {