Public/Backup-VM.ps1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
function Backup-VM {
    <#
    .SYNOPSIS
    Performs a backup of one or more Hyper-V Virtual Machines.

    .DESCRIPTION
    Performs a backup of one or more Hyper-V Virtual Machines. This module exports Virtual Machines and compress them using 7zip.

    .PARAMETER Name
    Name of the Virtual Machine. You can get a list of your Hyper-V machines using Get-VM.

    .PARAMETER Destination
    Specify the location of the backup.

    .PARAMETER CompressionLevel
    Set the compression level of the archive.

    .PARAMETER CompressionMethod
    Set the compresseion method of the archive.

    .PARAMETER NoCompression
    Specify if you only want to export the VM and not archive it.

    .PARAMETER Force
    The Force parameter allows the user to skip the "Should Continue" box.

    .EXAMPLE
    Backup-VM -Name "GAME-01", "VPN-01" -Destination 'D:\Backup\Hyper-V'

    Backups two VMs (GAME-01 and VPN-01) to the destination 'D:\Backup\Hyper-V'.

    .EXAMPLE
    Get-VM | Backup-VM -BackupDestination 'D:\Backup\Hyper-V'

    Backups all VMs on the Hyper-V host to 'D:\Backup\Hyper-V'.

    .NOTES
    Author: Frederik Hjorslev Poulsen

    Cmdlet must be executed from an elevated prompt.

    .LINK
    https://hjorslev.github.io/HyperVBackup/Backup-VM.html

    #>


    [CmdletBinding(SupportsShouldProcess = $true,
        ConfirmImpact = 'Medium')]
    param
    (
        [Parameter(Mandatory = $true,
            ValueFromPipeline = $true,
            ValueFromPipelineByPropertyName = $true,
            HelpMessage = 'Enter one or more Hyper-V virtual machine names seperated by commas.',
            Position = 0
        )]
        [string[]]$Name,

        [Parameter(Mandatory = $true,
            HelpMessage = 'Enter the backup destination.',
            Position = 1
        )]
        [Alias('BackupDestination')]
        [string]$Destination,

        [Parameter(Mandatory = $false)]
        [ValidateSet('None', 'Fast', 'Low', 'Normal', 'High', 'Ultra')]
        [string]$CompressionLevel = 'Normal',

        [Parameter(Mandatory = $false)]
        [ValidateSet('Copy', 'Deflate', 'Deflate64', 'BZip2', 'Lzma', 'Lzma2', 'Ppmd', 'Default')]
        [string]$CompressionMethod = 'Default',

        [Parameter(Mandatory = $false)]
        [switch]$NoCompression,

        [Parameter(Mandatory = $false)]
        [switch]$Force
    )

    process {
        $BackupSCMessage = @"
Do you want to backup the following Hyper-V machine:
    $($Name)
"@

        if ($Force -or $PSCmdlet.ShouldContinue($BackupSCMessage, 'Backup Virtual Machine?')) {
            Write-Verbose -Message "Virtual machine to backup: $($Name)."
            Write-Verbose -Message "Backup destination: $($Destination)."
            $TimeStamp = Get-Date -Format "yyyy-MM-dd-HHmm"

            # Exporting the VM.
            Export-VM -Name $Name -Path "$($Destination)\$($Name)-$($TimeStamp)"

            if (-not $NoCompression) {
                # Splat with parameters
                $CompressParameters = @{
                    'Path'            = "$($Destination)\$($Name)-$($TimeStamp)";
                    'ArchiveFileName' = "$($Destination)\$($Name)-$($TimeStamp).7z"
                }

                # Add CompressionLevel to the splat if variable is populated.
                if ($null -ne $CompressionLevel) {
                    Write-Verbose -Message "CompressionLevel set to $($CompressionLevel)."

                    $CompressParameters += @{
                        'CompressionLevel' = $CompressionLevel
                    }
                }

                # Add CompressionMethod to the splat if variable is populated.
                if ($null -ne $CompressionMethod) {
                    Write-Verbose -Message "CompressionMethod set to $($CompressionMethod)."
                    $CompressParameters += @{
                        'CompressionMethod' = $CompressionMethod
                    }
                }

                # Compress the exported VM using 7Zip4PowerShell if the parameter is set.
                Write-Verbose -Message 'Backup will be compressed to a .7z archive.'
                Compress-7Zip @CompressParameters

                # Remove the exported folder as it's now compressed.
                Remove-Item -Path "$($Destination)\$($Name)-$($TimeStamp)" -Force -Recurse
            }
        } # ShouldContinue
    } # Process
} # Cmdlet