Merge "Fix flavor_access extension follow API V3 rules"
This commit is contained in:
@@ -71,11 +71,9 @@ class FlavorAccessTemplate(xmlutil.TemplateBuilder):
|
||||
def _marshall_flavor_access(flavor_id):
|
||||
rval = []
|
||||
try:
|
||||
access_list = flavors.\
|
||||
get_flavor_access_by_flavor_id(flavor_id)
|
||||
except exception.FlavorNotFound:
|
||||
explanation = _("Flavor not found.")
|
||||
raise webob.exc.HTTPNotFound(explanation=explanation)
|
||||
access_list = flavors.get_flavor_access_by_flavor_id(flavor_id)
|
||||
except exception.FlavorNotFound as e:
|
||||
raise webob.exc.HTTPNotFound(explanation=e.format_message())
|
||||
|
||||
for access in access_list:
|
||||
rval.append({'flavor_id': flavor_id,
|
||||
@@ -90,6 +88,7 @@ class FlavorAccessController(object):
|
||||
def __init__(self):
|
||||
super(FlavorAccessController, self).__init__()
|
||||
|
||||
@extensions.expected_errors(404)
|
||||
@wsgi.serializers(xml=FlavorAccessTemplate)
|
||||
def index(self, req, flavor_id):
|
||||
context = req.environ['nova.context']
|
||||
@@ -97,9 +96,8 @@ class FlavorAccessController(object):
|
||||
|
||||
try:
|
||||
flavor = flavors.get_flavor_by_flavor_id(flavor_id)
|
||||
except exception.FlavorNotFound:
|
||||
explanation = _("Flavor not found.")
|
||||
raise webob.exc.HTTPNotFound(explanation=explanation)
|
||||
except exception.FlavorNotFound as e:
|
||||
raise webob.exc.HTTPNotFound(explanation=e.format_message())
|
||||
|
||||
# public flavor to all projects
|
||||
if flavor['is_public']:
|
||||
@@ -112,11 +110,6 @@ class FlavorAccessController(object):
|
||||
|
||||
class FlavorActionController(wsgi.Controller):
|
||||
"""The flavor access API controller for the OpenStack API."""
|
||||
|
||||
def _check_body(self, body):
|
||||
if body is None or body == "":
|
||||
raise webob.exc.HTTPBadRequest(explanation=_("No request body"))
|
||||
|
||||
def _get_flavor_refs(self, context):
|
||||
"""Return a dictionary mapping flavorid to flavor_ref."""
|
||||
|
||||
@@ -163,36 +156,51 @@ class FlavorActionController(wsgi.Controller):
|
||||
|
||||
self._extend_flavor(resp_obj.obj['flavor'], db_flavor)
|
||||
|
||||
@extensions.expected_errors((400, 404, 409))
|
||||
@wsgi.serializers(xml=FlavorAccessTemplate)
|
||||
@wsgi.action("addTenantAccess")
|
||||
def _addTenantAccess(self, req, id, body):
|
||||
@wsgi.action("add_tenant_access")
|
||||
def _add_tenant_access(self, req, id, body):
|
||||
context = req.environ['nova.context']
|
||||
authorize(context)
|
||||
self._check_body(body)
|
||||
if not self.is_valid_body(body, 'add_tenant_access'):
|
||||
raise webob.exc.HTTPBadRequest(explanation=_("Invalid request"))
|
||||
|
||||
vals = body['addTenantAccess']
|
||||
tenant = vals['tenant']
|
||||
vals = body['add_tenant_access']
|
||||
try:
|
||||
tenant = vals['tenant_id']
|
||||
except KeyError:
|
||||
raise webob.exc.HTTPBadRequest(
|
||||
explanation=_("tenant_id is required"))
|
||||
|
||||
try:
|
||||
flavors.add_flavor_access(id, tenant, context)
|
||||
except exception.FlavorAccessExists as err:
|
||||
raise webob.exc.HTTPConflict(explanation=err.format_message())
|
||||
except exception.FlavorNotFound as e:
|
||||
raise webob.exc.HTTPNotFound(explanation=e.format_message())
|
||||
|
||||
return _marshall_flavor_access(id)
|
||||
|
||||
@extensions.expected_errors((400, 404))
|
||||
@wsgi.serializers(xml=FlavorAccessTemplate)
|
||||
@wsgi.action("removeTenantAccess")
|
||||
def _removeTenantAccess(self, req, id, body):
|
||||
@wsgi.action("remove_tenant_access")
|
||||
def _remove_tenant_access(self, req, id, body):
|
||||
context = req.environ['nova.context']
|
||||
authorize(context)
|
||||
self._check_body(body)
|
||||
if not self.is_valid_body(body, 'remove_tenant_access'):
|
||||
raise webob.exc.HTTPBadRequest(explanation=_("Invalid request"))
|
||||
|
||||
vals = body['removeTenantAccess']
|
||||
tenant = vals['tenant']
|
||||
vals = body['remove_tenant_access']
|
||||
try:
|
||||
tenant = vals['tenant_id']
|
||||
except KeyError:
|
||||
raise webob.exc.HTTPBadRequest(
|
||||
explanation=_("tenant_id is required"))
|
||||
|
||||
try:
|
||||
flavors.remove_flavor_access(id, tenant, context)
|
||||
except exception.FlavorAccessNotFound as e:
|
||||
except (exception.FlavorAccessNotFound,
|
||||
exception.FlavorNotFound) as e:
|
||||
raise webob.exc.HTTPNotFound(explanation=e.format_message())
|
||||
|
||||
return _marshall_flavor_access(id)
|
||||
|
||||
@@ -136,8 +136,8 @@ class FlavorAccessTest(test.TestCase):
|
||||
|
||||
def test_list_flavor_access_public(self):
|
||||
# query os-flavor-access on public flavor should return 404
|
||||
req = fakes.HTTPRequest.blank('/v3/fake/flavors/os-flavor-access',
|
||||
use_admin_context=True)
|
||||
req = fakes.HTTPRequestV3.blank('/flavors/os-flavor-access',
|
||||
use_admin_context=True)
|
||||
self.assertRaises(exc.HTTPNotFound,
|
||||
self.flavor_access_controller.index,
|
||||
self.req, '1')
|
||||
@@ -151,38 +151,38 @@ class FlavorAccessTest(test.TestCase):
|
||||
|
||||
def test_list_flavor_with_admin_default_proj1(self):
|
||||
expected = {'flavors': [{'id': '0'}, {'id': '1'}]}
|
||||
req = fakes.HTTPRequest.blank('/v3/fake/flavors',
|
||||
use_admin_context=True)
|
||||
req = fakes.HTTPRequestV3.blank('/flavors',
|
||||
use_admin_context=True)
|
||||
req.environ['nova.context'].project_id = 'proj1'
|
||||
result = self.flavor_controller.index(req)
|
||||
self._verify_flavor_list(result['flavors'], expected['flavors'])
|
||||
|
||||
def test_list_flavor_with_admin_default_proj2(self):
|
||||
expected = {'flavors': [{'id': '0'}, {'id': '1'}, {'id': '2'}]}
|
||||
req = fakes.HTTPRequest.blank('/v3/fake/flavors',
|
||||
use_admin_context=True)
|
||||
req = fakes.HTTPRequestV3.blank('/flavors',
|
||||
use_admin_context=True)
|
||||
req.environ['nova.context'].project_id = 'proj2'
|
||||
result = self.flavor_controller.index(req)
|
||||
self._verify_flavor_list(result['flavors'], expected['flavors'])
|
||||
|
||||
def test_list_flavor_with_admin_ispublic_true(self):
|
||||
expected = {'flavors': [{'id': '0'}, {'id': '1'}]}
|
||||
req = fakes.HTTPRequest.blank('/v3/fake/flavors?is_public=true',
|
||||
use_admin_context=True)
|
||||
req = fakes.HTTPRequestV3.blank('/flavors?is_public=true',
|
||||
use_admin_context=True)
|
||||
result = self.flavor_controller.index(req)
|
||||
self._verify_flavor_list(result['flavors'], expected['flavors'])
|
||||
|
||||
def test_list_flavor_with_admin_ispublic_false(self):
|
||||
expected = {'flavors': [{'id': '2'}, {'id': '3'}]}
|
||||
req = fakes.HTTPRequest.blank('/v3/fake/flavors?is_public=false',
|
||||
use_admin_context=True)
|
||||
req = fakes.HTTPRequestV3.blank('/flavors?is_public=false',
|
||||
use_admin_context=True)
|
||||
result = self.flavor_controller.index(req)
|
||||
self._verify_flavor_list(result['flavors'], expected['flavors'])
|
||||
|
||||
def test_list_flavor_with_admin_ispublic_false_proj2(self):
|
||||
expected = {'flavors': [{'id': '2'}, {'id': '3'}]}
|
||||
req = fakes.HTTPRequest.blank('/v3/fake/flavors?is_public=false',
|
||||
use_admin_context=True)
|
||||
req = fakes.HTTPRequestV3.blank('/flavors?is_public=false',
|
||||
use_admin_context=True)
|
||||
req.environ['nova.context'].project_id = 'proj2'
|
||||
result = self.flavor_controller.index(req)
|
||||
self._verify_flavor_list(result['flavors'], expected['flavors'])
|
||||
@@ -190,36 +190,36 @@ class FlavorAccessTest(test.TestCase):
|
||||
def test_list_flavor_with_admin_ispublic_none(self):
|
||||
expected = {'flavors': [{'id': '0'}, {'id': '1'}, {'id': '2'},
|
||||
{'id': '3'}]}
|
||||
req = fakes.HTTPRequest.blank('/v3/fake/flavors?is_public=none',
|
||||
use_admin_context=True)
|
||||
req = fakes.HTTPRequestV3.blank('/flavors?is_public=none',
|
||||
use_admin_context=True)
|
||||
result = self.flavor_controller.index(req)
|
||||
self._verify_flavor_list(result['flavors'], expected['flavors'])
|
||||
|
||||
def test_list_flavor_with_no_admin_default(self):
|
||||
expected = {'flavors': [{'id': '0'}, {'id': '1'}]}
|
||||
req = fakes.HTTPRequest.blank('/v3/fake/flavors',
|
||||
use_admin_context=False)
|
||||
req = fakes.HTTPRequestV3.blank('/flavors',
|
||||
use_admin_context=False)
|
||||
result = self.flavor_controller.index(req)
|
||||
self._verify_flavor_list(result['flavors'], expected['flavors'])
|
||||
|
||||
def test_list_flavor_with_no_admin_ispublic_true(self):
|
||||
expected = {'flavors': [{'id': '0'}, {'id': '1'}]}
|
||||
req = fakes.HTTPRequest.blank('/v3/fake/flavors?is_public=true',
|
||||
use_admin_context=False)
|
||||
req = fakes.HTTPRequestV3.blank('/flavors?is_public=true',
|
||||
use_admin_context=False)
|
||||
result = self.flavor_controller.index(req)
|
||||
self._verify_flavor_list(result['flavors'], expected['flavors'])
|
||||
|
||||
def test_list_flavor_with_no_admin_ispublic_false(self):
|
||||
expected = {'flavors': [{'id': '0'}, {'id': '1'}]}
|
||||
req = fakes.HTTPRequest.blank('/v3/fake/flavors?is_public=false',
|
||||
use_admin_context=False)
|
||||
req = fakes.HTTPRequestV3.blank('/flavors?is_public=false',
|
||||
use_admin_context=False)
|
||||
result = self.flavor_controller.index(req)
|
||||
self._verify_flavor_list(result['flavors'], expected['flavors'])
|
||||
|
||||
def test_list_flavor_with_no_admin_ispublic_none(self):
|
||||
expected = {'flavors': [{'id': '0'}, {'id': '1'}]}
|
||||
req = fakes.HTTPRequest.blank('/v3/fake/flavors?is_public=none',
|
||||
use_admin_context=False)
|
||||
req = fakes.HTTPRequestV3.blank('/flavors?is_public=none',
|
||||
use_admin_context=False)
|
||||
result = self.flavor_controller.index(req)
|
||||
self._verify_flavor_list(result['flavors'], expected['flavors'])
|
||||
|
||||
@@ -253,25 +253,61 @@ class FlavorAccessTest(test.TestCase):
|
||||
stub_add_flavor_access)
|
||||
expected = {'flavor_access':
|
||||
[{'flavor_id': '3', 'tenant_id': 'proj3'}]}
|
||||
body = {'addTenantAccess': {'tenant': 'proj2'}}
|
||||
req = fakes.HTTPRequest.blank('/v3/fake/flavors/2/action',
|
||||
use_admin_context=True)
|
||||
body = {'add_tenant_access': {'tenant_id': 'proj2'}}
|
||||
req = fakes.HTTPRequestV3.blank('/flavors/3/action',
|
||||
use_admin_context=True)
|
||||
result = self.flavor_action_controller.\
|
||||
_addTenantAccess(req, '3', body)
|
||||
_add_tenant_access(req, '3', body)
|
||||
self.assertEqual(result, expected)
|
||||
|
||||
def test_add_tenant_access_with_non_existed_flavor(self):
|
||||
def stub_add_flavor_access(flavorid, projectid, ctxt=None):
|
||||
raise exception.FlavorNotFound(flavor_id=flavorid)
|
||||
self.stubs.Set(flavors, 'add_flavor_access',
|
||||
stub_add_flavor_access)
|
||||
body = {'add_tenant_access': {'tenant_id': 'proj2'}}
|
||||
req = fakes.HTTPRequestV3.blank('/flavors/3/action',
|
||||
use_admin_context=True)
|
||||
self.assertRaises(exc.HTTPNotFound,
|
||||
self.flavor_action_controller._add_tenant_access,
|
||||
req, '3', body)
|
||||
|
||||
def test_add_tenant_access_without_tenant_id(self):
|
||||
def stub_add_flavor_access(flavorid, projectid, ctxt=None):
|
||||
raise exception.FlavorNotFound(flavor_id=flavorid)
|
||||
self.stubs.Set(flavors, 'add_flavor_access',
|
||||
stub_add_flavor_access)
|
||||
body = {'add_tenant_access': {}}
|
||||
req = fakes.HTTPRequestV3.blank('/flavors/3/action',
|
||||
use_admin_context=True)
|
||||
self.assertRaises(exc.HTTPBadRequest,
|
||||
self.flavor_action_controller._add_tenant_access,
|
||||
req, '3', body)
|
||||
|
||||
def test_add_tenant_access_with_invalid_request(self):
|
||||
def stub_add_flavor_access(flavorid, projectid, ctxt=None):
|
||||
raise exception.FlavorNotFound(flavor_id=flavorid)
|
||||
self.stubs.Set(flavors, 'add_flavor_access',
|
||||
stub_add_flavor_access)
|
||||
body = {'add_tenant_access': None}
|
||||
req = fakes.HTTPRequestV3.blank('/flavors/3/action',
|
||||
use_admin_context=True)
|
||||
self.assertRaises(exc.HTTPBadRequest,
|
||||
self.flavor_action_controller._add_tenant_access,
|
||||
req, '3', body)
|
||||
|
||||
def test_add_tenant_access_with_already_added_access(self):
|
||||
def stub_add_flavor_access(flavorid, projectid, ctxt=None):
|
||||
raise exception.FlavorAccessExists(flavor_id=flavorid,
|
||||
project_id=projectid)
|
||||
self.stubs.Set(flavors, 'add_flavor_access',
|
||||
stub_add_flavor_access)
|
||||
body = {'addTenantAccess': {'tenant': 'proj2'}}
|
||||
req = fakes.HTTPRequest.blank('/v3/fake/flavors/2/action',
|
||||
use_admin_context=True)
|
||||
body = {'add_tenant_access': {'tenant_id': 'proj2'}}
|
||||
req = fakes.HTTPRequestV3.blank('/flavors/3/action',
|
||||
use_admin_context=True)
|
||||
self.assertRaises(exc.HTTPConflict,
|
||||
self.flavor_action_controller._addTenantAccess,
|
||||
self.req, '3', body)
|
||||
self.flavor_action_controller._add_tenant_access,
|
||||
req, '3', body)
|
||||
|
||||
def test_remove_tenant_access_with_bad_access(self):
|
||||
def stub_remove_flavor_access(flavorid, projectid, ctxt=None):
|
||||
@@ -279,12 +315,48 @@ class FlavorAccessTest(test.TestCase):
|
||||
project_id=projectid)
|
||||
self.stubs.Set(flavors, 'remove_flavor_access',
|
||||
stub_remove_flavor_access)
|
||||
body = {'removeTenantAccess': {'tenant': 'proj2'}}
|
||||
req = fakes.HTTPRequest.blank('/v3/fake/flavors/2/action',
|
||||
use_admin_context=True)
|
||||
body = {'remove_tenant_access': {'tenant_id': 'proj2'}}
|
||||
req = fakes.HTTPRequestV3.blank('/flavors/3/action',
|
||||
use_admin_context=True)
|
||||
self.assertRaises(exc.HTTPNotFound,
|
||||
self.flavor_action_controller._removeTenantAccess,
|
||||
self.req, '3', body)
|
||||
self.flavor_action_controller._remove_tenant_access,
|
||||
req, '3', body)
|
||||
|
||||
def test_remove_tenant_access_with_non_existed_flavor(self):
|
||||
def stub_remove_flavor_access(flavorid, projectid, ctxt=None):
|
||||
raise exception.FlavorNotFound(flavor_id=flavorid)
|
||||
self.stubs.Set(flavors, 'remove_flavor_access',
|
||||
stub_remove_flavor_access)
|
||||
body = {'remove_tenant_access': {'tenant_id': 'proj2'}}
|
||||
req = fakes.HTTPRequestV3.blank('/flavors/3/action',
|
||||
use_admin_context=True)
|
||||
self.assertRaises(exc.HTTPNotFound,
|
||||
self.flavor_action_controller._remove_tenant_access,
|
||||
req, '3', body)
|
||||
|
||||
def test_remove_tenant_access_without_tenant_id(self):
|
||||
def stub_remove_flavor_access(flavorid, projectid, ctxt=None):
|
||||
raise exception.FlavorNotFound(flavor_id=flavorid)
|
||||
self.stubs.Set(flavors, 'remove_flavor_access',
|
||||
stub_remove_flavor_access)
|
||||
body = {'remove_tenant_access': {}}
|
||||
req = fakes.HTTPRequestV3.blank('/flavors/3/action',
|
||||
use_admin_context=True)
|
||||
self.assertRaises(exc.HTTPBadRequest,
|
||||
self.flavor_action_controller._remove_tenant_access,
|
||||
req, '3', body)
|
||||
|
||||
def test_remove_tenant_access_with_invalid_request(self):
|
||||
def stub_remove_flavor_access(flavorid, projectid, ctxt=None):
|
||||
raise exception.FlavorNotFound(flavor_id=flavorid)
|
||||
self.stubs.Set(flavors, 'remove_flavor_access',
|
||||
stub_remove_flavor_access)
|
||||
body = {'remove_tenant_access': None}
|
||||
req = fakes.HTTPRequestV3.blank('/flavors/3/action',
|
||||
use_admin_context=True)
|
||||
self.assertRaises(exc.HTTPBadRequest,
|
||||
self.flavor_action_controller._remove_tenant_access,
|
||||
req, '3', body)
|
||||
|
||||
|
||||
class FlavorAccessSerializerTest(test.TestCase):
|
||||
|
||||
Reference in New Issue
Block a user