I’ve recently been working with Altaro VM Backup and I must say that I’ve been very impressed with the ease and simplicity of the product. The back-end portion of the product can run on a virtual or physical server with or without the GUI (Server Core is supported). It can backup to just about any type of drive (local disk, UNC path, USB drive, etc). It doesn’t require SQL Server. In my environment, adding a Hyper-V server (running Windows Server 2012 R2) installed a service on the Hypervisor, but did not require a reboot. There’s no agent to install on the VM’s themselves. Recovering an entire VM or specific files within the VM is simple enough. There’s a mode where automated scheduled restores can be performed to validate the end-to-end backup and restore process. Even their licensing model is straightforward. This is how backups and restores are suppose to work <period>.
One very important thing to keep in mind is that Altaro VM Backup is designed to backup VM’s which means that all of the data that you intend on backing up needs to reside in a virtual file (VHD or VHDX for Hyper-V). If some of your VM’s have pass-through drives or you’ve passed through iSCSI network cards and made direct connections to iSCSI targets from VM’s, those drives won’t been seen or backed up by Altaro VM Backup.
There are a number of reasons why a backup taken with Altaro VM Backup may be crash consistent instead of application consistent so I decided to write an operational readiness test using PowerShell and Pester as shown in the following code example to validate all the items listed in one of their support articles.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 | #Requires -Version 3.0 -Modules Pester function Test-MrVMBackupRequirement { <# .SYNOPSIS Tests the requirements for live backups of a Hyper-V Guest VM for use with Altaro VM Backup. .DESCRIPTION Test the requirements for live backups of a Hyper-V Guest VM as defined in this Altaro support article: http://support.altaro.com/customer/portal/articles/808575-what-are-the-requirements-for-live-backups-of-a-hyper-v-guest-vm-. .PARAMETER ComputerName Name of the Hyper-V host virtualization server that the specified VM's are running on. .PARAMETER VMHost Name of the VM (Guest) server to test the requirements for. .PARAMETER Credential Specifies a user account that has permission to perform this action. The default is the current user. .EXAMPLE Test-MrVMBackupRequirement -ComputerName HyperVServer01 -VMName VM01, VCM02 -Credential (Get-Credential) .INPUTS String .OUTPUTS None .NOTES Author: Mike F Robbins Website: http://mikefrobbins.com Twitter: @mikefrobbins #> [CmdletBinding()] param ( [Parameter(Mandatory)] [Alias('VMHost')] [string]$ComputerName, [Parameter(ValueFromPipeline)] [string[]]$VMName, [System.Management.Automation.Credential()]$Credential = [System.Management.Automation.PSCredential]::Empty ) BEGIN { try { $HostSession = New-PSSession -ComputerName $ComputerName -Credential $Credential -ErrorAction Stop } catch { Throw "Unable to connect to Hyper-V host '$ComputerName'. Aborting Pester tests." } $VMs = (Invoke-Command -Session $HostSession { Get-VM | Select-Object -Property Name }).Name if (-not($PSBoundParameters.VMName)) { $VMName = $VMs } } PROCESS { foreach ($VM in $VMName) { Describe "Validation of Altaro VM Backup Requirements for Live Backups of Hyper-V Guest VM: '$VM'" { if ($VM -notin $VMs) { Write-Warning -Message "The VM: '$VM' does not exist on the Hyper-V host: '$ComputerName'" Continue } try { $GuestSession = New-PSSession -ComputerName $VM -Credential $Credential -ErrorAction Stop } catch { Write-Warning -Message "Unable to connect. Aborting Pester tests for computer: '$VM'." Continue } $SupportedGuestOS = '2008 R2', 'Server 2012', 'Server 2012 R2' It "Should be running one of the supported guest OS's ($($SupportedGuestOS -join ', '))" { $OS = (Invoke-Command -Session $GuestSession { Get-WmiObject -Class Win32_OperatingSystem -Property Caption }).caption ($SupportedGuestOS | ForEach-Object {$OS -like "*$_*"}) -contains $true | Should Be $true } $VMInfo = Invoke-Command -Session $HostSession { Get-VM -Name $Using:VM | Select-Object -Property IntegrationServicesState, State } It 'Should have the latest Integration Services version installed' { $VMInfo.IntegrationServicesState -eq 'Up to date' | Should Be $true } It 'Should have Backup (volume snapshot) enabled in the Hyper-V settings' { (Invoke-Command -Session $HostSession { Get-VM -Name $Using:VM | Get-VMIntegrationService -Name VSS | Select-Object -Property Enabled }).enabled | Should Be $true } It 'Should be running' { $VMInfo.State.Value | Should Be 'Running' } $GuestDiskInfo = Invoke-Command -Session $GuestSession { Get-WMIObject -Class Win32_Volume -Filter 'DriveType = 3' -Property Capacity, FileSystem, FreeSpace, Label } It 'Should have at least 10% free disk space on all disks' { $GuestDiskInfo | ForEach-Object {$_.FreeSpace / $_.Capacity * 100} | Should BeGreaterThan 10 } $GuestServiceInfo = Invoke-Command -Session $GuestSession { Get-Service -DisplayName 'Hyper-V Volume Shadow Copy Requestor', 'Volume Shadow Copy', 'COM+ Event System', 'Distributed Transaction Coordinator', 'Remote Procedure Call (RPC)', 'System Event Notification Service' } It 'Should be running the "Hyper-V Volume Shadow Copy Requestor" service on the guest' { ($GuestServiceInfo | Where-Object DisplayName -eq 'Hyper-V Volume Shadow Copy Requestor' ).status | Should Be 'Running' } It 'Should have snapshot file location for VM set to same location as VM VHD file' { #Hyper-V on Windows Server 2008 R2 and higher: The .AVHD file is always created in the same location as its parent virtual hard disk. $HostOS = (Invoke-Command -Session $HostSession { Get-WmiObject -Class Win32_OperatingSystem -Property Version }).version [Version]$HostOS -gt [Version]'6.1.7600' | Should Be $true } It 'Should be running VSS in the guest OS' { ($GuestServiceInfo | Where-Object Name -eq VSS ).status | Should Be 'Running' } It 'Should have a SCSI controller attached in the VM settings' { Invoke-Command -Session $HostSession { Get-VM -Name $Using:VM | Get-VMScsiController } | Should Be $true } It 'Should not have an explicit shadow storage assignment of a volume other than itself' { Invoke-Command -Session $GuestSession { $Results = vssadmin.exe list shadowstorage | Select-String -SimpleMatch 'For Volume', 'Shadow Copy Storage volume' if ($Results) { for ($i = 0; $i -lt $Results.Count; $i+=2){ ($Results[$i] -split 'volume:')[1].trim() -eq ($Results[$i+1] -split 'volume:')[1].trim() } } else { $true } } | Should Be $true } It 'Should not have any App-V drives installed on the VM' { #App-V drives installed on the VM creates a non-NTFS volume. $GuestDiskInfo.filesystem | Should Be 'NTFS' } It 'Should have at least 45MB of free space on system reserved partition if one exists in the guest OS' { ($GuestDiskInfo | Where-Object Label -eq 'System Reserved').freespace / 1MB | Should BeGreaterThan 45 } It 'Should have all volumes formated with NTFS in the guest OS' { $GuestDiskInfo.filesystem | Should Be 'NTFS' } It 'Should have volume containing VHD files formated with NTFS' { $HostDiskLetter = (Invoke-Command -Session $HostSession { Get-VM -Name $Using:VM | Get-VMHardDiskDrive }).path -replace '\\.*$' $HostDiskInfo = Invoke-Command -Session $HostSession { Get-WMIObject -Class Win32_Volume -Filter 'DriveType = 3' -Property DriveLetter, FileSystem } ($HostDiskLetter | ForEach-Object {$HostDiskInfo | Where-Object DriveLetter -eq $_}).filesystem | Should Be 'NTFS' } It 'Should only contain basic and not dynamic disks in the guest OS' { Invoke-Command -Session $GuestSession { $DynamicDisk = 'Logical Disk Manager', 'GPT: Logical Disk Manager Data' Get-WmiObject -Class Win32_DiskPartition -Property Type | ForEach-Object {$DynamicDisk -contains $_.Type} } | Should Be $false } It 'Should be running specific services within the VM' { $RunningServices = 'COM+ Event System', 'Distributed Transaction Coordinator', 'Remote Procedure Call (RPC)', 'System Event Notification Service' ($GuestServiceInfo | Where-Object DisplayName -in $RunningServices).status | Should Be 'Running' } It 'Should have specific services set to manual or automatic within the VM' { $StartMode = (Invoke-Command -Session $GuestSession { Get-WmiObject -Class Win32_Service -Filter "DisplayName = 'COM+ System Application' or DisplayName = 'Microsoft Software Shadow Copy Provider' or DisplayName = 'Volume Shadow Copy'" }).StartMode $StartMode | ForEach-Object {$_ -eq 'Manual' -or $_ -eq 'Automatic'} | Should Be $true } Remove-PSSession -Session $GuestSession } } } END { Remove-PSSession -Session $HostSession } } |
To run the operational validation test, point the ComputerName parameter to a Hyper-V host virtualization server and it will automatically determine all of the VM’s on the host and run the test on each of the VM’s. You can specify specific VM’s to test via the VMName parameter. Use the credential parameter to specify a userid and password with admin privileges on the Hyper-V host and VM’s if you’re running PowerShell as a user who doesn’t have sufficient access.
You could use the PowerShell console or ISE (Integrated Scripting Environment) to run the test from, but the syntax highlighting and progress indicator of Visual Studio Code look amazing:
See my previous articles on how to setup Visual Studio Code for use with PowerShell if that’s something you’re interested in.
The Test-MrVMBackupRequirement function shown in this blog article can be downloaded from my PowerShell repository on GitHub. Found a bug or a better way of accomplishing a task shown in the example code? Feel free to contribute by forking the repository and submitting a pull request.
µ