Merge "NSX|V3: Support QoS ingress rules"

This commit is contained in:
Jenkins 2017-07-02 11:31:22 +00:00 committed by Gerrit Code Review
commit 63154b510b
3 changed files with 116 additions and 41 deletions

View File

@ -33,7 +33,8 @@ SUPPORTED_RULES = {
qos_consts.MAX_BURST: {
'type:range': [0, n_consts.DB_INTEGER_MAX_VALUE]},
qos_consts.DIRECTION: {
'type:values': [n_consts.EGRESS_DIRECTION]}
'type:values': [n_consts.EGRESS_DIRECTION,
n_consts.INGRESS_DIRECTION]}
},
qos_consts.RULE_TYPE_DSCP_MARKING: {
qos_consts.DSCP_MARK: {'type:values': n_consts.VALID_DSCP_MARKS}
@ -67,17 +68,8 @@ class NSXv3QosDriver(base.DriverBase):
def update_policy(self, context, policy):
if (hasattr(policy, "rules")):
# we may have up to 1 rule of each type
bw_rule = None
dscp_rule = None
for rule in policy["rules"]:
if rule.rule_type == qos_consts.RULE_TYPE_BANDWIDTH_LIMIT:
bw_rule = rule
else:
dscp_rule = rule
self.handler.update_policy_rules(
context, policy.id, bw_rule, dscp_rule)
context, policy.id, policy["rules"])
# May also need to update name / description
self.handler.update_policy(context, policy.id, policy)

View File

@ -17,6 +17,7 @@
from oslo_config import cfg
from oslo_log import log as logging
from neutron.common import constants as n_consts
from neutron.services.qos import qos_consts
from neutron_lib.api import validators
from neutron_lib import exceptions as n_exc
@ -150,25 +151,45 @@ class QosNotificationsHandler(object):
return qos_marking, dscp
def update_policy_rules(self, context, policy_id, bw_rule, dscp_rule):
def update_policy_rules(self, context, policy_id, rules):
"""Update the QoS switch profile with the BW limitations and
DSCP marking configuration
"""
profile_id = nsx_db.get_switch_profile_by_qos_policy(
context.session, policy_id)
(shaping_enabled, burst_size, peak_bw,
average_bw) = self._get_bw_values_from_rule(bw_rule)
ingress_bw_rule = None
egress_bw_rule = None
dscp_rule = None
for rule in rules:
if rule.rule_type == qos_consts.RULE_TYPE_BANDWIDTH_LIMIT:
if rule.direction == n_consts.EGRESS_DIRECTION:
egress_bw_rule = rule
else:
ingress_bw_rule = rule
else:
dscp_rule = rule
# the NSX direction is opposite to the neutron direction
(ingress_bw_enabled, ingress_burst_size, ingress_peak_bw,
ingress_average_bw) = self._get_bw_values_from_rule(egress_bw_rule)
(egress_bw_enabled, egress_burst_size, egress_peak_bw,
egress_average_bw) = self._get_bw_values_from_rule(ingress_bw_rule)
qos_marking, dscp = self._get_dscp_values_from_rule(dscp_rule)
self._nsxlib_qos.update_shaping(
self._nsxlib_qos.set_profile_shaping(
profile_id,
shaping_enabled=shaping_enabled,
burst_size=burst_size,
peak_bandwidth=peak_bw,
average_bandwidth=average_bw,
qos_marking=qos_marking,
dscp=dscp)
ingress_bw_enabled=ingress_bw_enabled,
ingress_burst_size=ingress_burst_size,
ingress_peak_bandwidth=ingress_peak_bw,
ingress_average_bandwidth=ingress_average_bw,
egress_bw_enabled=egress_bw_enabled,
egress_burst_size=egress_burst_size,
egress_peak_bandwidth=egress_peak_bw,
egress_average_bandwidth=egress_average_bw,
qos_marking=qos_marking, dscp=dscp)
def validate_policy_rule(self, context, policy_id, rule):
"""Raise an exception if the rule values are not supported"""

View File

@ -57,6 +57,11 @@ class TestQosNsxV3Notification(base.BaseQosTestCase,
'bandwidth_limit_rule': {'id': uuidutils.generate_uuid(),
'max_kbps': 2000,
'max_burst_kbps': 150}}
self.ingress_rule_data = {
'bandwidth_limit_rule': {'id': uuidutils.generate_uuid(),
'max_kbps': 3000,
'max_burst_kbps': 350,
'direction': 'ingress'}}
self.dscp_rule_data = {
'dscp_marking_rule': {'id': uuidutils.generate_uuid(),
'dscp_mark': 22}}
@ -64,8 +69,12 @@ class TestQosNsxV3Notification(base.BaseQosTestCase,
self.policy = policy_object.QosPolicy(
self.ctxt, **self.policy_data['policy'])
# egress BW limit rule
self.rule = rule_object.QosBandwidthLimitRule(
self.ctxt, **self.rule_data['bandwidth_limit_rule'])
# ingress bw limit rule
self.ingress_rule = rule_object.QosBandwidthLimitRule(
self.ctxt, **self.ingress_rule_data['bandwidth_limit_rule'])
self.dscp_rule = rule_object.QosDscpMarkingRule(
self.ctxt, **self.dscp_rule_data['dscp_marking_rule'])
@ -140,7 +149,7 @@ class TestQosNsxV3Notification(base.BaseQosTestCase,
@mock.patch.object(policy_object.QosPolicy, '_reload_rules')
def test_bw_rule_create_profile(self, *mocks):
# test the switch profile update when a QoS BW rule is created
# test the switch profile update when a egress QoS BW rule is created
_policy = policy_object.QosPolicy(
self.ctxt, **self.policy_data['policy'])
# add a rule to the policy
@ -149,7 +158,7 @@ class TestQosNsxV3Notification(base.BaseQosTestCase,
return_value=_policy):
with mock.patch(
'vmware_nsxlib.v3.core_resources.NsxLibQosSwitchingProfile.'
'update_shaping'
'set_profile_shaping'
) as update_profile:
with mock.patch('neutron.objects.db.api.update_object',
return_value=self.rule_data):
@ -162,14 +171,59 @@ class TestQosNsxV3Notification(base.BaseQosTestCase,
rule_dict['max_kbps']) / 1024))
expected_burst = rule_dict['max_burst_kbps'] * 128
expected_peak = int(expected_bw * self.peak_bw_multiplier)
# egress neutron rule -> ingress nsx args
update_profile.assert_called_once_with(
self.fake_profile_id,
average_bandwidth=expected_bw,
burst_size=expected_burst,
peak_bandwidth=expected_peak,
shaping_enabled=True,
qos_marking='trusted',
dscp=0
ingress_bw_enabled=True,
ingress_burst_size=expected_burst,
ingress_peak_bandwidth=expected_peak,
ingress_average_bandwidth=expected_bw,
egress_bw_enabled=False,
egress_burst_size=None,
egress_peak_bandwidth=None,
egress_average_bandwidth=None,
dscp=0,
qos_marking='trusted'
)
@mock.patch.object(policy_object.QosPolicy, '_reload_rules')
def test_ingress_bw_rule_create_profile(self, *mocks):
# test the switch profile update when a ingress QoS BW rule is created
_policy = policy_object.QosPolicy(
self.ctxt, **self.policy_data['policy'])
# add a rule to the policy
setattr(_policy, "rules", [self.ingress_rule])
with mock.patch('neutron.objects.qos.policy.QosPolicy.get_object',
return_value=_policy):
with mock.patch(
'vmware_nsxlib.v3.core_resources.NsxLibQosSwitchingProfile.'
'set_profile_shaping'
) as update_profile:
with mock.patch('neutron.objects.db.api.update_object',
return_value=self.ingress_rule_data):
self.qos_plugin.update_policy_bandwidth_limit_rule(
self.ctxt, self.ingress_rule.id, _policy.id,
self.ingress_rule_data)
# validate the data on the profile
rule_dict = self.ingress_rule_data['bandwidth_limit_rule']
expected_bw = int(round(float(
rule_dict['max_kbps']) / 1024))
expected_burst = rule_dict['max_burst_kbps'] * 128
expected_peak = int(expected_bw * self.peak_bw_multiplier)
# ingress neutron rule -> egress nsx args
update_profile.assert_called_once_with(
self.fake_profile_id,
egress_bw_enabled=True,
egress_burst_size=expected_burst,
egress_peak_bandwidth=expected_peak,
egress_average_bandwidth=expected_bw,
ingress_bw_enabled=False,
ingress_burst_size=None,
ingress_peak_bandwidth=None,
ingress_average_bandwidth=None,
dscp=0,
qos_marking='trusted'
)
@mock.patch.object(policy_object.QosPolicy, '_reload_rules')
@ -233,7 +287,7 @@ class TestQosNsxV3Notification(base.BaseQosTestCase,
return_value=_policy):
with mock.patch(
'vmware_nsxlib.v3.core_resources.NsxLibQosSwitchingProfile.'
'update_shaping'
'set_profile_shaping'
) as update_profile:
with mock.patch('neutron.objects.db.api.'
'update_object', return_value=self.dscp_rule_data):
@ -246,12 +300,16 @@ class TestQosNsxV3Notification(base.BaseQosTestCase,
dscp_mark = rule_dict['dscp_mark']
update_profile.assert_called_once_with(
self.fake_profile_id,
average_bandwidth=None,
burst_size=None,
peak_bandwidth=None,
shaping_enabled=False,
qos_marking='untrusted',
dscp=dscp_mark
ingress_bw_enabled=False,
ingress_burst_size=None,
ingress_peak_bandwidth=None,
ingress_average_bandwidth=None,
egress_bw_enabled=False,
egress_burst_size=None,
egress_peak_bandwidth=None,
egress_average_bandwidth=None,
dscp=dscp_mark,
qos_marking='untrusted'
)
def test_rule_delete_profile(self):
@ -264,7 +322,7 @@ class TestQosNsxV3Notification(base.BaseQosTestCase,
return_value=_policy):
with mock.patch(
'vmware_nsxlib.v3.core_resources.NsxLibQosSwitchingProfile.'
'update_shaping'
'set_profile_shaping'
) as update_profile:
setattr(_policy, "rules", [self.rule])
self.qos_plugin.delete_policy_bandwidth_limit_rule(
@ -272,11 +330,15 @@ class TestQosNsxV3Notification(base.BaseQosTestCase,
# validate the data on the profile
update_profile.assert_called_once_with(
self.fake_profile_id,
shaping_enabled=False,
average_bandwidth=None,
burst_size=None,
ingress_bw_enabled=False,
ingress_burst_size=None,
ingress_peak_bandwidth=None,
ingress_average_bandwidth=None,
egress_bw_enabled=False,
egress_burst_size=None,
egress_peak_bandwidth=None,
egress_average_bandwidth=None,
dscp=0,
peak_bandwidth=None,
qos_marking='trusted'
)