From 7937144fce54570b2da543663e6ee5e64b1c3cdb Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Fri, 14 Sep 2012 00:21:03 +0000 Subject: Clean up handling of project_only in network_get There was some funky logic for getting networks to work around the project only decorator. This changes the code to match what we actually want which is: In Flat and FlatDHCP mode non-admins should be able to access networks that belong to their project or networks that have no project_id assigned. In VlanManager, project_id=None projects should not be accessible as this means the project hasn't been assigned yet. The assignment is done with an elevated context. This patch adds some logic to model_query to allow None in the project_only filter and makes network_get_all_by_uuids and network_get use it. fixes bug 1048869 Change-Id: I5377cea87dec8e9d0d9cec84e07128c5c6e8dca3 --- nova/db/api.py | 10 ++++++---- nova/db/sqlalchemy/api.py | 40 +++++++++++++++++++--------------------- 2 files changed, 25 insertions(+), 25 deletions(-) (limited to 'nova/db') diff --git a/nova/db/api.py b/nova/db/api.py index 785944d14..de393287a 100644 --- a/nova/db/api.py +++ b/nova/db/api.py @@ -810,9 +810,9 @@ def network_disassociate(context, network_id): return IMPL.network_disassociate(context, network_id) -def network_get(context, network_id): +def network_get(context, network_id, project_only="allow_none"): """Get a network or raise if it does not exist.""" - return IMPL.network_get(context, network_id) + return IMPL.network_get(context, network_id, project_only=project_only) def network_get_all(context): @@ -820,9 +820,11 @@ def network_get_all(context): return IMPL.network_get_all(context) -def network_get_all_by_uuids(context, network_uuids, project_id=None): +def network_get_all_by_uuids(context, network_uuids, + project_only="allow_none"): """Return networks by ids.""" - return IMPL.network_get_all_by_uuids(context, network_uuids, project_id) + return IMPL.network_get_all_by_uuids(context, network_uuids, + project_only=project_only) # pylint: disable=C0103 diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index f39856cc6..ea8d7cbec 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -188,20 +188,21 @@ def require_aggregate_exists(f): return wrapper -def model_query(context, *args, **kwargs): +def model_query(context, model, *args, **kwargs): """Query helper that accounts for context's `read_deleted` field. :param context: context to query under :param session: if present, the session to use :param read_deleted: if present, overrides context's read_deleted field. :param project_only: if present and context is user-type, then restrict - query to match the context's project_id. + query to match the context's project_id. If set to 'allow_none', + restriction includes project_id = None. """ session = kwargs.get('session') or get_session() read_deleted = kwargs.get('read_deleted') or context.read_deleted - project_only = kwargs.get('project_only') + project_only = kwargs.get('project_only', False) - query = session.query(*args) + query = session.query(model, *args) if read_deleted == 'no': query = query.filter_by(deleted=False) @@ -213,8 +214,12 @@ def model_query(context, *args, **kwargs): raise Exception( _("Unrecognized read_deleted value '%s'") % read_deleted) - if project_only and is_user_context(context): - query = query.filter_by(project_id=context.project_id) + if is_user_context(context) and project_only: + if project_only == 'allow_none': + query = query.filter(or_(model.project_id == context.project_id, + model.project_id == None)) + else: + query = query.filter_by(project_id=context.project_id) return query @@ -2130,9 +2135,9 @@ def network_disassociate(context, network_id): @require_context -def network_get(context, network_id, session=None): +def network_get(context, network_id, session=None, project_only='allow_none'): result = model_query(context, models.Network, session=session, - project_only=True).\ + project_only=project_only).\ filter_by(id=network_id).\ first() @@ -2152,24 +2157,17 @@ def network_get_all(context): return result -@require_admin_context -def network_get_all_by_uuids(context, network_uuids, project_id=None): - project_or_none = or_(models.Network.project_id == project_id, - models.Network.project_id == None) - result = model_query(context, models.Network, read_deleted="no").\ +@require_context +def network_get_all_by_uuids(context, network_uuids, + project_only="allow_none"): + result = model_query(context, models.Network, read_deleted="no", + project_only=project_only).\ filter(models.Network.uuid.in_(network_uuids)).\ - filter(project_or_none).\ all() if not result: raise exception.NoNetworksFound() - #check if host is set to all of the networks - # returned in the result - for network in result: - if network['host'] is None: - raise exception.NetworkHostNotSet(network_id=network['id']) - #check if the result contains all the networks #we are looking for for network_uuid in network_uuids: @@ -2179,7 +2177,7 @@ def network_get_all_by_uuids(context, network_uuids, project_id=None): found = True break if not found: - if project_id: + if project_only: raise exception.NetworkNotFoundForProject( network_uuid=network_uuid, project_id=context.project_id) raise exception.NetworkNotFound(network_id=network_uuid) -- cgit