📋 Planificateur de point de contrôle sur un cluster hyper-v
Gestionnaire de Snapshots planifiés pour Cluster Hyper-V.
Planificateur de point de contrôle sur un cluster hyper-v
Ce script permet de planifier automatiquement des points de contrôle (snapshots) sur un cluster Hyper-V.
Les référents métiers demandent régulièrement la création de points de contrôle avant une opération sensible (mise à jour applicative, changement de configuration, maintenance, etc.). Jusqu’à présent, cela nécessitait l’ouverture d’un ticket de support puis une intervention manuelle le jour J à l’heure H, avec connexion sur un nœud du cluster pour exécuter l’action.
Afin de répondre à ce besoin et de gagner en réactivité, j’ai mis en place une solution reposant sur :
- un script PowerShell (.ps1) chargé d’exécuter les opérations,
- le Planificateur de tâches Windows pour lancer automatiquement les traitements à la date et l’heure souhaitées,
- des fichiers de configuration .psd1 permettant de déclarer simplement les machines virtuelles concernées et les points de contrôle à créer.
Script
<#
.SYNOPSIS
Gestionnaire de Snapshots planifiés pour Cluster Hyper-V.
Supporte l'exécution directe ou via file d'attente PSD1.
#>
param(
[string]$ClusterName,
[string]$VMName,
[string]$PSD1Folder = "C:\PlannedSnapshot",
[int]$RetentionDays = 3,
[bool]$DeleteOldSnapshot = $true,
[bool]$EmailNotification = $true
)
--- Configuration Email ---
$SmtpConfig = @{
Server = "smtp.domain.tld"
Port = 25
From = "[email protected]"
}
--- Fonction d'envoi d'Email ---
function Send-Notification {
param([string]$TargetVM, [string]$Status, [string]$Details, [string]$Recipient)
if ([string]::IsNullOrWhiteSpace($Recipient)) { $Recipient = "[email protected]" }
$Subject = "[$Status] Snapshot Cluster Hyper-V : $TargetVM"
$Body = "Action sur la VM : $TargetVMnStatut : $StatusnDate : $(Get-Date)nnDétails :`n$Details"
try {
Send-MailMessage -SmtpServer $SmtpConfig.Server -Port $SmtpConfig.Port `
-From $SmtpConfig.From -To $Recipient `
-Subject $Subject -Body $Body -Encoding UTF8
} catch {
Write-Warning "Impossible d'envoyer l'email : $($_.Exception.Message)"
}
}
--- Fonction Principale d'Action ---
function Invoke-ClusterSnapshot {
param($CName, $VName, $RetDays, $DoDelete, $EmailNotify, $To)
Write-Host "--- Traitement de $VName sur $CName ---" -ForegroundColor Cyan
try {
# 1. Vérification connectivité
if (!(Test-Connection -ComputerName $CName -Count 1 -Quiet)) {
throw "Le cluster $CName est injoignable par le réseau."
}
# 2. Localisation de la VM
if (!(Get-Module FailoverClusters)) { Import-Module FailoverClusters }
$VMGroup = Get-ClusterGroup -Cluster $CName | Where-Object { $_.Name -like "$VName" }
if (-not $VMGroup) { throw "La VM '$VName' n'a pas été trouvée sur le cluster $CName." }
$OwnerNode = $VMGroup.OwnerNode.Name
Write-Host "VM localisée sur le nœud : $OwnerNode" -ForegroundColor Gray
# 3. Exécution Hyper-V sur le nœud propriétaire
Invoke-Command -ComputerName $OwnerNode -ScriptBlock {
param($TargetVM, $Retention, $Delete)
Import-Module Hyper-V
$DateStr = Get-Date -Format "yyyy-MM-dd-HHmm"
$SnapshotName = "Auto-Snapshot-$DateStr"
# Création du checkpoint
CheckPoint-VM -Name $TargetVM -SnapshotName $SnapshotName -ErrorAction Stop
# Nettoyage
if ($Delete) {
$LimitDate = (Get-Date).AddDays(-$Retention)
$Old = Get-VMSnapshot -VMName $TargetVM | Where-Object { $_.CreationTime -lt $LimitDate }
if ($Old) { $Old | Remove-VMSnapshot }
}
} -ArgumentList $VName, $RetDays, $DoDelete
if ($EmailNotify) { Send-Notification -TargetVM $VName -Status "SUCCÈS" -Details "Checkpoint créé avec succès sur $OwnerNode." -Recipient $To }
return $true
} catch {
$err = "Erreur : $($_.Exception.Message)"
Write-Host $err -ForegroundColor Red
if ($EmailNotify) { Send-Notification -TargetVM $VName -Status "ERREUR" -Details $err -Recipient $To }
return $false
}
}
--- LOGIQUE D'EXÉCUTION ---
CAS 1 : APPEL DIRECT (Paramètres manuels)
if (![string]::IsNullOrWhiteSpace($ClusterName) -and ![string]::IsNullOrWhiteSpace($VMName)) {
Invoke-ClusterSnapshot -CName $ClusterName -VName $VMName -RetDays $RetentionDays -DoDelete $DeleteOldSnapshot -EmailNotify $EmailNotification
}
CAS 2 : SCAN DU DOSSIER (Mode Automatique)
else {
if (!(Test-Path $PSD1Folder)) {
Write-Error "Dossier $PSD1Folder introuvable."
exit 100
}
$Files = Get-ChildItem -Path $PSD1Folder -Filter "*.psd1"
$Now = Get-Date
# Fenêtre de rattrapage : On traite tout ce qui est prévu entre il y a 20 min et maintenant + 1 min
$StartWindow = $Now.AddMinutes(-20)
$EndWindow = $Now.AddMinutes(1)
foreach ($File in $Files) {
try {
$Config = Import-PowerShellDataFile -Path $File.FullName
$PlannedDate = [datetime]::ParseExact("$($Config.Date) $($Config.Heure)", "dd/MM/yyyy HH:mm", $null)
if ($PlannedDate -ge $StartWindow -and $PlannedDate -le $EndWindow) {
Write-Host "Fichier trouvé : $($File.Name) (Prévu à $PlannedDate)" -ForegroundColor Yellow
$Result = Invoke-ClusterSnapshot -CName $Config.ClusterName `
-VName $Config.VMName `
-RetDays $RetentionDays `
-DoDelete $DeleteOldSnapshot `
-EmailNotify ([bool]$Config.EmailNotification) `
-To $Config.NotifTo
# Renommage selon le résultat
$Suffix = if ($Result) { ".success" } else { ".failed" }
Rename-Item -Path $File.FullName -NewName ($File.Name + $Suffix) -Force
}
} catch {
Write-Warning "Impossible de lire le fichier $($File.Name) : $($_.Exception.Message)"
}
}
}
--- NETTOYAGE OPTIONNEL ---
Supprime les fichiers d'historique vieux de plus de 15 jours
Get-ChildItem "$PSD1Folder\.success", "$PSD1Folder\.failed" | Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-15) } | Remove-Item
Utilisation
- Sur le serveur (noeud du cluster ou serveur de management qui possede le module Powershell :
FailoverClusters), copier le script ci-dessus dans un fichier .ps1 - Créer le dossier
C:\PlannedSnapshotpour le stockage des fichiers.psd1, il est possible de changer le dossier dans le script. - Créer une tâche planifiée qui appel le script toutes les X minutes
- Dans le dossier
C:\PlannedSnapshotcréer des fichiers .psd1 en fonction du modèle ci-dessous
@{
ClusterName = "CLUSTER-NAME.domain.tld"
VMName = "VM-NAME"
Date = "dd/mm/yyyy"
Heure = "HH:MM"
EmailNotification = "$true"
NotifTo = "[email protected]"
}
L'utilisateur qui execute la tâche planifiée doit avoir des droits d'administration sur le Cluster et les droits Hyper-V
Plus de 40 outils AdminSys gratuits · SSL · DNS · Docker · Nginx · SSH · Mermaid · et plus