Automated VM provisioning

The use cases for PowerCLI and automation continue to amaze me, a couple of nice use cases I have seen recently involve automating the deployment of VM’s for various reasons.

The first reason, performance, what happens when a VM which is sat there for most of the year suddenly becomes busy and doesn’t have enough resources to satisfy whatever service it is trying to provide, do you add more ram, more CPU, what happens when you get to the maximum 8 CPU’s and the maximum vSphere VM memory of 255GB, do you then deploy a second VM and a third etc etc

Take this scenario into consideration:

You work in the UK for a county wide radio station, most of the time your virtualised cluster of web servers is sat there doing nothing, serving the odd hit now and again…but then it snows !

As we know, the UK can not handle snow at the best of times, the country grinds to a halt, the only means of knowing if your children’s school is closed is to check the local radio station’s website….enter our problem.

As you are also snowed in and unable to make it to the office you are unable to build the VM’s and add them to the cluster to allow the existing VMs which are now stuck on 100% CPU usage whilst you dig your car out.

Wouldn’t it be nice if we could have an automated response to this ? I held aloft my sword and said “With the power of CLI” (He-Man fans will get this).

I have two methods for this, the first one is a great script and the second is a bit of fun to show exactly how powerful PowerShell and PowerCLI can be.

Automation Script 1

This script takes advantage of vSphere Alarms, the idea is to set an alarm on your VM which hosts the website, set an Alert to activate a script as shown on the PowerCLI blog, once the VM’s CPU hits our magic number, 75% – 90% maybe, we can run our script which deploys a templated VM, once deployed with your custom OS specification the VM automatically joins the cluster and takes some of the load from the original web server.

The script:

# Get our Web Server
$OriginalSRV = Get-VM "RadioWebServer"

# Get the OS Customisation spec we want to use
$Spec = Get-OSCustomizationSpec "Radio Web Server"

# Get our templated VM
$Template = Get-Template "Radio Web Server Template"

# Get the Cluster the web server is in
$OriginalCluster = $OriginalSRV | Get-Cluster

# Get a Date time number we can use for a unique, identafiable name
$DateTime = (Get-Date).Ticks
$NewName = $OriginalSRV.Name + "-$DateTime"

# Find the least used host in that cluster
$NewHost = $OriginalCluster | Get-VMHost | Sort $_.CPuUsageMhz -Descending | Select -First 1

# Find a datastore on that host with enough room
$OriginalSRV | Select -ExpandProperty HardDisks | Foreach { $Total += $_.CapacityKB }
$SpaceNeeded = $Total * 1.1  / 1MB # Add 10%
$NewDatastore = $NewHost | Get-Datastore | Where { $_.FreespaceMB -gt $SpaceNeeded } | Select -First 1

Write-Host "Creating $NewName on... `n Host: $($NewHost.Name) `n Datastore: $($NewDatastore.Name)"

$CreatedVM = New-VM -RunAsync -Name $NewName -OSCustomizationSpec $Spec -VMHost $NewHost -Template $Template -Datastore $NewDatastore

Automation Script 2

This one is just a bit of fun really but run once in the morning it could check the weather to see if it will snow and then deploy a VM ready for the onslaught of traffic !

$weather = New-WebServiceProxy -uri "http://www.webservicex.net/globalweather.asmx?wsdl"
[xml]$CurrentWeather = $weather.GetWeather('London', 'United Kingdom')
If ($CurrentWeather.currentweather.skyconditions -like "*snow*"){
	# Get our Web Server
	$OriginalSRV = Get-VM "RadioWebServer"

	# Get the OS Customisation spec we want to use
	$Spec = Get-OSCustomizationSpec "Radio Web Server"

	# Get our templated VM
	$Template = Get-Template "Radio Web Server Template"

	# Get the Cluster the web server is in
	$OriginalCluster = $OriginalSRV | Get-Cluster

	# Get a Date time number we can use for a unique, identafiable name
	$DateTime = (Get-Date).Ticks
	$NewName = $OriginalSRV.Name + "-$DateTime"

	# Find the least used host in that cluster
	$NewHost = $OriginalCluster | Get-VMHost | Sort $_.CPuUsageMhz -Descending | Select -First 1

	# Find a datastore on that host with enough room
	$OriginalSRV | Select -ExpandProperty HardDisks | Foreach { $Total += $_.CapacityKB }
	$SpaceNeeded = $Total * 1.1  / 1MB # Add 10%
	$NewDatastore = $NewHost | Get-Datastore | Where { $_.FreespaceMB -gt $SpaceNeeded } | Select -First 1

	Write-Host "Creating $NewName on... `n Host: $($NewHost.Name) `n Datastore: $($NewDatastore.Name)"

	$CreatedVM = New-VM -RunAsync -Name $NewName -OSCustomizationSpec $Spec -VMHost $NewHost -Template $Template -Datastore $NewDatastore
}

