76
76
static unixctl_cb_func ovsdb_server_compact;
77
77
static unixctl_cb_func ovsdb_server_reconnect;
79
struct add_remote_aux {
79
struct server_config {
80
80
struct sset *remotes;
81
struct shash *all_dbs;
83
82
FILE *config_tmpfile;
83
struct ovsdb_jsonrpc_server *jsonrpc;
85
85
static unixctl_cb_func ovsdb_server_add_remote;
87
struct remove_remote_aux {
91
86
static unixctl_cb_func ovsdb_server_remove_remote;
92
87
static unixctl_cb_func ovsdb_server_list_remotes;
89
static unixctl_cb_func ovsdb_server_add_database;
90
static unixctl_cb_func ovsdb_server_remove_database;
91
static unixctl_cb_func ovsdb_server_list_databases;
93
static char *open_db(struct server_config *config, const char *filename);
94
95
static void parse_options(int *argc, char **argvp[],
95
96
struct sset *remotes, char **unixctl_pathp,
96
97
char **run_command);
97
98
static void usage(void) NO_RETURN;
99
static void reconfigure_from_db(struct ovsdb_jsonrpc_server *jsonrpc,
100
const struct db dbs[], size_t n_dbs,
101
struct sset *remotes);
100
static char *reconfigure_remotes(struct ovsdb_jsonrpc_server *,
101
const struct shash *all_dbs,
102
struct sset *remotes);
103
static char *reconfigure_ssl(const struct shash *all_dbs);
104
static void report_error_if_changed(char *error, char **last_errorp);
103
106
static void update_remote_status(const struct ovsdb_jsonrpc_server *jsonrpc,
104
107
const struct sset *remotes,
105
struct db dbs[], size_t n_dbs);
108
struct shash *all_dbs);
107
static void save_config(FILE *config_file, const struct sset *);
108
static void load_config(FILE *config_file, struct sset *);
110
static void save_config__(FILE *config_file, const struct sset *remotes,
111
const struct sset *db_filenames);
112
static void save_config(struct server_config *);
113
static void load_config(FILE *config_file, struct sset *remotes,
114
struct sset *db_filenames);
111
117
main(int argc, char *argv[])
144
150
if (!config_tmpfile) {
145
151
ovs_fatal(errno, "failed to create temporary file");
147
save_config(config_tmpfile, &remotes);
154
sset_init(&db_filenames);
156
for (i = 0; i < argc; i++) {
157
sset_add(&db_filenames, argv[i]);
160
char *default_db = xasprintf("%s/conf.db", ovs_dbdir());
161
sset_add(&db_filenames, default_db);
165
server_config.remotes = &remotes;
166
server_config.config_tmpfile = config_tmpfile;
168
save_config__(config_tmpfile, &remotes, &db_filenames);
149
170
daemonize_start();
151
172
/* Load the saved config. */
152
load_config(config_tmpfile, &remotes);
154
n_dbs = MAX(1, argc);
155
dbs = xcalloc(n_dbs + 1, sizeof *dbs);
157
for (i = 0; i < argc; i++) {
158
dbs[i].filename = argv[i];
161
dbs[0].filename = xasprintf("%s/conf.db", ovs_dbdir());
164
for (i = 0; i < n_dbs; i++) {
165
struct ovsdb_error *error;
167
error = ovsdb_file_open(dbs[i].filename, false,
168
&dbs[i].db, &dbs[i].file);
170
ovs_fatal(0, "%s", ovsdb_error_to_string(error));
173
load_config(config_tmpfile, &remotes, &db_filenames);
174
174
jsonrpc = ovsdb_jsonrpc_server_create();
175
for (i = 0; i < n_dbs; i++) {
176
if (!ovsdb_jsonrpc_server_add_db(jsonrpc, dbs[i].db)) {
177
ovs_fatal(0, "%s: duplicate database name",
178
dbs[i].db->schema->name);
176
shash_init(&all_dbs);
177
server_config.all_dbs = &all_dbs;
178
server_config.jsonrpc = jsonrpc;
179
SSET_FOR_EACH (db_filename, &db_filenames) {
180
error = open_db(&server_config, db_filename);
182
ovs_fatal(0, "%s", error);
181
reconfigure_from_db(jsonrpc, dbs, n_dbs, &remotes);
186
error = reconfigure_remotes(jsonrpc, &all_dbs, &remotes);
188
error = reconfigure_ssl(&all_dbs);
191
ovs_fatal(0, "%s", error);
183
194
retval = unixctl_server_create(unixctl_path, &unixctl);
213
224
unixctl_command_register("exit", "", 0, 0, ovsdb_server_exit, &exiting);
214
225
unixctl_command_register("ovsdb-server/compact", "", 0, 1,
215
ovsdb_server_compact, dbs);
226
ovsdb_server_compact, &all_dbs);
216
227
unixctl_command_register("ovsdb-server/reconnect", "", 0, 0,
217
228
ovsdb_server_reconnect, jsonrpc);
219
add_remote_aux.remotes = &remotes;
220
add_remote_aux.dbs = dbs;
221
add_remote_aux.n_dbs = n_dbs;
222
add_remote_aux.config_tmpfile = config_tmpfile;
223
230
unixctl_command_register("ovsdb-server/add-remote", "REMOTE", 1, 1,
224
ovsdb_server_add_remote, &add_remote_aux);
226
remove_remote_aux.remotes = &remotes;
227
remove_remote_aux.config_tmpfile = config_tmpfile;
231
ovsdb_server_add_remote, &server_config);
228
232
unixctl_command_register("ovsdb-server/remove-remote", "REMOTE", 1, 1,
229
ovsdb_server_remove_remote, &remove_remote_aux);
233
ovsdb_server_remove_remote, &server_config);
231
234
unixctl_command_register("ovsdb-server/list-remotes", "", 0, 0,
232
235
ovsdb_server_list_remotes, &remotes);
237
unixctl_command_register("ovsdb-server/add-db", "DB", 1, 1,
238
ovsdb_server_add_database, &server_config);
239
unixctl_command_register("ovsdb-server/remove-db", "DB", 1, 1,
240
ovsdb_server_remove_database, &server_config);
241
unixctl_command_register("ovsdb-server/list-dbs", "", 0, 0,
242
ovsdb_server_list_databases, &all_dbs);
246
remotes_error = NULL;
235
247
while (!exiting) {
239
249
if (memory_should_report()) {
240
250
struct simap usage;
242
252
simap_init(&usage);
243
253
ovsdb_jsonrpc_server_get_memory_usage(jsonrpc, &usage);
244
for (i = 0; i < n_dbs; i++) {
245
ovsdb_get_memory_usage(dbs[i].db, &usage);
254
SHASH_FOR_EACH(node, &all_dbs) {
255
struct db *db = node->data;
256
ovsdb_get_memory_usage(db->db, &usage);
247
258
memory_report(&usage);
248
259
simap_destroy(&usage);
251
/* Run unixctl_server_run() before reconfigure_from_db() because
262
/* Run unixctl_server_run() before reconfigure_remotes() because
252
263
* ovsdb-server/add-remote and ovsdb-server/remove-remote can change
253
* the set of remotes that reconfigure_from_db() uses. */
264
* the set of remotes that reconfigure_remotes() uses. */
254
265
unixctl_server_run(unixctl);
256
reconfigure_from_db(jsonrpc, dbs, n_dbs, &remotes);
267
report_error_if_changed(
268
reconfigure_remotes(jsonrpc, &all_dbs, &remotes),
270
report_error_if_changed(reconfigure_ssl(&all_dbs), &ssl_error);
257
271
ovsdb_jsonrpc_server_run(jsonrpc);
259
for (i = 0; i < n_dbs; i++) {
260
ovsdb_trigger_run(dbs[i].db, time_msec());
273
SHASH_FOR_EACH(node, &all_dbs) {
274
struct db *db = node->data;
275
ovsdb_trigger_run(db->db, time_msec());
262
if (run_process && process_exited(run_process)) {
279
if (process_exited(run_process)) {
266
284
/* update Manager status(es) every 5 seconds */
267
285
if (time_msec() >= status_timer) {
268
286
status_timer = time_msec() + 5000;
269
update_remote_status(jsonrpc, &remotes, dbs, n_dbs);
287
update_remote_status(jsonrpc, &remotes, &all_dbs);
273
291
ovsdb_jsonrpc_server_wait(jsonrpc);
274
292
unixctl_server_wait(unixctl);
275
for (i = 0; i < n_dbs; i++) {
276
ovsdb_trigger_wait(dbs[i].db, time_msec());
293
SHASH_FOR_EACH(node, &all_dbs) {
294
struct db *db = node->data;
295
ovsdb_trigger_wait(db->db, time_msec());
278
297
if (run_process) {
279
298
process_wait(run_process);
326
open_db(struct server_config *config, const char *filename)
328
struct ovsdb_error *db_error;
332
db = xzalloc(sizeof *db);
333
db->filename = xstrdup(filename);
335
db_error = ovsdb_file_open(db->filename, false, &db->db, &db->file);
337
error = ovsdb_error_to_string(db_error);
338
} else if (!ovsdb_jsonrpc_server_add_db(config->jsonrpc, db->db)) {
339
error = xasprintf("%s: duplicate database name", db->db->schema->name);
341
shash_add_assert(config->all_dbs, db->db->schema->name, db);
345
ovsdb_error_destroy(db_error);
346
ovsdb_destroy(db->db);
305
352
static const struct db *
306
find_db(const struct db dbs[], size_t n_dbs, const char *db_name)
353
find_db(const struct shash *all_dbs, const char *db_name)
355
struct shash_node *node;
310
for (i = 0; i < n_dbs; i++) {
311
if (!strcmp(dbs[i].db->schema->name, db_name)) {
357
SHASH_FOR_EACH(node, all_dbs) {
358
struct db *db = node->data;
359
if (!strcmp(db->db->schema->name, db_name)) {
338
386
tokens[0] = strtok_r(NULL, ",", &save_ptr);
339
387
tokens[1] = strtok_r(NULL, ",", &save_ptr);
340
388
tokens[2] = strtok_r(NULL, ",", &save_ptr);
341
if (!tokens[0] || !tokens[1]) {
389
if (!tokens[0] || !tokens[1] || !tokens[2]) {
342
390
return xasprintf("\"%s\": invalid syntax", name_);
345
const char *db_name = tokens[0];
346
table_name = tokens[1];
347
column_name = tokens[2];
349
db = find_db(dbs, n_dbs, tokens[0]);
351
return xasprintf("\"%s\": no database named %s", name_, db_name);
355
return xasprintf("\"%s\": database name must be specified "
356
"(because multiple databases are configured)",
360
table_name = tokens[0];
361
column_name = tokens[1];
394
table_name = tokens[1];
395
column_name = tokens[2];
397
db = find_db(all_dbs, tokens[0]);
399
return xasprintf("\"%s\": no database named %s", name_, db_name);
365
402
table = ovsdb_get_table(db->db, table_name);
813
859
update_remote_status(const struct ovsdb_jsonrpc_server *jsonrpc,
814
860
const struct sset *remotes,
815
struct db dbs[], size_t n_dbs)
861
struct shash *all_dbs)
817
863
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
818
864
const char *remote;
866
struct shash_node *node;
821
for (i = 0; i < n_dbs; i++) {
822
dbs[i].txn = ovsdb_txn_create(dbs[i].db);
868
SHASH_FOR_EACH(node, all_dbs) {
870
db->txn = ovsdb_txn_create(db->db);
825
873
/* Iterate over --remote arguments given on command line. */
826
874
SSET_FOR_EACH (remote, remotes) {
827
update_remote_rows(dbs, n_dbs, remote, jsonrpc);
875
update_remote_rows(all_dbs, remote, jsonrpc);
830
for (i = 0; i < n_dbs; i++) {
831
struct ovsdb_error *error = ovsdb_txn_commit(dbs[i].txn, false);
878
SHASH_FOR_EACH(node, all_dbs) {
879
struct ovsdb_error *error;
881
error = ovsdb_txn_commit(db->txn, false);
833
883
VLOG_ERR_RL(&rl, "Failed to update remote status: %s",
834
884
ovsdb_error_to_string(error));
857
908
ovsdb_jsonrpc_server_set_remotes(jsonrpc, &resolved_remotes);
858
909
shash_destroy_free_data(&resolved_remotes);
861
stream_ssl_set_key_and_cert(query_db_string(dbs, n_dbs, private_key_file),
862
query_db_string(dbs, n_dbs, certificate_file));
863
stream_ssl_set_ca_cert_file(query_db_string(dbs, n_dbs, ca_cert_file),
911
return errors.string;
915
reconfigure_ssl(const struct shash *all_dbs)
917
struct ds errors = DS_EMPTY_INITIALIZER;
918
const char *resolved_private_key;
919
const char *resolved_certificate;
920
const char *resolved_ca_cert;
922
resolved_private_key = query_db_string(all_dbs, private_key_file, &errors);
923
resolved_certificate = query_db_string(all_dbs, certificate_file, &errors);
924
resolved_ca_cert = query_db_string(all_dbs, ca_cert_file, &errors);
926
stream_ssl_set_key_and_cert(resolved_private_key, resolved_certificate);
927
stream_ssl_set_ca_cert_file(resolved_ca_cert, bootstrap_ca_cert);
929
return errors.string;
933
report_error_if_changed(char *error, char **last_errorp)
936
if (!*last_errorp || strcmp(error, *last_errorp)) {
937
VLOG_WARN("%s", error);
939
*last_errorp = error;
958
1044
* that ovsdb-server services. */
960
1046
ovsdb_server_remove_remote(struct unixctl_conn *conn, int argc OVS_UNUSED,
961
const char *argv[], void *aux_)
1047
const char *argv[], void *config_)
963
struct remove_remote_aux *aux = aux_;
1049
struct server_config *config = config_;
964
1050
struct sset_node *node;
966
node = sset_find(aux->remotes, argv[1]);
1052
node = sset_find(config->remotes, argv[1]);
968
sset_delete(aux->remotes, node);
969
save_config(aux->config_tmpfile, aux->remotes);
1054
sset_delete(config->remotes, node);
1055
save_config(config);
970
1056
unixctl_command_reply(conn, NULL);
972
1058
unixctl_command_reply_error(conn, "no such remote");
1084
/* "ovsdb-server/add-db DB": adds the DB to ovsdb-server. */
1086
ovsdb_server_add_database(struct unixctl_conn *conn, int argc OVS_UNUSED,
1087
const char *argv[], void *config_)
1089
struct server_config *config = config_;
1090
const char *filename = argv[1];
1093
error = open_db(config, filename);
1095
save_config(config);
1096
unixctl_command_reply(conn, NULL);
1098
unixctl_command_reply_error(conn, error);
1104
ovsdb_server_remove_database(struct unixctl_conn *conn, int argc OVS_UNUSED,
1105
const char *argv[], void *config_)
1107
struct server_config *config = config_;
1108
struct shash_node *node;
1112
node = shash_find(config->all_dbs, argv[1]);
1114
unixctl_command_reply_error(conn, "Failed to find the database.");
1119
ok = ovsdb_jsonrpc_server_remove_db(config->jsonrpc, db->db);
1122
ovsdb_destroy(db->db);
1123
shash_delete(config->all_dbs, node);
1127
save_config(config);
1128
unixctl_command_reply(conn, NULL);
1132
ovsdb_server_list_databases(struct unixctl_conn *conn, int argc OVS_UNUSED,
1133
const char *argv[] OVS_UNUSED, void *all_dbs_)
1135
struct shash *all_dbs = all_dbs_;
1136
const struct shash_node **nodes;
1142
nodes = shash_sort(all_dbs);
1143
for (i = 0; i < shash_count(all_dbs); i++) {
1144
struct db *db = nodes[i]->data;
1145
ds_put_format(&s, "%s\n", db->db->schema->name);
1149
unixctl_command_reply(conn, ds_cstr(&s));
998
1154
parse_options(int *argcp, char **argvp[],
999
1155
struct sset *remotes, char **unixctl_pathp, char **run_command)
1114
1267
" --unixctl=SOCKET override default control socket name\n"
1115
1268
" -h, --help display this help message\n"
1116
1269
" -V, --version display version information\n");
1117
leak_checker_usage();
1118
1270
exit(EXIT_SUCCESS);
1121
/* Truncates and replaces the contents of 'config_file' by a representation
1273
static struct json *
1274
sset_to_json(const struct sset *sset)
1279
array = json_array_create_empty();
1280
SSET_FOR_EACH (s, sset) {
1281
json_array_add(array, json_string_create(s));
1286
/* Truncates and replaces the contents of 'config_file' by a representation of
1287
* 'remotes' and 'db_filenames'. */
1124
save_config(FILE *config_file, const struct sset *remotes)
1289
save_config__(FILE *config_file, const struct sset *remotes,
1290
const struct sset *db_filenames)
1130
1295
if (ftruncate(fileno(config_file), 0) == -1) {
1131
VLOG_FATAL("failed to truncate temporary file (%s)", strerror(errno));
1296
VLOG_FATAL("failed to truncate temporary file (%s)",
1297
ovs_strerror(errno));
1134
json = json_array_create_empty();
1135
SSET_FOR_EACH (remote, remotes) {
1136
json_array_add(json, json_string_create(remote));
1138
s = json_to_string(json, 0);
1300
obj = json_object_create();
1301
json_object_put(obj, "remotes", sset_to_json(remotes));
1302
json_object_put(obj, "db_filenames", sset_to_json(db_filenames));
1303
s = json_to_string(obj, 0);
1141
1306
if (fseek(config_file, 0, SEEK_SET) != 0
1142
1307
|| fputs(s, config_file) == EOF
1143
1308
|| fflush(config_file) == EOF) {
1144
VLOG_FATAL("failed to write temporary file (%s)", strerror(errno));
1309
VLOG_FATAL("failed to write temporary file (%s)", ovs_strerror(errno));
1149
/* Clears and replaces 'remotes' by a configuration read from 'config_file',
1150
* which must have been previously written by save_config(). */
1152
load_config(FILE *config_file, struct sset *remotes)
1314
/* Truncates and replaces the contents of 'config_file' by a representation of
1317
save_config(struct server_config *config)
1319
struct sset db_filenames;
1320
struct shash_node *node;
1322
sset_init(&db_filenames);
1323
SHASH_FOR_EACH (node, config->all_dbs) {
1324
struct db *db = node->data;
1325
sset_add(&db_filenames, db->filename);
1328
save_config__(config->config_tmpfile, config->remotes, &db_filenames);
1330
sset_destroy(&db_filenames);
1334
sset_from_json(struct sset *sset, const struct json *array)
1340
ovs_assert(array->type == JSON_ARRAY);
1341
for (i = 0; i < array->u.array.n; i++) {
1342
const struct json *elem = array->u.array.elems[i];
1343
sset_add(sset, json_string(elem));
1347
/* Clears and replaces 'remotes' and 'dbnames' by a configuration read from
1348
* 'config_file', which must have been previously written by save_config(). */
1350
load_config(FILE *config_file, struct sset *remotes, struct sset *db_filenames)
1154
1352
struct json *json;
1157
sset_clear(remotes);
1159
1354
if (fseek(config_file, 0, SEEK_SET) != 0) {
1160
VLOG_FATAL("seek failed in temporary file (%s)", strerror(errno));
1355
VLOG_FATAL("seek failed in temporary file (%s)", ovs_strerror(errno));
1162
1357
json = json_from_stream(config_file);
1163
1358
if (json->type == JSON_STRING) {
1164
1359
VLOG_FATAL("reading json failed (%s)", json_string(json));
1166
ovs_assert(json->type == JSON_ARRAY);
1167
for (i = 0; i < json->u.array.n; i++) {
1168
const struct json *remote = json->u.array.elems[i];
1169
sset_add(remotes, json_string(remote));
1361
ovs_assert(json->type == JSON_OBJECT);
1363
sset_from_json(remotes, shash_find_data(json_object(json), "remotes"));
1364
sset_from_json(db_filenames,
1365
shash_find_data(json_object(json), "db_filenames"));
1171
1366
json_destroy(json);