Search code examples
azurepowershellazure-powershellpowershell-4.0azure-rm

How to get the list of azure servers having Auto-Shutdown disabled using PowerShell?


I want to get the list of azure servers having auto-shutdown disabled on them, I have the below script but the issue with the script is that it gets the list of RG's under the Subscription GUID but repeats the output after every loop.

Import-AzureRmContext -Path "$PSScriptRoot\AzureProfile.json"

Select-AzureRmSubscription -SubscriptionId {subscriptionId}


[array]$ResourceGroupArray = Get-AzureRMVm | Select-Object -Property ResourceGroupName, Name, VmId
   
foreach ($resourceGroup in $ResourceGroupArray){
    $targetResourceId = (Get-AzureRmVM -ResourceGroupName $resourcegroup.ResourceGroupName -Name $resourceGroup.Name).Id
    $shutdownInformation = (Get-AzureRmResource -ResourceGroupName $resourcegroup.ResourceGroupName -ResourceType Microsoft.DevTestLab/schedules -Expandproperties).Properties
    Write-Host "ID: " $targetResourceId
    $shutdownInformation

The output for each VM is displayed in the following format,

enter image description here

What I want is simple, I want the VM name and its status of Auto-shutdown to be displayed on the screen so that its easy for me to find out which all VM have auto-shutdown currently disabled on them.

Any help related to this would be helpful.


Solution

  • You just need to get the microsoft.devtestlab/schedules resource ID using:

    /subscriptions/{subscriptionId}/resourceGroups/{rgName}/providers/microsoft.devtestlab/schedules/shutdown-computevm-{vmName}
    

    Then iterate over all your VMs using Get-AzVM, Get the microsoft.devtestlab/schedules resource using Get-AzResource, then output VM name and status into a table using Format-Table.

    $subscriptionId = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
    
    Set-AzContext -SubscriptionId $subscriptionId
    
    & {
        foreach ($vm in Get-AzVM) {
            try {
                $shutdownResource = Get-AzResource `
                    -ResourceId "/subscriptions/$subscriptionId/resourceGroups/$($vm.ResourceGroupName)/providers/microsoft.devtestlab/schedules/shutdown-computevm-$($vm.Name)" `
                    -ErrorAction Stop
    
                [PSCustomObject]@{
                    VMName = $vm.Name
                    ShutdownStatus = $shutdownResource.Properties.status
                }
            }
            catch {
                [PSCustomObject]@{
                    VMName = $vm.Name
                    ShutdownStatus = $_.Exception.Message
                }
            }
        }
    } | Format-Table -AutoSize
    

    To set the context to the correct subscription, we can use Set-AzContext.

    The above however is using the latest Az modules. You can do the same using the equivalent AzureRm modules.

    $subscriptionId = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
    
    Set-AzureRmContext -SubscriptionId $subscriptionId
    
    & {
        foreach ($vm in Get-AzureRmVM) {
            try {
                $shutdownResource = Get-AzureRmResource `
                    -ResourceId "/subscriptions/$subscriptionId/resourceGroups/$($vm.ResourceGroupName)/providers/microsoft.devtestlab/schedules/shutdown-computevm-$($vm.Name)" `
                    -ErrorAction Stop
    
                [PSCustomObject]@{
                    VMName = $vm.Name
                    ShutdownStatus = $shutdownResource.Properties.status
                }
            }
            catch {
                [PSCustomObject]@{
                    VMName = $vm.Name
                    ShutdownStatus = $_.Exception.Message
                }
            }
        }
    } | Format-Table -AutoSize
    

    Although I do recommend moving to the Az module since support for AzureRm is ending December 2020. You can read the documentation for more information about this.

    The above code should give you an output similar to the following

    VMName    ShutdownStatus
    ------    --------------
    vm1       Enabled
    vm2       Disabled
    

    Update

    The Call operator & is used here to run the for loop as a script block. You can read more about this in about_Script_Blocks.