Assistance with looping through multiple subscriptions

Copper Contributor

Hi Community,

 

I'm using the below script from http://vcloud-lab.com/entries/microsoft-azure/get-azure-virtual-machine-backup-reports-using-powersh... to pull Azure VM backup details. Currently I have to run the script against each subscription, I would love to have it loop though all subscriptions.

 

I've been trying to get it working using this example https://www.jpaul.me/2019/05/azure-automation-how-to-quickly-work-with-many-subscriptions/ but I'm new to Powershell and am struggling. Any suggestions would be really appreciated.

 

 

[CmdletBinding(SupportsShouldProcess=$True,
    ConfirmImpact='Medium',
    HelpURI='http://vcloud-lab.com',
    DefaultParameterSetName = 'AllVirtualMachines'
)]

<#
    .SYNOPSIS
    Collect Azure VM Backup Information

    .DESCRIPTION
    This Script collects Azure Virtual Machine Backup Recovery service vault information, This report includes the complete backup status Information of VM.

    .PARAMETER AllVirtualMachines
    Collect Backup information of the all Azure Virtual Machines, This is default parameter.

    .PARAMETER VirtualMachineList
    You can specify for which virtual machine you want backup information.

    .INPUTS
    None. Provides virtual machine information.

    .OUTPUTS
    Generate Backup information. You can pipe information to Export-CSV.

    .EXAMPLE
    PS> .\Get-AzVMBackupInformation.ps1
    
    VM_Name                         : vcloud-lab-vm01
    VM_Location                     : uksouth
    VM_ResourceGroupName            : VCLOUD-LAB.COM
    VM_BackedUp                     : True
    VM_RecoveryVaultName            : vault828
    VM_RecoveryVaultPolicy          : DailyPolicy-kosrnox0
    VM_BackupHealthStatus           : Passed
    VM_BackupProtectionStatus       : Healthy
    VM_LastBackupStatus             : Completed
    VM_LastBackupTime               : 27-05-2021 19:32:34
    VM_BackupDeleteState            : NotDeleted
    VM_BackupLatestRecoveryPoint    : 27-05-2021 19:32:37
    VM_Id                           : /subscriptions/9e22xxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/VCLOUD-LAB.COM/providers/Microsoft.Compute/virtualMachines/vcloud-lab-vm01
    RecoveryVault_ResourceGroupName : vCloud-lab.com
    RecoveryVault_Location          : uksouth
    RecoveryVault_SubscriptionId    : /subscriptions/9e22xxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/vCloud-lab.com/providers/Microsoft.RecoveryServices/vaults/vault828

    .EXAMPLE
    PS> .\Get-AzVMBackupInformation.ps1 -AllVirtualMachines
    This produces same result as .\Get-AzVMBackupInformation.ps1 from all VMs

    .EXAMPLE
    PS> .\Get-AzVMBackupInformation.ps1 -VirtualMachineList
    Provide either single virtual machine name or in list
    
    .LINK
    Online version: http://vcloud-lab.com

    .LINK
    Get-AzVMBackupInformation.ps1
