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()