Public/snapshot.ps1
|
# Volume snapshots, snapshot policies, and VM snapshots. # Restore-CSVMSnapshot (revertToVMSnapshot) lives in vm.ps1. function Get-CSSnapshot { <# .SYNOPSIS Lists volume snapshots. .DESCRIPTION Wraps listSnapshots. Accepts volume objects (or volume names) on the pipeline and lists each volume's snapshots, so 'Get-CSVM web-01 | Get-CSVolume | Get-CSSnapshot' returns every snapshot of a VM's disks. .PARAMETER Id Filter by snapshot ID .PARAMETER Ids Filter by several snapshot IDs. Mutually exclusive with -Id. .PARAMETER Name Filter by snapshot name .PARAMETER Keyword Filter by keyword .PARAMETER Volume A volume name or volume object whose snapshots to list. Binds from the pipeline. .PARAMETER VolumeId List the snapshots of this volume ID .PARAMETER SnapshotType MANUAL or RECURRING (taken by a snapshot policy) .PARAMETER IntervalType Filter by the policy interval: HOURLY, DAILY, WEEKLY, or MONTHLY .PARAMETER ZoneId Filter by zone ID .PARAMETER StorageId Filter by primary storage pool ID .PARAMETER ImageStoreId Filter by image store (secondary storage) ID .PARAMETER LocationType primary or secondary. Only applies with -ShowUnique $false. .PARAMETER ShowUnique $false lists a snapshot once per zone and storage it is on .PARAMETER Tags Filter by resource tags, as a hashtable of key = value pairs .PARAMETER Account Filter by account name. Must be used with -DomainId. .PARAMETER DomainId Filter by domain ID .PARAMETER ProjectId Filter by project ID (-1 for all projects) .PARAMETER IsRecursive With -DomainId, also include snapshots in subdomains .PARAMETER ListAll List every snapshot the caller is allowed to see .PARAMETER Page Page number of results to return .PARAMETER PageSize Number of results per page .EXAMPLE Get-CSSnapshot -Volume 'web-01-data' Lists the snapshots of a volume found by name. .EXAMPLE Get-CSVM -Name 'web-01' | Get-CSVolume | Get-CSSnapshot Lists the snapshots of every disk on a VM. .EXAMPLE Get-CSSnapshot -SnapshotType MANUAL -ListAll | Where-Object { [datetime]$_.created -lt (Get-Date).AddDays(-90) } Finds manual snapshots older than 90 days. #> [CmdletBinding()] param( [string]$Id, [string[]]$Ids, [string]$Name, [string]$Keyword, [Parameter(ValueFromPipeline = $true)] [object]$Volume, [string]$VolumeId, [ValidateSet('MANUAL', 'RECURRING')] [string]$SnapshotType, [ValidateSet('HOURLY', 'DAILY', 'WEEKLY', 'MONTHLY')] [string]$IntervalType, [string]$ZoneId, [string]$StorageId, [string]$ImageStoreId, [ValidateSet('primary', 'secondary')] [string]$LocationType, [bool]$ShowUnique, [hashtable]$Tags, [string]$Account, [string]$DomainId, [string]$ProjectId, [switch]$IsRecursive, [switch]$ListAll, [int]$Page, [int]$PageSize ) process { if ($PSBoundParameters.ContainsKey('Id') -and $PSBoundParameters.ContainsKey('Ids')) { throw 'Specify either -Id or -Ids, not both.' } if ($PSBoundParameters.ContainsKey('Volume') -and $PSBoundParameters.ContainsKey('VolumeId')) { throw 'Specify either -Volume or -VolumeId, not both.' } if ($PSBoundParameters.ContainsKey('Account') -and -not $PSBoundParameters.ContainsKey('DomainId')) { throw 'DomainId is required when Account is specified.' } $apiParams = @{} Add-CSOptionalParameter -ApiParameters $apiParams -BoundParameters $PSBoundParameters -Map ([ordered]@{ Id = 'id'; Ids = 'ids'; Name = 'name'; Keyword = 'keyword'; VolumeId = 'volumeid' SnapshotType = 'snapshottype'; IntervalType = 'intervaltype'; ZoneId = 'zoneid'; StorageId = 'storageid' ImageStoreId = 'imagestoreid'; LocationType = 'locationtype'; ShowUnique = 'showunique'; Account = 'account' DomainId = 'domainid'; ProjectId = 'projectid'; IsRecursive = 'isrecursive'; ListAll = 'listall' Page = 'page'; PageSize = 'pagesize' }) if ($PSBoundParameters.ContainsKey('Volume')) { $apiParams['volumeid'] = Resolve-CSVolumeId -Volume $Volume } Add-CSMapParameter -ApiParameters $apiParams -Name 'tags' -Map $Tags -KeyField 'key' -ValueField 'value' ConvertFrom-CSResponse -Response (Invoke-CSApiRequest -Command 'listSnapshots' -Parameters $apiParams) -Command 'listSnapshots' } } function New-CSSnapshot { <# .SYNOPSIS Takes a snapshot of a volume. .DESCRIPTION Wraps createSnapshot. Accepts volume objects from Get-CSVolume on the pipeline. This is an asynchronous job; use -Wait to get the finished snapshot back instead of the job handle. .PARAMETER VolumeId The volume to snapshot (binds from a piped volume's id) .PARAMETER Name A name for the snapshot. Never bound from the pipeline, because a piped volume's name is the volume's. .PARAMETER Tags Resource tags for the snapshot, as a hashtable of key = value pairs .PARAMETER ZoneIds Extra zones to make the snapshot available in. The volume's own zone is always included. .PARAMETER PolicyId The snapshot policy to associate the snapshot with. Defaults to the manual policy. .PARAMETER LocationType Managed storage only: keep the snapshot on primary (default) or secondary storage .PARAMETER QuiesceVM Quiesce the VM before taking the snapshot .PARAMETER AsyncBackup Back the snapshot up to secondary storage in the background .PARAMETER Account Account that will own the snapshot. Must be used with -DomainId. .PARAMETER DomainId Domain of the owning account .PARAMETER Wait Wait for the async job to finish and return the snapshot .EXAMPLE New-CSSnapshot -VolumeId vol-uuid -Name 'before-upgrade' -Wait Snapshots a volume and waits for the snapshot to finish. .EXAMPLE Get-CSVM -Name 'db-01' | Get-CSVolume | New-CSSnapshot -QuiesceVM -Tags @{ reason = 'pre-patch' } Snapshots every disk on a VM, quiescing it first. #> [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Low')] param( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [Alias('Id')] [string]$VolumeId, [string]$Name, [hashtable]$Tags, [string[]]$ZoneIds, [string]$PolicyId, [ValidateSet('primary', 'secondary')] [string]$LocationType, [switch]$QuiesceVM, [switch]$AsyncBackup, [string]$Account, [string]$DomainId, [switch]$Wait ) process { if ($PSBoundParameters.ContainsKey('Account') -and -not $PSBoundParameters.ContainsKey('DomainId')) { throw 'DomainId is required when Account is specified.' } $apiParams = @{ volumeid = $VolumeId } Add-CSOptionalParameter -ApiParameters $apiParams -BoundParameters $PSBoundParameters -Map ([ordered]@{ Name = 'name'; ZoneIds = 'zoneids'; PolicyId = 'policyid'; LocationType = 'locationtype' QuiesceVM = 'quiescevm'; AsyncBackup = 'asyncbackup'; Account = 'account'; DomainId = 'domainid' }) Add-CSMapParameter -ApiParameters $apiParams -Name 'tags' -Map $Tags -KeyField 'key' -ValueField 'value' if ($PSCmdlet.ShouldProcess("volume $VolumeId", 'Take snapshot')) { Invoke-CSAsyncApiRequest -Command 'createSnapshot' -Parameters $apiParams -Wait:$Wait } } } function Remove-CSSnapshot { <# .SYNOPSIS Deletes a volume snapshot. .DESCRIPTION Wraps deleteSnapshot. Without -ZoneId the snapshot is deleted from every zone it was copied to. This is an asynchronous job; use -Wait to block until it finishes. Accepts snapshot objects from Get-CSSnapshot on the pipeline. .PARAMETER Id The ID of the snapshot to delete (binds from a piped snapshot's id) .PARAMETER ZoneId Only delete the snapshot's copy in this zone. Never bound from the pipeline, so a piped snapshot is deleted everywhere unless you say otherwise. .PARAMETER Wait Wait for the async job to finish and return its result .EXAMPLE Remove-CSSnapshot -Id snapshot-uuid Deletes a snapshot after prompting for confirmation. .EXAMPLE Get-CSSnapshot -SnapshotType MANUAL -ListAll | Where-Object { [datetime]$_.created -lt (Get-Date).AddDays(-90) } | Remove-CSSnapshot -Confirm:$false Deletes manual snapshots older than 90 days without prompting. .EXAMPLE Remove-CSSnapshot -Id snapshot-uuid -ZoneId dr-zone-uuid -WhatIf Shows what removing only the DR-zone copy would do, without doing it. #> [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'High')] param( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [string]$Id, [string]$ZoneId, [switch]$Wait ) process { $apiParams = @{ id = $Id } if ($PSBoundParameters.ContainsKey('ZoneId')) { $apiParams['zoneid'] = $ZoneId } $target = if ($ZoneId) { "snapshot $Id in zone $ZoneId" } else { "snapshot $Id in all zones" } if ($PSCmdlet.ShouldProcess($target, 'Delete')) { Invoke-CSAsyncApiRequest -Command 'deleteSnapshot' -Parameters $apiParams -Wait:$Wait } } } function Restore-CSSnapshot { <# .SYNOPSIS Reverts a volume to one of its snapshots. .DESCRIPTION Wraps revertSnapshot (KVM only). Everything written to the volume since the snapshot was taken is lost. The volume's VM should be stopped. This is an asynchronous job; use -Wait to block until it finishes. Accepts snapshot objects from Get-CSSnapshot on the pipeline. To create a new volume from a snapshot instead, use New-CSVolume -SnapshotId. .PARAMETER Id The ID of the snapshot to revert to (binds from a piped snapshot's id) .PARAMETER Wait Wait for the async job to finish and return the snapshot .EXAMPLE Restore-CSSnapshot -Id snapshot-uuid -Wait Reverts a volume to a snapshot after prompting for confirmation. .EXAMPLE Get-CSSnapshot -Volume 'db-01-root' | Sort-Object { [datetime]$_.created } | Select-Object -Last 1 | Restore-CSSnapshot Reverts a volume to its most recent snapshot. #> [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'High')] param( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [string]$Id, [switch]$Wait ) process { if ($PSCmdlet.ShouldProcess("snapshot $Id", 'Revert its volume to this snapshot')) { Invoke-CSAsyncApiRequest -Command 'revertSnapshot' -Parameters @{ id = $Id } -Wait:$Wait } } } function Move-CSSnapshot { <# .SYNOPSIS Moves a snapshot from primary storage to secondary storage. .DESCRIPTION Wraps archiveSnapshot, which copies a snapshot kept on primary storage to secondary storage and frees the space on primary. ('Archive' is not an approved PowerShell verb.) This is an asynchronous job; use -Wait to get the moved snapshot back. Accepts snapshot objects from Get-CSSnapshot on the pipeline. .PARAMETER Id The ID of the snapshot to move (binds from a piped snapshot's id) .PARAMETER Wait Wait for the async job to finish and return the snapshot .EXAMPLE Move-CSSnapshot -Id snapshot-uuid -Wait Moves a snapshot to secondary storage. .EXAMPLE Get-CSSnapshot -ShowUnique $false -LocationType primary -ListAll | Move-CSSnapshot Moves every snapshot still on primary storage to secondary storage. #> [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium')] param( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [string]$Id, [switch]$Wait ) process { if ($PSCmdlet.ShouldProcess("snapshot $Id", 'Move to secondary storage')) { Invoke-CSAsyncApiRequest -Command 'archiveSnapshot' -Parameters @{ id = $Id } -Wait:$Wait } } } function Copy-CSSnapshot { <# .SYNOPSIS Copies a snapshot to one or more other zones. .DESCRIPTION Wraps copySnapshot, e.g. to keep a copy in a disaster-recovery zone. This is an asynchronous job; use -Wait to get the snapshot back. Accepts snapshot objects from Get-CSSnapshot on the pipeline. .PARAMETER Id The ID of the snapshot to copy (binds from a piped snapshot's id) .PARAMETER DestinationZoneId One or more zones to copy the snapshot to .PARAMETER SourceZoneId The zone to copy from. Defaults to the zone of the snapshot's volume. .PARAMETER Wait Wait for the async job to finish and return the snapshot .EXAMPLE Copy-CSSnapshot -Id snapshot-uuid -DestinationZoneId dr-zone-uuid -Wait Copies a snapshot to a DR zone. .EXAMPLE Get-CSVM -Name 'db-01' | Get-CSVolume | Get-CSSnapshot | Copy-CSSnapshot -DestinationZoneId dr-zone-a, dr-zone-b Copies every snapshot of a VM's disks to two zones. #> [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Low')] param( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [string]$Id, [Parameter(Mandatory = $true)] [string[]]$DestinationZoneId, [string]$SourceZoneId, [switch]$Wait ) process { $apiParams = @{ id = $Id } # destzoneid and destzoneids are mutually exclusive; use the single form when it fits. if ($DestinationZoneId.Count -eq 1) { $apiParams['destzoneid'] = $DestinationZoneId[0] } else { $apiParams['destzoneids'] = $DestinationZoneId -join ',' } if ($PSBoundParameters.ContainsKey('SourceZoneId')) { $apiParams['sourcezoneid'] = $SourceZoneId } if ($PSCmdlet.ShouldProcess("snapshot $Id", "Copy to zone(s) $($DestinationZoneId -join ', ')")) { Invoke-CSAsyncApiRequest -Command 'copySnapshot' -Parameters $apiParams -Wait:$Wait } } } function Export-CSSnapshot { <# .SYNOPSIS Gets a download URL for a snapshot. .DESCRIPTION Wraps extractSnapshot. The snapshot must be in the BackedUp state. This is an asynchronous job; use -Wait to get the result, whose 'url' property is the download link. Accepts snapshot objects from Get-CSSnapshot on the pipeline; the snapshot's zone binds to -ZoneId automatically. .PARAMETER Id The ID of the snapshot (binds from a piped snapshot's id) .PARAMETER ZoneId The zone the snapshot is in (binds from a piped snapshot's zoneid) .PARAMETER Wait Wait for the async job to finish and return the extract result .EXAMPLE (Export-CSSnapshot -Id snapshot-uuid -ZoneId zone-uuid -Wait).url Gets a download URL for a snapshot. .EXAMPLE Get-CSSnapshot -Name 'before-upgrade' | Export-CSSnapshot -Wait | Select-Object name, url Gets a download URL for a snapshot found by name; its zone comes from the snapshot object. #> [CmdletBinding()] param( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [string]$Id, [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [string]$ZoneId, [switch]$Wait ) process { Invoke-CSAsyncApiRequest -Command 'extractSnapshot' -Parameters @{ id = $Id; zoneid = $ZoneId } -Wait:$Wait } } function Get-CSSnapshotDetail { <# .SYNOPSIS Gets the storage details of a volume snapshot. .DESCRIPTION Wraps getVolumeSnapshotDetails, which returns the iSCSI name of a snapshot held on managed storage. Accepts snapshot objects from Get-CSSnapshot on the pipeline. .PARAMETER Id The ID of the snapshot (binds from a piped snapshot's id) .EXAMPLE Get-CSSnapshotDetail -Id snapshot-uuid Returns a snapshot's iSCSI name. .EXAMPLE Get-CSSnapshot -Volume 'db-01-data' | Get-CSSnapshotDetail Returns the iSCSI name of every snapshot of a volume. #> [CmdletBinding()] param( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [string]$Id ) process { ConvertFrom-CSResponse -Response (Invoke-CSApiRequest -Command 'getVolumeSnapshotDetails' -Parameters @{ snapshotid = $Id }) -Command 'getVolumeSnapshotDetails' } } function New-CSSnapshotFromVMSnapshot { <# .SYNOPSIS Creates a volume snapshot from a VM snapshot. .DESCRIPTION Wraps createSnapshotFromVMSnapshot, which turns one disk of a VM snapshot into a standalone volume snapshot (which can then be copied, extracted, or turned into a volume). This is an asynchronous job; use -Wait to get the snapshot back. Accepts VM snapshot objects from Get-CSVMSnapshot on the pipeline. .PARAMETER VMSnapshotId The VM snapshot (binds from a piped VM snapshot's id) .PARAMETER VolumeId The volume of the VM whose disk to take from the VM snapshot .PARAMETER Name A name for the new snapshot .PARAMETER Wait Wait for the async job to finish and return the snapshot .EXAMPLE New-CSSnapshotFromVMSnapshot -VMSnapshotId vmsnapshot-uuid -VolumeId vol-uuid -Name 'db-data-nightly' -Wait Extracts one disk from a VM snapshot as a volume snapshot. .EXAMPLE $root = Get-CSVM -Name 'web-01' | Get-CSVolume -Type ROOT Get-CSVMSnapshot -VM 'web-01' | Select-Object -Last 1 | New-CSSnapshotFromVMSnapshot -VolumeId $root.id Turns the root disk of web-01's latest VM snapshot into a volume snapshot. #> [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Low')] param( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [Alias('Id')] [string]$VMSnapshotId, [Parameter(Mandatory = $true)] [string]$VolumeId, [string]$Name, [switch]$Wait ) process { $apiParams = @{ vmsnapshotid = $VMSnapshotId; volumeid = $VolumeId } if ($PSBoundParameters.ContainsKey('Name')) { $apiParams['name'] = $Name } if ($PSCmdlet.ShouldProcess("VM snapshot $VMSnapshotId", "Create snapshot of volume $VolumeId")) { Invoke-CSAsyncApiRequest -Command 'createSnapshotFromVMSnapshot' -Parameters $apiParams -Wait:$Wait } } } function Get-CSSnapshotPolicy { <# .SYNOPSIS Lists snapshot policies. .DESCRIPTION Wraps listSnapshotPolicies. Accepts volume objects (or volume names) on the pipeline and lists each volume's policies. .PARAMETER Id Filter by policy ID .PARAMETER Volume A volume name or volume object whose policies to list. Binds from the pipeline. .PARAMETER VolumeId List the policies of this volume ID .PARAMETER ForDisplay Filter by the display flag (root admin only) .PARAMETER Keyword Filter by keyword .PARAMETER Page Page number of results to return .PARAMETER PageSize Number of results per page .EXAMPLE Get-CSSnapshotPolicy -Volume 'db-01-data' Lists a volume's snapshot policies. .EXAMPLE Get-CSVM -Name 'db-01' | Get-CSVolume | Get-CSSnapshotPolicy Lists the snapshot policies on every disk of a VM. #> [CmdletBinding()] param( [string]$Id, [Parameter(ValueFromPipeline = $true)] [object]$Volume, [string]$VolumeId, [bool]$ForDisplay, [string]$Keyword, [int]$Page, [int]$PageSize ) process { if ($PSBoundParameters.ContainsKey('Volume') -and $PSBoundParameters.ContainsKey('VolumeId')) { throw 'Specify either -Volume or -VolumeId, not both.' } $apiParams = @{} Add-CSOptionalParameter -ApiParameters $apiParams -BoundParameters $PSBoundParameters -Map ([ordered]@{ Id = 'id'; VolumeId = 'volumeid'; ForDisplay = 'fordisplay'; Keyword = 'keyword'; Page = 'page'; PageSize = 'pagesize' }) if ($PSBoundParameters.ContainsKey('Volume')) { $apiParams['volumeid'] = Resolve-CSVolumeId -Volume $Volume } ConvertFrom-CSResponse -Response (Invoke-CSApiRequest -Command 'listSnapshotPolicies' -Parameters $apiParams) -Command 'listSnapshotPolicies' } } function New-CSSnapshotPolicy { <# .SYNOPSIS Creates a recurring snapshot schedule for a volume. .DESCRIPTION Wraps createSnapshotPolicy. The -Schedule format depends on -IntervalType (MM = minute, HH = hour, DD = day): HOURLY 'MM' e.g. '15' (every hour at :15) DAILY 'MM:HH' e.g. '30:02' (every day at 02:30) WEEKLY 'MM:HH:DD' e.g. '00:03:1' (DD 1-7, 1 = Sunday) MONTHLY 'MM:HH:DD' e.g. '00:04:1' (DD 1-28) The format is checked before the request is sent. Accepts volume objects from Get-CSVolume on the pipeline. .PARAMETER VolumeId The volume to schedule snapshots for (binds from a piped volume's id) .PARAMETER IntervalType HOURLY, DAILY, WEEKLY, or MONTHLY .PARAMETER Schedule When to take the snapshot, in the format for -IntervalType (see the description) .PARAMETER Timezone Time zone the schedule is evaluated in, e.g. 'America/Detroit' .PARAMETER MaxSnaps How many snapshots to keep; the oldest is deleted when a new one is taken .PARAMETER ZoneIds Extra zones to make each snapshot available in .PARAMETER Tags Resource tags for the policy, as a hashtable of key = value pairs .PARAMETER ForDisplay Whether end users can see the policy .EXAMPLE New-CSSnapshotPolicy -VolumeId vol-uuid -IntervalType DAILY -Schedule '30:02' -Timezone 'America/Detroit' -MaxSnaps 7 Snapshots a volume every night at 02:30 and keeps a week of snapshots. .EXAMPLE Get-CSVM -Name 'db-01' | Get-CSVolume | New-CSSnapshotPolicy -IntervalType WEEKLY -Schedule '00:03:1' -Timezone 'UTC' -MaxSnaps 4 -ZoneIds dr-zone-uuid Snapshots every disk of db-01 on Sundays at 03:00 UTC, keeping four weeks, with a copy in a DR zone. #> [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Low')] param( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [Alias('Id')] [string]$VolumeId, [Parameter(Mandatory = $true)] [ValidateSet('HOURLY', 'DAILY', 'WEEKLY', 'MONTHLY')] [string]$IntervalType, [Parameter(Mandatory = $true)] [string]$Schedule, [Parameter(Mandatory = $true)] [string]$Timezone, [Parameter(Mandatory = $true)] [ValidateRange(1, [int]::MaxValue)] [int]$MaxSnaps, [string[]]$ZoneIds, [hashtable]$Tags, [bool]$ForDisplay ) begin { $minute = '([0-5]?[0-9])' $hour = '([01]?[0-9]|2[0-3])' $patterns = @{ HOURLY = @("^$minute$", "'MM', e.g. '15'") DAILY = @("^${minute}:${hour}$", "'MM:HH', e.g. '30:02'") WEEKLY = @("^${minute}:${hour}:[1-7]$", "'MM:HH:DD' with DD 1-7, e.g. '00:03:1'") MONTHLY = @("^${minute}:${hour}:([1-9]|1[0-9]|2[0-8])$", "'MM:HH:DD' with DD 1-28, e.g. '00:04:1'") } $pattern = $patterns[$IntervalType.ToUpperInvariant()] if ($Schedule -notmatch $pattern[0]) { throw "Schedule '$Schedule' does not fit a $IntervalType policy. Use $($pattern[1])." } } process { $apiParams = @{ volumeid = $VolumeId intervaltype = $IntervalType.ToUpperInvariant() schedule = $Schedule timezone = $Timezone maxsnaps = $MaxSnaps } Add-CSOptionalParameter -ApiParameters $apiParams -BoundParameters $PSBoundParameters -Map ([ordered]@{ ZoneIds = 'zoneids'; ForDisplay = 'fordisplay' }) Add-CSMapParameter -ApiParameters $apiParams -Name 'tags' -Map $Tags -KeyField 'key' -ValueField 'value' if ($PSCmdlet.ShouldProcess("volume $VolumeId", "Create $IntervalType snapshot policy ($Schedule $Timezone, keep $MaxSnaps)")) { ConvertFrom-CSResponse -Response (Invoke-CSApiRequest -Command 'createSnapshotPolicy' -Parameters $apiParams) -Command 'createSnapshotPolicy' } } } function Set-CSSnapshotPolicy { <# .SYNOPSIS Updates a snapshot policy's display flag or custom ID. .DESCRIPTION Wraps updateSnapshotPolicy. CloudStack cannot change a policy's schedule, interval, or retention in place; to change those, create a new policy with New-CSSnapshotPolicy and remove the old one. This is an asynchronous job; use -Wait to get the updated policy back. Accepts policy objects from Get-CSSnapshotPolicy on the pipeline. .PARAMETER Id The ID of the policy (binds from a piped policy's id) .PARAMETER ForDisplay Whether end users can see the policy .PARAMETER CustomId A custom ID for the policy (root admin only) .PARAMETER Wait Wait for the async job to finish and return the policy .EXAMPLE Set-CSSnapshotPolicy -Id policy-uuid -ForDisplay $false -Wait Hides a policy from end users. .EXAMPLE Get-CSSnapshotPolicy -Volume 'db-01-data' | Set-CSSnapshotPolicy -ForDisplay $true Makes every policy on a volume visible to end users. #> [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Low')] param( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [string]$Id, [bool]$ForDisplay, [string]$CustomId, [switch]$Wait ) process { $apiParams = @{ id = $Id } Add-CSOptionalParameter -ApiParameters $apiParams -BoundParameters $PSBoundParameters -Map ([ordered]@{ ForDisplay = 'fordisplay'; CustomId = 'customid' }) if ($apiParams.Count -eq 1) { throw 'Specify -ForDisplay or -CustomId.' } if ($PSCmdlet.ShouldProcess("snapshot policy $Id", 'Update')) { Invoke-CSAsyncApiRequest -Command 'updateSnapshotPolicy' -Parameters $apiParams -Wait:$Wait } } } function Remove-CSSnapshotPolicy { <# .SYNOPSIS Deletes snapshot policies. .DESCRIPTION Wraps deleteSnapshotPolicies. Snapshots already taken by the policy are kept. Accepts policy objects from Get-CSSnapshotPolicy on the pipeline. .PARAMETER Id The ID of the policy to delete (binds from a piped policy's id) .EXAMPLE Remove-CSSnapshotPolicy -Id policy-uuid Deletes a policy after prompting for confirmation. .EXAMPLE Get-CSVM -Name 'old-app' | Get-CSVolume | Get-CSSnapshotPolicy | Remove-CSSnapshotPolicy -Confirm:$false Stops scheduled snapshots of every disk on a VM. #> [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'High')] param( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [string]$Id ) process { if ($PSCmdlet.ShouldProcess("snapshot policy $Id", 'Delete')) { ConvertFrom-CSResponse -Response (Invoke-CSApiRequest -Command 'deleteSnapshotPolicies' -Parameters @{ id = $Id }) -Command 'deleteSnapshotPolicies' } } } function Get-CSVMSnapshot { <# .SYNOPSIS Lists VM snapshots. .DESCRIPTION Wraps listVMSnapshot. Accepts VM objects (or VM names) on the pipeline and lists each VM's snapshots. Pipe the results to Restore-CSVMSnapshot, Remove-CSVMSnapshot, or New-CSSnapshotFromVMSnapshot. .PARAMETER Id Filter by VM snapshot ID .PARAMETER Ids Filter by several VM snapshot IDs. Mutually exclusive with -Id. .PARAMETER Name Filter by name or display name .PARAMETER Keyword Filter by keyword .PARAMETER VM A VM name or VM object whose snapshots to list. Binds from the pipeline. .PARAMETER VirtualMachineId List the snapshots of this VM ID .PARAMETER State Filter by state, e.g. Ready .PARAMETER Tags Filter by resource tags, as a hashtable of key = value pairs .PARAMETER Account Filter by account name. Must be used with -DomainId. .PARAMETER DomainId Filter by domain ID .PARAMETER ProjectId Filter by project ID (-1 for all projects) .PARAMETER IsRecursive With -DomainId, also include snapshots in subdomains .PARAMETER ListAll List every VM snapshot the caller is allowed to see .PARAMETER Page Page number of results to return .PARAMETER PageSize Number of results per page .EXAMPLE Get-CSVMSnapshot -VM 'web-01' Lists web-01's VM snapshots. .EXAMPLE Get-CSVM -Keyword 'dev-' | Get-CSVMSnapshot | Where-Object { [datetime]$_.created -lt (Get-Date).AddDays(-30) } | Remove-CSVMSnapshot Deletes VM snapshots older than 30 days on every dev VM. #> [CmdletBinding()] param( [string]$Id, [string[]]$Ids, [string]$Name, [string]$Keyword, [Parameter(Position = 0, ValueFromPipeline = $true)] [object]$VM, [string]$VirtualMachineId, [string]$State, [hashtable]$Tags, [string]$Account, [string]$DomainId, [string]$ProjectId, [switch]$IsRecursive, [switch]$ListAll, [int]$Page, [int]$PageSize ) process { if ($PSBoundParameters.ContainsKey('Id') -and $PSBoundParameters.ContainsKey('Ids')) { throw 'Specify either -Id or -Ids, not both.' } if ($PSBoundParameters.ContainsKey('VM') -and $PSBoundParameters.ContainsKey('VirtualMachineId')) { throw 'Specify either -VM or -VirtualMachineId, not both.' } if ($PSBoundParameters.ContainsKey('Account') -and -not $PSBoundParameters.ContainsKey('DomainId')) { throw 'DomainId is required when Account is specified.' } $apiParams = @{} Add-CSOptionalParameter -ApiParameters $apiParams -BoundParameters $PSBoundParameters -Map ([ordered]@{ Id = 'vmsnapshotid'; Ids = 'vmsnapshotids'; Name = 'name'; Keyword = 'keyword' VirtualMachineId = 'virtualmachineid'; State = 'state'; Account = 'account'; DomainId = 'domainid' ProjectId = 'projectid'; IsRecursive = 'isrecursive'; ListAll = 'listall'; Page = 'page'; PageSize = 'pagesize' }) if ($PSBoundParameters.ContainsKey('VM')) { $apiParams['virtualmachineid'] = Resolve-CSVMTagId -VM $VM } Add-CSMapParameter -ApiParameters $apiParams -Name 'tags' -Map $Tags -KeyField 'key' -ValueField 'value' ConvertFrom-CSResponse -Response (Invoke-CSApiRequest -Command 'listVMSnapshot' -Parameters $apiParams) -Command 'listVMSnapshot' } } function New-CSVMSnapshot { <# .SYNOPSIS Takes a snapshot of a whole virtual machine. .DESCRIPTION Wraps createVMSnapshot. A VM snapshot covers all of the VM's disks, and optionally its memory, at one point in time. Roll back with Restore-CSVMSnapshot. Accepts -VM (a name or a piped VM object) or -VirtualMachineId. This is an asynchronous job; use -Wait to get the VM snapshot back. .PARAMETER VirtualMachineId The ID of the VM to snapshot .PARAMETER VM A VM name or VM object. Binds from the pipeline. .PARAMETER Name A display name for the snapshot .PARAMETER Description A description for the snapshot .PARAMETER SnapshotMemory Include the VM's memory, so reverting resumes the running VM rather than booting it .PARAMETER QuiesceVM Quiesce the VM's file systems before taking the snapshot .PARAMETER Wait Wait for the async job to finish and return the VM snapshot .EXAMPLE New-CSVMSnapshot -VM 'web-01' -Name 'before-upgrade' -SnapshotMemory -Wait Snapshots web-01, including its memory. .EXAMPLE Get-CSVM -Keyword 'app-' | New-CSVMSnapshot -Name "pre-patch-$(Get-Date -Format yyyyMMdd)" -QuiesceVM Snapshots every app VM before patching. .EXAMPLE $snap = New-CSVMSnapshot -VM 'web-01' -Name 'before-upgrade' -Wait # ...upgrade fails... $snap | Restore-CSVMSnapshot -Wait Takes a snapshot, then rolls the VM back to it. #> [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Low')] param( [Parameter(Mandatory = $false)] [string]$VirtualMachineId, [Parameter(Mandatory = $false, Position = 0, ValueFromPipeline = $true)] [object]$VM, [string]$Name, [string]$Description, [switch]$SnapshotMemory, [switch]$QuiesceVM, [switch]$Wait ) process { $resolvedId = Resolve-CSVMTagId -VirtualMachineId $VirtualMachineId -VM $VM $apiParams = @{ virtualmachineid = $resolvedId } Add-CSOptionalParameter -ApiParameters $apiParams -BoundParameters $PSBoundParameters -Map ([ordered]@{ Name = 'name'; Description = 'description'; SnapshotMemory = 'snapshotmemory'; QuiesceVM = 'quiescevm' }) if ($PSCmdlet.ShouldProcess("VM $resolvedId", 'Take VM snapshot')) { Invoke-CSAsyncApiRequest -Command 'createVMSnapshot' -Parameters $apiParams -Wait:$Wait } } } function Remove-CSVMSnapshot { <# .SYNOPSIS Deletes a VM snapshot. .DESCRIPTION Wraps deleteVMSnapshot. The VM itself is not affected. This is an asynchronous job; use -Wait to block until it finishes. Accepts VM snapshot objects from Get-CSVMSnapshot on the pipeline. .PARAMETER VMSnapshotId The ID of the VM snapshot to delete (binds from a piped VM snapshot's id) .PARAMETER Wait Wait for the async job to finish and return its result .EXAMPLE Remove-CSVMSnapshot -VMSnapshotId vmsnapshot-uuid Deletes a VM snapshot after prompting for confirmation. .EXAMPLE Get-CSVMSnapshot -VM 'web-01' -Name 'before-upgrade' | Remove-CSVMSnapshot -Confirm:$false -Wait Deletes a VM snapshot found by name once it is no longer needed. #> [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'High')] param( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [Alias('Id')] [string]$VMSnapshotId, [switch]$Wait ) process { if ($PSCmdlet.ShouldProcess("VM snapshot $VMSnapshotId", 'Delete')) { Invoke-CSAsyncApiRequest -Command 'deleteVMSnapshot' -Parameters @{ vmsnapshotid = $VMSnapshotId } -Wait:$Wait } } } |