Différences entre les versions de « HyperV script de copie de snapshot »
De BlaxWiki
Aller à la navigationAller à la recherche (Page créée avec « Ceci est un script windows permettant de faire un snapshot des vm sur un hyperV. Il est appelé en crontab. Ce script fait appel à 2 sous script === HyperVBackup.ps1 ===... ») |
|||
| Ligne 1 : | Ligne 1 : | ||
__TOC__ | |||
Ceci est un script windows permettant de faire un snapshot des vm sur un hyperV. Il est appelé en crontab. Ce script fait appel à 2 sous script | Ceci est un script windows permettant de faire un snapshot des vm sur un hyperV. Il est appelé en crontab. Ce script fait appel à 2 sous script | ||
=== Description === | |||
Bien que le log d'execution soit remonté dans la supervision, il est possible de consulter le fichier de log localement sur infra-hv1.fbd : C:\Agarik\Scripts\HyperVBackup\HyperVBackup.log | |||
Configuration (à effectuer dans le bloc "CONFIGURATION" présent dans le script) : | |||
<pre> | |||
# Which cluster shared volume (CSV) to backup | |||
$strVolumePath = "C:\ClusterStorage\Volume1" | |||
# Where to mount the snapshot ($strSnapshotDrive) and where to find the VM | |||
($strSourcePath) | |||
$strSnapshotDrive = "Z:" | |||
$strSourcePath = $strSnapshotDrive | |||
# Where to backup | |||
$strBackupPath = "\\infra-backup\f$\VirtualMachines" | |||
# What to backup | |||
$arrVirtualMachines = | |||
@("wsus.fbd","txt-iis.fbd","txt-app.fbd","txt-sql1.fbd","ba-iis.fbd","ba-sql1.fbd","ba-app.fbd","ad2.fbd","ad1.fbd","vm-admin.fbd","mediacontact.fbd") | |||
# Retention | |||
$intRetention = 7 | |||
</pre> | |||
Le script effectue les actions suivantes : | |||
<pre> | |||
- ouverture fichier de log C:\Agarik\Scripts\HyperVBackup\HyperVBackup.log | |||
- verification de l'état de $strVolumePath, (BackupState = 0 (None) sinon on quitte avec une erreur) | |||
- preparation de $strVolumePath a être snapshoté via l'appel au binaire $strExePCSV (qui appelle la fonctione ClusterPrepareSharedVolumeForBackup, voir David Couderc si le binaire a | |||
un problème, la création d'un binaire a été nécessaire car aucun langage "non compilé" ne permet l'appel à cette fonction) | |||
- verification de l'état de $strVolumePath (BackupState = 1 (InProgress) sinon on quitte avec une erreur) | |||
- creation du snapshot et montage en tant que Z: (avec diskshadow.exe) | |||
- archivage des precedents backups dans la limite de $intRetention | |||
- pour chaque VM dans la liste $arrVirtualMachines, backup vers $strBackupPath | |||
- demontage du lecteur Z: et suppression du snapshot (avec diskshadow.exe) | |||
- envoi du resultat à la supervision (avec vc_send) | |||
</pre> | |||
=== HyperVBackup.ps1 === | === HyperVBackup.ps1 === | ||
Version du 26 octobre 2012 à 12:29
Ceci est un script windows permettant de faire un snapshot des vm sur un hyperV. Il est appelé en crontab. Ce script fait appel à 2 sous script
Description
Bien que le log d'execution soit remonté dans la supervision, il est possible de consulter le fichier de log localement sur infra-hv1.fbd : C:\Agarik\Scripts\HyperVBackup\HyperVBackup.log
Configuration (à effectuer dans le bloc "CONFIGURATION" présent dans le script) :
# Which cluster shared volume (CSV) to backup
$strVolumePath = "C:\ClusterStorage\Volume1"
# Where to mount the snapshot ($strSnapshotDrive) and where to find the VM
($strSourcePath)
$strSnapshotDrive = "Z:"
$strSourcePath = $strSnapshotDrive
# Where to backup
$strBackupPath = "\\infra-backup\f$\VirtualMachines"
# What to backup
$arrVirtualMachines =
@("wsus.fbd","txt-iis.fbd","txt-app.fbd","txt-sql1.fbd","ba-iis.fbd","ba-sql1.fbd","ba-app.fbd","ad2.fbd","ad1.fbd","vm-admin.fbd","mediacontact.fbd")
# Retention
$intRetention = 7
Le script effectue les actions suivantes :
- ouverture fichier de log C:\Agarik\Scripts\HyperVBackup\HyperVBackup.log - verification de l'état de $strVolumePath, (BackupState = 0 (None) sinon on quitte avec une erreur) - preparation de $strVolumePath a être snapshoté via l'appel au binaire $strExePCSV (qui appelle la fonctione ClusterPrepareSharedVolumeForBackup, voir David Couderc si le binaire a un problème, la création d'un binaire a été nécessaire car aucun langage "non compilé" ne permet l'appel à cette fonction) - verification de l'état de $strVolumePath (BackupState = 1 (InProgress) sinon on quitte avec une erreur) - creation du snapshot et montage en tant que Z: (avec diskshadow.exe) - archivage des precedents backups dans la limite de $intRetention - pour chaque VM dans la liste $arrVirtualMachines, backup vers $strBackupPath - demontage du lecteur Z: et suppression du snapshot (avec diskshadow.exe) - envoi du resultat à la supervision (avec vc_send)
HyperVBackup.ps1
# ------------------------------------------------------------------
# ABOUT
# ABOUT::Author
# Yoann Moriot
# ABOUT::Version
# 1.5 2012/09/12 Suppression du bloc de backup des VMs ad1 et ad2 (pas de consistance du backup effectué de cette manière)
# 1.4 2012/07/26 Ajout d'un bloc pour le backup des VMs ad1 et ad2
# 1.3 2012/04/25 Improved output display
# 1.2 2012/04/24 Added $script:arrErrLog to store errors
# and output them on top of the log
# 1.1 2012/04/23 Added Operia integration with vc_send
# 1.0 2012/04/19
# /ABOUT
# ------------------------------------------------------------------
# ------------------------------------------------------------------
# CONFIGURATION
# Monitoring
$strVCSend = "C:\Agarik\Vision\bin\vc_send.exe"
$strVCDest = "10.252.15.235"
$strVCHost = "infra-backup.fbd"
$strVCService = "backup"
$strVCColor = "red"
$intVCValidity = 1560
$strVCMessage = ""
# Which cluster shared volume (CSV) to backup
$strVolumePath = "C:\ClusterStorage\Volume2"
# Where to mount the snapshot ($strSnapshotDrive) and where to find the VM ($strSourcePath)
$strSnapshotDrive = "Z:"
$strSourcePath = $strSnapshotDrive
# Where to backup
$strBackupPath = "\\infra-backup\f$\VirtualMachines"
# What to backup
$arrVirtualMachines = @("wsus.fbd","cas-e2k10.fbd","txt-iis.fbd","txt-app.fbd","txt-sql1.fbd","ba-iis.fbd","ba-sql1.fbd","ba-app.fbd","vm-admin.fbd","mediacontact.fbd","sicompta_iis1.fbd","sicompta_sql1.fbd","sicompta_tse1.fbd")
# Retention
$intRetention = 5
# /CONFIGURATION
# ------------------------------------------------------------------
# ------------------------------------------------------------------
# SYSTEM
$bDEBUG = 0 # 0 = disabled, 1 = enabled
# DONT EDIT BELOW THIS LINE
$ERROR_CSV_BACKUPSTATE_CANNOTPREPARE = 1
$ERROR_CSV_BACKUPSTATE_NOTREADY = 2
$ERROR_DS_CREATESNAPSHOT_FAILED = 3
$ERROR_DS_REMOVESNAPSHOT_FAILED = 4
$ERROR_CSV_PREPAREBACKUP_FAILED = 5
$intError = 0
$strScriptDir = Split-Path -Path $MyInvocation.MyCommand.Definition
$strExePCSV = $strScriptDir + "\bin\PCSV.exe" # path to ClusterPrepareSharedVolumeForBackup binary
$strExeDS = "C:\Windows\system32\diskshadow.exe"
$colVMBackup = @{} # will hold the backup result per VM
$strLogFile = $strScriptDir + "\HyperVBackup.log"
$script:arrLog = @()
$script:arrErrLog = @()
# Temp files
$strDSMetadata = $strScriptDir + "\metadata.cab"
$strCreateSnapshot = $strScriptDir + "\scripts\CreateSnapshot.script"
$strRemoveSnapshot = $strScriptDir + "\scripts\RemoveSnapshot.script"
# /SYSTEM
# ------------------------------------------------------------------
# ------------------------------------------------------------------
# FUNCTIONS
# Get-SharedVolume : returns an object containing properties for the $strPath shared volume
# See http://msdn.microsoft.com/en-us/library/windows/desktop/ee342510(v=vs.85).aspx
function Get-SharedVolume( [string]$strPath )
{
$strPath = $strPath.Replace("\", "\\")
$strQuery = "select * from MSCluster_ClusterSharedVolume where Name='" + $strPath + "'"
get-wmiobject -namespace root\MSCluster -query $strQuery
}
function log( [string]$strString )
{
$strLine = (Get-CurrentTimestamp) + " > " + $strString + "`r`n"
$script:arrLog += $strLine
If ( $strString.StartsWith("ERROR") )
{
$script:arrErrLog += $strLine
}
write-host $strLine
}
function Get-CurrentTimestamp
{
$objDate = Get-Date
$strCurrentTimestamp = $objDate.ToShortDateString() + " " + $objDate.ToLongTimeString()
$strCurrentTimestamp
}
function vc_send
{
If ( $script:arrErrLog.Length -gt 0 )
{
$strVCMessage += "ERRORS : `r`n`r`n"
ForEach($strLogLine in $script:arrErrLog)
{
$strVCMessage += $strLogLine
}
$strVCMessage += "`r`n"
$strVCMessage += "================================================="
$strVCMessage += "`r`n"
$strVCMessage += "`r`n"
}
ForEach($strLogLine In $script:arrLog)
{
$strVCMessage += $strLogLine
}
& $strVCSend $strVCDest $strVCHost $strVCService $strVCColor $intVCValidity $strVCMessage
Stop-Transcript
}
# /FUNCTIONS
# ------------------------------------------------------------------
Start-Transcript $strLogFile
# ------------------------------------------------------------------
# PREFLIGHT
# PREFLIGHT::Check
log "-------------------------------------------------"
log "INFO: Checking for $strVolumePath status"
$objSharedVolume = Get-SharedVolume $strVolumePath
If ( $bDEBUG ) { log "DEBUG: objSharedVolume.BackupState = $($objSharedVolume.BackupState)" } # expect : 0 (None)
If ( $bDEBUG ) { log "DEBUG: objSharedVolume.FaultState = $($objSharedVolume.FaultState)" } # expect : 0 (NoFaults)
If ( $objSharedVolume.BackupState -ne 0 ) {
log "ERROR ($ERROR_CSV_BACKUPSTATE_CANNOTPREPARE): $strVolumePath cannot be prepared for shadow copy (objSharedVolume.BackupState -ne 0)"
vc_send
exit $ERROR_CSV_BACKUPSTATE_CANNOTPREPARE
}
log "INFO: $strVolumePath ready to be prepared for snapshot"
# PREFLIGHT::Prepare
log "-------------------------------------------------"
log "INFO: Preparing $strVolumePath for snapshot with $strExePCSV"
# ClusterPrepareSharedVolumeForBackup
& $strExePCSV $strVolumePath
If (! ($?) ) {
log "ERROR ($ERROR_CSV_PREPAREBACKUP_FAILED): Failed to run $strExePCSV, exit code : $lastexitcode"
vc_send
exit $ERROR_CSV_PREPAREFAILED
}
log "INFO: $strVolumePath prepared for snapshot"
log "-------------------------------------------------"
log "INFO: Checking for $strVolumePath status"
$objSharedVolume = Get-SharedVolume $strVolumePath
If ( $bDEBUG ) { log "DEBUG: objSharedVolume.BackupState = $($objSharedVolume.BackupState)" } # expect : 1 (InProgress)
If ( $bDEBUG ) { log "DEBUG: objSharedVolume.FaultState = $($objSharedVolume.FaultState)" } # expect : 1 (NoDirectIO)
If ( $objSharedVolume.BackupState -ne 1 ) {
log "ERROR ($ERROR_CSV_BACKUPSTATE_NOTREADY): $strVolumePath not ready for shadow copy (objSharedVolume.BackupState -ne 1)"
vc_send
exit $ERROR_CSV_BACKUPSTATE_NOTREADY
}
log "INFO: $strVolumePath ready for snapshot"
# PREFLIGHT::BUILD_SCRIPTS
# PREFLIGHT::BUILD_SCRIPTS::CreateSnapshot
$arrCreateSnapshot = @()
$arrCreateSnapshot += "set context persistent nowriters"
$arrCreateSnapshot += "set verbose on"
$arrCreateSnapshot += "set metadata " + $strDSMetadata
$arrCreateSnapshot += "begin backup"
$arrCreateSnapshot += "add volume " + $objSharedVolume.VolumeName + " alias vm"
$arrCreateSnapshot += "create"
$arrCreateSnapshot += "expose %vm% " + $strSnapshotDrive
$arrCreateSnapshot | out-file -Encoding ASCII $strCreateSnapshot
# PREFLIGHT::BUILD_SCRIPTS::RemoveSnapshot
$arrRemoveSnapshot = @()
$arrRemoveSnapshot += "set context persistent nowriters"
$arrRemoveSnapshot += "delete shadows exposed " + $strSnapshotDrive
$arrRemoveSnapshot += "end backup"
$arrRemoveSnapshot | out-file -Encoding ASCII $strRemoveSnapshot
# /PREFLIGHT::BUILD_SCRIPTS
# /PREFLIGHT
# ------------------------------------------------------------------
# ------------------------------------------------------------------
# MAIN
# MAIN::ROTATE_BACKUP
log "-------------------------------------------------"
log "INFO: Rotating backups"
# Delete the backup that reached $intRetention
$strPrevBackupPath = $strBackupPath + "." + $intRetention
If ( Test-Path -Path $strPrevBackupPath )
{
log "INFO: Deleting $strPrevBackupPath"
Remove-Item -Recurse -Force $strPrevBackupPath
sleep 5
}
# Rotate the backups
For ($i = $intRetention; $i -gt 0; $i--)
{
If ( $i -eq 1 )
{
$strPrevBackupPath = $strBackupPath
}
Else
{
$strPrevBackupPath = $strBackupPath + "." + ($i - 1)
}
$strNewBackupPath = $strBackupPath + "." + $i
If ( Test-Path -Path $strPrevBackupPath ) {
log "INFO: Moving $strPrevBackupPath to $strNewBackupPath"
Rename-Item $strPrevBackupPath $strNewBackupPath
sleep 1
}
}
# /MAIN::ROTATE_BACKUP
# MAIN::CREATE_SNAPSHOT::run_diskshadow
log "-------------------------------------------------"
log "INFO: Creating snapshot of $strVolumePath and mounting it as $strSnapshotDrive"
& $strExeDS -s $strCreateSnapshot
If (! ($?) ) {
log "ERROR ($ERROR_DS_CREATESNAPSHOT_FAILED): Failed to run $strExeDS /s $strCreateSnapshot, exit code : $lastexitcode"
vc_send
exit $ERROR_DS_CREATESNAPSHOT_FAILED
}
log "INFO: $strExeDS -s $strCreateSnapshot ended with exit code $lastexitcode"
# /MAIN::CREATE_SNAPSHOT
# MAIN::BACKUP_VIRTUALMACHINES
ForEach($strVM In $arrVirtualMachines) {
$strVMSourcePath = $strSourcePath + "\" + $strVM
$strVMBackupPath = $strBackupPath + "\" + $strVM
If ( $bDEBUG ) { log "DEBUG: strVMSourcePath = $strVMSourcePath" }
If ( $bDEBUG ) { log "DEBUG: strVMBackupPath = $strVMBackupPath" }
# Create $colVMBackup entry for $strVM
$colVM = @{}
$colVMBackup.Add($strVM, $colVM)
$colVMBackup[$strVM]["Start"] = Get-CurrentTimestamp
$colVMBackup[$strVM]["SourceDir"] = $strVMSourcePath
$colVMBackup[$strVM]["BackupDir"] = $strVMBackupPath
$colVMBackup[$strVM]["CurrentSize"] = 0
$colVMBackup[$strVM]["BackupSize"] = 0
$colVMBackup[$strVM]["End"] = 0
$colVMBackup[$strVM]["BackupDuration"] = 0
$colVMBackup[$strVM]["Result"] = 0
log "-------------------------------------------------"
log "INFO: Starting backup of $strVM"
# Backup the VM
If ( ! ( Test-Path -path $strVMSourcePath ) ) {
$colVMBackup[$strVM]["Result"] = "ERROR: Cannot find " + $strVMSourcePath
log "ERROR (0): Cannot find $strVMSourcePath, cannot backup $strVM"
$intError++
}
Else
{
# Get the current VM size
$objVMSourcePath = (Get-ChildItem $strVMSourcePath -recurse | Measure-Object -property length -sum)
$colVMBackup[$strVM]["CurrentSize"] = "{0:N2}" -f ($objVMSourcePath.sum / 1MB) + " MB"
# Copy the VM, copy-item automatically creates destination dir if required
log "INFO: Copying $strVMSourcePath to $strVMBackupPath"
Copy-Item $strVMSourcePath -destination $strVMBackupPath -recurse
If ( $? )
{
$colVMBackup[$strVM]["Result"] = "Success"
}
Else
{
$colVMBackup[$strVM]["Result"] = "ERROR (0): Failed to copy $strVMSourcePath to $strVMBackupPath"
log "ERROR (0): Failed to copy $strVMSourcePath to $strVMBackupPath"
$intError++
}
# Get the backup size
$objVMBackupPath = (Get-ChildItem $strVMBackupPath -recurse | Measure-Object -property length -sum)
$colVMBackup[$strVM]["BackupSize"] = "{0:N2}" -f ($objVMBackupPath.sum / 1MB) + " MB"
$colVMBackup[$strVM]["End"] = Get-CurrentTimestamp
$colVMBackup[$strVM]["BackupDuration"] = New-Timespan $colVMBackup[$strVM]["Start"] $colVMBackup[$strVM]["End"]
}
log "INFO: Finished backup of $strVM, BackupSize = $($colVMBackup[$strVM][`"BackupSize`"]), SourceSize = $($colVMBackup[$strVM][`"CurrentSize`"]), BackupDuration = $($colVMBackup[$strVM][`"BackupDuration`"])"
log "INFO: Result = $($colVMBackup[$strVM][`"Result`"])"
}
# /MAIN::BACKUP_VIRTUALMACHINES
# MAIN::REMOVE_SNAPSHOT::run_diskshadow
log "-------------------------------------------------"
log "INFO: Unmounting $strSnapshotDrive and removing snapshot of $strVolumePath"
& $strExeDS /s $strRemoveSnapshot
If (! ($?) ) {
log "ERROR ($ERROR_DS_REMOVESNAPSHOT_FAILED): Failed to run $strExeDS /s $strRemoveSnapshot, exit code : $lastexitcode"
vc_send
exit $ERROR_DS_REMOVESNAPSHOT_FAILED
}
log "INFO: $strExeDS -s $strRemoveSnapshot ended with exit code $lastexitcode"
# /MAIN::REMOVE_SNAPSHOT
# MAIN::MONITORING
If ( $intError -eq 0 ) { $strVCColor = "green" }
vc_send
exit 0
CreateSnapshot.script
set context persistent nowriters
set verbose on
set metadata C:\Agarik\Scripts\HyperVBackup\metadata.cab
begin backup
add volume \\?\Volume{41bf2ab9-d5fd-4cb7-ae13-a5a6291e3596} alias vm
create
expose %vm% Z:
RemoveSnapshot.script
set context persistent nowriters delete shadows exposed Z: end backup