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 !