Public/cloud-image.ps1
|
function Get-CloudImage { <# .SYNOPSIS Gets images from the Cloud Server. .DESCRIPTION Retrieves a list of images. Automatically handles token refresh. .PARAMETER Name Optional. Filter by Image name. .EXAMPLE # Get all cloud images Get-CloudImage .EXAMPLE # Get the cloud image with the name "web-server-01" Get-CloudImage -Name "web-server-01" .EXAMPLE # Get the cloud image with the ID 561 Get-CloudImage -ID 561 #> [CmdletBinding()] param( [Parameter(Mandatory = $false)] [string]$Name, [Parameter(Mandatory = $false)] [int]$ID ) # Build the URI - adjust this to match your actual API endpoint $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/image" # Use the helper function which handles token refresh automatically $response = Invoke-CloudApiRequest -Uri $uri -Method Get # Extract images from the response $images = $response.images # Filter by name if specified if ($Name) { $images = $images | Where-Object { $_.name -like "*$Name*" } } # Filter by ID if specified - use PSBoundParameters to check if parameter was provided elseif ($PSBoundParameters.ContainsKey('ID')) { $images = $images | Where-Object { ($_.id -eq $ID) -and ($null -ne $_.id) } } return $images } function Rename-CloudImage { <# .SYNOPSIS Rename an image in the Cloud Server. .DESCRIPTION Renames an image. Automatically handles token refresh. .PARAMETER Name New name of the image .PARAMETER ID ID of the image .EXAMPLE # Rename cloud image with the ID 5 to "new-name" Rename-CloudImage -Name "new-name" -ID 5 #> [CmdletBinding()] param( [Parameter(Mandatory = $true)] [string]$Name, [Parameter(Mandatory = $true)] [int]$ID ) $newname = @{ name = $Name } $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/image/${ID}/name" $response = Invoke-CloudApiRequest -Uri $uri -Method Patch -Body $newname return $response } function Lock-CloudImage { <# .SYNOPSIS Lock an image in the Cloud Server. .DESCRIPTION Lock an image. Automatically handles token refresh. .PARAMETER ID ID of the image .PARAMETER Level Lock level (USE, MANAGE, ADMIN, ALL) .PARAMETER Test When set, performs a test lock instead of a real one. .EXAMPLE # Lock the image 5 to the level ADMIN Lock-CloudImage -ID 5 -Level ADMIN .EXAMPLE # Shows the results of a test application of lock level USE on image 5 Lock-CloudImage -ID 5 -Level USE -Test #> [CmdletBinding()] param( [Parameter(Mandatory = $true)] [int]$ID, [Parameter(Mandatory = $true)] [ValidateSet('USE','MANAGE','ADMIN','ALL')] [string]$Level, [switch]$Test ) $lockdata = @{ level = $Level test = [bool]$Test } $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/image/${ID}/lock" $response = Invoke-CloudApiRequest -Uri $uri -Method Patch -Body $lockdata return $response } function Unlock-CloudImage { <# .SYNOPSIS Unlock an image in the Cloud Server. .DESCRIPTION Unlock an image. Automatically handles token refresh. .PARAMETER ID ID of the image .EXAMPLE # Unlock image 5 Unlock-CloudImage -ID 5 #> [CmdletBinding()] param( [Parameter(Mandatory = $true)] [int]$ID ) $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/image/${ID}/unlock" $response = Invoke-CloudApiRequest -Uri $uri -Method Patch return $response } function Remove-CloudImage { <# .SYNOPSIS Removes an image from the Cloud Server. .DESCRIPTION Removes an image. Automatically handles token refresh. .PARAMETER ID Required. Image ID. .EXAMPLE # Remove image with confirmation prompt (default behavior): Remove-CloudImage -ID 3 Confirm Are you sure you want to perform this action? Performing the operation "Remove Image" on target "Image ID 3 (MyImage)". [Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "Y"): Y .EXAMPLE # Remove image without confirmation prompt: Remove-CloudImage -ID 3 -Confirm:$false #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact='High')] param( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [int]$ID ) process { $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/image/${ID}" Invoke-CloudResourceRemoval ` -CallerPSCmdlet $PSCmdlet ` -ResourceType "Image" ` -ID $ID ` -Uri $uri ` -GetResourceScript { Get-CloudImage -ID $ID } } } function New-CloudBlankDisk { <# .SYNOPSIS Creates a new generic datablock image on the Cloud Server. .DESCRIPTION Creates a new blank disk image. Automatically handles token refresh. .PARAMETER Name Required. Name of the new image. .PARAMETER DatastoreID Required. Datastore ID (default: 100). .PARAMETER Size Optional. Size in MB (default: 1024). .EXAMPLE # Creates a new blank disk image named "BlankDisk" of default size 1024MB on default datastore 100 New-CloudBlankDisk -Name "BlankDisk" .EXAMPLE # Creates a 10GB/10240MB disk image named "Data-Disk-01" on datastore 2 New-CloudBlankDisk -Name "Data-Disk-01" -Size 10240 -DatastoreID 2 #> [CmdletBinding()] param( [Parameter(Mandatory = $true)] [string]$Name, [Parameter(Mandatory = $True)] [int]$DatastoreID = 100, [Parameter(Mandatory = $True)] [int]$Size = 1024 ) # Build the configuration - NAME goes INSIDE the template string $config = [PSCustomObject]@{ datastore = $DatastoreID template = "NAME=$Name DEV_PREFIX=vd DRIVER=raw SIZE=$Size TYPE=DATABLOCK" } # Build the URI $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/image" Write-Verbose "Creating image '$Name' with size ${Size}MB on datastore $DatastoreID" Write-Verbose "Request body: $($config | ConvertTo-Json -Compress)" # Use the helper function which handles token refresh automatically $response = Invoke-CloudApiRequest -Uri $uri -Method Post -Body $config Write-Host "Image '$Name' created successfully." -ForegroundColor Green return $response } function New-CloudImage { <# .SYNOPSIS Creates a new image on the Cloud Server. .DESCRIPTION Creates a new image of various types (OS disk, ISO, or data block). Can create blank images or upload from a file path. .PARAMETER Name Required. Name of the new image. .PARAMETER Type Required. Type of image to create: OS, CDROM, or Datablock. .PARAMETER Path Optional. Path to source file for uploading (for OS disks or ISOs). .PARAMETER DatastoreID Optional. Datastore ID (default: 100). .PARAMETER Size Optional. Size in MB. Required for blank Datablock images. .PARAMETER Description Optional. Description for the image. .PARAMETER Driver Optional. Disk driver (default: raw). Options: raw, qcow2. .PARAMETER DevPrefix Optional. Device prefix. Auto-determined based on type if not specified. - OS: sd (default) - CDROM: hd (default) - Datablock: vd (default) .PARAMETER Persistent Optional. Make the image persistent (not cloned, directly used). .EXAMPLE # Create a blank data disk New-CloudImage -Name "Data-Disk-01" -Type Datablock -Size 10240 .EXAMPLE # Upload an ISO New-CloudImage -Name "Ubuntu 24.04" -Type CDROM -Path "/path/to/ubuntu.iso" .EXAMPLE # Upload an OS disk New-CloudImage -Name "Windows Server 2022" -Type OS -Path "/path/to/disk.qcow2" -Driver qcow2 -Description "Windows Server base image" .EXAMPLE # Create a persistent image New-CloudImage -Name "Shared-Data" -Type Datablock -Size 51200 -Persistent .EXAMPLE # Upload a QCOW2 from a URL New-CloudImage -Name "Ubuntu-2204-Cloud" -Type OS -Path "https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img" -Driver qcow2 -Description "Ubuntu 22.04 Cloud" #> [CmdletBinding()] param( [Parameter(Mandatory = $true)] [string]$Name, [Parameter(Mandatory = $true)] [ValidateSet('OS', 'CDROM', 'Datablock')] [string]$Type, [Parameter(Mandatory = $false)] [string]$Path, [Parameter(Mandatory = $false)] [int]$DatastoreID = 100, [Parameter(Mandatory = $false)] [int]$Size, [Parameter(Mandatory = $false)] [string]$Description, [Parameter(Mandatory = $false)] [ValidateSet('raw', 'qcow2', 'vmdk')] [string]$Driver = 'raw', [Parameter(Mandatory = $false)] [string]$DevPrefix, [Parameter(Mandatory = $false)] [switch]$Persistent ) # Validate Size is provided for blank Datablock images if ($Type -eq 'Datablock' -and -not $Path -and -not $Size) { throw "Size parameter is required when creating a blank Datablock image." } # Auto-determine DevPrefix based on Type if not specified if (-not $DevPrefix) { switch ($Type) { 'OS' { $DevPrefix = 'sd' } 'CDROM' { $DevPrefix = 'hd' } 'Datablock' { $DevPrefix = 'vd' } } } # Build the template string $templateParts = @() # NAME is always first $templateParts += "NAME=$Name" # Add TYPE $templateParts += "TYPE=$Type" # Add DEV_PREFIX $templateParts += "DEV_PREFIX=$DevPrefix" # Add DRIVER $templateParts += "DRIVER=$Driver" # Add PATH if provided (for uploading) if ($Path) { $templateParts += "PATH=$Path" } # Add SIZE if provided if ($Size) { $templateParts += "SIZE=$Size" } # Add DESCRIPTION if provided if ($Description) { $templateParts += "DESCRIPTION=`"$Description`"" } # Add PERSISTENT if specified if ($Persistent) { $templateParts += "PERSISTENT=YES" } # Join all parts with spaces $templateString = $templateParts -join ' ' # Build the configuration $config = [PSCustomObject]@{ datastore = $DatastoreID template = $templateString } # Build the URI $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/image" Write-Verbose "Creating $Type image '$Name'" if ($Path) { Write-Verbose "Source path: $Path" } elseif ($Size) { Write-Verbose "Size: ${Size}MB" } Write-Verbose "Request body: $($config | ConvertTo-Json -Compress)" try { # Use the helper function which handles token refresh automatically $response = Invoke-CloudApiRequest -Uri $uri -Method Post -Body $config Write-Host "$Type image '$Name' created successfully (ID: $($response.image))." -ForegroundColor Green return $response } catch { Write-Error "Failed to create image: $_" throw } } function Update-CloudImageOwner { <# .SYNOPSIS Updates the ownership of an image in the Cloud Server. .DESCRIPTION Changes the user and/or group ownership of an image. Prompts for confirmation. .PARAMETER ID Required. ID of the image. .PARAMETER UserID Required. ID of the user to own the image. .PARAMETER GroupID Optional. ID of the group to own the image. .EXAMPLE # Change the ownership of image 5 to user 2 Update-CloudImageOwner -ID 5 -UserID 2 .EXAMPLE # Change the ownership of image 5 to user 2 and group 100 Update-CloudImageOwner -ID 5 -UserID 2 -GroupID 100 .EXAMPLE # Change the ownership of image 5 to user 2 without confirmation Update-CloudImageOwner -ID 5 -UserID 2 -Confirm:$false #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact='High')] param( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [int]$ID, [Parameter(Mandatory = $true)] [Alias('User')] [int]$UserID, [Parameter(Mandatory = $false)] [Alias('Group')] [int]$GroupID ) process { # Build the update body $body = [PSCustomObject]@{ user = $UserID } if ($PSBoundParameters.ContainsKey('GroupID')) { $body | Add-Member -NotePropertyName 'group' -NotePropertyValue $GroupID } $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/image/${ID}/ownership" # Build action description for confirmation $actionParts = @("Change owner to User ID $UserID") if ($PSBoundParameters.ContainsKey('GroupID')) { $actionParts += "Group ID $GroupID" } $actionDescription = $actionParts -join " and " # Use the helper function Invoke-CloudResourceUpdate ` -CallerPSCmdlet $PSCmdlet ` -ResourceType "Image" ` -ID $ID ` -Uri $uri ` -Body $body ` -Action $actionDescription ` -GetResourceScript { Get-CloudImage -ID $ID } ` -SuccessMessage "Image $ID ownership updated successfully." } } function Update-CloudImagePermissions { <# .SYNOPSIS Updates the permissions of an image in the Cloud Server. .DESCRIPTION Changes the permission of an image. Prompts for confirmation. .PARAMETER ID Required. ID of the image. .PARAMETER OwnerUse Optional. True or false, enable OwnerUse .PARAMETER OwnerManage Optional. True or false, enable OwnerManage .PARAMETER OwnerAdmin Optional. True or false, enable OwnerAdmin .PARAMETER GroupUse Optional. True or false, enable GroupUse .PARAMETER GroupManage Optional. True or false, enable GroupManage .PARAMETER GroupAdmin Optional. True or false, enable GroupAdmin .PARAMETER OtherUse Optional. True or false, enable OtherUse .PARAMETER OtherManage Optional. True or false, enable OtherManage .PARAMETER OtherAdmin Optional. True or false, enable OtherManage .EXAMPLE # Give group users permission to use the image Update-CloudImagePermissions -ID 35 -GroupUse $true .EXAMPLE # Deny group admin permission to the image Update-CloudImagePermissions -ID 35 -GroupAdmin $false .EXAMPLE # Set multiple permissions at once Update-CloudImagePermissions -ID 35 -GroupUse $true -GroupManage $true -OtherUse $true #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact='High')] param( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [int]$ID, [Parameter(Mandatory = $false)] [bool]$OwnerUse, [Parameter(Mandatory = $false)] [bool]$OwnerManage, [Parameter(Mandatory = $false)] [bool]$OwnerAdmin, [Parameter(Mandatory = $false)] [bool]$GroupUse, [Parameter(Mandatory = $false)] [bool]$GroupManage, [Parameter(Mandatory = $false)] [bool]$GroupAdmin, [Parameter(Mandatory = $false)] [bool]$OtherUse, [Parameter(Mandatory = $false)] [bool]$OtherManage, [Parameter(Mandatory = $false)] [bool]$OtherAdmin ) process { # Build the permissions object structure as shown in the API spec $permissions = @{} if ($PSBoundParameters.ContainsKey('OwnerUse')) { $permissions['owner_use'] = $OwnerUse } if ($PSBoundParameters.ContainsKey('OwnerManage')) { $permissions['owner_manage'] = $OwnerManage } if ($PSBoundParameters.ContainsKey('OwnerAdmin')) { $permissions['owner_admin'] = $OwnerAdmin } if ($PSBoundParameters.ContainsKey('GroupUse')) { $permissions['group_use'] = $GroupUse } if ($PSBoundParameters.ContainsKey('GroupManage')) { $permissions['group_manage'] = $GroupManage } if ($PSBoundParameters.ContainsKey('GroupAdmin')) { $permissions['group_admin'] = $GroupAdmin } if ($PSBoundParameters.ContainsKey('OtherUse')) { $permissions['other_use'] = $OtherUse } if ($PSBoundParameters.ContainsKey('OtherManage')) { $permissions['other_manage'] = $OtherManage } if ($PSBoundParameters.ContainsKey('OtherAdmin')) { $permissions['other_admin'] = $OtherAdmin } # Create the body with the permissions nested structure $body = @{ permissions = $permissions } $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/image/${ID}/permissions" Invoke-CloudResourceUpdate ` -CallerPSCmdlet $PSCmdlet ` -ResourceType "Image" ` -ID $ID ` -Uri $uri ` -Body $body ` -Action "Update permissions" ` -GetResourceScript { Get-CloudImage -ID $ID } } } function Disable-CloudImage { <# .SYNOPSIS Disables an image from the Cloud Server. .DESCRIPTION Disables an image. Automatically handles token refresh. .PARAMETER Name Required. Image ID. .EXAMPLE # Disable image with confirmation prompt (default behavior): Disable-CloudImage -ID 3 Confirm Are you sure you want to perform this action? Performing the operation "Disable Image" on target "Image ID 3 (MyImage)". [Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "Y"): Y .EXAMPLE # Disable image without confirmation prompt: Disable-CloudImage -ID 3 -Confirm:$false #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact='High')] param( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [int]$ID ) process { $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/image/${ID}/enable" $body = @{ enable = $false } $actionParts = @("Disable image $ImageID") Invoke-CloudResourceUpdate ` -CallerPSCmdlet $PSCmdlet ` -ResourceType "Image" ` -ID $ID ` -Uri $uri ` -Body $body ` -Action "Disable" ` -GetResourceScript { Get-CloudImage -ID $ID } ` -SuccessMessage "Image $ID disabled successfully." } } function Enable-CloudImage { <# .SYNOPSIS Enables an image from the Cloud Server. .DESCRIPTION Enables an image. Automatically handles token refresh. .PARAMETER Name Required. Image ID. .EXAMPLE # Enable image with confirmation prompt (default behavior): Enable-CloudImage -ID 3 Confirm Are you sure you want to perform this action? Performing the operation "Enable Image" on target "Image ID 3 (MyImage)". [Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "Y"): Y .EXAMPLE # Enable image without confirmation prompt: Enable-CloudImage -ID 3 -Confirm:$false #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact='High')] param( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [int]$ID ) process { $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/image/${ID}/enable" $body = @{ enable = $true } $Action = "update" Invoke-CloudResourceUpdate ` -CallerPSCmdlet $PSCmdlet ` -ResourceType "Image" ` -ID $ID ` -Uri $uri ` -Body $body ` -Action "Ensable" ` -GetResourceScript { Get-CloudImage -ID $ID } ` -SuccessMessage "Image $ID enabled successfully." } } function Disable-CloudImagePersistence { <# .SYNOPSIS Sets an image to non-persistent on the Cloud Server. .DESCRIPTION Sets an image to persistent. Automatically handles token refresh. .PARAMETER Name Required. Image ID. .EXAMPLE # Disable image persistence with confirmation prompt (default behavior): Disable-CloudImagePersistence -ID 3 Confirm Are you sure you want to perform this action? Performing the operation "Disable Persistence" on target "Image ID 3 (MyImage)". [Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "Y"): Y .EXAMPLE # Disable image persistence without confirmation prompt: Disable-CloudImagePersistence -ID 3 -Confirm:$false #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact='High')] param( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [int]$ID ) process { $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/image/${ID}/persistent" $body = @{ persistent = $false } $Action = "update" Invoke-CloudResourceUpdate ` -CallerPSCmdlet $PSCmdlet ` -ResourceType "Image" ` -ID $ID ` -Uri $uri ` -Body $body ` -Action "Update" ` -GetResourceScript { Get-CloudImage -ID $ID } ` -SuccessMessage "Image $ID persistence disabled successfully." } } function Enable-CloudImagePersistence { <# .SYNOPSIS Sets an image to persistent on the Cloud Server. .DESCRIPTION Sets an image to persistent. Automatically handles token refresh. .PARAMETER Name Required. Image ID. .EXAMPLE # Enable image persistence with confirmation prompt (default behavior): Enable-CloudImagePersistence -ID 3 Confirm Are you sure you want to perform this action? Performing the operation "Enable Persistence" on target "Image ID 3 (MyImage)". [Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "Y"): Y .EXAMPLE # Enable image persistence without confirmation prompt: Enable-CloudImagePersistence -ID 3 -Confirm:$false #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact='High')] param( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [int]$ID ) process { $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/image/${ID}/persistent" $body = @{ persistent = $true } $Action = "update" Invoke-CloudResourceUpdate ` -CallerPSCmdlet $PSCmdlet ` -ResourceType "Image" ` -ID $ID ` -Uri $uri ` -Body $body ` -Action "Update" ` -GetResourceScript { Get-CloudImage -ID $ID } ` -SuccessMessage "Image $ID persistence enabled successfully." } } function Update-CloudImage { <# .SYNOPSIS Updates an image on the Cloud Server. .DESCRIPTION Updates an image's template. You can choose to merge with the existing template or replace it entirely. Merge is enabled by default. Automatically handles token refresh. .PARAMETER ID Required. ID of the image to update. .PARAMETER Template Required. Template content for the image in OpenNebula format. .PARAMETER Merge Optional. If true (default), merges with existing template. If false, replaces the template entirely. Use -Merge:$false to completely replace the image configuration. .EXAMPLE # Update image description (merge with existing) $template = 'DESCRIPTION="Updated description for this image"' Update-CloudImage -ID 123 -Template $template .EXAMPLE # Make an image persistent $template = 'PERSISTENT="YES"' Update-CloudImage -ID 123 -Template $template .EXAMPLE # Replace entire image template $template = @" NAME="Ubuntu-2204-Updated" DESCRIPTION="Ubuntu 22.04 LTS Server" TYPE="OS" PERSISTENT="NO" "@ Update-CloudImage -ID 123 -Template $template -Merge:$false .EXAMPLE # Update multiple attributes $template = @" DESCRIPTION="Production Web Server Image" PERSISTENT="YES" DEV_PREFIX="sd" "@ Update-CloudImage -ID 456 -Template $template .EXAMPLE # Change image driver $template = 'DRIVER="qcow2"' Update-CloudImage -ID 789 -Template $template #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact='Medium')] param( [Parameter(Mandatory = $true)] [int]$ID, [Parameter(Mandatory = $true, ValueFromPipeline = $true)] [string]$Template, [Parameter()] [bool]$Merge = $true ) process { # Build the request body $body = @{ merge = $Merge template = $Template } $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/image/${ID}" if ($PSCmdlet.ShouldProcess("Image ID '$ID'", "Update image")) { Write-Verbose "Request URI: $uri" Write-Verbose "Merge: $Merge" Write-Verbose "Template:`n$Template" try { $response = Invoke-CloudApiRequest -Uri $uri -Method Patch -Body $body Write-Verbose "Successfully updated image ID: $ID" Write-Host "Image ID $ID updated successfully." -ForegroundColor Green return $response.image } catch { Write-Error "Failed to update image '$ID': $_" throw } } } } function Update-CloudImageType { <# .SYNOPSIS Updates an image type on the Cloud Server. .DESCRIPTION Updates an image type. .PARAMETER ID Required. ID of the image to update. .PARAMETER Type Required. use either OS, CDROM, DATABLOCK, or CONTEXT .EXAMPLE # Change an image to the OS type Update-CloudImageType -ID 123 -Type OS .EXAMPLE # Change an image to the CDROM type Update-CloudImageType -ID 123 -Type CDROM .EXAMPLE # Change an image to the DATABLOCK type Update-CloudImageType -ID 123 -Type DATABLOCK .EXAMPLE # Change an image to the CONTEXT type Update-CloudImageType -ID 123 -Type CONTEXT #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact='High')] param( [Parameter(Mandatory = $true)] [int]$ID, [Parameter(Mandatory = $true, ValueFromPipeline = $true)] [string]$Type ) process { # Build the request body $body = @{ type = $Type } $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/image/${ID}/type" if ($PSCmdlet.ShouldProcess("Image ID '$ID'", "Update image type")) { Write-Verbose "Request URI: $uri" Write-Verbose "Template:`n$Template" try { $response = Invoke-CloudApiRequest -Uri $uri -Method Patch -Body $body Write-Verbose "Successfully updated image $ID to type $Type" Write-Host "Image ID $ID updated successfully." -ForegroundColor Green return $response.image } catch { Write-Error "Failed to update image type for '$ID': $_" throw } } } } function Get-CloudImageSnapshot { <# .SYNOPSIS Gets snapshots for Cloud images. .DESCRIPTION Retrieves all snapshots for one or more images. Shows snapshot details including date, size, parent relationships, and active status. .PARAMETER ImageID Optional. ID of a specific image to get snapshots for. If not specified, gets snapshots for all images. .PARAMETER SnapshotID Optional. Get a specific snapshot by ID. .EXAMPLE # Get all snapshots for image 50 Get-CloudImageSnapshot -ImageID 50 .EXAMPLE # Get a specific snapshot Get-CloudImageSnapshot -ImageID 50 -SnapshotID 0 .EXAMPLE # Get snapshots for all images Get-CloudImageSnapshot .EXAMPLE # Get snapshots from pipeline Get-CloudImage -ID 50 | Get-CloudImageSnapshot .EXAMPLE # Get snapshots with formatted date Get-CloudImageSnapshot -ImageID 50 | Format-Table image_name, id, name, date_formatted, size #> [CmdletBinding()] param( [Parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] [Alias('ID', 'image_id')] [int]$ImageID, [Parameter(Mandatory = $false)] [int]$SnapshotID ) process { try { # Get images - either specific one or all if ($ImageID) { $images = @(Get-CloudImage -ID $ImageID) } else { $images = Get-CloudImage } foreach ($image in $images) { Write-Verbose "Getting snapshots for Image ID: $($image.id) ($($image.name))" # Check if image has snapshots if (-not $image.snapshots -or -not $image.snapshots.snapshot) { Write-Verbose "No snapshots found for Image ID: $($image.id)" continue } $snapshots = $image.snapshots.snapshot # Filter by SnapshotID if specified if ($PSBoundParameters.ContainsKey('SnapshotID')) { $snapshots = $snapshots | Where-Object { $_.id -eq $SnapshotID } if (-not $snapshots) { Write-Warning "Snapshot ID $SnapshotID not found for Image ID: $($image.id)" continue } } # Process each snapshot foreach ($snapshot in $snapshots) { # Add image context $snapshot | Add-Member -NotePropertyName 'image_id' -NotePropertyValue $image.id -Force $snapshot | Add-Member -NotePropertyName 'image_name' -NotePropertyValue $image.name -Force # Add formatted date if ($snapshot.date -and $snapshot.date -match '^\d+$') { try { $dateFormatted = [DateTimeOffset]::FromUnixTimeSeconds([long]$snapshot.date).LocalDateTime $snapshot | Add-Member -NotePropertyName 'date_formatted' -NotePropertyValue $dateFormatted -Force } catch { $snapshot | Add-Member -NotePropertyName 'date_formatted' -NotePropertyValue $null -Force } } else { $snapshot | Add-Member -NotePropertyName 'date_formatted' -NotePropertyValue $null -Force } # Add snapshot metadata from parent object $snapshot | Add-Member -NotePropertyName 'allow_orphans' -NotePropertyValue $image.snapshots.allow_orphans -Force $snapshot | Add-Member -NotePropertyName 'current_base' -NotePropertyValue $image.snapshots.current_base -Force $snapshot | Add-Member -NotePropertyName 'next_snapshot' -NotePropertyValue $image.snapshots.next_snapshot -Force # Output the enhanced snapshot Write-Output $snapshot } } } catch { Write-Error "Failed to get image snapshots: $_" throw } } } function Remove-CloudImageSnapshot { <# .SYNOPSIS Deletes a snapshot from a Cloud image. .DESCRIPTION Removes a specific snapshot from an image. This action cannot be undone. .PARAMETER ImageID Required. ID of the image. .PARAMETER SnapshotID Required. ID of the snapshot to delete. .EXAMPLE # Delete snapshot 0 from image 50 Remove-CloudImageSnapshot -ImageID 50 -SnapshotID 0 .EXAMPLE # Delete without confirmation Remove-CloudImageSnapshot -ImageID 50 -SnapshotID 0 -Confirm:$false #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact='High')] param( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [Alias('image_id')] [int]$ImageID, [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [Alias('id')] [int]$SnapshotID ) process { # Build the URI $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/image/${ImageID}/snapshot/${SnapshotID}" if ($PSCmdlet.ShouldProcess("Image ID $ImageID", "Delete snapshot ID $SnapshotID")) { Write-Verbose "Deleting snapshot ID $SnapshotID from Image ID: $ImageID" Write-Verbose "Request URI: $uri" try { $response = Invoke-CloudApiRequest -Uri $uri -Method Delete Write-Host "Snapshot ID $SnapshotID deleted successfully from Image ID $ImageID." -ForegroundColor Green return $response } catch { Write-Error "Failed to delete snapshot from Image ${ImageID}: $_" throw } } } } function Merge-CloudImageSnapshot { <# .SYNOPSIS Flattens (merges) an image snapshot. .DESCRIPTION Flattens a snapshot into the base image, consolidating the snapshot data. This operation merges the snapshot's changes into the parent image. .PARAMETER ImageID Required. ID of the image. .PARAMETER SnapshotID Required. ID of the snapshot to flatten. .EXAMPLE # Flatten snapshot 0 of image 50 Merge-CloudImageSnapshot -ImageID 50 -SnapshotID 0 .EXAMPLE # Flatten without confirmation Merge-CloudImageSnapshot -ImageID 50 -SnapshotID 0 -Confirm:$false #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact='High')] param( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [Alias('image_id')] [int]$ImageID, [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [Alias('id')] [int]$SnapshotID ) process { # Build the URI $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/image/${ImageID}/snapshot/${SnapshotID}/flatten" if ($PSCmdlet.ShouldProcess("Image ID $ImageID", "Flatten snapshot ID $SnapshotID")) { Write-Verbose "Flattening snapshot ID $SnapshotID for Image ID: $ImageID" Write-Verbose "Request URI: $uri" try { $response = Invoke-CloudApiRequest -Uri $uri -Method Patch Write-Host "Snapshot ID $SnapshotID flattened successfully for Image ID $ImageID." -ForegroundColor Green return $response } catch { Write-Error "Failed to flatten snapshot for Image ${ImageID}: $_" throw } } } } function Restore-CloudImageSnapshot { <# .SYNOPSIS Reverts an image to a previous snapshot. .DESCRIPTION Reverts the image to the state captured in the specified snapshot. This will discard any changes made after the snapshot was taken. .PARAMETER ImageID Required. ID of the image. .PARAMETER SnapshotID Required. ID of the snapshot to revert to. .EXAMPLE # Revert image 50 to snapshot 0 Restore-CloudImageSnapshot -ImageID 50 -SnapshotID 0 .EXAMPLE # Revert without confirmation Restore-CloudImageSnapshot -ImageID 50 -SnapshotID 0 -Confirm:$false #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact='High')] param( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [Alias('image_id')] [int]$ImageID, [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [Alias('id')] [int]$SnapshotID ) process { # Build the URI $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/image/${ImageID}/snapshot/${SnapshotID}/revert" if ($PSCmdlet.ShouldProcess("Image ID $ImageID", "Revert to snapshot ID $SnapshotID")) { Write-Verbose "Reverting Image ID $ImageID to snapshot ID: $SnapshotID" Write-Verbose "Request URI: $uri" try { $response = Invoke-CloudApiRequest -Uri $uri -Method Patch Write-Host "Image ID $ImageID reverted successfully to snapshot ID $SnapshotID." -ForegroundColor Green return $response } catch { Write-Error "Failed to revert snapshot for Image ${ImageID}: $_" throw } } } } |