Merge "[quota] Enable ``DbQuotaDriverNull`` as a production driver"

This commit is contained in:
Zuul 2022-04-12 14:55:22 +00:00 committed by Gerrit Code Review
commit a5bcc34bf4
14 changed files with 167 additions and 76 deletions

View File

@ -19,8 +19,13 @@ from oslo_config import cfg
from neutron._i18n import _ from neutron._i18n import _
QUOTA_DB_MODULE = 'neutron.db.quota.driver_nolock' QUOTA_DB_DIRECTORY = 'neutron.db.quota.'
QUOTA_DB_DRIVER = QUOTA_DB_MODULE + '.DbQuotaNoLockDriver' QUOTA_DB_DRIVER_LEGACY = QUOTA_DB_DIRECTORY + 'driver.DbQuotaDriver'
QUOTA_DB_DRIVER_NO_LOCK = (QUOTA_DB_DIRECTORY +
'driver_nolock.DbQuotaNoLockDriver')
QUOTA_DB_DRIVER_NULL = QUOTA_DB_DIRECTORY + 'driver_null.DbQuotaDriverNull'
QUOTA_DB_DRIVER = QUOTA_DB_DRIVER_NO_LOCK
QUOTAS_CFG_GROUP = 'QUOTAS' QUOTAS_CFG_GROUP = 'QUOTAS'
DEFAULT_QUOTA = -1 DEFAULT_QUOTA = -1

View File

@ -16,7 +16,6 @@ import collections
import datetime import datetime
from neutron_lib.db import api as db_api from neutron_lib.db import api as db_api
from neutron_lib.db import quota_api as nlib_quota_api
from oslo_db import exception as db_exc from oslo_db import exception as db_exc
from neutron.common import utils from neutron.common import utils
@ -250,58 +249,3 @@ def remove_expired_reservations(context, project_id=None, timeout=None):
expiring_time -= datetime.timedelta(seconds=timeout) expiring_time -= datetime.timedelta(seconds=timeout)
return quota_obj.Reservation.delete_expired(context, expiring_time, return quota_obj.Reservation.delete_expired(context, expiring_time,
project_id) project_id)
class NullQuotaDriver(nlib_quota_api.QuotaDriverAPI):
@staticmethod
def get_default_quotas(context, resources, project_id):
pass
@staticmethod
def get_project_quotas(context, resources, project_id):
pass
@staticmethod
def get_detailed_project_quotas(context, resources, project_id):
pass
@staticmethod
def delete_project_quota(context, project_id):
pass
@staticmethod
def get_all_quotas(context, resources):
pass
@staticmethod
def update_quota_limit(context, project_id, resource, limit):
pass
@staticmethod
def make_reservation(context, project_id, resources, deltas, plugin):
pass
@staticmethod
def commit_reservation(context, reservation_id):
pass
@staticmethod
def cancel_reservation(context, reservation_id):
pass
@staticmethod
def limit_check(context, project_id, resources, values):
pass
@staticmethod
def get_resource_usage(context, project_id, resources, resource_name):
pass
@staticmethod
def quota_limit_check(context, project_id, resources, deltas):
pass
@staticmethod
def get_workers():
return []

View File

@ -0,0 +1,71 @@
# Copyright (c) 2022 Red Hat, Inc.
# 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.
from neutron_lib.db import quota_api as nlib_quota_api
class DbQuotaDriverNull(nlib_quota_api.QuotaDriverAPI):
@staticmethod
def get_default_quotas(context, resources, project_id):
return {}
@staticmethod
def get_project_quotas(context, resources, project_id):
return {}
@staticmethod
def get_detailed_project_quotas(context, resources, project_id):
return {}
@staticmethod
def delete_project_quota(context, project_id):
pass
@staticmethod
def get_all_quotas(context, resources):
return []
@staticmethod
def update_quota_limit(context, project_id, resource, limit):
pass
@staticmethod
def make_reservation(context, project_id, resources, deltas, plugin):
pass
@staticmethod
def commit_reservation(context, reservation_id):
pass
@staticmethod
def cancel_reservation(context, reservation_id):
pass
@staticmethod
def limit_check(context, project_id, resources, values):
pass
@staticmethod
def get_resource_usage(context, project_id, resources, resource_name):
return 0
@staticmethod
def quota_limit_check(context, project_id, resources, deltas):
pass
@staticmethod
def get_workers():
return []

View File