Note these scripts are just to show you what we can do, if I was to use them in production I would obviously add more error checking !

13 thoughts on “Automated VM provisioning

  1. Pingback: Get-Scripting Podcast Episode 16 – (Ed Wilson – The Scripting Guy) | CrypticZero

  2. Pingback: Orchestrator 2012 Integration with SCOM, SCVMM,VMware and SCSM | Leon Taljaard – System Center

  3. Pingback: All things Virtual V « TheSaffaGeek

  4. Virtu-Al

    @Chris,

    Yeah thats a nice way to do it but its worth noting that you are assuming you have enough room on the databases, mine checks the size of the original VM and makes sure that space is on the disk.

    Obviously if I was to take this script further we would put some nice error checiking in there to do both and also send an email if there was not enough room etc.

    Thanks for the comment, I love people adding their own code.

  5. Chris

    I use this to find the datastore with the most free space for my (still rough) script that deploys VMs using a CSV file as input. Sometime soon I need to add in logic for our free space buffer and if no disks have enough free space. Also, I wrote it a few months ago and just pasting it here I see some things I can improve. 🙂

    ==================
    #Parameter- Name of the VMware cluster the VM will be assigned to
    param ($cluster)

    #get alphabetically last ESX host in the VMware cluster (it’s likely the last host added to the cluster, so this might smoke out any problems)
    $vmh = get-vmhost -Location $cluster | Select-Object -Property Name | Sort-Object Name | Select -Last 1 -Property Name

    #select the LUN with the most free space
    $luns = Get-Datastore -VMHost $vmh.Name

    $dst = $luns | Where-Object { $_.Type -eq “VMFS” } | Sort-Object FreeSpaceMB | Select-Object -Last 1 -Property Name

    write-output $dst

  6. Virtu-Al

    Mike, Glad you got it working, allworks fine for me on my home lab and at work, not sure I get the issue

    Glad its working now, thanks fo the comments.

  7. Mike R

    Actually-I was able to cast the $Total var and then all worked beautifully-thanks much for the code!

    $OriginalSRV | Select -ExpandProperty HardDisks | Foreach { [int]$Total += $_.CapacityKB }

  8. Mike R

    Hey,
    great scripts-but one question-it’s not picking up a datastore because querying the disks on line 24 and then adding for required size is actually concatenating, not adding, so you never find a datastore with enough room. I’ve tried an explicit cast for $_.CapacityKB values to int, but no luck. It will work if I manually specify a value for the $NewDatastore var…

    $OriginalSRV | Select -ExpandProperty HardDisks | Foreach { $Total += $_.CapacityKB }

  9. Virtu-Al

    Yeah shouldnt be too bad, just a VM which runs a batch file as part of the sysprep.

    Im glad you enjoyed the weather addin, just shows the power of PowerShell

  10. Ionut Nica

    Nice post, the weather stuff was particularly funny 🙂

    The real magic lies within the templated VM, which is prepped to join the load balancing fun:)

  11. Pingback: uberVU - social comments

  12. Virtu-Al

    Yeah I agree, this was more of a proof of concept to show people what could be done.

    We could obviously have a script to do the reverse and remove teh VM’s once they are no loger needed.

    Thanks for the comment.

  13. Michael Keen

    Great post Alan. I like the idea here of using the power of Powershell, but I also wanted to point out that besides automating the creation of VMs to handle the load, you need to also to add some sort of lifecycle mgmt to remove those VMs to recapture the resources that you consumed. Just want to point out the obvious elephant in the room here. You know this as well as I do, this is why so many companies are dealing with virtual sprawl today.

    Use the power of PoSh to manage that lifecycle and you have a killer use case.

Leave a Reply to Mike R

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.