Skip to content

Commit ae3addd

Browse files
committed
Remove deleted projects from flavor access list
Previously Nova was unable to remove deleted projects from flavor's access lists. This patch lifts described limitation and improves logic of nova/api/openstack/identity.py library by introducing two separate kinds of exceptions: - webob.exc.HTTPInternalServerError is raised when Keystone identity service version 3.0 was not found. - webob.exc.HTTPBadRequest is raised when specified project is not found. Closes-bug: #1980845 Change-Id: Icbf3bdd944f9a6c38f25ddea0b521ca48ee87a7f (cherry picked from commit 8c6daaa) (cherry picked from commit 2ea2b55) (cherry picked from commit 6c1b862) (cherry picked from commit 61c14bd)
1 parent 57c084f commit ae3addd

File tree

3 files changed

+45
-11
lines changed

3 files changed

+45
-11
lines changed

nova/api/openstack/compute/flavor_access.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,14 @@ def _remove_tenant_access(self, req, id, body):
9393

9494
vals = body['removeTenantAccess']
9595
tenant = vals['tenant']
96-
identity.verify_project_id(context, tenant)
96+
# It doesn't really matter if project exists or not: we can delete
97+
# it from flavor's access list in both cases.
98+
try:
99+
identity.verify_project_id(context, tenant)
100+
except webob.exc.HTTPBadRequest as identity_exc:
101+
msg = "Project ID %s is not a valid project." % tenant
102+
if msg not in identity_exc.explanation:
103+
raise
97104

98105
# NOTE(gibi): We have to load a flavor from the db here as
99106
# flavor.remove_access() will try to emit a notification and that needs

nova/api/openstack/identity.py

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,24 +27,27 @@ def verify_project_id(context, project_id):
2727
"""verify that a project_id exists.
2828
2929
This attempts to verify that a project id exists. If it does not,
30-
an HTTPBadRequest is emitted.
30+
an HTTPBadRequest is emitted. Also HTTPBadRequest is emitted
31+
if Keystone identity service version 3.0 is not found.
3132
3233
"""
3334
adap = utils.get_ksa_adapter(
3435
'identity', ksa_auth=context.get_auth_plugin(),
3536
min_version=(3, 0), max_version=(3, 'latest'))
3637

37-
failure = webob.exc.HTTPBadRequest(
38-
explanation=_("Project ID %s is not a valid project.") %
39-
project_id)
4038
try:
4139
resp = adap.get('/projects/%s' % project_id)
4240
except kse.EndpointNotFound:
4341
LOG.error(
44-
"Keystone identity service version 3.0 was not found. This might "
45-
"be because your endpoint points to the v2.0 versioned endpoint "
46-
"which is not supported. Please fix this.")
47-
raise failure
42+
"Keystone identity service version 3.0 was not found. This "
43+
"might be caused by Nova misconfiguration or Keystone "
44+
"problems.")
45+
msg = _("Nova was unable to find Keystone service endpoint.")
46+
# TODO(astupnik). It may be reasonable to switch to HTTP 503
47+
# (HTTP Service Unavailable) instead of HTTP Bad Request here.
48+
# If proper Keystone servie is inaccessible, then technially
49+
# this is a server side error and not an error in Nova.
50+
raise webob.exc.HTTPBadRequest(explanation=msg)
4851
except kse.ClientException:
4952
# something is wrong, like there isn't a keystone v3 endpoint,
5053
# or nova isn't configured for the interface to talk to it;
@@ -57,7 +60,8 @@ def verify_project_id(context, project_id):
5760
return True
5861
elif resp.status_code == 404:
5962
# we got access, and we know this project is not there
60-
raise failure
63+
msg = _("Project ID %s is not a valid project.") % project_id
64+
raise webob.exc.HTTPBadRequest(explanation=msg)
6165
elif resp.status_code == 403:
6266
# we don't have enough permission to verify this, so default
6367
# to "it's ok".

nova/tests/unit/api/openstack/compute/test_flavor_access.py

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -351,14 +351,37 @@ def test_add_tenant_access_with_invalid_tenant(self, mock_verify):
351351
mock_verify.assert_called_once_with(
352352
req.environ['nova.context'], 'proj2')
353353

354+
@mock.patch('nova.objects.Flavor.remove_access')
354355
@mock.patch('nova.api.openstack.identity.verify_project_id',
355356
side_effect=exc.HTTPBadRequest(
356357
explanation="Project ID proj2 is not a valid project."))
357-
def test_remove_tenant_access_with_invalid_tenant(self, mock_verify):
358+
def test_remove_tenant_access_with_invalid_tenant(self,
359+
mock_verify,
360+
mock_remove_access):
358361
"""Tests the case that the tenant does not exist in Keystone."""
359362
req = fakes.HTTPRequest.blank(self._prefix + '/flavors/2/action',
360363
use_admin_context=True)
361364
body = {'removeTenantAccess': {'tenant': 'proj2'}}
365+
366+
self.flavor_action_controller._remove_tenant_access(
367+
req, '2', body=body)
368+
mock_verify.assert_called_once_with(
369+
req.environ['nova.context'], 'proj2')
370+
mock_remove_access.assert_called_once_with('proj2')
371+
372+
@mock.patch('nova.api.openstack.identity.verify_project_id',
373+
side_effect=exc.HTTPBadRequest(
374+
explanation="Nova was unable to find Keystone "
375+
"service endpoint."))
376+
def test_remove_tenant_access_missing_keystone_endpoint(self,
377+
mock_verify):
378+
"""Tests the case that Keystone identity service endpoint
379+
version 3.0 was not found.
380+
"""
381+
req = fakes.HTTPRequest.blank(self._prefix + '/flavors/2/action',
382+
use_admin_context=True)
383+
body = {'removeTenantAccess': {'tenant': 'proj2'}}
384+
362385
self.assertRaises(exc.HTTPBadRequest,
363386
self.flavor_action_controller._remove_tenant_access,
364387
req, '2', body=body)

0 commit comments

Comments
 (0)