Rebase start/stop instance pull code

pull/18777/head
HAMSIK Adam 9 years ago committed by Matt Clay
parent ec8a94f748
commit 217764ba3c

@ -142,7 +142,7 @@ options:
instance_tags: instance_tags:
version_added: "1.0" version_added: "1.0"
description: description:
- a hash/dictionary of tags to add to the new instance; '{"key":"value"}' and '{"key":"value","key":"value"}' - a hash/dictionary of tags to add to the new instance or for for starting/stopping instance by tag; '{"key":"value"}' and '{"key":"value","key":"value"}'
required: false required: false
default: null default: null
aliases: [] aliases: []
@ -226,19 +226,19 @@ options:
exact_count: exact_count:
version_added: "1.5" version_added: "1.5"
description: description:
- An integer value which indicates how many instances that match the 'count_tag' parameter should be running. Instances are either created or terminated based on this value. - An integer value which indicates how many instances that match the 'count_tag' parameter should be running. Instances are either created or terminated based on this value.
required: false required: false
default: null default: null
aliases: [] aliases: []
count_tag: count_tag:
version_added: "1.5" version_added: "1.5"
description: description:
- Used with 'exact_count' to determine how many nodes based on a specific tag criteria should be running. This can be expressed in multiple ways and is shown in the EXAMPLES section. For instance, one can request 25 servers that are tagged with "class=webserver". - Used with 'exact_count' to determine how many nodes based on a specific tag criteria should be running. This can be expressed in multiple ways and is shown in the EXAMPLES section. For instance, one can request 25 servers that are tagged with "class=webserver".
required: false required: false
default: null default: null
aliases: [] aliases: []
author: author:
- "Tim Gerla (@tgerla)" - "Tim Gerla (@tgerla)"
- "Lester Wade (@lwade)" - "Lester Wade (@lwade)"
- "Seth Vidal" - "Seth Vidal"
@ -268,7 +268,7 @@ EXAMPLES = '''
wait: yes wait: yes
wait_timeout: 500 wait_timeout: 500
count: 5 count: 5
instance_tags: instance_tags:
db: postgres db: postgres
monitoring: yes monitoring: yes
vpc_subnet_id: subnet-29e63245 vpc_subnet_id: subnet-29e63245
@ -302,7 +302,7 @@ EXAMPLES = '''
wait: yes wait: yes
wait_timeout: 500 wait_timeout: 500
count: 5 count: 5
instance_tags: instance_tags:
db: postgres db: postgres
monitoring: yes monitoring: yes
vpc_subnet_id: subnet-29e63245 vpc_subnet_id: subnet-29e63245
@ -363,7 +363,7 @@ EXAMPLES = '''
region: us-east-1 region: us-east-1
tasks: tasks:
- name: Launch instance - name: Launch instance
ec2: ec2:
key_name: "{{ keypair }}" key_name: "{{ keypair }}"
group: "{{ security_group }}" group: "{{ security_group }}"
instance_type: "{{ instance_type }}" instance_type: "{{ instance_type }}"
@ -443,6 +443,15 @@ EXAMPLES = '''
vpc_subnet_id: subnet-29e63245 vpc_subnet_id: subnet-29e63245
assign_public_ip: yes assign_public_ip: yes
#
# Start stopped instances specified by tag
#
- local_action:
module: ec2
instance_tags:
Name: ExtraPower
state: running
# #
# Enforce that 5 instances with a tag "foo" are running # Enforce that 5 instances with a tag "foo" are running
# (Highly recommended!) # (Highly recommended!)
@ -471,11 +480,11 @@ EXAMPLES = '''
image: ami-40603AD1 image: ami-40603AD1
wait: yes wait: yes
group: webserver group: webserver
instance_tags: instance_tags:
Name: database Name: database
dbtype: postgres dbtype: postgres
exact_count: 5 exact_count: 5
count_tag: count_tag:
Name: database Name: database
dbtype: postgres dbtype: postgres
vpc_subnet_id: subnet-29e63245 vpc_subnet_id: subnet-29e63245
@ -528,8 +537,8 @@ def find_running_instances_by_count_tag(module, ec2, count_tag, zone=None):
for res in reservations: for res in reservations:
if hasattr(res, 'instances'): if hasattr(res, 'instances'):
for inst in res.instances: for inst in res.instances:
instances.append(inst) instances.append(inst)
return reservations, instances return reservations, instances
@ -540,7 +549,7 @@ def _set_none_to_blank(dictionary):
result[k] = _set_none_to_blank(result[k]) result[k] = _set_none_to_blank(result[k])
elif not result[k]: elif not result[k]:
result[k] = "" result[k] = ""
return result return result
def get_reservations(module, ec2, tags=None, state=None, zone=None): def get_reservations(module, ec2, tags=None, state=None, zone=None):
@ -679,7 +688,7 @@ def create_block_device(module, ec2, volume):
# http://aws.amazon.com/about-aws/whats-new/2013/10/09/ebs-provisioned-iops-maximum-iops-gb-ratio-increased-to-30-1/ # http://aws.amazon.com/about-aws/whats-new/2013/10/09/ebs-provisioned-iops-maximum-iops-gb-ratio-increased-to-30-1/
MAX_IOPS_TO_SIZE_RATIO = 30 MAX_IOPS_TO_SIZE_RATIO = 30
if 'snapshot' not in volume and 'ephemeral' not in volume: if 'snapshot' not in volume and 'ephemeral' not in volume:
if 'volume_size' not in volume: if 'volume_size' not in volume:
module.fail_json(msg = 'Size must be specified when creating a new volume or modifying the root volume') module.fail_json(msg = 'Size must be specified when creating a new volume or modifying the root volume')
if 'snapshot' in volume: if 'snapshot' in volume:
if 'device_type' in volume and volume.get('device_type') == 'io1' and 'iops' not in volume: if 'device_type' in volume and volume.get('device_type') == 'io1' and 'iops' not in volume:
@ -692,7 +701,7 @@ def create_block_device(module, ec2, volume):
if 'encrypted' in volume: if 'encrypted' in volume:
module.fail_json(msg = 'You can not set encyrption when creating a volume from a snapshot') module.fail_json(msg = 'You can not set encyrption when creating a volume from a snapshot')
if 'ephemeral' in volume: if 'ephemeral' in volume:
if 'snapshot' in volume: if 'snapshot' in volume:
module.fail_json(msg = 'Cannot set both ephemeral and snapshot') module.fail_json(msg = 'Cannot set both ephemeral and snapshot')
return BlockDeviceType(snapshot_id=volume.get('snapshot'), return BlockDeviceType(snapshot_id=volume.get('snapshot'),
ephemeral_name=volume.get('ephemeral'), ephemeral_name=volume.get('ephemeral'),
@ -757,18 +766,18 @@ def enforce_count(module, ec2, vpc):
for inst in instance_dict_array: for inst in instance_dict_array:
inst['state'] = "terminated" inst['state'] = "terminated"
terminated_list.append(inst) terminated_list.append(inst)
instance_dict_array = terminated_list instance_dict_array = terminated_list
# ensure all instances are dictionaries # ensure all instances are dictionaries
all_instances = [] all_instances = []
for inst in instances: for inst in instances:
if type(inst) is not dict: if type(inst) is not dict:
inst = get_instance_info(inst) inst = get_instance_info(inst)
all_instances.append(inst) all_instances.append(inst)
return (all_instances, instance_dict_array, changed_instance_ids, changed) return (all_instances, instance_dict_array, changed_instance_ids, changed)
def create_instances(module, ec2, vpc, override_count=None): def create_instances(module, ec2, vpc, override_count=None):
""" """
Creates new instances Creates new instances
@ -876,7 +885,7 @@ def create_instances(module, ec2, vpc, override_count=None):
if ebs_optimized: if ebs_optimized:
params['ebs_optimized'] = ebs_optimized params['ebs_optimized'] = ebs_optimized
# 'tenancy' always has a default value, but it is not a valid parameter for spot instance resquest # 'tenancy' always has a default value, but it is not a valid parameter for spot instance resquest
if not spot_price: if not spot_price:
params['tenancy'] = tenancy params['tenancy'] = tenancy
@ -909,7 +918,7 @@ def create_instances(module, ec2, vpc, override_count=None):
groups=group_id, groups=group_id,
associate_public_ip_address=assign_public_ip) associate_public_ip_address=assign_public_ip)
interfaces = boto.ec2.networkinterface.NetworkInterfaceCollection(interface) interfaces = boto.ec2.networkinterface.NetworkInterfaceCollection(interface)
params['network_interfaces'] = interfaces params['network_interfaces'] = interfaces
else: else:
params['subnet_id'] = vpc_subnet_id params['subnet_id'] = vpc_subnet_id
if vpc_subnet_id: if vpc_subnet_id:
@ -919,11 +928,11 @@ def create_instances(module, ec2, vpc, override_count=None):
if volumes: if volumes:
bdm = BlockDeviceMapping() bdm = BlockDeviceMapping()
for volume in volumes: for volume in volumes:
if 'device_name' not in volume: if 'device_name' not in volume:
module.fail_json(msg = 'Device name must be set for volume') module.fail_json(msg = 'Device name must be set for volume')
# Minimum volume size is 1GB. We'll use volume size explicitly set to 0 # Minimum volume size is 1GB. We'll use volume size explicitly set to 0
# to be a signal not to create this volume # to be a signal not to create this volume
if 'volume_size' not in volume or int(volume['volume_size']) > 0: if 'volume_size' not in volume or int(volume['volume_size']) > 0:
bdm[volume['device_name']] = create_block_device(module, ec2, volume) bdm[volume['device_name']] = create_block_device(module, ec2, volume)
@ -1013,7 +1022,7 @@ def create_instances(module, ec2, vpc, override_count=None):
num_running = 0 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_timeout > time.time() and num_running < len(instids):
try: try:
res_list = ec2.get_all_instances(instids) res_list = ec2.get_all_instances(instids)
except boto.exception.BotoServerError, e: except boto.exception.BotoServerError, e:
if e.error_code == 'InvalidInstanceID.NotFound': if e.error_code == 'InvalidInstanceID.NotFound':
@ -1026,7 +1035,7 @@ def create_instances(module, ec2, vpc, override_count=None):
for res in res_list: for res in res_list:
num_running += len([ i for i in res.instances if i.state=='running' ]) num_running += len([ i for i in res.instances if i.state=='running' ])
if len(res_list) <= 0: if len(res_list) <= 0:
# got a bad response of some sort, possibly due to # got a bad response of some sort, possibly due to
# stale/cached data. Wait a second and then try again # stale/cached data. Wait a second and then try again
time.sleep(1) time.sleep(1)
continue continue
@ -1138,12 +1147,12 @@ def terminate_instances(module, ec2, instance_ids):
filters={'instance-state-name':'terminated'}): filters={'instance-state-name':'terminated'}):
for inst in res.instances: for inst in res.instances:
instance_dict_array.append(get_instance_info(inst)) instance_dict_array.append(get_instance_info(inst))
return (changed, instance_dict_array, terminated_instance_ids) return (changed, instance_dict_array, terminated_instance_ids)
def startstop_instances(module, ec2, instance_ids, state): def startstop_instances(module, ec2, instance_ids, state, instance_tags):
""" """
Starts or stops a list of existing instances Starts or stops a list of existing instances
@ -1151,6 +1160,8 @@ def startstop_instances(module, ec2, instance_ids, state):
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>}, ..]
instance_tags: A dict of tag keys and values in the form of
{key: value, ... }
state: Intended state ("running" or "stopped") state: Intended state ("running" or "stopped")
Returns a dictionary of instance information Returns a dictionary of instance information
@ -1159,19 +1170,33 @@ def startstop_instances(module, ec2, instance_ids, state):
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.
Note that if instance_ids and instance_tags are both non-empty,
this method will process the intersection of the two
""" """
wait = module.params.get('wait') wait = module.params.get('wait')
wait_timeout = int(module.params.get('wait_timeout')) wait_timeout = int(module.params.get('wait_timeout'))
changed = False changed = False
instance_dict_array = [] instance_dict_array = []
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') # Fail unless the user defined instance tags
if not instance_tags:
module.fail_json(msg='instance_ids should be a list of instances, aborting')
# To make an EC2 tag filter, we need to prepend 'tag:' to each key.
# An empty filter does no filtering, so it's safe to pass it to the
# get_all_instances method even if the user did not specify instance_tags
filters = {}
if instance_tags:
for key, value in instance_tags.items():
filters["tag:" + key] = value
# Check that our instances are not in the state we want to take
# Check (and eventually change) instances attributes and instances state # Check (and eventually change) instances attributes and instances 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, filters=filters):
for inst in res.instances: for inst in res.instances:
# Check "source_dest_check" attribute # Check "source_dest_check" attribute
@ -1292,11 +1317,12 @@ def main():
(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 state in ('running', 'stopped'): elif state in ('running', 'stopped'):
instance_ids = module.params['instance_ids'] instance_ids = module.params.get('instance_ids')
if not instance_ids: instance_tags = module.params.get('instance_tags')
module.fail_json(msg='instance_ids list is requried for %s state' % state) if not (isinstance(instance_ids, list) or isinstance(instance_tags, dict)):
module.fail_json(msg='running list needs to be a list of instances or set of tags to run: %s' % instance_ids)
(changed, instance_dict_array, new_instance_ids) = startstop_instances(module, ec2, instance_ids, state) (changed, instance_dict_array, new_instance_ids) = startstop_instances(module, ec2, instance_ids, state, instance_tags)
elif 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

Loading…
Cancel
Save