Use PowerShell and Pester for Operational Readiness Testing of Altaro VM Backup
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
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#Requires -Version 3.0 -Modules Pester
2function Test-MrVMBackupRequirement {
3
4<#
5.SYNOPSIS
6 Tests the requirements for live backups of a Hyper-V Guest VM for use with Altaro VM Backup.
7
8.DESCRIPTION
9 Test the requirements for live backups of a Hyper-V Guest VM as defined in this Altaro support article:
10 http://support.altaro.com/customer/portal/articles/808575-what-are-the-requirements-for-live-backups-of-a-hyper-v-guest-vm-.
11
12.PARAMETER ComputerName
13 Name of the Hyper-V host virtualization server that the specified VM's are running on.
14
15.PARAMETER VMHost
16 Name of the VM (Guest) server to test the requirements for.
17
18.PARAMETER Credential
19 Specifies a user account that has permission to perform this action. The default is the current user.
20
21.EXAMPLE
22 Test-MrVMBackupRequirement -ComputerName HyperVServer01 -VMName VM01, VCM02 -Credential (Get-Credential)
23
24.INPUTS
25 String
26
27.OUTPUTS
28 None
29
30.NOTES
31 Author: Mike F Robbins
32 Website: http://mikefrobbins.com
33 Twitter: @mikefrobbins
34#>
35
36 [CmdletBinding()]
37 param (
38 [Parameter(Mandatory)]
39 [Alias('VMHost')]
40 [string]$ComputerName,
41
42 [Parameter(ValueFromPipeline)]
43 [string[]]$VMName,
44
45 [System.Management.Automation.Credential()]$Credential = [System.Management.Automation.PSCredential]::Empty
46 )
47
48 BEGIN {
49 try {
50 $HostSession = New-PSSession -ComputerName $ComputerName -Credential $Credential -ErrorAction Stop
51 }
52 catch {
53 Throw "Unable to connect to Hyper-V host '$ComputerName'. Aborting Pester tests."
54 }
55
56 $VMs = (Invoke-Command -Session $HostSession {
57 Get-VM | Select-Object -Property Name
58 }).Name
59
60 if (-not($PSBoundParameters.VMName)) {
61 $VMName = $VMs
62 }
63
64 }
65
66 PROCESS {
67 foreach ($VM in $VMName) {
68 Describe "Validation of Altaro VM Backup Requirements for Live Backups of Hyper-V Guest VM: '$VM'" {
69
70 if ($VM -notin $VMs) {
71 Write-Warning -Message "The VM: '$VM' does not exist on the Hyper-V host: '$ComputerName'"
72 Continue
73 }
74
75 try {
76 $GuestSession = New-PSSession -ComputerName $VM -Credential $Credential -ErrorAction Stop
77 }
78 catch {
79 Write-Warning -Message "Unable to connect. Aborting Pester tests for computer: '$VM'."
80 Continue
81 }
82
83 $SupportedGuestOS = '2008 R2', 'Server 2012', 'Server 2012 R2'
84
85 It "Should be running one of the supported guest OS's ($($SupportedGuestOS -join ', '))" {
86 $OS = (Invoke-Command -Session $GuestSession {
87 Get-WmiObject -Class Win32_OperatingSystem -Property Caption
88 }).caption
89
90 ($SupportedGuestOS | ForEach-Object {$OS -like "*$_*"}) -contains $true |
91 Should Be $true
92 }
93
94 $VMInfo = Invoke-Command -Session $HostSession {
95 Get-VM -Name $Using:VM | Select-Object -Property IntegrationServicesState, State
96 }
97
98 It 'Should have the latest Integration Services version installed' {
99 $VMInfo.IntegrationServicesState -eq 'Up to date' |
100 Should Be $true
101 }
102
103 It 'Should have Backup (volume snapshot) enabled in the Hyper-V settings' {
104 (Invoke-Command -Session $HostSession {
105 Get-VM -Name $Using:VM | Get-VMIntegrationService -Name VSS | Select-Object -Property Enabled
106 }).enabled |
107 Should Be $true
108 }
109
110 It 'Should be running' {
111 $VMInfo.State.Value |
112 Should Be 'Running'
113 }
114
115 $GuestDiskInfo = Invoke-Command -Session $GuestSession {
116 Get-WMIObject -Class Win32_Volume -Filter 'DriveType = 3' -Property Capacity, FileSystem, FreeSpace, Label
117 }
118
119 It 'Should have at least 10% free disk space on all disks' {
120 $GuestDiskInfo | ForEach-Object {$_.FreeSpace / $_.Capacity * 100} |
121 Should BeGreaterThan 10
122 }
123
124 $GuestServiceInfo = Invoke-Command -Session $GuestSession {
125 Get-Service -DisplayName 'Hyper-V Volume Shadow Copy Requestor', 'Volume Shadow Copy', 'COM+ Event System',
126 'Distributed Transaction Coordinator', 'Remote Procedure Call (RPC)', 'System Event Notification Service'
127 }
128
129 It 'Should be running the "Hyper-V Volume Shadow Copy Requestor" service on the guest' {
130 ($GuestServiceInfo |
131 Where-Object DisplayName -eq 'Hyper-V Volume Shadow Copy Requestor'
132 ).status |
133 Should Be 'Running'
134 }
135
136 It 'Should have snapshot file location for VM set to same location as VM VHD file' {
137 #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.
138 $HostOS = (Invoke-Command -Session $HostSession {
139 Get-WmiObject -Class Win32_OperatingSystem -Property Version
140 }).version
141
142 [Version]$HostOS -gt [Version]'6.1.7600' |
143 Should Be $true
144 }
145
146 It 'Should be running VSS in the guest OS' {
147 ($GuestServiceInfo |
148 Where-Object Name -eq VSS
149 ).status |
150 Should Be 'Running'
151 }
152
153 It 'Should have a SCSI controller attached in the VM settings' {
154 Invoke-Command -Session $HostSession {
155 Get-VM -Name $Using:VM | Get-VMScsiController
156 } |
157 Should Be $true
158 }
159
160 It 'Should not have an explicit shadow storage assignment of a volume other than itself' {
161 Invoke-Command -Session $GuestSession {
162 $Results = vssadmin.exe list shadowstorage | Select-String -SimpleMatch 'For Volume', 'Shadow Copy Storage volume'
163 if ($Results) {
164 for ($i = 0; $i -lt $Results.Count; $i+=2){
165 ($Results[$i] -split 'volume:')[1].trim() -eq ($Results[$i+1] -split 'volume:')[1].trim()
166 }
167 }
168 else {
169 $true
170 }
171 } |
172 Should Be $true
173 }
174
175 It 'Should not have any App-V drives installed on the VM' {
176 #App-V drives installed on the VM creates a non-NTFS volume.
177 $GuestDiskInfo.filesystem |
178 Should Be 'NTFS'
179 }
180
181 It 'Should have at least 45MB of free space on system reserved partition if one exists in the guest OS' {
182 ($GuestDiskInfo |
183 Where-Object Label -eq 'System Reserved').freespace / 1MB |
184 Should BeGreaterThan 45
185 }
186
187 It 'Should have all volumes formated with NTFS in the guest OS' {
188 $GuestDiskInfo.filesystem |
189 Should Be 'NTFS'
190 }
191
192 It 'Should have volume containing VHD files formated with NTFS' {
193 $HostDiskLetter = (Invoke-Command -Session $HostSession {
194 Get-VM -Name $Using:VM | Get-VMHardDiskDrive
195 }).path -replace '\\.*$'
196
197 $HostDiskInfo = Invoke-Command -Session $HostSession {
198 Get-WMIObject -Class Win32_Volume -Filter 'DriveType = 3' -Property DriveLetter, FileSystem
199 }
200
201 ($HostDiskLetter | ForEach-Object {$HostDiskInfo | Where-Object DriveLetter -eq $_}).filesystem |
202 Should Be 'NTFS'
203 }
204
205 It 'Should only contain basic and not dynamic disks in the guest OS' {
206 Invoke-Command -Session $GuestSession {
207 $DynamicDisk = 'Logical Disk Manager', 'GPT: Logical Disk Manager Data'
208 Get-WmiObject -Class Win32_DiskPartition -Property Type |
209 ForEach-Object {$DynamicDisk -contains $_.Type}
210 } |
211 Should Be $false
212 }
213
214 It 'Should be running specific services within the VM' {
215 $RunningServices = 'COM+ Event System', 'Distributed Transaction Coordinator', 'Remote Procedure Call (RPC)', 'System Event Notification Service'
216 ($GuestServiceInfo | Where-Object DisplayName -in $RunningServices).status |
217 Should Be 'Running'
218 }
219
220 It 'Should have specific services set to manual or automatic within the VM' {
221 $StartMode = (Invoke-Command -Session $GuestSession {
222 Get-WmiObject -Class Win32_Service -Filter "DisplayName = 'COM+ System Application' or DisplayName = 'Microsoft Software Shadow Copy Provider' or DisplayName = 'Volume Shadow Copy'"
223 }).StartMode
224
225 $StartMode | ForEach-Object {$_ -eq 'Manual' -or $_ -eq 'Automatic'} |
226 Should Be $true
227
228 }
229
230 Remove-PSSession -Session $GuestSession
231
232 }
233
234 }
235
236 }
237
238 END {
239 Remove-PSSession -Session $HostSession
240 }
241
242}
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.
µ