ec2_ami_search 6.03 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
#!/usr/bin/python
#
# (c) 2013, Nimbis Services
#
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible.  If not, see <http://www.gnu.org/licenses/>.
DOCUMENTATION = '''
---
21 22
module: ec2_ami_search
short_description: Retrieve AWS AMI for a given operating system.
23
version_added: "1.6"
24
description:
25
  - Look up the most recent AMI on AWS for a given operating system.
26 27
  - Returns C(ami), C(aki), C(ari), C(serial), C(tag)
  - If there is no AKI or ARI associated with an image, these will be C(null).
28
  - Only supports images from cloud-images.ubuntu.com
29 30
  - 'Example output: C({"ami": "ami-69f5a900", "changed": false, "aki": "aki-88aa75e1", "tag": "release", "ari": null, "serial": "20131024"})'
version_added: "1.6"
31
options:
32 33 34 35
  distro:
    description: Linux distribution (e.g., C(ubuntu))
    required: true
    choices: ["ubuntu"]
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
  release:
    description: short name of the release (e.g., C(precise))
    required: true
  stream:
    description: Type of release.
    required: false
    default: "server"
    choices: ["server", "desktop"]
  store:
    description: Back-end store for instance
    required: false
    default: "ebs"
    choices: ["ebs", "instance-store"]
  arch:
    description: CPU architecture
    required: false
    default: "amd64"
    choices: ["i386", "amd64"]
  region:
    description: EC2 region
    required: false
    default: us-east-1
    choices: ["ap-northeast-1", "ap-southeast-1", "ap-southeast-2",
              "eu-west-1", "sa-east-1", "us-east-1", "us-west-1", "us-west-2"]
  virt:
    description: virutalization type
    required: false
    default: paravirtual
    choices: ["paravirtual", "hvm"]

author: Lorin Hochstein
'''

EXAMPLES = '''
follower committed
70
- name: Launch an Ubuntu 12.04 (Precise Pangolin) EC2 instance
71 72 73 74
  hosts: 127.0.0.1
  connection: local
  tasks:
  - name: Get the Ubuntu precise AMI
75
    ec2_ami_search: distro=ubuntu release=precise region=us-west-1 store=instance-store
76 77 78 79 80 81 82 83 84 85
    register: ubuntu_image
  - name: Start the EC2 instance
    ec2: image={{ ubuntu_image.ami }} instance_type=m1.small key_name=mykey
'''

import csv
import json
import urllib2
import urlparse

86 87
SUPPORTED_DISTROS = ['ubuntu']

88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
AWS_REGIONS = ['ap-northeast-1',
               'ap-southeast-1',
               'ap-southeast-2',
               'eu-west-1',
               'sa-east-1',
               'us-east-1',
               'us-west-1',
               'us-west-2']


def get_url(module, url):
    """ Get url and return response """
    try:
        r = urllib2.urlopen(url)
    except (urllib2.HTTPError, urllib2.URLError), e:
        code = getattr(e, 'code', -1)
        module.fail_json(msg="Request failed: %s" % str(e), status_code=code)
    return r


108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
def ubuntu(module):
    """ Get the ami for ubuntu """

    release = module.params['release']
    stream = module.params['stream']
    store = module.params['store']
    arch = module.params['arch']
    region = module.params['region']
    virt = module.params['virt']

    url = get_ubuntu_url(release, stream)

    req = get_url(module, url)
    reader = csv.reader(req, delimiter='\t')
    try:
        ami, aki, ari, tag, serial = lookup_ubuntu_ami(reader, release, stream,
            store, arch, region, virt)
        module.exit_json(changed=False, ami=ami, aki=aki, ari=ari, tag=tag,
            serial=serial)
    except KeyError:
        module.fail_json(msg="No matching AMI found")


def lookup_ubuntu_ami(table, release, stream, store, arch, region, virt):
    """ Look up the Ubuntu AMI that matches query given a table of AMIs
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169

        table: an iterable that returns a row of
               (release, stream, tag, serial, region, ami, aki, ari, virt)
        release: ubuntu release name
        stream: 'server' or 'desktop'
        store: 'ebs' or 'instance-store'
        arch: 'i386' or 'amd64'
        region: EC2 region
        virt: 'paravirtual' or 'hvm'

        Returns (ami, aki, ari, tag, serial)"""
    expected = (release, stream, store, arch, region, virt)

    for row in table:
        (actual_release, actual_stream, tag, serial,
            actual_store, actual_arch, actual_region, ami, aki, ari,
            actual_virt) = row
        actual = (actual_release, actual_stream, actual_store, actual_arch,
            actual_region, actual_virt)
        if actual == expected:
            # aki and ari are sometimes blank
            if aki == '':
                aki = None
            if ari == '':
                ari = None
            return (ami, aki, ari, tag, serial)

    raise KeyError()


def get_ubuntu_url(release, stream):
    url = "https://cloud-images.ubuntu.com/query/%s/%s/released.current.txt"
    return url % (release, stream)


def main():
    arg_spec = dict(
170
        distro=dict(required=True, choices=SUPPORTED_DISTROS),
171 172 173 174 175 176 177 178 179 180 181 182
        release=dict(required=True),
        stream=dict(required=False, default='server',
            choices=['desktop', 'server']),
        store=dict(required=False, default='ebs',
            choices=['ebs', 'instance-store']),
        arch=dict(required=False, default='amd64',
            choices=['i386', 'amd64']),
        region=dict(required=False, default='us-east-1', choices=AWS_REGIONS),
        virt=dict(required=False, default='paravirtual',
            choices=['paravirtual', 'hvm'])
    )
    module = AnsibleModule(argument_spec=arg_spec)
183
    distro = module.params['distro']
184

185 186 187 188
    if distro == 'ubuntu':
        ubuntu(module)
    else:
        module.fail_json(msg="Unsupported distro: %s" % distro)
189 190 191 192 193 194 195 196



# this is magic, see lib/ansible/module_common.py
#<<INCLUDE_ANSIBLE_MODULE_COMMON>>

if __name__ == '__main__':
    main()