mirror of
https://github.com/openvswitch/ovs
synced 2025-08-22 01:51:26 +00:00
ovsdb-tool: Convert clustered db to standalone db.
Add support in ovsdb-tool for migrating clustered dbs to standalone dbs. E.g. usage to migrate nb/sb db to standalone db from raft: ovsdb-tool cluster-to-standalone ovnnb_db.db ovnnb_db_cluster.db Acked-by: Han Zhou <hzhou8@ebay.com> Signed-off-by: Aliasgar Ginwala <aginwala@ebay.com> Signed-off-by: Ben Pfaff <blp@ovn.org>
This commit is contained in:
parent
45bd8c5632
commit
00de46f9ee
@ -514,6 +514,9 @@ standalone database from the contents of a running clustered database.
|
||||
When the cluster is down and cannot be revived, ``ovsdb-client backup`` will
|
||||
not work.
|
||||
|
||||
Use ``ovsdb-tool cluster-to-standalone`` to convert clustered database to
|
||||
standalone database when the cluster is down and cannot be revived.
|
||||
|
||||
Upgrading or Downgrading a Database
|
||||
-----------------------------------
|
||||
|
||||
|
3
NEWS
3
NEWS
@ -52,6 +52,9 @@ v2.12.0 - 03 Sep 2019
|
||||
quickly after a brief disconnection, saving bandwidth and CPU time.
|
||||
See section 4.1.15 of ovsdb-server(7) for details of related OVSDB
|
||||
protocol extension.
|
||||
* Support to convert from cluster database to standalone database is now
|
||||
available when clustered is down and cannot be revived using ovsdb-tool
|
||||
. Check "Database Migration Commands" in ovsdb-tool man section.
|
||||
- OVN:
|
||||
* IPAM/MACAM:
|
||||
- select IPAM mac_prefix in a random manner if not provided by the user
|
||||
|
@ -146,6 +146,14 @@ avoid this possibility, specify \fB\-\-cid=\fIuuid\fR, where
|
||||
\fIuuid\fR is the cluster ID of the cluster to join, as printed by
|
||||
\fBovsdb\-tool get\-cid\fR.
|
||||
.
|
||||
.SS "Database Migration Commands"
|
||||
This commands will convert cluster database to standalone database.
|
||||
.
|
||||
.IP "\fBcluster\-to\-standalone\fI db clusterdb"
|
||||
Use this command to convert to standalone database from clustered database
|
||||
when the cluster is down and cannot be revived. It creates new standalone
|
||||
\fIdb\fR file from the given cluster \fIdb\fR file.
|
||||
.
|
||||
.SS "Version Management Commands"
|
||||
.so ovsdb/ovsdb-schemas.man
|
||||
.PP
|
||||
|
@ -173,6 +173,9 @@ usage(void)
|
||||
" compare-versions A OP B compare OVSDB schema version numbers\n"
|
||||
" query [DB] TRNS execute read-only transaction on DB\n"
|
||||
" transact [DB] TRNS execute read/write transaction on DB\n"
|
||||
" cluster-to-standalone DB DB Convert clustered DB to\n"
|
||||
" standalone DB when cluster is down and cannot be\n"
|
||||
" revived\n"
|
||||
" [-m]... show-log [DB] print DB's log entries\n"
|
||||
"The default DB is %s.\n"
|
||||
"The default SCHEMA is %s.\n",
|
||||
@ -942,6 +945,55 @@ print_raft_record(const struct raft_record *r,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
raft_header_to_standalone_log(const struct raft_header *h,
|
||||
struct ovsdb_log *db_log_data)
|
||||
{
|
||||
if (h->snap_index) {
|
||||
if (!h->snap.data || json_array(h->snap.data)->n != 2) {
|
||||
ovs_fatal(0, "Incorrect raft header data array length");
|
||||
}
|
||||
|
||||
struct json *schema_json = json_array(h->snap.data)->elems[0];
|
||||
if (schema_json->type != JSON_NULL) {
|
||||
struct ovsdb_schema *schema;
|
||||
check_ovsdb_error(ovsdb_schema_from_json(schema_json, &schema));
|
||||
ovsdb_schema_destroy(schema);
|
||||
check_ovsdb_error(ovsdb_log_write_and_free(db_log_data,
|
||||
schema_json));
|
||||
}
|
||||
|
||||
struct json *data_json = json_array(h->snap.data)->elems[1];
|
||||
if (!data_json || data_json->type != JSON_OBJECT) {
|
||||
ovs_fatal(0, "Invalid raft header data");
|
||||
}
|
||||
if (data_json->type != JSON_NULL) {
|
||||
check_ovsdb_error(ovsdb_log_write_and_free(db_log_data,
|
||||
data_json));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
raft_record_to_standalone_log(const struct raft_record *r,
|
||||
struct ovsdb_log *db_log_data)
|
||||
{
|
||||
if (r->type == RAFT_REC_ENTRY) {
|
||||
if (!r->entry.data) {
|
||||
return;
|
||||
}
|
||||
if (json_array(r->entry.data)->n != 2) {
|
||||
ovs_fatal(0, "Incorrect raft record array length");
|
||||
}
|
||||
|
||||
struct json *data_json = json_array(r->entry.data)->elems[1];
|
||||
if (data_json->type != JSON_NULL) {
|
||||
check_ovsdb_error(ovsdb_log_write_and_free(db_log_data,
|
||||
data_json));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
do_show_log_cluster(struct ovsdb_log *log)
|
||||
{
|
||||
@ -1511,6 +1563,51 @@ do_compare_versions(struct ovs_cmdl_context *ctx)
|
||||
exit(result ? 0 : 2);
|
||||
}
|
||||
|
||||
static void
|
||||
do_convert_to_standalone(struct ovsdb_log *log, struct ovsdb_log *db_log_data)
|
||||
{
|
||||
for (unsigned int i = 0; ; i++) {
|
||||
struct json *json;
|
||||
check_ovsdb_error(ovsdb_log_read(log, &json));
|
||||
if (!json) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == 0) {
|
||||
struct raft_header h;
|
||||
check_ovsdb_error(raft_header_from_json(&h, json));
|
||||
raft_header_to_standalone_log(&h, db_log_data);
|
||||
raft_header_uninit(&h);
|
||||
} else {
|
||||
struct raft_record r;
|
||||
check_ovsdb_error(raft_record_from_json(&r, json));
|
||||
raft_record_to_standalone_log(&r, db_log_data);
|
||||
raft_record_uninit(&r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
do_cluster_standalone(struct ovs_cmdl_context *ctx)
|
||||
{
|
||||
const char *db_file_name = ctx->argv[1];
|
||||
const char *cluster_db_file_name = ctx->argv[2];
|
||||
struct ovsdb_log *log;
|
||||
struct ovsdb_log *db_log_data;
|
||||
|
||||
check_ovsdb_error(ovsdb_log_open(cluster_db_file_name,
|
||||
OVSDB_MAGIC"|"RAFT_MAGIC,
|
||||
OVSDB_LOG_READ_ONLY, -1, &log));
|
||||
check_ovsdb_error(ovsdb_log_open(db_file_name, OVSDB_MAGIC,
|
||||
OVSDB_LOG_CREATE_EXCL, -1, &db_log_data));
|
||||
if (strcmp(ovsdb_log_get_magic(log), RAFT_MAGIC) != 0) {
|
||||
ovs_fatal(0, "Database is not clustered db.\n");
|
||||
}
|
||||
do_convert_to_standalone(log, db_log_data);
|
||||
check_ovsdb_error(ovsdb_log_commit_block(db_log_data));
|
||||
ovsdb_log_close(db_log_data);
|
||||
ovsdb_log_close(log);
|
||||
}
|
||||
|
||||
static void
|
||||
do_help(struct ovs_cmdl_context *ctx OVS_UNUSED)
|
||||
@ -1550,7 +1647,9 @@ static const struct ovs_cmdl_command all_commands[] = {
|
||||
{ "compare-versions", "a op b", 3, 3, do_compare_versions, OVS_RO },
|
||||
{ "help", NULL, 0, INT_MAX, do_help, OVS_RO },
|
||||
{ "list-commands", NULL, 0, INT_MAX, do_list_commands, OVS_RO },
|
||||
{ NULL, NULL, 0, 0, NULL, OVS_RO },
|
||||
{ "cluster-to-standalone", "db clusterdb", 2, 2,
|
||||
do_cluster_standalone, OVS_RW },
|
||||
{ NULL, NULL, 2, 2, NULL, OVS_RO },
|
||||
};
|
||||
|
||||
static const struct ovs_cmdl_command *get_all_commands(void)
|
||||
|
@ -459,3 +459,41 @@ OVS_APP_EXIT_AND_WAIT([ovsdb-server])
|
||||
# Make sure that the clustered data matched the standalone data.
|
||||
AT_CHECK([cat dump2], [0], [expout])
|
||||
AT_CLEANUP
|
||||
|
||||
AT_SETUP([ovsdb-tool convert-to-standalone])
|
||||
AT_KEYWORDS([ovsdb file positive])
|
||||
ordinal_schema > schema
|
||||
AT_CHECK([ovsdb-tool create-cluster db schema unix:s1.raft], [0], [stdout], [ignore])
|
||||
AT_CHECK([ovsdb-server --detach --no-chdir --pidfile --remote=punix:socket --log-file db >/dev/null 2>&1])
|
||||
for txn in m4_foreach([txn], [[[["ordinals",
|
||||
{"op": "insert",
|
||||
"table": "ordinals",
|
||||
"row": {"number": 0, "name": "zero"}},
|
||||
{"op": "insert",
|
||||
"table": "ordinals",
|
||||
"row": {"number": 1, "name": "one"}},
|
||||
{"op": "insert",
|
||||
"table": "ordinals",
|
||||
"row": {"number": 2, "name": "two"}}]]]], ['txn' ]); do
|
||||
AT_CHECK([ovsdb-client transact unix:socket "$txn"], [0], [ignore], [ignore])
|
||||
done
|
||||
AT_CHECK([ovsdb-client transact unix:socket '[["ordinals"]]'], [0],
|
||||
[ignore], [ignore])
|
||||
AT_CHECK([ovsdb-client dump unix:socket > clusterdump])
|
||||
AT_CHECK([ovs-appctl -t ovsdb-server -e exit], [0], [ignore], [ignore])
|
||||
|
||||
# Convert to standalone database from clustered database.
|
||||
AT_CHECK(ovsdb-tool cluster-to-standalone db1 db)
|
||||
|
||||
# Check its standalone db
|
||||
AT_CHECK([ovsdb-tool db-is-standalone db1])
|
||||
|
||||
# Dump the standalone db data.
|
||||
AT_CHECK([ovsdb-server -vconsole:off -vfile -vvlog:off --detach --no-chdir --pidfile --log-file --remote=punix:db.sock db1])
|
||||
AT_CHECK([ovsdb_client_wait ordinals connected])
|
||||
AT_CHECK([ovsdb-client dump > standalonedump])
|
||||
OVS_APP_EXIT_AND_WAIT([ovsdb-server])
|
||||
|
||||
# Make sure both standalone and cluster db data matches.
|
||||
AT_CHECK([diff standalonedump clusterdump])
|
||||
AT_CLEANUP
|
||||
|
Loading…
x
Reference in New Issue
Block a user