PageRenderTime 45ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/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. #
  23. import getopt
  24. import sys
  25. import imp
  26. import time
  27. import boto
  28. usage_string = """
  29. SYNOPSIS
  30. launch_ami.py -a ami_id [-b script_bucket] [-s script_name]
  31. [-m module] [-c class_name] [-r]
  32. [-g group] [-k key_name] [-n num_instances]
  33. [-w] [extra_data]
  34. Where:
  35. ami_id - the id of the AMI you wish to launch
  36. module - The name of the Python module containing the class you
  37. want to run when the instance is started. If you use this
  38. option the Python module must already be stored on the
  39. instance in a location that is on the Python path.
  40. script_file - The name of a local Python module that you would like
  41. to have copied to S3 and then run on the instance
  42. when it is started. The specified module must be
  43. import'able (i.e. in your local Python path). It
  44. will then be copied to the specified bucket in S3
  45. (see the -b option). Once the new instance(s)
  46. start up the script will be copied from S3 and then
  47. run locally on the instance.
  48. class_name - The name of the class to be instantiated within the
  49. module or script file specified.
  50. script_bucket - the name of the bucket in which the script will be
  51. stored
  52. group - the name of the security group the instance will run in
  53. key_name - the name of the keypair to use when launching the AMI
  54. num_instances - how many instances of the AMI to launch (default 1)
  55. input_queue_name - Name of SQS to read input messages from
  56. output_queue_name - Name of SQS to write output messages to
  57. extra_data - additional name-value pairs that will be passed as
  58. userdata to the newly launched instance. These should
  59. be of the form "name=value"
  60. The -r option reloads the Python module to S3 without launching
  61. another instance. This can be useful during debugging to allow
  62. you to test a new version of your script without shutting down
  63. your instance and starting up another one.
  64. The -w option tells the script to run synchronously, meaning to
  65. wait until the instance is actually up and running. It then prints
  66. the IP address and internal and external DNS names before exiting.
  67. """
  68. def usage():
  69. print usage_string
  70. sys.exit()
  71. def main():
  72. try:
  73. opts, args = getopt.getopt(sys.argv[1:], 'a:b:c:g:hi:k:m:n:o:rs:w',
  74. ['ami', 'bucket', 'class', 'group', 'help',
  75. 'inputqueue', 'keypair', 'module',
  76. 'numinstances', 'outputqueue',
  77. 'reload', 'script_name', 'wait'])
  78. except:
  79. usage()
  80. params = {'module_name' : None,
  81. 'script_name' : None,
  82. 'class_name' : None,
  83. 'script_bucket' : None,
  84. 'group' : 'default',
  85. 'keypair' : None,
  86. 'ami' : None,
  87. 'num_instances' : 1,
  88. 'input_queue_name' : None,
  89. 'output_queue_name' : None}
  90. reload = None
  91. wait = None
  92. for o, a in opts:
  93. if o in ('-a', '--ami'):
  94. params['ami'] = a
  95. if o in ('-b', '--bucket'):
  96. params['script_bucket'] = a
  97. if o in ('-c', '--class'):
  98. params['class_name'] = a
  99. if o in ('-g', '--group'):
  100. params['group'] = a
  101. if o in ('-h', '--help'):
  102. usage()
  103. if o in ('-i', '--inputqueue'):
  104. params['input_queue_name'] = a
  105. if o in ('-k', '--keypair'):
  106. params['keypair'] = a
  107. if o in ('-m', '--module'):
  108. params['module_name'] = a
  109. if o in ('-n', '--num_instances'):
  110. params['num_instances'] = int(a)
  111. if o in ('-o', '--outputqueue'):
  112. params['output_queue_name'] = a
  113. if o in ('-r', '--reload'):
  114. reload = True
  115. if o in ('-s', '--script'):
  116. params['script_name'] = a
  117. if o in ('-w', '--wait'):
  118. wait = True
  119. # check required fields
  120. required = ['ami']
  121. for pname in required:
  122. if not params.get(pname, None):
  123. print '%s is required' % pname
  124. usage()
  125. if params['script_name']:
  126. # first copy the desired module file to S3 bucket
  127. if reload:
  128. print 'Reloading module %s to S3' % params['script_name']
  129. else:
  130. print 'Copying module %s to S3' % params['script_name']
  131. l = imp.find_module(params['script_name'])
  132. c = boto.connect_s3()
  133. bucket = c.get_bucket(params['script_bucket'])
  134. key = bucket.new_key(params['script_name']+'.py')
  135. key.set_contents_from_file(l[0])
  136. params['script_md5'] = key.md5
  137. # we have everything we need, now build userdata string
  138. l = []
  139. for k, v in params.items():
  140. if v:
  141. l.append('%s=%s' % (k, v))
  142. c = boto.connect_ec2()
  143. l.append('aws_access_key_id=%s' % c.aws_access_key_id)
  144. l.append('aws_secret_access_key=%s' % c.aws_secret_access_key)
  145. for kv in args:
  146. l.append(kv)
  147. s = '|'.join(l)
  148. if not reload:
  149. rs = c.get_all_images([params['ami']])
  150. img = rs[0]
  151. r = img.run(user_data=s, key_name=params['keypair'],
  152. security_groups=[params['group']],
  153. max_count=params.get('num_instances', 1))
  154. print 'AMI: %s - %s (Started)' % (params['ami'], img.location)
  155. print 'Reservation %s contains the following instances:' % r.id
  156. for i in r.instances:
  157. print '\t%s' % i.id
  158. if wait:
  159. running = False
  160. while not running:
  161. time.sleep(30)
  162. [i.update() for i in r.instances]
  163. status = [i.state for i in r.instances]
  164. print status
  165. if status.count('running') == len(r.instances):
  166. running = True
  167. for i in r.instances:
  168. print 'Instance: %s' % i.ami_launch_index
  169. print 'Public DNS Name: %s' % i.public_dns_name
  170. print 'Private DNS Name: %s' % i.private_dns_name
  171. if __name__ == "__main__":
  172. main()