Hyper V Backup Script

under Programming PowerShell

 

The following powershell script creates snapshots or exports of VMs on the local, and performs retention/cleanup as well. Be forewarned. There are known bugs with the current hyper-v snapshot integration and *nix systems.

<#
.SYNOPSIS
vmbackup - Creates snapshots or exports of VMs on this server
.DESCRIPTION
vmbackup - Creates snapshots or exports of VMs on this server
.PARAMETER mode
[Required] Snapshot mode or export/backup mode
.PARAMETER snap_days_retention
[Optional] Number of days to retain snapshots (defaults 3)
.PARAMETER num_exports_retention
[Optional] Number of exports to retain (defaults 2)
.PARAMETER export_path
[Optional] Path to export to
.PARAMETER debug
[Optional] Outputs debug level details
.NOTES
#>
Param(
	[Parameter(Mandatory=$true)]
	[ValidateSet('snapshot','export')]
	[string]$mode,
	[int]$num_exports_retention=2,
	[int]$snap_days_retention=1,
	[string]$export_path='F:\ExportedVMs',
	[string]$Logfile='C:\Scripts\Log\vmbackup.log'
)
$ErrorActionPreference = "Stop"
<#
Formated output
#>
function Write-Output($message, $iserror=$false)
{
    $message = ("{0} {1}" -f (Get-Date -Format s), $message);
    if ($iserror -eq $true)
    {
        $Host.UI.WriteErrorLine($message);
	}
    else
    {
        Write-Host $message;
    }
}
<#
Snapshot all running VMs, and delete snapshots older than given days
#>
function snapshotAllRunningVMs($snap_days_retention)
{
    # Get list of VMs (that are running)
    Get-VM | Where {$_.State -eq 'Running'} | ForEach-Object {
        # Create a snapshot
        Checkpoint-VM -VM $_;
        # Delete snapshots older than $snap_days_retention days
        Get-VMSnapshot -VM $_ | Where {$_.CreationTime -lt (Get-Date).AddDays(-$snap_days_retention)} | Remove-VMSnapshot;
    }
}
<#
Returns true if given string is a parseable date
#>
function isDate([string]$date)
{
    $result = 0
    if (!([DateTime]::TryParse($date, [ref]$result)))
    {
        return $false;
    }
 	return $true;
}
<#
Performs a export backup of config and data togiven path for all vms
with a subdirectory dated
#>
function exportALLVMs($exports_retention, $export_path)
{
    # Create our backup folder
    $bk_folder = (Join-Path $export_path $(get-date -f yyyy-MM-dd));
    New-Item -ItemType Directory -Force -Path $bk_folder | Out-Null;
    Write-Output ("Exporting VMs to {0}" -f $bk_folder);
	try
	{
	    # Get list of all VMs
    	Get-VM | ForEach-Object {
        	Write-Output ("Exporting {0}..." -f $_.Name);
        	$_ | Export-VM -Path $bk_folder;
    	}
	}
	catch [Exception]
	{
		echo $_.Exception|format-list -force
		exit -1;
	}
	try
	{
   	 	# Delete directories over the number retention
    	Get-ChildItem -Path $export_path -Directory | Where { isDate $_.Name -eq $true } |
		Where { ([DateTime] $_.Name ) -lt (Get-Date).AddDays(-$exports_retention)} |
		ForEach-Object {
			Write-Output ("Remove exports for {0}" -f $_.Name);
			# Remove folder recursivly
			Remove-Item -Recurse -Force $_.FullName;
		}
	}
	catch [Exception]
	{
		echo $_.Exception|format-list -force
		exit -2;
	}
}
if ($mode -eq 'snapshot')
{
    snapshotAllRunningVMs $snap_days_retention;
}
if ($mode -eq 'export')
{
    exportAllVMs $num_exports_retention $export_path;
}