By being able to start up ovn-northd-ddlog in a paused state, we can
produce a recording for use in debugging without having to restart one
of the real ovn-northd-ddlog processes or disturbing the system.

Signed-off-by: Ben Pfaff <[email protected]>
CC: Ihar Hrachyshka <[email protected]>
---
 NEWS                      |  2 +-
 northd/ovn-northd-ddlog.c | 43 ++++++++++++++++++++++++---------------
 northd/ovn-northd.8.xml   | 25 ++++++++++++++++++++---
 northd/ovn-northd.c       | 19 ++++++++++++-----
 tests/ovn-macros.at       | 22 ++++++++++++++------
 tests/ovn-northd.at       | 16 +++++++--------
 6 files changed, 88 insertions(+), 39 deletions(-)

diff --git a/NEWS b/NEWS
index f96ed73f0823..96c9397361a2 100644
--- a/NEWS
+++ b/NEWS
@@ -18,7 +18,7 @@ Post-v21.03.0
     datapath flows with this field used.
   - Introduce a new "allow-stateless" ACL verb to always bypass connection
     tracking. The existing "allow" verb behavior is left intact.
-  - Added support in native DNS to respond to PTR request types.
+  - New --dry-run option for ovn-northd and ovn-northd-ddlog.
 
 OVN v21.03.0 - 12 Mar 2021
 -------------------------