@ -21,8 +21,6 @@ from neutron.conf import quota
from neutron.quota import resource_registry from neutron.quota import resource_registry
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
QUOTA_DB_MODULE = quota.QUOTA_DB_MODULE
QUOTA_DB_DRIVER = quota.QUOTA_DB_DRIVER
# Register the configuration options # Register the configuration options

View File

@ -94,6 +94,9 @@ class NeutronConfigFixture(ConfigFixture):
'report_interval': str(env_desc.agent_down_time // 2), 'report_interval': str(env_desc.agent_down_time // 2),
'log_agent_heartbeats': 'True', 'log_agent_heartbeats': 'True',
}, },
'quotas': {
'quota_driver': env_desc.quota_driver
},
}) })
if use_local_apipaste: if use_local_apipaste:

View File

@ -19,6 +19,7 @@ from oslo_config import cfg
from neutron.agent.linux import ip_lib from neutron.agent.linux import ip_lib
from neutron.common import utils as common_utils from neutron.common import utils as common_utils
from neutron.conf import quota as quota_conf
from neutron.plugins.ml2.drivers.linuxbridge.agent import \ from neutron.plugins.ml2.drivers.linuxbridge.agent import \
linuxbridge_neutron_agent as lb_agent linuxbridge_neutron_agent as lb_agent
from neutron.tests.common.exclusive_resources import ip_address from neutron.tests.common.exclusive_resources import ip_address
@ -42,7 +43,8 @@ class EnvironmentDescription(object):
has_placement=False, placement_port=None, has_placement=False, placement_port=None,
dhcp_scheduler_class=None, ml2_extension_drivers=None, dhcp_scheduler_class=None, ml2_extension_drivers=None,
api_workers=1, api_workers=1,
enable_traditional_dhcp=True, local_ip_ext=False): enable_traditional_dhcp=True, local_ip_ext=False,
quota_driver=quota_conf.QUOTA_DB_DRIVER):
self.network_type = network_type self.network_type = network_type
self.l2_pop = l2_pop self.l2_pop = l2_pop
self.qos = qos self.qos = qos
@ -69,6 +71,7 @@ class EnvironmentDescription(object):
self.local_ip_ext = local_ip_ext self.local_ip_ext = local_ip_ext
if self.local_ip_ext: if self.local_ip_ext:
self.service_plugins += ',local_ip' self.service_plugins += ',local_ip'
self.quota_driver = quota_driver
@property @property
def tunneling_enabled(self): def tunneling_enabled(self):

View File

@ -0,0 +1,51 @@
# Copyright (c) 2022 Red Hat, Inc.
# 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.
from oslo_utils import uuidutils
from neutron.conf import quota as quota_conf
from neutron.tests.fullstack import base
from neutron.tests.fullstack.resources import environment
from neutron.tests.unit import testlib_api
load_tests = testlib_api.module_load_tests
class TestQuota(base.BaseFullStackTestCase):
scenarios = [
('DbQuotaDriver',
{'quota_driver': quota_conf.QUOTA_DB_DRIVER_LEGACY}),
('DbQuotaNoLockDriver',
{'quota_driver': quota_conf.QUOTA_DB_DRIVER_NO_LOCK}),
('DbQuotaDriverNull',
{'quota_driver': quota_conf.QUOTA_DB_DRIVER_NULL}),
]
def setUp(self, *args):
host_descriptions = [environment.HostDescription()]
env = environment.Environment(environment.EnvironmentDescription(
quota_driver=self.quota_driver), host_descriptions)
super().setUp(env)
self.tenant_id = uuidutils.generate_uuid()
def test_create_network_and_port(self):
network = self.safe_client.create_network(self.tenant_id)
self.safe_client.create_subnet(self.tenant_id, network['id'],
'20.0.0.0/24')
port = self.safe_client.create_port(self.tenant_id, network['id'])
port_id = port['id']
port = self.safe_client.client.list_ports(id=port_id)['ports'][0]
self.assertEqual(port_id, port['id'])

View File

@ -1033,7 +1033,7 @@ class ExtensionExtendedAttributeTestCase(base.BaseTestCase):
quota.QUOTAS._driver = None quota.QUOTAS._driver = None
cfg.CONF.set_override('quota_driver', cfg.CONF.set_override('quota_driver',
'neutron.db.quota.api.NullQuotaDriver', 'neutron.db.quota.driver_null.DbQuotaDriverNull',
group='QUOTAS') group='QUOTAS')
def _do_request(self, method, path, data=None, params=None, action=None): def _do_request(self, method, path, data=None, params=None, action=None):

