summaryrefslogtreecommitdiff
path: root/ovsdb/replication.c
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/replication.c
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/replication.c')
-rw-r--r--ovsdb/replication.c59
1 files changed, 50 insertions, 9 deletions
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: