Blame SOURCES/0004-Fix-sbd-cluster-match-qdevice-sync_timeout-against-w.patch

f21030
From 4c3e4049b08799094a64dac289a48deef4d3d916 Mon Sep 17 00:00:00 2001
f21030
From: Klaus Wenninger <klaus.wenninger@aon.at>
f21030
Date: Fri, 24 Jul 2020 14:31:01 +0200
f21030
Subject: [PATCH] Fix: sbd-cluster: match qdevice-sync_timeout against
f21030
 wd-timeout
f21030
f21030
---
f21030
 configure.ac      |  13 +++
f21030
 src/sbd-cluster.c | 252 +++++++++++++++++++++++++++++++++++++++++++++---------
f21030
 2 files changed, 223 insertions(+), 42 deletions(-)
f21030
f21030
diff --git a/configure.ac b/configure.ac
f21030
index 3391c5f..23547cf 100644
f21030
--- a/configure.ac
f21030
+++ b/configure.ac
f21030
@@ -109,6 +109,12 @@ AC_TEST_NO_QUORUM_POLICY(no_quorum_demote)
f21030
 dnl check for new pe-API
f21030
 AC_CHECK_FUNCS(pe_new_working_set)
f21030
 
f21030
+dnl check if votequorum comes with default for qdevice-sync_timeout
f21030
+AC_CHECK_DECLS([VOTEQUORUM_QDEVICE_DEFAULT_SYNC_TIMEOUT],
f21030
+               HAVE_DECL_VOTEQUORUM_QDEVICE_DEFAULT_SYNC_TIMEOUT=1,
f21030
+               HAVE_DECL_VOTEQUORUM_QDEVICE_DEFAULT_SYNC_TIMEOUT=0,
f21030
+               [#include <corosync/votequorum.h>])
f21030
+
f21030
 if test "$missing" = "yes"; then
f21030
    AC_MSG_ERROR([Missing required libraries or functions.])
f21030
 fi
f21030
@@ -140,6 +146,13 @@ AM_CONDITIONAL(CHECK_TWO_NODE, test "$HAVE_cmap" = "1")
f21030
 AC_DEFINE_UNQUOTED(CHECK_VOTEQUORUM_HANDLE, $HAVE_votequorum, Turn on periodic checking of votequorum-handle)
f21030
 AM_CONDITIONAL(CHECK_VOTEQUORUM_HANDLE, test "$HAVE_votequorum" = "1")
f21030
 
f21030
+AC_DEFINE_UNQUOTED(CHECK_QDEVICE_SYNC_TIMEOUT,
f21030
+                   ($HAVE_DECL_VOTEQUORUM_QDEVICE_DEFAULT_SYNC_TIMEOUT && $HAVE_cmap),
f21030
+                   Turn on checking if watchdog-timeout and qdevice-sync_timeout are matching)
f21030
+AM_CONDITIONAL(CHECK_QDEVICE_SYNC_TIMEOUT,
f21030
+               test "$HAVE_DECL_VOTEQUORUM_QDEVICE_DEFAULT_SYNC_TIMEOUT" = "1" &&
f21030
+               test "$HAVE_cmap" = "1")
f21030
+
f21030
 CONFIGDIR=""
f21030
 AC_ARG_WITH(configdir,
f21030
     [  --with-configdir=DIR
f21030
diff --git a/src/sbd-cluster.c b/src/sbd-cluster.c
f21030
index 13fa580..b6c5512 100644
f21030
--- a/src/sbd-cluster.c
f21030
+++ b/src/sbd-cluster.c
f21030
@@ -33,7 +33,7 @@
f21030
 #include <crm/cluster.h>
f21030
 #include <crm/common/mainloop.h>
f21030
 
f21030
-#if CHECK_TWO_NODE
f21030
+#if CHECK_TWO_NODE || CHECK_QDEVICE_SYNC_TIMEOUT
f21030
 #include <glib-unix.h>
f21030
 #endif
f21030
 
f21030
@@ -86,11 +86,20 @@ sbd_plugin_membership_dispatch(cpg_handle_t handle,
f21030
 static votequorum_handle_t votequorum_handle = 0;
f21030
 #endif
f21030
 
f21030
+#if CHECK_TWO_NODE
f21030
 static bool two_node = false;
f21030
+#endif
f21030
 static bool ever_seen_both = false;
f21030
 static int cpg_membership_entries = -1;
f21030
 
f21030
-#if CHECK_TWO_NODE
f21030
+#if CHECK_QDEVICE_SYNC_TIMEOUT
f21030
+#include <corosync/votequorum.h>
f21030
+static bool using_qdevice = false;
f21030
+static uint32_t qdevice_sync_timeout = /* in seconds */
f21030
+    VOTEQUORUM_QDEVICE_DEFAULT_SYNC_TIMEOUT / 1000;
f21030
+#endif
f21030
+
f21030
+#if CHECK_TWO_NODE || CHECK_QDEVICE_SYNC_TIMEOUT
f21030
 #include <corosync/cmap.h>
f21030
 
f21030
 static cmap_handle_t cmap_handle = 0;
f21030
@@ -102,28 +111,59 @@ void
f21030
 sbd_cpg_membership_health_update()
f21030
 {
f21030
     if(cpg_membership_entries > 0) {
f21030
-        bool quorum_is_suspect =
f21030
+#if CHECK_TWO_NODE
f21030
+        bool quorum_is_suspect_two_node =
f21030
             (two_node && ever_seen_both && cpg_membership_entries == 1);
f21030
+#endif
f21030
+#if CHECK_QDEVICE_SYNC_TIMEOUT
f21030
+        bool quorum_is_suspect_qdevice_timing =
f21030
+            using_qdevice && (qdevice_sync_timeout > timeout_watchdog);
f21030
+#endif
f21030
 
f21030
-        if (!quorum_is_suspect) {
f21030
+        do {
f21030
+#if CHECK_TWO_NODE
f21030
+            if (quorum_is_suspect_two_node) {
f21030
+               /* Alternative would be asking votequorum for number of votes.
f21030
+                * Using pacemaker's cpg as source for number of active nodes
f21030
+                * avoids binding to an additional library, is definitely
f21030
+                * less code to write and we wouldn't have to combine data
f21030
+                * from 3 sources (cmap, cpg & votequorum) in a potentially
f21030
+                * racy environment.
f21030
+                */
f21030
+                set_servant_health(pcmk_health_noquorum, LOG_WARNING,
f21030
+                    "Connected to %s but requires both nodes present",
f21030
+                    name_for_cluster_type(get_cluster_type())
f21030
+                    );
f21030
+                break;
f21030
+            }
f21030
+#endif
f21030
+#if CHECK_QDEVICE_SYNC_TIMEOUT
f21030
+            if (quorum_is_suspect_qdevice_timing) {
f21030
+               /* We can't really trust quorum info as qdevice-sync_timeout
f21030
+                * makes reaction of quorum too sluggish for our
f21030
+                * watchdog-timeout.
f21030
+                */
f21030
+                set_servant_health(pcmk_health_noquorum, LOG_WARNING,
f21030
+                    "Connected to %s but quorum using qdevice is distrusted "
f21030
+                    "for SBD as qdevice-sync_timeout (%ds) > watchdog-timeout "
f21030
+                    "(%lus).",
f21030
+                    name_for_cluster_type(get_cluster_type()),
f21030
+                    qdevice_sync_timeout, timeout_watchdog
f21030
+                    );
f21030
+                break;
f21030
+            }
f21030
+#endif
f21030
             set_servant_health(pcmk_health_online, LOG_INFO,
f21030
-                           "Connected to %s (%u members)",
f21030
-                           name_for_cluster_type(get_cluster_type()),
f21030
-                           cpg_membership_entries
f21030
-                          );
f21030
-        } else {
f21030
-            /* Alternative would be asking votequorum for number of votes.
f21030
-             * Using pacemaker's cpg as source for number of active nodes
f21030
-             * avoids binding to an additional library, is definitely
f21030
-             * less code to write and we wouldn't have to combine data
f21030
-             * from 3 sources (cmap, cpq & votequorum) in a potentially
f21030
-             * racy environment.
f21030
-             */
f21030
-            set_servant_health(pcmk_health_noquorum, LOG_WARNING,
f21030
-                           "Connected to %s but requires both nodes present",
f21030
-                           name_for_cluster_type(get_cluster_type())
f21030
-                          );
f21030
-        }
f21030
+                "Connected to %s (%u members)%s",
f21030
+                name_for_cluster_type(get_cluster_type()),
f21030
+                cpg_membership_entries,
f21030
+#if CHECK_QDEVICE_SYNC_TIMEOUT
f21030
+                using_qdevice?" using qdevice for quorum":""
f21030
+#else
f21030
+                ""
f21030
+#endif
f21030
+            );
f21030
+        } while (false);
f21030
 
f21030
         if (cpg_membership_entries > 1) {
f21030
             ever_seen_both = true;
f21030
@@ -146,7 +186,7 @@ sbd_cpg_membership_dispatch(cpg_handle_t handle,
f21030
     notify_parent();
f21030
 }
f21030
 
f21030
-#if CHECK_TWO_NODE
f21030
+#if CHECK_TWO_NODE || CHECK_QDEVICE_SYNC_TIMEOUT
f21030
 static void sbd_cmap_notify_fn(
f21030
     cmap_handle_t cmap_handle,
f21030
     cmap_track_handle_t cmap_track_handle,
f21030
@@ -156,21 +196,99 @@ static void sbd_cmap_notify_fn(
f21030
     struct cmap_notify_value old_val,
f21030
     void *user_data)
f21030
 {
f21030
-    if (new_val.type == CMAP_VALUETYPE_UINT8) {
f21030
-        switch (event) {
f21030
-            case CMAP_TRACK_ADD:
f21030
-            case CMAP_TRACK_MODIFY:
f21030
-                two_node = *((uint8_t *) new_val.data);
f21030
-                break;
f21030
-            case CMAP_TRACK_DELETE:
f21030
-                two_node = false;
f21030
-                break;
f21030
-            default:
f21030
-                return;
f21030
-        }
f21030
-        sbd_cpg_membership_health_update();
f21030
-        notify_parent();
f21030
+    switch (event) {
f21030
+        case CMAP_TRACK_ADD:
f21030
+        case CMAP_TRACK_MODIFY:
f21030
+            switch (new_val.type) {
f21030
+                case CMAP_VALUETYPE_UINT8:
f21030
+#if CHECK_TWO_NODE
f21030
+                    if (!strcmp(key_name, "quorum.two_node")) {
f21030
+                        two_node = *((uint8_t *) new_val.data);
f21030
+                    } else {
f21030
+                        return;
f21030
+                    }
f21030
+                    break;
f21030
+#else
f21030
+                    return;
f21030
+#endif
f21030
+                case CMAP_VALUETYPE_STRING:
f21030
+#if CHECK_QDEVICE_SYNC_TIMEOUT
f21030
+                    if (!strcmp(key_name, "quorum.device.model")) {
f21030
+                        using_qdevice =
f21030
+                            ((new_val.data) && strlen((char *) new_val.data));
f21030
+                    } else {
f21030
+                        return;
f21030
+                    }
f21030
+                    break;
f21030
+#else
f21030
+                    return;
f21030
+#endif
f21030
+                case CMAP_VALUETYPE_UINT32:
f21030
+#if CHECK_QDEVICE_SYNC_TIMEOUT
f21030
+                    if (!strcmp(key_name, "quorum.device.sync_timeout")) {
f21030
+                        if (new_val.data) {
f21030
+                            qdevice_sync_timeout =
f21030
+                                *((uint32_t *) new_val.data) / 1000;
f21030
+                        } else {
f21030
+                            qdevice_sync_timeout =
f21030
+                                VOTEQUORUM_QDEVICE_DEFAULT_SYNC_TIMEOUT / 1000;
f21030
+                        }
f21030
+                    } else {
f21030
+                        return;
f21030
+                    }
f21030
+                    break;
f21030
+#else
f21030
+                    return;
f21030
+#endif
f21030
+                default:
f21030
+                    return;
f21030
+            }
f21030
+            break;
f21030
+        case CMAP_TRACK_DELETE:
f21030
+            switch (new_val.type) {
f21030
+                case CMAP_VALUETYPE_UINT8:
f21030
+#if CHECK_TWO_NODE
f21030
+                    if (!strcmp(key_name, "quorum.two_node")) {
f21030
+                        two_node = false;
f21030
+                    } else {
f21030
+                        return;
f21030
+                    }
f21030
+                    break;
f21030
+#else
f21030
+                    return;
f21030
+#endif
f21030
+                case CMAP_VALUETYPE_STRING:
f21030
+#if CHECK_QDEVICE_SYNC_TIMEOUT
f21030
+                    if (!strcmp(key_name, "quorum.device.model")) {
f21030
+                        using_qdevice = false;
f21030
+                    } else {
f21030
+                        return;
f21030
+                    }
f21030
+                    break;
f21030
+#else
f21030
+                    return;
f21030
+#endif
f21030
+                case CMAP_VALUETYPE_UINT32:
f21030
+#if CHECK_QDEVICE_SYNC_TIMEOUT
f21030
+                    if (!strcmp(key_name, "quorum.device.sync_timeout")) {
f21030
+                        qdevice_sync_timeout =
f21030
+                            VOTEQUORUM_QDEVICE_DEFAULT_SYNC_TIMEOUT / 1000;
f21030
+                    } else {
f21030
+                        return;
f21030
+                    }
f21030
+                    break;
f21030
+#else
f21030
+                    return;
f21030
+#endif
f21030
+                default:
f21030
+                    return;
f21030
+            }
f21030
+            break;
f21030
+        default:
f21030
+            return;
f21030
     }
f21030
+    sbd_cpg_membership_health_update();
f21030
+    notify_parent();
f21030
 }
f21030
 
f21030
 static gboolean
f21030
@@ -200,9 +318,14 @@ cmap_destroy(void)
f21030
 }
f21030
 
f21030
 static gboolean
f21030
-sbd_get_two_node(void)
f21030
+verify_against_cmap_config(void)
f21030
 {
f21030
+#if CHECK_TWO_NODE
f21030
     uint8_t two_node_u8 = 0;
f21030
+#endif
f21030
+#if CHECK_QDEVICE_SYNC_TIMEOUT
f21030
+    char *qdevice_model = NULL;
f21030
+#endif
f21030
     int cmap_fd;
f21030
 
f21030
     if (!track_handle) {
f21030
@@ -211,12 +334,31 @@ sbd_get_two_node(void)
f21030
             goto out;
f21030
         }
f21030
 
f21030
+#if CHECK_TWO_NODE
f21030
         if (cmap_track_add(cmap_handle, "quorum.two_node",
f21030
                             CMAP_TRACK_DELETE|CMAP_TRACK_MODIFY|CMAP_TRACK_ADD,
f21030
                             sbd_cmap_notify_fn, NULL, &track_handle) != CS_OK) {
f21030
             cl_log(LOG_WARNING, "Failed adding CMAP tracker for 2Node-mode\n");
f21030
             goto out;
f21030
         }
f21030
+#endif
f21030
+
f21030
+#if CHECK_QDEVICE_SYNC_TIMEOUT
f21030
+        if (cmap_track_add(cmap_handle, "quorum.device.model",
f21030
+                            CMAP_TRACK_DELETE|CMAP_TRACK_MODIFY|CMAP_TRACK_ADD,
f21030
+                            sbd_cmap_notify_fn, NULL, &track_handle) != CS_OK) {
f21030
+            cl_log(LOG_WARNING, "Failed adding CMAP tracker for qdevice-model\n");
f21030
+            goto out;
f21030
+        }
f21030
+
f21030
+        if (cmap_track_add(cmap_handle, "quorum.device.sync_timeout",
f21030
+                            CMAP_TRACK_DELETE|CMAP_TRACK_MODIFY|CMAP_TRACK_ADD,
f21030
+                            sbd_cmap_notify_fn, NULL, &track_handle) != CS_OK) {
f21030
+            cl_log(LOG_WARNING,
f21030
+                   "Failed adding CMAP tracker for qdevice-sync_timeout\n");
f21030
+            goto out;
f21030
+        }
f21030
+#endif
f21030
 
f21030
         /* add the tracker to mainloop */
f21030
         if (cmap_fd_get(cmap_handle, &cmap_fd) != CS_OK) {
f21030
@@ -232,13 +374,39 @@ sbd_get_two_node(void)
f21030
         g_source_attach(cmap_source, NULL);
f21030
     }
f21030
 
f21030
-    if (cmap_get_uint8(cmap_handle, "quorum.two_node", &two_node_u8) == CS_OK) {
f21030
+#if CHECK_TWO_NODE
f21030
+    if (cmap_get_uint8(cmap_handle, "quorum.two_node", &two_node_u8)
f21030
+            == CS_OK) {
f21030
         cl_log(two_node_u8? LOG_NOTICE : LOG_INFO,
f21030
                "Corosync is%s in 2Node-mode", two_node_u8?"":" not");
f21030
         two_node = two_node_u8;
f21030
     } else {
f21030
         cl_log(LOG_INFO, "quorum.two_node not present in cmap\n");
f21030
     }
f21030
+#endif
f21030
+
f21030
+#if CHECK_QDEVICE_SYNC_TIMEOUT
f21030
+    if (cmap_get_string(cmap_handle, "quorum.device.model",
f21030
+                        &qdevice_model) == CS_OK) {
f21030
+        using_qdevice = qdevice_model && strlen(qdevice_model);
f21030
+        cl_log(using_qdevice? LOG_NOTICE : LOG_INFO,
f21030
+               "Corosync is%s using qdevice", using_qdevice?"":" not");
f21030
+    } else {
f21030
+        cl_log(LOG_INFO, "quorum.device.model not present in cmap\n");
f21030
+    }
f21030
+
f21030
+    if (cmap_get_uint32(cmap_handle, "quorum.device.sync_timeout",
f21030
+                        &qdevice_sync_timeout) == CS_OK) {
f21030
+        qdevice_sync_timeout /= 1000;
f21030
+        cl_log(LOG_INFO,
f21030
+               "Corosync is using qdevice-sync_timeout=%ds",
f21030
+               qdevice_sync_timeout);
f21030
+    } else {
f21030
+        cl_log(LOG_INFO,
f21030
+               "quorum.device.sync_timeout not present in cmap\n");
f21030
+    }
f21030
+#endif
f21030
+
f21030
     return TRUE;
f21030
 
f21030
 out:
f21030
@@ -331,15 +499,15 @@ sbd_membership_connect(void)
f21030
         } else {
f21030
             cl_log(LOG_INFO, "Attempting connection to %s", name_for_cluster_type(stack));
f21030
 
f21030
-#if SUPPORT_COROSYNC && CHECK_TWO_NODE
f21030
-            if (sbd_get_two_node()) {
f21030
+#if SUPPORT_COROSYNC && (CHECK_TWO_NODE || CHECK_QDEVICE_SYNC_TIMEOUT)
f21030
+            if (verify_against_cmap_config()) {
f21030
 #endif
f21030
 
f21030
                 if(crm_cluster_connect(&cluster)) {
f21030
                     connected = true;
f21030
                 }
f21030
 
f21030
-#if SUPPORT_COROSYNC && CHECK_TWO_NODE
f21030
+#if SUPPORT_COROSYNC && (CHECK_TWO_NODE || CHECK_QDEVICE_SYNC_TIMEOUT)
f21030
             }
f21030
 #endif
f21030
         }
f21030
@@ -362,7 +530,7 @@ sbd_membership_destroy(gpointer user_data)
f21030
     cl_log(LOG_WARNING, "Lost connection to %s", name_for_cluster_type(get_cluster_type()));
f21030
 
f21030
     if (get_cluster_type() != pcmk_cluster_unknown) {
f21030
-#if SUPPORT_COROSYNC && CHECK_TWO_NODE
f21030
+#if SUPPORT_COROSYNC && (CHECK_TWO_NODE || CHECK_QDEVICE_SYNC_TIMEOUT)
f21030
         cmap_destroy();
f21030
 #endif
f21030
     }
f21030
-- 
f21030
1.8.3.1
f21030