+ unixctl_command_reply(conn, NULL);
+}
+
+/* "ovsdb-server/add-remote REMOTE": adds REMOTE to the set of remotes that
+ * ovsdb-server services. */
+static void
+ovsdb_server_add_remote(struct unixctl_conn *conn, int argc OVS_UNUSED,
+ const char *argv[], void *config_)
+{
+ struct server_config *config = config_;
+ const char *remote = argv[1];
+
+ const struct ovsdb_column *column;
+ const struct ovsdb_table *table;
+ const struct db *db;
+ char *retval;
+
+ retval = (strncmp("db:", remote, 3)
+ ? NULL
+ : parse_db_column(config->all_dbs, remote,
+ &db, &table, &column));
+ if (!retval) {
+ if (sset_add(config->remotes, remote)) {
+ save_config(config);
+ }
+ unixctl_command_reply(conn, NULL);
+ } else {
+ unixctl_command_reply_error(conn, retval);
+ free(retval);
+ }
+}
+
+/* "ovsdb-server/remove-remote REMOTE": removes REMOTE frmo the set of remotes
+ * that ovsdb-server services. */
+static void
+ovsdb_server_remove_remote(struct unixctl_conn *conn, int argc OVS_UNUSED,
+ const char *argv[], void *config_)
+{
+ struct server_config *config = config_;
+ struct sset_node *node;
+
+ node = sset_find(config->remotes, argv[1]);
+ if (node) {
+ sset_delete(config->remotes, node);
+ save_config(config);
+ unixctl_command_reply(conn, NULL);
+ } else {
+ unixctl_command_reply_error(conn, "no such remote");
+ }
+}
+
+/* "ovsdb-server/list-remotes": outputs a list of configured rmeotes. */
+static void
+ovsdb_server_list_remotes(struct unixctl_conn *conn, int argc OVS_UNUSED,
+ const char *argv[] OVS_UNUSED, void *remotes_)
+{
+ struct sset *remotes = remotes_;
+ const char **list, **p;
+ struct ds s;
+
+ ds_init(&s);
+
+ list = sset_sort(remotes);
+ for (p = list; *p; p++) {
+ ds_put_format(&s, "%s\n", *p);
+ }
+ free(list);
+
+ unixctl_command_reply(conn, ds_cstr(&s));
+ ds_destroy(&s);
+}
+
+
+/* "ovsdb-server/add-db DB": adds the DB to ovsdb-server. */
+static void
+ovsdb_server_add_database(struct unixctl_conn *conn, int argc OVS_UNUSED,
+ const char *argv[], void *config_)
+{
+ struct server_config *config = config_;
+ const char *filename = argv[1];
+ char *error;
+
+ error = open_db(config, filename);
+ if (!error) {
+ save_config(config);
+ unixctl_command_reply(conn, NULL);
+ } else {
+ unixctl_command_reply_error(conn, error);
+ free(error);
+ }
+}
+
+static void
+ovsdb_server_remove_database(struct unixctl_conn *conn, int argc OVS_UNUSED,
+ const char *argv[], void *config_)
+{
+ struct server_config *config = config_;
+ struct shash_node *node;
+ struct db *db;
+ bool ok;
+
+ node = shash_find(config->all_dbs, argv[1]);
+ if (!node) {
+ unixctl_command_reply_error(conn, "Failed to find the database.");
+ return;
+ }
+ db = node->data;
+
+ ok = ovsdb_jsonrpc_server_remove_db(config->jsonrpc, db->db);
+ ovs_assert(ok);
+
+ ovsdb_destroy(db->db);
+ shash_delete(config->all_dbs, node);
+ free(db->filename);
+ free(db);
+
+ save_config(config);
+ unixctl_command_reply(conn, NULL);
+}
+
+static void
+ovsdb_server_list_databases(struct unixctl_conn *conn, int argc OVS_UNUSED,
+ const char *argv[] OVS_UNUSED, void *all_dbs_)
+{
+ struct shash *all_dbs = all_dbs_;
+ const struct shash_node **nodes;
+ struct ds s;
+ size_t i;
+
+ ds_init(&s);
+
+ nodes = shash_sort(all_dbs);
+ for (i = 0; i < shash_count(all_dbs); i++) {
+ struct db *db = nodes[i]->data;
+ ds_put_format(&s, "%s\n", db->db->schema->name);
+ }
+ free(nodes);
+
+ unixctl_command_reply(conn, ds_cstr(&s));
+ ds_destroy(&s);