cleanup checking of options in the API before calling compute_api's get_all()

This commit is contained in:
Chris Behrens
2011-08-04 01:36:12 -07:00
parent b5ac286fad
commit c0851f2ec5
2 changed files with 49 additions and 62 deletions

View File

@@ -44,55 +44,25 @@ LOG = logging.getLogger('nova.api.openstack.servers')
FLAGS = flags.FLAGS
def check_admin_search_options(context, search_options, admin_api_options):
"""Check for any 'admin_api_options' specified in 'search_options'.
If admin api is not enabled, we should pretend that we know nothing
about those options.. Ie, they don't exist in user-facing API. To
achieve this, we will strip any admin options that we find from
search_options
If admin api is enabled, we should require admin context for any
admin options specified, and return an exception in this case.
If any exist and admin api is not enabled, strip them from
search_options (has the effect of treating them like they don't exist).
search_options is a dictionary of "search_option": value
admin_api_options is a list
Returns: None if options are okay.
Modifies: admin options could be stripped from search_options
Raises: exception.AdminRequired for needing admin context
"""
if not FLAGS.allow_admin_api:
# Remove any admin_api_options from search_options
for option in admin_api_options:
search_options.pop(option, None)
return
# allow_admin_api is True and admin context? Any command is okay.
if context.is_admin:
return
spec_admin_opts = [opt for opt in search_options.iterkeys()
if opt in admin_api_options]
if spec_admin_opts:
admin_opt_str = ", ".join(spec_admin_opts)
LOG.error(_("Received request for admin-only search options "
"'%(admin_opt_str)s' from non-admin context") %
locals())
raise exception.AdminRequired()
class Controller(object):
""" The Server API controller for the OpenStack API """
""" The Server API base controller class for the OpenStack API """
servers_search_options = []
def __init__(self):
self.compute_api = compute.API()
self.helper = helper.CreateInstanceHelper(self)
def _check_servers_options(self, search_options):
if FLAGS.allow_admin_api and context.is_admin:
# Allow all options
return
# Otherwise, strip out all unknown options
unknown_options = [opt for opt in search_options
if opt not in self.servers_search_options]
for opt in unknown_options:
search_options.pop(opt, None)
def index(self, req):
""" Returns a list of server names and ids for a given user """
try:
@@ -131,21 +101,38 @@ class Controller(object):
search_opts = {}
# If search by 'status', we need to convert it to 'state'
# If the status is unknown, bail
status = search_opts.pop('status', None)
if status is not None:
# If the status is unknown, bail.
# Leave 'state' in search_opts so compute can pass it on to
# child zones..
if 'status' in search_opts:
status = search_opts['status']
search_opts['state'] = power_state.states_from_status(status)
if len(search_opts['state']) == 0:
reason = _('Invalid server status: %(status)s') % locals()
LOG.error(reason)
raise exception.InvalidInput(reason=reason)
# Don't pass these along to compute API, if they exist.
search_opts.pop('changes-since', None)
search_opts.pop('fresh', None)
# By default, compute's get_all() will return deleted instances.
# If an admin hasn't specified a 'deleted' search option, we need
# to filter out deleted instances by setting the filter ourselves.
# ... Unless 'changes-since' is specified, because 'changes-since'
# should return recently deleted images according to the API spec.
if 'deleted' not in search_opts:
# Admin hasn't specified deleted filter
if 'changes-since' not in search_opts:
# No 'changes-since', so we need to find non-deleted servers
search_opts['deleted'] = '^False$'
else:
# This is the default, but just in case..
search_opts['deleted'] = '^True$'
instance_list = self.compute_api.get_all(
context, search_opts=search_opts)
# FIXME(comstud): 'changes-since' is not fully implemented. Where
# should this be filtered?
limited_list = self._limit_items(instance_list, req)
servers = [self._build_view(req, inst, is_detail)['server']
for inst in limited_list]
@@ -160,21 +147,12 @@ class Controller(object):
search_opts = {}
search_opts.update(req.str_GET)
admin_api = ['ip', 'ip6', 'instance_name']
context = req.environ['nova.context']
try:
check_admin_search_options(context, search_opts, admin_api)
except exception.AdminRequired, e:
raise exc.HTTPForbidden(detail=str(e))
self._check_servers_options(context, search_opts)
# Convert recurse_zones into a boolean
search_opts['recurse_zones'] = utils.bool_from_str(
search_opts.get('recurse_zones', False))
# convert flavor into an int
if 'flavor' in search_opts:
search_opts['flavor'] = int(search_opts['flavor'])
return self._servers_search(context, req, is_detail,
search_opts=search_opts)
@@ -581,6 +559,10 @@ class Controller(object):
class ControllerV10(Controller):
"""v1.0 OpenStack API controller"""
servers_search_options = ["reservation_id", "fixed_ip",
"name", "recurse_zones"]
@scheduler_api.redirect_handler
def delete(self, req, id):
@@ -645,6 +627,10 @@ class ControllerV10(Controller):
class ControllerV11(Controller):
"""v1.1 OpenStack API controller"""
servers_search_options = ["reservation_id", "name", "recurse_zones",
"status", "image", "flavor", "changes-since"]
@scheduler_api.redirect_handler
def delete(self, req, id):

View File

@@ -1149,7 +1149,9 @@ def instance_get_all(context):
@require_context
def instance_get_all_by_filters(context, filters):
"""Return instances the match all filters"""
"""Return instances the match all filters. Deleted instances
will be returned by default, unless there's a filter that says
otherwise"""
def _filter_by_ipv6(instance, filter_re):
for interface in instance['virtual_interfaces']:
@@ -1195,8 +1197,7 @@ def instance_get_all_by_filters(context, filters):
options(joinedload('security_groups')).\
options(joinedload_all('fixed_ips.network')).\
options(joinedload('metadata')).\
options(joinedload('instance_type')).\
filter_by(deleted=can_read_deleted(context))
options(joinedload('instance_type'))
filters = filters.copy()