Intro

I wanted to add a second backup method to an Hyper-V hypervisor. The backup destination had to be an USB disk. In fact, the need was to have a secondary backup which could be usable in case of ransomware attack (to face the case where our main backup destination has been infected). We will do a backup to two differents USB disks : when the first one is connected, the second will not. Veeam Backup & Replication Free was a good choice, because it's a good software backup, it's free, and we can script it with PowerShell.

Code

v1.0 - Simplest one

###########################
# author : shebangthedolphins.net
# version : 1.0
# date : 2019.02
# role : veeam backup to a USB disk and send an e-mail report
# other :
# - Need to install  Veeam Backup Replication Free
# - Tested on a Windows 2012R2 Standard, with Hyper-V role and Veeam Backup & Replication Free 9.5 Update 4
# - USB disk are set to be mounted with F:\ letter
# updates :
#       - 1.0 : first version, simple one

#Import veeam PowerShell snap-ins to the current session
Add-PSSnapin veeamPSSnapin

#Set Variables
$VMs = Get-Vm | select -ExpandProperty Name #Put every VM names into $VMs variable
$Error = 0 #set $Error flag
$encoding = [System.Text.Encoding]::UTF8
$array = @()
$Body = ""

foreach ($VM in $VMs) {
    $HVObject = Find-VBRHvEntity -Server HV01 -Name $VM
    $Result = Start-VBRZip -Folder "F:\VEEAM" -Entity $HVObject -AutoDelete Tonight -Compression 5 | select -ExpandProperty Result #do "Get-Help Start-VBRZip -detailed" to know more
    if ([string]$Result -ne 'Success' -or -not ($?)) {
        $Error = 1 #we set Error flag to 1
        $Result = "Error"
    }
    $array += @{ Vm = $VM; Result = $Result }
}

foreach($value in $array) #We set our e-mail body
{
    $Body += "VM Backup " + $value.Vm + " ended with : " + $value.Result + "result`n"
}

#email backup report
if ($Error -eq "0") {
    Send-MailMessage -To veeam-usb-backup@shebangthedolphins.net -Subject "Veeam USB Backup - OK" -From backup-usb@shebangthedolphins.net -smtpserver smtp.shebangthedolphins.net -Body $Body -Encoding $encoding #send email
} else {
    Send-MailMessage -To veeam-usb-backup@shebangthedolphins.net -Subject "Veeam USB Backup - KO" -From backup-usb@shebangthedolphins.net -smtpserver smtp.shebangthedolphins.net -Body $Body -Encoding $encoding  #send email
}

v2.0 - Retries up to 5 times if it fails

###########################
# author : shebangthedolphins.net
# version : 2.0
# date : 2019.03
# role : veeam backup to a USB disk and send an e-mail report
# other :
# - Need to install  Veeam Backup Replication Free
# - Tested on a Windows 2012R2 Standard, with Hyper-V role and Veeam Backup & Replication Free 9.5 Update 4
# - USB disk are set to be mounted with F:\ letter
# updates :
#       - 2.0 : if a backup fails, try again until 5 times. Automaticaly delete backups which have failed.

#Import veeam PowerShell snap-ins to the current session
Add-PSSnapin veeamPSSnapin

#Set Variables
$VMs = Get-Vm | select -ExpandProperty Name #Put every VM names into $VMs variable
$Error = 0 #set $Error flag
$encoding = [System.Text.Encoding]::UTF8
$array = @()
$array_VMs_Error = @()
$Body = ""
$i = 0

foreach ($VM in $VMs) {
    $HVObject = Find-VBRHvEntity -Server HYPER-V -Name $VM #Replace HYPER-V by your own server hostname
    $Result = Start-VBRZip -Folder "F:\VEEAM" -Entity $HVObject -AutoDelete TomorrowNight -Compression 5 | select -ExpandProperty Result #do "Get-Help Start-VBRZip -detailed" to know more
    $ExitCode = $?
    if ([string]$Result -ne 'Success' -or -not ($ExitCode)) {
	$array_VMs_Error += @{ Vm = $VM } #We log VMs which failed to be saved
    } else {
        $array += @{ Vm = $VM; Result = $Result } #We log VMs which success
    }
}

foreach($value in $array_VMs_Error) #If VMs has failed we try to backup them again here
{
    $HVObject = Find-VBRHvEntity -Server HYPER-V -Name $value.Vm #Replace HYPER-V by your own server hostname
    $Result = Start-VBRZip -Folder "F:\VEEAM" -Entity $HVObject -AutoDelete TomorrowNight -Compression 5 | select -ExpandProperty Result #do "Get-Help Start-VBRZip -detailed" to know more
    $ExitCode = $?
    While (([string]$Result -ne 'Success' -or -not ($ExitCode)) -and $i -lt 5) { #Try to backup again if error but abord it already tried 5 times
        $i++
        $Result = Start-VBRZip -Folder "F:\VEEAM" -Entity $HVObject -AutoDelete TomorrowNight -Compression 5 | select -ExpandProperty Result
        $ExitCode = $?
    }
    if ([string]$Result -ne 'Success' -or -not ($ExitCode)) { #if backup fails after 5 times
        $Error = 1 #we set Error flag to 1
        $Result = "Error"
    }
    $array += @{ Vm = $value.Vm; Result = $Result } #We had entry to our array which contains results for all VMs
    $i = 0
}

foreach($value in $array) #We set our e-mail body
{
    $Body += "VM Backup " + $value.Vm + " ended with : " + $value.Result + "result`n"
}

#Delete backups which have failed (all vbk files on F:\ which are less than 25Mo) :
Get-ChildItem F:\ -Recurse -Filter *vbk | Where-Object { $_.Length / 1MB -lt 25 } | Remove-Item -Force

#email backup report
if ($Error -eq "0") {
    Send-MailMessage -To veeam-usb-backup@shebangthedolphins.net -Subject "Veeam USB Backup - OK" -From backup-usb@shebangthedolphins.net -smtpserver smtp.shebangthedolphins.net -Body $Body -Encoding $encoding #send email
} else {
    Send-MailMessage -To veeam-usb-backup@shebangthedolphins.net -Subject "Veeam USB Backup - KO" -From backup-usb@shebangthedolphins.net -smtpserver smtp.shebangthedolphins.net -Body $Body -Encoding $encoding  #send email
}

Task Scheduler

Have to do this later..

Licence Creative Commons
This websitehttp://shebangthedolphins.net is licensed to the public under a licence Creative Commons Attribution licence.
Contact :