summaryrefslogtreecommitdiffstats
path: root/nova/api
diff options
context:
space:
mode:
authorEd Leafe <ed@leafe.com>2011-02-17 22:09:26 +0000
committerEd Leafe <ed@leafe.com>2011-02-17 22:09:26 +0000
commitc0972233901774598fe6c836fcc3a0dd1f28f180 (patch)
treec3fe737f4e84031ffdd6316cdeb645d725ef6c0e /nova/api
parent396b02f876030f1f54b7af32cf94fccbbe1fe46b (diff)
parent52753aae3486f654b9fb19d6423fc26dc180644d (diff)
Uncommitted changes using the wrong author, and re-committing under the correct author
Diffstat (limited to 'nova/api')
-rw-r--r--nova/api/ec2/__init__.py22
-rw-r--r--nova/api/ec2/admin.py11
-rw-r--r--nova/api/ec2/cloud.py33
-rw-r--r--nova/api/openstack/__init__.py5
-rw-r--r--nova/api/openstack/common.py33
-rw-r--r--nova/api/openstack/servers.py33
6 files changed, 105 insertions, 32 deletions
diff --git a/nova/api/ec2/__init__.py b/nova/api/ec2/__init__.py
index e25943a13..1a06b3f01 100644
--- a/nova/api/ec2/__init__.py
+++ b/nova/api/ec2/__init__.py
@@ -21,7 +21,6 @@ Starting point for routing EC2 requests.
"""
import datetime
-import routes
import webob
import webob.dec
import webob.exc
@@ -171,7 +170,7 @@ class Authenticate(wsgi.Middleware):
req.path)
# Be explicit for what exceptions are 403, the rest bubble as 500
except (exception.NotFound, exception.NotAuthorized) as ex:
- LOG.audit(_("Authentication Failure: %s"), ex.args[0])
+ LOG.audit(_("Authentication Failure: %s"), unicode(ex))
raise webob.exc.HTTPForbidden()
# Authenticated!
@@ -233,7 +232,7 @@ class Authorizer(wsgi.Middleware):
super(Authorizer, self).__init__(application)
self.action_roles = {
'CloudController': {
- 'DescribeAvailabilityzones': ['all'],
+ 'DescribeAvailabilityZones': ['all'],
'DescribeRegions': ['all'],
'DescribeSnapshots': ['all'],
'DescribeKeyPairs': ['all'],
@@ -316,30 +315,31 @@ class Executor(wsgi.Application):
try:
result = api_request.invoke(context)
except exception.InstanceNotFound as ex:
- LOG.info(_('InstanceNotFound raised: %s'), ex.args[0],
+ LOG.info(_('InstanceNotFound raised: %s'), unicode(ex),
context=context)
ec2_id = cloud.id_to_ec2_id(ex.instance_id)
message = _('Instance %s not found') % ec2_id
return self._error(req, context, type(ex).__name__, message)
except exception.VolumeNotFound as ex:
- LOG.info(_('VolumeNotFound raised: %s'), ex.args[0],
+ LOG.info(_('VolumeNotFound raised: %s'), unicode(ex),
context=context)
ec2_id = cloud.id_to_ec2_id(ex.volume_id, 'vol-%08x')
message = _('Volume %s not found') % ec2_id
return self._error(req, context, type(ex).__name__, message)
except exception.NotFound as ex:
- LOG.info(_('NotFound raised: %s'), ex.args[0], context=context)
- return self._error(req, context, type(ex).__name__, ex.args[0])
+ LOG.info(_('NotFound raised: %s'), unicode(ex), context=context)
+ return self._error(req, context, type(ex).__name__, unicode(ex))
except exception.ApiError as ex:
- LOG.exception(_('ApiError raised: %s'), ex.args[0],
+ LOG.exception(_('ApiError raised: %s'), unicode(ex),
context=context)
if ex.code:
- return self._error(req, context, ex.code, ex.args[0])
+ return self._error(req, context, ex.code, unicode(ex))
else:
- return self._error(req, context, type(ex).__name__, ex.args[0])
+ return self._error(req, context, type(ex).__name__,
+ unicode(ex))
except Exception as ex:
extra = {'environment': req.environ}
- LOG.exception(_('Unexpected error raised: %s'), ex.args[0],
+ LOG.exception(_('Unexpected error raised: %s'), unicode(ex),
extra=extra, context=context)
return self._error(req,
context,
diff --git a/nova/api/ec2/admin.py b/nova/api/ec2/admin.py
index d7e899d12..735951082 100644
--- a/nova/api/ec2/admin.py
+++ b/nova/api/ec2/admin.py
@@ -184,6 +184,17 @@ class AdminController(object):
description=None,
member_users=None))
+ def modify_project(self, context, name, manager_user, description=None,
+ **kwargs):
+ """Modifies a project"""
+ msg = _("Modify project: %(name)s managed by"
+ " %(manager_user)s") % locals()
+ LOG.audit(msg, context=context)
+ manager.AuthManager().modify_project(name,
+ manager_user=manager_user,
+ description=description)
+ return True
+
def deregister_project(self, context, name):
"""Permanently deletes a project."""
LOG.audit(_("Delete project: %s"), name, context=context)
diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py
index 00d044e95..6919cd8d2 100644
--- a/nova/api/ec2/cloud.py
+++ b/nova/api/ec2/cloud.py
@@ -327,7 +327,9 @@ class CloudController(object):
if not group_name is None:
groups = [g for g in groups if g.name in group_name]
- return {'securityGroupInfo': groups}
+ return {'securityGroupInfo':
+ list(sorted(groups,
+ key=lambda k: (k['ownerId'], k['groupName'])))}
def _format_security_group(self, context, group):
g = {}
@@ -512,8 +514,11 @@ class CloudController(object):
def get_console_output(self, context, instance_id, **kwargs):
LOG.audit(_("Get console output for instance %s"), instance_id,
context=context)
- # instance_id is passed in as a list of instances
- ec2_id = instance_id[0]
+ # instance_id may be passed in as a list of instances
+ if type(instance_id) == list:
+ ec2_id = instance_id[0]
+ else:
+ ec2_id = instance_id
instance_id = ec2_id_to_id(ec2_id)
output = self.compute_api.get_console_output(
context, instance_id=instance_id)
@@ -836,11 +841,26 @@ class CloudController(object):
self.compute_api.update(context, instance_id=instance_id, **kwargs)
return True
+ def _format_image(self, context, image):
+ """Convert from format defined by BaseImageService to S3 format."""
+ i = {}
+ i['imageId'] = image.get('id')
+ i['kernelId'] = image.get('kernel_id')
+ i['ramdiskId'] = image.get('ramdisk_id')
+ i['imageOwnerId'] = image.get('owner_id')
+ i['imageLocation'] = image.get('location')
+ i['imageState'] = image.get('status')
+ i['type'] = image.get('type')
+ i['isPublic'] = image.get('is_public')
+ i['architecture'] = image.get('architecture')
+ return i
+
def describe_images(self, context, image_id=None, **kwargs):
- # Note: image_id is a list!
+ # NOTE: image_id is a list!
images = self.image_service.index(context)
if image_id:
- images = filter(lambda x: x['imageId'] in image_id, images)
+ images = filter(lambda x: x['id'] in image_id, images)
+ images = [self._format_image(context, i) for i in images]
return {'imagesSet': images}
def deregister_image(self, context, image_id, **kwargs):
@@ -863,6 +883,9 @@ class CloudController(object):
% attribute)
try:
image = self.image_service.show(context, image_id)
+ image = self._format_image(context,
+ self.image_service.show(context,
+ image_id))
except IndexError:
raise exception.ApiError(_('invalid id: %s') % image_id)
result = {'image_id': image_id, 'launchPermission': []}
diff --git a/nova/api/openstack/__init__.py b/nova/api/openstack/__init__.py
index c70bb39ed..dc3738d4a 100644
--- a/nova/api/openstack/__init__.py
+++ b/nova/api/openstack/__init__.py
@@ -51,8 +51,8 @@ class FaultWrapper(wsgi.Middleware):
try:
return req.get_response(self.application)
except Exception as ex:
- LOG.exception(_("Caught error: %s"), str(ex))
- exc = webob.exc.HTTPInternalServerError(explanation=str(ex))
+ LOG.exception(_("Caught error: %s"), unicode(ex))
+ exc = webob.exc.HTTPInternalServerError(explanation=unicode(ex))
return faults.Fault(exc)
@@ -79,6 +79,7 @@ class APIRouter(wsgi.Router):
server_members["actions"] = "GET"
server_members['suspend'] = 'POST'
server_members['resume'] = 'POST'
+ server_members['reset_network'] = 'POST'
mapper.resource("server", "servers", controller=servers.Controller(),
collection={'detail': 'GET'},
diff --git a/nova/api/openstack/common.py b/nova/api/openstack/common.py
index 6d2fa16e8..1dc3767e2 100644
--- a/nova/api/openstack/common.py
+++ b/nova/api/openstack/common.py
@@ -18,22 +18,29 @@
from nova import exception
-def limited(items, req):
- """Return a slice of items according to requested offset and limit.
-
- items - a sliceable
- req - wobob.Request possibly containing offset and limit GET variables.
- offset is where to start in the list, and limit is the maximum number
- of items to return.
+def limited(items, request, max_limit=1000):
+ """
+ Return a slice of items according to requested offset and limit.
- If limit is not specified, 0, or > 1000, defaults to 1000.
+ @param items: A sliceable entity
+ @param request: `webob.Request` possibly containing 'offset' and 'limit'
+ GET variables. 'offset' is where to start in the list,
+ and 'limit' is the maximum number of items to return. If
+ 'limit' is not specified, 0, or > max_limit, we default
+ to max_limit.
+ @kwarg max_limit: The maximum number of items to return from 'items'
"""
+ try:
+ offset = int(request.GET.get('offset', 0))
+ except ValueError:
+ offset = 0
+
+ try:
+ limit = int(request.GET.get('limit', max_limit))
+ except ValueError:
+ limit = max_limit
- offset = int(req.GET.get('offset', 0))
- limit = int(req.GET.get('limit', 0))
- if not limit:
- limit = 1000
- limit = min(1000, limit)
+ limit = min(max_limit, limit or max_limit)
range_end = offset + limit
return items[offset:range_end]
diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/servers.py
index 17c5519a1..bed633da8 100644
--- a/nova/api/openstack/servers.py
+++ b/nova/api/openstack/servers.py
@@ -64,6 +64,22 @@ def _translate_detail_keys(inst):
inst_dict['status'] = power_mapping[inst_dict['status']]
inst_dict['addresses'] = dict(public=[], private=[])
+
+ # grab single private fixed ip
+ try:
+ private_ip = inst['fixed_ip']['address']
+ if private_ip:
+ inst_dict['addresses']['private'].append(private_ip)
+ except KeyError:
+ LOG.debug(_("Failed to read private ip"))
+
+ # grab all public floating ips
+ try:
+ for floating in inst['fixed_ip']['floating_ips']:
+ inst_dict['addresses']['public'].append(floating['address'])
+ except KeyError:
+ LOG.debug(_("Failed to read public ip(s)"))
+
inst_dict['metadata'] = {}
inst_dict['hostId'] = ''
@@ -163,7 +179,8 @@ class Controller(wsgi.Controller):
display_name=env['server']['name'],
display_description=env['server']['name'],
key_name=key_pair['name'],
- key_data=key_pair['public_key'])
+ key_data=key_pair['public_key'],
+ onset_files=env.get('onset_files', []))
return _translate_keys(instances[0])
def update(self, req, id):
@@ -249,6 +266,20 @@ class Controller(wsgi.Controller):
return faults.Fault(exc.HTTPUnprocessableEntity())
return exc.HTTPAccepted()
+ def reset_network(self, req, id):
+ """
+ Reset networking on an instance (admin only).
+
+ """
+ context = req.environ['nova.context']
+ try:
+ self.compute_api.reset_network(context, id)
+ except:
+ readable = traceback.format_exc()
+ LOG.exception(_("Compute.api::reset_network %s"), readable)
+ return faults.Fault(exc.HTTPUnprocessableEntity())
+ return exc.HTTPAccepted()
+
def pause(self, req, id):
""" Permit Admins to Pause the server. """
ctxt = req.environ['nova.context']