[stable-only][ovn] Fix ovsdbapp db_set command for stable branches

The lack of an if_exists on the db_set function in ovsdbapp causes the
network log object deletion to not be a asynchronous operation on the
ML2/OVN plugin. The if_exists was recently added to ovsdbapp, but since
that is an API change[0] it will not be backported to older branches,
so this patch overrides the function. This way we avoid the
possibility of getting errors when concurrently making operations
with security groups and network log objects.

Closes-bug: #2019887

[0] https://review.opendev.org/c/openstack/ovsdbapp/+/880687

Change-Id: I628591da75c1cc367076f5a3051ca3c1e131d216
(cherry picked from commit 551ba73aa4)
This commit is contained in:
Elvira García 2023-05-15 01:24:27 +02:00 committed by Elvira García Ruiz
parent 08a6168a07
commit 1529c0a297
2 changed files with 42 additions and 0 deletions

View File

@ -11,6 +11,8 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import collections
from collections import abc
from oslo_utils import timeutils
from ovsdbapp.backend.ovs_idl import command
@ -922,3 +924,35 @@ class UnsetLSwitchPortToVirtualTypeCommand(command.BaseCommand):
virtual_parents)
setattr(lsp, 'options', options)
class DbSetCommand(command.BaseCommand):
def __init__(self, api, table, record, *col_values, if_exists=False,
**columns):
super().__init__(api)
self.table = table
self.record = record
self.col_values = col_values or columns.items()
self.if_exists = if_exists
def run_idl(self, txn):
try:
record = self.api.lookup(self.table, self.record)
except idlutils.RowNotFound:
if self.if_exists:
return
raise
for col, val in self.col_values:
if isinstance(val, abc.Mapping):
if isinstance(val, collections.OrderedDict):
val = dict(val)
existing = getattr(record, col, {})
existing.update(val)
val = existing
# Since we are updating certain keys and leaving existing keys
# but rewriting the whole external_ids column, we must verify()
record.verify(col)
# For non-map columns, we unconditionally overwrite the values that
# exist, so prior state doesn't matter and we don't need verify()
self.set_column(record, col, val)

View File

@ -828,6 +828,10 @@ class OvsdbNbOvnIdl(nb_impl_idl.OvnNbApiIdlImpl, Backend):
def update_lb_external_ids(self, lb_name, values, if_exists=True):
return cmd.UpdateLbExternalIds(self, lb_name, values, if_exists)
def db_set(self, table, record, *col_values, if_exists=True, **columns):
return cmd.DbSetCommand(self, table, record, *col_values,
if_exists=if_exists, **columns)
class OvsdbSbOvnIdl(sb_impl_idl.OvnSbApiIdlImpl, Backend):
def __init__(self, connection):
@ -948,3 +952,7 @@ class OvsdbSbOvnIdl(sb_impl_idl.OvnSbApiIdlImpl, Backend):
# and just start using chassis objects so db_find_rows could be used
rows = self.db_list_rows('Port_Binding').execute(check_error=True)
return [r for r in rows if r.chassis and r.chassis[0].name == chassis]
def db_set(self, table, record, *col_values, if_exists=True, **columns):
return cmd.DbSetCommand(self, table, record, *col_values,
if_exists=if_exists, **columns)