Managing Windows Azure VMs through PowerShell

I make no secret of the fact that I love PowerShell - all the jokes about it being a mechanism to turn IT Pro's into developers without them realising it aside, you can do some seriously powerful stuff with it. This week I got my head around a few more things I can script up with it, and the area of focus was on managing my Windows Azure virtual machines. There is an Azure PowerShell module that you can install and configure to be able to easily connect to your subscription (only takes a couple of minutes to set up, the instructions are at https://www.windowsazure.com/en-us/documentation/articles/install-configure-powershell/) and once that's done you can start getting in to some scripting

Powering on and shutting down virtual machines

One of the things I use the Azure Management Portal for the most is to log in and start up and shut down my virtual machines. It's not the most complex task, but it's something I do frequently - so I wanted to script it so that I don't need to do it manually every day. Lucky for me this is very straightforward. To turn a VM on:

 Start-AzureVM -ServiceName " {Cloud service name} " -Name " {VM Name} "

And then off again:

 Stop-AzureVM -ServiceName " {Cloud service name} " -Name " {VM Name} " -Force

That's about as easy as it's ever going to get! Just substitute in your cloud service and VM names and you are good to go. Now the Force attribute on the end of the Stop-AzureVM cmdlet is used to bypass a message that will come up when you shut down the last VM in a deployment, as this will mean that you lose the public IP address assigned to the VMs. You can add an additional flag to this though to tell the machines to shut down but to not de-provision, which will keep the IP address active. This might be useful for production environments where public DNS is depending on the IP address, but in my case this is for a dev environment and I don't care what the public IP is, so I can happily force the shut down and de-provision.

Deleting a virtual machine

The next thing I looked at was a process to delete and recreate virtual machines, so step one was a script to delete a machine so I could create it again from a base image. Lucky for us, this is straightforward too.

 Remove-AzureVM -ServiceName  "{Cloud service name} " -Name " {VM name} " -DeleteVHD

Again substitute in the service and VM names and you're done. The DeleteVHD tells Azure to delete the virtual disk from the storage account as well, so you can use that or leave it as you need to.

Creating a virtual machine

Now that the old machine was deleted I could recreate it, here is the script for it, I'll explain it line by line below

 $newVM = New-AzureVMConfig -Name " {new VM name} " -InstanceSize  {Instance size}  -ImageName  {Image file name}  -HostCaching ReadWrite -DiskLabel "OS" -MediaLocation "https:// {Storage account URL} .blob.core.windows.net/vhds/ {disk name} .vhd" |
 Add-AzureProvisioningConfig -WindowsDomain -AdminUsername " {admin user} " -Password " {password} " -Domain " {NetBIOS domain name} " -DomainUserName " {domain user} " -DomainPassword " {domain password} " -JoinDomain " {FQDN of domain} " |
 Set-AzureSubnet -SubnetNames " {Subnet name} "
 New-AzureVM -VMs $newVm -ServiceName  {Cloud service name} 

There are a few things going on here, and through some pipes the commands string together a little - at it's core we are doing two things, the first we are establishing the config for the machine, and the second part we are actually creating it. The line at the bottom with the New-AzureVM command is the one were we create it, its everything above it that looks a little scarier, but when you break it down it's all straight forward.

The first command is New-AzureVMConfig - this gives us the base configuration object and in my example I set the following options:

  • new VM name - the name of the new machine
  • Instance size - what size is the VM? (Small, A5, etc)
  • Image name - the VHD image to base the VM off, I'll explain how to look up an image below
  • Storage account URL and file name - details of where the disk will live for this VM

Next we pipe the output of that to the Add-AzureProvisioningConfig command, which allows us to extend the initial config with some additional parameters. In my example I'm specifying some settings that will tell the provisioning to join the VM to an existing domain that I have already provisioned on the network, so here I specify some options to support that:

  • admin user - the name of the local administrator account
  • password - the password of the local administrator account
  • NetBIOS domain name - exactly what it sounds like, so in a domain of "contoso.local" this will usually be "CONTOSO"
  • Domain user - credentials of a user that has access to allow the machine to be added to the domain
  • Domain password - the password of the above account
  • FQDN of domain - the fully qualified domain name (eg. "contoso.local")

The last part of the command is to pipe it to the Set-AzureSubnet command - this lets us specify the name of the subnet to join, which needs to be specified in my example as the network already exists. Once you put it all together you end up with an object called $newVM which I pass to the final New-AzureVM command, where I add the cloud service name that it will execute within, and then the command goes to work.

Looking up VM images

As part of the above process I had to specify an image name for the virtual machine to be based on - you can look these up easily with the Get-AzureVMImage cmdlet. This will return a list of all available images which you can filter your way through as you need, finding the image you need and then passing the ImageName property of the appropriate image object in to the above script. For example, at the time of me writing this I was using a Server 2012 image which had an imagename of "a699494373c04fc0bc8f2bb1389d6106__Windows-Server-2012-Datacenter-201312.01-en.us-127GB.vhd"

 

So there you have it, some cool scripts to start automating virtual machine use in Windows Azure. There is a whole lot more you can do with this than what I have shown here, below is a good article to get you started.