Clients may want to know if current replica actually has an active connection with the replication source. For example, if one of the replicas lost connection, clients may want to re-connect to another replica in order to receive all the up-to-date database content.
Signed-off-by: Ilya Maximets <[email protected]> --- NEWS | 3 +++ lib/ovsdb-cs.c | 6 +++++- ovsdb/_server.xml | 18 ++++++++++-------- ovsdb/ovsdb-server.c | 16 +++++++++------- ovsdb/replication.c | 8 ++++++++ ovsdb/replication.h | 7 ++++--- python/ovs/db/idl.py | 9 +++++++-- 7 files changed, 46 insertions(+), 21 deletions(-) diff --git a/NEWS b/NEWS index d2b12b23c..fe25f2fc0 100644 --- a/NEWS +++ b/NEWS @@ -8,6 +8,9 @@ Post-v2.15.0 replication source (active server). Data from the 'Database' table of the active server stored in '_synced_Database' table on backup and available for monitoring. + * Replication (backup) server now reports 'connected: false' in Database + table of _Server database if it's not currently connected to the + replication source (active server). - In ovs-vsctl and vtep-ctl, the "find" command now accept new operators {in} and {not-in}. - Userspace datapath: diff --git a/lib/ovsdb-cs.c b/lib/ovsdb-cs.c index 7e861d1f1..4d6c41030 100644 --- a/lib/ovsdb-cs.c +++ b/lib/ovsdb-cs.c @@ -1876,13 +1876,13 @@ ovsdb_cs_check_server_db_row(struct ovsdb_cs *cs, const char *server_name = jsonrpc_session_get_name(cs->session); const char *model = server_column_get_string(db_row, COL_MODEL, ""); const char *schema = server_column_get_string(db_row, COL_SCHEMA, NULL); + bool connected = server_column_get_bool(db_row, COL_CONNECTED, false); bool ok = false; if (cs->leader_only && db_row->synced_table) { VLOG_INFO("%s is a replication server and therefore not a leader; " "trying another server", server_name); } else if (!strcmp(model, "clustered")) { - bool connected = server_column_get_bool(db_row, COL_CONNECTED, false); bool leader = server_column_get_bool(db_row, COL_LEADER, false); uint64_t index = server_column_get_int(db_row, COL_INDEX, 0); @@ -1905,6 +1905,10 @@ ovsdb_cs_check_server_db_row(struct ovsdb_cs *cs, } else { if (!schema) { VLOG_INFO("%s: missing database schema", server_name); + } else if (!connected) { + VLOG_INFO("%s: replication server is disconnected from the " + "replication source; trying another server", + server_name); } else { ok = true; } diff --git a/ovsdb/_server.xml b/ovsdb/_server.xml index 2e8b3393d..cf1b8b61b 100644 --- a/ovsdb/_server.xml +++ b/ovsdb/_server.xml @@ -78,6 +78,16 @@ database, this is empty until it finishes joining its cluster. </column> + <column name="connected"> + True if the database is connected to its storage. A standalone database + is always connected. A clustered database is connected if the server is + in contact with a majority of its cluster. An active-backup database + is connected if the server is in contact with the replication source, + i.e. is connected to the server it syncs from. + An unconnected database cannot be modified and its data might be + unavailable or stale. + </column> + <group title="Clustered Databases"> <p> These columns are most interesting and in some cases only relevant for @@ -85,14 +95,6 @@ column is <code>clustered</code>. </p> - <column name="connected"> - True if the database is connected to its storage. A standalone or - active-backup database is always connected. A clustered database is - connected if the server is in contact with a majority of its cluster. - An unconnected database cannot be modified and its data might be - unavailable or stale. - </column> - <column name="leader"> True if the database is the leader in its cluster. For a standalone or active-backup database, this is always true. diff --git a/ovsdb/ovsdb-server.c b/ovsdb/ovsdb-server.c index 89780dac8..93de2d1be 100644 --- a/ovsdb/ovsdb-server.c +++ b/ovsdb/ovsdb-server.c @@ -139,7 +139,7 @@ static void report_error_if_changed(char *error, char **last_errorp); static void update_remote_status(const struct ovsdb_jsonrpc_server *jsonrpc, const struct sset *remotes, struct shash *all_dbs); -static void update_server_status(struct shash *all_dbs); +static void update_server_status(struct shash *all_dbs, bool is_backup); static void save_config__(FILE *config_file, const struct sset *remotes, const struct sset *db_filenames, @@ -267,7 +267,7 @@ main_loop(struct server_config *config, update_remote_status(jsonrpc, remotes, all_dbs); } - update_server_status(all_dbs); + update_server_status(all_dbs, *is_backup); memory_wait(); if (*is_backup) { @@ -1154,13 +1154,14 @@ update_remote_status(const struct ovsdb_jsonrpc_server *jsonrpc, /* Updates 'row', a row in the _Server database's Database table, to match * 'db'. */ static void -update_database_status(struct ovsdb_row *row, struct db *db) +update_database_status(struct ovsdb_row *row, struct db *db, bool is_backup) { ovsdb_util_write_string_column(row, "name", db->db->name); ovsdb_util_write_string_column(row, "model", ovsdb_storage_get_model(db->db->storage)); ovsdb_util_write_bool_column(row, "connected", - ovsdb_storage_is_connected(db->db->storage)); + is_backup ? replication_is_connected() + : ovsdb_storage_is_connected(db->db->storage)); ovsdb_util_write_bool_column(row, "leader", ovsdb_storage_is_leader(db->db->storage)); ovsdb_util_write_uuid_column(row, "cid", @@ -1195,7 +1196,7 @@ update_database_status(struct ovsdb_row *row, struct db *db) /* Updates the Database table in the _Server database. */ static void -update_server_status(struct shash *all_dbs) +update_server_status(struct shash *all_dbs, bool is_backup) { struct db *server_db = shash_find_data(all_dbs, "_Server"); struct ovsdb_table *database_table = shash_find_data( @@ -1212,7 +1213,8 @@ update_server_status(struct shash *all_dbs) if (!db || !db->db) { ovsdb_txn_row_delete(txn, row); } else { - update_database_status(ovsdb_txn_row_modify(txn, row), db); + update_database_status(ovsdb_txn_row_modify(txn, row), + db, is_backup); } } @@ -1238,7 +1240,7 @@ update_server_status(struct shash *all_dbs) /* Add row. */ struct ovsdb_row *new_row = ovsdb_row_create(database_table); uuid_generate(ovsdb_row_get_uuid_rw(new_row)); - update_database_status(new_row, db); + update_database_status(new_row, db, is_backup); ovsdb_txn_row_insert(txn, new_row); next:; diff --git a/ovsdb/replication.c b/ovsdb/replication.c index 5aac325f2..a02f2514d 100644 --- a/ovsdb/replication.c +++ b/ovsdb/replication.c @@ -952,6 +952,14 @@ replication_is_alive(void) return false; } +/* Returns 'true' if there is an active established connection with a + * replication source. */ +bool +replication_is_connected(void) +{ + return session ? jsonrpc_session_is_connected(session) : false; +} + /* Return the last error reported on a connection by 'session'. The * return value is 0 if replication is not currently running, or * if replication session has not encountered any error. diff --git a/ovsdb/replication.h b/ovsdb/replication.h index 6d1be820f..bfef4f32a 100644 --- a/ovsdb/replication.h +++ b/ovsdb/replication.h @@ -35,9 +35,9 @@ struct ovsdb; * - replication_destroy() should be called when OVSDB server shutdown to * reclaim resources. * - * - replication_run(), replication_wait(), replication_is_alive() and - * replication_get_last_error() should be call within the main loop - * whenever OVSDB server runs in the backup mode. + * - replication_run(), replication_wait(), replication_is_alive(), + * replication_is_connected() and replication_get_last_error() should be + * called within the main loop whenever OVSDB server runs in the backup mode. * * - set_excluded_tables(), get_excluded_tables(), disconnect_active_server() * and replication_usage() are support functions used mainly by unixctl @@ -54,6 +54,7 @@ void replication_destroy(void); void replication_usage(void); void replication_add_local_db(const char *databse, struct ovsdb *db); bool replication_is_alive(void); +bool replication_is_connected(void); int replication_get_last_error(void); char *replication_status(void); void replication_set_probe_interval(int); diff --git a/python/ovs/db/idl.py b/python/ovs/db/idl.py index 0d581a110..f8474d8de 100644 --- a/python/ovs/db/idl.py +++ b/python/ovs/db/idl.py @@ -774,8 +774,13 @@ class Idl(object): % (session_name, self._db.name)) return False - if (database.model == CLUSTERED and - self._session.get_num_of_remotes() > 1): + if database.model != CLUSTERED: + if not database.connected: + vlog.info('%s: replication server is disconnected from the ' + 'replication source; trying another server' + % session_name) + elif (database.model == CLUSTERED and + self._session.get_num_of_remotes() > 1): if not database.schema: vlog.info('%s: clustered database server has not yet joined ' 'cluster; trying another server' % session_name) -- 2.26.3 _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