diff --git a/northd/ovn-northd-ddlog.c b/northd/ovn-northd-ddlog.c
index c79e15312b64..73bf5290eb35 100644
--- a/northd/ovn-northd-ddlog.c
+++ b/northd/ovn-northd-ddlog.c
@@ -159,7 +159,8 @@ northd_ctx_create(const char *server, const char *database,
                   ddlog_prog ddlog, ddlog_delta *delta,
                   const char **input_relations,
                   const char **output_relations,
-                  const char **output_only_relations)
+                  const char **output_only_relations,
+                  bool paused)
 {
     struct northd_ctx *ctx = xmalloc(sizeof *ctx);
     *ctx = (struct northd_ctx) {
@@ -175,7 +176,7 @@ northd_ctx_create(const char *server, const char *database,
         .db_name = database,
         /* 'output_only_relations' will get filled in later. */
         .lock_name = lock_name,
-        .paused = false,
+        .paused = paused,
     };
 
     ovsdb_cs_set_remote(ctx->cs, server, true);
@@ -1041,7 +1042,7 @@ static void
 usage(void)
 {
     printf("\
-%s: OVN northbound management daemon\n\
+%s: OVN northbound management daemon (DDlog version)\n\
 usage: %s [OPTIONS]\n\
 \n\
 Options:\n\
@@ -1049,6 +1050,7 @@ Options:\n\
                             (default: %s)\n\
   --ovnsb-db=DATABASE       connect to ovn-sb database at DATABASE\n\
                             (default: %s)\n\
+  --dry-run                 start in paused state (do not commit db changes)\n\
   --ddlog-record=FILE.TXT   record db changes to replay later for debugging\n\
   --unixctl=SOCKET          override default control socket name\n\
   -h, --help                display this help message\n\
@@ -1061,22 +1063,25 @@ Options:\n\
 }
 
 static void
-parse_options(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
+parse_options(int argc OVS_UNUSED, char *argv[] OVS_UNUSED,
+              bool *pause)
 {
     enum {
         OVN_DAEMON_OPTION_ENUMS,
         VLOG_OPTION_ENUMS,
         SSL_OPTION_ENUMS,
+        OPT_DRY_RUN,
         OPT_DDLOG_RECORD
     };
     static const struct option long_options[] = {
-        {"ddlog-record", required_argument, NULL, OPT_DDLOG_RECORD},
         {"ovnsb-db", required_argument, NULL, 'd'},
         {"ovnnb-db", required_argument, NULL, 'D'},
         {"unixctl", required_argument, NULL, 'u'},
         {"help", no_argument, NULL, 'h'},
         {"options", no_argument, NULL, 'o'},
         {"version", no_argument, NULL, 'V'},
+        {"dry-run", no_argument, NULL, OPT_DRY_RUN},
+        {"ddlog-record", required_argument, NULL, OPT_DDLOG_RECORD},
         OVN_DAEMON_LONG_OPTIONS,
         VLOG_LONG_OPTIONS,
         STREAM_SSL_LONG_OPTIONS,
@@ -1097,10 +1102,6 @@ parse_options(int argc OVS_UNUSED, char *argv[] 
OVS_UNUSED)
         VLOG_OPTION_HANDLERS;
         STREAM_SSL_OPTION_HANDLERS;
 
-        case OPT_DDLOG_RECORD:
-            record_file = optarg;
-            break;
-
         case 'd':
             ovnsb_db = optarg;
             break;
@@ -1125,6 +1126,14 @@ parse_options(int argc OVS_UNUSED, char *argv[] 
OVS_UNUSED)
             ovs_print_version(0, 0);
             exit(EXIT_SUCCESS);
 
+        case OPT_DRY_RUN:
+            *pause = true;
+            break;
+
+        case OPT_DDLOG_RECORD:
+            record_file = optarg;
+            break;
+
         default:
             break;
         }
@@ -1148,6 +1157,10 @@ main(int argc, char *argv[])
     struct unixctl_server *unixctl;
     int retval;
     bool exiting;
+    struct northd_status status = {
+        .locked = false,
+        .pause = false,
+    };
 
     init_table_ids();
 
@@ -1155,7 +1168,7 @@ main(int argc, char *argv[])
     ovs_cmdl_proctitle_init(argc, argv);
     set_program_name(argv[0]);
     service_start(&argc, &argv);
-    parse_options(argc, argv);
+    parse_options(argc, argv, &status.pause);
 
     daemonize_start(false);
 
@@ -1167,10 +1180,6 @@ main(int argc, char *argv[])
         exit(EXIT_FAILURE);
     }
 
-    struct northd_status status = {
-        .locked = false,
-        .pause = false,
-    };
     unixctl_command_register("exit", "", 0, 0, ovn_northd_exit, &exiting);
     unixctl_command_register("status", "", 0, 0, ovn_northd_status, &status);
 
@@ -1202,10 +1211,12 @@ main(int argc, char *argv[])
 
     struct northd_ctx *nb_ctx = northd_ctx_create(
         ovnnb_db, "OVN_Northbound", "nb", NULL, ddlog, delta,
-        nb_input_relations, nb_output_relations, nb_output_only_relations);
+        nb_input_relations, nb_output_relations, nb_output_only_relations,
+        status.pause);
     struct northd_ctx *sb_ctx = northd_ctx_create(
         ovnsb_db, "OVN_Southbound", "sb", "ovn_northd", ddlog, delta,
-        sb_input_relations, sb_output_relations, sb_output_only_relations);
+        sb_input_relations, sb_output_relations, sb_output_only_relations,
+        status.pause);
 
     unixctl_command_register("pause", "", 0, 0, ovn_northd_pause, sb_ctx);
     unixctl_command_register("resume", "", 0, 0, ovn_northd_resume, sb_ctx);
diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml
index b7214b05e7ed..0c75d0795817 100644
--- a/northd/ovn-northd.8.xml
+++ b/northd/ovn-northd.8.xml
@@ -52,6 +52,22 @@
         <code>debugging-ddlog.rst</code> in the OVN documentation for more
         details.
       </dd>
+      <dt><code>--dry-run</code></dt>
+      <dd>
+        <p>
+          Causes <code>ovn-northd</code> to start paused.  In the paused state,
+          <code>ovn-northd</code> does not apply any changes to the databases,
+          although it continues to monitor them.  For more information, see the
+          <code>pause</code> command, under <code>Runtime Management
+          Commands</code> below.
+        </p>
+
+        <p>
+          For <code>ovn-northd-ddlog</code>, one could use this option with
+          <code>--ddlog-record</code> to generate a replay log without
+          restarting a process or disturbing a running system.
+        </p>
+      </dd>
     </dl>
     <p>
       <var>database</var> in the above options must be an OVSDB active or
@@ -91,9 +107,12 @@
 
       <dt><code>pause</code></dt>
       <dd>
-        Pauses the ovn-northd operation from processing any Northbound and
-        Southbound database changes.  This will also instruct ovn-northd to
-        drop any lock on SB DB.
+        Pauses <code>ovn-northd</code>.  When it is paused,
+        <code>ovn-northd</code> receives changes from the Northbound and
+        Southbound database changes as usual, but it does not send any updates.
+        A paused <code>ovn-northd</code> also drops database locks, which
+        allows any other non-paused instance of <code>ovn-northd</code> to take
+        over.
       </dd>
 
       <dt><code>resume</code></dt>
diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c
index 0e5092a875ff..f97b23dec0b2 100644
--- a/northd/ovn-northd.c
+++ b/northd/ovn-northd.c
@@ -401,6 +401,7 @@ Options:\n\
                             (default: %s)\n\
   --ovnsb-db=DATABASE       connect to ovn-sb database at DATABASE\n\
                             (default: %s)\n\
+  --dry-run                 start in paused state (do not commit db changes)\n\
   --unixctl=SOCKET          override default control socket name\n\
   -h, --help                display this help message\n\
   -o, --options             list available options\n\
@@ -13977,12 +13978,14 @@ ovn_db_run(struct northd_context *ctx,
 }
 
 static void
-parse_options(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
+parse_options(int argc OVS_UNUSED, char *argv[] OVS_UNUSED,
+              bool *paused)
 {
     enum {
         OVN_DAEMON_OPTION_ENUMS,
         VLOG_OPTION_ENUMS,
         SSL_OPTION_ENUMS,
+        OPT_DRY_RUN,
     };
     static const struct option long_options[] = {
         {"ovnsb-db", required_argument, NULL, 'd'},
@@ -13991,6 +13994,7 @@ parse_options(int argc OVS_UNUSED, char *argv[] 
OVS_UNUSED)
         {"help", no_argument, NULL, 'h'},
         {"options", no_argument, NULL, 'o'},
         {"version", no_argument, NULL, 'V'},
+        {"dry-run", no_argument, NULL, OPT_DRY_RUN},
         OVN_DAEMON_LONG_OPTIONS,
         VLOG_LONG_OPTIONS,
         STREAM_SSL_LONG_OPTIONS,
@@ -14035,6 +14039,10 @@ parse_options(int argc OVS_UNUSED, char *argv[] 
OVS_UNUSED)
             ovn_print_version(0, 0);
             exit(EXIT_SUCCESS);
 
+        case OPT_DRY_RUN:
+            *paused = true;
+            break;
+
         default:
             break;
         }
@@ -14066,13 +14074,16 @@ main(int argc, char *argv[])
     struct unixctl_server *unixctl;
     int retval;
     bool exiting;
-    struct northd_state state;
+    struct northd_state state = {
+        .had_lock = false,
+        .paused = false
+    };
 
     fatal_ignore_sigpipe();
     ovs_cmdl_proctitle_init(argc, argv);
     ovn_set_program_name(argv[0]);
     service_start(&argc, &argv);
-    parse_options(argc, argv);
+    parse_options(argc, argv, &state.paused);
 
     daemonize_start(false);
 
@@ -14371,8 +14382,6 @@ main(int argc, char *argv[])
 
     /* Main loop. */
     exiting = false;
-    state.had_lock = false;
-    state.paused = false;
 
     while (!exiting) {
         memory_run();
diff --git a/tests/ovn-macros.at b/tests/ovn-macros.at
index 94fba405ea33..2217131ab234 100644
--- a/tests/ovn-macros.at
+++ b/tests/ovn-macros.at
@@ -149,8 +149,12 @@ ovn_init_ic_db () {
     ovn_init_db ovn-ic-sb
 }
 
-# ovn_start_northd (primary|backup) [AZ]
+# ovn_start_northd [--paused] (primary|backup) [AZ]
 ovn_start_northd() {
+    local northd_args=
+    case $1 in
+        --paused) northd_args=--dry-run; shift ;;
+    esac
     local priority=$1
     local AZ=$2
     local msg_prefix=${AZ:+$AZ: }
@@ -161,10 +165,9 @@ ovn_start_northd() {
         backup) suffix=-backup ;;
     esac
 
-    local northd_args=
     case ${NORTHD_TYPE:=ovn-northd} in
         ovn-northd) ;;
-        ovn-northd-ddlog) 
northd_args="--ddlog-record=${AZ:+$AZ/}northd$suffix/replay.dat -v" ;;
+        ovn-northd-ddlog) northd_args="$northd_args 
--ddlog-record=${AZ:+$AZ/}northd$suffix/replay.dat -v" ;;
     esac
 
     local name=${d_prefix}northd${suffix}
@@ -174,16 +177,23 @@ ovn_start_northd() {
                --ovnnb-db=$OVN_NB_DB --ovnsb-db=$OVN_SB_DB
 }
 
-# ovn_start [--no-backup-northd] [AZ]
+# ovn_start [--backup-northd=none|paused] [AZ]
 #
 # Creates and initializes ovn-sb and ovn-nb databases and starts their
 # ovsdb-server instance, sets appropriate environment variables so that
 # ovn-sbctl and ovn-nbctl use them by default, and starts ovn-northd running
 # against them.
+#
+# Normally this starts an active northd and a backup norhtd.  The following
+# options are accepted to adjust that:
+#   --backup-northd=none    Don't start a backup northd.
+#   --backup-northd=paused  Start the backup northd in the paused state.
 ovn_start () {
     local backup_northd=:
+    local backup_northd_options=
     case $1 in
-        --no-backup-northd) backup_northd=false; shift ;;
+        --backup-northd=none) backup_northd=false; shift ;;
+        --backup-northd=paused) backup_northd_options=--paused; shift ;;
     esac
     local AZ=$1
     local msg_prefix=${AZ:+$AZ: }
@@ -201,7 +211,7 @@ ovn_start () {
 
     ovn_start_northd primary $AZ
     if $backup_northd; then
-        ovn_start_northd backup $AZ
+        ovn_start_northd $backup_northd_options backup $AZ
     fi
 
     if test X$HAVE_OPENSSL = Xyes; then
diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
index bff2ade43b4d..28a46702cf48 100644
--- a/tests/ovn-northd.at
+++ b/tests/ovn-northd.at
@@ -641,7 +641,10 @@ AT_CLEANUP
 
 OVN_FOR_EACH_NORTHD([
 AT_SETUP([ovn -- ovn-northd pause and resume])
-ovn_start
+# By starting the backup northd paused, we ensure that the primary
+# northd is active; otherwise, there's a race.  (We also test that
+# the ovn-northd --dry-run option works.)
+ovn_start --backup-northd=paused
 
 get_northd_status() {
     as northd ovn-appctl -t NORTHD_TYPE is-paused
@@ -650,10 +653,7 @@ get_northd_status() {
     as northd-backup ovn-appctl -t NORTHD_TYPE status
 }
 
-AS_BOX([Pause the backup])
-# This forces the main northd to become active (otherwise there's no
-# guarantee, ovn_start is racy).
-check as northd-backup ovs-appctl -t NORTHD_TYPE pause
+AS_BOX([Check that the backup is paused])
 OVS_WAIT_FOR_OUTPUT([get_northd_status], [0], [false
 Status: active
 true
@@ -709,7 +709,7 @@ AT_CLEANUP
 
 OVN_FOR_EACH_NORTHD([
 AT_SETUP([ovn -- ovn-northd restart])
-ovn_start --no-backup-northd
+ovn_start --backup-northd=none
 
 # Check that ovn-northd is active, by verifying that it creates and
 # destroys southbound datapaths as one would expect.
@@ -741,7 +741,7 @@ dnl This test doesn't take into account flows that are 
shared between
 dnl datapaths when datapath groups are enabled.
 AT_SKIP_IF([test NORTHD_USE_DP_GROUPS = yes])
 
-ovn_start --no-backup-northd
+ovn_start --backup-northd=none
 
 # Check that ovn-northd is active, by verifying that it creates and
 # destroys southbound datapaths as one would expect.
@@ -781,7 +781,7 @@ dnl This test doesn't take into account flows that are 
shared between
 dnl datapaths when datapath groups are enabled.
 AT_SKIP_IF([test NORTHD_USE_DP_GROUPS = yes])
 
-ovn_start --no-backup-northd
+ovn_start --backup-northd=none
 
 # Check that ovn-northd is active, by verifying that it creates and
 # destroys southbound datapaths as one would expect.
-- 
2.31.1

_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to