From patchwork Mon Aug 6 21:45:51 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Pfaff X-Patchwork-Id: 954250 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=ovn.org Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 41krnZ0Pyhz9s4c for ; Tue, 7 Aug 2018 07:46:26 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 50A14DE1; Mon, 6 Aug 2018 21:46:05 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 7DCBDDDE for ; Mon, 6 Aug 2018 21:46:04 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from relay2-d.mail.gandi.net (relay2-d.mail.gandi.net [217.70.183.194]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 8EC71735 for ; Mon, 6 Aug 2018 21:46:03 +0000 (UTC) X-Originating-IP: 208.91.3.26 Received: from sigabrt.benpfaff.org (unknown [208.91.3.26]) (Authenticated sender: blp@ovn.org) by relay2-d.mail.gandi.net (Postfix) with ESMTPSA id EA91840005; Mon, 6 Aug 2018 21:45:59 +0000 (UTC) From: Ben Pfaff To: dev@openvswitch.org Date: Mon, 6 Aug 2018 14:45:51 -0700 Message-Id: <20180806214553.28185-2-blp@ovn.org> X-Mailer: git-send-email 2.16.1 In-Reply-To: <20180806214553.28185-1-blp@ovn.org> References: <20180806214553.28185-1-blp@ovn.org> X-Spam-Status: No, score=-2.6 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_LOW autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Cc: Ben Pfaff , Alin Gabriel Serdean Subject: [ovs-dev] [PATCH v3 1/3] unixctl: Make path to unixctl_server socket available to the client. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org Acked-by: Alin Gabriel Serdean Acked-by: Mark Michelson Signed-off-by: Ben Pfaff --- lib/unixctl.c | 52 ++++++++++++++++++++++++++++------------------------ lib/unixctl.h | 2 ++ tests/daemon.at | 4 ++-- 3 files changed, 32 insertions(+), 26 deletions(-) diff --git a/lib/unixctl.c b/lib/unixctl.c index bd9c1caeedef..9b3b0671f33c 100644 --- a/lib/unixctl.c +++ b/lib/unixctl.c @@ -56,6 +56,7 @@ struct unixctl_conn { struct unixctl_server { struct pstream *listener; struct ovs_list conns; + char *path; }; static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 5); @@ -216,48 +217,44 @@ unixctl_command_reply_error(struct unixctl_conn *conn, const char *error) int unixctl_server_create(const char *path, struct unixctl_server **serverp) { - struct unixctl_server *server; - struct pstream *listener; - char *punix_path; - int error; - *serverp = NULL; if (path && !strcmp(path, "none")) { return 0; } - if (path) { - char *abs_path; - abs_path = abs_file_name(ovs_rundir(), path); - punix_path = xasprintf("punix:%s", abs_path); - free(abs_path); - } else { -#ifndef _WIN32 - punix_path = xasprintf("punix:%s/%s.%ld.ctl", ovs_rundir(), - program_name, (long int) getpid()); +#ifdef _WIN32 + enum { WINDOWS = 1 }; #else - punix_path = xasprintf("punix:%s/%s.ctl", ovs_rundir(), program_name); + enum { WINDOWS = 0 }; #endif - } - error = pstream_open(punix_path, &listener, 0); + long int pid = getpid(); + char *abs_path + = (path ? abs_file_name(ovs_rundir(), path) + : WINDOWS ? xasprintf("%s/%s.ctl", ovs_rundir(), program_name) + : xasprintf("%s/%s.%ld.ctl", ovs_rundir(), program_name, pid)); + + struct pstream *listener; + char *punix_path = xasprintf("punix:%s", abs_path); + int error = pstream_open(punix_path, &listener, 0); + free(punix_path); + if (error) { - ovs_error(error, "could not initialize control socket %s", punix_path); - goto exit; + ovs_error(error, "%s: could not initialize control socket", abs_path); + free(abs_path); + return error; } unixctl_command_register("list-commands", "", 0, 0, unixctl_list_commands, NULL); unixctl_command_register("version", "", 0, 0, unixctl_version, NULL); - server = xmalloc(sizeof *server); + struct unixctl_server *server = xmalloc(sizeof *server); server->listener = listener; + server->path = abs_path; ovs_list_init(&server->conns); *serverp = server; - -exit: - free(punix_path); - return error; + return 0; } static void @@ -429,10 +426,17 @@ unixctl_server_destroy(struct unixctl_server *server) kill_connection(conn); } + free (server->path); pstream_close(server->listener); free(server); } } + +const char * +unixctl_server_get_path(const struct unixctl_server *server) +{ + return server ? server->path : NULL; +} /* On POSIX based systems, connects to a unixctl server socket. 'path' should * be the name of a unixctl server socket. If it does not start with '/', it diff --git a/lib/unixctl.h b/lib/unixctl.h index ce43893c6a7d..4562dbc49113 100644 --- a/lib/unixctl.h +++ b/lib/unixctl.h @@ -28,6 +28,8 @@ void unixctl_server_run(struct unixctl_server *); void unixctl_server_wait(struct unixctl_server *); void unixctl_server_destroy(struct unixctl_server *); +const char *unixctl_server_get_path(const struct unixctl_server *); + /* Client for Unix domain socket control connection. */ struct jsonrpc; int unixctl_client_create(const char *path, struct jsonrpc **client); diff --git a/tests/daemon.at b/tests/daemon.at index 952d5a7c7bbe..b379fa83f9aa 100644 --- a/tests/daemon.at +++ b/tests/daemon.at @@ -149,7 +149,7 @@ AT_SETUP([daemon --detach startup errors]) AT_CAPTURE_FILE([pid]) OVSDB_INIT([db]) AT_CHECK([ovsdb-server --detach --no-chdir --pidfile --unixctl=nonexistent/unixctl db], [1], [], [stderr]) -AT_CHECK([grep 'ovsdb-server: could not initialize control socket' stderr], +AT_CHECK([grep 'could not initialize control socket' stderr], [0], [ignore]) AT_CHECK([test ! -s pid]) AT_CLEANUP @@ -159,7 +159,7 @@ AT_SKIP_IF([test "$IS_WIN32" = "yes"]) AT_CAPTURE_FILE([pid]) OVSDB_INIT([db]) AT_CHECK([ovsdb-server --detach --no-chdir --pidfile --monitor --unixctl=nonexistent/unixctl db], [1], [], [stderr]) -AT_CHECK([grep 'ovsdb-server: could not initialize control socket' stderr], +AT_CHECK([grep 'could not initialize control socket' stderr], [0], [ignore]) AT_CHECK([test ! -s pid]) AT_CLEANUP From patchwork Mon Aug 6 21:45:52 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Pfaff X-Patchwork-Id: 954251 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=ovn.org Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 41krp03Hlgz9s4c for ; Tue, 7 Aug 2018 07:46:48 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 293DEE24; Mon, 6 Aug 2018 21:46:08 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 00E99E04 for ; Mon, 6 Aug 2018 21:46:07 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from relay2-d.mail.gandi.net (relay2-d.mail.gandi.net [217.70.183.194]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id F04C163D for ; Mon, 6 Aug 2018 21:46:05 +0000 (UTC) X-Originating-IP: 208.91.3.26 Received: from sigabrt.benpfaff.org (unknown [208.91.3.26]) (Authenticated sender: blp@ovn.org) by relay2-d.mail.gandi.net (Postfix) with ESMTPSA id D203D40004; Mon, 6 Aug 2018 21:46:02 +0000 (UTC) From: Ben Pfaff To: dev@openvswitch.org Date: Mon, 6 Aug 2018 14:45:52 -0700 Message-Id: <20180806214553.28185-3-blp@ovn.org> X-Mailer: git-send-email 2.16.1 In-Reply-To: <20180806214553.28185-1-blp@ovn.org> References: <20180806214553.28185-1-blp@ovn.org> X-Spam-Status: No, score=-2.6 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_LOW autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Cc: Ben Pfaff Subject: [ovs-dev] [PATCH v3 2/3] ovn-nbctl: Separate command-line options parsing and interpretation. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org This will allow selected options to be interpreted locally and others to be passed to the daemon, when the daemon is in use. Signed-off-by: Ben Pfaff --- lib/command-line.c | 108 ++++++++++++++++++++++++++++++++++++++++++++++ lib/command-line.h | 10 +++++ ovn/utilities/ovn-nbctl.c | 39 +++++++++-------- 3 files changed, 138 insertions(+), 19 deletions(-) diff --git a/lib/command-line.c b/lib/command-line.c index 81283314d1f3..9e000bd28d1a 100644 --- a/lib/command-line.c +++ b/lib/command-line.c @@ -52,6 +52,114 @@ ovs_cmdl_long_options_to_short_options(const struct option options[]) return xstrdup(short_options); } +static char * OVS_WARN_UNUSED_RESULT +build_short_options(const struct option *long_options) +{ + char *tmp, *short_options; + + tmp = ovs_cmdl_long_options_to_short_options(long_options); + short_options = xasprintf("+:%s", tmp); + free(tmp); + + return short_options; +} + +static const struct option * +find_option_by_value(const struct option *options, int value) +{ + const struct option *o; + + for (o = options; o->name; o++) { + if (o->val == value) { + return o; + } + } + return NULL; +} + +/* Parses the command-line options in 'argc' and 'argv'. The caller specifies + * the supported options in 'options'. On success, stores the parsed options + * in '*pop', the number of options in '*n_pop', and returns NULL. On failure, + * returns an error message and zeros the output arguments. */ +char * OVS_WARN_UNUSED_RESULT +ovs_cmdl_parse_all(int argc, char *argv[], + const struct option *options, + struct ovs_cmdl_parsed_option **pop, size_t *n_pop) +{ + /* Count number of options so we can have better assertions later. */ + size_t n_options OVS_UNUSED = 0; + while (options[n_options].name) { + n_options++; + } + + char *short_options = build_short_options(options); + + struct ovs_cmdl_parsed_option *po = NULL; + size_t allocated_po = 0; + size_t n_po = 0; + + char *error; + + optind = 0; + opterr = 0; + for (;;) { + int idx = -1; + int c = getopt_long(argc, argv, short_options, options, &idx); + switch (c) { + case -1: + *pop = po; + *n_pop = n_po; + free(short_options); + return NULL; + + case 0: + /* getopt_long() processed the option directly by setting a flag + * variable. This is probably undesirable for use with this + * function. */ + OVS_NOT_REACHED(); + + case '?': + if (optopt && find_option_by_value(options, optopt)) { + error = xasprintf("option '%s' doesn't allow an argument", + argv[optind - 1]); + } else if (optopt) { + error = xasprintf("unrecognized option '%c'", optopt); + } else { + error = xasprintf("unrecognized option '%s'", + argv[optind - 1]); + } + goto error; + + case ':': + error = xasprintf("option '%s' requires an argument", + argv[optind - 1]); + goto error; + + default: + if (n_po >= allocated_po) { + po = x2nrealloc(po, &allocated_po, sizeof *po); + } + if (idx == -1) { + po[n_po].o = find_option_by_value(options, c); + } else { + ovs_assert(idx >= 0 && idx < n_options); + po[n_po].o = &options[idx]; + } + po[n_po].arg = optarg; + n_po++; + break; + } + } + OVS_NOT_REACHED(); + +error: + free(po); + *pop = NULL; + *n_pop = 0; + free(short_options); + return error; +} + /* Given the 'struct ovs_cmdl_command' array, prints the usage of all commands. */ void ovs_cmdl_print_commands(const struct ovs_cmdl_command commands[]) diff --git a/lib/command-line.h b/lib/command-line.h index 00ace949bad6..9d62dc2501c5 100644 --- a/lib/command-line.h +++ b/lib/command-line.h @@ -45,8 +45,18 @@ struct ovs_cmdl_command { }; char *ovs_cmdl_long_options_to_short_options(const struct option *options); + +struct ovs_cmdl_parsed_option { + const struct option *o; + char *arg; +}; +char *ovs_cmdl_parse_all(int argc, char *argv[], const struct option *, + struct ovs_cmdl_parsed_option **, size_t *) + OVS_WARN_UNUSED_RESULT; + void ovs_cmdl_print_options(const struct option *options); void ovs_cmdl_print_commands(const struct ovs_cmdl_command *commands); + void ovs_cmdl_run_command(struct ovs_cmdl_context *, const struct ovs_cmdl_command[]); void ovs_cmdl_run_command_read_only(struct ovs_cmdl_context *, diff --git a/ovn/utilities/ovn-nbctl.c b/ovn/utilities/ovn-nbctl.c index c625546bb8c0..0659ced378ef 100644 --- a/ovn/utilities/ovn-nbctl.c +++ b/ovn/utilities/ovn-nbctl.c @@ -368,24 +368,23 @@ parse_options(int argc, char *argv[], struct shash *local_options) {NULL, 0, NULL, 0}, }; const int n_global_long_options = ARRAY_SIZE(global_long_options) - 1; - char *short_options; struct option *options; size_t i; - short_options = build_short_options(global_long_options, true); options = append_command_options(global_long_options, OPT_LOCAL); - for (;;) { - int idx; - int c; - - c = getopt_long(argc, argv, short_options, options, &idx); - if (c == -1) { - break; - } + struct ovs_cmdl_parsed_option *parsed_options; + size_t n_po; + char *error = ovs_cmdl_parse_all(argc, argv, options, + &parsed_options, &n_po); + if (error) { + ctl_fatal("%s", error); + } + for (const struct ovs_cmdl_parsed_option *po = parsed_options; + po < &parsed_options[n_po]; po++) { bool handled; - char *error = handle_main_loop_option(c, optarg, &handled); + error = handle_main_loop_option(po->o->val, po->arg, &handled); if (error) { ctl_fatal("%s", error); } @@ -393,9 +392,10 @@ parse_options(int argc, char *argv[], struct shash *local_options) continue; } - switch (c) { + optarg = po->arg; + switch (po->o->val) { case OPT_DB: - db = optarg; + db = po->arg; break; case OPT_NO_SYSLOG: @@ -403,13 +403,13 @@ parse_options(int argc, char *argv[], struct shash *local_options) break; case OPT_LOCAL: - if (shash_find(local_options, options[idx].name)) { + if (shash_find(local_options, po->o->name)) { ctl_fatal("'%s' option specified multiple times", - options[idx].name); + po->o->name); } shash_add_nocopy(local_options, - xasprintf("--%s", options[idx].name), - nullable_xstrdup(optarg)); + xasprintf("--%s", po->o->name), + nullable_xstrdup(po->arg)); break; case 'h': @@ -435,7 +435,7 @@ parse_options(int argc, char *argv[], struct shash *local_options) STREAM_SSL_OPTION_HANDLERS case OPT_BOOTSTRAP_CA_CERT: - stream_ssl_set_ca_cert_file(optarg, true); + stream_ssl_set_ca_cert_file(po->arg, true); break; case '?': @@ -448,7 +448,7 @@ parse_options(int argc, char *argv[], struct shash *local_options) break; } } - free(short_options); + free(parsed_options); if (!db) { db = default_nb_db(); @@ -4984,6 +4984,7 @@ server_parse_options(int argc, char *argv[], struct shash *local_options, int *n_options_p) { static const struct option global_long_options[] = { + VLOG_LONG_OPTIONS, MAIN_LOOP_LONG_OPTIONS, TABLE_LONG_OPTIONS, {NULL, 0, NULL, 0}, From patchwork Mon Aug 6 21:45:53 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Pfaff X-Patchwork-Id: 954252 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=ovn.org Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 41krpV1xFWz9s3x for ; Tue, 7 Aug 2018 07:47:14 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id DA23EE2C; Mon, 6 Aug 2018 21:46:13 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 703C0E2B for ; Mon, 6 Aug 2018 21:46:12 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from relay2-d.mail.gandi.net (relay2-d.mail.gandi.net [217.70.183.194]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id A9F5F735 for ; Mon, 6 Aug 2018 21:46:09 +0000 (UTC) X-Originating-IP: 208.91.3.26 Received: from sigabrt.benpfaff.org (unknown [208.91.3.26]) (Authenticated sender: blp@ovn.org) by relay2-d.mail.gandi.net (Postfix) with ESMTPSA id 74D0040008; Mon, 6 Aug 2018 21:46:04 +0000 (UTC) From: Ben Pfaff To: dev@openvswitch.org Date: Mon, 6 Aug 2018 14:45:53 -0700 Message-Id: <20180806214553.28185-4-blp@ovn.org> X-Mailer: git-send-email 2.16.1 In-Reply-To: <20180806214553.28185-1-blp@ovn.org> References: <20180806214553.28185-1-blp@ovn.org> X-Spam-Status: No, score=-2.6 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_LOW autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Cc: Ben Pfaff Subject: [ovs-dev] [PATCH v3 3/3] ovn-nbctl: Make daemon mode more transparent. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org This makes ovn-nbctl transparently use daemon mode if an appropriate environment variable is set. It also transforms ovn-nbctl.at so that it runs each ovn-nbctl test in "direct" mode and in daemon mode. It uses a combination of m4 macros and shell functions to keep from expanding the generated testsuite more than necessary. Signed-off-by: Ben Pfaff Acked-by: Mark Michelson --- NEWS | 6 +- lib/daemon.h | 19 +++ lib/stream-ssl.h | 5 +- ovn/utilities/ovn-nbctl.8.xml | 61 +++++++-- ovn/utilities/ovn-nbctl.c | 292 +++++++++++++++++++++++++++++++++++------- tests/ovn-nbctl.at | 246 +++++++++++++---------------------- 6 files changed, 412 insertions(+), 217 deletions(-) diff --git a/NEWS b/NEWS index 27ef12d599d9..7875f6673e34 100644 --- a/NEWS +++ b/NEWS @@ -35,10 +35,8 @@ v2.10.0 - xx xxx xxxx * ACL match conditions can now match on Port_Groups as well as address sets that are automatically generated by Port_Groups. ACLs can be applied directly to Port_Groups as well. - * ovn-nbctl can now run as a daemon (long-lived, background process) - running commands in response to JSON-RPC requests received over a UNIX - socket. Requests to run commands can be sent using ovs-appctl tool, same - as for any other OVS/OVN daemon. See ovn-nbctl(8) for details. + * ovn-nbctl can now run as a daemon (long-lived, background process). + See ovn-nbctl(8) for details. - DPDK: * New 'check-dpdk' Makefile target to run a new system testsuite. See Testing topic for the details. diff --git a/lib/daemon.h b/lib/daemon.h index bfa06408c390..f33e9df8df7a 100644 --- a/lib/daemon.h +++ b/lib/daemon.h @@ -84,6 +84,15 @@ daemon_set_new_user(optarg); \ break; +#define DAEMON_OPTION_CASES \ + case OPT_DETACH: \ + case OPT_NO_SELF_CONFINEMENT: \ + case OPT_NO_CHDIR: \ + case OPT_PIDFILE: \ + case OPT_OVERWRITE_PIDFILE: \ + case OPT_MONITOR: \ + case OPT_USER_GROUP: + void set_detach(void); void daemon_set_monitor(void); void set_no_chdir(void); @@ -138,6 +147,16 @@ pid_t read_pidfile(const char *name); case OPT_USER_GROUP: \ daemon_set_new_user(optarg); +#define DAEMON_OPTION_CASES \ + case OPT_DETACH: \ + case OPT_NO_SELF_CONFINEMENT: \ + case OPT_NO_CHDIR: \ + case OPT_PIDFILE: \ + case OPT_PIPE_HANDLE: \ + case OPT_SERVICE: \ + case OPT_SERVICE_MONITOR: \ + case OPT_USER_GROUP: + void control_handler(DWORD request); void set_pipe_handle(const char *pipe_handle); #endif /* _WIN32 */ diff --git a/lib/stream-ssl.h b/lib/stream-ssl.h index 4bfe09b002c9..937f7c653ba9 100644 --- a/lib/stream-ssl.h +++ b/lib/stream-ssl.h @@ -58,6 +58,9 @@ void stream_ssl_set_ciphers(const char *arg); \ case OPT_SSL_CIPHERS: \ stream_ssl_set_ciphers(optarg); \ - break; + break; + +#define STREAM_SSL_CASES \ + case 'p': case 'c': case 'C': case OPT_SSL_PROTOCOLS: case OPT_SSL_CIPHERS: #endif /* stream-ssl.h */ diff --git a/ovn/utilities/ovn-nbctl.8.xml b/ovn/utilities/ovn-nbctl.8.xml index f09ef8767d2f..5e18fa7c06ee 100644 --- a/ovn/utilities/ovn-nbctl.8.xml +++ b/ovn/utilities/ovn-nbctl.8.xml @@ -971,15 +971,62 @@

Daemon Mode

- If ovn-nbctl is invoked with the --detach - option (see Daemon Options, below), it runs in the - background as a daemon and accepts commands from ovs-appctl - (or another JSON-RPC client) indefinitely. The currently supported - commands are described below. + When it is invoked in the most ordinary way, ovn-nbctl + connects to an OVSDB server that hosts the northbound database, retrieves + a partial copy of the database that is complete enough to do its work, + sends a transaction request to the server, and receives and processes the + server's reply. In common interactive use, this is fine, but if the + database is large, the step in which ovn-nbctl retrieves a + partial copy of the database can take a long time, which yields poor + performance overall.

+ To improve performance in such a case, ovn-nbctl offers a + "daemon mode," in which the user first starts ovn-nbctl + running in the background and afterward uses the daemon to execute + operations. Over several ovn-nbctl command invocations, + this performs better overall because it retrieves a copy of the database + only once at the beginning, not once per program run. +

+ +

+ Use the --detach option to start an ovn-nbctl + daemon. With this option, ovn-nbctl prints the name of a + control socket to stdout. The client should save this name in + environment variable OVN_NB_DAEMON. Under the Bourne shell + this might be done like this: +

+ +
+      export OVN_NB_DAEMON=$(ovn-nbctl --pidfile --detach)
+    
+ +

+ When OVN_NB_DAEMON is set, ovn-nbctl + automatically and transparently uses the daemon to execute its commands. +

+ +

+ When the daemon is no longer needed, kill it and unset the environment + variable, e.g.: +

+ +
+      kill $(cat /var/run/ovn-nbctl.pid)
+      unset OVN_NB_DAEMON
+    
+ +

+ Daemon mode is experimental. +

+

Daemon Commands

+ +

+ Daemon mode is internally implemented using the same mechanism used by + ovs-appctl. One may also use ovs-appctl + directly with the following commands:

@@ -1001,10 +1048,6 @@
Causes ovn-nbctl to gracefully terminate.
-

- Daemon mode is considered experimental. -

-

Options

diff --git a/ovn/utilities/ovn-nbctl.c b/ovn/utilities/ovn-nbctl.c index 0659ced378ef..35a3af3d5ff3 100644 --- a/ovn/utilities/ovn-nbctl.c +++ b/ovn/utilities/ovn-nbctl.c @@ -24,6 +24,7 @@ #include "db-ctl-base.h" #include "dirs.h" #include "fatal-signal.h" +#include "jsonrpc.h" #include "openvswitch/json.h" #include "ovn/lib/acl-log.h" #include "ovn/lib/ovn-nb-idl.h" @@ -91,7 +92,15 @@ static unixctl_cb_func server_cmd_run; static void nbctl_cmd_init(void); OVS_NO_RETURN static void usage(void); -static void parse_options(int argc, char *argv[], struct shash *local_options); +static struct option *get_all_options(void); +static bool has_option(const struct ovs_cmdl_parsed_option *, size_t n, + int option); +static void nbctl_client(const char *socket_name, + const struct ovs_cmdl_parsed_option *, size_t n, + int argc, char *argv[]); +static bool will_detach(const struct ovs_cmdl_parsed_option *, size_t n); +static void apply_options_direct(const struct ovs_cmdl_parsed_option *, + size_t n, struct shash *local_options); static char * OVS_WARN_UNUSED_RESULT run_prerequisites(struct ctl_command[], size_t n_commands, struct ovsdb_idl *); @@ -123,10 +132,47 @@ main(int argc, char *argv[]) nbctl_cmd_init(); - /* Parse command line. */ + /* ovn-nbctl has three operation modes: + * + * - Direct: Executes commands by contacting ovsdb-server directly. + * + * - Server: Runs in the background as a daemon waiting for requests + * from ovn-nbctl running in client mode. + * + * - Client: Executes commands by passing them to an ovn-nbctl running + * in the server mode. + * + * At this point we don't know what mode we're running in. The mode partly + * depends on the command line. So, for now we transform the command line + * into a parsed form, and figure out what to do with it later. + */ char *args = process_escape_args(argv); + struct ovs_cmdl_parsed_option *parsed_options; + size_t n_parsed_options; + char *error_s = ovs_cmdl_parse_all(argc, argv, get_all_options(), + &parsed_options, &n_parsed_options); + if (error_s) { + ctl_fatal("%s", error_s); + } + + /* Now figure out the operation mode: + * + * - A --detach option implies server mode. + * + * - An OVN_NB_DAEMON environment variable implies client mode. + * + * - Otherwise, we're in direct mode. */ + char *socket_name = getenv("OVN_NB_DAEMON"); + if (socket_name && socket_name[0] + && !will_detach(parsed_options, n_parsed_options)) { + nbctl_client(socket_name, parsed_options, n_parsed_options, + argc, argv); + } + + /* Parse command line. */ shash_init(&local_options); - parse_options(argc, argv, &local_options); + apply_options_direct(parsed_options, n_parsed_options, &local_options); + free(parsed_options); argc -= optind; argv += optind; @@ -256,6 +302,8 @@ enum { OPT_LOCAL, OPT_COMMANDS, OPT_OPTIONS, + OPT_LEADER_ONLY, + OPT_NO_LEADER_ONLY, OPT_BOOTSTRAP_CA_CERT, MAIN_LOOP_OPTION_ENUMS, DAEMON_OPTION_ENUMS, @@ -347,8 +395,8 @@ append_command_options(const struct option *options, int opt_val) return o; } -static void -parse_options(int argc, char *argv[], struct shash *local_options) +static struct option * +get_all_options(void) { static const struct option global_long_options[] = { {"db", required_argument, NULL, OPT_DB}, @@ -356,8 +404,8 @@ parse_options(int argc, char *argv[], struct shash *local_options) {"help", no_argument, NULL, 'h'}, {"commands", no_argument, NULL, OPT_COMMANDS}, {"options", no_argument, NULL, OPT_OPTIONS}, - {"leader-only", no_argument, &leader_only, true}, - {"no-leader-only", no_argument, &leader_only, false}, + {"leader-only", no_argument, NULL, OPT_LEADER_ONLY}, + {"no-leader-only", no_argument, NULL, OPT_NO_LEADER_ONLY}, {"version", no_argument, NULL, 'V'}, MAIN_LOOP_LONG_OPTIONS, DAEMON_LONG_OPTIONS, @@ -367,24 +415,57 @@ parse_options(int argc, char *argv[], struct shash *local_options) TABLE_LONG_OPTIONS, {NULL, 0, NULL, 0}, }; - const int n_global_long_options = ARRAY_SIZE(global_long_options) - 1; - struct option *options; - size_t i; - options = append_command_options(global_long_options, OPT_LOCAL); + static struct option *options; + if (!options) { + options = append_command_options(global_long_options, OPT_LOCAL); + } - struct ovs_cmdl_parsed_option *parsed_options; - size_t n_po; - char *error = ovs_cmdl_parse_all(argc, argv, options, - &parsed_options, &n_po); - if (error) { - ctl_fatal("%s", error); + return options; +} + +static bool +has_option(const struct ovs_cmdl_parsed_option *parsed_options, size_t n, + int option) +{ + for (const struct ovs_cmdl_parsed_option *po = parsed_options; + po < &parsed_options[n]; po++) { + if (po->o->val == option) { + return true; + } + } + return false; +} + +static bool +will_detach(const struct ovs_cmdl_parsed_option *parsed_options, size_t n) +{ + return has_option(parsed_options, n, OPT_DETACH); +} + +static char * OVS_WARN_UNUSED_RESULT +add_local_option(const char *name, const char *arg, + struct shash *local_options) +{ + char *full_name = xasprintf("--%s", name); + if (shash_find(local_options, full_name)) { + char *error = xasprintf("'%s' option specified multiple times", + full_name); + free(full_name); + return error; } + shash_add_nocopy(local_options, full_name, nullable_xstrdup(arg)); + return NULL; +} +static void +apply_options_direct(const struct ovs_cmdl_parsed_option *parsed_options, + size_t n, struct shash *local_options) +{ for (const struct ovs_cmdl_parsed_option *po = parsed_options; - po < &parsed_options[n_po]; po++) { + po < &parsed_options[n]; po++) { bool handled; - error = handle_main_loop_option(po->o->val, po->arg, &handled); + char *error = handle_main_loop_option(po->o->val, po->arg, &handled); if (error) { ctl_fatal("%s", error); } @@ -403,13 +484,10 @@ parse_options(int argc, char *argv[], struct shash *local_options) break; case OPT_LOCAL: - if (shash_find(local_options, po->o->name)) { - ctl_fatal("'%s' option specified multiple times", - po->o->name); + error = add_local_option(po->o->name, po->arg, local_options); + if (error) { + ctl_fatal("%s", error); } - shash_add_nocopy(local_options, - xasprintf("--%s", po->o->name), - nullable_xstrdup(po->arg)); break; case 'h': @@ -421,9 +499,17 @@ parse_options(int argc, char *argv[], struct shash *local_options) /* fall through */ case OPT_OPTIONS: - ctl_print_options(global_long_options); + ctl_print_options(get_all_options()); /* fall through */ + case OPT_LEADER_ONLY: + leader_only = true; + break; + + case OPT_NO_LEADER_ONLY: + leader_only = false; + break; + case 'V': ovs_print_version(0, 0); printf("DB Schema %s\n", nbrec_get_db_version()); @@ -448,16 +534,10 @@ parse_options(int argc, char *argv[], struct shash *local_options) break; } } - free(parsed_options); if (!db) { db = default_nb_db(); } - - for (i = n_global_long_options; options[i].name; i++) { - free(CONST_CAST(char *, options[i].name)); - } - free(options); } static void @@ -641,6 +721,10 @@ Other options:\n\ exit(EXIT_SUCCESS); } +/* One should not use ctl_fatal() within commands because it will kill the + * daemon if we're in daemon mode. Use ctl_error() instead and return + * gracefully. */ +#define ctl_fatal dont_use_ctl_fatal_use_ctl_error_and_return /* Find a logical router given its id. */ static char * OVS_WARN_UNUSED_RESULT @@ -2368,35 +2452,41 @@ nbctl_meter_add(struct ctl_context *ctx) const char *name = ctx->argv[1]; NBREC_METER_FOR_EACH (meter, ctx->idl) { if (!strcmp(meter->name, name)) { - ctl_fatal("meter with name \"%s\" already exists", name); + ctl_error(ctx, "meter with name \"%s\" already exists", name); + return; } } if (!strncmp(name, "__", 2)) { - ctl_fatal("meter names that begin with \"__\" are reserved"); + ctl_error(ctx, "meter names that begin with \"__\" are reserved"); + return; } const char *action = ctx->argv[2]; if (strcmp(action, "drop")) { - ctl_fatal("action must be \"drop\""); + ctl_error(ctx, "action must be \"drop\""); + return; } int64_t rate; if (!ovs_scan(ctx->argv[3], "%"SCNd64, &rate) || rate < 1 || rate > UINT32_MAX) { - ctl_fatal("rate must be in the range 1...4294967295"); + ctl_error(ctx, "rate must be in the range 1...4294967295"); + return; } const char *unit = ctx->argv[4]; if (strcmp(unit, "kbps") && strcmp(unit, "pktps")) { - ctl_fatal("unit must be \"kbps\" or \"pktps\""); + ctl_error(ctx, "unit must be \"kbps\" or \"pktps\""); + return; } int64_t burst = 0; if (ctx->argc > 5) { if (!ovs_scan(ctx->argv[5], "%"SCNd64, &burst) || burst < 0 || burst > UINT32_MAX) { - ctl_fatal("burst must be in the range 0...4294967295"); + ctl_error(ctx, "burst must be in the range 0...4294967295"); + return; } } @@ -4965,6 +5055,10 @@ nbctl_cmd_init(void) ctl_init(&nbrec_idl_class, nbrec_table_classes, tables, NULL, nbctl_exit); ctl_register_commands(nbctl_commands); } + +/* Server implementation. */ + +#undef ctl_fatal static const struct option * find_option_by_value(const struct option *options, int value) @@ -5021,14 +5115,10 @@ server_parse_options(int argc, char *argv[], struct shash *local_options, switch (c) { case OPT_LOCAL: - if (shash_find(local_options, options[idx].name)) { - error = xasprintf("'%s' option specified multiple times", - options[idx].name); + error = add_local_option(options[idx].name, optarg, local_options); + if (error) { goto out; } - shash_add_nocopy(local_options, - xasprintf("--%s", options[idx].name), - nullable_xstrdup(optarg)); break; VLOG_OPTION_HANDLERS @@ -5177,7 +5267,7 @@ static void server_cmd_init(struct ovsdb_idl *idl, bool *exiting) { unixctl_command_register("exit", "", 0, 0, server_cmd_exit, exiting); - unixctl_command_register("run", "", 1, INT_MAX, server_cmd_run, idl); + unixctl_command_register("run", "", 0, INT_MAX, server_cmd_run, idl); } static void @@ -5192,6 +5282,8 @@ server_loop(struct ovsdb_idl *idl) ctl_fatal("failed to create unixctl server (%s)", ovs_retval_to_string(error)); } + puts(unixctl_server_get_path(server)); + fflush(stdout); server_cmd_init(idl, &exiting); for (;;) { @@ -5217,3 +5309,113 @@ server_loop(struct ovsdb_idl *idl) unixctl_server_destroy(server); } + +static void +nbctl_client(const char *socket_name, + const struct ovs_cmdl_parsed_option *parsed_options, size_t n, + int argc, char *argv[]) +{ + struct svec args = SVEC_EMPTY_INITIALIZER; + + for (const struct ovs_cmdl_parsed_option *po = parsed_options; + po < &parsed_options[n]; po++) { + optarg = po->arg; + switch (po->o->val) { + case OPT_DB: + VLOG_WARN("not using ovn-nbctl daemon because of %s option", + po->o->name); + svec_destroy(&args); + return; + + case OPT_NO_SYSLOG: + vlog_set_levels(&this_module, VLF_SYSLOG, VLL_WARN); + break; + + case 'h': + usage(); + exit(EXIT_SUCCESS); + + case OPT_COMMANDS: + ctl_print_commands(); + /* fall through */ + + case OPT_OPTIONS: + ctl_print_options(get_all_options()); + /* fall through */ + + case OPT_LEADER_ONLY: + case OPT_NO_LEADER_ONLY: + case OPT_BOOTSTRAP_CA_CERT: + STREAM_SSL_CASES + DAEMON_OPTION_CASES + VLOG_INFO("using ovn-nbctl daemon, ignoring %s option", + po->o->name); + break; + + case 'V': + ovs_print_version(0, 0); + printf("DB Schema %s\n", nbrec_get_db_version()); + exit(EXIT_SUCCESS); + + case 't': + timeout = strtoul(po->arg, NULL, 10); + if (timeout < 0) { + ctl_fatal("value %s on -t or --timeout is invalid", po->arg); + } + break; + + VLOG_OPTION_HANDLERS + TABLE_OPTION_HANDLERS(&table_style) + + case OPT_LOCAL: + default: + if (po->arg) { + svec_add_nocopy(&args, + xasprintf("--%s=%s", po->o->name, po->arg)); + } else { + svec_add_nocopy(&args, xasprintf("--%s", po->o->name)); + } + break; + } + } + svec_add(&args, "--"); + for (int i = optind; i < argc; i++) { + svec_add(&args, argv[i]); + } + + if (timeout) { + time_alarm(timeout); + } + + struct jsonrpc *client; + int error = unixctl_client_create(socket_name, &client); + if (error) { + ctl_fatal("%s: could not connect to ovn-nb daemon (%s); " + "unset OVN_NB_DAEMON to avoid using daemon", + socket_name, ovs_strerror(error)); + } + + char *cmd_result; + char *cmd_error; + error = unixctl_client_transact(client, "run", + args.n, args.names, + &cmd_result, &cmd_error); + if (error) { + ctl_fatal("%s: transaction error (%s)", + socket_name, ovs_strerror(error)); + } + svec_destroy(&args); + + int exit_status; + if (cmd_error) { + exit_status = EXIT_FAILURE; + fprintf(stderr, "%s: %s", program_name, cmd_error); + } else { + exit_status = EXIT_SUCCESS; + fputs(cmd_result, stdout); + } + free(cmd_result); + free(cmd_error); + jsonrpc_close(client); + exit(exit_status); +} diff --git a/tests/ovn-nbctl.at b/tests/ovn-nbctl.at index 88e37191ee0a..725665b76d3f 100644 --- a/tests/ovn-nbctl.at +++ b/tests/ovn-nbctl.at @@ -1,30 +1,59 @@ AT_BANNER([ovn-nbctl]) +OVS_START_SHELL_HELPERS # OVN_NBCTL_TEST_START m4_define([OVN_NBCTL_TEST_START], - [dnl Create ovn-nb database. - AT_KEYWORDS([ovn]) + [AT_KEYWORDS([ovn]) + AT_CAPTURE_FILE([ovsdb-server.log]) + ovn_nbctl_test_start $1]) +ovn_nbctl_test_start() { + dnl Create ovn-nb database. AT_CHECK([ovsdb-tool create ovn-nb.db $abs_top_srcdir/ovn/ovn-nb.ovsschema]) dnl Start ovsdb-server. AT_CHECK([ovsdb-server --detach --no-chdir --pidfile --log-file --remote=punix:$OVS_RUNDIR/ovnnb_db.sock ovn-nb.db], [0], [], [stderr]) on_exit "kill `cat ovsdb-server.pid`" + AS_CASE([$1], + [daemon], + [export OVN_NB_DAEMON=$(ovn-nbctl --pidfile --detach --log-file -vsocket_util:off) + on_exit "kill `cat ovn-nbctl.pid`"], + [direct], [], + [*], [AT_FAIL_IF(:)]) AT_CHECK([ovn-nbctl init]) AT_CHECK([[sed < stderr ' /vlog|INFO|opened log file/d /ovsdb_server|INFO|ovsdb-server (Open vSwitch)/d']]) - AT_CAPTURE_FILE([ovsdb-server.log]) -]) +} # OVN_NBCTL_TEST_STOP -m4_define([OVN_NBCTL_TEST_STOP], - [AT_CHECK([check_logs "$1"]) - OVS_APP_EXIT_AND_WAIT([ovsdb-server])]) - - -AT_SETUP([ovn-nbctl - basic switch commands]) -OVN_NBCTL_TEST_START - +m4_define([OVN_NBCTL_TEST_STOP], [ovn_nbctl_test_stop]) +ovn_nbctl_test_stop() { + AT_CHECK([check_logs "$1"]) + OVS_APP_EXIT_AND_WAIT([ovsdb-server]) +} +OVS_END_SHELL_HELPERS + +# OVN_NBCTL_TEST(NAME, TITLE, COMMANDS) +m4_define([OVN_NBCTL_TEST], + [OVS_START_SHELL_HELPERS + $1() { + $3 + } + OVS_END_SHELL_HELPERS + + AT_SETUP([ovn-nbctl - $2 - direct]) + OVN_NBCTL_TEST_START direct + $1 + OVN_NBCTL_TEST_STOP + AT_CLEANUP + + AT_SETUP([ovn-nbctl - $2 - daemon]) + OVN_NBCTL_TEST_START daemon + $1 + OVN_NBCTL_TEST_STOP + AT_CLEANUP]) + +OVN_NBCTL_TEST([ovn_nbctl_basic_switch], [basic switch commands], [ AT_CHECK([ovn-nbctl ls-add ls0]) AT_CHECK([ovn-nbctl ls-list | uuidfilt], [0], [dnl <0> (ls0) @@ -73,16 +102,11 @@ AT_CHECK([ovn-nbctl --add-duplicate ls-add], [1], [], ]) AT_CHECK([ovn-nbctl --may-exist ls-add], [1], [], [ovn-nbctl: --may-exist requires specifying a name -]) - -OVN_NBCTL_TEST_STOP -AT_CLEANUP +])]) dnl --------------------------------------------------------------------- -AT_SETUP([ovn-nbctl - basic logical switch port commands]) -OVN_NBCTL_TEST_START - +OVN_NBCTL_TEST([ovn_nbctl_basic_lsp], [basic logical switch port commands], [ AT_CHECK([ovn-nbctl ls-add ls0]) AT_CHECK([ovn-nbctl lsp-add ls0 lp0]) AT_CHECK([ovn-nbctl lsp-add ls0 lp0], [1], [], @@ -125,16 +149,11 @@ AT_CHECK([ovn-nbctl --may-exist lsp-add ls0 lp2 lp3 10], [1], [], AT_CHECK([ovn-nbctl clear Logical_Switch_Port lp2 tag_request]) AT_CHECK([ovn-nbctl --may-exist lsp-add ls0 lp2 lp3 5], [1], [], [ovn-nbctl: lp2: port already exists but has no tag_request -]) - -OVN_NBCTL_TEST_STOP -AT_CLEANUP +])]) dnl --------------------------------------------------------------------- -AT_SETUP([ovn-nbctl - lport addresses]) -OVN_NBCTL_TEST_START - +OVN_NBCTL_TEST([ovn_nbctl_lport_addresses], [lport addresses], [ AT_CHECK([ovn-nbctl ls-add ls0]) AT_CHECK([ovn-nbctl lsp-add ls0 lp0]) AT_CHECK([ovn-nbctl lsp-get-addresses lp0], [0], [dnl @@ -148,16 +167,11 @@ unknown AT_CHECK([ovn-nbctl lsp-set-addresses lp0]) AT_CHECK([ovn-nbctl lsp-get-addresses lp0], [0], [dnl -]) - -OVN_NBCTL_TEST_STOP -AT_CLEANUP +])]) dnl --------------------------------------------------------------------- -AT_SETUP([ovn-nbctl - port security]) -OVN_NBCTL_TEST_START - +OVN_NBCTL_TEST([ovn_nbctl_port_security], [port security], [ AT_CHECK([ovn-nbctl ls-add ls0]) AT_CHECK([ovn-nbctl lsp-add ls0 lp0]) AT_CHECK([ovn-nbctl lsp-get-addresses lp0], [0], [dnl @@ -171,15 +185,13 @@ aa:bb:cc:dd:ee:ff AT_CHECK([ovn-nbctl lsp-set-port-security lp0]) AT_CHECK([ovn-nbctl lsp-get-port-security lp0], [0], [dnl -]) - -OVN_NBCTL_TEST_STOP -AT_CLEANUP +])]) dnl --------------------------------------------------------------------- -m4_define([OVN_NBCTL_TEST_ACL], - [AT_CHECK([ovn-nbctl $2 --log acl-add $1 from-lport 600 udp drop]) +OVN_NBCTL_TEST([ovn_nbctl_acls], [ACLs], [ +ovn_nbctl_test_acl() { + AT_CHECK([ovn-nbctl $2 --log acl-add $1 from-lport 600 udp drop]) AT_CHECK([ovn-nbctl $2 --log --name=test --severity=info acl-add $1 to-lport 500 udp drop]) AT_CHECK([ovn-nbctl $2 acl-add $1 from-lport 400 tcp drop]) AT_CHECK([ovn-nbctl $2 acl-add $1 to-lport 300 tcp drop]) @@ -222,17 +234,14 @@ from-lport 200 (ip) drop from-lport 600 (udp) drop from-lport 200 (ip) drop ]) -]) - -AT_SETUP([ovn-nbctl - ACLs]) -OVN_NBCTL_TEST_START +} AT_CHECK([ovn-nbctl ls-add ls0]) -OVN_NBCTL_TEST_ACL([ls0]) +ovn_nbctl_test_acl ls0 AT_CHECK([ovn-nbctl ls-add ls1]) -OVN_NBCTL_TEST_ACL([ls1], [--type=switch]) +ovn_nbctl_test_acl ls1 --type=switch AT_CHECK([ovn-nbctl create port_group name=pg0], [0], [ignore]) -OVN_NBCTL_TEST_ACL([pg0], [--type=port-group]) +ovn_nbctl_test_acl pg0 --type=port-group dnl Test when port group doesn't exist AT_CHECK([ovn-nbctl --type=port-group acl-add pg1 to-lport 100 ip drop], [1], [], [dnl @@ -243,16 +252,11 @@ dnl Test when same name exists in logical switches and portgroups AT_CHECK([ovn-nbctl create port_group name=ls0], [0], [ignore]) AT_CHECK([ovn-nbctl acl-add ls0 to-lport 100 ip drop], [1], [], [stderr]) AT_CHECK([grep 'exists in both' stderr], [0], [ignore]) -AT_CHECK([ovn-nbctl --type=port-group acl-add ls0 to-lport 100 ip drop], [0], [ignore]) - -OVN_NBCTL_TEST_STOP -AT_CLEANUP +AT_CHECK([ovn-nbctl --type=port-group acl-add ls0 to-lport 100 ip drop], [0], [ignore])]) dnl --------------------------------------------------------------------- -AT_SETUP([ovn-nbctl - QoS]) -OVN_NBCTL_TEST_START - +OVN_NBCTL_TEST([ovn_nbctl_qos], [QoS], [ AT_CHECK([ovn-nbctl ls-add ls0]) AT_CHECK([ovn-nbctl qos-add ls0 from-lport 600 tcp dscp=63]) AT_CHECK([ovn-nbctl qos-add ls0 from-lport 500 udp rate=100 burst=1000]) @@ -317,16 +321,11 @@ AT_CHECK([ovn-nbctl qos-add ls0 from-lport 600 ip dscpa=-1], [1], [], AT_CHECK([ovn-nbctl qos-add ls0 from-lport 600 ip burst=123], [1], [], [ovn-nbctl: Either "rate" and/or "dscp" must be specified -]) - -OVN_NBCTL_TEST_STOP -AT_CLEANUP +])]) dnl --------------------------------------------------------------------- -AT_SETUP([ovn-nbctl - Meters]) -OVN_NBCTL_TEST_START - +OVN_NBCTL_TEST([ovn_nbctl_meters], [meters], [ AT_CHECK([ovn-nbctl meter-add meter1 drop 10 kbps]) AT_CHECK([ovn-nbctl meter-add meter2 drop 3 kbps 2]) AT_CHECK([ovn-nbctl meter-add meter3 drop 100 kbps 200]) @@ -384,15 +383,11 @@ meter4: bands: dnl Delete all meters. AT_CHECK([ovn-nbctl meter-del]) AT_CHECK([ovn-nbctl meter-list], [0], [dnl -]) - -OVN_NBCTL_TEST_STOP -AT_CLEANUP +])]) dnl --------------------------------------------------------------------- -AT_SETUP([ovn-nbctl - NATs]) -OVN_NBCTL_TEST_START +OVN_NBCTL_TEST([ovn_nbctl_nats], [NATs], [ AT_CHECK([ovn-nbctl lr-add lr0]) AT_CHECK([ovn-nbctl lr-nat-add lr0 snatt 30.0.0.2 192.168.1.2], [1], [], [ovn-nbctl: snatt: type must be one of "dnat", "snat" and "dnat_and_snat". @@ -537,15 +532,11 @@ snat 30.0.0.1 192.168.1.0/24 AT_CHECK([ovn-nbctl lr-nat-del lr0]) AT_CHECK([ovn-nbctl lr-nat-list lr0], [0], []) AT_CHECK([ovn-nbctl lr-nat-del lr0]) -AT_CHECK([ovn-nbctl lr-nat-del lr0 dnat]) -OVN_NBCTL_TEST_STOP -AT_CLEANUP +AT_CHECK([ovn-nbctl lr-nat-del lr0 dnat])]) dnl --------------------------------------------------------------------- -AT_SETUP([ovn-nbctl - LBs]) -OVN_NBCTL_TEST_START - +OVN_NBCTL_TEST([ovn_nbctl_lbs], [LBs], [ dnl Add two LBs. AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0.10:80a 192.168.10.10:80,192.168.10.20:80 tcp], [1], [], [ovn-nbctl: 30.0.0.10:80a: should be an IP address (or an IP address and a port number with : as a separator). @@ -761,16 +752,11 @@ AT_CHECK([ovn-nbctl lr-lb-add lr0 lb0]) AT_CHECK([ovn-nbctl lr-lb-add lr0 lb1]) AT_CHECK([ovn-nbctl lr-lb-add lr0 lb3]) AT_CHECK([ovn-nbctl lr-lb-del lr0]) -AT_CHECK([ovn-nbctl lr-lb-list lr0 | uuidfilt], [0], []) +AT_CHECK([ovn-nbctl lr-lb-list lr0 | uuidfilt], [0], [])]) -OVN_NBCTL_TEST_STOP -AT_CLEANUP -dnl dnl --------------------------------------------------------------------- -AT_SETUP([ovn-nbctl - LBs IPv6]) -OVN_NBCTL_TEST_START - +OVN_NBCTL_TEST([ovn_nbctl_lbs_ipv6], [LBs IPv6], [ dnl A bunch of commands that should fail AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 [[ae0f::10]]:80a [[fd0f::10]]:80,[[fd0f::20]]:80 tcp], [1], [], [ovn-nbctl: [[ae0f::10]]:80a: should be an IP address (or an IP address and a port number with : as a separator). @@ -1025,15 +1011,11 @@ AT_CHECK([ovn-nbctl lr-lb-add lr0 lb0]) AT_CHECK([ovn-nbctl lr-lb-add lr0 lb1]) AT_CHECK([ovn-nbctl lr-lb-add lr0 lb3]) AT_CHECK([ovn-nbctl lr-lb-del lr0]) -AT_CHECK([ovn-nbctl lr-lb-list lr0 | uuidfilt], [0], []) +AT_CHECK([ovn-nbctl lr-lb-list lr0 | uuidfilt], [0], [])]) -OVN_NBCTL_TEST_STOP -AT_CLEANUP dnl --------------------------------------------------------------------- -AT_SETUP([ovn-nbctl - basic logical router commands]) -OVN_NBCTL_TEST_START - +OVN_NBCTL_TEST([ovn_nbctl_basic_lr], [basic logical router commands], [ AT_CHECK([ovn-nbctl lr-add lr0]) AT_CHECK([ovn-nbctl lr-list | uuidfilt], [0], [dnl <0> (lr0) @@ -1082,16 +1064,11 @@ AT_CHECK([ovn-nbctl --add-duplicate lr-add], [1], [], ]) AT_CHECK([ovn-nbctl --may-exist lr-add], [1], [], [ovn-nbctl: --may-exist requires specifying a name -]) - -OVN_NBCTL_TEST_STOP -AT_CLEANUP +])]) dnl --------------------------------------------------------------------- -AT_SETUP([ovn-nbctl - basic logical router port commands]) -OVN_NBCTL_TEST_START - +OVN_NBCTL_TEST([ovn_nbctl_basic_lrp], [basic logical router port commands], [ AT_CHECK([ovn-nbctl lr-add lr0]) AT_CHECK([ovn-nbctl lrp-add lr0 lrp0 00:00:00:01:02 192.168.1.1/24], [1], [], [ovn-nbctl: lrp0: invalid mac address 00:00:00:01:02 @@ -1157,15 +1134,11 @@ AT_CHECK([ovn-nbctl --may-exist lrp-add lr0 lrp1 00:00:00:01:02:03 192.168.1.1/2 [ovn-nbctl: lrp1: port already exists with different network ]) -AT_CHECK([ovn-nbctl --may-exist lrp-add lr0 lrp1 00:00:00:01:02:03 10.0.0.1/24 192.168.1.1/24 peer=lrp1-peer]) - -OVN_NBCTL_TEST_STOP -AT_CLEANUP +AT_CHECK([ovn-nbctl --may-exist lrp-add lr0 lrp1 00:00:00:01:02:03 10.0.0.1/24 192.168.1.1/24 peer=lrp1-peer])]) dnl --------------------------------------------------------------------- -AT_SETUP([ovn-nbctl - logical router port gateway chassis]) -OVN_NBCTL_TEST_START +OVN_NBCTL_TEST([ovn_nbctl_lrp_gw_chassi], [logical router port gateway chassis], [ AT_CHECK([ovn-nbctl lr-add lr0]) AT_CHECK([ovn-nbctl lrp-add lr0 lrp0 00:00:00:01:02:03 192.168.1.1/24]) AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lrp0], [0], []) @@ -1221,16 +1194,11 @@ AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lrp0], [0], [dnl lrp0-chassis2 10 lrp0-chassis3 5 lrp0-chassis1 1 -]) - -OVN_NBCTL_TEST_STOP -AT_CLEANUP +])]) dnl --------------------------------------------------------------------- -AT_SETUP([ovn-nbctl - logical router port enable and disable]) -OVN_NBCTL_TEST_START - +OVN_NBCTL_TEST([ovn_nbctl_lrp_enable], [logical router port enable and disable], [ AT_CHECK([ovn-nbctl lr-add lr0]) AT_CHECK([ovn-nbctl lrp-add lr0 lrp0 00:00:00:01:02:03 192.168.1.1/24]) AT_CHECK([ovn-nbctl lrp-get-enabled lrp0], [0], [enabled @@ -1246,16 +1214,11 @@ AT_CHECK([ovn-nbctl lrp-get-enabled lrp0], [0], [enabled AT_CHECK([ovn-nbctl lrp-set-enabled lrp0 xyzzy], [1], [], [ovn-nbctl: xyzzy: state must be "enabled" or "disabled" -]) - -OVN_NBCTL_TEST_STOP -AT_CLEANUP +])]) dnl --------------------------------------------------------------------- -AT_SETUP([ovn-nbctl - routes]) -OVN_NBCTL_TEST_START - +OVN_NBCTL_TEST([ovn_nbctl_routes], [routes], [ AT_CHECK([ovn-nbctl lr-add lr0]) dnl Check IPv4 routes @@ -1364,16 +1327,11 @@ IPv6 Routes 2001:db8::/64 2001:db8:0:f102::1 dst-ip lp0 2001:db8:1::/64 2001:db8:0:f103::1 dst-ip ::/0 2001:db8:0:f101::1 dst-ip -]) - -OVN_NBCTL_TEST_STOP -AT_CLEANUP +])]) dnl --------------------------------------------------------------------- -AT_SETUP([ovn-nbctl - lsp types]) -OVN_NBCTL_TEST_START - +OVN_NBCTL_TEST([ovn_nbctl_lsp_types], [lsp types], [ AT_CHECK([ovn-nbctl ls-add ls0]) AT_CHECK([ovn-nbctl lsp-add ls0 lp0]) @@ -1437,30 +1395,20 @@ dnl Empty string should work too AT_CHECK([ovn-nbctl lsp-set-type lp0 ""]) AT_CHECK([ovn-nbctl lsp-get-type lp0], [0], [dnl -]) - -OVN_NBCTL_TEST_STOP -AT_CLEANUP +])]) dnl --------------------------------------------------------------------- -AT_SETUP([ovn-nbctl - connection]) -OVN_NBCTL_TEST_START - +OVN_NBCTL_TEST([ovn_nbctl_connection], [connection], [ AT_CHECK([ovn-nbctl --inactivity-probe=30000 set-connection ptcp:6641:127.0.0.1 punix:$OVS_RUNDIR/ovnnb_db.sock]) AT_CHECK([ovn-nbctl list connection | grep inactivity_probe], [0], [dnl inactivity_probe : 30000 inactivity_probe : 30000 -]) - -OVN_NBCTL_TEST_STOP -AT_CLEANUP +])]) dnl --------------------------------------------------------------------- -AT_SETUP([ovn-nbctl - dry run mode]) -OVN_NBCTL_TEST_START - +OVN_NBCTL_TEST([ovn_nbctl_dry_run_mode], [dry run mode], [ dnl Check that dry run has no permanent effect. AT_CHECK([ovn-nbctl --dry-run ls-add ls0 -- ls-list | uuidfilt], [0], [dnl <0> (ls0) @@ -1472,16 +1420,11 @@ dnl Check that dry-run mode is not sticky. AT_CHECK([ovn-nbctl ls-add ls0]) AT_CHECK([ovn-nbctl ls-list | uuidfilt], [0], [dnl <0> (ls0) -]) - -OVN_NBCTL_TEST_STOP -AT_CLEANUP +])]) dnl --------------------------------------------------------------------- -AT_SETUP([ovn-nbctl - oneline output]) -OVN_NBCTL_TEST_START - +OVN_NBCTL_TEST([ovn_nbctl_oneline_output], [oneline output], [ AT_CHECK([ovn-nbctl ls-add ls0 -- ls-add ls1]) dnl Expect one line for one command. @@ -1493,16 +1436,11 @@ dnl Expect lines for two commands. AT_CHECK([ovn-nbctl --oneline ls-list -- ls-list | uuidfilt], [0], [dnl <0> (ls0)\n<1> (ls1) <0> (ls0)\n<1> (ls1) -]) - -OVN_NBCTL_TEST_STOP -AT_CLEANUP +])]) dnl --------------------------------------------------------------------- -AT_SETUP([ovn-nbctl - commands parser error paths]) -OVN_NBCTL_TEST_START - +OVN_NBCTL_TEST([ovn_nbctl_error_paths], [commands parser error paths], [ dnl FIXME: Duplicate options are allowed when passed with global options. dnl For example: ovn-nbctl --if-exists --if-exists list Logical_Switch @@ -1569,21 +1507,13 @@ AT_CHECK([ovn-nbctl show foo --bar], [1], [], [stderr]) AT_CHECK([grep 'command takes at most .* arguments' stderr], [0], [ignore]) AT_CHECK([ovn-nbctl -- show foo --bar], [1], [], [stderr]) -AT_CHECK([grep 'command takes at most .* arguments' stderr], [0], [ignore]) - -OVN_NBCTL_TEST_STOP -AT_CLEANUP +AT_CHECK([grep 'command takes at most .* arguments' stderr], [0], [ignore])]) dnl --------------------------------------------------------------------- -AT_SETUP([ovn-nbctl - Port Groups]) -OVN_NBCTL_TEST_START - +OVN_NBCTL_TEST([ovn_nbctl_port_groups], [port groups], [ dnl Check that port group can be looked up by name AT_CHECK([ovn-nbctl create Port_Group name=pg0], [0], [ignore]) AT_CHECK([ovn-nbctl get Port_Group pg0 name], [0], [dnl "pg0" -]) - -OVN_NBCTL_TEST_STOP -AT_CLEANUP +])])