Merge "New API call to get details of supported QoS rule type"
This commit is contained in:
commit
bea5cd24a9
@ -165,3 +165,7 @@ PORT_BINDING_STATUS_ACTIVE = 'ACTIVE'
|
||||
PORT_BINDING_STATUS_INACTIVE = 'INACTIVE'
|
||||
PORT_BINDING_STATUSES = (PORT_BINDING_STATUS_ACTIVE,
|
||||
PORT_BINDING_STATUS_INACTIVE)
|
||||
|
||||
# Possible types of values (e.g. in QoS rule types)
|
||||
VALUES_TYPE_CHOICES = "choices"
|
||||
VALUES_TYPE_RANGE = "range"
|
||||
|
@ -48,6 +48,8 @@ QOS_RULE_COMMON_FIELDS = {
|
||||
'is_visible': True},
|
||||
}
|
||||
|
||||
RULE_TYPES = "rule_types"
|
||||
|
||||
RESOURCE_ATTRIBUTE_MAP = {
|
||||
COLLECTION_NAME: {
|
||||
'id': {'allow_post': False, 'allow_put': False,
|
||||
@ -66,7 +68,7 @@ RESOURCE_ATTRIBUTE_MAP = {
|
||||
'is_visible': True},
|
||||
'rules': {'allow_post': False, 'allow_put': False, 'is_visible': True},
|
||||
},
|
||||
'rule_types': {
|
||||
RULE_TYPES: {
|
||||
'type': {'allow_post': False, 'allow_put': False,
|
||||
'is_visible': True}
|
||||
}
|
||||
@ -309,6 +311,10 @@ class QoSPluginBase(service_base.ServicePluginBase):
|
||||
def get_plugin_type(cls):
|
||||
return constants.QOS
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_rule_type(self, context, rule_type_name, fields=None):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_rule_types(self, context, filters=None, fields=None, sorts=None,
|
||||
limit=None, marker=None, page_reverse=False):
|
||||
|
74
neutron/extensions/qos_rule_type_details.py
Normal file
74
neutron/extensions/qos_rule_type_details.py
Normal file
@ -0,0 +1,74 @@
|
||||
# Copyright (c) 2017 OVH SAS
|
||||
# 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.api import extensions as api_extensions
|
||||
|
||||
from neutron.extensions import qos
|
||||
|
||||
|
||||
# The name of the extension.
|
||||
NAME = "Details of QoS rule types"
|
||||
|
||||
# The alias of the extension.
|
||||
ALIAS = "qos-rule-type-details"
|
||||
|
||||
# The description of the extension.
|
||||
DESCRIPTION = ("Expose details about QoS rule types supported by loaded "
|
||||
"backend drivers")
|
||||
|
||||
# The list of required extensions.
|
||||
REQUIRED_EXTENSIONS = [qos.ALIAS]
|
||||
|
||||
# The list of optional extensions.
|
||||
OPTIONAL_EXTENSIONS = None
|
||||
|
||||
# The resource attribute map for the extension.
|
||||
RESOURCE_ATTRIBUTE_MAP = {
|
||||
qos.RULE_TYPES: {
|
||||
'drivers': {'allow_post': False, 'allow_put': False,
|
||||
'is_visible': True}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class Qos_rule_type_details(api_extensions.ExtensionDescriptor):
|
||||
|
||||
@classmethod
|
||||
def get_name(cls):
|
||||
return NAME
|
||||
|
||||
@classmethod
|
||||
def get_alias(cls):
|
||||
return ALIAS
|
||||
|
||||
@classmethod
|
||||
def get_description(cls):
|
||||
return DESCRIPTION
|
||||
|
||||
@classmethod
|
||||
def get_updated(cls):
|
||||
return "2017-06-22T10:00:00-00:00"
|
||||
|
||||
def get_required_extensions(self):
|
||||
return REQUIRED_EXTENSIONS or []
|
||||
|
||||
def get_optional_extensions(self):
|
||||
return OPTIONAL_EXTENSIONS or []
|
||||
|
||||
def get_extended_resources(self, version):
|
||||
if version == "2.0":
|
||||
return RESOURCE_ATTRIBUTE_MAP
|
||||
else:
|
||||
return {}
|
@ -13,10 +13,12 @@
|
||||
from neutron.plugins.common import constants
|
||||
from neutron_lib.plugins import directory
|
||||
from oslo_log import log as logging
|
||||
from oslo_utils import versionutils
|
||||
from oslo_versionedobjects import base as obj_base
|
||||
from oslo_versionedobjects import fields as obj_fields
|
||||
|
||||
from neutron.objects import base
|
||||
from neutron.objects import common_types
|
||||
from neutron.services.qos import qos_consts
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
@ -35,12 +37,29 @@ class QosRuleType(base.NeutronObject):
|
||||
# Version 1.0: Initial version
|
||||
# Version 1.1: Added QosDscpMarkingRule
|
||||
# Version 1.2: Added QosMinimumBandwidthRule
|
||||
VERSION = '1.2'
|
||||
# Version 1.3: Added drivers field
|
||||
VERSION = '1.3'
|
||||
|
||||
fields = {
|
||||
'type': RuleTypeField(),
|
||||
'drivers': obj_fields.ListOfObjectsField(
|
||||
'QosRuleTypeDriver', nullable=True)
|
||||
}
|
||||
|
||||
synthetic_fields = ['drivers']
|
||||
|
||||
# we don't receive context because we don't need db access at all
|
||||
@classmethod
|
||||
def get_object(cls, rule_type_name, **kwargs):
|
||||
plugin = directory.get_plugin(alias=constants.QOS)
|
||||
drivers = plugin.supported_rule_type_details(rule_type_name)
|
||||
drivers_obj = [QosRuleTypeDriver(
|
||||
name=driver['name'],
|
||||
supported_parameters=driver['supported_parameters'])
|
||||
for driver in drivers]
|
||||
|
||||
return cls(type=rule_type_name, drivers=drivers_obj)
|
||||
|
||||
# we don't receive context because we don't need db access at all
|
||||
@classmethod
|
||||
def get_objects(cls, validate_filters=True, **kwargs):
|
||||
@ -52,3 +71,29 @@ class QosRuleType(base.NeutronObject):
|
||||
|
||||
# TODO(ihrachys): apply filters to returned result
|
||||
return [cls(type=type_) for type_ in rule_types]
|
||||
|
||||
def obj_make_compatible(self, primitive, target_version):
|
||||
_target_version = versionutils.convert_version_to_tuple(target_version)
|
||||
|
||||
if _target_version < (1, 3):
|
||||
primitive.pop('drivers', None)
|
||||
|
||||
|
||||
@obj_base.VersionedObjectRegistry.register
|
||||
class QosRuleTypeDriver(base.NeutronObject):
|
||||
# Version 1.0: Initial version
|
||||
VERSION = '1.0'
|
||||
|
||||
fields = {
|
||||
'name': obj_fields.StringField(),
|
||||
'supported_parameters': common_types.ListOfDictOfMiscValuesField()
|
||||
}
|
||||
|
||||
def to_dict(self):
|
||||
return {
|
||||
'name': self.name,
|
||||
'supported_parameters': self.supported_parameters}
|
||||
|
||||
@classmethod
|
||||
def get_objects(cls, context, **kwargs):
|
||||
raise NotImplementedError()
|
||||
|
@ -20,6 +20,7 @@ from neutron.api.rpc.callbacks import events as rpc_events
|
||||
from neutron.api.rpc.callbacks.producer import registry as rpc_registry
|
||||
from neutron.api.rpc.callbacks import resources
|
||||
from neutron.api.rpc.handlers import resources_rpc
|
||||
from neutron.common import constants
|
||||
from neutron.common import exceptions
|
||||
from neutron.objects.qos import policy as policy_object
|
||||
from neutron.services.qos import qos_consts
|
||||
@ -83,6 +84,20 @@ class QosServiceDriverManager(object):
|
||||
'driver': driver.name})
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def _parse_parameter_values(parameter_values):
|
||||
validator, possible_values = list(parameter_values.items())[0]
|
||||
if validator == 'type:range':
|
||||
parameter_values = {
|
||||
"start": possible_values[0],
|
||||
"end": possible_values[1]
|
||||
}
|
||||
parameter_type = constants.VALUES_TYPE_RANGE
|
||||
elif validator == 'type:values':
|
||||
parameter_values = possible_values
|
||||
parameter_type = constants.VALUES_TYPE_CHOICES
|
||||
return parameter_values, parameter_type
|
||||
|
||||
def call(self, method_name, *args, **kwargs):
|
||||
"""Helper method for calling a method across all extension drivers."""
|
||||
exc_list = []
|
||||
@ -158,3 +173,27 @@ class QosServiceDriverManager(object):
|
||||
LOG.debug("Supported QoS rule types "
|
||||
"(common subset for all loaded QoS drivers): %s", rule_types)
|
||||
return rule_types
|
||||
|
||||
def supported_rule_type_details(self, rule_type_name):
|
||||
if not self._drivers:
|
||||
return []
|
||||
|
||||
rule_type_drivers = []
|
||||
for driver in self._drivers:
|
||||
if rule_type_name in driver.supported_rules:
|
||||
supported_parameters = []
|
||||
rule_parameters = driver.supported_rules.get(rule_type_name)
|
||||
for name, values in rule_parameters.items():
|
||||
parameter_values, parameter_type = (
|
||||
self._parse_parameter_values(values))
|
||||
supported_parameters.append({
|
||||
"parameter_name": name,
|
||||
"parameter_values": parameter_values,
|
||||
"parameter_type": parameter_type
|
||||
})
|
||||
rule_type_drivers.append({
|
||||
"name": driver.name,
|
||||
"supported_parameters": supported_parameters
|
||||
})
|
||||
|
||||
return rule_type_drivers
|
||||
|
@ -16,6 +16,7 @@
|
||||
from neutron_lib.callbacks import events as callbacks_events
|
||||
from neutron_lib.callbacks import registry as callbacks_registry
|
||||
from neutron_lib.callbacks import resources as callbacks_resources
|
||||
from neutron_lib import exceptions as lib_exc
|
||||
|
||||
from neutron.common import exceptions as n_exc
|
||||
from neutron.db import api as db_api
|
||||
@ -40,7 +41,8 @@ class QoSPlugin(qos.QoSPluginBase):
|
||||
"""
|
||||
supported_extension_aliases = ['qos',
|
||||
'qos-bw-limit-direction',
|
||||
'qos-default']
|
||||
'qos-default',
|
||||
'qos-rule-type-details']
|
||||
|
||||
__native_pagination_support = True
|
||||
__native_sorting_support = True
|
||||
@ -264,6 +266,13 @@ class QoSPlugin(qos.QoSPluginBase):
|
||||
return policy_object.QosPolicy.get_objects(context, _pager=pager,
|
||||
**filters)
|
||||
|
||||
@db_base_plugin_common.filter_fields
|
||||
@db_base_plugin_common.convert_result_to_dict
|
||||
def get_rule_type(self, context, rule_type_name, fields=None):
|
||||
if not context.is_admin:
|
||||
raise lib_exc.NotAuthorized()
|
||||
return rule_type_object.QosRuleType.get_object(rule_type_name)
|
||||
|
||||
@db_base_plugin_common.filter_fields
|
||||
@db_base_plugin_common.convert_result_to_dict
|
||||
def get_rule_types(self, context, filters=None, fields=None,
|
||||
@ -273,6 +282,9 @@ class QoSPlugin(qos.QoSPluginBase):
|
||||
filters = {}
|
||||
return rule_type_object.QosRuleType.get_objects(**filters)
|
||||
|
||||
def supported_rule_type_details(self, rule_type_name):
|
||||
return self.driver_manager.supported_rule_type_details(rule_type_name)
|
||||
|
||||
@property
|
||||
def supported_rule_types(self):
|
||||
return self.driver_manager.supported_rule_types
|
||||
|
@ -31,6 +31,12 @@ class QosTestJSON(base.BaseAdminNetworkTest):
|
||||
|
||||
required_extensions = ['qos']
|
||||
|
||||
@staticmethod
|
||||
def _get_driver_details(rule_type_details, driver_name):
|
||||
for driver in rule_type_details['drivers']:
|
||||
if driver['name'] == driver_name:
|
||||
return driver
|
||||
|
||||
@decorators.idempotent_id('108fbdf7-3463-4e47-9871-d07f3dcf5bbb')
|
||||
def test_create_policy(self):
|
||||
policy = self.create_qos_policy(name='test-policy',
|
||||
@ -172,6 +178,31 @@ class QosTestJSON(base.BaseAdminNetworkTest):
|
||||
for rule in actual_list_rule_types:
|
||||
self.assertEqual(tuple(expected_rule_keys), tuple(rule.keys()))
|
||||
|
||||
@decorators.idempotent_id('8ececa21-ef97-4904-a152-9f04c90f484d')
|
||||
def test_show_rule_type_details_as_user(self):
|
||||
self.assertRaises(
|
||||
exceptions.Forbidden,
|
||||
self.client.show_qos_rule_type,
|
||||
qos_consts.RULE_TYPE_BANDWIDTH_LIMIT)
|
||||
|
||||
@decorators.idempotent_id('d0a2460b-7325-481f-a531-050bd96ab25e')
|
||||
def test_show_rule_type_details_as_admin(self):
|
||||
# Since returned rule types depend on loaded backend drivers this test
|
||||
# is checking only if returned keys are same as expected keys
|
||||
|
||||
# In theory, we could make the test conditional on which ml2 drivers
|
||||
# are enabled in gate, but that option doesn't seem to be
|
||||
# available through tempest.lib framework
|
||||
expected_rule_type_details_keys = ['type', 'drivers']
|
||||
|
||||
rule_type_details = self.admin_client.show_qos_rule_type(
|
||||
qos_consts.RULE_TYPE_BANDWIDTH_LIMIT).get("rule_type")
|
||||
|
||||
# Verify that only required fields present in rule details
|
||||
self.assertEqual(
|
||||
sorted(tuple(expected_rule_type_details_keys)),
|
||||
sorted(tuple(rule_type_details.keys())))
|
||||
|
||||
def _disassociate_network(self, client, network_id):
|
||||
updated_network = client.update_network(network_id,
|
||||
qos_policy_id=None)
|
||||
|
@ -728,6 +728,14 @@ class NetworkClientJSON(service_client.RestClient):
|
||||
body = jsonutils.loads(body)
|
||||
return service_client.ResponseBody(resp, body)
|
||||
|
||||
def show_qos_rule_type(self, rule_type_name):
|
||||
uri = '%s/qos/rule-types/%s' % (
|
||||
self.uri_prefix, rule_type_name)
|
||||
resp, body = self.get(uri)
|
||||
self.expected_success(200, resp.status)
|
||||
body = jsonutils.loads(body)
|
||||
return service_client.ResponseBody(resp, body)
|
||||
|
||||
def create_trunk(self, parent_port_id, subports,
|
||||
tenant_id=None, name=None, admin_state_up=None,
|
||||
description=None):
|
||||
|
@ -16,6 +16,7 @@
|
||||
import mock
|
||||
from oslo_config import cfg
|
||||
|
||||
from neutron.common import constants
|
||||
from neutron import manager
|
||||
from neutron.objects.qos import rule_type
|
||||
from neutron.services.qos import qos_consts
|
||||
@ -25,6 +26,22 @@ from neutron.tests import base as test_base
|
||||
|
||||
DB_PLUGIN_KLASS = 'neutron.db.db_base_plugin_v2.NeutronDbPluginV2'
|
||||
|
||||
DRIVER_SUPPORTED_PARAMETERS = [
|
||||
{
|
||||
'parameter_name': qos_consts.MAX_KBPS,
|
||||
'parameter_type': constants.VALUES_TYPE_RANGE,
|
||||
'parameter_values': {"start": 0, "end": constants.DB_INTEGER_MAX_VALUE}
|
||||
}, {
|
||||
'parameter_name': qos_consts.MAX_BURST,
|
||||
'parameter_type': constants.VALUES_TYPE_RANGE,
|
||||
'parameter_values': {"start": 0, "end": constants.DB_INTEGER_MAX_VALUE}
|
||||
}, {
|
||||
'parameter_name': qos_consts.DIRECTION,
|
||||
'parameter_type': constants.VALUES_TYPE_CHOICES,
|
||||
'parameter_values': constants.VALID_DIRECTIONS
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
class QosRuleTypeObjectTestCase(test_base.BaseTestCase):
|
||||
|
||||
@ -37,6 +54,26 @@ class QosRuleTypeObjectTestCase(test_base.BaseTestCase):
|
||||
cfg.CONF.set_override("service_plugins", ["qos"])
|
||||
manager.init()
|
||||
|
||||
def test_get_object(self):
|
||||
driver_details = {
|
||||
'name': "backend_driver",
|
||||
'supported_parameters': DRIVER_SUPPORTED_PARAMETERS
|
||||
}
|
||||
with mock.patch.object(
|
||||
qos_plugin.QoSPlugin, 'supported_rule_type_details',
|
||||
return_value=[driver_details]
|
||||
):
|
||||
rule_type_details = rule_type.QosRuleType.get_object(
|
||||
qos_consts.RULE_TYPE_BANDWIDTH_LIMIT)
|
||||
self.assertEqual(
|
||||
driver_details['name'], rule_type_details.drivers[0].name)
|
||||
self.assertEqual(
|
||||
driver_details['supported_parameters'],
|
||||
rule_type_details.drivers[0].supported_parameters)
|
||||
self.assertEqual(1, len(rule_type_details.drivers))
|
||||
self.assertEqual(
|
||||
qos_consts.RULE_TYPE_BANDWIDTH_LIMIT, rule_type_details.type)
|
||||
|
||||
def test_get_objects(self):
|
||||
rule_types_mock = mock.PropertyMock(
|
||||
return_value=set(qos_consts.VALID_RULE_TYPES))
|
||||
@ -64,3 +101,14 @@ class QosRuleTypeObjectTestCase(test_base.BaseTestCase):
|
||||
self.assertIn(qos_consts.RULE_TYPE_DSCP_MARKING,
|
||||
tuple(rule_type_v1_1.fields['type'].AUTO_TYPE.
|
||||
_valid_values))
|
||||
|
||||
def test_object_version_degradation_1_3_to_1_2(self):
|
||||
drivers_obj = rule_type.QosRuleTypeDriver(
|
||||
name="backend_driver", supported_parameters=[{}]
|
||||
)
|
||||
qos_rule_type = rule_type.QosRuleType(
|
||||
type=qos_consts.RULE_TYPE_BANDWIDTH_LIMIT, drivers=[drivers_obj])
|
||||
|
||||
rule_type_v1_2 = self._policy_through_version(qos_rule_type, '1.2')
|
||||
self.assertNotIn("drivers", rule_type_v1_2)
|
||||
self.assertIn("type", rule_type_v1_2)
|
||||
|
@ -66,7 +66,8 @@ object_data = {
|
||||
'QosBandwidthLimitRule': '1.3-51b662b12a8d1dfa89288d826c6d26d3',
|
||||
'QosDscpMarkingRule': '1.3-0313c6554b34fd10c753cb63d638256c',
|
||||
'QosMinimumBandwidthRule': '1.3-314c3419f4799067cc31cc319080adff',
|
||||
'QosRuleType': '1.2-e6fd08fcca152c339cbd5e9b94b1b8e7',
|
||||
'QosRuleType': '1.3-7286188edeb3a0386f9cf7979b9700fc',
|
||||
'QosRuleTypeDriver': '1.0-7d8cb9f0ef661ac03700eae97118e3db',
|
||||
'QosPolicy': '1.6-4adb0cde3102c10d8970ec9487fd7fe7',
|
||||
'QosPolicyDefault': '1.0-59e5060eedb1f06dd0935a244d27d11c',
|
||||
'QosPolicyNetworkBinding': '1.0-df53a1e0f675aab8d27a1ccfed38dc42',
|
||||
|
@ -206,6 +206,89 @@ class TestQosDriversManagerRules(TestQosDriversManagerBase):
|
||||
})
|
||||
self.assertEqual(driver_manager.supported_rule_types, set([]))
|
||||
|
||||
def test__parse_parameter_values(self):
|
||||
range_parameter = {'type:range': [0, 10]}
|
||||
values_parameter = {'type:values': [1, 10, 100, 1000]}
|
||||
expected_parsed_range_parameter = {'start': 0, 'end': 10}
|
||||
expected_parsed_values_parameter = [1, 10, 100, 1000]
|
||||
|
||||
parameter_values, parameter_type = (
|
||||
driver_mgr.QosServiceDriverManager._parse_parameter_values(
|
||||
range_parameter))
|
||||
self.assertEqual(
|
||||
expected_parsed_range_parameter, parameter_values)
|
||||
self.assertEqual(
|
||||
constants.VALUES_TYPE_RANGE, parameter_type)
|
||||
|
||||
parameter_values, parameter_type = (
|
||||
driver_mgr.QosServiceDriverManager._parse_parameter_values(
|
||||
values_parameter))
|
||||
self.assertEqual(
|
||||
expected_parsed_values_parameter, parameter_values)
|
||||
self.assertEqual(
|
||||
constants.VALUES_TYPE_CHOICES, parameter_type)
|
||||
|
||||
def test_supported_rule_type_details(self):
|
||||
driver_manager = self._create_manager_with_drivers({
|
||||
'driver-A': {
|
||||
'is_loaded': True,
|
||||
'rules': {
|
||||
qos_consts.RULE_TYPE_BANDWIDTH_LIMIT: {
|
||||
"max_kbps": {'type:range': [0, 1000]},
|
||||
"max_burst_kbps": {'type:range': [0, 1000]}
|
||||
}
|
||||
}
|
||||
},
|
||||
'driver-B': {
|
||||
'is_loaded': True,
|
||||
'rules': {
|
||||
qos_consts.RULE_TYPE_MINIMUM_BANDWIDTH: {
|
||||
"min_kbps": {'type:range': [0, 1000]},
|
||||
'direction': {
|
||||
'type:values': constants.VALID_DIRECTIONS}
|
||||
},
|
||||
qos_consts.RULE_TYPE_DSCP_MARKING: {
|
||||
"dscp_mark": {
|
||||
'type:values': constants.VALID_DSCP_MARKS}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
expected_rule_type_details = [{
|
||||
'name': 'driver-A',
|
||||
'supported_parameters': [{
|
||||
'parameter_name': 'max_kbps',
|
||||
'parameter_type': constants.VALUES_TYPE_RANGE,
|
||||
'parameter_values': {'start': 0, 'end': 1000}
|
||||
}, {
|
||||
'parameter_name': 'max_burst_kbps',
|
||||
'parameter_type': constants.VALUES_TYPE_RANGE,
|
||||
'parameter_values': {'start': 0, 'end': 1000}
|
||||
}]
|
||||
}]
|
||||
bandwidth_limit_details = driver_manager.supported_rule_type_details(
|
||||
qos_consts.RULE_TYPE_BANDWIDTH_LIMIT)
|
||||
self.assertEqual(
|
||||
len(expected_rule_type_details), len(bandwidth_limit_details))
|
||||
self.assertEqual(
|
||||
expected_rule_type_details[0]['name'],
|
||||
bandwidth_limit_details[0]['name'])
|
||||
self.assertEqual(
|
||||
len(expected_rule_type_details[0]['supported_parameters']),
|
||||
len(bandwidth_limit_details[0]['supported_parameters'])
|
||||
)
|
||||
for parameter in expected_rule_type_details[0]['supported_parameters']:
|
||||
self.assertIn(
|
||||
parameter,
|
||||
bandwidth_limit_details[0]['supported_parameters'])
|
||||
|
||||
def test_supported_rule_type_details_no_drivers_loaded(self):
|
||||
driver_manager = self._create_manager_with_drivers({})
|
||||
self.assertEqual(
|
||||
[],
|
||||
driver_manager.supported_rule_type_details(
|
||||
qos_consts.RULE_TYPE_BANDWIDTH_LIMIT))
|
||||
|
||||
|
||||
class TestQosDriversCalls(TestQosDriversManagerBase):
|
||||
"""Test QoS driver calls"""
|
||||
|
@ -12,16 +12,18 @@
|
||||
|
||||
import mock
|
||||
from neutron_lib import context
|
||||
from neutron_lib import exceptions as lib_exc
|
||||
from neutron_lib.plugins import directory
|
||||
from oslo_config import cfg
|
||||
from oslo_utils import uuidutils
|
||||
|
||||
from neutron.common import constants
|
||||
from neutron.common import exceptions as n_exc
|
||||
from neutron import manager
|
||||
from neutron.objects import base as base_object
|
||||
from neutron.objects.qos import policy as policy_object
|
||||
from neutron.objects.qos import rule as rule_object
|
||||
from neutron.plugins.common import constants
|
||||
from neutron.plugins.common import constants as plugins_constants
|
||||
from neutron.services.qos import qos_consts
|
||||
from neutron.services.qos import qos_plugin
|
||||
from neutron.tests.unit.services.qos import base
|
||||
@ -55,7 +57,7 @@ class TestQosPlugin(base.BaseQosTestCase):
|
||||
cfg.CONF.set_override("service_plugins", ["qos"])
|
||||
|
||||
manager.init()
|
||||
self.qos_plugin = directory.get_plugin(constants.QOS)
|
||||
self.qos_plugin = directory.get_plugin(plugins_constants.QOS)
|
||||
|
||||
self.qos_plugin.driver_manager = mock.Mock()
|
||||
|
||||
@ -811,6 +813,34 @@ class TestQosPlugin(base.BaseQosTestCase):
|
||||
self.assertRaises(AttributeError, getattr, self.qos_plugin,
|
||||
'create_policy_bandwidth_limit_rules')
|
||||
|
||||
def test_get_rule_type(self):
|
||||
admin_ctxt = context.get_admin_context()
|
||||
drivers_details = [{
|
||||
'name': 'fake-driver',
|
||||
'supported_parameters': [{
|
||||
'parameter_name': 'max_kbps',
|
||||
'parameter_type': constants.VALUES_TYPE_RANGE,
|
||||
'parameter_range': {'start': 0, 'end': 100}
|
||||
}]
|
||||
}]
|
||||
with mock.patch.object(
|
||||
qos_plugin.QoSPlugin, "supported_rule_type_details",
|
||||
return_value=drivers_details
|
||||
):
|
||||
rule_type_details = self.qos_plugin.get_rule_type(
|
||||
admin_ctxt, qos_consts.RULE_TYPE_BANDWIDTH_LIMIT)
|
||||
self.assertEqual(
|
||||
qos_consts.RULE_TYPE_BANDWIDTH_LIMIT,
|
||||
rule_type_details['type'])
|
||||
self.assertEqual(
|
||||
drivers_details, rule_type_details['drivers'])
|
||||
|
||||
def test_get_rule_type_as_user(self):
|
||||
self.assertRaises(
|
||||
lib_exc.NotAuthorized,
|
||||
self.qos_plugin.get_rule_type,
|
||||
self.ctxt, qos_consts.RULE_TYPE_BANDWIDTH_LIMIT)
|
||||
|
||||
def test_get_rule_types(self):
|
||||
rule_types_mock = mock.PropertyMock(
|
||||
return_value=qos_consts.VALID_RULE_TYPES)
|
||||
|
@ -0,0 +1,8 @@
|
||||
---
|
||||
prelude: >
|
||||
New API to get details of supported rule types.
|
||||
features:
|
||||
- |
|
||||
The QoS service plugin can now expose details about supported QoS rule
|
||||
types in Neutron deployment.
|
||||
New API call is allowed only for users with admin priviliges.
|
Loading…
Reference in New Issue
Block a user