2
0
mirror of https://github.com/openvswitch/ovs synced 2025-08-22 09:58:01 +00:00

ovsdb: Check for ephemeral columns before writing a new schema.

Clustered databases do not support ephemeral columns, but ovsdb-server
checks for them after the conversion result is read from the storage.
It's much easier to recover if this constraint is checked before writing
to the storage instead.

It's not a big problem, because the check is always performed by the
native ovsdb clients before sending a conversion request.  But the
server, in general, should not trust clients to do the right thing.

Check in the update_schema() remains, because we shouldn't blindly
trust the storage.

Reviewed-by: Simon Horman <simon.horman@corigine.com>
Acked-by: Dumitru Ceara <dceara@redhat.com>
Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
This commit is contained in:
Ilya Maximets 2023-03-27 21:42:57 +02:00
parent 5575539f6c
commit a73b0206ba
5 changed files with 24 additions and 12 deletions

View File

@ -623,7 +623,7 @@ ovsdb_storage_store_snapshot(struct ovsdb_storage *storage,
struct ovsdb_write * OVS_WARN_UNUSED_RESULT struct ovsdb_write * OVS_WARN_UNUSED_RESULT
ovsdb_storage_write_schema_change(struct ovsdb_storage *storage, ovsdb_storage_write_schema_change(struct ovsdb_storage *storage,
const struct json *schema, const struct ovsdb_schema *schema,
const struct json *data, const struct json *data,
const struct uuid *prereq, const struct uuid *prereq,
struct uuid *resultp) struct uuid *resultp)
@ -633,13 +633,23 @@ ovsdb_storage_write_schema_change(struct ovsdb_storage *storage,
if (storage->error) { if (storage->error) {
w->error = ovsdb_error_clone(storage->error); w->error = ovsdb_error_clone(storage->error);
} else if (storage->raft) { } else if (storage->raft) {
struct json *txn_json = json_array_create_2(json_clone(schema), /* Clustered storage doesn't support ephemeral columns. */
json_clone(data)); w->error = ovsdb_schema_check_for_ephemeral_columns(schema);
w->command = raft_command_execute(storage->raft, txn_json, if (!w->error) {
prereq, &result); struct json *schema_json, *txn_json;
json_destroy(txn_json);
schema_json = ovsdb_schema_to_json(schema);
txn_json = json_array_create_2(schema_json, json_clone(data));
w->command = raft_command_execute(storage->raft, txn_json,
prereq, &result);
json_destroy(txn_json);
}
} else if (storage->log) { } else if (storage->log) {
w->error = ovsdb_storage_store_snapshot__(storage, schema, data, 0); struct json *schema_json = ovsdb_schema_to_json(schema);
w->error = ovsdb_storage_store_snapshot__(storage, schema_json,
data, 0);
json_destroy(schema_json);
} else { } else {
/* When 'error' and 'command' are both null, it indicates that the /* When 'error' and 'command' are both null, it indicates that the
* command is complete. This is fine since this unbacked storage drops * command is complete. This is fine since this unbacked storage drops

View File

@ -85,7 +85,7 @@ struct ovsdb_error *ovsdb_storage_store_snapshot(struct ovsdb_storage *storage,
struct ovsdb_write *ovsdb_storage_write_schema_change( struct ovsdb_write *ovsdb_storage_write_schema_change(
struct ovsdb_storage *, struct ovsdb_storage *,
const struct json *schema, const struct json *data, const struct ovsdb_schema *, const struct json *data,
const struct uuid *prereq, struct uuid *result) const struct uuid *prereq, struct uuid *result)
OVS_WARN_UNUSED_RESULT; OVS_WARN_UNUSED_RESULT;

View File

@ -1251,7 +1251,7 @@ ovsdb_txn_precheck_prereq(const struct ovsdb *db)
struct ovsdb_txn_progress * struct ovsdb_txn_progress *
ovsdb_txn_propose_schema_change(struct ovsdb *db, ovsdb_txn_propose_schema_change(struct ovsdb *db,
const struct json *schema, const struct ovsdb_schema *schema,
const struct json *data) const struct json *data)
{ {
struct ovsdb_txn_progress *progress = xzalloc(sizeof *progress); struct ovsdb_txn_progress *progress = xzalloc(sizeof *progress);

View File

@ -21,6 +21,7 @@
struct json; struct json;
struct ovsdb; struct ovsdb;
struct ovsdb_schema;
struct ovsdb_table; struct ovsdb_table;
struct uuid; struct uuid;
@ -41,7 +42,7 @@ struct ovsdb_error *ovsdb_txn_propose_commit_block(struct ovsdb_txn *,
void ovsdb_txn_complete(struct ovsdb_txn *); void ovsdb_txn_complete(struct ovsdb_txn *);
struct ovsdb_txn_progress *ovsdb_txn_propose_schema_change( struct ovsdb_txn_progress *ovsdb_txn_propose_schema_change(
struct ovsdb *, const struct json *schema, const struct json *data); struct ovsdb *, const struct ovsdb_schema *, const struct json *data);
bool ovsdb_txn_progress_is_complete(const struct ovsdb_txn_progress *); bool ovsdb_txn_progress_is_complete(const struct ovsdb_txn_progress *);
const struct ovsdb_error *ovsdb_txn_progress_get_error( const struct ovsdb_error *ovsdb_txn_progress_get_error(

View File

@ -274,8 +274,8 @@ ovsdb_trigger_try(struct ovsdb_trigger *t, long long int now)
if (!error) { if (!error) {
error = ovsdb_convert(t->db, new_schema, &newdb); error = ovsdb_convert(t->db, new_schema, &newdb);
} }
ovsdb_schema_destroy(new_schema);
if (error) { if (error) {
ovsdb_schema_destroy(new_schema);
trigger_convert_error(t, error); trigger_convert_error(t, error);
return false; return false;
} }
@ -286,7 +286,8 @@ ovsdb_trigger_try(struct ovsdb_trigger *t, long long int now)
/* Propose the change. */ /* Propose the change. */
t->progress = ovsdb_txn_propose_schema_change( t->progress = ovsdb_txn_propose_schema_change(
t->db, new_schema_json, txn_json); t->db, new_schema, txn_json);
ovsdb_schema_destroy(new_schema);
json_destroy(txn_json); json_destroy(txn_json);
t->reply = jsonrpc_create_reply(json_object_create(), t->reply = jsonrpc_create_reply(json_object_create(),
t->request->id); t->request->id);