I am attempting to restore a virtual machine that was backed up to Azure Storage using our on-premises Veeam Backup & Replication Server.
To automate the restore process, I’ve written a PowerShell script that first fetches the necessary details and then initiates the restore. I am sharing the script below along with the error encountered.
I would appreciate it if you could kindly review the script and suggest any corrections or improvements that would help ensure a smooth restore operation.
Thank you in advance for your support.
Script -
Code: Select all
# Load Veeam PowerShell Snap-in
Add-PSSnapin VeeamPSSnapIn -ErrorAction SilentlyContinue
# Define parameters
$backupJobName = "Veeam1Backup Job 2_Tue_Thu_Sat"
$vmName = "Example-dc1"
$vmDate = Get-Date -Format 'yyyyMMddHHmm'
$newVmName = "$vmName-Restored-$vmDate"
$reason = "Azure DR Restore"
$azureAccountName = "ma-veeamazurecompute"
$resourceGroup = "Example-DR-SITE"
$subscriptionName = "Example-DR-SITE"
$vmSizeName = "Standard_B2as_v2"
$locationName = "southindia"
$nsgName = "MA-VEEAM-RECOVERY-nsg"
$vnetName = "Example-dr-site-si-vnet"
$subnetName = "Azure-Veeam-Restore"
# Initialize status variables
$allComponentsValid = $true
# Display configuration
Write-Host "`n=== VM Restore Configuration ===" -ForegroundColor Cyan
Write-Host "Backup Job: $backupJobName"
Write-Host "Source VM: $vmName"
Write-Host "New VM Name: $newVmName"
Write-Host "Azure Account: $azureAccountName"
Write-Host "Subscription: $subscriptionName"
Write-Host "Resource Group: $resourceGroup"
Write-Host "Location: $locationName"
Write-Host "VM Size: $vmSizeName"
Write-Host "NSG: $nsgName"
Write-Host "VNET: $vnetName"
Write-Host "Subnet: $subnetName"
Write-Host "`n"
# Get Azure account
Write-Host "Connecting to Azure account..." -ForegroundColor Yellow
$azureAccount = Get-VBRAzureAccount | Where-Object { $_.Name -eq $azureAccountName } | Select-Object -First 1
if (-not $azureAccount) {
Write-Host "❌ Azure account '$azureAccountName' not found." -ForegroundColor Red
$allComponentsValid = $false
} else {
Write-Host "✅ Azure account found: $($azureAccount.Name)" -ForegroundColor Green
}
# Get Azure subscription
Write-Host "`nGetting Azure subscription..." -ForegroundColor Yellow
$subscription = Get-VBRAzureSubscription -Account $azureAccount | Where-Object { $_.Name -eq $subscriptionName } | Select-Object -First 1
if (-not $subscription) {
Write-Host "❌ Azure subscription '$subscriptionName' not found." -ForegroundColor Red
$allComponentsValid = $false
} else {
Write-Host "✅ Subscription found: $($subscription.Name)" -ForegroundColor Green
}
# Get Azure location object
Write-Host "`nGetting Azure location..." -ForegroundColor Yellow
$location = Get-VBRAzureLocation -Subscription $subscription | Where-Object { $_.Name -eq $locationName } | Select-Object -First 1
if (-not $location) {
Write-Host "❌ Azure location '$locationName' not found in subscription." -ForegroundColor Red
$allComponentsValid = $false
} else {
Write-Host "✅ Location found: $($location.Name)" -ForegroundColor Green
}
# Get Azure VM size object
Write-Host "`nGetting VM size..." -ForegroundColor Yellow
$vmSize = Get-VBRAzureVMSize -Subscription $subscription -Location $location | Where-Object { $_.Name -eq $vmSizeName } | Select-Object -First 1
if (-not $vmSize) {
Write-Host "❌ VM size '$vmSizeName' not found in location '$locationName'." -ForegroundColor Red
$allComponentsValid = $false
} else {
Write-Host "✅ VM size found: $($vmSize.Name)" -ForegroundColor Green
}
# Get backup job object
Write-Host "`nFinding backup job..." -ForegroundColor Yellow
$job = Get-VBRJob | Where-Object { $_.Name -eq $backupJobName }
if (-not $job) {
Write-Host "❌ Backup job '$backupJobName' not found." -ForegroundColor Red
$allComponentsValid = $false
} else {
Write-Host "✅ Backup job found: $($job.Name)" -ForegroundColor Green
}
# Get backup object associated with the job
Write-Host "`nLocating backup data..." -ForegroundColor Yellow
$backup = Get-VBRBackup | Where-Object { $_.JobId -eq $job.Id }
if (-not $backup) {
Write-Host "❌ Backup object for job '$backupJobName' not found." -ForegroundColor Red
$allComponentsValid = $false
} else {
Write-Host "✅ Backup object found with $($backup.GetAllStorages().Count) restore points" -ForegroundColor Green
}
# Get restore point (using the most recent one)
Write-Host "`nFinding restore point..." -ForegroundColor Yellow
$restorePoint = Get-VBRRestorePoint -Backup $backup | Where-Object { $_.VMName -like "$vmName" } | Sort-Object -Property CreationTime -Descending | Select-Object -First 1
if (-not $restorePoint) {
Write-Host "❌ Restore point for VM '$vmName' not found in backup '$backupJobName'." -ForegroundColor Red
$allComponentsValid = $false
} else {
Write-Host "✅ Restore point found:" -ForegroundColor Green
Write-Host " VM Name: $($restorePoint.VMName)"
Write-Host " Creation Time: $($restorePoint.CreationTime)"
Write-Host " Backup File: $($restorePoint.FileName)"
}
# Get NSG object
Write-Host "`nLocating Network Security Group..." -ForegroundColor Yellow
$nsg = Get-VBRAzureNetworkSecurityGroup -Subscription $subscription | Where-Object { $_.Name -eq $nsgName } | Select-Object -First 1
if (-not $nsg) {
Write-Host "⚠️ Network Security Group '$nsgName' not found. Continuing without NSG." -ForegroundColor Yellow
} else {
Write-Host "✅ NSG found: $($nsg.Name)" -ForegroundColor Green
}
# Get Virtual Network and Subnet objects
Write-Host "`nGetting virtual network and subnet information..." -ForegroundColor Yellow
$vnet = Get-VBRAzureVirtualNetwork -Subscription $subscription | Where-Object { $_.Name -eq $vnetName } | Select-Object -First 1
if (-not $vnet) {
Write-Host "❌ Virtual network '$vnetName' not found." -ForegroundColor Red
$allComponentsValid = $false
} else {
Write-Host "✅ Virtual network found: $($vnet.Name)" -ForegroundColor Green
}
$subnet = $null
if ($vnet) {
$subnet = Get-VBRAzureNetworkSubnet -VirtualNetwork $vnet | Where-Object { $_.Name -eq $subnetName } | Select-Object -First 1
if (-not $subnet) {
Write-Host "❌ Subnet '$subnetName' not found in virtual network '$vnetName'." -ForegroundColor Red
Write-Host "Available subnets in '$vnetName':" -ForegroundColor Yellow
Get-VBRAzureNetworkSubnet -VirtualNetwork $vnet | Select-Object -ExpandProperty Name | ForEach-Object { Write-Host " $_" }
$allComponentsValid = $false
} else {
Write-Host "✅ Subnet found: $($subnet.Name)" -ForegroundColor Green
}
}
# Start VM restore to Azure if all required components are available
if ($allComponentsValid) {
Write-Host "`n🚀 Starting restore of '$vmName' to Azure as '$newVmName'..." -ForegroundColor Cyan
$restoreParams = @{
RestorePoint = $restorePoint
Reason = $reason
Subscription = $subscription
Location = $location
VMName = $newVmName
VMSize = $vmSize
ResourceGroup = $resourceGroup
VirtualNetwork = $vnet
VirtualSubnet = $subnet
}
if ($nsg) {
$restoreParams['NetworkSecurityGroup'] = $nsg
}
try {
$restoreSession = Start-VBRVMRestoreToAzure @restoreParams
if ($restoreSession) {
Write-Host "✅ Restore job started successfully!" -ForegroundColor Green
Write-Host " Session ID: $($restoreSession.Id)"
Write-Host " Start Time: $($restoreSession.CreationTime)"
Write-Host " Status: $($restoreSession.State)"
# Monitor restore progress
Write-Host "`n🔄 Monitoring restore progress (refresh every 30 seconds)..." -ForegroundColor Yellow
do {
$session = Get-VBRSession -Id $restoreSession.Id
Write-Host " Status: $($session.State) - Progress: $($session.Progress)" -ForegroundColor Gray
if ($session.State -eq "Working") {
Start-Sleep -Seconds 30
}
} while ($session.State -eq "Working")
Write-Host "`n🎉 Restore job completed with status: $($session.State)" -ForegroundColor Green
} else {
Write-Host "⚠️ Restore session object not returned." -ForegroundColor Red
}
} catch {
Write-Host "❌ Error starting restore job: $_" -ForegroundColor Red
}
} else {
Write-Host "`n⛔ Cannot start restore due to missing or invalid components (see errors above)." -ForegroundColor Red
}
Write-Host "`nScript completed." -ForegroundColor Cyan
Error
Get-VBRAzureNetworkSubnet : The term 'Get-VBRAzureNetworkSubnet' is not recognized as the name of a cmdlet, function,
script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is
correct and try again.
At line:2 char:15
+ $subnet = Get-VBRAzureNetworkSubnet -VirtualNetwork $vnet | Where ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Get-VBRAzureNetworkSubnet:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
❌ Subnet 'Azure-Veeam-Restore' not found in virtual network 'mariapps-dr-site-si-vnet'.
Available subnets in 'mariapps-dr-site-si-vnet':
Get-VBRAzureNetworkSubnet : The term 'Get-VBRAzureNetworkSubnet' is not recognized as the name of a cmdlet, function,
script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is
correct and try again.
At line:6 char:9
+ Get-VBRAzureNetworkSubnet -VirtualNetwork $vnet | Select-Obje ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Get-VBRAzureNetworkSubnet:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException