diff --git a/neutron/agent/common/ovs_lib.py b/neutron/agent/common/ovs_lib.py index b5d520c31e8..e2f26c00664 100644 --- a/neutron/agent/common/ovs_lib.py +++ b/neutron/agent/common/ovs_lib.py @@ -1013,9 +1013,14 @@ class OVSBridge(BaseOVS): self._min_bw_qos_id, qos_constants.RULE_TYPE_MINIMUM_BANDWIDTH, qos_id=qos_id, queues=qos_queues) - self.ovsdb.db_clear('Port', port_id, 'qos').execute( - check_error=False) - if not qos_queues: + else: + # Find the physical bridge interface with the QoS assigned and + # unset it. + for port in self.ovsdb.db_find( + 'Port', ('qos', '=', qos_id), + columns=['_uuid', 'qos']).execute(check_error=True): + self.ovsdb.db_clear('Port', port['_uuid'], + 'qos').execute(check_error=True) self._delete_qos(qos_id) self._delete_queue( queue['_uuid'], qos_constants.RULE_TYPE_MINIMUM_BANDWIDTH) diff --git a/neutron/tests/functional/agent/common/test_ovs_lib.py b/neutron/tests/functional/agent/common/test_ovs_lib.py index 758f9a6ff0f..326de08ecc6 100644 --- a/neutron/tests/functional/agent/common/test_ovs_lib.py +++ b/neutron/tests/functional/agent/common/test_ovs_lib.py @@ -125,14 +125,15 @@ class BaseOVSTestCase(base.BaseSudoTestCase): return None return qoses - def _create_bridge(self): - self.ovs.ovsdb.add_br(self.br_name).execute() - self.elements_to_clean['bridges'].append(self.br_name) + def _create_bridge(self, br_name=None): + br_name = br_name or self.br_name + self.ovs.ovsdb.add_br(br_name).execute() + self.elements_to_clean['bridges'].append(br_name) - def _create_port(self, port_name): + def _create_port(self, port_name, br_name=None): row_event = WaitForPortCreateEvent(port_name) self.ovs.ovsdb.idl.notify_handler.watch_event(row_event) - self.ovs.ovsdb.add_port(self.br_name, port_name).execute( + self.ovs.ovsdb.add_port(br_name or self.br_name, port_name).execute( check_error=True) self.assertTrue(row_event.wait()) @@ -505,6 +506,15 @@ class BaseOVSTestCase(base.BaseSudoTestCase): rule_type_id=self.ovs._min_bw_qos_id) self._check_value({'_uuid': qos_id}, self._list_qos, qos_id, keys_to_check=['_uuid']) + + # Assign the QoS policy to the physical bridge interface. This QoS + # must be unset once the minimum bandwidth queue is removed. + br_phy = ('br-phy-' + uuidutils.generate_uuid())[:6] + ext_port = ('phy-' + uuidutils.generate_uuid())[:9] + self._create_bridge(br_name=br_phy) + self._create_port(ext_port, br_name=br_phy) + self.ovs._set_port_qos(ext_port, qos_id=qos_id) + qos = self._list_qos(qos_id) self.assertEqual(queue_id_1, qos['queues'][1].uuid) self.assertEqual(queue_id_2, qos['queues'][2].uuid) @@ -515,9 +525,16 @@ class BaseOVSTestCase(base.BaseSudoTestCase): qos = self._list_qos(qos_id) self.assertEqual(1, len(qos['queues'])) self.assertEqual(queue_id_1, qos['queues'][1].uuid) + ports_with_qos = self.ovs.ovsdb.db_find( + 'Port', ('qos', '=', qos_id)).execute(check_error=True) + self.assertEqual(1, len(ports_with_qos)) + self.assertEqual(ext_port, ports_with_qos[0]['name']) self.ovs.delete_minimum_bandwidth_queue(neutron_port_id_1) self.assertIsNone(self._list_qos(qos_id)) + ports_with_qos = self.ovs.ovsdb.db_find( + 'Port', ('qos', '=', qos_id)).execute(check_error=True) + self.assertEqual(0, len(ports_with_qos)) def test_delete_minimum_bandwidth_queue_no_qos_found(self): queue_id, neutron_port_id = self._create_queue(queue_num=1)