From 1b331422a0dd1f9886d7b1f8c4ed39c56207b015 Mon Sep 17 00:00:00 2001 From: Adit Sarfaty Date: Tue, 26 Apr 2016 11:17:04 +0300 Subject: [PATCH] NSX|V3 QoS: handle illegal max bandwidth The backed does not allow max bandwidth < 1M. Since the switch update is done from a notification callback, we cannot fail the user action. Instead, we log a warning, and use the minimal possible value. Change-Id: Ic5aa7f933d7faf959bafd7f3f589fe29d6ded06d --- vmware_nsx/common/exceptions.py | 5 --- vmware_nsx/services/qos/nsx_v3/utils.py | 8 +++- .../services/qos/test_nsxv3_notification.py | 37 +++++++++++++++++++ 3 files changed, 43 insertions(+), 7 deletions(-) diff --git a/vmware_nsx/common/exceptions.py b/vmware_nsx/common/exceptions.py index 8748d0f763..af8d1421f3 100644 --- a/vmware_nsx/common/exceptions.py +++ b/vmware_nsx/common/exceptions.py @@ -175,8 +175,3 @@ class NsxResourceNotFound(n_exc.NotFound): class NsxQosPolicyMappingNotFound(n_exc.NotFound): message = _('Unable to find mapping for QoS policy: %(policy)s') - - -class NsxQosSmallBw(n_exc.InvalidInput): - message = _("Invalid input for max_kbps. Reason: The minimal legal value " - "for max_kbps is 1024") diff --git a/vmware_nsx/services/qos/nsx_v3/utils.py b/vmware_nsx/services/qos/nsx_v3/utils.py index 6125370434..e22dfa810e 100644 --- a/vmware_nsx/services/qos/nsx_v3/utils.py +++ b/vmware_nsx/services/qos/nsx_v3/utils.py @@ -20,7 +20,7 @@ from neutron import context as n_context from neutron.objects.qos import policy as qos_policy from oslo_log import log as logging -from vmware_nsx._i18n import _ +from vmware_nsx._i18n import _, _LW from vmware_nsx.common import exceptions as nsx_exc from vmware_nsx.common import utils from vmware_nsx.db import db as nsx_db @@ -130,7 +130,11 @@ class QosNotificationsHandler(object): # validate the max_kbps - it must be at least 1Mbps for the # switch profile configuration to succeed. if (bw_rule.max_kbps < MAX_KBPS_MIN_VALUE): - raise nsx_exc.NsxQosSmallBw() + # Since failing the action from the notification callback is not + # possible, just log the warning and use the minimal value + LOG.warning(_LW("Invalid input for max_kbps. " + "The minimal legal value is 1024")) + bw_rule.max_kbps = MAX_KBPS_MIN_VALUE # 'None' value means we will keep the old value burst_size = peak_bandwidth = average_bandwidth = None diff --git a/vmware_nsx/tests/unit/services/qos/test_nsxv3_notification.py b/vmware_nsx/tests/unit/services/qos/test_nsxv3_notification.py index a5fa53c8f9..c6c8529dee 100644 --- a/vmware_nsx/tests/unit/services/qos/test_nsxv3_notification.py +++ b/vmware_nsx/tests/unit/services/qos/test_nsxv3_notification.py @@ -27,6 +27,7 @@ from neutron.tests.unit.services.qos import base from vmware_nsx.common import utils from vmware_nsx.db import db as nsx_db from vmware_nsx.nsxlib import v3 as nsxlib +from vmware_nsx.services.qos.nsx_v3 import utils as qos_utils from vmware_nsx.tests.unit.nsxlib.v3 import nsxlib_testcase @@ -154,6 +155,42 @@ class TestQosNsxV3Notification(nsxlib_testcase.NsxClientTestCase, shaping_enabled=True ) + @mock.patch.object(policy_object.QosPolicy, 'reload_rules') + def test_bw_rule_create_profile_minimal_val(self, *mocks): + # test the switch profile update when a QoS rule is created + # with an invalid limit value + bad_limit = qos_utils.MAX_KBPS_MIN_VALUE - 1 + rule_data = { + 'bandwidth_limit_rule': {'id': uuidutils.generate_uuid(), + 'max_kbps': bad_limit, + 'max_burst_kbps': 150}} + + rule = rule_object.QosBandwidthLimitRule( + self.ctxt, **rule_data['bandwidth_limit_rule']) + + _policy = policy_object.QosPolicy( + self.ctxt, **self.policy_data['policy']) + # add a rule to the policy + setattr(_policy, "rules", [rule]) + with mock.patch('neutron.objects.qos.policy.QosPolicy.get_object', + return_value=_policy): + with mock.patch.object(nsxlib, + 'update_qos_switching_profile_shaping') as update_profile: + self.qos_plugin.update_policy_bandwidth_limit_rule( + self.ctxt, rule.id, _policy.id, rule_data) + + # validate the data on the profile + rule_dict = rule_data['bandwidth_limit_rule'] + expected_bw = qos_utils.MAX_KBPS_MIN_VALUE / 1024 + expected_burst = rule_dict['max_burst_kbps'] * 128 + update_profile.assert_called_once_with( + self.fake_profile_id, + average_bandwidth=expected_bw, + burst_size=expected_burst, + peak_bandwidth=expected_bw, + shaping_enabled=True + ) + def test_rule_delete_profile(self): # test the switch profile update when a QoS rule is deleted _policy = policy_object.QosPolicy(