View File

@ -40,6 +40,7 @@ from neutron.api import api_common
from neutron.api import extensions from neutron.api import extensions
from neutron.api.v2 import base as v2_base from neutron.api.v2 import base as v2_base
from neutron.api.v2 import router from neutron.api.v2 import router
from neutron.conf import quota as quota_conf
from neutron import policy from neutron import policy
from neutron import quota from neutron import quota
from neutron.tests import base from neutron.tests import base
@ -49,7 +50,7 @@ from neutron.tests.unit import testlib_api
EXTDIR = os.path.join(base.ROOTDIR, 'unit/extensions') EXTDIR = os.path.join(base.ROOTDIR, 'unit/extensions')
NULL_QUOTA_DRIVER = 'neutron.db.quota.api.NullQuotaDriver' NULL_QUOTA_DRIVER = 'neutron.db.quota.driver_null.DbQuotaDriverNull'
_uuid = uuidutils.generate_uuid _uuid = uuidutils.generate_uuid
@ -98,7 +99,7 @@ class APIv2TestBase(base.BaseTestCase):
self.api = webtest.TestApp(api) self.api = webtest.TestApp(api)
quota.QUOTAS._driver = None quota.QUOTAS._driver = None
cfg.CONF.set_override('quota_driver', quota.QUOTA_DB_DRIVER, cfg.CONF.set_override('quota_driver', quota_conf.QUOTA_DB_DRIVER,
group='QUOTAS') group='QUOTAS')
# APIRouter initialization resets policy module, re-initializing it # APIRouter initialization resets policy module, re-initializing it

View File

@ -25,6 +25,7 @@ from webob import exc
import webtest import webtest
from neutron.api import extensions from neutron.api import extensions
from neutron.conf import quota as quota_conf
from neutron import manager from neutron import manager
from neutron import quota from neutron import quota
from neutron.tests.unit.api import test_extensions from neutron.tests.unit.api import test_extensions
@ -83,7 +84,7 @@ class ExtensionTestCase(testlib_api.WebTestCase):
setattr(instance, native_sorting_attr_name, True) setattr(instance, native_sorting_attr_name, True)
if use_quota: if use_quota:
quota.QUOTAS._driver = None quota.QUOTAS._driver = None
cfg.CONF.set_override('quota_driver', quota.QUOTA_DB_DRIVER, cfg.CONF.set_override('quota_driver', quota_conf.QUOTA_DB_DRIVER,
group='QUOTAS') group='QUOTAS')
setattr(instance, 'path_prefix', resource_prefix) setattr(instance, 'path_prefix', resource_prefix)

View File

@ -27,6 +27,7 @@ import webtest
from neutron.api import extensions from neutron.api import extensions
from neutron.api.v2 import router from neutron.api.v2 import router
from neutron.conf import quota as quota_conf
from neutron.extensions import providernet as pnet from neutron.extensions import providernet as pnet
from neutron import quota from neutron import quota
from neutron.tests import tools from neutron.tests import tools
@ -80,7 +81,7 @@ class ProvidernetExtensionTestCase(testlib_api.WebTestCase):
self.api = webtest.TestApp(router.APIRouter()) self.api = webtest.TestApp(router.APIRouter())
quota.QUOTAS._driver = None quota.QUOTAS._driver = None
cfg.CONF.set_override('quota_driver', quota.QUOTA_DB_DRIVER, cfg.CONF.set_override('quota_driver', quota_conf.QUOTA_DB_DRIVER,
group='QUOTAS') group='QUOTAS')
def _prepare_net_data(self): def _prepare_net_data(self):

View File

