From e8a99433b40f62d9782b9678c16237767cfb0db3 Mon Sep 17 00:00:00 2001 From: Tingmao Wang Date: Tue, 11 Feb 2025 21:12:32 +0000 Subject: [PATCH 1/8] Add DummyDiskManager A DiskManager that simply presents a OS disk, and does not try to do any discovery. Useful in containers. --- .../VirtualClient.Core/DependencyFactory.cs | 20 ++-- .../VirtualClient.Core/DummyDiskManager.cs | 97 +++++++++++++++++++ 2 files changed, 110 insertions(+), 7 deletions(-) create mode 100644 src/VirtualClient/VirtualClient.Core/DummyDiskManager.cs diff --git a/src/VirtualClient/VirtualClient.Core/DependencyFactory.cs b/src/VirtualClient/VirtualClient.Core/DependencyFactory.cs index 2cbcd0a741..f9004aef06 100644 --- a/src/VirtualClient/VirtualClient.Core/DependencyFactory.cs +++ b/src/VirtualClient/VirtualClient.Core/DependencyFactory.cs @@ -84,7 +84,13 @@ public static IBlobManager CreateBlobManager(DependencyStore dependencyStore) /// A logger for capturing disk management telemetry. public static DiskManager CreateDiskManager(PlatformID platform, Microsoft.Extensions.Logging.ILogger logger = null) { + if (PlatformSpecifics.IsRunningInContainer()) + { + return new DummyDiskManager(platform, logger); + } + DiskManager manager = null; + switch (platform) { case PlatformID.Win32NT: @@ -326,8 +332,8 @@ public static IEnumerable CreateFileLoggerProviders(string logF // Metrics/Results ILoggerProvider metricsLoggerProvider = DependencyFactory.CreateFileLoggerProvider( - Path.Combine(logFileDirectory, settings.MetricsFileName), - TimeSpan.FromSeconds(3), + Path.Combine(logFileDirectory, settings.MetricsFileName), + TimeSpan.FromSeconds(3), LogLevel.Trace, new SerilogJsonTextFormatter(propertiesToExcludeForMetrics)).HandleMetrics(); @@ -336,7 +342,7 @@ public static IEnumerable CreateFileLoggerProviders(string logF // Metrics/Results in CSV Format ILoggerProvider metricsCsvLoggerProvider = DependencyFactory.CreateCsvFileLoggerProvider( - Path.Combine(logFileDirectory, + Path.Combine(logFileDirectory, settings.MetricsCsvFileName)).HandleMetrics(); VirtualClientRuntime.CleanupTasks.Add(new Action_(() => metricsCsvLoggerProvider.Dispose())); @@ -344,8 +350,8 @@ public static IEnumerable CreateFileLoggerProviders(string logF // System Events ILoggerProvider eventsLoggerProvider = DependencyFactory.CreateFileLoggerProvider( - Path.Combine(logFileDirectory, settings.EventsFileName), - TimeSpan.FromSeconds(5), + Path.Combine(logFileDirectory, settings.EventsFileName), + TimeSpan.FromSeconds(5), LogLevel.Trace, new SerilogJsonTextFormatter(propertiesToExcludeForEvents)).HandleSystemEvents(); @@ -670,7 +676,7 @@ public static VirtualClientProxyApiClient CreateVirtualClientProxyApiClient(Uri public static void FlushTelemetry(TimeSpan? timeout = null) { Parallel.ForEach(DependencyFactory.telemetryChannels, channel => channel.Flush(timeout)); - } + } /// /// Applies a filter to the logger generated by the provider that will handle the logging @@ -708,4 +714,4 @@ internal static ILoggerProvider HandleTraces(this ILoggerProvider loggerProvider return loggerProvider.WithFilter((eventId, logLevel, state) => (LogType)eventId.Id <= LogType.Error); } } -} \ No newline at end of file +} diff --git a/src/VirtualClient/VirtualClient.Core/DummyDiskManager.cs b/src/VirtualClient/VirtualClient.Core/DummyDiskManager.cs new file mode 100644 index 0000000000..daca372184 --- /dev/null +++ b/src/VirtualClient/VirtualClient.Core/DummyDiskManager.cs @@ -0,0 +1,97 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace VirtualClient +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Threading; + using System.Threading.Tasks; + using Microsoft.Extensions.Logging; + using Polly; + using VirtualClient.Common; + using VirtualClient.Common.Extensions; + using VirtualClient.Common.Telemetry; + using VirtualClient.Contracts; + + /// + /// A DiskManager that simply presents a OS disk, and does not try to do any + /// discovery. Useful in containers. + /// + public class DummyDiskManager : DiskManager + { + private readonly DiskVolume volume; + private readonly Disk disk; + + /// + /// Create a new instance. + /// + /// + /// + public DummyDiskManager(PlatformID platform, ILogger logger = null) + : base(logger) + { + string defaultMountPath = platform == PlatformID.Win32NT ? "C:\\" : "/"; + string devicePath = platform == PlatformID.Win32NT ? "C:\\" : "/dev/sda"; + + var volumeProps = new Dictionary(); + + // TODO: determine size with `df` or whatever on Windows + + if (platform == PlatformID.Win32NT) + { + volumeProps.Add(Disk.WindowsDiskProperties.Info, "Boot"); + volumeProps.Add(Disk.WindowsDiskProperties.Size, 1ul << 30); + } + else + { + volumeProps.Add(Disk.UnixDiskProperties.Size, 1ul << 30); + } + + this.volume = new DiskVolume(0, devicePath, new[] { defaultMountPath }, volumeProps); + this.disk = new Disk(0, devicePath, new[] { this.volume }); + } + + /// + /// Get the set of disks. + /// + /// + /// + public override Task> GetDisksAsync(CancellationToken cancellationToken) + { + return Task.FromResult>(new[] { this.disk }); + } + + /// + /// No-op + /// + /// + /// + /// + /// + /// + public override Task FormatDiskAsync(Disk disk, PartitionType partitionType, FileSystemType fileSystemType, CancellationToken cancellationToken) + { + return Task.CompletedTask; + } + + /// + /// No-op + /// + /// + /// + /// + /// + /// + public override Task CreateMountPointAsync(DiskVolume volume, string mountPoint, CancellationToken cancellationToken) + { + if (volume != this.volume) + { + throw new ArgumentException("Invalid volume provided to DummyDiskManager::CreateMountPointAsync"); + } + + return Task.CompletedTask; + } + } +} From a86dcd39367619e6f236c608b8fc1dbc98eb4014 Mon Sep 17 00:00:00 2001 From: Tingmao Wang Date: Tue, 11 Feb 2025 21:12:57 +0000 Subject: [PATCH 2/8] Fix likely typo in DiskExtensions.cs --- .../VirtualClient.Contracts/DiskExtensions.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/VirtualClient/VirtualClient.Contracts/DiskExtensions.cs b/src/VirtualClient/VirtualClient.Contracts/DiskExtensions.cs index 24046551b3..91f671db75 100644 --- a/src/VirtualClient/VirtualClient.Contracts/DiskExtensions.cs +++ b/src/VirtualClient/VirtualClient.Contracts/DiskExtensions.cs @@ -11,7 +11,7 @@ namespace VirtualClient.Contracts using System.Text.RegularExpressions; /// - /// + /// /// public static class DiskExtensions { @@ -42,11 +42,10 @@ public static string GetPreferredAccessPath(this Disk disk, PlatformID platform) path = "/"; } - else if (platform == PlatformID.Unix && disk.IsOperatingSystem()) + else if (platform == PlatformID.Win32NT && disk.IsOperatingSystem()) { // If it is OS disk, test on OS partition path = disk.Volumes.Where(v => v.IsOperatingSystem()).FirstOrDefault().AccessPaths.FirstOrDefault(); - } else { @@ -178,7 +177,7 @@ public static long SizeInBytes(this Disk disk, PlatformID platform) else { result = disk.Volumes.Sum(v => v.SizeInBytes(platform)); - } + } } return result; From 9b5ac6efd02d70e25b0b3a934f8497367c7a5890 Mon Sep 17 00:00:00 2001 From: Tingmao Wang Date: Tue, 11 Feb 2025 21:28:27 +0000 Subject: [PATCH 3/8] PERF-POSTGRESQL-HAMMERDB-TPCC.json: pass-through DiskFilter parameter to FormatDisks/MountDisks --- .../profiles/PERF-POSTGRESQL-HAMMERDB-TPCC.json | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/VirtualClient/VirtualClient.Main/profiles/PERF-POSTGRESQL-HAMMERDB-TPCC.json b/src/VirtualClient/VirtualClient.Main/profiles/PERF-POSTGRESQL-HAMMERDB-TPCC.json index b3600e54bd..fcd0d35e88 100644 --- a/src/VirtualClient/VirtualClient.Main/profiles/PERF-POSTGRESQL-HAMMERDB-TPCC.json +++ b/src/VirtualClient/VirtualClient.Main/profiles/PERF-POSTGRESQL-HAMMERDB-TPCC.json @@ -49,14 +49,16 @@ "Type": "FormatDisks", "Parameters": { "Scenario": "FormatDisks", - "Role": "Server" + "Role": "Server", + "DiskFilter": "$.Parameters.DiskFilter" } }, { "Type": "MountDisks", "Parameters": { "Scenario": "CreateMountPoints", - "Role": "Server" + "Role": "Server", + "DiskFilter": "$.Parameters.DiskFilter" } }, { @@ -103,7 +105,8 @@ "Role": "Server", "DatabaseName": "$.Parameters.DatabaseName", "Port": "$.Parameters.Port", - "SharedMemoryBuffer": "$.Parameters.SharedMemoryBuffer" + "SharedMemoryBuffer": "$.Parameters.SharedMemoryBuffer", + "DiskFilter": "$.Parameters.DiskFilter" } }, { @@ -154,4 +157,4 @@ } } ] -} \ No newline at end of file +} From 2444752026b768dfa07313fb6c02556f42e933bd Mon Sep 17 00:00:00 2001 From: Tingmao Wang Date: Thu, 13 Feb 2025 15:31:11 +0000 Subject: [PATCH 4/8] PostgreSQL profile: Take in a DataDirectory parameter to specify which dir to use on the disk Particularly useful when using the os disk --- .../PostgreSQLServerConfiguration.cs | 36 +++++++++++++++++-- .../PERF-POSTGRESQL-HAMMERDB-TPCC.json | 4 ++- .../PERF-POSTGRESQL-SYSBENCH-OLTP.json | 4 ++- .../PERF-POSTGRESQL-SYSBENCH-TPCC.json | 6 ++-- 4 files changed, 43 insertions(+), 7 deletions(-) diff --git a/src/VirtualClient/VirtualClient.Dependencies/PostgreSQLServer/PostgreSQLServerConfiguration.cs b/src/VirtualClient/VirtualClient.Dependencies/PostgreSQLServer/PostgreSQLServerConfiguration.cs index 876f7d8ca3..8416d799e4 100644 --- a/src/VirtualClient/VirtualClient.Dependencies/PostgreSQLServer/PostgreSQLServerConfiguration.cs +++ b/src/VirtualClient/VirtualClient.Dependencies/PostgreSQLServer/PostgreSQLServerConfiguration.cs @@ -5,6 +5,7 @@ namespace VirtualClient.Dependencies { using System; using System.Collections.Generic; + using System.IO; using System.Linq; using System.Net; using System.Security.Cryptography; @@ -78,6 +79,17 @@ public string DiskFilter } } + /// + /// Directory for the PostgreSQL database within the disk. + /// + public string DataDirectory + { + get + { + return this.Parameters.GetValue(nameof(this.DataDirectory), string.Empty); + } + } + /// /// Database Name to create and utilize /// @@ -108,8 +120,15 @@ public string SuperUserPassword { get { - byte[] hashBytes = SHA256.HashData(Encoding.UTF8.GetBytes(this.ExperimentId)); - return Convert.ToBase64String(hashBytes); + if (this.Parameters.ContainsKey(nameof(this.SuperUserPassword))) + { + return this.Parameters.GetValue(nameof(this.SuperUserPassword)); + } + else + { + byte[] hashBytes = SHA256.HashData(Encoding.UTF8.GetBytes(this.ExperimentId)); + return Convert.ToBase64String(hashBytes); + } } } @@ -267,7 +286,18 @@ private async Task GetPostgreSQLInnodbDirectoriesAsync(CancellationToken foreach (Disk disk in disksToTest) { - diskPaths += $"{disk.GetPreferredAccessPath(this.Platform)};"; + string path = disk.GetPreferredAccessPath(this.Platform); + + if (!string.IsNullOrEmpty(this.DataDirectory)) + { + path = Path.Join(path, this.DataDirectory); + if (!Directory.Exists(path)) + { + Directory.CreateDirectory(path); + } + } + + diskPaths += $"{path};"; } } diff --git a/src/VirtualClient/VirtualClient.Main/profiles/PERF-POSTGRESQL-HAMMERDB-TPCC.json b/src/VirtualClient/VirtualClient.Main/profiles/PERF-POSTGRESQL-HAMMERDB-TPCC.json index fcd0d35e88..2f35603751 100644 --- a/src/VirtualClient/VirtualClient.Main/profiles/PERF-POSTGRESQL-HAMMERDB-TPCC.json +++ b/src/VirtualClient/VirtualClient.Main/profiles/PERF-POSTGRESQL-HAMMERDB-TPCC.json @@ -9,6 +9,7 @@ "Parameters": { "DatabaseName": "hammerdb_tpcc", "DiskFilter": "osdisk:false&sizegreaterthan:256g", + "DataDirectory": "", "Port": "5432", "VirtualUsers": "{calculate({LogicalCoreCount})}", "WarehouseCount": "{calculate({SystemMemoryMegabytes} * 15 / 800)}", @@ -132,7 +133,8 @@ "DiskFilter": "$.Parameters.DiskFilter", "PackageName": "postgresql", "Port": "$.Parameters.Port", - "Role": "Server" + "Role": "Server", + "DataDirectory": "$.Parameters.DataDirectory" } }, { diff --git a/src/VirtualClient/VirtualClient.Main/profiles/PERF-POSTGRESQL-SYSBENCH-OLTP.json b/src/VirtualClient/VirtualClient.Main/profiles/PERF-POSTGRESQL-SYSBENCH-OLTP.json index b884e450b5..818c69dfed 100644 --- a/src/VirtualClient/VirtualClient.Main/profiles/PERF-POSTGRESQL-SYSBENCH-OLTP.json +++ b/src/VirtualClient/VirtualClient.Main/profiles/PERF-POSTGRESQL-SYSBENCH-OLTP.json @@ -9,6 +9,7 @@ "Parameters": { "DatabaseName": "sbtest", "DiskFilter": "osdisk:false&sizegreaterthan:256g", + "DataDirectory": "", "Port": "5432", "SharedMemoryBuffer": "{calculate({SystemMemoryMegabytes} * 85 / 100)}", "DatabaseScenario": "Balanced", @@ -249,7 +250,8 @@ "DiskFilter": "$.Parameters.DiskFilter", "PackageName": "postgresql", "Port": "$.Parameters.Port", - "Role": "Server" + "Role": "Server", + "DataDirectory": "$.Parameters.DataDirectory" } }, { diff --git a/src/VirtualClient/VirtualClient.Main/profiles/PERF-POSTGRESQL-SYSBENCH-TPCC.json b/src/VirtualClient/VirtualClient.Main/profiles/PERF-POSTGRESQL-SYSBENCH-TPCC.json index 9b25fe91d4..030020965e 100644 --- a/src/VirtualClient/VirtualClient.Main/profiles/PERF-POSTGRESQL-SYSBENCH-TPCC.json +++ b/src/VirtualClient/VirtualClient.Main/profiles/PERF-POSTGRESQL-SYSBENCH-TPCC.json @@ -9,6 +9,7 @@ "Parameters": { "DatabaseName": "sbtest", "DiskFilter": "osdisk:false&sizegreaterthan:256g", + "DataDirectory": "", "Port": "5432", "SharedMemoryBuffer": "{calculate({SystemMemoryMegabytes} * 85 / 100)}", "DatabaseScenario": "Balanced", @@ -137,7 +138,8 @@ "DiskFilter": "$.Parameters.DiskFilter", "PackageName": "postgresql", "Port": "$.Parameters.Port", - "Role": "Server" + "Role": "Server", + "DataDirectory": "$.Parameters.DataDirectory" } }, { @@ -160,4 +162,4 @@ } } ] -} \ No newline at end of file +} From 424166210a0324476235faf12b4de6e4a947b9fa Mon Sep 17 00:00:00 2001 From: Tingmao Wang Date: Thu, 13 Feb 2025 15:31:20 +0000 Subject: [PATCH 5/8] UnixFirewallManager: Skip enabling inbound connections when running in a container We won't have permission to change netfilter rules from within a container --- .../VirtualClient.Core/UnixFirewallManager.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/VirtualClient/VirtualClient.Core/UnixFirewallManager.cs b/src/VirtualClient/VirtualClient.Core/UnixFirewallManager.cs index c04782a600..c2888c7788 100644 --- a/src/VirtualClient/VirtualClient.Core/UnixFirewallManager.cs +++ b/src/VirtualClient/VirtualClient.Core/UnixFirewallManager.cs @@ -11,6 +11,7 @@ namespace VirtualClient using VirtualClient.Common; using VirtualClient.Common.Extensions; using VirtualClient.Common.Platform; + using VirtualClient.Contracts; /// /// Provides methods for managing Unix/Linux system/OS firewall operations. @@ -45,6 +46,13 @@ public override Task EnableInboundAppAsync(FirewallEntry firewallEntry, Cancella public async override Task EnableInboundConnectionAsync(FirewallEntry firewallEntry, CancellationToken cancellationToken) { firewallEntry.ThrowIfNull(nameof(firewallEntry)); + + if (PlatformSpecifics.IsRunningInContainer()) + { + // Can't set iptables from within a container. + return; + } + if (!cancellationToken.IsCancellationRequested) { string ports = null; From 5cd5e54f2f3db07de10909494e1c0afe1581fa02 Mon Sep 17 00:00:00 2001 From: Tingmao Wang Date: Thu, 13 Feb 2025 15:32:07 +0000 Subject: [PATCH 6/8] Fix typo in PERF-POSTGRESQL-SYSBENCH-TPCC.json description --- .../profiles/PERF-POSTGRESQL-SYSBENCH-TPCC.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/VirtualClient/VirtualClient.Main/profiles/PERF-POSTGRESQL-SYSBENCH-TPCC.json b/src/VirtualClient/VirtualClient.Main/profiles/PERF-POSTGRESQL-SYSBENCH-TPCC.json index 030020965e..2eb65672d4 100644 --- a/src/VirtualClient/VirtualClient.Main/profiles/PERF-POSTGRESQL-SYSBENCH-TPCC.json +++ b/src/VirtualClient/VirtualClient.Main/profiles/PERF-POSTGRESQL-SYSBENCH-TPCC.json @@ -1,5 +1,5 @@ { - "Description": "Sysbench TPCC MySQL Database Server Performance Workload", + "Description": "Sysbench TPCC PostgreSQL Database Server Performance Workload", "MinimumExecutionInterval": "00:01:00", "Metadata": { "RecommendedMinimumExecutionTime": "04:00:00", From 094cad876ac627196598794f027eb2aabedee1e6 Mon Sep 17 00:00:00 2001 From: Tingmao Wang Date: Thu, 13 Feb 2025 15:33:39 +0000 Subject: [PATCH 7/8] PostgreSQL: DiskFilter is not used in ConfigureServer, so remove it --- .../profiles/PERF-POSTGRESQL-HAMMERDB-TPCC.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/VirtualClient/VirtualClient.Main/profiles/PERF-POSTGRESQL-HAMMERDB-TPCC.json b/src/VirtualClient/VirtualClient.Main/profiles/PERF-POSTGRESQL-HAMMERDB-TPCC.json index 2f35603751..40a6b5d036 100644 --- a/src/VirtualClient/VirtualClient.Main/profiles/PERF-POSTGRESQL-HAMMERDB-TPCC.json +++ b/src/VirtualClient/VirtualClient.Main/profiles/PERF-POSTGRESQL-HAMMERDB-TPCC.json @@ -106,8 +106,7 @@ "Role": "Server", "DatabaseName": "$.Parameters.DatabaseName", "Port": "$.Parameters.Port", - "SharedMemoryBuffer": "$.Parameters.SharedMemoryBuffer", - "DiskFilter": "$.Parameters.DiskFilter" + "SharedMemoryBuffer": "$.Parameters.SharedMemoryBuffer" } }, { From bb9601d1c030e47e1c8f3003851709fbb7977210 Mon Sep 17 00:00:00 2001 From: Tingmao Wang Date: Thu, 13 Feb 2025 15:35:14 +0000 Subject: [PATCH 8/8] Pass DiskFilter to Format/MountDisks in the two other postgresql profile --- .../profiles/PERF-POSTGRESQL-SYSBENCH-OLTP.json | 8 +++++--- .../profiles/PERF-POSTGRESQL-SYSBENCH-TPCC.json | 6 ++++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/VirtualClient/VirtualClient.Main/profiles/PERF-POSTGRESQL-SYSBENCH-OLTP.json b/src/VirtualClient/VirtualClient.Main/profiles/PERF-POSTGRESQL-SYSBENCH-OLTP.json index 818c69dfed..c65ca9bd0d 100644 --- a/src/VirtualClient/VirtualClient.Main/profiles/PERF-POSTGRESQL-SYSBENCH-OLTP.json +++ b/src/VirtualClient/VirtualClient.Main/profiles/PERF-POSTGRESQL-SYSBENCH-OLTP.json @@ -156,7 +156,8 @@ "Type": "FormatDisks", "Parameters": { "Scenario": "FormatDisks", - "Role": "Server" + "Role": "Server", + "DiskFilter": "$.Parameters.DiskFilter" } }, { @@ -164,7 +165,8 @@ "Parameters": { "Scenario": "CreateMountPoints", "MountLocation": "Root", - "Role": "Server" + "Role": "Server", + "DiskFilter": "$.Parameters.DiskFilter" } }, { @@ -274,4 +276,4 @@ } } ] -} \ No newline at end of file +} diff --git a/src/VirtualClient/VirtualClient.Main/profiles/PERF-POSTGRESQL-SYSBENCH-TPCC.json b/src/VirtualClient/VirtualClient.Main/profiles/PERF-POSTGRESQL-SYSBENCH-TPCC.json index 2eb65672d4..9b9ec76678 100644 --- a/src/VirtualClient/VirtualClient.Main/profiles/PERF-POSTGRESQL-SYSBENCH-TPCC.json +++ b/src/VirtualClient/VirtualClient.Main/profiles/PERF-POSTGRESQL-SYSBENCH-TPCC.json @@ -44,7 +44,8 @@ "Type": "FormatDisks", "Parameters": { "Scenario": "FormatDisks", - "Role": "Server" + "Role": "Server", + "DiskFilter": "$.Parameters.DiskFilter" } }, { @@ -52,7 +53,8 @@ "Parameters": { "Scenario": "CreateMountPoints", "MountLocation": "Root", - "Role": "Server" + "Role": "Server", + "DiskFilter": "$.Parameters.DiskFilter" } }, {