Image management is an advanced subject that will be discussed in detail in Chapter 6. For the time being, we will merely summarize the API operations that are available to manage your AMIs in EC2.
The RegisterImage operation outlined in Table 5-24 registers an AMI to make it available in the EC2 environment. Before it can be registered, the AMI must first be bundled into image files and uploaded to S3 with a manifest XML file.
Table 5-24. RegisterImage request parameters
Parameter Name | Value | Required? |
---|---|---|
Action | RegisterImage | Yes |
ImageLocation | The full path to the image manifest file stored in S3, including the bucket name and object key | Yes |
Here is an XML document returned by the operation. It is very simple, containing only the element imageId which contains a unique identifier for the AMI that has been registered.
<RegisterImageResponse xmlns='http://ec2.amazonaws.com/doc/2007-08-29/'> <imageId>ami-d39075ba</imageId> </RegisterImageResponse>
Example 5-17 defines a method to register an AMI that is described by an image manifest file stored in S3. The method returns the unique identifier value assigned to the registered AMI.
Example 5-17. Register an image: EC2.rb
def register_image(image_location) parameters = build_query_params(API_VERSION, SIGNATURE_VERSION, { 'Action' => 'RegisterImage', 'ImageLocation' => image_location, }) response = do_query(HTTP_METHOD, ENDPOINT_URI, parameters) xml_doc = REXML::Document.new(response.body) return xml_doc.elements['//imageId'].text end
The DeregisterImage operation shown in Table 5-25 deregisters an image. You must deregister an image if you have removed the bundled image files from S3 or if you have updated these image files to store a new version of your AMI.
Do not forget to deregister an image if you make any changes to it. Failing to do so can lead to odd situations in which the old image can still be launched in some circumstances and not in others.
Table 5-25. DeregisterImage request parameters
Parameter Name | Value | Required? |
---|---|---|
Action | DeregisterImage | Yes |
ImageId | The identifier of the AMI to de-register | Yes |
Here is an XML document returned by the operation. It is very simple, containing only the element return, which contains a Boolean value indicating whether the operation was successful.
<DeregisterImageResponse xmlns='http://ec2.amazonaws.com/doc/2007-08-29/'> <return>true</return> </DeregisterImageResponse>
A method that deregisters an AMI image is shown in Example 5-18.
An AMI registered for use in EC2 can have attributes associated with it. These attributes may be listed, modified, and reset by the AMI’s owner using API operations. Image attributes are used for two purposes: sharing images and setting product codes.
The launchPermission
attribute allows you to specify which EC2 account holders can
launch instances from an AMI that you created. You can allow
specific users to start your AMI by assigning them launch
permissions, or you can make your AMI publicly available by
assigning permissions to all EC2 users. By default, you are
the only one who can access your AMIs.
The productCodes
attribute allows you to assign a product code value to your
image. Product codes are generally used to identify an image
as a Paid AMI. This feature is not generally used directly by
EC2 users. This attribute can only be set once and cannot be
changed.
The ModifyImageAttribute operation modifies the attributes associated with an AMI. The modification operation can either add or remove attribute values.
Table 5-26 lists the mandatory parameters required to modify an attribute for an AMI image. Depending on which attribute you are modifying, you must also provide additional parameters.
Table 5-26. ModifyImageAttributes request parameters
Parameter Name | Value | Required? |
---|---|---|
Action | ModifyImageAttribute | Yes |
ImageId | The identifier of the AMI whose attribute will be modified | Yes |
Attribute | The name of the attribute to modify; the only valid
values for this parameter are launchPermission and productCodes | Yes |
OperationType | The operation to perform on the named attribute, legal
values are add or remove | Yes |
Table 5-27
lists the additional query parameters that are necessary to modify the
launchPermission
image
attribute.
Table 5-27. ModifyImageAttributes request parameters: launch permission
Parameter Name | Value | Required? |
---|---|---|
UserId (Indexed) | A list of identifiers of EC2 users whose ability to run
the AMI will be granted with an add operation or revoked with a
remove operation | Yes, if the UserGroup parameter is not provided |
UserGroup (Indexed) | A list of user group names whose ability to run the AMI
will be granted with an add
operation or revoked with a remove operation. Currently the only
valid group name is all ,
which denotes public access within EC2. | Yes, if the UserId parameter is not provided |
Table 5-28
lists the additional query parameters that are necessary to
modify the productCodes
image
attribute.
Table 5-28. ModifyImageAttributes request parameters: product codes
Parameter Name | Value | Required? |
---|---|---|
ProductCode (Indexed) | A list of product codes that will be associated with
the AMI. Only the add
operation is legal for product codes, because they can only be
set once and never changed. | Yes |
Here is an XML document returned by the operation. It is very simple as it includes only the element return, which contains a Boolean value indicating whether the operation was successful.
<ModifyImageAttributeResponse xmlns='http://ec2.amazonaws.com/doc/2007-08-29/'> <return>true</return> </ModifyImageAttributeResponse>
Example 5-19 defines a method that adds attributes to, or removes them from, an AMI registered in EC2.
Example 5-19. Modify image attribute: EC2.rb
def modify_image_attribute(image_id, attribute, operation_type, attribute_values) parameters = build_query_params(API_VERSION, SIGNATURE_VERSION, { 'Action' => 'ModifyImageAttribute', 'ImageId' => image_id, 'Attribute' => attribute, 'OperationType' => operation_type, }, attribute_values) response = do_query(HTTP_METHOD, ENDPOINT_URI, parameters) return true end
If you wish to allow other people to start an AMI you own, you
can use the modify_image_attribute
method to define the set of EC2 users allowed to run your AMI. You
specify which users to allow using their EC2 Account IDs. The commands
below demonstrate how to permit EC2 users 123456789012
and 210987654321
to run the AMI with ID ami-889075e1
.
The Account ID that identifies EC2 users is not the AWS Access Key as you might expect, but is rather the user’s 12-digit account number as listed on their AWS account activity statement. Notice that it is possible to add launch permission attributes to an AMI even when they do not make sense. We are able to add access permissions for fake user IDs without any errors.
irb> ec2.modify_image_attribute('ami-889075e1', 'launchPermission', 'add', {'UserId'=>['123456789012','210987654321']})
To allow all EC2 users to run your image—that is, to make your
AMI publicly accessible—you would add a launchPermission
attribute specifying the
user group named all
.
irb> ec2.modify_image_attribute('ami-889075e1', 'launchPermission', 'add', {'UserGroup'=>'all'})
The DescribeImageAttribute operation, outlined in Table 5-29, lists the attribute settings that apply to your AMI. The response document returned by this operation will vary according to the attribute you ask to be described.
Table 5-29. DescribeImageAttributes request parameters
Parameter Name | Value | Required? |
---|---|---|
Action | DescribeImageAttribute | Yes |
ImageId | The identifier of the AMI whose attributes will be listed | Yes |
Attribute | The name of the attribute to list | Yes |
Here is an XML document returned when you request details about
the launchPermission
attribute.
This document includes a listing of permission items, containing
either the number (userId) of the user who has been granted permission
to launch the AMI, or the name of a group that has been granted that
permission. If no permissions have been granted, the launchPermission
element will be
empty.
<DescribeImageAttributeResponse xmlns='http://ec2.amazonaws.com/doc/2007-08-29/'> <imageId>ami-889075e1</imageId> <launchPermission> <item> <userId>123456789012</userId> </item> <item> <group>all</group> </item> </launchPermission> </DescribeImageAttributeResponse>
Here is an XML document returned when you request details about
the productCodes
attribute. This
document includes a listing of product code strings inside item/productCode elements.
<DescribeImageAttributeResponse xmlns='http://ec2.amazonaws.com/doc/2007-08-29/'> <imageId>ami-889075e1</imageId> <productCodes> <item> <productCode>123456789012</productCode> </item> </productCodes> </DescribeImageAttributeResponse>
Example 5-20 defines a method
that retrieves the value of an attribute that applies to an AMI and
interprets the response document. The method can interpret the details
for both the productCodes
and
launchPermission
attributes. The
product codes associated with an AMI are returned in the :product_codes
hash item, while user and
group launch permissions are returned in the :launch_perms_user
and :launch_perms_group
hash items
respectively.
Example 5-20. Describe image attribute: EC2.rb
def describe_image_attribute(image_id, attribute='launchPermission') parameters = build_query_params(API_VERSION, SIGNATURE_VERSION, { 'Action' => 'DescribeImageAttribute', 'ImageId' => image_id, 'Attribute' => attribute, }) response = do_query(HTTP_METHOD, ENDPOINT_URI, parameters) xml_doc = REXML::Document.new(response.body) result = {:id => xml_doc.elements['//imageId'].text} if xml_doc.elements['//launchPermission'] result[:launch_perms_user] = [] result[:launch_perms_group] = [] xml_doc.elements.each('//launchPermission/item') do |lp| elems = lp.elements result[:launch_perms_group] << elems['group'].text if elems['group'] result[:launch_perms_user] << elems['userId'].text if elems['userId'] end end if xml_doc.elements['//productCodes'] result[:product_codes] = [] xml_doc.elements.each('//productCodes/item') do |pc| result[:product_codes] << pc.text end end return result end
We can use this method to list the launch permissions for our AMI or the product codes associated with it.
# List the launch permissions for our AMI (2 user perms, 1 group perm) irb> ec2.describe_image_attribute('ami-889075e1', 'launchPermission') {:id=>"ami-889075e1", :launch_perms_group=>["all"], :launch_perms_user=>["210987654321", "123456789012"]} # List the product codes associated for our AMI irb> puts ec2.describe_image_attribute('ami-889075e1', 'productCodes') {:product_codes=>[], :id=>"ami-889075e1"}
The RestImageAttribute operation detailed in Table 5-30 resets an AMI’s attribute value back to its default setting.
Table 5-30. ResetImageAttribute request parameters
Parameter Name | Value | Required? |
---|---|---|
Action | ResetImageAttribute | Yes |
ImageId | The Id of the AMI whose attributes will be reset | Yes |
Attribute | The name of the attribute to reset | Yes |
Here is an XML document returned by the operation. It is very simple, containing only the element return, which contains a Boolean value indicating whether the operation was successful.
<ResetImageAttributeResponse xmlns='http://ec2.amazonaws.com/doc/2007-08-29/'> <return>true</return> </ResetImageAttributeResponse>
Example 5-21 defines a method
that resets the named attribute to its default value. Unless you
specify a different attribute name, the method will reset the launchPermission
attribute.
Example 5-21. Reset image attribute: EC2.rb
def reset_image_attribute(image_id, attribute='launchPermission') parameters = build_query_params(API_VERSION, SIGNATURE_VERSION, { 'Action' => 'ResetImageAttribute', 'ImageId' => image_id, 'Attribute' => attribute, }) response = do_query(HTTP_METHOD, ENDPOINT_URI, parameters) return true end
Resetting the launchPermission image attribute will remove the fake user launch permission we added earlier.
# Reset the launchPermission attribute irb> ec2.reset_image_attribute('ami-889075e1', 'launchPermission') => true # Confirm that all the launch permissions have been removed irb> ec2.describe_image_attribute('ami-889075e1', 'launchPermission') => {:launch_perms_group=>[], :id=>"ami-889075e1", :launch_perms_user=>[]}
The ConfirmProductInstance operation shown in Table 5-31 checks whether a running instance is based on an AMI with a given product code; if it is, the operation returns the identifier of the instance’s owner.
This operation is only useful to EC2 developers who have sold an AMI to a customer with a support agreement and an associated product code. In this circumstance, it allows you to confirm that the instance a customer is running is eligible for support.
Table 5-31. ConfirmProductInstance request parameters
Parameter Name | Value | Required? |
---|---|---|
Action | ConfirmProductInstance | Yes |
ProductCode | The product code that should be associated with the AMI on which the instance is based | Yes |
InstanceId | The identifier of an EC2 instance that is currently running, which a customer claims is covered under a support agreement | Yes |
Here is an XML document returned by the operation:
<ConfirmProductInstanceResponse xmlns='http://ec2.amazonaws.com/doc/2007-08-29/'> <result>true</result> <ownerId>123456789012</ownerId> </ConfirmProductInstanceResponse>
The response document from the operation includes the confirmation information shown in Table 5-32.
Table 5-32. ConfirmProductInstanceResponse element
Element Name | Description |
---|---|
result | Indicates whether the given instance is indeed based on
an AMI with the given product code. This value will be
true or false. |
ownerId | The account identifier of the instance’s owner. This
value is only returned if the result value is true. |
Example 5-22 defines a method that confirms whether a running instance is based on an AMI with a product code attribute that matches a specific value.
Example 5-22. Confirm product instance: EC2.rb
def confirm_product_instance(product_code, instance_id) parameters = build_query_params(API_VERSION, SIGNATURE_VERSION, { 'Action' => 'ConfirmProductInstance', 'ProductCode' => product_code, 'InstanceId' => instance_id }) response = do_query(HTTP_METHOD, ENDPOINT_URI, parameters) elems = REXML::Document.new(response.body).elements result = { :result => elems['//result'].text == true } result[:owner_id] = elems['//ownerId'].text if elems['//ownerId'] return result end