summaryrefslogtreecommitdiff
path: root/ovsdb
diff options
context:
space:
mode:
authorIlya Maximets <i.maximets@ovn.org>2023-03-27 21:42:56 +0200
committerIlya Maximets <i.maximets@ovn.org>2023-04-24 22:34:49 +0200
commit5575539f6c98cbec91f955805ae079899396f521 (patch)
tree242b4ab7e6f17b9a1859381e07305ae92663b0b8 /ovsdb
parentd70688a7291edb432fd66b9230a92842fcfd3607 (diff)
downloadopenvswitch-5575539f6c98cbec91f955805ae079899396f521.tar.gz
ovsdb-tool: Fix cluster-to-standalone for DB conversion records.
If database conversion happens, both schema and the new data are present in the database record. However, the schema is just silently ignored by ovsdb-tool cluster-to-standalone. This creates data inconsistency if the new data contains new columns, for example, so the resulting database file will not be readable, or data will be lost. Fix that by re-setting the database whenever a conversion record is found and actually writing a new schema that will match the actual data. The database file will not be that similar to the original, but there is no way to represent conversion in a standalone database file format otherwise. Fixes: 00de46f9ee42 ("ovsdb-tool: Convert clustered db to standalone db.") Reviewed-by: Simon Horman <simon.horman@corigine.com> Acked-by: Dumitru Ceara <dceara@redhat.com> Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
Diffstat (limited to 'ovsdb')
-rw-r--r--ovsdb/log.c17
-rw-r--r--ovsdb/log.h3
-rw-r--r--ovsdb/ovsdb-tool.c18
3 files changed, 38 insertions, 0 deletions
diff --git a/ovsdb/log.c b/ovsdb/log.c
index e42f00246..fff7c6ba1 100644
--- a/ovsdb/log.c
+++ b/ovsdb/log.c
@@ -552,6 +552,23 @@ ovsdb_log_truncate(struct ovsdb_log *file)
return error;
}
+/* Removes all the data from the log by moving current offset to zero and
+ * truncating the file to zero bytes. After this operation the file is empty
+ * and in a write state. */
+struct ovsdb_error * OVS_WARN_UNUSED_RESULT
+ovsdb_log_reset(struct ovsdb_log *file)
+{
+ ovsdb_error_destroy(file->error);
+ file->offset = file->prev_offset = 0;
+ file->error = ovsdb_log_truncate(file);
+ if (file->error) {
+ file->state = OVSDB_LOG_WRITE_ERROR;
+ return ovsdb_error_clone(file->error);
+ }
+ file->state = OVSDB_LOG_WRITE;
+ return NULL;
+}
+
/* Composes a log record for 'json' by filling 'header' with a header line and
* 'data' with a data line (each ending with a new-line). To write the record
* to a file, write 'header' followed by 'data'.
diff --git a/ovsdb/log.h b/ovsdb/log.h
index 90714ea13..63e5681a0 100644
--- a/ovsdb/log.h
+++ b/ovsdb/log.h
@@ -66,6 +66,9 @@ struct ovsdb_error *ovsdb_log_read(struct ovsdb_log *, struct json **)
OVS_WARN_UNUSED_RESULT;
void ovsdb_log_unread(struct ovsdb_log *);
+struct ovsdb_error *ovsdb_log_reset(struct ovsdb_log *)
+ OVS_WARN_UNUSED_RESULT;
+
void ovsdb_log_compose_record(const struct json *, const char *magic,
struct ds *header, struct ds *data);
diff --git a/ovsdb/ovsdb-tool.c b/ovsdb/ovsdb-tool.c
index 60f353197..ea2b75b46 100644
--- a/ovsdb/ovsdb-tool.c
+++ b/ovsdb/ovsdb-tool.c
@@ -1018,7 +1018,25 @@ raft_record_to_standalone_log(const struct raft_record *r,
if (pa->n != 2) {
ovs_fatal(0, "Incorrect raft record array length");
}
+
+ struct json *schema_json = pa->elems[0];
struct json *data_json = pa->elems[1];
+
+ if (schema_json->type != JSON_NULL) {
+ /* This is a database conversion record. Reset the log and
+ * write the new schema. Data JSON should also be part of
+ * the conversion. */
+ struct ovsdb_schema *schema;
+
+ if (data_json->type == JSON_NULL) {
+ ovs_fatal(
+ 0, "Invalid database conversion in the log: no data");
+ }
+ check_ovsdb_error(ovsdb_schema_from_json(schema_json, &schema));
+ ovsdb_schema_destroy(schema);
+ check_ovsdb_error(ovsdb_log_reset(db_log_data));
+ check_ovsdb_error(ovsdb_log_write(db_log_data, schema_json));
+ }
if (data_json->type != JSON_NULL) {
check_ovsdb_error(ovsdb_log_write(db_log_data, data_json));
}