~james-page/ubuntu/saucy/openvswitch/1.12-snapshot

« back to all changes in this revision

Viewing changes to ovsdb/ovsdb-server.c

  • Committer: James Page
  • Date: 2013-08-21 10:16:57 UTC
  • mfrom: (1.1.20)
  • Revision ID: james.page@canonical.com-20130821101657-3o0z0qeiv5zkwlzi
New upstream snapshot

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
 
18
18
#include <errno.h>
19
19
#include <getopt.h>
 
20
#include <inttypes.h>
20
21
#include <signal.h>
21
22
#include <unistd.h>
22
23
 
31
32
#include "json.h"
32
33
#include "jsonrpc.h"
33
34
#include "jsonrpc-server.h"
34
 
#include "leak-checker.h"
35
35
#include "list.h"
36
36
#include "memory.h"
37
37
#include "ovsdb.h"
42
42
#include "process.h"
43
43
#include "row.h"
44
44
#include "simap.h"
 
45
#include "shash.h"
45
46
#include "stream-ssl.h"
46
47
#include "stream.h"
47
 
#include "stress.h"
48
48
#include "sset.h"
49
49
#include "table.h"
50
50
#include "timeval.h"
76
76
static unixctl_cb_func ovsdb_server_compact;
77
77
static unixctl_cb_func ovsdb_server_reconnect;
78
78
 
79
 
struct add_remote_aux {
 
79
struct server_config {
80
80
    struct sset *remotes;
81
 
    struct db *dbs;
82
 
    size_t n_dbs;
 
81
    struct shash *all_dbs;
83
82
    FILE *config_tmpfile;
 
83
    struct ovsdb_jsonrpc_server *jsonrpc;
84
84
};
85
85
static unixctl_cb_func ovsdb_server_add_remote;
86
 
 
87
 
struct remove_remote_aux {
88
 
    struct sset *remotes;
89
 
    FILE *config_tmpfile;
90
 
};
91
86
static unixctl_cb_func ovsdb_server_remove_remote;
92
87
static unixctl_cb_func ovsdb_server_list_remotes;
93
88
 
 
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;
 
92
 
 
93
static char *open_db(struct server_config *config, const char *filename);
 
94
 
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;
98
99
 
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);
102
105
 
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);
106
109
 
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);
109
115
 
110
116
int
111
117
main(int argc, char *argv[])
114
120
    char *run_command = NULL;
115
121
    struct unixctl_server *unixctl;
116
122
    struct ovsdb_jsonrpc_server *jsonrpc;
117
 
    struct sset remotes;
 
123
    struct sset remotes, db_filenames;
 
124
    const char *db_filename;
118
125
    struct process *run_process;
119
126
    bool exiting;
120
127
    int retval;
121
128
    long long int status_timer = LLONG_MIN;
122
 
    struct add_remote_aux add_remote_aux;
123
 
    struct remove_remote_aux remove_remote_aux;
124
129
    FILE *config_tmpfile;
125
 
 
126
 
    struct db *dbs;
127
 
    int n_dbs;
 
130
    struct server_config server_config;
 
131
    struct shash all_dbs;
 
132
    struct shash_node *node;
 
133
    char *remotes_error, *ssl_error;
 
134
    char *error;
128
135
    int i;
129
136
 
130
137
    proctitle_init(argc, argv);
131
138
    set_program_name(argv[0]);
132
 
    stress_init_command();
133
139
    signal(SIGPIPE, SIG_IGN);
134
140
    process_init();
135
141
 
144
150
    if (!config_tmpfile) {
145
151
        ovs_fatal(errno, "failed to create temporary file");
146
152
    }
147
 
    save_config(config_tmpfile, &remotes);
 
153
 
 
154
    sset_init(&db_filenames);
 
155
    if (argc > 0) {
 
156
        for (i = 0; i < argc; i++) {
 
157
            sset_add(&db_filenames, argv[i]);
 
158
         }
 
159
    } else {
 
160
        char *default_db = xasprintf("%s/conf.db", ovs_dbdir());
 
161
        sset_add(&db_filenames, default_db);
 
162
        free(default_db);
 
163
    }
 
164
 
 
165
    server_config.remotes = &remotes;
 
166
    server_config.config_tmpfile = config_tmpfile;
 
167
 
 
168
    save_config__(config_tmpfile, &remotes, &db_filenames);
