Like many people we want to shutdown Azure VM’s when they are not being used, however with different time zones and working schedules this can vary. The obvious way is to shutdown VM’s based on Tags.
Jobs can be scheduled through the Automation Account or via a Logic App if preferred.
The script was originally created by Christopher Scott, however it was using the older commands. I’ve updated the commands and also allowed for the tag name to be set as a Runbook Parameter when executing, these can easily be changed. This script is set to use an Azure RunAs Automation Account, but this can of course be run interactively by removing this section. The script is set to use a Tag called “ShutdownCycle” you can change this to whatever you want.
Shutdown Script
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
param ([parameter(Mandatory=$true)] [string]$TagValue ) ##################### Connect to Azure using RunAsAccount ##################### $connectionName = "AzureRunAsConnection" try { $servicePrincipalConnection=Get-AutomationConnection -Name $connectionName "Logging in to Azure..." Connect-AzAccount ` -ServicePrincipal ` -TenantId $servicePrincipalConnection.TenantId ` -ApplicationId $servicePrincipalConnection.ApplicationId ` -CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint } catch { if (!$servicePrincipalConnection) { $ErrorMessage = "Connection $connectionName not found." throw $ErrorMessage } else{ Write-Error -Message $_.Exception throw $_.Exception } } #This is where you would set your custom Tags Keys and Values $VMs = Get-AzVm | Where {$_.Tags.Keys -contains "ShutdownCycle" -and $_.Tags.Values -contains "$TagValue"} | Select Name, ResourceGroupName, Tags ForEach ($VM in $VMs) { $VMStatus2 = Get-AzVM -Name $VM.Name -ResourceGroupName $VM.ResourceGroupName -Status | Select Name, ResourceGroupName, DisplayStatus, Tags $VMN=$VM.Name $VMRG=$VM.ResourceGroupName If ($VMStatus2 = "VM Running") { Stop-AzVM -Name $VMN -ResourceGroupName $VMRG -force "$VMN is Shutdown and Deallocated" } } |
Start Up Script
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
param ([parameter(Mandatory=$true)] [string]$TagValue ) ##################### Connect to Azure using RunAsAccount ##################### $connectionName = "AzureRunAsConnection" try { $servicePrincipalConnection=Get-AutomationConnection -Name $connectionName "Logging in to Azure..." Connect-AzAccount ` -ServicePrincipal ` -TenantId $servicePrincipalConnection.TenantId ` -ApplicationId $servicePrincipalConnection.ApplicationId ` -CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint } catch { if (!$servicePrincipalConnection) { $ErrorMessage = "Connection $connectionName not found." throw $ErrorMessage } else{ Write-Error -Message $_.Exception throw $_.Exception } } #This is where you would set your custom Tags Keys and Values $VMs = Get-AzVm | Where {$_.Tags.Keys -contains "ShutdownCycle" -and $_.Tags.Values -contains "$TagValue"} | Select Name, ResourceGroupName, Tags ForEach ($VM in $VMs) { $VMStatus2 = Get-AzVM -Name $VM.Name -ResourceGroupName $VM.ResourceGroupName -Status | Select Name, ResourceGroupName, DisplayStatus, Tags $VMN=$VM.Name $VMRG=$VM.ResourceGroupName If ($VMStatus2 = "VM Running") { Start-AzVM -Name $VMN -ResourceGroupName $VMRG "$VMN is Started" } } |
Hope this helps!
Hi Rich.
Thanks for sharing it.
I have VMs hosted in different resource groups, will these scripts works for my entire subscription or for a specific resource group?
Thank you so much and congrats for the blog.
Marcus
Hi there!
It’s configured to work for specific resource groups, that said, it should be possible to configure for usage against everything in a subscription.
Thanks!