NSX QoS ext: RXTX factor can be decimal
In Nova flavors it is ok to specify a decimal RXTX factor. For this reason when applying QoS to a port Neutron should not convert this factor to an integer value, but simply ensure it's a valid float number and positive. This patch ialso drops the conversion to integer that happens in the NSX-mh plugin but also ensures that the resulting maximum bandwidth after applying the RXTX factor is still an integer value. Closes-Bug: #1463363 Patch applied from commit: 9f61b082093fde7db135f400d7d99724c6c01a43 Change-Id: I9f5e166e349de0703a8711fa73a127e90059f506
This commit is contained in:
parent
d9c78880d2
commit
86701a3c7e
|
@ -553,6 +553,24 @@ def convert_to_int(data):
|
|||
raise n_exc.InvalidInput(error_message=msg)
|
||||
|
||||
|
||||
def convert_to_positive_float_or_none(val):
|
||||
# NOTE(salv-orlando): This conversion function is currently used by
|
||||
# a vendor specific extension only at the moment It is used for
|
||||
# port's RXTX factor in neutron.plugins.vmware.extensions.qos.
|
||||
# It is deemed however generic enough to be in this module as it
|
||||
# might be used in future for other API attributes.
|
||||
if val is None:
|
||||
return
|
||||
try:
|
||||
val = float(val)
|
||||
if val < 0:
|
||||
raise ValueError()
|
||||
except (ValueError, TypeError):
|
||||
msg = _("'%s' must be a non negative decimal.") % val
|
||||
raise n_exc.InvalidInput(error_message=msg)
|
||||
return val
|
||||
|
||||
|
||||
def convert_kvp_str_to_list(data):
|
||||
"""Convert a value of the form 'key=value' to ['key', 'value'].
|
||||
|
||||
|
|
|
@ -270,7 +270,8 @@ class QoSDbMixin(qos.QueuePluginBase):
|
|||
# create the queue
|
||||
tenant_id = self._get_tenant_id_for_create(context, port)
|
||||
if port.get(qos.RXTX_FACTOR) and queue_to_create.get('max'):
|
||||
queue_to_create['max'] *= int(port[qos.RXTX_FACTOR])
|
||||
queue_to_create['max'] = int(queue_to_create['max'] *
|
||||
port[qos.RXTX_FACTOR])
|
||||
queue = {'qos_queue': {'name': queue_to_create.get('name'),
|
||||
'min': queue_to_create.get('min'),
|
||||
'max': queue_to_create.get('max'),
|
||||
|
|
|
@ -145,7 +145,7 @@ EXTENDED_ATTRIBUTES_2_0 = {
|
|||
'is_visible': False,
|
||||
'default': 1,
|
||||
'enforce_policy': True,
|
||||
'convert_to': convert_to_unsigned_int_or_none},
|
||||
'convert_to': attr.convert_to_positive_float_or_none},
|
||||
|
||||
QUEUE: {'allow_post': False,
|
||||
'allow_put': False,
|
||||
|
|
|
@ -774,6 +774,35 @@ class TestConvertToInt(base.BaseTestCase):
|
|||
value, attributes.convert_none_to_empty_list(value))
|
||||
|
||||
|
||||
class TestConvertToFloat(base.BaseTestCase):
|
||||
# NOTE: the routine being tested here is a plugin-specific extension
|
||||
# module. As the plugin split proceed towards its second phase this
|
||||
# test should either be remove, or the validation routine moved into
|
||||
# neutron.api.v2.attributes
|
||||
|
||||
def test_convert_to_float_positve_value(self):
|
||||
self.assertEqual(
|
||||
1.111, attributes.convert_to_positive_float_or_none(1.111))
|
||||
self.assertEqual(1, attributes.convert_to_positive_float_or_none(1))
|
||||
self.assertEqual(0, attributes.convert_to_positive_float_or_none(0))
|
||||
|
||||
def test_convert_to_float_negative_value(self):
|
||||
self.assertRaises(n_exc.InvalidInput,
|
||||
attributes.convert_to_positive_float_or_none,
|
||||
-1.11)
|
||||
|
||||
def test_convert_to_float_string(self):
|
||||
self.assertEqual(4, attributes.convert_to_positive_float_or_none('4'))
|
||||
self.assertEqual(
|
||||
4.44, attributes.convert_to_positive_float_or_none('4.44'))
|
||||
self.assertRaises(n_exc.InvalidInput,
|
||||
attributes.convert_to_positive_float_or_none,
|
||||
'garbage')
|
||||
|
||||
def test_convert_to_float_none_value(self):
|
||||
self.assertIsNone(attributes.convert_to_positive_float_or_none(None))
|
||||
|
||||
|
||||
class TestConvertKvp(base.BaseTestCase):
|
||||
|
||||
def test_convert_kvp_list_to_dict_succeeds_for_missing_values(self):
|
||||
|
|
|
@ -262,8 +262,8 @@ class TestQoSQueue(test_nsx_plugin.NsxPluginV2TestCase):
|
|||
neutron_context=neutron_context)
|
||||
self.assertNotIn(ext_qos.QUEUE, port['port'])
|
||||
|
||||
def test_rxtx_factor(self):
|
||||
with self.qos_queue(max=10) as q1:
|
||||
def _test_rxtx_factor(self, max_value, rxtx_factor):
|
||||
with self.qos_queue(max=max_value) as q1:
|
||||
|
||||
res = self._create_network('json', 'net1', True,
|
||||
arg_list=(ext_qos.QUEUE,),
|
||||
|
@ -271,10 +271,20 @@ class TestQoSQueue(test_nsx_plugin.NsxPluginV2TestCase):
|
|||
net1 = self.deserialize('json', res)
|
||||
res = self._create_port('json', net1['network']['id'],
|
||||
arg_list=(ext_qos.RXTX_FACTOR,),
|
||||
rxtx_factor=2, device_id='1')
|
||||
rxtx_factor=rxtx_factor, device_id='1')
|
||||
port = self.deserialize('json', res)
|
||||
req = self.new_show_request('qos-queues',
|
||||
port['port'][ext_qos.QUEUE])
|
||||
res = req.get_response(self.ext_api)
|
||||
queue = self.deserialize('json', res)
|
||||
self.assertEqual(queue['qos_queue']['max'], 20)
|
||||
self.assertEqual(queue['qos_queue']['max'],
|
||||
max_value * rxtx_factor)
|
||||
|
||||
def test_rxtx_factor(self):
|
||||
self._test_rxtx_factor(10, 2)
|
||||
|
||||
def test_decimal_rxtx_factor(self):
|
||||
self._test_rxtx_factor(10, 1.5)
|
||||
|
||||
def test_decimal_rxtx_factor_below_1(self):
|
||||
self._test_rxtx_factor(10, 0.5)
|
||||
|
|
Loading…
Reference in New Issue