]> git.proxmox.com Git - mirror_corosync.git/commitdiff
cfg: Reinstate cfg tracking
authorChristine Caulfield <ccaulfie@redhat.com>
Mon, 11 Jan 2021 09:28:34 +0000 (09:28 +0000)
committerJan Friesse <jfriesse@redhat.com>
Thu, 14 Jan 2021 15:09:46 +0000 (16:09 +0100)
CFG tracking was removed in 815375411e80131f31b172d7c43625769ee8b53d,
probably as a mistake, as part of the tidy up of cfg and the removal of
dynamic loading. This means that shutdown tracking (using
cfg_try_shutdown()) stopped working.

This patch restores the trackstart & trackstop API calls (renamed to be
more consistent with the exiting libraries) so that shutdown tracking
can be used again.

Change cfg.shutdown_timeout to be in milliseconds rather than seconds
nd use libqb macros for conversion.

Add --force option to corosync-cfgtool -H

Signed-off-by: Christine Caulfield <ccaulfie@redhat.com>
Reviewed-by: Jan Friesse <jfriesse@redhat.com>
exec/cfg.c
include/corosync/cfg.h
include/corosync/ipc_cfg.h
lib/cfg.c
lib/libcfg.versions
lib/libcfg.verso
man/cmap_keys.7
man/corosync-cfgtool.8
tools/corosync-cfgtool.c

index 991baf2215bbe05f8c507ec3a2dc4d523cde422c..05b0ede53aefb56259d31420f11999fac88a03db 100644 (file)
@@ -55,6 +55,7 @@
 #include <qb/qbipc_common.h>
 #include <corosync/cfg.h>
 #include <qb/qblist.h>
+#include <qb/qbutil.h>
 #include <corosync/mar_gen.h>
 #include <corosync/totem/totemip.h>
 #include <corosync/totem/totem.h>
@@ -79,7 +80,8 @@ enum cfg_message_req_types {
        MESSAGE_REQ_EXEC_CFG_CRYPTO_RECONFIG = 4
 };
 
-#define DEFAULT_SHUTDOWN_TIMEOUT 5
+/* in milliseconds */
+#define DEFAULT_SHUTDOWN_TIMEOUT 5000
 
 static struct qb_list_head trackers_list;
 
@@ -162,6 +164,14 @@ static void message_handler_req_lib_cfg_replytoshutdown (
        void *conn,
        const void *msg);
 
+static void message_handler_req_lib_cfg_trackstart (
+       void *conn,
+       const void *msg);
+
+static void message_handler_req_lib_cfg_trackstop (
+       void *conn,
+       const void *msg);
+
 static void message_handler_req_lib_cfg_get_node_addrs (
        void *conn,
        const void *msg);
@@ -222,7 +232,16 @@ static struct corosync_lib_handler cfg_lib_engine[] =
        { /* 9 */
                .lib_handler_fn         = message_handler_req_lib_cfg_nodestatusget,
                .flow_control           = CS_LIB_FLOW_CONTROL_NOT_REQUIRED
-       }
+       },
+       { /* 10 */
+               .lib_handler_fn         = message_handler_req_lib_cfg_trackstart,
+               .flow_control           = CS_LIB_FLOW_CONTROL_REQUIRED
+       },
+       { /* 11 */
+               .lib_handler_fn         = message_handler_req_lib_cfg_trackstop,
+               .flow_control           = CS_LIB_FLOW_CONTROL_REQUIRED
+       },
+
 };
 
 static struct corosync_exec_handler cfg_exec_engine[] =
@@ -1045,6 +1064,52 @@ ipc_response_send:
        LEAVE();
 }
 
