From af68be15c6022da1095c36accd057c39acc84b5d Mon Sep 17 00:00:00 2001 From: Jonh Wendell Date: Mon, 30 Mar 2015 15:36:33 -0300 Subject: [PATCH] New plugin: ec2_launch It adds the ability to automatically launch an EC2 instance after AMI registration. It has no mandatory configuration, only optional ones, like instance type, security groups, etc. They should be documented in later documentation patches. --- bootstrapvz/plugins/ec2_launch/__init__.py | 11 +++ .../plugins/ec2_launch/manifest-schema.yml | 18 +++++ bootstrapvz/plugins/ec2_launch/tasks.py | 70 +++++++++++++++++++ 3 files changed, 99 insertions(+) create mode 100644 bootstrapvz/plugins/ec2_launch/__init__.py create mode 100644 bootstrapvz/plugins/ec2_launch/manifest-schema.yml create mode 100644 bootstrapvz/plugins/ec2_launch/tasks.py diff --git a/bootstrapvz/plugins/ec2_launch/__init__.py b/bootstrapvz/plugins/ec2_launch/__init__.py new file mode 100644 index 0000000..c1e8caf --- /dev/null +++ b/bootstrapvz/plugins/ec2_launch/__init__.py @@ -0,0 +1,11 @@ +def validate_manifest(data, validator, error): + import os.path + schema_path = os.path.normpath(os.path.join(os.path.dirname(__file__), 'manifest-schema.yml')) + validator(data, schema_path) + + +def resolve_tasks(taskset, manifest): + import tasks + taskset.add(tasks.LaunchEC2Instance) + if 'print_public_ip' in manifest.plugins['ec2_launch']: + taskset.add(tasks.PrintPublicIPAddress) diff --git a/bootstrapvz/plugins/ec2_launch/manifest-schema.yml b/bootstrapvz/plugins/ec2_launch/manifest-schema.yml new file mode 100644 index 0000000..faba1e8 --- /dev/null +++ b/bootstrapvz/plugins/ec2_launch/manifest-schema.yml @@ -0,0 +1,18 @@ +--- +$schema: http://json-schema.org/draft-04/schema# +title: EC2-launch plugin manifest +type: object +properties: + plugins: + type: object + properties: + ec2_launch: + type: object + properties: + security_group_ids: + type: array + items: {type: string} + uniqueItems: true + instance_type: {type: string} + print_public_ip: {type: string} + tags: {type: object} diff --git a/bootstrapvz/plugins/ec2_launch/tasks.py b/bootstrapvz/plugins/ec2_launch/tasks.py new file mode 100644 index 0000000..53190ef --- /dev/null +++ b/bootstrapvz/plugins/ec2_launch/tasks.py @@ -0,0 +1,70 @@ +from bootstrapvz.base import Task +from bootstrapvz.common import phases +from bootstrapvz.providers.ec2.tasks import ami +import time +import logging + + +class LaunchEC2Instance(Task): + description = 'Launching EC2 instance' + phase = phases.image_registration + predecessors = [ami.RegisterAMI] + + @classmethod + def run(cls, info): + conn = info._ec2['connection'] + r = conn.run_instances(info._ec2['image'], + security_group_ids=info.manifest.plugins['ec2_launch'].get('security_group_ids'), + instance_type=info.manifest.plugins['ec2_launch'].get('instance_type', 't2.micro')) + info._ec2['instance_id'] = r.instances[0].id + + if 'tags' in info.manifest.plugins['ec2_launch']: + def apply_format(v): + return v.format(**info.manifest_vars) + tags = info.manifest.plugins['ec2_launch']['tags'] + r = {k: apply_format(v) for k, v in tags.items()} + conn.create_tags([info._ec2['instance_id']], r) + + +class PrintPublicIPAddress(Task): + description = 'Waiting for the instance to launch' + phase = phases.image_registration + predecessors = [LaunchEC2Instance] + + @classmethod + def run(cls, info): + ec2 = info._ec2 + logger = logging.getLogger(__name__) + filename = info.manifest.plugins['ec2_launch']['print_public_ip'] + if not filename: + filename = '/dev/null' + f = open(filename, 'w') + + i = 0 + instance = None + while True: + logger.debug('Waiting a bit to get instance metadata...') + time.sleep(5) + + i += 1 + if i > 10: + logger.error('Waited too much, giving up') + break + + r = ec2['connection'].get_only_instances([ec2['instance_id']]) + if not r and not r[0]: + logger.error('Could not get instance metadata') + break + + instance = r[0] + if instance.ip_address: + break + + if instance and instance.ip_address: + logger.info('******* EC2 IP ADDRESS: %s *******' % instance.ip_address) + f.write(instance.ip_address) + else: + logger.error('Could not get IP address for the instance') + f.write('') + + f.close()