Creating a Training Lab on Windows Azure
- by Michael Stephenson
Originally posted on: http://geekswithblogs.net/michaelstephenson/archive/2013/06/17/153149.aspxThis week we are preparing for a training course that Alan Smith will be running for the support teams at one of my customers around Windows Azure. In order to facilitate the training lab we have a few prerequisites we need to handle. One of the biggest ones is that although the support team all have MSDN accounts the local desktops they work on are not ideal for running most of the labs as we want to give them some additional developer background training around Azure.
Some recent Azure announcements really help us in this area:
MSDN software can now be used on Azure VM
You don't pay for Azure VM's when they are no longer used
Since the support team only have limited experience of Windows Azure and the organisation also have an Enterprise Agreement we decided it would be best value for money to spin up a training lab in a subscription on the EA and then we can turn the machines off when we are done. At the same time we would be able to spin them back up when the users need to do some additional lab work once the training course is completed.
In order to achieve this I wanted to create a powershell script which would setup my training lab. The aim was to create 18 VM's which would be based on a prebuilt template with Visual Studio and the Azure development tools.
The script I used is described below
The Start & Variables
The below text will setup the powershell environment and some variables which I will use elsewhere in the script. It will also import the Azure Powershell cmdlets.
You can see below that I will need to download my publisher settings file and know some details from my Azure account. At this point I will assume you have a basic understanding of Azure & Powershell so already know how to do this.
Set-ExecutionPolicy
Unrestrictedcls
$startTime
=
get-dateImport-Module
"C:\Program Files (x86)\Microsoft SDKs\Windows Azure\PowerShell\Azure\Azure.psd1"# Azure Publisher Settings
$azurePublisherSettings
=
'<Your settings file>.publishsettings'
# Subscription Details
$subscriptionName
=
"<Your subscription name>"
$defaultStorageAccount
=
"<Your default storage account>"
# Affinity Group Details
$affinityGroup
=
'<Your affinity group>'
$dataCenter
=
'West Europe'
# From Get-AzureLocation
# VM Details
$baseVMName
=
'TRN'
$adminUserName
=
'<Your admin username>'
$password
=
'<Your admin password>'
$size
=
'Medium'
$vmTemplate
=
'<The name of your VM template image>'
$rdpFilePath
=
'<File path to save RDP files to>'
$machineSettingsPath
=
'<File path to save machine info to>'
Functions
In the next section of the script I have some functions which are used to perform certain actions. The first is called CreateVM. This will do the following actions:
If the VM already exists it will be deleted
Create the cloud service
Create the VM from the template I have created
Add an endpoint so we can RDP to them all over the same port
Download the RDP file so there is a short cut the trainees can easily access the machine via
Write settings for the machine to a log file
function
CreateVM($machineNo)
{
# Specify a name for the new VM
$machineName
=
"$baseVMName-$machineNo"
Write-Host
"Creating VM: $machineName"
# Get the Azure VM Image
$myImage
=
Get-AzureVMImage
$vmTemplate
#If the VM already exists delete and re-create it
$existingVm
=
Get-AzureVM
-Name
$machineName
-ServiceName
$serviceName
if($existingVm
-ne
$null)
{
Write-Host
"VM already exists so deleting it"
Remove-AzureVM
-Name
$machineName
-ServiceName
$serviceName
}
"Creating Service"
$serviceName
=
"bupa-azure-train-$machineName"
Remove-AzureService
-Force
-ServiceName
$serviceName
New-AzureService
-Location
$dataCenter
-ServiceName
$serviceName
Write-Host
"Creating VM: $machineName"
New-AzureQuickVM
-Windows
-name
$machineName
-ServiceName
$serviceName
-ImageName $myImage.ImageName -InstanceSize $size
-AdminUsername
$adminUserName
-Password
$password Write-Host
"Updating the RDP endpoint for $machineName"
Get-AzureVM
-name
$machineName
-ServiceName
$serviceName `
|
Add-AzureEndpoint
-Name
RDP
-Protocol
TCP
-LocalPort
3389
-PublicPort
550 `
|
Update-AzureVM
Write-Host
"Get the RDP File for machine $machineName"
$machineRDPFilePath
=
"$rdpFilePath\$machineName.rdp"
Get-AzureRemoteDesktopFile
-name
$machineName
-ServiceName
$serviceName
-LocalPath
"$machineRDPFilePath"
WriteMachineSettings
"$machineName"
"$serviceName"
}
The delete machine settings function is used to delete the log file before we start re-running the process.
function
DeleteMachineSettings()
{
Write-Host
"Deleting the machine settings output file"
[System.IO.File]::Delete("$machineSettingsPath");
}
The write machine settings function will get the VM and then record its details to the log file. The importance of the log file is that I can easily provide the information for all of the VM's to our infrastructure team to be able to configure access to all of the VM's
function
WriteMachineSettings([string]$vmName,
[string]$vmServiceName)
{
Write-Host
"Writing to the machine settings output file"
$vm
=
Get-AzureVM
-name
$vmName
-ServiceName
$vmServiceName
$vmEndpoint
=
Get-AzureEndpoint
-VM
$vm
-Name
RDP
$sb
=
new-object
System.Text.StringBuilder
$sb.Append("Service Name: ");
$sb.Append($vm.ServiceName);
$sb.Append(", ");
$sb.Append("VM: ");
$sb.Append($vm.Name);
$sb.Append(", ");
$sb.Append("RDP Public Port: ");
$sb.Append($vmEndpoint.Port);
$sb.Append(", ");
$sb.Append("Public DNS: ");
$sb.Append($vmEndpoint.Vip);
$sb.AppendLine("");
[System.IO.File]::AppendAllText($machineSettingsPath, $sb.ToString());
}
# end functions
Rest of Script
In the rest of the script it is really just the bit that orchestrates the actions we want to happen. It will load the publisher settings, select the Azure subscription and then loop around the CreateVM function and create 16 VM's
Import-AzurePublishSettingsFile
$azurePublisherSettings
Set-AzureSubscription
-SubscriptionName
$subscriptionName
-CurrentStorageAccount
$defaultStorageAccount
Select-AzureSubscription
-SubscriptionName
$subscriptionName
DeleteMachineSettings
"Starting creating Bupa International Azure Training Lab"
$numberOfVMs
=
16
for ($index=1; $index -le $numberOfVMs; $index++)
{
$vmNo
=
"$index"
CreateVM($vmNo);
}
"Finished creating Bupa International Azure Training Lab"
# Give it a Minute
Start-Sleep
-s
60
$endTime
=
get-date
"Script run time "
+ ($endTime
-
$startTime)
Conclusion
As you can see there is nothing too fancy about this script but in our case of creating a small isolated training lab which is not connected to our corporate network then we can easily use this to provision the lab. Im sure if this is of use to anyone you can easily modify it to do other things with the lab environment too.
A couple of points to note are that there are some soft limits in Azure about the number of cores and services your subscription can use. You may need to contact the Azure support team to be able to increase this limit.
In terms of the real business value of this approach, it was not possible to use the existing desktops to do the training on, and getting some internal virtual machines would have been relatively expensive and time consuming for our ops team to do. With the Azure option we are able to spin these machines up for a temporary period during the training course and then throw them away when we are done. We expect the costing of this test lab to be very small, especially considering we have EA pricing.
As a ball park I think my 18 lab VM training environment will cost in the region of $80 per day on our EA. This is a fraction of the cost of the creation of a single VM on premise.