diff --git a/src/VirtualClient/VirtualClient.Actions.FunctionalTests/SysbenchProfileTests.cs b/src/VirtualClient/VirtualClient.Actions.FunctionalTests/SysbenchProfileTests.cs index 93db09060d..bb34053657 100644 --- a/src/VirtualClient/VirtualClient.Actions.FunctionalTests/SysbenchProfileTests.cs +++ b/src/VirtualClient/VirtualClient.Actions.FunctionalTests/SysbenchProfileTests.cs @@ -485,18 +485,18 @@ private IEnumerable GetProfileExpectedCommands(bool singleVM, string dat $"python3 {this.sysbenchPackagePath}/configure-workload-generator.py --distro Ubuntu --databaseSystem MySQL --packagePath {this.sysbenchPackagePath}", - $"python3 {this.sysbenchPackagePath}/populate-database.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --tableCount 10 --recordCount 1 --threadCount 8 --password [A-Za-z0-9+/=]+", + $"python3 {this.sysbenchPackagePath}/populate-database.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --threadCount 8 --tableCount 10 --recordCount 1 --password [A-Za-z0-9+/=]+", $"python3 {this.mySQLPackagePath}/distribute-database.py --dbName sbtest --directories \"/mnt_vc_0;/mnt_vc_1;/mnt_vc_2;\"", - $"python3 {this.sysbenchPackagePath}/populate-database.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --tableCount 10 --recordCount 1000 --threadCount 8", - - $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --tableCount 10 --recordCount 1000 --threadCount 8 --workload oltp_read_write --hostIpAddress 127.0.0.1 --durationSecs 300 --password [A-Za-z0-9+/=]+", - $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --tableCount 10 --recordCount 1000 --threadCount 8 --workload oltp_read_only --hostIpAddress 127.0.0.1 --durationSecs 300 --password [A-Za-z0-9+/=]+", - $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --tableCount 10 --recordCount 1000 --threadCount 8 --workload oltp_delete --hostIpAddress 127.0.0.1 --durationSecs 300 --password [A-Za-z0-9+/=]+", - $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --tableCount 10 --recordCount 1000 --threadCount 8 --workload oltp_insert --hostIpAddress 127.0.0.1 --durationSecs 300 --password [A-Za-z0-9+/=]+", - $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --tableCount 10 --recordCount 1000 --threadCount 8 --workload oltp_update_index --hostIpAddress 127.0.0.1 --durationSecs 300 --password [A-Za-z0-9+/=]+", - $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --tableCount 10 --recordCount 1000 --threadCount 8 --workload oltp_update_non_index --hostIpAddress 127.0.0.1 --durationSecs 300 --password [A-Za-z0-9+/=]+", - $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --tableCount 1 --recordCount 1000 --threadCount 8 --workload select_random_points --hostIpAddress 127.0.0.1 --durationSecs 300 --password [A-Za-z0-9+/=]+", - $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --tableCount 1 --recordCount 1000 --threadCount 8 --workload select_random_ranges --hostIpAddress 127.0.0.1 --durationSecs 300 --password [A-Za-z0-9+/=]+" + $"python3 {this.sysbenchPackagePath}/populate-database.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --threadCount 8 --tableCount 10 --recordCount 1000", + + $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --threadCount 8 --tableCount 10 --recordCount 1000 --workload oltp_read_write --hostIpAddress 127.0.0.1 --durationSecs 300 --password [A-Za-z0-9+/=]+", + $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --threadCount 8 --tableCount 10 --recordCount 1000 --workload oltp_read_only --hostIpAddress 127.0.0.1 --durationSecs 300 --password [A-Za-z0-9+/=]+", + $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --threadCount 8 --tableCount 10 --recordCount 1000 --workload oltp_delete --hostIpAddress 127.0.0.1 --durationSecs 300 --password [A-Za-z0-9+/=]+", + $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --threadCount 8 --tableCount 10 --recordCount 1000 --workload oltp_insert --hostIpAddress 127.0.0.1 --durationSecs 300 --password [A-Za-z0-9+/=]+", + $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --threadCount 8 --tableCount 10 --recordCount 1000 --workload oltp_update_index --hostIpAddress 127.0.0.1 --durationSecs 300 --password [A-Za-z0-9+/=]+", + $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --threadCount 8 --tableCount 10 --recordCount 1000 --workload oltp_update_non_index --hostIpAddress 127.0.0.1 --durationSecs 300 --password [A-Za-z0-9+/=]+", + $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --threadCount 8 --tableCount 1 --recordCount 1000 --workload select_random_points --hostIpAddress 127.0.0.1 --durationSecs 300 --password [A-Za-z0-9+/=]+", + $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --threadCount 8 --tableCount 1 --recordCount 1000 --workload select_random_ranges --hostIpAddress 127.0.0.1 --durationSecs 300 --password [A-Za-z0-9+/=]+" }; } else @@ -511,11 +511,11 @@ private IEnumerable GetProfileExpectedCommands(bool singleVM, string dat $"python3 {this.sysbenchPackagePath}/configure-workload-generator.py --distro Ubuntu --databaseSystem MySQL --packagePath {this.sysbenchPackagePath}", - $"python3 {this.sysbenchPackagePath}/populate-database.py --dbName sbtest --databaseSystem MySQL --benchmark TPCC --tableCount 10 --warehouses 1 --threadCount 8 --password [A-Za-z0-9+/=]+", + $"python3 {this.sysbenchPackagePath}/populate-database.py --dbName sbtest --databaseSystem MySQL --benchmark TPCC --threadCount 8 --tableCount 10 --warehouses 1 --password [A-Za-z0-9+/=]+", $"python3 {this.mySQLPackagePath}/distribute-database.py --dbName sbtest --directories \"/mnt_vc_0;/mnt_vc_1;/mnt_vc_2;\"", - $"python3 {this.sysbenchPackagePath}/populate-database.py --dbName sbtest --databaseSystem MySQL --benchmark TPCC --tableCount 10 --warehouses 100 --threadCount 8 --password [A-Za-z0-9+/=]+", + $"python3 {this.sysbenchPackagePath}/populate-database.py --dbName sbtest --databaseSystem MySQL --benchmark TPCC --threadCount 8 --tableCount 10 --warehouses 100 --password [A-Za-z0-9+/=]+", - $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem MySQL --benchmark TPCC --tableCount 10 --warehouses 100 --threadCount 8 --workload tpcc --hostIpAddress 127.0.0.1 --durationSecs 1800 --password [A-Za-z0-9+/=]+", + $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem MySQL --benchmark TPCC --threadCount 8 --tableCount 10 --warehouses 100 --workload tpcc --hostIpAddress 127.0.0.1 --durationSecs 1800 --password [A-Za-z0-9+/=]+", }; } } @@ -529,14 +529,14 @@ private IEnumerable GetProfileExpectedCommands(bool singleVM, string dat $"python3 {this.sysbenchPackagePath}/configure-workload-generator.py --distro Ubuntu --databaseSystem MySQL --packagePath {this.sysbenchPackagePath}", - $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --tableCount 10 --recordCount 1000 --threadCount 8 --workload oltp_read_write --hostIpAddress 1.2.3.5 --durationSecs 300 --password [A-Za-z0-9+/=]+", - $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --tableCount 10 --recordCount 1000 --threadCount 8 --workload oltp_read_only --hostIpAddress 1.2.3.5 --durationSecs 300 --password [A-Za-z0-9+/=]+", - $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --tableCount 10 --recordCount 1000 --threadCount 8 --workload oltp_delete --hostIpAddress 1.2.3.5 --durationSecs 300 --password [A-Za-z0-9+/=]+", - $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --tableCount 10 --recordCount 1000 --threadCount 8 --workload oltp_insert --hostIpAddress 1.2.3.5 --durationSecs 300 --password [A-Za-z0-9+/=]+", - $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --tableCount 10 --recordCount 1000 --threadCount 8 --workload oltp_update_index --hostIpAddress 1.2.3.5 --durationSecs 300 --password [A-Za-z0-9+/=]+", - $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --tableCount 10 --recordCount 1000 --threadCount 8 --workload oltp_update_non_index --hostIpAddress 1.2.3.5 --durationSecs 300 --password [A-Za-z0-9+/=]+", - $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --tableCount 1 --recordCount 1000 --threadCount 8 --workload select_random_points --hostIpAddress 1.2.3.5 --durationSecs 300 --password [A-Za-z0-9+/=]+", - $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --tableCount 1 --recordCount 1000 --threadCount 8 --workload select_random_ranges --hostIpAddress 1.2.3.5 --durationSecs 300 --password [A-Za-z0-9+/=]+" + $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --threadCount 8 --tableCount 10 --recordCount 1000 --workload oltp_read_write --hostIpAddress 1.2.3.5 --durationSecs 300 --password [A-Za-z0-9+/=]+", + $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --threadCount 8 --tableCount 10 --recordCount 1000 --workload oltp_read_only --hostIpAddress 1.2.3.5 --durationSecs 300 --password [A-Za-z0-9+/=]+", + $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --threadCount 8 --tableCount 10 --recordCount 1000 --workload oltp_delete --hostIpAddress 1.2.3.5 --durationSecs 300 --password [A-Za-z0-9+/=]+", + $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --threadCount 8 --tableCount 10 --recordCount 1000 --workload oltp_insert --hostIpAddress 1.2.3.5 --durationSecs 300 --password [A-Za-z0-9+/=]+", + $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --threadCount 8 --tableCount 10 --recordCount 1000 --workload oltp_update_index --hostIpAddress 1.2.3.5 --durationSecs 300 --password [A-Za-z0-9+/=]+", + $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --threadCount 8 --tableCount 10 --recordCount 1000 --workload oltp_update_non_index --hostIpAddress 1.2.3.5 --durationSecs 300 --password [A-Za-z0-9+/=]+", + $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --threadCount 8 --tableCount 1 --recordCount 1000 --workload select_random_points --hostIpAddress 1.2.3.5 --durationSecs 300 --password [A-Za-z0-9+/=]+", + $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --threadCount 8 --tableCount 1 --recordCount 1000 --workload select_random_ranges --hostIpAddress 1.2.3.5 --durationSecs 300 --password [A-Za-z0-9+/=]+" }; } else @@ -545,7 +545,7 @@ private IEnumerable GetProfileExpectedCommands(bool singleVM, string dat { "apt install python3 --yes --quiet", $"python3 {this.sysbenchPackagePath}/configure-workload-generator.py --distro Ubuntu --databaseSystem MySQL --packagePath {this.sysbenchPackagePath}", - $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem MySQL --benchmark TPCC --tableCount 10 --warehouses 100 --threadCount 8 --workload tpcc --hostIpAddress 1.2.3.5 --durationSecs 1800 --password [A-Za-z0-9+/=]+", + $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem MySQL --benchmark TPCC --threadCount 8 --tableCount 10 --warehouses 100 --workload tpcc --hostIpAddress 1.2.3.5 --durationSecs 1800 --password [A-Za-z0-9+/=]+", }; } } @@ -568,18 +568,18 @@ private IEnumerable GetProfileExpectedCommands(bool singleVM, string dat $"python3 {this.sysbenchPackagePath}/configure-workload-generator.py --distro Ubuntu --databaseSystem PostgreSQL --packagePath {this.sysbenchPackagePath}", - $"python3 {this.sysbenchPackagePath}/populate-database.py --dbName sbtest --databaseSystem PostgreSQL --benchmark OLTP --tableCount 10 --recordCount 1 --threadCount 8 --password [A-Za-z0-9+/=]+", + $"python3 {this.sysbenchPackagePath}/populate-database.py --dbName sbtest --databaseSystem PostgreSQL --benchmark OLTP --threadCount 8 --tableCount 10 --recordCount 1 --password [A-Za-z0-9+/=]+", $"python3 {this.postgreSQLPackagePath}/distribute-database.py --dbName sbtest --directories \"/mnt_vc_0;/mnt_vc_1;/mnt_vc_2;\" --password [A-Za-z0-9+/=]+", - $"python3 {this.sysbenchPackagePath}/populate-database.py --dbName sbtest --databaseSystem PostgreSQL --benchmark OLTP --tableCount 10 --recordCount 1000 --threadCount 8 --password [A-Za-z0-9+/=]+", - - $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --tableCount 10 --recordCount 1000 --threadCount 8 --workload oltp_read_write --hostIpAddress 127.0.0.1 --durationSecs 300 --password [A-Za-z0-9+/=]+", - $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --tableCount 10 --recordCount 1000 --threadCount 8 --workload oltp_read_only --hostIpAddress 127.0.0.1 --durationSecs 300 --password [A-Za-z0-9+/=]+", - $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --tableCount 10 --recordCount 1000 --threadCount 8 --workload oltp_delete --hostIpAddress 127.0.0.1 --durationSecs 300 --password [A-Za-z0-9+/=]+", - $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --tableCount 10 --recordCount 1000 --threadCount 8 --workload oltp_insert --hostIpAddress 127.0.0.1 --durationSecs 300 --password [A-Za-z0-9+/=]+", - $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --tableCount 10 --recordCount 1000 --threadCount 8 --workload oltp_update_index --hostIpAddress 127.0.0.1 --durationSecs 300 --password [A-Za-z0-9+/=]+", - $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --tableCount 10 --recordCount 1000 --threadCount 8 --workload oltp_update_non_index --hostIpAddress 127.0.0.1 --durationSecs 300 --password [A-Za-z0-9+/=]+", - $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --tableCount 1 --recordCount 1000 --threadCount 8 --workload select_random_points --hostIpAddress 127.0.0.1 --durationSecs 300 --password [A-Za-z0-9+/=]+", - $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --tableCount 1 --recordCount 1000 --threadCount 8 --workload select_random_ranges --hostIpAddress 127.0.0.1 --durationSecs 300 --password [A-Za-z0-9+/=]+" + $"python3 {this.sysbenchPackagePath}/populate-database.py --dbName sbtest --databaseSystem PostgreSQL --benchmark OLTP --threadCount 8 --tableCount 10 --recordCount 1000 --password [A-Za-z0-9+/=]+", + + $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem PostgreSQL --benchmark OLTP --threadCount 8 --tableCount 10 --recordCount 1000 --workload oltp_read_write --hostIpAddress 127.0.0.1 --durationSecs 300 --password [A-Za-z0-9+/=]+", + $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem PostgreSQL --benchmark OLTP --threadCount 8 --tableCount 10 --recordCount 1000 --workload oltp_read_only --hostIpAddress 127.0.0.1 --durationSecs 300 --password [A-Za-z0-9+/=]+", + $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem PostgreSQL --benchmark OLTP --threadCount 8 --tableCount 10 --recordCount 1000 --workload oltp_delete --hostIpAddress 127.0.0.1 --durationSecs 300 --password [A-Za-z0-9+/=]+", + $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem PostgreSQL --benchmark OLTP --threadCount 8 --tableCount 10 --recordCount 1000 --workload oltp_insert --hostIpAddress 127.0.0.1 --durationSecs 300 --password [A-Za-z0-9+/=]+", + $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem PostgreSQL --benchmark OLTP --threadCount 8 --tableCount 10 --recordCount 1000 --workload oltp_update_index --hostIpAddress 127.0.0.1 --durationSecs 300 --password [A-Za-z0-9+/=]+", + $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem PostgreSQL --benchmark OLTP --threadCount 8 --tableCount 10 --recordCount 1000 --workload oltp_update_non_index --hostIpAddress 127.0.0.1 --durationSecs 300 --password [A-Za-z0-9+/=]+", + $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem PostgreSQL --benchmark OLTP --threadCount 8 --tableCount 1 --recordCount 1000 --workload select_random_points --hostIpAddress 127.0.0.1 --durationSecs 300 --password [A-Za-z0-9+/=]+", + $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem PostgreSQL --benchmark OLTP --threadCount 8 --tableCount 1 --recordCount 1000 --workload select_random_ranges --hostIpAddress 127.0.0.1 --durationSecs 300 --password [A-Za-z0-9+/=]+" }; } else @@ -594,11 +594,11 @@ private IEnumerable GetProfileExpectedCommands(bool singleVM, string dat $"python3 {this.sysbenchPackagePath}/configure-workload-generator.py --distro Ubuntu --databaseSystem PostgreSQL --packagePath {this.sysbenchPackagePath}", - $"python3 {this.sysbenchPackagePath}/populate-database.py --dbName sbtest --databaseSystem PostgreSQL --benchmark TPCC --tableCount 10 --warehouses 1 --threadCount 8 --password [A-Za-z0-9+/=]+", + $"python3 {this.sysbenchPackagePath}/populate-database.py --dbName sbtest --databaseSystem PostgreSQL --benchmark TPCC --threadCount 8 --tableCount 10 --warehouses 1 --password [A-Za-z0-9+/=]+", $"python3 {this.postgreSQLPackagePath}/distribute-database.py --dbName sbtest --directories \"/mnt_vc_0;/mnt_vc_1;/mnt_vc_2;\" --password [A-Za-z0-9+/=]+", - $"python3 {this.sysbenchPackagePath}/populate-database.py --dbName sbtest --databaseSystem PostgreSQL --benchmark TPCC --tableCount 10 --warehouses 100 --threadCount 8 --password [A-Za-z0-9+/=]+", + $"python3 {this.sysbenchPackagePath}/populate-database.py --dbName sbtest --databaseSystem PostgreSQL --benchmark TPCC --threadCount 8 --tableCount 10 --warehouses 100 --password [A-Za-z0-9+/=]+", - $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem PostgreSQL --benchmark TPCC --tableCount 10 --warehouses 100 --threadCount 8 --workload tpcc --hostIpAddress 127.0.0.1 --durationSecs 1800 --password [A-Za-z0-9+/=]+", + $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem PostgreSQL --benchmark TPCC --threadCount 8 --tableCount 10 --warehouses 100 --workload tpcc --hostIpAddress 127.0.0.1 --durationSecs 1800 --password [A-Za-z0-9+/=]+", }; } } @@ -612,14 +612,14 @@ private IEnumerable GetProfileExpectedCommands(bool singleVM, string dat $"python3 {this.sysbenchPackagePath}/configure-workload-generator.py --distro Ubuntu --databaseSystem PostgreSQL --packagePath {this.sysbenchPackagePath}", - $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --tableCount 10 --recordCount 1000 --threadCount 8 --workload oltp_read_write --hostIpAddress 1.2.3.5 --durationSecs 300 --password [A-Za-z0-9+/=]+", - $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --tableCount 10 --recordCount 1000 --threadCount 8 --workload oltp_read_only --hostIpAddress 1.2.3.5 --durationSecs 300 --password [A-Za-z0-9+/=]+", - $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --tableCount 10 --recordCount 1000 --threadCount 8 --workload oltp_delete --hostIpAddress 1.2.3.5 --durationSecs 300 --password [A-Za-z0-9+/=]+", - $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --tableCount 10 --recordCount 1000 --threadCount 8 --workload oltp_insert --hostIpAddress 1.2.3.5 --durationSecs 300 --password [A-Za-z0-9+/=]+", - $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --tableCount 10 --recordCount 1000 --threadCount 8 --workload oltp_update_index --hostIpAddress 1.2.3.5 --durationSecs 300 --password [A-Za-z0-9+/=]+", - $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --tableCount 10 --recordCount 1000 --threadCount 8 --workload oltp_update_non_index --hostIpAddress 1.2.3.5 --durationSecs 300 --password [A-Za-z0-9+/=]+", - $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --tableCount 1 --recordCount 1000 --threadCount 8 --workload select_random_points --hostIpAddress 1.2.3.5 --durationSecs 300 --password [A-Za-z0-9+/=]+", - $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --tableCount 1 --recordCount 1000 --threadCount 8 --workload select_random_ranges --hostIpAddress 1.2.3.5 --durationSecs 300 --password [A-Za-z0-9+/=]+" + $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem PostgreSQL --benchmark OLTP --threadCount 8 --tableCount 10 --recordCount 1000 --workload oltp_read_write --hostIpAddress 1.2.3.5 --durationSecs 300 --password [A-Za-z0-9+/=]+", + $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem PostgreSQL --benchmark OLTP --threadCount 8 --tableCount 10 --recordCount 1000 --workload oltp_read_only --hostIpAddress 1.2.3.5 --durationSecs 300 --password [A-Za-z0-9+/=]+", + $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem PostgreSQL --benchmark OLTP --threadCount 8 --tableCount 10 --recordCount 1000 --workload oltp_delete --hostIpAddress 1.2.3.5 --durationSecs 300 --password [A-Za-z0-9+/=]+", + $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem PostgreSQL --benchmark OLTP --threadCount 8 --tableCount 10 --recordCount 1000 --workload oltp_insert --hostIpAddress 1.2.3.5 --durationSecs 300 --password [A-Za-z0-9+/=]+", + $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem PostgreSQL --benchmark OLTP --threadCount 8 --tableCount 10 --recordCount 1000 --workload oltp_update_index --hostIpAddress 1.2.3.5 --durationSecs 300 --password [A-Za-z0-9+/=]+", + $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem PostgreSQL --benchmark OLTP --threadCount 8 --tableCount 10 --recordCount 1000 --workload oltp_update_non_index --hostIpAddress 1.2.3.5 --durationSecs 300 --password [A-Za-z0-9+/=]+", + $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem PostgreSQL --benchmark OLTP --threadCount 8 --tableCount 1 --recordCount 1000 --workload select_random_points --hostIpAddress 1.2.3.5 --durationSecs 300 --password [A-Za-z0-9+/=]+", + $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem PostgreSQL --benchmark OLTP --threadCount 8 --tableCount 1 --recordCount 1000 --workload select_random_ranges --hostIpAddress 1.2.3.5 --durationSecs 300 --password [A-Za-z0-9+/=]+" }; } else @@ -628,7 +628,7 @@ private IEnumerable GetProfileExpectedCommands(bool singleVM, string dat { "apt install python3 --yes --quiet", $"python3 {this.sysbenchPackagePath}/configure-workload-generator.py --distro Ubuntu --databaseSystem PostgreSQL --packagePath {this.sysbenchPackagePath}", - $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem PostgreSQL --benchmark TPCC --tableCount 10 --warehouses 100 --threadCount 8 --workload tpcc --hostIpAddress 1.2.3.5 --durationSecs 1800 --password [A-Za-z0-9+/=]+", + $"python3 {this.sysbenchPackagePath}/run-workload.py --dbName sbtest --databaseSystem PostgreSQL --benchmark TPCC --threadCount 8 --tableCount 10 --warehouses 100 --workload tpcc --hostIpAddress 1.2.3.5 --durationSecs 1800 --password [A-Za-z0-9+/=]+", }; } } diff --git a/src/VirtualClient/VirtualClient.Actions.UnitTests/Sysbench/SysbenchClientExecutorTests.cs b/src/VirtualClient/VirtualClient.Actions.UnitTests/Sysbench/SysbenchClientExecutorTests.cs index 39e6103181..9fdc6f9616 100644 --- a/src/VirtualClient/VirtualClient.Actions.UnitTests/Sysbench/SysbenchClientExecutorTests.cs +++ b/src/VirtualClient/VirtualClient.Actions.UnitTests/Sysbench/SysbenchClientExecutorTests.cs @@ -90,7 +90,7 @@ public async Task SysbenchClientExecutorRunsTheExpectedWorkloadCommand() { SetupDefaultBehavior(); - string expectedCommand = @$"python3 {this.mockPackagePath}/run-workload.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --tableCount 10 --recordCount 1000 --threadCount 8 --workload oltp_read_write --hostIpAddress 1.2.3.5 --durationSecs 10 --password [A-Za-z0-9+/=]+"; + string expectedCommand = @$"python3 {this.mockPackagePath}/run-workload.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --threadCount 8 --tableCount 10 --recordCount 1000 --workload oltp_read_write --hostIpAddress 1.2.3.5 --durationSecs 10 --password [A-Za-z0-9+/=]+"; bool commandExecuted = false; this.fixture.ProcessManager.OnCreateProcess = (exe, arguments, workingDir) => @@ -136,7 +136,7 @@ public async Task SysbenchClientExecutorUsesDefinedParametersWhenRunningTheWorkl this.fixture.Parameters[nameof(SysbenchClientExecutor.TableCount)] = "40"; this.fixture.Parameters[nameof(SysbenchClientExecutor.DatabaseScenario)] = "Configure"; - string expectedCommand = @$"python3 {this.mockPackagePath}/run-workload.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --tableCount 40 --recordCount 1000 --threadCount 64 --workload oltp_read_write --hostIpAddress 1.2.3.5 --durationSecs 10 --password [A-Za-z0-9+/=]+"; + string expectedCommand = @$"python3 {this.mockPackagePath}/run-workload.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --threadCount 64 --tableCount 40 --recordCount 1000 --workload oltp_read_write --hostIpAddress 1.2.3.5 --durationSecs 10 --password [A-Za-z0-9+/=]+"; bool commandExecuted = false; this.fixture.ProcessManager.OnCreateProcess = (exe, arguments, workingDir) => @@ -179,7 +179,7 @@ public async Task SysbenchClientExecutorRunsTheExpectedBalancedScenario() this.fixture.Parameters[nameof(SysbenchClientExecutor.DatabaseScenario)] = "Balanced"; - string expectedCommand = $"python3 {this.mockPackagePath}/run-workload.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --tableCount 10 --recordCount 1000 --threadCount 8 --workload oltp_read_write --hostIpAddress 1.2.3.5 --durationSecs 10 --password [A-Za-z0-9+/=]+"; + string expectedCommand = $"python3 {this.mockPackagePath}/run-workload.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --threadCount 8 --tableCount 10 --recordCount 1000 --workload oltp_read_write --hostIpAddress 1.2.3.5 --durationSecs 10 --password [A-Za-z0-9+/=]+"; bool commandExecuted = false; this.fixture.ProcessManager.OnCreateProcess = (exe, arguments, workingDir) => @@ -222,7 +222,7 @@ public async Task SysbenchClientExecutorRunsInMemoryScenario() this.fixture.Parameters[nameof(SysbenchClientExecutor.DatabaseScenario)] = "InMemory"; - string expectedCommand = $"python3 {this.mockPackagePath}/run-workload.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --tableCount 10 --recordCount 100000 --threadCount 8 --workload oltp_read_write --hostIpAddress 1.2.3.5 --durationSecs 10 --password [A-Za-z0-9+/=]+"; + string expectedCommand = $"python3 {this.mockPackagePath}/run-workload.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --threadCount 8 --tableCount 10 --recordCount 100000 --workload oltp_read_write --hostIpAddress 1.2.3.5 --durationSecs 10 --password [A-Za-z0-9+/=]+"; bool commandExecuted = false; this.fixture.ProcessManager.OnCreateProcess = (exe, arguments, workingDir) => @@ -264,8 +264,9 @@ public async Task SysbenchClientExecutorRunsTheExpectedTPCCWorkloadCommand() SetupDefaultBehavior(); this.fixture.Parameters[nameof(SysbenchClientExecutor.Benchmark)] = "TPCC"; + this.fixture.Parameters[nameof(SysbenchClientExecutor.Workload)] = "tpcc"; - string expectedCommand = $"python3 {this.mockPackagePath}/run-workload.py --dbName sbtest --databaseSystem MySQL --benchmark TPCC --tableCount 10 --warehouses 100 --threadCount 8 --workload tpcc --hostIpAddress 1.2.3.5 --durationSecs 10 --password [A-Za-z0-9+/=]+"; + string expectedCommand = $"python3 {this.mockPackagePath}/run-workload.py --dbName sbtest --databaseSystem MySQL --benchmark TPCC --threadCount 8 --tableCount 10 --warehouses 100 --workload tpcc --hostIpAddress 1.2.3.5 --durationSecs 10 --password [A-Za-z0-9+/=]+"; bool commandExecuted = false; this.fixture.ProcessManager.OnCreateProcess = (exe, arguments, workingDir) => @@ -308,7 +309,7 @@ public async Task SysbenchClientExecutorRunsTheExpectedPostgreSQLOLTPWorkloadCom this.fixture.Parameters[nameof(SysbenchClientExecutor.DatabaseSystem)] = "PostgreSQL"; - string expectedCommand = $"python3 {this.mockPackagePath}/run-workload.py --dbName sbtest --databaseSystem PostgreSQL --benchmark OLTP --tableCount 10 --recordCount 1000 --threadCount 8 --workload oltp_read_write --hostIpAddress 1.2.3.5 --durationSecs 10 --password [A-Za-z0-9+/=]+"; + string expectedCommand = $"python3 {this.mockPackagePath}/run-workload.py --dbName sbtest --databaseSystem PostgreSQL --benchmark OLTP --threadCount 8 --tableCount 10 --recordCount 1000 --workload oltp_read_write --hostIpAddress 1.2.3.5 --durationSecs 10 --password [A-Za-z0-9+/=]+"; bool commandExecuted = false; this.fixture.ProcessManager.OnCreateProcess = (exe, arguments, workingDir) => @@ -351,8 +352,9 @@ public async Task SysbenchClientExecutorRunsTheExpectedPostgreSQLTPCCWorkloadCom this.fixture.Parameters[nameof(SysbenchClientExecutor.DatabaseSystem)] = "PostgreSQL"; this.fixture.Parameters[nameof(SysbenchClientExecutor.Benchmark)] = "TPCC"; + this.fixture.Parameters[nameof(SysbenchClientExecutor.Workload)] = "tpcc"; - string expectedCommand = $"python3 {this.mockPackagePath}/run-workload.py --dbName sbtest --databaseSystem PostgreSQL --benchmark TPCC --tableCount 10 --warehouses 100 --threadCount 8 --workload tpcc --hostIpAddress 1.2.3.5 --durationSecs 10 --password [A-Za-z0-9+/=]+"; + string expectedCommand = $"python3 {this.mockPackagePath}/run-workload.py --dbName sbtest --databaseSystem PostgreSQL --benchmark TPCC --threadCount 8 --tableCount 10 --warehouses 100 --workload tpcc --hostIpAddress 1.2.3.5 --durationSecs 10 --password [A-Za-z0-9+/=]+"; bool commandExecuted = false; this.fixture.ProcessManager.OnCreateProcess = (exe, arguments, workingDir) => diff --git a/src/VirtualClient/VirtualClient.Actions.UnitTests/Sysbench/SysbenchConfigurationTests.cs b/src/VirtualClient/VirtualClient.Actions.UnitTests/Sysbench/SysbenchConfigurationTests.cs index 98268dbf24..ef40077228 100644 --- a/src/VirtualClient/VirtualClient.Actions.UnitTests/Sysbench/SysbenchConfigurationTests.cs +++ b/src/VirtualClient/VirtualClient.Actions.UnitTests/Sysbench/SysbenchConfigurationTests.cs @@ -49,6 +49,7 @@ public void SetupDefaultBehavior() this.fixture.Parameters = new Dictionary() { { nameof(SysbenchConfiguration.DatabaseSystem), "MySQL" }, + { nameof(SysbenchConfiguration.Action), "PopulateTables" }, { nameof(SysbenchConfiguration.Benchmark), "OLTP" }, { nameof(SysbenchConfiguration.DatabaseName), "sbtest" }, { nameof(SysbenchConfiguration.PackageName), "sysbench" }, @@ -77,7 +78,7 @@ public async Task SysbenchConfigurationSkipsSysbenchInitialization() string[] expectedCommands = { - $"python3 {this.mockPackagePath}/populate-database.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --tableCount 10 --recordCount 1000 --threadCount 8 --password [A-Za-z0-9+/=]+", + $"python3 {this.mockPackagePath}/populate-database.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --threadCount 8 --tableCount 10 --recordCount 1000 --password [A-Za-z0-9+/=]+ --host \"1.2.3.5\"", }; int commandNumber = 0; @@ -122,7 +123,7 @@ public async Task SysbenchConfigurationPreparesDatabase() string[] expectedCommands = { $"python3 {this.mockPackagePath}/configure-workload-generator.py --distro Ubuntu --databaseSystem MySQL --packagePath {this.mockPackagePath}", - $"python3 {this.mockPackagePath}/populate-database.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --tableCount 10 --recordCount 1000 --threadCount 8 --password [A-Za-z0-9+/=]+", + $"python3 {this.mockPackagePath}/populate-database.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --threadCount 8 --tableCount 10 --recordCount 1000 --password [A-Za-z0-9+/=]+", }; int commandNumber = 0; @@ -173,7 +174,7 @@ public async Task SysbenchConfigurationUsesDefinedParametersWhenRunningTheWorklo string[] expectedCommands = { $"python3 {this.mockPackagePath}/configure-workload-generator.py --distro Ubuntu --databaseSystem MySQL --packagePath {this.mockPackagePath}", - $"python3 {this.mockPackagePath}/populate-database.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --tableCount 40 --recordCount 1000 --threadCount 16 --password [A-Za-z0-9+/=]+", + $"python3 {this.mockPackagePath}/populate-database.py --dbName sbtest --databaseSystem MySQL --benchmark OLTP --threadCount 16 --tableCount 40 --recordCount 1000 --password [A-Za-z0-9+/=]+", }; int commandNumber = 0; @@ -213,7 +214,7 @@ public async Task SysbenchConfigurationUsesDefinedParametersWhenRunningTheWorklo } [Test] - public async Task SysbenchConfigurationSkipsDatabasePopulationWhenInitialized() + public void SysbenchConfigurationThrowsErrorWhenDatabasePopulated() { this.fixture.StateManager.OnGetState().ReturnsAsync(JObject.FromObject(new SysbenchExecutor.SysbenchState() { @@ -258,7 +259,8 @@ public async Task SysbenchConfigurationSkipsDatabasePopulationWhenInitialized() using (TestSysbenchConfiguration SysbenchExecutor = new TestSysbenchConfiguration(this.fixture.Dependencies, this.fixture.Parameters)) { - await SysbenchExecutor.ExecuteAsync(CancellationToken.None).ConfigureAwait(false); + DependencyException error = Assert.ThrowsAsync(() => SysbenchExecutor.ExecuteAsync(CancellationToken.None)); + Assert.IsTrue(error.Reason == ErrorReason.NotSupported); } } @@ -274,7 +276,7 @@ public async Task SysbenchConfigurationProperlyExecutesTPCCPreparation() string[] expectedCommands = { - $"python3 {this.mockPackagePath}/populate-database.py --dbName sbtest --databaseSystem MySQL --benchmark TPCC --tableCount 10 --warehouses 100 --threadCount 8 --password [A-Za-z0-9+/=]+" + $"python3 {this.mockPackagePath}/populate-database.py --dbName sbtest --databaseSystem MySQL --benchmark TPCC --threadCount 8 --tableCount 10 --warehouses 100 --password [A-Za-z0-9+/=]+ --host \"1.2.3.5\"" }; int commandNumber = 0; @@ -330,7 +332,7 @@ public async Task SysbenchConfigurationProperlyExecutesTPCCConfigurablePreparati string[] expectedCommands = { - $"python3 {this.mockPackagePath}/populate-database.py --dbName sbtest --databaseSystem MySQL --benchmark TPCC --tableCount 40 --warehouses 1000 --threadCount 16 --password [A-Za-z0-9+/=]+" + $"python3 {this.mockPackagePath}/populate-database.py --dbName sbtest --databaseSystem MySQL --benchmark TPCC --threadCount 16 --tableCount 40 --warehouses 1000 --password [A-Za-z0-9+/=]+ --host \"1.2.3.5\"" }; int commandNumber = 0; @@ -386,7 +388,7 @@ public async Task SysbenchConfigurationProperlyExecutesPostgreSQLOLTPConfigurabl string[] expectedCommands = { - $"python3 {this.mockPackagePath}/populate-database.py --dbName sbtest --databaseSystem PostgreSQL --benchmark OLTP --tableCount 40 --recordCount 1000 --threadCount 16 --password [A-Za-z0-9+/=]+" + $"python3 {this.mockPackagePath}/populate-database.py --dbName sbtest --databaseSystem PostgreSQL --benchmark OLTP --threadCount 16 --tableCount 40 --recordCount 1000 --password [A-Za-z0-9+/=]+" }; int commandNumber = 0; @@ -444,7 +446,7 @@ public async Task SysbenchConfigurationProperlyExecutesPostgreSQLTPCCConfigurabl string[] expectedCommands = { - $"python3 {this.mockPackagePath}/populate-database.py --dbName sbtest --databaseSystem PostgreSQL --benchmark TPCC --tableCount 40 --warehouses 1000 --threadCount 16 --password [A-Za-z0-9+/=]+" + $"python3 {this.mockPackagePath}/populate-database.py --dbName sbtest --databaseSystem PostgreSQL --benchmark TPCC --threadCount 16 --tableCount 40 --warehouses 1000 --password [A-Za-z0-9+/=]+ --host \"1.2.3.5\"" }; int commandNumber = 0; diff --git a/src/VirtualClient/VirtualClient.Actions/HammerDB/HammerDBExecutor.cs b/src/VirtualClient/VirtualClient.Actions/HammerDB/HammerDBExecutor.cs index be86aa7046..6a36f17e5c 100644 --- a/src/VirtualClient/VirtualClient.Actions/HammerDB/HammerDBExecutor.cs +++ b/src/VirtualClient/VirtualClient.Actions/HammerDB/HammerDBExecutor.cs @@ -16,7 +16,6 @@ namespace VirtualClient.Actions using VirtualClient; using VirtualClient.Common; using VirtualClient.Common.Extensions; - using VirtualClient.Common.Platform; using VirtualClient.Common.Telemetry; using VirtualClient.Contracts; @@ -44,6 +43,18 @@ public HammerDBExecutor(IServiceCollection dependencies, IDictionary + /// The specifed action that controls the execution of the dependency. + /// + public string Action + { + get + { + this.Parameters.TryGetValue(nameof(this.Action), out IConvertible action); + return action?.ToString(); + } + } + /// /// Defines the name of the createDB TCL file. /// @@ -196,7 +207,7 @@ protected override async Task ExecuteAsync(EventContext telemetryContext, Cancel HammerDBState state = await this.stateManager.GetStateAsync(nameof(HammerDBState), cancellationToken) ?? new HammerDBState(); - if (state.DatabaseCreated != 2) + if (!state.DatabasePopulated) { await this.Logger.LogMessageAsync($"{this.TypeName}.{this.Scenario}", telemetryContext.Clone(), async () => { @@ -205,8 +216,12 @@ await this.Logger.LogMessageAsync($"{this.TypeName}.{this.Scenario}", telemetryC await this.PrepareSQLDatabase(telemetryContext, cancellationToken); } }); - state.DatabaseCreated++; - await this.stateManager.SaveStateAsync(nameof(HammerDBState), state, cancellationToken); + + if (this.Action == ConfigurationAction.PopulateTables) + { + state.DatabasePopulated = true; + await this.stateManager.SaveStateAsync(nameof(HammerDBState), state, cancellationToken); + } } } @@ -318,9 +333,20 @@ private async Task PrepareSQLDatabase(EventContext telemetryContext, Cancellatio private async Task ConfigureCreateHammerDBFile(EventContext telemetryContext, CancellationToken cancellationToken) { + string warehouseCount = this.WarehouseCount; + string virtualUsers = this.VirtualUsers; + + // For CreateTables action, we set warehouse count and virtual users to 1 + // Then will run populate again to fill up the tables in entirety. + if (this.Action == ConfigurationAction.CreateTables) + { + warehouseCount = "1"; + virtualUsers = "1"; + } + string command = $"python3"; string arguments = $"{this.HammerDBPackagePath}/configure-workload-generator.py --workload {this.Workload} --sqlServer {this.SQLServer} --port {this.Port}" + - $" --virtualUsers {this.VirtualUsers} --warehouseCount {this.WarehouseCount} --password {this.SuperUserPassword} --dbName {this.DatabaseName} --hostIPAddress {this.ServerIpAddress}"; + $" --virtualUsers {virtualUsers} --warehouseCount {warehouseCount} --password {this.SuperUserPassword} --dbName {this.DatabaseName} --hostIPAddress {this.ServerIpAddress}"; using (IProcessProxy process = await this.ExecuteCommandAsync( command, @@ -406,18 +432,34 @@ public bool HammerDBInitialized } } - public int DatabaseCreated + public bool DatabasePopulated { get { - return this.Properties.GetValue(nameof(HammerDBState.DatabaseCreated), 0); + return this.Properties.GetValue(nameof(HammerDBState.DatabasePopulated), false); } set { - this.Properties[nameof(HammerDBState.DatabaseCreated)] = value; + this.Properties[nameof(HammerDBState.DatabasePopulated)] = value; } } } + + /// + /// Supported HammerDB Configuration actions. + /// + internal class ConfigurationAction + { + /// + /// Initializes the tables on the database. + /// + public const string CreateTables = nameof(CreateTables); + + /// + /// Populates Database on server. + /// + public const string PopulateTables = nameof(PopulateTables); + } } } \ No newline at end of file diff --git a/src/VirtualClient/VirtualClient.Actions/Sysbench/SysbenchClientExecutor.cs b/src/VirtualClient/VirtualClient.Actions/Sysbench/SysbenchClientExecutor.cs index cd91c51c52..a5316798c3 100644 --- a/src/VirtualClient/VirtualClient.Actions/Sysbench/SysbenchClientExecutor.cs +++ b/src/VirtualClient/VirtualClient.Actions/Sysbench/SysbenchClientExecutor.cs @@ -24,8 +24,6 @@ public class SysbenchClientExecutor : SysbenchExecutor { private string sysbenchExecutionArguments; private string sysbenchLoggingArguments; - private string sysbenchPrepareArguments; - private string packageDirectory; /// /// Initializes a new instance of the class. @@ -181,48 +179,18 @@ private Task ExecuteWorkloadAsync(EventContext telemetryContext, CancellationTok { using (BackgroundOperations profiling = BackgroundOperations.BeginProfiling(this, cancellationToken)) { - if (this.DatabaseSystem == "MySQL") + switch (this.Benchmark) { - string mysqlVersion = await this.GetMySQLVersionAsync(telemetryContext, cancellationToken); - - this.MetadataContract.Add("mysql_version", mysqlVersion, MetadataContract.DependenciesCategory); - this.MetadataContract.Apply(telemetryContext); - } - - if (this.Benchmark == BenchmarkName.OLTP) - { - if (this.Action == ClientAction.TruncateDatabase) - { - DependencyPath workloadPackage = await this.GetPackageAsync(this.PackageName, cancellationToken).ConfigureAwait(false); - workloadPackage.ThrowIfNull(this.PackageName); - - DependencyPath package = await this.GetPlatformSpecificPackageAsync(this.PackageName, cancellationToken); - this.packageDirectory = package.Path; - - await this.TruncateMySQLDatabaseAsync(telemetryContext, cancellationToken).ConfigureAwait(false); - } - else if (this.Action == ClientAction.PopulateDatabase) - { - await this.PrepareOLTPMySQLDatabase(telemetryContext, cancellationToken); - } - else if (this.Action == ClientAction.Cleanup) - { - await this.CleanUpDatabase(telemetryContext, cancellationToken); - } - else - { + case BenchmarkName.OLTP: await this.RunOLTPWorkloadAsync(telemetryContext, cancellationToken); - } - } - else if (this.Benchmark == BenchmarkName.TPCC) - { - await this.RunTPCCWorkloadAsync(telemetryContext, cancellationToken); - } - else - { - throw new DependencyException( - $"The '{this.Benchmark}' benchmark is not supported with the Sysbench workload. Supported options include: \"OLTP, TPCC\".", - ErrorReason.NotSupported); + break; + case BenchmarkName.TPCC: + await this.RunTPCCWorkloadAsync(telemetryContext, cancellationToken); + break; + default: + throw new DependencyException( + $"The '{this.Benchmark}' benchmark is not supported with the Sysbench workload. Supported options include: \"OLTP, TPCC\".", + ErrorReason.NotSupported); } } }); @@ -230,8 +198,8 @@ private Task ExecuteWorkloadAsync(EventContext telemetryContext, CancellationTok private async Task RunOLTPWorkloadAsync(EventContext telemetryContext, CancellationToken cancellationToken) { - this.sysbenchLoggingArguments = $"{this.BuildSysbenchLoggingOLTPBasicArguments()} --workload {this.Workload} "; - this.sysbenchExecutionArguments = this.sysbenchLoggingArguments + $"--hostIpAddress {this.ServerIpAddress} --durationSecs {this.Duration.TotalSeconds} --password {this.SuperUserPassword}"; + this.sysbenchLoggingArguments = this.BuildSysbenchLoggingArguments(prepare: false); + this.sysbenchExecutionArguments = $"{this.sysbenchLoggingArguments} --workload {this.Workload} --hostIpAddress {this.ServerIpAddress} --durationSecs {this.Duration.TotalSeconds} --password {this.SuperUserPassword}"; string script = $"{this.SysbenchPackagePath}/run-workload.py "; @@ -252,41 +220,10 @@ private async Task RunOLTPWorkloadAsync(EventContext telemetryContext, Cancellat } } - private async Task CleanUpDatabase(EventContext telemetryContext, CancellationToken cancellationToken) - { - int tableCount = GetTableCount(this.DatabaseScenario, this.TableCount, this.Workload); - - string serverIp = (this.GetLayoutClientInstances(ClientRole.Server, false) ?? Enumerable.Empty()) - .FirstOrDefault()?.IPAddress - ?? "localhost"; - - string sysbenchCleanupArguments = $"--dbName {this.DatabaseName} --databaseSystem {this.DatabaseSystem} --benchmark {this.Benchmark} --tableCount {tableCount} --hostIpAddress {serverIp}"; - - string script = $"{this.SysbenchPackagePath}/cleanup-database.py "; - - using (IProcessProxy process = await this.ExecuteCommandAsync( - SysbenchExecutor.PythonCommand, - script + sysbenchCleanupArguments, - this.SysbenchPackagePath, - telemetryContext, - cancellationToken)) - { - if (!cancellationToken.IsCancellationRequested) - { - await this.LogProcessDetailsAsync(process, telemetryContext, "Sysbench", logToFile: true); - process.ThrowIfErrored(process.StandardError.ToString(), ErrorReason.WorkloadFailed); - } - } - } - private async Task RunTPCCWorkloadAsync(EventContext telemetryContext, CancellationToken cancellationToken) { - int tableCount = GetTableCount(this.Scenario, this.TableCount, this.Workload); - int threadCount = GetThreadCount(this.SystemManager, this.DatabaseScenario, this.Threads); - int warehouseCount = GetWarehouseCount(this.DatabaseScenario, this.WarehouseCount); - - this.sysbenchLoggingArguments = $"{this.BuildSysbenchLoggingTPCCBasicArguments()} --workload tpcc "; - this.sysbenchExecutionArguments = this.sysbenchLoggingArguments + $"--hostIpAddress {this.ServerIpAddress} --durationSecs {this.Duration.TotalSeconds} --password {this.SuperUserPassword}"; + this.sysbenchLoggingArguments = this.BuildSysbenchLoggingArguments(prepare: false); + this.sysbenchExecutionArguments = $"{this.sysbenchLoggingArguments} --workload {this.Workload} --hostIpAddress {this.ServerIpAddress} --durationSecs {this.Duration.TotalSeconds} --password {this.SuperUserPassword}"; string script = $"{this.SysbenchPackagePath}/run-workload.py "; @@ -306,84 +243,5 @@ private async Task RunTPCCWorkloadAsync(EventContext telemetryContext, Cancellat } } } - - private async Task TruncateMySQLDatabaseAsync(EventContext telemetryContext, CancellationToken cancellationToken) - { - string arguments = $"{this.packageDirectory}/truncate-tables.py --dbName {this.DatabaseName}"; - - string serverIps = (this.GetLayoutClientInstances(ClientRole.Server, false) ?? Enumerable.Empty()) - .FirstOrDefault()?.IPAddress - ?? "localhost"; - - arguments += $" --clientIps \"{serverIps}\""; - - using (IProcessProxy process = await this.ExecuteCommandAsync( - SysbenchExecutor.PythonCommand, - arguments, - Environment.CurrentDirectory, - telemetryContext, - cancellationToken)) - { - if (!cancellationToken.IsCancellationRequested) - { - await this.LogProcessDetailsAsync(process, telemetryContext, "Sysbench", logToFile: true); - process.ThrowIfDependencyInstallationFailed(process.StandardError.ToString()); - } - } - } - - private async Task PrepareOLTPMySQLDatabase(EventContext telemetryContext, CancellationToken cancellationToken) - { - this.sysbenchLoggingArguments = this.BuildSysbenchLoggingOLTPBasicArguments(); - - this.sysbenchPrepareArguments = $"{this.sysbenchLoggingArguments} --password {this.SuperUserPassword}"; - - string serverIp = (this.GetLayoutClientInstances(ClientRole.Server, false) ?? Enumerable.Empty()) - .FirstOrDefault()?.IPAddress - ?? "localhost"; - - this.sysbenchPrepareArguments += $" --host \"{serverIp}\""; - - string arguments = $"{this.SysbenchPackagePath}/populate-database.py "; - - using (IProcessProxy process = await this.ExecuteCommandAsync( - SysbenchExecutor.PythonCommand, - arguments + this.sysbenchPrepareArguments, - this.SysbenchPackagePath, - telemetryContext, - cancellationToken)) - { - if (!cancellationToken.IsCancellationRequested) - { - await this.LogProcessDetailsAsync(process, telemetryContext, "Sysbench", logToFile: true); - process.ThrowIfErrored(process.StandardError.ToString(), ErrorReason.WorkloadUnexpectedAnomaly); - - this.AddMetric(this.sysbenchLoggingArguments, process, telemetryContext, cancellationToken); - } - } - } - - /// - /// Returns MySQL Version. - /// - /// - /// - private async Task GetMySQLVersionAsync(EventContext telemetryContext, CancellationToken cancellationToken) - { - try - { - IProcessProxy mysqlversionprocess = await this.ExecuteCommandAsync("sudo", $"mysql -u {this.DatabaseName} -h {this.ServerIpAddress} -e \"SELECT VERSION();\"", Environment.CurrentDirectory, telemetryContext, cancellationToken); - string mysqlVersion = mysqlversionprocess.StandardOutput.ToString(); - - Regex regex = new Regex(@"(\d+\.\d+\.\d+)"); - Match match = regex.Match(mysqlVersion); - - return match.Success ? match.Groups[1].Value : string.Empty; - } - catch (Exception) - { - return string.Empty; - } - } } } diff --git a/src/VirtualClient/VirtualClient.Actions/Sysbench/SysbenchConfiguration.cs b/src/VirtualClient/VirtualClient.Actions/Sysbench/SysbenchConfiguration.cs index 53a188866e..7bac756352 100644 --- a/src/VirtualClient/VirtualClient.Actions/Sysbench/SysbenchConfiguration.cs +++ b/src/VirtualClient/VirtualClient.Actions/Sysbench/SysbenchConfiguration.cs @@ -12,6 +12,7 @@ namespace VirtualClient.Actions using VirtualClient.Common.Extensions; using VirtualClient.Common.Telemetry; using VirtualClient.Contracts; + using VirtualClient.Contracts.Metadata; /// /// Configures the MySQL database for Sysbench use. @@ -19,7 +20,7 @@ namespace VirtualClient.Actions public class SysbenchConfiguration : SysbenchExecutor { private readonly IStateManager stateManager; - private string sysbenchPrepareArguments; + private string sysbenchPopulationArguments; /// /// Initializes a new instance of the class. @@ -32,6 +33,18 @@ public SysbenchConfiguration(IServiceCollection dependencies, IDictionary(); } + /// + /// The specifed action that controls the execution of the dependency. + /// + public string Action + { + get + { + this.Parameters.TryGetValue(nameof(this.Action), out IConvertible action); + return action?.ToString(); + } + } + /// /// Executes the workload. /// @@ -39,91 +52,292 @@ public SysbenchConfiguration(IServiceCollection dependencies, IDictionaryA token that can be used to cancel the operation. protected override async Task ExecuteAsync(EventContext telemetryContext, CancellationToken cancellationToken) { - SysbenchState state = await this.stateManager.GetStateAsync(nameof(SysbenchState), cancellationToken) - ?? new SysbenchState(); - - if (!state.DatabasePopulated) + if (!cancellationToken.IsCancellationRequested) { - await this.Logger.LogMessageAsync($"{this.TypeName}.PopulateDatabase", telemetryContext.Clone(), async () => + switch (this.Action) { - if (!cancellationToken.IsCancellationRequested) - { - if (this.Benchmark == BenchmarkName.OLTP) + case ConfigurationAction.Cleanup: + await this.CleanUpDatabase(telemetryContext, cancellationToken); + break; + case ConfigurationAction.CreateTables: + if (this.Benchmark.Equals("oltp", StringComparison.OrdinalIgnoreCase)) { - await this.PrepareOLTPMySQLDatabase(telemetryContext, cancellationToken); + await this.PrepareOLTPDatabase(telemetryContext, cancellationToken); } - else if (this.Benchmark == BenchmarkName.TPCC) + else if (this.Benchmark.Equals("tpcc", StringComparison.OrdinalIgnoreCase)) { - await this.PrepareTPCCMySQLDatabase(telemetryContext, cancellationToken); + await this.PrepareTPCCDatabase(telemetryContext, cancellationToken); } - else + + break; + case ConfigurationAction.PopulateTables: + if (this.Benchmark.Equals("oltp", StringComparison.OrdinalIgnoreCase)) { - throw new DependencyException( - $"The '{this.Benchmark}' benchmark is not supported with the Sysbench workload. Supported options include: \"OLTP, TPCC\".", - ErrorReason.NotSupported); + await this.PopulateOLTPDatabase(telemetryContext, cancellationToken); + } + else if (this.Benchmark.Equals("tpcc", StringComparison.OrdinalIgnoreCase)) + { + await this.PopulateTPCCDatabase(telemetryContext, cancellationToken); } - } - }); - if (this.RecordCount > 1 || this.WarehouseCount > 1) - { - state.DatabasePopulated = true; - await this.stateManager.SaveStateAsync(nameof(SysbenchState), state, cancellationToken); + break; + default: + throw new DependencyException( + $"The specified Sysbench action '{this.Action}' is not supported. Supported actions include: \"{ConfigurationAction.PopulateTables}, {ConfigurationAction.Cleanup}, {ConfigurationAction.CreateTables}\".", + ErrorReason.NotSupported); } } } - private async Task PrepareOLTPMySQLDatabase(EventContext telemetryContext, CancellationToken cancellationToken) + private async Task CleanUpDatabase(EventContext telemetryContext, CancellationToken cancellationToken) { - string sysbenchLoggingArguments = this.BuildSysbenchLoggingOLTPBasicArguments(); + SysbenchState state = await this.stateManager.GetStateAsync(nameof(SysbenchState), cancellationToken) + ?? new SysbenchState(); + + if (state.DatabasePopulated) + { + int tableCount = GetTableCount(this.DatabaseScenario, this.TableCount, this.Workload); - this.sysbenchPrepareArguments = $"{sysbenchLoggingArguments} --password {this.SuperUserPassword}"; + string serverIp = (this.IsMultiRoleLayout() && this.IsInRole(ClientRole.Client)) ? this.ServerIpAddress : "localhost"; - string serverIp = "localhost"; + string sysbenchCleanupArguments = $"--dbName {this.DatabaseName} --databaseSystem {this.DatabaseSystem} --benchmark {this.Benchmark} --tableCount {tableCount} --hostIpAddress \"{serverIp}\""; + + string script = $"{this.SysbenchPackagePath}/cleanup-database.py"; + + using (IProcessProxy process = await this.ExecuteCommandAsync( + SysbenchExecutor.PythonCommand, + $"{script} {sysbenchCleanupArguments}", + this.SysbenchPackagePath, + telemetryContext, + cancellationToken)) + { + if (!cancellationToken.IsCancellationRequested) + { + await this.LogProcessDetailsAsync(process, telemetryContext, "Sysbench", logToFile: true); + process.ThrowIfErrored(process.StandardError.ToString(), ErrorReason.WorkloadFailed); + } + } + } - this.sysbenchPrepareArguments += $" --host \"{serverIp}\""; + state.DatabasePopulated = false; + await this.stateManager.SaveStateAsync(nameof(SysbenchState), state, cancellationToken); + } - string arguments = $"{this.SysbenchPackagePath}/populate-database.py "; + private async Task PrepareOLTPDatabase(EventContext telemetryContext, CancellationToken cancellationToken) + { + SysbenchState state = await this.stateManager.GetStateAsync(nameof(SysbenchState), cancellationToken) + ?? new SysbenchState(); - using (IProcessProxy process = await this.ExecuteCommandAsync( - SysbenchExecutor.PythonCommand, - arguments + this.sysbenchPrepareArguments, - this.SysbenchPackagePath, - telemetryContext, - cancellationToken)) + if (!state.DatabasePopulated) { - if (!cancellationToken.IsCancellationRequested) + string serverIp = (this.IsMultiRoleLayout() && this.IsInRole(ClientRole.Client)) ? this.ServerIpAddress : "localhost"; + string sysbenchPrepareArguments = $"{this.BuildSysbenchLoggingArguments(prepare: true)} --password {this.SuperUserPassword} --host \"{serverIp}\""; + + string command = $"{this.SysbenchPackagePath}/populate-database.py"; + + using (IProcessProxy process = await this.ExecuteCommandAsync( + SysbenchExecutor.PythonCommand, + $"{command} {sysbenchPrepareArguments}", + this.SysbenchPackagePath, + telemetryContext, + cancellationToken)) { - await this.LogProcessDetailsAsync(process, telemetryContext, "Sysbench", logToFile: true); - process.ThrowIfErrored(process.StandardError.ToString(), ErrorReason.WorkloadUnexpectedAnomaly); + if (!cancellationToken.IsCancellationRequested) + { + await this.LogProcessDetailsAsync(process, telemetryContext, "Sysbench", logToFile: true); + process.ThrowIfErrored(process.StandardError.ToString(), ErrorReason.WorkloadUnexpectedAnomaly); + } + } + } + else + { + throw new DependencyException( + $"Database preparation failed. A database has already been populated on the system. Please drop the tables, or run \"{ConfigurationAction.Cleanup}\" Action" + + $"before attempting to create new tables on this database.", + ErrorReason.NotSupported); + } + } + + private async Task PrepareTPCCDatabase(EventContext telemetryContext, CancellationToken cancellationToken) + { + SysbenchState state = await this.stateManager.GetStateAsync(nameof(SysbenchState), cancellationToken) + ?? new SysbenchState(); + + if (!state.DatabasePopulated) + { + string serverIp = (this.IsMultiRoleLayout() && this.IsInRole(ClientRole.Client)) ? this.ServerIpAddress : "localhost"; + string sysbenchPrepareArguments = $"{this.BuildSysbenchLoggingArguments(prepare: true)} --password {this.SuperUserPassword} --host \"{serverIp}\""; - this.AddMetric(sysbenchLoggingArguments, process, telemetryContext, cancellationToken); + string script = $"{this.SysbenchPackagePath}/populate-database.py"; + + using (IProcessProxy process = await this.ExecuteCommandAsync( + SysbenchExecutor.PythonCommand, + $"{script} {sysbenchPrepareArguments}", + this.SysbenchPackagePath, + telemetryContext, + cancellationToken)) + { + if (!cancellationToken.IsCancellationRequested) + { + await this.LogProcessDetailsAsync(process, telemetryContext, "Sysbench", logToFile: true); + process.ThrowIfErrored(process.StandardError.ToString(), ErrorReason.WorkloadUnexpectedAnomaly); + } } } + else + { + throw new DependencyException( + $"Database preparation failed. A database has already been populated on the system. Please drop the tables, or run \"{ConfigurationAction.Cleanup}\" Action" + + $"before attempting to create new tables on this database.", + ErrorReason.NotSupported); + } } - private async Task PrepareTPCCMySQLDatabase(EventContext telemetryContext, CancellationToken cancellationToken) + private async Task PopulateOLTPDatabase(EventContext telemetryContext, CancellationToken cancellationToken) { - string sysbenchLoggingArguments = this.BuildSysbenchLoggingTPCCBasicArguments(); - this.sysbenchPrepareArguments = $"{sysbenchLoggingArguments} --password {this.SuperUserPassword}"; + SysbenchState state = await this.stateManager.GetStateAsync(nameof(SysbenchState), cancellationToken) + ?? new SysbenchState(); + + if (!state.DatabasePopulated) + { + await this.Logger.LogMessageAsync($"{this.TypeName}.PopulateDatabase", telemetryContext.Clone(), async () => + { + string serverIp = (this.IsMultiRoleLayout() && this.IsInRole(ClientRole.Client)) ? this.ServerIpAddress : "localhost"; + + string sysbenchLoggingArguments = this.BuildSysbenchLoggingArguments(prepare: false); + this.sysbenchPopulationArguments = $"{sysbenchLoggingArguments} --password {this.SuperUserPassword} --host \"{serverIp}\""; + + string script = $"{this.SysbenchPackagePath}/populate-database.py"; + + using (IProcessProxy process = await this.ExecuteCommandAsync( + SysbenchExecutor.PythonCommand, + $"{script} {this.sysbenchPopulationArguments}", + this.SysbenchPackagePath, + telemetryContext, + cancellationToken)) + { + if (!cancellationToken.IsCancellationRequested) + { + await this.LogProcessDetailsAsync(process, telemetryContext, "Sysbench", logToFile: true); + process.ThrowIfErrored(process.StandardError.ToString(), ErrorReason.WorkloadUnexpectedAnomaly); + + this.AddPopulationDurationMetric(sysbenchLoggingArguments, process, telemetryContext, cancellationToken); + } + } + + state.DatabasePopulated = true; + await this.stateManager.SaveStateAsync(nameof(SysbenchState), state, cancellationToken); + }); + } + else + { + throw new DependencyException( + $"Database preparation failed. A database has already been populated on the system. Please drop the tables, or run \"{ConfigurationAction.Cleanup}\" Action" + + $"before attempting to add new records to the populated tables.", + ErrorReason.NotSupported); + } + } - string arguments = $"{this.SysbenchPackagePath}/populate-database.py "; + private async Task PopulateTPCCDatabase(EventContext telemetryContext, CancellationToken cancellationToken) + { + SysbenchState state = await this.stateManager.GetStateAsync(nameof(SysbenchState), cancellationToken) + ?? new SysbenchState(); - using (IProcessProxy process = await this.ExecuteCommandAsync( - SysbenchExecutor.PythonCommand, - arguments + this.sysbenchPrepareArguments, - this.SysbenchPackagePath, - telemetryContext, - cancellationToken)) + if (!state.DatabasePopulated) { - if (!cancellationToken.IsCancellationRequested) + await this.Logger.LogMessageAsync($"{this.TypeName}.PopulateDatabase", telemetryContext.Clone(), async () => { - await this.LogProcessDetailsAsync(process, telemetryContext, "Sysbench", logToFile: true); - process.ThrowIfErrored(process.StandardError.ToString(), ErrorReason.WorkloadUnexpectedAnomaly); + string serverIp = (this.IsMultiRoleLayout() && this.IsInRole(ClientRole.Client)) ? this.ServerIpAddress : "localhost"; - this.AddMetric(sysbenchLoggingArguments, process, telemetryContext, cancellationToken); - } + string sysbenchLoggingArguments = this.BuildSysbenchLoggingArguments(prepare: false); + this.sysbenchPopulationArguments = $"{sysbenchLoggingArguments} --password {this.SuperUserPassword} --host \"{serverIp}\""; + + string script = $"{this.SysbenchPackagePath}/populate-database.py"; + + using (IProcessProxy process = await this.ExecuteCommandAsync( + SysbenchExecutor.PythonCommand, + $"{script} {this.sysbenchPopulationArguments}", + this.SysbenchPackagePath, + telemetryContext, + cancellationToken)) + { + if (!cancellationToken.IsCancellationRequested) + { + await this.LogProcessDetailsAsync(process, telemetryContext, "Sysbench", logToFile: true); + process.ThrowIfErrored(process.StandardError.ToString(), ErrorReason.WorkloadUnexpectedAnomaly); + + this.AddPopulationDurationMetric(sysbenchLoggingArguments, process, telemetryContext, cancellationToken); + } + } + + state.DatabasePopulated = true; + await this.stateManager.SaveStateAsync(nameof(SysbenchState), state, cancellationToken); + }); + } + else + { + throw new DependencyException( + $"Database preparation failed. A database has already been populated on the system. Please drop the tables, or run \"{ConfigurationAction.Cleanup}\" Action" + + $"before attempting to add new records to the populated tables.", + ErrorReason.NotSupported); + } + } + + /// + /// Add metrics to telemtry. + /// + /// + /// + /// + /// + private void AddPopulationDurationMetric(string arguments, IProcessProxy process, EventContext telemetryContext, CancellationToken cancellationToken) + { + if (!cancellationToken.IsCancellationRequested) + { + this.MetadataContract.AddForScenario( + "Sysbench", + process.FullCommand()); + + this.MetadataContract.Apply(telemetryContext); + + string text = process.StandardOutput.ToString(); + + List metrics = new List(); + double duration = (process.ExitTime - process.StartTime).TotalMinutes; + metrics.Add(new Metric("PopulateDatabaseDuration", duration, "minutes", MetricRelativity.LowerIsBetter)); + + this.Logger.LogMetrics( + toolName: "Sysbench", + scenarioName: this.MetricScenario ?? this.Scenario, + process.StartTime, + process.ExitTime, + metrics, + null, + scenarioArguments: arguments, + this.Tags, + telemetryContext); } } + + /// + /// Supported Sysbench Configuration actions. + /// + internal class ConfigurationAction + { + /// + /// Initializes the tables on the database. + /// + public const string CreateTables = nameof(CreateTables); + + /// + /// Creates Database on MySQL server and Users on Server and any Clients. + /// + public const string PopulateTables = nameof(PopulateTables); + + /// + /// Runs sysbench cleanup action. + /// + public const string Cleanup = nameof(Cleanup); + } } } diff --git a/src/VirtualClient/VirtualClient.Actions/Sysbench/SysbenchExecutor.cs b/src/VirtualClient/VirtualClient.Actions/Sysbench/SysbenchExecutor.cs index 310bd17fac..0ba26c0e81 100644 --- a/src/VirtualClient/VirtualClient.Actions/Sysbench/SysbenchExecutor.cs +++ b/src/VirtualClient/VirtualClient.Actions/Sysbench/SysbenchExecutor.cs @@ -11,6 +11,7 @@ namespace VirtualClient.Actions using System.Runtime.InteropServices; using System.Security.Cryptography; using System.Text; + using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; @@ -176,18 +177,6 @@ public string Workload } } - /// - /// The specifed action that controls the execution of the dependency. - /// - public string Action - { - get - { - this.Parameters.TryGetValue(nameof(this.Action), out IConvertible action); - return action?.ToString(); - } - } - /// /// Client used to communicate with the hosted instance of the /// Virtual Client API at server side. @@ -308,10 +297,7 @@ await this.CheckDistroSupportAsync(telemetryContext, cancellationToken) DependencyPath package = await this.GetPackageAsync(this.PackageName, cancellationToken); this.SysbenchPackagePath = package.Path; - if (this.Action != ClientAction.TruncateDatabase) - { - await this.InitializeExecutablesAsync(telemetryContext, cancellationToken); - } + await this.InitializeExecutablesAsync(telemetryContext, cancellationToken); this.InitializeApiClients(telemetryContext, cancellationToken); @@ -389,77 +375,35 @@ protected async Task InitializeExecutablesAsync(EventContext telemetryContext, C await this.stateManager.SaveStateAsync(nameof(SysbenchState), state, cancellationToken); } - /// - /// Add metrics to telemtry. - /// - /// - /// - /// - /// - protected void AddMetric(string arguments, IProcessProxy process, EventContext telemetryContext, CancellationToken cancellationToken) - { - if (!cancellationToken.IsCancellationRequested) - { - this.MetadataContract.AddForScenario( - "Sysbench", - process.FullCommand(), - toolVersion: null); - - this.MetadataContract.Apply(telemetryContext); - - string text = process.StandardOutput.ToString(); - - List metrics = new List(); - double duration = (process.ExitTime - process.StartTime).TotalMinutes; - metrics.Add(new Metric("PopulateDatabaseDuration", duration, "minutes", MetricRelativity.LowerIsBetter)); - - this.Logger.LogMetrics( - toolName: "Sysbench", - scenarioName: this.MetricScenario ?? this.Scenario, - process.StartTime, - process.ExitTime, - metrics, - null, - scenarioArguments: arguments, - this.Tags, - telemetryContext); - } - } - /// /// Build the Sysbench Logging Basic Arguments, having the common parameters /// dbName, databaseSystem, benchmark and tableCount. /// /// - protected string BuildSysbenchLoggingBasicArguments() + protected string BuildSysbenchLoggingArguments(bool prepare) { int tableCount = GetTableCount(this.DatabaseScenario, this.TableCount, this.Workload); + int threadCount = GetThreadCount(this.SystemManager, this.DatabaseScenario, this.Threads); - return $"--dbName {this.DatabaseName} --databaseSystem {this.DatabaseSystem} --benchmark {this.Benchmark} --tableCount {tableCount}"; - } + string loggingArguments = $"--dbName {this.DatabaseName} --databaseSystem {this.DatabaseSystem} --benchmark {this.Benchmark} --threadCount {threadCount} --tableCount {tableCount}"; - /// - /// Build the Sysbench Logging OLTP Basic Arguments, having the common parameters - /// dbName, databaseSystem, benchmark, tableCount, recordCount and threadCount. - /// - /// - protected string BuildSysbenchLoggingOLTPBasicArguments() - { - int recordCount = GetRecordCount(this.SystemManager, this.DatabaseScenario, this.RecordCount); - int threadCount = GetThreadCount(this.SystemManager, this.DatabaseScenario, this.Threads); - return $"{this.BuildSysbenchLoggingBasicArguments()} --recordCount {recordCount} --threadCount {threadCount}"; - } + switch (this.Benchmark) + { + case BenchmarkName.OLTP: + int recordCount = GetRecordCount(this.SystemManager, this.DatabaseScenario, this.RecordCount); + loggingArguments = $"{loggingArguments} --recordCount {recordCount}"; + break; + case BenchmarkName.TPCC: + int warehouseCount = GetWarehouseCount(this.DatabaseScenario, this.WarehouseCount); + loggingArguments = $"{loggingArguments} --warehouses {warehouseCount}"; + break; + default: + throw new DependencyException( + $"The '{this.Benchmark}' benchmark is not supported with the Sysbench workload. Supported options include: \"OLTP, TPCC\".", + ErrorReason.NotSupported); + } - /// - /// Build the Sysbench Logging TPCC Basic Arguments, having the common parameters - /// dbName, databaseSystem, benchmark, tableCount, warehouses and threadCount. - /// - /// - protected string BuildSysbenchLoggingTPCCBasicArguments() - { - int warehouseCount = GetWarehouseCount(this.DatabaseScenario, this.WarehouseCount); - int threadCount = GetThreadCount(this.SystemManager, this.DatabaseScenario, this.Threads); - return $"{this.BuildSysbenchLoggingBasicArguments()} --warehouses {warehouseCount} --threadCount {threadCount}"; + return loggingArguments; } private async Task CheckDistroSupportAsync(EventContext telemetryContext, CancellationToken cancellationToken) @@ -545,31 +489,5 @@ internal class BenchmarkName public const string OLTP = nameof(OLTP); public const string TPCC = nameof(TPCC); } - - /// - /// Supported Sysbench Client actions. - /// - internal class ClientAction - { - /// - /// Creates Database on MySQL server and Users on Server and any Clients. - /// - public const string PopulateDatabase = nameof(PopulateDatabase); - - /// - /// Truncates all tables existing in database - /// - public const string TruncateDatabase = nameof(TruncateDatabase); - - /// - /// Runs specified workload. - /// - public const string RunWorkload = nameof(RunWorkload); - - /// - /// Runs sysbench cleanup action. - /// - public const string Cleanup = nameof(Cleanup); - } } } \ No newline at end of file diff --git a/src/VirtualClient/VirtualClient.Actions/Sysbench/SysbenchServerExecutor.cs b/src/VirtualClient/VirtualClient.Actions/Sysbench/SysbenchServerExecutor.cs index 485adfafb5..8fb8234e85 100644 --- a/src/VirtualClient/VirtualClient.Actions/Sysbench/SysbenchServerExecutor.cs +++ b/src/VirtualClient/VirtualClient.Actions/Sysbench/SysbenchServerExecutor.cs @@ -8,7 +8,6 @@ namespace VirtualClient.Actions using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; - using VirtualClient.Common.Extensions; using VirtualClient.Common.Telemetry; using VirtualClient.Contracts; diff --git a/src/VirtualClient/VirtualClient.Dependencies.UnitTests/MySqlServer/MySQLServerInstallationTests.cs b/src/VirtualClient/VirtualClient.Dependencies.UnitTests/MySqlServer/MySQLServerInstallationTests.cs index 6e3093fc9f..8081dd1df1 100644 --- a/src/VirtualClient/VirtualClient.Dependencies.UnitTests/MySqlServer/MySQLServerInstallationTests.cs +++ b/src/VirtualClient/VirtualClient.Dependencies.UnitTests/MySqlServer/MySQLServerInstallationTests.cs @@ -60,6 +60,7 @@ public async Task MySQLInstallationExecutesTheExpectedProcessForCreateDatabaseCo string[] expectedCommands = { + $"sudo mysql -e \"SELECT VERSION();\"", $"python3 {this.packagePath}/install.py --distro Ubuntu", }; diff --git a/src/VirtualClient/VirtualClient.Dependencies/MySqlServer/MySqlServerInstallation.cs b/src/VirtualClient/VirtualClient.Dependencies/MySqlServer/MySqlServerInstallation.cs index fbdfe3a4ae..27f5280bad 100644 --- a/src/VirtualClient/VirtualClient.Dependencies/MySqlServer/MySqlServerInstallation.cs +++ b/src/VirtualClient/VirtualClient.Dependencies/MySqlServer/MySqlServerInstallation.cs @@ -5,6 +5,7 @@ namespace VirtualClient.Dependencies.MySqlServer { using System; using System.Collections.Generic; + using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; @@ -14,6 +15,7 @@ namespace VirtualClient.Dependencies.MySqlServer using VirtualClient.Common.Extensions; using VirtualClient.Common.Telemetry; using VirtualClient.Contracts; + using VirtualClient.Contracts.Metadata; /// /// Installation component for MySQL @@ -79,6 +81,8 @@ protected override async Task ExecuteAsync(EventContext telemetryContext, Cancel telemetryContext.AddContext(nameof(installationState), installationState); + await this.AddServerVersionAsync(telemetryContext, cancellationToken); + if (installationState == null && !this.SkipInitialize) { switch (this.Action) @@ -121,6 +125,32 @@ private async Task InstallMySQLServerAsync(EventContext telemetryContext, Cancel } } + /// + /// Returns Server Version Version. + /// + /// + /// + private async Task AddServerVersionAsync(EventContext telemetryContext, CancellationToken cancellationToken) + { + try + { + IProcessProxy mysqlversionprocess = await this.ExecuteCommandAsync("sudo", $"mysql -e \"SELECT VERSION();\"", Environment.CurrentDirectory, telemetryContext, cancellationToken); + string mysqlVersion = mysqlversionprocess.StandardOutput.ToString(); + + Regex regex = new Regex(@"(\d+\.\d+\.\d+)"); + Match match = regex.Match(mysqlVersion); + + if (match.Success) + { + this.MetadataContract.Add("mysql_version", match.Groups[1].Value, MetadataContract.DependenciesCategory); + this.MetadataContract.Apply(telemetryContext); + } + } + catch (Exception) + { + } + } + /// /// Supported MySQL Server installation actions. /// diff --git a/src/VirtualClient/VirtualClient.Main/profiles/PERF-MYSQL-SYSBENCH-OLTP.json b/src/VirtualClient/VirtualClient.Main/profiles/PERF-MYSQL-SYSBENCH-OLTP.json index 7d95cb7235..4ee1f21ca3 100644 --- a/src/VirtualClient/VirtualClient.Main/profiles/PERF-MYSQL-SYSBENCH-OLTP.json +++ b/src/VirtualClient/VirtualClient.Main/profiles/PERF-MYSQL-SYSBENCH-OLTP.json @@ -240,11 +240,11 @@ { "Type": "SysbenchConfiguration", "Parameters": { - "Scenario": "PopulateMySQLDatabase", + "Scenario": "PrepareMySQLDatabase", + "Action": "CreateTables", "DatabaseSystem": "MySQL", "Benchmark": "OLTP", "DatabaseName": "$.Parameters.DatabaseName", - "RecordCount": 1, "DatabaseScenario": "$.Parameters.DatabaseScenario", "PackageName": "sysbench", "Role": "Server" @@ -265,6 +265,7 @@ "Type": "SysbenchConfiguration", "Parameters": { "Scenario": "PopulateMySQLDatabase", + "Action": "PopulateTables", "DatabaseSystem": "MySQL", "Benchmark": "OLTP", "DatabaseName": "$.Parameters.DatabaseName", diff --git a/src/VirtualClient/VirtualClient.Main/profiles/PERF-MYSQL-SYSBENCH-TPCC.json b/src/VirtualClient/VirtualClient.Main/profiles/PERF-MYSQL-SYSBENCH-TPCC.json index eb966e653c..f48802a6e2 100644 --- a/src/VirtualClient/VirtualClient.Main/profiles/PERF-MYSQL-SYSBENCH-TPCC.json +++ b/src/VirtualClient/VirtualClient.Main/profiles/PERF-MYSQL-SYSBENCH-TPCC.json @@ -10,6 +10,7 @@ "DatabaseName": "sbtest", "DatabaseScenario": "Balanced", "DiskFilter": "osdisk:false&sizegreaterthan:256g", + "InnodbBufferPoolSize": "{calculate({SystemMemoryBytes} * 80 / 100)}", "Duration": "00:30:00" }, "Actions": [ @@ -67,7 +68,7 @@ "Parameters": { "Scenario": "DownloadSysbenchPackage", "BlobContainer": "packages", - "BlobName": "sysbench-1.0.20.rev1.zip", + "BlobName": "sysbench-1.0.20.rev3.zip", "PackageName": "sysbench", "Extract": true } @@ -117,7 +118,9 @@ "Scenario": "SetMySQLGlobalVariables", "Action": "SetGlobalVariables", "Benchmark": "TPCC", - "Variables": "MAX_PREPARED_STMT_COUNT=1000000;MAX_CONNECTIONS=1000000", + "DiskFilter": "$.Parameters.DiskFilter", + "InnodbBufferPoolSize": "$.Parameters.InnodbBufferPoolSize", + "Variables": "MAX_PREPARED_STMT_COUNT=1000000;MAX_CONNECTIONS=100000;innodb_buffer_pool_size={InnodbBufferPoolSize};innodb_lock_wait_timeout=300;innodb_io_capacity=10000;innodb_io_capacity_max=10000;innodb_buffer_pool_dump_at_shutdown=OFF;innodb_change_buffering=0;table_open_cache=20000;", "PackageName": "mysql-server", "Role": "Server" } @@ -125,11 +128,11 @@ { "Type": "SysbenchConfiguration", "Parameters": { - "Scenario": "PopulateMySQLDatabase", + "Scenario": "PrepareMySQLDatabase", + "Action": "CreateTables", "DatabaseSystem": "MySQL", "Benchmark": "TPCC", "DatabaseName": "$.Parameters.DatabaseName", - "WarehouseCount": 1, "DatabaseScenario": "$.Parameters.DatabaseScenario", "PackageName": "sysbench", "Role": "Server" @@ -150,6 +153,7 @@ "Type": "SysbenchConfiguration", "Parameters": { "Scenario": "PopulateMySQLDatabase", + "Action": "PopulateTables", "DatabaseSystem": "MySQL", "Benchmark": "TPCC", "DatabaseName": "$.Parameters.DatabaseName", 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 4f0378e86f..e80ed74bdb 100644 --- a/src/VirtualClient/VirtualClient.Main/profiles/PERF-POSTGRESQL-HAMMERDB-TPCC.json +++ b/src/VirtualClient/VirtualClient.Main/profiles/PERF-POSTGRESQL-HAMMERDB-TPCC.json @@ -109,13 +109,12 @@ { "Type": "HammerDBExecutor", "Parameters": { - "Scenario": "CreatePostgreSQLDatabase", + "Scenario": "CreatePostgreSQLTables", + "Action": "CreateTables", "DatabaseName": "$.Parameters.DatabaseName", "Workload": "tpcc", "SQLServer": "postgresql", "PackageName": "hammerdb", - "VirtualUsers": 1, - "WarehouseCount": 1, "Port": "$.Parameters.Port", "Role": "Server" } @@ -135,7 +134,8 @@ { "Type": "HammerDBExecutor", "Parameters": { - "Scenario": "PopulatePostgreSQLDatabase", + "Scenario": "PopulatePostgreSQLTables", + "Action": "PopulateTables", "DatabaseName": "$.Parameters.DatabaseName", "Workload": "tpcc", "SQLServer": "postgresql", 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 1b53cd10b9..f23278cc60 100644 --- a/src/VirtualClient/VirtualClient.Main/profiles/PERF-POSTGRESQL-SYSBENCH-OLTP.json +++ b/src/VirtualClient/VirtualClient.Main/profiles/PERF-POSTGRESQL-SYSBENCH-OLTP.json @@ -229,11 +229,11 @@ { "Type": "SysbenchConfiguration", "Parameters": { - "Scenario": "PopulatePostgreSQLDatabase", + "Scenario": "PreparePostgreSQLDatabase", + "Action": "CreateTables", "DatabaseSystem": "PostgreSQL", "Benchmark": "OLTP", "DatabaseName": "$.Parameters.DatabaseName", - "RecordCount": 1, "DatabaseScenario": "$.Parameters.DatabaseScenario", "PackageName": "sysbench", "Role": "Server" @@ -255,6 +255,7 @@ "Type": "SysbenchConfiguration", "Parameters": { "Scenario": "PopulatePostgreSQLDatabase", + "Action": "PopulateTables", "DatabaseSystem": "PostgreSQL", "Benchmark": "OLTP", "DatabaseName": "$.Parameters.DatabaseName", 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 95679d61b2..ddc4c907b2 100644 --- a/src/VirtualClient/VirtualClient.Main/profiles/PERF-POSTGRESQL-SYSBENCH-TPCC.json +++ b/src/VirtualClient/VirtualClient.Main/profiles/PERF-POSTGRESQL-SYSBENCH-TPCC.json @@ -117,11 +117,11 @@ { "Type": "SysbenchConfiguration", "Parameters": { - "Scenario": "PopulatePostgreSQLDatabase", + "Scenario": "PreparePostgreSQLDatabase", + "Action": "CreateTables", "DatabaseSystem": "PostgreSQL", "Benchmark": "TPCC", "DatabaseName": "$.Parameters.DatabaseName", - "WarehouseCount": 1, "DatabaseScenario": "$.Parameters.DatabaseScenario", "PackageName": "sysbench", "Role": "Server" @@ -143,6 +143,7 @@ "Type": "SysbenchConfiguration", "Parameters": { "Scenario": "PopulatePostgreSQLDatabase", + "Action": "PopulateTables", "DatabaseSystem": "PostgreSQL", "Benchmark": "TPCC", "DatabaseName": "$.Parameters.DatabaseName", diff --git a/website/docs/dependencies/0060-configure-mysql.md b/website/docs/dependencies/0060-configure-mysql.md index 230d81b56b..26869ece0e 100644 --- a/website/docs/dependencies/0060-configure-mysql.md +++ b/website/docs/dependencies/0060-configure-mysql.md @@ -27,7 +27,7 @@ The following section describes the different options for the 'Action' parameter | **Action** | **Description** | |----------------------------|-----------------------------------------------------------------------------------------------------------------| | StartDatabaseServer | Starts the MySQL server. | -| CreateDatabase | Creates a database under \ in the MySQL server. | +| CreateDatabase | Creates a database under \ in the MySQL server. | | RaisedStatementCount | Increases number of statements MySQL can prepare (only recommended for larger VMs). | | ConfigureNetwork | Modifies the configuration file to make MySQL server accessible to the private network of VMs. | | CreateUser | Creates user access to the server for each client VM in the provided environment layout. | diff --git a/website/docs/workloads/sysbench/sysbench-profiles.md b/website/docs/workloads/sysbench/sysbench-profiles.md index 39823ec2fd..07c768d9e6 100644 --- a/website/docs/workloads/sysbench/sysbench-profiles.md +++ b/website/docs/workloads/sysbench/sysbench-profiles.md @@ -105,52 +105,88 @@ There are a lot of moving parts to this workload that allows for both out-of-box ### Actions * **SysbenchConfiguration** - Populates the MySQL database using the Sysbench tool. Note that the default Sysbench settings does not populate a database on the data disks, but on the OS disk. Thus, the - recommended profile format is as follows. The below setup creates N tables in the database with one record each. Only then can MySQL equally distribute the database onto different + Populates the MySQL database using the Sysbench tool. The below setup creates N tables in the database with one record each. Only then can MySQL equally distribute the database onto different data disks mounted on the system, as it copies the tables and their schemas into new tables. From there, Sysbench can add additional records to further populate the database tables. - Once populated, VC persists the state, and it will not drop or recreate tables. - ``` bash +``` bash +{ { "Type": "SysbenchConfiguration", "Parameters": { - "Scenario": "PopulateMySQLDatabase", - "BenchmarkName": "TPCC", - "DatabaseName": "sbtest", - "WarehouseCount": 1, - "NumTables": 10, - "PackageName": "sysbench", - "Role": "Server" + "Scenario": "PrepareMySQLDatabase", + "Action": "CreateTables", + "DatabaseSystem": "MySQL", + "Benchmark": "OLTP", + "DatabaseName": "$.Parameters.DatabaseName", + "DatabaseScenario": "$.Parameters.DatabaseScenario", + "PackageName": "sysbench", + "Role": "Server" } - }, - { + }, + { "Type": "MySQLServerConfiguration", "Parameters": { - "Scenario": "DistributeMySQLDatabase", - "BenchmarkName": "TPCC", - "Action": "DistributeDatabase", - "DatabaseName": "sbtest", - "NumTables": 10, - "PackageName": "mysql-server", - "Role": "Server" + "Scenario": "DistributeMySQLDatabase", + "Action": "DistributeDatabase", + "DiskFilter": "$.Parameters.DiskFilter", + "DatabaseName": "$.Parameters.DatabaseName", + "PackageName": "mysql-server", + "Role": "Server" } - }, - { + }, + { "Type": "SysbenchConfiguration", "Parameters": { - "Scenario": "PopulateMySQLDatabase", - "BenchmarkName": "TPCC", - "DatabaseName": "sbtest", - "NumTables": 10, - "WarehouseCount": 100, - "PackageName": "sysbench", - "Role": "Server" + "Scenario": "PopulateMySQLDatabase", + "Action": "PopulateTables", + "DatabaseSystem": "MySQL", + "Benchmark": "OLTP", + "DatabaseName": "$.Parameters.DatabaseName", + "DatabaseScenario": "$.Parameters.DatabaseScenario", + "PackageName": "sysbench", + "Role": "Server" } } - ``` +} +``` + + Once populated, VC persists the state, and it will not drop or recreate tables unless the 'cleanup' action is performed. An example is shown below. In a multi-disk scenario without striping, the DistributeDatabase step must be performed after the CreateTables step once again to re-distribute the tables evenly on each disk. + +``` bash +{ + { + "Type": "SysbenchConfiguration", + "Parameters": + { + "Scenario": "CleanMySQLDatabase", + "Action": "Cleanup", + "DatabaseSystem": "MySQL", + "Benchmark": "OLTP", + "DatabaseName": "$.Parameters.DatabaseName", + "DatabaseScenario": "$.Parameters.DatabaseScenario", + "PackageName": "sysbench", + "Role": "Server" + } + }, + { + "Type": "SysbenchConfiguration", + "Parameters": + { + "Scenario": "PrepareMySQLDatabase", + "Action": "CreateTables", + "DatabaseSystem": "MySQL", + "Benchmark": "OLTP", + "DatabaseName": "$.Parameters.DatabaseName", + "DatabaseScenario": "$.Parameters.DatabaseScenario", + "PackageName": "sysbench", + "Role": "Server" + } + }, +} +``` * **SysbenchClientExecutor** Runs a given workload from the client-side on the server database. Note that this action can run with different arguments from SysbenchConfiguration -- though a database of 10 tables