b5990a7bd7
The cfg API is now available via the oslo-config library, so switch to it and remove the copied-and-pasted version. Add the 2013.1b3 tarball to tools/pip-requires - this will be changed to 'oslo-config>=2013.1' when oslo-config is published to pypi. This will happen in time for grizzly final. Remove the 'deps = pep8' from tox.ini as it means all the other deps get installed with easy_install which can't install oslo-config from the URL. Retain dummy cfg.py file until keystoneclient middleware has been updated (I18c450174277c8e2d15ed93879da6cd92074c27a). Change-Id: I4815aeb8a9341a31a250e920157f15ee15cfc5bc
200 lines
8.3 KiB
Python
200 lines
8.3 KiB
Python
import unittest2 as unittest
|
|
import webtest
|
|
|
|
import mock
|
|
from oslo.config import cfg
|
|
|
|
from quantum.api import extensions
|
|
from quantum.api.v2 import attributes
|
|
from quantum.common import config
|
|
from quantum.common import exceptions
|
|
from quantum import context
|
|
from quantum.db import api as db
|
|
from quantum import manager
|
|
from quantum.plugins.linuxbridge.db import l2network_db_v2
|
|
from quantum import quota
|
|
from quantum.tests.unit import test_api_v2
|
|
from quantum.tests.unit import test_extensions
|
|
from quantum.tests.unit import testlib_api
|
|
|
|
TARGET_PLUGIN = ('quantum.plugins.linuxbridge.lb_quantum_plugin'
|
|
'.LinuxBridgePluginV2')
|
|
|
|
_get_path = test_api_v2._get_path
|
|
|
|
|
|
class QuotaExtensionTestCase(testlib_api.WebTestCase):
|
|
fmt = 'json'
|
|
|
|
def setUp(self):
|
|
db._ENGINE = None
|
|
db._MAKER = None
|
|
# Ensure 'stale' patched copies of the plugin are never returned
|
|
manager.QuantumManager._instance = None
|
|
|
|
# Ensure existing ExtensionManager is not used
|
|
extensions.PluginAwareExtensionManager._instance = None
|
|
|
|
# Save the global RESOURCE_ATTRIBUTE_MAP
|
|
self.saved_attr_map = {}
|
|
for resource, attrs in attributes.RESOURCE_ATTRIBUTE_MAP.iteritems():
|
|
self.saved_attr_map[resource] = attrs.copy()
|
|
|
|
# Create the default configurations
|
|
args = ['--config-file', test_extensions.etcdir('quantum.conf.test')]
|
|
config.parse(args=args)
|
|
|
|
# Update the plugin and extensions path
|
|
cfg.CONF.set_override('core_plugin', TARGET_PLUGIN)
|
|
cfg.CONF.set_override(
|
|
'quota_driver',
|
|
'quantum.db.quota_db.DbQuotaDriver',
|
|
group='QUOTAS')
|
|
cfg.CONF.set_override(
|
|
'quota_items',
|
|
['network', 'subnet', 'port', 'extra1'],
|
|
group='QUOTAS')
|
|
quota.QUOTAS = quota.QuotaEngine()
|
|
quota.register_resources_from_config()
|
|
self._plugin_patcher = mock.patch(TARGET_PLUGIN, autospec=True)
|
|
self.plugin = self._plugin_patcher.start()
|
|
self.plugin.return_value.supported_extension_aliases = ['quotas']
|
|
# QUOTAS will regester the items in conf when starting
|
|
# extra1 here is added later, so have to do it manually
|
|
quota.QUOTAS.register_resource_by_name('extra1')
|
|
ext_mgr = extensions.PluginAwareExtensionManager.get_instance()
|
|
l2network_db_v2.initialize()
|
|
app = config.load_paste_app('extensions_test_app')
|
|
ext_middleware = extensions.ExtensionMiddleware(app, ext_mgr=ext_mgr)
|
|
self.api = webtest.TestApp(ext_middleware)
|
|
super(QuotaExtensionTestCase, self).setUp()
|
|
|
|
def tearDown(self):
|
|
self._plugin_patcher.stop()
|
|
self.api = None
|
|
self.plugin = None
|
|
db._ENGINE = None
|
|
db._MAKER = None
|
|
cfg.CONF.reset()
|
|
|
|
# Restore the global RESOURCE_ATTRIBUTE_MAP
|
|
attributes.RESOURCE_ATTRIBUTE_MAP = self.saved_attr_map
|
|
|
|
def test_quotas_loaded_right(self):
|
|
res = self.api.get(_get_path('quotas', fmt=self.fmt))
|
|
quota = self.deserialize(res)
|
|
self.assertEqual([], quota['quotas'])
|
|
self.assertEqual(200, res.status_int)
|
|
|
|
def test_quotas_default_values(self):
|
|
tenant_id = 'tenant_id1'
|
|
env = {'quantum.context': context.Context('', tenant_id)}
|
|
res = self.api.get(_get_path('quotas', id=tenant_id, fmt=self.fmt),
|
|
extra_environ=env)
|
|
quota = self.deserialize(res)
|
|
self.assertEqual(10, quota['quota']['network'])
|
|
self.assertEqual(10, quota['quota']['subnet'])
|
|
self.assertEqual(50, quota['quota']['port'])
|
|
self.assertEqual(-1, quota['quota']['extra1'])
|
|
|
|
def test_show_quotas_with_admin(self):
|
|
tenant_id = 'tenant_id1'
|
|
env = {'quantum.context': context.Context('', tenant_id + '2',
|
|
is_admin=True)}
|
|
res = self.api.get(_get_path('quotas', id=tenant_id, fmt=self.fmt),
|
|
extra_environ=env)
|
|
self.assertEqual(200, res.status_int)
|
|
|
|
def test_show_quotas_without_admin_forbidden(self):
|
|
tenant_id = 'tenant_id1'
|
|
env = {'quantum.context': context.Context('', tenant_id + '2',
|
|
is_admin=False)}
|
|
res = self.api.get(_get_path('quotas', id=tenant_id, fmt=self.fmt),
|
|
extra_environ=env, expect_errors=True)
|
|
self.assertEqual(403, res.status_int)
|
|
|
|
def test_update_quotas_without_admin_forbidden(self):
|
|
tenant_id = 'tenant_id1'
|
|
env = {'quantum.context': context.Context('', tenant_id,
|
|
is_admin=False)}
|
|
quotas = {'quota': {'network': 100}}
|
|
res = self.api.put(_get_path('quotas', id=tenant_id, fmt=self.fmt),
|
|
self.serialize(quotas), extra_environ=env,
|
|
expect_errors=True)
|
|
self.assertEqual(403, res.status_int)
|
|
|
|
def test_update_quotas_with_admin(self):
|
|
tenant_id = 'tenant_id1'
|
|
env = {'quantum.context': context.Context('', tenant_id + '2',
|
|
is_admin=True)}
|
|
quotas = {'quota': {'network': 100}}
|
|
res = self.api.put(_get_path('quotas', id=tenant_id, fmt=self.fmt),
|
|
self.serialize(quotas), extra_environ=env)
|
|
self.assertEqual(200, res.status_int)
|
|
env2 = {'quantum.context': context.Context('', tenant_id)}
|
|
res = self.api.get(_get_path('quotas', id=tenant_id, fmt=self.fmt),
|
|
extra_environ=env2)
|
|
quota = self.deserialize(res)
|
|
self.assertEqual(100, quota['quota']['network'])
|
|
|
|
def test_delete_quotas_with_admin(self):
|
|
tenant_id = 'tenant_id1'
|
|
env = {'quantum.context': context.Context('', tenant_id + '2',
|
|
is_admin=True)}
|
|
res = self.api.delete(_get_path('quotas', id=tenant_id, fmt=self.fmt),
|
|
extra_environ=env)
|
|
self.assertEqual(204, res.status_int)
|
|
|
|
def test_delete_quotas_without_admin_forbidden(self):
|
|
tenant_id = 'tenant_id1'
|
|
env = {'quantum.context': context.Context('', tenant_id,
|
|
is_admin=False)}
|
|
res = self.api.delete(_get_path('quotas', id=tenant_id, fmt=self.fmt),
|
|
extra_environ=env, expect_errors=True)
|
|
self.assertEqual(403, res.status_int)
|
|
|
|
def test_quotas_loaded_bad(self):
|
|
try:
|
|
res = self.api.get(_get_path('quotas'), expect_errors=True)
|
|
self.assertEqual(404, res.status_int)
|
|
except Exception:
|
|
pass
|
|
|
|
def test_quotas_limit_check(self):
|
|
tenant_id = 'tenant_id1'
|
|
env = {'quantum.context': context.Context('', tenant_id,
|
|
is_admin=True)}
|
|
quotas = {'quota': {'network': 5}}
|
|
res = self.api.put(_get_path('quotas', id=tenant_id,
|
|
fmt=self.fmt),
|
|
self.serialize(quotas), extra_environ=env)
|
|
self.assertEqual(200, res.status_int)
|
|
quota.QUOTAS.limit_check(context.Context('', tenant_id),
|
|
tenant_id,
|
|
network=4)
|
|
|
|
def test_quotas_limit_check_with_over_quota(self):
|
|
tenant_id = 'tenant_id1'
|
|
env = {'quantum.context': context.Context('', tenant_id,
|
|
is_admin=True)}
|
|
quotas = {'quota': {'network': 5}}
|
|
res = self.api.put(_get_path('quotas', id=tenant_id,
|
|
fmt=self.fmt),
|
|
self.serialize(quotas), extra_environ=env)
|
|
self.assertEqual(200, res.status_int)
|
|
with self.assertRaises(exceptions.OverQuota):
|
|
quota.QUOTAS.limit_check(context.Context('', tenant_id),
|
|
tenant_id,
|
|
network=6)
|
|
|
|
def test_quotas_limit_check_with_invalid_quota_value(self):
|
|
tenant_id = 'tenant_id1'
|
|
with self.assertRaises(exceptions.InvalidQuotaValue):
|
|
quota.QUOTAS.limit_check(context.Context('', tenant_id),
|
|
tenant_id,
|
|
network=-1)
|
|
|
|
|
|
class QuotaExtensionTestCaseXML(QuotaExtensionTestCase):
|
|
fmt = 'xml'
|