diff --git a/nova/api/openstack/compute/plugins/v3/servers.py b/nova/api/openstack/compute/plugins/v3/servers.py index 92e029c7d8ec..693ad60bcc49 100644 --- a/nova/api/openstack/compute/plugins/v3/servers.py +++ b/nova/api/openstack/compute/plugins/v3/servers.py @@ -539,6 +539,21 @@ class ServersController(wsgi.Controller): msg = _("Only administrators may list deleted instances") raise exc.HTTPBadRequest(explanation=msg) + # If tenant_id is passed as a search parameter this should + # imply that all_tenants is also enabled unless explicitly + # disabled. Note that the tenant_id parameter is filtered out + # by remove_invalid_options above unless the requestor is an + # admin. + if 'tenant_id' in search_opts and not 'all_tenants' in search_opts: + # We do not need to add the all_tenants flag if the tenant + # id associated with the token is the tenant id + # specified. This is done so a request that does not need + # the all_tenants flag does not fail because of lack of + # policy permission for compute:get_all_tenants when it + # doesn't actually need it. + if context.project_id != search_opts.get('tenant_id'): + search_opts['all_tenants'] = 1 + # If all tenants is passed with 0 or false as the value # then remove it from the search options. Nothing passed as # the value for all_tenants is considered to enable the feature diff --git a/nova/tests/api/openstack/compute/plugins/v3/test_servers.py b/nova/tests/api/openstack/compute/plugins/v3/test_servers.py index 75bbb03a3817..b83452539bb6 100644 --- a/nova/tests/api/openstack/compute/plugins/v3/test_servers.py +++ b/nova/tests/api/openstack/compute/plugins/v3/test_servers.py @@ -697,6 +697,42 @@ class ServersControllerTest(ControllerTest): self.assertIn('servers', res) + def test_tenant_id_filter_no_admin_context(self): + def fake_get_all(context, filters=None, sort_key=None, + sort_dir='desc', limit=None, marker=None, + columns_to_join=None): + self.assertNotEqual(filters, None) + self.assertEqual(filters['project_id'], 'fake') + return [fakes.stub_instance(100)] + + self.stubs.Set(db, 'instance_get_all_by_filters', + fake_get_all) + + req = fakes.HTTPRequestV3.blank('/servers?tenant_id=newfake') + res = self.controller.index(req) + self.assertTrue('servers' in res) + + def test_tenant_id_filter_implies_all_tenants(self): + def fake_get_all(context, filters=None, sort_key=None, + sort_dir='desc', limit=None, marker=None, + columns_to_join=None): + self.assertNotEqual(filters, None) + # The project_id assertion checks that the project_id + # filter is set to that specified in the request url and + # not that of the context, verifying that the all_tenants + # flag was enabled + self.assertEqual(filters['project_id'], 'newfake') + self.assertFalse(filters.get('tenant_id')) + return [fakes.stub_instance(100)] + + self.stubs.Set(db, 'instance_get_all_by_filters', + fake_get_all) + + req = fakes.HTTPRequestV3.blank('/servers?tenant_id=newfake', + use_admin_context=True) + res = self.controller.index(req) + self.assertTrue('servers' in res) + def test_all_tenants_param_normal(self): def fake_get_all(context, filters=None, sort_key=None, sort_dir='desc', limit=None, marker=None,