#>
Param
( 
    [parameter(Position=0, ParameterSetName = 'AllVMs' )]
    [Switch]$AllVirtualMachines,
    [parameter(Position=0, ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True, ParameterSetName = 'VM' )]
    [alias('Name')]
    [String[]]$VirtualMachineList
) #Param
Begin 
{
    #Collecing Azure virtual machines Information
    Write-Host "Collecing Azure virtual machine Information" -BackgroundColor DarkGreen
    if (($PSBoundParameters.ContainsKey('AllVirtualMachines')) -or ($PSBoundParameters.Count -eq 0))
    {
        $vms = Get-AzVM
    } #if ($PSBoundParameters.ContainsKey('AllVirtualMachines'))
    elseif ($PSBoundParameters.ContainsKey('VirtualMachineList'))
    {
        $vms = @()
        foreach ($vmname in $VirtualMachineList)
        {
            $vms += Get-AzVM -Name $vmname
            
        } #foreach ($vmname in $VirtualMachineList)
    } #elseif ($PSBoundParameters.ContainsKey('VirtualMachineList'))

    #Collecing All Azure backup recovery vaults Information
    Write-Host "Collecting all Backup Recovery Vault information" -BackgroundColor DarkGreen
    $backupVaults = Get-AzRecoveryServicesVault
} #Begin 
Process
{
    $vmBackupReport = [System.Collections.ArrayList]::new()
    foreach ($vm in $vms) 
    {
        $recoveryVaultInfo = Get-AzRecoveryServicesBackupStatus -Name $vm.Name -ResourceGroupName $vm.ResourceGroupName -Type 'AzureVM'
        if ($recoveryVaultInfo.BackedUp -eq $true)
        {
            Write-Host "$($vm.Name) - BackedUp : Yes"
            #Backup Recovery Vault Information
            $vmBackupVault = $backupVaults | Where-Object {$_.ID -eq $recoveryVaultInfo.VaultId}

            #Backup recovery Vault policy Information
            $container = Get-AzRecoveryServicesBackupContainer -ContainerType AzureVM -VaultId $vmBackupVault.ID -FriendlyName $vm.Name #-Status "Registered" 
            $backupItem = Get-AzRecoveryServicesBackupItem -Container $container -WorkloadType AzureVM -VaultId $vmBackupVault.ID
        } #if ($recoveryVaultInfo.BackedUp -eq $true)
        else 
        {
            Write-Host "$($vm.Name) - BackedUp : No" -BackgroundColor DarkRed
            $vmBackupVault = $null
            $container =  $null
            $backupItem =  $null
        } #else if ($recoveryVaultInfo.BackedUp -eq $true)
        
        [void]$vmBackupReport.Add([PSCustomObject]@{
            VM_Name = $vm.Name
            VM_Location = $vm.Location
            VM_ResourceGroupName = $vm.ResourceGroupName
            VM_BackedUp = $recoveryVaultInfo.BackedUp
            VM_RecoveryVaultName =  $vmBackupVault.Name
            VM_RecoveryVaultPolicy = $backupItem.ProtectionPolicyName
            VM_BackupHealthStatus = $backupItem.HealthStatus
            VM_BackupProtectionStatus = $backupItem.ProtectionStatus
            VM_LastBackupStatus = $backupItem.LastBackupStatus
            VM_LastBackupTime = $backupItem.LastBackupTime
            VM_BackupDeleteState = $backupItem.DeleteState
            VM_BackupLatestRecoveryPoint = $backupItem.LatestRecoveryPoint
            VM_Id = $vm.Id
            RecoveryVault_ResourceGroupName = $vmBackupVault.ResourceGroupName
            RecoveryVault_Location = $vmBackupVault.Location
            RecoveryVault_SubscriptionId = $vmBackupVault.ID
        }) #[void]$vmBackupReport.Add([PSCustomObject]@{
    } #foreach ($vm in $vms) 
} #Process
end
{
    $vmBackupReport
} #end

 

 

6 Replies

Hello @Hairy_Zeus,

One of the option would be to leave current function intact and add another function (wrapper) around it. Wrapper will loop through all Azure Subscriptions and will execute Get-AzVMBackupInformation for each subscription.
Something similar to this:

#List to store all results
$Result=New-Object System.Collections.Generic.List[PSObject]
#All Azure Subscriptions
$Subscriptions = Get-AzSubscription
#Looping through each and every subscription
foreach ($sub in $Subscriptions) {
    #Setting context so the script will be executed within the subscription's scope
    Get-AzSubscription -SubscriptionName $sub.Name | Set-AzContext
    #Getting VM backup info for all VMs in subscription
    $Obj=.\Get-AzVMBackupInformation.ps1 -AllVirtualMachines
    #Enriching the output with SubscriptionId for future reference and convenience
    $Obj | Add-Member -NotePropertyName SubscriptionId -NotePropertyValue $Sub.Id
    #Adding results to resulting List
    $Result.Add($Obj)
}
$Result

Hope that helps.

@AndySvints 

 

I modified the script as mentioned by you. However, I'm getting the below error message: ( if you can assist fixing it will be highly appreciated )

Line |
160 | $Obj=.\Get-AzVMBackupInformation.ps1 -AllVirtualMachines
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| The term '.\Get-AzVMBackupInformation.ps1' is not recognized as a name of a cmdlet, function, script file, or executable program. Check the spelling of the name, or if a path was included, verify that
| the path is correct and try again.

 

Export-Csv: Cannot bind argument to parameter 'InputObject' because it is null.

 

== My Objective is to execute the above code for multiple subscription ==

I have modified the above script to capture VM TAG details and VM subscription details. 

I'm unable to get an accurate subscription details. 

 

I executed the below code ( --> It is getting looping through multiple subscription.  However I'm not getting subscription name in the output csv file)

====Code====

$subscription = ( Get-AzContext -ListAvailable | Select-Object Name)
foreach ($sub in $subscription){
    Select-AzContext $sub.Name | Out-Null
    Get-AzVMBackupInformation
}

Hello @Subhankar131,

Get-AzVMBackupInformation.ps1 is the name of  the function that you posted.

So the algorithm is the following. Save your posted function to Get-AzVMBackupInformation.ps1 file and then code that I've provided is additional function which will executed the existing one.

 

Hope that helps.

Hello @AndySvints,

 

Thank you for your clarification.

The above code mentioned by you it works. I need to Export it to a csv file along with subscription name mentioned with VM details. Can it be addressed by modifying your code? 

Hello @AndySvints,

I was able to achieve the desired output. :)