[pkg-eucalyptus-commits] [SCM] managing cloud instances for Eucalyptus branch, master, updated. 3.0.0-alpha3-257-g1da8e3a

Garrett Holmstrom gholms at fedoraproject.org
Sun Jun 16 02:29:57 UTC 2013


The following commit has been merged in the master branch:
commit a629896e58b3e9c5726f92659d34f104008a4cf4
Merge: f5745102324e9bf91aeb4849c8c6254eeacad844 97495528e6f5b345ffff9e9030e56ec4472a7143
Author: Garrett Holmstrom <gholms at fedoraproject.org>
Date:   Sat Nov 3 21:14:35 2012 -0700

    Merge branch 'master' into requestbuilder
    
    Conflicts:
    	euca2ools/__init__.py
    	euca2ools/commands/euca/createkeypair.py
    	euca2ools/commands/euca/describeaddresses.py
    	euca2ools/commands/euca/describeimageattribute.py
    	euca2ools/commands/euca/describeimages.py
    	euca2ools/commands/euca/describeinstances.py
    	euca2ools/commands/euca/getpassword.py
    	euca2ools/commands/euca/register.py
    	setup.py

diff --combined euca2ools/commands/bundle/bundleimage.py
index 0408ecf,7b278ac..7b278ac
--- a/euca2ools/commands/bundle/bundleimage.py
+++ b/euca2ools/commands/bundle/bundleimage.py
@@@ -34,6 -34,7 +34,7 @@@ import euca2ools.commands.eucacomman
  from boto.roboto.param import Param
  import euca2ools.bundler
  from euca2ools.exceptions import NotFoundError, CommandFailed
+ import sys
  
  class BundleImage(euca2ools.commands.eucacommand.EucaCommand):
  
