As I explained in the previous post, Azure allows the provisioning of extensions to cloud-hosted VMs through a VM Agent.
If you have ever gone through a large deployment of extensions to existing Azure VMs, via the Set-AzureVMDscExtension cmdlet, you have probably sought a way to check for the deployment status in a simpler manner then browsing into each and every VM in the Azure Portal:
Here's how PowerShell answers this need, and it does it in just one line of code. The core cmdlet here is Get-AzureRmVM, which is generally used to report VM status:
Get-AzureRmVM -WarningAction SilentlyContinue ResourceGroupName Name Location VmSize OsType NIC ProvisioningState ----------------- ---- -------- ------ ------ --- ----------------- RG-AD adVM westeurope Standard_D2_v2 Windows adNic Succeeded RG-AppServices VM0 westeurope Standard_A1 Windows nic0 Succeeded RG-AppServices VM1 westeurope Standard_A1 Windows nic1 Succeeded RG-DSC VM2012 westeurope Standard_A1 Windows vm2012373 Succeeded RG-DSC VM2016 westeurope Standard_A1 Windows vm2016964 SucceededAs a side information, I am settings the WarningAction parameter to SilentlyContinue simply because I don't want the following warning message to make my output less readable:
WARNING: Breaking change notice: In upcoming releaese, top level properties, DataDiskNames and NetworkInterfaceIDs, will be removed from VM object because they are also in StorageProfile and NetworkProfile, respectively.
I know very well that releases of Azure cmdlet are coming at a fast pace, so I can suppress this message.
Here's the oneliner I wrote:
Get-AzureRmVM -WarningAction SilentlyContinue | % { (Get-AzureRmVM -ResourceGroupName $_.ResourceGroupName -name $_.name -status -OutVariable x -WarningAction SilentlyContinue).extensions | % { $_ | select @{Name="VmName";Expression={$x.name}},@{Name="Extension";Expression={$_.name}},@{Name="Level";Expression={$_.statuses.level}},@{Name="Status";Expression={$_.statuses.displaystatus}},@{Name="Time";Expression={$_.statuses.time}} } }
The output can be piped to Format-Table if I want a table view, or to Out-Gridview, if you prefer:
Get-AzureRmVM -WarningAction SilentlyContinue | % { (Get-AzureRmVM -ResourceGroupName $_.ResourceGroupName -name $_.name -status -OutVariable x -WarningAction SilentlyContinue).extensions | % { $_ | select @{Name="VmName";Expression={$x.name}},@{Name="Extension";Expression={$_.name}},@{Name="Level";Expression={$_.statuses.level}},@{Name="Status";Expression={$_.statuses.displaystatus}},@{Name="Time";Expression={$_.statuses.time}} } } | Format-Table * -Autosize VmName Extension Level Status Time ------ --------- ----- ------ ---- adVM CreateADForest Info Provisioning succeeded 6/30/2017 9:13:55 AM myVM0 PuppetAgent Info Provisioning succeeded myVM0 Site24x7WindowsServerAgent Info Provisioning succeeded myVM1 IaaSAntimalware Info Provisioning succeeded VM2012 DSC Error Provisioning failed 6/29/2017 2:35:39 PM VM2012 IaaSAntimalware Info Provisioning succeeded VM2016 DSC Info Provisioning succeeded 6/29/2017 9:53:20 AMI could also think of showing just the failures:
Get-AzureRmVM -WarningAction SilentlyContinue | % { (Get-AzureRmVM -ResourceGroupName $_.ResourceGroupName -name $_.name -status -OutVariable x -WarningAction SilentlyContinue).extensions | % { $_ | select @{Name="VmName";Expression={$x.name}},@{Name="Extension";Expression={$_.name}},@{Name="Level";Expression={$_.statuses.level}},@{Name="Status";Expression={$_.statuses.displaystatus}},@{Name="Time";Expression={$_.statuses.time}} } } | ? Status -match 'Failed' VmName : VM2012 Extension : DSC Level : Error Status : Provisioning failed Time : 6/29/2017 2:35:39 PM
As I can see in the last output, the DSC extension failed to deploy on one of my Azure VMs, and I need to take corrective actions. I will discuss in a future post how to automatically solve this kind of issues staying on the same line of code.
If you have any technical question on the way I implemented this line of code, feel free to get in touch with me. Feel free to share if you like the content of this post.
If you have any technical question on the way I implemented this line of code, feel free to get in touch with me. Feel free to share if you like the content of this post.