Windows Server 2012: backup VM in Hyper-V
Con Windows Server 2012 è stato introdotto il modulo per la gestione di Hyper-V tramite PowerShell che rende disponibili 164 cmdlets, per l’elenco e la documentazione di ciascun cmdlet si veda la sezione di TechNet Hyper-V Cmdlets in Windows PowerShell.
E’ possibile vedere l’elenco dei comandi dalla console di PowerShell tramite i comandi:
- Elenco cmdlets: Get-Command -Module Hyper-V
- Count dei cmdlets: (Get-Command -Module Hyper-V).Count
- Help di un cmdlet: Get-Help NomeCmdlet (xes: Get-Help GET-VM la prima volta che si invoca il cmd Get-Help verrà richiesto di scaricare l’help, ovvero verrà eseguito il cmdlet Update-Help)
L’introduzione del modulo PowerShell Hyper-V rende quindi non più necessaria la PowerShell Management Library for Hyper-V che rendeva disponibile circa 80 cmdlets per la gestione di Hyper-V in Windows Server 2008 R2.
Questo significa che ad esempio è possibile rivedere lo script che avevo descritto nel post Hyper-V backup di macchine virtuali sfruttando i cmdlet offerti dal modulo Hyper-V in Windows Server 2012.
Di seguito riporto la versione per Windows Server 2012 dello script che può eseguire le operazioni di arresto VM, compattazione dei VHD nella VM, export della VM, avvio della VM, gestione del mantenimento del numero di copie di back e gestione log.
Nella nella sezione iniziale dello script è possibile impostare le seguenti configurazioni:
- Nome macchina virtuale ($vmName = “VMTest”)
- Path backup ($bkpPath = “F:\HyperV-Export”)
- Numero di backup da mantenere ($bkpCopiesRetained = 2)
- Compressione VHD della VM prima dell’esportazione ($compressVHDs = $TRUE)
- Avvio della VM al termine del backup ($startVM = $TRUE)
- Esecuzione dell’esportazione della VM ($exportVM = $TRUE)
- Path dei file log ($logFilePath = $bkpPath)
- Suffisso del nome dei file log ($logFileNameSuffix = “LogBackup”)
- Numero di file di log da mantenere ($logFilesRetained = 3)
Script BackupVMTest.ps1:
# *** Impostazioni ***
$vmName = “VMTest”
$bkpPath = “F:\HyperV-Export”
$bkpCopiesRetained = 2
$compressVHDs = $TRUE
$startVM = $TRUE
$exportVM = $TRUE
$logFilePath = $bkpPath
$logFileNameSuffix = “LogBackup”
$logFilesRetained = 3
# ************************# *** Import modulo Hyper-V
Import-Module Hyper-V# *** Inizializzazioni ***
$now = Get-Date
$expPathVM = $bkpPath + “\” + $vmName
$bkpPathVM = $expPathVM + “-” + $now.ToString(“yyyy-MM-dd-HH-mm-ss”)
$logFileNameBase = $logFilePath + “\” + $logFileNameSuffix + “-” + $vmName
$logFile = $logFileNameBase + “-” + $now.ToString(“yyyy-MM-dd-HH-mm-ss”) + “.txt”
# ************************# *** Creazione Backup Path
if (!(Test-Path $bkpPath)){
New-Item $bkpPath -type directory
}# *** Creazione Log Path
if (!(Test-Path $logFilePath)){
New-Item $logFilePath -type directory
}# *** Avvio backup
(Get-Date).ToString(“yyyy-MM-dd HH:mm:ss”) + ” Avvio Backup” | Out-File $logFile# **** Shutdown virtual machines
if ((Get-VM -Name $vmName).State -eq “Running”){
(Get-Date).ToString(“yyyy-MM-dd HH:mm:ss”) + ” Arresto VM ” + $vmName | Out-File $logFile -append
Stop-VM -Name $vmName -force -Verbose | Out-File $logFile -append
}
else{
(Get-Date).ToString(“yyyy-MM-dd HH:mm:ss”) + ” VM ” + $vmName + ” non attiva”| Out-File $logFile -append
}# *** Compattamento VHD
if ($compressVHDs){
Get-VMHardDiskDrive -VMName $vmName | foreach {
if ($_.Path -ne $NULL) {
if ($_.Path.EndsWith(“.iso”) -eq $FALSE){
(Get-Date).ToString(“yyyy-MM-dd HH:mm:ss”) + ” Compressione VHD ” + $_.DiskPath | Out-File $logFile -append
Optimize-VHD -Path $_.Path -Verbose | Out-File $logFile -append
}
}
}
}# *** Export virtual machines
if ($exportVM){
(Get-Date).ToString(“yyyy-MM-dd HH:mm:ss”) + ” Esportazione VM ” + $vmName | Out-File $logFile -append
Export-VM -Name $vmName -Path $bkpPath -Verbose | Out-File $logFile -append
}# *** Avvio VM
if ($startVM){
(Get-Date).ToString(“yyyy-MM-dd HH:mm:ss”) + ” Avvio VM ” + $vmName | Out-File $logFile -append
Start-VM -Name $vmName -Verbose | Out-File $logFile -append
}# *** Rename directory esportazione
if (Test-Path ($expPathVM)){
(Get-Date).ToString(“yyyy-MM-dd HH:mm:ss”) + ” Rename directory esportazione” | Out-File $logFile -append
Move-Item $expPathVM $bkpPathVM -Verbose | Out-File $logFile -append
}# *** Eliminazione backup obsoleti
$bkpFolders = Get-ChildItem $bkpPath | Where {$_.psIsContainer -eq $true -and $_.FullName -like ($expPathVM + “*”)} | Sort $_.FullNameif ($bkpFolders.Count -gt $bkpCopiesRetained){
for ($i = 1; $i -le $bkpFolders.Count – $bkpCopiesRetained; $i++) {
(Get-Date).ToString(“yyyy-MM-dd HH:mm:ss”) + ” Eliminazione backup directory ” + $bkpFolders[$i-1].FullName | Out-File $logFile -append
Remove-Item $bkpFolders[$i-1].FullName -Recurse -Verbose | Out-File $logFile -append
}
}# *** Eliminazione log file obsoleti
$logFiles = Get-ChildItem $logFilePath | Where {$_.psIsContainer -eq $false -and $_.FullName -like ($logFileNameBase + “*”)} | Sort $_.FullNameif ($logFiles.Count -gt $logFilesRetained){
for ($i = 1; $i -le $logFiles.Count – $logFilesRetained; $i++) {
(Get-Date).ToString(“yyyy-MM-dd HH:mm:ss”) + ” Eliminazione log file ” + $logFiles[$i-1].FullName | Out-File $logFile -append
Remove-Item $logFiles[$i-1].FullName -Verbose | Out-File $logFile -append
}
}# *** Termine backup
(Get-Date).ToString(“yyyy-MM-dd HH:mm:ss”) + ” Backup terminato” | Out-File $logFile –append
Per avviare lo script ad esempio da un’operazione schedulata è possibile utilizzare il comando:
%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe Path\BackupVMTest.ps1
Per poter eseguire gli script PowerShell locali occorre impostare l’execution policy ad esempio su RemoteSigned con il seguente comando (a riguardo si veda Using the Set-ExecutionPolicy Cmdlet):
Set-ExecutionPolicy RemoteSigned
Lo script può essere eseguito anche in ambiente Windows 8 dove è stato installato il Client Hyper-V, a tal proposito dal momento che sui sistemi operativi client l’account Administrator è disabilitato per default si ricordi che lo script deve essere eseguito con privilegi amministrativi.