Examples/11-RestoreFromCloudSnapshot.ps1
|
#Requires -Version 7.4 #Requires -Modules PSVergeOS <# .SYNOPSIS Interactive script to restore a VM or Tenant from a cloud snapshot. .DESCRIPTION This script provides an interactive workflow to: 1. Search for a VM or tenant across all cloud snapshots 2. Display available snapshots containing the target 3. Let the user select which snapshot to restore from 4. Choose to restore as a new object or replace existing .PARAMETER Name The name of the VM or tenant to restore. .PARAMETER Type Specifies whether to restore a VM or Tenant. Valid values: VM, Tenant .PARAMETER Server Optional VergeOS server address. If not specified, uses the current connection. .EXAMPLE ./11-RestoreFromCloudSnapshot.ps1 -Name "WebServer01" -Type VM Searches for VM "WebServer01" in all cloud snapshots and guides through restore. .EXAMPLE ./11-RestoreFromCloudSnapshot.ps1 -Name "CustomerA" -Type Tenant Searches for tenant "CustomerA" in all cloud snapshots and guides through restore. .NOTES Requires an active connection to VergeOS (use Connect-VergeOS first). #> [CmdletBinding()] param( [Parameter(Mandatory, Position = 0)] [string]$Name, [Parameter(Mandatory, Position = 1)] [ValidateSet('VM', 'Tenant')] [string]$Type, [Parameter()] [string]$Server ) #region Helper Functions function Write-Header { param([string]$Text) $line = "=" * 60 Write-Host "`n$line" -ForegroundColor Cyan Write-Host " $Text" -ForegroundColor Cyan Write-Host "$line" -ForegroundColor Cyan } function Write-Step { param([int]$Number, [string]$Text) Write-Host "`n[$Number] $Text" -ForegroundColor Yellow } function Get-UserSelection { param( [array]$Options, [string]$Prompt = "Select an option" ) if ($Options.Count -eq 0) { return $null } Write-Host "" for ($i = 0; $i -lt $Options.Count; $i++) { Write-Host " [$($i + 1)] $($Options[$i])" -ForegroundColor White } Write-Host " [0] Cancel" -ForegroundColor DarkGray Write-Host "" do { $selection = Read-Host $Prompt if ($selection -eq '0') { return $null } $index = [int]$selection - 1 } while ($index -lt 0 -or $index -ge $Options.Count) return $index } function Format-SnapshotInfo { param($Snapshot, $ItemCount, $ItemType) $created = if ($Snapshot.Created) { $Snapshot.Created.ToString("yyyy-MM-dd HH:mm") } else { "Unknown" } $expires = if ($Snapshot.NeverExpires) { "Never" } elseif ($Snapshot.Expires) { $Snapshot.Expires.ToString("yyyy-MM-dd HH:mm") } else { "Unknown" } return "$($Snapshot.Name) | Created: $created | Expires: $expires | $ItemCount ${ItemType}(s)" } #endregion #region Main Script Write-Header "VergeOS Cloud Snapshot Restore" Write-Host " Target: $Name ($Type)" # Verify connection Write-Step 1 "Verifying VergeOS connection..." $connection = Get-VergeConnection -ErrorAction SilentlyContinue if (-not $connection) { Write-Host " ERROR: Not connected to VergeOS." -ForegroundColor Red Write-Host " Please run Connect-VergeOS first." -ForegroundColor Red exit 1 } Write-Host " Connected to: $($connection.Server)" -ForegroundColor Green # Get all cloud snapshots Write-Step 2 "Searching cloud snapshots for '$Name'..." $allSnapshots = Get-VergeCloudSnapshot -IncludeExpired if (-not $allSnapshots -or $allSnapshots.Count -eq 0) { Write-Host " ERROR: No cloud snapshots found on this system." -ForegroundColor Red exit 1 } Write-Host " Found $($allSnapshots.Count) total cloud snapshots" # Search for the target in each snapshot $matchingSnapshots = @() foreach ($snapshot in $allSnapshots) { Write-Host " Scanning: $($snapshot.Name)..." -NoNewline if ($Type -eq 'VM') { $snapWithItems = Get-VergeCloudSnapshot -Key $snapshot.Key -IncludeVMs $items = $snapWithItems.VMs | Where-Object { $_.Name -like "*$Name*" } } else { $snapWithItems = Get-VergeCloudSnapshot -Key $snapshot.Key -IncludeTenants $items = $snapWithItems.Tenants | Where-Object { $_.Name -like "*$Name*" } } if ($items -and @($items).Count -gt 0) { Write-Host " FOUND ($(@($items).Count) matches)" -ForegroundColor Green $matchingSnapshots += [PSCustomObject]@{ Snapshot = $snapWithItems Items = @($items) } } else { Write-Host " none" -ForegroundColor DarkGray } } if ($matchingSnapshots.Count -eq 0) { Write-Host "`n No snapshots found containing '$Name'" -ForegroundColor Red Write-Host " Tip: The name search is case-insensitive and supports partial matches." -ForegroundColor Yellow exit 1 } # Display matching snapshots Write-Step 3 "Select a snapshot to restore from" $snapshotOptions = $matchingSnapshots | ForEach-Object { Format-SnapshotInfo -Snapshot $_.Snapshot -ItemCount $_.Items.Count -ItemType $Type } $snapshotIndex = Get-UserSelection -Options $snapshotOptions -Prompt "Enter snapshot number" if ($null -eq $snapshotIndex) { Write-Host "`n Restore cancelled." -ForegroundColor Yellow exit 0 } $selectedSnapshot = $matchingSnapshots[$snapshotIndex] Write-Host " Selected: $($selectedSnapshot.Snapshot.Name)" -ForegroundColor Green # If multiple items match, let user select specific one Write-Step 4 "Select the $Type to restore" if ($selectedSnapshot.Items.Count -eq 1) { $selectedItem = $selectedSnapshot.Items[0] Write-Host " Found: $($selectedItem.Name)" -ForegroundColor Green } else { $itemOptions = $selectedSnapshot.Items | ForEach-Object { if ($Type -eq 'VM') { "$($_.Name) | CPU: $($_.CPUCores) | RAM: $($_.RAMMB) MB" } else { "$($_.Name) | Nodes: $($_.Nodes) | CPU: $($_.CPUCores) | RAM: $($_.RAMMB) MB" } } $itemIndex = Get-UserSelection -Options $itemOptions -Prompt "Enter $Type number" if ($null -eq $itemIndex) { Write-Host "`n Restore cancelled." -ForegroundColor Yellow exit 0 } $selectedItem = $selectedSnapshot.Items[$itemIndex] } Write-Host " Selected: $($selectedItem.Name)" -ForegroundColor Green # Ask about restore mode Write-Step 5 "Choose restore mode" $restoreModes = @( "Restore as NEW (create a copy with new name)" "Restore OVER EXISTING (replace current $Type)" ) $modeIndex = Get-UserSelection -Options $restoreModes -Prompt "Enter restore mode" if ($null -eq $modeIndex) { Write-Host "`n Restore cancelled." -ForegroundColor Yellow exit 0 } $restoreAsNew = ($modeIndex -eq 0) # Get new name if restoring as new $newName = $null if ($restoreAsNew) { Write-Host "" $defaultName = "$($selectedItem.Name)-restored" $newName = Read-Host " Enter new name (default: $defaultName)" if ([string]::IsNullOrWhiteSpace($newName)) { $newName = $defaultName } Write-Host " Will restore as: $newName" -ForegroundColor Green } else { Write-Host "" Write-Host " WARNING: This will replace the existing $Type '$($selectedItem.Name)'" -ForegroundColor Red Write-Host " The current $Type will be DELETED and replaced with the snapshot version." -ForegroundColor Red $confirm = Read-Host " Type 'YES' to confirm" if ($confirm -ne 'YES') { Write-Host "`n Restore cancelled." -ForegroundColor Yellow exit 0 } } # Perform the restore Write-Step 6 "Executing restore..." Write-Host " Snapshot: $($selectedSnapshot.Snapshot.Name)" Write-Host " $Type`: $($selectedItem.Name)" Write-Host " Mode: $(if ($restoreAsNew) { 'New copy' } else { 'Replace existing' })" if ($newName) { Write-Host " New Name: $newName" } Write-Host "" try { if ($Type -eq 'VM') { if ($restoreAsNew) { $result = Restore-VergeVMFromCloudSnapshot ` -CloudSnapshotKey $selectedSnapshot.Snapshot.Key ` -VMKey $selectedItem.Key ` -NewName $newName ` -Verbose } else { # For overwrite, we need to: # 1. Delete the existing VM # 2. Restore with the original name Write-Host " Removing existing VM '$($selectedItem.Name)'..." -ForegroundColor Yellow $existingVM = Get-VergeVM -Name $selectedItem.Name -ErrorAction SilentlyContinue if ($existingVM) { # Stop if running if ($existingVM.PowerState -eq 'Running') { Write-Host " Stopping VM..." -ForegroundColor Yellow Stop-VergeVM -Key $existingVM.Key -Force -Confirm:$false Start-Sleep -Seconds 5 } Remove-VergeVM -Key $existingVM.Key -Force -Confirm:$false Start-Sleep -Seconds 2 } Write-Host " Restoring from snapshot..." -ForegroundColor Yellow $result = Restore-VergeVMFromCloudSnapshot ` -CloudSnapshotKey $selectedSnapshot.Snapshot.Key ` -VMKey $selectedItem.Key ` -Verbose } } else { # Tenant restore if ($restoreAsNew) { $result = Restore-VergeTenantFromCloudSnapshot ` -CloudSnapshotKey $selectedSnapshot.Snapshot.Key ` -TenantKey $selectedItem.Key ` -NewName $newName ` -Verbose } else { # For overwrite, we need to: # 1. Stop and delete the existing tenant # 2. Restore with the original name Write-Host " Removing existing Tenant '$($selectedItem.Name)'..." -ForegroundColor Yellow $existingTenant = Get-VergeTenant -Name $selectedItem.Name -ErrorAction SilentlyContinue if ($existingTenant) { # Stop if running if ($existingTenant.Status -eq 'online') { Write-Host " Stopping Tenant..." -ForegroundColor Yellow Stop-VergeTenant -Key $existingTenant.Key -Force -Confirm:$false Start-Sleep -Seconds 10 } Remove-VergeTenant -Key $existingTenant.Key -Force -Confirm:$false Start-Sleep -Seconds 5 } Write-Host " Restoring from snapshot..." -ForegroundColor Yellow $result = Restore-VergeTenantFromCloudSnapshot ` -CloudSnapshotKey $selectedSnapshot.Snapshot.Key ` -TenantKey $selectedItem.Key ` -Verbose } } Write-Header "Restore Initiated Successfully" if ($result) { Write-Host " Status: $($result.Status)" -ForegroundColor Green Write-Host " $Type`: $($result."${Type}Name")" if ($result.RestoredAs) { Write-Host " Restored As: $($result.RestoredAs)" } if ($result.TaskKey) { Write-Host " Task ID: $($result.TaskKey)" Write-Host "" Write-Host " Monitor progress with: Get-VergeTask -Key $($result.TaskKey)" -ForegroundColor Cyan } } Write-Host "" Write-Host " Note: The restore operation runs asynchronously." -ForegroundColor Yellow Write-Host " Use Get-VergeVM or Get-VergeTenant to check when complete." -ForegroundColor Yellow } catch { Write-Host "" Write-Host " ERROR: Restore failed!" -ForegroundColor Red Write-Host " $($_.Exception.Message)" -ForegroundColor Red exit 1 } #endregion |