mirror of
https://github.com/openvswitch/ovs
synced 2025-08-22 01:51:26 +00:00
ovsdb-server: Add new RPC "set_db_change_aware".
The _Server database recently added to ovsdb-server can be used to dump out information about databases, but monitoring updates to _Server is not yet very useful because for historical reasons ovsdb-server drops all of its OVSDB connections whenever databases are added or removed or otherwise change in some major way. It is not a good idea to change this behavior for all clients, because some of them rely on it, but this commit introduces a new RPC that allows clients that understand _Server to suppress the connection-closing behavior. Signed-off-by: Ben Pfaff <blp@ovn.org>
This commit is contained in:
parent
6bb9b060d5
commit
10621d7953
@ -146,6 +146,19 @@ notifications (see below) to the request, it must be unique among all active
|
||||
monitors. ``ovsdb-server`` rejects attempt to create two monitors with the
|
||||
same identifier.
|
||||
|
||||
4.1.7 Monitor Cancellation
|
||||
--------------------------
|
||||
|
||||
When a database monitored by a session is removed, and database change
|
||||
awareness is enabled for the session (see Section 4.1.16), the database server
|
||||
spontaneously cancels all monitors (including conditional monitors described in
|
||||
Section 4.1.12) for the removed database. For each canceled monitor, it issues
|
||||
a notification in the following form::
|
||||
|
||||
"method": "monitor_canceled"
|
||||
"params": [<json-value>]
|
||||
"id": null
|
||||
|
||||
4.1.12 Monitor_cond
|
||||
-------------------
|
||||
|
||||
@ -371,6 +384,36 @@ The response object contains the following members::
|
||||
running OVSDB server process. A fresh UUID is generated when the process
|
||||
restarts.
|
||||
|
||||
4.1.16 Database Change Awareness
|
||||
--------------------------------
|
||||
|
||||
RFC 7047 does not provide a way for a client to find out about some kinds of
|
||||
configuration changes, such as about databases added or removed while a client
|
||||
is connected to the server, or databases changing between read/write and
|
||||
read-only due to a transition between active and backup roles. Traditionally,
|
||||
``ovsdb-server`` disconnects all of its clients when this happens, because this
|
||||
prompts a well-written client to reassess what is available from the server
|
||||
when it reconnects.
|
||||
|
||||
OVS 2.9 provides a way for clients to keep track of these kinds of changes, by
|
||||
monitoring the ``Database`` table in the ``_Server`` database introduced in
|
||||
this release (see ``ovsdb-server(5)`` for details). By itself, this does not
|
||||
suppress ``ovsdb-server`` disconnection behavior, because a client might
|
||||
monitor this database without understanding its special semantics. Instead,
|
||||
``ovsdb-server`` provides a special request::
|
||||
|
||||
"method": "set_db_change_aware"
|
||||
"params": [<boolean>]
|
||||
"id": <nonnull-json-value>
|
||||
|
||||
If the boolean in the request is true, it suppresses the connection-closing
|
||||
behavior for the current connection, and false restores the default behavior.
|
||||
The reply is always the same::
|
||||
|
||||
"result": {}
|
||||
"error": null
|
||||
"id": same "id" as request
|
||||
|
||||
5.1 Notation
|
||||
------------
|
||||
|
||||
|
@ -13,6 +13,40 @@
|
||||
one row per database. As its database configuration and status changes,
|
||||
the server automatically and immediately updates the table to match.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The OVSDB protocol specified in RFC 7047 does not provide a way for an
|
||||
OVSDB client to find out about some kinds of configuration changes, such
|
||||
as about databases added or removed while a client is connected to the
|
||||
server, or databases changing between read/write and read-only due to a
|
||||
transition between active and backup roles. This table provides a
|
||||
solution: clients can monitor the table's contents to find out about
|
||||
important changes.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Traditionally, <code>ovsdb-server</code> disconnects all of its clients
|
||||
when a significant configuration change occurs, because this prompts a
|
||||
well-written client to reassess what is available from the server when it
|
||||
reconnects. Because this table provides an alternative and more
|
||||
efficient way to find out about those changes, OVS 2.9 also introduces
|
||||
the <code>set_db_change_aware</code> RPC, documented in
|
||||
<code>ovsdb-server</code>(7), to allow clients to suppress this
|
||||
disconnection behavior.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
When a database is removed from the server, in addition to
|
||||
<code>Database</code> table updates, the server sends <code>cancel</code>
|
||||
messages, as described in RFC 7047 section 4.1.4, in reply to outstanding
|
||||
transactions for the removed database. The server also cancels any
|
||||
outstanding monitoring initiated by <code>monitor</code> or
|
||||
<code>monitor_cond</code> requested on the removed database, sending the
|
||||
<code>monitor_canceled</code> RPC described in
|
||||
<code>ovsdb-server</code>(7). Only clients that disable disconnection
|
||||
with <code>set_db_change_aware</code> receive these messages.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Clients can use the <code>_uuid</code> column in this table as a
|
||||
generation number. The server generates a fresh <code>_uuid</code> every
|
||||
|
@ -57,12 +57,15 @@ static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
|
||||
/* Sessions. */
|
||||
static struct ovsdb_jsonrpc_session *ovsdb_jsonrpc_session_create(
|
||||
struct ovsdb_jsonrpc_remote *, struct jsonrpc_session *, bool);
|
||||
static void ovsdb_jsonrpc_session_preremove_db(struct ovsdb_jsonrpc_remote *,
|
||||
struct ovsdb *);
|
||||
static void ovsdb_jsonrpc_session_run_all(struct ovsdb_jsonrpc_remote *);
|
||||
static void ovsdb_jsonrpc_session_wait_all(struct ovsdb_jsonrpc_remote *);
|
||||
static void ovsdb_jsonrpc_session_get_memory_usage_all(
|
||||
const struct ovsdb_jsonrpc_remote *, struct simap *usage);
|
||||
static void ovsdb_jsonrpc_session_close_all(struct ovsdb_jsonrpc_remote *);
|
||||
static void ovsdb_jsonrpc_session_reconnect_all(struct ovsdb_jsonrpc_remote *);
|
||||
static void ovsdb_jsonrpc_session_reconnect_all(struct ovsdb_jsonrpc_remote *,
|
||||
bool force);
|
||||
static void ovsdb_jsonrpc_session_set_all_options(
|
||||
struct ovsdb_jsonrpc_remote *, const struct ovsdb_jsonrpc_options *);
|
||||
static bool ovsdb_jsonrpc_active_session_get_status(
|
||||
@ -83,6 +86,8 @@ static void ovsdb_jsonrpc_trigger_create(struct ovsdb_jsonrpc_session *,
|
||||
static struct ovsdb_jsonrpc_trigger *ovsdb_jsonrpc_trigger_find(
|
||||
struct ovsdb_jsonrpc_session *, const struct json *id, size_t hash);
|
||||
static void ovsdb_jsonrpc_trigger_complete(struct ovsdb_jsonrpc_trigger *);
|
||||
static void ovsdb_jsonrpc_trigger_preremove_db(struct ovsdb_jsonrpc_session *,
|
||||
struct ovsdb *);
|
||||
static void ovsdb_jsonrpc_trigger_complete_all(struct ovsdb_jsonrpc_session *);
|
||||
static void ovsdb_jsonrpc_trigger_complete_done(
|
||||
struct ovsdb_jsonrpc_session *);
|
||||
@ -99,6 +104,8 @@ static struct jsonrpc_msg *ovsdb_jsonrpc_monitor_cancel(
|
||||
struct ovsdb_jsonrpc_session *,
|
||||
struct json_array *params,
|
||||
const struct json *request_id);
|
||||
static void ovsdb_jsonrpc_monitor_preremove_db(struct ovsdb_jsonrpc_session *,
|
||||
struct ovsdb *);
|
||||
static void ovsdb_jsonrpc_monitor_remove_all(struct ovsdb_jsonrpc_session *);
|
||||
static void ovsdb_jsonrpc_monitor_flush_all(struct ovsdb_jsonrpc_session *);
|
||||
static bool ovsdb_jsonrpc_monitor_needs_flush(struct ovsdb_jsonrpc_session *);
|
||||
@ -157,34 +164,25 @@ ovsdb_jsonrpc_server_create(bool read_only)
|
||||
bool
|
||||
ovsdb_jsonrpc_server_add_db(struct ovsdb_jsonrpc_server *svr, struct ovsdb *db)
|
||||
{
|
||||
/* The OVSDB protocol doesn't have a way to notify a client that a
|
||||
* database has been added. If some client tried to use the database
|
||||
* that we're adding and failed, then forcing it to reconnect seems like
|
||||
* a reasonable way to make it try again.
|
||||
*
|
||||
* If this is too big of a hammer in practice, we could be more selective,
|
||||
* e.g. disconnect only connections that actually tried to use a database
|
||||
* with 'db''s name. */
|
||||
ovsdb_jsonrpc_server_reconnect(svr);
|
||||
|
||||
ovsdb_jsonrpc_server_reconnect(svr, false);
|
||||
return ovsdb_server_add_db(&svr->up, db);
|
||||
}
|
||||
|
||||
/* Removes 'db' from the set of databases served out by 'svr'. Returns
|
||||
* true if successful, false if there is no database associated with 'db'. */
|
||||
bool
|
||||
/* Removes 'db' from the set of databases served out by 'svr'. */
|
||||
void
|
||||
ovsdb_jsonrpc_server_remove_db(struct ovsdb_jsonrpc_server *svr,
|
||||
struct ovsdb *db)
|
||||
{
|
||||
/* There might be pointers to 'db' from 'svr', such as monitors or
|
||||
* outstanding transactions. Disconnect all JSON-RPC connections to avoid
|
||||
* accesses to freed memory.
|
||||
*
|
||||
* If this is too big of a hammer in practice, we could be more selective,
|
||||
* e.g. disconnect only connections that actually reference 'db'. */
|
||||
ovsdb_jsonrpc_server_reconnect(svr);
|
||||
struct shash_node *node;
|
||||
SHASH_FOR_EACH (node, &svr->remotes) {
|
||||
struct ovsdb_jsonrpc_remote *remote = node->data;
|
||||
|
||||
return ovsdb_server_remove_db(&svr->up, db);
|
||||
ovsdb_jsonrpc_session_preremove_db(remote, db);
|
||||
}
|
||||
|
||||
ovsdb_jsonrpc_server_reconnect(svr, false);
|
||||
|
||||
ovsdb_server_remove_db(&svr->up, db);
|
||||
}
|
||||
|
||||
void
|
||||
@ -333,17 +331,20 @@ ovsdb_jsonrpc_server_free_remote_status(
|
||||
free(status->locks_lost);
|
||||
}
|
||||
|
||||
/* Forces all of the JSON-RPC sessions managed by 'svr' to disconnect and
|
||||
* reconnect. */
|
||||
/* Makes all of the JSON-RPC sessions managed by 'svr' disconnect. (They will
|
||||
* then generally reconnect.).
|
||||
*
|
||||
* If 'force' is true, disconnects all sessions. Otherwise, disconnects only
|
||||
* sesions that aren't database change aware. */
|
||||
void
|
||||
ovsdb_jsonrpc_server_reconnect(struct ovsdb_jsonrpc_server *svr)
|
||||
ovsdb_jsonrpc_server_reconnect(struct ovsdb_jsonrpc_server *svr, bool force)
|
||||
{
|
||||
struct shash_node *node;
|
||||
|
||||
SHASH_FOR_EACH (node, &svr->remotes) {
|
||||
struct ovsdb_jsonrpc_remote *remote = node->data;
|
||||
|
||||
ovsdb_jsonrpc_session_reconnect_all(remote);
|
||||
ovsdb_jsonrpc_session_reconnect_all(remote, force);
|
||||
}
|
||||
}
|
||||
|
||||
@ -353,7 +354,7 @@ ovsdb_jsonrpc_server_set_read_only(struct ovsdb_jsonrpc_server *svr,
|
||||
{
|
||||
if (svr->read_only != read_only) {
|
||||
svr->read_only = read_only;
|
||||
ovsdb_jsonrpc_server_reconnect(svr);
|
||||
ovsdb_jsonrpc_server_reconnect(svr, false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -426,6 +427,20 @@ struct ovsdb_jsonrpc_session {
|
||||
struct ovsdb_session up;
|
||||
struct ovsdb_jsonrpc_remote *remote;
|
||||
|
||||
/* RFC 7047 does not contemplate how to alert clients to changes to the set
|
||||
* of databases, e.g. databases that are added or removed while the
|
||||
* database server is running. Traditionally, ovsdb-server disconnects all
|
||||
* of its clients when this happens; a well-written client will reassess
|
||||
* what is available from the server upon reconnection.
|
||||
*
|
||||
* OVS 2.9 introduces a way for clients to monitor changes to the databases
|
||||
* being served, through the Database table in the _Server database that
|
||||
* OVSDB adds in this version. ovsdb-server suppresses the connection
|
||||
* close for clients that identify themselves as taking advantage of this
|
||||
* mechanism. When this member is true, it indicates that the client
|
||||
* requested such suppression. */
|
||||
bool db_change_aware;
|
||||
|
||||
/* Triggers. */
|
||||
struct hmap triggers; /* Hmap of "struct ovsdb_jsonrpc_trigger"s. */
|
||||
|
||||
@ -472,6 +487,20 @@ ovsdb_jsonrpc_session_create(struct ovsdb_jsonrpc_remote *remote,
|
||||
return s;
|
||||
}
|
||||
|
||||
/* Database 'db' is about to be removed from the database server. To prepare,
|
||||
* this function removes all references to 'db' from 'remote'. */
|
||||
static void
|
||||
ovsdb_jsonrpc_session_preremove_db(struct ovsdb_jsonrpc_remote *remote,
|
||||
struct ovsdb *db)
|
||||
{
|
||||
struct ovsdb_jsonrpc_session *s;
|
||||
|
||||
LIST_FOR_EACH (s, node, &remote->sessions) {
|
||||
ovsdb_jsonrpc_monitor_preremove_db(s, db);
|
||||
ovsdb_jsonrpc_trigger_preremove_db(s, db);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ovsdb_jsonrpc_session_close(struct ovsdb_jsonrpc_session *s)
|
||||
{
|
||||
@ -600,17 +629,23 @@ ovsdb_jsonrpc_session_close_all(struct ovsdb_jsonrpc_remote *remote)
|
||||
}
|
||||
}
|
||||
|
||||
/* Forces all of the JSON-RPC sessions managed by 'remote' to disconnect and
|
||||
* reconnect. */
|
||||
/* Makes all of the JSON-RPC sessions managed by 'remote' disconnect. (They
|
||||
* will then generally reconnect.).
|
||||
*
|
||||
* If 'force' is true, disconnects all sessions. Otherwise, disconnects only
|
||||
* sesions that aren't database change aware. */
|
||||
static void
|
||||
ovsdb_jsonrpc_session_reconnect_all(struct ovsdb_jsonrpc_remote *remote)
|
||||
ovsdb_jsonrpc_session_reconnect_all(struct ovsdb_jsonrpc_remote *remote,
|
||||
bool force)
|
||||
{
|
||||
struct ovsdb_jsonrpc_session *s, *next;
|
||||
|
||||
LIST_FOR_EACH_SAFE (s, next, node, &remote->sessions) {
|
||||
jsonrpc_session_force_reconnect(s->js);
|
||||
if (!jsonrpc_session_is_alive(s->js)) {
|
||||
ovsdb_jsonrpc_session_close(s);
|
||||
if (force || !s->db_change_aware) {
|
||||
jsonrpc_session_force_reconnect(s->js);
|
||||
if (!jsonrpc_session_is_alive(s->js)) {
|
||||
ovsdb_jsonrpc_session_close(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -852,6 +887,17 @@ ovsdb_jsonrpc_session_unlock__(struct ovsdb_lock_waiter *waiter)
|
||||
ovsdb_lock_waiter_destroy(waiter);
|
||||
}
|
||||
|
||||
static struct jsonrpc_msg *
|
||||
syntax_error_reply(const struct jsonrpc_msg *request, const char *details)
|
||||
{
|
||||
struct ovsdb_error *error = ovsdb_syntax_error(
|
||||
request->params, NULL, "%s: %s", request->method, details);
|
||||
struct jsonrpc_msg *msg = jsonrpc_create_error(ovsdb_error_to_json(error),
|
||||
request->id);
|
||||
ovsdb_error_destroy(error);
|
||||
return msg;
|
||||
}
|
||||
|
||||
static struct jsonrpc_msg *
|
||||
ovsdb_jsonrpc_session_unlock(struct ovsdb_jsonrpc_session *s,
|
||||
struct jsonrpc_msg *request)
|
||||
@ -866,24 +912,21 @@ ovsdb_jsonrpc_session_unlock(struct ovsdb_jsonrpc_session *s,
|
||||
|
||||
error = ovsdb_jsonrpc_session_parse_lock_name(request, &lock_name);
|
||||
if (error) {
|
||||
goto error;
|
||||
return jsonrpc_create_error(ovsdb_error_to_json_free(error),
|
||||
request->id);
|
||||
}
|
||||
|
||||
/* Report error if this session has not issued a "lock" or "steal" for this
|
||||
* lock. */
|
||||
waiter = ovsdb_session_get_lock_waiter(&s->up, lock_name);
|
||||
if (!waiter) {
|
||||
error = ovsdb_syntax_error(
|
||||
request->params, NULL, "\"unlock\" without \"lock\" or \"steal\"");
|
||||
goto error;
|
||||
return syntax_error_reply(request,
|
||||
"\"unlock\" without \"lock\" or \"steal\"");
|
||||
}
|
||||
|
||||
ovsdb_jsonrpc_session_unlock__(waiter);
|
||||
|
||||
return jsonrpc_create_reply(json_object_create(), request->id);
|
||||
|
||||
error:
|
||||
return jsonrpc_create_error(ovsdb_error_to_json_free(error), request->id);
|
||||
}
|
||||
|
||||
static struct jsonrpc_msg *
|
||||
@ -897,6 +940,21 @@ execute_transaction(struct ovsdb_jsonrpc_session *s, struct ovsdb *db,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct jsonrpc_msg *
|
||||
ovsdb_jsonrpc_session_set_db_change_aware(struct ovsdb_jsonrpc_session *s,
|
||||
const struct jsonrpc_msg *request)
|
||||
{
|
||||
const struct json_array *params = json_array(request->params);
|
||||
if (params->n != 1
|
||||
|| (params->elems[0]->type != JSON_TRUE &&
|
||||
params->elems[0]->type != JSON_FALSE)) {
|
||||
return syntax_error_reply(request, "true or false parameter expected");
|
||||
}
|
||||
|
||||
s->db_change_aware = json_boolean(params->elems[0]);
|
||||
return jsonrpc_create_reply(json_object_create(), request->id);
|
||||
}
|
||||
|
||||
static void
|
||||
ovsdb_jsonrpc_session_got_request(struct ovsdb_jsonrpc_session *s,
|
||||
struct jsonrpc_msg *request)
|
||||
@ -957,6 +1015,8 @@ ovsdb_jsonrpc_session_got_request(struct ovsdb_jsonrpc_session *s,
|
||||
reply = ovsdb_jsonrpc_session_lock(s, request, OVSDB_LOCK_STEAL);
|
||||
} else if (!strcmp(request->method, "unlock")) {
|
||||
reply = ovsdb_jsonrpc_session_unlock(s, request);
|
||||
} else if (!strcmp(request->method, "set_db_change_aware")) {
|
||||
reply = ovsdb_jsonrpc_session_set_db_change_aware(s, request);
|
||||
} else if (!strcmp(request->method, "echo")) {
|
||||
reply = jsonrpc_create_reply(json_clone(request->params), request->id);
|
||||
} else {
|
||||
@ -1092,14 +1152,34 @@ ovsdb_jsonrpc_trigger_complete(struct ovsdb_jsonrpc_trigger *t)
|
||||
}
|
||||
|
||||
static void
|
||||
ovsdb_jsonrpc_trigger_complete_all(struct ovsdb_jsonrpc_session *s)
|
||||
ovsdb_jsonrpc_trigger_remove__(struct ovsdb_jsonrpc_session *s,
|
||||
struct ovsdb *db)
|
||||
{
|
||||
struct ovsdb_jsonrpc_trigger *t, *next;
|
||||
HMAP_FOR_EACH_SAFE (t, next, hmap_node, &s->triggers) {
|
||||
ovsdb_jsonrpc_trigger_complete(t);
|
||||
if (!db || t->trigger.db == db) {
|
||||
ovsdb_jsonrpc_trigger_complete(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Database 'db' is about to be removed from the database server. To prepare,
|
||||
* this function removes all references from triggers in 's' to 'db'. */
|
||||
static void
|
||||
ovsdb_jsonrpc_trigger_preremove_db(struct ovsdb_jsonrpc_session *s,
|
||||
struct ovsdb *db)
|
||||
{
|
||||
ovs_assert(db);
|
||||
ovsdb_jsonrpc_trigger_remove__(s, db);
|
||||
}
|
||||
|
||||
/* Removes all triggers from 's'. */
|
||||
static void
|
||||
ovsdb_jsonrpc_trigger_complete_all(struct ovsdb_jsonrpc_session *s)
|
||||
{
|
||||
ovsdb_jsonrpc_trigger_remove__(s, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
ovsdb_jsonrpc_trigger_complete_done(struct ovsdb_jsonrpc_session *s)
|
||||
{
|
||||
@ -1519,15 +1599,42 @@ ovsdb_jsonrpc_monitor_cancel(struct ovsdb_jsonrpc_session *s,
|
||||
}
|
||||
|
||||
static void
|
||||
ovsdb_jsonrpc_monitor_remove_all(struct ovsdb_jsonrpc_session *s)
|
||||
ovsdb_jsonrpc_monitor_remove__(struct ovsdb_jsonrpc_session *s,
|
||||
struct ovsdb *db)
|
||||
{
|
||||
struct ovsdb_jsonrpc_monitor *m, *next;
|
||||
|
||||
HMAP_FOR_EACH_SAFE (m, next, node, &s->monitors) {
|
||||
ovsdb_jsonrpc_monitor_destroy(m);
|
||||
if (!db || m->db == db) {
|
||||
if (db && jsonrpc_session_is_connected(s->js)
|
||||
&& s->db_change_aware) {
|
||||
struct jsonrpc_msg *notify = jsonrpc_create_notify(
|
||||
"monitor_canceled",
|
||||
json_array_create_1(json_clone(m->monitor_id)));
|
||||
ovsdb_jsonrpc_session_send(s, notify);
|
||||
}
|
||||
ovsdb_jsonrpc_monitor_destroy(m);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Database 'db' is about to be removed from the database server. To prepare,
|
||||
* this function removes all references from monitors in 's' to 'db'. */
|
||||
static void
|
||||
ovsdb_jsonrpc_monitor_preremove_db(struct ovsdb_jsonrpc_session *s,
|
||||
struct ovsdb *db)
|
||||
{
|
||||
ovs_assert(db);
|
||||
ovsdb_jsonrpc_monitor_remove__(s, db);
|
||||
}
|
||||
|
||||
/* Cancels all monitors in 's'. */
|
||||
static void
|
||||
ovsdb_jsonrpc_monitor_remove_all(struct ovsdb_jsonrpc_session *s)
|
||||
{
|
||||
ovsdb_jsonrpc_monitor_remove__(s, NULL);
|
||||
}
|
||||
|
||||
static struct json *
|
||||
ovsdb_jsonrpc_monitor_compose_update(struct ovsdb_jsonrpc_monitor *m,
|
||||
bool initial)
|
||||
|
@ -27,7 +27,7 @@ struct uuid;
|
||||
struct ovsdb_jsonrpc_server *ovsdb_jsonrpc_server_create(bool read_only);
|
||||
bool ovsdb_jsonrpc_server_add_db(struct ovsdb_jsonrpc_server *,
|
||||
struct ovsdb *);
|
||||
bool ovsdb_jsonrpc_server_remove_db(struct ovsdb_jsonrpc_server *,
|
||||
void ovsdb_jsonrpc_server_remove_db(struct ovsdb_jsonrpc_server *,
|
||||
struct ovsdb *);
|
||||
void ovsdb_jsonrpc_server_destroy(struct ovsdb_jsonrpc_server *);
|
||||
|
||||
@ -64,7 +64,7 @@ bool ovsdb_jsonrpc_server_get_remote_status(
|
||||
void ovsdb_jsonrpc_server_free_remote_status(
|
||||
struct ovsdb_jsonrpc_remote_status *);
|
||||
|
||||
void ovsdb_jsonrpc_server_reconnect(struct ovsdb_jsonrpc_server *);
|
||||
void ovsdb_jsonrpc_server_reconnect(struct ovsdb_jsonrpc_server *, bool force);
|
||||
|
||||
void ovsdb_jsonrpc_server_run(struct ovsdb_jsonrpc_server *);
|
||||
void ovsdb_jsonrpc_server_wait(struct ovsdb_jsonrpc_server *);
|
||||
|
@ -75,6 +75,13 @@ struct ovsdb_client_command {
|
||||
/* --timestamp: Print a timestamp before each update on "monitor" command? */
|
||||
static bool timestamp;
|
||||
|
||||
/* --db-change-aware, --no-db-change-aware: Enable db_change_aware feature for
|
||||
* "monitor" command?
|
||||
*
|
||||
* (This option is undocumented because it is expected to be useful only for
|
||||
* testing that the db_change_aware feature actually works.) */
|
||||
static int db_change_aware;
|
||||
|
||||
/* --force: Ignore schema differences for "restore" command? */
|
||||
static bool force;
|
||||
|
||||
@ -201,6 +208,8 @@ parse_options(int argc, char *argv[])
|
||||
{"timestamp", no_argument, NULL, OPT_TIMESTAMP},
|
||||
{"force", no_argument, NULL, OPT_FORCE},
|
||||
{"timeout", required_argument, NULL, 't'},
|
||||
{"db-change-aware", no_argument, &db_change_aware, 1},
|
||||
{"no-db-change-aware", no_argument, &db_change_aware, 0},
|
||||
VLOG_LONG_OPTIONS,
|
||||
DAEMON_LONG_OPTIONS,
|
||||
#ifdef HAVE_OPENSSL
|
||||
@ -1034,7 +1043,6 @@ do_monitor__(struct jsonrpc *rpc, const char *database,
|
||||
const char *table_name = argv[0];
|
||||
struct unixctl_server *unixctl;
|
||||
struct ovsdb_schema *schema;
|
||||
struct jsonrpc_msg *request;
|
||||
struct json *monitor, *monitor_requests, *request_id;
|
||||
bool exiting = false;
|
||||
bool blocked = false;
|
||||
@ -1102,11 +1110,29 @@ do_monitor__(struct jsonrpc *rpc, const char *database,
|
||||
free(nodes);
|
||||
}
|
||||
|
||||
if (db_change_aware) {
|
||||
struct jsonrpc_msg *request = jsonrpc_create_request(
|
||||
"set_db_change_aware",
|
||||
json_array_create_1(json_boolean_create(true)),
|
||||
NULL);
|
||||
struct jsonrpc_msg *reply;
|
||||
int error = jsonrpc_transact_block(rpc, request, &reply);
|
||||
if (error) {
|
||||
ovs_fatal(error, "%s: error setting db_change_aware", server);
|
||||
}
|
||||
if (reply->type == JSONRPC_ERROR) {
|
||||
ovs_fatal(0, "%s: set_db_change_aware failed (%s)",
|
||||
server, json_to_string(reply->error, 0));
|
||||
}
|
||||
jsonrpc_msg_destroy(reply);
|
||||
}
|
||||
|
||||
monitor = json_array_create_3(json_string_create(database),
|
||||
json_null_create(), monitor_requests);
|
||||
const char *method = version == OVSDB_MONITOR_V2 ? "monitor_cond"
|
||||
: "monitor";
|
||||
|
||||
struct jsonrpc_msg *request;
|
||||
request = jsonrpc_create_request(method, monitor, NULL);
|
||||
request_id = json_clone(request->id);
|
||||
jsonrpc_send(rpc, request);
|
||||
|
@ -1240,7 +1240,7 @@ ovsdb_server_disable_monitor_cond(struct unixctl_conn *conn,
|
||||
struct ovsdb_jsonrpc_server *jsonrpc = jsonrpc_;
|
||||
|
||||
ovsdb_jsonrpc_disable_monitor_cond();
|
||||
ovsdb_jsonrpc_server_reconnect(jsonrpc);
|
||||
ovsdb_jsonrpc_server_reconnect(jsonrpc, true);
|
||||
unixctl_command_reply(conn, NULL);
|
||||
}
|
||||
|
||||
@ -1298,7 +1298,7 @@ ovsdb_server_reconnect(struct unixctl_conn *conn, int argc OVS_UNUSED,
|
||||
const char *argv[] OVS_UNUSED, void *jsonrpc_)
|
||||
{
|
||||
struct ovsdb_jsonrpc_server *jsonrpc = jsonrpc_;
|
||||
ovsdb_jsonrpc_server_reconnect(jsonrpc);
|
||||
ovsdb_jsonrpc_server_reconnect(jsonrpc, true);
|
||||
unixctl_command_reply(conn, NULL);
|
||||
}
|
||||
|
||||
@ -1400,10 +1400,9 @@ ovsdb_server_add_database(struct unixctl_conn *conn, int argc OVS_UNUSED,
|
||||
static void
|
||||
remove_db(struct server_config *config, struct shash_node *node)
|
||||
{
|
||||
struct db *db;
|
||||
struct db *db = node->data;
|
||||
|
||||
db = node->data;
|
||||
ovs_assert(ovsdb_jsonrpc_server_remove_db(config->jsonrpc, db->db));
|
||||
ovsdb_jsonrpc_server_remove_db(config->jsonrpc, db->db);
|
||||
|
||||
close_db(db);
|
||||
shash_delete(config->all_dbs, node);
|
||||
|
@ -169,14 +169,31 @@ AT_CLEANUP
|
||||
|
||||
AT_SETUP([ovsdb-server/add-db and remove-db])
|
||||
AT_KEYWORDS([ovsdb server positive])
|
||||
on_exit 'kill `cat ovsdb-server.pid`'
|
||||
on_exit 'kill `cat *.pid`'
|
||||
ordinal_schema > schema1
|
||||
constraint_schema > schema2
|
||||
AT_CHECK([ovsdb-tool create db1 schema1], [0], [ignore], [ignore])
|
||||
AT_CHECK([ovsdb-tool create db2 schema2], [0], [ignore], [ignore])
|
||||
|
||||
# Start ovsdb-server with just a single database - db1.
|
||||
AT_CHECK([ovsdb-server --detach --no-chdir --pidfile --remote=punix:db.sock db1], [0])
|
||||
AT_CHECK([ovsdb-server -vfile -vvlog:off --log-file --detach --no-chdir --pidfile --remote=punix:db.sock db1], [0])
|
||||
CHECK_DBS([ordinals
|
||||
])
|
||||
|
||||
# Remove the database.
|
||||
AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/remove-db ordinals], [0])
|
||||
CHECK_DBS([])
|
||||
|
||||
# Start monitoring processes.
|
||||
AT_CHECK([ovsdb-client --detach --pidfile=ovsdb-client-1.pid --no-db-change-aware --no-headings monitor _Server Database name > db-change-unaware.stdout 2> db-change-unaware.stderr])
|
||||
AT_CHECK([ovsdb-client --detach --pidfile=ovsdb-client-2.pid --db-change-aware --no-headings monitor _Server Database name > db-change-aware.stdout 2> db-change-aware.stderr])
|
||||
AT_CAPTURE_FILE([db-change-unaware.stdout])
|
||||
AT_CAPTURE_FILE([db-change-unaware.stderr])
|
||||
AT_CAPTURE_FILE([db-change-aware.stdout])
|
||||
AT_CAPTURE_FILE([db-change-aware.stderr])
|
||||
|
||||
# Add the first database back.
|
||||
AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/add-db db1], [0])
|
||||
CHECK_DBS([ordinals
|
||||
])
|
||||
|
||||
@ -243,6 +260,25 @@ AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/add-db db2], [0])
|
||||
CHECK_DBS([constraints
|
||||
])
|
||||
AT_CHECK([ovsdb-client list-tables unix:db.sock constraints], [0], [ignore], [ignore])
|
||||
|
||||
# Check the monitoring results.
|
||||
AT_CHECK([uuidfilt db-change-aware.stdout], [0], [dnl
|
||||
<0> initial _Server
|
||||
|
||||
<1> insert ordinals
|
||||
|
||||
<2> insert constraints
|
||||
|
||||
<1> delete ordinals
|
||||
|
||||
<2> delete constraints
|
||||
|
||||
<3> insert constraints
|
||||
])
|
||||
AT_CHECK([uuidfilt db-change-unaware.stdout], [0], [dnl
|
||||
<0> initial _Server
|
||||
])
|
||||
|
||||
OVS_APP_EXIT_AND_WAIT([ovsdb-server])
|
||||
AT_CLEANUP
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user