summaryrefslogtreecommitdiff
path: root/ovsdb
diff options
context:
space:
mode:
authorAndy Zhou <azhou@ovn.org>2017-02-06 14:00:22 -0800
committerAndy Zhou <azhou@ovn.org>2017-02-13 12:20:21 -0800
commit05ac209a5d3a5e85896f58d16b244e6b2a4cf2d0 (patch)
tree43e034cba1613025b409865894666e32cb59f00f /ovsdb
parent64fada26016c0d7ad8376d11c2cf653616d0db21 (diff)
downloadopenvswitch-05ac209a5d3a5e85896f58d16b244e6b2a4cf2d0.tar.gz
ovsdb: Prevent OVSDB server from replicating itself.
Replication OVSDB server from itself is usually caused by configuration errors. Such configuration errors can lead to OVSDB server data loss. See "reported-at" for more details. This patch adds logics that prevent OVSDB server from replicating itself. Reported-by: Guishuai Li <ligs@dtdream.com> Reported-at: https://mail.openvswitch.org/pipermail/ovs-dev/2017-January/326963.html Suggested-by: Ben Pfaff <blp@ovn.org> Signed-off-by: Andy Zhou <azhou@ovn.org> Acked-by: Ben Pfaff <blp@ovn.org>
Diffstat (limited to 'ovsdb')
-rw-r--r--ovsdb/jsonrpc-server.c7
-rw-r--r--ovsdb/ovsdb-server.1.in30
-rw-r--r--ovsdb/ovsdb-server.c24
-rw-r--r--ovsdb/replication.c59
-rw-r--r--ovsdb/replication.h3
5 files changed, 106 insertions, 17 deletions
diff --git a/ovsdb/jsonrpc-server.c b/ovsdb/jsonrpc-server.c
index 5353ba743..1ba6bb390 100644
--- a/ovsdb/jsonrpc-server.c
+++ b/ovsdb/jsonrpc-server.c
@@ -944,6 +944,13 @@ ovsdb_jsonrpc_session_got_request(struct ovsdb_jsonrpc_session *s,
}
reply = jsonrpc_create_reply(json_array_create(dbs, n_dbs),
request->id);
+ } else if (!strcmp(request->method, "get_server_id")) {
+ const struct uuid *uuid = &s->up.server->uuid;
+ struct json *result;
+
+ result = json_string_create_nocopy(xasprintf(UUID_FMT,
+ UUID_ARGS(uuid)));
+ reply = jsonrpc_create_reply(result, request->id);
} else if (!strcmp(request->method, "lock")) {
reply = ovsdb_jsonrpc_session_lock(s, request, OVSDB_LOCK_WAIT);
} else if (!strcmp(request->method, "steal")) {
diff --git a/ovsdb/ovsdb-server.1.in b/ovsdb/ovsdb-server.1.in
index a55af399a..3c798dd17 100644
--- a/ovsdb/ovsdb-server.1.in
+++ b/ovsdb/ovsdb-server.1.in
@@ -577,6 +577,36 @@ Initial views of rows are not presented in update2 notifications,
but in the response object to the monitor_cond request. The formatting
of the <table-updates2> object, however, is the same in either case.
.
+.IP "4.1.15. Get Server ID"
+A new RPC method added in Open vSwitch version 2.7. The request contains
+the following members:
+.
+.PP
+.RS
+.nf
+"method": "get_server_id"
+"params": null
+"id": <nonnull-json-value>
+.fi
+.RE
+.
+.IP
+The response object contains the following members:
+.
+.PP
+.RS
+.nf
+"result": "<server_id>"
+"error": null
+"id": same "id" as request
+.fi
+.RE
+.
+.IP
+<server_id> is JSON string that contains a UUID that uniquely identifies
+the running OVSDB server process. A fresh UUID is generated when the
+process restarts.
+.
.IP "5.1. Notation"
For <condition>, RFC 7047 only allows the use of \fB!=\fR, \fB==\fR,
\fBincludes\fR, and \fBexcludes\fR operators with set types. Open
diff --git a/ovsdb/ovsdb-server.c b/ovsdb/ovsdb-server.c
index 9b669c90a..52af4d36a 100644
--- a/ovsdb/ovsdb-server.c
+++ b/ovsdb/ovsdb-server.c
@@ -139,9 +139,9 @@ static void load_config(FILE *config_file, struct sset *remotes,
static void
ovsdb_replication_init(const char *sync_from, const char *exclude,
- struct shash *all_dbs)
+ struct shash *all_dbs, const struct uuid *server_uuid)
{
- replication_init(sync_from, exclude);
+ replication_init(sync_from, exclude, server_uuid);
struct shash_node *node;
SHASH_FOR_EACH (node, all_dbs) {
struct db *db = node->data;
@@ -425,7 +425,9 @@ main(int argc, char *argv[])
ovsdb_server_disable_monitor_cond, jsonrpc);
if (is_backup) {
- ovsdb_replication_init(sync_from, sync_exclude, &all_dbs);
+ const struct uuid *server_uuid;
+ server_uuid = ovsdb_jsonrpc_server_get_uuid(jsonrpc);
+ ovsdb_replication_init(sync_from, sync_exclude, &all_dbs, server_uuid);
}
main_loop(jsonrpc, &all_dbs, unixctl, &remotes, run_process, &exiting,
@@ -1185,8 +1187,10 @@ ovsdb_server_connect_active_ovsdb_server(struct unixctl_conn *conn,
if ( !*config->sync_from) {
msg = "Unable to connect: active server is not specified.\n";
} else {
+ const struct uuid *server_uuid;
+ server_uuid = ovsdb_jsonrpc_server_get_uuid(config->jsonrpc);
ovsdb_replication_init(*config->sync_from, *config->sync_exclude,
- config->all_dbs);
+ config->all_dbs, server_uuid);
if (!*config->is_backup) {
*config->is_backup = true;
save_config(config);
@@ -1223,8 +1227,10 @@ ovsdb_server_set_sync_exclude_tables(struct unixctl_conn *conn,
*config->sync_exclude = xstrdup(argv[1]);
save_config(config);
if (*config->is_backup) {
+ const struct uuid *server_uuid;
+ server_uuid = ovsdb_jsonrpc_server_get_uuid(config->jsonrpc);
ovsdb_replication_init(*config->sync_from, *config->sync_exclude,
- config->all_dbs);
+ config->all_dbs, server_uuid);
}
err = set_blacklist_tables(argv[1], false);
}
@@ -1430,8 +1436,10 @@ ovsdb_server_add_database(struct unixctl_conn *conn, int argc OVS_UNUSED,
if (!error) {
save_config(config);
if (*config->is_backup) {
+ const struct uuid *server_uuid;
+ server_uuid = ovsdb_jsonrpc_server_get_uuid(config->jsonrpc);
ovsdb_replication_init(*config->sync_from, *config->sync_exclude,
- config->all_dbs);
+ config->all_dbs, server_uuid);
}
unixctl_command_reply(conn, NULL);
} else {
@@ -1464,8 +1472,10 @@ ovsdb_server_remove_database(struct unixctl_conn *conn, int argc OVS_UNUSED,
save_config(config);
if (*config->is_backup) {
+ const struct uuid *server_uuid;
+ server_uuid = ovsdb_jsonrpc_server_get_uuid(config->jsonrpc);
ovsdb_replication_init(*config->sync_from, *config->sync_exclude,
- config->all_dbs);
+ config->all_dbs, server_uuid);
}
unixctl_command_reply(conn, NULL);
}
diff --git a/ovsdb/replication.c b/ovsdb/replication.c
index 1c77b1876..b896adc41 100644
--- a/ovsdb/replication.c
+++ b/ovsdb/replication.c
@@ -1,6 +1,6 @@
/*
* (c) Copyright 2016 Hewlett Packard Enterprise Development LP
- * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2016 Nicira, Inc.
+ * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2016, 2017 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -34,10 +34,12 @@
#include "svec.h"
#include "table.h"
#include "transaction.h"
+#include "uuid.h"
VLOG_DEFINE_THIS_MODULE(replication);
static char *sync_from;
+static struct uuid server_uuid;
static struct jsonrpc_session *session;
static unsigned int session_seqno = UINT_MAX;
@@ -88,6 +90,7 @@ void request_ids_clear(void);
enum ovsdb_replication_state {
RPL_S_INIT,
+ RPL_S_SERVER_ID_REQUESTED,
RPL_S_DB_REQUESTED,
RPL_S_SCHEMA_REQUESTED,
RPL_S_MONITOR_REQUESTED,
@@ -110,7 +113,8 @@ static struct ovsdb* find_db(const char *db_name);
void
-replication_init(const char *sync_from_, const char *exclude_tables)
+replication_init(const char *sync_from_, const char *exclude_tables,
+ const struct uuid *server)
{
free(sync_from);
sync_from = xstrdup(sync_from_);
@@ -128,6 +132,10 @@ replication_init(const char *sync_from_, const char *exclude_tables)
session = jsonrpc_session_open(sync_from, true);
session_seqno = UINT_MAX;
+
+ /* Keep a copy of local server uuid. */
+ server_uuid = *server;
+
state = RPL_S_INIT;
}
@@ -155,16 +163,13 @@ replication_run(void)
session_seqno = seqno;
request_ids_clear();
struct jsonrpc_msg *request;
- request = jsonrpc_create_request("list_dbs",
+ request = jsonrpc_create_request("get_server_id",
json_array_create_empty(), NULL);
request_ids_add(request->id, NULL);
jsonrpc_session_send(session, request);
- replication_dbs_destroy();
- replication_dbs = replication_db_clone(&local_dbs);
-
- state = RPL_S_DB_REQUESTED;
- VLOG_DBG("Send list_dbs request");
+ state = RPL_S_SERVER_ID_REQUESTED;
+ VLOG_DBG("send server ID request.");
}
msg = jsonrpc_session_recv(session);
@@ -197,10 +202,45 @@ replication_run(void)
}
switch (state) {
+ case RPL_S_SERVER_ID_REQUESTED: {
+ struct uuid uuid;
+ if (msg->result->type != JSON_STRING ||
+ !uuid_from_string(&uuid, json_string(msg->result))) {
+ struct ovsdb_error *error;
+ error = ovsdb_error("get_server_id failed",
+ "Server ID is not valid UUID");
+
+ ovsdb_error_assert(error);
+ state = RPL_S_ERR;
+ break;
+ }
+
+ if (uuid_equals(&uuid, &server_uuid)) {
+ struct ovsdb_error *error;
+ error = ovsdb_error("Server ID check failed",
+ "Self replicating is not allowed");
+
+ ovsdb_error_assert(error);
+ state = RPL_S_ERR;
+ break;
+ }
+
+ struct jsonrpc_msg *request;
+ request = jsonrpc_create_request("list_dbs",
+ json_array_create_empty(),
+ NULL);
+ request_ids_add(request->id, NULL);
+ jsonrpc_session_send(session, request);
+
+ replication_dbs_destroy();
+ replication_dbs = replication_db_clone(&local_dbs);
+ state = RPL_S_DB_REQUESTED;
+ break;
+ }
case RPL_S_DB_REQUESTED:
if (msg->result->type != JSON_ARRAY) {
struct ovsdb_error *error;
- error = ovsdb_error("list-dbs failed",
+ error = ovsdb_error("list_dbs failed",
"list_dbs response is not array");
ovsdb_error_assert(error);
state = RPL_S_ERR;
@@ -802,6 +842,7 @@ replication_status(void)
if (alive) {
switch(state) {
case RPL_S_INIT:
+ case RPL_S_SERVER_ID_REQUESTED:
case RPL_S_DB_REQUESTED:
case RPL_S_SCHEMA_REQUESTED:
case RPL_S_MONITOR_REQUESTED:
diff --git a/ovsdb/replication.h b/ovsdb/replication.h
index 622d35541..1f9c32fa7 100644
--- a/ovsdb/replication.h
+++ b/ovsdb/replication.h
@@ -44,7 +44,8 @@ struct ovsdb;
* used mainly by uinxctl commands.
*/
-void replication_init(const char *sync_from, const char *exclude_tables);
+void replication_init(const char *sync_from, const char *exclude_tables,
+ const struct uuid *server);
void replication_run(void);
void replication_wait(void);
void replication_destroy(void);