[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:51 UTC 2013
The following commit has been merged in the master branch:
commit 2985cf32ff225577a09bedb288c202d8e35c438f
Author: Garrett Holmstrom <gholms at fedoraproject.org>
Date: Sun Apr 29 00:11:13 2012 -0700
Rewrite RunInstances
diff --git a/bin/euca-run-instances b/bin/euca-run-instances
index cf971ed..b46f75c 100755
--- a/bin/euca-run-instances
+++ b/bin/euca-run-instances
@@ -1,42 +1,6 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Software License Agreement (BSD License)
-#
-# Copyright (c) 2009-2011, Eucalyptus Systems, Inc.
-# All rights reserved.
-#
-# Redistribution and use of this software in source and binary forms, with or
-# without modification, are permitted provided that the following conditions
-# are met:
-#
-# Redistributions of source code must retain the above
-# copyright notice, this list of conditions and the
-# following disclaimer.
-#
-# Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the
-# following disclaimer in the documentation and/or other
-# materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-# 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
+#!/usr/bin/python -tt
import euca2ools.commands.euca.runinstances
if __name__ == '__main__':
- cmd = euca2ools.commands.euca.runinstances.RunInstances()
- cmd.main_cli()
-
+ euca2ools.commands.euca.runinstances.RunInstances().do_cli()
diff --git a/euca2ools/commands/euca/argtypes.py b/euca2ools/commands/euca/argtypes.py
index e0742ab..7d72a1d 100644
--- a/euca2ools/commands/euca/argtypes.py
+++ b/euca2ools/commands/euca/argtypes.py
@@ -29,6 +29,7 @@
# POSSIBILITY OF SUCH DAMAGE.
import argparse
+import base64
from requestbuilder import EMPTY
import sys
@@ -45,7 +46,7 @@ def block_device_mapping(map_as_str):
map_dict = {'DeviceName': device}
if mapping.lower() == 'none':
## FIXME: EC2 does not accept this, despite its documentation
- map_dict['Ebs'] = {'NoDevice': 'true'}
+ map_dict['Ebs'] = {'NoDevice': EMPTY}
elif mapping.startswith('ephemeral'):
map_dict['VirtualName'] = mapping
elif (mapping.startswith('snap-') or mapping.startswith('vol-') or
@@ -98,6 +99,13 @@ def file_contents(filename):
with open(filename) as arg_file:
return arg_file.read()
+def b64encoded_file_contents(filename):
+ if filename == '-':
+ return base64.b64encode(sys.stdin.read())
+ else:
+ with open(filename) as arg_file:
+ return base64.b64encode(arg_file.read())
+
def binary_tag_def(tag_str):
'''
Parse a tag definition from the command line. Return a dict that depends
diff --git a/euca2ools/commands/euca/runinstances.py b/euca2ools/commands/euca/runinstances.py
index 56fc2d2..477910e 100644
--- a/euca2ools/commands/euca/runinstances.py
+++ b/euca2ools/commands/euca/runinstances.py
@@ -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,127 +27,101 @@
# 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
-import euca2ools.utils
+import argparse
+import base64
import os.path
+from requestbuilder import Arg, MutuallyExclusiveArgList
+import sys
+from . import EucalyptusRequest
+from .argtypes import b64encoded_file_contents, block_device_mapping
-class RunInstances(euca2ools.commands.eucacommand.EucaCommand):
-
- Description = 'Starts instances.'
- Options = [Param(name='count', short_name='n', long_name='instance-count',
- optional=True, ptype='string', default='1',
- doc='Number of instances to run.'),
- Param(name='group_name', short_name='g', long_name='group',
- optional=True, ptype='string', cardinality='*',
- doc='Security group to run the instance in.'),
- Param(name='keyname', short_name='k', long_name='key',
- optional=True, ptype='string',
- doc='Name of a keypair.'),
- Param(name='user_data', short_name='d', long_name='user-data',
- optional=True, doc='User data to pass to the instance.'),
- Param(name='user_data_force', long_name='user-data-force',
- optional=True,
- doc='Just like --user-data, but ignore any checks.'),
- Param(name='user_data_file',
- short_name='f', long_name='user-data-file',
- optional=True, ptype='file',
- doc='File containing user data to pass to the instance.'),
- Param(name='addressing', long_name='addressing',
- optional=True, ptype='string',
- doc='Deprecated.'),
- Param(name='instance_type',
- short_name='t', long_name='instance-type',
- optional=True, ptype='string', default='m1.small',
- doc='VM Image type to run the instance as.'),
- Param(name='kernel', long_name='kernel',
- optional=True, ptype='string',
- doc='ID of the kernel to be used.'),
- Param(name='ramdisk', long_name='ramdisk',
- optional=True, ptype='string',
- doc='ID of the ramdisk to be used.'),
- Param(name='block_device_mapping',
- short_name='b', long_name='block-device-mapping',
- optional=True, ptype='string', cardinality='*',
- doc="""Block device mapping for the instance(s).
- Option may be used multiple times"""),
- Param(name='monitor', long_name='monitor',
- optional=True, ptype='boolean', default=False,
- doc='Enable monitoring for the instance.'),
- Param(name='subnet', short_name='s', long_name='subnet',
- optional=True, ptype='string',
- doc='Amazon VPC subnet ID for the instance.'),
- Param(name='zone', short_name='z', long_name='availability-zone',
- optional=True, ptype='string',
- doc='availability zone to run the instance in')]
- Args = [Param(name='image_id', ptype='string',
- optional=False,
- doc='ID of the image to run.')]
-
- def display_reservations(self, reservation):
- reservation_string = '%s\t%s' % (reservation.id,
- reservation.owner_id)
- group_delim = '\t'
- for group in reservation.groups:
- reservation_string += '%s%s' % (group_delim, group.id)
- group_delim = ', '
- print 'RESERVATION\t%s' % reservation_string
- euca2ools.utils.print_instances(reservation.instances)
-
- def read_user_data(self, user_data_filename):
- fp = open(user_data_filename)
- user_data = fp.read()
- fp.close()
- return user_data
+class RunInstances(EucalyptusRequest):
+ Description = 'Launch instances of a machine image'
+ Args = [Arg('ImageId', metavar='IMAGE', help='image to instantiate'),
+ Arg('-n', '--instance-count', dest='count', metavar='MIN[-MAX]',
+ default='1', route_to=None,
+ help='''number of instances to launch. If this number of
+ instances cannot be launched, no instances will launch.
+ If specified as a range (min-max), the server will
+ attempt to launch the maximum number, but no fewer
+ than the minimum number.'''),
+ Arg('-g', '--group', dest='group', action='append', default=[],
+ route_to=None,
+ help='security group(s) in which to launch the instances'),
+ Arg('-k', '--key', dest='KeyName', metavar='KEYPAIR',
+ help='name of the key pair to use'),
+ MutuallyExclusiveArgList(
+ Arg('-d', '--user-data', dest='UserData', metavar='DATA',
+ type=base64.b64encode,
+ help='''user data to make available to instances in this
+ reservation'''),
+ Arg('--user-data-force', dest='UserData',
+ type=base64.b64encode, help=argparse.SUPPRESS),
+ # ^ deprecated
+ Arg('-f', '--user-data-file', dest='UserData',
+ metavar='DATA-FILE', type=b64encoded_file_contents,
+ help='''file containing user data to make available to the
+ instances in this reservation''')),
+ Arg('--addressing', dest='AddressingType',
+ choices=('public', 'private'),
+ help='addressing scheme to launch the instance with'),
+ Arg('-t', '--instance-type',
+ help='type of instance to launch'),
+ Arg('--kernel', dest='KernelId', metavar='KERNEL',
+ help='kernel to launch the instance(s) with'),
+ Arg('--ramdisk', dest='RamdiskId', metavar='RAMDISK',
+ help='ramdisk to launch the instance(s) with'),
+ Arg('-b', '--block-device-mapping', metavar='DEVICE=MAPPED',
+ dest='BlockDeviceMapping', action='append',
+ type=block_device_mapping, default=[],
+ help='''define a block device mapping for the instances, in the
+ form DEVICE=MAPPED, where "MAPPED" is "none",
+ "ephemeral(0-3)", or
+ "[SNAP-ID]:[SIZE]:[true|false]"'''),
+ Arg('-m', '--monitor', dest='Monitoring.Enabled',
+ action='store_const', const='true',
+ help='enable monitoring for the instance(s)'),
+ Arg('--subnet', dest='SubnetId', metavar='SUBNET',
+ help='VPC subnet in which to launch the instance(s)'),
+ Arg('-z', '--availability-zone', metavar='ZONE',
+ dest='Placement.AvailabilityZone')]
def main(self):
- t = self.count.split('-')
- try:
- if len(t) > 1:
- min_count = int(t[0])
- max_count = int(t[1])
- else:
- min_count = max_count = int(t[0])
- except ValueError:
- msg = 'Invalid value for --instance-count: %s' % count
- self.display_error_and_exit(msg)
-
- if self.user_data and os.path.isfile(self.user_data):
- msg = ('string provided as user-data [%s] is a file.\nTry %s or %s'
- % (self.user_data, '--user-data-file', '--user-data-force'))
- self.display_error_and_exit(msg)
-
- if self.user_data_force:
- self.user_data = self.user_data_force
-
- if not self.user_data:
- if self.user_data_file:
- self.user_data = self.read_user_data(self.user_data_file)
+ self.params = {}
+ counts = self.args['count'].split('-')
+ if len(counts) == 1:
+ try:
+ self.params['MinCount'] = int(counts[0])
+ self.params['MaxCount'] = int(counts[0])
+ except ValueError:
+ self._cli_parser.error('argument -n/--instance-count: '
+ 'instance count must be in integer')
+ elif len(counts) == 2:
+ try:
+ self.params['MinCount'] = int(counts[0])
+ self.params['MaxCount'] = int(counts[1])
+ except ValueError:
+ self._cli_parser.error('argument -n/--instance-count: '
+ 'instance count range must be must be comprised of '
+ 'integers')
+ else:
+ self._cli_parser.error('argument -n/--instance-count: value must '
+ 'have format "1" or "1-2"')
+ if self.params['MinCount'] < 1 or self.params['MaxCount'] < 1:
+ self._cli_parser.error('argument -n/--instance-count: instance '
+ 'count must be positive')
- if self.block_device_mapping:
- self.block_device_mapping = self.parse_block_device_args(self.block_device_mapping)
- conn = self.make_connection_cli()
- return self.make_request_cli(conn, 'run_instances',
- image_id=self.image_id,
- min_count=min_count,
- max_count=max_count,
- key_name=self.keyname,
- security_groups=self.group_name,
- user_data=self.user_data,
- addressing_type=self.addressing,
- instance_type=self.instance_type,
- placement=self.zone,
- kernel_id=self.kernel,
- ramdisk_id=self.ramdisk,
- block_device_map=self.block_device_mapping,
- monitoring_enabled=self.monitor,
- subnet_id=self.subnet)
+ for group in self.args['group']:
+ # Uncomment this during the next API version bump
+ #if group.startswith('sg-'):
+ # self.params.setdefault('SecurityGroupId', [])
+ # self.params['SecurityGroupId'].append(group)
+ #else:
+ self.params.setdefault('SecurityGroup', [])
+ self.params['SecurityGroup'].append(group)
- def main_cli(self):
- reservation = self.main()
- self.display_reservations(reservation)
+ return self.send()
+ def print_result(self, result):
+ self.print_reservation(result)
--
managing cloud instances for Eucalyptus
More information about the pkg-eucalyptus-commits
mailing list