PageRenderTime 22ms CodeModel.GetById 9ms app.highlight 8ms RepoModel.GetById 1ms app.codeStats 1ms

/boto-2.5.2/boto/pyami/launch_ami.py

#
Python | 178 lines | 155 code | 1 blank | 22 comment | 0 complexity | 22d4571558c279f26f047cf0bc64cb50 MD5 | raw file
  1#!/usr/bin/env python
  2# Copyright (c) 2006,2007 Mitch Garnaat http://garnaat.org/
  3#
  4# Permission is hereby granted, free of charge, to any person obtaining a
  5# copy of this software and associated documentation files (the
  6# "Software"), to deal in the Software without restriction, including
  7# without limitation the rights to use, copy, modify, merge, publish, dis-
  8# tribute, sublicense, and/or sell copies of the Software, and to permit
  9# persons to whom the Software is furnished to do so, subject to the fol-
 10# lowing conditions:
 11#
 12# The above copyright notice and this permission notice shall be included
 13# in all copies or substantial portions of the Software.
 14#
 15# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 16# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
 17# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
 18# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
 19# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 20# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 21# IN THE SOFTWARE.
 22#
 23import getopt
 24import sys
 25import imp
 26import time
 27import boto
 28
 29usage_string = """
 30SYNOPSIS
 31    launch_ami.py -a ami_id [-b script_bucket] [-s script_name]
 32                  [-m module] [-c class_name] [-r] 
 33                  [-g group] [-k key_name] [-n num_instances]
 34                  [-w] [extra_data]
 35    Where:
 36        ami_id - the id of the AMI you wish to launch
 37        module - The name of the Python module containing the class you
 38                 want to run when the instance is started.  If you use this
 39                 option the Python module must already be stored on the
 40                 instance in a location that is on the Python path.
 41        script_file - The name of a local Python module that you would like
 42                      to have copied to S3 and then run on the instance
 43                      when it is started.  The specified module must be
 44                      import'able (i.e. in your local Python path).  It
 45                      will then be copied to the specified bucket in S3
 46                      (see the -b option).  Once the new instance(s)
 47                      start up the script will be copied from S3 and then
 48                      run locally on the instance.
 49        class_name - The name of the class to be instantiated within the
 50                     module or script file specified.
 51        script_bucket - the name of the bucket in which the script will be
 52                        stored
 53        group - the name of the security group the instance will run in
 54        key_name - the name of the keypair to use when launching the AMI
 55        num_instances - how many instances of the AMI to launch (default 1)
 56        input_queue_name - Name of SQS to read input messages from
 57        output_queue_name - Name of SQS to write output messages to
 58        extra_data - additional name-value pairs that will be passed as
 59                     userdata to the newly launched instance.  These should
 60                     be of the form "name=value"
 61        The -r option reloads the Python module to S3 without launching
 62        another instance.  This can be useful during debugging to allow
 63        you to test a new version of your script without shutting down
 64        your instance and starting up another one.
 65        The -w option tells the script to run synchronously, meaning to
 66        wait until the instance is actually up and running.  It then prints
 67        the IP address and internal and external DNS names before exiting.
 68"""
 69
 70def usage():
 71    print usage_string
 72    sys.exit()
 73
 74def main():
 75    try:
 76        opts, args = getopt.getopt(sys.argv[1:], 'a:b:c:g:hi:k:m:n:o:rs:w',
 77                                   ['ami', 'bucket', 'class', 'group', 'help',
 78                                    'inputqueue', 'keypair', 'module',
 79                                    'numinstances', 'outputqueue',
 80                                    'reload', 'script_name', 'wait'])
 81    except:
 82        usage()
 83    params = {'module_name' : None,
 84              'script_name' : None,
 85              'class_name' : None,
 86              'script_bucket' : None,
 87              'group' : 'default',
 88              'keypair' : None,
 89              'ami' : None,
 90              'num_instances' : 1,
 91              'input_queue_name' : None,
 92              'output_queue_name' : None}
 93    reload = None
 94    wait = None
 95    for o, a in opts:
 96        if o in ('-a', '--ami'):
 97            params['ami'] = a
 98        if o in ('-b', '--bucket'):
 99            params['script_bucket'] = a
100        if o in ('-c', '--class'):
101            params['class_name'] = a
102        if o in ('-g', '--group'):
103            params['group'] = a
104        if o in ('-h', '--help'):
105            usage()
106        if o in ('-i', '--inputqueue'):
107            params['input_queue_name'] = a
108        if o in ('-k', '--keypair'):
109            params['keypair'] = a
110        if o in ('-m', '--module'):
111            params['module_name'] = a
112        if o in ('-n', '--num_instances'):
113            params['num_instances'] = int(a)
114        if o in ('-o', '--outputqueue'):
115            params['output_queue_name'] = a
116        if o in ('-r', '--reload'):
117            reload = True
118        if o in ('-s', '--script'):
119            params['script_name'] = a
120        if o in ('-w', '--wait'):
121            wait = True
122
123    # check required fields
124    required = ['ami']
125    for pname in required:
126        if not params.get(pname, None):
127            print '%s is required' % pname
128            usage()
129    if params['script_name']:
130        # first copy the desired module file to S3 bucket
131        if reload:
132            print 'Reloading module %s to S3' % params['script_name']
133        else:
134            print 'Copying module %s to S3' % params['script_name']
135        l = imp.find_module(params['script_name'])
136        c = boto.connect_s3()
137        bucket = c.get_bucket(params['script_bucket'])
138        key = bucket.new_key(params['script_name']+'.py')
139        key.set_contents_from_file(l[0])
140        params['script_md5'] = key.md5
141    # we have everything we need, now build userdata string
142    l = []
143    for k, v in params.items():
144        if v:
145            l.append('%s=%s' % (k, v))
146    c = boto.connect_ec2()
147    l.append('aws_access_key_id=%s' % c.aws_access_key_id)
148    l.append('aws_secret_access_key=%s' % c.aws_secret_access_key)
149    for kv in args:
150        l.append(kv)
151    s = '|'.join(l)
152    if not reload:
153        rs = c.get_all_images([params['ami']])
154        img = rs[0]
155        r = img.run(user_data=s, key_name=params['keypair'],
156                    security_groups=[params['group']],
157                    max_count=params.get('num_instances', 1))
158        print 'AMI: %s - %s (Started)' % (params['ami'], img.location)
159        print 'Reservation %s contains the following instances:' % r.id
160        for i in r.instances:
161            print '\t%s' % i.id
162        if wait:
163            running = False
164            while not running:
165                time.sleep(30)
166                [i.update() for i in r.instances]
167                status = [i.state for i in r.instances]
168                print status
169                if status.count('running') == len(r.instances):
170                    running = True
171            for i in r.instances:
172                print 'Instance: %s' % i.ami_launch_index
173                print 'Public DNS Name: %s' % i.public_dns_name
174                print 'Private DNS Name: %s' % i.private_dns_name
175
176if __name__ == "__main__":
177    main()
178