summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2012-01-24 19:32:49 +0000
committerGerrit Code Review <review@openstack.org>2012-01-24 19:32:49 +0000
commit8dfd968e83cbcdc0796caa44289144d38a6a5ce8 (patch)
treee0e2e571a9aae49fc71736ad034d8fb6ed31b0b0
parentc88771d8202f9c1c3f7a7260dea200d902b3c3aa (diff)
parent9cb5f547dc6f3242edf393928dbc14b7cbfbbdd4 (diff)
downloadnova-8dfd968e83cbcdc0796caa44289144d38a6a5ce8.tar.gz
nova-8dfd968e83cbcdc0796caa44289144d38a6a5ce8.tar.xz
nova-8dfd968e83cbcdc0796caa44289144d38a6a5ce8.zip
Merge "Remove admin_only ext attr in favor of authz"
-rw-r--r--doc/source/devref/distributed_scheduler.rst2
-rw-r--r--doc/source/devref/zone.rst2
-rw-r--r--etc/nova/policy.json32
-rw-r--r--nova/api/mapper.py3
-rw-r--r--nova/api/openstack/compute/__init__.py3
-rw-r--r--nova/api/openstack/compute/contrib/accounts.py17
-rw-r--r--nova/api/openstack/compute/contrib/admin_actions.py12
-rw-r--r--nova/api/openstack/compute/contrib/cloudpipe.py6
-rw-r--r--nova/api/openstack/compute/contrib/console_output.py4
-rw-r--r--nova/api/openstack/compute/contrib/consoles.py2
-rw-r--r--nova/api/openstack/compute/contrib/createserverext.py7
-rw-r--r--nova/api/openstack/compute/contrib/deferred_delete.py5
-rw-r--r--nova/api/openstack/compute/contrib/disk_config.py57
-rw-r--r--nova/api/openstack/compute/contrib/extended_status.py48
-rw-r--r--nova/api/openstack/compute/contrib/flavorextraspecs.py12
-rw-r--r--nova/api/openstack/compute/contrib/floating_ip_dns.py8
-rw-r--r--nova/api/openstack/compute/contrib/floating_ip_pools.py2
-rw-r--r--nova/api/openstack/compute/contrib/floating_ips.py7
-rw-r--r--nova/api/openstack/compute/contrib/hosts.py5
-rw-r--r--nova/api/openstack/compute/contrib/keypairs.py6
-rw-r--r--nova/api/openstack/compute/contrib/multinic.py7
-rw-r--r--nova/api/openstack/compute/contrib/networks.py6
-rw-r--r--nova/api/openstack/compute/contrib/quotas.py6
-rw-r--r--nova/api/openstack/compute/contrib/rescue.py3
-rw-r--r--nova/api/openstack/compute/contrib/security_groups.py9
-rw-r--r--nova/api/openstack/compute/contrib/server_action_list.py3
-rw-r--r--nova/api/openstack/compute/contrib/server_diagnostics.py3
-rw-r--r--nova/api/openstack/compute/contrib/simple_tenant_usage.py4
-rw-r--r--nova/api/openstack/compute/contrib/users.py16
-rw-r--r--nova/api/openstack/compute/contrib/virtual_interfaces.py2
-rw-r--r--nova/api/openstack/compute/contrib/virtual_storage_arrays.py15
-rw-r--r--nova/api/openstack/compute/contrib/volumes.py15
-rw-r--r--nova/api/openstack/compute/contrib/volumetypes.py16
-rw-r--r--nova/api/openstack/compute/contrib/zones.py15
-rw-r--r--nova/api/openstack/compute/servers.py2
-rw-r--r--nova/api/openstack/extensions.py33
-rw-r--r--nova/tests/api/openstack/compute/contrib/test_accounts.py8
-rw-r--r--nova/tests/api/openstack/compute/contrib/test_admin_actions.py6
-rw-r--r--nova/tests/api/openstack/compute/contrib/test_cloudpipe.py1
-rw-r--r--nova/tests/api/openstack/compute/contrib/test_deferred_delete.py3
-rw-r--r--nova/tests/api/openstack/compute/contrib/test_extendedstatus.py1
-rw-r--r--nova/tests/api/openstack/compute/contrib/test_hosts.py3
-rw-r--r--nova/tests/api/openstack/compute/contrib/test_networks.py1
-rw-r--r--nova/tests/api/openstack/compute/contrib/test_server_action_list.py1
-rw-r--r--nova/tests/api/openstack/compute/contrib/test_server_diagnostics.py1
-rw-r--r--nova/tests/api/openstack/compute/contrib/test_simple_tenant_usage.py1
-rw-r--r--nova/tests/api/openstack/compute/contrib/test_users.py8
-rw-r--r--nova/tests/api/openstack/compute/contrib/test_zones.py1
-rw-r--r--nova/tests/api/openstack/compute/test_extensions.py30
-rw-r--r--nova/tests/api/openstack/compute/test_servers.py67
-rw-r--r--nova/tests/policy.json32
51 files changed, 326 insertions, 233 deletions
diff --git a/doc/source/devref/distributed_scheduler.rst b/doc/source/devref/distributed_scheduler.rst
index 7a631d69f..a185095be 100644
--- a/doc/source/devref/distributed_scheduler.rst
+++ b/doc/source/devref/distributed_scheduler.rst
@@ -164,14 +164,12 @@ All this Zone and Distributed Scheduler stuff can seem a little daunting to conf
::
- --allow_admin_api=true
--enable_zone_routing=true
--zone_name=zone1
--build_plan_encryption_key=c286696d887c9aa0611bbb3e2025a45b
--scheduler_driver=nova.scheduler.base_scheduler.BaseScheduler
--default_host_filter=nova.scheduler.filters.AllHostsFilter
-`--allow_admin_api` must be set for OS API to enable the new `/zones/*` commands.
`--enable_zone_routing` must be set for OS API commands such as `create()`, `pause()` and `delete()` to get routed from Zone to Zone when looking for instances.
`--zone_name` is only required in child Zones. The default Zone name is `nova`, but you may want to name your child Zones something useful. Duplicate Zone names are not an issue.
`build_plan_encryption_key` is the SHA-256 key for encrypting/decrypting the Host information when it leaves a Zone. Be sure to change this key for each Zone you create. Do not duplicate keys.
diff --git a/doc/source/devref/zone.rst b/doc/source/devref/zone.rst
index 3dc0f80fd..241cbf46c 100644
--- a/doc/source/devref/zone.rst
+++ b/doc/source/devref/zone.rst
@@ -55,8 +55,6 @@ Zone administrative operations are usually done using python-novaclient_
.. _python-novaclient: https://github.com/rackspace/python-novaclient
-In order to use the Zone operations, be sure to enable administrator operations in OpenStack API by setting the `--allow_admin_api=true` flag.
-
Finally you need to enable Zone Forwarding. This will be used by the Distributed Scheduler initiative currently underway. Set `--enable_zone_routing=true` to enable this feature.
Find out about this Zone
diff --git a/etc/nova/policy.json b/etc/nova/policy.json
index 7d97c3be1..abf8908f6 100644
--- a/etc/nova/policy.json
+++ b/etc/nova/policy.json
@@ -9,6 +9,38 @@
"compute:get_all": [],
+ "admin_api": [["role:admin"]],
+ "compute_extension:accounts": [["rule:admin_api"]],
+ "compute_extension:admin_actions": [["rule:admin_api"]],
+ "compute_extension:cloudpipe": [],
+ "compute_extension:console_output": [],
+ "compute_extension:consoles": [],
+ "compute_extension:createserverext": [],
+ "compute_extension:deferred_delete": [],
+ "compute_extension:disk_config": [],
+ "compute_extension:extended_status": [["rule:admin_api"]],
+ "compute_extension:flavorextraspecs": [],
+ "compute_extension:floating_ip_dns": [],
+ "compute_extension:floating_ip_pools": [],
+ "compute_extension:floating_ips": [],
+ "compute_extension:hosts": [["rule:admin_api"]],
+ "compute_extension:keypairs": [],
+ "compute_extension:multinic": [],
+ "compute_extension:networks": [["rule:admin_api"]],
+ "compute_extension:quotas": [],
+ "compute_extension:rescue": [],
+ "compute_extension:security_groups": [],
+ "compute_extension:server_action_list": [["rule:admin_api"]],
+ "compute_extension:server_diagnostics": [["rule:admin_api"]],
+ "compute_extension:simple_tenant_usage": [["rule:admin_api"]],
+ "compute_extension:users": [["rule:admin_api"]],
+ "compute_extension:virtual_interfaces": [],
+ "compute_extension:virtual_storage_arrays": [],
+ "compute_extension:volumes": [],
+ "compute_extension:volumetypes": [],
+ "compute_extension:zones": [],
+
+
"volume:create": [],
"volume:get_all": [],
"volume:get_volume_metadata": [],
diff --git a/nova/api/mapper.py b/nova/api/mapper.py
index cd26e06ee..aaa59f97f 100644
--- a/nova/api/mapper.py
+++ b/nova/api/mapper.py
@@ -32,9 +32,6 @@ from nova import wsgi as base_wsgi
LOG = logging.getLogger('nova.api.openstack.compute')
FLAGS = flags.FLAGS
-flags.DEFINE_bool('allow_admin_api',
- False,
- 'When True, this API service will accept admin operations.')
flags.DEFINE_bool('allow_instance_snapshots',
True,
'When True, this API service will permit instance snapshot operations.')
diff --git a/nova/api/openstack/compute/__init__.py b/nova/api/openstack/compute/__init__.py
index 9e0509e71..f074ac941 100644
--- a/nova/api/openstack/compute/__init__.py
+++ b/nova/api/openstack/compute/__init__.py
@@ -42,9 +42,6 @@ from nova import wsgi as base_wsgi
LOG = logging.getLogger('nova.api.openstack.compute')
FLAGS = flags.FLAGS
-flags.DEFINE_bool('allow_admin_api',
- False,
- 'When True, this API service will accept admin operations.')
flags.DEFINE_bool('allow_instance_snapshots',
True,
'When True, this API service will permit instance snapshot operations.')
diff --git a/nova/api/openstack/compute/contrib/accounts.py b/nova/api/openstack/compute/contrib/accounts.py
index 9253c037d..939912942 100644
--- a/nova/api/openstack/compute/contrib/accounts.py
+++ b/nova/api/openstack/compute/contrib/accounts.py
@@ -26,6 +26,7 @@ from nova import log as logging
FLAGS = flags.FLAGS
LOG = logging.getLogger('nova.api.openstack.compute.contrib.accounts')
+authorize = extensions.extension_authorizer('compute', 'accounts')
class AccountTemplate(xmlutil.TemplateBuilder):
@@ -51,23 +52,18 @@ class Controller(object):
def __init__(self):
self.manager = manager.AuthManager()
- def _check_admin(self, context):
- """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.AdminRequired()
-
def index(self, req):
raise webob.exc.HTTPNotImplemented()
@wsgi.serializers(xml=AccountTemplate)
def show(self, req, id):
"""Return data about the given account id"""
+ authorize(req.environ['nova.context'])
account = self.manager.get_project(id)
return dict(account=_translate_keys(account))
def delete(self, req, id):
- self._check_admin(req.environ['nova.context'])
+ authorize(req.environ['nova.context'])
self.manager.delete_project(id)
return {}
@@ -79,7 +75,7 @@ class Controller(object):
@wsgi.serializers(xml=AccountTemplate)
def update(self, req, id, body):
"""This is really create or update."""
- self._check_admin(req.environ['nova.context'])
+ authorize(req.environ['nova.context'])
description = body['account'].get('description')
manager = body['account'].get('manager')
try:
@@ -97,11 +93,8 @@ class Accounts(extensions.ExtensionDescriptor):
alias = "os-accounts"
namespace = "http://docs.openstack.org/compute/ext/accounts/api/v1.1"
updated = "2011-12-23T00:00:00+00:00"
- admin_only = True
def get_resources(self):
#TODO(bcwaldon): This should be prefixed with 'os-'
- res = extensions.ResourceExtension('accounts',
- Controller())
-
+ res = extensions.ResourceExtension('accounts', Controller())
return [res]
diff --git a/nova/api/openstack/compute/contrib/admin_actions.py b/nova/api/openstack/compute/contrib/admin_actions.py
index b44f16a1e..cbd54117d 100644
--- a/nova/api/openstack/compute/contrib/admin_actions.py
+++ b/nova/api/openstack/compute/contrib/admin_actions.py
@@ -30,6 +30,7 @@ from nova.scheduler import api as scheduler_api
FLAGS = flags.FLAGS
LOG = logging.getLogger("nova.api.openstack.compute.contrib.admin_actions")
+authorize = extensions.extension_authorizer('compute', 'admin_actions')
class AdminActionsController(wsgi.Controller):
@@ -45,6 +46,7 @@ class AdminActionsController(wsgi.Controller):
def _pause(self, req, id, body):
"""Permit Admins to pause the server"""
ctxt = req.environ['nova.context']
+ authorize(ctxt)
try:
server = self.compute_api.get(ctxt, id)
self.compute_api.pause(ctxt, server)
@@ -63,6 +65,7 @@ class AdminActionsController(wsgi.Controller):
def _unpause(self, req, id, body):
"""Permit Admins to unpause the server"""
ctxt = req.environ['nova.context']
+ authorize(ctxt)
try:
server = self.compute_api.get(ctxt, id)
self.compute_api.unpause(ctxt, server)
@@ -81,6 +84,7 @@ class AdminActionsController(wsgi.Controller):
def _suspend(self, req, id, body):
"""Permit admins to suspend the server"""
context = req.environ['nova.context']
+ authorize(context)
try:
server = self.compute_api.get(context, id)
self.compute_api.suspend(context, server)
@@ -99,6 +103,7 @@ class AdminActionsController(wsgi.Controller):
def _resume(self, req, id, body):
"""Permit admins to resume the server from suspend"""
context = req.environ['nova.context']
+ authorize(context)
try:
server = self.compute_api.get(context, id)
self.compute_api.resume(context, server)
@@ -117,6 +122,7 @@ class AdminActionsController(wsgi.Controller):
def _migrate(self, req, id, body):
"""Permit admins to migrate a server to a new host"""
context = req.environ['nova.context']
+ authorize(context)
try:
instance = self.compute_api.get(context, id)
self.compute_api.resize(req.environ['nova.context'], instance)
@@ -134,6 +140,7 @@ class AdminActionsController(wsgi.Controller):
def _reset_network(self, req, id, body):
"""Permit admins to reset networking on an server"""
context = req.environ['nova.context']
+ authorize(context)
try:
instance = self.compute_api.get(context, id)
self.compute_api.reset_network(context, instance)
@@ -149,6 +156,7 @@ class AdminActionsController(wsgi.Controller):
def _inject_network_info(self, req, id, body):
"""Permit admins to inject network info into a server"""
context = req.environ['nova.context']
+ authorize(context)
try:
instance = self.compute_api.get(context, id)
self.compute_api.inject_network_info(context, instance)
@@ -166,6 +174,7 @@ class AdminActionsController(wsgi.Controller):
def _lock(self, req, id, body):
"""Permit admins to lock a server"""
context = req.environ['nova.context']
+ authorize(context)
try:
instance = self.compute_api.get(context, id)
self.compute_api.lock(context, instance)
@@ -183,6 +192,7 @@ class AdminActionsController(wsgi.Controller):
def _unlock(self, req, id, body):
"""Permit admins to lock a server"""
context = req.environ['nova.context']
+ authorize(context)
try:
instance = self.compute_api.get(context, id)
self.compute_api.unlock(context, instance)
@@ -207,6 +217,7 @@ class AdminActionsController(wsgi.Controller):
"""
context = req.environ["nova.context"]
+ authorize(context)
try:
entity = body["createBackup"]
@@ -273,7 +284,6 @@ class Admin_actions(extensions.ExtensionDescriptor):
alias = "os-admin-actions"
namespace = "http://docs.openstack.org/compute/ext/admin-actions/api/v1.1"
updated = "2011-09-20T00:00:00+00:00"
- admin_only = True
def get_controller_extensions(self):
controller = AdminActionsController()
diff --git a/nova/api/openstack/compute/contrib/cloudpipe.py b/nova/api/openstack/compute/contrib/cloudpipe.py
index 17bfa810b..1cf47a2a9 100644
--- a/nova/api/openstack/compute/contrib/cloudpipe.py
+++ b/nova/api/openstack/compute/contrib/cloudpipe.py
@@ -32,6 +32,7 @@ from nova import utils
FLAGS = flags.FLAGS
LOG = logging.getLogger("nova.api.openstack.compute.contrib.cloudpipe")
+authorize = extensions.extension_authorizer('compute', 'cloudpipe')
class CloudpipeTemplate(xmlutil.TemplateBuilder):
@@ -120,6 +121,7 @@ class CloudpipeController(object):
"""
ctxt = req.environ['nova.context']
+ authorize(ctxt)
params = body.get('cloudpipe', {})
project_id = params.get('project_id', ctxt.project_id)
instance = self._get_cloudpipe_for_project(ctxt, project_id)
@@ -137,8 +139,9 @@ class CloudpipeController(object):
@wsgi.serializers(xml=CloudpipesTemplate)
def index(self, req):
- """Show admins the list of running cloudpipe instances."""
+ """List running cloudpipe instances."""
context = req.environ['nova.context']
+ authorize(context)
vpns = []
# TODO(todd): could use compute_api.get_all with admin context?
for project in self.auth_manager.get_projects():
@@ -162,7 +165,6 @@ class Cloudpipe(extensions.ExtensionDescriptor):
alias = "os-cloudpipe"
namespace = "http://docs.openstack.org/compute/ext/cloudpipe/api/v1.1"
updated = "2011-12-16T00:00:00+00:00"
- admin_only = True
def get_resources(self):
resources = []
diff --git a/nova/api/openstack/compute/contrib/console_output.py b/nova/api/openstack/compute/contrib/console_output.py
index ac578676e..04f975d5b 100644
--- a/nova/api/openstack/compute/contrib/console_output.py
+++ b/nova/api/openstack/compute/contrib/console_output.py
@@ -26,6 +26,7 @@ from nova.api.openstack import wsgi
LOG = logging.getLogger('nova.api.openstack.compute.contrib.console_output')
+authorize = extensions.extension_authorizer('compute', 'console_output')
class ConsoleOutputController(wsgi.Controller):
@@ -37,6 +38,7 @@ class ConsoleOutputController(wsgi.Controller):
def get_console_output(self, req, id, body):
"""Get text console output."""
context = req.environ['nova.context']
+ authorize(context)
try:
instance = self.compute_api.routing_get(context, id)
@@ -54,8 +56,6 @@ class ConsoleOutputController(wsgi.Controller):
length)
except exception.ApiError, e:
raise webob.exc.HTTPBadRequest(explanation=e.message)
- except exception.NotAuthorized, e:
- raise webob.exc.HTTPUnauthorized()
return {'output': output}
diff --git a/nova/api/openstack/compute/contrib/consoles.py b/nova/api/openstack/compute/contrib/consoles.py
index 46e3559ff..c3509e7a8 100644
--- a/nova/api/openstack/compute/contrib/consoles.py
+++ b/nova/api/openstack/compute/contrib/consoles.py
@@ -24,6 +24,7 @@ from nova.api.openstack import wsgi
LOG = logging.getLogger('nova.api.openstack.compute.contrib.console')
+authorize = extensions.extension_authorizer('compute', 'consoles')
class ConsolesController(wsgi.Controller):
@@ -35,6 +36,7 @@ class ConsolesController(wsgi.Controller):
def get_vnc_console(self, req, id, body):
"""Get text console output."""
context = req.environ['nova.context']
+ authorize(context)
console_type = body['os-getVNCConsole'].get('type')
diff --git a/nova/api/openstack/compute/contrib/createserverext.py b/nova/api/openstack/compute/contrib/createserverext.py
index 05b0c7d9c..de4ba8dd0 100644
--- a/nova/api/openstack/compute/contrib/createserverext.py
+++ b/nova/api/openstack/compute/contrib/createserverext.py
@@ -19,13 +19,18 @@ from nova.api.openstack.compute import servers
from nova.api.openstack.compute import views
+authorize = extensions.soft_extension_authorizer('compute', 'createserverext')
+
+
class ViewBuilder(views.servers.ViewBuilder):
"""Adds security group output when viewing server details."""
def show(self, request, instance):
"""Detailed view of a single instance."""
server = super(ViewBuilder, self).show(request, instance)
- server["server"]["security_groups"] = self._get_groups(instance)
+ context = request.environ['nova.context']
+ if authorize(context):
+ server["server"]["security_groups"] = self._get_groups(instance)
return server
def _get_groups(self, instance):
diff --git a/nova/api/openstack/compute/contrib/deferred_delete.py b/nova/api/openstack/compute/contrib/deferred_delete.py
index c0164eead..10f776558 100644
--- a/nova/api/openstack/compute/contrib/deferred_delete.py
+++ b/nova/api/openstack/compute/contrib/deferred_delete.py
@@ -26,6 +26,7 @@ from nova import log as logging
LOG = logging.getLogger("nova.api.openstack.compute.contrib.deferred-delete")
+authorize = extensions.extension_authorizer('compute', 'deferred_delete')
class DeferredDeleteController(wsgi.Controller):
@@ -36,8 +37,8 @@ class DeferredDeleteController(wsgi.Controller):
@wsgi.action('restore')
def _restore(self, req, id, body):
"""Restore a previously deleted instance."""
-
context = req.environ["nova.context"]
+ authorize(context)
instance = self.compute_api.get(context, id)
try:
self.compute_api.restore(context, instance)
@@ -49,8 +50,8 @@ class DeferredDeleteController(wsgi.Controller):
@wsgi.action('forceDelete')
def _force_delete(self, req, id, body):
"""Force delete of instance before deferred cleanup."""
-
context = req.environ["nova.context"]
+ authorize(context)
instance = self.compute_api.get(context, id)
try:
self.compute_api.force_delete(context, instance)
diff --git a/nova/api/openstack/compute/contrib/disk_config.py b/nova/api/openstack/compute/contrib/disk_config.py
index cf78b847e..46c09ffa8 100644
--- a/nova/api/openstack/compute/contrib/disk_config.py
+++ b/nova/api/openstack/compute/contrib/disk_config.py
@@ -28,6 +28,7 @@ ALIAS = 'OS-DCF'
XMLNS_DCF = "http://docs.openstack.org/compute/ext/disk_config/api/v1.1"
API_DISK_CONFIG = "%s:diskConfig" % ALIAS
INTERNAL_DISK_CONFIG = "auto_disk_config"
+authorize = extensions.soft_extension_authorizer('compute', 'disk_config')
def disk_config_to_api(value):
@@ -70,16 +71,16 @@ class ImageDiskConfigController(wsgi.Controller):
@wsgi.extends
def show(self, req, resp_obj, id):
- if 'image' in resp_obj.obj:
- context = req.environ['nova.context']
+ context = req.environ['nova.context']
+ if 'image' in resp_obj.obj and authorize(context):
resp_obj.attach(xml=ImageDiskConfigTemplate())
image = resp_obj.obj['image']
self._add_disk_config(context, [image])
@wsgi.extends
def detail(self, req, resp_obj):
- if 'images' in resp_obj.obj:
- context = req.environ['nova.context']
+ context = req.environ['nova.context']
+ if 'images' in resp_obj.obj and authorize(context):
resp_obj.attach(xml=ImagesDiskConfigTemplate())
images = resp_obj.obj['images']
self._add_disk_config(context, images)
@@ -102,13 +103,14 @@ class ServersDiskConfigTemplate(xmlutil.TemplateBuilder):
class ServerDiskConfigController(wsgi.Controller):
def _add_disk_config(self, context, servers):
- # Filter out any servers that already have the key set (most likely
- # from a remote zone)
+ # Filter out any servers that already have the key set
+ # (most likely from a remote zone)
servers = [s for s in servers if API_DISK_CONFIG not in s]
# Get DB information for servers
uuids = [server['id'] for server in servers]
- db_servers = db.instance_get_all_by_filters(context, {'uuid': uuids})
+ db_servers = db.instance_get_all_by_filters(context,
+ {'uuid': uuids})
db_servers_by_uuid = dict((s['uuid'], s) for s in db_servers)
for server in servers:
@@ -117,21 +119,22 @@ class ServerDiskConfigController(wsgi.Controller):
value = db_server[INTERNAL_DISK_CONFIG]
server[API_DISK_CONFIG] = disk_config_to_api(value)
- def _show(self, req, resp_obj):
+ def _show(self, context, resp_obj):
if 'server' in resp_obj.obj:
- context = req.environ['nova.context']
resp_obj.attach(xml=ServerDiskConfigTemplate())
server = resp_obj.obj['server']
self._add_disk_config(context, [server])
@wsgi.extends
def show(self, req, resp_obj, id):
- self._show(req, resp_obj)
+ context = req.environ['nova.context']
+ if authorize(context):
+ self._show(context, resp_obj)
@wsgi.extends
def detail(self, req, resp_obj):
- if 'servers' in resp_obj.obj:
- context = req.environ['nova.context']
+ context = req.environ['nova.context']
+ if 'servers' in resp_obj.obj and authorize(context):
resp_obj.attach(xml=ServersDiskConfigTemplate())
servers = resp_obj.obj['servers']
self._add_disk_config(context, servers)
@@ -144,26 +147,34 @@ class ServerDiskConfigController(wsgi.Controller):
@wsgi.extends
def create(self, req, body):
- self._set_disk_config(body['server'])
- resp_obj = (yield)
- self._show(req, resp_obj)
+ context = req.environ['nova.context']
+ if authorize(context):
+ self._set_disk_config(body['server'])
+ resp_obj = (yield)
+ self._show(context, resp_obj)
@wsgi.extends
def update(self, req, id, body):
- self._set_disk_config(body['server'])
- resp_obj = (yield)
- self._show(req, resp_obj)
+ context = req.environ['nova.context']
+ if authorize(context):
+ self._set_disk_config(body['server'])
+ resp_obj = (yield)
+ self._show(context, resp_obj)
@wsgi.extends(action='rebuild')
def _action_rebuild(self, req, id, body):
- self._set_disk_config(body['rebuild'])
- resp_obj = (yield)
- self._show(req, resp_obj)
+ context = req.environ['nova.context']
+ if authorize(context):
+ self._set_disk_config(body['rebuild'])
+ resp_obj = (yield)
+ self._show(context, resp_obj)
@wsgi.extends(action='resize')
def _action_resize(self, req, id, body):
- self._set_disk_config(body['resize'])
- yield
+ context = req.environ['nova.context']
+ if authorize(context):
+ self._set_disk_config(body['resize'])
+ yield
class Disk_config(extensions.ExtensionDescriptor):
diff --git a/nova/api/openstack/compute/contrib/extended_status.py b/nova/api/openstack/compute/contrib/extended_status.py
index 7479d6f00..4ab7ca756 100644
--- a/nova/api/openstack/compute/contrib/extended_status.py
+++ b/nova/api/openstack/compute/contrib/extended_status.py
@@ -27,6 +27,7 @@ from nova import log as logging
FLAGS = flags.FLAGS
LOG = logging.getLogger("nova.api.openstack.compute.contrib.extendedstatus")
+authorize = extensions.soft_extension_authorizer('compute', 'extended_status')
class ExtendedStatusController(wsgi.Controller):
@@ -48,34 +49,34 @@ class ExtendedStatusController(wsgi.Controller):
@wsgi.extends
def show(self, req, resp_obj, id):
context = req.environ['nova.context']
+ if authorize(context):
+ # Attach our slave template to the response object
+ resp_obj.attach(xml=ExtendedStatusTemplate())
- # Attach our slave template to the response object
- resp_obj.attach(xml=ExtendedStatusTemplate())
-
- try:
- self._get_and_extend_one(context, id, resp_obj.obj['server'])
- except exception.NotFound:
- explanation = _("Server not found.")
- raise exc.HTTPNotFound(explanation=explanation)
+ try:
+ self._get_and_extend_one(context, id, resp_obj.obj['server'])
+ except exception.NotFound:
+ explanation = _("Server not found.")
+ raise exc.HTTPNotFound(explanation=explanation)
@wsgi.extends
def detail(self, req, resp_obj):
context = req.environ['nova.context']
-
- # Attach our slave template to the response object
- resp_obj.attach(xml=ExtendedStatusesTemplate())
-
- for server in list(resp_obj.obj['servers']):
- try:
- self._get_and_extend_one(context, server['id'], server)
- except exception.NotFound:
- # NOTE(dtroyer): A NotFound exception at this point
- # happens because a delete was in progress and the
- # server that was present in the original call to
- # compute.api.get_all() is no longer present.
- # Delete it from the response and move on.
- resp_obj.obj['servers'].remove(server)
- continue
+ if authorize(context):
+ # Attach our slave template to the response object
+ resp_obj.attach(xml=ExtendedStatusesTemplate())
+
+ for server in list(resp_obj.obj['servers']):
+ try:
+ self._get_and_extend_one(context, server['id'], server)
+ except exception.NotFound:
+ # NOTE(dtroyer): A NotFound exception at this point
+ # happens because a delete was in progress and the
+ # server that was present in the original call to
+ # compute.api.get_all() is no longer present.
+ # Delete it from the response and move on.
+ resp_obj.obj['servers'].remove(server)
+ continue
class Extended_status(extensions.ExtensionDescriptor):
@@ -86,7 +87,6 @@ class Extended_status(extensions.ExtensionDescriptor):
namespace = "http://docs.openstack.org/compute/ext/" \
"extended_status/api/v1.1"
updated = "2011-11-03T00:00:00+00:00"
- admin_only = True
def get_controller_extensions(self):
controller = ExtendedStatusController()
diff --git a/nova/api/openstack/compute/contrib/flavorextraspecs.py b/nova/api/openstack/compute/contrib/flavorextraspecs.py
index eafea5d1f..faf023659 100644
--- a/nova/api/openstack/compute/contrib/flavorextraspecs.py
+++ b/nova/api/openstack/compute/contrib/flavorextraspecs.py
@@ -26,6 +26,9 @@ from nova import db
from nova import exception
+authorize = extensions.extension_authorizer('compute', 'flavorextraspecs')
+
+
class ExtraSpecsTemplate(xmlutil.TemplateBuilder):
def construct(self):
return xmlutil.MasterTemplate(xmlutil.make_flat_dict('extra_specs'), 1)
@@ -50,12 +53,14 @@ class FlavorExtraSpecsController(object):
def index(self, req, flavor_id):
""" Returns the list of extra specs for a givenflavor """
context = req.environ['nova.context']
+ authorize(context)
return self._get_extra_specs(context, flavor_id)
@wsgi.serializers(xml=ExtraSpecsTemplate)
def create(self, req, flavor_id, body):
- self._check_body(body)
context = req.environ['nova.context']
+ authorize(context)
+ self._check_body(body)
specs = body.get('extra_specs')
try:
db.instance_type_extra_specs_update_or_create(context,
@@ -67,8 +72,9 @@ class FlavorExtraSpecsController(object):
@wsgi.serializers(xml=ExtraSpecsTemplate)
def update(self, req, flavor_id, id, body):
- self._check_body(body)
context = req.environ['nova.context']
+ authorize(context)
+ self._check_body(body)
if not id in body:
expl = _('Request body and URI mismatch')
raise exc.HTTPBadRequest(explanation=expl)
@@ -88,6 +94,7 @@ class FlavorExtraSpecsController(object):
def show(self, req, flavor_id, id):
""" Return a single extra spec item """
context = req.environ['nova.context']
+ authorize(context)
specs = self._get_extra_specs(context, flavor_id)
if id in specs['extra_specs']:
return {id: specs['extra_specs'][id]}
@@ -97,6 +104,7 @@ class FlavorExtraSpecsController(object):
def delete(self, req, flavor_id, id):
""" Deletes an existing extra spec """
context = req.environ['nova.context']
+ authorize(context)
db.instance_type_extra_specs_delete(context, flavor_id, id)
def _handle_quota_error(self, error):
diff --git a/nova/api/openstack/compute/contrib/floating_ip_dns.py b/nova/api/openstack/compute/contrib/floating_ip_dns.py
index a0ac9241f..dbdd0c3a9 100644
--- a/nova/api/openstack/compute/contrib/floating_ip_dns.py
+++ b/nova/api/openstack/compute/contrib/floating_ip_dns.py
@@ -27,6 +27,7 @@ from nova import network
LOG = logging.getLogger('nova.api.openstack.compute.contrib.floating_ip_dns')
+authorize = extensions.extension_authorizer('compute', 'floating_ip_dns')
def make_dns_entry(elem):
@@ -138,6 +139,7 @@ class FloatingIPDNSDomainController(object):
def index(self, req):
"""Return a list of available DNS domains."""
context = req.environ['nova.context']
+ authorize(context)
domains = self.network_api.get_dns_domains(context)
domainlist = [_create_domain_entry(domain['domain'],
domain.get('scope'),
@@ -151,6 +153,7 @@ class FloatingIPDNSDomainController(object):
def update(self, req, id, body):
"""Add or modify domain entry"""
context = req.environ['nova.context']
+ authorize(context)
fqdomain = _unquote_domain(id)
try:
entry = body['domain_entry']
@@ -185,6 +188,7 @@ class FloatingIPDNSDomainController(object):
def delete(self, req, id):
"""Delete the domain identified by id. """
context = req.environ['nova.context']
+ authorize(context)
params = req.str_GET
domain = _unquote_domain(id)
@@ -210,6 +214,7 @@ class FloatingIPDNSEntryController(object):
def show(self, req, domain_id, id):
"""Return the DNS entry that corresponds to domain_id and id."""
context = req.environ['nova.context']
+ authorize(context)
domain = _unquote_domain(domain_id)
name = id
@@ -222,6 +227,7 @@ class FloatingIPDNSEntryController(object):
def index(self, req, domain_id):
"""Return a list of dns entries for the specified domain and ip."""
context = req.environ['nova.context']
+ authorize(context)
params = req.GET
floating_ip = params.get('ip')
domain = _unquote_domain(domain_id)
@@ -241,6 +247,7 @@ class FloatingIPDNSEntryController(object):
def update(self, req, domain_id, id, body):
"""Add or modify dns entry"""
context = req.environ['nova.context']
+ authorize(context)
domain = _unquote_domain(domain_id)
name = id
try:
@@ -268,6 +275,7 @@ class FloatingIPDNSEntryController(object):
def delete(self, req, domain_id, id):
"""Delete the entry identified by req and id. """
context = req.environ['nova.context']
+ authorize(context)
domain = _unquote_domain(domain_id)
name = id
diff --git a/nova/api/openstack/compute/contrib/floating_ip_pools.py b/nova/api/openstack/compute/contrib/floating_ip_pools.py
index 0bf2362af..574ef26b0 100644
--- a/nova/api/openstack/compute/contrib/floating_ip_pools.py
+++ b/nova/api/openstack/compute/contrib/floating_ip_pools.py
@@ -22,6 +22,7 @@ from nova import network
LOG = logging.getLogger('nova.api.openstack.compute.contrib.floating_ip_pools')
+authorize = extensions.extension_authorizer('compute', 'floating_ip_pools')
def _translate_floating_ip_view(pool):
@@ -69,6 +70,7 @@ class FloatingIPPoolsController(object):
def index(self, req):
"""Return a list of pools."""
context = req.environ['nova.context']
+ authorize(context)
pools = self.network_api.get_floating_ip_pools(context)
return _translate_floating_ip_pools_view(pools)
diff --git a/nova/api/openstack/compute/contrib/floating_ips.py b/nova/api/openstack/compute/contrib/floating_ips.py
index 3cfbc0604..afbdcf83a 100644
--- a/nova/api/openstack/compute/contrib/floating_ips.py
+++ b/nova/api/openstack/compute/contrib/floating_ips.py
@@ -30,6 +30,7 @@ from nova import rpc
LOG = logging.getLogger('nova.api.openstack.compute.contrib.floating_ips')
+authorize = extensions.extension_authorizer('compute', 'floating_ips')
def make_float_ip(elem):
@@ -116,6 +117,7 @@ class FloatingIPController(object):
def show(self, req, id):
"""Return data about the given floating ip."""
context = req.environ['nova.context']
+ authorize(context)
try:
floating_ip = self.network_api.get_floating_ip(context, id)
@@ -130,6 +132,7 @@ class FloatingIPController(object):
def index(self, req):
"""Return a list of floating ips allocated to a project."""
context = req.environ['nova.context']
+ authorize(context)
floating_ips = self.network_api.get_floating_ips_by_project(context)
@@ -141,6 +144,7 @@ class FloatingIPController(object):
@wsgi.serializers(xml=FloatingIPTemplate)
def create(self, req, body=None):
context = req.environ['nova.context']
+ authorize(context)
pool = None
if body and 'pool' in body:
@@ -163,6 +167,7 @@ class FloatingIPController(object):
def delete(self, req, id):
context = req.environ['nova.context']
+ authorize(context)
floating_ip = self.network_api.get_floating_ip(context, id)
if floating_ip.get('fixed_ip_id'):
@@ -188,6 +193,7 @@ class FloatingIPActionController(wsgi.Controller):
def _add_floating_ip(self, req, id, body):
"""Associate floating_ip to an instance."""
context = req.environ['nova.context']
+ authorize(context)
try:
address = body['addFloatingIp']['address']
@@ -213,6 +219,7 @@ class FloatingIPActionController(wsgi.Controller):
def _remove_floating_ip(self, req, id, body):
"""Dissociate floating_ip from an instance."""
context = req.environ['nova.context']
+ authorize(context)
try:
address = body['removeFloatingIp']['address']
diff --git a/nova/api/openstack/compute/contrib/hosts.py b/nova/api/openstack/compute/contrib/hosts.py
index 66dd64def..6ee89859b 100644
--- a/nova/api/openstack/compute/contrib/hosts.py
+++ b/nova/api/openstack/compute/contrib/hosts.py
@@ -31,6 +31,7 @@ from nova.scheduler import api as scheduler_api
LOG = logging.getLogger("nova.api.openstack.compute.contrib.hosts")
FLAGS = flags.FLAGS
+authorize = extensions.extension_authorizer('compute', 'hosts')
class HostIndexTemplate(xmlutil.TemplateBuilder):
@@ -112,12 +113,14 @@ class HostController(object):
@wsgi.serializers(xml=HostIndexTemplate)
def index(self, req):
+ authorize(req.environ['nova.context'])
return {'hosts': _list_hosts(req)}
@wsgi.serializers(xml=HostUpdateTemplate)
@wsgi.deserializers(xml=HostDeserializer)
@check_host
def update(self, req, id, body):
+ authorize(req.environ['nova.context'])
for raw_key, raw_val in body.iteritems():
key = raw_key.lower().strip()
val = raw_val.lower().strip()
@@ -149,6 +152,7 @@ class HostController(object):
def _host_power_action(self, req, host, action):
"""Reboots, shuts down or powers up the host."""
context = req.environ['nova.context']
+ authorize(context)
try:
result = self.compute_api.host_power_action(context, host=host,
action=action)
@@ -176,7 +180,6 @@ class Hosts(extensions.ExtensionDescriptor):
alias = "os-hosts"
namespace = "http://docs.openstack.org/compute/ext/hosts/api/v1.1"
updated = "2011-06-29T00:00:00+00:00"
- admin_only = True
def get_resources(self):
resources = [extensions.ResourceExtension('os-hosts',
diff --git a/nova/api/openstack/compute/contrib/keypairs.py b/nova/api/openstack/compute/contrib/keypairs.py
index 504539d55..7cd919673 100644
--- a/nova/api/openstack/compute/contrib/keypairs.py
+++ b/nova/api/openstack/compute/contrib/keypairs.py
@@ -31,6 +31,9 @@ from nova import db
from nova import exception
+authorize = extensions.extension_authorizer('compute', 'keypairs')
+
+
class KeypairTemplate(xmlutil.TemplateBuilder):
def construct(self):
return xmlutil.MasterTemplate(xmlutil.make_flat_dict('keypair'), 1)
@@ -77,6 +80,7 @@ class KeypairController(object):
"""
context = req.environ['nova.context']
+ authorize(context)
params = body['keypair']
name = params['name']
@@ -109,6 +113,7 @@ class KeypairController(object):
Delete a keypair with a given name
"""
context = req.environ['nova.context']
+ authorize(context)
db.key_pair_destroy(context, context.user_id, id)
return webob.Response(status_int=202)
@@ -118,6 +123,7 @@ class KeypairController(object):
List of keypairs for a user
"""
context = req.environ['nova.context']
+ authorize(context)
key_pairs = db.key_pair_get_all_by_user(context, context.user_id)
rval = []
for key_pair in key_pairs:
diff --git a/nova/api/openstack/compute/contrib/multinic.py b/nova/api/openstack/compute/contrib/multinic.py
index eea4532df..a3b4a8dc8 100644
--- a/nova/api/openstack/compute/contrib/multinic.py
+++ b/nova/api/openstack/compute/contrib/multinic.py
@@ -26,6 +26,7 @@ from nova import log as logging
LOG = logging.getLogger("nova.api.openstack.compute.contrib.multinic")
+authorize = extensions.extension_authorizer('compute', 'multinic')
class MultinicController(wsgi.Controller):
@@ -43,13 +44,14 @@ class MultinicController(wsgi.Controller):
@wsgi.action('addFixedIp')
def _add_fixed_ip(self, req, id, body):
"""Adds an IP on a given network to an instance."""
+ context = req.environ['nova.context']
+ authorize(context)
# Validate the input entity
if 'networkId' not in body['addFixedIp']:
msg = _("Missing 'networkId' argument for addFixedIp")
raise exc.HTTPUnprocessableEntity(explanation=msg)
- context = req.environ['nova.context']
instance = self._get_instance(context, id)
network_id = body['addFixedIp']['networkId']
self.compute_api.add_fixed_ip(context, instance, network_id)
@@ -58,13 +60,14 @@ class MultinicController(wsgi.Controller):
@wsgi.action('removeFixedIp')
def _remove_fixed_ip(self, req, id, body):
"""Removes an IP from an instance."""
+ context = req.environ['nova.context']
+ authorize(context)
# Validate the input entity
if 'address' not in body['removeFixedIp']:
msg = _("Missing 'address' argument for removeFixedIp")
raise exc.HTTPUnprocessableEntity(explanation=msg)
- context = req.environ['nova.context']
instance = self._get_instance(context, id)
address = body['removeFixedIp']['address']
diff --git a/nova/api/openstack/compute/contrib/networks.py b/nova/api/openstack/compute/contrib/networks.py
index f2381a19d..765a1d2fe 100644
--- a/nova/api/openstack/compute/contrib/networks.py
+++ b/nova/api/openstack/compute/contrib/networks.py
@@ -28,6 +28,7 @@ import nova.network.api
FLAGS = flags.FLAGS
LOG = logging.getLogger('nova.api.openstack.compute.contrib.networks')
+authorize = extensions.extension_authorizer('compute', 'networks')
def network_dict(network):
@@ -65,6 +66,7 @@ class NetworkController(object):
def _disassociate(self, request, network_id, body):
context = request.environ['nova.context']
+ authorize(context)
LOG.debug(_("Disassociating network with id %s" % network_id))
try:
self.network_api.disassociate(context, network_id)
@@ -74,12 +76,14 @@ class NetworkController(object):
def index(self, req):
context = req.environ['nova.context']
+ authorize(context)
networks = self.network_api.get_all(context)
result = [network_dict(net_ref) for net_ref in networks]
return {'networks': result}
def show(self, req, id):
context = req.environ['nova.context']
+ authorize(context)
LOG.debug(_("Showing network with id %s") % id)
try:
network = self.network_api.get(context, id)
@@ -89,6 +93,7 @@ class NetworkController(object):
def delete(self, req, id):
context = req.environ['nova.context']
+ authorize(context)
LOG.info(_("Deleting network with id %s") % id)
try:
self.network_api.delete(context, id)
@@ -107,7 +112,6 @@ class Networks(extensions.ExtensionDescriptor):
alias = "os-networks"
namespace = "http://docs.openstack.org/compute/ext/networks/api/v1.1"
updated = "2011-12-23 00:00:00"
- admin_only = True
def get_resources(self):
member_actions = {'action': 'POST'}
diff --git a/nova/api/openstack/compute/contrib/quotas.py b/nova/api/openstack/compute/contrib/quotas.py
index 5e4a20568..ce466af3f 100644
--- a/nova/api/openstack/compute/contrib/quotas.py
+++ b/nova/api/openstack/compute/contrib/quotas.py
@@ -25,6 +25,9 @@ from nova import exception
from nova import quota
+authorize = extensions.extension_authorizer('compute', 'quotas')
+
+
quota_resources = ['metadata_items', 'injected_file_content_bytes',
'volumes', 'gigabytes', 'ram', 'floating_ips', 'instances',
'injected_files', 'cores']
@@ -57,6 +60,7 @@ class QuotaSetsController(object):
@wsgi.serializers(xml=QuotaTemplate)
def show(self, req, id):
context = req.environ['nova.context']
+ authorize(context)
try:
db.sqlalchemy.api.authorize_project_context(context, id)
return self._format_quota_set(id,
@@ -67,6 +71,7 @@ class QuotaSetsController(object):
@wsgi.serializers(xml=QuotaTemplate)
def update(self, req, id, body):
context = req.environ['nova.context']
+ authorize(context)
project_id = id
for key in body['quota_set'].keys():
if key in quota_resources:
@@ -80,6 +85,7 @@ class QuotaSetsController(object):
return {'quota_set': quota.get_project_quotas(context, project_id)}
def defaults(self, req, id):
+ authorize(req.environ['nova.context'])
return self._format_quota_set(id, quota._get_default_quotas())
diff --git a/nova/api/openstack/compute/contrib/rescue.py b/nova/api/openstack/compute/contrib/rescue.py
index b0d5c6f97..e5fbb8388 100644
--- a/nova/api/openstack/compute/contrib/rescue.py
+++ b/nova/api/openstack/compute/contrib/rescue.py
@@ -28,6 +28,7 @@ from nova import utils
FLAGS = flags.FLAGS
LOG = logging.getLogger("nova.api.openstack.compute.contrib.rescue")
+authorize = exts.extension_authorizer('compute', 'rescue')
class RescueController(wsgi.Controller):
@@ -47,6 +48,7 @@ class RescueController(wsgi.Controller):
def _rescue(self, req, id, body):
"""Rescue an instance."""
context = req.environ["nova.context"]
+ authorize(context)
if body['rescue'] and 'adminPass' in body['rescue']:
password = body['rescue']['adminPass']
@@ -62,6 +64,7 @@ class RescueController(wsgi.Controller):
def _unrescue(self, req, id, body):
"""Unrescue an instance."""
context = req.environ["nova.context"]
+ authorize(context)
instance = self._get_instance(context, id)
self.compute_api.unrescue(context, instance)
return webob.Response(status_int=202)
diff --git a/nova/api/openstack/compute/contrib/security_groups.py b/nova/api/openstack/compute/contrib/security_groups.py
index 23b741145..45d72bf61 100644
--- a/nova/api/openstack/compute/contrib/security_groups.py
+++ b/nova/api/openstack/compute/contrib/security_groups.py
@@ -35,6 +35,7 @@ from nova import utils
LOG = logging.getLogger("nova.api.openstack.compute.contrib.security_groups")
FLAGS = flags.FLAGS
+authorize = extensions.extension_authorizer('compute', 'security_groups')
def make_rule(elem):
@@ -223,6 +224,7 @@ class SecurityGroupController(object):
def show(self, req, id):
"""Return data about the given security group."""
context = req.environ['nova.context']
+ authorize(context)
security_group = self._get_security_group(context, id)
return {'security_group': self._format_security_group(context,
security_group)}
@@ -230,6 +232,7 @@ class SecurityGroupController(object):
def delete(self, req, id):
"""Delete a security group."""
context = req.environ['nova.context']
+ authorize(context)
security_group = self._get_security_group(context, id)
LOG.audit(_("Delete security group %s"), id, context=context)
db.security_group_destroy(context, security_group.id)
@@ -240,6 +243,7 @@ class SecurityGroupController(object):
def index(self, req):
"""Returns a list of security groups"""
context = req.environ['nova.context']
+ authorize(context)
self.compute_api.ensure_default_security_group(context)
groups = db.security_group_get_by_project(context,
@@ -257,6 +261,7 @@ class SecurityGroupController(object):
def create(self, req, body):
"""Creates a new security group."""
context = req.environ['nova.context']
+ authorize(context)
if not body:
raise exc.HTTPUnprocessableEntity()
@@ -313,6 +318,7 @@ class SecurityGroupRulesController(SecurityGroupController):
@wsgi.deserializers(xml=SecurityGroupRulesXMLDeserializer)
def create(self, req, body):
context = req.environ['nova.context']
+ authorize(context)
if not body:
raise exc.HTTPUnprocessableEntity()
@@ -471,6 +477,7 @@ class SecurityGroupRulesController(SecurityGroupController):
def delete(self, req, id):
context = req.environ['nova.context']
+ authorize(context)
self.compute_api.ensure_default_security_group(context)
try:
@@ -505,6 +512,7 @@ class SecurityGroupActionController(wsgi.Controller):
@wsgi.action('addSecurityGroup')
def _addSecurityGroup(self, req, id, body):
context = req.environ['nova.context']
+ authorize(context)
try:
body = body['addSecurityGroup']
@@ -535,6 +543,7 @@ class SecurityGroupActionController(wsgi.Controller):
@wsgi.action('removeSecurityGroup')
def _removeSecurityGroup(self, req, id, body):
context = req.environ['nova.context']
+ authorize(context)
try:
body = body['removeSecurityGroup']
diff --git a/nova/api/openstack/compute/contrib/server_action_list.py b/nova/api/openstack/compute/contrib/server_action_list.py
index 436758572..24d3595d4 100644
--- a/nova/api/openstack/compute/contrib/server_action_list.py
+++ b/nova/api/openstack/compute/contrib/server_action_list.py
@@ -23,6 +23,7 @@ from nova import exception
sa_nsmap = {None: wsgi.XMLNS_V11}
+authorize = extensions.extension_authorizer('compute', 'server_action_list')
class ServerActionsTemplate(xmlutil.TemplateBuilder):
@@ -39,6 +40,7 @@ class ServerActionListController(object):
@wsgi.serializers(xml=ServerActionsTemplate)
def index(self, req, server_id):
context = req.environ["nova.context"]
+ authorize(context)
compute_api = compute.API()
try:
@@ -66,7 +68,6 @@ class Server_action_list(extensions.ExtensionDescriptor):
namespace = "http://docs.openstack.org/compute/ext/" \
"server-actions-list/api/v1.1"
updated = "2011-12-21T00:00:00+00:00"
- admin_only = True
def get_resources(self):
parent_def = {'member_name': 'server', 'collection_name': 'servers'}
diff --git a/nova/api/openstack/compute/contrib/server_diagnostics.py b/nova/api/openstack/compute/contrib/server_diagnostics.py
index 11d1affaf..49afcac01 100644
--- a/nova/api/openstack/compute/contrib/server_diagnostics.py
+++ b/nova/api/openstack/compute/contrib/server_diagnostics.py
@@ -23,6 +23,7 @@ from nova import exception
from nova.scheduler import api as scheduler_api
+authorize = extensions.extension_authorizer('compute', 'server_diagnostics')
sd_nsmap = {None: wsgi.XMLNS_V11}
@@ -41,6 +42,7 @@ class ServerDiagnosticsController(object):
@scheduler_api.redirect_handler
def index(self, req, server_id):
context = req.environ["nova.context"]
+ authorize(context)
compute_api = compute.API()
try:
instance = compute_api.get(context, id)
@@ -58,7 +60,6 @@ class Server_diagnostics(extensions.ExtensionDescriptor):
namespace = "http://docs.openstack.org/compute/ext/" \
"server-diagnostics/api/v1.1"
updated = "2011-12-21T00:00:00+00:00"
- admin_only = True
def get_resources(self):
parent_def = {'member_name': 'server', 'collection_name': 'servers'}
diff --git a/nova/api/openstack/compute/contrib/simple_tenant_usage.py b/nova/api/openstack/compute/contrib/simple_tenant_usage.py
index 85ea9a859..8e4201546 100644
--- a/nova/api/openstack/compute/contrib/simple_tenant_usage.py
+++ b/nova/api/openstack/compute/contrib/simple_tenant_usage.py
@@ -29,6 +29,7 @@ from nova import flags
FLAGS = flags.FLAGS
+authorize = extensions.extension_authorizer('compute', 'simple_tenant_usage')
def make_usage(elem):
@@ -211,6 +212,7 @@ class SimpleTenantUsageController(object):
def index(self, req):
"""Retrive tenant_usage for all tenants"""
context = req.environ['nova.context']
+ authorize(context)
if not context.is_admin:
return webob.Response(status_int=403)
@@ -227,6 +229,7 @@ class SimpleTenantUsageController(object):
"""Retrive tenant_usage for a specified tenant"""
tenant_id = id
context = req.environ['nova.context']
+ authorize(context)
if not context.is_admin:
if tenant_id != context.project_id:
@@ -253,7 +256,6 @@ class Simple_tenant_usage(extensions.ExtensionDescriptor):
namespace = "http://docs.openstack.org/compute/ext/" \
"os-simple-tenant-usage/api/v1.1"
updated = "2011-08-19T00:00:00+00:00"
- admin_only = True
def get_resources(self):
resources = []
diff --git a/nova/api/openstack/compute/contrib/users.py b/nova/api/openstack/compute/contrib/users.py
index 55dba02e4..b2a97f327 100644
--- a/nova/api/openstack/compute/contrib/users.py
+++ b/nova/api/openstack/compute/contrib/users.py
@@ -27,6 +27,7 @@ from nova import log as logging
FLAGS = flags.FLAGS
LOG = logging.getLogger('nova.api.openstack.users')
+authorize = extensions.extension_authorizer('compute', 'users')
def make_user(elem):
@@ -65,15 +66,10 @@ class Controller(object):
def __init__(self):
self.manager = manager.AuthManager()
- def _check_admin(self, context):
- """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.AdminRequired()
-
@wsgi.serializers(xml=UsersTemplate)
def index(self, req):
"""Return all users in brief"""
+ authorize(req.environ['nova.context'])
users = self.manager.get_users()
users = common.limited(users, req)
users = [_translate_keys(user) for user in users]
@@ -87,6 +83,7 @@ class Controller(object):
@wsgi.serializers(xml=UserTemplate)
def show(self, req, id):
"""Return data about the given user id"""
+ authorize(req.environ['nova.context'])
#NOTE(justinsb): The drivers are a little inconsistent in how they
# deal with "NotFound" - some throw, some return None.
@@ -101,13 +98,13 @@ class Controller(object):
return dict(user=_translate_keys(user))
def delete(self, req, id):
- self._check_admin(req.environ['nova.context'])
+ authorize(req.environ['nova.context'])
self.manager.delete_user(id)
return {}
@wsgi.serializers(xml=UserTemplate)
def create(self, req, body):
- self._check_admin(req.environ['nova.context'])
+ authorize(req.environ['nova.context'])
is_admin = body['user'].get('admin') in ('T', 'True', True)
name = body['user'].get('name')
access = body['user'].get('access')
@@ -117,7 +114,7 @@ class Controller(object):
@wsgi.serializers(xml=UserTemplate)
def update(self, req, id, body):
- self._check_admin(req.environ['nova.context'])
+ authorize(req.environ['nova.context'])
is_admin = body['user'].get('admin')
if is_admin is not None:
is_admin = is_admin in ('T', 'True', True)
@@ -134,7 +131,6 @@ class Users(extensions.ExtensionDescriptor):
alias = "os-users"
namespace = "http://docs.openstack.org/compute/ext/users/api/v1.1"
updated = "2011-08-08T00:00:00+00:00"
- admin_only = True
def get_resources(self):
coll_actions = {'detail': 'GET'}
diff --git a/nova/api/openstack/compute/contrib/virtual_interfaces.py b/nova/api/openstack/compute/contrib/virtual_interfaces.py
index ea37c4d97..e8da23c00 100644
--- a/nova/api/openstack/compute/contrib/virtual_interfaces.py
+++ b/nova/api/openstack/compute/contrib/virtual_interfaces.py
@@ -25,6 +25,7 @@ from nova import network
LOG = logging.getLogger("nova.api.openstack.compute."
"contrib.virtual_interfaces")
+authorize = extensions.extension_authorizer('compute', 'virtual_interfaces')
vif_nsmap = {None: wsgi.XMLNS_V11}
@@ -68,6 +69,7 @@ class ServerVirtualInterfaceController(object):
@wsgi.serializers(xml=VirtualInterfaceTemplate)
def index(self, req, server_id):
"""Returns the list of VIFs for a given instance."""
+ authorize(req.environ['nova.context'])
return self._items(req, server_id,
entity_maker=_translate_vif_summary_view)
diff --git a/nova/api/openstack/compute/contrib/virtual_storage_arrays.py b/nova/api/openstack/compute/contrib/virtual_storage_arrays.py
index 10e8a1001..ed4b12a92 100644
--- a/nova/api/openstack/compute/contrib/virtual_storage_arrays.py
+++ b/nova/api/openstack/compute/contrib/virtual_storage_arrays.py
@@ -36,9 +36,11 @@ from nova import log as logging
from nova import vsa
from nova import volume
-FLAGS = flags.FLAGS
+FLAGS = flags.FLAGS
LOG = logging.getLogger("nova.api.openstack.compute.contrib.vsa")
+authorize = extensions.extension_authorizer('compute',
+ 'virtual_storage_arrays')
def _vsa_view(context, vsa, details=False, instances=None):
@@ -124,6 +126,7 @@ class VsaController(object):
def _items(self, req, details):
"""Return summary or detailed list of VSAs."""
context = req.environ['nova.context']
+ authorize(context)
vsas = self.vsa_api.get_all(context)
limited_list = common.limited(vsas, req)
@@ -147,6 +150,7 @@ class VsaController(object):
def show(self, req, id):
"""Return data about the given VSA."""
context = req.environ['nova.context']
+ authorize(context)
try:
vsa = self.vsa_api.get(context, vsa_id=id)
@@ -160,6 +164,7 @@ class VsaController(object):
def create(self, req, body):
"""Create a new VSA."""
context = req.environ['nova.context']
+ authorize(context)
if not body or 'vsa' not in body:
LOG.debug(_("No body provided"), context=context)
@@ -193,6 +198,7 @@ class VsaController(object):
def delete(self, req, id):
"""Delete a VSA."""
context = req.environ['nova.context']
+ authorize(context)
LOG.audit(_("Delete VSA with id: %s"), id, context=context)
@@ -206,6 +212,7 @@ class VsaController(object):
auto or manually associate an IP to VSA
"""
context = req.environ['nova.context']
+ authorize(context)
if body is None:
ip = 'auto'
@@ -234,6 +241,7 @@ class VsaController(object):
auto or manually associate an IP to VSA
"""
context = req.environ['nova.context']
+ authorize(context)
if body is None:
ip = 'auto'
@@ -293,6 +301,7 @@ class VsaVolumeDriveController(volumes.VolumeController):
def _items(self, req, vsa_id, details):
"""Return summary or detailed list of volumes for particular VSA."""
context = req.environ['nova.context']
+ authorize(context)
vols = self.volume_api.get_all(context,
search_opts={'metadata': {self.direction: str(vsa_id)}})
@@ -317,6 +326,7 @@ class VsaVolumeDriveController(volumes.VolumeController):
"""Create a new volume from VSA."""
LOG.audit(_("Create. vsa_id=%(vsa_id)s, body=%(body)s"), locals())
context = req.environ['nova.context']
+ authorize(context)
if not body:
raise exc.HTTPUnprocessableEntity()
@@ -345,6 +355,7 @@ class VsaVolumeDriveController(volumes.VolumeController):
def update(self, req, vsa_id, id, body):
"""Update a volume."""
context = req.environ['nova.context']
+ authorize(context)
try:
self._check_volume_ownership(context, vsa_id, id)
@@ -380,6 +391,7 @@ class VsaVolumeDriveController(volumes.VolumeController):
def delete(self, req, vsa_id, id):
"""Delete a volume."""
context = req.environ['nova.context']
+ authorize(context)
LOG.audit(_("Delete. vsa_id=%(vsa_id)s, id=%(id)s"), locals())
@@ -395,6 +407,7 @@ class VsaVolumeDriveController(volumes.VolumeController):
def show(self, req, vsa_id, id):
"""Return data about the given volume."""
context = req.environ['nova.context']
+ authorize(context)
LOG.audit(_("Show. vsa_id=%(vsa_id)s, id=%(id)s"), locals())
diff --git a/nova/api/openstack/compute/contrib/volumes.py b/nova/api/openstack/compute/contrib/volumes.py
index 83e67102b..c3ba33eef 100644
--- a/nova/api/openstack/compute/contrib/volumes.py
+++ b/nova/api/openstack/compute/contrib/volumes.py
@@ -32,9 +32,8 @@ from nova.volume import volume_types
LOG = logging.getLogger("nova.api.openstack.compute.contrib.volumes")
-
-
FLAGS = flags.FLAGS
+authorize = extensions.extension_authorizer('compute', 'volumes')
def _translate_volume_detail_view(context, vol):
@@ -130,6 +129,7 @@ class VolumeController(object):
def show(self, req, id):
"""Return data about the given volume."""
context = req.environ['nova.context']
+ authorize(context)
try:
vol = self.volume_api.get(context, id)
@@ -141,6 +141,7 @@ class VolumeController(object):
def delete(self, req, id):
"""Delete a volume."""
context = req.environ['nova.context']
+ authorize(context)
LOG.audit(_("Delete volume with id: %s"), id, context=context)
@@ -164,6 +165,7 @@ class VolumeController(object):
def _items(self, req, entity_maker):
"""Returns a list of volumes, transformed through entity_maker."""
context = req.environ['nova.context']
+ authorize(context)
volumes = self.volume_api.get_all(context)
limited_list = common.limited(volumes, req)
@@ -174,6 +176,7 @@ class VolumeController(object):
def create(self, req, body):
"""Creates a new volume."""
context = req.environ['nova.context']
+ authorize(context)
if not body:
raise exc.HTTPUnprocessableEntity()
@@ -289,6 +292,7 @@ class VolumeAttachmentController(object):
def show(self, req, server_id, id):
"""Return data about the given volume attachment."""
context = req.environ['nova.context']
+ authorize(context)
volume_id = id
try:
@@ -309,6 +313,7 @@ class VolumeAttachmentController(object):
def create(self, req, server_id, body):
"""Attach a volume to an instance."""
context = req.environ['nova.context']
+ authorize(context)
if not body:
raise exc.HTTPUnprocessableEntity()
@@ -350,6 +355,7 @@ class VolumeAttachmentController(object):
def delete(self, req, server_id, id):
"""Detach a volume from an instance."""
context = req.environ['nova.context']
+ authorize(context)
volume_id = id
LOG.audit(_("Detach volume %s"), volume_id, context=context)
@@ -372,6 +378,7 @@ class VolumeAttachmentController(object):
def _items(self, req, server_id, entity_maker):
"""Returns a list of attachments, transformed through entity_maker."""
context = req.environ['nova.context']
+ authorize(context)
try:
instance = self.compute_api.get(context, server_id)
@@ -452,6 +459,7 @@ class SnapshotController(object):
def show(self, req, id):
"""Return data about the given snapshot."""
context = req.environ['nova.context']
+ authorize(context)
try:
vol = self.volume_api.get_snapshot(context, id)
@@ -463,6 +471,7 @@ class SnapshotController(object):
def delete(self, req, id):
"""Delete a snapshot."""
context = req.environ['nova.context']
+ authorize(context)
LOG.audit(_("Delete snapshot with id: %s"), id, context=context)
@@ -485,6 +494,7 @@ class SnapshotController(object):
def _items(self, req, entity_maker):
"""Returns a list of snapshots, transformed through entity_maker."""
context = req.environ['nova.context']
+ authorize(context)
snapshots = self.volume_api.get_all_snapshots(context)
limited_list = common.limited(snapshots, req)
@@ -495,6 +505,7 @@ class SnapshotController(object):
def create(self, req, body):
"""Creates a new snapshot."""
context = req.environ['nova.context']
+ authorize(context)
if not body:
return exc.HTTPUnprocessableEntity()
diff --git a/nova/api/openstack/compute/contrib/volumetypes.py b/nova/api/openstack/compute/contrib/volumetypes.py
index bf249f3f8..cbc205ea7 100644
--- a/nova/api/openstack/compute/contrib/volumetypes.py
+++ b/nova/api/openstack/compute/contrib/volumetypes.py
@@ -27,6 +27,9 @@ from nova import exception
from nova.volume import volume_types
+authorize = extensions.extension_authorizer('compute', 'volumetypes')
+
+
def make_voltype(elem):
elem.set('id')
elem.set('name')
@@ -57,12 +60,14 @@ class VolumeTypesController(object):
def index(self, req):
""" Returns the list of volume types """
context = req.environ['nova.context']
+ authorize(context)
return volume_types.get_all_types(context)
@wsgi.serializers(xml=VolumeTypeTemplate)
def create(self, req, body):
"""Creates a new volume type."""
context = req.environ['nova.context']
+ authorize(context)
if not body or body == "":
raise exc.HTTPUnprocessableEntity()
@@ -91,6 +96,7 @@ class VolumeTypesController(object):
def show(self, req, id):
""" Return a single volume type item """
context = req.environ['nova.context']
+ authorize(context)
try:
vol_type = volume_types.get_volume_type(context, id)
@@ -102,6 +108,7 @@ class VolumeTypesController(object):
def delete(self, req, id):
""" Deletes an existing volume type """
context = req.environ['nova.context']
+ authorize(context)
try:
vol_type = volume_types.get_volume_type(context, id)
@@ -155,12 +162,14 @@ class VolumeTypeExtraSpecsController(object):
def index(self, req, vol_type_id):
""" Returns the list of extra specs for a given volume type """
context = req.environ['nova.context']
+ authorize(context)
return self._get_extra_specs(context, vol_type_id)
@wsgi.serializers(xml=VolumeTypeExtraSpecsTemplate)
def create(self, req, vol_type_id, body):
- self._check_body(body)
context = req.environ['nova.context']
+ authorize(context)
+ self._check_body(body)
specs = body.get('extra_specs')
try:
db.volume_type_extra_specs_update_or_create(context,
@@ -172,8 +181,9 @@ class VolumeTypeExtraSpecsController(object):
@wsgi.serializers(xml=VolumeTypeExtraSpecTemplate)
def update(self, req, vol_type_id, id, body):
- self._check_body(body)
context = req.environ['nova.context']
+ authorize(context)
+ self._check_body(body)
if not id in body:
expl = _('Request body and URI mismatch')
raise exc.HTTPBadRequest(explanation=expl)
@@ -193,6 +203,7 @@ class VolumeTypeExtraSpecsController(object):
def show(self, req, vol_type_id, id):
""" Return a single extra spec item """
context = req.environ['nova.context']
+ authorize(context)
specs = self._get_extra_specs(context, vol_type_id)
if id in specs['extra_specs']:
return {id: specs['extra_specs'][id]}
@@ -202,6 +213,7 @@ class VolumeTypeExtraSpecsController(object):
def delete(self, req, vol_type_id, id):
""" Deletes an existing extra spec """
context = req.environ['nova.context']
+ authorize(context)
db.volume_type_extra_specs_delete(context, vol_type_id, id)
def _handle_quota_error(self, error):
diff --git a/nova/api/openstack/compute/contrib/zones.py b/nova/api/openstack/compute/contrib/zones.py
index 539833ee2..fac3d7188 100644
--- a/nova/api/openstack/compute/contrib/zones.py
+++ b/nova/api/openstack/compute/contrib/zones.py
@@ -34,6 +34,7 @@ import nova.scheduler.api
LOG = logging.getLogger("nova.api.openstack.compute.contrib.zones")
FLAGS = flags.FLAGS
+authorize = extensions.extension_authorizer('compute', 'zones')
class CapabilitySelector(object):
@@ -117,6 +118,7 @@ class Controller(object):
@wsgi.serializers(xml=ZonesTemplate)
def index(self, req):
"""Return all zones in brief"""
+ authorize(req.environ['nova.context'])
# Ask the ZoneManager in the Scheduler for most recent data,
# or fall-back to the database ...
items = nova.scheduler.api.get_zone_list(req.environ['nova.context'])
@@ -133,6 +135,7 @@ class Controller(object):
def info(self, req):
"""Return name and capabilities for this zone."""
context = req.environ['nova.context']
+ authorize(context)
zone_capabs = nova.scheduler.api.get_zone_capabilities(context)
# NOTE(comstud): This should probably return, instead:
# {'zone': {'name': FLAGS.zone_name,
@@ -143,13 +146,15 @@ class Controller(object):
@wsgi.serializers(xml=ZoneTemplate)
def show(self, req, id):
"""Return data about the given zone id"""
- zone_id = int(id)
context = req.environ['nova.context']
+ authorize(context)
+ zone_id = int(id)
zone = nova.scheduler.api.zone_get(context, zone_id)
return dict(zone=_scrub_zone(zone))
def delete(self, req, id):
"""Delete a child zone entry."""
+ authorize(req.environ['nova.context'])
zone_id = int(id)
nova.scheduler.api.zone_delete(req.environ['nova.context'], zone_id)
return {}
@@ -159,6 +164,7 @@ class Controller(object):
def create(self, req, body):
"""Create a child zone entry."""
context = req.environ['nova.context']
+ authorize(context)
zone = nova.scheduler.api.zone_create(context, body["zone"])
return dict(zone=_scrub_zone(zone))
@@ -166,6 +172,7 @@ class Controller(object):
def update(self, req, id, body):
"""Update a child zone entry."""
context = req.environ['nova.context']
+ authorize(context)
zone_id = int(id)
zone = nova.scheduler.api.zone_update(context, zone_id, body["zone"])
return dict(zone=_scrub_zone(zone))
@@ -175,9 +182,10 @@ class Controller(object):
def select(self, req, body):
"""Returns a weighted list of costs to create instances
of desired capabilities."""
- ctx = req.environ['nova.context']
+ context = req.environ['nova.context']
+ authorize(context)
specs = json.loads(body)
- build_plan = nova.scheduler.api.select(ctx, specs=specs)
+ build_plan = nova.scheduler.api.select(context, specs=specs)
cooked = self._scrub_build_plan(build_plan)
return {"weights": cooked}
@@ -205,7 +213,6 @@ class Zones(extensions.ExtensionDescriptor):
alias = "os-zones"
namespace = "http://docs.openstack.org/compute/ext/zones/api/v1.1"
updated = "2011-09-21T00:00:00+00:00"
- admin_only = True
def get_resources(self):
#NOTE(bcwaldon): This resource should be prefixed with 'os-'
diff --git a/nova/api/openstack/compute/servers.py b/nova/api/openstack/compute/servers.py
index ee7038c6e..d0e771e22 100644
--- a/nova/api/openstack/compute/servers.py
+++ b/nova/api/openstack/compute/servers.py
@@ -1170,7 +1170,7 @@ def create_resource():
def remove_invalid_options(context, search_options, allowed_search_options):
"""Remove search options that are not valid for non-admin API/context"""
- if FLAGS.allow_admin_api and context.is_admin:
+ if context.is_admin:
# Allow all options
return
# Otherwise, strip out all unknown options
diff --git a/nova/api/openstack/extensions.py b/nova/api/openstack/extensions.py
index 4b8da21ed..bf415765c 100644
--- a/nova/api/openstack/extensions.py
+++ b/nova/api/openstack/extensions.py
@@ -16,8 +16,10 @@
# License for the specific language governing permissions and limitations
# under the License.
+import functools
import os
import routes
+
import webob.dec
import webob.exc
@@ -27,13 +29,12 @@ from nova.api.openstack import xmlutil
from nova import exception
from nova import flags
from nova import log as logging
+import nova.policy
from nova import utils
from nova import wsgi as base_wsgi
LOG = logging.getLogger('nova.api.openstack.extensions')
-
-
FLAGS = flags.FLAGS
@@ -61,10 +62,6 @@ class ExtensionDescriptor(object):
# '2011-01-22T13:25:27-06:00'
updated = None
- # This attribute causes the extension to load only when
- # the admin api is enabled
- admin_only = False
-
def __init__(self, ext_mgr):
"""Register extension with the extension manager."""
@@ -246,15 +243,10 @@ class ExtensionManager(object):
' '.join(extension.__doc__.strip().split()))
LOG.debug(_('Ext namespace: %s'), extension.namespace)
LOG.debug(_('Ext updated: %s'), extension.updated)
- LOG.debug(_('Ext admin_only: %s'), extension.admin_only)
except AttributeError as ex:
LOG.exception(_("Exception loading extension: %s"), unicode(ex))
return False
- # Don't load admin api extensions if the admin api isn't enabled
- if not FLAGS.allow_admin_api and extension.admin_only:
- return False
-
return True
def load_extension(self, ext_factory):
@@ -384,3 +376,22 @@ def load_standard_extensions(ext_mgr, logger, path, package):
# Update the list of directories we'll explore...
dirnames[:] = subdirs
+
+
+def extension_authorizer(api_name, extension_name):
+ def authorize(context):
+ action = '%s_extension:%s' % (api_name, extension_name)
+ nova.policy.enforce(context, action, {})
+ return authorize
+
+
+def soft_extension_authorizer(api_name, extension_name):
+ hard_authorize = extension_authorizer(api_name, extension_name)
+
+ def authorize(context):
+ try:
+ hard_authorize(context)
+ return True
+ except exception.NotAuthorized:
+ return False
+ return authorize
diff --git a/nova/tests/api/openstack/compute/contrib/test_accounts.py b/nova/tests/api/openstack/compute/contrib/test_accounts.py
index dbf0e2600..6b820bd57 100644
--- a/nova/tests/api/openstack/compute/contrib/test_accounts.py
+++ b/nova/tests/api/openstack/compute/contrib/test_accounts.py
@@ -29,18 +29,12 @@ def fake_init(self):
self.manager = fakes.FakeAuthManager()
-def fake_admin_check(self, req):
- return True
-
-
class AccountsTest(test.TestCase):
def setUp(self):
super(AccountsTest, self).setUp()
- self.flags(verbose=True, allow_admin_api=True)
+ self.flags(verbose=True)
self.stubs.Set(accounts.Controller, '__init__',
fake_init)
- self.stubs.Set(accounts.Controller, '_check_admin',
- fake_admin_check)
fakes.FakeAuthManager.clear_fakes()
fakes.FakeAuthDatabase.data = {}
fakes.stub_out_networking(self.stubs)
diff --git a/nova/tests/api/openstack/compute/contrib/test_admin_actions.py b/nova/tests/api/openstack/compute/contrib/test_admin_actions.py
index 3878ce676..f572b12d9 100644
--- a/nova/tests/api/openstack/compute/contrib/test_admin_actions.py
+++ b/nova/tests/api/openstack/compute/contrib/test_admin_actions.py
@@ -79,7 +79,6 @@ class AdminActionsTest(test.TestCase):
super(AdminActionsTest, self).setUp()
self.stubs.Set(compute.API, 'get', fake_compute_api_get)
self.UUID = utils.gen_uuid()
- self.flags(allow_admin_api=True)
for _method in self._methods:
self.stubs.Set(compute.API, _method, fake_compute_api)
@@ -122,8 +121,9 @@ class CreateBackupTests(test.TestCase):
self.stubs.Set(compute.API, 'get', fake_compute_api_get)
self.backup_stubs = fakes.stub_out_compute_api_backup(self.stubs)
- self.flags(allow_admin_api=True)
- self.app = compute_api.APIRouter()
+ router = compute_api.APIRouter()
+ ext_middleware = extensions.ExtensionMiddleware(router)
+ self.app = wsgi.LazySerializationMiddleware(ext_middleware)
self.uuid = utils.gen_uuid()
diff --git a/nova/tests/api/openstack/compute/contrib/test_cloudpipe.py b/nova/tests/api/openstack/compute/contrib/test_cloudpipe.py
index 64b206aef..27341f199 100644
--- a/nova/tests/api/openstack/compute/contrib/test_cloudpipe.py
+++ b/nova/tests/api/openstack/compute/contrib/test_cloudpipe.py
@@ -107,7 +107,6 @@ class CloudpipeTest(test.TestCase):
def setUp(self):
super(CloudpipeTest, self).setUp()
- self.flags(allow_admin_api=True)
self.app = fakes.wsgi_app()
inner_app = compute.APIRouter()
self.context = context.RequestContext('fake', 'fake', is_admin=True)
diff --git a/nova/tests/api/openstack/compute/contrib/test_deferred_delete.py b/nova/tests/api/openstack/compute/contrib/test_deferred_delete.py
index a864aa595..d02569e00 100644
--- a/nova/tests/api/openstack/compute/contrib/test_deferred_delete.py
+++ b/nova/tests/api/openstack/compute/contrib/test_deferred_delete.py
@@ -18,6 +18,7 @@
import webob
from nova.api.openstack.compute.contrib import deferred_delete
+import nova.context
from nova import compute
from nova import exception
from nova import test
@@ -34,7 +35,7 @@ class DeferredDeleteExtensionTest(test.TestCase):
self.extension = deferred_delete.DeferredDeleteController()
self.fake_input_dict = {}
self.fake_uuid = 'fake_uuid'
- self.fake_context = 'fake_context'
+ self.fake_context = nova.context.RequestContext('fake', 'fake')
self.fake_req = FakeRequest(self.fake_context)
def test_force_delete(self):
diff --git a/nova/tests/api/openstack/compute/contrib/test_extendedstatus.py b/nova/tests/api/openstack/compute/contrib/test_extendedstatus.py
index dc7f0cefa..738ab8290 100644
--- a/nova/tests/api/openstack/compute/contrib/test_extendedstatus.py
+++ b/nova/tests/api/openstack/compute/contrib/test_extendedstatus.py
@@ -41,7 +41,6 @@ class ExtendedStatusTest(test.TestCase):
self.uuid = '70f6db34-de8d-4fbd-aafb-4065bdfa6114'
self.url = '/v2/fake/servers/%s' % self.uuid
fakes.stub_out_nw_api(self.stubs)
- self.flags(allow_admin_api=True)
self.stubs.Set(compute.api.API, 'routing_get', fake_compute_get)
def _make_request(self):
diff --git a/nova/tests/api/openstack/compute/contrib/test_hosts.py b/nova/tests/api/openstack/compute/contrib/test_hosts.py
index e6a91477e..af4818c90 100644
--- a/nova/tests/api/openstack/compute/contrib/test_hosts.py
+++ b/nova/tests/api/openstack/compute/contrib/test_hosts.py
@@ -94,17 +94,14 @@ class HostTestCase(test.TestCase):
self.assertEqual(result_c2["status"], "disabled")
def test_host_startup(self):
- self.flags(allow_admin_api=True)
result = self.controller.startup(self.req, "host_c1")
self.assertEqual(result["power_action"], "startup")
def test_host_shutdown(self):
- self.flags(allow_admin_api=True)
result = self.controller.shutdown(self.req, "host_c1")
self.assertEqual(result["power_action"], "shutdown")
def test_host_reboot(self):
- self.flags(allow_admin_api=True)
result = self.controller.reboot(self.req, "host_c1")
self.assertEqual(result["power_action"], "reboot")
diff --git a/nova/tests/api/openstack/compute/contrib/test_networks.py b/nova/tests/api/openstack/compute/contrib/test_networks.py
index 0eefca652..ed928348e 100644
--- a/nova/tests/api/openstack/compute/contrib/test_networks.py
+++ b/nova/tests/api/openstack/compute/contrib/test_networks.py
@@ -92,7 +92,6 @@ class NetworksTest(test.TestCase):
def setUp(self):
super(NetworksTest, self).setUp()
- self.flags(allow_admin_api=True)
self.fake_network_api = FakeNetworkAPI()
self.controller = networks.NetworkController(self.fake_network_api)
fakes.stub_out_networking(self.stubs)
diff --git a/nova/tests/api/openstack/compute/contrib/test_server_action_list.py b/nova/tests/api/openstack/compute/contrib/test_server_action_list.py
index ffd4f744d..2a175f1dd 100644
--- a/nova/tests/api/openstack/compute/contrib/test_server_action_list.py
+++ b/nova/tests/api/openstack/compute/contrib/test_server_action_list.py
@@ -47,7 +47,6 @@ class ServerActionsTest(test.TestCase):
def setUp(self):
super(ServerActionsTest, self).setUp()
- self.flags(allow_admin_api=True)
self.flags(verbose=True)
self.stubs.Set(nova.compute.API, 'get_actions', fake_get_actions)
self.stubs.Set(nova.compute.API, 'get', fake_instance_get)
diff --git a/nova/tests/api/openstack/compute/contrib/test_server_diagnostics.py b/nova/tests/api/openstack/compute/contrib/test_server_diagnostics.py
index 688940e3d..b18b5018d 100644
--- a/nova/tests/api/openstack/compute/contrib/test_server_diagnostics.py
+++ b/nova/tests/api/openstack/compute/contrib/test_server_diagnostics.py
@@ -40,7 +40,6 @@ class ServerDiagnosticsTest(test.TestCase):
def setUp(self):
super(ServerDiagnosticsTest, self).setUp()
- self.flags(allow_admin_api=True)
self.flags(verbose=True)
self.stubs.Set(nova.compute.API, 'get_diagnostics',
fake_get_diagnostics)
diff --git a/nova/tests/api/openstack/compute/contrib/test_simple_tenant_usage.py b/nova/tests/api/openstack/compute/contrib/test_simple_tenant_usage.py
index b41773824..812aac297 100644
--- a/nova/tests/api/openstack/compute/contrib/test_simple_tenant_usage.py
+++ b/nova/tests/api/openstack/compute/contrib/test_simple_tenant_usage.py
@@ -88,7 +88,6 @@ class SimpleTenantUsageTest(test.TestCase):
self.alt_user_context = context.RequestContext('fakeadmin_0',
'faketenant_1',
is_admin=False)
- FLAGS.allow_admin_api = True
def test_verify_index(self):
req = webob.Request.blank(
diff --git a/nova/tests/api/openstack/compute/contrib/test_users.py b/nova/tests/api/openstack/compute/contrib/test_users.py
index 5895f4f66..3dd0b3074 100644
--- a/nova/tests/api/openstack/compute/contrib/test_users.py
+++ b/nova/tests/api/openstack/compute/contrib/test_users.py
@@ -26,18 +26,12 @@ def fake_init(self):
self.manager = fakes.FakeAuthManager()
-def fake_admin_check(self, req):
- return True
-
-
class UsersTest(test.TestCase):
def setUp(self):
super(UsersTest, self).setUp()
- self.flags(verbose=True, allow_admin_api=True)
+ self.flags(verbose=True)
self.stubs.Set(users.Controller, '__init__',
fake_init)
- self.stubs.Set(users.Controller, '_check_admin',
- fake_admin_check)
fakes.FakeAuthManager.clear_fakes()
fakes.FakeAuthManager.projects = dict(testacct=Project('testacct',
'testacct',
diff --git a/nova/tests/api/openstack/compute/contrib/test_zones.py b/nova/tests/api/openstack/compute/contrib/test_zones.py
index e23ea85e6..9f887cb0d 100644
--- a/nova/tests/api/openstack/compute/contrib/test_zones.py
+++ b/nova/tests/api/openstack/compute/contrib/test_zones.py
@@ -95,7 +95,6 @@ def zone_select(context, specs):
class ZonesTest(test.TestCase):
def setUp(self):
super(ZonesTest, self).setUp()
- self.flags(verbose=True, allow_admin_api=True)
fakes.stub_out_networking(self.stubs)
fakes.stub_out_rate_limiting(self.stubs)
diff --git a/nova/tests/api/openstack/compute/test_extensions.py b/nova/tests/api/openstack/compute/test_extensions.py
index 796880e1f..54d0e4625 100644
--- a/nova/tests/api/openstack/compute/test_extensions.py
+++ b/nova/tests/api/openstack/compute/test_extensions.py
@@ -150,7 +150,6 @@ class ExtensionControllerTest(ExtensionTestCase):
def setUp(self):
super(ExtensionControllerTest, self).setUp()
- self.flags(allow_admin_api=True)
self.ext_list = [
"Accounts",
"AdminActions",
@@ -355,19 +354,6 @@ class InvalidExtension(object):
alias = "THIRD"
-class AdminExtension(base_extensions.ExtensionDescriptor):
- """Admin-only extension"""
-
- name = "Admin Ext"
- alias = "ADMIN"
- namespace = "http://www.example.com/"
- updated = "2011-01-22T13:25:27-06:00"
- admin_only = True
-
- def __init__(self, *args, **kwargs):
- pass
-
-
class ExtensionManagerTest(ExtensionTestCase):
response_body = "Try to say this Mr. Knox, sir..."
@@ -388,22 +374,6 @@ class ExtensionManagerTest(ExtensionTestCase):
self.assertTrue('FOXNSOX' in ext_mgr.extensions)
self.assertTrue('THIRD' not in ext_mgr.extensions)
- def test_admin_extensions(self):
- self.flags(allow_admin_api=True)
- app = compute.APIRouter()
- ext_mgr = compute_extensions.ExtensionManager()
- ext_mgr.register(AdminExtension())
- self.assertTrue('FOXNSOX' in ext_mgr.extensions)
- self.assertTrue('ADMIN' in ext_mgr.extensions)
-
- def test_admin_extensions_no_admin_api(self):
- self.flags(allow_admin_api=False)
- app = compute.APIRouter()
- ext_mgr = compute_extensions.ExtensionManager()
- ext_mgr.register(AdminExtension())
- self.assertTrue('FOXNSOX' in ext_mgr.extensions)
- self.assertTrue('ADMIN' not in ext_mgr.extensions)
-
class ActionExtensionTest(ExtensionTestCase):
diff --git a/nova/tests/api/openstack/compute/test_servers.py b/nova/tests/api/openstack/compute/test_servers.py
index f545aeaec..c6c7fcc43 100644
--- a/nova/tests/api/openstack/compute/test_servers.py
+++ b/nova/tests/api/openstack/compute/test_servers.py
@@ -861,7 +861,6 @@ class ServersControllerTest(test.TestCase):
return [fakes.stub_instance(100, uuid=server_uuid)]
self.stubs.Set(nova.compute.API, 'get_all', fake_get_all)
- self.flags(allow_admin_api=False)
req = fakes.HTTPRequest.blank('/v2/fake/servers?image=12345')
servers = self.controller.index(req)['servers']
@@ -878,7 +877,6 @@ class ServersControllerTest(test.TestCase):
self.stubs.Set(nova.db, 'instance_get_all_by_filters',
fake_get_all)
- self.flags(allow_admin_api=True)
req = fakes.HTTPRequest.blank('/v2/fake/servers?tenant_id=fake',
use_admin_context=True)
@@ -897,7 +895,6 @@ class ServersControllerTest(test.TestCase):
return [fakes.stub_instance(100, uuid=server_uuid)]
self.stubs.Set(nova.compute.API, 'get_all', fake_get_all)
- self.flags(allow_admin_api=False)
req = fakes.HTTPRequest.blank('/v2/fake/servers?flavor=12345')
servers = self.controller.index(req)['servers']
@@ -915,7 +912,6 @@ class ServersControllerTest(test.TestCase):
return [fakes.stub_instance(100, uuid=server_uuid)]
self.stubs.Set(nova.compute.API, 'get_all', fake_get_all)
- self.flags(allow_admin_api=False)
req = fakes.HTTPRequest.blank('/v2/fake/servers?status=active')
servers = self.controller.index(req)['servers']
@@ -925,8 +921,8 @@ class ServersControllerTest(test.TestCase):
def test_get_servers_invalid_status(self):
"""Test getting servers by invalid status"""
- self.flags(allow_admin_api=False)
- req = fakes.HTTPRequest.blank('/v2/fake/servers?status=unknown')
+ req = fakes.HTTPRequest.blank('/v2/fake/servers?status=unknown',
+ use_admin_context=False)
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.index, req)
def test_get_servers_allows_name(self):
@@ -939,7 +935,6 @@ class ServersControllerTest(test.TestCase):
return [fakes.stub_instance(100, uuid=server_uuid)]
self.stubs.Set(nova.compute.API, 'get_all', fake_get_all)
- self.flags(allow_admin_api=False)
req = fakes.HTTPRequest.blank('/v2/fake/servers?name=whee.*')
servers = self.controller.index(req)['servers']
@@ -972,47 +967,11 @@ class ServersControllerTest(test.TestCase):
req = fakes.HTTPRequest.blank('/v2/fake/servers?%s' % params)
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.index, req)
- def test_get_servers_unknown_or_admin_options1(self):
- """Test getting servers by admin-only or unknown options.
- This tests when admin_api is off. Make sure the admin and
- unknown options are stripped before they get to
- compute_api.get_all()
+ def test_get_servers_admin_filters_as_user(self):
+ """Test getting servers by admin-only or unknown options when
+ context is not admin. Make sure the admin and unknown options
+ are stripped before they get to compute_api.get_all()
"""
-
- self.flags(allow_admin_api=False)
-
- server_uuid = str(utils.gen_uuid())
-
- def fake_get_all(compute_self, context, search_opts=None):
- self.assertNotEqual(search_opts, None)
- # Allowed by user
- self.assertTrue('name' in search_opts)
- self.assertTrue('status' in search_opts)
- # Allowed only by admins with admin API on
- self.assertFalse('ip' in search_opts)
- self.assertFalse('unknown_option' in search_opts)
- return [fakes.stub_instance(100, uuid=server_uuid)]
-
- self.stubs.Set(nova.compute.API, 'get_all', fake_get_all)
-
- query_str = "name=foo&ip=10.*&status=active&unknown_option=meow"
- req = fakes.HTTPRequest.blank('/v2/fake/servers?%s' % query_str,
- use_admin_context=True)
- res = self.controller.index(req)
-
- servers = res['servers']
- self.assertEqual(len(servers), 1)
- self.assertEqual(servers[0]['id'], server_uuid)
-
- def test_get_servers_unknown_or_admin_options2(self):
- """Test getting servers by admin-only or unknown options.
- This tests when admin_api is on, but context is a user.
- Make sure the admin and unknown options are stripped before
- they get to compute_api.get_all()
- """
-
- self.flags(allow_admin_api=True)
-
server_uuid = str(utils.gen_uuid())
def fake_get_all(compute_self, context, search_opts=None):
@@ -1035,14 +994,10 @@ class ServersControllerTest(test.TestCase):
self.assertEqual(len(servers), 1)
self.assertEqual(servers[0]['id'], server_uuid)
- def test_get_servers_unknown_or_admin_options3(self):
- """Test getting servers by admin-only or unknown options.
- This tests when admin_api is on and context is admin.
- All options should be passed through to compute_api.get_all()
+ def test_get_servers_admin_options_as_admin(self):
+ """Test getting servers by admin-only or unknown options when
+ context is admin. All options should be passed
"""
-
- self.flags(allow_admin_api=True)
-
server_uuid = str(utils.gen_uuid())
def fake_get_all(compute_self, context, search_opts=None):
@@ -1069,8 +1024,6 @@ class ServersControllerTest(test.TestCase):
"""Test getting servers by ip with admin_api enabled and
admin context
"""
- self.flags(allow_admin_api=True)
-
server_uuid = str(utils.gen_uuid())
def fake_get_all(compute_self, context, search_opts=None):
@@ -1092,8 +1045,6 @@ class ServersControllerTest(test.TestCase):
"""Test getting servers by ip6 with admin_api enabled and
admin context
"""
- self.flags(allow_admin_api=True)
-
server_uuid = str(utils.gen_uuid())
def fake_get_all(compute_self, context, search_opts=None):
diff --git a/nova/tests/policy.json b/nova/tests/policy.json
index 807de6921..ff30cd43d 100644
--- a/nova/tests/policy.json
+++ b/nova/tests/policy.json
@@ -69,6 +69,38 @@
"compute:restore": [],
+ "compute_extension:accounts": [],
+ "compute_extension:admin_actions": [],
+ "compute_extension:cloudpipe": [],
+ "compute_extension:console_output": [],
+ "compute_extension:consoles": [],
+ "compute_extension:createserverext": [],
+ "compute_extension:deferred_delete": [],
+ "compute_extension:disk_config": [],
+ "compute_extension:extended_status": [],
+ "compute_extension:flavorextraspecs": [],
+ "compute_extension:floating_ip_dns": [],
+ "compute_extension:floating_ip_pools": [],
+ "compute_extension:floating_ips": [],
+ "compute_extension:hosts": [],
+ "compute_extension:keypairs": [],
+ "compute_extension:multinic": [],
+ "compute_extension:networks": [],
+ "compute_extension:quotas": [],
+ "compute_extension:rescue": [],
+ "compute_extension:security_groups": [],
+ "compute_extension:server_action_list": [],
+ "compute_extension:server_diagnostics": [],
+ "compute_extension:simple_tenant_usage": [],
+ "compute_extension:users": [],
+ "compute_extension:virtual_interfaces": [],
+ "compute_extension:virtual_storage_arrays": [],
+ "compute_extension:volumes": [],
+ "compute_extension:volumetypes": [],
+ "compute_extension:zones": [],
+
+
+
"volume:create": [],
"volume:get": [],
"volume:get_all": [],