c563b9
From a32b6e14ba51fefbda2d4a699cf1c48dd3a1bb5a Mon Sep 17 00:00:00 2001
c563b9
From: Chris Lumens <clumens@redhat.com>
c563b9
Date: Thu, 7 Jan 2021 11:37:51 -0500
c563b9
Subject: [PATCH 01/10] Fix: tools: Don't pass stonith history to
c563b9
 print_simple_status.
c563b9
c563b9
It's not being used.
c563b9
---
c563b9
 tools/crm_mon.c | 7 +++----
c563b9
 1 file changed, 3 insertions(+), 4 deletions(-)
c563b9
c563b9
diff --git a/tools/crm_mon.c b/tools/crm_mon.c
c563b9
index 4555516..729f6a1 100644
c563b9
--- a/tools/crm_mon.c
c563b9
+++ b/tools/crm_mon.c
c563b9
@@ -1,5 +1,5 @@
c563b9
 /*
c563b9
- * Copyright 2004-2020 the Pacemaker project contributors
c563b9
+ * Copyright 2004-2021 the Pacemaker project contributors
c563b9
  *
c563b9
  * The version control history for this file may have further details.
c563b9
  *
c563b9
@@ -1451,14 +1451,13 @@ main(int argc, char **argv)
c563b9
  * \brief Print one-line status suitable for use with monitoring software
c563b9
  *
c563b9
  * \param[in] data_set  Working set of CIB state
c563b9
- * \param[in] history   List of stonith actions
c563b9
  *
c563b9
  * \note This function's output (and the return code when the program exits)
c563b9
  *       should conform to https://www.monitoring-plugins.org/doc/guidelines.html
c563b9
  */
c563b9
 static void