+static void message_handler_req_lib_cfg_trackstart (
+       void *conn,
+       const void *msg)
+{
+       struct cfg_info *ci = (struct cfg_info *)api->ipc_private_data_get (conn);
+       struct res_lib_cfg_trackstart res_lib_cfg_trackstart;
+
+       ENTER();
+
+       /*
+        * We only do shutdown tracking at the moment
+        */
+       if (qb_list_empty(&ci->list)) {
+               qb_list_add(&ci->list, &trackers_list);
+               ci->tracker_conn = conn;
+
+               if (shutdown_con) {
+                       /*
+                        * Shutdown already in progress, ask the newcomer's opinion
+                        */
+                       ci->shutdown_reply = SHUTDOWN_REPLY_UNKNOWN;
+                       shutdown_expected++;
+                       send_test_shutdown(conn, NULL, CS_OK);
+               }
+       }
+
+       res_lib_cfg_trackstart.header.size = sizeof(struct res_lib_cfg_trackstart);
+       res_lib_cfg_trackstart.header.id = MESSAGE_RES_CFG_STATETRACKSTART;
+       res_lib_cfg_trackstart.header.error = CS_OK;
+
+       api->ipc_response_send(conn, &res_lib_cfg_trackstart,
+                                   sizeof(res_lib_cfg_trackstart));
+
+       LEAVE();
+}
+
+static void message_handler_req_lib_cfg_trackstop (
+       void *conn,
+       const void *msg)
+{
+       struct cfg_info *ci = (struct cfg_info *)api->ipc_private_data_get (conn);
+
+       ENTER();
+       remove_ci_from_shutdown(ci);
+       LEAVE();
+}
 
 static void message_handler_req_lib_cfg_ringreenable (
        void *conn,
@@ -1240,7 +1305,7 @@ static void message_handler_req_lib_cfg_tryshutdown (
                 * Start the timer. If we don't get a full set of replies before this goes
                 * off we'll cancel the shutdown
                 */
-               api->timer_add_duration((unsigned long long)shutdown_timeout*1000000000, NULL,
+               api->timer_add_duration((unsigned long long)shutdown_timeout*QB_TIME_NS_IN_MSEC, NULL,
                                        shutdown_timer_fn, &shutdown_timer);
 
                /*
index a7babc28996fbcdef73698ae63c8e2440edfdc11..f3bce09e07e42c078dbba87489086cbae4c2b239 100644 (file)
@@ -217,6 +217,30 @@ corosync_cfg_kill_node (
        unsigned int nodeid,
        const char *reason);
 
+/**
+ * @brief corosync_cfg_trackstart
+ * Track CFG for shutdown requests
+ * @param cfg_handle
+ * @param track_flags (none currently supported)
+ * @param reason
+ * @return
+ */
+cs_error_t
+corosync_cfg_trackstart (
+        corosync_cfg_handle_t cfg_handle,
+        uint8_t track_flags);
+
+/**
+ * @brief corosync_cfg_trackstop
+ * Stop tracking CFG for shutdown requests
+ * @param cfg_handle
+ * @param reason
+ * @return
+ */
+cs_error_t
+corosync_cfg_trackstop (
+        corosync_cfg_handle_t cfg_handle);
+
 /**
  * @brief corosync_cfg_try_shutdown
  * @param cfg_handle
index 65285a68f90a331867a03ecfb78464f87bd88410..07e4adcd922064ae96636da43b2dd63172472634 100644 (file)
@@ -60,7 +60,9 @@ enum req_lib_cfg_types {
        MESSAGE_REQ_CFG_LOCAL_GET = 6,
        MESSAGE_REQ_CFG_RELOAD_CONFIG = 7,
        MESSAGE_REQ_CFG_REOPEN_LOG_FILES = 8,
-       MESSAGE_REQ_CFG_NODESTATUSGET = 9
+       MESSAGE_REQ_CFG_NODESTATUSGET = 9,
+       MESSAGE_REQ_CFG_TRACKSTART = 10,
+       MESSAGE_REQ_CFG_TRACKSTOP = 11
 };
 
 /**
@@ -255,6 +257,24 @@ struct res_lib_cfg_reopen_log_files {
        struct qb_ipc_response_header header __attribute__((aligned(8)));
 };
 
+struct req_lib_cfg_trackstart {
+       struct qb_ipc_request_header header;
+       uint8_t track_flags;
+};
+
+struct res_lib_cfg_trackstart {
+       struct qb_ipc_response_header header;
+};
+
+struct req_lib_cfg_trackstop {
+       struct qb_ipc_request_header header;
+};
+
+struct res_lib_cfg_trackstop {
+       struct qb_ipc_response_header header;
+};
+
+
 /**
  * @brief corosync_administrative_target_t enum
  */
index 4ce3582ddee1539772a2b365f6287c60eff5bf1b..f0a3e9acaaeaa1c3c4df45a5119c1fd00e105d1e 100644 (file)
--- a/lib/cfg.c
+++ b/lib/cfg.c
@@ -447,6 +447,75 @@ error_put:
        return (error);
 }
 
+
+cs_error_t
+corosync_cfg_trackstart (
+       corosync_cfg_handle_t cfg_handle,
+       uint8_t track_flags)
+{
+       struct cfg_inst *cfg_inst;
+       struct req_lib_cfg_trackstart req_lib_cfg_trackstart;
+       struct res_lib_cfg_trackstart res_lib_cfg_trackstart;
+       cs_error_t error;
+       struct iovec iov;
+
+       req_lib_cfg_trackstart.header.size = sizeof (struct req_lib_cfg_trackstart);
+       req_lib_cfg_trackstart.header.id = MESSAGE_REQ_CFG_TRACKSTART;
+       req_lib_cfg_trackstart.track_flags = track_flags;
+
+       error = hdb_error_to_cs(hdb_handle_get (&cfg_hdb, cfg_handle,
+               (void *)&cfg_inst));
+       if (error != CS_OK) {
+               return (error);
+       }
+
+       iov.iov_base = (void *)&req_lib_cfg_trackstart,
+       iov.iov_len = sizeof (struct req_lib_cfg_trackstart),
+
+       error = qb_to_cs_error (qb_ipcc_sendv_recv (cfg_inst->c,
+               &iov,
+               1,
+               &res_lib_cfg_trackstart,
+               sizeof (struct res_lib_cfg_trackstart), CS_IPC_TIMEOUT_MS));
+
+       (void)hdb_handle_put (&cfg_hdb, cfg_handle);
+
+       return (error == CS_OK ? res_lib_cfg_trackstart.header.error : error);
+}
+
+cs_error_t
+corosync_cfg_trackstop (
+       corosync_cfg_handle_t cfg_handle)
+{
+       struct cfg_inst *cfg_inst;
+       struct req_lib_cfg_trackstop req_lib_cfg_trackstop;
+       struct res_lib_cfg_trackstop res_lib_cfg_trackstop;
+       cs_error_t error;
+       struct iovec iov;
+
+       error = hdb_error_to_cs (hdb_handle_get (&cfg_hdb, cfg_handle,
+               (void *)&cfg_inst));
+       if (error != CS_OK) {
+               return (error);
+       }
+
+       req_lib_cfg_trackstop.header.size = sizeof (struct req_lib_cfg_trackstop);
+       req_lib_cfg_trackstop.header.id = MESSAGE_REQ_CFG_TRACKSTOP;
+
+       iov.iov_base = (void *)&req_lib_cfg_trackstop,
+       iov.iov_len = sizeof (struct req_lib_cfg_trackstop),
+
+       error = qb_to_cs_error (qb_ipcc_sendv_recv (cfg_inst->c,
+               &iov,
+               1,
+               &res_lib_cfg_trackstop,
+               sizeof (struct res_lib_cfg_trackstop), CS_IPC_TIMEOUT_MS));
+
+       (void)hdb_handle_put (&cfg_hdb, cfg_handle);
+
+       return (error == CS_OK ? res_lib_cfg_trackstop.header.error : error);
+}
+
 cs_error_t
 corosync_cfg_kill_node (
        corosync_cfg_handle_t cfg_handle,
@@ -487,7 +556,7 @@ corosync_cfg_kill_node (
 
        (void)hdb_handle_put (&cfg_hdb, cfg_handle);
 
-        return (error == CS_OK ? res_lib_cfg_killnode.header.error : error);
+       return (error == CS_OK ? res_lib_cfg_killnode.header.error : error);
 }
 
 cs_error_t
@@ -522,7 +591,7 @@ corosync_cfg_try_shutdown (
 
        (void)hdb_handle_put (&cfg_hdb, cfg_handle);
 
-        return (error == CS_OK ? res_lib_cfg_tryshutdown.header.error : error);
+       return (error == CS_OK ? res_lib_cfg_tryshutdown.header.error : error);
 }
 
 cs_error_t
index 8fba91848fa8d548bcc3064fb0e1cc9bbc937316..18d18f70da798c4f470177c5f61654e806be83b7 100644 (file)
@@ -13,6 +13,6 @@ COROSYNC_CFG_0.82 {
                corosync_cfg_ring_status_get;
                corosync_cfg_node_status_get;
                corosync_cfg_ring_reenable;
-               corosync_cfg_service_load;
-               corosync_cfg_service_unload;
+               corosync_cfg_trackstart;
+               corosync_cfg_trackstop;
 };
index 0ee843cc60466c722c3e7f2460f9761ad0e46b63..1502020768a7b4ee9a2968d4efa1fcb13ce8d53f 100644 (file)
@@ -1 +1 @@
-7.2.0
+7.3.0
index da95c51d0ab0a206149a76f501b23ec25a20c054..320917aa302e77d8e75ccd8b2c364dbdc5eb1d8c 100644 (file)
@@ -147,6 +147,11 @@ quorum.cancel_wait_for_all
 Tells votequorum to cancel waiting for all nodes at cluster startup. Can be used
 to unblock quorum if notes are known to be down. For pcs use only.
 
+.TP
+cfg.shutdown_timeout
+Sets the timeout within which daemons that are registered for cfg callbacks must respond
+to a corosync_cfg_try_shutdown() request. the default is 5000 mS
+
 .TP
 config.reload_in_progress
 This value will be set to 1 (or created) when a corosync.conf reload is started,
index 007cbbe344d71a671d74aab6ea21304714c460c8..119821344b128fec3a0d3f8ad07860291e3c3aec 100644 (file)
@@ -35,7 +35,7 @@
 .SH "NAME"
 corosync-cfgtool \- An administrative tool for corosync.
 .SH "SYNOPSIS"
-.B corosync\-cfgtool [[\-i IP_address] [\-b] [\-s] [\-n] [\-R] [\-L] [\-k nodeid] [\-a nodeid] [\-h] [\-H]
+.B corosync\-cfgtool [[\-i IP_address] [\-b] [\-s] [\-n] [\-R] [\-L] [\-k nodeid] [\-a nodeid] [\-h] [\-H] [\--force]
 .SH "DESCRIPTION"
 .B corosync\-cfgtool
 A tool for displaying and configuring active parameters within corosync.
@@ -123,6 +123,12 @@ Print basic usage.
 .TP
 .B -H
 Shutdown corosync cleanly on this node.
+corosync-cfgtool -H will request a shutdown from corosync, which means it will
+consult any interested daemons before shutting down and the shutdown maybe vetoed if a
+daemon regards the shutdown as inappropriate.
+If --force is added to the command line then corosync will shutdown regardless
+of the daemons' opinions on the matter.
+
 .SH "SEE ALSO"
 .BR corosync_overview (7),
 .SH "AUTHOR"
index 0de50bd796ef9c8faf9e59e2f5df62ee9dfb0a90..23125558351c0af400e084f00e9a81f53cf19a50 100644 (file)
@@ -47,6 +47,7 @@
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <limits.h>
+#include <getopt.h>
 
 #include <corosync/corotypes.h>
 #include <corosync/totem/totem.h>
@@ -341,13 +342,19 @@ static int reopen_log_files_do (void)
        return (rc);
 }
 
-static void shutdown_do(void)
+static void shutdown_do(int force)
 {
        cs_error_t result;
        corosync_cfg_handle_t handle;
        corosync_cfg_callbacks_t callbacks;
+       int flag;
 
        callbacks.corosync_cfg_shutdown_callback = NULL;
+       if (force) {
+               flag = COROSYNC_CFG_SHUTDOWN_FLAG_REGARDLESS;
+       } else {
+               flag = COROSYNC_CFG_SHUTDOWN_FLAG_REQUEST;
+       }
 
        result = corosync_cfg_initialize (&handle, &callbacks);
        if (result != CS_OK) {
@@ -356,7 +363,7 @@ static void shutdown_do(void)
        }
 
        printf ("Shutting down corosync\n");
-       cs_repeat(result, 30, corosync_cfg_try_shutdown (handle, COROSYNC_CFG_SHUTDOWN_FLAG_REQUEST));
+       cs_repeat(result, 30, corosync_cfg_try_shutdown (handle, flag));
        if (result != CS_OK) {
                fprintf (stderr, "Could not shutdown (error = %d)\n", result);
        }
@@ -450,10 +457,10 @@ static void usage_do (void)
        printf ("\t-a\tDisplay the IP address(es) of a node\n");
        printf ("\t-h\tPrint basic usage.\n");
        printf ("\t-H\tShutdown corosync cleanly on this node.\n");
+       printf ("\t\t--force will shut down corosync regardless of daemon vetos\n");
 }
 
 int main (int argc, char *argv[]) {
-       const char *options = "i:snbrRLk:a:hH";
        int opt;
        unsigned int nodeid = 0;
        char interface_name[128] = "";
@@ -461,9 +468,30 @@ int main (int argc, char *argv[]) {
        enum user_action action = ACTION_NOOP;
        int brief = 0;
        long long int l;
-
-       while ( (opt = getopt(argc, argv, options)) != -1 ) {
+       int option_index = 0;
+       int force_shutdown  = 0;
+       const char *options = "i:snbrRLk:a:hH";
+       struct option long_options[] = {
+               {"if",       required_argument, 0, 'i'},
+               {"status",   no_argument,       0, 's'},
+               {"nodes",    no_argument,       0, 'n'},
+               {"brief",    no_argument,       0, 'b'},
+               {"reload",   no_argument,       0, 'R'},
+               {"reopen",   no_argument,       0, 'L'},
+               {"kill",     required_argument, 0, 'k'},
+               {"address",  required_argument, 0, 'a'},
+               {"shutdown", no_argument,       0, 'H'},
+               {"force",    no_argument,       0, 0},
+               {0,          0,                 0, 0}
+       };
+
+               while ( (opt = getopt_long(argc, argv, options, long_options, &option_index)) != -1 ) {
                switch (opt) {
+                       case 0: // options with no short equivalent - just --force ATM
+                       if (strcmp(long_options[option_index].name, "force") == 0) {
+                               force_shutdown = 1;
+                       }
+                       break;
                case 'i':
                        strncpy(interface_name, optarg, sizeof(interface_name));
                        interface_name[sizeof(interface_name) - 1] = '\0';
@@ -527,7 +555,7 @@ int main (int argc, char *argv[]) {
                killnode_do(nodeid);
                break;
        case ACTION_SHUTDOW:
-               shutdown_do();
+               shutdown_do(force_shutdown);
                break;
        case ACTION_SHOWADDR:
                rc = showaddrs_do(nodeid);