Merge branch 'hs-loadtest' into pr-arm-best-practices

This commit is contained in:
Hosung Song 2018-02-23 11:53:30 -08:00
Родитель 358c8d7a2e d1c4c4b1e9
Коммит f1b6a509c5
33 изменённых файлов: 4610 добавлений и 3267 удалений

7
.gitignore поставляемый
Просмотреть файл

@ -99,3 +99,10 @@ ENV/
# mypy
.mypy_cache/
# test outputs
loadtest/test_outputs/
# Emacs
*#*#

Просмотреть файл

@ -8,7 +8,7 @@ Once you have an Azure account you can deploy Moodle via the Azure
portal using the button below, or you can [deploy Moodle via the
CLI](docs/Deploy.md).
[![Deploy to Azure](http://azuredeploy.net/deploybutton.png)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2FMoodle%2Fmaster%2Fazuredeploy.json) [![Visualize](https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/1-CONTRIBUTION-GUIDE/images/visualizebutton.png)](http://armviz.io/#/?load=https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2FMoodle%2Fmaster%2Fazuredeploy.json)
[![Deploy to Azure](http://azuredeploy.net/deploybutton.png)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2FMoodle%2Fhs-loadtest%2Fazuredeploy.json) [![Visualize](https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/1-CONTRIBUTION-GUIDE/images/visualizebutton.png)](http://armviz.io/#/?load=https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2FMoodle%2Fhs-loadtest%2Fazuredeploy.json)
## What this stack will give you

Просмотреть файл

@ -2,6 +2,20 @@
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"_artifactsLocation": {
"type": "string",
"metadata": {
"description": "The base URI where artifacts required by this template are located. When the template is deployed using the accompanying scripts, a private location in the subscription will be used and this value will be automatically generated."
},
"defaultValue": "https://raw.githubusercontent.com/Azure/Moodle/hs-loadtest/"
},
"_artifactsLocationSasToken": {
"type": "securestring",
"metadata": {
"description": "The sasToken required to access _artifactsLocation. When the template is deployed using the accompanying scripts, a sasToken will be automatically generated."
},
"defaultValue": ""
},
"applyScriptsSwitch": {
"defaultValue": true,
"metadata": {
@ -16,6 +30,13 @@
},
"type": "bool"
},
"vnetGwDeploySwitch": {
"defaultValue": false,
"metadata": {
"description": "Switch to deploy a virtual network gateway or not"
},
"type": "bool"
},
"installO365pluginsSwitch": {
"defaultValue": false,
"metadata": {
@ -30,16 +51,15 @@
},
"type": "bool"
},
"blobStorageAccountType": {
"storageAccountType": {
"defaultValue": "Standard_LRS",
"allowedValues": [
"Standard_LRS",
"Standard_GRS",
"Standard_ZRS",
"Premium_LRS"
"Standard_ZRS"
],
"metadata": {
"description": "Blob Storage Account type"
"description": "Storage Account type"
},
"type": "string"
},
@ -54,6 +74,17 @@
},
"type": "string"
},
"fileServerType": {
"defaultValue": "gluster",
"allowedValues": [
"gluster",
"nfs"
],
"metadata": {
"description": "File server type: GlusterFS, Azure Files (CIFS)--disabled due to too slow perf, NFS--not highly available"
},
"type": "string"
},
"webServerType": {
"defaultValue": "apache",
"allowedValues": [
@ -128,17 +159,19 @@
},
"type": "string"
},
"glusterDiskSize": {
"fileServerDiskSize": {
"defaultValue": 127,
"metadata": {
"description": "Size per disk for gluster nodes"
"description": "Size per disk for gluster nodes or nfs server"
},
"type": "int"
},
"glusterDiskCount": {
"fileServerDiskCount": {
"defaultValue": 4,
"minValue": 2,
"maxValue": 8,
"metadata": {
"description": "Number of disks in raid0 per gluster node"
"description": "Number of disks in raid0 per gluster node or nfs server"
},
"type": "int"
},
@ -324,7 +357,7 @@
}
},
"templateLink": {
"uri": "[concat(variables('moodleCommon').baseTemplateUrl, parameters('dbServerType'), '.json')]"
"uri": "[concat(variables('moodleCommon').baseTemplateUrl, parameters('dbServerType'), '.json', parameters('_artifactsLocationSasToken'))]"
}
},
"type": "Microsoft.Resources/deployments"
@ -341,7 +374,7 @@
}
},
"templateLink": {
"uri": "[concat(variables('moodleCommon').baseTemplateUrl,'recoveryservices.json')]"
"uri": "[concat(variables('moodleCommon').baseTemplateUrl,'recoveryservices.json',parameters('_artifactsLocationSasToken'))]"
}
},
"type": "Microsoft.Resources/deployments"
@ -360,7 +393,7 @@
}
},
"templateLink": {
"uri": "[concat(variables('moodleCommon').baseTemplateUrl,'redis.json')]"
"uri": "[concat(variables('moodleCommon').baseTemplateUrl,'redis.json',parameters('_artifactsLocationSasToken'))]"
}
},
"type": "Microsoft.Resources/deployments"
@ -376,7 +409,7 @@
}
},
"templateLink": {
"uri": "[concat(variables('moodleCommon').baseTemplateUrl,'network.json')]"
"uri": "[concat(variables('moodleCommon').baseTemplateUrl,'network.json',parameters('_artifactsLocationSasToken'))]"
}
},
"type": "Microsoft.Resources/deployments"
@ -397,12 +430,13 @@
}
},
"templateLink": {
"uri": "[concat(variables('moodleCommon').baseTemplateUrl,'elastic.json')]"
"uri": "[concat(variables('moodleCommon').baseTemplateUrl,'elastic.json',parameters('_artifactsLocationSasToken'))]"
}
},
"type": "Microsoft.Resources/deployments"
},
{
"condition": "[equals(parameters('fileServerType'),'gluster')]",
"apiVersion": "2015-01-01",
"dependsOn": [
"Microsoft.Resources/deployments/networkTemplate",
@ -417,7 +451,7 @@
}
},
"templateLink": {
"uri": "[concat(variables('moodleCommon').baseTemplateUrl,'gluster.json')]"
"uri": "[concat(variables('moodleCommon').baseTemplateUrl,'gluster.json',parameters('_artifactsLocationSasToken'))]"
}
},
"type": "Microsoft.Resources/deployments"
@ -429,7 +463,7 @@
"Microsoft.Resources/deployments/glusterTemplate",
"Microsoft.Resources/deployments/recoveryTemplate",
"Microsoft.Resources/deployments/redisTemplate",
"Microsoft.Resources/deployments/blobStorageAccountTemplate"
"Microsoft.Resources/deployments/storageAccountTemplate"
],
"name": "controllerTemplate",
"properties": {
@ -438,15 +472,15 @@
"moodleCommon": {
"value": "[variables('moodleCommon')]"
},
"blobStorageAccountKey": {
"value": "[reference('blobStorageAccountTemplate').outputs.blobStorageAccountKey.value]"
"storageAccountKey": {
"value": "[reference('storageAccountTemplate').outputs.storageAccountKey.value]"
},
"redisPrimaryKey": {
"value": "[reference('redisTemplate').outputs.redisPrimaryKey.value]"
}
},
"templateLink": {
"uri": "[concat(variables('moodleCommon').baseTemplateUrl,'controller.json')]"
"uri": "[concat(variables('moodleCommon').baseTemplateUrl,'controller.json',parameters('_artifactsLocationSasToken'))]"
}
},
"type": "Microsoft.Resources/deployments"
@ -464,17 +498,20 @@
"parameters": {
"moodleCommon": {
"value": "[variables('moodleCommon')]"
},
"storageAccountKey": {
"value": "[reference('storageAccountTemplate').outputs.storageAccountKey.value]"
}
},
"templateLink": {
"uri": "[concat(variables('moodleCommon').baseTemplateUrl,'webvmss.json')]"
"uri": "[concat(variables('moodleCommon').baseTemplateUrl,'webvmss.json',parameters('_artifactsLocationSasToken'))]"
}
},
"type": "Microsoft.Resources/deployments"
},
{
"apiVersion": "2015-01-01",
"name": "blobStorageAccountTemplate",
"name": "storageAccountTemplate",
"properties": {
"mode": "Incremental",
"parameters": {
@ -483,7 +520,7 @@
}
},
"templateLink": {
"uri": "[concat(variables('moodleCommon').baseTemplateUrl,'blobStorageAccount.json')]"
"uri": "[concat(variables('moodleCommon').baseTemplateUrl,'storageAccount.json',parameters('_artifactsLocationSasToken'))]"
}
},
"type": "Microsoft.Resources/deployments"
@ -518,6 +555,14 @@
"type": "string",
"value": "[variables('moodleCommon').moodleAdminPass]"
},
"moodleDbUsername": {
"type": "string",
"value": "[variables('moodleCommon').moodleDbUserAzure]"
},
"moodleDbPassword": {
"type": "string",
"value": "[variables('moodleCommon').moodleDbPass]"
},
"loadBalancerDNS": {
"type": "string",
"value": "[variables('moodleCommon').lbDns]"
@ -536,15 +581,15 @@
"documentation10": " controller - creates a jumpbox and deploys code",
"documentation11": "GlusterFS Sizing guidance",
"moodleCommon": {
"baseTemplateUrl": "https://raw.githubusercontent.com/Azure/Moodle/master/nested/",
"scriptLocation": "https://raw.githubusercontent.com/Azure/Moodle/master/scripts/",
"baseTemplateUrl": "[concat(parameters('_artifactsLocation'), 'nested/')]",
"scriptLocation": "[concat(parameters('_artifactsLocation'), 'scripts/')]",
"artifactsSasToken": "[parameters('_artifactsLocationSasToken')]",
"applyScriptsSwitch": "[parameters('applyScriptsSwitch')]",
"autoscaleVmCount": "[parameters('autoscaleVmCount')]",
"autoscaleVmSku": "[parameters('autoscaleVmSku')]",
"azureBackupSwitch": "[parameters( 'azureBackupSwitch')]",
"blobStorageAccountName": "[tolower(concat('abs',variables('resourceprefix')))]",
"blobStorageAccountType": "[parameters('blobStorageAccountType')]",
"commonFunctionsScriptUri": "[concat(parameters('_artifactsLocation'),'scripts/helper_functions.sh',parameters('_artifactsLocationSasToken'))]",
"computeApi": "2016-04-30-preview",
"controllerVmSku": "[parameters('controllerVmSku')]",
"dbLogin": "[parameters('dbLogin')]",
@ -569,6 +614,9 @@
"extFeName": "[concat('lb-frontend-',variables('resourceprefix'))]",
"extNatPool": "[concat('lb-natpool-',variables('resourceprefix'))]",
"extProbe": "[concat('lb-probe-',variables('resourceprefix'))]",
"fileServerDiskCount": "[parameters('fileServerDiskCount')]",
"fileServerDiskSize": "[parameters('fileServerDiskSize')]",
"fileServerType": "[parameters('fileServerType')]",
"firewallRuleName": "[parameters('firewallRuleName')]",
"gatewayName": "[concat('vnet-gateway-',variables('resourceprefix'))]",
"gatewayPublicIPName": "[concat('vnet-gw-ip-',variables('resourceprefix'))]",
@ -578,8 +626,6 @@
"gatewayType": "[parameters('gatewayType')]",
"gfsNameRoot": "[concat('gluster-vm-',variables('resourceprefix'))]",
"gfxAvailabilitySetName": "[concat('gluster-avset-',variables('resourceprefix'))]",
"glusterDiskCount": "[parameters('glusterDiskCount')]",
"glusterDiskSize": "[parameters('glusterDiskSize')]",
"glusterScriptFilename": "install_gluster.sh",
"glusterVmCount": 2,
"glusterVmSku": "[parameters('glusterVmSku')]",
@ -597,8 +643,7 @@
"moodleDbPass": "[concat('9#36^', substring(uniqueString(resourceGroup().id, deployment().name), 5, 8), toUpper('ercq'))]",
"moodleDbUser": "moodle",
"moodleDbUserAzure": "[concat('moodle', '@', parameters('dbServerType'), '-', variables('resourceprefix'))]",
"moodleInstallScriptFilename": "[concat(parameters('dbServerType'), '_', 'install_moodle.sh')]",
"moodleSetupScriptFilename": "setup_moodle.sh",
"moodleInstallScriptFilename": "install_moodle.sh",
"moodleVersion": "[parameters('moodleVersion')]",
"mysqlVersion": "[parameters('mysqlVersion')]",
"osType": {
@ -623,6 +668,8 @@
"sshPublicKey": "[parameters('sshPublicKey')]",
"sshUsername": "[parameters('sshUsername')]",
"sslEnforcement": "[parameters('sslEnforcement')]",
"storageAccountName": "[tolower(concat('abs',variables('resourceprefix')))]",
"storageAccountType": "[parameters('storageAccountType')]",
"subnetElastic": "[concat('elastic-subnet-',variables('resourceprefix'))]",
"subnetElasticPrefix": "[concat( variables('octets')[0], '.', variables('octets')[1], '.', string(add(int(variables('octets')[2]),4)))]",
"subnetElasticRange": "[concat( variables('octets')[0], '.', variables('octets')[1], '.', string(add(int(variables('octets')[2]),4)), '.0/24')]",
@ -639,8 +686,10 @@
"vaultName": "[concat('vault-',variables('resourceprefix'))]",
"vmssName": "[concat('vmss-',variables('resourceprefix'))]",
"vmssdStorageAccounttName": "[concat('vmss',uniqueString(resourceGroup().id))]",
"vnetGwDeploySwitch": "[parameters('vnetGwDeploySwitch')]",
"vnetName": "[concat('vnet-',variables('resourceprefix'))]",
"vpnType": "[parameters('vpnType')]",
"webServerSetupScriptFilename": "setup_webserver.sh",
"webServerType": "[parameters('webServerType')]"
},
"octets": "[split(parameters('vNetAddressSpace'), '.')]",

Просмотреть файл

@ -5,13 +5,13 @@
"autoscaleVmCount": { "value": 10 },
"autoscaleVmSku": { "value": "Standard_DS2_v2" },
"azureBackupSwitch": { "value": true },
"blobStorageAccountType": { "value": "Standard_LRS"},
"storageAccountType": { "value": "Standard_LRS"},
"controllerVmSku": { "value": "Standard_DS1_v2" },
"dbServerType": { "value": "mysql" },
"webServerType": { "value": "apache" },
"elasticVmSku": { "value": "Standard_DS2_v2" },
"glusterDiskCount": { "value": 4 },
"glusterDiskSize": { "value": 127 },
"fileServerDiskCount": { "value": 4 },
"fileServerDiskSize": { "value": 127 },
"glusterVmSku": { "value": "Standard_DS2_v2" },
"moodleVersion": { "value": "MOODLE_34_STABLE" },
"mysqlVersion": { "value": "5.7" },

22
docs/Cleanup.md Normal file
Просмотреть файл

@ -0,0 +1,22 @@
# Cleanup All Resource
To cleanup a Moodle deployment simply delete the Resource Group that
contains it. The commands below will iterate over your workspace
directory and delete all deployments.
## Prerequisites
First we need to ensure our [environment variables](./Environment-Variables.md) are correctly configured.
## Remove each resource group
This command will delete all resources in *all* resource groups. Run
with caution.
Note, that this command will not fully delete the resource group if
you have Azure Backup enabled since the Recovery Services Vault will
not be deleted (it's got the backups of you data!).
``` bash
for filename in $MOODLE_AZURE_WORKSPACE/*; do az group delete --yes --name $(basename $filename) --no-wait; done
```

Просмотреть файл

@ -1,8 +0,0 @@
# Delete a Moodle Cluster
If you want to remove all resources associated with a Moodle Cluster
simply delete the assocaited resource group as follows:
```
az group delete --name $MOODLE_RG_NAME
```

Просмотреть файл

@ -9,26 +9,9 @@ install.
## Prerequisites
You will need a local copy of the Moodle ARM templates. These are
published on GitHub so you should clone them locally (possibly after
forking them on GitHub).
To make things consitent across different sessions managing Moodle we
should [configure the environment](./Preparation.md).
## Configuration
We will use a number of environment variables to configure our
deployment. To customize them for your environment copy `env.json`
into `env.local.json` and edit the contents accordingly. The values
set within that file are:
``` shell
TIME=$(date +%s)
MOODLE_RG_NAME=moodle_$TIME
MOODLE_RG_LOCATION=southcentralus
MOODLE_DEPLOYMENT_NAME="MasterDeploy"
echo "Resource Group Name : $MOODLE_RG_NAME"
echo "Resource Group Location : $MOODLE_RG_LOCATION"
echo "Deployment Name : $MOODLE_DEPLOYMENT_NAME"
```
## Create Resource Group
@ -56,7 +39,7 @@ Results:
}
```
## Create Azure Deployment Paramaters
## Create Azure Deployment Parameters
Your deployment will be configured using an
`azuredeploy.parameters.json` file. It is possible to provide these
@ -72,7 +55,11 @@ proceed with the defaults, but there is one value, the `sshPublicKey`
that **must** be provided. To automatically add your default SSH key
(in Bash) use the following command:
FIXME: sed command to add SSH key
``` bash
ssh_pub_key=`cat $MOODLE_SSH_KEY_FILENAME.pub`
echo $ssh_pub_key
sed "s|GEN-SSH-PUB-KEY|$ssh_pub_key|g" $MOODLE_AZURE_WORKSPACE/arm_template/azuredeploy.parameters.json > $MOODLE_AZURE_WORKSPACE/$MOODLE_RG_NAME/azuredeploy.parameters.json
```
## Deploy cluster
@ -80,7 +67,7 @@ Now that we have a resource group and a configuration file we can
create the cluster itself. This is done with a single command:
```
az group deployment create --name $MOODLE_DEPLOYMENT_NAME --resource-group $MOODLE_RG_NAME --template-file ../azuredeploy.json --parameters azuredeploy.parameters.json
az group deployment create --name $MOODLE_DEPLOYMENT_NAME --resource-group $MOODLE_RG_NAME --template-file $MOODLE_AZURE_WORKSPACE/arm_template/azuredeploy.json --parameters $MOODLE_AZURE_WORKSPACE/$MOODLE_RG_NAME/azuredeploy.parameters.json
```
## Using the created stack

Просмотреть файл

@ -0,0 +1,43 @@
# Environment Variables
In order to configure our deployment and tools we'll set up some
environment variables to ensure consistency. If you are running these
scripts through SimDem you can customize these values by copying and
editing `env.json` into `env.local.json`.
We'll need a unique name for our Resource Group in Azure, but when
running in an automated mode it is useful to have a (mostly) unique
name for your deployment and related resources. We'll use a timestamp.
If the environmnt variable `MOODLE_RG_NAME` is not set we will
create a new value using a timestamp:
``` shell
if [ -z "$MOODLE_RG_NAME" ]; then MOODLE_RG_NAME=moodle_$(date +%Y-%m-%d-%H); fi
echo "Resource Group Name : $MOODLE_RG_NAME"
```
Other configurable values for our Azure deployment include the
location and depoloyment name. We'll standardize these, but you can
use different values if you like.
``` shell
MOODLE_RG_LOCATION=southcentralus
MOODLE_DEPLOYMENT_NAME=MasterDeploy
```
We also need to provide an SSH key. Later we'll generate this if it
doesn't already exist but to enable us to reuse an existing key we'll
store it's filename in an Environment Variable.
``` shell
MOODLE_SSH_KEY_FILENAME=~/.ssh/moodle_id_rsa
```
We need a workspace for storing configuration files and other
per-deployment artifacts:
``` shell
MOODLE_AZURE_WORKSPACE=~/.moodle
```

Просмотреть файл

@ -6,6 +6,11 @@ are available in the portal, but in this document we will retrieve
them using the AZ command line tools and through the AZ CLI tool. This
document describes the available parameters and how to retrieve them.
## Prerequisites
In order to configure our deployment and tools we'll set up some
[environment variables](./Environment-Variables.md) to ensure consistency.
## Output Paramater Overview
The available output parameters are:

Просмотреть файл

@ -5,6 +5,9 @@ management tasks on a scalable Moodle cluster on Azure.
## Prerequisites
In order to configure our deployment and tools we'll set up some
[environment variables](./Environment-Variables.md) to ensure consistency.
In order to manage a cluster it is clearly necessary to first [deploy
a scalable Moodle cluster on Azure](./Deploy.md).

56
docs/Preparation.md Normal file
Просмотреть файл

@ -0,0 +1,56 @@
# Environment Preparation
This document describes how to ensure your environment is configured
for working with Moodle on Azure.
## Prerequisites
In order to configure our deployment and tools we'll set up some
[environment variables](./Environment-Variables.md) to ensure consistency.
## Required software
We'll use a number of tools when working with Moodle on Azure. Let's
ensure they are all installed:
``` shell
sudo apt-get update
sudo apt-get install wget -y
sudo apt-get openssh-client -y
```
The [Azure CLI](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli-apt?view=azure-cli-latest) is also important:
```bash
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 apt-transport-https
sudo apt-get update && sudo apt-get install azure-cli
```
## Ensure we have a valid SSH key pair
We use SSH for secure communication with our hosts. The following line
will check there is a valid SSH key available and, if not, create one.
```
if [ ! -f "$MOODLE_SSH_KEY_FILENAME" ]; then ssh-keygen -t rsa -N "" -f $MOODLE_SSH_KEY_FILENAME; fi
```
## Create Workspace
Ensure the workspace for this particular deployment exists:
```
mkdir -p $MOODLE_AZURE_WORKSPACE/$MOODLE_RG_NAME
```
## Checkout the Moodle ARM Template
The Moodle Azure Resource Manager template is hosted on GitHub. We'll
checkout the template into our workspace.
```
git clone git@github.com:Azure/Moodle.git $MOODLE_AZURE_WORKSPACE/arm_template
```

Просмотреть файл

@ -1,27 +0,0 @@
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"autoscaleVmCount": { "value": 10 },
"autoscaleVmSku": { "value": "Standard_DS2_v2" },
"azureBackupSwitch": { "value": true },
"blobStorageAccountType": { "value": "Standard_LRS"},
"controllerVmSku": { "value": "Standard_DS1_v2" },
"dbServerType": { "value": "mysql" },
"webServerType": { "value": "apache" },
"elasticVmSku": { "value": "Standard_DS2_v2" },
"glusterDiskCount": { "value": 4 },
"glusterDiskSize": { "value": 127 },
"glusterVmSku": { "value": "Standard_DS2_v2" },
"moodleVersion": { "value": "MOODLE_34_STABLE" },
"mysqlVersion": { "value": "5.7" },
"postgresVersion": { "value": "9.6" },
"siteURL": { "value": "www.example.org" },
"skuCapacityDTU": { "value": 50 },
"skuName": { "value": "MYSQLB50" },
"skuSizeMB": { "value": 51200 },
"skuTier": { "value": "Basic" },
"vNetAddressSpace": { "value": "172.31.0.0" },
"sshPublicKey": { "value": "GEN-SSH-PUB-KEY" }
}
}

7
etc/changeBranchInURL.sh Normal file
Просмотреть файл

@ -0,0 +1,7 @@
#!/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

73
loadtest/README.md Normal file
Просмотреть файл

@ -0,0 +1,73 @@
# Load-Testing Deployed Moodle Cluster
This directory currently contains utility scripts, a Moodle test course,
and a jMeter test plan that can be used to load-test a Moodle cluster
that's deployed on Azure using the templates in this repo.
## Setting up the test host
To run load tests using the resources in this directory, you'll want to spin up
an Ubuntu 16.04 Linux VM on your Azure subscription and an Azure location where
you'll be deploying your Moodle cluster (so that test traffic can be from the
same Azure region to avoid egress charges). Once your Ubuntu 16.04 Linux VM is
ready, you need to install Java and [jMeter](https://jmeter.apache.org/).
You also need the [Azure CLI](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest)
installed on your Ubuntu 16.04 Linux VM (let's call it the jMeter host) for
necessary Azure operations (deployment, metadata retrieval).
These dependencies can be installed using the included utility scripts as follows:
```
$ cd [local_repo]/loadtest
$ . loadtest.sh
$ install_java_and_jmeter
$ install_az_cli
```
Steps above need to be performed only once.
## Deploying Moodle using templates and running load test
Once dependencies are installed, you can initiate the whole process of a load
testing process using included utility scripts,
starting from a whole Moodle cluter template deployment, setting up the test course
and enrolling students on the Moodle host, and running the synthetic test workload
using jMeter. See the included example `run_load_test_example` that's as follows:
```
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/hs-loadtest/azuredeploy.json azuredeploy.parameters.loadtest.defaults.json apache Standard_DS2_v2 mysql 200 125 nfs 2 128 "$(cat ~/.ssh/authorized_keys)" 1600 4800 18000
}
```
Running the script function above will deploy the templates with 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), using your SSH pub key in
your home directory (make sure to copy the corresponding SSH private key as
`~/.ssh/id_rsa` and have it added to ssh-agent using `eval $(ssh-agent)` and
`ssh-add`). Once the template deployment is successfully completed, the script
will configure the deployed Moodle server with a test course and test students
(installing/running [moosh](https://moosh-online.com/) on the Moodle host over ssh),
and finally run the synthetic workload with designated number of concurrent threads
(1600 above) and the time duration of the simulation run (18000 seconds=5 hours, and
4800 seconds rampup time---make sure to give a sufficient rampup time for the number
of concurrent threads).
## Please contribute!
It'd be great if we have other test plans (like uploading files populating the
`moodledata` directory intensely), 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 plan
also has 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,
the whole process could be automated without too much difficulty, which was
really nice.

Просмотреть файл

@ -0,0 +1,16 @@
{
"$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__" },
"skuCapacityDTU": { "value": 100 },
"skuName": { "value": "__DB_SKU_NAME__" },
"skuSizeMB": { "value": 128 },
"webServerType": { "value": "__WEB_SERVER_TYPE__" },
"fileServerType": { "value": "__FILE_SERVER_TYPE__" },
"fileServerDiskCount": { "value": 2 },
"fileServerDiskSize": { "value": 128 },
"sshPublicKey": { "value": "__SSH_PUB_KEY__" }
}
}

315
loadtest/loadtest.sh Normal file
Просмотреть файл

@ -0,0 +1,315 @@
#!/bin/bash
# This is not tested myself. Just documenting what's needed.
function install_java_and_jmeter
{
sudo apt update
sudo apt install -y openjdk-8-jdk
wget -O apache-jmeter-4.0.tgz http://www-us.apache.org/dist//jmeter/binaries/apache-jmeter-4.0.tgz
tar xfz apache-jmeter-4.0.tgz
mkdir -p ~/bin/jmeter
ln -s apache-jmeter-4.0/bin/jmeter ~/bin/jmeter
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
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
mv postgres-42.2.1.jar apache-jmeter-4.0/lib
}
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
sudo apt-get update && sudo apt-get install -y azure-cli
}
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 dtu=${1}
local size=${2}
if [ "$dtu" != 100 -a "$dtu" != 200 -a "$dtu" != 400 -a "$dtu" != 800 ]; then
echo "Invalid DTU ($dtu). Only allowed are 100, 200, 400, 800."
return 1
fi
if [ "$size" != 125 ] && [ "$size" != 250 ] && [ "$size" != 375 ] && [ "$size" != 500 ] && [ "$size" != 625 ] && [ "$size" != 750 ] && [ "$size" != 875 ] && [ "$size" 1000 ]; then
echo "Invalid DB size ($size). Only allowed are 125, 250, 375, ... 875, 1000."
return 1
fi
}
function get_db_sku_name
{
local db_server_type=${1}
local db_dtu=${2}
if [ "$db_server_type" = mysql ]; then
echo "MYSQLS${db_dtu}"
elif [ "$db_server_type" = postgres ]; then
echo "PGSQLS${db_dtu}"
else
echo "Invalid DB type ($db_server_type). Only mysql or postgres are allowed"
return 1
fi
}
# TODO hard-coded Azure location in global variable. Parametrize this later.
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_dtu=${7} # 100, 200, 400, 800 only
local db_size=${8} # 125, 250, 375, 500, 625, 750, 875. 1000 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 ssh_pub_key=${12} # Your ssh authorized_keys content
local no_wait_flag=${13} # Must be "--no-wait" to be passed to az
check_db_sku_params $db_dtu $db_size || return 1
local db_sku_name=$(get_db_sku_name $db_server_type $db_dtu) || return 1
local db_size_mb=$(($db_size * 1024))
local cmd="az group create --resource-group $resource_group --location $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 skuCapacityDTU=$db_dtu skuName=$db_sku_name skuSizeMB=$db_size_mb fileServerType=$file_server_type fileServerDiskCount=$file_server_disk_count fileServerDiskSize=$file_server_disk_size 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
{
sudo apt update
sudo apt install -y composer
cd ~
git clone git://github.com/tmuras/moosh.git
cd moosh
composer install
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 ~/bin/moosh --moodle-path=$MOODLE_PATH course-delete $course_id
}
function create_course
{
local course_id=${1}
sudo -u www-data ~/bin/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 ~/bin/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 ~/bin/moosh --moodle-path=$MOODLE_PATH user-create -p $password m_azuretestuser_{1..200}
sudo -u www-data ~/bin/moosh --moodle-path=$MOODLE_PATH user-create -p $password m_azuretestuser_{201..400}
sudo -u www-data ~/bin/moosh --moodle-path=$MOODLE_PATH user-create -p $password m_azuretestuser_{401..600}
sudo -u www-data ~/bin/moosh --moodle-path=$MOODLE_PATH user-create -p $password m_azuretestuser_{601..800}
sudo -u www-data ~/bin/moosh --moodle-path=$MOODLE_PATH user-create -p $password m_azuretestuser_{801..1000}
sudo -u www-data ~/bin/moosh --moodle-path=$MOODLE_PATH user-create -p $password m_azuretestuser_{1001..1200}
sudo -u www-data ~/bin/moosh --moodle-path=$MOODLE_PATH user-create -p $password m_azuretestuser_{1201..1400}
sudo -u www-data ~/bin/moosh --moodle-path=$MOODLE_PATH user-create -p $password m_azuretestuser_{1401..1600}
sudo -u www-data ~/bin/moosh --moodle-path=$MOODLE_PATH user-create -p $password m_azuretestuser_{1601..1800}
sudo -u www-data ~/bin/moosh --moodle-path=$MOODLE_PATH user-create -p $password m_azuretestuser_{1801..2000}
sudo -u www-data ~/bin/moosh --moodle-path=$MOODLE_PATH course-enrol $course_id m_azuretestuser_{1..200}
sudo -u www-data ~/bin/moosh --moodle-path=$MOODLE_PATH course-enrol $course_id m_azuretestuser_{201..400}
sudo -u www-data ~/bin/moosh --moodle-path=$MOODLE_PATH course-enrol $course_id m_azuretestuser_{401..600}
sudo -u www-data ~/bin/moosh --moodle-path=$MOODLE_PATH course-enrol $course_id m_azuretestuser_{601..800}
sudo -u www-data ~/bin/moosh --moodle-path=$MOODLE_PATH course-enrol $course_id m_azuretestuser_{801..1000}
sudo -u www-data ~/bin/moosh --moodle-path=$MOODLE_PATH course-enrol $course_id m_azuretestuser_{1001..1200}
sudo -u www-data ~/bin/moosh --moodle-path=$MOODLE_PATH course-enrol $course_id m_azuretestuser_{1201..1400}
sudo -u www-data ~/bin/moosh --moodle-path=$MOODLE_PATH course-enrol $course_id m_azuretestuser_{1401..1600}
sudo -u www-data ~/bin/moosh --moodle-path=$MOODLE_PATH course-enrol $course_id m_azuretestuser_{1601..1800}
sudo -u www-data ~/bin/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 ~/bin/moosh --moodle-path=$MOODLE_PATH block-manage hide myoverview
}
# TODO hard-coded values...
LOADTEST_BASE_URI=https://raw.githubusercontent.com/Azure/Moodle/hs-loadtest/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_dtu=${8}
local db_size=${9}
local file_server_type=${10}
local file_server_disk_count=${11}
local file_server_disk_size=${12}
local ssh_pub_key=${13}
local test_threads_count=${14}
local test_rampup_time_sec=${15}
local test_run_time_sec=${16}
local delete_resource_group_flag=${17} # Any non-empty string is considered true
LOCATION=$location
deploy_moodle_with_some_parameters $resource_group $template_url $parameters_template_file $web_server_type $web_vm_sku $db_server_type $db_dtu $db_size $file_server_type $file_server_disk_count $file_server_disk_size "$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/hs-loadtest/azuredeploy.json azuredeploy.parameters.loadtest.defaults.json apache Standard_DS2_v2 mysql 200 125 nfs 2 128 "$(cat ~/.ssh/authorized_keys)" 1600 4800 18000
}

Двоичные данные
loadtest/moodle-on-azure-test-course-1.mbz Normal file

Двоичный файл не отображается.

2552
loadtest/simple-test-1.jmx Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -8,7 +8,7 @@
},
"type": "object"
},
"blobStorageAccountKey": {
"storageAccountKey": {
"metadata": {
"description": "Key used to create a storage container"
},
@ -107,10 +107,54 @@
},
"type": "Microsoft.Network/networkInterfaces"
},
{
"condition": "[equals(parameters('moodleCommon').fileServerType,'nfs')]",
"apiVersion": "[parameters('moodleCommon').computeApi]",
"copy": {
"count": "[parameters('moodleCommon').fileServerDiskCount]",
"name": "[variables('diskLoop')]"
},
"location": "[resourceGroup().location]",
"name": "[concat(variables('vmName'),'-datadisk',copyIndex(1))]",
"properties": {
"accountType": "Premium_LRS",
"creationData": {
"createOption": "Empty"
},
"diskSizeGB": "[parameters('moodleCommon').fileServerDiskSize]"
},
"tags": {
"displayName": "Gluster VM Data Disk"
},
"type": "Microsoft.Compute/disks"
},
{
"apiVersion": "2015-01-01",
"dependsOn": [
"[variables('diskLoop')]"
],
"name": "[concat(variables('vmName'),'-diskSelection')]",
"properties": {
"mode": "Incremental",
"parameters": {
"vmDiskCount": {
"value": "[parameters('moodleCommon').fileServerDiskCount]"
},
"vmName": {
"value": "[variables('vmName')]"
}
},
"templateLink": {
"uri": "[concat(parameters('moodleCommon').baseTemplateUrl,'diskSelection.json',parameters('moodleCommon').artifactsSasToken)]"
}
},
"type": "Microsoft.Resources/deployments"
},
{
"apiVersion": "[parameters('moodleCommon').computeApi]",
"dependsOn": [
"[concat('Microsoft.Network/networkInterfaces/', parameters('moodleCommon').jboxNicName)]"
"[concat('Microsoft.Network/networkInterfaces/', parameters('moodleCommon').jboxNicName)]",
"[concat('Microsoft.Resources/deployments/',concat(variables('vmName'),'-diskSelection'))]"
],
"location": "[resourceGroup().location]",
"name": "[parameters('moodleCommon').jboxVmName]",
@ -141,7 +185,7 @@
}
},
"storageProfile": {
"dataDisks": [],
"dataDisks": "[if(equals(parameters('moodleCommon').fileServerType,'nfs'), reference(concat(variables('vmName'),'-diskSelection')).outputs.dataDiskArray.value, reference(concat(variables('vmName'),'-diskSelection')).outputs.emptyDataDiskArray.value)]",
"imageReference": "[parameters('moodleCommon').osType]",
"osDisk": {
"createOption": "FromImage",
@ -153,7 +197,7 @@
}
},
"tags": {
"displayName": "Gluster Virtual Machine"
"displayName": "Jumpbox (controller) Virtual Machine"
},
"type": "Microsoft.Compute/virtualMachines"
},
@ -170,8 +214,8 @@
"moodleCommon": {
"value": "[parameters('moodleCommon')]"
},
"blobStorageAccountKey": {
"value": "[parameters('blobStorageAccountKey')]"
"storageAccountKey": {
"value": "[parameters('storageAccountKey')]"
},
"redisPrimaryKey": {
"value": "[parameters('redisPrimaryKey')]"
@ -179,7 +223,7 @@
},
"templateLink": {
"uri": "[concat(parameters('moodleCommon').baseTemplateUrl,'controllerconfig.json')]"
"uri": "[concat(parameters('moodleCommon').baseTemplateUrl,'controllerconfig.json',parameters('moodleCommon').artifactsSasToken)]"
}
},
"type": "Microsoft.Resources/deployments"
@ -202,7 +246,7 @@
}
},
"templateLink": {
"uri": "[concat(parameters('moodleCommon').baseTemplateUrl,'recoveryservicesEnlist.json')]"
"uri": "[concat(parameters('moodleCommon').baseTemplateUrl,'recoveryservicesEnlist.json',parameters('moodleCommon').artifactsSasToken)]"
}
},
"type": "Microsoft.Resources/deployments"
@ -220,6 +264,8 @@
"documentation09": "This sub-template calls other sub-templates",
"documentation10": " controllerconfig - conditionally applies post-deployment script on the VM",
"documentation18": " recoveryservicesEnlist - conditionally enlists the VM into the backup regimen",
"vmName": "[parameters('moodleCommon').jboxVmName]",
"diskLoop": "[concat(variables('vmName'),'-disk')]",
"nicRef": "[resourceId('Microsoft.Network/networkInterfaces', parameters('moodleCommon').jboxNicName)]",
"nsgRef": "[resourceId('Microsoft.Network/networkSecurityGroups', parameters('moodleCommon').jboxNsgName)]",
"pipRef": "[resourceId('Microsoft.Network/publicIPAddresses', parameters('moodleCommon').jboxPipName)]",

Просмотреть файл

@ -8,7 +8,7 @@
},
"type": "object"
},
"blobStorageAccountKey": {
"storageAccountKey": {
"metadata": {
"description": "Key used to create a storage container"
},
@ -31,7 +31,8 @@
"publisher": "Microsoft.Azure.Extensions",
"settings": {
"fileUris": [
"[variables('scriptUri')]"
"[variables('scriptUri')]",
"[parameters('moodleCommon').commonFunctionsScriptUri]"
]
},
"protectedSettings":{
@ -47,10 +48,10 @@
}
],
"variables": {
"cmdExec": "[concat('sh ', parameters('moodleCommon').moodleInstallScriptFilename, ' ', parameters('moodleCommon').moodleVersion, ' ', concat(parameters('moodleCommon').gfsNameRoot, '0'), ' ', 'data', ' ', parameters('moodleCommon').siteURL, ' ', concat(parameters('moodleCommon').dbServerType, '-', parameters('moodleCommon').resourcesPrefix, '.', parameters('moodleCommon').dbServerType, '.database.azure.com'), ' ', parameters('moodleCommon').moodleDbName, ' ', parameters('moodleCommon').moodleDbUser, ' ', parameters('moodleCommon').moodleDbPass, ' ', parameters('moodleCommon').moodleAdminPass, ' ', concat(parameters('moodleCommon').dbLogin, '@', parameters('moodleCommon').dbServerType, '-', parameters('moodleCommon').resourcesPrefix), ' ', parameters('moodleCommon').dbLoginPassword, ' ', parameters('moodleCommon').blobStorageAccountName, ' ', parameters('blobStorageAccountKey'), ' ', parameters('moodleCommon').moodleDbUserAzure, ' ', parameters('moodleCommon').redisDns, ' ', parameters('redisPrimaryKey'), ' ', parameters('moodleCommon').elasticVm1IP, ' ', parameters('moodleCommon').installO365pluginsSwitch, ' ', parameters('moodleCommon').installElasticSearchSwitch)]",
"cmdExec": "[concat('bash ', parameters('moodleCommon').moodleInstallScriptFilename, ' ', parameters('moodleCommon').moodleVersion, ' ', concat(parameters('moodleCommon').gfsNameRoot, '0'), ' ', 'data', ' ', parameters('moodleCommon').siteURL, ' ', concat(parameters('moodleCommon').dbServerType, '-', parameters('moodleCommon').resourcesPrefix, '.', parameters('moodleCommon').dbServerType, '.database.azure.com'), ' ', parameters('moodleCommon').moodleDbName, ' ', parameters('moodleCommon').moodleDbUser, ' ', parameters('moodleCommon').moodleDbPass, ' ', parameters('moodleCommon').moodleAdminPass, ' ', concat(parameters('moodleCommon').dbLogin, '@', parameters('moodleCommon').dbServerType, '-', parameters('moodleCommon').resourcesPrefix), ' ', parameters('moodleCommon').dbLoginPassword, ' ', parameters('moodleCommon').storageAccountName, ' ', parameters('storageAccountKey'), ' ', parameters('moodleCommon').moodleDbUserAzure, ' ', parameters('moodleCommon').redisDns, ' ', parameters('redisPrimaryKey'), ' ', parameters('moodleCommon').elasticVm1IP, ' ', parameters('moodleCommon').installO365pluginsSwitch, ' ', parameters('moodleCommon').installElasticSearchSwitch, ' ', parameters('moodleCommon').dbServerType, ' ', parameters('moodleCommon').fileServerType)]",
"documentation01": "This sub-template applies a specific post-deployment script to the controller vm",
"documentation02": "It expects certain values in the 'common' datastructure.",
"documentation03": " ScriptLocation - web URI",
"documentation03": " scriptLocation - web URI",
"documentation04": " moodleInstallScriptFilename - name of script file",
"documentation05": " siteURL - URL of the website",
"documentation06": " gfsNameRoot - nameroot of gluster farm - note that the code applies a 0 to get to the first node",
@ -60,6 +61,6 @@
"documentation10": " moodleDbUser - database user for moodle",
"documentation11": " moodleDbPass - database password for moodleDbUser",
"documentation12": " moodleAdminPass - password for moodle admin user",
"scriptUri": "[concat(parameters('moodleCommon').ScriptLocation,parameters('moodleCommon').moodleInstallScriptFilename)]"
"scriptUri": "[concat(parameters('moodleCommon').scriptLocation,parameters('moodleCommon').moodleInstallScriptFilename,parameters('moodleCommon').artifactsSasToken)]"
}
}

Просмотреть файл

@ -5,6 +5,10 @@
"dataDiskArray": {
"type": "array",
"value": "[take(variables('diskArray'),parameters('vmDiskCount'))]"
},
"emptyDataDiskArray": {
"type": "array",
"value": []
}
},
"parameters": {

Просмотреть файл

@ -99,7 +99,7 @@
},
"templateLink": {
"uri": "[concat(parameters('moodleCommon').baseTemplateUrl,'elasticconfig.json')]"
"uri": "[concat(parameters('moodleCommon').baseTemplateUrl,'elasticconfig.json',parameters('moodleCommon').artifactsSasToken)]"
}
},
"type": "Microsoft.Resources/deployments"
@ -122,7 +122,7 @@
}
},
"templateLink": {
"uri": "[concat(parameters('moodleCommon').baseTemplateUrl,'recoveryservicesEnlist.json')]"
"uri": "[concat(parameters('moodleCommon').baseTemplateUrl,'recoveryservicesEnlist.json',parameters('moodleCommon').artifactsSasToken)]"
}
},
"type": "Microsoft.Resources/deployments"
@ -206,7 +206,7 @@
},
"templateLink": {
"uri": "[concat(parameters('moodleCommon').baseTemplateUrl,'elasticconfig.json')]"
"uri": "[concat(parameters('moodleCommon').baseTemplateUrl,'elasticconfig.json',parameters('moodleCommon').artifactsSasToken)]"
}
},
"type": "Microsoft.Resources/deployments"
@ -229,7 +229,7 @@
}
},
"templateLink": {
"uri": "[concat(parameters('moodleCommon').baseTemplateUrl,'recoveryservicesEnlist.json')]"
"uri": "[concat(parameters('moodleCommon').baseTemplateUrl,'recoveryservicesEnlist.json',parameters('moodleCommon').artifactsSasToken)]"
}
},
"type": "Microsoft.Resources/deployments"
@ -313,7 +313,7 @@
},
"templateLink": {
"uri": "[concat(parameters('moodleCommon').baseTemplateUrl,'elasticconfig.json')]"
"uri": "[concat(parameters('moodleCommon').baseTemplateUrl,'elasticconfig.json',parameters('moodleCommon').artifactsSasToken)]"
}
},
"type": "Microsoft.Resources/deployments"
@ -336,7 +336,7 @@
}
},
"templateLink": {
"uri": "[concat(parameters('moodleCommon').baseTemplateUrl,'recoveryservicesEnlist.json')]"
"uri": "[concat(parameters('moodleCommon').baseTemplateUrl,'recoveryservicesEnlist.json',parameters('moodleCommon').artifactsSasToken)]"
}
},
"type": "Microsoft.Resources/deployments"

Просмотреть файл

@ -84,9 +84,9 @@
"cmdExec": "[concat('bash ', parameters('moodleCommon').elasticScriptFilename, ' ', parameters('moodleCommon').elasticClusterName, ' ', parameters('moodleCommon').elasticVm1IP, ' ', parameters('moodleCommon').elasticVm2IP, ' ', parameters('moodleCommon').elasticVm3IP)]",
"documentation01": "This sub-template applies a specific post-deployment script to the controller vm",
"documentation02": "It expects certain values in the 'common' datastructure.",
"documentation03": " ScriptLocation - web URI",
"documentation03": " scriptLocation - web URI",
"documentation04": " elasticScriptFilename - name of script file",
"documentation05": " elasticVmName - name of the elastic search vm generic name",
"scriptUri": "[concat(parameters('moodleCommon').ScriptLocation,parameters('moodleCommon').elasticScriptFilename)]"
"scriptUri": "[concat(parameters('moodleCommon').scriptLocation,parameters('moodleCommon').elasticScriptFilename,parameters('moodleCommon').artifactsSasToken)]"
}
}

Просмотреть файл

@ -45,7 +45,7 @@
}
},
"templateLink": {
"uri": "[concat( parameters('moodleCommon').baseTemplateUrl,'glustervm.json')]"
"uri": "[concat( parameters('moodleCommon').baseTemplateUrl,'glustervm.json',parameters('moodleCommon').artifactsSasToken)]"
}
},
"type": "Microsoft.Resources/deployments"

Просмотреть файл

@ -41,7 +41,7 @@
{
"apiVersion": "[parameters('moodleCommon').computeApi]",
"copy": {
"count": "[parameters('moodleCommon').glusterDiskCount]",
"count": "[parameters('moodleCommon').fileServerDiskCount]",
"name": "[variables('diskLoop')]"
},
"location": "[resourceGroup().location]",
@ -51,7 +51,7 @@
"creationData": {
"createOption": "Empty"
},
"diskSizeGB": "[parameters('moodleCommon').glusterDiskSize]"
"diskSizeGB": "[parameters('moodleCommon').fileServerDiskSize]"
},
"tags": {
"displayName": "Gluster VM Data Disk"
@ -68,14 +68,14 @@
"mode": "Incremental",
"parameters": {
"vmDiskCount": {
"value": "[parameters('moodleCommon').glusterDiskCount]"
"value": "[parameters('moodleCommon').fileServerDiskCount]"
},
"vmName": {
"value": "[variables('vmName')]"
}
},
"templateLink": {
"uri": "[concat(parameters('moodleCommon').baseTemplateUrl,'diskSelection.json')]"
"uri": "[concat(parameters('moodleCommon').baseTemplateUrl,'diskSelection.json',parameters('moodleCommon').artifactsSasToken)]"
}
},
"type": "Microsoft.Resources/deployments"
@ -155,7 +155,7 @@
}
},
"templateLink": {
"uri": "[concat( parameters('moodleCommon').baseTemplateUrl,'glustervmconfig.json')]"
"uri": "[concat(parameters('moodleCommon').baseTemplateUrl,'glustervmconfig.json',parameters('moodleCommon').artifactsSasToken)]"
}
},
"type": "Microsoft.Resources/deployments"
@ -178,7 +178,7 @@
}
},
"templateLink": {
"uri": "[concat(parameters('moodleCommon').baseTemplateUrl,'recoveryservicesEnlist.json')]"
"uri": "[concat(parameters('moodleCommon').baseTemplateUrl,'recoveryservicesEnlist.json',parameters('moodleCommon').artifactsSasToken)]"
}
},
"type": "Microsoft.Resources/deployments"
@ -202,8 +202,8 @@
"documentation16": " diskSelection - returns an arry of disk names - for flexible sizing",
"documentation17": " glustervmconfig - conditionally applies post-deployment script on the VM",
"documentation18": " recoveryservicesEnlist - conditionally enlists the VM into the backup regimen",
"documentation19": " glusterDiskCount - Number of disks to raid0 for the gluster mount",
"documentation20": " glusterDiskSize - Size per disk for gluster",
"documentation19": " fileServerDiskCount - Number of disks to raid0 for the gluster mount",
"documentation20": " fileServerDiskSize - Size per disk for gluster",
"nicName": "[concat(variables('vmName'),'-nic')]",
"nicRef": "[resourceId('Microsoft.Network/networkInterfaces', variables('nicName'))]",
"subnetSanRef": "[concat(resourceId('Microsoft.Network/virtualNetworks', parameters('moodleCommon').vnetName), '/subnets/',parameters('moodleCommon').subnetSan)]",

Просмотреть файл

@ -49,10 +49,10 @@
"cmdExec": "[concat('bash ', parameters('moodleCommon').glusterScriptFilename, ' ', parameters('moodleCommon').gfsNameRoot, ' ', parameters('moodleCommon').subnetSanPrefix, ' data ', parameters('vmNumber'), ' ', parameters('moodleCommon').glusterVmCount)]",
"documentation01": "This sub-template applies a specific post-deployment script to the gluster vms",
"documentation02": "It expects certain values in the 'common' datastructure.",
"documentation03": " ScriptLocation - partial web URI (equivalent to folder)",
"documentation03": " scriptLocation - partial web URI (equivalent to folder)",
"documentation04": " glusterScriptFilename - name of script file",
"documentation06": " gfsNameRoot - nameroot of gluster farm - note that the code applies a vmNumber to get to the specific node",
"documentation07": " glusterVmCount - database (mariadb) password",
"scriptUri": "[concat(parameters('moodleCommon').ScriptLocation,parameters('moodleCommon').glusterScriptFilename)]"
"scriptUri": "[concat(parameters('moodleCommon').scriptLocation,parameters('moodleCommon').glusterScriptFilename,parameters('moodleCommon').artifactsSasToken)]"
}
}

Просмотреть файл

@ -56,6 +56,7 @@
"type": "Microsoft.Network/virtualNetworks"
},
{
"condition": "[parameters('moodleCommon').vnetGwDeploySwitch]",
"apiVersion": "2015-06-15",
"location": "[resourceGroup().location]",
"name": "[parameters('moodleCommon').gatewayPublicIPName]",
@ -68,6 +69,7 @@
"type": "Microsoft.Network/publicIPAddresses"
},
{
"condition": "[parameters('moodleCommon').vnetGwDeploySwitch]",
"apiVersion": "2015-06-15",
"dependsOn": [
"[resourceId('Microsoft.Network/virtualNetworks', parameters('moodleCommon').vnetName)]"
@ -79,6 +81,7 @@
"type": "Microsoft.Network/virtualNetworks/subnets"
},
{
"condition": "[parameters('moodleCommon').vnetGwDeploySwitch]",
"apiVersion": "2015-06-15",
"dependsOn": [
"[resourceId('Microsoft.Network/publicIPAddresses', parameters('moodleCommon').gatewayPublicIPName)]",
@ -168,7 +171,7 @@
"probe": {
"id": "[variables('extProbeID')]"
},
"protocol": "tcp"
"protocol": "Tcp"
}
},
{
@ -187,7 +190,7 @@
"probe": {
"id": "[variables('extProbeID')]"
},
"protocol": "tcp"
"protocol": "Tcp"
}
}
],
@ -195,10 +198,10 @@
{
"name": "[parameters('moodleCommon').extProbe ]",
"properties": {
"intervalInSeconds": "5",
"numberOfProbes": "3",
"intervalInSeconds": 5,
"numberOfProbes": 3,
"port": 80,
"protocol": "tcp"
"protocol": "Tcp"
}
}
]

Просмотреть файл

@ -11,15 +11,14 @@
},
"resources": [
{
"kind": "BlobStorage",
"kind": "Storage",
"location": "[resourceGroup().location]",
"name": "[parameters('moodleCommon').blobStorageAccountName]",
"name": "[parameters('moodleCommon').storageAccountName]",
"apiVersion": "2017-06-01",
"sku": {
"name": "[parameters('moodleCommon').blobStorageAccountType]"
"name": "[parameters('moodleCommon').storageAccountType]"
},
"properties": {
"accessTier": "Hot",
"encryption": {
"keySource": "Microsoft.Storage",
"services": {
@ -43,15 +42,14 @@
}
],
"variables": {
"documentation1": "This sub-template creates a blob storage account. It expects certain values in the 'common' datastructure.",
"documentation2": " blobStorageAccountName - name of storage account",
"documentation3": " blobStorageAccountType - type of storage account",
"scriptUri": "[concat(parameters('moodleCommon').ScriptLocation,parameters('moodleCommon').moodleInstallScriptFilename)]",
"blobStorageAccountId": "[concat(resourceGroup().id,'/providers/Microsoft.Storage/storageAccounts/', parameters('moodleCommon').blobStorageAccountName)]"
"documentation1": "This sub-template creates a storage account. It expects certain values in the 'common' datastructure.",
"documentation2": " storageAccountName - name of storage account",
"documentation3": " storageAccountType - type of storage account",
"storageAccountId": "[concat(resourceGroup().id,'/providers/Microsoft.Storage/storageAccounts/', parameters('moodleCommon').storageAccountName)]"
},
"outputs": {
"blobStorageAccountKey": {
"value": "[listKeys(variables('blobStorageAccountId'), '2017-06-01').keys[0].value]",
"storageAccountKey": {
"value": "[listKeys(variables('storageAccountId'), '2017-06-01').keys[0].value]",
"type": "string"
}
}

Просмотреть файл

@ -7,6 +7,12 @@
"description": "Common Moodle values"
},
"type": "object"
},
"storageAccountKey": {
"metadata": {
"description": "Storage account key that may be needed in the VM setup scripts"
},
"type": "string"
}
},
"resources": [
@ -41,7 +47,8 @@
"publisher": "Microsoft.Azure.Extensions",
"settings": {
"fileUris": [
"[variables('scriptUri')]"
"[variables('scriptUri')]",
"[parameters('moodleCommon').commonFunctionsScriptUri]"
]
},
"protectedSettings":{
@ -181,14 +188,14 @@
}
],
"variables": {
"cmdExec": "[concat('bash ',parameters('moodleCommon').moodleSetupScriptFilename,' ',parameters('moodleCommon').gfsNameRoot,'0', ' ','data', ' ', parameters('moodleCommon').siteURL, ' ', concat('jumpbox-vm-',parameters('moodleCommon').resourcesPrefix), ' ', parameters('moodleCommon').webServerType)]",
"cmdExec": "[concat('bash ',parameters('moodleCommon').webServerSetupScriptFilename,' ',parameters('moodleCommon').gfsNameRoot,'0', ' ','data', ' ', parameters('moodleCommon').siteURL, ' ', concat('jumpbox-vm-',parameters('moodleCommon').resourcesPrefix), ' ', parameters('moodleCommon').webServerType, ' ', parameters('moodleCommon').fileServerType, ' ', parameters('moodleCommon').storageAccountName, ' ', parameters('storageAccountKey'), ' ', parameters('moodleCommon').jboxVmName)]",
"dstorID": "[resourceId('Microsoft.Storage/storageAccounts',parameters('moodleCommon').vmssdStorageAccounttName)]",
"extBeID": "[concat(variables('extLbID'),'/backendAddressPools/',parameters('moodleCommon').extBeName)]",
"extFeID": "[concat(variables('extLbID'),'/frontendIPConfigurations/',parameters('moodleCommon').extFeName)]",
"extLbID": "[resourceId('Microsoft.Network/loadBalancers',parameters('moodleCommon').lbName)]",
"extProbeID": "[concat(variables('extLbID'),'/probes/',parameters('moodleCommon').extProbe )]",
"pipID": "[resourceId('Microsoft.Network/publicIPAddresses',parameters('moodleCommon').lbPipName)]",
"scriptUri": "[concat(parameters('moodleCommon').ScriptLocation,parameters('moodleCommon').moodleSetupScriptFilename)]",
"scriptUri": "[concat(parameters('moodleCommon').scriptLocation,parameters('moodleCommon').webServerSetupScriptFilename,parameters('moodleCommon').artifactsSasToken)]",
"storageApiVersion": "2015-06-15",
"subnetWebRef": "[concat(resourceId('Microsoft.Network/virtualNetworks',parameters('moodleCommon').vnetName),'/subnets/',parameters('moodleCommon').subnetWeb)]",
"vmssID": "[resourceId('Microsoft.Compute/virtualMachineScaleSets',parameters('moodleCommon').vmssName)]",

1131
scripts/helper_functions.sh Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -27,12 +27,23 @@ glusterVolume=$2
siteFQDN=$3
syslogserver=$4
webServerType=$5
fileServerType=$6
storageAccountName=$7
storageAccountKey=$8
nfsVmName=$9
echo $glusterNode >> /tmp/vars.txt
echo $glusterVolume >> /tmp/vars.txt
echo $siteFQDN >> /tmp/vars.txt
echo $syslogserver >> /tmp/vars.txt
echo $webServerType >> /tmp/vars.txt
echo $fileServerType >> /tmp/vars.txt
echo $storageAccountName >> /tmp/vars.txt
echo $storageAccountKey >> /tmp/vars.txt
echo $nfsVmName >> /tmp/vars.txt
. ./helper_functions.sh
check_fileServerType_param $fileServerType
{
# make sure the system does automatic update
@ -42,10 +53,16 @@ echo $webServerType >> /tmp/vars.txt
# install pre-requisites
sudo apt-get -y install python-software-properties unzip rsyslog
#configure gluster repository & install gluster client
sudo add-apt-repository ppa:gluster/glusterfs-3.8 -y
sudo apt-get -y update
sudo apt-get -y install glusterfs-client postgresql-client mysql-client git
sudo apt-get -y install postgresql-client mysql-client git
if [ $fileServerType = "gluster" ]; then
#configure gluster repository & install gluster client
sudo add-apt-repository ppa:gluster/glusterfs-3.8 -y
sudo apt-get -y update
sudo apt-get -y install glusterfs-client
else # "azurefiles"
sudo apt-get -y install cifs-utils
fi
# install the base stack
sudo apt-get -y install nginx varnish php php-cli php-curl php-zip
@ -61,14 +78,20 @@ echo $webServerType >> /tmp/vars.txt
# Moodle requirements
sudo apt-get install -y graphviz aspell php-soap php-json php-redis php-bcmath php-gd php-pgsql php-mysql php-xmlrpc php-intl php-xml php-bz2
# Mount gluster fs for /moodle
sudo mkdir -p /moodle
sudo chown www-data /moodle
sudo chmod 770 /moodle
sudo echo -e 'mount -t glusterfs '$glusterNode':/'$glusterVolume' /moodle'
sudo mount -t glusterfs $glusterNode:/$glusterVolume /moodle
sudo echo -e $glusterNode':/'$glusterVolume' /moodle glusterfs defaults,_netdev,log-level=WARNING,log-file=/var/log/gluster.log 0 0' >> /etc/fstab
sudo mount -a
if [ $fileServerType = "gluster" ]; then
# Mount gluster fs for /moodle
sudo mkdir -p /moodle
sudo chown www-data /moodle
sudo chmod 770 /moodle
sudo echo -e 'mount -t glusterfs '$glusterNode':/'$glusterVolume' /moodle'
sudo mount -t glusterfs $glusterNode:/$glusterVolume /moodle
sudo echo -e $glusterNode':/'$glusterVolume' /moodle glusterfs defaults,_netdev,log-level=WARNING,log-file=/var/log/gluster.log 0 0' >> /etc/fstab
sudo mount -a
elif [ $fileServerType = "nfs" ]; then
configure_nfs_client_and_mount $nfsVmName /moodle /moodle
else # "azurefiles"
setup_and_mount_azure_files_moodle_share $storageAccountName $storageAccountKey
fi
# Configure syslog to forward
cat <<EOF >> /etc/rsyslog.conf
@ -171,6 +194,11 @@ server {
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_pass http://localhost:80;
proxy_connect_timeout 3600;
proxy_send_timeout 3600;
proxy_read_timeout 3600;
send_timeout 3600;
}
}
EOF