Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <#
- .SYNOPSIS
- V2.1 MULTI-Threaded Version
- A Scirpt to backup XenServer VMs to Windows file shares.
- Converted to a Multi-Threaded process by making original script a SINGLE packup as MyScriptBlock
- Changed original remainder to the Multi-Threading calls.
- Thanks to Bill Rogge for creating multi-threaded script.
- .DESCRIPTION
- This script will take a snapshot of the selected VMs on XenServer. Then it will export the snapshot to a fileshare. You can choose to send a log file trough email. And ZIP the backup.
- .LINK
- https://workspace-guru.com
- .EXAMPLE
- Invoke-XenBackup -ExportPath "C:\Backup" -VMnames "VM01" -username "root" -password "P@ssw0rd" -XenHost "XenHost01" -LogPath "C:\temp"
- This will backup VM01 from XenHost01 in C:\Backup. Username and Password are for XenHost01.Logfile will be written in C:\Temp
- .EXAMPLE
- Invoke-XenBackup -ExportPath "C:\Backup" -VMnames "VM01","VM02","VM03" -username "root" -password "P@ssw0rd" -XenHost "XenHost01" -LogPath "C:\Temp" -Email -SMTPServer "smtp.domain.com" -FromEmail "[email protected]" -ToEmail "[email protected]" -ZIP
- This will backup VM01, VM02 and VM03 from XenHost01 in C:\Backup. Username and Password are for XenHost01.
- After the backup the folder will be ZIPd and the backup logfile will be send in a email to [email protected]
- .NOTES
- File Name : Invoke-XenServerBackup.ps1
- Author : Chris Twiest - [email protected] and Bill Rogge - [email protected]
- To get PowerShell working with Citrix XenServer you need to download and install the XenServer SDK from here https://www.citrix.com/downloads/xenserver/product-software/xenserver-72-standard-edition.html under the Development Components section
- ============================================================
- #>
- # There is always ThreadCount + 1 jobs running simultaneously
- $global:threadCount = 6
- $global:MyScriptBlock = {
- param ([string]$Exp,
- [string]$VM,
- [string]$un,
- [string]$pw,
- [string]$XenH
- )
- $backupdate = Get-Date -format yyyy-MM-dd
- $namedate = Get-Date -format yyyy-dd-MM-hh-mm-ss
- #### If Export or Log path is network drive ###
- if ($Exp -like "\\*") {
- $ExpORG = $Exp
- $testnetworklocation = $Exp | test-path
- if ($testnetworklocation) {
- $drvlist = (Get-PSDrive -PSProvider filesystem).Name
- Foreach ($drvltr in "DEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray()) {
- If ($drvlist -notcontains $drvltr) {
- New-PSDrive -PSProvider FileSystem -Name $drvltr -Root $ExpORG -Persist | Out-Null
- break
- }
- }
- $Exp = $drvltr + ":"
- }
- }
- #### Create Backup Folder ######
- $l1 = "$(Get-Date -format yyyy-dd-MM-hh:mm:ss) $Date --- Start Backup for $VM."
- $Testexportpath = $Exp | Test-Path
- if (!$Testexportpath) {
- New-Item -ItemType Directory -Path "$Exp" | Out-Null
- }
- $Testbackuppath = "$Exp\XenBackup-$backupdate" | Test-Path
- if (!$Testbackuppath) {
- New-Item -ItemType Directory -Path "$Exp\XenBackup-$backupdate" | Out-Null
- }
- Import-Module XenServerPSModule
- $env:TMP = $Exp
- $env:TEMP = $Exp
- Try {
- $Session = Connect-XenServer -Url https://$XenH -UserName $un -Password $pw -NoWarnCertificates -SetDefaultSession
- }
- Catch [XenAPI.Failure] {
- [string]$PoolMaster = $_.Exception.ErrorDescription[1]
- $Pools.Pool = $PoolMaster
- $Session = Connect-XenServer -url http://$PoolMaster -UserName $un -Password $pw -NoWarnCertificates -SetDefaultSession
- }
- #### Create Snapshot and backup folder for each VM ####
- $l2 = "$(Get-Date -format yyyy-dd-MM-hh-mm-ss) $Date --- Create Snapshot $VM"
- $Testbackupvmpath = "$Exp\XenBackup-$backupdate\$VM" | Test-Path
- if ($testbackupvmpath -like "False") {
- New-Item -ItemType Directory -Path "$Exp\XenBackup-$backupdate\$VM" | Out-Null
- }
- $VMUuid = get-XenVM -Name $VM | Select-Object UUID
- $theVMUUID = $VMUuid.uuid
- $theName = "$VM-Backup-$namedate"
- Invoke-XenVM -Uuid $theVMUUID -XenAction Snapshot -NewName $theName -ErrorAction SilentlyContinue
- #### Export Snapshot #####
- $l3 = "$(Get-Date -format yyyy-dd-MM-hh-mm-ss) $Date --- Export Snapshot $VM"
- $theXVA = "$Exp\XenBackup-$backupdate\$VM\$VM-backup.xva"
- Remove-Item $theXVA -Force -ErrorAction SilentlyContinue
- $SnapshotUuid = get-XenVM -Name $theName | select UUID
- $theSSUUID = $SnapshotUuid.uuid
- $l4 = Export-XenVm -Uuid $theSSUUID -XenHost $XenH -path $theXVA
- $pathtest = $theXVA | test-path
- if ($pathtest -like "False") {
- $l5 = "$(Get-Date -format yyyy-dd-MM-hh-mm-ss) $Date --- ERROR ---- Export Snapshot $VM failed"
- }
- else {
- $l5 = "$(Get-Date -format yyyy-dd-MM-hh-mm-ss) $Date --- Export Snapshot $VM finished"
- }
- #### Remove Snapshot #####
- $l6 = "$(Get-Date -format yyyy-dd-MM-hh-mm-ss) $Date --- Delete Snapshot $VM"
- Try { $SnapShot = Get-XenVM -Name $theName | Where is_a_snapshot }
- Catch { $c1 = "$theName was not found on $XenH" }
- Try { $SnapShot | Select -ExpandProperty VBDs | Get-XenVBD | Select -ExpandProperty VDI | where { $_ -ne "OpaqueRef:NULL" } | Remove-XenVDI }
- Catch { $c2 = " --> $($_.Exception.Message)" }
- $theUUID = $SnapShot.uuid
- Try { Remove-XenVM -Uuid $theUUID ; $l7 = "$(Get-Date -format yyyy-dd-MM-hh:mm:ss) $Date --- Snapshot has been removed." }
- Catch { $c3 = " --> $($_.Exception.Message)" }
- #### If Export path is network drive ###
- if ($ExpORG -like "\\*") {
- try {
- Remove-Psdrive -Name $drvltr
- }
- catch {
- $l8 = "$(Get-Date -format yyyy-dd-MM-hh:mm:ss) $Date --- Remove-Psdrive -Name $drvltr ... FAILED"
- }
- }
- $return = $l1 + '|' + $l2 + '|' + $l3 + '|' + $l4 + '|' + $l5 + '|' + $l6 + '|' + $l7 + '|' + $l8
- $return
- } # MyScriptBlock
- Function Invoke-XenBackup {
- [CmdletBinding()]
- param (
- [Parameter(Mandatory = $True)]
- [string]$ExportPath,
- [array]$VMnames,
- [string]$username,
- [string]$password,
- [string]$XenHost,
- [string]$LogPath,
- [Parameter(Mandatory = $false)]
- [switch]$Email,
- [string]$SMTPServer,
- [string]$FromEmail,
- [string]$ToEmail,
- [switch]$Zip
- )
- #### If Export or Log path is network drive ###
- $backupdate = Get-Date -format yyyy-MM-dd
- if ($logpath -like "\\*") {
- $LogPathOrg = $LogPath
- $testnetworkloglocation = $Logpath | test-path
- if (!$testnetworkloglocation) {
- Write-Output "$(Get-Date -format yyyy-dd-MM-hh-mm-ss) - Can't acces networkdrive make sure the script is run with the correct rights."
- }
- else {
- Write-Output "$(Get-Date -format yyyy-dd-MM-hh-mm-ss) - $LogPath is Network drive, will mount drive"
- $logshare = "$logpath"
- $logdrvlist = (Get-PSDrive -PSProvider filesystem).Name
- Foreach ($logdrvletter in "ZYXWVUTSRQPONMLKJIHGFED".ToCharArray()) {
- If ($logdrvlist -notcontains $logdrvletter) {
- New-PSDrive -PSProvider filesystem -Name $logdrvletter -Root $logshare -Persist | Out-Null
- break
- }
- }
- $LogPath = $logdrvletter + ":"
- }
- }
- #%# Write-Host "Using $LogPath for the LogPath..."
- #### Create Logfile #######
- $datelogfile = Get-Date -format yyyy-dd-MM-hh-mm-ss
- $logfile = "$LogPath\XenBackupLog_$datelogfile.txt"
- $testlogpath = "$LogPath" | test-path
- if ($testlogpath -like "False") {
- New-Item -ItemType Directory -Path "$LogPath"
- }
- New-Item -ItemType File -Path "$logfile" | Out-Null
- $date = Get-Date -format yyyy-dd-MM-hh:mm:ss
- Write-Host "$Date --- Start Backup Process"
- Add-Content $logfile "$Date --- Start Backup Process for $VMNames to $Exportpath"
- $dataJobs = @()
- [int]$loop = 0
- [int]$max = $VMNames.Count
- # Run the multi-threading to have the collection done simultaneously.
- while ($loop -lt $max) {
- $VMName = $VMNames[$loop]
- while ((Get-Job -State Running).count -ge $global:threadCount) { Start-Sleep -Seconds 3 }
- $wl = "$(Get-Date -format yyyy-dd-MM-hh:mm:ss) --- Spawning sub-task for VM '$VMName'"
- Write-Host $wl
- Add-Content $logfile $wl
- $dataJobs += (Start-Job -ScriptBlock $global:MyScriptBlock -Name "$VMName" -ArgumentList @($ExportPath, $VMname, $username, $password, $XenHost))
- Start-Sleep -Seconds 3
- $loop++
- } # while ind -it max
- While (@(Get-Job | Where { $_.State -eq "Running" }).Count -ne 0) {
- Start-Sleep -Seconds 3
- }
- # Collect the data from the individual runs.
- foreach ($theJob in $dataJobs) {
- $item = $null
- $item = Receive-Job -Job $theJob
- $L_1, $L_2, $L_3, $L_4, $L_5, $L_6, $L_7, $L_8 = $item.Split('|')
- if ( $L_1.Length -gt 0 ) { Write-Output $L_1 ; Add-Content $logfile $L_1 }
- if ( $L_2.Length -gt 0 ) { Write-Output $L_2 ; Add-Content $logfile $L_2 }
- if ( $L_3.Length -gt 0 ) { Write-Output $L_3 ; Add-Content $logfile $L_3 }
- if ( $L_4.Length -gt 0 ) { Write-Output $L_4 ; Add-Content $logfile $L_4 }
- if ( $L_5.Length -gt 0 ) { Write-Output $L_5 ; Add-Content $logfile $L_5 }
- if ( $L_6.Length -gt 0 ) { Write-Output $L_6 ; Add-Content $logfile $L_6 }
- if ( $L_7.Length -gt 0 ) { Write-Output $L_7 ; Add-Content $logfile $L_7 }
- if ( $L_8.Length -gt 0 ) { Write-Output $L_8 ; Add-Content $logfile $L_8 }
- Remove-Job $theJob
- } # ForEach $job in $dataJobs
- #### ZIP Backup #####
- if ($zip) {
- $date = Get-Date -format yyyy-dd-MM-hh:mm:ss
- Write-Host "$Date --- Start ZIP of Backup"
- Add-Content $logfile "$Date --- Start ZIP of Backup"
- $source = "$exportpath\XenBackup-$backupdate"
- $destination = "$Exportpath\XenBackup-$backupdate.zip"
- If (Test-path $destination) { Remove-item $destination }
- Add-Type -assembly "system.io.compression.filesystem"
- [io.compression.zipfile]::CreateFromDirectory($Source, $destination)
- $date = Get-Date -format yyyy-dd-MM-hh:mm:ss
- Write-Host "$Date --- Delete non ZIPd backup"
- Add-Content $logfile "$Date --- Delete non ZIPd backup"
- Remove-item $source -Force -Confirm:$false -Recurse
- }
- #### Backup Finished ###
- $date = Get-Date -format yyyy-dd-MM-hh:mm:ss
- Write-Host "$Date --- Backup process done"
- Add-Content $logfile "$Date --- Backup process completed"
- if ($Email) {
- $MessageContent = "
- <head>
- <style>
- body {
- font-family: Arial;
- font-size: 12px;
- }
- </style>
- </head>
- <BODY>
- <P>To Whom It May Concern,<BR>
- <BR>
- XenServer Backup of $VMnames to $ExportPath has finished on $date check attached logfile for more info.
- <P>
- Greetings,<BR>
- <BR>
- XenServer Backup Script
- </P>
- </BODY>
- "
- $messageSubject = "XenServer Backup $(Get-Date -UFormat "%A %d %B %Y") is done."
- $body = $MessageContent
- send-mailmessage -from $FromEmail -to $ToEmail -subject $messageSubject -body $body -BodyAsHtml -smtpServer $SMTPServer -Attachments "$Logfile"
- }
- if ($LogPathOrg -like "\\*") {
- Write-Output "$(Get-Date -format yyyy-MM-dd) - $LogPathOrg is Network drive, will dismount drive"
- Remove-Psdrive -Name $logdrvletter
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment