From patchwork Mon Nov 28 03:56:13 2022
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
X-Patchwork-Submitter: Numan Siddique
X-Patchwork-Id: 1709518
Return-Path:
X-Original-To: incoming@patchwork.ozlabs.org
Delivered-To: patchwork-incoming@legolas.ozlabs.org
Authentication-Results: legolas.ozlabs.org;
spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org
(client-ip=140.211.166.137; helo=smtp4.osuosl.org;
envelope-from=ovs-dev-bounces@openvswitch.org; receiver=)
Received: from smtp4.osuosl.org (smtp4.osuosl.org [140.211.166.137])
(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
key-exchange X25519 server-signature ECDSA (P-384) server-digest SHA384)
(No client certificate requested)
by legolas.ozlabs.org (Postfix) with ESMTPS id 4NLBVd5KHCz23nT
for ; Mon, 28 Nov 2022 14:56:56 +1100 (AEDT)
Received: from localhost (localhost [127.0.0.1])
by smtp4.osuosl.org (Postfix) with ESMTP id 4C4F64154D;
Mon, 28 Nov 2022 03:56:52 +0000 (UTC)
DKIM-Filter: OpenDKIM Filter v2.11.0 smtp4.osuosl.org 4C4F64154D
X-Virus-Scanned: amavisd-new at osuosl.org
Received: from smtp4.osuosl.org ([127.0.0.1])
by localhost (smtp4.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)
with ESMTP id ghwXTYp1xKoM; Mon, 28 Nov 2022 03:56:50 +0000 (UTC)
Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56])
by smtp4.osuosl.org (Postfix) with ESMTPS id EEB2B414D1;
Mon, 28 Nov 2022 03:56:48 +0000 (UTC)
DKIM-Filter: OpenDKIM Filter v2.11.0 smtp4.osuosl.org EEB2B414D1
Received: from lf-lists.osuosl.org (localhost [127.0.0.1])
by lists.linuxfoundation.org (Postfix) with ESMTP id B3326C0033;
Mon, 28 Nov 2022 03:56:48 +0000 (UTC)
X-Original-To: dev@openvswitch.org
Delivered-To: ovs-dev@lists.linuxfoundation.org
Received: from smtp1.osuosl.org (smtp1.osuosl.org [IPv6:2605:bc80:3010::138])
by lists.linuxfoundation.org (Postfix) with ESMTP id EDC5BC002D
for ; Mon, 28 Nov 2022 03:56:46 +0000 (UTC)
Received: from localhost (localhost [127.0.0.1])
by smtp1.osuosl.org (Postfix) with ESMTP id CF3F4819F6
for ; Mon, 28 Nov 2022 03:56:46 +0000 (UTC)
DKIM-Filter: OpenDKIM Filter v2.11.0 smtp1.osuosl.org CF3F4819F6
X-Virus-Scanned: amavisd-new at osuosl.org
Received: from smtp1.osuosl.org ([127.0.0.1])
by localhost (smtp1.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)
with ESMTP id T5hlT2unk30C for ;
Mon, 28 Nov 2022 03:56:45 +0000 (UTC)
X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0
DKIM-Filter: OpenDKIM Filter v2.11.0 smtp1.osuosl.org B9EA8819D6
Received: from relay4-d.mail.gandi.net (relay4-d.mail.gandi.net
[217.70.183.196])
by smtp1.osuosl.org (Postfix) with ESMTPS id B9EA8819D6
for ; Mon, 28 Nov 2022 03:56:44 +0000 (UTC)
Received: (Authenticated sender: numans@ovn.org)
by mail.gandi.net (Postfix) with ESMTPSA id 21787E000D;
Mon, 28 Nov 2022 03:56:38 +0000 (UTC)
From: numans@ovn.org
To: dev@openvswitch.org
Date: Sun, 27 Nov 2022 22:56:13 -0500
Message-Id: <20221128035613.36207-1-numans@ovn.org>
X-Mailer: git-send-email 2.38.1
MIME-Version: 1.0
Cc: i.maximets@ovn.org
Subject: [ovs-dev] [PATCH v8] ovsdb-idl: Add the support to specify the uuid
for row insert.
X-BeenThere: ovs-dev@openvswitch.org
X-Mailman-Version: 2.1.15
Precedence: list
List-Id:
List-Unsubscribe: ,
List-Archive:
List-Post:
List-Help:
List-Subscribe: ,
Errors-To: ovs-dev-bounces@openvswitch.org
Sender: "dev"
From: Numan Siddique
ovsdb-server allows the OVSDB clients to specify the uuid for
the row inserts [1]. Both the C IDL client library and Python
IDL are missing this feature. This patch adds this support.
In C IDL, for each schema table, a new function is generated -
insert_persistent_uuid(txn, uuid) which can
be used the clients to persist the uuid.
ovs-vsctl and other derivatives of ctl now supports the same
in the generic 'create' command with the option "--id=".
In Python IDL, the uuid to persist can be specified in
the Transaction.insert() function.
[1] - a529e3cd1f("ovsdb-server: Allow OVSDB clients to specify the UUID for inserted rows.:)
Signed-off-by: Numan Siddique
Acked-by: Adrian Moreno
Acked-by: Han Zhou
CC: twilson@redhat.com
CC: i.maximets@ovn.org
Acked-by: Terry Wilson
---
v7 -> v8
---
* Addressed the review comments from Ilya.
- Added the same support in Python IDL.
- Reworked the test cases to make them
generic - for both C and Python.
v6 -> v7
---
* Rebased to resolve conflicts.
v5 -> v6
---
* Rebased to resolve conflicts.
v4 -> v5
---
* Addressed review comments from Ilya.
- Added NEWS item entry.
v3 -> v4
---
* Added an entry in python/TODO.rst.
v2 -> v3
----
* Addressed review comments from Han
- Added test case for --id ctl option
v1 -> v2
-----
* Addressed review comments from Adrian Moreno
* Added the support in generic 'create' command to specify the uuid in
--id option.
NEWS | 3 ++
lib/db-ctl-base.c | 38 ++++++++++++------
lib/db-ctl-base.man | 5 ++-
lib/db-ctl-base.xml | 6 ++-
lib/ovsdb-idl-provider.h | 1 +
lib/ovsdb-idl.c | 85 +++++++++++++++++++++++++++++-----------
lib/ovsdb-idl.h | 3 ++
ovsdb/ovsdb-idlc.in | 15 +++++++
python/ovs/db/idl.py | 26 ++++++++----
tests/ovs-vsctl.at | 25 ++++++++++++
tests/ovsdb-idl.at | 58 +++++++++++++++++++++++++++
tests/test-ovsdb.c | 28 +++++++++++--
tests/test-ovsdb.py | 20 +++++++++-
13 files changed, 263 insertions(+), 50 deletions(-)
diff --git a/NEWS b/NEWS
index ff77ee404..b827a64ab 100644
--- a/NEWS
+++ b/NEWS
@@ -24,6 +24,9 @@ Post-v3.0.0
If a user wishes to benefit from these fixes it is recommended to use
DPDK 21.11.2.
+ - OVSDB-IDL:
+ * Add the support to specify the persistent uuid for row insert in both
+ C and Python IDLs.
v3.0.0 - 15 Aug 2022
--------------------
diff --git a/lib/db-ctl-base.c b/lib/db-ctl-base.c
index bc85e9921..856832a04 100644
--- a/lib/db-ctl-base.c
+++ b/lib/db-ctl-base.c
@@ -1731,29 +1731,43 @@ cmd_create(struct ctl_context *ctx)
const struct ovsdb_idl_table_class *table;
const struct ovsdb_idl_row *row;
const struct uuid *uuid = NULL;
+ bool persist_uuid = false;
+ struct uuid uuid_;
int i;
ctx->error = get_table(table_name, &table);
if (ctx->error) {
return;
}
+
if (id) {
- struct ovsdb_symbol *symbol = NULL;
+ if (uuid_from_string(&uuid_, id)) {
+ uuid = &uuid_;
+ persist_uuid = true;
+ } else {
+ struct ovsdb_symbol *symbol = NULL;
- ctx->error = create_symbol(ctx->symtab, id, &symbol, NULL);
- if (ctx->error) {
- return;
- }
- if (table->is_root) {
- /* This table is in the root set, meaning that rows created in it
- * won't disappear even if they are unreferenced, so disable
- * warnings about that by pretending that there is a reference. */
- symbol->strong_ref = true;
+ ctx->error = create_symbol(ctx->symtab, id, &symbol, NULL);
+ if (ctx->error) {
+ return;
+ }
+ if (table->is_root) {
+ /* This table is in the root set, meaning that rows created in
+ * it won't disappear even if they are unreferenced, so disable
+ * warnings about that by pretending that there is a
+ * reference. */
+ symbol->strong_ref = true;
+ }
+ uuid = &symbol->uuid;
}
- uuid = &symbol->uuid;
}
- row = ovsdb_idl_txn_insert(ctx->txn, table, uuid);
+ if (persist_uuid) {
+ row = ovsdb_idl_txn_insert_persist_uuid(ctx->txn, table, uuid);
+ } else {
+ row = ovsdb_idl_txn_insert(ctx->txn, table, uuid);
+ }
+
for (i = 2; i < ctx->argc; i++) {
ctx->error = set_column(table, row, ctx->argv[i], ctx->symtab);
if (ctx->error) {
diff --git a/lib/db-ctl-base.man b/lib/db-ctl-base.man
index a529d8b4d..c8111c9ef 100644
--- a/lib/db-ctl-base.man
+++ b/lib/db-ctl-base.man
@@ -203,7 +203,7 @@ Without \fB\-\-if-exists\fR, it is an error if \fIrecord\fR does not
exist. With \fB\-\-if-exists\fR, this command does nothing if
\fIrecord\fR does not exist.
.
-.IP "[\fB\-\-id=@\fIname\fR] \fBcreate\fR \fItable column\fR[\fB:\fIkey\fR]\fB=\fIvalue\fR..."
+.IP "[\fB\-\-id=(@\fIname\fR | \fIuuid\fR] \fBcreate\fR \fItable column\fR[\fB:\fIkey\fR]\fB=\fIvalue\fR..."
Creates a new record in \fItable\fR and sets the initial values of
each \fIcolumn\fR. Columns not explicitly set will receive their
default values. Outputs the UUID of the new row.
@@ -212,6 +212,9 @@ If \fB@\fIname\fR is specified, then the UUID for the new row may be
referred to by that name elsewhere in the same \fB\*(PN\fR
invocation in contexts where a UUID is expected. Such references may
precede or follow the \fBcreate\fR command.
+.IP
+If a valid \fIuuid\fR is specified, then it is used as the UUID
+of the new row.
.
.RS
.IP "Caution (ovs-vsctl as example)"
diff --git a/lib/db-ctl-base.xml b/lib/db-ctl-base.xml
index f6efe98ea..27c999fe7 100644
--- a/lib/db-ctl-base.xml
+++ b/lib/db-ctl-base.xml
@@ -310,7 +310,7 @@
- [--id=@
name] create
table column[:
key]=
value...
+ [--id=(@
name|uuid)] create
table column[:
key]=
value...
Creates a new record in table and sets the initial values of
@@ -323,6 +323,10 @@
invocation in contexts where a UUID is expected. Such references may
precede or follow the create
command.
+
+ If a valid uuid is specified, then it is used as the
+ UUID of the new row.
+
- Caution (ovs-vsctl as example)
-
diff --git a/lib/ovsdb-idl-provider.h b/lib/ovsdb-idl-provider.h
index 8797686f9..8d2b7d6b9 100644
--- a/lib/ovsdb-idl-provider.h
+++ b/lib/ovsdb-idl-provider.h
@@ -74,6 +74,7 @@ struct ovsdb_idl_row {
struct ovs_list dst_arcs; /* Backward arcs (ovsdb_idl_arc.dst_node). */
struct ovsdb_idl_table *table; /* Containing table. */
struct ovsdb_datum *old_datum; /* Committed data (null if orphaned). */
+ bool persist_uuid; /* Persist 'uuid' during insert txn if set. */
bool parsed; /* Whether the row is parsed. */
struct ovs_list reparse_node; /* Rows that needs to be re-parsed due to
* insertion of a referenced row. */
diff --git a/lib/ovsdb-idl.c b/lib/ovsdb-idl.c
index 99b58422e..dbdfe45d8 100644
--- a/lib/ovsdb-idl.c
+++ b/lib/ovsdb-idl.c
@@ -2855,11 +2855,14 @@ substitute_uuids(struct json *json, const struct ovsdb_idl_txn *txn)
row = ovsdb_idl_txn_get_row(txn, &uuid);
if (row && !row->old_datum && row->new_datum) {
- json_destroy(json);
-
- return json_array_create_2(
- json_string_create("named-uuid"),
- json_string_create_nocopy(ovsdb_data_row_name(&uuid)));
+ if (row->persist_uuid) {
+ return json;
+ } else {
+ json_destroy(json);
+ return json_array_create_2(
+ json_string_create("named-uuid"),
+ json_string_create_nocopy(ovsdb_data_row_name(&uuid)));
+ }
}
}
@@ -3284,9 +3287,19 @@ ovsdb_idl_txn_commit(struct ovsdb_idl_txn *txn)
any_updates = true;
- json_object_put(op, "uuid-name",
- json_string_create_nocopy(
- ovsdb_data_row_name(&row->uuid)));
+ char *uuid_json;
+ struct json *value;
+ if (row->persist_uuid) {
+ uuid_json = "uuid";
+ value = json_string_create_nocopy(
+ xasprintf(UUID_FMT, UUID_ARGS(&row->uuid)));
+ } else {
+ uuid_json = "uuid-name";
+ value = json_string_create_nocopy(
+ ovsdb_data_row_name(&row->uuid));
+ }
+
+ json_object_put(op, uuid_json, value);
insert = xmalloc(sizeof *insert);
insert->dummy = row->uuid;
@@ -3770,6 +3783,31 @@ ovsdb_idl_txn_delete(const struct ovsdb_idl_row *row_)
row->new_datum = NULL;
}
+static const struct ovsdb_idl_row *
+ovsdb_idl_txn_insert__(struct ovsdb_idl_txn *txn,
+ const struct ovsdb_idl_table_class *class,
+ const struct uuid *uuid,
+ bool persist_uuid)
+{
+ struct ovsdb_idl_row *row = ovsdb_idl_row_create__(class);
+
+ ovs_assert(uuid || !persist_uuid);
+ if (uuid) {
+ ovs_assert(!ovsdb_idl_txn_get_row(txn, uuid));
+ row->uuid = *uuid;
+ } else {
+ uuid_generate(&row->uuid);
+ }
+ row->persist_uuid = persist_uuid;
+ row->table = ovsdb_idl_table_from_class(txn->idl, class);
+ row->new_datum = xmalloc(class->n_columns * sizeof *row->new_datum);
+ hmap_insert(&row->table->rows, &row->hmap_node, uuid_hash(&row->uuid));
+ hmap_insert(&txn->txn_rows, &row->txn_node, uuid_hash(&row->uuid));
+ ovsdb_idl_add_to_indexes(row);
+
+ return row;
+}
+
/* Inserts and returns a new row in the table with the specified 'class' in the
* database with open transaction 'txn'.
*
@@ -3787,22 +3825,23 @@ ovsdb_idl_txn_insert(struct ovsdb_idl_txn *txn,
const struct ovsdb_idl_table_class *class,
const struct uuid *uuid)
{
- struct ovsdb_idl_row *row = ovsdb_idl_row_create__(class);
-
- if (uuid) {
- ovs_assert(!ovsdb_idl_txn_get_row(txn, uuid));
- row->uuid = *uuid;
- } else {
- uuid_generate(&row->uuid);
- }
-
- row->table = ovsdb_idl_table_from_class(txn->idl, class);
- row->new_datum = xmalloc(class->n_columns * sizeof *row->new_datum);
- hmap_insert(&row->table->rows, &row->hmap_node, uuid_hash(&row->uuid));
- hmap_insert(&txn->txn_rows, &row->txn_node, uuid_hash(&row->uuid));
- ovsdb_idl_add_to_indexes(row);
+ return ovsdb_idl_txn_insert__(txn, class, uuid, false);
+}
- return row;
+/* Inserts and returns a new row in the table with the specified 'class' in the
+ * database with open transaction 'txn'.
+ *
+ * The new row is assigned the specified UUID (which cannot be null).
+ *
+ * Usually this function is used indirectly through one of the
+ * "insert_persist_uuid" functions generated by ovsdb-idlc. */
+const struct ovsdb_idl_row *
+ovsdb_idl_txn_insert_persist_uuid(struct ovsdb_idl_txn *txn,
+ const struct ovsdb_idl_table_class *class,
+ const struct uuid *uuid)
+{
+ ovs_assert(uuid);
+ return ovsdb_idl_txn_insert__(txn, class, uuid, true);
}
static void
diff --git a/lib/ovsdb-idl.h b/lib/ovsdb-idl.h
index fbd9f671a..9a3e19f20 100644
--- a/lib/ovsdb-idl.h
+++ b/lib/ovsdb-idl.h
@@ -375,6 +375,9 @@ void ovsdb_idl_txn_delete(const struct ovsdb_idl_row *);
const struct ovsdb_idl_row *ovsdb_idl_txn_insert(
struct ovsdb_idl_txn *, const struct ovsdb_idl_table_class *,
const struct uuid *);
+const struct ovsdb_idl_row *ovsdb_idl_txn_insert_persist_uuid(
+ struct ovsdb_idl_txn *txn, const struct ovsdb_idl_table_class *class,
+ const struct uuid *uuid);
struct ovsdb_idl *ovsdb_idl_txn_get_idl (struct ovsdb_idl_txn *);
void ovsdb_idl_get_initial_snapshot(struct ovsdb_idl *);
diff --git a/ovsdb/ovsdb-idlc.in b/ovsdb/ovsdb-idlc.in
index 5a97a8ea3..9a54f06a1 100755
--- a/ovsdb/ovsdb-idlc.in
+++ b/ovsdb/ovsdb-idlc.in
@@ -362,6 +362,8 @@ struct %(s)s *%(s)s_cursor_data(struct ovsdb_idl_cursor *);
void %(s)s_init(struct %(s)s *);
void %(s)s_delete(const struct %(s)s *);
struct %(s)s *%(s)s_insert(struct ovsdb_idl_txn *);
+struct %(s)s *%(s)s_insert_persist_uuid(
+ struct ovsdb_idl_txn *txn, const struct uuid *uuid);
/* Returns true if the tracked column referenced by 'enum %(s)s_column_id' of
* the row referenced by 'struct %(s)s *' was updated since the last change
@@ -809,6 +811,19 @@ struct %(s)s *
return %(s)s_cast(ovsdb_idl_txn_insert(txn, &%(p)stable_%(tl)s, NULL));
}
+/* Inserts and returns a new row in the table "%(t)s" in the database
+ * with open transaction 'txn'.
+ *
+ * The new row is assigned the UUID specified in the 'uuid' parameter
+ * (which cannot be null). ovsdb-server will try to assign the same
+ * UUID when 'txn' is committed. */
+struct %(s)s *
+%(s)s_insert_persist_uuid(struct ovsdb_idl_txn *txn, const struct uuid *uuid)
+{
+ return %(s)s_cast(ovsdb_idl_txn_insert_persist_uuid(
+ txn, &%(p)stable_%(tl)s, uuid));
+}
+
bool
%(s)s_is_updated(const struct %(s)s *row, enum %(s)s_column_id column)
{
diff --git a/python/ovs/db/idl.py b/python/ovs/db/idl.py
index 8e31e02d7..fe66402cf 100644
--- a/python/ovs/db/idl.py
+++ b/python/ovs/db/idl.py
@@ -1223,7 +1223,7 @@ class Row(object):
d["a"] = "b"
row.mycolumn = d
"""
- def __init__(self, idl, table, uuid, data):
+ def __init__(self, idl, table, uuid, data, persist_uuid=False):
# All of the explicit references to self.__dict__ below are required
# to set real attributes with invoking self.__getattr__().
self.__dict__["uuid"] = uuid
@@ -1278,6 +1278,10 @@ class Row(object):
# in the dictionary are all None.
self.__dict__["_prereqs"] = {}
+ # Indicates if the specified 'uuid' should be used as the row uuid
+ # or let the server generate it.
+ self.__dict__["_persist_uuid"] = persist_uuid
+
def __lt__(self, other):
if not isinstance(other, Row):
return NotImplemented
@@ -1816,7 +1820,11 @@ class Transaction(object):
op = {"table": row._table.name}
if row._data is None:
op["op"] = "insert"
- op["uuid-name"] = _uuid_name_from_uuid(row.uuid)
+ if row._persist_uuid:
+ op["uuid"] = row.uuid
+ else:
+ op["uuid-name"] = _uuid_name_from_uuid(row.uuid)
+
any_updates = True
op_index = len(operations) - 1
@@ -2056,20 +2064,22 @@ class Transaction(object):
row._mutations['_removes'].pop(column.name, None)
row._changes[column.name] = datum.copy()
- def insert(self, table, new_uuid=None):
+ def insert(self, table, new_uuid=None, persist_uuid=False):
"""Inserts and returns a new row in 'table', which must be one of the
ovs.db.schema.TableSchema objects in the Idl's 'tables' dict.
The new row is assigned a provisional UUID. If 'uuid' is None then one
is randomly generated; otherwise 'uuid' should specify a randomly
- generated uuid.UUID not otherwise in use. ovsdb-server will assign a
- different UUID when 'txn' is committed, but the IDL will replace any
- uses of the provisional UUID in the data to be to be committed by the
- UUID assigned by ovsdb-server."""
+ generated uuid.UUID not otherwise in use. If 'persist_uuid' is true
+ and 'new_uuid' is specified, IDL requests the ovsdb-server to assign
+ the same UUID, otherwise ovsdb-server will assign a different UUID when
+ 'txn' is committed and the IDL will replace any uses of the provisional
+ UUID in the data to be committed by the UUID assigned by
+ ovsdb-server."""
assert self._status == Transaction.UNCOMMITTED
if new_uuid is None:
new_uuid = uuid.uuid4()
- row = Row(self.idl, table, new_uuid, None)
+ row = Row(self.idl, table, new_uuid, None, persist_uuid=persist_uuid)
table.rows[row.uuid] = row
self._txn_rows[row.uuid] = row
return row
diff --git a/tests/ovs-vsctl.at b/tests/ovs-vsctl.at
index d6cd2c084..abf4fb9cf 100644
--- a/tests/ovs-vsctl.at
+++ b/tests/ovs-vsctl.at
@@ -1710,3 +1710,28 @@ ingress_policing_kpkts_rate: 100
])
OVS_VSCTL_CLEANUP
AT_CLEANUP
+
+AT_SETUP([ovs-vsctl create bridge with uuid])
+AT_KEYWORDS([create bridge with uuid])
+OVS_VSCTL_SETUP
+
+AT_CHECK([ovs-vsctl --no-wait --id=c5cc12f8-eaa1-43a7-8a73-bccd18df1111 create bridge \
+name=tst0 -- add open . bridges c5cc12f8-eaa1-43a7-8a73-bccd18df1111], [0],[dnl
+c5cc12f8-eaa1-43a7-8a73-bccd18df1111
+])
+
+AT_CHECK([ovs-vsctl --no-wait --id=c5cc12f8-eaa1-43a7-8a73-bccd18df1111 create bridge \
+name=tst1 -- add open . bridges c5cc12f8-eaa1-43a7-8a73-bccd18df1111], [1], [ignore], [ignore])
+
+AT_CHECK([ovs-vsctl --no-wait --bare --columns _uuid,name list bridge], [0], [dnl
+c5cc12f8-eaa1-43a7-8a73-bccd18df1111
+tst0
+])
+
+ovs-vsctl --no-wait --id=@a create bridge \
+name=tst1 -- add open . bridges @a
+
+AT_CHECK([ovs-vsctl --no-wait --bare --columns _uuid,name list bridge tst1], [0], [ignore])
+
+OVS_VSCTL_CLEANUP
+AT_CLEANUP
diff --git a/tests/ovsdb-idl.at b/tests/ovsdb-idl.at
index 8e75d00d7..c2970984b 100644
--- a/tests/ovsdb-idl.at
+++ b/tests/ovsdb-idl.at
@@ -2555,3 +2555,61 @@ OVSDB_CHECK_IDL_TRACK([track, insert and delete, refs to link2],
005: table link2: i=1 l1= uuid=<1>
006: done
]])
+
+m4_define([OVSDB_CHECK_IDL_PERS_UUID_INSERT_C],
+ [AT_SETUP([$1 - C])
+ AT_KEYWORDS([idl persistent uuid insert])
+ AT_CHECK([ovsdb_start_idltest "" "$abs_srcdir/idltest.ovsschema"])
+ AT_CHECK([test-ovsdb '-vPATTERN:console:test-ovsdb|%c|%m' -vjsonrpc -t10 idl unix:socket $2],
+ [0], [stdout], [stderr])
+ AT_CHECK([sort stdout],
+ [0], [$3])
+ AT_CHECK([grep $4 stderr], [0], [ignore])
+ OVSDB_SERVER_SHUTDOWN
+ AT_CLEANUP])
+
+m4_define([OVSDB_CHECK_IDL_PERS_UUID_INSERT_PY],
+ [AT_SETUP([$1 - Python3])
+ AT_KEYWORDS([idl persistent uuid insert])
+ AT_CHECK([ovsdb_start_idltest "" "$abs_srcdir/idltest.ovsschema"])
+ AT_CHECK([$PYTHON3 $srcdir/test-ovsdb.py -t10 idl $srcdir/idltest.ovsschema unix:socket $2],
+ [0], [stdout], [stderr])
+ AT_CHECK([sort stdout],
+ [0], [$3])
+ AT_CHECK([grep $4 stderr], [0], [ignore])
+ OVSDB_SERVER_SHUTDOWN
+ AT_CLEANUP])
+
+
+m4_define([OVSDB_CHECK_IDL_PERS_UUID_INSERT],
+ [OVSDB_CHECK_IDL_PERS_UUID_INSERT_C($@)
+ OVSDB_CHECK_IDL_PERS_UUID_INSERT_PY($@)])
+
+OVSDB_CHECK_IDL_PERS_UUID_INSERT([simple idl, persistent uuid insert],
+ [['insert_uuid c5cc12f8-eaa1-43a7-8a73-bccd18df2222 2, insert_uuid c5cc12f8-eaa1-43a7-8a73-bccd18df3333 3' \
+ 'insert_uuid c5cc12f8-eaa1-43a7-8a73-bccd18df4444 4, insert_uuid c5cc12f8-eaa1-43a7-8a73-bccd18df2222 5' \
+ 'insert_uuid c5cc12f8-eaa1-43a7-8a73-bccd18df4444 4' \
+ 'delete 2' \
+ 'insert_uuid c5cc12f8-eaa1-43a7-8a73-bccd18df2222 5'
+ ]],
+ [[000: empty
+001: commit, status=success
+002: table simple: i=2 r=0 b=false s= u=00000000-0000-0000-0000-000000000000 ia=[] ra=[] ba=[] sa=[] ua=[] uuid=c5cc12f8-eaa1-43a7-8a73-bccd18df2222
+002: table simple: i=3 r=0 b=false s= u=00000000-0000-0000-0000-000000000000 ia=[] ra=[] ba=[] sa=[] ua=[] uuid=c5cc12f8-eaa1-43a7-8a73-bccd18df3333
+003: commit, status=error
+004: table simple: i=2 r=0 b=false s= u=00000000-0000-0000-0000-000000000000 ia=[] ra=[] ba=[] sa=[] ua=[] uuid=c5cc12f8-eaa1-43a7-8a73-bccd18df2222
+004: table simple: i=3 r=0 b=false s= u=00000000-0000-0000-0000-000000000000 ia=[] ra=[] ba=[] sa=[] ua=[] uuid=c5cc12f8-eaa1-43a7-8a73-bccd18df3333
+005: commit, status=success
+006: table simple: i=2 r=0 b=false s= u=00000000-0000-0000-0000-000000000000 ia=[] ra=[] ba=[] sa=[] ua=[] uuid=c5cc12f8-eaa1-43a7-8a73-bccd18df2222
+006: table simple: i=3 r=0 b=false s= u=00000000-0000-0000-0000-000000000000 ia=[] ra=[] ba=[] sa=[] ua=[] uuid=c5cc12f8-eaa1-43a7-8a73-bccd18df3333
+006: table simple: i=4 r=0 b=false s= u=00000000-0000-0000-0000-000000000000 ia=[] ra=[] ba=[] sa=[] ua=[] uuid=c5cc12f8-eaa1-43a7-8a73-bccd18df4444
+007: commit, status=success
+008: table simple: i=3 r=0 b=false s= u=00000000-0000-0000-0000-000000000000 ia=[] ra=[] ba=[] sa=[] ua=[] uuid=c5cc12f8-eaa1-43a7-8a73-bccd18df3333
+008: table simple: i=4 r=0 b=false s= u=00000000-0000-0000-0000-000000000000 ia=[] ra=[] ba=[] sa=[] ua=[] uuid=c5cc12f8-eaa1-43a7-8a73-bccd18df4444
+009: commit, status=success
+010: table simple: i=3 r=0 b=false s= u=00000000-0000-0000-0000-000000000000 ia=[] ra=[] ba=[] sa=[] ua=[] uuid=c5cc12f8-eaa1-43a7-8a73-bccd18df3333
+010: table simple: i=4 r=0 b=false s= u=00000000-0000-0000-0000-000000000000 ia=[] ra=[] ba=[] sa=[] ua=[] uuid=c5cc12f8-eaa1-43a7-8a73-bccd18df4444
+010: table simple: i=5 r=0 b=false s= u=00000000-0000-0000-0000-000000000000 ia=[] ra=[] ba=[] sa=[] ua=[] uuid=c5cc12f8-eaa1-43a7-8a73-bccd18df2222
+011: done
+]],
+ [['This UUID would duplicate a UUID already present within the table or deleted within the same transaction']])
diff --git a/tests/test-ovsdb.c b/tests/test-ovsdb.c
index 5f7110f41..84fe23276 100644
--- a/tests/test-ovsdb.c
+++ b/tests/test-ovsdb.c
@@ -2400,7 +2400,7 @@ idltest_find_simple(struct ovsdb_idl *idl, int i)
return NULL;
}
-static void
+static bool
idl_set(struct ovsdb_idl *idl, char *commands, int step)
{
char *cmd, *save_ptr1 = NULL;
@@ -2458,6 +2458,19 @@ idl_set(struct ovsdb_idl *idl, char *commands, int step)
s = idltest_simple_insert(txn);
idltest_simple_set_i(s, atoi(arg1));
+ } else if (!strcmp(name, "insert_uuid")) {
+ struct idltest_simple *s;
+
+ if (!arg1 || !arg2) {
+ ovs_fatal(0, "\"insert\" command requires 2 arguments");
+ }
+
+ struct uuid s_uuid;
+ if (!uuid_from_string(&s_uuid, arg1)) {
+ ovs_fatal(0, "\"insert_uuid\" command requires valid uuid");
+ }
+ s = idltest_simple_insert_persist_uuid(txn, &s_uuid);
+ idltest_simple_set_i(s, atoi(arg2));
} else if (!strcmp(name, "delete")) {
const struct idltest_simple *s;
@@ -2522,7 +2535,7 @@ idl_set(struct ovsdb_idl *idl, char *commands, int step)
print_and_log("%03d: destroy", step);
ovsdb_idl_txn_destroy(txn);
ovsdb_idl_check_consistency(idl);
- return;
+ return true;
} else {
ovs_fatal(0, "unknown command %s", name);
}
@@ -2543,6 +2556,8 @@ idl_set(struct ovsdb_idl *idl, char *commands, int step)
ovsdb_idl_txn_destroy(txn);
ovsdb_idl_check_consistency(idl);
+
+ return (status != TXN_ERROR);
}
static const struct ovsdb_idl_table_class *
@@ -2777,7 +2792,14 @@ do_idl(struct ovs_cmdl_context *ctx)
update_conditions(idl, arg + strlen(cond_s));
print_and_log("%03d: change conditions", step++);
} else if (arg[0] != '[') {
- idl_set(idl, arg, step++);
+ if (!idl_set(idl, arg, step++)) {
+ /* If idl_set() returns false, then no transaction
+ * was sent to the server and most likely 'seqno'
+ * would remain the same. And the above 'Wait for update'
+ * for loop poll_block() would never return.
+ * So set seqno to 0. */
+ seqno = 0;
+ }
} else {
struct json *json = parse_json(arg);
substitute_uuids(json, symtab);
diff --git a/tests/test-ovsdb.py b/tests/test-ovsdb.py
index 402cacbe9..cca1818ea 100644
--- a/tests/test-ovsdb.py
+++ b/tests/test-ovsdb.py
@@ -429,6 +429,14 @@ def idl_set(idl, commands, step):
s = txn.insert(idl.tables["simple"])
s.i = int(args[0])
+ elif name == "insert_uuid":
+ if len(args) != 2:
+ sys.stderr.write('"set" command requires 2 argument\n')
+ sys.exit(1)
+
+ s = txn.insert(idl.tables["simple"], new_uuid=args[0],
+ persist_uuid=True)
+ s.i = int(args[1])
elif name == "delete":
if len(args) != 1:
sys.stderr.write('"delete" command requires 1 argument\n')
@@ -491,7 +499,7 @@ def idl_set(idl, commands, step):
print("%03d: destroy" % step)
sys.stdout.flush()
txn.abort()
- return
+ return True
elif name == "linktest":
l1_0 = txn.insert(idl.tables["link1"])
l1_0.i = 1
@@ -615,6 +623,8 @@ def idl_set(idl, commands, step):
sys.stdout.write("\n")
sys.stdout.flush()
+ return status != ovs.db.idl.Transaction.ERROR
+
def update_condition(idl, commands):
commands = commands[len("condition "):].split(";")
@@ -748,7 +758,13 @@ def do_idl(schema_file, remote, *commands):
sys.stdout.flush()
step += 1
elif not command.startswith("["):
- idl_set(idl, command, step)
+ if not idl_set(idl, command, step):
+ # If idl_set() returns false, then no transaction
+ # was sent to the server and most likely seqno
+ # would remain the same. And the above 'Wait for update'
+ # for loop poller.block() would never return.
+ # So set seqno to 0.
+ seqno = 0
step += 1
else:
json = ovs.json.from_string(command)