New-IpsAwsImage.ps1
<# .SYNOPSIS Create an Amazon Machine Image from the result of an Image Portability Service AWS image prepare job. .DESCRIPTION Creates an Amazon Machine Image (AMI) from the volume containing the prepared image resulting from an Image Portability Service AWS image prepare job. An intermediate EC2 snapshot is also created. The id of the volume to turn into the AMI is specified either by piping the output of Wait-IpsJob into this command or explicitly using the -VolumeId parameter. The volume id of the prepared image for an already completed job can be found in the output from running the Get-IpsJob command. .PARAMETER ImageName Specifies the name for the created image. If unspecified a name is chosen by the system and will be shown in the output. .PARAMETER Tags Specifies a hash table of string values to apply as labels to the created disk image. .PARAMETER LogFileDir Specifies the path to the file to log to. The local directory is the default. .PARAMETER LogFileName Specifies the name of the file to log to. .PARAMETER OverwriteLog If specified the log file is overwritten otherwise it is appended to. .INPUTS PSCustomObject. The output from Wait-IpsJob after waiting on an AWS prepare job. .OUTPUTS PSCustomObject. A custom object including the image name, image id, and the intermediate snapshot id. .EXAMPLE PS> Start-IpsAwsPrepareJob ... | Wait-IpsJob | New-IpsAwsImage -ImageName example-image .EXAMPLE PS> $job = Get-IpsJob aef7aa4a-19e7-46fd-b3c7-1f87ddfa375e PS> New-IpsAwsImage -ImageName example-image -VolumeId $job.additionalInfo.artifacts.output.id #> 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 } } } } |