Python boto ec2 – How do I wait till an image is created or failed

Question:

I am writing a code to iterate through all available instances and create an AMI for them as below:

for reservation in reservations:
    ......
    ami_id = ec2_conn.create_image(instance.id, ami_name, description=ami_desc, no_reboot=True)

But how do I wait till an image is created before proceeding with the creation of next image? Because I need to track the status of each ami created.

I know that I can retrieve the state using:

image_status = get_image(ami_id).state

So, do I iterate through the list of ami_ids created and then fetch the state for each of them? If so, then what if the image is still pending when I read the state of the image? How will I find out if the image creation has failed eventually?

Thanks.

Asked By: drunkenfist

||

Answers:

If I understand correctly, you want to initiate the create_image call and then wait until the server-side operation completes before moving on. To do this, you have to poll the EC2 service periodically until the state of the image is either available (meaning it succeeded) or failed (meaning it failed). The code would look something like this:

import time
...
image_id = ec2_conn.create_image(instance.id, ...)
image = ec2_conn.get_all_images(image_ids=[image_id])[0]
while image.state == 'pending':
    time.sleep(5)
    image.update()
if image.state == 'available':
    # success, do something here
else:
    # handle failure here
Answered By: garnaat

For someone who is using boto3, the following would work:

import boto3
import time
region = 'us-west-1'
client = boto3.client('ec2', region_name=region)
def is_image_available(image_id):
    try:
        available = 0
        while available == 0:
            print "Not created yet.. Gonna sleep for 10 seconds"
            time.sleep(10)
            image = client.describe_images(ImageIds=[image_id])
            if image['Images'][0]['State'] == 'available':
                available = 1
        if available == 1:
            print "Image is now available for use."
            return True
    except Exception, e:
        print e

Using this function you should be able to pass the image_id and get the status as true if its available. You can use it in an if condition as follows:

if is_image_available(image_id):
# Do something if image is available

Hope it helps.

Answered By: user3228188

Boto now has the wait_until_running method which saves rolling your own polling code:

http://boto3.readthedocs.io/en/latest/reference/services/ec2.html#EC2.Instance.wait_until_running

Answered By: Snowcrash

I’ll answer the exact same question.

Keep updating the image state variable while the state is not running.
At any point if the state is running, break the loop.
You can also check for terminated states or failed states.

image = ec2.Image(image_id)
if(image.state == 'pending'):
        print("Waiting for image to be available.")
        while(image.state != 'available'):
            image = ec2.Image(image_id)
        print("Image Available to use")

TIP:
Don’t wait for images to be available while creating the images.
Check for images to be available while creating the instances from those images. It will save you a lot of time because a lot of pending images will be able to concurrently come into the available state.

If you wait for each image to be available, you are just adding all the creation time to your program.

Hope it helps.

Answered By: Ashwani Jha

I think the best thing to do is use a waiter, none of the answers above do that:

https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ec2.html#EC2.Waiter.ImageAvailable

Answered By: piotr

I use the following snippet to wait for an AMI image:

import boto3

def is_image_available(image_id):
    client = boto3.client('ec2')
    waiter = client.get_waiter('image_available')
    waiter.wait(Filters=[{'Name': 'image-id', 'Values': [image_id]}])
    image = client.describe_images(ImageIds=[image_id])
    if image['Images'][0]['State'] == 'available':
       return True
    return False
Answered By: SlashGordon

Use get_waiter.

waiter = client.get_waiter('image_available')

waiter.wait(
    ImageIds=[
        image_id
    ]
)

print('Image availabled')

Reference: https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ec2.html#EC2.Waiter.ImageAvailable

Answered By: Thuc Tran Van
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.