Backup Citrix VD templates with OVF Tool utility & PowerCLI

This script will automate the process of backing up your Citrix VD templates. As a matter of fact, you can use it for backing up any VM in your vCenter server.

The script leverages the OVF Tool utility. This tool can be downloaded from myvmware.com and should be installed on the server you’re scheduling the script on. For more info: www.vmware.com/support/developer/ovf

The script will run the OVF Tool utility for each Template or VM defined in the CSV file. It will then zip the log files generated by the OVF Tool utility and email them to the email addresses defined in the variables section.

NOTE – Each time the script runs the OVF data is overwritten. Export job logs for previous runs are archived in the Log-Archive folder. The script also creates a console log file in the root of the export folder.

Pre-reqs:

Create a folder on the drive you want to export the Templates or VMs to:

D:\Template-Backups

Copy the VMware OVF Tool folder (C:\Program Files\VMware\VMware OVF Tool) to the root of the folder you created.

Create a CSV file including Template or VM names. Row 1 value must be “Name”.

Copy CSV and script to the root of the folder you created.

NOTE – script will automatically create 3 folders in the root of your backup folder – Backups, Logs, Log-Archive. OVF Tool utility will create a folder for each Template or VM it exports in the Backups folder.

Create a vsphere.local account with following privileges.

Create a (domain) service account. Make this service account a local admin on the server you’re scheduling the script on. The service account will require Anonymous relay privileges on relevant SMTP server and “logon as a batch job” privileges.

Define variables in script:

VariableDescription
$region = “UK”Region identifier
$drive = “D:”Drive on backup server
$backuppath = “\Template-Backups”Folder on root of drive
$SMTPserver = “smtp.domain.com”SMTP server
$SMTPfrom = “email@domain.com”SMTP from address
$SMTPto = “email@domain.com”SMTP to address (can be a Distro group)
$vcenterUsr = “user@vsphere.local”vSphere.local account
$vcenterUsrPsw = “PASSWORD”Password
$vcenter = “vcenter.domain.com”vCenter FQDN
$VDC = “Datacentre” Virtual Datacentre Name
$Folder =”VM folder” Templates folder in vCenter

Scheduling script in Windows Task Manager:

Make sure you use the service account to schedule the task. The “Run with highest privileges” box should be ticked.

Create New Action –

Enter following in Program/script box:
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe

Enter following in Add arguments (optional) box:

-ExecutionPolicy Bypass D:\Template-Backups\template-backup-script.ps1

In the Start in (optional) box:

Enter the Export destination drive e.g. D:\

Testing script:

Run PowerShell in Administrator mode and execute script from the root of the backup folder.

Comment out the console log lines, easier to see where the script is failing.

You can add “–NoDisks” to the OVF Tool command which will ensure the VMDK files are not downloaded.

The Script:

#####################################################################################################
# Written by Cengiz Ulusahin
# Version 1.1 | 04/02/2019
# This script will backup all Citrix VD templates (or any VM) defined in a CSV file by exporting templates as OVF files using the OVF Tool utility 
# The script will power off the templates (if powered on) before carrying out the export process
# The OVF files will be overwritten each time this script runs
# Logs will be archived in the Log-Archive folder
# The script will email log files to the user addresses defined in the variables section for verification purposes
#####################################################################################################

#Function to zip log files
Function ZipFiles($logzipfile, $logsourcedir)
{
Add-Type -Assembly System.IO.Compression.FileSystem
$compressionLevel = [System.IO.Compression.CompressionLevel]::Optimal
[System.IO.Compression.ZipFile]::CreateFromDirectory($logsourcedir,
$logzipfile, $compressionLevel, $false)
}

#Function to send logs via email 
Function Send-Logs
{
Send-MailMessage -SmtpServer "$($SMTPserver)" -To "$($SMTPto)" -From "$($SMTPfrom)" -Subject "$($region) VDI Template backup job is complete" -Body "$($region) VDI Template backup job is complete, please check attached log files!" -Attachment $($logzipfile)
}

#Modify variables below
$region = "UK"
$drive = "D:"
$backuppath = "\Template-Backups"
$SMTPserver = "smtp.domain.com"
$SMTPfrom = "email@domain.com"
$SMTPto = "emeail@domain.com"
$vcenterUsr = "user@vsphere.local"
$vcenterUsrPsw = "PASSWORD"
$vcenter = "vcenter.domain.com"
$VDC = "Datacentre"
$Folder ="VM folder"

#Save and schedule script in Windows scheduler using an account which has access to the backup path

#Do not modify following variable
$console_log = "$($drive)$($backuppath)\console-log.txt"

$(

#Connect to vCenter
Connect-Viserver $vcenter -Username $vcenterUsr -Password $vcenterUsrPsw

#Create folder structure
$ChkBkpPath = "$($drive)$($backuppath)\Backups"
$BkpFolderExists = Test-Path -PathType Container $ChkBkpPath

If ($BkpFolderExists -eq $True) {}

else {
New-Item -ItemType directory -Path "$($drive)$($backuppath)\Backups"
}

$ChkLogPath = "$($drive)$($backuppath)\Logs"
$LogFolderExists = Test-Path -PathType Container $ChkLogPath

If ($LogFolderExists -eq $True) {}

else {
New-Item -ItemType directory -Path "$($drive)$($backuppath)\Logs"
}

$ChkLogArchivePath = "$($drive)$($backuppath)\Log-Archive"
$LogArchiveFolderExists = Test-Path -PathType Container $ChkLogArchivePath

If ($LogArchiveFolderExists -eq $True) {}

else {
New-Item -ItemType directory -Path "$($drive)$($backuppath)\Log-Archive"
}

#Delete old log files
Get-ChildItem -Path "$($drive)$($backuppath)\Logs\*.*" | Remove-Item

#Do not modify following variables
$srcFile = "$($drive)$($backuppath)\VDI-templates-$($region).csv"
$templates = Import-Csv -path $srcFile
$ovftool = "$($drive)$($backuppath)\VMware OVF Tool\ovftool.exe"
$ovflogexportdir = "$($backuppath)\Logs"
$ovfexportdir = "$($backuppath)\Backups"
$date = get-date -f dd-MM-yyyy_HH-mm
$logzipfile = "$($drive)$($backuppath)\Log-Archive\logs_$($date).zip"
$logsourcedir = "$($drive)$($backuppath)\Logs"

#When testing add "--noDisks" to prevent the VMDK file from downloading each time 

foreach ($template in $templates){
& $ovftool "--X:logFile=$($ovflogexportdir)\$($template.Name).txt" "--X:logLevel=verbose" "--noDisks" "--shaAlgorithm=sha1" "--allowAllExtraConfig" "--powerOffSource" "--overwrite" "vi://$($vcenterUsr):$($vcenterUsrPsw)@$($vcenter)/$($VDC)/vm/$($Folder)/$($template.Name)" "$($ovfexportdir)"
} 

#Discconect from vCenter
Disconnect-VIServer -server $vcenter -Confirm:$false

#Zip log files
ZipFiles $logzipfile $logsourcedir

#Send logs for verification
Send-Logs

) *>&1 > "$console_log"

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.