Removed Moodle specific load tests and Travis CI content.
This commit is contained in:
Родитель
f5e7dac3b0
Коммит
c8bebff00a
28
.jshintrc
28
.jshintrc
|
@ -1,28 +0,0 @@
|
|||
{
|
||||
"esnext": true,
|
||||
"node": true,
|
||||
"browser": true,
|
||||
"nomen": false,
|
||||
"bitwise": true,
|
||||
"eqeqeq": true,
|
||||
"forin": true,
|
||||
"immed": true,
|
||||
"latedef": true,
|
||||
"newcap": true,
|
||||
"noarg": true,
|
||||
"noempty": true,
|
||||
"nonew": true,
|
||||
"plusplus": true,
|
||||
"regexp": true,
|
||||
"undef": true,
|
||||
"unused": true,
|
||||
"trailing": true,
|
||||
"indent": 4,
|
||||
"esnext": true,
|
||||
"onevar": true,
|
||||
"white": true,
|
||||
"quotmark": "double",
|
||||
"predef": {
|
||||
}
|
||||
}
|
||||
|
29
.travis.yml
29
.travis.yml
|
@ -1,29 +0,0 @@
|
|||
dist: trusty
|
||||
|
||||
language: python
|
||||
|
||||
node_js: "0.12"
|
||||
|
||||
python: "3.5"
|
||||
|
||||
cache:
|
||||
- directories: node_modules
|
||||
- pip
|
||||
|
||||
env:
|
||||
- PYTHONUNBUFFERED=TRUE
|
||||
|
||||
install:
|
||||
- npm install # Install task runners for lint checking.
|
||||
- pip install azure-mgmt-subscription azure-mgmt-resource keyring pycurl # Install Azure Python SDK (we only need the sub & the resource manager packages)
|
||||
|
||||
before_script:
|
||||
- ssh-keygen -q -f azure_moodle_id_rsa -N "" # Generate SSH keys to send to deployment
|
||||
|
||||
script:
|
||||
- npm test
|
||||
- ./etc/travis.py
|
||||
|
||||
notifications:
|
||||
|
||||
webhooks: https://outlook.office.com/webhook/e75ee820-3466-49a6-bb0f-ecae0daf8fe1@72f988bf-86f1-41af-91ab-2d7cd011db47/TravisCI/00abc9d7ce1044818f216da49d30d54d/a38fc8f6-fb60-4169-bde6-dd2bbf01304f
|
|
@ -1,7 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
from=$1
|
||||
to=$2
|
||||
|
||||
sed -i s/%2F${from}%2F/%2F${to}%2F/g README.md
|
||||
sed -i s#/${from}/#/${to}/#g azuredeploy.json
|
|
@ -1,58 +0,0 @@
|
|||
# Ensure that the Base URL for templates, scripts and deploy to Azure buttons
|
||||
# is correctly set for the current git branch.
|
||||
|
||||
# Correct values for locations
|
||||
CURRENT_BRANCH=$(git branch | sed -n -e 's/^\* \(.*\)/\1/p')
|
||||
echo "Current git branch is '$CURRENT_BRANCH'"
|
||||
|
||||
BASE_TEMPLATE_URL=https://raw.githubusercontent.com/Azure/Moodle/$CURRENT_BRANCH/nested/
|
||||
echo "Base template URL: $BASE_TEMPLATE_URL"
|
||||
|
||||
SCRIPT_LOCATION=https://raw.githubusercontent.com/Azure/Moodle/$CURRENT_BRANCH/scripts/
|
||||
echo "Script location: $SCRIPT_LOCATION"
|
||||
|
||||
DEPLOY_TO_AZURE_URL=https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2FMoodle%2F$CURRENT_BRANCH%2Fazuredeploy.json
|
||||
echo "Deploy to Azure URL: $DEPLOY_TO_AZURE_URL"
|
||||
|
||||
VISUALIZE_URL=http://armviz.io/#/?load=https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2FMoodle%2F$CURRENT_BRANCH%2Fazuredeploy.json
|
||||
echo "Visualize template URL: $VISUALIZE_URL"
|
||||
|
||||
# Check values in README.md
|
||||
|
||||
VALUE=$(sed -n -e 's/.*deploybutton.png)](\([^)]*\)).*/\1/p' README.md)
|
||||
if [[ "$VALUE" = "$DEPLOY_TO_AZURE_URL" ]]
|
||||
then
|
||||
echo "Deploy to Azure URL is set correctly"
|
||||
else
|
||||
echo "!!!!! Deploy to Azure URL is not set correctly in README.md, it is currently:"
|
||||
echo $VALUE
|
||||
fi
|
||||
|
||||
VALUE=$(sed -n -e 's/.*visualizebutton.png)](\([^)]*\)).*/\1/p' README.md)
|
||||
if [[ "$VALUE" = "$VISUALIZE_URL" ]]
|
||||
then
|
||||
echo "Visualize URL is set correctly"
|
||||
else
|
||||
echo "!!!!! Visualize URL is not set correctly in README.md, it is currently:"
|
||||
echo $VALUE
|
||||
fi
|
||||
|
||||
# Check values in azuredeploy.json
|
||||
|
||||
VALUE=$(sed -n -e 's/.*\"baseTemplateUrl\": \"\([^\"]*\)\",/\1/p' azuredeploy.json)
|
||||
if [[ "$VALUE" = "$BASE_TEMPLATE_URL" ]]
|
||||
then
|
||||
echo "baseTemplateURL is set correctly"
|
||||
else
|
||||
echo "!!!!! baseTemplateURL is not set correctly, it is currently:"
|
||||
echo $VALUE
|
||||
fi
|
||||
|
||||
VALUE=$(sed -n -e 's/.*\"scriptLocation\": \"\([^\"]*\)\",/\1/p' azuredeploy.json)
|
||||
if [[ "$VALUE" = "$SCRIPT_LOCATION" ]]
|
||||
then
|
||||
echo "scriptLocation is set correctly"
|
||||
else
|
||||
echo "!!!!! scriptLocation is not set correctly, it is currently:"
|
||||
echo $VALUE
|
||||
fi
|
163
etc/keyvault.sh
163
etc/keyvault.sh
|
@ -1,163 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Based on https://github.com/Azure/azure-quickstart-templates/blob/master/201-vmss-ubuntu-web-ssl/keyvault.sh
|
||||
|
||||
#set -e
|
||||
|
||||
usage()
|
||||
{
|
||||
echo usage: keyvault.sh '<keyvaultname> <resource group name> <location> <secretname> <certpemfile> <keypemfile> <cacertpemfile>'
|
||||
echo The cacertpem file is optional. The template will accept a self-signed cert and key.
|
||||
}
|
||||
|
||||
creategroup()
|
||||
{
|
||||
|
||||
local group=$(az group show -g $rgname)
|
||||
if [ -n "$group" ]; then
|
||||
echo Resource Group $rgname already exists. Skipping creation.
|
||||
else
|
||||
# Create a resource group for the keyvault
|
||||
az group create -n $rgname -l $location
|
||||
fi
|
||||
}
|
||||
|
||||
createkeyvault()
|
||||
{
|
||||
|
||||
az keyvault show -n $vaultname 2> /dev/null
|
||||
if [ $? -eq 0 ]
|
||||
then
|
||||
echo Key Vault $vaultname already exists. Skipping creation.
|
||||
else
|
||||
echo Creating Key Vault $vaultname.
|
||||
|
||||
creategroup
|
||||
# Create the key vault
|
||||
az keyvault create --name $vaultname --resource-group $rgname --location $location --enabled-for-template-deployment true --enabled-for-deployment true
|
||||
fi
|
||||
}
|
||||
|
||||
convertcert()
|
||||
{
|
||||
local cert=$1
|
||||
local key=$2
|
||||
local pfxfile=$3
|
||||
local pass=$4
|
||||
|
||||
echo Creating PFX $pfxfile
|
||||
openssl pkcs12 -export -out $pfxfile -inkey $key -in $cert -password pass:$pass 2> /dev/null
|
||||
if [ $? -eq 1 ]
|
||||
then
|
||||
echo problem converting $key and $cert to pfx
|
||||
exit 1
|
||||
fi
|
||||
|
||||
fingerprint=$(openssl x509 -in $cert -noout -fingerprint | cut -d= -f2 | sed 's/://g' )
|
||||
}
|
||||
|
||||
convertcacert()
|
||||
{
|
||||
local cert=$1
|
||||
local pfxfile=$2
|
||||
local pass=$3
|
||||
|
||||
echo Creating PFX $pfxfile
|
||||
openssl pkcs12 -export -out $pfxfile -nokeys -in $cert -password pass:$pass 2> /dev/null
|
||||
if [ $? -eq 1 ]
|
||||
then
|
||||
echo problem converting $cert to pfx
|
||||
exit 1
|
||||
fi
|
||||
|
||||
fingerprint=$(openssl x509 -in $cert -noout -fingerprint | cut -d= -f2 | sed 's/://g' )
|
||||
}
|
||||
|
||||
storesecret()
|
||||
{
|
||||
local secretfile=$1
|
||||
local name=$2
|
||||
filecontentencoded=$( cat $secretfile | base64 $base64_unwrap )
|
||||
|
||||
json=$(cat << EOF
|
||||
{
|
||||
"data": "${filecontentencoded}",
|
||||
"dataType" :"pfx",
|
||||
"password": "${pwd}"
|
||||
}
|
||||
EOF
|
||||
)
|
||||
|
||||
jsonEncoded=$( echo $json | base64 $base64_unwrap )
|
||||
|
||||
r=$(az keyvault secret set --vault-name $vaultname --name $name --value $jsonEncoded)
|
||||
if [ $? -eq 1 ]
|
||||
then
|
||||
echo problem storing secret $name in $vaultname
|
||||
exit 1
|
||||
fi
|
||||
|
||||
id=$(az keyvault secret show --vault-name $vaultname --name $name --query id -o tsv)
|
||||
echo Secret ID is $id
|
||||
}
|
||||
|
||||
# We need at least 6 parameters
|
||||
if [ "$#" -lt 6 ]; then
|
||||
usage
|
||||
exit
|
||||
fi
|
||||
|
||||
# The base64 command on OSX does not know about the -w parameter, but outputs unwrapped base64 by default
|
||||
base64_unwrap="-w 0"
|
||||
[[ $(uname) == "Darwin" ]] && base64_unwrap=""
|
||||
|
||||
vaultname=$1
|
||||
rgname=$2
|
||||
location=$3
|
||||
secretname=$4
|
||||
certfile=$5
|
||||
keyfile=$6
|
||||
cacertfile=$7
|
||||
|
||||
# Create a random password with 33 bytes of entropy
|
||||
# I picked 33 so the last character will not be =
|
||||
pwd=$(dd if=/dev/urandom bs=32 count=1 2>/dev/null | base64)
|
||||
|
||||
certpfxfile=${certfile%.*crt}.pfx
|
||||
cacertpfxfile=${cacertfile%.*crt}.pfx
|
||||
casecretname=ca$secretname
|
||||
|
||||
createkeyvault
|
||||
|
||||
# converting SSL cert to pfx
|
||||
convertcert $certfile $keyfile $certpfxfile $pwd
|
||||
certprint=$fingerprint
|
||||
echo $certpfxfile fingerprint is $fingerprint
|
||||
# storing pfx in keyvault
|
||||
echo Storing $certpfxfile as $secretname
|
||||
storesecret $certpfxfile $secretname
|
||||
certid=$id
|
||||
rm -f $certpfxfile
|
||||
|
||||
if [ ! -z $cacertfile ]
|
||||
then
|
||||
# converting CA cert to pfx
|
||||
convertcacert $cacertfile $cacertpfxfile $pwd
|
||||
echo $cacertpfxfile fingerprint is $fingerprint
|
||||
cacertprint=$fingerprint
|
||||
# storing pfx in key vault
|
||||
echo Storing $cacertpfxfile as $casecretname
|
||||
storesecret $cacertpfxfile $casecretname
|
||||
cacertid=$id
|
||||
rm -f $cacertpfxfile
|
||||
fi
|
||||
|
||||
echo "Specified SSL cert/key .pem files are now stored in your Azure Key Vault and ready to be used by the template."
|
||||
echo "Use the following values for the related template parameters:"
|
||||
echo
|
||||
echo "- keyVaultResourceId: $(az keyvault show --name $vaultname --query id -o tsv)"
|
||||
echo "- sslCertKeyVaultURL: $certid"
|
||||
echo "- sslCertThumbprint: $certprint"
|
||||
echo "- caCertKeyVaultURL: $cacertid"
|
||||
echo "- caCertThumbprint: $cacertprint"
|
||||
echo Done
|
|
@ -1,5 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
from travis.DeploymentTester import DeploymentTester
|
||||
|
||||
DeploymentTester().run()
|
|
@ -1,85 +0,0 @@
|
|||
import json
|
||||
import os
|
||||
import time
|
||||
|
||||
from azure.mgmt.resource.resources.v2017_05_10.models import DeploymentMode
|
||||
|
||||
|
||||
class Configuration:
|
||||
def __init__(self):
|
||||
self.deployment_name = 'azuredeploy'
|
||||
self.client_id = os.getenv('SPNAME')
|
||||
self.secret = os.getenv('SPPASSWORD')
|
||||
self.tenant_id = os.getenv('SPTENANT')
|
||||
self.location = os.getenv('LOCATION', 'westus2')
|
||||
self.source_branch = self.identify_source_branch()
|
||||
self.fullci_branches = os.getenv('FULLCI_BRANCHES', 'master').split(':')
|
||||
self.commit_message = os.getenv('TRAVIS_COMMIT_MESSAGE', None)
|
||||
self.ssh_key = self.identify_ssh_key()
|
||||
self.resource_group = self.identify_resource_group()
|
||||
self.deployment_properties = self.generate_deployment_properties()
|
||||
|
||||
def identify_resource_group(self):
|
||||
resource_group = os.getenv('RESOURCEGROUP')
|
||||
if resource_group is None:
|
||||
resource_group = 'azmdl-travis-' + os.getenv('TRAVIS_BUILD_NUMBER', 'manual-{}'.format(time.time()))
|
||||
return resource_group
|
||||
|
||||
def identify_ssh_key(self):
|
||||
ssh_key = os.getenv('SPSSHKEY')
|
||||
if ssh_key is None:
|
||||
with open('azure_moodle_id_rsa.pub', 'r') as sshkey_fd:
|
||||
ssh_key = sshkey_fd.read()
|
||||
return ssh_key
|
||||
|
||||
def generate_deployment_properties(self):
|
||||
with open('azuredeploy.json', 'r') as template_fd:
|
||||
template = json.load(template_fd)
|
||||
|
||||
with open('azuredeploy.parameters.json', 'r') as parameters_fd:
|
||||
parameters = json.load(parameters_fd)
|
||||
parameters = parameters['parameters']
|
||||
parameters['sshPublicKey']['value'] = self.ssh_key
|
||||
parameters['_artifactsLocation'] = {'value': self.identify_artifacts_location()}
|
||||
|
||||
return {
|
||||
'mode': DeploymentMode.incremental,
|
||||
'template': template,
|
||||
'parameters': parameters,
|
||||
}
|
||||
|
||||
def identify_artifacts_location(self):
|
||||
slug = os.getenv('TRAVIS_PULL_REQUEST_SLUG')
|
||||
if not slug:
|
||||
slug = os.getenv('TRAVIS_REPO_SLUG')
|
||||
return "https://raw.githubusercontent.com/{}/{}/".format(slug, self.source_branch)
|
||||
|
||||
def identify_source_branch(self):
|
||||
branch = os.getenv('TRAVIS_PULL_REQUEST_BRANCH')
|
||||
if not branch:
|
||||
branch = os.getenv('TRAVIS_BRANCH')
|
||||
return branch
|
||||
|
||||
def is_valid(self):
|
||||
valid = True
|
||||
|
||||
for key, value in vars(self).items():
|
||||
if value is None:
|
||||
valid = False
|
||||
print('(missing configuration for {})'.format(key))
|
||||
|
||||
if self.deployment_properties['parameters']['_artifactsLocation']['value'] is None:
|
||||
valid = False
|
||||
print('(could not identify _artifactsLocation)')
|
||||
|
||||
return valid
|
||||
|
||||
def should_run_full_ci(self):
|
||||
if self.source_branch in self.fullci_branches:
|
||||
return True
|
||||
|
||||
message = self.commit_message.upper()
|
||||
if '[FULL CI]' in message or '[FULLCI]' in message:
|
||||
return True
|
||||
|
||||
return False
|
|
@ -1,177 +0,0 @@
|
|||
import os
|
||||
import pycurl
|
||||
import sys
|
||||
import tempfile
|
||||
import time
|
||||
import urllib
|
||||
from io import BytesIO
|
||||
from pycurl import Curl
|
||||
|
||||
from azure.mgmt.resource import ResourceManagementClient
|
||||
from azure.mgmt.subscription import SubscriptionClient
|
||||
from msrestazure.azure_active_directory import ServicePrincipalCredentials
|
||||
|
||||
from travis.Configuration import Configuration
|
||||
|
||||
|
||||
class DeploymentTester:
|
||||
@staticmethod
|
||||
def elapsed(since):
|
||||
elapsed = int(time.time() - since)
|
||||
elapsed = '{:02d}:{:02d}:{:02d}'.format(elapsed // 3600, (elapsed % 3600 // 60), elapsed % 60)
|
||||
return elapsed
|
||||
|
||||
def __init__(self):
|
||||
self.config = Configuration()
|
||||
self.deployment = None
|
||||
|
||||
self.credentials = None
|
||||
""":type : ServicePrincipalCredentials"""
|
||||
|
||||
self.resource_client = None
|
||||
""":type : ResourceManagementClient"""
|
||||
|
||||
def run(self):
|
||||
should_delete_resource_group = False
|
||||
try:
|
||||
self.check_configuration()
|
||||
self.login()
|
||||
self.create_resource_group()
|
||||
self.validate()
|
||||
if not self.config.should_run_full_ci():
|
||||
print('\n\nBasic CI tests successful.')
|
||||
should_delete_resource_group = True
|
||||
return
|
||||
self.deploy()
|
||||
self.moodle_smoke_test()
|
||||
self.moodle_admin_login()
|
||||
print('\n\nFull CI tests successful!')
|
||||
should_delete_resource_group = True
|
||||
finally:
|
||||
if should_delete_resource_group:
|
||||
self.delete_resource_group()
|
||||
|
||||
def check_configuration(self):
|
||||
print('\nChecking configuration...')
|
||||
if not self.config.is_valid():
|
||||
print('No Azure deployment info given, skipping test deployment and exiting.')
|
||||
print('Further information: https://github.com/Azure/Moodle#automated-testing-travis-ci')
|
||||
sys.exit()
|
||||
artifacts_location = self.config.deployment_properties['parameters']['_artifactsLocation']
|
||||
print('- Detected "_artifactsLocation": ' + artifacts_location['value'])
|
||||
print("(all check)")
|
||||
|
||||
def login(self):
|
||||
print('\nLogging in...')
|
||||
self.credentials = ServicePrincipalCredentials(
|
||||
client_id=self.config.client_id,
|
||||
secret=self.config.secret,
|
||||
tenant=self.config.tenant_id,
|
||||
)
|
||||
print('(got credentials)')
|
||||
subscription_client = SubscriptionClient(self.credentials)
|
||||
subscription = next(subscription_client.subscriptions.list())
|
||||
print('(found subscription)')
|
||||
self.resource_client = ResourceManagementClient(self.credentials, subscription.subscription_id)
|
||||
print("(logged in)")
|
||||
|
||||
def create_resource_group(self):
|
||||
print('\nCreating group "{}" on "{}"...'.format(self.config.resource_group, self.config.location))
|
||||
self.resource_client.resource_groups.create_or_update(self.config.resource_group,
|
||||
{'location': self.config.location})
|
||||
print('(created)')
|
||||
|
||||
def validate(self):
|
||||
print('\nValidating template...')
|
||||
|
||||
validation = self.resource_client.deployments.validate(self.config.resource_group,
|
||||
self.config.deployment_name,
|
||||
self.config.deployment_properties)
|
||||
if validation.error is not None:
|
||||
print("*** VALIDATION FAILED ({}) ***".format(validation.error))
|
||||
print(validation.error.message)
|
||||
for detail in validation.error.details:
|
||||
print("- {}:\n{}".format(detail.code, detail.message))
|
||||
sys.exit(1)
|
||||
|
||||
print("(valid)")
|
||||
|
||||
def deploy(self):
|
||||
print('\nDeploying template, feel free to take a nap...')
|
||||
deployment = self.resource_client.deployments.create_or_update(self.config.resource_group,
|
||||
self.config.deployment_name,
|
||||
self.config.deployment_properties)
|
||||
""":type : msrestazure.azure_operation.AzureOperationPoller"""
|
||||
started = time.time()
|
||||
while not deployment.done():
|
||||
print('... after {} still "{}" ...'.format(self.elapsed(started), deployment.status()))
|
||||
deployment.wait(60)
|
||||
print("WAKE UP! After {} we finally got status {}.".format(self.elapsed(started), deployment.status()))
|
||||
|
||||
print("Checking deployment response...")
|
||||
properties = deployment.result(0).properties
|
||||
if properties.provisioning_state != 'Succeeded':
|
||||
print("*** DEPLOY FAILED ***")
|
||||
print('Provisioning state: ' + properties.provisioning_state)
|
||||
sys.exit(1)
|
||||
self.load_deployment_outputs(properties.outputs)
|
||||
print("(success)")
|
||||
|
||||
def load_deployment_outputs(self, outputs):
|
||||
self.deployment = {}
|
||||
for key, value in outputs.items():
|
||||
self.deployment[key] = value['value']
|
||||
print("- Found: " + key)
|
||||
|
||||
def moodle_smoke_test(self):
|
||||
print("\nMoodle Smoke Test...")
|
||||
url = 'https://' + self.deployment['siteURL']
|
||||
curl = Curl()
|
||||
curl.setopt(pycurl.URL, url)
|
||||
curl.setopt(pycurl.SSL_VERIFYPEER, False)
|
||||
curl.setopt(pycurl.WRITEFUNCTION, lambda x: None)
|
||||
curl.perform()
|
||||
status = curl.getinfo(pycurl.HTTP_CODE)
|
||||
if status != 200:
|
||||
print("*** DEPLOY FAILED ***")
|
||||
print('HTTP Status Code: {}'.format(status))
|
||||
sys.exit(1)
|
||||
print('(ok: {})'.format(status))
|
||||
|
||||
def moodle_admin_login(self):
|
||||
print("\nLogging in into Moodle as 'admin'...")
|
||||
response = self.moodle_admin_login_curl()
|
||||
if 'Admin User' not in response:
|
||||
print("*** FAILED: 'Admin User' keyword not found ***")
|
||||
sys.exit(1)
|
||||
print('(it worked)')
|
||||
|
||||
def moodle_admin_login_curl(self):
|
||||
fd, path = tempfile.mkstemp()
|
||||
try:
|
||||
response = BytesIO()
|
||||
url = 'https://' + self.deployment['siteURL'] + '/login/index.php'
|
||||
curl = Curl()
|
||||
curl.setopt(pycurl.URL, url)
|
||||
curl.setopt(pycurl.SSL_VERIFYPEER, False)
|
||||
curl.setopt(pycurl.WRITEFUNCTION, response.write)
|
||||
curl.setopt(pycurl.POST, True)
|
||||
curl.setopt(pycurl.COOKIEJAR, path)
|
||||
curl.setopt(pycurl.COOKIEFILE, path)
|
||||
post = urllib.parse.urlencode({'username': 'admin', 'password': self.deployment['moodleAdminPassword']})
|
||||
curl.setopt(pycurl.POSTFIELDS, post)
|
||||
curl.setopt(pycurl.FOLLOWLOCATION, True)
|
||||
curl.perform()
|
||||
status = curl.getinfo(pycurl.HTTP_CODE)
|
||||
if status != 200:
|
||||
print("*** FAILED: {} ***".format(status))
|
||||
sys.exit(1)
|
||||
response = response.getvalue().decode('utf-8')
|
||||
finally:
|
||||
os.remove(path)
|
||||
return response
|
||||
|
||||
def delete_resource_group(self):
|
||||
print('\n\nDeleting the resource group for this passing build...')
|
||||
self.resource_client.resource_groups.delete(self.config.resource_group, polling=False)
|
||||
print('(delete initiated, not polling)')
|
|
@ -1,9 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Should be run at the git repo root as: $ ./etc/updateDocsParameters.sh
|
||||
|
||||
dpkg -l jq &> /dev/null || sudo apt install jq
|
||||
|
||||
sed -i '/## Available Parameters/q' docs/Parameters.md
|
||||
echo >> docs/Parameters.md
|
||||
jq -r '.parameters | to_entries[] | "### " + .key + "\n\n" + .value.metadata.description + "\n\nType: " + .value.type + "\n\nPossible Values: " + (.value.allowedValues | @text) + "\n\nDefault: " + (.value.defaultValue | @text) + "\n\n"' azuredeploy.json >> docs/Parameters.md
|
|
@ -1,41 +0,0 @@
|
|||
# Login to Azure
|
||||
|
||||
Before we start a load test session we need to first veriy that we are
|
||||
logged in to Azure using the CLI.
|
||||
|
||||
## Azure Login
|
||||
|
||||
``` bash
|
||||
az login --username $AZURE_USERNAME --password $AZURE_PASWORD
|
||||
```
|
||||
|
||||
Note that if your username or password has any special characters in
|
||||
it, such as '$' this may fail. You can login using a browser using `az login`.
|
||||
|
||||
``` bash
|
||||
az account set --subscription $AZURE_SUBSCRIPTION_ID
|
||||
```
|
||||
|
||||
## Validation
|
||||
|
||||
``` bash
|
||||
az account show
|
||||
```
|
||||
|
||||
Results:
|
||||
|
||||
```
|
||||
{
|
||||
"environmentName": "AzureCloud",
|
||||
"id": "325e7c34-99fb-4190-aa87-1df746c67705",
|
||||
"isDefault": true,
|
||||
"name": "Ross Dev Account",
|
||||
"state": "Enabled",
|
||||
"tenantId": "72f988bf-86f1-41af-91ab-2d7cd011db47",
|
||||
"user": {
|
||||
"name": "rogardle@microsoft.com",
|
||||
"type": "user"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
@ -1,125 +0,0 @@
|
|||
# Setting up a test host
|
||||
|
||||
To run load tests using the resources in this directory, you'll want
|
||||
to spin up an Ubuntu VM (let's call it the jMeter host) in your Azure
|
||||
subscription. This should be located in the same region as your Moodle
|
||||
cluster in order to avoid egress charges. Once your VM is ready, you
|
||||
need to install Java and [jMeter](https://jmeter.apache.org/).
|
||||
|
||||
## Prerequisites
|
||||
|
||||
To make things consistent across different sessions load testing Moodle we
|
||||
should [configure the moodle environment](../docs/Preparation.md).
|
||||
|
||||
We will want to use a consistent resource group name in order to avoid
|
||||
wasting resource in these tests:
|
||||
|
||||
```
|
||||
MOODLE_RG_NAME=loadtest
|
||||
```
|
||||
|
||||
And we'll need a name for our load test VM:
|
||||
|
||||
```
|
||||
MOODLE_LOAD_TEST_VM_NAME=LoadTestVM
|
||||
```
|
||||
|
||||
## Deploy the Load Test VM
|
||||
|
||||
First you need a resource group within which all your resources will be deployed.
|
||||
|
||||
``` bash
|
||||
az group create --name $MOODLE_RG_NAME --location $MOODLE_RG_LOCATION
|
||||
```
|
||||
|
||||
Now we can create our VM in this group. The following command will
|
||||
create the VM and, if necessary, generate the SSH keys.
|
||||
|
||||
``` bash
|
||||
az vm create --resource-group $MOODLE_RG_NAME --name $MOODLE_LOAD_TEST_VM_NAME --image UbuntuLTS --generate-ssh-keys
|
||||
```
|
||||
|
||||
Results:
|
||||
|
||||
``` json
|
||||
{
|
||||
"fqdns": "",
|
||||
"id": "/subscriptions/325e7c34-99fb-4190-aa87-1df746c67705/resourceGroups/loadtestvm/providers/Microsoft.Compute/virtualMachines/LoadTestVM",
|
||||
"location": "southcentralus",
|
||||
"macAddress": "00-0D-3A-70-91-57",
|
||||
"powerState": "VM running",
|
||||
"privateIpAddress": "10.0.0.4",
|
||||
"publicIpAddress": "13.84.131.173",
|
||||
"resourceGroup": "loadtestvm",
|
||||
"zones": ""
|
||||
}
|
||||
```
|
||||
|
||||
You will need the IP number from this output. For convenience we'll
|
||||
place it into an environment variable:
|
||||
|
||||
``` bash
|
||||
ipAddress=$(az network public-ip show --name ${MOODLE_LOAD_TEST_VM_NAME}PublicIP --resource-group $MOODLE_RG_NAME --query "ipAddress" --output tsv)
|
||||
echo $ipAddress
|
||||
```
|
||||
|
||||
We can now connect to the VM using ssh, and run commands. The first thing we want to do is pull down the Moodle on Azure repo. Since this document is used to automatically run tests all our commands need to be non-interactive. We will therefore skip the host key validation step. Note that you should never do this in a production environment (remove `-o StrictHostKeyChecking=no`):
|
||||
|
||||
``` bash
|
||||
ssh -o StrictHostKeyChecking=no $ipAddress "rm -Rf Moodle; git clone git://github.com/Azure/Moodle.git"
|
||||
```
|
||||
|
||||
Now we can install the load testing scripts, we will have these loaded
|
||||
via the `.profile` so that they are always availble.
|
||||
|
||||
``` bash
|
||||
ssh $ipAddress 'echo ". ~/Moodle/loadtest/loadtest.sh" >> ~/.profile'
|
||||
```
|
||||
|
||||
This script provides some helper functions for installing dependencies
|
||||
on the VM.
|
||||
|
||||
``` bash
|
||||
ssh $ipAddress 'install_java_and_jmeter; install_az_cli'
|
||||
```
|
||||
|
||||
We need to login to Azure using the CLI. The command below is
|
||||
convenient but is not secure since it stores your password in clear
|
||||
text in an environment variable. However, it is convenient for test
|
||||
purposes.
|
||||
|
||||
``` bash
|
||||
ssh $ipAddress "az login --username $AZURE_LOGIN --password $AZURE_PASSWORD; az account set --subscription $AZURE_SUBSCRIPTION_ID"
|
||||
```
|
||||
|
||||
## Validation
|
||||
|
||||
Finally, we will verify that key dependencies have been installed. First lets check Java is present:
|
||||
|
||||
``` bash
|
||||
ssh -o StrictHostKeyChecking=no $ipAddress "java -version"
|
||||
```
|
||||
|
||||
Results:
|
||||
|
||||
```
|
||||
openjdk version "1.8.0_151"
|
||||
OpenJDK Runtime Environment (build 1.8.0_151-8u151-b12-0ubuntu0.16.04.2-b12)
|
||||
OpenJDK 64-Bit Server VM (build 25.151-b12, mixed mode)
|
||||
```
|
||||
|
||||
We will also need to confirm the Azure CLI is present:
|
||||
|
||||
``` bash
|
||||
ssh -o StrictHostKeyChecking=no $ipAddress "if hash az 2>/dev/null; then echo "Azure CLI Installed"; else echo "Missing dependency: Azure CLI"; fi"
|
||||
```
|
||||
|
||||
Results:
|
||||
|
||||
```
|
||||
Azure CLI Installed
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,139 +0,0 @@
|
|||
# Load-Testing Deployed Moodle Cluster
|
||||
|
||||
This directory currently contains utility scripts, a Moodle test
|
||||
course, and an Apache jMeter test plan that can be used to load-test a
|
||||
Moodle cluster on Azure using the Azure Resource Manager templates in
|
||||
this repository.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
To run load tests using the resources in this directory, you'll want
|
||||
to spin up a VM to manage the [Load Test](Deploy_Load_Test_VM.md) in
|
||||
your Azure subscription. This VM will generate the traffic, running it
|
||||
in Azure will minimize network charges.
|
||||
|
||||
## Deploying Moodle using templates and running load test
|
||||
|
||||
Once dependencies are installed, you can initiate the load testing
|
||||
process by using included utility scripts. These scripts will:
|
||||
|
||||
* deploy a Moodle cluster
|
||||
* set up the test course in Moodle
|
||||
* enrol students for the course
|
||||
* run a synthetic test workload using jMeter
|
||||
* teardown the test cluster
|
||||
|
||||
Use the function `deploy_run_test1_teardown` to perform all these
|
||||
steps. This function takes 18 parameters in the following order:
|
||||
|
||||
See the included example `run_load_test_example` in
|
||||
`loadtest/loadtest.sh`. At the time of writing this example is
|
||||
configured as follows:
|
||||
|
||||
``` bash
|
||||
ssh $ipAddress "az login --username $AZURE_LOGIN --password $AZURE_PASSWORD; az account set --subscription $AZURE_SUBSCRIPTION_ID; run_load_test_example"
|
||||
```
|
||||
|
||||
Running this example will deploy a cluster with the following configuration:
|
||||
|
||||
* Apache web server
|
||||
* Standard_DS2_v2 Azure VM SKU
|
||||
* mysql database (with 200 DTU and 125GB DB size)
|
||||
* NFS file share (with 2 disks and 128GB disk size each)
|
||||
* uses your SSH pub key in `~/.ssh/id_rsa`
|
||||
|
||||
[NOTE ON SSH KEYS] Ensure your `~/.ssh/id_rsa` has been added to ssh-agent using `eval $(ssh-agent)` and `ssh-add`).
|
||||
|
||||
Once the Moodle cluster is deployed and configured with course and
|
||||
student data (using [moosh](https://moosh-online.com/) it will run the
|
||||
synthetic workload with designated number of concurrent threads (in
|
||||
the example we use 1600 thread) for the designated duration and rampup
|
||||
time (18000 seconds = 5 hours duration, 4800 seconds rampup time in
|
||||
the example).
|
||||
|
||||
## Test plans
|
||||
|
||||
We'd like to offer test plans that are as realistic as possible, so that potential
|
||||
Moodle users on Azure can have better confidence with their Moodle deployment on Azure.
|
||||
We are just starting out in that direction and here are descriptions of currently
|
||||
available test plans.
|
||||
|
||||
### Simple Scenario [simple-test-1.jmx](./simple-test-1.jmx)
|
||||
|
||||
This test plan is a simple scenario that performs the following operations repeatedly:
|
||||
|
||||
* Login to the Moodle site
|
||||
* View the test course
|
||||
* View any resource if any
|
||||
* View a forum in the test course
|
||||
* View any forum discussion
|
||||
* Post a new discussion topic
|
||||
* Take a quiz and submit
|
||||
|
||||
The scripts in [loadtest.sh](./loadtest.sh) are tailored for this test plan.
|
||||
|
||||
### Moodle Data Stress Testing [simple-test-2.jmx](./simple-test-2.jmx)
|
||||
|
||||
Currently [loadtest.sh](./loadtest.sh) doesn't have any tailored scripts for this
|
||||
test plan. Therefore, this test plan will need to be executed by issuing the
|
||||
actual jmeter command with properly modified parameters manually, or it'd be
|
||||
greatly appreciated if someone can contribute better support for this test plan
|
||||
in [loadtest.hs](./loadtest.sh).
|
||||
|
||||
The purpose of this test plan is to try stressing the moodledata directory
|
||||
in a shared file system (either a gluster volume or an NFS share, depending
|
||||
on the choice). Initially attaching a random file in a forum discussion post
|
||||
was tried, but for some reason (probably due to my lack of understanding
|
||||
in PHP/web interaction), files were not attached. I instead tried to upload
|
||||
random files to each test Moodle users's Private Files area, and it did work.
|
||||
This test plan basically performs the following operations repeatedly:
|
||||
|
||||
* Login to the Moodle site
|
||||
* Open the Moodle user's Private Files repository
|
||||
* Upload a randomly generated file (of a random size within a hard-coded range)
|
||||
* Save the change
|
||||
|
||||
This way, we were able to populate the shared moodledata directory with
|
||||
random files in Moodle users' Private Files repositories. The mechanism
|
||||
to generate random files is not so efficient, so that's currently what
|
||||
slows down the upload speed, and any improvement in that BeanShell preprocessor
|
||||
code would be great. Note that the uploaded files have to be different.
|
||||
Moodle seems so good at deduplicating that a single file uploaded multiple
|
||||
times by different users won't increase the file system usage beyond its
|
||||
single copy.
|
||||
|
||||
It'd be also great if we add a download operation step in the test plan,
|
||||
and it's left as a future work item.
|
||||
|
||||
### Latency-Sensitive Stress Testing [time-gated-exam-test.jmx](./time-gated-exam-test.jmx)
|
||||
|
||||
This test stresses the deployed Moodle cluster with 1000 emulated students
|
||||
trying to get in an exam (quiz) that's initially closed and will be opened
|
||||
at the designated exam start time (have to be manually set on the test course's
|
||||
corresponding quiz's Settings). Once the exam start time passes, each emulated
|
||||
student continues taking the exam for 10 times.
|
||||
|
||||
This test has been used to find out how responsive
|
||||
a deployed Moodle cluster can be on very latency-sensitive workloads. We've been
|
||||
using this test with different file server types to find out which file server
|
||||
type offers best response times.
|
||||
|
||||
## Please contribute
|
||||
|
||||
It'd be great if we have more test plans, and make other parameters configurable (for
|
||||
example, make the auto-scaling thresholds configurable, which actually requires
|
||||
some changes in the templates as well). The currently available test plans
|
||||
also have hard-coded database type (JDBC connection string) that won't work
|
||||
for Postgres SQL server, so making it work would be also greatly appreciated.
|
||||
Also, if you run this load test with any parameters, it'd be great to share
|
||||
the numeric results so that we can have more performance data on various
|
||||
configurations. Here is [a link to an Excel spreadsheet](https://1drv.ms/x/s!Aj6KpM6lFGAjgd4D6IV8_6M42q9omA)
|
||||
where anyone can share their load testing results.
|
||||
|
||||
## Acknowledgement
|
||||
|
||||
The original test course and the test plan were generously provided by
|
||||
[Catalyst](https://github.com/catalyst) as part of this template modernization
|
||||
project. jMeter is a great load testing tool, and also thanks to [moosh](http://moosh-online.com/),
|
||||
the whole process could be automated without too much difficulty, which was
|
||||
really nice.
|
|
@ -1,16 +0,0 @@
|
|||
{
|
||||
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
|
||||
"contentVersion": "1.0.0.0",
|
||||
"parameters": {
|
||||
"autoscaleVmSku": { "value": "__WEB_VM_SKU__" },
|
||||
"dbServerType": { "value": "__DB_SERVER_TYPE__" },
|
||||
"mysqlPgresVcores": { "value": 2 },
|
||||
"mysqlPgresStgSizeGB": { "value": 125 },
|
||||
"webServerType": { "value": "__WEB_SERVER_TYPE__" },
|
||||
"fileServerType": { "value": "__FILE_SERVER_TYPE__" },
|
||||
"fileServerDiskCount": { "value": 2 },
|
||||
"fileServerDiskSize": { "value": 128 },
|
||||
"redisDeploySwitch": { "value": false },
|
||||
"sshPublicKey": { "value": "__SSH_PUB_KEY__" }
|
||||
}
|
||||
}
|
|
@ -1,326 +0,0 @@
|
|||
#!/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 http://www-us.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)
|
||||
echo "deb [arch=amd64] https://packages.microsoft.com/repos/azure-cli/ $az_repo main" | sudo tee /etc/apt/sources.list.d/azure-cli.list
|
||||
sudo apt-key adv --keyserver packages.microsoft.com --recv-keys 52E16F86FEE04B979B07E28DB02C46DF417A0893
|
||||
sudo apt-get install -y apt-transport-https || return 1
|
||||
sudo apt-get update && sudo apt-get install -y 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 trusty main'
|
||||
sudo apt-get update || true
|
||||
sudo apt-get install -y --allow-unauthenticated 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
|
||||
}
|
Двоичные данные
loadtest/moodle-on-azure-test-course-1.mbz
Двоичные данные
loadtest/moodle-on-azure-test-course-1.mbz
Двоичный файл не отображается.
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Загрузка…
Ссылка в новой задаче