Merge "[OVN][QoS] Update the Logical_Swith_Port options with the QoS values"
This commit is contained in:
@@ -205,7 +205,23 @@ class OVNClientQosExtension:
|
||||
|
||||
return ovn_qos_rule
|
||||
|
||||
def _ovn_lsp_rule(self, rules):
|
||||
def get_lsp_options_qos(self, port_id):
|
||||
"""Return the current LSP.options QoS fields, passing the port ID"""
|
||||
qos_options = {}
|
||||
lsp = self.nb_idl.lookup('Logical_Switch_Port', port_id, default=None)
|
||||
if not lsp:
|
||||
return {}
|
||||
|
||||
for qos_key in (ovn_const.LSP_OPTIONS_QOS_MAX_RATE,
|
||||
ovn_const.LSP_OPTIONS_QOS_BURST,
|
||||
ovn_const.LSP_OPTIONS_QOS_MIN_RATE):
|
||||
qos_value = lsp.options.get(qos_key)
|
||||
if qos_value is not None:
|
||||
qos_options[qos_key] = qos_value
|
||||
return qos_options
|
||||
|
||||
@staticmethod
|
||||
def _ovn_lsp_rule(rules):
|
||||
"""Generate the OVN LSP.options for physical network ports (egress)
|
||||
|
||||
The Logical_Switch_Port options field is a dictionary that can contain
|
||||
|
||||
@@ -497,8 +497,11 @@ class OVNClient:
|
||||
if self.is_mcast_flood_broken and port_type not in (
|
||||
'vtep', ovn_const.LSP_TYPE_LOCALPORT, 'router'):
|
||||
options.update({ovn_const.LSP_OPTIONS_MCAST_FLOOD_REPORTS: 'true'})
|
||||
|
||||
sg_ids = ' '.join(utils.get_lsp_security_groups(port))
|
||||
|
||||
lsp_options_qos = self._qos_driver.get_lsp_options_qos(port['id'])
|
||||
options.update(lsp_options_qos)
|
||||
|
||||
return OvnPortInfo(port_type, options, addresses, port_security,
|
||||
parent_name, tag, dhcpv4_options, dhcpv6_options,
|
||||
cidrs.strip(), device_owner, sg_ids,
|
||||
|
||||
@@ -16,8 +16,11 @@ from neutron_lib.api.definitions import external_net
|
||||
from neutron_lib.api.definitions import network_mtu as mtu_def
|
||||
from neutron_lib.api.definitions import provider_net
|
||||
from neutron_lib import constants
|
||||
from neutron_lib.plugins import constants as plugins_constants
|
||||
from neutron_lib.services.qos import constants as qos_const
|
||||
from oslo_config import cfg
|
||||
from oslo_utils import strutils
|
||||
from oslo_utils import uuidutils
|
||||
|
||||
from neutron.common.ovn import constants as ovn_const
|
||||
from neutron.common.ovn import utils as ovn_utils
|
||||
@@ -30,8 +33,11 @@ from neutron.tests.unit.extensions import test_l3
|
||||
class TestOVNClient(base.TestOVNFunctionalBase,
|
||||
test_l3.L3NatTestCaseMixin):
|
||||
|
||||
def setUp(self, **kwargs):
|
||||
super().setUp(**kwargs)
|
||||
_extension_drivers = ['qos']
|
||||
|
||||
def setUp(self, *args):
|
||||
service_plugins = {plugins_constants.QOS: 'qos'}
|
||||
super().setUp(service_plugins=service_plugins)
|
||||
ext_mgr = test_l3.L3TestExtensionManager()
|
||||
self.ext_api = test_extensions.setup_extensions_middleware(ext_mgr)
|
||||
|
||||
@@ -309,3 +315,55 @@ class TestOVNClient(base.TestOVNFunctionalBase,
|
||||
# MTU connected to the router.
|
||||
self._check_gw_lrp_mtu(router_id,
|
||||
min(router_attached_net_mtus))
|
||||
|
||||
def test_update_port_with_qos(self):
|
||||
def _check_bw(port_id, max_kbps=None, max_burst_kbps=None):
|
||||
lsp = self.nb_api.lookup('Logical_Switch_Port', port_id)
|
||||
if max_kbps:
|
||||
self.assertEqual(
|
||||
'{}'.format(max_kbps * 1000),
|
||||
lsp.options[ovn_const.LSP_OPTIONS_QOS_MAX_RATE])
|
||||
else:
|
||||
self.assertNotIn(ovn_const.LSP_OPTIONS_QOS_MAX_RATE,
|
||||
lsp.options)
|
||||
if max_burst_kbps:
|
||||
self.assertEqual(
|
||||
'{}'.format(max_burst_kbps * 1000),
|
||||
lsp.options[ovn_const.LSP_OPTIONS_QOS_BURST])
|
||||
else:
|
||||
self.assertNotIn(ovn_const.LSP_OPTIONS_QOS_BURST,
|
||||
lsp.options)
|
||||
|
||||
res = self._create_qos_policy(self.fmt, is_admin=True)
|
||||
qos = self.deserialize(self.fmt, res)['policy']
|
||||
max_kbps, max_burst_kbps = 1000, 800
|
||||
self._create_qos_rule(self.fmt, qos['id'],
|
||||
qos_const.RULE_TYPE_BANDWIDTH_LIMIT,
|
||||
max_kbps=max_kbps, max_burst_kbps=max_burst_kbps,
|
||||
is_admin=True)
|
||||
net_args = {provider_net.NETWORK_TYPE: 'flat',
|
||||
provider_net.PHYSICAL_NETWORK: 'datacentre'}
|
||||
with self.network(uuidutils.generate_uuid(),
|
||||
arg_list=tuple(net_args.keys()), as_admin=True,
|
||||
**net_args) as net:
|
||||
with self.subnet(net) as subnet:
|
||||
with self.port(subnet) as port:
|
||||
port_data = port['port']
|
||||
# Check no QoS options.
|
||||
_check_bw(port_data['id'])
|
||||
|
||||
# Add QoS policy.
|
||||
req = self.new_update_request(
|
||||
'ports',
|
||||
{'port': {'qos_policy_id': qos['id']}},
|
||||
port_data['id'])
|
||||
req.get_response(self.api)
|
||||
_check_bw(port_data['id'], max_kbps, max_burst_kbps)
|
||||
|
||||
# Update port.
|
||||
req = self.new_update_request(
|
||||
'ports',
|
||||
{'port': {'name': uuidutils.generate_uuid()}},
|
||||
port_data['id'])
|
||||
req.get_response(self.api)
|
||||
_check_bw(port_data['id'], max_kbps, max_burst_kbps)
|
||||
|
||||
@@ -97,7 +97,9 @@ class MechDriverSetupBase(abc.ABC):
|
||||
self.mech_driver.nb_ovn = fakes.FakeOvsdbNbOvnIdl()
|
||||
self.mech_driver.sb_ovn = fakes.FakeOvsdbSbOvnIdl()
|
||||
self.mech_driver._post_fork_event.set()
|
||||
self.mech_driver._ovn_client._qos_driver = mock.Mock()
|
||||
self.mech_driver._ovn_client._qos_driver = mock.Mock(
|
||||
get_lsp_options_qos=mock.Mock(return_value={})
|
||||
)
|
||||
self._agent_cache = neutron_agent.AgentCache(self.mech_driver)
|
||||
agent1 = self._add_agent('agent1')
|
||||
neutron_agent.AgentCache().get_agents = mock.Mock()
|
||||
@@ -189,6 +191,8 @@ class TestOVNMechanismDriverBase(MechDriverSetupBase,
|
||||
self.rp_ns = self.mech_driver.resource_provider_uuid5_namespace
|
||||
self.placement_ext = self.mech_driver._ovn_client.placement_extension
|
||||
self.placement_ext._reset(self.placement_ext._driver)
|
||||
mock.patch.object(self.mech_driver._ovn_client._qos_driver,
|
||||
'get_lsp_options_qos', return_value={}).start()
|
||||
|
||||
self.fake_subnet = fakes.FakeSubnet.create_one_subnet().info()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user