From 456e6f5a558f02837c93782294173c7455657bcf Mon Sep 17 00:00:00 2001 From: Tim Gerla Date: Tue, 22 Jan 2013 12:09:31 -0800 Subject: [PATCH] library/ec2: - use boto instead of euca2ools - improve error handling/propagation for run failures - rename keypair to key_name (and preserve alias for old playbooks) - should be 100% backward compatible with the euca2ools version --- library/ec2 | 68 ++++++++++++++++++++++++++--------------------------- 1 file changed, 33 insertions(+), 35 deletions(-) diff --git a/library/ec2 b/library/ec2 index eb9100ecc49..eadec94436a 100644 --- a/library/ec2 +++ b/library/ec2 @@ -22,12 +22,12 @@ description: - creates ec2 instances and optionally waits for it to be 'running'. This module has a dependency on the external I(euca2ools) package. version_added: "0.9" options: - keypair: + key_name: description: - key pair to use on the instance required: true default: null - aliases: [] + aliases: ['keypair'] group: description: - security group to use on the instance @@ -92,25 +92,18 @@ options: examples: - code: "local_action: ec2 keypair=admin instance_type=m1.large image=emi-40603AD1 wait=true group=webserver" description: "Examples from Ansible Playbooks" -requirements: [ "euca2ools" ] +requirements: [ "boto" ] author: Seth Vidal ''' -import euca2ools.commands.euca.runinstances +import boto import time - -def _run(cmd): - # returns (rc, stdout, stderr) from shell command - process = subprocess.Popen(cmd, stdout=subprocess.PIPE, - stderr=subprocess.PIPE, shell=True) - stdout, stderr = process.communicate() - return (process.returncode, stdout, stderr) - +from urlparse import urlparse def main(): module = AnsibleModule( argument_spec = dict( - keypair = dict(required=True), + key_name = dict(required=True, aliases = ['keypair']), group = dict(default='default'), instance_type = dict(aliases=['type']), image = dict(required=True), @@ -125,7 +118,7 @@ def main(): ) ) - keypair = module.params.get('keypair') + key_name = module.params.get('key_name') group = module.params.get('group') instance_type = module.params.get('instance_type') image = module.params.get('image') @@ -138,29 +131,34 @@ def main(): ec2_access_key = module.params.get('ec2_access_key') user_data = module.params.get('user_data') - if ec2_url: - os.environ['EC2_URL'] = ec2_url - if ec2_secret_key: - os.environ['EC2_SECRET_KEY'] = ec2_secret_key - if ec2_access_key: - os.environ['EC2_ACCESS_KEY'] = ec2_access_key + # allow eucarc environment variables to be used if ansible vars aren't set + if not ec2_url and 'EC2_URL' in os.environ: + ec2_url = os.environ['EC2_URL'] + if not ec2_secret_key and 'EC2_SECRET_KEY' in os.environ: + ec2_secret_key = os.environ['EC2_SECRET_KEY'] + if not ec2_access_key and 'EC2_ACCESS_KEY' in os.environ: + ec2_access_key = os.environ['EC2_ACCESS_KEY'] + if ec2_url: # if we have an URL set, assume Eucalyptus + url = urlparse(ec2_url) + ec2 = boto.connect_euca(host = url.netloc.split(":")[0], + aws_access_key_id = ec2_access_key, + aws_secret_access_key = ec2_secret_key, + port = url.port, + path = url.path) + else: # otherwise it's Amazon. + ec2 = boto.connect_ec2() - # yes I recognize how hacky this is - but it is easier than rewriting - # all the try/except's myself. - sys.argv.append(image) - eri = euca2ools.commands.euca.runinstances.RunInstances() - conn = eri.make_connection() - res = eri.make_request_cli(conn, 'run_instances', - image_id=image, - min_count=1, - max_count=1, - key_name=keypair, - security_groups=[group], - instance_type=instance_type, - kernel_id=kernel, - ramdisk_id=ramdisk, - user_data=user_data) + try: + res = ec2.run_instances(image, key_name = key_name, + min_count = 1, max_count = 1, + security_groups = [group], + instance_type = instance_type, + kernel_id = kernel, + ramdisk_id = ramdisk, + user_data = user_data) + except boto.exception.EC2ResponseError as e: + module.fail_json(msg = "%s: %s" % (e.error_code, e.error_message)) instids = [ i.id for i in res.instances ]