Startup/Shutdown VMs in Azure after hours – Gotchas

A few of our VMs (Dev/test servers) don’t need to be on overnight so we have some scripts to shut them down. This is a little bit tricky in Azure because of the runbook credentials. These are easy to create, a good post here about it. But in all the articles I’ve read, no one mentions that the passwords in Azure AD expire, so every 90 days or so you have to go in and rest your passwords.

Another gotcha I ran into was that with the run books, errors don’t make them fail, only exceptions do. So i had to check for error states and throw.

So when my automation user’s credentials expired and started throwing errors, I got no alerts about this. Until that was, someone read that months bill 🙂

AzureRunbookStatusCompleteButErrorFromScript

So I’ve put together a little post on how to work around these as it’s not easy.

First of all, lets assume you have followed the above post already and have automation credentials already.

You then need to use powershell to set the user’s password to never expire. To do this you need download and install the following.

  1. Microsoft Online Services Sign-In Assistant for IT Professionals RTW
  2. Windows Azure Active Directory Module for Windows PowerShell 

After that you can use the following PowerShell script from you local to set the user’s password never to expire

WARNING: You cannot use a Microsoft LIVE account to run this script, you need to use an organisational account.


Import-Module MSOnline
# you cannot login with a LVIE account, it must be an organisational account
Connect-MsolService
Set-MsolUser -UserPrincipalName "myaccount@myorg.onmicrosoft.com" -PasswordNeverExpires $true

Now below is my shutdown and startup scripts that i set on a Schedule, with error detection for common errors in them

workflow shutdown
{
$Cred = Get-AutomationPSCredential -Name 'MyAutomationCred'

$a = Add-AzureAccount -Credential $Cred -ErrorAction Stop
if ($a.Subscriptions) {
Write-Output 'User Logged in'
} else {
throw 'User logged in with no subscriptions'
}
InlineScript
{
Select-AzureSubscription 'MySubscription'
#Array of server names here
$VMS = "web02","web03"
ForEach ($VM in $VMS)
{
$aVM = get-azurevm $VM
if($aVM -eq $null)
{
throw "Unable to get VM, check permissions perhaps?"
}
$VMName = $aVM.Name
Write-Output "Attempting to stop VM: $VMName"
Stop-AzureVM -ServiceName $aVM.ServiceName -StayProvisioned $true -Name $aVM.Name
}
}
}

 


workflow startup
{
$Cred = Get-AutomationPSCredential -Name 'MyAutomationCred'

$a = Add-AzureAccount -Credential $Cred -ErrorAction Stop
if ($a.Subscriptions) {
Write-Output 'User Logged in'
} else {
throw 'User logged in with no subscriptions'
}
InlineScript
{
Select-AzureSubscription 'MySubscription'
#Array of server names here
$VMS = "web02","web03"
ForEach ($VM in $VMS)
{
$aVM = get-azurevm $VM
if($aVM -eq $null)
{
throw "Unable to get VM, check permissions perhaps?"
}
$VMName = $aVM.Name
Write-Output "Attempting to start VM: $VMName"
Start-AzureVM -ServiceName $aVM.ServiceName -Name $aVM.Name
}
}
}

You will note the checks and throws as Errors are ignored by the runbook.

 

One thought on “Startup/Shutdown VMs in Azure after hours – Gotchas

Leave a comment