Craig Forrester

The Pleasure of Finding Things Out

github linkedin email rss
Resize Azure Virtual Machine with Azure PowerShell
December 31, 2018
4 minutes read

In several previous posts, I discussed how to resize the virtual hard disks on an Azure virtual machine using Azure CLI and PowerShell. In this post, I’m going to walk through how to resize an Azure virtual machine with PowerShell, and cover how to convert these commands into a script.

Log In and Verify Subscription

As always, we want to be sure we have PowerShell connected to Azure and that we using the right subscription. So, we login and then call Get-AzureRmContext to see which subscription is selected:

Login-AzureRmAccount
(Get-AzureRmContext).Subscription.Name

Example output:

Visual Studio Enterprise

If you see no output, you are not connected to any Subscription. If you see the wrong subscription, then you will need to change it with Set-AzureRmContext as follows:

$subscription = Get-AzureRmSubscription `
                    -SubscriptionName "BizSpark"
Set-AzureRmContext -SubscriptionObject $subscription

Deallocate the Virtual Machine

In order to resize a virtual machine, we have to shut it down and deallocate it first:

Get-AzureRmVM -ResourceGroupName $rg -Name $vm_name | 
    Stop-AzureRmVM -Force -AsJob

Throughout the post I refer to variables instead of the literal names, like the above example. We will be able to convert this to a script later much more easily as a result, and it will allow you to use the examples on whatever specific instances in your environment with minimal change.

We are doing our work in PowerShell, so to use these variables names we simply assign them values, as in this example:

$rg = 'lab1-rg'
$vm = 'ws2016server1'

To verify our virtual machine is deallocated, we have a couple of options. If we used the -AsJob switch, like I did above, then all we need to do is pull that job up and check its status, like this:

Get-Job -Newest 1 | select Name,JobStateInfo

Example Output:

Name                                        JobStateInfo
----                                        ------------
Long Running Operation for 'Stop-AzureRmVM' Completed

Otherwise, we can use the Get-AzureRmVM cmdlet again, with the virtual machine name and the -Status switch, which will show us detailed status by returning what’s called an Instance View of the virtual machine:

Get-AzureRmVM -ResourceGroupName $rg -Name $vm -Status

Example output:


ResourceGroupName : lab-rg
Name              : ws2016server1
Disks[0]          :
  Name            : ws2016server1-disk-os
  Statuses[0]     :
    Code          : ProvisioningState/succeeded
    Level         : Info
    DisplayStatus : Provisioning succeeded
    Time          : <Date and Time>
Statuses[0]       :
  Code            : ProvisioningState/succeeded
  Level           : Info
  DisplayStatus   : Provisioning succeeded
  Time            : <Date and Time>
Statuses[1]       :
  Code            : PowerState/deallocated
  Level           : Info
  DisplayStatus   : VM deallocated

Note the PowerState under Statuses[1]. If we want to access this particular status by name later, in our script, PowerShell provides us a number of ways. Here’s one…

$vm_state = Get-AzureRmVM -ResourceGroupName $rg -Name $vm -Status
$vm_state.Statuses.Code -match 'Power'

Example Output:

PowerState/deallocated

We could then further extend our script functionality based on that PowerState status.

Get the Current Disk Size

Next we should determine the current size of the disk, so we can compare it against the size we want to expand it to. The first step is to locate the disk ID and assign it to a variable, with the following query:

$vm_current = Get-AzureRmVM -ResourceGroupName $rg -Name $vm

$disk_name = $vm_current.StorageProfile.OsDisk.Name

(We could have done this in one line, but it’s a bit easier to read this way.)

Once we have the OS disk ID assigned to $disk_id, we can use it to lookup the disk:

Get-AzureRmDisk $rg $disk_name | 
    select Name,DiskSizeGB,@{N='Tier';E={$_.Sku.Name}}

(If you’re wondering what the last bit is with the @{N='Tier'..., it’s just a way for us to map the Storage SKU Name into a custom column of our output object, instead of having $_.Sku.Name as the column header.)

Example output:

Name                  DiskSizeGB Tier
----                  ---------- ----
ws2016server1-disk-os 127        StandardLRS

This is good output because it confirms both the current size of the disk, and reminds us what storage tier it’s using, in case that’s a concern.

Aside: You may be wondering why we didn’t just look up the disk directly, by name. We could have. The reason we didn’t is that most of the time we need to expand a disk, we are doing so based on some request that refers to the virtual machine by name, not the disk. Additionally, in some environments disk names are “square” with the virtual machine names, and in others, they aren’t. So, it’s a good idea to start at the source and programmatically move to the destination.

Additional Reading


Back to posts