AWS Developer Blog

Using the New Import Cmdlets for Amazon EC2

by Steve Roberts | on | in .NET | Permalink | Comments |  Share

Using the New Import Cmdlets for Amazon EC2

Amazon EC2 recently released an updated set of APIs for importing virtual machine images and disks. These new APIs, ImportImage and ImportSnapshot, are faster and more flexible than the original import APIs and are now available in the AWS Tools for Windows PowerShell (from version 2.3.43.0) through two new cmdlets – Import-EC2Image and Import-EC2Snapshot. Let’s take a look at how we use the new cmdlets to perform imports.

Importing a VM Image

Importing an image to EC2 can be done in just a couple of steps. First, we have to upload the disk image to Amazon S3, and then we run the import cmdlet that will yield an Amazon Machine Image (AMI) we can launch. We also need to set up an Identity and Access Management role, plus associated role policy, that gives EC2 access to the S3 artifacts. This is a one-time operation.

Import Prerequisites

As detailed in the EC2 user guide topic, the new import service APIs use an Identity and Access Management role, with associated role policy, to access the image file(s) that you upload to Amazon S3 during import. Setting these up is a one-time operation (assuming you use the same bucket to hold the image file for each import) and can be done from PowerShell very easily, as follows.

First, we create the role. The EC2 import API defaults to a role name of ”vmimport” if a custom role name is not supplied when we run the import command. For the sake of simplicity, that’s the name we’ll use in this blog example:

PS C:> $importPolicyDocument = @"
{
   "Version":"2012-10-17",
   "Statement":[
      {
         "Sid":"",
         "Effect":"Allow",
         "Principal":{
            "Service":"vmie.amazonaws.com"
         },
         "Action":"sts:AssumeRole",
         "Condition":{
            "StringEquals":{
               "sts:ExternalId":"vmimport"
            }
         }
      }
   ]
}
"@

PS C:> New-IAMRole -RoleName vmimport -AssumeRolePolicyDocument $importPolicyDocument

Now that we have created the role, we add a policy allowing EC2 access to the bucket containing our image:

PS C:> $bucketName = "myvmimportimages"
PS C:> $rolePolicyDocument = @"
{
   "Version":"2012-10-17",
   "Statement":[
      {
         "Effect":"Allow",
         "Action":[
            "s3:ListBucket",
            "s3:GetBucketLocation"
         ],
         "Resource":[
            "arn:aws:s3:::$bucketName"
         ]
      },
      {
         "Effect":"Allow",
         "Action":[
            "s3:GetObject"
         ],
         "Resource":[
            "arn:aws:s3:::$bucketName/*"
         ]
      },
      {
         "Effect":"Allow",
         "Action":[
            "ec2:ModifySnapshotAttribute",
            "ec2:CopySnapshot",
            "ec2:RegisterImage",
            "ec2:Describe*"
         ],
         "Resource":"*"
      }
   ]
}
"@

PS C:> Write-IAMRolePolicy -RoleName vmimport -PolicyName vmimport -PolicyDocument $rolePolicyDocument

That completes the prerequisites. If we want to use a different bucket (or additional buckets) in the future, we simply reconstruct the policy here-string shown above with the name(s) of the new or additional buckets and re-run the Write-IAMRolePolicy cmdlet.

Uploading the Image

The VM or disk image must be uploaded to S3. To do this, we use the Write-S3Object cmdlet. Assume we have a Windows Server 2012 R2 image consisting of a single disk that we want to import. This image is located on disk in the file C:CustomWindows2012R2.vhd. We’re also using the same bucket declared in the prerequisites above, ”myvmimportimages”, which we captured in a variable:

PS C:> Write-S3Object -BucketName $bucketName -File .CustomWindows2012R2.vhd

Because we did not supply a -Key parameter to the cmdlet to identify the object in the bucket, the file name is used by default. If the VM image to be imported consists of multiple disk images, simply repeat the use of Write-S3Object to upload all the images.

We’re now ready to import the image.

Importing the Image

