New-IpsAwsImage.ps1

<#
 .Synopsis
  Creates an AWS disk image based on the result of the AWS prepare job.

 .Description
  Creates an AWS disk image based on the result of the AWS prepare job.
#>

Function New-IpsAwsImage
{
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)] # Artifacts come from pipeline and contain the volume id
        [psobject]$Artifacts = [PSCustomObject]@{},
        [Parameter(Mandatory = $false)]
        [string]$VolumeId, # Use VolumeId if no Artifacts
        [Parameter(Mandatory = $false)]
        [string]$ImageName,
        [Parameter(Mandatory = $false)]
        [HashTable]$Tags = @{},
        [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)]
        [string]$LogFileDir = "",
        [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)]
        [string]$LogFileName = 'CreateToAws.log',
        [Parameter(Mandatory = $false)]
        [switch]$OverwriteLog
    )
    Begin
    {
    }
    Process
    {
        try {
            # Set parameter 'Verbose' by internal parameter 'VerbosePreference', since the option -Verbose is occupied by powershell cmdlet
            if($VerbosePreference -eq 'Continue') {
                $Verbose = $True
            } else {
                $Verbose = $False
            }
            LogInit $LogFileDir $LogFileName $OverwriteLog $Verbose

            if (($Artifacts.Count -eq 0) -and [String]::IsNullOrWhiteSpace($VolumeId)) {
                throw "Invalid parameters. Must contain either Artifacts or VolumeId"
            }

            if ([String]::IsNullOrWhiteSpace($VolumeId)) {
                # Get volume ID from the artifacts
                try {
                    if ($Artifacts | Get-Member "volumeId") {
                        $VolumeId = $Artifacts.volumeId
                    } else {
                        $VolumeId = $Artifacts["output"][0].id
                    }
                } catch {
                }
                if ([String]::IsNullOrWhiteSpace($VolumeId)) {
                    LogIt 'Invalid Artifacts' $False
                    LogIt ($Artifacts | Out-String) $False
                    throw "Invalid Artifacts"
                }
                LogIt "Using volume $volumeId from Artifacts"
            }

            if ([String]::IsNullOrWhiteSpace($ImageName)) {
                $ImageName = "ImageCreatedFromMigratedVolume-" + $VolumeId
                LogIt "Using default image name $ImageName"
            }

            $DefaultTagsString = "{Key=SourceScript,Value=New-IpsAwsImage},{Key=SourceVolume,Value=" + $VolumeId + "}"
            $TagsString = $Tags.keys.foreach({ "{Key=$_, Value=$($Tags[$_])}" }) -join ','

            if ([String]::IsNullOrWhiteSpace($TagsString)) {
                LogIt "Using default tags"
                $TagsListString = '[' + $DefaultTagsString + ']'
            } else {
                $TagsListString = '[' + $TagsString + ',' + $DefaultTagsString + ']'
            }

            try {
                # create the snapshot
                $TagsSpecsString = 'ResourceType=snapshot,Tags=' + $TagsListString
                LogIt "Creating snapshot from volume $VolumeId with TagSpecifications $TagsSpecsString"

                $SnapshotResponse = aws ec2 create-snapshot --description 'Created with a Citrix migrated volume' --volume-id $VolumeId --tag-specifications $TagsSpecsString

                if ($LastExitCode -ne 0) {
                    throw "Failed to create VM Volume Snapshot. Failed with error code $LastExitCode"
                }

                $SnapshotResponseObject = $SnapshotResponse | ConvertFrom-Json
                $SnapshotId = $SnapshotResponseObject.SnapshotId

                LogIt "Initiated snapshot creation $snapshotId from volume $VolumeId. Waiting for snapshot to be completed ..."

                # wait for snapshot to be completed
                aws ec2 wait snapshot-completed --snapshot-ids $SnapshotId

                if ($LastExitCode -ne 0) {
                    throw "Failed to create snapshot. Failed with error code $LastExitCode"
                }

                Write-Host "Snapshot $($SnapshotId) is ready for conversion to an image"

                # create the image
                $BlockDeviceMappingsString = 'DeviceName=/dev/sda1,Ebs={SnapshotId=' + $SnapshotId + '}'

                $ImageResponse = aws ec2 register-image --name $ImageName --architecture 'x86_64' --root-device-name '/dev/sda1' --boot-mode uefi --ena-support --virtualization-type 'hvm' --block-device-mappings $BlockDeviceMappingsString

                if ($LastExitCode -ne 0) {
                    throw "Failed to create VM Image. Failed with error code $LastExitCode"
                }

                $ImageResponseObject = $ImageResponse | ConvertFrom-Json
                $ImageId = $ImageResponseObject.ImageId
                LogIt "Created VM Image $ImageName ($ImageId) from snapshot $SnapshotId"

                $output = [PSCustomObject]@{
                    ImageName = $ImageName
                    ImageId = $ImageId
                    SnapshotId = $SnapshotId
                    Tags = $TagsListString
                }

                Write-Output $output
            }
            catch {
                LogFatal "Failed to create VM Image $ImageName from volume $($VolumeId): $_"
            }
        }
        finally {
            # Clear credentials if at end of a pipeline
            if (($PSCmdlet.MyInvocation.PipelinePosition -eq $PSCmdlet.MyInvocation.PipelineLength) -and ($PSCmdlet.MyInvocation.PipelineLength -gt 1)) {
                Clear-XDCredentials
            }
        }
    }
}