Fix TypeError in native of_interface _get_dpid
If no bridge datapath_id was returned for some
reason (like broken deployment), _get_dpid()
would process further and raise TypeError while
trying to use int conversion on an empty list.
This patch addresses the problem by raising a
RuntimeError if no datapath was found for a
bridge.
Conflicts:
neutron/agent/common/ovs_lib.py
Closes-Bug: #1615690
Change-Id: Ie97540793e5d2b14120d3f1bafbf659427c44117
(cherry picked from commit 59d29f7cda
)
This commit is contained in:
parent
d963792542
commit
30ff2f397f
|
@ -58,17 +58,13 @@ OVS_DEFAULT_CAPS = {
|
|||
_SENTINEL = object()
|
||||
|
||||
|
||||
def _ofport_result_pending(result):
|
||||
def _ovsdb_result_pending(result):
|
||||
"""Return True if ovs-vsctl indicates the result is still pending."""
|
||||
# ovs-vsctl can return '[]' for an ofport that has not yet been assigned
|
||||
try:
|
||||
int(result)
|
||||
return False
|
||||
except (ValueError, TypeError):
|
||||
return True
|
||||
return result == []
|
||||
|
||||
|
||||
def _ofport_retry(fn):
|
||||
def _ovsdb_retry(fn):
|
||||
"""Decorator for retrying when OVS has yet to assign an ofport.
|
||||
|
||||
The instance's vsctl_timeout is used as the max waiting time. This relies
|
||||
|
@ -79,7 +75,7 @@ def _ofport_retry(fn):
|
|||
self = args[0]
|
||||
new_fn = tenacity.retry(
|
||||
reraise=True,
|
||||
retry=tenacity.retry_if_result(_ofport_result_pending),
|
||||
retry=tenacity.retry_if_result(_ovsdb_result_pending),
|
||||
wait=tenacity.wait_exponential(multiplier=0.01, max=1),
|
||||
stop=tenacity.stop_after_delay(
|
||||
self.vsctl_timeout))(fn)
|
||||
|
@ -307,7 +303,7 @@ class OVSBridge(BaseOVS):
|
|||
def remove_all_flows(self):
|
||||
self.run_ofctl("del-flows", [])
|
||||
|
||||
@_ofport_retry
|
||||
@_ovsdb_retry
|
||||
def _get_port_ofport(self, port_name):
|
||||
return self.db_get_val("Interface", port_name, "ofport")
|
||||
|
||||
|
@ -321,9 +317,19 @@ class OVSBridge(BaseOVS):
|
|||
port_name)
|
||||
return ofport
|
||||
|
||||
@_ovsdb_retry
|
||||
def _get_datapath_id(self):
|
||||
return self.db_get_val('Bridge', self.br_name, 'datapath_id')
|
||||
|
||||
def get_datapath_id(self):
|
||||
return self.db_get_val('Bridge',
|
||||
self.br_name, 'datapath_id')
|
||||
try:
|
||||
return self._get_datapath_id()
|
||||
except tenacity.RetryError:
|
||||
# if ovs fails to find datapath_id then something is likely to be
|
||||
# broken here
|
||||
LOG.exception(_LE("Timed out retrieving datapath_id on bridge "
|
||||
"%s."), self.br_name)
|
||||
raise RuntimeError('No datapath_id on bridge %s' % self.br_name)
|
||||
|
||||
def do_action_flows(self, action, kwargs_list):
|
||||
if action != 'del':
|
||||
|
|
|
@ -33,3 +33,16 @@ class OVSAgentBridgeTestCase(ovs_test_base.OVSRyuTestBase):
|
|||
# make sure it correctly raises RuntimeError, not UnboundLocalError as
|
||||
# in LP https://bugs.launchpad.net/neutron/+bug/1588042
|
||||
self.assertRaises(RuntimeError, br._get_dp)
|
||||
|
||||
def test_get_datapath_no_data_returned(self):
|
||||
|
||||
def _mock_db_get_val(tb, rec, col):
|
||||
if tb == 'Bridge':
|
||||
return []
|
||||
|
||||
mock.patch('neutron.agent.common.ovs_lib.OVSBridge.db_get_val',
|
||||
side_effect=_mock_db_get_val).start()
|
||||
br = self.br_int_cls('br-int')
|
||||
# make sure that in case of any misconfiguration when no datapath is
|
||||
# found a proper exception, not a TypeError is raised
|
||||
self.assertRaises(RuntimeError, br._get_dp)
|
||||
|
|
Loading…
Reference in New Issue