Forum Discussion

Hairy_Zeus's avatar
Hairy_Zeus
Copper Contributor
Mar 03, 2022

Assistance with looping through multiple subscriptions

Hi Community,

 

I'm using the below script from http://vcloud-lab.com/entries/microsoft-azure/get-azure-virtual-machine-backup-reports-using-powershell 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

 

 

  • AndySvints's avatar
    AndySvints
    Steel Contributor

    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.

    • Subhankar131's avatar
      Subhankar131
      Copper Contributor

      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
      }
      • AndySvints's avatar
        AndySvints
        Steel Contributor

        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.

Resources