diff --git a/neutron/quota.py b/neutron/quota.py index 908b256f2c..411107864d 100644 --- a/neutron/quota.py +++ b/neutron/quota.py @@ -16,6 +16,8 @@ """Quotas for instances, volumes, and floating ips.""" +import sys + from oslo.config import cfg import webob @@ -25,6 +27,10 @@ from neutron.openstack.common import importutils from neutron.openstack.common import log as logging LOG = logging.getLogger(__name__) +QUOTA_DB_MODULE = 'neutron.db.quota_db' +QUOTA_DB_DRIVER = 'neutron.db.quota_db.DbQuotaDriver' +QUOTA_CONF_DRIVER = 'neutron.quota.ConfDriver' + quota_opts = [ cfg.ListOpt('quota_items', default=['network', 'subnet', 'port'], @@ -47,7 +53,7 @@ quota_opts = [ help=_('Number of ports allowed per tenant, minus for ' 'unlimited')), cfg.StrOpt('quota_driver', - default='neutron.db.quota_db.DbQuotaDriver', + default=QUOTA_DB_DRIVER, help=_('Default driver to use for quota checks')), ] # Register the configuration options @@ -217,9 +223,16 @@ class QuotaEngine(object): if self._driver is None: _driver_class = (self._driver_class or cfg.CONF.QUOTAS.quota_driver) + if (_driver_class == QUOTA_DB_DRIVER and + QUOTA_DB_MODULE not in sys.modules): + # If quotas table is not loaded, force config quota driver. + _driver_class = QUOTA_CONF_DRIVER + LOG.info(_("ConfDriver is used as quota_driver because the " + "loaded plugin does not support 'quotas' table.")) if isinstance(_driver_class, basestring): _driver_class = importutils.import_object(_driver_class) self._driver = _driver_class + LOG.info(_('Loaded quota_driver: %s.'), _driver_class) return self._driver def __contains__(self, resource): diff --git a/neutron/tests/unit/test_quota_ext.py b/neutron/tests/unit/test_quota_ext.py index 3f572adf6d..085bd23662 100644 --- a/neutron/tests/unit/test_quota_ext.py +++ b/neutron/tests/unit/test_quota_ext.py @@ -15,6 +15,8 @@ # License for the specific language governing permissions and limitations # under the License. +import sys + import mock from oslo.config import cfg import testtools @@ -408,3 +410,32 @@ class TestDbQuotaDriver(base.BaseTestCase): get_tenant_quotas.assert_called_once_with(ctx, default_quotas, target_tenant) + + +class TestQuotaDriverLoad(base.BaseTestCase): + def setUp(self): + super(TestQuotaDriverLoad, self).setUp() + # Make sure QuotaEngine is reinitialized in each test. + quota.QUOTAS._driver = None + + def _test_quota_driver(self, cfg_driver, loaded_driver, + with_quota_db_module=True): + cfg.CONF.set_override('quota_driver', cfg_driver, group='QUOTAS') + with mock.patch.dict(sys.modules, {}): + if (not with_quota_db_module and + 'neutron.db.quota_db' in sys.modules): + del sys.modules['neutron.db.quota_db'] + driver = quota.QUOTAS.get_driver() + self.assertEqual(loaded_driver, driver.__class__.__name__) + + def test_quota_db_driver_with_quotas_table(self): + self._test_quota_driver('neutron.db.quota_db.DbQuotaDriver', + 'DbQuotaDriver', True) + + def test_quota_db_driver_fallback_conf_driver(self): + self._test_quota_driver('neutron.db.quota_db.DbQuotaDriver', + 'ConfDriver', False) + + def test_quota_conf_driver(self): + self._test_quota_driver('neutron.quota.ConfDriver', + 'ConfDriver', True)