Lors de différentes interventions, les administrateurs systèmes m'ont exposé le besoin d'effectuer la sauvegarde complète d'une machine virtuelle Hyper-V en ligne de commande. Ce besoin fait suite généralement que l'existant ne permet pas la sauvegarde automatique des machines ou que le client ne souhaite pas acquérir des licences pour effectuer cette tâche (comme Microsoft System Center Virtual Machine Manager ou Veritas Backup Exec).
Au jour d'aujourd'hui, lors de l'installation d'une plateforme Hyper-V, Microsoft ne fournit pas de commandes PowerShell pour effectuer cette tâche. Mais un projet CodePlex nommé "PowerShell Management Library for Hyper-V" à l'adresse http://pshyperv.codeplex.com/ est disponible et fournit plus de 80 commandes PowerShell.
Cet article va utiliser la commande "Export-VM" qui permet l'export d'une machine virtuelle. Celle-ci est la seule qui permet de définir explicitement l'emplacement où seront stockés les fichiers de sauvegarde. L'inconvénient est que l'on ne peut réaliser un export que lorsque que la machine virtuelle est inactive. Bien entendu cette méthode est à proscrire pour effectuer une sauvegarde complète et récurrente sur des systèmes à haute disponibilité.
Les prérequis sont bien entendu que la fonctionnalité PowerShell soit installé sur le système et l'installation du module Hyper-V "PowerShell Management Library for Hyper-V". Le fichier d'installation est à l'adresse suivante: http://pshyperv.codeplex.com/releases/.
Je vous invite à télécharger la documentation technique complète présente sur la même page pour découvrir l'intégralité des commandes disponibles.
Dès l'installation terminée, vous pouvez de suite utiliser les commandes Hyper-V après avoir chargé le module dans votre script via la ligne suivante:
Import-Module "C:\Program Files\modules\HyperV\HyperV.psd1"
Ensuite, vous devez récupérer une ou plusieurs instances d'objet WMI pour effectuer un traitement sur cette ou ces machines. La commande "Get-VM" et le paramètre "Name" permet d'effectuer cette tâche.
$VmWMIObject = Get-VM –Name "Nom de la machine virtuelle"
Comme explicité, lors du début de l'article, l'export d'une machine ne peut se faire que lorsque celle-ci est éteinte. Les commandes "Invoke-VMShutdown" et "Start-VM" vont permettre d'éteindre le système hôte et de le redémarrer une fois l'export effectué.
Invoke-VMShutdown $VmWMIObject -Reason "Sauvegarde" –Force Start-VM $VmWMIObject -Force –Wait
Les paramètres :
- $VmWMIObject : est l'instance ou les instances de l'objet WMI récupérés auparavant
- Reason : donne une raison de l'extinction du système d'exploitation qui sera stocké dans le journal d'évènement Windows
- Force : ne demande pas la confirmation de l'exécution de la commande à l'utilisateur (ce paramètre est obligatoire si utilisé dans un fichier script)
- Wait: retourne un résultat seulement à la fin de l'exécution de la commande WMI
Pour terminer, nous pouvons effectuer l'export de la machine virtuelle via la commande Export-VM
Export-VM $VmWMIObject -path “Chemin de la sauvegarde” -Copystate -Force –Wait
Les paramètres :
- $VmWMIObject : est l'instance ou les instances de l'objet WMI récupérés auparavant
- Path: Emplacement de sauvegarde des fichiers
- CopyState : donne l'instruction de sauvegarde tous les fichiers de la machine virtuelle (dont les fichiers VHD)
- Force : ne demande pas la confirmation de l'exécution de la commande à l'utilisateur (ce paramètre est obligatoire si utilisé dans un fichier script)
- Wait: retourne un résultat seulement à la fin de l'exécution de la commande WMI
Ci-dessous, vous pouvez lire un script PowerShell complet qui reprend les commandes ci-dessous et j'y ai ajouté la gestion des dossiers de sauvegarde, la gestion des exceptions et l'envoi de courriel:
####################################################
# Paramétrage
####################################################
# Paramétrage Dossier
$BackupFolder = "C:\Backup"
# Paramétrage VM
$VMName = "Machine virtuel"
# Parametrage Email
$EmailFrom = "mail@neos-sdi.com"
$EmailTo = "mail@neos-sdi.com"
$EmailSubject = "[HYPER-V] Sauvegarde Hyper-V"
$EmailBodySuccess = "Succès de la sauvegarde des machines virtuelles"
$EmailBodyFail = "Erreur lors de la sauvegarde des machines virtuelles`n"
$EmailSmtpServer = "mail.neos-sdi.com"
# Paramétrage de la gestion des erreurs
[int]$global:ErrorCount = 0
$global:ErrorMessage = ""
$global:Exit = 0
# Import du module Hyper-V
Import-Module "C:\Program Files\modules\HyperV\HyperV.psd1"
####################################################
# Déclaration des fonctions
####################################################
# Envoi de courriel
function SendEmail()
{
$smtp = new-object Net.Mail.SmtpClient($EmailSmtpServer)
if ($global:ErrorCount -eq [int]0)
{ $t = $smtp.Send($EmailFrom, $EmailTo, $EmailSubject, $EmailBodySuccess) }
else
{ $t = $smtp.Send($EmailFrom, $EmailTo, $EmailSubject, $EmailBodyFail + $global:ErrorMessage) }
}
####################################################
# Gestion des exceptions globales
####################################################
trap { $global:ErrorCount += 1;
$global:ErrorMessage += $_.Exception.GetType().FullName;
$global:ErrorMessage += "`n";
$global:ErrorMessage += $_.Exception.Message;
$global:ErrorMessage += "`n";
$global:ErrorMessage += "`n";
if ($global:Exit -eq [int]0) { continue } else { SendEmail exit } }
####################################################
# Sauvegarde de la machine virtuelle
####################################################
# Suppression de l'ancienne sauvegarde
Remove-Item $BackupFolder -force -recurse -erroraction:SilentlyContinue
# Création du dossier de sauvegarde
New-Item $BackupFolder -type directory
# Récupération de l'objet WMI
$VmWMIObject = Get-VM -name $VMName
if ($VmWMIObject -eq $null)
{ $global:Exit = 1 throw (new-object Exception("Machine virtuelle introuvable.")) }
# Arret de la machine virtuelle
Invoke-VMShutdown $VmWMIObject -reason "Sauvegarde" -force
# Export de la machine virtuelle
Export-VM $VmWMIObject -path $backupfolder -copystate -force -wait
# Démarrage de la machine virtuelle
Start-VM $VmObject -force -wait
# Envoi d'un courriel de succès de la sauvegarde
SendEmail
Vous pouvez utiliser ce script via le planificateur de tâche ou tout autre ordonnanceur.
A bientôt.