From 0c6a21c06406ca942c92e39a4a2b3fab61fefb60 Mon Sep 17 00:00:00 2001 From: Rodolfo Alonso Hernandez Date: Thu, 21 Feb 2019 12:06:39 +0000 Subject: [PATCH] Add function "has_table_columns" to OVSDB implementation API Change-Id: Ide8ffcc99a05edf15ce511b1bd4a9b1552dad5d1 Closes-Bug: #1814577 --- vif_plug_ovs/ovsdb/api.py | 15 +++++++++++ vif_plug_ovs/ovsdb/impl_vsctl.py | 14 ++++++++++- vif_plug_ovs/ovsdb/ovsdb_lib.py | 4 +-- .../tests/unit/ovsdb/test_ovsdb_lib.py | 25 +++++++++++++++++++ 4 files changed, 54 insertions(+), 4 deletions(-) diff --git a/vif_plug_ovs/ovsdb/api.py b/vif_plug_ovs/ovsdb/api.py index c0be34e9..5f3b1983 100644 --- a/vif_plug_ovs/ovsdb/api.py +++ b/vif_plug_ovs/ovsdb/api.py @@ -10,7 +10,10 @@ # License for the specific language governing permissions and limitations # under the License. +import abc + from oslo_utils import importutils +import six interface_map = { @@ -25,3 +28,15 @@ def get_instance(context, iface_name=None): iface = importutils.import_module( interface_map[iface_name or context.interface]) return iface.api_factory(context) + + +@six.add_metaclass(abc.ABCMeta) +class ImplAPI(object): + @abc.abstractmethod + def has_table_column(self, table, column): + """Check if a column exists in a database table + + :param table: (string) table name + :param column: (string) column name + :return: True if the column exists, False if not. + """ diff --git a/vif_plug_ovs/ovsdb/impl_vsctl.py b/vif_plug_ovs/ovsdb/impl_vsctl.py index 062b255e..9df1650f 100644 --- a/vif_plug_ovs/ovsdb/impl_vsctl.py +++ b/vif_plug_ovs/ovsdb/impl_vsctl.py @@ -24,6 +24,7 @@ from oslo_utils import uuidutils from ovsdbapp import api as ovsdb_api import six +from vif_plug_ovs.ovsdb import api from vif_plug_ovs import privsep @@ -214,7 +215,7 @@ class BrExistsCommand(DbCommand): log_errors=False) -class OvsdbVsctl(ovsdb_api.API): +class OvsdbVsctl(ovsdb_api.API, api.ImplAPI): def __init__(self, context): super(OvsdbVsctl, self).__init__() self.context = context @@ -353,6 +354,17 @@ class OvsdbVsctl(ovsdb_api.API): def db_remove(self, table, record, column, *values, **keyvalues): raise NotImplementedError() + def has_table_column(self, table, column): + try: + self.db_list(table, columns=[column]).execute(check_error=True) + return True + except processutils.ProcessExecutionError as e: + msg = ('ovs-vsctl: %s does not contain a column whose name ' + 'matches "%s"' % (table, column)) + if msg in e.stderr: + return False + raise e + def _set_colval_args(*col_values): args = [] diff --git a/vif_plug_ovs/ovsdb/ovsdb_lib.py b/vif_plug_ovs/ovsdb/ovsdb_lib.py index 0d14958e..3ef05517 100644 --- a/vif_plug_ovs/ovsdb/ovsdb_lib.py +++ b/vif_plug_ovs/ovsdb/ovsdb_lib.py @@ -31,9 +31,7 @@ class BaseOVS(object): self.ovsdb = ovsdb_api.get_instance(self) def _ovs_supports_mtu_requests(self): - return bool(self.ovsdb.db_list( - 'Interface', columns=['mtu_request']).execute(check_error=True, - log_errors=True)) + return self.ovsdb.has_table_column('Interface', 'mtu_request') def _set_mtu_request(self, dev, mtu): self.ovsdb.db_set('Interface', dev, ('mtu_request', mtu)).execute() diff --git a/vif_plug_ovs/tests/unit/ovsdb/test_ovsdb_lib.py b/vif_plug_ovs/tests/unit/ovsdb/test_ovsdb_lib.py index 198f1ea5..7ea2a8c3 100644 --- a/vif_plug_ovs/tests/unit/ovsdb/test_ovsdb_lib.py +++ b/vif_plug_ovs/tests/unit/ovsdb/test_ovsdb_lib.py @@ -13,6 +13,7 @@ import mock import testtools +from oslo_concurrency import processutils from oslo_config import cfg from oslo_utils import uuidutils @@ -142,3 +143,27 @@ class BaseOVSTest(testtools.TestCase): self.br.ensure_ovs_bridge('bridge', constants.OVS_DATAPATH_SYSTEM) self.mock_add_br('bridge', may_exist=True, datapath_type=constants.OVS_DATAPATH_SYSTEM) + + def test__ovs_supports_mtu_requests(self): + with mock.patch.object(self.br.ovsdb, 'db_list') as mock_db_list: + self.assertTrue(self.br._ovs_supports_mtu_requests()) + mock_db_list.assert_called_once_with('Interface', + columns=['mtu_request']) + + def test__ovs_supports_mtu_requests_not_supported(self): + with mock.patch.object(self.br.ovsdb, 'db_list') as mock_db_list: + mock_db_list.side_effect = processutils.ProcessExecutionError( + stderr='ovs-vsctl: Interface does not contain a column whose ' + 'name matches "mtu_request"') + self.assertFalse(self.br._ovs_supports_mtu_requests()) + mock_db_list.assert_called_once_with('Interface', + columns=['mtu_request']) + + def test__ovs_supports_mtu_requests_other_error(self): + with mock.patch.object(self.br.ovsdb, 'db_list') as mock_db_list: + mock_db_list.side_effect = processutils.ProcessExecutionError( + stderr='other error') + self.assertRaises(processutils.ProcessExecutionError, + self.br._ovs_supports_mtu_requests) + mock_db_list.assert_called_once_with('Interface', + columns=['mtu_request'])