1 /* Copyright (c) 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
25 #include "command-line.h"
29 #include "dynamic-string.h"
34 #include "jsonrpc-server.h"
35 #include "leak-checker.h"
39 #include "ovsdb-data.h"
40 #include "ovsdb-types.h"
41 #include "ovsdb-error.h"
42 #include "poll-loop.h"
46 #include "stream-ssl.h"
52 #include "transaction.h"
58 VLOG_DEFINE_THIS_MODULE(ovsdb_server
);
61 /* Initialized in main(). */
63 struct ovsdb_file
*file
;
66 /* Only used by update_remote_status(). */
67 struct ovsdb_txn
*txn
;
70 /* SSL configuration. */
71 static char *private_key_file
;
72 static char *certificate_file
;
73 static char *ca_cert_file
;
74 static bool bootstrap_ca_cert
;
76 static unixctl_cb_func ovsdb_server_exit
;
77 static unixctl_cb_func ovsdb_server_compact
;
78 static unixctl_cb_func ovsdb_server_reconnect
;
80 struct add_remote_aux
{
85 static unixctl_cb_func ovsdb_server_add_remote
;
86 static unixctl_cb_func ovsdb_server_remove_remote
;
87 static unixctl_cb_func ovsdb_server_list_remotes
;
89 static void parse_options(int *argc
, char **argvp
[],
90 struct sset
*remotes
, char **unixctl_pathp
,
92 static void usage(void) NO_RETURN
;
94 static void reconfigure_from_db(struct ovsdb_jsonrpc_server
*jsonrpc
,
95 const struct db dbs
[], size_t n_dbs
,
96 struct sset
*remotes
);
98 static void update_remote_status(const struct ovsdb_jsonrpc_server
*jsonrpc
,
99 const struct sset
*remotes
,
100 struct db dbs
[], size_t n_dbs
);
103 main(int argc
, char *argv
[])
105 char *unixctl_path
= NULL
;
106 char *run_command
= NULL
;
107 struct unixctl_server
*unixctl
;
108 struct ovsdb_jsonrpc_server
*jsonrpc
;
110 struct process
*run_process
;
113 long long int status_timer
= LLONG_MIN
;
114 struct add_remote_aux add_remote_aux
;
120 proctitle_init(argc
, argv
);
121 set_program_name(argv
[0]);
122 stress_init_command();
123 signal(SIGPIPE
, SIG_IGN
);
126 parse_options(&argc
, &argv
, &remotes
, &unixctl_path
, &run_command
);
130 n_dbs
= MAX(1, argc
);
131 dbs
= xcalloc(n_dbs
+ 1, sizeof *dbs
);
133 for (i
= 0; i
< argc
; i
++) {
134 dbs
[i
].filename
= argv
[i
];
137 dbs
[0].filename
= xasprintf("%s/conf.db", ovs_dbdir());
140 for (i
= 0; i
< n_dbs
; i
++) {
141 struct ovsdb_error
*error
;
143 error
= ovsdb_file_open(dbs
[i
].filename
, false,
144 &dbs
[i
].db
, &dbs
[i
].file
);
146 ovs_fatal(0, "%s", ovsdb_error_to_string(error
));
150 jsonrpc
= ovsdb_jsonrpc_server_create();
151 for (i
= 0; i
< n_dbs
; i
++) {
152 if (!ovsdb_jsonrpc_server_add_db(jsonrpc
, dbs
[i
].db
)) {
153 ovs_fatal(0, "%s: duplicate database name",
154 dbs
[i
].db
->schema
->name
);
157 reconfigure_from_db(jsonrpc
, dbs
, n_dbs
, &remotes
);
159 retval
= unixctl_server_create(unixctl_path
, &unixctl
);
167 run_argv
[0] = "/bin/sh";
169 run_argv
[2] = run_command
;
172 retval
= process_start(run_argv
, &run_process
);
174 ovs_fatal(retval
, "%s: process failed to start", run_command
);
180 daemonize_complete();
183 /* ovsdb-server is usually a long-running process, in which case it
184 * makes plenty of sense to log the version, but --run makes
185 * ovsdb-server more like a command-line tool, so skip it. */
186 VLOG_INFO("%s (Open vSwitch) %s", program_name
, VERSION
);
189 unixctl_command_register("exit", "", 0, 0, ovsdb_server_exit
, &exiting
);
190 unixctl_command_register("ovsdb-server/compact", "", 0, 1,
191 ovsdb_server_compact
, dbs
);
192 unixctl_command_register("ovsdb-server/reconnect", "", 0, 0,
193 ovsdb_server_reconnect
, jsonrpc
);
195 add_remote_aux
.remotes
= &remotes
;
196 add_remote_aux
.dbs
= dbs
;
197 add_remote_aux
.n_dbs
= n_dbs
;
198 unixctl_command_register("ovsdb-server/add-remote", "REMOTE", 1, 1,
199 ovsdb_server_add_remote
, &add_remote_aux
);
200 unixctl_command_register("ovsdb-server/remove-remote", "REMOTE", 1, 1,
201 ovsdb_server_remove_remote
, &remotes
);
202 unixctl_command_register("ovsdb-server/list-remotes", "", 0, 0,
203 ovsdb_server_list_remotes
, &remotes
);
210 if (memory_should_report()) {
214 ovsdb_jsonrpc_server_get_memory_usage(jsonrpc
, &usage
);
215 for (i
= 0; i
< n_dbs
; i
++) {
216 ovsdb_get_memory_usage(dbs
[i
].db
, &usage
);
218 memory_report(&usage
);
219 simap_destroy(&usage
);
222 /* Run unixctl_server_run() before reconfigure_from_db() because
223 * ovsdb-server/add-remote and ovsdb-server/remove-remote can change
224 * the set of remotes that reconfigure_from_db() uses. */
225 unixctl_server_run(unixctl
);
227 reconfigure_from_db(jsonrpc
, dbs
, n_dbs
, &remotes
);
228 ovsdb_jsonrpc_server_run(jsonrpc
);
230 for (i
= 0; i
< n_dbs
; i
++) {
231 ovsdb_trigger_run(dbs
[i
].db
, time_msec());
235 if (process_exited(run_process
)) {
240 /* update Manager status(es) every 5 seconds */
241 if (time_msec() >= status_timer
) {
242 status_timer
= time_msec() + 5000;
243 update_remote_status(jsonrpc
, &remotes
, dbs
, n_dbs
);
247 ovsdb_jsonrpc_server_wait(jsonrpc
);
248 unixctl_server_wait(unixctl
);
249 for (i
= 0; i
< n_dbs
; i
++) {
250 ovsdb_trigger_wait(dbs
[i
].db
, time_msec());
253 process_wait(run_process
);
256 poll_immediate_wake();
258 poll_timer_wait_until(status_timer
);
261 ovsdb_jsonrpc_server_destroy(jsonrpc
);
262 for (i
= 0; i
< n_dbs
; i
++) {
263 ovsdb_destroy(dbs
[i
].db
);
265 sset_destroy(&remotes
);
266 unixctl_server_destroy(unixctl
);
268 if (run_process
&& process_exited(run_process
)) {
269 int status
= process_status(run_process
);
271 ovs_fatal(0, "%s: child exited, %s",
272 run_command
, process_status_msg(status
));
279 static const struct db
*
280 find_db(const struct db dbs
[], size_t n_dbs
, const char *db_name
)
284 for (i
= 0; i
< n_dbs
; i
++) {
285 if (!strcmp(dbs
[i
].db
->schema
->name
, db_name
)) {
293 static char * WARN_UNUSED_RESULT
294 parse_db_column__(const struct db dbs
[], size_t n_dbs
,
295 const char *name_
, char *name
,
296 const struct db
**dbp
,
297 const struct ovsdb_table
**tablep
,
298 const struct ovsdb_column
**columnp
)
300 const char *table_name
, *column_name
;
301 const struct ovsdb_column
*column
;
302 const struct ovsdb_table
*table
;
303 const char *tokens
[3];
304 char *save_ptr
= NULL
;
311 strtok_r(name
, ":", &save_ptr
); /* "db:" */
312 tokens
[0] = strtok_r(NULL
, ",", &save_ptr
);
313 tokens
[1] = strtok_r(NULL
, ",", &save_ptr
);
314 tokens
[2] = strtok_r(NULL
, ",", &save_ptr
);
315 if (!tokens
[0] || !tokens
[1]) {
316 return xasprintf("\"%s\": invalid syntax", name_
);
319 const char *db_name
= tokens
[0];
320 table_name
= tokens
[1];
321 column_name
= tokens
[2];
323 db
= find_db(dbs
, n_dbs
, tokens
[0]);
325 return xasprintf("\"%s\": no database named %s", name_
, db_name
);
329 return xasprintf("\"%s\": database name must be specified "
330 "(because multiple databases are configured)",
334 table_name
= tokens
[0];
335 column_name
= tokens
[1];
339 table
= ovsdb_get_table(db
->db
, table_name
);
341 return xasprintf("\"%s\": no table named %s", name_
, table_name
);
344 column
= ovsdb_table_schema_get_column(table
->schema
, column_name
);
346 return xasprintf("\"%s\": table \"%s\" has no column \"%s\"",
347 name_
, table_name
, column_name
);
356 /* Returns NULL if successful, otherwise a malloc()'d string describing the
358 static char * WARN_UNUSED_RESULT
359 parse_db_column(const struct db dbs
[], size_t n_dbs
,
361 const struct db
**dbp
,
362 const struct ovsdb_table
**tablep
,
363 const struct ovsdb_column
**columnp
)
365 char *name
= xstrdup(name_
);
366 char *retval
= parse_db_column__(dbs
, n_dbs
, name_
, name
,
367 dbp
, tablep
, columnp
);
372 /* Returns NULL if successful, otherwise a malloc()'d string describing the
374 static char * WARN_UNUSED_RESULT
375 parse_db_string_column(const struct db dbs
[], size_t n_dbs
,
377 const struct db
**dbp
,
378 const struct ovsdb_table
**tablep
,
379 const struct ovsdb_column
**columnp
)
383 retval
= parse_db_column(dbs
, n_dbs
, name
, dbp
, tablep
, columnp
);
388 if ((*columnp
)->type
.key
.type
!= OVSDB_TYPE_STRING
389 || (*columnp
)->type
.value
.type
!= OVSDB_TYPE_VOID
) {
390 return xasprintf("\"%s\": table \"%s\" column \"%s\" is "
391 "not string or set of strings",
392 name
, (*tablep
)->schema
->name
, (*columnp
)->name
);
398 static OVS_UNUSED
const char *
399 query_db_string(const struct db dbs
[], size_t n_dbs
, const char *name
)
401 if (!name
|| strncmp(name
, "db:", 3)) {
404 const struct ovsdb_column
*column
;
405 const struct ovsdb_table
*table
;
406 const struct ovsdb_row
*row
;
410 retval
= parse_db_string_column(dbs
, n_dbs
, name
,
411 &db
, &table
, &column
);
413 ovs_fatal(0, "%s", retval
);
416 HMAP_FOR_EACH (row
, hmap_node
, &table
->rows
) {
417 const struct ovsdb_datum
*datum
;
420 datum
= &row
->fields
[column
->index
];
421 for (i
= 0; i
< datum
->n
; i
++) {
422 if (datum
->keys
[i
].string
[0]) {
423 return datum
->keys
[i
].string
;
431 static struct ovsdb_jsonrpc_options
*
432 add_remote(struct shash
*remotes
, const char *target
)
434 struct ovsdb_jsonrpc_options
*options
;
436 options
= shash_find_data(remotes
, target
);
438 options
= ovsdb_jsonrpc_default_options(target
);
439 shash_add(remotes
, target
, options
);
445 static struct ovsdb_datum
*
446 get_datum(struct ovsdb_row
*row
, const char *column_name
,
447 const enum ovsdb_atomic_type key_type
,
448 const enum ovsdb_atomic_type value_type
,
451 static struct vlog_rate_limit rl
= VLOG_RATE_LIMIT_INIT(1, 1);
452 const struct ovsdb_table_schema
*schema
= row
->table
->schema
;
453 const struct ovsdb_column
*column
;
455 column
= ovsdb_table_schema_get_column(schema
, column_name
);
457 VLOG_DBG_RL(&rl
, "Table `%s' has no `%s' column",
458 schema
->name
, column_name
);
462 if (column
->type
.key
.type
!= key_type
463 || column
->type
.value
.type
!= value_type
464 || column
->type
.n_max
!= n_max
) {
465 if (!VLOG_DROP_DBG(&rl
)) {
466 char *type_name
= ovsdb_type_to_english(&column
->type
);
467 VLOG_DBG("Table `%s' column `%s' has type %s, not expected "
468 "key type %s, value type %s, max elements %zd.",
469 schema
->name
, column_name
, type_name
,
470 ovsdb_atomic_type_to_string(key_type
),
471 ovsdb_atomic_type_to_string(value_type
),
478 return &row
->fields
[column
->index
];
481 /* Read string-string key-values from a map. Returns the value associated with
482 * 'key', if found, or NULL */
484 read_map_string_column(const struct ovsdb_row
*row
, const char *column_name
,
487 const struct ovsdb_datum
*datum
;
488 union ovsdb_atom
*atom_key
= NULL
, *atom_value
= NULL
;
491 datum
= get_datum(CONST_CAST(struct ovsdb_row
*, row
), column_name
,
492 OVSDB_TYPE_STRING
, OVSDB_TYPE_STRING
, UINT_MAX
);
498 for (i
= 0; i
< datum
->n
; i
++) {
499 atom_key
= &datum
->keys
[i
];
500 if (!strcmp(atom_key
->string
, key
)){
501 atom_value
= &datum
->values
[i
];
506 return atom_value
? atom_value
->string
: NULL
;
509 static const union ovsdb_atom
*
510 read_column(const struct ovsdb_row
*row
, const char *column_name
,
511 enum ovsdb_atomic_type type
)
513 const struct ovsdb_datum
*datum
;
515 datum
= get_datum(CONST_CAST(struct ovsdb_row
*, row
), column_name
, type
,
517 return datum
&& datum
->n
? datum
->keys
: NULL
;
521 read_integer_column(const struct ovsdb_row
*row
, const char *column_name
,
522 long long int *integerp
)
524 const union ovsdb_atom
*atom
;
526 atom
= read_column(row
, column_name
, OVSDB_TYPE_INTEGER
);
527 *integerp
= atom
? atom
->integer
: 0;
532 read_string_column(const struct ovsdb_row
*row
, const char *column_name
,
533 const char **stringp
)
535 const union ovsdb_atom
*atom
;
537 atom
= read_column(row
, column_name
, OVSDB_TYPE_STRING
);
538 *stringp
= atom
? atom
->string
: NULL
;
543 write_bool_column(struct ovsdb_row
*row
, const char *column_name
, bool value
)
545 const struct ovsdb_column
*column
;
546 struct ovsdb_datum
*datum
;
548 column
= ovsdb_table_schema_get_column(row
->table
->schema
, column_name
);
549 datum
= get_datum(row
, column_name
, OVSDB_TYPE_BOOLEAN
,
556 ovsdb_datum_destroy(datum
, &column
->type
);
559 datum
->keys
= xmalloc(sizeof *datum
->keys
);
560 datum
->values
= NULL
;
563 datum
->keys
[0].boolean
= value
;
567 write_string_string_column(struct ovsdb_row
*row
, const char *column_name
,
568 char **keys
, char **values
, size_t n
)
570 const struct ovsdb_column
*column
;
571 struct ovsdb_datum
*datum
;
574 column
= ovsdb_table_schema_get_column(row
->table
->schema
, column_name
);
575 datum
= get_datum(row
, column_name
, OVSDB_TYPE_STRING
, OVSDB_TYPE_STRING
,
578 for (i
= 0; i
< n
; i
++) {
585 /* Free existing data. */
586 ovsdb_datum_destroy(datum
, &column
->type
);
588 /* Allocate space for new values. */
590 datum
->keys
= xmalloc(n
* sizeof *datum
->keys
);
591 datum
->values
= xmalloc(n
* sizeof *datum
->values
);
593 for (i
= 0; i
< n
; ++i
) {
594 datum
->keys
[i
].string
= keys
[i
];
595 datum
->values
[i
].string
= values
[i
];
598 /* Sort and check constraints. */
599 ovsdb_datum_sort_assert(datum
, column
->type
.key
.type
);
602 /* Adds a remote and options to 'remotes', based on the Manager table row in
605 add_manager_options(struct shash
*remotes
, const struct ovsdb_row
*row
)
607 static struct vlog_rate_limit rl
= VLOG_RATE_LIMIT_INIT(1, 1);
608 struct ovsdb_jsonrpc_options
*options
;
609 long long int max_backoff
, probe_interval
;
610 const char *target
, *dscp_string
;
612 if (!read_string_column(row
, "target", &target
) || !target
) {
613 VLOG_INFO_RL(&rl
, "Table `%s' has missing or invalid `target' column",
614 row
->table
->schema
->name
);
618 options
= add_remote(remotes
, target
);
619 if (read_integer_column(row
, "max_backoff", &max_backoff
)) {
620 options
->max_backoff
= max_backoff
;
622 if (read_integer_column(row
, "inactivity_probe", &probe_interval
)) {
623 options
->probe_interval
= probe_interval
;
626 options
->dscp
= DSCP_DEFAULT
;
627 dscp_string
= read_map_string_column(row
, "other_config", "dscp");
629 int dscp
= atoi(dscp_string
);
630 if (dscp
>= 0 && dscp
<= 63) {
631 options
->dscp
= dscp
;
637 query_db_remotes(const char *name
, const struct db dbs
[], size_t n_dbs
,
638 struct shash
*remotes
)
640 const struct ovsdb_column
*column
;
641 const struct ovsdb_table
*table
;
642 const struct ovsdb_row
*row
;
646 retval
= parse_db_column(dbs
, n_dbs
, name
, &db
, &table
, &column
);
648 ovs_fatal(0, "%s", retval
);
651 if (column
->type
.key
.type
== OVSDB_TYPE_STRING
652 && column
->type
.value
.type
== OVSDB_TYPE_VOID
) {
653 HMAP_FOR_EACH (row
, hmap_node
, &table
->rows
) {
654 const struct ovsdb_datum
*datum
;
657 datum
= &row
->fields
[column
->index
];
658 for (i
= 0; i
< datum
->n
; i
++) {
659 add_remote(remotes
, datum
->keys
[i
].string
);
662 } else if (column
->type
.key
.type
== OVSDB_TYPE_UUID
663 && column
->type
.key
.u
.uuid
.refTable
664 && column
->type
.value
.type
== OVSDB_TYPE_VOID
) {
665 const struct ovsdb_table
*ref_table
= column
->type
.key
.u
.uuid
.refTable
;
666 HMAP_FOR_EACH (row
, hmap_node
, &table
->rows
) {
667 const struct ovsdb_datum
*datum
;
670 datum
= &row
->fields
[column
->index
];
671 for (i
= 0; i
< datum
->n
; i
++) {
672 const struct ovsdb_row
*ref_row
;
674 ref_row
= ovsdb_table_get_row(ref_table
, &datum
->keys
[i
].uuid
);
676 add_manager_options(remotes
, ref_row
);
684 update_remote_row(const struct ovsdb_row
*row
, struct ovsdb_txn
*txn
,
685 const struct ovsdb_jsonrpc_server
*jsonrpc
)
687 struct ovsdb_jsonrpc_remote_status status
;
688 struct ovsdb_row
*rw_row
;
690 char *keys
[9], *values
[9];
693 /* Get the "target" (protocol/host/port) spec. */
694 if (!read_string_column(row
, "target", &target
)) {
695 /* Bad remote spec or incorrect schema. */
698 rw_row
= ovsdb_txn_row_modify(txn
, row
);
699 ovsdb_jsonrpc_server_get_remote_status(jsonrpc
, target
, &status
);
701 /* Update status information columns. */
702 write_bool_column(rw_row
, "is_connected", status
.is_connected
);
705 keys
[n
] = xstrdup("state");
706 values
[n
++] = xstrdup(status
.state
);
708 if (status
.sec_since_connect
!= UINT_MAX
) {
709 keys
[n
] = xstrdup("sec_since_connect");
710 values
[n
++] = xasprintf("%u", status
.sec_since_connect
);
712 if (status
.sec_since_disconnect
!= UINT_MAX
) {
713 keys
[n
] = xstrdup("sec_since_disconnect");
714 values
[n
++] = xasprintf("%u", status
.sec_since_disconnect
);
716 if (status
.last_error
) {
717 keys
[n
] = xstrdup("last_error");
719 xstrdup(ovs_retval_to_string(status
.last_error
));
721 if (status
.locks_held
&& status
.locks_held
[0]) {
722 keys
[n
] = xstrdup("locks_held");
723 values
[n
++] = xstrdup(status
.locks_held
);
725 if (status
.locks_waiting
&& status
.locks_waiting
[0]) {
726 keys
[n
] = xstrdup("locks_waiting");
727 values
[n
++] = xstrdup(status
.locks_waiting
);
729 if (status
.locks_lost
&& status
.locks_lost
[0]) {
730 keys
[n
] = xstrdup("locks_lost");
731 values
[n
++] = xstrdup(status
.locks_lost
);
733 if (status
.n_connections
> 1) {
734 keys
[n
] = xstrdup("n_connections");
735 values
[n
++] = xasprintf("%d", status
.n_connections
);
737 if (status
.bound_port
!= htons(0)) {
738 keys
[n
] = xstrdup("bound_port");
739 values
[n
++] = xasprintf("%"PRIu16
, ntohs(status
.bound_port
));
741 write_string_string_column(rw_row
, "status", keys
, values
, n
);
743 ovsdb_jsonrpc_server_free_remote_status(&status
);
747 update_remote_rows(const struct db dbs
[], size_t n_dbs
,
748 const char *remote_name
,
749 const struct ovsdb_jsonrpc_server
*jsonrpc
)
751 const struct ovsdb_table
*table
, *ref_table
;
752 const struct ovsdb_column
*column
;
753 const struct ovsdb_row
*row
;
757 if (strncmp("db:", remote_name
, 3)) {
761 retval
= parse_db_column(dbs
, n_dbs
, remote_name
, &db
, &table
, &column
);
763 ovs_fatal(0, "%s", retval
);
766 if (column
->type
.key
.type
!= OVSDB_TYPE_UUID
767 || !column
->type
.key
.u
.uuid
.refTable
768 || column
->type
.value
.type
!= OVSDB_TYPE_VOID
) {
772 ref_table
= column
->type
.key
.u
.uuid
.refTable
;
774 HMAP_FOR_EACH (row
, hmap_node
, &table
->rows
) {
775 const struct ovsdb_datum
*datum
;
778 datum
= &row
->fields
[column
->index
];
779 for (i
= 0; i
< datum
->n
; i
++) {
780 const struct ovsdb_row
*ref_row
;
782 ref_row
= ovsdb_table_get_row(ref_table
, &datum
->keys
[i
].uuid
);
784 update_remote_row(ref_row
, db
->txn
, jsonrpc
);
791 update_remote_status(const struct ovsdb_jsonrpc_server
*jsonrpc
,
792 const struct sset
*remotes
,
793 struct db dbs
[], size_t n_dbs
)
795 static struct vlog_rate_limit rl
= VLOG_RATE_LIMIT_INIT(1, 1);
799 for (i
= 0; i
< n_dbs
; i
++) {
800 dbs
[i
].txn
= ovsdb_txn_create(dbs
[i
].db
);
803 /* Iterate over --remote arguments given on command line. */
804 SSET_FOR_EACH (remote
, remotes
) {
805 update_remote_rows(dbs
, n_dbs
, remote
, jsonrpc
);
808 for (i
= 0; i
< n_dbs
; i
++) {
809 struct ovsdb_error
*error
= ovsdb_txn_commit(dbs
[i
].txn
, false);
811 VLOG_ERR_RL(&rl
, "Failed to update remote status: %s",
812 ovsdb_error_to_string(error
));
813 ovsdb_error_destroy(error
);
818 /* Reconfigures ovsdb-server based on information in the database. */
820 reconfigure_from_db(struct ovsdb_jsonrpc_server
*jsonrpc
,
821 const struct db dbs
[], size_t n_dbs
, struct sset
*remotes
)
823 struct shash resolved_remotes
;
826 /* Configure remotes. */
827 shash_init(&resolved_remotes
);
828 SSET_FOR_EACH (name
, remotes
) {
829 if (!strncmp(name
, "db:", 3)) {
830 query_db_remotes(name
, dbs
, n_dbs
, &resolved_remotes
);
832 add_remote(&resolved_remotes
, name
);
835 ovsdb_jsonrpc_server_set_remotes(jsonrpc
, &resolved_remotes
);
836 shash_destroy_free_data(&resolved_remotes
);
839 stream_ssl_set_key_and_cert(query_db_string(dbs
, n_dbs
, private_key_file
),
840 query_db_string(dbs
, n_dbs
, certificate_file
));
841 stream_ssl_set_ca_cert_file(query_db_string(dbs
, n_dbs
, ca_cert_file
),
846 ovsdb_server_exit(struct unixctl_conn
*conn
, int argc OVS_UNUSED
,
847 const char *argv
[] OVS_UNUSED
,
850 bool *exiting
= exiting_
;
852 unixctl_command_reply(conn
, NULL
);
856 ovsdb_server_compact(struct unixctl_conn
*conn
, int argc
,
857 const char *argv
[], void *dbs_
)
859 struct db
*dbs
= dbs_
;
865 for (db
= dbs
; db
->filename
!= NULL
; db
++) {
866 const char *name
= db
->db
->schema
->name
;
868 if (argc
< 2 || !strcmp(argv
[1], name
)) {
869 struct ovsdb_error
*error
;
871 VLOG_INFO("compacting %s database by user request", name
);
873 error
= ovsdb_file_compact(db
->file
);
875 char *s
= ovsdb_error_to_string(error
);
876 ds_put_format(&reply
, "%s\n", s
);
885 unixctl_command_reply_error(conn
, "no database by that name");
886 } else if (reply
.length
) {
887 unixctl_command_reply_error(conn
, ds_cstr(&reply
));
889 unixctl_command_reply(conn
, NULL
);
894 /* "ovsdb-server/reconnect": makes ovsdb-server drop all of its JSON-RPC
895 * connections and reconnect. */
897 ovsdb_server_reconnect(struct unixctl_conn
*conn
, int argc OVS_UNUSED
,
898 const char *argv
[] OVS_UNUSED
, void *jsonrpc_
)
900 struct ovsdb_jsonrpc_server
*jsonrpc
= jsonrpc_
;
902 ovsdb_jsonrpc_server_reconnect(jsonrpc
);
903 unixctl_command_reply(conn
, NULL
);
906 /* "ovsdb-server/add-remote REMOTE": adds REMOTE to the set of remotes that
907 * ovsdb-server services. */
909 ovsdb_server_add_remote(struct unixctl_conn
*conn
, int argc OVS_UNUSED
,
910 const char *argv
[], void *aux_
)
912 struct add_remote_aux
*aux
= aux_
;
913 const char *remote
= argv
[1];
915 const struct ovsdb_column
*column
;
916 const struct ovsdb_table
*table
;
920 retval
= (strncmp("db:", remote
, 3)
922 : parse_db_column(aux
->dbs
, aux
->n_dbs
, remote
,
923 &db
, &table
, &column
));
925 sset_add(aux
->remotes
, remote
);
926 unixctl_command_reply(conn
, NULL
);
928 unixctl_command_reply_error(conn
, retval
);
933 /* "ovsdb-server/remove-remote REMOTE": removes REMOTE frmo the set of remotes
934 * that ovsdb-server services. */
936 ovsdb_server_remove_remote(struct unixctl_conn
*conn
, int argc OVS_UNUSED
,
937 const char *argv
[], void *remotes_
)
939 struct sset
*remotes
= remotes_
;
940 struct sset_node
*node
;
942 node
= sset_find(remotes
, argv
[1]);
944 sset_delete(remotes
, node
);
945 unixctl_command_reply(conn
, NULL
);
947 unixctl_command_reply_error(conn
, "no such remote");
951 /* "ovsdb-server/list-remotes": outputs a list of configured rmeotes. */
953 ovsdb_server_list_remotes(struct unixctl_conn
*conn
, int argc OVS_UNUSED
,
954 const char *argv
[] OVS_UNUSED
, void *remotes_
)
956 struct sset
*remotes
= remotes_
;
957 const char **list
, **p
;
962 list
= sset_sort(remotes
);
963 for (p
= list
; *p
; p
++) {
964 ds_put_format(&s
, "%s\n", *p
);
968 unixctl_command_reply(conn
, ds_cstr(&s
));
973 parse_options(int *argcp
, char **argvp
[],
974 struct sset
*remotes
, char **unixctl_pathp
, char **run_command
)
977 OPT_REMOTE
= UCHAR_MAX
+ 1,
980 OPT_BOOTSTRAP_CA_CERT
,
983 LEAK_CHECKER_OPTION_ENUMS
,
986 static const struct option long_options
[] = {
987 {"remote", required_argument
, NULL
, OPT_REMOTE
},
988 {"unixctl", required_argument
, NULL
, OPT_UNIXCTL
},
989 {"run", required_argument
, NULL
, OPT_RUN
},
990 {"help", no_argument
, NULL
, 'h'},
991 {"version", no_argument
, NULL
, 'V'},
994 LEAK_CHECKER_LONG_OPTIONS
,
995 {"bootstrap-ca-cert", required_argument
, NULL
, OPT_BOOTSTRAP_CA_CERT
},
996 {"private-key", required_argument
, NULL
, 'p'},
997 {"certificate", required_argument
, NULL
, 'c'},
998 {"ca-cert", required_argument
, NULL
, 'C'},
999 {"enable-dummy", optional_argument
, NULL
, OPT_ENABLE_DUMMY
},
1002 char *short_options
= long_options_to_short_options(long_options
);
1004 char **argv
= *argvp
;
1010 c
= getopt_long(argc
, argv
, short_options
, long_options
, NULL
);
1017 sset_add(remotes
, optarg
);
1021 *unixctl_pathp
= optarg
;
1025 *run_command
= optarg
;
1032 ovs_print_version(0, 0);
1035 VLOG_OPTION_HANDLERS
1036 DAEMON_OPTION_HANDLERS
1037 LEAK_CHECKER_OPTION_HANDLERS
1040 private_key_file
= optarg
;
1044 certificate_file
= optarg
;
1048 ca_cert_file
= optarg
;
1049 bootstrap_ca_cert
= false;
1052 case OPT_BOOTSTRAP_CA_CERT
:
1053 ca_cert_file
= optarg
;
1054 bootstrap_ca_cert
= true;
1057 case OPT_ENABLE_DUMMY
:
1058 dummy_enable(optarg
&& !strcmp(optarg
, "override"));
1068 free(short_options
);
1077 printf("%s: Open vSwitch database server\n"
1078 "usage: %s [OPTIONS] [DATABASE...]\n"
1079 "where each DATABASE is a database file in ovsdb format.\n"
1080 "The default DATABASE, if none is given, is\n%s/conf.db.\n",
1081 program_name
, program_name
, ovs_dbdir());
1082 printf("\nJSON-RPC options (may be specified any number of times):\n"
1083 " --remote=REMOTE connect or listen to REMOTE\n");
1084 stream_usage("JSON-RPC", true, true, true);
1087 printf("\nOther options:\n"
1088 " --run COMMAND run COMMAND as subprocess then exit\n"
1089 " --unixctl=SOCKET override default control socket name\n"
1090 " -h, --help display this help message\n"
1091 " -V, --version display version information\n");
1092 leak_checker_usage();