Merge "Adds an option to skip ports on ovs_cleanup"
This commit is contained in:
@@ -307,19 +307,29 @@ class OVSBridge(BaseOVS):
|
|||||||
self.run_ofctl("del-flows", [])
|
self.run_ofctl("del-flows", [])
|
||||||
|
|
||||||
@_ovsdb_retry
|
@_ovsdb_retry
|
||||||
def _get_port_ofport(self, port_name):
|
def _get_port_val(self, port_name, port_val):
|
||||||
return self.db_get_val("Interface", port_name, "ofport")
|
return self.db_get_val("Interface", port_name, port_val)
|
||||||
|
|
||||||
def get_port_ofport(self, port_name):
|
def get_port_ofport(self, port_name):
|
||||||
"""Get the port's assigned ofport, retrying if not yet assigned."""
|
"""Get the port's assigned ofport, retrying if not yet assigned."""
|
||||||
ofport = INVALID_OFPORT
|
ofport = INVALID_OFPORT
|
||||||
try:
|
try:
|
||||||
ofport = self._get_port_ofport(port_name)
|
ofport = self._get_port_val(port_name, "ofport")
|
||||||
except tenacity.RetryError:
|
except tenacity.RetryError:
|
||||||
LOG.exception(_LE("Timed out retrieving ofport on port %s."),
|
LOG.exception(_LE("Timed out retrieving ofport on port %s."),
|
||||||
port_name)
|
port_name)
|
||||||
return ofport
|
return ofport
|
||||||
|
|
||||||
|
def get_port_external_ids(self, port_name):
|
||||||
|
"""Get the port's assigned ofport, retrying if not yet assigned."""
|
||||||
|
port_external_ids = dict()
|
||||||
|
try:
|
||||||
|
port_external_ids = self._get_port_val(port_name, "external_ids")
|
||||||
|
except tenacity.RetryError:
|
||||||
|
LOG.exception(_LE("Timed out retrieving external_ids on port %s."),
|
||||||
|
port_name)
|
||||||
|
return port_external_ids
|
||||||
|
|
||||||
def get_port_mac(self, port_name):
|
def get_port_mac(self, port_name):
|
||||||
"""Get the port's mac address.
|
"""Get the port's mac address.
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ from neutron.common import config
|
|||||||
from neutron.conf.agent import cmd
|
from neutron.conf.agent import cmd
|
||||||
from neutron.conf.agent import common as agent_config
|
from neutron.conf.agent import common as agent_config
|
||||||
from neutron.conf.agent.l3 import config as l3_config
|
from neutron.conf.agent.l3 import config as l3_config
|
||||||
|
from neutron.plugins.ml2.drivers.openvswitch.agent.common import constants
|
||||||
|
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
@@ -44,12 +45,22 @@ def setup_conf():
|
|||||||
return conf
|
return conf
|
||||||
|
|
||||||
|
|
||||||
|
def get_bridge_deletable_ports(br):
|
||||||
|
"""
|
||||||
|
Return a list of OVS Bridge ports, excluding the ports who should not be
|
||||||
|
cleaned. such ports are tagged with the 'skip_cleanup' key in external_ids.
|
||||||
|
"""
|
||||||
|
return [port.port_name for port in br.get_vif_ports()
|
||||||
|
if constants.SKIP_CLEANUP not in
|
||||||
|
br.get_port_external_ids(port.port_name)]
|
||||||
|
|
||||||
|
|
||||||
def collect_neutron_ports(bridges):
|
def collect_neutron_ports(bridges):
|
||||||
"""Collect ports created by Neutron from OVS."""
|
"""Collect ports created by Neutron from OVS."""
|
||||||
ports = []
|
ports = []
|
||||||
for bridge in bridges:
|
for bridge in bridges:
|
||||||
ovs = ovs_lib.OVSBridge(bridge)
|
ovs = ovs_lib.OVSBridge(bridge)
|
||||||
ports += [port.port_name for port in ovs.get_vif_ports()]
|
ports += get_bridge_deletable_ports(ovs)
|
||||||
return ports
|
return ports
|
||||||
|
|
||||||
|
|
||||||
@@ -94,7 +105,12 @@ def main():
|
|||||||
for bridge in bridges:
|
for bridge in bridges:
|
||||||
LOG.info(_LI("Cleaning bridge: %s"), bridge)
|
LOG.info(_LI("Cleaning bridge: %s"), bridge)
|
||||||
ovs = ovs_lib.OVSBridge(bridge)
|
ovs = ovs_lib.OVSBridge(bridge)
|
||||||
ovs.delete_ports(all_ports=conf.ovs_all_ports)
|
if conf.ovs_all_ports:
|
||||||
|
port_names = ovs.get_port_name_list()
|
||||||
|
else:
|
||||||
|
port_names = get_bridge_deletable_ports(ovs)
|
||||||
|
for port_name in port_names:
|
||||||
|
ovs.delete_port(port_name)
|
||||||
|
|
||||||
# Remove remaining ports created by Neutron (usually veth pair)
|
# Remove remaining ports created by Neutron (usually veth pair)
|
||||||
delete_neutron_ports(ports)
|
delete_neutron_ports(ports)
|
||||||
|
|||||||
@@ -149,3 +149,7 @@ OVS_BRIDGE_NAME = 'ovs_bridge_name'
|
|||||||
|
|
||||||
# callback resource for notifying to ovsdb handler
|
# callback resource for notifying to ovsdb handler
|
||||||
OVSDB_RESOURCE = 'ovsdb'
|
OVSDB_RESOURCE = 'ovsdb'
|
||||||
|
|
||||||
|
# Used in ovs port 'external_ids' in order mark it for no cleanup when
|
||||||
|
# ovs_cleanup script is used.
|
||||||
|
SKIP_CLEANUP = 'skip_cleanup'
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ class OVSAgentQoSExtensionTestFramework(base.OVSAgentTestFramework):
|
|||||||
self.agent.int_br, port['vif_name'], rule)
|
self.agent.int_br, port['vif_name'], rule)
|
||||||
|
|
||||||
def _assert_dscp_marking_rule_is_set(self, port, dscp_rule):
|
def _assert_dscp_marking_rule_is_set(self, port, dscp_rule):
|
||||||
port_num = self.agent.int_br._get_port_ofport(port['vif_name'])
|
port_num = self.agent.int_br._get_port_val(port['vif_name'], 'ofport')
|
||||||
|
|
||||||
flows = self.agent.int_br.dump_flows_for(table='0',
|
flows = self.agent.int_br.dump_flows_for(table='0',
|
||||||
in_port=str(port_num))
|
in_port=str(port_num))
|
||||||
@@ -132,7 +132,7 @@ class OVSAgentQoSExtensionTestFramework(base.OVSAgentTestFramework):
|
|||||||
self.assertEqual(dscp_rule.dscp_mark << 2, tos_mark)
|
self.assertEqual(dscp_rule.dscp_mark << 2, tos_mark)
|
||||||
|
|
||||||
def _assert_dscp_marking_rule_not_set(self, port):
|
def _assert_dscp_marking_rule_not_set(self, port):
|
||||||
port_num = self.agent.int_br._get_port_ofport(port['vif_name'])
|
port_num = self.agent.int_br._get_port_val(port['vif_name'], 'ofport')
|
||||||
|
|
||||||
flows = self.agent.int_br.dump_flows_for(table='0',
|
flows = self.agent.int_br.dump_flows_for(table='0',
|
||||||
in_port=str(port_num))
|
in_port=str(port_num))
|
||||||
|
|||||||
@@ -875,7 +875,7 @@ class OVS_Lib_Test(base.BaseTestCase):
|
|||||||
with mock.patch.object(
|
with mock.patch.object(
|
||||||
self.br, 'db_get_val',
|
self.br, 'db_get_val',
|
||||||
side_effect=[[], [], [], [], 1]):
|
side_effect=[[], [], [], [], 1]):
|
||||||
self.assertEqual(1, self.br._get_port_ofport('1'))
|
self.assertEqual(1, self.br._get_port_val('1', 'ofport'))
|
||||||
|
|
||||||
def test_get_port_ofport_retry_fails(self):
|
def test_get_port_ofport_retry_fails(self):
|
||||||
# reduce timeout for faster execution
|
# reduce timeout for faster execution
|
||||||
@@ -885,7 +885,27 @@ class OVS_Lib_Test(base.BaseTestCase):
|
|||||||
self.br, 'db_get_val',
|
self.br, 'db_get_val',
|
||||||
side_effect=[[] for _ in range(7)]):
|
side_effect=[[] for _ in range(7)]):
|
||||||
self.assertRaises(tenacity.RetryError,
|
self.assertRaises(tenacity.RetryError,
|
||||||
self.br._get_port_ofport, '1')
|
self.br._get_port_val, '1', 'ofport')
|
||||||
|
|
||||||
|
def test_get_port_external_ids_retry(self):
|
||||||
|
external_ids = [["iface-id", "tap99id"],
|
||||||
|
["iface-status", "active"],
|
||||||
|
["attached-mac", "de:ad:be:ef:13:37"]]
|
||||||
|
with mock.patch.object(
|
||||||
|
self.br, 'db_get_val',
|
||||||
|
side_effect=[[], [], [], [], external_ids]):
|
||||||
|
self.assertEqual(external_ids,
|
||||||
|
self.br._get_port_val('1', 'external_ids'))
|
||||||
|
|
||||||
|
def test_get_port_external_ids_retry_fails(self):
|
||||||
|
# reduce timeout for faster execution
|
||||||
|
self.br.vsctl_timeout = 1
|
||||||
|
# after 7 calls the retry will timeout and raise
|
||||||
|
with mock.patch.object(
|
||||||
|
self.br, 'db_get_val',
|
||||||
|
side_effect=[[] for _ in range(7)]):
|
||||||
|
self.assertRaises(tenacity.RetryError,
|
||||||
|
self.br._get_port_val, '1', 'external_ids')
|
||||||
|
|
||||||
|
|
||||||
class TestDeferredOVSBridge(base.BaseTestCase):
|
class TestDeferredOVSBridge(base.BaseTestCase):
|
||||||
|
|||||||
@@ -46,8 +46,6 @@ class TestOVSCleanup(base.BaseTestCase):
|
|||||||
mock_collect.return_value = ports
|
mock_collect.return_value = ports
|
||||||
|
|
||||||
util.main()
|
util.main()
|
||||||
mock_ovs.assert_has_calls([mock.call().delete_ports(
|
|
||||||
all_ports=False)])
|
|
||||||
mock_collect.assert_called_once_with(set(bridges))
|
mock_collect.assert_called_once_with(set(bridges))
|
||||||
mock_delete.assert_called_once_with(ports)
|
mock_delete.assert_called_once_with(ports)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user