python boto3 aws lambda – An error occurred (IncorrectInstanceState) when calling the StartInstances operation:

Question:

I wrote a lambda using python boto3 to bring up all EC2 instances. It works fine. I went ahead and terminated 2 instances. When I run the code now, it tries to bring up the terminated instances also. That is very odd. Shouldn’t the lambda ignore the terminated instances and bring up only the ones that are in "stopped" status. I shouldn’t be writing the logic to check the status of a instance and bring up only the instances that are in "Stopped" state right?

[ERROR] ClientError: An error occurred (IncorrectInstanceState) when calling the StartInstances operation: The instance ‘i-002d545f637ad1ebd’ is not in a state from which it can be started.
Traceback (most recent call last):

import json
import boto3
import pprint
from pprint import pprint


def lambda_handler(event, context):
    aws_mgmt_console = boto3.session.Session()
    ec2_console_resource = aws_mgmt_console.resource('ec2')
    ec2_console_client = aws_mgmt_console.client('ec2')
  

    #starting all instances at the same time
    #First step get the list of all instances      
  
    all_instance_ids=[]
    for each_instance in ec2_console_resource.instances.all():
         all_instance_ids.append(each_instance.id)
  
    #step 2 create  a waiter       
    waiter=ec2_console_client.get_waiter('instance_running')
 
    ec2_console_resource.instances.start()
    
    waiter.wait(InstanceIds=all_instance_ids) 

    print("All Your ec2 instace are up and running")
  
Asked By: Jason

||

Answers:

Based on the instance lifecycle, only stopped instances can be started.

As such, the user must filter for the instance state they require, as seen in this example.


So, you can obtain a list of stopped instances,

is_running_filter = {'Name': 'instance-state-name', 'Values': ['stopped']}
stopped_instance_ids = []
for each_instance in ec2_console_resource.instances.filter(Filters=[is_running_filter]):
    stopped_instance_ids.append(each_instance.id)

and then only start the stopped instances.

ec2_console_client.start_instances(InstanceIds=stopped_instance_ids)
Answered By: t_krill