StopStartVM.ps1
<#PSScriptInfo .DESCRIPTION Azure Automation Workflow Runbook Script to stop or start all Virtual Machines in the current subscription or in a specific Resource Group. Useful for dev and test environments. Written to be used as either a scheduled job at the close of business or ad hoc when VMs are finished with for the moment. If the VM is tagged with ShutdownPolicy = Excluded, the VM is not stopped. VMs are also not stopped if it is already managed by a schedule. May exclude VMs using tag. Requires an Azure Automation account using System Managed Identity. .VERSION 1.0.6 .GUID 81441e5f-d154-4666-97cf-b8f3decb9341 .AUTHOR Rob Goodridge .COPYRIGHT (c) 2020 Rob Goodridge. All rights reserved. .TAGS Azure Automation Cloud AzureAutomation AzureDevOps DevOps AzureRM Workflow Runbook .LICENSEURI .PROJECTURI .ICONURI .EXTERNALMODULEDEPENDENCIES .REQUIREDSCRIPTS .EXTERNALSCRIPTDEPENDENCIES .RELEASENOTES 1.0.1: - Add initial version 1.0.2: - Gallery text changes 1.0.3: - Use Connect-AzureAutomation module 1.0.4: - Deal with 0 VMs 1.0.5: - Update to Managed Identity and Az Modules 1.0.6: - Edit synopsis #> <# .SYNOPSIS Stop or start all Virtual Machines in the current subscription or in a specific Resource Group, exclude by tag .PARAMETER ResourceGroupName The Azure resource group name or leave empty to target ALL VMs in the current subscription .PARAMETER Action Specify either 'stop' or 'start' to stop or start the VMs. #> workflow StopStartVM { Param ( [Parameter(Mandatory=$true)] [ValidateSet("Start","Stop")] [String] $Action, [Parameter(Mandatory=$false)] [String] $AzureResourceGroup ) try { "Logging in to Azure..." Connect-AzAccount -Identity } catch { Write-Error -Message $_.Exception throw $_.Exception } $DevTestLabs = Get-AzResource | Where-Object {$_.ResourceType -eq "Microsoft.DevTestLab/schedules"} $RGIsNull = [String]::IsNullOrWhiteSpace($AzureResourceGroup) if ( $RGIsNull ) { "All VMs" $VMs = Get-AzVM -Status # $VMs = @(Get-AzureRmVM -Status | Select-Object ResourceGroupName,Name,Location, tags, @{ label = "VMStatus"; Expression = { $_.PowerState } }) } else { "Resource Group filter $AzureResourceGroup" $VMs = @(Get-AzVM -ResourceGroupName $AzureResourceGroup -Status) } "Processing VMs" if ( $VMs ) { # $VMs if ( $Action -eq "Stop") { Write-Output "Stopping VMs" foreach -parallel ($vm in ($VMs) ) { $vm.Name $ShutDownName = "shutdown-computevm-{0}" -f $vm.Name if ($vm.PowerState -eq "VM running" -and $vm.Tags["ShutdownPolicy"] -ne "Excluded" -and (-not $DevTestLabs -or ($DevTestLabs.Name -notcontains $ShutdownName) )) { Write-Output "Stopping VM '$($vm.ResourceGroupName)/$($vm.name)'" Stop-AzVm -ResourceGroupName $vm.ResourceGroupName -Name $vm.name -Force -Verbose } else { Write-Output "Skipping VM '$($vm.ResourceGroupName)/$($vm.name)'" } } } else { Write-Output "Starting VMs" foreach -parallel ($vm in ($VMs) ) { $vm.Name if ($vm.PowerState -ne "VM running") { Write-Output "Starting VM '$($vm.ResourceGroupName)/$($vm.name)'" Start-AzVm -ResourceGroupName $vm.ResourceGroupName -Name $vm.name -Verbose } else { Write-Output "Skipping VM '$($vm.ResourceGroupName)/$($vm.name)'" } } } "Runbook Complete" } else { Write-Output "There are 0 VMs matching the criteria" } } |