[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:55 UTC 2013
The following commit has been merged in the master branch:
commit c0fb084a3492c5de2b8975cca70246bb1f3f2493
Author: Garrett Holmstrom <gholms at fedoraproject.org>
Date: Sun Jul 8 01:22:15 2012 -0700
Port to requests-based requestbuilder
diff --git a/euca2ools/commands/__init__.py b/euca2ools/commands/__init__.py
index 71ba8c8..d18111a 100644
--- a/euca2ools/commands/__init__.py
+++ b/euca2ools/commands/__init__.py
@@ -28,6 +28,7 @@
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
+import platform
import requestbuilder.command
import requestbuilder.request
from .. import __version__, __codename__
@@ -36,4 +37,14 @@ class Euca2oolsCommand(requestbuilder.command.BaseCommand):
Version = 'euca2ools {0} ({1})'.format(__version__, __codename__)
class Euca2oolsRequest(Euca2oolsCommand, requestbuilder.request.BaseRequest):
- pass
+ @property
+ def user_agent(self):
+ if not self.__user_agent:
+ template = ('euca2ools/{ver} ({os} {osver}; {python} {pyver}) '
+ 'requestbuilder/{rqver}')
+ self.__user_agent = template.format(ver=__version__,
+ os=platform.uname()[0], osver=platform.uname()[2],
+ python=platform.python_implementation(),
+ pyver=platform.python_version(),
+ rqver=requestbuilder.__version__)
+ return self.__user_agent
diff --git a/euca2ools/commands/euare/__init__.py b/euca2ools/commands/euare/__init__.py
index c8e6048..7dc8e8f 100644
--- a/euca2ools/commands/euare/__init__.py
+++ b/euca2ools/commands/euare/__init__.py
@@ -28,7 +28,7 @@
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
-from requestbuilder import Arg, STD_AUTH_ARGS, CONNECTION
+from requestbuilder import Arg, SERVICE, STD_AUTH_ARGS
import requestbuilder.service
from .. import Euca2oolsRequest
@@ -37,24 +37,23 @@ class Euare(requestbuilder.service.BaseService):
APIVersion = '2010-05-08'
EnvURL = 'EUARE_URL'
- Endpoints = {None: 'iam.amazonaws.com'}
-
class EuareRequest(Euca2oolsRequest):
ServiceClass = Euare
- Args = [Arg('-U', '--url', route_to=CONNECTION,
- help='EUARE service URL')] + STD_AUTH_ARGS
+ Args = [Arg('-U', '--url', dest='endpoint', metavar='URL',
+ route_to=SERVICE,
+ help='identity service endpoint URL')] + STD_AUTH_ARGS
- def parse_http_response(self, response_body):
- response = Euca2oolsRequest.parse_http_response(self, response_body)
+ def parse_response(self, response):
+ response_dict = Euca2oolsRequest.parse_response(self, response)
# EUARE responses enclose their useful data inside FooResponse
# elements. If that's all we have after stripping out ResponseMetadata
# then just return its contents.
useful_keys = filter(lambda x: x != 'ResponseMetadata',
- response.keys())
+ response_dict.keys())
if len(useful_keys) == 1:
- return response[useful_keys[0]]
+ return response_dict[useful_keys[0]]
else:
- return response
+ return response_dict
DELEGATE = Arg('--delegate', dest='DelegateAccount', metavar='ACCOUNT',
help='''[Eucalyptus only] interpret this command as if the
diff --git a/euca2ools/commands/euare/listusers.py b/euca2ools/commands/euare/listusers.py
index ad04379..7eed565 100644
--- a/euca2ools/commands/euare/listusers.py
+++ b/euca2ools/commands/euare/listusers.py
@@ -37,8 +37,7 @@ class ListUsers(EuareRequest):
help='''limit results to users who begin with a given path
(default: list all users)'''),
DELEGATE]
- ListMarkers = ['Users']
- ItemMarkers = ['member']
+ ListDelims = ['Users']
def print_result(self, result):
for user in result.get('Users', []):
diff --git a/euca2ools/commands/euca/__init__.py b/euca2ools/commands/euca/__init__.py
index ca34bb8..aa6dd9b 100644
--- a/euca2ools/commands/euca/__init__.py
+++ b/euca2ools/commands/euca/__init__.py
@@ -31,59 +31,76 @@
import argparse
from operator import itemgetter
import os.path
-from requestbuilder import Arg, CONNECTION
+from requestbuilder import Arg, AUTH, SERVICE, STD_AUTH_ARGS
from requestbuilder.mixins import TabifyingCommand
import requestbuilder.service
import shlex
from string import Template
+import sys
from .. import Euca2oolsRequest
class Eucalyptus(requestbuilder.service.BaseService):
- Description = 'Eucalyptus compute cloud controller'
+ Description = 'Eucalyptus compute cloud service'
APIVersion = '2009-11-30'
EnvURL = 'EC2_URL'
- def __init__(self, configfile=None, **kwargs):
+ def __init__(self, log, configfile=None, deprecated_key_id=None,
+ deprecated_key=None, auth_args=None, **kwargs):
self.configfile_name = configfile
- requestbuilder.service.BaseService.__init__(self, **kwargs)
+ if deprecated_key_id and not auth_args.get('key_id'):
+ auth_args['key_id'] = deprecated_key_id
+ msg = 'given access key ID argument is deprecated; use -I instead'
+ log.warn(msg)
+ print >> sys.stderr, 'warning:', msg
+ if deprecated_key and not auth_args.get('key'):
+ auth_args['key'] = deprecated_key
+ msg = 'argument -s is deprecated; use -S instead'
+ log.warn(msg)
+ print >> sys.stderr, 'warning:', msg
+ requestbuilder.service.BaseService.__init__(self, log,
+ auth_args=auth_args,
+ **kwargs)
def find_credentials(self):
# CLI-given env-style config file
if os.path.isfile(self.configfile_name or ''):
config = _parse_configfile(self.configfile_name)
- self._populate_init_args_from_env_config(config)
+ self._populate_self_from_env_config(config)
# AWS credential file (path is in the environment)
requestbuilder.service.BaseService.find_credentials(self)
# Environment
config = self._get_env_config_from_env()
- self._populate_init_args_from_env_config(config)
+ self._populate_self_from_env_config(config)
# User, systemwide env-style config files
for configfile_name in ('~/.eucarc', '~/.eucarc/eucarc'):
configfile_name = os.path.expandvars(configfile_name)
configfile_name = os.path.expanduser(configfile_name)
if os.path.isfile(configfile_name):
config = _parse_configfile(configfile_name)
- self._populate_init_args_from_env_config(config)
-
- _init_args_key_map = {'EC2_ACCESS_KEY': 'aws_access_key_id',
- 'EC2_SECRET_KEY': 'aws_secret_access_key',
- 'EC2_URL': 'url'}
+ self._populate_self_from_env_config(config)
def _get_env_config_from_env(self):
envconfig = {}
- for key in self._init_args_key_map:
+ for key in ('EC2_ACCESS_KEY', 'EC2_SECRET_KEY', 'EC2_URL'):
if key in os.environ:
envconfig[key] = os.getenv(key)
return envconfig
- def _populate_init_args_from_env_config(self, envconfig):
+ def _populate_self_from_env_config(self, envconfig):
'''
- Populate self._init_args from the contents of an environment
+ Populate this service from the contents of an environment
variable-like dict.
'''
- for (env_key, initargs_key) in self._init_args_key_map.iteritems():
- if env_key in envconfig and not self._init_args.get(initargs_key):
- self._init_args[initargs_key] = envconfig[env_key]
+ for (env_key, val) in envconfig.iteritems():
+ if (env_key == 'EC2_ACCESS_KEY' and
+ not self._auth_args.get('key_id')):
+ self._auth_args['key_id'] = val
+ elif (env_key == 'EC2_SECRET_KEY' and
+ not self._auth_args.get('key')):
+ self._auth_args['key'] = val
+ elif env_key == 'EC2_URL' and not self.endpoint:
+ self.endpoint = val
+ self.region_name = '__config__' ## FIXME
def _parse_configfile(configfile_name):
def sourcehook(filename):
@@ -113,15 +130,20 @@ def _parse_configfile(configfile_name):
class EucalyptusRequest(Euca2oolsRequest, TabifyingCommand):
ServiceClass = Eucalyptus
- Args = [Arg('-I', '-a', '--access-key-id', '--access-key',
- metavar='KEY_ID', dest='aws_access_key_id',
- route_to=CONNECTION),
- Arg('-S', '-s', '--secret-key', metavar='KEY',
- dest='aws_secret_access_key', route_to=CONNECTION),
- Arg('-U', '--url', route_to=CONNECTION,
- help='cloud controller URL'),
+ # For compatibility with euca2ools versions earlier than 3, we include the
+ # old -a/--access-key/-s args. As before, if either -a or -s conflicts
+ # with another arg, both are capitalized. All are deprecated. They are no
+ # longer documented and using them will result in warnings.
+ Args = [Arg('-a', '--access-key', metavar='KEY_ID',
+ dest='deprecated_key_id', route_to=SERVICE,
+ help=argparse.SUPPRESS),
+ Arg('-s', metavar='KEY', dest='deprecated_key', route_to=SERVICE,
+ help=argparse.SUPPRESS),
Arg('--config', dest='configfile', metavar='CFGFILE',
- route_to=CONNECTION)]
+ route_to=SERVICE),
+ Arg('-U', '--url', dest='endpoint', metavar='URL',
+ route_to=SERVICE,
+ help='compute service endpoint URL')] + STD_AUTH_ARGS
def __init__(self, **kwargs):
# If an inheriting class defines '-a' or '-s' args, resolve conflicts
@@ -131,13 +153,12 @@ class EucalyptusRequest(Euca2oolsRequest, TabifyingCommand):
s_args = _find_args_by_parg(self.Args, '-s')
if len(a_args) > 1 or len(s_args) > 1:
for arg in a_args:
- if '--access-key' in arg.pargs:
+ if arg.kwargs.get('dest') == 'deprecated_key_id':
arg.pargs = tuple('-A' if parg == '-a' else parg
for parg in arg.pargs)
for arg in s_args:
- if '--secret-key' in arg.pargs:
- arg.pargs = tuple(parg for parg in arg.pargs
- if parg != '-s')
+ if arg.kwargs.get('dest') == 'deprecated_key':
+ arg.kwargs['dest'] = argparse.SUPPRESS
Euca2oolsRequest.__init__(self, **kwargs)
def parse_http_response(self, response_body):
diff --git a/euca2ools/commands/euca/createkeypair.py b/euca2ools/commands/euca/createkeypair.py
index 12d8638..668b967 100644
--- a/euca2ools/commands/euca/createkeypair.py
+++ b/euca2ools/commands/euca/createkeypair.py
@@ -33,7 +33,7 @@ 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')]
+ Args = [Arg('KeyName', metavar='KEYPAIR', help='name of the new key pair')]
def print_result(self, result):
print self.tabify(('KEYPAIR', result['keyName'],
diff --git a/euca2ools/commands/euca/describeaddresses.py b/euca2ools/commands/euca/describeaddresses.py
index 24223c1..dade340 100644
--- a/euca2ools/commands/euca/describeaddresses.py
+++ b/euca2ools/commands/euca/describeaddresses.py
@@ -44,8 +44,7 @@ class DescribeAddresses(EucalyptusRequest):
Filter('instance-id',
help='instance the address is associated with'),
Filter('public-ip', help='the elastic IP address')]
- ListMarkers = ['addressesSet']
- ItemMarkers = ['item']
+ ListDelims = ['addressesSet']
def main(self):
alloc_ids = set(addr for addr in self.args.get('address', [])
diff --git a/euca2ools/commands/euca/describeavailabilityzones.py b/euca2ools/commands/euca/describeavailabilityzones.py
index 19f8d06..e211135 100644
--- a/euca2ools/commands/euca/describeavailabilityzones.py
+++ b/euca2ools/commands/euca/describeavailabilityzones.py
@@ -42,8 +42,7 @@ class DescribeAvailabilityZones(EucalyptusRequest):
help='region the availability zone is in'),
Filter('state', help='state of the availability zone'),
Filter('zone-name', help='name of the availability zone')]
- ListMarkers = ['availabilityZoneInfo', 'messageSet']
- ItemMarkers = ['item']
+ ListDelims = ['availabilityZoneInfo', 'messageSet']
def print_result(self, result):
for zone in result.get('availabilityZoneInfo', []):
diff --git a/euca2ools/commands/euca/describebundletasks.py b/euca2ools/commands/euca/describebundletasks.py
index 83b5085..c99a174 100644
--- a/euca2ools/commands/euca/describebundletasks.py
+++ b/euca2ools/commands/euca/describebundletasks.py
@@ -51,8 +51,7 @@ class DescribeBundleTasks(EucalyptusRequest):
choices=('pending', 'waiting-for-shutdown', 'bundling',
'storing', 'cancelling', 'complete', 'failed')),
Filter('update-time', help='most recent task update time')]
- ListMarkers = ['bundleInstanceTasksSet']
- ItemMarkers = ['item']
+ ListDelims = ['bundleInstanceTasksSet']
def print_result(self, result):
for task in result.get('bundleInstanceTasksSet', []):
diff --git a/euca2ools/commands/euca/describeimageattribute.py b/euca2ools/commands/euca/describeimageattribute.py
index 51c567a..e37e0b4 100644
--- a/euca2ools/commands/euca/describeimageattribute.py
+++ b/euca2ools/commands/euca/describeimageattribute.py
@@ -50,8 +50,7 @@ class DescribeImageAttribute(EucalyptusRequest):
const='ramdisk', help='show associated ramdisk image ID'),
Arg('--description', dest='Attribute', action='store_const',
const='description', help="show the image's description"))]
- ListMarkers = ['blockDeviceMapping', 'launchPermission', 'productCodes']
- ItemMarkers = ['item']
+ ListDelims = ['blockDeviceMapping', 'launchPermission', 'productCodes']
def print_result(self, result):
image_id = result.get('imageId')
diff --git a/euca2ools/commands/euca/describeimages.py b/euca2ools/commands/euca/describeimages.py
index 49ef836..de68717 100644
--- a/euca2ools/commands/euca/describeimages.py
+++ b/euca2ools/commands/euca/describeimages.py
@@ -43,9 +43,11 @@ class DescribeImages(EucalyptusRequest):
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', action='append',
+ Arg('-o', '--owner', dest='Owner', metavar='ACCOUNT',
+ action='append',
help='describe images owned by the specified owner'),
- Arg('-x', '--executable-by', dest='ExecutableBy', action='append',
+ 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'),
@@ -94,8 +96,7 @@ class DescribeImages(EucalyptusRequest):
help='virtualization type ("paravirtual" or "hvm")'),
Filter('hypervisor', choices=('ovm', 'xen'),
help='image\'s hypervisor type ("ovm" or "xen")')]
- ListMarkers = ['imagesSet', 'blockDeviceMapping', 'tagSet']
- ItemMarkers = ['item']
+ ListDelims = ['imagesSet', 'blockDeviceMapping', 'tagSet']
def main(self):
if not any(self.args.get(item) for item in ('all', 'ImageId',
diff --git a/euca2ools/commands/euca/describeinstances.py b/euca2ools/commands/euca/describeinstances.py
index 810d896..da389de 100644
--- a/euca2ools/commands/euca/describeinstances.py
+++ b/euca2ools/commands/euca/describeinstances.py
@@ -98,9 +98,8 @@ class DescribeInstances(EucalyptusRequest):
help='specific tag key/value combination'),
Filter('virtualization-type', choices=['paravirtual', 'hvm']),
Filter('vpc-id', help='ID of the VPC the instance is in')]
- ListMarkers = ['reservationSet', 'instancesSet', 'groupSet', 'tagSet',
- 'blockDeviceMapping']
- ItemMarkers = ['item']
+ ListDelims = ['reservationSet', 'instancesSet', 'groupSet', 'tagSet',
+ 'blockDeviceMapping', 'productCodes']
def print_result(self, result):
for reservation in result.get('reservationSet'):
diff --git a/euca2ools/commands/euca/describekeypairs.py b/euca2ools/commands/euca/describekeypairs.py
index 6d6d6ef..68d6d9a 100644
--- a/euca2ools/commands/euca/describekeypairs.py
+++ b/euca2ools/commands/euca/describekeypairs.py
@@ -38,8 +38,7 @@ class DescribeKeyPairs(EucalyptusRequest):
help='limit results to specific key pairs')]
Filters = [Filter('fingerprint', help='fingerprint of the key pair'),
Filter('key-name', help='name of the key pair')]
- ListMarkers = ['keySet']
- ItemMarkers = ['item']
+ ListDelims = ['keySet']
def print_result(self, result):
for key in result.get('keySet', []):
diff --git a/euca2ools/commands/euca/describeregions.py b/euca2ools/commands/euca/describeregions.py
index 06d66b9..a2bb026 100644
--- a/euca2ools/commands/euca/describeregions.py
+++ b/euca2ools/commands/euca/describeregions.py
@@ -38,8 +38,7 @@ class DescribeRegions(EucalyptusRequest):
help='limit results to specific regions')]
Filters = [Filter('endpoint'),
Filter('region-name')]
- ListMarkers = ['regionInfo']
- ItemMarkers = ['item']
+ ListDelims = ['regionInfo']
def print_result(self, result):
for region in result.get('regionInfo', []):
diff --git a/euca2ools/commands/euca/describesecuritygroups.py b/euca2ools/commands/euca/describesecuritygroups.py
index 51d41d6..6263b6f 100644
--- a/euca2ools/commands/euca/describesecuritygroups.py
+++ b/euca2ools/commands/euca/describesecuritygroups.py
@@ -62,9 +62,8 @@ class DescribeSecurityGroups(EucalyptusRequest):
Filter('tag-key', help='key of a tag assigned to the group'),
Filter('tag-value',
help='value of a tag assigned to the group')]
- ListMarkers = ['securityGroupInfo', 'ipPermissions', 'ipPermissionsEgress',
- 'groups', 'ipRanges']
- ItemMarkers = ['item']
+ ListDelims = ['securityGroupInfo', 'ipPermissions', 'ipPermissionsEgress',
+ 'groups', 'ipRanges']
def main(self):
self.params = {}
diff --git a/euca2ools/commands/euca/describesnapshots.py b/euca2ools/commands/euca/describesnapshots.py
index 82b9703..ecd5afb 100644
--- a/euca2ools/commands/euca/describesnapshots.py
+++ b/euca2ools/commands/euca/describesnapshots.py
@@ -63,8 +63,7 @@ class DescribeSnapshots(EucalyptusRequest):
help='specific tag key/value combination'),
Filter('volume-id', help='source volume ID'),
Filter('volume-size', type=int)]
- ListMarkers = ['snapshotSet', 'tagSet']
- ItemMarkers = ['item']
+ ListDelims = ['snapshotSet', 'tagSet']
def main(self):
if not any(self.args.get(item) for item in ('all', 'Owner',
diff --git a/euca2ools/commands/euca/describetags.py b/euca2ools/commands/euca/describetags.py
index 31b9075..e6eefd2 100644
--- a/euca2ools/commands/euca/describetags.py
+++ b/euca2ools/commands/euca/describetags.py
@@ -39,8 +39,7 @@ class DescribeTags(EucalyptusRequest):
Filter('resource-type',
choices=sorted(tuple(RESOURCE_TYPE_MAP))),
Filter('value')]
- ListMarkers = ['tagSet']
- ItemMarkers = ['item']
+ ListDelims = ['tagSet']
def print_result(self, result):
for tag in result.get('tagSet', []):
diff --git a/euca2ools/commands/euca/describevolumes.py b/euca2ools/commands/euca/describevolumes.py
index ea5259d..004cab2 100644
--- a/euca2ools/commands/euca/describevolumes.py
+++ b/euca2ools/commands/euca/describevolumes.py
@@ -59,8 +59,7 @@ class DescribeVolumes(EucalyptusRequest):
GenericTagFilter('tag:KEY',
help='specific tag key/value combination'),
Filter(name='volume-id')]
- ListMarkers = ['volumeSet', 'attachmentSet', 'tagSet']
- ItemMarkers = ['item']
+ ListDelims = ['volumeSet', 'attachmentSet', 'tagSet']
def print_result(self, result):
for volume in result.get('volumeSet'):
diff --git a/euca2ools/commands/euca/monitorinstances.py b/euca2ools/commands/euca/monitorinstances.py
index 36e449a..4a6d200 100644
--- a/euca2ools/commands/euca/monitorinstances.py
+++ b/euca2ools/commands/euca/monitorinstances.py
@@ -35,8 +35,7 @@ class MonitorInstances(EucalyptusRequest):
Description = 'Enable monitoring for one or more instances'
Args = [Arg('InstanceId', metavar='INSTANCE', nargs='+',
help='instance(s) to monitor')]
- ListMarkers = ['instancesSet']
- ItemMarkers = ['item']
+ ListDelims = ['instancesSet']
def print_result(self, result):
for instance in result.get('instancesSet', []):
diff --git a/euca2ools/commands/euca/startinstances.py b/euca2ools/commands/euca/startinstances.py
index ff30d55..728d73c 100644
--- a/euca2ools/commands/euca/startinstances.py
+++ b/euca2ools/commands/euca/startinstances.py
@@ -35,8 +35,7 @@ class StartInstances(EucalyptusRequest):
Description = 'Start one or more stopped instances'
Args = [Arg('InstanceId', metavar='INSTANCE', nargs='+',
help='instance(s) to start')]
- ListMarkers = ['instancesSet']
- ItemMarkers = ['item']
+ ListDelims = ['instancesSet']
def print_result(self, result):
for instance in result.get('instancesSet', []):
diff --git a/euca2ools/commands/euca/stopinstances.py b/euca2ools/commands/euca/stopinstances.py
index 808417a..a6cf32a 100644
--- a/euca2ools/commands/euca/stopinstances.py
+++ b/euca2ools/commands/euca/stopinstances.py
@@ -38,8 +38,7 @@ class StopInstances(EucalyptusRequest):
Arg('-f', '--force', dest='Force', action='store_const',
const='true',
help='immediately stop the instance. Data may be lost')]
- ListMarkers = ['instancesSet']
- ItemMarkers = ['item']
+ ListDelims = ['instancesSet']
def print_result(self, result):
for instance in result.get('instancesSet', []):
diff --git a/euca2ools/commands/euca/terminateinstances.py b/euca2ools/commands/euca/terminateinstances.py
index 30f340b..46d2d76 100644
--- a/euca2ools/commands/euca/terminateinstances.py
+++ b/euca2ools/commands/euca/terminateinstances.py
@@ -35,8 +35,7 @@ class TerminateInstances(EucalyptusRequest):
Description = 'Terminate one or more instances'
Args = [Arg('InstanceId', metavar='INSTANCE', nargs='+',
help='instance(s) to terminate')]
- ListMarkers = ['instancesSet']
- ItemMarkers = ['item']
+ ListDelims = ['instancesSet']
def print_result(self, result):
for instance in result.get('instancesSet', []):
diff --git a/euca2ools/commands/euca/unmonitorinstances.py b/euca2ools/commands/euca/unmonitorinstances.py
index 98eb9c1..0c6775e 100644
--- a/euca2ools/commands/euca/unmonitorinstances.py
+++ b/euca2ools/commands/euca/unmonitorinstances.py
@@ -35,8 +35,7 @@ class UnmonitorInstances(EucalyptusRequest):
Description = 'Disable monitoring for one or more instances'
Args = [Arg('InstanceId', metavar='INSTANCE', nargs='+',
help='instance(s) to un-monitor')]
- ListMarkers = ['instancesSet']
- ItemMarkers = ['item']
+ ListDelims = ['instancesSet']
def print_result(self, result):
for instance in result.get('instancesSet', []):
--
managing cloud instances for Eucalyptus
More information about the pkg-eucalyptus-commits
mailing list