The cmdlet to import VM images, Import-EC2Image, accepts a number of parameters that allow you to describe the import for future reference and detail which object in S3 contains the image EC2 should operate on. You can also specify a custom role name (with the -RoleName parameter) granting EC2 access to the S3 object. Earlier in this post we showed how to set up the role and policy using the default name EC2 assumes if a custom role is not specified, so this parameter will not be used here.

First, we must construct one or more ImageDiskContainer instances. If you are importing a VM that consists of multiple disk images (and therefore multiple S3 objects), we would create multiple container instances and pass them as an array to the cmdlet. Our sample image for this post contains just a single image file:

PS C:> $windowsContainer = New-Object Amazon.EC2.Model.ImageDiskContainer
PS C:> $windowsContainer.Format="VHD"

Details of the S3 location of the image file are specified in a nested object:

PS C:> $userBucket = New-Object Amazon.EC2.Model.UserBucket
PS C:> $userBucket.S3Bucket = $bucketName
PS C:> $userBucket.S3Key = "CustomWindows2012R2.vhd"
PS C:> $windowsContainer.UserBucket = $userBucket

Having constructed the disk container object(s), we can set up the parameters to the import cmdlet. One of the parameters, ClientToken, allows us to pass an idempotency token – this ensures that if a problem arises and we need to re-run the command, EC2 does not start a new import:

PS C:> $params = @{
    "ClientToken"="CustomWindows2012R2_" + (Get-Date)
    "Description"="My custom Windows 2012R2 image import"
    "Platform"="Windows"
    "LicenseType"="AWS"
}

We’re now ready to run the import cmdlet:

PS C:> Import-EC2Image -DiskContainer $windowsContainer @params 

Architecture    : 
Description     : My custom Windows 2012R2 image import
Hypervisor      : 
ImageId         : 
ImportTaskId    : import-ami-abcdefgh
LicenseType     : AWS
Platform        : Windows
Progress        : 2
SnapshotDetails : {}
Status          : active
StatusMessage   : pending

We can check progress on an import (or set of imports) using the Get-EC2ImportImageTask cmdlet, which outputs the same information as above for each import task. Optionally, we can query a specific import by supplying a value to the ImportTaskId parameter. We can also supply a set of filters if we don’t want to slice-n-dice the output through the PowerShell pipeline.

To abandon an import, we use the Stop-EC2ImportTask cmdlet. This cmdlet is used for both VM image and disk snapshot imports. It accepts the import task id of the import to be stopped.

Importing a Disk Snapshot

Importing disk snapshots to be used as additional EBS volumes to attach to EC2 instances is very similar to importing a VM image except that we’re always importing a single image:

PS C:> Write-S3Object -BucketName $bucketName -File .DataDisk.vhd
PS C:> $params = @{
    "ClientToken"="MySnapshotImport_" + (Get-Date)
    "Description"="My Data Disk Image"
    "DiskContainer_Description" = "Data disk import"
    "DiskContainer_Format" = "VHD"
    "DiskContainer_S3Bucket" = $bucketName
    "DiskContainer_S3Key" = "DataDisk.vhd"
}

PS C:> Import-EC2Snapshot @params | fl

Description         : My Data Disk Image
ImportTaskId        : import-snap-abcdefg
SnapshotTaskDetail  : Amazon.EC2.Model.SnapshotTaskDetail

To check progress of a snapshot import, we use the Get-EC2ImportSnapshotTask cmdlet, which is very similar to Get-EC2ImportImageTask. As mentioned earlier, a snapshot import can be stopped using Stop-EC2ImportTask.

Deprecated: Original Import Cmdlets

The original import cmdlets (Import-EC2Instance, Import-EC2Volume, Get-EC2ConversionTask and Stop-EC2ConversionTask) have now been marked as deprecated. They will be removed in a future release.

More Information

We hope you find the new cmdlets easier to use! For more information about importing VM images and disk snapshots to Amazon EC2, see this post on the official AWS Blog. You can also access the EC2 documentation for the feature.