azure-deployment.sh 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. #!/bin/bash
  2. #
  3. # Bash script to deploy Web Framework Benchmarks on Windows Azure.
  4. #
  5. # Note: These scripts are designed to run both on Windows (under Cygwin) and
  6. # on Linux and Mac. To achieve that, they have to use some workarounds that
  7. # wouldn't seem necessary or usual in a pure Linux environment.
  8. #
  9. set -o nounset -o errexit
  10. BENCHMARK_DEPLOYMENT_HOME="toolset/deployment"
  11. if [ ! -d "$BENCHMARK_DEPLOYMENT_HOME" ]; then echo "Could not find the '$BENCHMARK_DEPLOYMENT_HOME' directory. This script must be run from the FrameworkBenchmarks directory."; exit 1; fi
  12. source "$BENCHMARK_DEPLOYMENT_HOME/common/bash-common.sh"
  13. source "$BENCHMARK_DEPLOYMENT_HOME/azure/azure-deployment-configuration.sh"
  14. function azure_check_configuration {
  15. set +o nounset
  16. # Validate AZURE_DEPLOYMENT_PUBLISHSETTINGS_LOCATION.
  17. if [ -z "$AZURE_DEPLOYMENT_PUBLISHSETTINGS_LOCATION" ]; then fail "AZURE_DEPLOYMENT_PUBLISHSETTINGS_LOCATION is not defined."; fi
  18. if [ ! -f "$AZURE_DEPLOYMENT_PUBLISHSETTINGS_LOCATION" ]; then fail "File not found: '$AZURE_DEPLOYMENT_PUBLISHSETTINGS_LOCATION'. Use the absolute pathname without shortcuts like '~'."; fi
  19. # Validate AZURE_DEPLOYMENT_SUBSCRIPTION.
  20. if [ -z "$AZURE_DEPLOYMENT_SUBSCRIPTION" ]; then fail "AZURE_DEPLOYMENT_SUBSCRIPTION is not defined."; fi
  21. # Validate AZURE_DEPLOYMENT_LOCATION.
  22. if [ -z "$AZURE_DEPLOYMENT_LOCATION" ]; then fail "AZURE_DEPLOYMENT_LOCATION is not defined."; fi
  23. # Validate AZURE_DEPLOYMENT_NAME.
  24. if [ -z "$AZURE_DEPLOYMENT_NAME" ]; then fail "AZURE_DEPLOYMENT_NAME is not defined."; fi
  25. if [ ${#AZURE_DEPLOYMENT_NAME} -gt 12 ]; then fail "AZURE_DEPLOYMENT_NAME must be at most 12 characters long."; fi
  26. # Validate $AZURE_WINDOWS_PASSWORD.
  27. if [ -z "$AZURE_WINDOWS_PASSWORD" ]; then fail "AZURE_WINDOWS_PASSWORD is not defined."; fi
  28. if [ ${#AZURE_WINDOWS_PASSWORD} -lt 10 ]; then fail "AZURE_WINDOWS_PASSWORD must be at least 10 characters long."; fi
  29. # Validate AZURE_DEPLOYMENT_VM_SIZE.
  30. if [ -z "$AZURE_DEPLOYMENT_VM_SIZE" ]; then fail "AZURE_DEPLOYMENT_VM_SIZE is not defined."; fi
  31. set -o nounset
  32. }
  33. function azure_set_variables {
  34. # Set variables used in several steps.
  35. AZURE_LINUX_USER="ubuntu"
  36. AZURE_WINDOWS_USER="windows"
  37. AZURE_SSH_DIR="$HOME/.ssh"
  38. AZURE_KEY_NAME="id_rsa-${AZURE_DEPLOYMENT_NAME}"
  39. AZURE_KEY_FILE="${AZURE_SSH_DIR}/${AZURE_KEY_NAME}"
  40. AZURE_PEM_FILE="${AZURE_SSH_DIR}/${AZURE_KEY_NAME}.x509.pub.pem"
  41. AZURE_CER_FILE="${AZURE_SSH_DIR}/${AZURE_KEY_NAME}.cer"
  42. CLIENT_VM_NAME="${AZURE_DEPLOYMENT_NAME}cli"
  43. LINUX_SERVER_VM_NAME="${AZURE_DEPLOYMENT_NAME}lsr"
  44. WINDOWS_SERVER_VM_NAME="${AZURE_DEPLOYMENT_NAME}wsr"
  45. SQL_SERVER_VM_NAME="${AZURE_DEPLOYMENT_NAME}sql"
  46. BENCHMARK_WORKING_DIR="$HOME/tmp/${AZURE_DEPLOYMENT_NAME}"
  47. mkdir -p "$BENCHMARK_WORKING_DIR" || fail "Could not create directory $BENCHMARK_WORKING_DIR."
  48. AZURE_DEPLOYMENT_INSTRUCTIONS_FILE="$BENCHMARK_WORKING_DIR/azure-instructions.txt"
  49. AZURE_CONFIGURATION_OUTPUT_FILE="$BENCHMARK_WORKING_DIR/deployment-configuration.sh"
  50. BENCHMARK_REPOSITORY=${BENCHMARK_REPOSITORY:-"https://github.com/TechEmpower/FrameworkBenchmarks.git"}
  51. BENCHMARK_BRANCH=${BENCHMARK_BRANCH:-"master"}
  52. UBUNTU_IMAGE_VERSION="12_04"
  53. UBUNTU_IMAGE_TEMPLATE="Ubuntu_DAILY_BUILD-precise-${UBUNTU_IMAGE_VERSION}.*-LTS-amd64-server"
  54. # Under CYGWIN this script uses a helper function to call the Windows Azure command line program.
  55. if iscygwin; then
  56. AZURE_COMMAND="cywgin_cmd azure.cmd"
  57. else
  58. AZURE_COMMAND="azure"
  59. fi
  60. # TODO azure.cmd is not returning status code from node
  61. }
  62. function azure_configure_command_line_tools {
  63. information "******************************************************************************"
  64. information "Windows Azure Deployment: Configuring command line tools"
  65. information "******************************************************************************"
  66. # Create directory for Windows Azure command line tools configuration.
  67. AZURE_HOME="$HOME/.azure"
  68. echo ""
  69. echo "Creating Windows Azure configuration directory at $AZURE_HOME"
  70. mkdir -p ${AZURE_HOME} || fail "Error creating directory $AZURE_HOME."
  71. # Import publish settings.
  72. echo ""
  73. echo "Importing publish settings at $AZURE_DEPLOYMENT_PUBLISHSETTINGS_LOCATION"
  74. $AZURE_COMMAND account import $AZURE_DEPLOYMENT_PUBLISHSETTINGS_LOCATION || fail "Error importing publish settings."
  75. # Set default subscription.
  76. echo ""
  77. echo "Setting default subscription to $AZURE_DEPLOYMENT_SUBSCRIPTION"
  78. $AZURE_COMMAND account set "$AZURE_DEPLOYMENT_SUBSCRIPTION" || fail "Error setting default subscription."
  79. echo ""
  80. }
  81. function azure_create_common_resources {
  82. information "******************************************************************************"
  83. information "Windows Azure Deployment: Creating common resources"
  84. information "******************************************************************************"
  85. # Create affinity group.
  86. echo ""
  87. echo "Creating affinity group $AZURE_DEPLOYMENT_NAME at $AZURE_DEPLOYMENT_LOCATION"
  88. $AZURE_COMMAND account affinity-group show $AZURE_DEPLOYMENT_NAME || $AZURE_COMMAND account affinity-group create $AZURE_DEPLOYMENT_NAME --label $AZURE_DEPLOYMENT_NAME --location "$AZURE_DEPLOYMENT_LOCATION" || fail "Error creating affinity group $AZURE_DEPLOYMENT_NAME."
  89. # Create storage account.
  90. echo ""
  91. echo "Creating storage account $AZURE_DEPLOYMENT_NAME"
  92. $AZURE_COMMAND account storage show $AZURE_DEPLOYMENT_NAME || $AZURE_COMMAND account storage create $AZURE_DEPLOYMENT_NAME --affinity-group $AZURE_DEPLOYMENT_NAME || fail "Error creating storage account $AZURE_DEPLOYMENT_NAME."
  93. # Create virtual network.
  94. echo ""
  95. echo "Creating virtual network $AZURE_DEPLOYMENT_NAME"
  96. [[ -n `$AZURE_COMMAND network vnet list | grep $AZURE_DEPLOYMENT_NAME` ]] || $AZURE_COMMAND network vnet create $AZURE_DEPLOYMENT_NAME --affinity-group $AZURE_DEPLOYMENT_NAME || fail "Error creating virtual network $AZURE_DEPLOYMENT_NAME."
  97. # Create directory for keys.
  98. echo ""
  99. echo "Creating directory for keys at $AZURE_SSH_DIR"
  100. mkdir -p ${AZURE_SSH_DIR} || fail "Error creating directory $AZURE_SSH_DIR."
  101. # Create key files.
  102. if [ ! -e "$AZURE_KEY_FILE" ]; then
  103. echo "Creating key pair at $AZURE_KEY_FILE"
  104. ssh-keygen -t rsa -b 2048 -f "$AZURE_KEY_FILE" -C "$AZURE_KEY_NAME" -q -N "" || fail "Error creating SSH key."
  105. chmod 600 "$AZURE_KEY_FILE"
  106. warning "-----------------------------------------------------------------------"
  107. warning "Protect this key file. It has no passphrase and is stored in plaintext."
  108. warning "-----------------------------------------------------------------------"
  109. fi
  110. if [ ! -e "$AZURE_PEM_FILE" ]; then
  111. echo "Creating PEM file at $AZURE_PEM_FILE"
  112. openssl req -new -x509 -days 365 -subj "/CN=$AZURE_DEPLOYMENT_NAME/O=Web Framework Benchmarks" -key "$AZURE_KEY_FILE" -out "$AZURE_PEM_FILE" || fail "Error creating PEM file."
  113. chmod 600 "$AZURE_PEM_FILE"
  114. fi
  115. if [ ! -e "$AZURE_CER_FILE" ]; then
  116. echo "Creating CER file at $AZURE_CER_FILE"
  117. openssl x509 -outform der -in "$AZURE_PEM_FILE" -out "$AZURE_CER_FILE" || fail "Error creating CER file."
  118. chmod 600 "$AZURE_CER_FILE"
  119. fi
  120. echo ""
  121. }
  122. function azure_create_vms {
  123. information "******************************************************************************"
  124. information "Windows Azure Deployment: Creating virtual machines"
  125. information "******************************************************************************"
  126. # Get latest Ubuntu Server 12.04 daily VM image.
  127. echo ""
  128. echo "Latest Ubuntu Server 12.04 image:"
  129. LATEST_UBUNTU_IMAGE=$($AZURE_COMMAND vm image list | grep $UBUNTU_IMAGE_TEMPLATE | sort | tail -1 | cut -c 10-120)
  130. echo $LATEST_UBUNTU_IMAGE
  131. # Create client VM.
  132. echo ""
  133. echo "Creating client VM: $CLIENT_VM_NAME"
  134. $AZURE_COMMAND vm list | grep $CLIENT_VM_NAME || $AZURE_COMMAND vm create $CLIENT_VM_NAME $LATEST_UBUNTU_IMAGE $AZURE_LINUX_USER --ssh-cert "$AZURE_PEM_FILE" --no-ssh-password --vm-name $CLIENT_VM_NAME --vm-size $AZURE_DEPLOYMENT_VM_SIZE --virtual-network-name $AZURE_DEPLOYMENT_NAME --ssh --affinity-group $AZURE_DEPLOYMENT_NAME || fail "Error creating virtual machine $CLIENT_VM_NAME."
  135. # Create Ubuntu server VM.
  136. echo ""
  137. echo "Creating Linux server VM: $LINUX_SERVER_VM_NAME"
  138. $AZURE_COMMAND vm list | grep $LINUX_SERVER_VM_NAME || $AZURE_COMMAND vm create $LINUX_SERVER_VM_NAME $LATEST_UBUNTU_IMAGE $AZURE_LINUX_USER --ssh-cert "$AZURE_PEM_FILE" --no-ssh-password --vm-name $LINUX_SERVER_VM_NAME --vm-size $AZURE_DEPLOYMENT_VM_SIZE --virtual-network-name $AZURE_DEPLOYMENT_NAME --ssh --affinity-group $AZURE_DEPLOYMENT_NAME || fail "Error creating virtual machine $LINUX_SERVER_VM_NAME."
  139. # Get latest Windows Server 2012 Datacenter image.
  140. echo ""
  141. echo "Latest Windows Server 2012 Datacenter image:"
  142. LATEST_WINDOWS_IMAGE=$($AZURE_COMMAND vm image list | grep Windows-Server-2012-Datacenter | sort | tail -1 | cut -c 10-120)
  143. echo $LATEST_WINDOWS_IMAGE
  144. # Create Windows server VM.
  145. echo ""
  146. echo "Creating Windows server VM: $WINDOWS_SERVER_VM_NAME"
  147. $AZURE_COMMAND vm list | grep $WINDOWS_SERVER_VM_NAME || $AZURE_COMMAND vm create $WINDOWS_SERVER_VM_NAME $LATEST_WINDOWS_IMAGE $AZURE_WINDOWS_USER $AZURE_WINDOWS_PASSWORD --vm-name $WINDOWS_SERVER_VM_NAME --vm-size $AZURE_DEPLOYMENT_VM_SIZE --virtual-network-name $AZURE_DEPLOYMENT_NAME --rdp --affinity-group $AZURE_DEPLOYMENT_NAME || fail "Error creating virtual machine $WINDOWS_SERVER_VM_NAME."
  148. # Create SQL Server VM.
  149. echo ""
  150. echo "SQL Server image:"
  151. SQL_SERVER_IMAGE="fb83b3509582419d99629ce476bcb5c8__Microsoft-SQL-Server-2012SP1-CU4-11.0.3368.0-Standard-ENU-Win2012"
  152. echo $SQL_SERVER_IMAGE
  153. echo ""
  154. echo "Creating SQL Server VM: $SQL_SERVER_VM_NAME"
  155. $AZURE_COMMAND vm list | grep $SQL_SERVER_VM_NAME || $AZURE_COMMAND vm create $SQL_SERVER_VM_NAME $SQL_SERVER_IMAGE $AZURE_WINDOWS_USER $AZURE_WINDOWS_PASSWORD --vm-name $SQL_SERVER_VM_NAME --vm-size $AZURE_DEPLOYMENT_VM_SIZE --virtual-network-name $AZURE_DEPLOYMENT_NAME --rdp --affinity-group $AZURE_DEPLOYMENT_NAME || fail "Error creating virtual machine $SQL_SERVER_VM_NAME."
  156. echo ""
  157. }
  158. function azure_get_vm_ip {
  159. local vm_name=$1
  160. local vm_status=""
  161. until [[ "$vm_status" == "ReadyRole" ]]
  162. do
  163. local vm_properties=`$AZURE_COMMAND vm show $vm_name --json`
  164. json=$vm_properties
  165. prop='InstanceStatus'
  166. local vm_status=`jsonval`
  167. if [[ "$vm_status" != "ReadyRole" ]]; then { error "$vm_name status is '$vm_status'. Retrying in 30s..."; sleep 30s; } fi
  168. done
  169. prop='IPAddress'
  170. local ip_address=`jsonval`
  171. if [ -z "$ip_address" ]; then fail "ip_address not found."; fi
  172. echo $ip_address
  173. }
  174. function azure_save_deployment_configuration {
  175. information "******************************************************************************"
  176. information "Windows Azure Deployment: Creating deployment configuration file"
  177. information "******************************************************************************"
  178. # Get client IP.
  179. echo "Retrieving $CLIENT_VM_NAME IP:"
  180. CLIENT_IP=`azure_get_vm_ip $CLIENT_VM_NAME`
  181. echo "$CLIENT_IP"
  182. # Get Linux server IP.
  183. echo ""
  184. echo "Retrieving $LINUX_SERVER_VM_NAME IP:"
  185. LINUX_SERVER_IP=`azure_get_vm_ip $LINUX_SERVER_VM_NAME`
  186. echo "$LINUX_SERVER_IP"
  187. echo ""
  188. echo "Saving configuration file at $AZURE_CONFIGURATION_OUTPUT_FILE"
  189. cat >$AZURE_CONFIGURATION_OUTPUT_FILE <<_EOF_
  190. BENCHMARK_LINUX_CLIENT="$CLIENT_VM_NAME.cloudapp.net"
  191. BENCHMARK_LINUX_CLIENT_IP="$CLIENT_IP"
  192. BENCHMARK_LINUX_SERVER="$LINUX_SERVER_VM_NAME.cloudapp.net"
  193. BENCHMARK_LINUX_SERVER_IP="$LINUX_SERVER_IP"
  194. BENCHMARK_LINUX_USER="$AZURE_LINUX_USER"
  195. BENCHMARK_SSH_KEY="$AZURE_KEY_FILE"
  196. BENCHMARK_WINDOWS_SERVER="$WINDOWS_SERVER_VM_NAME.cloudapp.net"
  197. BENCHMARK_WINDOWS_SERVER_USER="$WINDOWS_SERVER_VM_NAME\\$AZURE_WINDOWS_USER"
  198. BENCHMARK_SQL_SERVER="$SQL_SERVER_VM_NAME.cloudapp.net"
  199. BENCHMARK_SQL_SERVER_USER="$SQL_SERVER_VM_NAME\\$AZURE_WINDOWS_USER"
  200. BENCHMARK_WORKING_DIR="$BENCHMARK_WORKING_DIR"
  201. BENCHMARK_REPOSITORY="$BENCHMARK_REPOSITORY"
  202. BENCHMARK_BRANCH="$BENCHMARK_BRANCH"
  203. _EOF_
  204. echo ""
  205. }
  206. function azure_print_instructions {
  207. information "******************************************************************************"
  208. information "Windows Azure Deployment: Instructions"
  209. information "******************************************************************************"
  210. AZURE_VMS_DEPLOYED=`$AZURE_COMMAND vm list | grep -E "DNS Name|$AZURE_DEPLOYMENT_NAME" | cut -c 10-`
  211. if iscygwin; then
  212. AZURE_DEPLOYMENT_PUBLISHSETTINGS_LOCATION=`cygpath -w "$AZURE_DEPLOYMENT_PUBLISHSETTINGS_LOCATION"`
  213. fi
  214. cat >$AZURE_DEPLOYMENT_INSTRUCTIONS_FILE <<_EOF_
  215. Windows Azure resources provisioned at $AZURE_DEPLOYMENT_LOCATION with the base name $AZURE_DEPLOYMENT_NAME under the subscription $AZURE_DEPLOYMENT_SUBSCRIPTION using $AZURE_DEPLOYMENT_VM_SIZE virtual machines.
  216. VMs deployed:
  217. $AZURE_VMS_DEPLOYED
  218. To connect to the client VM:
  219. ssh $AZURE_LINUX_USER@$CLIENT_VM_NAME.cloudapp.net -i $AZURE_KEY_FILE
  220. To connect to the Linux server VM:
  221. ssh $AZURE_LINUX_USER@$LINUX_SERVER_VM_NAME.cloudapp.net -i $AZURE_KEY_FILE
  222. To connect to the Windows server VM:
  223. mstsc /v:$WINDOWS_SERVER_VM_NAME.cloudapp.net /admin /f
  224. User name: $WINDOWS_SERVER_VM_NAME\\$AZURE_WINDOWS_USER
  225. To connect to the SQL Server VM:
  226. mstsc /v:$SQL_SERVER_VM_NAME.cloudapp.net /admin /f
  227. User name: $SQL_SERVER_VM_NAME\\$AZURE_WINDOWS_USER
  228. To manage the Windows Azure resources:
  229. https://manage.windowsazure.com
  230. For your security delete the publish settings file when you don't need it anymore:
  231. $AZURE_DEPLOYMENT_PUBLISHSETTINGS_LOCATION
  232. Remember to stop the virtual machines when they're not needed anymore.
  233. VMs in "Stopped (Deallocated)" status don't incur in computing costs.
  234. Virtual disks (VHD) incur in storage costs until they are deleted.
  235. Deployment configuration file saved at:
  236. $AZURE_CONFIGURATION_OUTPUT_FILE
  237. _EOF_
  238. # TODO: instructions to stop and start the VMs
  239. # TODO: instructions to list tests available at each server
  240. # TODO: instructions to run tests
  241. echo ""
  242. cat $AZURE_DEPLOYMENT_INSTRUCTIONS_FILE
  243. if iscygwin; then
  244. AZURE_DEPLOYMENT_INSTRUCTIONS_FILE=`cygpath -w "$AZURE_DEPLOYMENT_INSTRUCTIONS_FILE"`
  245. fi
  246. echo ""
  247. warning "You can review these instructions at $AZURE_DEPLOYMENT_INSTRUCTIONS_FILE"
  248. echo ""
  249. }
  250. function azure_continue_deployment {
  251. echo "Starting automated deployment on the provisioned VMs..."
  252. echo ""
  253. run_bash "$BENCHMARK_DEPLOYMENT_HOME/common/deployment.sh" "$AZURE_CONFIGURATION_OUTPUT_FILE"
  254. }
  255. information "Deploying Web Framework Benchmarks to Windows Azure..."
  256. echo ""
  257. azure_check_configuration
  258. azure_set_variables
  259. echo "The resources will be created with the base name $AZURE_DEPLOYMENT_NAME" \
  260. "in $AZURE_DEPLOYMENT_LOCATION under the subscription $AZURE_DEPLOYMENT_SUBSCRIPTION" \
  261. "using $AZURE_DEPLOYMENT_VM_SIZE virtual machines."
  262. echo "The benchmark suite will be cloned from the $BENCHMARK_BRANCH branch of the repository at $BENCHMARK_REPOSITORY."
  263. echo ""
  264. azure_configure_command_line_tools
  265. azure_create_common_resources
  266. azure_create_vms
  267. azure_save_deployment_configuration
  268. azure_print_instructions
  269. azure_continue_deployment
  270. warning "Instructions were saved to $AZURE_DEPLOYMENT_INSTRUCTIONS_FILE"
  271. echo ""