148
169
 
149
170
    daemonize_start();
150
171
 
151
172
    /* Load the saved config. */
152
 
    load_config(config_tmpfile, &remotes);
153
 
 
154
 
    n_dbs = MAX(1, argc);
155
 
    dbs = xcalloc(n_dbs + 1, sizeof *dbs);
156
 
    if (argc > 0) {
157
 
        for (i = 0; i < argc; i++) {
158
 
            dbs[i].filename = argv[i];
159
 
        }
160
 
    } else {
161
 
        dbs[0].filename = xasprintf("%s/conf.db", ovs_dbdir());
162
 
    }
163
 
 
164
 
    for (i = 0; i < n_dbs; i++) {
165
 
        struct ovsdb_error *error;
166
 
 
167
 
        error = ovsdb_file_open(dbs[i].filename, false,
168
 
                                &dbs[i].db, &dbs[i].file);
169
 
        if (error) {
170
 
            ovs_fatal(0, "%s", ovsdb_error_to_string(error));
171
 
        }
172
 
    }
173
 
 
 
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);
 
175
 
 
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);
 
181
        if (error) {
 
182
            ovs_fatal(0, "%s", error);
179
183
        }
180
184
    }
181
 
    reconfigure_from_db(jsonrpc, dbs, n_dbs, &remotes);
 
185
 
 
186
    error = reconfigure_remotes(jsonrpc, &all_dbs, &remotes);
 
187
    if (!error) {
 
188
        error = reconfigure_ssl(&all_dbs);
 
189
    }
 
190
    if (error) {
 
191
        ovs_fatal(0, "%s", error);
 
192
    }
182
193
 
183
194
    retval = unixctl_server_create(unixctl_path, &unixctl);
184
195
    if (retval) {
193
204
        run_argv[2] = run_command;
194
205
        run_argv[3] = NULL;
195
206
 
196
 
        retval = process_start(run_argv, NULL, 0, NULL, 0, &run_process);
 
207
        retval = process_start(run_argv, &run_process);
197
208
        if (retval) {
198
209
            ovs_fatal(retval, "%s: process failed to start", run_command);
199
210
        }
212
223
 
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);
218
229
 
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);
225
 
 
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);
230
 
 
 
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);
233
236
 
 
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);
 
243
 
234
244
    exiting = false;
 
245
    ssl_error = NULL;
 
246
    remotes_error = NULL;
235
247
    while (!exiting) {
236
 
        int i;
237
 
 
238
248
        memory_run();
239
249
        if (memory_should_report()) {
240
250
            struct simap usage;
241
251
 
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);
246
257
            }
247
258
            memory_report(&usage);
248
259
            simap_destroy(&usage);
249
260
        }
250
261
 
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);
255
266
 
256
 
        reconfigure_from_db(jsonrpc, dbs, n_dbs, &remotes);
 
267
        report_error_if_changed(
 
268
            reconfigure_remotes(jsonrpc, &all_dbs, &remotes),
 
269
            &remotes_error);
 
270
        report_error_if_changed(reconfigure_ssl(&all_dbs), &ssl_error);
257
271
        ovsdb_jsonrpc_server_run(jsonrpc);
258
272
 
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());
261
276
        }
262
 
        if (run_process && process_exited(run_process)) {
263
 
            exiting = true;
 
277
        if (run_process) {
 
278
            process_run();
 
279
            if (process_exited(run_process)) {
 
280
                exiting = true;
 
281
            }
264
282
        }
265
283
 
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);
270
288
        }
271
289
 
272
290
        memory_wait();
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());
277
296
        }
278
297
        if (run_process) {
279
298
            process_wait(run_process);
285
304
        poll_block();
286
305
    }
287
306
    ovsdb_jsonrpc_server_destroy(jsonrpc);
288
 
    for (i = 0; i < n_dbs; i++) {
289
 
        ovsdb_destroy(dbs[i].db);
 
307
    SHASH_FOR_EACH(node, &all_dbs) {
 
308
        struct db *db = node->data;
 
309
        ovsdb_destroy(db->db);
290
310
    }
291
311
    sset_destroy(&remotes);
292
312
    unixctl_server_destroy(unixctl);
302
322
    return 0;
303
323
}
304
324
 
 
325
static char *
 
326
open_db(struct server_config *config, const char *filename)
 
