ec2: Fix bug with running/stopped state and wait=yes.
If `get_all_instances` returns multiple reservations, the old wait loop only dealt with the first reservation. Thus, the wait loop may end before all instances get to be running/stopped. Also clean up the code a little.
This commit is contained in:
parent
ac72d44219
commit
d2329baa93
1 changed files with 20 additions and 30 deletions
50
cloud/ec2
50
cloud/ec2
|
@ -193,7 +193,7 @@ options:
|
||||||
instance_ids:
|
instance_ids:
|
||||||
version_added: "1.3"
|
version_added: "1.3"
|
||||||
description:
|
description:
|
||||||
- list of instance ids, currently only used when state='absent'
|
- list of instance ids, currently used for states: absent, running, stopped
|
||||||
required: false
|
required: false
|
||||||
default: null
|
default: null
|
||||||
aliases: []
|
aliases: []
|
||||||
|
@ -1039,7 +1039,7 @@ def terminate_instances(module, ec2, instance_ids):
|
||||||
return (changed, instance_dict_array, terminated_instance_ids)
|
return (changed, instance_dict_array, terminated_instance_ids)
|
||||||
|
|
||||||
|
|
||||||
def startstop_instances(module, ec2, instance_ids):
|
def startstop_instances(module, ec2, instance_ids, state):
|
||||||
"""
|
"""
|
||||||
Starts or stops a list of existing instances
|
Starts or stops a list of existing instances
|
||||||
|
|
||||||
|
@ -1047,9 +1047,10 @@ def startstop_instances(module, ec2, instance_ids):
|
||||||
ec2: authenticated ec2 connection object
|
ec2: authenticated ec2 connection object
|
||||||
instance_ids: The list of instances to start in the form of
|
instance_ids: The list of instances to start in the form of
|
||||||
[ {id: <inst-id>}, ..]
|
[ {id: <inst-id>}, ..]
|
||||||
|
state: Intended state ("running" or "stopped")
|
||||||
|
|
||||||
Returns a dictionary of instance information
|
Returns a dictionary of instance information
|
||||||
about the instances started.
|
about the instances started/stopped.
|
||||||
|
|
||||||
If the instance was not able to change state,
|
If the instance was not able to change state,
|
||||||
"changed" will be set to False.
|
"changed" will be set to False.
|
||||||
|
@ -1064,18 +1065,15 @@ def startstop_instances(module, ec2, instance_ids):
|
||||||
if not isinstance(instance_ids, list) or len(instance_ids) < 1:
|
if not isinstance(instance_ids, list) or len(instance_ids) < 1:
|
||||||
module.fail_json(msg='instance_ids should be a list of instances, aborting')
|
module.fail_json(msg='instance_ids should be a list of instances, aborting')
|
||||||
|
|
||||||
dest_state = module.params.get('state')
|
|
||||||
dest_state_ec2 = 'stopped' if dest_state == 'stopped' else 'running'
|
|
||||||
|
|
||||||
# Check that our instances are not in the state we want to take them to
|
# Check that our instances are not in the state we want to take them to
|
||||||
# and change them to our desired state
|
# and change them to our desired state
|
||||||
running_instances_array = []
|
running_instances_array = []
|
||||||
for res in ec2.get_all_instances(instance_ids):
|
for res in ec2.get_all_instances(instance_ids):
|
||||||
for inst in res.instances:
|
for inst in res.instances:
|
||||||
if not inst.state == dest_state_ec2:
|
if inst.state != state:
|
||||||
instance_dict_array.append(get_instance_info(inst))
|
instance_dict_array.append(get_instance_info(inst))
|
||||||
try:
|
try:
|
||||||
if dest_state == 'running':
|
if state == 'running':
|
||||||
inst.start()
|
inst.start()
|
||||||
else:
|
else:
|
||||||
inst.stop()
|
inst.stop()
|
||||||
|
@ -1084,21 +1082,14 @@ def startstop_instances(module, ec2, instance_ids):
|
||||||
changed = True
|
changed = True
|
||||||
|
|
||||||
## Wait for all the instances to finish starting or stopping
|
## Wait for all the instances to finish starting or stopping
|
||||||
instids = [ i.id for i in res.instances ]
|
|
||||||
this_res = []
|
|
||||||
num_running = 0
|
|
||||||
wait_timeout = time.time() + wait_timeout
|
wait_timeout = time.time() + wait_timeout
|
||||||
while wait_timeout > time.time() and num_running < len(instids):
|
while wait and wait_timeout > time.time():
|
||||||
res_list = res.connection.get_all_instances(instids)
|
matched_instances = []
|
||||||
if len(res_list) > 0:
|
for res in ec2.get_all_instances(instance_ids):
|
||||||
this_res = res_list[0]
|
for i in res.instances:
|
||||||
num_running = len([ i for i in this_res.instances if i.state == dest_state_ec2 ])
|
if i.state == state:
|
||||||
else:
|
matched_instances.append(i)
|
||||||
# got a bad response of some sort, possibly due to
|
if len(matched_instances) < len(instance_ids):
|
||||||
# stale/cached data. Wait a second and then try again
|
|
||||||
time.sleep(1)
|
|
||||||
continue
|
|
||||||
if wait and num_running < len(instids):
|
|
||||||
time.sleep(5)
|
time.sleep(5)
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
|
@ -1107,10 +1098,7 @@ def startstop_instances(module, ec2, instance_ids):
|
||||||
# waiting took too long
|
# waiting took too long
|
||||||
module.fail_json(msg = "wait for instances running timeout on %s" % time.asctime())
|
module.fail_json(msg = "wait for instances running timeout on %s" % time.asctime())
|
||||||
|
|
||||||
for inst in this_res.instances:
|
return (changed, instance_dict_array, instance_ids)
|
||||||
running_instances_array.append(inst.id)
|
|
||||||
|
|
||||||
return (changed, instance_dict_array, running_instances_array)
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
@ -1160,21 +1148,23 @@ def main():
|
||||||
|
|
||||||
tagged_instances = []
|
tagged_instances = []
|
||||||
|
|
||||||
if module.params.get('state') == 'absent':
|
state = module.params.get('state')
|
||||||
|
|
||||||
|
if state == 'absent':
|
||||||
instance_ids = module.params.get('instance_ids')
|
instance_ids = module.params.get('instance_ids')
|
||||||
if not isinstance(instance_ids, list):
|
if not isinstance(instance_ids, list):
|
||||||
module.fail_json(msg='termination_list needs to be a list of instances to terminate')
|
module.fail_json(msg='termination_list needs to be a list of instances to terminate')
|
||||||
|
|
||||||
(changed, instance_dict_array, new_instance_ids) = terminate_instances(module, ec2, instance_ids)
|
(changed, instance_dict_array, new_instance_ids) = terminate_instances(module, ec2, instance_ids)
|
||||||
|
|
||||||
elif module.params.get('state') == 'running' or module.params.get('state') == 'stopped':
|
elif state in ('running', 'stopped'):
|
||||||
instance_ids = module.params.get('instance_ids')
|
instance_ids = module.params.get('instance_ids')
|
||||||
if not isinstance(instance_ids, list):
|
if not isinstance(instance_ids, list):
|
||||||
module.fail_json(msg='running list needs to be a list of instances to run: %s' % instance_ids)
|
module.fail_json(msg='running list needs to be a list of instances to run: %s' % instance_ids)
|
||||||
|
|
||||||
(changed, instance_dict_array, new_instance_ids) = startstop_instances(module, ec2, instance_ids)
|
(changed, instance_dict_array, new_instance_ids) = startstop_instances(module, ec2, instance_ids, state)
|
||||||
|
|
||||||
elif module.params.get('state') == 'present':
|
elif state == 'present':
|
||||||
# Changed is always set to true when provisioning new instances
|
# Changed is always set to true when provisioning new instances
|
||||||
if not module.params.get('image'):
|
if not module.params.get('image'):
|
||||||
module.fail_json(msg='image parameter is required for new instance')
|
module.fail_json(msg='image parameter is required for new instance')
|
||||||
|
|
Loading…
Reference in a new issue