As part of a project recently I was asked to run a report against a customer’s environment with hundreds of Azure VMs. We wanted to retrieve all of their VMs and their corresponding operating systems. Easy using Powershell right? It turns out no, it is not as easy as expected at all. This was to do with a quirk of the cmdlet Get-AzVM, which took a while to work out. I wanted to share what I found out and how I got this Powershell script to work.
In Azure, you will notice that there are two fields describing an Azure VM’s operating system:
The first parameter is either ‘Windows’ or ‘Linux’ and is retrieved using the Get-AzVM parameter ‘OsType’:
However, we want the specific version of Windows that the VM is running (the information in brackets in the portal). This is retrieved using the Azure VM extension and is only available when the VM is running. You’ll notice this info is not available when the VM is turned off:
Unfortunately, if we try and select the OsType from Powershell the return is null:
Get-AzVm -Name AC-VMSRV01 | Select OsType
Instead we need to retrieve this information using the parameter StorageProfile.OsDisk.OsType
:
$vm1 = Get-AzVM -Name AC-VM-SRV01
$vm1.StorageProfile.OsDisk.OsType
This still only give us the high-level information of whether the VM was Windows or Linux. Ideally, we want the exact version of Windows or Linux.
More info can be retrieved using the StorageProfile.ImageReference
parameter of the Azure VM:
$vm1 = Get-AzVM -Name AC-VM-SRV01
$vm1.StorageProfile.ImageReference
From this information we can actually see that the VM is running Windows Server 2019 datacenter from the two parameters
$vm1.StorageProfile.ImageReference.Offer and $vm1.StorageProfile.ImageReference.Sku
At this point in my work I thought I’d almost finished, all I needed to do was to compile this into a report using PowerShell. However, quite quickly I realised that the StorageProfile.ImageReference
was only populated if the VM was deployed from a Microsoft supplied image or from the Azure marketplace. In the customer’s case they had a large number of VMs which had been migrated into Azure so weren’t deployed using Microsoft supplied images or the Azure marketplace. In this case StorageProfile.ImageReference
is completely empty.
I then came across this thread which lists that the Azure extension OS information should be in the Azure VM ‘Instance View’.
Virtual Machine Properties not shown · Issue #11296 · Azure/azure-powershell · GitHub
However, despite this being included in the Get-AzVM output, it doesn’t currently work.
However, we can instead retrieve the Instance View (which returns more information than previously) using Get-AzVM -Status
$vm1 = Get-AzVM -Name AC-VM-SRV01 -Status
$vm1 | fl *
Here you can see the parameters OsName and OsVersion are populated with the information we want! The StorageProfile also contains the previously retrieved information. So, we can now use this to compile a report:
$Report = [System.Collections.Generic.List[Object]]::new()
$vms = $null
$vms = Get-azVm -Status
Foreach ($vm in $vms){
$obj = [PSCustomObject][ordered]@{
"Server Name" = $vm.Name
"OS" = $vm.StorageProfile.ImageReference.offer
"OS Sku" = $vm.StorageProfile.ImageReference.sku
"OS Name" = $vm.OsName
"OS Version" = $vm.OsVersion
}
$report.Add($obj)
}
$Report | Export-CSV C:\temp\ArchieVM_Status.csv
This results in a CSV file with the columns as illustrated below. This can be run against any subscription to retrieve Azure VMs and their corresponding operating systems. NOTE: The OS Name and OS Version will not be populated if the VM is turned off/deallocated.