summaryrefslogtreecommitdiffstats
path: root/nova/api
diff options
context:
space:
mode:
authorBrian Waldon <brian.waldon@rackspace.com>2011-04-30 07:16:27 -0400
committerBrian Waldon <brian.waldon@rackspace.com>2011-04-30 07:16:27 -0400
commitdb81474a8b67334d88173ea2d93e57a113d4af06 (patch)
tree061fe026fe247ff8e5ae31fd9eb7aafc23295580 /nova/api
parent721fafcfe0679e21fc4f60ec9fa0cfb5dcc468b1 (diff)
parent757709eeaed44ac315d4767620636773ac7f8804 (diff)
merging trunk
Diffstat (limited to 'nova/api')
-rw-r--r--nova/api/ec2/__init__.py10
-rw-r--r--nova/api/ec2/admin.py2
-rw-r--r--nova/api/ec2/apirequest.py2
-rw-r--r--nova/api/ec2/cloud.py54
-rw-r--r--nova/api/ec2/ec2utils.py5
-rw-r--r--nova/api/openstack/accounts.py2
-rw-r--r--nova/api/openstack/auth.py20
-rw-r--r--nova/api/openstack/common.py14
-rw-r--r--nova/api/openstack/contrib/volumes.py3
-rw-r--r--nova/api/openstack/server_metadata.py29
-rw-r--r--nova/api/openstack/servers.py64
-rw-r--r--nova/api/openstack/users.py2
12 files changed, 122 insertions, 85 deletions
diff --git a/nova/api/ec2/__init__.py b/nova/api/ec2/__init__.py
index a3c3b25a1..cd59340bd 100644
--- a/nova/api/ec2/__init__.py
+++ b/nova/api/ec2/__init__.py
@@ -46,8 +46,6 @@ flags.DEFINE_integer('lockout_minutes', 15,
'Number of minutes to lockout if triggered.')
flags.DEFINE_integer('lockout_window', 15,
'Number of minutes for lockout window.')
-flags.DEFINE_list('lockout_memcached_servers', None,
- 'Memcached servers or None for in process cache.')
class RequestLogging(wsgi.Middleware):
@@ -107,11 +105,11 @@ class Lockout(wsgi.Middleware):
def __init__(self, application):
"""middleware can use fake for testing."""
- if FLAGS.lockout_memcached_servers:
+ if FLAGS.memcached_servers:
import memcache
else:
from nova import fakememcache as memcache
- self.mc = memcache.Client(FLAGS.lockout_memcached_servers,
+ self.mc = memcache.Client(FLAGS.memcached_servers,
debug=0)
super(Lockout, self).__init__(application)
@@ -322,9 +320,7 @@ class Executor(wsgi.Application):
except exception.InstanceNotFound as ex:
LOG.info(_('InstanceNotFound raised: %s'), unicode(ex),
context=context)
- ec2_id = ec2utils.id_to_ec2_id(ex.instance_id)
- message = _('Instance %s not found') % ec2_id
- return self._error(req, context, type(ex).__name__, message)
+ return self._error(req, context, type(ex).__name__, ex.message)
except exception.VolumeNotFound as ex:
LOG.info(_('VolumeNotFound raised: %s'), unicode(ex),
context=context)
diff --git a/nova/api/ec2/admin.py b/nova/api/ec2/admin.py
index 6a5609d4a..ea94d9c1f 100644
--- a/nova/api/ec2/admin.py
+++ b/nova/api/ec2/admin.py
@@ -266,7 +266,7 @@ class AdminController(object):
def _vpn_for(self, context, project_id):
"""Get the VPN instance for a project ID."""
for instance in db.instance_get_all_by_project(context, project_id):
- if (instance['image_id'] == FLAGS.vpn_image_id
+ if (instance['image_id'] == str(FLAGS.vpn_image_id)
and not instance['state_description'] in
['shutting_down', 'shutdown']):
return instance
diff --git a/nova/api/ec2/apirequest.py b/nova/api/ec2/apirequest.py
index d7ad08d2f..6672e60bb 100644
--- a/nova/api/ec2/apirequest.py
+++ b/nova/api/ec2/apirequest.py
@@ -196,7 +196,7 @@ class APIRequest(object):
elif isinstance(data, datetime.datetime):
data_el.appendChild(
xml.createTextNode(_database_to_isoformat(data)))
- elif data != None:
+ elif data is not None:
data_el.appendChild(xml.createTextNode(str(data)))
return data_el
diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py
index 10b1d0ac5..092b80fa2 100644
--- a/nova/api/ec2/cloud.py
+++ b/nova/api/ec2/cloud.py
@@ -49,8 +49,6 @@ flags.DECLARE('service_down_time', 'nova.scheduler.driver')
LOG = logging.getLogger("nova.api.cloud")
-InvalidInputException = exception.InvalidInputException
-
def _gen_key(context, user_id, key_name):
"""Generate a key
@@ -61,8 +59,7 @@ def _gen_key(context, user_id, key_name):
# creation before creating key_pair
try:
db.key_pair_get(context, user_id, key_name)
- raise exception.Duplicate(_("The key_pair %s already exists")
- % key_name)
+ raise exception.KeyPairExists(key_name=key_name)
except exception.NotFound:
pass
private_key, public_key, fingerprint = crypto.generate_key_pair()
@@ -159,7 +156,7 @@ class CloudController(object):
floating_ip = db.instance_get_floating_address(ctxt,
instance_ref['id'])
ec2_id = ec2utils.id_to_ec2_id(instance_ref['id'])
- image_ec2_id = self._image_ec2_id(instance_ref['image_id'], 'ami')
+ image_ec2_id = self.image_ec2_id(instance_ref['image_id'])
data = {
'user-data': base64.b64decode(instance_ref['user_data']),
'meta-data': {
@@ -187,9 +184,9 @@ class CloudController(object):
'mpi': mpi}}
for image_type in ['kernel', 'ramdisk']:
- if '%s_id' % image_type in instance_ref:
- ec2_id = self._image_ec2_id(instance_ref['%s_id' % image_type],
- self._image_type(image_type))
+ if instance_ref.get('%s_id' % image_type):
+ ec2_id = self.image_ec2_id(instance_ref['%s_id' % image_type],
+ self._image_type(image_type))
data['meta-data']['%s-id' % image_type] = ec2_id
if False: # TODO(vish): store ancestor ids
@@ -399,11 +396,11 @@ class CloudController(object):
ip_protocol = str(ip_protocol)
if ip_protocol.upper() not in ['TCP', 'UDP', 'ICMP']:
- raise InvalidInputException(_('%s is not a valid ipProtocol') %
- (ip_protocol,))
+ raise exception.InvalidIpProtocol(protocol=ip_protocol)
if ((min(from_port, to_port) < -1) or
(max(from_port, to_port) > 65535)):
- raise InvalidInputException(_('Invalid port range'))
+ raise exception.InvalidPortRange(from_port=from_port,
+ to_port=to_port)
values['protocol'] = ip_protocol
values['from_port'] = from_port
@@ -442,7 +439,7 @@ class CloudController(object):
group_name)
criteria = self._revoke_rule_args_to_dict(context, **kwargs)
- if criteria == None:
+ if criteria is None:
raise exception.ApiError(_("Not enough parameters to build a "
"valid rule."))
@@ -613,7 +610,7 @@ class CloudController(object):
# TODO(vish): Instance should be None at db layer instead of
# trying to lazy load, but for now we turn it into
# a dict to avoid an error.
- return {'volumeSet': [self._format_volume(context, dict(volume))]}
+ return self._format_volume(context, dict(volume))
def delete_volume(self, context, volume_id, **kwargs):
volume_id = ec2utils.ec2_id_to_id(volume_id)
@@ -664,7 +661,7 @@ class CloudController(object):
'volumeId': ec2utils.id_to_ec2_id(volume_id, 'vol-%08x')}
def _convert_to_set(self, lst, label):
- if lst == None or lst == []:
+ if lst is None or lst == []:
return None
if not isinstance(lst, list):
lst = [lst]
@@ -703,13 +700,13 @@ class CloudController(object):
instances = self.compute_api.get_all(context, **kwargs)
for instance in instances:
if not context.is_admin:
- if instance['image_id'] == FLAGS.vpn_image_id:
+ if instance['image_id'] == str(FLAGS.vpn_image_id):
continue
i = {}
instance_id = instance['id']
ec2_id = ec2utils.id_to_ec2_id(instance_id)
i['instanceId'] = ec2_id
- i['imageId'] = self._image_ec2_id(instance['image_id'])
+ i['imageId'] = self.image_ec2_id(instance['image_id'])
i['instanceState'] = {
'code': instance['state'],
'name': instance['state_description']}
@@ -726,7 +723,9 @@ class CloudController(object):
instance['mac_address'])
i['privateDnsName'] = fixed_addr
+ i['privateIpAddress'] = fixed_addr
i['publicDnsName'] = floating_addr
+ i['ipAddress'] = floating_addr or fixed_addr
i['dnsName'] = i['publicDnsName'] or i['privateDnsName']
i['keyName'] = instance['key_name']
@@ -898,7 +897,7 @@ class CloudController(object):
return image_type
@staticmethod
- def _image_ec2_id(image_id, image_type='ami'):
+ def image_ec2_id(image_id, image_type='ami'):
"""Returns image ec2_id using id and three letter type."""
template = image_type + '-%08x'
return ec2utils.id_to_ec2_id(int(image_id), template=template)
@@ -907,25 +906,25 @@ class CloudController(object):
try:
internal_id = ec2utils.ec2_id_to_id(ec2_id)
return self.image_service.show(context, internal_id)
- except exception.NotFound:
+ except ValueError:
try:
return self.image_service.show_by_name(context, ec2_id)
except exception.NotFound:
- raise exception.NotFound(_('Image %s not found') % ec2_id)
+ raise exception.ImageNotFound(image_id=ec2_id)
def _format_image(self, image):
"""Convert from format defined by BaseImageService to S3 format."""
i = {}
image_type = self._image_type(image.get('container_format'))
- ec2_id = self._image_ec2_id(image.get('id'), image_type)
+ ec2_id = self.image_ec2_id(image.get('id'), image_type)
name = image.get('name')
i['imageId'] = ec2_id
kernel_id = image['properties'].get('kernel_id')
if kernel_id:
- i['kernelId'] = self._image_ec2_id(kernel_id, 'aki')
+ i['kernelId'] = self.image_ec2_id(kernel_id, 'aki')
ramdisk_id = image['properties'].get('ramdisk_id')
if ramdisk_id:
- i['ramdiskId'] = self._image_ec2_id(ramdisk_id, 'ari')
+ i['ramdiskId'] = self.image_ec2_id(ramdisk_id, 'ari')
i['imageOwnerId'] = image['properties'].get('owner_id')
if name:
i['imageLocation'] = "%s (%s)" % (image['properties'].
@@ -955,8 +954,7 @@ class CloudController(object):
try:
image = self._get_image(context, ec2_id)
except exception.NotFound:
- raise exception.NotFound(_('Image %s not found') %
- ec2_id)
+ raise exception.ImageNotFound(image_id=ec2_id)
images.append(image)
else:
images = self.image_service.detail(context)
@@ -976,8 +974,8 @@ class CloudController(object):
metadata = {'properties': {'image_location': image_location}}
image = self.image_service.create(context, metadata)
image_type = self._image_type(image.get('container_format'))
- image_id = self._image_ec2_id(image['id'],
- image_type)
+ image_id = self.image_ec2_id(image['id'],
+ image_type)
msg = _("Registered image %(image_location)s with"
" id %(image_id)s") % locals()
LOG.audit(msg, context=context)
@@ -990,7 +988,7 @@ class CloudController(object):
try:
image = self._get_image(context, image_id)
except exception.NotFound:
- raise exception.NotFound(_('Image %s not found') % image_id)
+ raise exception.ImageNotFound(image_id=image_id)
result = {'imageId': image_id, 'launchPermission': []}
if image['is_public']:
result['launchPermission'].append({'group': 'all'})
@@ -1013,7 +1011,7 @@ class CloudController(object):
try:
image = self._get_image(context, image_id)
except exception.NotFound:
- raise exception.NotFound(_('Image %s not found') % image_id)
+ raise exception.ImageNotFound(image_id=image_id)
internal_id = image['id']
del(image['id'])
diff --git a/nova/api/ec2/ec2utils.py b/nova/api/ec2/ec2utils.py
index 3b34f6ea5..1ac48163c 100644
--- a/nova/api/ec2/ec2utils.py
+++ b/nova/api/ec2/ec2utils.py
@@ -21,10 +21,7 @@ from nova import exception
def ec2_id_to_id(ec2_id):
"""Convert an ec2 ID (i-[base 16 number]) to an instance id (int)"""
- try:
- return int(ec2_id.split('-')[-1], 16)
- except ValueError:
- raise exception.NotFound(_("Id %s Not Found") % ec2_id)
+ return int(ec2_id.split('-')[-1], 16)
def id_to_ec2_id(instance_id, template='i-%08x'):
diff --git a/nova/api/openstack/accounts.py b/nova/api/openstack/accounts.py
index 6e3763e47..00fdd4540 100644
--- a/nova/api/openstack/accounts.py
+++ b/nova/api/openstack/accounts.py
@@ -48,7 +48,7 @@ class Controller(common.OpenstackController):
"""We cannot depend on the db layer to check for admin access
for the auth manager, so we do it here"""
if not context.is_admin:
- raise exception.NotAuthorized(_("Not admin user."))
+ raise exception.AdminRequired()
def index(self, req):
raise faults.Fault(webob.exc.HTTPNotImplemented())
diff --git a/nova/api/openstack/auth.py b/nova/api/openstack/auth.py
index f3a9bdeca..311e6bde9 100644
--- a/nova/api/openstack/auth.py
+++ b/nova/api/openstack/auth.py
@@ -55,6 +55,9 @@ class AuthMiddleware(wsgi.Middleware):
user = self.get_user_by_authentication(req)
accounts = self.auth.get_projects(user=user)
if not user:
+ token = req.headers["X-Auth-Token"]
+ msg = _("%(user)s could not be found with token '%(token)s'")
+ LOG.warn(msg % locals())
return faults.Fault(webob.exc.HTTPUnauthorized())
if accounts:
@@ -66,6 +69,8 @@ class AuthMiddleware(wsgi.Middleware):
if not self.auth.is_admin(user) and \
not self.auth.is_project_member(user, account):
+ msg = _("%(user)s must be an admin or a member of %(account)s")
+ LOG.warn(msg % locals())
return faults.Fault(webob.exc.HTTPUnauthorized())
req.environ['nova.context'] = context.RequestContext(user, account)
@@ -82,12 +87,16 @@ class AuthMiddleware(wsgi.Middleware):
# honor it
path_info = req.path_info
if len(path_info) > 1:
- return faults.Fault(webob.exc.HTTPUnauthorized())
+ msg = _("Authentication requests must be made against a version "
+ "root (e.g. /v1.0 or /v1.1).")
+ LOG.warn(msg)
+ return faults.Fault(webob.exc.HTTPUnauthorized(explanation=msg))
try:
username = req.headers['X-Auth-User']
key = req.headers['X-Auth-Key']
- except KeyError:
+ except KeyError as ex:
+ LOG.warn(_("Could not find %s in request.") % ex)
return faults.Fault(webob.exc.HTTPUnauthorized())
token, user = self._authorize_user(username, key, req)
@@ -100,6 +109,7 @@ class AuthMiddleware(wsgi.Middleware):
res.headers['X-CDN-Management-Url'] = token.cdn_management_url
res.content_type = 'text/plain'
res.status = '204'
+ LOG.debug(_("Successfully authenticated '%s'") % username)
return res
else:
return faults.Fault(webob.exc.HTTPUnauthorized())
@@ -139,6 +149,7 @@ class AuthMiddleware(wsgi.Middleware):
try:
user = self.auth.get_user_from_access_key(key)
except exception.NotFound:
+ LOG.warn(_("User not found with provided API key."))
user = None
if user and user.name == username:
@@ -153,4 +164,9 @@ class AuthMiddleware(wsgi.Middleware):
token_dict['user_id'] = user.id
token = self.db.auth_token_create(ctxt, token_dict)
return token, user
+ elif user and user.name != username:
+ msg = _("Provided API key is valid, but not for user "
+ "'%(username)s'") % locals()
+ LOG.warn(msg)
+
return None, None
diff --git a/nova/api/openstack/common.py b/nova/api/openstack/common.py
index 234f921ab..65ed1e143 100644
--- a/nova/api/openstack/common.py
+++ b/nova/api/openstack/common.py
@@ -25,7 +25,7 @@ from nova import log as logging
from nova import wsgi
-LOG = logging.getLogger('common')
+LOG = logging.getLogger('nova.api.openstack.common')
FLAGS = flags.FLAGS
@@ -116,9 +116,15 @@ def get_image_id_from_image_hash(image_service, context, image_hash):
items = image_service.index(context)
for image in items:
image_id = image['id']
- if abs(hash(image_id)) == int(image_hash):
- return image_id
- raise exception.NotFound(image_hash)
+ try:
+ if abs(hash(image_id)) == int(image_hash):
+ return image_id
+ except ValueError:
+ msg = _("Requested image_id has wrong format: %s,"
+ "should have numerical format") % image_id
+ LOG.error(msg)
+ raise Exception(msg)
+ raise exception.ImageNotFound(image_id=image_hash)
def get_id_from_href(href):
diff --git a/nova/api/openstack/contrib/volumes.py b/nova/api/openstack/contrib/volumes.py
index 6efacce52..18de2ec71 100644
--- a/nova/api/openstack/contrib/volumes.py
+++ b/nova/api/openstack/contrib/volumes.py
@@ -322,8 +322,7 @@ class Volumes(extensions.ExtensionDescriptor):
# Does this matter?
res = extensions.ResourceExtension('volumes',
VolumeController(),
- collection_actions={'detail': 'GET'}
- )
+ collection_actions={'detail': 'GET'})
resources.append(res)
res = extensions.ResourceExtension('volume_attachments',
diff --git a/nova/api/openstack/server_metadata.py b/nova/api/openstack/server_metadata.py
index 5c1390b9c..fd64ee4fb 100644
--- a/nova/api/openstack/server_metadata.py
+++ b/nova/api/openstack/server_metadata.py
@@ -18,6 +18,7 @@
from webob import exc
from nova import compute
+from nova import quota
from nova import wsgi
from nova.api.openstack import common
from nova.api.openstack import faults
@@ -44,10 +45,14 @@ class Controller(common.OpenstackController):
def create(self, req, server_id):
context = req.environ['nova.context']
- body = self._deserialize(req.body, req.get_content_type())
- self.compute_api.update_or_create_instance_metadata(context,
- server_id,
- body['metadata'])
+ data = self._deserialize(req.body, req.get_content_type())
+ metadata = data.get('metadata')
+ try:
+ self.compute_api.update_or_create_instance_metadata(context,
+ server_id,
+ metadata)
+ except quota.QuotaError as error:
+ self._handle_quota_error(error)
return req.body
def update(self, req, server_id, id):
@@ -59,9 +64,13 @@ class Controller(common.OpenstackController):
if len(body) > 1:
expl = _('Request body contains too many items')
raise exc.HTTPBadRequest(explanation=expl)
- self.compute_api.update_or_create_instance_metadata(context,
- server_id,
- body)
+ try:
+ self.compute_api.update_or_create_instance_metadata(context,
+ server_id,
+ body)
+ except quota.QuotaError as error:
+ self._handle_quota_error(error)
+
return req.body
def show(self, req, server_id, id):
@@ -77,3 +86,9 @@ class Controller(common.OpenstackController):
""" Deletes an existing metadata """
context = req.environ['nova.context']
self.compute_api.delete_instance_metadata(context, server_id, id)
+
+ def _handle_quota_error(self, error):
+ """Reraise quota errors as api-specific http exceptions."""
+ if error.code == "MetadataLimitExceeded":
+ raise exc.HTTPBadRequest(explanation=error.message)
+ raise error
diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/servers.py
index 43e0c7963..9b883f06b 100644
--- a/nova/api/openstack/servers.py
+++ b/nova/api/openstack/servers.py
@@ -40,7 +40,7 @@ import nova.api.openstack
from nova.scheduler import api as scheduler_api
-LOG = logging.getLogger('server')
+LOG = logging.getLogger('nova.api.openstack.servers')
FLAGS = flags.FLAGS
@@ -118,6 +118,8 @@ class Controller(common.OpenstackController):
context = req.environ['nova.context']
+ password = self._get_server_admin_password(env['server'])
+
key_name = None
key_data = None
key_pairs = auth_manager.AuthManager.get_key_pairs(context)
@@ -127,21 +129,16 @@ class Controller(common.OpenstackController):
key_data = key_pair['public_key']
requested_image_id = self._image_id_from_req_data(env)
- image_id = common.get_image_id_from_image_hash(self._image_service,
- context, requested_image_id)
+ try:
+ image_id = common.get_image_id_from_image_hash(self._image_service,
+ context, requested_image_id)
+ except:
+ msg = _("Can not find requested image")
+ return faults.Fault(exc.HTTPBadRequest(msg))
+
kernel_id, ramdisk_id = self._get_kernel_ramdisk_from_image(
req, image_id)
- # Metadata is a list, not a Dictionary, because we allow duplicate keys
- # (even though JSON can't encode this)
- # In future, we may not allow duplicate keys.
- # However, the CloudServers API is not definitive on this front,
- # and we want to be compatible.
- metadata = []
- if env['server'].get('metadata'):
- for k, v in env['server']['metadata'].items():
- metadata.append({'key': k, 'value': v})
-
personality = env['server'].get('personality')
injected_files = []
if personality:
@@ -170,7 +167,7 @@ class Controller(common.OpenstackController):
display_description=name,
key_name=key_name,
key_data=key_data,
- metadata=metadata,
+ metadata=env['server'].get('metadata', {}),
injected_files=injected_files)
except quota.QuotaError as error:
self._handle_quota_error(error)
@@ -180,7 +177,6 @@ class Controller(common.OpenstackController):
builder = self._get_view_builder(req)
server = builder.build(inst, is_detail=True)
- password = utils.generate_password(16)
server['server']['adminPass'] = password
self.compute_api.set_admin_password(context, server['server']['id'],
password)
@@ -242,6 +238,10 @@ class Controller(common.OpenstackController):
# if the original error is okay, just reraise it
raise error
+ def _get_server_admin_password(self, server):
+ """ Determine the admin password for a server on creation """
+ return utils.generate_password(16)
+
@scheduler_api.redirect_handler
def update(self, req, id):
""" Updates the server name or password """
@@ -321,6 +321,7 @@ class Controller(common.OpenstackController):
return exc.HTTPAccepted()
def _action_rebuild(self, input_dict, req, id):
+ LOG.debug(_("Rebuild server action is not implemented"))
return faults.Fault(exc.HTTPNotImplemented())
def _action_resize(self, input_dict, req, id):
@@ -336,18 +337,20 @@ class Controller(common.OpenstackController):
except Exception, e:
LOG.exception(_("Error in resize %s"), e)
return faults.Fault(exc.HTTPBadRequest())
- return faults.Fault(exc.HTTPAccepted())
+ return exc.HTTPAccepted()
def _action_reboot(self, input_dict, req, id):
- try:
+ if 'reboot' in input_dict and 'type' in input_dict['reboot']:
reboot_type = input_dict['reboot']['type']
- except Exception:
- raise faults.Fault(exc.HTTPNotImplemented())
+ else:
+ LOG.exception(_("Missing argument 'type' for reboot"))
+ return faults.Fault(exc.HTTPUnprocessableEntity())
try:
# TODO(gundlach): pass reboot_type, support soft reboot in
# virt driver
self.compute_api.reboot(req.environ['nova.context'], id)
- except:
+ except Exception, e:
+ LOG.exception(_("Error in reboot %s"), e)
return faults.Fault(exc.HTTPUnprocessableEntity())
return exc.HTTPAccepted()
@@ -561,9 +564,8 @@ class Controller(common.OpenstackController):
"""
image_id = image_meta['id']
if image_meta['status'] != 'active':
- raise exception.Invalid(
- _("Cannot build from image %(image_id)s, status not active") %
- locals())
+ raise exception.ImageUnacceptable(image_id=image_id,
+ reason=_("status is not active"))
if image_meta.get('container_format') != 'ami':
return None, None
@@ -571,14 +573,12 @@ class Controller(common.OpenstackController):
try:
kernel_id = image_meta['properties']['kernel_id']
except KeyError:
- raise exception.NotFound(
- _("Kernel not found for image %(image_id)s") % locals())
+ raise exception.KernelNotFoundForImage(image_id=image_id)
try:
ramdisk_id = image_meta['properties']['ramdisk_id']
except KeyError:
- raise exception.NotFound(
- _("Ramdisk not found for image %(image_id)s") % locals())
+ raise exception.RamdiskNotFoundForImage(image_id=image_id)
return kernel_id, ramdisk_id
@@ -648,6 +648,16 @@ class ControllerV11(Controller):
def _limit_items(self, items, req):
return common.limited_by_marker(items, req)
+ def _get_server_admin_password(self, server):
+ """ Determine the admin password for a server on creation """
+ password = server.get('adminPass')
+ if password is None:
+ return utils.generate_password(16)
+ if not isinstance(password, basestring) or password == '':
+ msg = _("Invalid adminPass")
+ raise exc.HTTPBadRequest(msg)
+ return password
+
def get_default_xmlns(self, req):
return common.XML_NS_V11
diff --git a/nova/api/openstack/users.py b/nova/api/openstack/users.py
index 077ccfc79..7ae4c3232 100644
--- a/nova/api/openstack/users.py
+++ b/nova/api/openstack/users.py
@@ -48,7 +48,7 @@ class Controller(common.OpenstackController):
"""We cannot depend on the db layer to check for admin access
for the auth manager, so we do it here"""
if not context.is_admin:
- raise exception.NotAuthorized(_("Not admin user"))
+ raise exception.AdminRequired()
def index(self, req):
"""Return all users in brief"""