#!/bin/bash # This is not fully tested. Just documenting what's needed. function install_java_and_jmeter { sudo apt update || return 1 sudo apt install -y openjdk-8-jdk || return 1 wget -O apache-jmeter-4.0.tgz https://archive.apache.org/dist/jmeter/binaries/apache-jmeter-4.0.tgz || return 1 tar xfz apache-jmeter-4.0.tgz -C ~ mkdir -p ~/bin ln -s ~/apache-jmeter-4.0/bin/jmeter ~/bin/jmeter rm apache-jmeter-4.0.tgz wget -O mysql-connector-java-5.1.45.tar.gz https://dev.mysql.com/get/Downloads/Connector-J/mysql-connector-java-5.1.45.tar.gz || return 1 tar xfz mysql-connector-java-5.1.45.tar.gz mv mysql-connector-java-5.1.45/mysql-connector-java-5.1.45-bin.jar ~/apache-jmeter-4.0/lib rm -rf mysql-connector-java-5.1.45* wget -O postgres-42.2.1.jar https://jdbc.postgresql.org/download/postgresql-42.2.1.jar || return 1 mv postgres-42.2.1.jar ~/apache-jmeter-4.0/lib # Have to have jmeter plugins manager and have it download the needed plugins in advance... wget -O jmeter-plugins-manager-0.19.jar http://search.maven.org/remotecontent?filepath=kg/apc/jmeter-plugins-manager/0.19/jmeter-plugins-manager-0.19.jar || return 1 mv jmeter-plugins-manager-0.19.jar ~/apache-jmeter-4.0/lib/ext wget -O cmdrunner-2.0.jar http://search.maven.org/remotecontent?filepath=kg/apc/cmdrunner/2.0/cmdrunner-2.0.jar || return 1 mv cmdrunner-2.0.jar ~/apache-jmeter-4.0/lib java -cp ~/apache-jmeter-4.0/lib/ext/jmeter-plugins-manager-0.19.jar org.jmeterplugins.repository.PluginManagerCMDInstaller # TODO Hard-coded .jmx file here. Do this for each individual .jmx file wget -O tmp-for-plugin-install.jmx https://raw.githubusercontent.com/Azure/Moodle/master/loadtest/simple-test-1.jmx || return 1 ~/apache-jmeter-4.0/bin/PluginsManagerCMD.sh install-for-jmx tmp-for-plugin-install.jmx rm tmp-for-plugin-install.jmx } function install_az_cli { local az_repo=$(lsb_release -cs) sudo mkdir -p /etc/apt/keyrings curl -sLS https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor | sudo tee /etc/apt/keyrings/microsoft.gpg > /dev/null sudo chmod go+r /etc/apt/keyrings/microsoft.gpg echo "deb [arch=`dpkg --print-architecture` signed-by=/etc/apt/keyrings/microsoft.gpg] https://packages.microsoft.com/repos/azure-cli/ $az_repo main" | sudo tee /etc/apt/sources.list.d/azure-cli.list export DEBIAN_FRONTEND=noninteractive sudo apt-get -qq -o=Dpkg::Use-Pty=0 update || return 1 sudo apt-get --yes --no-install-recommends \ -qq -o=Dpkg::Use-Pty=0 \ -o Dpkg::Options::="--force-confdef" \ -o Dpkg::Options::="--force-confold" \ install azure-cli || return 1 } function check_if_logged_on_azure { az account show --query id -o tsv > /dev/null 2>&1 if [ $? != "0" ]; then echo "Not logged on to Azure. Run 'az login' first and make sure subscription is set to your desired one." return 1 fi } function show_command_to_run { echo "Running command: $*" } function check_db_sku_params { local vcores=${1} local size=${2} # In GB if [ "$vcores" != 1 -a "$vcores" != 2 -a "$vcores" != 4 -a "$vcores" != 8 -a "$vcores" != 16 -a "$vcores" != 32 ]; then echo "Invalid vCores ($vcores). Only allowed are 1, 2, 4, 8, 16, 32." return 1 fi if [ -z "${size##*[!0-9]*}" ] || [ "$size" -lt 5 ] || [ "$size" -gt 1024 ]; then echo "Invalid DB size ($size). Only allowed are 5, 6, 7, ..., 1024." return 1 fi # TODO Add other SKU params: Tiers (Basic/GeneralPurpose/MemoryOptimized), HW family (Gen4/Gen5) } # TODO hard-coded Azure location in global variable. Parametrize this later. MOODLE_RG_LOCATION=southcentralus function deploy_moodle_with_some_parameters { check_if_logged_on_azure || return 1 local resource_group=${1} # Azure resource group where templates will be deployed local template_url=${2} # Github URL of the top template to deploy local parameters_template_file=${3} # Local parameter template file local web_server_type=${4} # E.g., apache or nginx local web_vm_sku=${5} # E.g., Standard_DS2_v2 local db_server_type=${6} # E.g., mysql or postgres local db_vcores=${7} # 1, 2, 4, 8, 16, 32 only local db_size_gb=${8} # 5 to 1024, integer only local file_server_type=${9} # E.g., nfs or gluster local file_server_disk_count=${10} # 2, 3, 4 local file_server_disk_size=${11} # in GB local redis_cache=${12} # Redis cache choice. Currently 'true' or 'false' only. local ssh_pub_key=${13} # Your ssh authorized_keys content local no_wait_flag=${14} # Must be "--no-wait" to be passed to az check_db_sku_params $db_vcores $db_size_gb || return 1 local cmd="az group create --resource-group $resource_group --location $MOODLE_RG_LOCATION" show_command_to_run $cmd eval $cmd || return 1 local deployment_name="${resource_group}-deployment" local cmd="az group deployment create --resource-group $resource_group --name $deployment_name $no_wait_flag --template-uri $template_url --parameters @$parameters_template_file webServerType=$web_server_type autoscaleVmSku=$web_vm_sku dbServerType=$db_server_type mysqlPgresVcores=$db_vcores mysqlPgresStgSizeGB=$db_size_gb fileServerType=$file_server_type fileServerDiskCount=$file_server_disk_count fileServerDiskSize=$file_server_disk_size redisDeploySwitch=$redis_cache sshPublicKey='$ssh_pub_key'" show_command_to_run $cmd eval $cmd } function delete_resource_group { check_if_logged_on_azure || return 1 local resource_group=${1} local cmd="az group delete --resource-group $resource_group" show_command_to_run $cmd eval $cmd } function install_moosh { # 'composer install' keeps failing, so try apt... sudo apt-add-repository "deb http://ppa.launchpad.net/zabuch/ppa/ubuntu $(lsb_release -sc) main" sudo apt-get update || true sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys CA1F0167ECFEA95 sudo apt-get install --assume-yes moosh # sudo apt update || return 1 # sudo apt install -y composer || return 1 # cd ~ # git clone git://github.com/tmuras/moosh.git || return 1 # cd moosh # composer install || sleep 30 && composer install || sleep 30 && composer install || return 1 # mkdir -p ~/bin # ln -s $PWD/moosh.php ~/bin/moosh } MOODLE_PATH=/moodle/html/moodle function delete_course { local course_id=${1} sudo -u www-data moosh --moodle-path=$MOODLE_PATH course-delete $course_id } function create_course { local course_id=${1} sudo -u www-data moosh --moodle-path=$MOODLE_PATH course-create --idnumber=$course_id empty@test.course } function restore_course_from_url { local url=${1} wget $url -O backup_to_restore.mbz sudo -u www-data moosh --moodle-path=$MOODLE_PATH course-restore backup_to_restore.mbz 1 } function create_2000_test_users_and_enroll_them_in_course { local course_id=${1} local password=${2} # TODO ugly... sudo -u www-data moosh --moodle-path=$MOODLE_PATH user-create -p $password m_azuretestuser_{1..200} sudo -u www-data moosh --moodle-path=$MOODLE_PATH user-create -p $password m_azuretestuser_{201..400} sudo -u www-data moosh --moodle-path=$MOODLE_PATH user-create -p $password m_azuretestuser_{401..600} sudo -u www-data moosh --moodle-path=$MOODLE_PATH user-create -p $password m_azuretestuser_{601..800} sudo -u www-data moosh --moodle-path=$MOODLE_PATH user-create -p $password m_azuretestuser_{801..1000} sudo -u www-data moosh --moodle-path=$MOODLE_PATH user-create -p $password m_azuretestuser_{1001..1200} sudo -u www-data moosh --moodle-path=$MOODLE_PATH user-create -p $password m_azuretestuser_{1201..1400} sudo -u www-data moosh --moodle-path=$MOODLE_PATH user-create -p $password m_azuretestuser_{1401..1600} sudo -u www-data moosh --moodle-path=$MOODLE_PATH user-create -p $password m_azuretestuser_{1601..1800} sudo -u www-data moosh --moodle-path=$MOODLE_PATH user-create -p $password m_azuretestuser_{1801..2000} sudo -u www-data moosh --moodle-path=$MOODLE_PATH course-enrol $course_id m_azuretestuser_{1..200} sudo -u www-data moosh --moodle-path=$MOODLE_PATH course-enrol $course_id m_azuretestuser_{201..400} sudo -u www-data moosh --moodle-path=$MOODLE_PATH course-enrol $course_id m_azuretestuser_{401..600} sudo -u www-data moosh --moodle-path=$MOODLE_PATH course-enrol $course_id m_azuretestuser_{601..800} sudo -u www-data moosh --moodle-path=$MOODLE_PATH course-enrol $course_id m_azuretestuser_{801..1000} sudo -u www-data moosh --moodle-path=$MOODLE_PATH course-enrol $course_id m_azuretestuser_{1001..1200} sudo -u www-data moosh --moodle-path=$MOODLE_PATH course-enrol $course_id m_azuretestuser_{1201..1400} sudo -u www-data moosh --moodle-path=$MOODLE_PATH course-enrol $course_id m_azuretestuser_{1401..1600} sudo -u www-data moosh --moodle-path=$MOODLE_PATH course-enrol $course_id m_azuretestuser_{1601..1800} sudo -u www-data moosh --moodle-path=$MOODLE_PATH course-enrol $course_id m_azuretestuser_{1801..2000} } function hide_course_overview_block_for_jmeter_test { # "myoverview" is the registered name of the "Course overview" block sudo -u www-data moosh --moodle-path=$MOODLE_PATH block-manage hide myoverview } # TODO hard-coded values... LOADTEST_BASE_URI=https://raw.githubusercontent.com/Azure/Moodle/master/loadtest MOODLE_TEST_USER_PASSWORD='testUserP@$$w0rd' function setup_test_course_and_users { install_moosh # TODO hard-coded test course backup location restore_course_from_url $LOADTEST_BASE_URI/moodle-on-azure-test-course-1.mbz local course_id=2 # TODO Fix this hard-coded course id #. Should be retrieved from the previous restore_course_from_url output local password=$MOODLE_TEST_USER_PASSWORD # TODO parameterize create_2000_test_users_and_enroll_them_in_course $course_id $password hide_course_overview_block_for_jmeter_test } function run_cmd_on_remote_host { local func_cmd=${1} # E.g., install_moosh or 'delete_course 2' local ssh_dest=${2} # E.g., azureadmin@10.2.3.4 local port=${3:-22} # E.g., 2222 local cmd="ssh -o 'StrictHostKeyChecking no' -p $port $ssh_dest 'wget $LOADTEST_BASE_URI/loadtest.sh -O loadtest.sh; source loadtest.sh; $func_cmd'" show_command_to_run $cmd eval $cmd } function run_simple_test_1_on_resource_group { local resource_group=${1} # Azure resource group where Moodle templates were deployed local test_threads_count=${2} # E.g., 400, 800, ... local test_rampup_time_sec=${3} # E.g., 900 (should be long enough for # threads above) local test_run_time_sec=${4} # E.g., 3600 for 1 hour local setup_test_course_users_flag=${5} # Run setup_test_course_and_users on moodle_host if nonzero sudo apt update; sudo apt install -y jq local deployment="${resource_group}-deployment" local output=$(az group deployment show -g $resource_group -n $deployment) local moodle_host=$(echo $output | jq -r .properties.outputs.siteURL.value) local db_host=$(echo $output | jq -r .properties.outputs.databaseDNS.value) local moodle_db_user=$(echo $output | jq -r .properties.outputs.moodleDbUsername.value) local moodle_db_pass=$(echo $output | jq -r .properties.outputs.moodleDbPassword.value) local moodle_user_pass=$MOODLE_TEST_USER_PASSWORD # TODO parameterize if [ -n "$setup_test_course_users_flag" ]; then local moodle_controller_ip=$(echo $output | jq -r .properties.outputs.controllerInstanceIP.value) run_cmd_on_remote_host setup_test_course_and_users azureadmin@${moodle_controller_ip} fi mkdir -p test_outputs local prefix="test_outputs/simple_test_1_$(date +%Y%m%d%H%M%S)" echo $output | jq . > ${prefix}.deployment.json export JVM_ARGS="-Xms1024m -Xmx4096m" local cmd="jmeter -n -t simple-test-1.jmx -l ${prefix}.jmeter.results.txt -j ${prefix}.jmeter.log -e -o ${prefix}.jmeter.report -Jhost=${moodle_host} -Jdb_host=${db_host} -Jdb_user=${moodle_db_user} '-Jdb_pass=${moodle_db_pass}' '-Jmoodle_user_pass=${moodle_user_pass}' -Jthreads=${test_threads_count} -Jrampup=${test_rampup_time_sec} -Jruntime=${test_run_time_sec}" show_command_to_run $cmd eval $cmd } function deallocate_services_in_resource_group { local rg=${1} # Deallocate VMSS's local scalesets=$(az vmss list -g $rg --query [].name -o tsv) for scaleset in $scalesets; do local cmd="az vmss deallocate -g $rg --name $scaleset" show_command_to_run $cmd eval $cmd done # Deallocate VMs local cmd="az vm deallocate --ids $(az vm list -g $rg --query [].id -o tsv)" show_command_to_run $cmd eval $cmd # Stopping DBs and redis cache is currently not possible on Azure. } function deploy_run_test1_teardown { local resource_group=${1} local location=${2} local template_url=${3} local parameters_template_file=${4} local web_server_type=${5} local web_vm_sku=${6} local db_server_type=${7} local db_vcores=${8} local db_size_gb=${9} local file_server_type=${10} local file_server_disk_count=${11} local file_server_disk_size=${12} local redis_cache=${13} local ssh_pub_key=${14} local test_threads_count=${15} local test_rampup_time_sec=${16} local test_run_time_sec=${17} local delete_resource_group_flag=${18} # Any non-empty string is considered true MOODLE_RG_LOCATION=$location deploy_moodle_with_some_parameters $resource_group $template_url $parameters_template_file $web_server_type $web_vm_sku $db_server_type $db_vcores $db_size_gb $file_server_type $file_server_disk_count $file_server_disk_size $redis_cache "$ssh_pub_key" || return 1 run_simple_test_1_on_resource_group $resource_group $test_threads_count $test_rampup_time_sec $test_run_time_sec 1 || return 1 if [ -n "$delete_resource_group_flag" ]; then az group delete -g $resource_group -y else deallocate_services_in_resource_group $resource_group fi } function check_ssh_agent_and_added_key { ssh-add -l if [ $? != "0" ]; then echo "No ssh key added to ssh-agent or no ssh-agent is running. Make sure to run ssh-agent (eval `ssh-agent`) and add the correct ssh key (usually just ssh-add will do), so that remote commands execution through ssh doesn't prompt for interactive password." return 1 fi } function run_load_test_example { check_ssh_agent_and_added_key || return 1 deploy_run_test1_teardown ltest6 southcentralus https://raw.githubusercontent.com/Azure/Moodle/master/azuredeploy.json azuredeploy.parameters.loadtest.defaults.json apache Standard_DS2_v2 mysql 4 125 nfs 2 128 false "$(cat ~/.ssh/authorized_keys)" 1600 4800 18000 } function run_load_test_postgres { check_ssh_agent_and_added_key || return 1 deploy_run_test1_teardown pgres southcentralus https://raw.githubusercontent.com/Azure/Moodle/master/azuredeploy.json azuredeploy.parameters.loadtest.defaults.json apache Standard_DS2_v2 postgres 16 256 nfs 2 128 false "$(cat ~/.ssh/authorized_keys)" 800 2400 36000 }