В облачном сервисе 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)\/"
}
]
