В облачном сервисе Microsoft Azure при запросе информации о виртуальных серверах через PowerShell-скрипт или Python API не выдается информация об их резервных копиях, так как механизм резервного копирования основан на отдельном сервисе.
Чтобы обойти это ограничение, я использую промежуточный PowerShell-скрипт, который запрашивает сервис Recovery Services Vault обо всех имеющихся в нем точках восстановления серверов и сохраняет эту информацию в json-файл. Данный файл я формирую один раз в несколько часов, так как информация о бэкапах меняется не очень часто. Впоследствии скрипты, которые запрашивают информацию о виртуальных машинах в Azure, подхватывают этот файл, сопоставляют имена серверов с точками восстановления из json-файла, выдают результат, который содержит как стандартные свойства сервера, так и информацию по резервным копиям каждого сервера.
# ------------------------------------------------------------------------------------------------ # Functions Function Write-ScriptLog { Param( [CmdletBinding()] [Parameter(ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)] [String]$Message, [Parameter(ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)] [String]$LogFile ) Process { $LogMessage = Get-Date -uformat "%d.%m.%Y %H:%M:%S" $LogMessage += "`t" $LogMessage += $Message $LogMessage | Out-File -FilePath $LogFile -Append } }#End Function # ------------------------------------------------------------------------------------------------ # Получение пути к скрипту $ScriptFolder = $MyInvocation.MyCommand.Path.SubString(0,($MyInvocation.MyCommand.Path.Length - $MyInvocation.MyCommand.Name.Length)) # Формирование пути к лог-файлу $LogFile = $ScriptFolder + $MyInvocation.MyCommand.Name.SubString(0,($MyInvocation.MyCommand.Name.Length - 4)) + ".log" $JsonFile = $ScriptFolder + $MyInvocation.MyCommand.Name.SubString(0,($MyInvocation.MyCommand.Name.Length - 4)) + ".json" # Создание лог-файла Out-File -FilePath $LogFile Write-ScriptLog -LogFile $LogFile -Message ($MyInvocation.MyCommand.Name + " started") # Чтение аргументов из командной строки Write-ScriptLog -LogFile $LogFile -Message "Reading input arguments" If ($args.length -ne 3) { Write-ScriptLog -LogFile $LogFile -Message "Wrong number of agruments" Write-ScriptLog -LogFile $LogFile -Message "Using default values" $AZU_TENANT_ID = 'abcdefjh-1234-abcd-1234-abcdefjhigkl' $AZU_CLIENT_ID = 'hjfedcba-4321-dcba-4321-lkgihjfedcba' $AZU_SECRET_KEY = '123.abc.1234567.abcdefj.123456789' } else { $AZU_TENANT_ID = $args[0] $AZU_CLIENT_ID = $args[1] $AZU_SECRET_KEY = $args[2] } Write-ScriptLog -LogFile $LogFile -Message " azu_tenant_id is $AZU_TENANT_ID" Write-ScriptLog -LogFile $LogFile -Message " azu_client_id is $AZU_CLIENT_ID" Write-ScriptLog -LogFile $LogFile -Message " aqzu_secret_key is $AZU_SECRET_KEY" Write-ScriptLog -LogFile $LogFile -Message " output json-file is $JsonFile" # вход в Azure Write-ScriptLog -LogFile $LogFile -Message "Logging in to Azure" $AZU_SECRET_KEY_SEC = ConvertTo-SecureString $AZU_SECRET_KEY -AsPlainText -Force $pscredential = New-Object -TypeName System.Management.Automation.PSCredential($AZU_CLIENT_ID, $AZU_SECRET_KEY_SEC) Disconnect-AzAccount Connect-AzAccount -ServicePrincipal -Credential $pscredential -Tenant $AZU_TENANT_ID | Out-Null # создание пустого списка свойств резервного копирования серверов $data = New-Object System.Collections.Generic.List[System.Object] # получение всех коллекций резервного копирования Write-ScriptLog -LogFile $LogFile -Message "Reading recovery services vaults" $vault_list = Get-AzRecoveryServicesVault Write-ScriptLog -LogFile $LogFile -Message ($vault_list.length.ToString() + " vaults found") ForEach ($vault_item in $vault_list) { # получение контейнеров резервного копирования для каждой коллекции Write-ScriptLog -LogFile $LogFile -Message (" Reading containers of " + $vault_item.Name) $container_list = Get-AzRecoveryServicesBackupContainer -ContainerType "AzureVM" -BackupManagementType "AzureVM" -VaultId $vault_item.ID Write-ScriptLog -LogFile $LogFile -Message (" " + $container_list.length.ToString() + " containers found") foreach ($container_item in $container_list) { # получение объекта резервного копирования сервера Write-ScriptLog -LogFile $LogFile -Message (" Reading properties of " + $container_item.FriendlyName) $backup_item = Get-AzRecoveryServicesBackupItem -Container $container_item -WorkloadType AzureVM -VaultId $vault_item.ID # получение свойств объекта резервного копирования $id = $backup_item.Id $vm_name = ($backup_item.ContainerName -split ";")[2].ToString().ToLower() $vm_rgp_name = ($backup_item.ContainerName -split ";")[1].ToString().ToLower() $container_name = $backup_item.ContainerName $policy_name = $backup_item.ProtectionPolicyName $vault_name = $vault_item.Name $vault_rgp_name = ($vault_item.ID -split "/")[4].ToString().ToLower() $id = ('/' + $vault_rgp_name + '/' + $vault_name + '/' + $container_name) $status = $backup_item.ProtectionStatus.ToString().ToLower() $latest_backup = [datetime]::parseexact($backup_item.LatestRecoveryPoint, 'MM/dd/yyyy HH:mm:ss', $null) # составление словаря свойств резервного копирования сервера $backup_properties = New-Object System.Object $backup_properties | Add-member -MemberType NoteProperty -Name id -Value $id $backup_properties | Add-member -MemberType NoteProperty -Name vm_name -Value $vm_name $backup_properties | Add-Member -MemberType NoteProperty -Name vm_rgp_name -Value $vm_rgp_name $backup_properties | Add-member -MemberType NoteProperty -Name container_name -Value $container_name $backup_properties | Add-member -MemberType NoteProperty -Name policy_name -Value $policy_name $backup_properties | Add-Member -MemberType NoteProperty -Name vault_name -Value $vault_name $backup_properties | Add-Member -MemberType NoteProperty -Name vault_rgp_name -Value $vault_rgp_name $backup_properties | Add-Member -MemberType NoteProperty -Name status -Value $status $backup_properties | Add-Member -MemberType NoteProperty -Name latest_backup -Value $latest_backup # добавление полученных свойств в список свойств резервного копирования серверов $data.Add($backup_properties) } } Write-ScriptLog -LogFile $LogFile -Message "Reading data from Azure is complete" Write-ScriptLog -LogFile $LogFile -Message "Deleteing the output file if it exists" If (Test-Path $JsonFile) { Remove-Item -Path $JsonFile } Write-ScriptLog -LogFile $LogFile -Message ("Saving json-file " + $JsonFile) $data | ConvertTo-Json | Out-File -FilePath $JsonFile -Encoding "utf8" # ------------------------------------------------------------------------------------------------ Write-ScriptLog -LogFile $LogFile -Message "----- The script finished -----"
Результат работы скрипта - json-файл с данными о серверах и их бэкапах
[ { "id": "/rgp-n-aaa-project1/rsv-n-aaa-project1-backupvault/iaasvmcontainerv2;rgp-n-aaa-project1;wsAAA056", "vm_name": "wsAAA056", "vm_rgp_name": "rgp-n-aaa-project1", "container_name": "iaasvmcontainerv2;rgp-n-aaa-project1;wsazn056", "policy_name": "pol-VM-Daily-10pm-4WeeksRetention", "vault_name": "rsv-n-aaa-project1-backupvault", "vault_rgp_name": "rgp-n-aaa-project1", "status": "healthy", "latest_backup": "\/Date(1612459418000)\/" }, { "id": "/rgp-n-aaa-project1/rsv-n-aaa-project1-backupvault/iaasvmcontainerv2;rgp-n-aaa-project1;wsAAA057", "vm_name": "wsAAA057", "vm_rgp_name": "rgp-n-aaa-project1", "container_name": "iaasvmcontainerv2;rgp-n-aaa-project1;wsazn057", "policy_name": "pol-VM-Weekly-10pm-4WeeksRetention", "vault_name": "rsv-n-aaa-project1-backupvault", "vault_rgp_name": "rgp-n-aaa-project1", "status": "healthy", "latest_backup": "\/Date(1612459319000)\/" } ]