If the driver is not going to bind a port, we should not use it as
justification to limit the subset of rule types available for the user.
The most common scenario for that would be l2pop, that does not handle port
binding, but merely modifies the implementation details of node
interconnection.
Change-Id: Iba0f3530deff3bb2871ebf893c43ef628a80c7c0
Closes-Bug: #
1488996
drivers should avoid making persistent state changes in
bind_port, or else must ensure that such state changes are
eventually cleaned up.
+
+ Implementing this method explicitly declares the mechanism
+ driver as having the intention to bind ports. This is inspected
+ by the QoS service to identify the available QoS rules you
+ can use with ports.
"""
pass
+ @property
+ def _supports_port_binding(self):
+ return self.__class__.bind_port != MechanismDriver.bind_port
+
def check_vlan_transparency(self, context):
"""Check if the network supports vlan transparency.
return []
rule_types = set(qos_consts.VALID_RULE_TYPES)
+ binding_driver_found = False
# Recalculate on every call to allow drivers determine supported rule
# types dynamically
for driver in self.ordered_mech_drivers:
- if hasattr(driver.obj, 'supported_qos_rule_types'):
- new_rule_types = \
- rule_types & set(driver.obj.supported_qos_rule_types)
- dropped_rule_types = new_rule_types - rule_types
- if dropped_rule_types:
- LOG.info(
- _LI("%(rule_types)s rule types disabled for ml2 "
- "because %(driver)s does not support them"),
- {'rule_types': ', '.join(dropped_rule_types),
- 'driver': driver.name})
- rule_types = new_rule_types
- else:
- # at least one of drivers does not support QoS, meaning there
- # are no rule types supported by all of them
- LOG.warn(
- _LW("%s does not support QoS; no rule types available"),
- driver.name)
- return []
-
- rule_types = list(rule_types)
+ driver_obj = driver.obj
+ if driver_obj._supports_port_binding:
+ binding_driver_found = True
+ if hasattr(driver_obj, 'supported_qos_rule_types'):
+ new_rule_types = \
+ rule_types & set(driver_obj.supported_qos_rule_types)
+ dropped_rule_types = new_rule_types - rule_types
+ if dropped_rule_types:
+ LOG.info(
+ _LI("%(rule_types)s rule types disabled for ml2 "
+ "because %(driver)s does not support them"),
+ {'rule_types': ', '.join(dropped_rule_types),
+ 'driver': driver.name})
+ rule_types = new_rule_types
+ else:
+ # at least one of drivers does not support QoS, meaning
+ # there are no rule types supported by all of them
+ LOG.warn(
+ _LW("%s does not support QoS; "
+ "no rule types available"),
+ driver.name)
+ return []
+
+ if binding_driver_found:
+ rule_types = list(rule_types)
+ else:
+ rule_types = []
LOG.debug("Supported QoS rule types "
"(common subset for all mech drivers): %s", rule_types)
return rule_types
from neutron.tests.fullstack.resources import environment
from neutron.tests.fullstack.resources import machine
+from neutron.plugins.ml2.drivers.openvswitch.mech_driver import \
+ mech_openvswitch as mech_ovs
+
BANDWIDTH_LIMIT = 500
BANDWIDTH_BURST = 100
vm.neutron_port['id'],
body={'port': {'qos_policy_id': None}})
_wait_for_rule_removed(vm)
+
+
+class TestQoSWithL2Population(base.BaseFullStackTestCase):
+
+ def setUp(self):
+ host_desc = [environment.HostDescription()]
+ env_desc = environment.EnvironmentDescription(qos=True, l2_pop=True)
+ env = environment.Environment(env_desc, host_desc)
+ super(TestQoSWithL2Population, self).setUp(env)
+
+ def test_supported_qos_rule_types(self):
+ res = self.client.list_qos_rule_types()
+ rule_types = {t['type'] for t in res['rule_types']}
+ expected_rules = (
+ set(mech_ovs.OpenvswitchMechanismDriver.supported_qos_rule_types))
+ self.assertEqual(expected_rules, rule_types)
qos_consts.VALID_RULE_TYPES,
self.driver.mechanism_manager.supported_qos_rule_types)
+ @mock.patch.object(mech_test.TestMechanismDriver,
+ 'supported_qos_rule_types',
+ new_callable=mock.PropertyMock,
+ return_value=qos_consts.VALID_RULE_TYPES,
+ create=True)
+ @mock.patch.object(mech_logger.LoggerMechanismDriver,
+ '_supports_port_binding',
+ new_callable=mock.PropertyMock,
+ return_value=False)
+ def test_rule_types_with_driver_that_does_not_implement_binding(self,
+ *mocks):
+ self.assertEqual(
+ qos_consts.VALID_RULE_TYPES,
+ self.driver.mechanism_manager.supported_qos_rule_types)
+
class TestMl2BasicGet(test_plugin.TestBasicGet,
Ml2PluginV2TestCase):