c563b9
 print_simple_status(pcmk__output_t *out, pe_working_set_t * data_set,
c563b9
-                    stonith_history_t *history, unsigned int mon_ops)
c563b9
+                    unsigned int mon_ops)
c563b9
 {
c563b9
     GListPtr gIter = NULL;
c563b9
     int nodes_online = 0;
c563b9
@@ -2012,7 +2011,7 @@ mon_refresh_display(gpointer user_data)
c563b9
             break;
c563b9
 
c563b9
         case mon_output_monitor:
c563b9
-            print_simple_status(out, mon_data_set, stonith_history, options.mon_ops);
c563b9
+            print_simple_status(out, mon_data_set, options.mon_ops);
c563b9
             if (pcmk_is_set(options.mon_ops, mon_op_has_warnings)) {
c563b9
                 clean_up(MON_STATUS_WARN);
c563b9
                 return FALSE;
c563b9
-- 
c563b9
1.8.3.1
c563b9
c563b9
c563b9
From 8b9c47089c70295bc0529671ba5991c6d831e14b Mon Sep 17 00:00:00 2001
c563b9
From: Chris Lumens <clumens@redhat.com>
c563b9
Date: Thu, 7 Jan 2021 13:17:04 -0500
c563b9
Subject: [PATCH 02/10] Refactor: tools: Don't pass output_format to
c563b9
 mon_refresh_display.
c563b9
c563b9
output_format is a global variable.
c563b9
---
c563b9
 tools/crm_mon.c | 2 +-
c563b9
 1 file changed, 1 insertion(+), 1 deletion(-)
c563b9
c563b9
diff --git a/tools/crm_mon.c b/tools/crm_mon.c
c563b9
index 729f6a1..b801560 100644
c563b9
--- a/tools/crm_mon.c
c563b9
+++ b/tools/crm_mon.c
c563b9
@@ -827,7 +827,7 @@ cib_connect(gboolean full)
c563b9
 
c563b9
         rc = cib->cmds->query(cib, NULL, &current_cib, cib_scope_local | cib_sync_call);
c563b9
         if (rc == pcmk_ok) {
c563b9
-            mon_refresh_display(&output_format);
c563b9
+            mon_refresh_display(NULL);
c563b9
         }
c563b9
 
c563b9
         if (rc == pcmk_ok && full) {
c563b9
-- 
c563b9
1.8.3.1
c563b9
c563b9
c563b9
From a1b14ad96f12746167da8588dc086b20e6f6d1d6 Mon Sep 17 00:00:00 2001
c563b9
From: Chris Lumens <clumens@redhat.com>
c563b9
Date: Thu, 7 Jan 2021 13:20:14 -0500
c563b9
Subject: [PATCH 03/10] Refactor: tools: Remove unnecessary checks for cib !=
c563b9
 NULL.
c563b9
c563b9
cib is guaranteed to not be NULL at these points, so there's no need to
c563b9
do an additional check.  This code was leftover from a previous
c563b9
reorganization that changed when the cib variable gets initialized.
c563b9
---
c563b9
 tools/crm_mon.c | 41 +++++++++++++++++++----------------------
c563b9
 1 file changed, 19 insertions(+), 22 deletions(-)
c563b9
c563b9
diff --git a/tools/crm_mon.c b/tools/crm_mon.c
c563b9
index b801560..1eedd38 100644
c563b9
--- a/tools/crm_mon.c
c563b9
+++ b/tools/crm_mon.c
c563b9
@@ -1346,7 +1346,7 @@ main(int argc, char **argv)
c563b9
 
c563b9
     /* Extra sanity checks when in CGI mode */
c563b9
     if (output_format == mon_output_cgi) {
c563b9
-        if (cib && cib->variant == cib_file) {
c563b9
+        if (cib->variant == cib_file) {
c563b9
             g_set_error(&error, PCMK__EXITC_ERROR, CRM_EX_USAGE, "CGI mode used with CIB file");
c563b9
             return clean_up(CRM_EX_USAGE);
c563b9
         } else if (options.external_agent != NULL) {
c563b9
@@ -1370,33 +1370,30 @@ main(int argc, char **argv)
c563b9
 
c563b9
     crm_info("Starting %s", crm_system_name);
c563b9
 
c563b9
-    if (cib) {
c563b9
-
c563b9
-        do {
c563b9
-            if (!pcmk_is_set(options.mon_ops, mon_op_one_shot)) {
c563b9
-                print_as(output_format ,"Waiting until cluster is available on this node ...\n");
c563b9
-            }
c563b9
-            rc = cib_connect(!pcmk_is_set(options.mon_ops, mon_op_one_shot));
c563b9
+    do {
c563b9
+        if (!pcmk_is_set(options.mon_ops, mon_op_one_shot)) {
c563b9
+            print_as(output_format ,"Waiting until cluster is available on this node ...\n");
c563b9
+        }
c563b9
+        rc = cib_connect(!pcmk_is_set(options.mon_ops, mon_op_one_shot));
c563b9
 
c563b9
-            if (pcmk_is_set(options.mon_ops, mon_op_one_shot)) {
c563b9
-                break;
c563b9
+        if (pcmk_is_set(options.mon_ops, mon_op_one_shot)) {
c563b9
+            break;
c563b9
 
c563b9
-            } else if (rc != pcmk_ok) {
c563b9
-                sleep(options.reconnect_msec / 1000);
c563b9
+        } else if (rc != pcmk_ok) {
c563b9
+            sleep(options.reconnect_msec / 1000);
c563b9
 #if CURSES_ENABLED
c563b9
-                if (output_format == mon_output_console) {
c563b9
-                    clear();
c563b9
-                    refresh();
c563b9
-                }
c563b9
+            if (output_format == mon_output_console) {
c563b9
+                clear();
c563b9
+                refresh();
c563b9
+            }
c563b9
 #endif
c563b9
-            } else {
c563b9
-                if (output_format == mon_output_html && out->dest != stdout) {
c563b9
-                    printf("Writing html to %s ...\n", args->output_dest);
c563b9
-                }
c563b9
+        } else {
c563b9
+            if (output_format == mon_output_html && out->dest != stdout) {
c563b9
+                printf("Writing html to %s ...\n", args->output_dest);
c563b9
             }
c563b9
+        }
c563b9
 
c563b9
-        } while (rc == -ENOTCONN);
c563b9
-    }
c563b9
+    } while (rc == -ENOTCONN);
c563b9
 
c563b9
     if (rc != pcmk_ok) {
c563b9
         if (output_format == mon_output_monitor) {
c563b9
-- 
c563b9
1.8.3.1
c563b9
c563b9
c563b9
From fe5284a12765e775905bdfe58711c5733a063132 Mon Sep 17 00:00:00 2001
c563b9
From: Chris Lumens <clumens@redhat.com>
c563b9
Date: Thu, 7 Jan 2021 14:15:40 -0500
c563b9
Subject: [PATCH 04/10] Fix: tools: mon_refresh_display should return an int.
c563b9
c563b9
While GSourceFunc is defined as returning a boolean, our public API
c563b9
mainloop function expect the dispatch function to return an int.  So
c563b9
change mon_refresh_display to do so.
c563b9
---
c563b9
 tools/crm_mon.c | 12 ++++++------
c563b9
 1 file changed, 6 insertions(+), 6 deletions(-)
c563b9
c563b9
diff --git a/tools/crm_mon.c b/tools/crm_mon.c
c563b9
index 1eedd38..8657a89 100644
c563b9
--- a/tools/crm_mon.c
c563b9
+++ b/tools/crm_mon.c
c563b9
@@ -125,7 +125,7 @@ struct {
c563b9
 static void clean_up_connections(void);
c563b9
 static crm_exit_t clean_up(crm_exit_t exit_code);
c563b9
 static void crm_diff_update(const char *event, xmlNode * msg);
c563b9
-static gboolean mon_refresh_display(gpointer user_data);
c563b9
+static int mon_refresh_display(gpointer user_data);
c563b9
 static int cib_connect(gboolean full);
c563b9
 static void mon_st_callback_event(stonith_t * st, stonith_event_t * e);
c563b9
 static void mon_st_callback_display(stonith_t * st, stonith_event_t * e);
c563b9
@@ -1925,7 +1925,7 @@ crm_diff_update(const char *event, xmlNode * msg)
c563b9
     kick_refresh(cib_updated);
c563b9
 }
c563b9
 
c563b9
-static gboolean
c563b9
+static int
c563b9
 mon_refresh_display(gpointer user_data)
c563b9
 {
c563b9
     xmlNode *cib_copy = copy_xml(current_cib);
c563b9
@@ -1940,7 +1940,7 @@ mon_refresh_display(gpointer user_data)
c563b9
         }
c563b9
         out->err(out, "Upgrade failed: %s", pcmk_strerror(-pcmk_err_schema_validation));
c563b9
         clean_up(CRM_EX_CONFIG);
c563b9
-        return FALSE;
c563b9
+        return 0;
c563b9
     }
c563b9
 
c563b9
     /* get the stonith-history if there is evidence we need it
c563b9
@@ -1966,7 +1966,7 @@ mon_refresh_display(gpointer user_data)
c563b9
         }
c563b9
         free_xml(cib_copy);
c563b9
         out->err(out, "Reading stonith-history failed");
c563b9
-        return FALSE;
c563b9
+        return 0;
c563b9
     }
c563b9
 
c563b9
     if (mon_data_set == NULL) {
c563b9
@@ -1995,7 +1995,7 @@ mon_refresh_display(gpointer user_data)
c563b9
                                   options.only_node, options.only_rsc) != 0) {
c563b9
                 g_set_error(&error, PCMK__EXITC_ERROR, CRM_EX_CANTCREAT, "Critical: Unable to output html file");
c563b9
                 clean_up(CRM_EX_CANTCREAT);
c563b9
-                return FALSE;
c563b9
+                return 0;
c563b9
             }
c563b9
             break;
c563b9
 
c563b9
@@ -2044,7 +2044,7 @@ mon_refresh_display(gpointer user_data)
c563b9
     stonith_history_free(stonith_history);
c563b9
     stonith_history = NULL;
c563b9
     pe_reset_working_set(mon_data_set);
c563b9
-    return TRUE;
c563b9
+    return 1;
c563b9
 }
c563b9
 
c563b9
 static void
c563b9
-- 
c563b9
1.8.3.1
c563b9
c563b9
c563b9
From 7f88a5a428ed73fb5161096ece2517abe1119f06 Mon Sep 17 00:00:00 2001
c563b9
From: Chris Lumens <clumens@redhat.com>
c563b9
Date: Thu, 7 Jan 2021 16:59:02 -0500
c563b9
Subject: [PATCH 05/10] Refactor: tools: Change a conditional in cib_connect.
c563b9
c563b9
This allows unindenting everything that occurs inside that conditional,
c563b9
which I think makes it a little bit easier to understand what is going
c563b9
on.
c563b9
---
c563b9
 tools/crm_mon.c | 86 +++++++++++++++++++++++++++++----------------------------
c563b9
 1 file changed, 44 insertions(+), 42 deletions(-)
c563b9
c563b9
diff --git a/tools/crm_mon.c b/tools/crm_mon.c
c563b9
index 8657a89..b8ba56b 100644
c563b9
--- a/tools/crm_mon.c
c563b9
+++ b/tools/crm_mon.c
c563b9
@@ -804,55 +804,57 @@ cib_connect(gboolean full)
c563b9
         }
c563b9
     }
c563b9
 
c563b9
-    if (cib->state != cib_connected_query && cib->state != cib_connected_command) {
c563b9
-        crm_trace("Connecting to the CIB");
c563b9
-
c563b9
-        /* Hack: the CIB signon will print the prompt for a password if needed,
c563b9
-         * but to stderr. If we're in curses, show it on the screen instead.
c563b9
-         *
c563b9
-         * @TODO Add a password prompt (maybe including input) function to
c563b9
-         *       pcmk__output_t and use it in libcib.
c563b9
-         */
c563b9
-        if ((output_format == mon_output_console) && need_pass && (cib->variant == cib_remote)) {
c563b9
-            need_pass = FALSE;
c563b9
-            print_as(output_format, "Password:");
c563b9
-        }
c563b9
+    if (cib->state == cib_connected_query || cib->state == cib_connected_command) {
c563b9
+        return rc;
c563b9
+    }
c563b9
 
c563b9
-        rc = cib->cmds->signon(cib, crm_system_name, cib_query);
c563b9
-        if (rc != pcmk_ok) {
c563b9
-            out->err(out, "Could not connect to the CIB: %s",
c563b9
-                     pcmk_strerror(rc));
c563b9
-            return rc;
c563b9
-        }
c563b9
+    crm_trace("Connecting to the CIB");
c563b9
 
c563b9
-        rc = cib->cmds->query(cib, NULL, &current_cib, cib_scope_local | cib_sync_call);
c563b9
-        if (rc == pcmk_ok) {
c563b9
-            mon_refresh_display(NULL);
c563b9
-        }
c563b9
+    /* Hack: the CIB signon will print the prompt for a password if needed,
c563b9
+     * but to stderr. If we're in curses, show it on the screen instead.
c563b9
+     *
c563b9
+     * @TODO Add a password prompt (maybe including input) function to
c563b9
+     *       pcmk__output_t and use it in libcib.
c563b9
+     */
c563b9
+    if ((output_format == mon_output_console) && need_pass && (cib->variant == cib_remote)) {
c563b9
+        need_pass = FALSE;
c563b9
+        print_as(output_format, "Password:");
c563b9
+    }
c563b9
 
c563b9
-        if (rc == pcmk_ok && full) {
c563b9
-            if (rc == pcmk_ok) {
c563b9
-                rc = cib->cmds->set_connection_dnotify(cib, mon_cib_connection_destroy_regular);
c563b9
-                if (rc == -EPROTONOSUPPORT) {
c563b9
-                    print_as
c563b9
-                        (output_format, "Notification setup not supported, won't be able to reconnect after failure");
c563b9
-                    if (output_format == mon_output_console) {
c563b9
-                        sleep(2);
c563b9
-                    }
c563b9
-                    rc = pcmk_ok;
c563b9
-                }
c563b9
+    rc = cib->cmds->signon(cib, crm_system_name, cib_query);
c563b9
+    if (rc != pcmk_ok) {
c563b9
+        out->err(out, "Could not connect to the CIB: %s",
c563b9
+                 pcmk_strerror(rc));
c563b9
+        return rc;
c563b9
+    }
c563b9
 
c563b9
-            }
c563b9
+    rc = cib->cmds->query(cib, NULL, &current_cib, cib_scope_local | cib_sync_call);
c563b9
+    if (rc == pcmk_ok) {
c563b9
+        mon_refresh_display(NULL);
c563b9
+    }
c563b9
 
c563b9
-            if (rc == pcmk_ok) {
c563b9
-                cib->cmds->del_notify_callback(cib, T_CIB_DIFF_NOTIFY, crm_diff_update);
c563b9
-                rc = cib->cmds->add_notify_callback(cib, T_CIB_DIFF_NOTIFY, crm_diff_update);
c563b9
+    if (rc == pcmk_ok && full) {
c563b9
+        if (rc == pcmk_ok) {
c563b9
+            rc = cib->cmds->set_connection_dnotify(cib, mon_cib_connection_destroy_regular);
c563b9
+            if (rc == -EPROTONOSUPPORT) {
c563b9
+                print_as
c563b9
+                    (output_format, "Notification setup not supported, won't be able to reconnect after failure");
c563b9
+                if (output_format == mon_output_console) {
c563b9
+                    sleep(2);
c563b9
+                }
c563b9
+                rc = pcmk_ok;
c563b9
             }
c563b9
 
c563b9
-            if (rc != pcmk_ok) {
c563b9
-                out->err(out, "Notification setup failed, could not monitor CIB actions");
c563b9
-                clean_up_connections();
c563b9
-            }
c563b9
+        }
c563b9
+
c563b9
+        if (rc == pcmk_ok) {
c563b9
+            cib->cmds->del_notify_callback(cib, T_CIB_DIFF_NOTIFY, crm_diff_update);
c563b9
+            rc = cib->cmds->add_notify_callback(cib, T_CIB_DIFF_NOTIFY, crm_diff_update);
c563b9
+        }
c563b9
+
c563b9
+        if (rc != pcmk_ok) {
c563b9
+            out->err(out, "Notification setup failed, could not monitor CIB actions");
c563b9
+            clean_up_connections();
c563b9
         }
c563b9
     }
c563b9
     return rc;
c563b9
-- 
c563b9
1.8.3.1
c563b9
c563b9
c563b9
From 178ba17e4ee62bef28f8e71cad2c002f823661b5 Mon Sep 17 00:00:00 2001
c563b9
From: Chris Lumens <clumens@redhat.com>
c563b9
Date: Thu, 7 Jan 2021 17:37:36 -0500
c563b9
Subject: [PATCH 06/10] Refactor: tools: Remove an unnecessary conditional in
c563b9
 cib_connect.
c563b9
c563b9
---
c563b9
 tools/crm_mon.c | 17 +++++++----------
c563b9
 1 file changed, 7 insertions(+), 10 deletions(-)
c563b9
c563b9
diff --git a/tools/crm_mon.c b/tools/crm_mon.c
c563b9
index b8ba56b..36249e8 100644
c563b9
--- a/tools/crm_mon.c
c563b9
+++ b/tools/crm_mon.c
c563b9
@@ -834,17 +834,14 @@ cib_connect(gboolean full)
c563b9
     }
c563b9
 
c563b9
     if (rc == pcmk_ok && full) {
c563b9
-        if (rc == pcmk_ok) {
c563b9
-            rc = cib->cmds->set_connection_dnotify(cib, mon_cib_connection_destroy_regular);
c563b9
-            if (rc == -EPROTONOSUPPORT) {
c563b9
-                print_as
c563b9
-                    (output_format, "Notification setup not supported, won't be able to reconnect after failure");
c563b9
-                if (output_format == mon_output_console) {
c563b9
-                    sleep(2);
c563b9
-                }
c563b9
-                rc = pcmk_ok;
c563b9
+        rc = cib->cmds->set_connection_dnotify(cib, mon_cib_connection_destroy_regular);
c563b9
+        if (rc == -EPROTONOSUPPORT) {
c563b9
+            print_as
c563b9
+                (output_format, "Notification setup not supported, won't be able to reconnect after failure");
c563b9
+            if (output_format == mon_output_console) {
c563b9
+                sleep(2);
c563b9
             }
c563b9
-
c563b9
+            rc = pcmk_ok;
c563b9
         }
c563b9
 
c563b9
         if (rc == pcmk_ok) {
c563b9
-- 
c563b9
1.8.3.1
c563b9
c563b9
c563b9
From 33bac5886417afc5c7bbf56f4d31e0e36f8ae947 Mon Sep 17 00:00:00 2001
c563b9
From: Chris Lumens <clumens@redhat.com>
c563b9
Date: Fri, 8 Jan 2021 10:00:50 -0500
c563b9
Subject: [PATCH 07/10] Refactor: tools: Simplify another conditional in
c563b9
 crm_mon.
c563b9
c563b9
---
c563b9
 tools/crm_mon.c | 6 ++----
c563b9
 1 file changed, 2 insertions(+), 4 deletions(-)
c563b9
c563b9
diff --git a/tools/crm_mon.c b/tools/crm_mon.c
c563b9
index 36249e8..8b47bbc 100644
c563b9
--- a/tools/crm_mon.c
c563b9
+++ b/tools/crm_mon.c
c563b9
@@ -1386,10 +1386,8 @@ main(int argc, char **argv)
c563b9
                 refresh();
c563b9
             }
c563b9
 #endif
c563b9
-        } else {
c563b9
-            if (output_format == mon_output_html && out->dest != stdout) {
c563b9
-                printf("Writing html to %s ...\n", args->output_dest);
c563b9
-            }
c563b9
+        } else if (output_format == mon_output_html && out->dest != stdout) {
c563b9
+            printf("Writing html to %s ...\n", args->output_dest);
c563b9
         }
c563b9
 
c563b9
     } while (rc == -ENOTCONN);
c563b9
-- 
c563b9
1.8.3.1
c563b9
c563b9
c563b9
From 40bc8b3147e7ebef4318211fa69973a8b5d32e79 Mon Sep 17 00:00:00 2001
c563b9
From: Chris Lumens <clumens@redhat.com>
c563b9
Date: Fri, 8 Jan 2021 12:12:37 -0500
c563b9
Subject: [PATCH 08/10] Refactor: libcrmcommon,tools,daemons: Put common xpath
c563b9
 code in one place.
c563b9
c563b9
---
c563b9
 configure.ac                                      |  1 +
c563b9
 daemons/controld/controld_te_callbacks.c          | 26 +++-----------
c563b9
 include/crm/common/xml_internal.h                 | 14 +++++++-
c563b9
 lib/common/tests/Makefile.am                      |  2 +-
c563b9
 lib/common/tests/xpath/Makefile.am                | 29 +++++++++++++++
c563b9
 lib/common/tests/xpath/pcmk__xpath_node_id_test.c | 43 +++++++++++++++++++++++
c563b9
 lib/common/xpath.c                                | 34 +++++++++++++++++-
c563b9
 tools/crm_mon.c                                   | 25 ++-----------
c563b9
 8 files changed, 127 insertions(+), 47 deletions(-)
c563b9
 create mode 100644 lib/common/tests/xpath/Makefile.am
c563b9
 create mode 100644 lib/common/tests/xpath/pcmk__xpath_node_id_test.c
c563b9
c563b9
diff --git a/configure.ac b/configure.ac
c563b9
index 5959116..ce0f1fe 100644
c563b9
--- a/configure.ac
c563b9
+++ b/configure.ac
c563b9
@@ -1920,6 +1920,7 @@ AC_CONFIG_FILES(Makefile                                            \
c563b9
                 lib/common/tests/operations/Makefile                \
c563b9
                 lib/common/tests/strings/Makefile                   \
c563b9
                 lib/common/tests/utils/Makefile                     \
c563b9
+                lib/common/tests/xpath/Makefile                     \
c563b9
                 lib/cluster/Makefile                                \
c563b9
                 lib/cib/Makefile                                    \
c563b9
                 lib/gnu/Makefile                                    \
c563b9
diff --git a/daemons/controld/controld_te_callbacks.c b/daemons/controld/controld_te_callbacks.c
c563b9
index 66fc645..4e3e4e6 100644
c563b9
--- a/daemons/controld/controld_te_callbacks.c
c563b9
+++ b/daemons/controld/controld_te_callbacks.c
c563b9
@@ -1,5 +1,5 @@
c563b9
 /*
c563b9
- * Copyright 2004-2020 the Pacemaker project contributors
c563b9
+ * Copyright 2004-2021 the Pacemaker project contributors
c563b9
  *
c563b9
  * The version control history for this file may have further details.
c563b9
  *
c563b9
@@ -276,24 +276,6 @@ process_resource_updates(const char *node, xmlNode *xml, xmlNode *change,
c563b9
     }
c563b9
 }
c563b9
 
c563b9
-#define NODE_PATT "/lrm[@id="
c563b9
-static char *get_node_from_xpath(const char *xpath) 
c563b9
-{
c563b9
-    char *nodeid = NULL;
c563b9
-    char *tmp = strstr(xpath, NODE_PATT);
c563b9
-
c563b9
-    if(tmp) {
c563b9
-        tmp += strlen(NODE_PATT);
c563b9
-        tmp += 1;
c563b9
-
c563b9
-        nodeid = strdup(tmp);
c563b9
-        tmp = strstr(nodeid, "\'");
c563b9
-        CRM_ASSERT(tmp);
c563b9
-        tmp[0] = 0;
c563b9
-    }
c563b9
-    return nodeid;
c563b9
-}
c563b9
-
c563b9
 static char *extract_node_uuid(const char *xpath) 
c563b9
 {
c563b9
     char *mutable_path = strdup(xpath);
c563b9
@@ -522,19 +504,19 @@ te_update_diff_v2(xmlNode *diff)
c563b9
             process_resource_updates(ID(match), match, change, op, xpath);
c563b9
 
c563b9
         } else if (strcmp(name, XML_LRM_TAG_RESOURCES) == 0) {
c563b9
-            char *local_node = get_node_from_xpath(xpath);
c563b9
+            char *local_node = pcmk__xpath_node_id(xpath, "lrm");
c563b9
 
c563b9
             process_resource_updates(local_node, match, change, op, xpath);
c563b9
             free(local_node);
c563b9
 
c563b9
         } else if (strcmp(name, XML_LRM_TAG_RESOURCE) == 0) {
c563b9
-            char *local_node = get_node_from_xpath(xpath);
c563b9
+            char *local_node = pcmk__xpath_node_id(xpath, "lrm");
c563b9
 
c563b9
             process_lrm_resource_diff(match, local_node);
c563b9
             free(local_node);
c563b9
 
c563b9
         } else if (strcmp(name, XML_LRM_TAG_RSC_OP) == 0) {
c563b9
-            char *local_node = get_node_from_xpath(xpath);
c563b9
+            char *local_node = pcmk__xpath_node_id(xpath, "lrm");
c563b9
 
c563b9
             process_graph_event(match, local_node);
c563b9
             free(local_node);
c563b9
diff --git a/include/crm/common/xml_internal.h b/include/crm/common/xml_internal.h
c563b9
index 1e80bc6..d8694ee 100644
c563b9
--- a/include/crm/common/xml_internal.h
c563b9
+++ b/include/crm/common/xml_internal.h
c563b9
@@ -1,5 +1,5 @@
c563b9
 /*
c563b9
- * Copyright 2017-2020 the Pacemaker project contributors
c563b9
+ * Copyright 2017-2021 the Pacemaker project contributors
c563b9
  *
c563b9
  * The version control history for this file may have further details.
c563b9
  *
c563b9
@@ -273,4 +273,16 @@ pcmk__xe_first_attr(const xmlNode *xe)
c563b9
     return (xe == NULL)? NULL : xe->properties;
c563b9
 }
c563b9
 
c563b9
+/*!
c563b9
+ * \internal
c563b9
+ * \brief Extract the ID attribute from an XML element
c563b9
+ *
c563b9
+ * \param[in] xpath String to search
c563b9
+ * \param[in] node  Node to get the ID for
c563b9
+ *
c563b9
+ * \return ID attribute of \p node in xpath string \p xpath
c563b9
+ */
c563b9
+char *
c563b9
+pcmk__xpath_node_id(const char *xpath, const char *node);
c563b9
+
c563b9
 #endif // PCMK__XML_INTERNAL__H
c563b9
diff --git a/lib/common/tests/Makefile.am b/lib/common/tests/Makefile.am
c563b9
index 2c33cc5..4c6e8b4 100644
c563b9
--- a/lib/common/tests/Makefile.am
c563b9
+++ b/lib/common/tests/Makefile.am
c563b9
@@ -1 +1 @@
c563b9
-SUBDIRS = agents cmdline flags operations strings utils
c563b9
+SUBDIRS = agents cmdline flags operations strings utils xpath
c563b9
diff --git a/lib/common/tests/xpath/Makefile.am b/lib/common/tests/xpath/Makefile.am
c563b9
new file mode 100644
c563b9
index 0000000..7a53683
c563b9
--- /dev/null
c563b9
+++ b/lib/common/tests/xpath/Makefile.am
c563b9
@@ -0,0 +1,29 @@
c563b9
+#
c563b9
+# Copyright 2021 the Pacemaker project contributors
c563b9
+#
c563b9
+# The version control history for this file may have further details.
c563b9
+#
c563b9
+# This source code is licensed under the GNU General Public License version 2
c563b9
+# or later (GPLv2+) WITHOUT ANY WARRANTY.
c563b9
+#
c563b9
+AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include
c563b9
+LDADD = $(top_builddir)/lib/common/libcrmcommon.la
c563b9
+
c563b9
+include $(top_srcdir)/mk/glib-tap.mk
c563b9
+
c563b9
+# Add each test program here.  Each test should be written as a little standalone
c563b9
+# program using the glib unit testing functions.  See the documentation for more
c563b9
+# information.
c563b9
+#
c563b9
+# https://developer.gnome.org/glib/unstable/glib-Testing.html
c563b9
+#
c563b9
+# Add "_test" to the end of all test program names to simplify .gitignore.
c563b9
+test_programs =	pcmk__xpath_node_id_test
c563b9
+
c563b9
+# If any extra data needs to be added to the source distribution, add it to the
c563b9
+# following list.
c563b9
+dist_test_data =
c563b9
+
c563b9
+# If any extra data needs to be used by tests but should not be added to the
c563b9
+# source distribution, add it to the following list.
c563b9
+test_data =
c563b9
diff --git a/lib/common/tests/xpath/pcmk__xpath_node_id_test.c b/lib/common/tests/xpath/pcmk__xpath_node_id_test.c
c563b9
new file mode 100644
c563b9
index 0000000..f6b5c10
c563b9
--- /dev/null
c563b9
+++ b/lib/common/tests/xpath/pcmk__xpath_node_id_test.c
c563b9
@@ -0,0 +1,43 @@
c563b9
+/*
c563b9
+ * Copyright 2021 the Pacemaker project contributors
c563b9
+ *
c563b9
+ * The version control history for this file may have further details.
c563b9
+ *
c563b9
+ * This source code is licensed under the GNU Lesser General Public License
c563b9
+ * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
c563b9
+ */
c563b9
+
c563b9
+#include <crm_internal.h>
c563b9
+#include <crm/common/xml_internal.h>
c563b9
+
c563b9
+static void
c563b9
+empty_input(void) {
c563b9
+    g_assert_null(pcmk__xpath_node_id(NULL, "lrm"));
c563b9
+    g_assert_null(pcmk__xpath_node_id("", "lrm"));
c563b9
+    g_assert_null(pcmk__xpath_node_id("/blah/blah", NULL));
c563b9
+    g_assert_null(pcmk__xpath_node_id("/blah/blah", ""));
c563b9
+    g_assert_null(pcmk__xpath_node_id(NULL, NULL));
c563b9
+}
c563b9
+
c563b9
+static void
c563b9
+not_present(void) {
c563b9
+    g_assert_null(pcmk__xpath_node_id("/some/xpath/string[@id='xyz']", "lrm"));
c563b9
+    g_assert_null(pcmk__xpath_node_id("/some/xpath/containing[@id='lrm']", "lrm"));
c563b9
+}
c563b9
+
c563b9
+static void
c563b9
+present(void) {
c563b9
+    g_assert_cmpint(strcmp(pcmk__xpath_node_id("/some/xpath/containing/lrm[@id='xyz']", "lrm"), "xyz"), ==, 0);
c563b9
+    g_assert_cmpint(strcmp(pcmk__xpath_node_id("/some/other/lrm[@id='xyz']/xpath", "lrm"), "xyz"), ==, 0);
c563b9
+}
c563b9
+
c563b9
+int
c563b9
+main(int argc, char **argv)
c563b9
+{
c563b9
+    g_test_init(&argc, &argv, NULL);
c563b9
+
c563b9
+    g_test_add_func("/common/xpath/node_id/empty_input", empty_input);
c563b9
+    g_test_add_func("/common/xpath/node_id/not_present", not_present);
c563b9
+    g_test_add_func("/common/xpath/node_id/present", present);
c563b9
+    return g_test_run();
c563b9
+}
c563b9
diff --git a/lib/common/xpath.c b/lib/common/xpath.c
c563b9
index 6fa4941..7851a7c 100644
c563b9
--- a/lib/common/xpath.c
c563b9
+++ b/lib/common/xpath.c
c563b9
@@ -1,5 +1,5 @@
c563b9
 /*
c563b9
- * Copyright 2004-2020 the Pacemaker project contributors
c563b9
+ * Copyright 2004-2021 the Pacemaker project contributors
c563b9
  *
c563b9
  * The version control history for this file may have further details.
c563b9
  *
c563b9
@@ -11,6 +11,7 @@
c563b9
 #include <stdio.h>
c563b9
 #include <string.h>
c563b9
 #include <crm/msg_xml.h>
c563b9
+#include <crm/common/xml_internal.h>
c563b9
 #include "crmcommon_private.h"
c563b9
 
c563b9
 /*
c563b9
@@ -297,3 +298,34 @@ xml_get_path(xmlNode *xml)
c563b9
     }
c563b9
     return NULL;
c563b9
 }
c563b9
+
c563b9
+char *
c563b9
+pcmk__xpath_node_id(const char *xpath, const char *node)
c563b9
+{
c563b9
+    char *retval = NULL;
c563b9
+    char *patt = NULL;
c563b9
+    char *start = NULL;
c563b9
+    char *end = NULL;
c563b9
+
c563b9
+    if (node == NULL || xpath == NULL) {
c563b9
+        return retval;
c563b9
+    }
c563b9
+
c563b9
+    patt = crm_strdup_printf("/%s[@id=", node);
c563b9
+    start = strstr(xpath, patt);
c563b9
+
c563b9
+    if (!start) {
c563b9
+        free(patt);
c563b9
+        return retval;
c563b9
+    }
c563b9
+
c563b9
+    start += strlen(patt);
c563b9
+    start++;
c563b9
+
c563b9
+    end = strstr(start, "\'");
c563b9
+    CRM_ASSERT(end);
c563b9
+    retval = strndup(start, end-start);
c563b9
+
c563b9
+    free(patt);
c563b9
+    return retval;
c563b9
+}
c563b9
diff --git a/tools/crm_mon.c b/tools/crm_mon.c
c563b9
index 8b47bbc..ff1b86b 100644
c563b9
--- a/tools/crm_mon.c
c563b9
+++ b/tools/crm_mon.c
c563b9
@@ -1719,25 +1719,6 @@ mon_trigger_refresh(gpointer user_data)
c563b9
     return FALSE;
c563b9
 }
c563b9
 
c563b9
-#define NODE_PATT "/lrm[@id="
c563b9
-static char *
c563b9
-get_node_from_xpath(const char *xpath)
c563b9
-{
c563b9
-    char *nodeid = NULL;
c563b9
-    char *tmp = strstr(xpath, NODE_PATT);
c563b9
-
c563b9
-    if(tmp) {
c563b9
-        tmp += strlen(NODE_PATT);
c563b9
-        tmp += 1;
c563b9
-
c563b9
-        nodeid = strdup(tmp);
c563b9
-        tmp = strstr(nodeid, "\'");
c563b9
-        CRM_ASSERT(tmp);
c563b9
-        tmp[0] = 0;
c563b9
-    }
c563b9
-    return nodeid;
c563b9
-}
c563b9
-
c563b9
 static void
c563b9
 crm_diff_update_v2(const char *event, xmlNode * msg)
c563b9
 {
c563b9
@@ -1822,19 +1803,19 @@ crm_diff_update_v2(const char *event, xmlNode * msg)
c563b9
             handle_rsc_op(match, node);
c563b9
 
c563b9
         } else if(strcmp(name, XML_LRM_TAG_RESOURCES) == 0) {
c563b9
-            char *local_node = get_node_from_xpath(xpath);
c563b9
+            char *local_node = pcmk__xpath_node_id(xpath, "lrm");
c563b9
 
c563b9
             handle_rsc_op(match, local_node);
c563b9
             free(local_node);
c563b9
 
c563b9
         } else if(strcmp(name, XML_LRM_TAG_RESOURCE) == 0) {
c563b9
-            char *local_node = get_node_from_xpath(xpath);
c563b9
+            char *local_node = pcmk__xpath_node_id(xpath, "lrm");
c563b9
 
c563b9
             handle_rsc_op(match, local_node);
c563b9
             free(local_node);
c563b9
 
c563b9
         } else if(strcmp(name, XML_LRM_TAG_RSC_OP) == 0) {
c563b9
-            char *local_node = get_node_from_xpath(xpath);
c563b9
+            char *local_node = pcmk__xpath_node_id(xpath, "lrm");
c563b9
 
c563b9
             handle_rsc_op(match, local_node);
c563b9
             free(local_node);
c563b9
-- 
c563b9
1.8.3.1
c563b9
c563b9
c563b9
From b0126373d8b2a739ec5b985a7e1f530e850618d3 Mon Sep 17 00:00:00 2001
c563b9
From: Chris Lumens <clumens@redhat.com>
c563b9
Date: Mon, 11 Jan 2021 10:20:11 -0500
c563b9
Subject: [PATCH 09/10] Refactor: libpacemaker: Move reduce_stonith_history
c563b9
 into the library.
c563b9
c563b9
And also rename it to pcmk__reduce_fence_history.  I don't see anywhere
c563b9
else that could use this function at the moment, but it seems too
c563b9
generic to keep in crm_mon.
c563b9
---
c563b9
 include/pcmki/pcmki_fence.h | 16 +++++++++++++-
c563b9
 lib/pacemaker/pcmk_fence.c  | 45 ++++++++++++++++++++++++++++++++++++++-
c563b9
 tools/crm_mon.c             | 52 +--------------------------------------------
c563b9
 3 files changed, 60 insertions(+), 53 deletions(-)
c563b9
c563b9
diff --git a/include/pcmki/pcmki_fence.h b/include/pcmki/pcmki_fence.h
c563b9
index 241d030..d4cef68 100644
c563b9
--- a/include/pcmki/pcmki_fence.h
c563b9
+++ b/include/pcmki/pcmki_fence.h
c563b9
@@ -1,5 +1,5 @@
c563b9
 /*
c563b9
- * Copyright 2019-2020 the Pacemaker project contributors
c563b9
+ * Copyright 2019-2021 the Pacemaker project contributors
c563b9
  *
c563b9
  * The version control history for this file may have further details.
c563b9
  *
c563b9
@@ -219,4 +219,18 @@ int pcmk__fence_validate(pcmk__output_t *out, stonith_t *st, const char *agent,
c563b9
                          const char *id, stonith_key_value_t *params,
c563b9
                          unsigned int timeout);
c563b9
 
c563b9
+/**
c563b9
+ * \brief Reduce the STONITH history
c563b9
+ *
c563b9
+ * STONITH history is reduced as follows:
c563b9
+ *  - The last successful action of every action-type and target is kept
c563b9
+ *  - For failed actions, who failed is kept
c563b9
+ *  - All actions in progress are kept
c563b9
+ *
c563b9
+ * \param[in] history List of STONITH actions
c563b9
+ *
c563b9
+ * \return The reduced history
c563b9
+ */
c563b9
+stonith_history_t *
c563b9
+pcmk__reduce_fence_history(stonith_history_t *history);
c563b9
 #endif
c563b9
diff --git a/lib/pacemaker/pcmk_fence.c b/lib/pacemaker/pcmk_fence.c
c563b9
index d591379..34540cc 100644
c563b9
--- a/lib/pacemaker/pcmk_fence.c
c563b9
+++ b/lib/pacemaker/pcmk_fence.c
c563b9
@@ -1,5 +1,5 @@
c563b9
 /*
c563b9
- * Copyright 2009-2020 the Pacemaker project contributors
c563b9
+ * Copyright 2009-2021 the Pacemaker project contributors
c563b9
  *
c563b9
  * The version control history for this file may have further details.
c563b9
  *
c563b9
@@ -520,3 +520,46 @@ pcmk_fence_validate(xmlNodePtr *xml, stonith_t *st, const char *agent,
c563b9
     return rc;
c563b9
 }
c563b9
 #endif
c563b9
+
c563b9
+stonith_history_t *
c563b9
+pcmk__reduce_fence_history(stonith_history_t *history)
c563b9
+{
c563b9
+    stonith_history_t *new, *hp, *np;
c563b9
+
c563b9
+    if (!history) {
c563b9
+        return history;
c563b9
+    }
c563b9
+
c563b9
+    new = history;
c563b9
+    hp = new->next;
c563b9
+    new->next = NULL;
c563b9
+
c563b9
+    while (hp) {
c563b9
+        stonith_history_t *hp_next = hp->next;
c563b9
+
c563b9
+        hp->next = NULL;
c563b9
+
c563b9
+        for (np = new; ; np = np->next) {
c563b9
+            if ((hp->state == st_done) || (hp->state == st_failed)) {
c563b9
+                /* action not in progress */
c563b9
+                if (pcmk__str_eq(hp->target, np->target, pcmk__str_casei) &&
c563b9
+                    pcmk__str_eq(hp->action, np->action, pcmk__str_casei) &&
c563b9
+                    (hp->state == np->state) &&
c563b9
+                    ((hp->state == st_done) ||
c563b9
+                     pcmk__str_eq(hp->delegate, np->delegate, pcmk__str_casei))) {
c563b9
+                        /* purge older hp */
c563b9
+                        stonith_history_free(hp);
c563b9
+                        break;
c563b9
+                }
c563b9
+            }
c563b9
+
c563b9
+            if (!np->next) {
c563b9
+                np->next = hp;
c563b9
+                break;
c563b9
+            }
c563b9
+        }
c563b9
+        hp = hp_next;
c563b9
+    }
c563b9
+
c563b9
+    return new;
c563b9
+}
c563b9
diff --git a/tools/crm_mon.c b/tools/crm_mon.c
c563b9
index ff1b86b..2179f53 100644
c563b9
--- a/tools/crm_mon.c
c563b9
+++ b/tools/crm_mon.c
c563b9
@@ -1520,56 +1520,6 @@ print_simple_status(pcmk__output_t *out, pe_working_set_t * data_set,
c563b9
     /* coverity[leaked_storage] False positive */
c563b9
 }
c563b9
 
c563b9
-/*!
c563b9
- * \internal
c563b9
- * \brief Reduce the stonith-history
c563b9
- *        for successful actions we keep the last of every action-type & target
c563b9
- *        for failed actions we record as well who had failed
c563b9
- *        for actions in progress we keep full track
c563b9
- *
c563b9
- * \param[in] history    List of stonith actions
c563b9
- *
c563b9
- */
c563b9
-static stonith_history_t *
c563b9
-reduce_stonith_history(stonith_history_t *history)
c563b9
-{
c563b9
-    stonith_history_t *new = history, *hp, *np;
c563b9
-
c563b9
-    if (new) {
c563b9
-        hp = new->next;
c563b9
-        new->next = NULL;
c563b9
-
c563b9
-        while (hp) {
c563b9
-            stonith_history_t *hp_next = hp->next;
c563b9
-
c563b9
-            hp->next = NULL;
c563b9
-
c563b9
-            for (np = new; ; np = np->next) {
c563b9
-                if ((hp->state == st_done) || (hp->state == st_failed)) {
c563b9
-                    /* action not in progress */
c563b9
-                    if (pcmk__str_eq(hp->target, np->target, pcmk__str_casei) &&
c563b9
-                        pcmk__str_eq(hp->action, np->action, pcmk__str_casei) &&
c563b9
-                        (hp->state == np->state) &&
c563b9
-                        ((hp->state == st_done) ||
c563b9
-                         pcmk__str_eq(hp->delegate, np->delegate, pcmk__str_casei))) {
c563b9
-                            /* purge older hp */
c563b9
-                            stonith_history_free(hp);
c563b9
-                            break;
c563b9
-                    }
c563b9
-                }
c563b9
-
c563b9
-                if (!np->next) {
c563b9
-                    np->next = hp;
c563b9
-                    break;
c563b9
-                }
c563b9
-            }
c563b9
-            hp = hp_next;
c563b9
-        }
c563b9
-    }
c563b9
-
c563b9
-    return new;
c563b9
-}
c563b9
-
c563b9
 static int
c563b9
 send_custom_trap(const char *node, const char *rsc, const char *task, int target_rc, int rc,
c563b9
                  int status, const char *desc)
c563b9
@@ -1935,7 +1885,7 @@ mon_refresh_display(gpointer user_data)
c563b9
                 if (!pcmk_is_set(options.mon_ops, mon_op_fence_full_history)
c563b9
                     && (output_format != mon_output_xml)) {
c563b9
 
c563b9
-                    stonith_history = reduce_stonith_history(stonith_history);
c563b9
+                    stonith_history = pcmk__reduce_fence_history(stonith_history);
c563b9
                 }
c563b9
                 break; /* all other cases are errors */
c563b9
             }
c563b9
-- 
c563b9
1.8.3.1
c563b9
c563b9
c563b9
From af3f1368bc76eb498c2c96b3eda9324b579c9380 Mon Sep 17 00:00:00 2001
c563b9
From: Chris Lumens <clumens@redhat.com>
c563b9
Date: Tue, 12 Jan 2021 15:46:55 -0500
c563b9
Subject: [PATCH 10/10] Low: tools: Adjust fencing shown indicator in crm_mon.
c563b9
c563b9
If any of the various fencing flags are set, but not all of them, no '*'
c563b9
will be shown next to the fencing line in the interactive change screen.
c563b9
This makes it seem like fencing should not be shown, and hitting 'm'
c563b9
should toggle the fencing display on.  However, that's not the case and
c563b9
hitting 'm' will actually toggle fencing off.  Hitting it again will
c563b9
toggle it on and the '*' will appear.
c563b9
c563b9
This is confusing, so just display the '*' if any fencing flag is set.
c563b9
---
c563b9
 tools/crm_mon.c | 5 ++++-
c563b9
 1 file changed, 4 insertions(+), 1 deletion(-)
c563b9
c563b9
diff --git a/tools/crm_mon.c b/tools/crm_mon.c
c563b9
index 2179f53..8ec97bb 100644
c563b9
--- a/tools/crm_mon.c
c563b9
+++ b/tools/crm_mon.c
c563b9
@@ -984,7 +984,10 @@ detect_user_input(GIOChannel *channel, GIOCondition condition, gpointer user_dat
c563b9
         print_option_help(out, 'R', pcmk_is_set(options.mon_ops, mon_op_print_clone_detail));
c563b9
         print_option_help(out, 'b', pcmk_is_set(options.mon_ops, mon_op_print_brief));
c563b9
         print_option_help(out, 'j', pcmk_is_set(options.mon_ops, mon_op_print_pending));
c563b9
-        print_option_help(out, 'm', pcmk_is_set(show, mon_show_fencing_all));
c563b9
+        print_option_help(out, 'm', pcmk_any_flags_set(show,
c563b9
+                                                       mon_show_fence_failed
c563b9
+                                                      |mon_show_fence_pending
c563b9
+                                                      |mon_show_fence_worked));
c563b9
         out->info(out, "%s", "\nToggle fields via field letter, type any other key to return");
c563b9
     }
c563b9
 
c563b9
-- 
c563b9
1.8.3.1
c563b9