Merge "Remove deleted projects from flavor access list"
This commit is contained in:
commit
922f5f6da4
|
@ -93,7 +93,14 @@ class FlavorActionController(wsgi.Controller):
|
||||||
|
|
||||||
vals = body['removeTenantAccess']
|
vals = body['removeTenantAccess']
|
||||||
tenant = vals['tenant']
|
tenant = vals['tenant']
|
||||||
identity.verify_project_id(context, tenant)
|
# It doesn't really matter if project exists or not: we can delete
|
||||||
|
# it from flavor's access list in both cases.
|
||||||
|
try:
|
||||||
|
identity.verify_project_id(context, tenant)
|
||||||
|
except webob.exc.HTTPBadRequest as identity_exc:
|
||||||
|
msg = "Project ID %s is not a valid project." % tenant
|
||||||
|
if msg not in identity_exc.explanation:
|
||||||
|
raise
|
||||||
|
|
||||||
# NOTE(gibi): We have to load a flavor from the db here as
|
# NOTE(gibi): We have to load a flavor from the db here as
|
||||||
# flavor.remove_access() will try to emit a notification and that needs
|
# flavor.remove_access() will try to emit a notification and that needs
|
||||||
|
|
|
@ -27,24 +27,27 @@ def verify_project_id(context, project_id):
|
||||||
"""verify that a project_id exists.
|
"""verify that a project_id exists.
|
||||||
|
|
||||||
This attempts to verify that a project id exists. If it does not,
|
This attempts to verify that a project id exists. If it does not,
|
||||||
an HTTPBadRequest is emitted.
|
an HTTPBadRequest is emitted. Also HTTPBadRequest is emitted
|
||||||
|
if Keystone identity service version 3.0 is not found.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
adap = utils.get_ksa_adapter(
|
adap = utils.get_ksa_adapter(
|
||||||
'identity', ksa_auth=context.get_auth_plugin(),
|
'identity', ksa_auth=context.get_auth_plugin(),
|
||||||
min_version=(3, 0), max_version=(3, 'latest'))
|
min_version=(3, 0), max_version=(3, 'latest'))
|
||||||
|
|
||||||
failure = webob.exc.HTTPBadRequest(
|
|
||||||
explanation=_("Project ID %s is not a valid project.") %
|
|
||||||
project_id)
|
|
||||||
try:
|
try:
|
||||||
resp = adap.get('/projects/%s' % project_id)
|
resp = adap.get('/projects/%s' % project_id)
|
||||||
except kse.EndpointNotFound:
|
except kse.EndpointNotFound:
|
||||||
LOG.error(
|
LOG.error(
|
||||||
"Keystone identity service version 3.0 was not found. This might "
|
"Keystone identity service version 3.0 was not found. This "
|
||||||
"be because your endpoint points to the v2.0 versioned endpoint "
|
"might be caused by Nova misconfiguration or Keystone "
|
||||||
"which is not supported. Please fix this.")
|
"problems.")
|
||||||
raise failure
|
msg = _("Nova was unable to find Keystone service endpoint.")
|
||||||
|
# TODO(astupnik). It may be reasonable to switch to HTTP 503
|
||||||
|
# (HTTP Service Unavailable) instead of HTTP Bad Request here.
|
||||||
|
# If proper Keystone servie is inaccessible, then technially
|
||||||
|
# this is a server side error and not an error in Nova.
|
||||||
|
raise webob.exc.HTTPBadRequest(explanation=msg)
|
||||||
except kse.ClientException:
|
except kse.ClientException:
|
||||||
# something is wrong, like there isn't a keystone v3 endpoint,
|
# something is wrong, like there isn't a keystone v3 endpoint,
|
||||||
# or nova isn't configured for the interface to talk to it;
|
# or nova isn't configured for the interface to talk to it;
|
||||||
|
@ -57,7 +60,8 @@ def verify_project_id(context, project_id):
|
||||||
return True
|
return True
|
||||||
elif resp.status_code == 404:
|
elif resp.status_code == 404:
|
||||||
# we got access, and we know this project is not there
|
# we got access, and we know this project is not there
|
||||||
raise failure
|
msg = _("Project ID %s is not a valid project.") % project_id
|
||||||
|
raise webob.exc.HTTPBadRequest(explanation=msg)
|
||||||
elif resp.status_code == 403:
|
elif resp.status_code == 403:
|
||||||
# we don't have enough permission to verify this, so default
|
# we don't have enough permission to verify this, so default
|
||||||
# to "it's ok".
|
# to "it's ok".
|
||||||
|
|
|
@ -353,14 +353,37 @@ class FlavorAccessTestV21(test.NoDBTestCase):
|
||||||
mock_verify.assert_called_once_with(
|
mock_verify.assert_called_once_with(
|
||||||
req.environ['nova.context'], 'proj2')
|
req.environ['nova.context'], 'proj2')
|
||||||
|
|
||||||
|
@mock.patch('nova.objects.Flavor.remove_access')
|
||||||
@mock.patch('nova.api.openstack.identity.verify_project_id',
|
@mock.patch('nova.api.openstack.identity.verify_project_id',
|
||||||
side_effect=exc.HTTPBadRequest(
|
side_effect=exc.HTTPBadRequest(
|
||||||
explanation="Project ID proj2 is not a valid project."))
|
explanation="Project ID proj2 is not a valid project."))
|
||||||
def test_remove_tenant_access_with_invalid_tenant(self, mock_verify):
|
def test_remove_tenant_access_with_invalid_tenant(self,
|
||||||
|
mock_verify,
|
||||||
|
mock_remove_access):
|
||||||
"""Tests the case that the tenant does not exist in Keystone."""
|
"""Tests the case that the tenant does not exist in Keystone."""
|
||||||
req = fakes.HTTPRequest.blank(self._prefix + '/flavors/2/action',
|
req = fakes.HTTPRequest.blank(self._prefix + '/flavors/2/action',
|
||||||
use_admin_context=True)
|
use_admin_context=True)
|
||||||
body = {'removeTenantAccess': {'tenant': 'proj2'}}
|
body = {'removeTenantAccess': {'tenant': 'proj2'}}
|
||||||
|
|
||||||
|
self.flavor_action_controller._remove_tenant_access(
|
||||||
|
req, '2', body=body)
|
||||||
|
mock_verify.assert_called_once_with(
|
||||||
|
req.environ['nova.context'], 'proj2')
|
||||||
|
mock_remove_access.assert_called_once_with('proj2')
|
||||||
|
|
||||||
|
@mock.patch('nova.api.openstack.identity.verify_project_id',
|
||||||
|
side_effect=exc.HTTPBadRequest(
|
||||||
|
explanation="Nova was unable to find Keystone "
|
||||||
|
"service endpoint."))
|
||||||
|
def test_remove_tenant_access_missing_keystone_endpoint(self,
|
||||||
|
mock_verify):
|
||||||
|
"""Tests the case that Keystone identity service endpoint
|
||||||
|
version 3.0 was not found.
|
||||||
|
"""
|
||||||
|
req = fakes.HTTPRequest.blank(self._prefix + '/flavors/2/action',
|
||||||
|
use_admin_context=True)
|
||||||
|
body = {'removeTenantAccess': {'tenant': 'proj2'}}
|
||||||
|
|
||||||
self.assertRaises(exc.HTTPBadRequest,
|
self.assertRaises(exc.HTTPBadRequest,
|
||||||
self.flavor_action_controller._remove_tenant_access,
|
self.flavor_action_controller._remove_tenant_access,
|
||||||
req, '2', body=body)
|
req, '2', body=body)
|
||||||
|
|
Loading…
Reference in New Issue