327
{
 
328
    struct ovsdb_error *db_error;
 
329
    struct db *db;
 
330
    char *error;
 
331
 
 
332
    db = xzalloc(sizeof *db);
 
333
    db->filename = xstrdup(filename);
 
334
 
 
335
    db_error = ovsdb_file_open(db->filename, false, &db->db, &db->file);
 
336
    if (db_error) {
 
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);
 
340
    } else {
 
341
        shash_add_assert(config->all_dbs, db->db->schema->name, db);
 
342
        return NULL;
 
343
    }
 
344
 
 
345
    ovsdb_error_destroy(db_error);
 
346
    ovsdb_destroy(db->db);
 
347
    free(db->filename);
 
348
    free(db);
 
349
    return error;
 
350
}
 
351
 
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)
307
354
{
308
 
    size_t i;
 
355
    struct shash_node *node;
309
356
 
310
 
    for (i = 0; i < n_dbs; i++) {
311
 
        if (!strcmp(dbs[i].db->schema->name, db_name)) {
312
 
            return &dbs[i];
 
357
    SHASH_FOR_EACH(node, all_dbs) {
 
358
        struct db *db = node->data;
 
359
        if (!strcmp(db->db->schema->name, db_name)) {
 
360
            return db;
313
361
        }
314
362
    }
315
363
 
317
365
}
318
366
 
319
367
static char * WARN_UNUSED_RESULT
320
 
parse_db_column__(const struct db dbs[], size_t n_dbs,
 
368
parse_db_column__(const struct shash *all_dbs,
321
369
                  const char *name_, char *name,
322
370
                  const struct db **dbp,
323
371
                  const struct ovsdb_table **tablep,
324
372
                  const struct ovsdb_column **columnp)
325
373
{
326
 
    const char *table_name, *column_name;
 
374
    const char *db_name, *table_name, *column_name;
327
375
    const struct ovsdb_column *column;
328
376
    const struct ovsdb_table *table;
329
377
    const char *tokens[3];
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_);
343
391
    }
344
 
    if (tokens[2]) {
345
 
        const char *db_name = tokens[0];
346
 
        table_name = tokens[1];
347
 
        column_name = tokens[2];
348
 
 
349
 
        db = find_db(dbs, n_dbs, tokens[0]);
350
 
        if (!db) {
351
 
            return xasprintf("\"%s\": no database named %s", name_, db_name);
352
 
        }
353
 
    } else {
354
 
        if (n_dbs > 1) {
355
 
            return xasprintf("\"%s\": database name must be specified "
356
 
                             "(because multiple databases are configured)",
357
 
                             name_);
358
 
        }
359
 
 
360
 
        table_name = tokens[0];
361
 
        column_name = tokens[1];
362
 
        db = &dbs[0];
 
392
 
 
393
    db_name = tokens[0];
 
394
    table_name = tokens[1];
 
395
    column_name = tokens[2];
 
396
 
 
397
    db = find_db(all_dbs, tokens[0]);
 
398
    if (!db) {
 
399
        return xasprintf("\"%s\": no database named %s", name_, db_name);
363
400
    }
364
401
 
365
402
    table = ovsdb_get_table(db->db, table_name);
382
419
/* Returns NULL if successful, otherwise a malloc()'d string describing the
383
420
 * error. */
384
421
static char * WARN_UNUSED_RESULT
385
 
parse_db_column(const struct db dbs[], size_t n_dbs,
 
422
parse_db_column(const struct shash *all_dbs,
386
423
                const char *name_,
387
424
                const struct db **dbp,
388
425
                const struct ovsdb_table **tablep,
389
426
                const struct ovsdb_column **columnp)
390
427
{
391
428
    char *name = xstrdup(name_);
392
 
    char *retval = parse_db_column__(dbs, n_dbs, name_, name,
 
429
    char *retval = parse_db_column__(all_dbs, name_, name,
393
430
                                     dbp, tablep, columnp);
394
431
    free(name);
395
432
    return retval;
398
435
/* Returns NULL if successful, otherwise a malloc()'d string describing the
399
436
 * error. */
400
437
static char * WARN_UNUSED_RESULT
401
 
parse_db_string_column(const struct db dbs[], size_t n_dbs,
 
438
parse_db_string_column(const struct shash *all_dbs,
402
439
                       const char *name,
403
440
                       const struct db **dbp,
404
441
                       const struct ovsdb_table **tablep,
406
443
{
407
444
    char *retval;
408
445
 
409
 
    retval = parse_db_column(dbs, n_dbs, name, dbp, tablep, columnp);
 
446
    retval = parse_db_column(all_dbs, name, dbp, tablep, columnp);
410
447
    if (retval) {
411
448
        return retval;
412
449
    }
421
458
    return NULL;
422
459
}
423
460
 
424
 
static OVS_UNUSED const char *
425
 
query_db_string(const struct db dbs[], size_t n_dbs, const char *name)
 
461
static const char *
 
462
query_db_string(const struct shash *all_dbs, const char *name,
 
463
                struct ds *errors)
426
464
{
427
465
    if (!name || strncmp(name, "db:", 3)) {
428
466
        return name;
433
471
        const struct db *db;
434
472
        char *retval;
435
473
 
436
 
        retval = parse_db_string_column(dbs, n_dbs, name,
 
474
        retval = parse_db_string_column(all_dbs, name,
437
475
                                        &db, &table, &column);
438
476
        if (retval) {
439
 
            ovs_fatal(0, "%s", retval);
 
477
            ds_put_format(errors, "%s\n", retval);
 
478
            return NULL;
440
479
        }
441
480
 
442
481
        HMAP_FOR_EACH (row, hmap_node, &table->rows) {
660
699
}
661
700
 
662
701
static void
663
 
query_db_remotes(const char *name, const struct db dbs[], size_t n_dbs,
664
 
                 struct shash *remotes)
 
702
query_db_remotes(const char *name, const struct shash *all_dbs,
 
703
                 struct shash *remotes, struct ds *errors)
665
704
{
666
705
    const struct ovsdb_column *column;
667
706
    const struct ovsdb_table *table;
669
708
    const struct db *db;
670
709
    char *retval;
671
710
 
672
 
    retval = parse_db_column(dbs, n_dbs, name, &db, &table, &column);
 
711
    retval = parse_db_column(all_dbs, name, &db, &table, &column);
673
712
    if (retval) {
674
 
        ovs_fatal(0, "%s", retval);
 
713
        ds_put_format(errors, "%s\n", retval);
 
714
        free(retval);
 
715
        return;
675
716
    }
676
717
 
677
718
    if (column->type.key.type == OVSDB_TYPE_STRING
713
754
    struct ovsdb_jsonrpc_remote_status status;
714
755
    struct ovsdb_row *rw_row;
715
756
    const char *target;
716
 
    char *keys[8], *values[8];
 
757
    char *keys[9], *values[9];
717
758
    size_t n = 0;
718
759
 
719
760
    /* Get the "target" (protocol/host/port) spec. */
760
801
        keys[n] = xstrdup("n_connections");
761
802
        values[n++] = xasprintf("%d", status.n_connections);
762
803
    }
 
804
    if (status.bound_port != htons(0)) {
 
805
        keys[n] = xstrdup("bound_port");
 
806
        values[n++] = xasprintf("%"PRIu16, ntohs(status.bound_port));
 
807
    }
763
808
    write_string_string_column(rw_row, "status", keys, values, n);
764
809
 
765
810
    ovsdb_jsonrpc_server_free_remote_status(&status);
766
811
}
767
812
 
768
813
static void
769
 
update_remote_rows(const struct db dbs[], size_t n_dbs,
 
814
update_remote_rows(const struct shash *all_dbs,
770
815
                   const char *remote_name,
771
816
                   const struct ovsdb_jsonrpc_server *jsonrpc)
772
817
{
780
825
        return;
781
826
    }
782
827
 
783
 
    retval = parse_db_column(dbs, n_dbs, remote_name, &db, &table, &column);
 
828
    retval = parse_db_column(all_dbs, remote_name, &db, &table, &column);
784
829
    if (retval) {
785
 
        ovs_fatal(0, "%s", retval);
 
830
        free(retval);
 
831
        return;
786
832
    }
787
833
 
788
834
    if (column->type.key.type != OVSDB_TYPE_UUID
812
858
static void
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)
816
862
{
817
863
    static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
818
864
    const char *remote;
819
 
    size_t i;
 
865
    struct db *db;
 
866
    struct shash_node *node;
820
867
 
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) {
 
869
        db = node->data;
 
870
        db->txn = ovsdb_txn_create(db->db);
823
871
    }
824
872
 
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);
828
876
    }
829
877
 
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;
 
880
        db = node->data;
 
881
        error = ovsdb_txn_commit(db->txn, false);
832
882
        if (error) {
833
883
            VLOG_ERR_RL(&rl, "Failed to update remote status: %s",
834
884
                        ovsdb_error_to_string(error));
837
887
    }
838
888
}
839
889
 
840
 
/* Reconfigures ovsdb-server based on information in the database. */
841
 
static void
842
 
reconfigure_from_db(struct ovsdb_jsonrpc_server *jsonrpc,
843
 
                    const struct db dbs[], size_t n_dbs, struct sset *remotes)
 
890
/* Reconfigures ovsdb-server's remotes based on information in the database. */
 
891
static char *
 
892
reconfigure_remotes(struct ovsdb_jsonrpc_server *jsonrpc,
 
893
                    const struct shash *all_dbs, struct sset *remotes)
844
894
{
 
895
    struct ds errors = DS_EMPTY_INITIALIZER;
845
896
    struct shash resolved_remotes;
846
897
    const char *name;
847
898
 
849
900
    shash_init(&resolved_remotes);
850
901
    SSET_FOR_EACH (name, remotes) {
851
902
        if (!strncmp(name, "db:", 3)) {
852
 
            query_db_remotes(name, dbs, n_dbs, &resolved_remotes);
 
903
            query_db_remotes(name, all_dbs, &resolved_remotes, &errors);
853
904
        } else {
854
905
            add_remote(&resolved_remotes, name);
855
906
        }
857
908
    ovsdb_jsonrpc_server_set_remotes(jsonrpc, &resolved_remotes);
858
909
    shash_destroy_free_data(&resolved_remotes);
859
910
 
860
 
    /* Configure SSL. */
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),
864
 
                                bootstrap_ca_cert);
 
911
    return errors.string;
 
912
}
 
913
 
 
914
static char *
 
915
reconfigure_ssl(const struct shash *all_dbs)
 
916
{
 
917
    struct ds errors = DS_EMPTY_INITIALIZER;
 
918
    const char *resolved_private_key;
 
919
    const char *resolved_certificate;
 
920
    const char *resolved_ca_cert;
 
921
 
 
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);
 
925
 
 
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);
 
928
 
 
929
    return errors.string;
 
930
}
 
931
 
 
932
static void
 
933
report_error_if_changed(char *error, char **last_errorp)
 
934
{
 
935
    if (error) {
 
936
        if (!*last_errorp || strcmp(error, *last_errorp)) {
 
937
            VLOG_WARN("%s", error);
 
938
            free(*last_errorp);
 
939
            *last_errorp = error;
 
940
            return;
 
941
        }
 
942
        free(error);
 
943
    } else {
 
944
        free(*last_errorp);
 
945
        *last_errorp = NULL;
 
946
    }
865
947
}
866
948
 
867
949
static void
878
960
ovsdb_server_compact(struct unixctl_conn *conn, int argc,
879
961
                     const char *argv[], void *dbs_)
880
962
{
881
 
    struct db *dbs = dbs_;
 
963
    struct shash *all_dbs = dbs_;
882
964
    struct ds reply;
883
965
    struct db *db;
 
966
    struct shash_node *node;
884
967
    int n = 0;
885
968
 
886
969
    ds_init(&reply);
887
 
    for (db = dbs; db->filename != NULL; db++) {
888
 
        const char *name = db->db->schema->name;
 
970
    SHASH_FOR_EACH(node, all_dbs) {
 
971
        const char *name;
 
972
 
 
973
        db = node->data;
 
974
        name = db->db->schema->name;
889
975
 
890
976
        if (argc < 2 || !strcmp(argv[1], name)) {
891
977
            struct ovsdb_error *error;
929
1015
 * ovsdb-server services. */
930
1016
static void
931
1017
ovsdb_server_add_remote(struct unixctl_conn *conn, int argc OVS_UNUSED,
932
 
                        const char *argv[], void *aux_)
 
1018
                        const char *argv[], void *config_)
933
1019
{
934
 
    struct add_remote_aux *aux = aux_;
 
1020
    struct server_config *config = config_;
935
1021
    const char *remote = argv[1];
936
1022
 
937
1023
    const struct ovsdb_column *column;
941
1027
 
942
1028
    retval = (strncmp("db:", remote, 3)
943
1029
              ? NULL
944
 
              : parse_db_column(aux->dbs, aux->n_dbs, remote,
 
1030
              : parse_db_column(config->all_dbs, remote,
945
1031
                                &db, &table, &column));
946
1032
    if (!retval) {
947
 
        if (sset_add(aux->remotes, remote)) {
948
 
            save_config(aux->config_tmpfile, aux->remotes);
 
1033
        if (sset_add(config->remotes, remote)) {
 
1034
            save_config(config);
949
1035
        }
950
1036
        unixctl_command_reply(conn, NULL);
951
1037
    } else {
958
1044
 * that ovsdb-server services. */
959
1045
static void
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_)
962
1048
{
963
 
    struct remove_remote_aux *aux = aux_;
 
1049
    struct server_config *config = config_;
964
1050
    struct sset_node *node;
965
1051
 
966
 
    node = sset_find(aux->remotes, argv[1]);
 
1052
    node = sset_find(config->remotes, argv[1]);
967
1053
    if (node) {
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);
971
1057
    } else {
972
1058
        unixctl_command_reply_error(conn, "no such remote");
994
1080
    ds_destroy(&s);
995
1081
}
996
1082
 
 
1083
 
 
1084
/* "ovsdb-server/add-db DB": adds the DB to ovsdb-server. */
 
1085
static void
 
1086
ovsdb_server_add_database(struct unixctl_conn *conn, int argc OVS_UNUSED,
 
1087
                          const char *argv[], void *config_)
 
1088
{
 
1089
    struct server_config *config = config_;
 
1090
    const char *filename = argv[1];
 
1091
    char *error;
 
1092
 
 
1093
    error = open_db(config, filename);
 
1094
    if (!error) {
 
1095
        save_config(config);
 
1096
        unixctl_command_reply(conn, NULL);
 
1097
    } else {
 
1098
        unixctl_command_reply_error(conn, error);
 
1099
        free(error);
 
1100
    }
 
1101
}
 
1102
 
 
1103
static void
 
1104
ovsdb_server_remove_database(struct unixctl_conn *conn, int argc OVS_UNUSED,
 
1105
                             const char *argv[], void *config_)
 
1106
{
 
1107
    struct server_config *config = config_;
 
1108
    struct shash_node *node;
 
1109
    struct db *db;
 
1110
    bool ok;
 
1111
 
 
1112
    node = shash_find(config->all_dbs, argv[1]);
 
1113
    if (!node)  {
 
1114
        unixctl_command_reply_error(conn, "Failed to find the database.");
 
1115
        return;
 
1116
    }
 
1117
    db = node->data;
 
1118
 
 
1119
    ok = ovsdb_jsonrpc_server_remove_db(config->jsonrpc, db->db);
 
1120
    ovs_assert(ok);
 
1121
 
 
1122
    ovsdb_destroy(db->db);
 
1123
    shash_delete(config->all_dbs, node);
 
1124
    free(db->filename);
 
1125
    free(db);
 
1126
 
 
1127
    save_config(config);
 
1128
    unixctl_command_reply(conn, NULL);
 
1129
}
 
1130
 
 
1131
static void
 
1132
ovsdb_server_list_databases(struct unixctl_conn *conn, int argc OVS_UNUSED,
 
1133
                            const char *argv[] OVS_UNUSED, void *all_dbs_)
 
1134
{
 
1135
    struct shash *all_dbs = all_dbs_;
 
1136
    const struct shash_node **nodes;
 
1137
    struct ds s;
 
1138
    size_t i;
 
1139
 
 
1140
    ds_init(&s);
 
1141
 
 
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);
 
1146
    }
 
1147
    free(nodes);
 
1148
 
 
1149
    unixctl_command_reply(conn, ds_cstr(&s));
 
1150
    ds_destroy(&s);
 
1151
}
 
1152
 
997
1153
static void
998
1154
parse_options(int *argcp, char **argvp[],
999
1155
              struct sset *remotes, char **unixctl_pathp, char **run_command)
1005
1161
        OPT_BOOTSTRAP_CA_CERT,
1006
1162
        OPT_ENABLE_DUMMY,
1007
1163
        VLOG_OPTION_ENUMS,
1008
 
        LEAK_CHECKER_OPTION_ENUMS,
1009
1164
        DAEMON_OPTION_ENUMS
1010
1165
    };
1011
 
    static struct option long_options[] = {
 
1166
    static const struct option long_options[] = {
1012
1167
        {"remote",      required_argument, NULL, OPT_REMOTE},
1013
1168
        {"unixctl",     required_argument, NULL, OPT_UNIXCTL},
1014
1169
        {"run",         required_argument, NULL, OPT_RUN},
1016
1171
        {"version",     no_argument, NULL, 'V'},
1017
1172
        DAEMON_LONG_OPTIONS,
1018
1173
        VLOG_LONG_OPTIONS,
1019
 
        LEAK_CHECKER_LONG_OPTIONS,
1020
1174
        {"bootstrap-ca-cert", required_argument, NULL, OPT_BOOTSTRAP_CA_CERT},
1021
1175
        {"private-key", required_argument, NULL, 'p'},
1022
1176
        {"certificate", required_argument, NULL, 'c'},
1059
1213
 
1060
1214
        VLOG_OPTION_HANDLERS
1061
1215
        DAEMON_OPTION_HANDLERS
1062
 
        LEAK_CHECKER_OPTION_HANDLERS
1063
1216
 
1064
1217
        case 'p':
1065
1218
            private_key_file = optarg;
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);
1119
1271
}
1120
1272
 
1121
 
/* Truncates and replaces the contents of 'config_file' by a representation
1122
 
 * of 'remotes'. */
 
1273
static struct json *
 
1274
sset_to_json(const struct sset *sset)
 
1275
{
 
1276
    struct json *array;
 
1277
    const char *s;
 
1278
 
 
1279
    array = json_array_create_empty();
 
1280
    SSET_FOR_EACH (s, sset) {
 
1281
        json_array_add(array, json_string_create(s));
 
1282
    }
 
1283
    return array;
 
1284
}
 
1285
 
 
1286
/* Truncates and replaces the contents of 'config_file' by a representation of
 
1287
 * 'remotes' and 'db_filenames'. */
1123
1288
static void
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)
1125
1291
{
1126
 
    const char *remote;
1127
 
    struct json *json;
 
1292
    struct json *obj;
1128
1293
    char *s;
1129
1294
 
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));
1132
1298
    }
1133
1299
 
1134
 
    json = json_array_create_empty();
1135
 
    SSET_FOR_EACH (remote, remotes) {
1136
 
        json_array_add(json, json_string_create(remote));
1137
 
    }
1138
 
    s = json_to_string(json, 0);
1139
 
    json_destroy(json);
 
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);
 
1304
    json_destroy(obj);
1140
1305
 
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));
1145
1310
    }
1146
1311
    free(s);
1147
1312
}
1148
1313
 
1149
 
/* Clears and replaces 'remotes' by a configuration read from 'config_file',
1150
 
 * which must have been previously written by save_config(). */
1151
 
static void
1152
 
load_config(FILE *config_file, struct sset *remotes)
 
1314
/* Truncates and replaces the contents of 'config_file' by a representation of
 
1315
 * 'config'. */
 
1316
static void
 
1317
save_config(struct server_config *config)
 
1318
{
 
1319
    struct sset db_filenames;
 
1320
    struct shash_node *node;
 
1321
 
 
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);
 
1326
    }
 
1327
 
 
1328
    save_config__(config->config_tmpfile, config->remotes, &db_filenames);
 
1329
 
 
1330
    sset_destroy(&db_filenames);
 
1331
}
 
1332
 
 
1333
static void
 
1334
sset_from_json(struct sset *sset, const struct json *array)
 
1335
{
 
1336
    size_t i;
 
1337
 
 
1338
    sset_clear(sset);
 
1339
 
 
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));
 
1344
    }
 
1345
}
 
1346
 
 
1347
/* Clears and replaces 'remotes' and 'dbnames' by a configuration read from
 
1348
 * 'config_file', which must have been previously written by save_config(). */
 
1349
static void
 
1350
load_config(FILE *config_file, struct sset *remotes, struct sset *db_filenames)
1153
1351
{
1154
1352
    struct json *json;
1155
 
    size_t i;
1156
 
 
1157
 
    sset_clear(remotes);
1158
1353
 
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));
1161
1356
    }
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));
1165
1360
    }
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));
1170
 
    }
 
1361
    ovs_assert(json->type == JSON_OBJECT);
 
1362
 
 
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);
1172
1367
}