Starting and stopping a VM using Azure Automation

Posted on Wednesday, September 9, 2015

There have been some people already who have blogged about Azure automation of Virtual Machines.
For my use case I needed a slightly different set up, so here is my use of Azure Automation.
My development machine is a Windows 10 Azure D3 VM which is running in my MSDN subscription.
Since my subscription has a limit on it, I really needed to make sure that I didn't have the VM runnning when I'm not using it.

So I decided to use Azure Automation to start the VM each weekday at 8AM and stop it each weekday at 6PM.

The first thing to do is to create a user in the Active Directory, this user will be used for the credentials in the Automation script.

After you created this user, you need to sign in to the Azure portal using this user so you can create a new password.

Now we need to let Automation know about this user.
Select your Automation account, or create one if you don't have on yet, and in the Assets tab add a setting for type Credentials, using the credentials of the user created earlier.

Now we're all set to create the actual automation script. First we need to create a new runbook, which can be easily done by selecting New => Automation => Runbook => quick create. You can give it any name you like, I just used Start-AzureVirtualMachine.
Now for the actual Powershel script, go to the Author tab and in the Draft section copy the following code:

Workflow Start-AzureVirtualMachine
{
    Param
    (   
        [Parameter(Mandatory=$true)]
        [String]
        $subscriptionName,

        [Parameter(Mandatory=$true)]
        [String]
        $credentials,
        
        [Parameter(Mandatory=$true)]
        [String]
        $vmName,
        
        [Parameter(Mandatory=$true)]
        [String]
        $cloudServiceName,
        
        [Parameter(Mandatory=$true)]
        [String]
        $daysOfWeekToExecute 
    )

	$dayOfWeek = [int](Get-Date).DayOfWeek + 1
	Write-Output "DayOfWeek $dayOfWeek"

	$dayToExecute = ""
	if ($daysOfWeekToExecute.Length -gt $dayOfWeek)
	{
		$dayToExecute = $daysOfWeekToExecute.substring($dayOfWeek - 1, 1)
	}
	Write-Output "DayToExecute value: $dayToExecute"
	if ($dayToExecute -eq "X" -or $dayToExecute -eq "x")
	{
	    Write-Output $credentials
	    $Cred = Get-AutomationPSCredential –Name $credentials
	    Write-Output $Cred

		Add-AzureAccount -Credential $Cred

		Write-Output "Select subscription"
		Select-AzureSubscription -SubscriptionName $subscriptionName

		foreach ($vm in $vmName.split(","))
		{
		    Write-Output "Starting VM $vm"
		    Start-AzureVM -ServiceName $cloudServiceName -Name $vm
		    Write-Output "VM $vm has been started"
		}
	}
	else
	{
		Write-Output "Skipping this day of the week"
	}
}

Now Save this script and then Publish it and after that we can create a schedule to run this script.
For this we need to select the Link to a new schedule in the Schedule tab.
Give the schedule some nice name and then enter all the details of the VM you want to automatically start.

The important thing to remember is the daysOfWeekToExecute.
It starts at Monday and the script will execute for every day the value equals X or x.
So if you only want to run the script on Monday and Thursday the value would be X--X---.

For stopping the VM, we can do pretty much the same thing except the script is slightly different.
The only real difference are the calls to Start-AzureVM and Stop-AzureVM.

Workflow Stop-AzureVirtualMachine
{
    Param
    (   
        [Parameter(Mandatory=$true)]
        [String]
        $subscriptionName,

        [Parameter(Mandatory=$true)]
        [String]
        $credentials,
        
        [Parameter(Mandatory=$true)]
        [String]
        $vmName,
        
        [Parameter(Mandatory=$true)]
        [String]
        $cloudServiceName,
        
        [Parameter(Mandatory=$true)]
        [String]
        $daysOfWeekToExecute 
    )

	$dayOfWeek = [int](Get-Date).DayOfWeek + 1
    Write-Output "DayOfWeek $dayOfWeek"

	$dayToExecute = ""
	if ($daysOfWeekToExecute.Length -gt $dayOfWeek)
	{
		$dayToExecute = $daysOfWeekToExecute.substring($dayOfWeek - 1, 1)
	}
	Write-Output "DayToExecute value: $dayToExecute"
	if ($dayToExecute -eq "X" -or $dayToExecute -eq "x")
	{
	    Write-Output $credentials
	    $Cred = Get-AutomationPSCredential –Name $credentials
	    Write-Output $Cred

		Add-AzureAccount -Credential $Cred

		Write-Output "Select subscription"
		Select-AzureSubscription -SubscriptionName $subscriptionName

		foreach ($vm in $vmName.split(","))
		{
		    Write-Output "Stopping VM $vm"
		    Stop-AzureVM -ServiceName $cloudServiceName -Name $vm
		    Write-Output "VM $vm has been stopped"
		}
	}
	else
	{
		Write-Output "Skipping this day of the week"
	}
}

Using these scripts it is also possible to start or stop multiple VM's in the same Cloud Service.
Simply specify a comma-separated value as the vmName, like this: vmName1,vmName2


Disclaimer: Any views or opinions expressed on this blog are my own personal ones and do not represent my employer in any way.