@@@ -81,7 -82,7 +82,7 @@@
                 Param(name='target_arch',
                       short_name='r', long_name='arch',
                       optional=True, ptype='string', default='x86_64',
-                      choices=['i386', 'x86_64'],
+                      choices=['i386', 'x86_64', 'armhf'],
                       doc='Target architecture for the image.'),
                 Param(name='batch', long_name='batch',
                       optional=True, ptype='boolean',
@@@ -89,13 -90,12 +90,12 @@@
  
      def get_block_devs(self):
          mapping_str = self.block_device_mapping
-         mapping = []
+         mapping = {}
          mapping_pairs = mapping_str.split(',')
          for m in mapping_pairs:
              m_parts = m.split('=')
              if len(m_parts) > 1:
-                 mapping.append(m_parts[0])
-                 mapping.append(m_parts[1])
+                 mapping[m_parts[0]] = m_parts[1]
          return mapping
  
      def add_product_codes(self):
diff --combined euca2ools/commands/bundle/bundleupload.py
index f6b0e16,d9c0a5c..fe5c85f
--- a/euca2ools/commands/bundle/bundleupload.py
+++ b/euca2ools/commands/bundle/bundleupload.py
@@@ -36,8 -36,8 +36,8 @@@ import o
  import euca2ools.commands.eucacommand
  from boto.roboto.param import Param
  from boto.exception import S3ResponseError, S3CreateError
 -from euca2ools.commands.euca.uploadbundle import UploadBundle
 -from euca2ools.commands.euca.bundleimage import BundleImage
 +from euca2ools.commands.bundle.uploadbundle import UploadBundle
 +from euca2ools.commands.bundle.bundleimage import BundleImage
  import euca2ools.bundler
  from euca2ools.exceptions import NotFoundError, CommandFailed
  
@@@ -86,7 -86,7 +86,7 @@@ class BundleUpload(UploadBundle, Bundle
                 Param(name='target_arch',
                       short_name='r', long_name='arch',
                       optional=True, ptype='string', default='x86_64',
-                      choices=['i386', 'x86_64'],
+                      choices=['i386', 'x86_64', 'armhf'],
                       doc='Target architecture for the image.'),
                 Param(name='acl', long_name='acl',
                       optional=True, ptype='string', default='ec2-bundle-read',
diff --combined euca2ools/commands/bundle/bundlevol.py
index cfc1873,f6452d0..f6452d0
--- a/euca2ools/commands/bundle/bundlevol.py
+++ b/euca2ools/commands/bundle/bundlevol.py
@@@ -40,14 -40,15 +40,15 @@@ import euca2ools.bundle
  import euca2ools.metadata
  from euca2ools.exceptions import *
  
- MAX_IMAGE_SIZE = 1024 * 10
+ IMAGE_MAX_SIZE_IN_MB = euca2ools.bundler.IMAGE_MAX_SIZE / 1024 // 1024
  
  class BundleVol(euca2ools.commands.eucacommand.EucaCommand):
- 
      Description = 'Bundles an image for use with Eucalyptus or Amazon EC2.'
      Options = [Param(name='size', short_name='s', long_name='size',
-                      optional=True, ptype='integer', default=MAX_IMAGE_SIZE,
-                      doc='Size of the image in MB(max=%d).' % MAX_IMAGE_SIZE),
+                      optional=True, ptype='integer',
+                      default=IMAGE_MAX_SIZE_IN_MB,
+                      doc=('Size of the image in MB (default: {0}; recommended '
+                           'maximum: {0})').format(IMAGE_MAX_SIZE_IN_MB)),
                 Param(name='user', short_name='u', long_name='user',
                       optional=True, ptype='string',
                       doc="""User ID (12-digit) of the user who is
@@@ -98,7 -99,7 +99,7 @@@
                 Param(name='target_architecture',
                       short_name='r', long_name='arch',
                       optional=True, ptype='string', default='x86_64',
-                      choices=['i386', 'x86_64'],
+                      choices=['i386', 'x86_64', 'armhf'],
                       doc='Target architecture for the image'),
                 Param(name='volume_path', long_name='volume',
                       optional=True, ptype='dir', default='/',
@@@ -120,11 -121,6 +121,6 @@@
              print 'Must be superuser to execute this command.'
              sys.exit()
  
-     def check_image_size(self, size):
-         if size > MAX_IMAGE_SIZE:
-             msg = 'Image Size is too large (Max = %d MB)' % MAX_IMAGE_SIZE
-             self.display_error_and_exit(msg)
- 
      def parse_excludes(self, excludes_string):
          excludes = []
          if excludes_string:
@@@ -175,7 -171,7 +171,7 @@@
                  ancestor_ami_ids)
  
  
-     def add_product_codes(self, product_code_string, product_codes):
+     def add_product_codes(self, product_code_string, product_codes=None):
          if not product_codes:
              product_codes = []
          product_code_values = product_code_string.split(',')
@@@ -225,9 -221,6 +221,6 @@@
              else:
                  self.fstab_path = 'new'
          self.check_root()
-         if self.size > MAX_IMAGE_SIZE:
-             msg = 'Image Size is too large (Max = %d MB)' % MAX_IMAGE_SIZE
-             self.display_error_and_exit(msg)
          self.volume_path = os.path.normpath(self.volume_path)
  
          noex='EUCA_BUNDLE_VOL_EMPTY_EXCLUDES'
@@@ -245,7 -238,7 +238,7 @@@
               ancestor_ami_ids) = self.get_instance_metadata(self.ramdisk_id,
                                                              self.kernel_id,
                                                              self.block_device_mapping)
-         if self.product_codes:
+         if self.product_codes and isinstance(self.product_codes, basestring):
              self.product_codes = self.add_product_codes(self.product_codes)
  
          try:
diff --combined euca2ools/commands/bundle/deletebundle.py
index 56c1c1b,5f6201b..5f6201b
--- a/euca2ools/commands/bundle/deletebundle.py
+++ b/euca2ools/commands/bundle/deletebundle.py
@@@ -36,6 -36,7 +36,7 @@@ from boto.roboto.param import Para
  import os
  import sys
  import textwrap
+ import time
  from xml.dom import minidom
  from boto.exception import S3ResponseError, S3CreateError
  from boto.s3.key import Key
@@@ -178,8 -179,15 +179,15 @@@ class DeleteBundle(euca2ools.commands.e
          directory = os.path.abspath('/tmp')
  
          if not self.manifest_path and not self.prefix:
-             print 'Neither manifestpath nor prefix was specified.'
-             print 'All manifest data in bucket will be deleted.'
+             print 'Neither a manifestpath nor a prefix was specified.'
+             print 'All bundles in bucket', self.bucket, 'will be deleted.'
+             print ('If this is not what you want, press Ctrl+C in the next '
+                    '10 seconds'),
+             for __ in range(10):
+                 sys.stdout.write('.')
+                 sys.stdout.flush()
+                 time.sleep(1)
+             print
  
          bucket_instance = self.ensure_bucket(self.bucket)
          manifests = None
diff --combined euca2ools/commands/euca/createkeypair.py
index 668b967,ec98b22..d5e5335
--- a/euca2ools/commands/euca/createkeypair.py
+++ b/euca2ools/commands/euca/createkeypair.py
@@@ -1,6 -1,6 +1,6 @@@
  # Software License Agreement (BSD License)
  #
 -# Copyright (c) 2009-2011, Eucalyptus Systems, Inc.
 +# Copyright (c) 2009-2012, Eucalyptus Systems, Inc.
  # All rights reserved.
  #
  # Redistribution and use of this software in source and binary forms, with or
@@@ -27,15 -27,50 +27,24 @@@
  # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  # POSSIBILITY OF SUCH DAMAGE.
 -#
 -# Author: Neil Soman neil at eucalyptus.com
 -#         Mitch Garnaat mgarnaat at eucalyptus.com
 -
 -import euca2ools.commands.eucacommand
 -from boto.roboto.param import Param
 -from os import chmod
 -from stat import *
 -
 -class CreateKeyPair(euca2ools.commands.eucacommand.EucaCommand):
 -
 -    Description = 'Creates a new key pair for use with instances'
 -    Options = [Param(name='filename', short_name='f',
 -                  long_name='filename', ptype='string',
 -                  doc='Filename to save the private key to. Default ' +
 -                  'action is to overwite the file.',
 -                  optional=True)]
 -
 -    Args = [Param(name='keypair_name', ptype='string',
 -                  doc='unique name for a keypair to be created',
 -                  cardinality=1, optional=False)]
 -
 -    def display_fingerprint(self, keypair):
 -        print 'KEYPAIR\t%s\t%s' % (keypair.name, keypair.fingerprint)
 -
 -    def display_keypair(self, keypair):
 -        print keypair.material
 -
 -    def save_keypair_to_file(self, keypair):
 -        keyfile = open(self.filename, 'w')
 -        keyfile.write(keypair.material)
 -        keyfile.close()
 -
 -        chmod(self.filename, S_IRUSR|S_IWUSR)
 -
 -    def main(self):
 -        conn = self.make_connection_cli()
 -        return self.make_request_cli(conn, 'create_key_pair',
 -                                     key_name=self.keypair_name)
  
 -    def main_cli(self):
 -        keypair = self.main()
 -        self.display_fingerprint(keypair)
 -        if self.filename != None:
 -            self.save_keypair_to_file(keypair)
++import os
 +from requestbuilder import Arg
 +from . import EucalyptusRequest
 +
 +class CreateKeyPair(EucalyptusRequest):
 +    Description = 'Create a new SSH key pair for use with instances'
-     Args = [Arg('KeyName', metavar='KEYPAIR', help='name of the new key pair')]
++    Args = [Arg('KeyName', metavar='KEYPAIR', help='name of the new key pair'),
++            Arg('-f', '--filename', metavar='FILE', route_to=None,
++                help='file name to save the private key to')]
 +
 +    def print_result(self, result):
 +        print self.tabify(('KEYPAIR', result['keyName'],
 +                           result['keyFingerprint']))
-         print result['keyMaterial']
++        if self.args.get('filename'):
++            prev_umask = os.umask(0o077)
++            with open(self.args['filename'], 'w') as privkeyfile:
++                privkeyfile.write(result['keyMaterial'])
++            os.umask(prev_umask)
+         else:
 -            self.display_keypair(keypair)
++            print result['keyMaterial']
diff --combined euca2ools/commands/euca/describeimages.py
index de68717,c421e90..2d7970c
--- a/euca2ools/commands/euca/describeimages.py
+++ b/euca2ools/commands/euca/describeimages.py
@@@ -1,6 -1,6 +1,6 @@@
  # Software License Agreement (BSD License)
  #
 -# Copyright (c) 2009-2011, Eucalyptus Systems, Inc.
 +# Copyright (c) 2009-2012, Eucalyptus Systems, Inc.
  # All rights reserved.
  #
  # Redistribution and use of this software in source and binary forms, with or
@@@ -27,122 -27,159 +27,122 @@@
  # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  # POSSIBILITY OF SUCH DAMAGE.
 -#
 -# Author: Neil Soman neil at eucalyptus.com
 -#         Mitch Garnaat mgarnaat at eucalyptus.com
 -
 -import euca2ools.commands.eucacommand
 -from boto.roboto.param import Param
  
 -class DescribeImages(euca2ools.commands.eucacommand.EucaCommand):
 -
 -    APIVersion = '2010-08-31'
 -    Description = 'Shows information about machine images.'
 -    Options = [Param(name='all', short_name='a', long_name='all',
 -                     optional=True, ptype='boolean', default=False,
 -                     doc='Show all images that the user has access to.'),
 -               Param(name='owner', short_name='o', long_name='owner',
 -                     optional=True, ptype='string', cardinality='*',
 -                     doc="""Show only images owned by the user.
 -                            Valid values: account ID|self|amazon"""),
 -               Param(name='executable_by',
 -                     short_name='x', long_name='executable-by',
 -                     optional=True, ptype='string', cardinality='*',
 -                     doc="""Show only images for which user has
 -                     explicit launch permissions.
 -                     Valid values: account ID|self|all""")]
 -    Args = [Param(name='image', ptype='string',
 -                  cardinality='+', optional=True)]
 -    Filters = [Param(name='architecture', ptype='string',
 -                     doc='Image architecture.  Valid values are i386 | x86_64 | armhf'),
 -               Param(name='block-device-mapping.delete-on-termination',
 -                     ptype='boolean',
 -                     doc="""Whether the Amazon EBS volume is deleted on
 -                     instance termination."""),
 -               Param(name='block-device-mapping.device-name', ptype='string',
 -                     doc="""Device name (e.g., /dev/sdh) for an Amazon EBS volume
 -                     mapped to the image."""),
 -               Param(name='block-device-mapping.snapshot-id', ptype='string',
 -                     doc="""Snapshot ID for an Amazon EBS volume mapped
 -                     to the image."""),
 -               Param(name='block-device-mapping.volume-size', ptype='integer',
 -                     doc="""Volume size for an Amazon EBS volume mapped
 -                     to the image."""),
 -               Param(name='description', ptype='string',
 -                     doc='Description of the AMI'),
 -               Param(name='hypervisor', ptype='string',
 -                     doc="""Hypervisor type of the image.
 -                     Valid values are ovm | xen."""),
 -               Param(name='image-id', ptype='string',
 -                     doc='ID of the imageID'),
 -               Param(name='image-type', ptype='string',
 -                     doc="""Type of the image.
 -                     Valid values are machine | kernel | ramdisk"""),
 -               Param(name='is-public', ptype='boolean',
 -                     doc='Whether the image is public.'),
 -               Param(name='kernel-id', ptype='string',
 -                     doc='Kernel ID.'),
 -               Param(name='manifest-location', ptype='string',
 -                     doc='Location of the image manifest.'),
 -               Param(name='name', ptype='string',
 -                     doc='Name of the AMI.'),
 -               Param(name='owner-alias', ptype='string',
 -                     doc="""AWS account alias (e.g., amazon or self) or
 -                     AWS account ID that owns the AMI."""),
 -               Param(name='owner-id', ptype='string',
 -                     doc='AWS account ID of the image owner.'),
 -               Param(name='platform', ptype='string',
 -                     doc="""Use windows if you have Windows based AMIs;
 -                     otherwise leave blank."""),
 -               Param(name='product-code', ptype='string',
 -                     doc='Product code associated with the AMI.'),
 -               Param(name='ramdisk-id', ptype='string',
 -                     doc='The ramdisk ID.'),
 -               Param(name='root-device-name', ptype='string',
 -                     doc='Root device name of the AMI (e.g., /dev/sda1).'),
 -               Param(name='root-device-type', ptype='string',
 -                     doc="""Root device type the AMI uses.
 -                     Valid Values: ebs | instance-store."""),
 -               Param(name='state', ptype='string',
 -                     doc="""State of the image.
 -                     Valid values: available | pending | failed."""),
 -               Param(name='state-reason-code', ptype='string',
 -                     doc='Reason code for the state change.'),
 -               Param(name='state-reason-message', ptype='string',
 -                     doc='Message for the state change.'),
 -               Param(name='tag-key', ptype='string',
 -                     doc='Key of a tag assigned to the resource.'),
 -               Param(name='tag-value', ptype='string',
 -                     doc='Value of a tag assigned to the resource.'),
 -               Param(name='tag:key', ptype='string',
 -                     doc="""Filters the results based on a specific
 -                     tag/value combination."""),
 -               Param(name='virtualization-type', ptype='string',
 -                     doc="""Virtualization type of the image.
 -                     Valid values: paravirtual | hvm""")]
 -    
 -    def display_images(self, images):
 -        for image in images:
 -            image_string = '%s\t%s\t%s\t%s' % (image.id, image.location,
 -                    image.ownerId, image.state)
 -            if image.is_public:
 -                image_string += '\tpublic'
 -            else:
 -                image_string += '\tprivate'
 +from requestbuilder import Arg, Filter, GenericTagFilter
 +from . import EucalyptusRequest
  
 -            image_string += '\t%s' % ','.join(image.product_codes)
 +class DescribeImages(EucalyptusRequest):
 +    Description = '''\
 +        Show information about images
  
 -            for i in [image.architecture, image.type, image.kernel_id,
 -                      image.ramdisk_id, image.platform,
 -                      image.root_device_type]:
 -                image_string += '\t%s' % (('' if i == None else i))
 +        By default, only images the caller owns and images for which the caller
 +        has explicit launch permissions are shown.'''
  
 -            print 'IMAGE\t%s' % image_string
 -            if image.block_device_mapping:
 -                block_dev_mapping = image.block_device_mapping
 -                if image.root_device_type == 'ebs':
 -                    block_dev_string = '%s\t%s\t%s' \
 -                        % (block_dev_mapping.current_name,
 -                           block_dev_mapping.current_value.snapshot_id,
 -                           block_dev_mapping.current_value.size)
 -                    print 'BLOCKDEVICEMAPPING\t%s' % block_dev_string
 +    APIVersion = '2010-08-31'
 +    Args = [Arg('ImageId', metavar='IMAGE', nargs='*',
 +                help='limit results to one or more images'),
 +            Arg('-a', '--all', action='store_true', route_to=None,
 +                help='describe all images'),
 +            Arg('-o', '--owner', dest='Owner', metavar='ACCOUNT',
 +                action='append',
 +                help='describe images owned by the specified owner'),
 +            Arg('-x', '--executable-by', dest='ExecutableBy',
 +                metavar='ACCOUNT', action='append',
 +                help='''describe images for which the specified entity has
 +                        explicit launch permissions''')]
-     Filters = [Filter('architecture', choices=('i386', 'x86_64'),
++    Filters = [Filter('architecture', choices=('i386', 'x86_64', 'armhf'),
 +                      help='image architecture'),
 +               Filter('block-device-mapping.delete-on-termination',
 +                      help='''whether a volume is deleted upon instance
 +                              termination'''),
 +               Filter('block-device-mapping.device-name',
 +                      help='device name for a volume mapped to the image'),
 +               Filter('block-device-mapping.snapshot-id',
 +                      help='snapshot ID for a volume mapped to the image'),
 +               Filter('block-device-mapping.volume-size',
 +                      help='volume size for a volume mapped to the image'),
 +               Filter('description', help='image description'),
 +               Filter('image-id'),
 +               Filter('image-type', choices=('machine', 'kernel', 'ramdisk'),
 +                      help='image type ("machine", "kernel", or "ramdisk")'),
 +               Filter('is-public', help='whether the image is public'),
 +               Filter('kernel-id'),
 +               Filter('manifest-location'),
 +               Filter('name'),
 +               Filter('owner-alias', help="image owner's account alias"),
 +               Filter('owner-id', help="image owner's account ID"),
 +               Filter('platform', help='"windows" for Windows images'),
 +               Filter('product-code',
 +                      help='product code associated with the image'),
 +               Filter('product-code.type', choices=('devpay', 'marketplace'),
 +                      help='type of product code associated with the image'),
 +               Filter('ramdisk-id'),
 +               Filter('root-device-name'),
 +               Filter('root-device-type', choices=('ebs', 'instance-store'),
 +                      help='root device type ("ebs" or "instance-store")'),
 +               Filter('state', choices=('available', 'pending', 'failed'),
 +                      help='''image state ("available", "pending", or
 +                              "failed")'''),
 +               Filter('state-reason-code',
 +                      help='reason code for the most recent state change'),
 +               Filter('state-reason-message',
 +                      help='message for the most recent state change'),
 +               Filter('tag-key', help='key of a tag assigned to the image'),
 +               Filter('tag-value',
 +                      help='value of a tag assigned to the image'),
 +               GenericTagFilter('tag:KEY',
 +                                help='specific tag key/value combination'),
 +               Filter('virtualization-type', choices=('paravirtual', 'hvm'),
 +                      help='virtualization type ("paravirtual" or "hvm")'),
 +               Filter('hypervisor', choices=('ovm', 'xen'),
 +                      help='image\'s hypervisor type ("ovm" or "xen")')]
 +    ListDelims = ['imagesSet', 'blockDeviceMapping', 'tagSet']
  
      def main(self):
 -        if self.all and (self.owner or self.executable_by or self.image):
 -            msg = '-a cannot be combined with owner, launch, or image list'
 -            self.display_error_and_exit(msg)
 -
 -        # if you specify "-a" then it means return ALL images
 -        if self.all:
 -            self.executable_by = []
 -            self.owner = []
 -
 -        conn = self.make_connection_cli()
 -        if (self.executable_by or self.owner or self.image or self.all):
 -            images = self.make_request_cli(conn, 'get_all_images',
 -                                           image_ids=self.image,
 -                                           owners=self.owner,
 -                                           executable_by=self.executable_by)
 -        else:
 -            owned = self.make_request_cli(conn, 'get_all_images',
 -                image_ids = None, owners = ("self",), executable_by = None)
 -            launchable = self.make_request_cli(conn, 'get_all_images',
 -                image_ids = None, owners = None, executable_by = ("self"))
 +        if not any(self.args.get(item) for item in ('all', 'ImageId',
 +                                                    'ExecutableBy', 'Owner')):
 +            # Default to owned images and images with explicit launch perms
 +            self.params = {'Owner': 'self'}
 +            owned = self.send()
 +            self.params = {'ExecutableBy': 'self'}
 +            executable = self.send()
 +            self.params = None
 +            owned['imagesSet'] = (owned.get(     'imagesSet', []) +
 +                                  executable.get('imagesSet', []))
 +            return owned
 +        if self.args['all']:
 +            if self.args.get('ImageId'):
 +                self._cli_parser.error('argument -a/--all: not allowed with '
 +                                       'a list of images')
 +            if self.args.get('ExecutableBy'):
 +                self._cli_parser.error('argument -a/--all: not allowed with '
 +                                       'argument -x/--executable-by')
 +            if self.args.get('Owner'):
 +                self._cli_parser.error('argument -a/--all: not allowed with '
 +                                       'argument -o/--owner')
 +        return self.send()
  
 -            seen = { }
 -            images = [ ]
 -            for image in owned:
 -                seen[image.id] = True
 -                images.append(image)
 -            for image in launchable:
 -                if image.id not in seen:
 -                    images.append(image)
 +    def print_result(self, result):
 +        for image in result.get('imagesSet', []):
 +            self.print_image(image)
  
 -        return images
 +    def print_image(self, image):
 +        print self.tabify(('IMAGE', image.get('imageId'),
 +                image.get('imageLocation'),
 +                image.get('imageOwnerAlias') or image.get('imageOwnerId'),
 +                image.get('imageState'),
 +                ('public' if image.get('isPublic') == 'true' else 'private'),
 +                image.get('architecture'), image.get('imageType'),
 +                image.get('kernelId'), image.get('ramdiskId'),
 +                image.get('platform'), image.get('rootDeviceType'),
 +                image.get('virtualizationType'), image.get('hypervisor')))
 +        for mapping in image.get('blockDeviceMapping', []):
 +            self.print_blockdevice_mapping(mapping)
 +        for tag in image.get('tagSet', []):
 +            self.print_resource_tag(tag, image.get('imageId'))
  
 -    def main_cli(self):
 -        images = self.main()
 -        self.display_images(images)
 +    def print_blockdevice_mapping(self, mapping):
 +        print self.tabify(('BLOCKDEVICEMAPPING', mapping.get('deviceName'),
 +                           mapping.get('ebs', {}).get('snapshotId'),
 +                           mapping.get('ebs', {}).get('volumeSize'),
 +                           mapping.get('ebs', {}).get('deleteOnTermination')))
diff --combined euca2ools/commands/euca/getpassword.py
index bbd4522,66a90f9..960ca89
--- a/euca2ools/commands/euca/getpassword.py
+++ b/euca2ools/commands/euca/getpassword.py
@@@ -1,6 -1,6 +1,6 @@@
  # Software License Agreement (BSD License)
  #
 -# Copyright (c) 20092011, Eucalyptus Systems, Inc.
 +# Copyright (c) 2009-2012, Eucalyptus Systems, Inc.
  # All rights reserved.
  #
  # Redistribution and use of this software in source and binary forms, with or
@@@ -27,25 -27,47 +27,29 @@@
  # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  # POSSIBILITY OF SUCH DAMAGE.
 -#
 -# Author: Neil Soman neil at eucalyptus.com
 -#         Mitch Garnaat mgarnaat at eucalyptus.com
 -
 -import euca2ools.commands.eucacommand
 -import euca2ools.bundler
 -import sys
 -from boto.roboto.param import Param
  
 -class GetPassword(euca2ools.commands.eucacommand.EucaCommand):
 +import base64
 +from M2Crypto import RSA
 +from requestbuilder import Arg
 +from .argtypes import file_contents
 +from .getpassworddata import GetPasswordData
  
 -    Description = """Retrieves decrypts the administrator password
 -    for a Windows instance."""
 -    Options = [Param(name='privatekey',
 -                     short_name='k', long_name='priv-launch-key',
 -                     ptype='file', optional=False,
 -                     doc="""The file that contains the private key
 -                     used to launch the instance.""")]
 -    Args = [Param(name='instance_id', ptype='string', optional=False,
 -                     doc='unique identifier for the Windows instance')]
 +class GetPassword(GetPasswordData):
 +    Action = 'GetPasswordData'
 +    Description = '''Retrieve the administrator password for an instance
 +                     running Windows'''
 +    Args = [Arg('-k', '--priv-launch-key', metavar='PRIVKEY',
 +                type=file_contents, required=True, route_to=None,
 +                help='''file containing the private key corresponding to the
 +                        key pair supplied at instance launch time''')]
  
 -    def main(self):
 -        conn = self.make_connection_cli()
 +    def print_result(self, result):
-         pwdata   = result['passwordData']
+         try:
 -            pd = self.make_request_cli(conn, 'get_password_data',
 -                                       instance_id=self.instance_id)
++            pwdata = result['passwordData']
+         except AttributeError:
 -            # The reply didn't contain a passwordData element.  Boto doesn't
 -            # handle this since EC2 always includes one, even if it is empty.
 -            return None
 -        if pd:
 -            # TODO - this is actually in the bundler
 -            # TODO validate file?
 -            return euca2ools.bundler.Bundler(self).decrypt_string(
 -                    pd, self.privatekey, encoded=True)
 -        else:
 -            return None
 -
 -    def main_cli(self):
 -        pw = self.main()
 -        if pw:
 -            print pw
 -        else:
 -            sys.exit('no password found for this instance')
++            # The reply didn't contain a passwordData element.
++            raise AttributeError('no password data found for this instance')
 +        privkey  = RSA.load_key_string(self.args['priv_launch_key'])
 +        password = privkey.private_decrypt(base64.b64decode(pwdata),
 +                                           RSA.pkcs1_padding)
 +        print password
diff --combined euca2ools/commands/eustore/installimage.py
index b2ef8e4,e15415d..d2f8e42
--- a/euca2ools/commands/eustore/installimage.py
+++ b/euca2ools/commands/eustore/installimage.py
@@@ -36,6 -36,7 +36,7 @@@ import o
  import sys
  import tarfile
  import hashlib
+ import re
  import zlib
  import tempfile
  import urllib2
@@@ -47,8 -48,8 +48,8 @@@ from boto.s3.connection import Locatio
  import euca2ools.bundler
  import euca2ools.commands.eustore
  import euca2ools.utils
 -from euca2ools.commands.euca.bundleimage import BundleImage
 -from euca2ools.commands.euca.uploadbundle import UploadBundle
 +from euca2ools.commands.bundle.bundleimage import BundleImage
 +from euca2ools.commands.bundle.uploadbundle import UploadBundle
  from euca2ools.commands.euca.register import Register
  from euca2ools.exceptions import NotFoundError, CommandFailed
  
@@@ -164,7 -165,7 +165,7 @@@ class InstallImage(AWSQueryRequest)
              print type+": "+name+" is already installed on the cloud, skipping installation of another one."
              return True
          else:
-             answer = raw_input(type+": "+name+" is already installed on ths cloud. Would you like to use it intead?(y/N)")
+             answer = raw_input(type + ": " + name + " is already installed on this cloud. Would you like to use it instead? (y/N)")
              if (answer=='y' or answer=='Y'):
                  return True
              return False
@@@ -268,14 -269,15 +269,15 @@@
                          if not(kernel_dir) and (os.path.dirname(path) != tar_root):
                              continue;
                          if not name.startswith('.'):
-                             if name.startswith('vmlin'):
+                             # Note that vmlinuz is not always at the beginning of the filename
+                             if name.find('vmlinu') != -1:
                                  print "Bundling/uploading kernel"
                                  if prefix:
                                      name = prefix+name
                                  kernel_id = self.bundleFile(path, name, description, arch, 'true', None)
                                  kernel_found = True
                                  print kernel_id
-                             elif name.startswith('initrd'):
+                             elif re.match(".*(initr(d|amfs)|loader).*", name):
                                  print "Bundling/uploading ramdisk"
                                  if prefix:
                                      name = prefix+name
diff --combined setup.py
index c7148d4,89433ab..e1d2633
--- a/setup.py
+++ b/setup.py
@@@ -31,13 -31,39 +31,39 @@@
  # Author: Neil Soman neil at eucalyptus.com
  #         Mitch Garnaat mgarnaat at eucalyptus.com
  
- try:
-     from setuptools import setup
- except ImportError:
-     from distutils.core import setup
+ from distutils.core import setup
+ from distutils.command.build_scripts import build_scripts
+ from distutils.command.install_scripts import install_scripts
+ import os.path
  
  from euca2ools import __version__
  
+ # Cheap hack:  install symlinks separately from regular files.
+ # cmd.copy_tree accepts a preserve_symlinks option, but when we call
+ # ``setup.py install'' more than once the method fails when it encounters
+ # symlinks that are already there.
+ 
+ class build_scripts_except_symlinks(build_scripts):
+     '''Like build_scripts, but ignoring symlinks'''
+     def copy_scripts(self):
+         orig_scripts = self.scripts
+         self.scripts = [script for script in self.scripts
+                         if not os.path.islink(script)]
+         build_scripts.copy_scripts(self)
+         self.scripts = orig_scripts
+ 
+ class install_scripts_and_symlinks(install_scripts):
+     '''Like install_scripts, but also replicating nonexistent symlinks'''
+     def run(self):
+         install_scripts.run(self)
+         # Replicate symlinks if they don't exist
+         for script in self.distribution.scripts:
+             if os.path.islink(script):
+                 target  = os.readlink(script)
+                 newlink = os.path.join(self.install_dir, os.path.basename(script))
+                 if not os.path.exists(newlink):
+                     os.symlink(target, newlink)
+ 
  setup(name = "euca2ools",
        version = __version__,
        description = "Elastic Utility Computing Architecture Command Line Tools",
@@@ -169,12 -195,11 +195,12 @@@
                   "bin/eustore-install-image"],
        url = "http://open.eucalyptus.com",
        packages = ["euca2ools", "euca2ools.nc", "euca2ools.commands",
 -                  "euca2ools.commands.euca", "euca2ools.commands.euare",
 -                  "euca2ools.commands.eustore"],
 +                  "euca2ools.commands.bundle", "euca2ools.commands.euca",
 +                  "euca2ools.commands.euare", "euca2ools.commands.eustore",
 +                  "euca2ools.commands.walrus"],
        license = 'BSD (Simplified)',
        platforms = 'Posix; MacOS X; Windows',
 -      classifiers = ['Development Status :: 5 - Production/Stable',
 +      classifiers = ['Development Status :: 2 - Pre-Alpha',
                       'Intended Audience :: Users',
                       'License :: OSI Approved :: Simplified BSD License',
                       'Operating System :: OS Independent',
@@@ -183,4 -208,5 +209,5 @@@
                       'Programming Language :: Python :: 2.6',
                       'Programming Language :: Python :: 2.7',
                       'Topic :: Internet'],
-       )
+       cmdclass = {'build_scripts':   build_scripts_except_symlinks,
+                   'install_scripts': install_scripts_and_symlinks})

-- 
managing cloud instances for Eucalyptus



More information about the pkg-eucalyptus-commits mailing list