Change v3 flavor_access to v2.1
This patch changes v3 flavor_access API to v2.1 and makes v2 unit tests share between v2 and v2.1. The differences between v2 and v3 are described on the wiki page https://wiki.openstack.org/wiki/NovaAPIv2tov3. Partially implements blueprint v2-on-v3-api Change-Id: I75891e76753fba937b4a01f592afb4bd03aacd9c
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"add_tenant_access": {
|
||||
"tenant_id": "fake_tenant"
|
||||
"addTenantAccess": {
|
||||
"tenant": "fake_tenant"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -5,6 +5,6 @@
|
||||
"vcpus": 2,
|
||||
"disk": 10,
|
||||
"id": "10",
|
||||
"flavor-access:is_public": false
|
||||
"os-flavor-access:is_public": false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -3,7 +3,7 @@
|
||||
"disabled": false,
|
||||
"disk": 10,
|
||||
"ephemeral": 0,
|
||||
"flavor-access:is_public": false,
|
||||
"os-flavor-access:is_public": false,
|
||||
"id": "10",
|
||||
"links": [
|
||||
{
|
||||
@@ -20,4 +20,4 @@
|
||||
"swap": 0,
|
||||
"vcpus": 2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -4,7 +4,7 @@
|
||||
"disabled": false,
|
||||
"disk": 1,
|
||||
"ephemeral": 0,
|
||||
"flavor-access:is_public": true,
|
||||
"os-flavor-access:is_public": true,
|
||||
"id": "1",
|
||||
"links": [
|
||||
{
|
||||
@@ -25,7 +25,7 @@
|
||||
"disabled": false,
|
||||
"disk": 20,
|
||||
"ephemeral": 0,
|
||||
"flavor-access:is_public": true,
|
||||
"os-flavor-access:is_public": true,
|
||||
"id": "2",
|
||||
"links": [
|
||||
{
|
||||
@@ -46,7 +46,7 @@
|
||||
"disabled": false,
|
||||
"disk": 40,
|
||||
"ephemeral": 0,
|
||||
"flavor-access:is_public": true,
|
||||
"os-flavor-access:is_public": true,
|
||||
"id": "3",
|
||||
"links": [
|
||||
{
|
||||
@@ -67,7 +67,7 @@
|
||||
"disabled": false,
|
||||
"disk": 80,
|
||||
"ephemeral": 0,
|
||||
"flavor-access:is_public": true,
|
||||
"os-flavor-access:is_public": true,
|
||||
"id": "4",
|
||||
"links": [
|
||||
{
|
||||
@@ -88,7 +88,7 @@
|
||||
"disabled": false,
|
||||
"disk": 160,
|
||||
"ephemeral": 0,
|
||||
"flavor-access:is_public": true,
|
||||
"os-flavor-access:is_public": true,
|
||||
"id": "5",
|
||||
"links": [
|
||||
{
|
||||
@@ -106,4 +106,4 @@
|
||||
"vcpus": 8
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"remove_tenant_access": {
|
||||
"tenant_id": "fake_tenant"
|
||||
"removeTenantAccess": {
|
||||
"tenant": "fake_tenant"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -3,7 +3,7 @@
|
||||
"disabled": false,
|
||||
"disk": 1,
|
||||
"ephemeral": 0,
|
||||
"flavor-access:is_public": true,
|
||||
"os-flavor-access:is_public": true,
|
||||
"id": "1",
|
||||
"links": [
|
||||
{
|
||||
@@ -20,4 +20,4 @@
|
||||
"swap": 0,
|
||||
"vcpus": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -3,7 +3,7 @@
|
||||
"disabled": false,
|
||||
"disk": 10,
|
||||
"ephemeral": 0,
|
||||
"flavor-access:is_public": true,
|
||||
"os-flavor-access:is_public": true,
|
||||
"id": "10",
|
||||
"links": [
|
||||
{
|
||||
@@ -20,4 +20,4 @@
|
||||
"swap": 0,
|
||||
"vcpus": 2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -3,7 +3,7 @@
|
||||
"disabled": false,
|
||||
"disk": 1,
|
||||
"ephemeral": 0,
|
||||
"flavor-access:is_public": true,
|
||||
"os-flavor-access:is_public": true,
|
||||
"id": "1",
|
||||
"links": [
|
||||
{
|
||||
@@ -20,4 +20,4 @@
|
||||
"swap": 0,
|
||||
"vcpus": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -4,7 +4,7 @@
|
||||
"disabled": false,
|
||||
"disk": 1,
|
||||
"ephemeral": 0,
|
||||
"flavor-access:is_public": true,
|
||||
"os-flavor-access:is_public": true,
|
||||
"id": "1",
|
||||
"links": [
|
||||
{
|
||||
@@ -25,7 +25,7 @@
|
||||
"disabled": false,
|
||||
"disk": 20,
|
||||
"ephemeral": 0,
|
||||
"flavor-access:is_public": true,
|
||||
"os-flavor-access:is_public": true,
|
||||
"id": "2",
|
||||
"links": [
|
||||
{
|
||||
@@ -46,7 +46,7 @@
|
||||
"disabled": false,
|
||||
"disk": 40,
|
||||
"ephemeral": 0,
|
||||
"flavor-access:is_public": true,
|
||||
"os-flavor-access:is_public": true,
|
||||
"id": "3",
|
||||
"links": [
|
||||
{
|
||||
@@ -67,7 +67,7 @@
|
||||
"disabled": false,
|
||||
"disk": 80,
|
||||
"ephemeral": 0,
|
||||
"flavor-access:is_public": true,
|
||||
"os-flavor-access:is_public": true,
|
||||
"id": "4",
|
||||
"links": [
|
||||
{
|
||||
@@ -88,7 +88,7 @@
|
||||
"disabled": false,
|
||||
"disk": 160,
|
||||
"ephemeral": 0,
|
||||
"flavor-access:is_public": true,
|
||||
"os-flavor-access:is_public": true,
|
||||
"id": "5",
|
||||
"links": [
|
||||
{
|
||||
@@ -106,4 +106,4 @@
|
||||
"vcpus": 8
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@@ -3,7 +3,7 @@
|
||||
"disabled": false,
|
||||
"disk": 1,
|
||||
"ephemeral": 0,
|
||||
"flavor-access:is_public": true,
|
||||
"os-flavor-access:is_public": true,
|
||||
"id": "1",
|
||||
"links": [
|
||||
{
|
||||
|
@@ -4,7 +4,7 @@
|
||||
"disabled": false,
|
||||
"disk": 1,
|
||||
"ephemeral": 0,
|
||||
"flavor-access:is_public": true,
|
||||
"os-flavor-access:is_public": true,
|
||||
"id": "1",
|
||||
"links": [
|
||||
{
|
||||
@@ -26,7 +26,7 @@
|
||||
"disabled": false,
|
||||
"disk": 20,
|
||||
"ephemeral": 0,
|
||||
"flavor-access:is_public": true,
|
||||
"os-flavor-access:is_public": true,
|
||||
"id": "2",
|
||||
"links": [
|
||||
{
|
||||
@@ -48,7 +48,7 @@
|
||||
"disabled": false,
|
||||
"disk": 40,
|
||||
"ephemeral": 0,
|
||||
"flavor-access:is_public": true,
|
||||
"os-flavor-access:is_public": true,
|
||||
"id": "3",
|
||||
"links": [
|
||||
{
|
||||
@@ -70,7 +70,7 @@
|
||||
"disabled": false,
|
||||
"disk": 80,
|
||||
"ephemeral": 0,
|
||||
"flavor-access:is_public": true,
|
||||
"os-flavor-access:is_public": true,
|
||||
"id": "4",
|
||||
"links": [
|
||||
{
|
||||
@@ -92,7 +92,7 @@
|
||||
"disabled": false,
|
||||
"disk": 160,
|
||||
"ephemeral": 0,
|
||||
"flavor-access:is_public": true,
|
||||
"os-flavor-access:is_public": true,
|
||||
"id": "5",
|
||||
"links": [
|
||||
{
|
||||
|
@@ -3,7 +3,7 @@
|
||||
"disabled": false,
|
||||
"disk": 10,
|
||||
"ephemeral": 0,
|
||||
"flavor-access:is_public": true,
|
||||
"os-flavor-access:is_public": true,
|
||||
"id": "100",
|
||||
"links": [
|
||||
{
|
||||
|
@@ -123,10 +123,10 @@
|
||||
"compute_extension:flavor_access": "",
|
||||
"compute_extension:flavor_access:addTenantAccess": "rule:admin_api",
|
||||
"compute_extension:flavor_access:removeTenantAccess": "rule:admin_api",
|
||||
"compute_extension:v3:flavor-access": "",
|
||||
"compute_extension:v3:flavor-access:discoverable": "",
|
||||
"compute_extension:v3:flavor-access:remove_tenant_access": "rule:admin_api",
|
||||
"compute_extension:v3:flavor-access:add_tenant_access": "rule:admin_api",
|
||||
"compute_extension:v3:os-flavor-access": "",
|
||||
"compute_extension:v3:os-flavor-access:discoverable": "",
|
||||
"compute_extension:v3:os-flavor-access:remove_tenant_access": "rule:admin_api",
|
||||
"compute_extension:v3:os-flavor-access:add_tenant_access": "rule:admin_api",
|
||||
"compute_extension:flavor_disabled": "",
|
||||
"compute_extension:flavor_rxtx": "",
|
||||
"compute_extension:v3:os-flavor-rxtx": "",
|
||||
|
@@ -64,12 +64,12 @@ CONF.register_opts(api_opts, api_opts_group)
|
||||
# TODO(cyeoh): Expand this list as the core APIs are ported to V3
|
||||
API_V3_CORE_EXTENSIONS = set(['consoles',
|
||||
'extensions',
|
||||
'flavor-access',
|
||||
'flavor-extra-specs',
|
||||
'flavor-manage',
|
||||
'flavors',
|
||||
'ips',
|
||||
'os-keypairs',
|
||||
'os-flavor-access',
|
||||
'server-metadata',
|
||||
'servers',
|
||||
'versions'])
|
||||
|
@@ -25,7 +25,7 @@ from nova import exception
|
||||
from nova.i18n import _
|
||||
from nova import objects
|
||||
|
||||
ALIAS = 'flavor-access'
|
||||
ALIAS = 'os-flavor-access'
|
||||
soft_authorize = extensions.soft_extension_authorizer('compute',
|
||||
'v3:' + ALIAS)
|
||||
authorize = extensions.extension_authorizer('compute', 'v3:%s' % ALIAS)
|
||||
@@ -106,14 +106,14 @@ class FlavorActionController(wsgi.Controller):
|
||||
self._extend_flavor(resp_obj.obj['flavor'], db_flavor)
|
||||
|
||||
@extensions.expected_errors((400, 403, 404, 409))
|
||||
@wsgi.action("add_tenant_access")
|
||||
@wsgi.action("addTenantAccess")
|
||||
@validation.schema(flavor_access.add_tenant_access)
|
||||
def _add_tenant_access(self, req, id, body):
|
||||
context = req.environ['nova.context']
|
||||
authorize(context, action="add_tenant_access")
|
||||
|
||||
vals = body['add_tenant_access']
|
||||
tenant = vals['tenant_id']
|
||||
vals = body['addTenantAccess']
|
||||
tenant = vals['tenant']
|
||||
|
||||
flavor = objects.Flavor(context=context, flavorid=id)
|
||||
try:
|
||||
@@ -127,14 +127,14 @@ class FlavorActionController(wsgi.Controller):
|
||||
return _marshall_flavor_access(flavor)
|
||||
|
||||
@extensions.expected_errors((400, 403, 404))
|
||||
@wsgi.action("remove_tenant_access")
|
||||
@wsgi.action("removeTenantAccess")
|
||||
@validation.schema(flavor_access.remove_tenant_access)
|
||||
def _remove_tenant_access(self, req, id, body):
|
||||
context = req.environ['nova.context']
|
||||
authorize(context, action="remove_tenant_access")
|
||||
|
||||
vals = body['remove_tenant_access']
|
||||
tenant = vals['tenant_id']
|
||||
vals = body['removeTenantAccess']
|
||||
tenant = vals['tenant']
|
||||
|
||||
flavor = objects.Flavor(context=context, flavorid=id)
|
||||
try:
|
||||
|
@@ -66,7 +66,7 @@ class FlavorManageController(wsgi.Controller):
|
||||
ephemeral_gb = vals.get('ephemeral', 0)
|
||||
swap = vals.get('swap', 0)
|
||||
rxtx_factor = vals.get('rxtx_factor', 1.0)
|
||||
is_public = vals.get('flavor-access:is_public', True)
|
||||
is_public = vals.get('os-flavor-access:is_public', True)
|
||||
|
||||
try:
|
||||
flavor = flavors.create(name, memory, vcpus, root_gb,
|
||||
|
@@ -15,19 +15,19 @@
|
||||
add_tenant_access = {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'add_tenant_access': {
|
||||
'addTenantAccess': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'tenant_id': {
|
||||
'tenant': {
|
||||
# defined from project_id in instance_type_projects table
|
||||
'type': 'string', 'minLength': 1, 'maxLength': 255,
|
||||
},
|
||||
},
|
||||
'required': ['tenant_id'],
|
||||
'required': ['tenant'],
|
||||
'additionalProperties': False,
|
||||
},
|
||||
},
|
||||
'required': ['add_tenant_access'],
|
||||
'required': ['addTenantAccess'],
|
||||
'additionalProperties': False,
|
||||
}
|
||||
|
||||
@@ -35,18 +35,18 @@ add_tenant_access = {
|
||||
remove_tenant_access = {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'remove_tenant_access': {
|
||||
'removeTenantAccess': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'tenant_id': {
|
||||
'tenant': {
|
||||
# defined from project_id in instance_type_projects table
|
||||
'type': 'string', 'minLength': 1, 'maxLength': 255,
|
||||
},
|
||||
},
|
||||
'required': ['tenant_id'],
|
||||
'required': ['tenant'],
|
||||
'additionalProperties': False,
|
||||
},
|
||||
},
|
||||
'required': ['remove_tenant_access'],
|
||||
'required': ['removeTenantAccess'],
|
||||
'additionalProperties': False,
|
||||
}
|
||||
|
@@ -59,7 +59,7 @@ create = {
|
||||
'pattern': '^[0-9]+(\.[0-9]+)?$',
|
||||
'minimum': 0, 'exclusiveMinimum': True
|
||||
},
|
||||
'flavor-access:is_public': parameter_types.boolean,
|
||||
'os-flavor-access:is_public': parameter_types.boolean,
|
||||
},
|
||||
# TODO(oomichi): 'id' should be required with v2.1+microversions.
|
||||
# On v2.0 API, nova-api generates a flavor-id automatically if
|
||||
|
@@ -18,8 +18,11 @@ import datetime
|
||||
from lxml import etree
|
||||
from webob import exc
|
||||
|
||||
from nova.api.openstack.compute.contrib import flavor_access
|
||||
from nova.api.openstack.compute.contrib import flavor_access \
|
||||
as flavor_access_v2
|
||||
from nova.api.openstack.compute import flavors as flavors_api
|
||||
from nova.api.openstack.compute.plugins.v3 import flavor_access \
|
||||
as flavor_access_v3
|
||||
from nova import context
|
||||
from nova import db
|
||||
from nova import exception
|
||||
@@ -117,12 +120,16 @@ class FakeResponse(object):
|
||||
pass
|
||||
|
||||
|
||||
class FlavorAccessTest(test.NoDBTestCase):
|
||||
class FlavorAccessTestV21(test.NoDBTestCase):
|
||||
api_version = "2.1"
|
||||
FlavorAccessController = flavor_access_v3.FlavorAccessController
|
||||
FlavorActionController = flavor_access_v3.FlavorActionController
|
||||
_prefix = "/v3"
|
||||
validation_ex = exception.ValidationError
|
||||
|
||||
def setUp(self):
|
||||
super(FlavorAccessTest, self).setUp()
|
||||
super(FlavorAccessTestV21, self).setUp()
|
||||
self.flavor_controller = flavors_api.Controller()
|
||||
self.flavor_access_controller = flavor_access.FlavorAccessController()
|
||||
self.flavor_action_controller = flavor_access.FlavorActionController()
|
||||
self.req = FakeRequest()
|
||||
self.context = self.req.environ['nova.context']
|
||||
self.stubs.Set(db, 'flavor_get_by_flavor_id',
|
||||
@@ -132,6 +139,9 @@ class FlavorAccessTest(test.NoDBTestCase):
|
||||
self.stubs.Set(db, 'flavor_access_get_by_flavor_id',
|
||||
fake_get_flavor_access_by_flavor_id)
|
||||
|
||||
self.flavor_access_controller = self.FlavorAccessController()
|
||||
self.flavor_action_controller = self.FlavorActionController()
|
||||
|
||||
def _verify_flavor_list(self, result, expected):
|
||||
# result already sorted by flavor_id
|
||||
self.assertEqual(len(result), len(expected))
|
||||
@@ -153,14 +163,19 @@ class FlavorAccessTest(test.NoDBTestCase):
|
||||
self.assertEqual(result, expected)
|
||||
|
||||
def test_list_with_no_context(self):
|
||||
req = fakes.HTTPRequest.blank('/v2/flavors/fake/flavors')
|
||||
req = fakes.HTTPRequest.blank(self._prefix + '/flavors/fake/flavors')
|
||||
|
||||
def fake_authorize(context, target=None, action=None):
|
||||
raise exception.PolicyNotAuthorized(action='index')
|
||||
|
||||
self.stubs.Set(flavor_access,
|
||||
'authorize',
|
||||
fake_authorize)
|
||||
if self.api_version == "2.1":
|
||||
self.stubs.Set(flavor_access_v3,
|
||||
'authorize',
|
||||
fake_authorize)
|
||||
else:
|
||||
self.stubs.Set(flavor_access_v2,
|
||||
'authorize',
|
||||
fake_authorize)
|
||||
|
||||
self.assertRaises(exception.PolicyNotAuthorized,
|
||||
self.flavor_access_controller.index,
|
||||
@@ -168,7 +183,7 @@ class FlavorAccessTest(test.NoDBTestCase):
|
||||
|
||||
def test_list_flavor_with_admin_default_proj1(self):
|
||||
expected = {'flavors': [{'id': '0'}, {'id': '1'}]}
|
||||
req = fakes.HTTPRequest.blank('/v2/fake/flavors',
|
||||
req = fakes.HTTPRequest.blank(self._prefix + '/fake/flavors',
|
||||
use_admin_context=True)
|
||||
req.environ['nova.context'].project_id = 'proj1'
|
||||
result = self.flavor_controller.index(req)
|
||||
@@ -176,7 +191,7 @@ class FlavorAccessTest(test.NoDBTestCase):
|
||||
|
||||
def test_list_flavor_with_admin_default_proj2(self):
|
||||
expected = {'flavors': [{'id': '0'}, {'id': '1'}, {'id': '2'}]}
|
||||
req = fakes.HTTPRequest.blank('/v2/fake/flavors',
|
||||
req = fakes.HTTPRequest.blank(self._prefix + '/flavors',
|
||||
use_admin_context=True)
|
||||
req.environ['nova.context'].project_id = 'proj2'
|
||||
result = self.flavor_controller.index(req)
|
||||
@@ -184,21 +199,24 @@ class FlavorAccessTest(test.NoDBTestCase):
|
||||
|
||||
def test_list_flavor_with_admin_ispublic_true(self):
|
||||
expected = {'flavors': [{'id': '0'}, {'id': '1'}]}
|
||||
req = fakes.HTTPRequest.blank('/v2/fake/flavors?is_public=true',
|
||||
url = self._prefix + '/flavors?is_public=true'
|
||||
req = fakes.HTTPRequest.blank(url,
|
||||
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('/v2/fake/flavors?is_public=false',
|
||||
url = self._prefix + '/flavors?is_public=false'
|
||||
req = fakes.HTTPRequest.blank(url,
|
||||
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('/v2/fake/flavors?is_public=false',
|
||||
url = self._prefix + '/flavors?is_public=false'
|
||||
req = fakes.HTTPRequest.blank(url,
|
||||
use_admin_context=True)
|
||||
req.environ['nova.context'].project_id = 'proj2'
|
||||
result = self.flavor_controller.index(req)
|
||||
@@ -207,35 +225,39 @@ class FlavorAccessTest(test.NoDBTestCase):
|
||||
def test_list_flavor_with_admin_ispublic_none(self):
|
||||
expected = {'flavors': [{'id': '0'}, {'id': '1'}, {'id': '2'},
|
||||
{'id': '3'}]}
|
||||
req = fakes.HTTPRequest.blank('/v2/fake/flavors?is_public=none',
|
||||
url = self._prefix + '/flavors?is_public=none'
|
||||
req = fakes.HTTPRequest.blank(url,
|
||||
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('/v2/fake/flavors',
|
||||
req = fakes.HTTPRequest.blank(self._prefix + '/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('/v2/fake/flavors?is_public=true',
|
||||
url = self._prefix + '/flavors?is_public=true'
|
||||
req = fakes.HTTPRequest.blank(url,
|
||||
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('/v2/fake/flavors?is_public=false',
|
||||
url = self._prefix + '/flavors?is_public=false'
|
||||
req = fakes.HTTPRequest.blank(url,
|
||||
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('/v2/fake/flavors?is_public=none',
|
||||
url = self._prefix + '/flavors?is_public=none'
|
||||
req = fakes.HTTPRequest.blank(url,
|
||||
use_admin_context=False)
|
||||
result = self.flavor_controller.index(req)
|
||||
self._verify_flavor_list(result['flavors'], expected['flavors'])
|
||||
@@ -262,6 +284,18 @@ class FlavorAccessTest(test.NoDBTestCase):
|
||||
self.assertEqual({'id': '0', 'os-flavor-access:is_public': True},
|
||||
resp.obj['flavor'])
|
||||
|
||||
def _get_add_access(self):
|
||||
if self.api_version == "2.1":
|
||||
return self.flavor_action_controller._add_tenant_access
|
||||
else:
|
||||
return self.flavor_action_controller._addTenantAccess
|
||||
|
||||
def _get_remove_access(self):
|
||||
if self.api_version == "2.1":
|
||||
return self.flavor_action_controller._remove_tenant_access
|
||||
else:
|
||||
return self.flavor_action_controller._removeTenantAccess
|
||||
|
||||
def test_add_tenant_access(self):
|
||||
def stub_add_flavor_access(context, flavorid, projectid):
|
||||
self.assertEqual('3', flavorid, "flavorid")
|
||||
@@ -271,31 +305,31 @@ class FlavorAccessTest(test.NoDBTestCase):
|
||||
expected = {'flavor_access':
|
||||
[{'flavor_id': '3', 'tenant_id': 'proj3'}]}
|
||||
body = {'addTenantAccess': {'tenant': 'proj2'}}
|
||||
req = fakes.HTTPRequest.blank('/v2/fake/flavors/2/action',
|
||||
req = fakes.HTTPRequest.blank(self._prefix + '/flavors/2/action',
|
||||
use_admin_context=True)
|
||||
result = self.flavor_action_controller.\
|
||||
_addTenantAccess(req, '3', body)
|
||||
|
||||
add_access = self._get_add_access()
|
||||
result = add_access(req, '3', body=body)
|
||||
self.assertEqual(result, expected)
|
||||
|
||||
def test_add_tenant_access_with_no_admin_user(self):
|
||||
req = fakes.HTTPRequest.blank('/v2/fake/flavors/2/action',
|
||||
req = fakes.HTTPRequest.blank(self._prefix + '/flavors/2/action',
|
||||
use_admin_context=False)
|
||||
body = {'addTenantAccess': {'tenant': 'proj2'}}
|
||||
add_access = self._get_add_access()
|
||||
self.assertRaises(exception.PolicyNotAuthorized,
|
||||
self.flavor_action_controller._addTenantAccess,
|
||||
req, '2', body)
|
||||
add_access, req, '2', body=body)
|
||||
|
||||
def test_add_tenant_access_with_no_tenant(self):
|
||||
req = fakes.HTTPRequest.blank('/v2/fake/flavors/2/action',
|
||||
req = fakes.HTTPRequest.blank(self._prefix + '/flavors/2/action',
|
||||
use_admin_context=True)
|
||||
body = {'addTenantAccess': {'foo': 'proj2'}}
|
||||
self.assertRaises(exc.HTTPBadRequest,
|
||||
self.flavor_action_controller._addTenantAccess,
|
||||
req, '2', body)
|
||||
add_access = self._get_add_access()
|
||||
self.assertRaises(self.validation_ex,
|
||||
add_access, req, '2', body=body)
|
||||
body = {'addTenantAccess': {'tenant': ''}}
|
||||
self.assertRaises(exc.HTTPBadRequest,
|
||||
self.flavor_action_controller._addTenantAccess,
|
||||
req, '2', body)
|
||||
self.assertRaises(self.validation_ex,
|
||||
add_access, req, '2', body=body)
|
||||
|
||||
def test_add_tenant_access_with_already_added_access(self):
|
||||
def stub_add_flavor_access(context, flavorid, projectid):
|
||||
@@ -304,9 +338,9 @@ class FlavorAccessTest(test.NoDBTestCase):
|
||||
self.stubs.Set(db, 'flavor_access_add',
|
||||
stub_add_flavor_access)
|
||||
body = {'addTenantAccess': {'tenant': 'proj2'}}
|
||||
add_access = self._get_add_access()
|
||||
self.assertRaises(exc.HTTPConflict,
|
||||
self.flavor_action_controller._addTenantAccess,
|
||||
self.req, '3', body)
|
||||
add_access, self.req, '3', body=body)
|
||||
|
||||
def test_remove_tenant_access_with_bad_access(self):
|
||||
def stub_remove_flavor_access(context, flavorid, projectid):
|
||||
@@ -315,34 +349,41 @@ class FlavorAccessTest(test.NoDBTestCase):
|
||||
self.stubs.Set(db, 'flavor_access_remove',
|
||||
stub_remove_flavor_access)
|
||||
body = {'removeTenantAccess': {'tenant': 'proj2'}}
|
||||
remove_access = self._get_remove_access()
|
||||
self.assertRaises(exc.HTTPNotFound,
|
||||
self.flavor_action_controller._removeTenantAccess,
|
||||
self.req, '3', body)
|
||||
remove_access, self.req, '3', body=body)
|
||||
|
||||
def test_delete_tenant_access_with_no_tenant(self):
|
||||
req = fakes.HTTPRequest.blank('/v2/fake/flavors/2/action',
|
||||
req = fakes.HTTPRequest.blank(self._prefix + '/flavors/2/action',
|
||||
use_admin_context=True)
|
||||
remove_access = self._get_remove_access()
|
||||
body = {'removeTenantAccess': {'foo': 'proj2'}}
|
||||
self.assertRaises(exc.HTTPBadRequest,
|
||||
self.flavor_action_controller._removeTenantAccess,
|
||||
req, '2', body)
|
||||
self.assertRaises(self.validation_ex,
|
||||
remove_access, req, '2', body=body)
|
||||
body = {'removeTenantAccess': {'tenant': ''}}
|
||||
self.assertRaises(exc.HTTPBadRequest,
|
||||
self.flavor_action_controller._removeTenantAccess,
|
||||
req, '2', body)
|
||||
self.assertRaises(self.validation_ex,
|
||||
remove_access, req, '2', body=body)
|
||||
|
||||
def test_remove_tenant_access_with_no_admin_user(self):
|
||||
req = fakes.HTTPRequest.blank('/v2/fake/flavors/2/action',
|
||||
req = fakes.HTTPRequest.blank(self._prefix + '/flavors/2/action',
|
||||
use_admin_context=False)
|
||||
body = {'removeTenantAccess': {'tenant': 'proj2'}}
|
||||
remove_access = self._get_remove_access()
|
||||
self.assertRaises(exception.PolicyNotAuthorized,
|
||||
self.flavor_action_controller._removeTenantAccess,
|
||||
req, '2', body)
|
||||
remove_access, req, '2', body=body)
|
||||
|
||||
|
||||
class FlavorAccessTestV20(FlavorAccessTestV21):
|
||||
api_version = "2.0"
|
||||
FlavorAccessController = flavor_access_v2.FlavorAccessController
|
||||
FlavorActionController = flavor_access_v2.FlavorActionController
|
||||
_prefix = "/v2/fake"
|
||||
validation_ex = exc.HTTPBadRequest
|
||||
|
||||
|
||||
class FlavorAccessSerializerTest(test.NoDBTestCase):
|
||||
def test_serializer_empty(self):
|
||||
serializer = flavor_access.FlavorAccessTemplate()
|
||||
serializer = flavor_access_v2.FlavorAccessTemplate()
|
||||
text = serializer.serialize(dict(flavor_access=[]))
|
||||
tree = etree.fromstring(text)
|
||||
self.assertEqual(len(tree), 0)
|
||||
@@ -356,6 +397,6 @@ class FlavorAccessSerializerTest(test.NoDBTestCase):
|
||||
access_list = [{'flavor_id': '2', 'tenant_id': 'proj2'},
|
||||
{'flavor_id': '2', 'tenant_id': 'proj3'}]
|
||||
|
||||
serializer = flavor_access.FlavorAccessTemplate()
|
||||
serializer = flavor_access_v2.FlavorAccessTemplate()
|
||||
text = serializer.serialize(dict(flavor_access=access_list))
|
||||
self.assertEqual(text, expected)
|
||||
|
@@ -1,412 +0,0 @@
|
||||
# Copyright 2012 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import datetime
|
||||
|
||||
from webob import exc
|
||||
|
||||
from nova.api.openstack.compute import flavors as flavors_api
|
||||
from nova.api.openstack.compute.plugins.v3 import flavor_access
|
||||
from nova import context
|
||||
from nova import db
|
||||
from nova import exception
|
||||
from nova import test
|
||||
from nova.tests.api.openstack import fakes
|
||||
|
||||
|
||||
def generate_flavor(flavorid, ispublic):
|
||||
return {
|
||||
'id': flavorid,
|
||||
'flavorid': str(flavorid),
|
||||
'root_gb': 1,
|
||||
'ephemeral_gb': 1,
|
||||
'name': u'test',
|
||||
'deleted': False,
|
||||
'created_at': datetime.datetime(2012, 1, 1, 1, 1, 1, 1),
|
||||
'updated_at': None,
|
||||
'memory_mb': 512,
|
||||
'vcpus': 1,
|
||||
'swap': 512,
|
||||
'rxtx_factor': 1.0,
|
||||
'disabled': False,
|
||||
'extra_specs': {},
|
||||
'deleted_at': None,
|
||||
'vcpu_weight': None,
|
||||
'is_public': bool(ispublic)
|
||||
}
|
||||
|
||||
|
||||
INSTANCE_TYPES = {
|
||||
'0': generate_flavor(0, True),
|
||||
'1': generate_flavor(1, True),
|
||||
'2': generate_flavor(2, False),
|
||||
'3': generate_flavor(3, False)}
|
||||
|
||||
|
||||
ACCESS_LIST = [{'flavor_id': '2', 'project_id': 'proj2'},
|
||||
{'flavor_id': '2', 'project_id': 'proj3'},
|
||||
{'flavor_id': '3', 'project_id': 'proj3'}]
|
||||
|
||||
|
||||
def fake_get_flavor_access_by_flavor_id(context, flavorid):
|
||||
res = []
|
||||
for access in ACCESS_LIST:
|
||||
if access['flavor_id'] == flavorid:
|
||||
res.append(access)
|
||||
return res
|
||||
|
||||
|
||||
def fake_get_flavor_by_flavor_id(context, flavorid, read_deleted):
|
||||
return INSTANCE_TYPES[flavorid]
|
||||
|
||||
|
||||
def _has_flavor_access(flavorid, projectid):
|
||||
for access in ACCESS_LIST:
|
||||
if access['flavor_id'] == flavorid and \
|
||||
access['project_id'] == projectid:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def fake_get_all_flavors_sorted_list(context, inactive=False,
|
||||
filters=None, sort_key='flavorid',
|
||||
sort_dir='asc', limit=None, marker=None):
|
||||
if filters is None or filters['is_public'] is None:
|
||||
return sorted(INSTANCE_TYPES.values(), key=lambda item: item[sort_key])
|
||||
|
||||
res = {}
|
||||
for k, v in INSTANCE_TYPES.iteritems():
|
||||
if filters['is_public'] and _has_flavor_access(k, context.project_id):
|
||||
res.update({k: v})
|
||||
continue
|
||||
if v['is_public'] == filters['is_public']:
|
||||
res.update({k: v})
|
||||
|
||||
res = sorted(res.values(), key=lambda item: item[sort_key])
|
||||
return res
|
||||
|
||||
|
||||
class FakeRequest(object):
|
||||
environ = {"nova.context": context.get_admin_context()}
|
||||
|
||||
def get_db_flavor(self, flavor_id):
|
||||
return INSTANCE_TYPES[flavor_id]
|
||||
|
||||
|
||||
class FakeResponse(object):
|
||||
obj = {'flavor': {'id': '0'},
|
||||
'flavors': [
|
||||
{'id': '0'},
|
||||
{'id': '2'}]
|
||||
}
|
||||
|
||||
def attach(self, **kwargs):
|
||||
pass
|
||||
|
||||
|
||||
class FlavorAccessTest(test.NoDBTestCase):
|
||||
def setUp(self):
|
||||
super(FlavorAccessTest, self).setUp()
|
||||
self.flavor_controller = flavors_api.Controller()
|
||||
self.flavor_access_controller = flavor_access.FlavorAccessController()
|
||||
self.flavor_action_controller = flavor_access.FlavorActionController()
|
||||
self.req = FakeRequest()
|
||||
self.context = self.req.environ['nova.context']
|
||||
self.stubs.Set(db, 'flavor_get_by_flavor_id',
|
||||
fake_get_flavor_by_flavor_id)
|
||||
self.stubs.Set(db, 'flavor_get_all',
|
||||
fake_get_all_flavors_sorted_list)
|
||||
self.stubs.Set(db, 'flavor_access_get_by_flavor_id',
|
||||
fake_get_flavor_access_by_flavor_id)
|
||||
|
||||
def _verify_flavor_list(self, result, expected):
|
||||
# result already sorted by flavor_id
|
||||
self.assertEqual(len(result), len(expected))
|
||||
|
||||
for d1, d2 in zip(result, expected):
|
||||
self.assertEqual(d1['id'], d2['id'])
|
||||
|
||||
def test_list_flavor_access_public(self):
|
||||
# query flavor-access on public flavor should return 404
|
||||
self.assertRaises(exc.HTTPNotFound,
|
||||
self.flavor_access_controller.index,
|
||||
self.req, '1')
|
||||
|
||||
def test_list_flavor_access_private(self):
|
||||
expected = {'flavor_access': [
|
||||
{'flavor_id': '2', 'tenant_id': 'proj2'},
|
||||
{'flavor_id': '2', 'tenant_id': 'proj3'}]}
|
||||
result = self.flavor_access_controller.index(self.req, '2')
|
||||
self.assertEqual(result, expected)
|
||||
|
||||
def test_list_with_no_context(self):
|
||||
req = fakes.HTTPRequestV3.blank('/flavors/2/flavor-access')
|
||||
|
||||
def fake_authorize(context, target=None, action=None):
|
||||
raise exception.PolicyNotAuthorized(action='index')
|
||||
|
||||
self.stubs.Set(flavor_access, 'authorize', fake_authorize)
|
||||
|
||||
self.assertRaises(exception.PolicyNotAuthorized,
|
||||
self.flavor_access_controller.index,
|
||||
req, '2')
|
||||
|
||||
def test_list_flavor_with_admin_default_proj1(self):
|
||||
expected = {'flavors': [{'id': '0'}, {'id': '1'}]}
|
||||
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.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.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.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.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'])
|
||||
|
||||
def test_list_flavor_with_admin_ispublic_none(self):
|
||||
expected = {'flavors': [{'id': '0'}, {'id': '1'}, {'id': '2'},
|
||||
{'id': '3'}]}
|
||||
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.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.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.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.HTTPRequestV3.blank('/flavors?is_public=none',
|
||||
use_admin_context=False)
|
||||
result = self.flavor_controller.index(req)
|
||||
self._verify_flavor_list(result['flavors'], expected['flavors'])
|
||||
|
||||
def test_show(self):
|
||||
resp = FakeResponse()
|
||||
self.flavor_action_controller.show(self.req, resp, '0')
|
||||
self.assertEqual({'id': '0', 'flavor-access:is_public': True},
|
||||
resp.obj['flavor'])
|
||||
self.flavor_action_controller.show(self.req, resp, '2')
|
||||
self.assertEqual({'id': '0', 'flavor-access:is_public': False},
|
||||
resp.obj['flavor'])
|
||||
|
||||
def test_detail(self):
|
||||
resp = FakeResponse()
|
||||
self.flavor_action_controller.detail(self.req, resp)
|
||||
self.assertEqual([{'id': '0', 'flavor-access:is_public': True},
|
||||
{'id': '2', 'flavor-access:is_public': False}],
|
||||
resp.obj['flavors'])
|
||||
|
||||
def test_create(self):
|
||||
resp = FakeResponse()
|
||||
self.flavor_action_controller.create(self.req, {}, resp)
|
||||
self.assertEqual({'id': '0', 'flavor-access:is_public': True},
|
||||
resp.obj['flavor'])
|
||||
|
||||
def test_add_tenant_access(self):
|
||||
def stub_add_flavor_access(context, flavorid, projectid):
|
||||
self.assertEqual('3', flavorid, "flavorid")
|
||||
self.assertEqual("proj2", projectid, "projectid")
|
||||
self.stubs.Set(db, 'flavor_access_add',
|
||||
stub_add_flavor_access)
|
||||
expected = {'flavor_access':
|
||||
[{'flavor_id': '3', 'tenant_id': 'proj3'}]}
|
||||
body = {'add_tenant_access': {'tenant_id': 'proj2'}}
|
||||
req = fakes.HTTPRequestV3.blank('/flavors/3/action',
|
||||
use_admin_context=True)
|
||||
result = self.flavor_action_controller.\
|
||||
_add_tenant_access(req, '3', body=body)
|
||||
self.assertEqual(result, expected)
|
||||
|
||||
def test_add_tenant_access_with_non_existed_flavor(self):
|
||||
def stub_flavor_access_add(context, flavorid, project_id):
|
||||
raise exception.FlavorNotFound(flavor_id=flavorid)
|
||||
self.stubs.Set(db, 'flavor_access_add',
|
||||
stub_flavor_access_add)
|
||||
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=body)
|
||||
|
||||
def test_add_tenant_access_with_no_admin_user(self):
|
||||
req = fakes.HTTPRequestV3.blank('/flavors/2/action')
|
||||
body = {'add_tenant_access': {'tenant_id': 'proj2'}}
|
||||
self.assertRaises(exception.PolicyNotAuthorized,
|
||||
self.flavor_action_controller._add_tenant_access,
|
||||
req, '2', body=body)
|
||||
|
||||
def test_add_tenant_access_without_policy_check(self):
|
||||
req = fakes.HTTPRequestV3.blank('/flavors/3/action')
|
||||
body = {'add_tenant_access': {'tenant_id': 'proj2'}}
|
||||
|
||||
def fake_authorize(context, target=None, action=None):
|
||||
pass
|
||||
|
||||
self.stubs.Set(flavor_access, 'authorize', fake_authorize)
|
||||
self.assertRaises(exc.HTTPForbidden,
|
||||
self.flavor_action_controller._add_tenant_access,
|
||||
req, '3', body=body)
|
||||
|
||||
def test_add_tenant_access_without_tenant_id(self):
|
||||
def stub_add_flavor_access(context, flavorid, projectid):
|
||||
raise exception.FlavorNotFound(flavor_id=flavorid)
|
||||
self.stubs.Set(db, 'flavor_access_add',
|
||||
stub_add_flavor_access)
|
||||
body = {'add_tenant_access': {}}
|
||||
req = fakes.HTTPRequestV3.blank('/flavors/3/action',
|
||||
use_admin_context=True)
|
||||
self.assertRaises(exception.ValidationError,
|
||||
self.flavor_action_controller._add_tenant_access,
|
||||
req, '3', body=body)
|
||||
|
||||
def test_add_tenant_access_with_invalid_request(self):
|
||||
def stub_add_flavor_access(context, flavorid, projectid):
|
||||
raise exception.FlavorNotFound(flavor_id=flavorid)
|
||||
self.stubs.Set(db, 'flavor_access_add',
|
||||
stub_add_flavor_access)
|
||||
body = {'add_tenant_access': None}
|
||||
req = fakes.HTTPRequestV3.blank('/flavors/3/action',
|
||||
use_admin_context=True)
|
||||
self.assertRaises(exception.ValidationError,
|
||||
self.flavor_action_controller._add_tenant_access,
|
||||
req, '3', body=body)
|
||||
|
||||
def test_add_tenant_access_with_already_added_access(self):
|
||||
def stub_add_flavor_access(context, flavorid, projectid):
|
||||
raise exception.FlavorAccessExists(flavor_id=flavorid,
|
||||
project_id=projectid)
|
||||
self.stubs.Set(db, 'flavor_access_add',
|
||||
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.HTTPConflict,
|
||||
self.flavor_action_controller._add_tenant_access,
|
||||
req, '3', body=body)
|
||||
|
||||
def test_remove_tenant_access_with_bad_access(self):
|
||||
def stub_remove_flavor_access(context, flavorid, projectid):
|
||||
raise exception.FlavorAccessNotFound(flavor_id=flavorid,
|
||||
project_id=projectid)
|
||||
self.stubs.Set(db, 'flavor_access_remove',
|
||||
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=body)
|
||||
|
||||
def test_remove_tenant_access_with_non_existed_flavor(self):
|
||||
def stub_remove_flavor_access(context, flavorid, projectid):
|
||||
raise exception.FlavorNotFound(flavor_id=flavorid)
|
||||
self.stubs.Set(db, 'flavor_access_remove',
|
||||
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=body)
|
||||
|
||||
def test_remove_tenant_access_without_tenant_id(self):
|
||||
def stub_remove_flavor_access(context, flavorid, projectid):
|
||||
raise exception.FlavorNotFound(flavor_id=flavorid)
|
||||
self.stubs.Set(db, 'flavor_access_remove',
|
||||
stub_remove_flavor_access)
|
||||
body = {'remove_tenant_access': {}}
|
||||
req = fakes.HTTPRequestV3.blank('/flavors/3/action',
|
||||
use_admin_context=True)
|
||||
self.assertRaises(exception.ValidationError,
|
||||
self.flavor_action_controller._remove_tenant_access,
|
||||
req, '3', body=body)
|
||||
|
||||
def test_remove_tenant_access_with_invalid_request(self):
|
||||
def stub_remove_flavor_access(context, flavorid, projectid):
|
||||
raise exception.FlavorNotFound(flavor_id=flavorid)
|
||||
self.stubs.Set(db, 'flavor_access_remove',
|
||||
stub_remove_flavor_access)
|
||||
body = {'remove_tenant_access': None}
|
||||
req = fakes.HTTPRequestV3.blank('/flavors/3/action',
|
||||
use_admin_context=True)
|
||||
self.assertRaises(exception.ValidationError,
|
||||
self.flavor_action_controller._remove_tenant_access,
|
||||
req, '3', body=body)
|
||||
|
||||
def test_remove_tenant_access_with_no_admin_user(self):
|
||||
req = fakes.HTTPRequestV3.blank('flavors/2/action',
|
||||
use_admin_context=False)
|
||||
body = {'remove_tenant_access': {'tenant_id': 'proj2'}}
|
||||
self.assertRaises(exception.PolicyNotAuthorized,
|
||||
self.flavor_action_controller._remove_tenant_access,
|
||||
req, '2', body=body)
|
||||
|
||||
def test_remove_tenant_access_without_policy_check(self):
|
||||
req = fakes.HTTPRequestV3.blank('/flavors/2/action')
|
||||
body = {'remove_tenant_access': {'tenant_id': 'proj2'}}
|
||||
|
||||
def fake_authorize(context, target=None, action=None):
|
||||
pass
|
||||
|
||||
self.stubs.Set(flavor_access, 'authorize', fake_authorize)
|
||||
self.assertRaises(exc.HTTPForbidden,
|
||||
self.flavor_action_controller._remove_tenant_access,
|
||||
req, '2', body=body)
|
@@ -94,7 +94,7 @@ class FlavorManageTest(test.NoDBTestCase):
|
||||
self.app = fakes.wsgi_app_v3(init_only=('servers', 'flavors',
|
||||
'flavor-manage',
|
||||
'os-flavor-rxtx',
|
||||
'flavor-access'))
|
||||
'os-flavor-access'))
|
||||
|
||||
self.base_request_dict = {
|
||||
"flavor": {
|
||||
@@ -106,7 +106,7 @@ class FlavorManageTest(test.NoDBTestCase):
|
||||
"id": unicode('1234'),
|
||||
"swap": 512,
|
||||
"rxtx_factor": 1,
|
||||
"flavor-access:is_public": True,
|
||||
"os-flavor-access:is_public": True,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,7 +120,7 @@ class FlavorManageTest(test.NoDBTestCase):
|
||||
"id": unicode('1234'),
|
||||
"swap": 512,
|
||||
"rxtx_factor": 1,
|
||||
"flavor-access:is_public": True,
|
||||
"os-flavor-access:is_public": True,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -232,7 +232,7 @@ class FlavorManageTest(test.NoDBTestCase):
|
||||
"id": unicode('1234'),
|
||||
"swap": 512,
|
||||
"rxtx_factor": 1,
|
||||
"flavor-access:is_public": True,
|
||||
"os-flavor-access:is_public": True,
|
||||
}
|
||||
}
|
||||
url = '/v3/flavors'
|
||||
@@ -308,7 +308,8 @@ class FlavorManageTest(test.NoDBTestCase):
|
||||
|
||||
def test_create_with_non_boolean_is_public(self):
|
||||
is_public = 1234
|
||||
self.base_request_dict['flavor']['flavor-access:is_public'] = is_public
|
||||
self.base_request_dict['flavor']['os-flavor-access:is_public'] =\
|
||||
is_public
|
||||
self._test_create_bad_request(self.base_request_dict)
|
||||
|
||||
|
||||
@@ -339,7 +340,7 @@ class PrivateFlavorManageTest(test.TestCase):
|
||||
"id": unicode('1234'),
|
||||
"swap": 512,
|
||||
"rxtx_factor": 1,
|
||||
"flavor-access:is_public": False
|
||||
"os-flavor-access:is_public": False
|
||||
}
|
||||
}
|
||||
|
||||
@@ -371,7 +372,7 @@ class PrivateFlavorManageTest(test.TestCase):
|
||||
flavor_access_body["flavor_access"])
|
||||
|
||||
def test_create_public_flavor_should_not_create_flavor_access(self):
|
||||
self.base_request_dict['flavor']['flavor-access:is_public'] = True
|
||||
self.base_request_dict['flavor']['os-flavor-access:is_public'] = True
|
||||
expected = {
|
||||
"flavor": {
|
||||
"name": "test",
|
||||
|
@@ -184,10 +184,10 @@ policy_data = """
|
||||
"compute_extension:flavor_access": "",
|
||||
"compute_extension:flavor_access:addTenantAccess": "rule:admin_api",
|
||||
"compute_extension:flavor_access:removeTenantAccess": "rule:admin_api",
|
||||
"compute_extension:v3:flavor-access": "",
|
||||
"compute_extension:v3:flavor-access:remove_tenant_access":
|
||||
"compute_extension:v3:os-flavor-access": "",
|
||||
"compute_extension:v3:os-flavor-access:remove_tenant_access":
|
||||
"rule:admin_api",
|
||||
"compute_extension:v3:flavor-access:add_tenant_access":
|
||||
"compute_extension:v3:os-flavor-access:add_tenant_access":
|
||||
"rule:admin_api",
|
||||
"compute_extension:flavor_disabled": "",
|
||||
"compute_extension:v3:os-flavor-disabled": "",
|
||||
|
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"add_tenant_access": {
|
||||
"tenant_id": "%(tenant_id)s"
|
||||
"addTenantAccess": {
|
||||
"tenant": "%(tenant_id)s"
|
||||
}
|
||||
}
|
||||
|
@@ -5,6 +5,6 @@
|
||||
"vcpus": 2,
|
||||
"disk": 10,
|
||||
"id": "%(flavor_id)s",
|
||||
"flavor-access:is_public": false
|
||||
"os-flavor-access:is_public": false
|
||||
}
|
||||
}
|
||||
|
@@ -13,7 +13,7 @@
|
||||
}
|
||||
],
|
||||
"name": "%(flavor_name)s",
|
||||
"flavor-access:is_public": false,
|
||||
"os-flavor-access:is_public": false,
|
||||
"ram": 1024,
|
||||
"vcpus": 2,
|
||||
"disabled": false,
|
||||
|
@@ -16,7 +16,7 @@
|
||||
}
|
||||
],
|
||||
"name": "m1.tiny",
|
||||
"flavor-access:is_public": true,
|
||||
"os-flavor-access:is_public": true,
|
||||
"ram": 512,
|
||||
"swap": 0,
|
||||
"vcpus": 1
|
||||
@@ -37,7 +37,7 @@
|
||||
}
|
||||
],
|
||||
"name": "m1.small",
|
||||
"flavor-access:is_public": true,
|
||||
"os-flavor-access:is_public": true,
|
||||
"ram": 2048,
|
||||
"swap": 0,
|
||||
"vcpus": 1
|
||||
@@ -58,7 +58,7 @@
|
||||
}
|
||||
],
|
||||
"name": "m1.medium",
|
||||
"flavor-access:is_public": true,
|
||||
"os-flavor-access:is_public": true,
|
||||
"ram": 4096,
|
||||
"swap": 0,
|
||||
"vcpus": 2
|
||||
@@ -79,7 +79,7 @@
|
||||
}
|
||||
],
|
||||
"name": "m1.large",
|
||||
"flavor-access:is_public": true,
|
||||
"os-flavor-access:is_public": true,
|
||||
"ram": 8192,
|
||||
"swap": 0,
|
||||
"vcpus": 4
|
||||
@@ -100,7 +100,7 @@
|
||||
}
|
||||
],
|
||||
"name": "m1.xlarge",
|
||||
"flavor-access:is_public": true,
|
||||
"os-flavor-access:is_public": true,
|
||||
"ram": 16384,
|
||||
"swap": 0,
|
||||
"vcpus": 8
|
||||
|
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"remove_tenant_access": {
|
||||
"tenant_id": "%(tenant_id)s"
|
||||
"removeTenantAccess": {
|
||||
"tenant": "%(tenant_id)s"
|
||||
}
|
||||
}
|
||||
|
@@ -13,7 +13,7 @@
|
||||
}
|
||||
],
|
||||
"name": "m1.tiny",
|
||||
"flavor-access:is_public": true,
|
||||
"os-flavor-access:is_public": true,
|
||||
"ram": 512,
|
||||
"vcpus": 1,
|
||||
"disabled": false,
|
||||
|
@@ -13,7 +13,7 @@
|
||||
}
|
||||
],
|
||||
"name": "%(flavor_name)s",
|
||||
"flavor-access:is_public": true,
|
||||
"os-flavor-access:is_public": true,
|
||||
"ram": 1024,
|
||||
"vcpus": 2,
|
||||
"disabled": false,
|
||||
|
@@ -13,7 +13,7 @@
|
||||
}
|
||||
],
|
||||
"name": "m1.tiny",
|
||||
"flavor-access:is_public": true,
|
||||
"os-flavor-access:is_public": true,
|
||||
"ram": 512,
|
||||
"vcpus": 1,
|
||||
"disabled": false,
|
||||
|
@@ -16,7 +16,7 @@
|
||||
}
|
||||
],
|
||||
"name": "m1.tiny",
|
||||
"flavor-access:is_public": true,
|
||||
"os-flavor-access:is_public": true,
|
||||
"ram": 512,
|
||||
"swap": 0,
|
||||
"vcpus": 1
|
||||
@@ -37,7 +37,7 @@
|
||||
}
|
||||
],
|
||||
"name": "m1.small",
|
||||
"flavor-access:is_public": true,
|
||||
"os-flavor-access:is_public": true,
|
||||
"ram": 2048,
|
||||
"swap": 0,
|
||||
"vcpus": 1
|
||||
@@ -58,7 +58,7 @@
|
||||
}
|
||||
],
|
||||
"name": "m1.medium",
|
||||
"flavor-access:is_public": true,
|
||||
"os-flavor-access:is_public": true,
|
||||
"ram": 4096,
|
||||
"swap": 0,
|
||||
"vcpus": 2
|
||||
@@ -79,7 +79,7 @@
|
||||
}
|
||||
],
|
||||
"name": "m1.large",
|
||||
"flavor-access:is_public": true,
|
||||
"os-flavor-access:is_public": true,
|
||||
"ram": 8192,
|
||||
"swap": 0,
|
||||
"vcpus": 4
|
||||
@@ -100,7 +100,7 @@
|
||||
}
|
||||
],
|
||||
"name": "m1.xlarge",
|
||||
"flavor-access:is_public": true,
|
||||
"os-flavor-access:is_public": true,
|
||||
"ram": 16384,
|
||||
"swap": 0,
|
||||
"vcpus": 8
|
||||
|
@@ -15,7 +15,7 @@
|
||||
}
|
||||
],
|
||||
"name": "m1.tiny",
|
||||
"flavor-access:is_public": true,
|
||||
"os-flavor-access:is_public": true,
|
||||
"ram": 512,
|
||||
"rxtx_factor": 1.0,
|
||||
"swap": 0,
|
||||
|
@@ -16,7 +16,7 @@
|
||||
}
|
||||
],
|
||||
"name": "m1.tiny",
|
||||
"flavor-access:is_public": true,
|
||||
"os-flavor-access:is_public": true,
|
||||
"ram": 512,
|
||||
"rxtx_factor": 1.0,
|
||||
"swap": 0,
|
||||
@@ -38,7 +38,7 @@
|
||||
}
|
||||
],
|
||||
"name": "m1.small",
|
||||
"flavor-access:is_public": true,
|
||||
"os-flavor-access:is_public": true,
|
||||
"ram": 2048,
|
||||
"rxtx_factor": 1.0,
|
||||
"swap": 0,
|
||||
@@ -60,7 +60,7 @@
|
||||
}
|
||||
],
|
||||
"name": "m1.medium",
|
||||
"flavor-access:is_public": true,
|
||||
"os-flavor-access:is_public": true,
|
||||
"ram": 4096,
|
||||
"rxtx_factor": 1.0,
|
||||
"swap": 0,
|
||||
@@ -82,7 +82,7 @@
|
||||
}
|
||||
],
|
||||
"name": "m1.large",
|
||||
"flavor-access:is_public": true,
|
||||
"os-flavor-access:is_public": true,
|
||||
"ram": 8192,
|
||||
"rxtx_factor": 1.0,
|
||||
"swap": 0,
|
||||
@@ -104,7 +104,7 @@
|
||||
}
|
||||
],
|
||||
"name": "m1.xlarge",
|
||||
"flavor-access:is_public": true,
|
||||
"os-flavor-access:is_public": true,
|
||||
"ram": 16384,
|
||||
"rxtx_factor": 1.0,
|
||||
"swap": 0,
|
||||
|
@@ -13,7 +13,7 @@
|
||||
}
|
||||
],
|
||||
"name": "%(flavor_name)s",
|
||||
"flavor-access:is_public": true,
|
||||
"os-flavor-access:is_public": true,
|
||||
"ram": 1024,
|
||||
"rxtx_factor": 2.0,
|
||||
"vcpus": 2,
|
||||
|
@@ -52,7 +52,7 @@ class FlavorAccessSampleJsonTests(api_sample_base.ApiSampleTestBaseV3):
|
||||
self._create_flavor()
|
||||
self._add_tenant()
|
||||
flavor_id = 10
|
||||
response = self._do_get('flavors/%s/flavor-access' % flavor_id)
|
||||
response = self._do_get('flavors/%s/os-flavor-access' % flavor_id)
|
||||
subs = {
|
||||
'flavor_id': flavor_id,
|
||||
'tenant_id': 'fake_tenant',
|
||||
|
Reference in New Issue
Block a user