Workspace-Guru

XenServerBackup2.5.ps1

May 21st, 2020
7,436
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. <#
  2. .SYNOPSIS
  3.     V2.1 MULTI-Threaded Version
  4.     A Scirpt to backup XenServer VMs to Windows file shares.
  5.     Converted to a Multi-Threaded process by making original script a SINGLE packup as MyScriptBlock
  6.     Changed original remainder to the Multi-Threading calls.
  7.     Thanks to Bill Rogge for creating multi-threaded script.
  8.  
  9. .DESCRIPTION
  10.                 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.
  11. .LINK
  12.     https://workspace-guru.com
  13.    
  14. .EXAMPLE
  15.     Invoke-XenBackup -ExportPath "C:\Backup" -VMnames "VM01" -username "root" -password "P@ssw0rd" -XenHost "XenHost01" -LogPath "C:\temp"
  16.     This will backup VM01 from XenHost01 in C:\Backup. Username and Password are for XenHost01.Logfile will be written in C:\Temp
  17. .EXAMPLE
  18.   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
  19.    This will backup VM01, VM02 and VM03 from XenHost01 in C:\Backup. Username and Password are for XenHost01.
  20.    After the backup the folder will be ZIPd and the backup logfile will be send in a email to [email protected]
  21.  
  22. .NOTES
  23.     File Name  : Invoke-XenServerBackup.ps1
  24.     Author     : Chris Twiest - [email protected] and Bill Rogge - [email protected]
  25.     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
  26. ============================================================
  27.  
  28. #>
  29.  
  30. # There is always ThreadCount + 1 jobs running simultaneously
  31. $global:threadCount = 6
  32. $global:MyScriptBlock = {
  33.     param ([string]$Exp,
  34.         [string]$VM,
  35.         [string]$un,
  36.         [string]$pw,
  37.         [string]$XenH
  38.     )
  39.  
  40.     $backupdate = Get-Date -format yyyy-MM-dd
  41.     $namedate = Get-Date -format yyyy-dd-MM-hh-mm-ss
  42.     #### If Export or Log path is network drive ###
  43.     if ($Exp -like "\\*") {
  44.         $ExpORG = $Exp
  45.         $testnetworklocation = $Exp | test-path
  46.                                
  47.         if ($testnetworklocation) {
  48.             $drvlist = (Get-PSDrive -PSProvider filesystem).Name
  49.             Foreach ($drvltr in "DEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray()) {
  50.                 If ($drvlist -notcontains $drvltr) {
  51.                    New-PSDrive -PSProvider FileSystem -Name $drvltr -Root $ExpORG -Persist | Out-Null
  52.                     break
  53.                 }
  54.             }
  55.             $Exp = $drvltr + ":"
  56.         }
  57.     }
  58.  
  59.     #### Create Backup Folder ######
  60.     $l1 = "$(Get-Date -format yyyy-dd-MM-hh:mm:ss)  $Date --- Start Backup for $VM."
  61.     $Testexportpath = $Exp | Test-Path
  62.     if (!$Testexportpath) {
  63.         New-Item -ItemType Directory -Path "$Exp" | Out-Null
  64.     }
  65.              
  66.     $Testbackuppath = "$Exp\XenBackup-$backupdate" | Test-Path
  67.     if (!$Testbackuppath) {
  68.         New-Item -ItemType Directory -Path "$Exp\XenBackup-$backupdate" | Out-Null
  69.     }
  70.              
  71.     Import-Module XenServerPSModule
  72.     $env:TMP = $Exp
  73.     $env:TEMP = $Exp
  74.    
  75.  
  76.     Try {
  77.         $Session = Connect-XenServer -Url https://$XenH -UserName $un -Password $pw -NoWarnCertificates -SetDefaultSession
  78.     }
  79.  
  80.     Catch [XenAPI.Failure] {
  81.         [string]$PoolMaster = $_.Exception.ErrorDescription[1]
  82.         $Pools.Pool = $PoolMaster
  83.         $Session = Connect-XenServer -url http://$PoolMaster -UserName $un -Password $pw -NoWarnCertificates -SetDefaultSession
  84.     }
  85.  
  86.     #### Create Snapshot and backup folder for each VM ####
  87.     $l2 = "$(Get-Date -format yyyy-dd-MM-hh-mm-ss)  $Date --- Create Snapshot $VM"
  88.     $Testbackupvmpath = "$Exp\XenBackup-$backupdate\$VM" | Test-Path
  89.     if ($testbackupvmpath -like "False") {
  90.         New-Item -ItemType Directory -Path "$Exp\XenBackup-$backupdate\$VM" | Out-Null
  91.     }
  92.  
  93.     $VMUuid = get-XenVM -Name $VM | Select-Object UUID
  94.     $theVMUUID = $VMUuid.uuid
  95.     $theName = "$VM-Backup-$namedate"
  96.     Invoke-XenVM -Uuid $theVMUUID -XenAction Snapshot -NewName $theName -ErrorAction SilentlyContinue
  97.  
  98.     #### Export Snapshot #####
  99.     $l3 = "$(Get-Date -format yyyy-dd-MM-hh-mm-ss)  $Date --- Export Snapshot $VM"
  100.     $theXVA = "$Exp\XenBackup-$backupdate\$VM\$VM-backup.xva"
  101.     Remove-Item $theXVA -Force -ErrorAction SilentlyContinue
  102.  
  103.     $SnapshotUuid = get-XenVM -Name $theName | select UUID
  104.     $theSSUUID = $SnapshotUuid.uuid
  105.     $l4 = Export-XenVm -Uuid $theSSUUID -XenHost $XenH -path $theXVA
  106.  
  107.     $pathtest = $theXVA | test-path
  108.     if ($pathtest -like "False") {
  109.         $l5 = "$(Get-Date -format yyyy-dd-MM-hh-mm-ss)  $Date --- ERROR ---- Export Snapshot $VM failed"
  110.     }
  111.     else {
  112.         $l5 = "$(Get-Date -format yyyy-dd-MM-hh-mm-ss)  $Date --- Export Snapshot $VM finished"
  113.     }
  114.  
  115.     #### Remove Snapshot #####
  116.     $l6 = "$(Get-Date -format yyyy-dd-MM-hh-mm-ss)  $Date --- Delete Snapshot $VM"
  117.     Try { $SnapShot = Get-XenVM -Name $theName | Where is_a_snapshot }
  118.     Catch { $c1 = "$theName was not found on $XenH" }
  119.     Try { $SnapShot | Select -ExpandProperty VBDs | Get-XenVBD | Select -ExpandProperty VDI | where { $_ -ne "OpaqueRef:NULL" } | Remove-XenVDI }
  120.     Catch { $c2 = "   --> $($_.Exception.Message)" }
  121.     $theUUID = $SnapShot.uuid
  122.     Try { Remove-XenVM -Uuid $theUUID ; $l7 = "$(Get-Date -format yyyy-dd-MM-hh:mm:ss)  $Date --- Snapshot has been removed." }
  123.     Catch { $c3 = "   --> $($_.Exception.Message)" }
  124.              
  125.     #### If Export path is network drive ###
  126.     if ($ExpORG -like "\\*") {
  127.         try {
  128.             Remove-Psdrive -Name $drvltr
  129.         }
  130.         catch {
  131.             $l8 = "$(Get-Date -format yyyy-dd-MM-hh:mm:ss)  $Date --- Remove-Psdrive -Name $drvltr ... FAILED"
  132.         }
  133.     }
  134.              
  135.     $return = $l1 + '|' + $l2 + '|' + $l3 + '|' + $l4 + '|' + $l5 + '|' + $l6 + '|' + $l7 + '|' + $l8
  136.     $return
  137. } # MyScriptBlock
  138.  
  139. Function Invoke-XenBackup {
  140.     [CmdletBinding()]
  141.     param (
  142.         [Parameter(Mandatory = $True)]
  143.         [string]$ExportPath,
  144.         [array]$VMnames,
  145.         [string]$username,
  146.         [string]$password,
  147.         [string]$XenHost,
  148.         [string]$LogPath,
  149.         [Parameter(Mandatory = $false)]
  150.         [switch]$Email,
  151.         [string]$SMTPServer,
  152.         [string]$FromEmail,
  153.         [string]$ToEmail,
  154.         [switch]$Zip
  155.     )
  156.  
  157.     #### If Export or Log path is network drive ###
  158.     $backupdate = Get-Date -format yyyy-MM-dd
  159.     if ($logpath -like "\\*") {
  160.         $LogPathOrg = $LogPath
  161.         $testnetworkloglocation = $Logpath | test-path
  162.         if (!$testnetworkloglocation) {
  163.             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."
  164.         }
  165.         else {
  166.             Write-Output "$(Get-Date -format yyyy-dd-MM-hh-mm-ss) - $LogPath is Network drive, will mount drive"
  167.             $logshare = "$logpath"
  168.             $logdrvlist = (Get-PSDrive -PSProvider filesystem).Name
  169.             Foreach ($logdrvletter in "ZYXWVUTSRQPONMLKJIHGFED".ToCharArray()) {
  170.                 If ($logdrvlist -notcontains $logdrvletter) {
  171.                     New-PSDrive -PSProvider filesystem -Name $logdrvletter -Root $logshare -Persist | Out-Null
  172.                     break
  173.                 }
  174.             }
  175.             $LogPath = $logdrvletter + ":"
  176.         }
  177.     }
  178.  
  179.     #%#       Write-Host "Using $LogPath for the LogPath..."
  180.     #### Create Logfile #######
  181.     $datelogfile = Get-Date -format yyyy-dd-MM-hh-mm-ss
  182.     $logfile = "$LogPath\XenBackupLog_$datelogfile.txt"
  183.  
  184.     $testlogpath = "$LogPath" | test-path
  185.  
  186.     if ($testlogpath -like "False") {
  187.         New-Item -ItemType Directory -Path "$LogPath"
  188.     }
  189.  
  190.     New-Item -ItemType File -Path "$logfile" | Out-Null
  191.              
  192.     $date = Get-Date -format yyyy-dd-MM-hh:mm:ss
  193.     Write-Host "$Date --- Start Backup Process"
  194.     Add-Content $logfile "$Date --- Start Backup Process for $VMNames to $Exportpath"
  195.  
  196.     $dataJobs = @()
  197.     [int]$loop = 0
  198.     [int]$max = $VMNames.Count
  199.  
  200.     # Run the multi-threading to have the collection done simultaneously.
  201.     while ($loop -lt $max) {
  202.         $VMName = $VMNames[$loop]
  203.         while ((Get-Job -State Running).count -ge $global:threadCount) { Start-Sleep -Seconds 3 }
  204.         $wl = "$(Get-Date -format yyyy-dd-MM-hh:mm:ss) --- Spawning sub-task for VM '$VMName'"
  205.         Write-Host $wl
  206.         Add-Content $logfile $wl
  207.         $dataJobs += (Start-Job -ScriptBlock $global:MyScriptBlock -Name "$VMName" -ArgumentList @($ExportPath, $VMname, $username, $password, $XenHost))
  208.         Start-Sleep -Seconds 3
  209.         $loop++
  210.     } # while ind -it max
  211.     While (@(Get-Job | Where { $_.State -eq "Running" }).Count -ne 0) {
  212.         Start-Sleep -Seconds 3
  213.     }
  214.  
  215.     # Collect the data from the individual runs.
  216.     foreach ($theJob in $dataJobs) {
  217.         $item = $null
  218.         $item = Receive-Job -Job $theJob
  219.         $L_1, $L_2, $L_3, $L_4, $L_5, $L_6, $L_7, $L_8 = $item.Split('|')
  220.         if ( $L_1.Length -gt 0 ) { Write-Output $L_1 ; Add-Content $logfile $L_1 }
  221.         if ( $L_2.Length -gt 0 ) { Write-Output $L_2 ; Add-Content $logfile $L_2 }
  222.         if ( $L_3.Length -gt 0 ) { Write-Output $L_3 ; Add-Content $logfile $L_3 }
  223.         if ( $L_4.Length -gt 0 ) { Write-Output $L_4 ; Add-Content $logfile $L_4 }
  224.         if ( $L_5.Length -gt 0 ) { Write-Output $L_5 ; Add-Content $logfile $L_5 }
  225.         if ( $L_6.Length -gt 0 ) { Write-Output $L_6 ; Add-Content $logfile $L_6 }
  226.         if ( $L_7.Length -gt 0 ) { Write-Output $L_7 ; Add-Content $logfile $L_7 }
  227.         if ( $L_8.Length -gt 0 ) { Write-Output $L_8 ; Add-Content $logfile $L_8 }
  228.         Remove-Job $theJob
  229.     } # ForEach $job in $dataJobs
  230.  
  231.     #### ZIP Backup #####
  232.     if ($zip) {
  233.         $date = Get-Date -format yyyy-dd-MM-hh:mm:ss
  234.         Write-Host "$Date --- Start ZIP of Backup"
  235.         Add-Content $logfile "$Date --- Start ZIP of Backup"
  236.                                
  237.         $source = "$exportpath\XenBackup-$backupdate"
  238.         $destination = "$Exportpath\XenBackup-$backupdate.zip"
  239.         If (Test-path $destination) { Remove-item $destination }
  240.         Add-Type -assembly "system.io.compression.filesystem"
  241.         [io.compression.zipfile]::CreateFromDirectory($Source, $destination)
  242.                              
  243.         $date = Get-Date -format yyyy-dd-MM-hh:mm:ss
  244.         Write-Host "$Date --- Delete non ZIPd backup"
  245.         Add-Content $logfile "$Date --- Delete non ZIPd backup"
  246.                              
  247.         Remove-item $source -Force -Confirm:$false -Recurse
  248.     }
  249.  
  250.     #### Backup Finished ###
  251.     $date = Get-Date -format yyyy-dd-MM-hh:mm:ss
  252.     Write-Host "$Date --- Backup process done"
  253.     Add-Content $logfile "$Date --- Backup process completed"
  254.  
  255.     if ($Email) {
  256.         $MessageContent = "
  257.                                <head>
  258.                                <style>
  259.                                body {
  260.                                font-family: Arial;
  261.                                font-size: 12px;
  262.                                }
  263.                                </style>
  264.                                </head>
  265.                                <BODY>
  266.                                <P>To Whom It May Concern,<BR>
  267.                                <BR>
  268.                                XenServer Backup of $VMnames to $ExportPath has finished on $date check attached logfile for more info.
  269.                                <P>
  270.                                Greetings,<BR>
  271.                                <BR>
  272.                                XenServer Backup Script
  273.                                </P>
  274.                                </BODY>
  275.                                "
  276.                              
  277.         $messageSubject = "XenServer Backup $(Get-Date -UFormat "%A %d %B %Y") is done."
  278.         $body = $MessageContent
  279.         send-mailmessage -from $FromEmail -to $ToEmail -subject $messageSubject -body $body -BodyAsHtml -smtpServer $SMTPServer -Attachments "$Logfile"
  280.     }
  281.  
  282.     if ($LogPathOrg -like "\\*") {
  283.         Write-Output "$(Get-Date -format yyyy-MM-dd) - $LogPathOrg is Network drive, will dismount drive"
  284.         Remove-Psdrive -Name $logdrvletter
  285.     }
  286.  
  287. }
Advertisement
Add Comment
Please, Sign In to add comment