Scale-AzureRMVMDownRunbook.ps1
<#PSScriptInfo .VERSION 1.1.0 .GUID 4e1d1e4a-baeb-4581-8f8e-6406fe424340 .AUTHOR Arjun Bahree .COMPANYNAME .COPYRIGHT (c) 2018 Arjun Bahree. All rights reserved. .TAGS Windows PowerShell Azure AzureAutomation Runbooks AzureManagedDisk AzureUnmanagedDisk AzureDataDisk AzureStorage .LICENSEURI https://github.com/bahreex/Bahree-PowerShell-Library/blob/master/LICENSE .PROJECTURI https://github.com/bahreex/Bahree-PowerShell-Library/tree/master/Azure%20Automation%20Runbooks .ICONURI .EXTERNALMODULEDEPENDENCIES AzureRM .REQUIREDSCRIPTS .EXTERNALSCRIPTDEPENDENCIES .RELEASENOTES #> <# .DESCRIPTION Lets you Scale down any Azure RM VM from its current size to a new size within the same Family. #> <# .SYNOPSIS Lets you Scale down any Azure RM VM from its current size to a new size within the same Family. .DESCRIPTION This Runbook lets you Scale down any Azure RM VM from its current Size to a new size that you specify. By default the new size to scale is Immediately before the current size in the Size Table published by Microsoft, which means the SizeStep parameter with value -1. However, if you specify another value for SizeStep parameter, which should be lesser than your current VM size number in the Size Table, your VM will be scaled down to that Size in the Size table corresponding to that number. If your VM is already at the most basic size for the VM family, you will not be able to scale down the VM any further as cross-family resizing is not allowed by Microsoft Azure. Since Microsoft does not make the VM Size Table available in a format that cna be consumed programmatically for reference, I have manually created the same and publicly shared through a Gist in my Github repository. The URL for the Gist is embedded in the Runbook code, which I will regularly update as and when Microsoft updates the VM Size table. You can find the most current VM Size table at the Gist URL (https://gist.github.com/bahreex/96a611b5ca05de2df2c3d7f45b11b75d) and within this repository as a CSV file named "Azure-VM-Sizes-29122017.csv". You need to execute this Runbook through a 'Azure Run As account (service principal)' Identity from an Azure Automation account. .Parameter ResourceGroupName Name of the Resource Group where the target VM is located .Parameter VMName Name of the target VM .Parameter SizeStep Scalar value between -1 to -8. This has a default value of -1, which will resize the VM to Immediately before size within same VM family within the Size Table. The value you specify in this parameter, which should be lesser than your current VM size number in the Size Table, will be used to scale down your VM to that Size in the Size table corresponding to the specified number. .EXAMPLE .\Scale-AzureRMVMDown.ps1 -ResourceGroupName rg-100 -VMName vm100 -SizeStep -2 .EXAMPLE .\Scale-AzureRMVMDown.ps1 -ResourceGroupName rg-100 -VMName vm100 .Notes Author: Arjun Bahree E-mail: arjun.bahree@gmail.com Creation Date: 11/Jan/2018 Last Revision Date: 15/Jan/2018 Development Environment: Azure Automation Runbook Editor and VS Code IDE PS Version: 5.1 Platform: Windows #> param ( [Parameter(Mandatory = $true)] [string]$ResourceGroupName, [Parameter(Mandatory = $true)] [string]$VMName, [Parameter(Mandatory = $false)] [ValidateRange(-8, -1)] [int]$SizeStep = -1 ) if (!(Get-AzureRmContext).Account) { $connectionName = "AzureRunAsConnection" try { # Get the connection "AzureRunAsConnection " $servicePrincipalConnection = Get-AutomationConnection -Name $connectionName Add-AzureRmAccount ` -ServicePrincipal ` -TenantId $servicePrincipalConnection.TenantId ` -ApplicationId $servicePrincipalConnection.ApplicationId ` -CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint > $null } catch { if (!$servicePrincipalConnection) { $ErrorMessage = "Connection $connectionName not found." throw $ErrorMessage } else { Write-Error -Message $_.Exception throw $_.Exception } } } # Create Stopwatch and Start the Timer $StopWatch = New-Object -TypeName System.Diagnostics.Stopwatch $StopWatch.Start() function ResizeVM ($rgName, $vmName, $newVMSize) { Write-Output "Scaling-Down $vmName to $newVMSize ... this will require a Reboot!" $vmRef = Get-AzureRmVM -ResourceGroupName $rgName -Name $vmName $vmRef.HardwareProfile.VmSize = $newVMSize Update-AzureRmVM -VM $vmRef -ResourceGroupName $rgName -AsJob > $null Get-Job | Wait-Job | Receive-Job > $null } Write-Output "Starting the VM Scaling-Down Process." $VM = Get-AzureRmVM -ResourceGroupName $ResourceGroupName -Name $VMName -ErrorAction SilentlyContinue if ($VM) { $vSize = $VM.HardwareProfile.VmSize $vmSizeURL = "https://gist.githubusercontent.com/bahreex/96a611b5ca05de2df2c3d7f45b11b75d/raw/bf2065fd27171d616b6c2373d58a387a82dff114/Azure-VM-Sizes-29122017.csv" $content = (Invoke-WebRequest -Uri $vmSizeURL -UseBasicParsing).Content $vmSizes = $content.Split("`r`n") $vmFamilyList = @() foreach ($line in $vmSizes) { $row = $line.split(','); if ($row -contains $vSize) { $index = $row.IndexOf($vSize) $count = 0 foreach ($subLine in $vmSizes) { $subRow = $subLine.split(','); if ($count -eq 0) { $vmFamily = $subRow[$index] } else { if ($subRow[$index]) { $vmFamilyList += $subRow[$index] } } $count++ } break } } $nextSizeIndex = $vmFamilyList.IndexOf($vSize) + $SizeStep if ($nextSizeIndex -lt 0) { # Stop the Timer $StopWatch.Stop() Write-Output "The VM $($VM.Name) is at the minimum allowed size for the $vmFamily family." } else { ResizeVM $ResourceGroupName $VMName $vmFamilyList[$nextSizeIndex] Write-Output "The Scaling-Down for VM $($VM.Name) has been completed!" # Stop the Timer $StopWatch.Stop() # Display the Elapsed Time Write-Output "Total Execution Time for Scaling Down the VM: $($StopWatch.Elapsed.ToString())" } } else { # Stop the Timer $StopWatch.Stop() Write-Output "Could not get the VM {$VMName} in the Resource Group {$ResourceGroupName}." } |