Skip to content

Commit

Permalink
ovsdb-server: Allow OVSDB clients to specify the UUID for inserted rows.
Browse files Browse the repository at this point in the history
Acked-by: Han Zhou <hzhou@ovn.org>
Requested-by: Leonid Ryzhyk <lryzhyk@vmware.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
  • Loading branch information
blp committed Jan 17, 2020
1 parent b9254f7 commit a529e3c
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 8 deletions.
9 changes: 9 additions & 0 deletions Documentation/ref/ovsdb-server.7.rst
Expand Up @@ -546,6 +546,15 @@ condition can be either a 3-element JSON array as described in the RFC or a
boolean value. In case of an empty array an implicit true boolean value will be
considered.

5.2.1 Insert
------------

As an extension, Open vSwitch 2.13 and later allow an optional ``uuid`` member
to specify the UUID for the new row. The specified UUID must be unique within
the table when it is inserted and not the UUID of a row previously deleted
within the transaction. If the UUID violates these rules, then the operation
fails with a ``duplicate uuid`` error.

5.2.6 Wait, 5.2.7 Commit, 5.2.9 Comment
---------------------------------------

Expand Down
1 change: 1 addition & 0 deletions NEWS
Expand Up @@ -36,6 +36,7 @@ Post-v2.12.0
command - ovsdb-server/set-active-ovsdb-server-probe-interval.
* Add hardware offload support for output, drop, set of MAC, IPv4 and
TCP/UDP ports actions (experimental).
* ovsdb-server: New OVSDB extension to allow clients to specify row UUIDs.
- 'ovs-appctl dpctl/dump-flows' can now show offloaded=partial for
partially offloaded flows, dp:dpdk for fully offloaded by dpdk, and
type filter supports new filters: "dpdk" and "partially-offloaded".
Expand Down
26 changes: 22 additions & 4 deletions ovsdb/execution.c
@@ -1,4 +1,4 @@
/* Copyright (c) 2009, 2010, 2011, 2012, 2013, 2017 Nicira, Inc.
/* Copyright (c) 2009, 2010, 2011, 2012, 2013, 2017, 2019 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -329,18 +329,32 @@ ovsdb_execute_insert(struct ovsdb_execution *x, struct ovsdb_parser *parser,
{
struct ovsdb_table *table;
struct ovsdb_row *row = NULL;
const struct json *uuid_name, *row_json;
const struct json *uuid_json, *uuid_name, *row_json;
struct ovsdb_error *error;
struct uuid row_uuid;

table = parse_table(x, parser, "table");
uuid_json = ovsdb_parser_member(parser, "uuid", OP_STRING | OP_OPTIONAL);
uuid_name = ovsdb_parser_member(parser, "uuid-name", OP_ID | OP_OPTIONAL);
row_json = ovsdb_parser_member(parser, "row", OP_OBJECT);
error = ovsdb_parser_get_error(parser);
if (error) {
return error;
}

if (uuid_json) {
if (!uuid_from_string(&row_uuid, json_string(uuid_json))) {
return ovsdb_syntax_error(uuid_json, NULL, "bad uuid");
}

if (!ovsdb_txn_may_create_row(table, &row_uuid)) {
return ovsdb_syntax_error(uuid_json, "duplicate uuid",
"This UUID would duplicate a UUID "
"already present within the table or "
"deleted within the same transaction.");
}
}

if (uuid_name) {
struct ovsdb_symbol *symbol;

Expand All @@ -350,9 +364,13 @@ ovsdb_execute_insert(struct ovsdb_execution *x, struct ovsdb_parser *parser,
"This \"uuid-name\" appeared on an "
"earlier \"insert\" operation.");
}
row_uuid = symbol->uuid;
if (uuid_json) {
symbol->uuid = row_uuid;
} else {
row_uuid = symbol->uuid;
}
symbol->created = true;
} else {
} else if (!uuid_json) {
uuid_generate(&row_uuid);
}

Expand Down
22 changes: 21 additions & 1 deletion ovsdb/transaction.c
@@ -1,4 +1,4 @@
/* Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2017 Nicira, Inc.
/* Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2017, 2019 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -1287,6 +1287,26 @@ ovsdb_txn_row_delete(struct ovsdb_txn *txn, const struct ovsdb_row *row_)
}
}

/* Returns true if 'row_uuid' may be used as the UUID for a newly created row
* in 'table' (that is, that it is unique within 'table'), false otherwise. */
bool
ovsdb_txn_may_create_row(const struct ovsdb_table *table,
const struct uuid *row_uuid)
{
/* If a row 'row_uuid' currently exists, disallow creating a duplicate. */
if (ovsdb_table_get_row(table, row_uuid)) {
return false;
}

/* If a row 'row_uuid' previously existed in this transaction, disallow
* creating a new row with the same UUID. */
if (find_txn_row(table, row_uuid)) {
return false;
}

return true;
}

void
ovsdb_txn_add_comment(struct ovsdb_txn *txn, const char *s)
{
Expand Down
5 changes: 4 additions & 1 deletion ovsdb/transaction.h
@@ -1,4 +1,4 @@
/* Copyright (c) 2009, 2010, 2017 Nicira, Inc.
/* Copyright (c) 2009, 2010, 2017, 2019 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -53,6 +53,9 @@ struct ovsdb_row *ovsdb_txn_row_modify(struct ovsdb_txn *,
void ovsdb_txn_row_insert(struct ovsdb_txn *, struct ovsdb_row *);
void ovsdb_txn_row_delete(struct ovsdb_txn *, const struct ovsdb_row *);

bool ovsdb_txn_may_create_row(const struct ovsdb_table *,
const struct uuid *row_uuid);

typedef bool ovsdb_txn_row_cb_func(const struct ovsdb_row *old,
const struct ovsdb_row *new,
const unsigned long int *changed,
Expand Down
24 changes: 24 additions & 0 deletions tests/ovsdb-execution.at
Expand Up @@ -249,6 +249,30 @@ OVSDB_CHECK_EXECUTION([insert row, query table],
[{"rows":[{"_uuid":["uuid","<0>"],"_version":["uuid","<1>"],"name":"zero","number":0}]}]
]])

OVSDB_CHECK_EXECUTION([insert row with uuid, query table],
[ordinal_schema],
dnl Insert initial row.
[[[["ordinals",
{"op": "insert",
"uuid": "ffffffff-971b-4cba-bf42-520515973b7e",
"table": "ordinals",
"row": {"number": 0, "name": "zero"}}]]],
dnl Query row back.
[[["ordinals",
{"op": "select",
"table": "ordinals",
"where": []}]]],
dnl Attempt to insert second row with same UUID (fails).
[[["ordinals",
{"op": "insert",
"uuid": "ffffffff-971b-4cba-bf42-520515973b7e",
"table": "ordinals",
"row": {"number": 0, "name": "zero"}}]]]],
[[[{"uuid":["uuid","ffffffff-971b-4cba-bf42-520515973b7e"]}]
[{"rows":[{"_uuid":["uuid","ffffffff-971b-4cba-bf42-520515973b7e"],"_version":["uuid","<0>"],"name":"zero","number":0}]}]
[{"details":"This UUID would duplicate a UUID already present within the table or deleted within the same transaction.","error":"duplicate uuid","syntax":"\"ffffffff-971b-4cba-bf42-520515973b7e\""}]
]])

OVSDB_CHECK_EXECUTION([insert rows, query by value],
[ordinal_schema],
[[[["ordinals",
Expand Down
18 changes: 16 additions & 2 deletions tests/uuidfilt.py
Expand Up @@ -18,7 +18,8 @@ def sort_set(match):


u = '[0-9a-fA-F]'
uuid_re = re.compile(r'%s{8}-%s{4}-%s{4}-%s{4}-%s{12}' % ((u,) * 5))
uuid_re = re.compile(r'%s{8}(?<!ffffffff)-%s{4}-%s{4}-%s{4}-%s{12}'
% ((u,) * 5))
set_re = re.compile(r'(\["set",\[(,?\["uuid","<\d+>"\])+\]\])')


Expand All @@ -43,7 +44,20 @@ def lf(match):


if __name__ == '__main__':
if len(sys.argv) > 1:
if '--help' in sys.argv:
print("""\
uuidfilt, for filtering UUIDs into numbered markers
usage: %s [INPUT..] > OUTPUT
or %s < INPUT > OUTPUT
Reads each INPUT, locates UUIDs in the standard textual form, and
converts them into numbered markers <0>, <1>, ..., <n>, where <0>
stands in for each instance of the first unique UUID found, <1> for
each instance of the second, and so on.
UUIDs that begin with ffffffff are not converted to markers.
""")
elif len(sys.argv) > 1:
for src in sys.argv[1:]:
filter_uuids(open(src), sys.stdout)
else:
Expand Down

0 comments on commit a529e3c

Please sign in to comment.