@ -31,6 +31,7 @@ from neutron.common import config
from neutron.conf import quota as qconf from neutron.conf import quota as qconf
from neutron.db.quota import driver from neutron.db.quota import driver
from neutron.db.quota import driver_nolock from neutron.db.quota import driver_nolock
from neutron.db.quota import driver_null
from neutron import quota from neutron import quota
from neutron.quota import resource_registry from neutron.quota import resource_registry
from neutron.tests import base from neutron.tests import base
@ -88,7 +89,7 @@ class QuotaExtensionDbTestCase(QuotaExtensionTestCase):
def setUp(self): def setUp(self):
cfg.CONF.set_override( cfg.CONF.set_override(
'quota_driver', quota.QUOTA_DB_DRIVER, group='QUOTAS') 'quota_driver', qconf.QUOTA_DB_DRIVER, group='QUOTAS')
super(QuotaExtensionDbTestCase, self).setUp() super(QuotaExtensionDbTestCase, self).setUp()
def test_quotas_loaded_right(self): def test_quotas_loaded_right(self):
@ -443,7 +444,7 @@ class QuotaExtensionCfgTestCase(QuotaExtensionTestCase):
def setUp(self): def setUp(self):
cfg.CONF.set_override( cfg.CONF.set_override(
'quota_driver', quota.QUOTA_DB_DRIVER, group='QUOTAS') 'quota_driver', qconf.QUOTA_DB_DRIVER, group='QUOTAS')
super(QuotaExtensionCfgTestCase, self).setUp() super(QuotaExtensionCfgTestCase, self).setUp()
def test_quotas_default_values(self): def test_quotas_default_values(self):
@ -524,20 +525,24 @@ class TestDbQuotaDriver(base.BaseTestCase):
class TestQuotaDriverLoad(base.BaseTestCase): class TestQuotaDriverLoad(base.BaseTestCase):
def _test_quota_driver(self, cfg_driver, loaded_driver, MODULE_CLASS = [
with_quota_db_module=True): (qconf.QUOTA_DB_DRIVER_LEGACY, driver.DbQuotaDriver),
(qconf.QUOTA_DB_DRIVER_NO_LOCK, driver_nolock.DbQuotaNoLockDriver),
(qconf.QUOTA_DB_DRIVER_NULL, driver_null.DbQuotaDriverNull),
]
def _test_quota_driver(self, module, cfg_driver, loaded_driver):
quota.QUOTAS._driver = None quota.QUOTAS._driver = None
cfg.CONF.set_override('quota_driver', cfg_driver, group='QUOTAS') cfg.CONF.set_override('quota_driver', cfg_driver, group='QUOTAS')
with mock.patch.dict(sys.modules, {}): with mock.patch.dict(sys.modules, {}):
if (not with_quota_db_module and if module in sys.modules:
quota.QUOTA_DB_MODULE in sys.modules):
del sys.modules[quota.QUOTA_DB_MODULE] del sys.modules[quota.QUOTA_DB_MODULE]
driver = quota.QUOTAS.get_driver() driver = quota.QUOTAS.get_driver()
self.assertEqual(loaded_driver, driver.__class__.__name__) self.assertEqual(loaded_driver, driver.__class__.__name__)
def test_quota_driver_load(self): def test_quota_driver_load(self):
for klass in (driver.DbQuotaDriver, for module, klass in self.MODULE_CLASS:
driver_nolock.DbQuotaNoLockDriver):
self._test_quota_driver( self._test_quota_driver(
module,
'.'.join([klass.__module__, klass.__name__]), '.'.join([klass.__module__, klass.__name__]),
klass.__name__, True) klass.__name__)

View File

@ -17,6 +17,7 @@ from neutron_lib.db import api as db_api
from oslo_config import cfg from oslo_config import cfg
from webob import exc as web_exc from webob import exc as web_exc
from neutron.conf import quota as quota_conf
from neutron.db import db_base_plugin_v2 from neutron.db import db_base_plugin_v2
from neutron.db import vlantransparent_db as vlt_db from neutron.db import vlantransparent_db as vlt_db
from neutron.extensions import vlantransparent as vlt from neutron.extensions import vlantransparent as vlt
@ -72,7 +73,7 @@ class VlanTransparentExtensionTestCase(test_db_base_plugin_v2.TestNetworksV2):
ext_mgr=ext_mgr) ext_mgr=ext_mgr)
quota.QUOTAS._driver = None quota.QUOTAS._driver = None
cfg.CONF.set_override('quota_driver', quota.QUOTA_DB_DRIVER, cfg.CONF.set_override('quota_driver', quota_conf.QUOTA_DB_DRIVER,
group='QUOTAS') group='QUOTAS')
def test_network_create_with_vlan_transparent_attr(self): def test_network_create_with_vlan_transparent_attr(self):

View File

@ -0,0 +1,7 @@
---
features:
- |
Enabled ``DbQuotaDriverNull`` as production ready database quota driver.
This driver does not have access to the database and will return empty
values to the request queries. This driver can be used to override the
Neutron quota engine.