Compare commits
No commits in common. "imports/c8/pacemaker-2.0.4-6.el8_3.1" and "c8" have entirely different histories.
imports/c8
...
c8
|
@ -1,2 +1,2 @@
|
|||
SOURCES/nagios-agents-metadata-105ab8a.tar.gz
|
||||
SOURCES/pacemaker-2deceaa.tar.gz
|
||||
SOURCES/pacemaker-0f7f88312.tar.gz
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
ea6c0a27fd0ae8ce02f84a11f08a0d79377041c3 SOURCES/nagios-agents-metadata-105ab8a.tar.gz
|
||||
78c94fdcf59cfb064d4433e1b8f71fd856eeec5f SOURCES/pacemaker-2deceaa.tar.gz
|
||||
88946a460e3be18852861269f8837aaaf339328c SOURCES/pacemaker-0f7f88312.tar.gz
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,42 @@
|
|||
From a3bffc7c66bf6f796f977cffd44f223635b008c5 Mon Sep 17 00:00:00 2001
|
||||
From: Reid Wahl <nrwahl@protonmail.com>
|
||||
Date: Wed, 20 Dec 2023 13:33:47 -0800
|
||||
Subject: [PATCH] Doc: Pacemaker Explained: Add replace for
|
||||
PCMK__REMOTE_SCHEMA_DIR
|
||||
|
||||
So that the existing use in local-options.rst expands correctly.
|
||||
|
||||
Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
|
||||
---
|
||||
doc/sphinx/Makefile.am | 1 +
|
||||
doc/sphinx/conf.py.in | 1 +
|
||||
3 files changed, 2 insertions(+)
|
||||
create mode 100644 doc/sphinx/conf.py.in.rej
|
||||
|
||||
diff --git a/doc/sphinx/Makefile.am b/doc/sphinx/Makefile.am
|
||||
index e48e19a..d0309ff 100644
|
||||
--- a/doc/sphinx/Makefile.am
|
||||
+++ b/doc/sphinx/Makefile.am
|
||||
@@ -134,6 +134,7 @@ $(BOOKS:%=%/conf.py): conf.py.in
|
||||
-e 's#%CRM_SCHEMA_DIRECTORY%#@CRM_SCHEMA_DIRECTORY@#g' \
|
||||
-e 's#%PACEMAKER_CONFIG_DIR%#@PACEMAKER_CONFIG_DIR@#g' \
|
||||
-e 's#%PCMK_GNUTLS_PRIORITIES%#@PCMK_GNUTLS_PRIORITIES@#g' \
|
||||
+ -e 's#%PCMK__REMOTE_SCHEMA_DIR%#@PCMK__REMOTE_SCHEMA_DIR@#g' \
|
||||
$(<) > "$@"
|
||||
|
||||
$(BOOK)/_build: $(STATIC_FILES) $(BOOK)/conf.py $(DEPS_$(BOOK)) $(wildcard $(srcdir)/$(BOOK)/*.rst)
|
||||
diff --git a/doc/sphinx/conf.py.in b/doc/sphinx/conf.py.in
|
||||
index 556eb72..511f029 100644
|
||||
--- a/doc/sphinx/conf.py.in
|
||||
+++ b/doc/sphinx/conf.py.in
|
||||
@@ -40,6 +40,7 @@ rst_prolog="""
|
||||
.. |PCMK_INIT_ENV_FILE| replace:: ``%PACEMAKER_CONFIG_DIR%/pcmk-init.env``
|
||||
.. |PCMK_LOG_FILE| replace:: %CRM_LOG_DIR%/pacemaker.log
|
||||
.. |PCMK_GNUTLS_PRIORITIES| replace:: %PCMK_GNUTLS_PRIORITIES%
|
||||
+.. |PCMK__REMOTE_SCHEMA_DIR| replace:: %PCMK__REMOTE_SCHEMA_DIR%
|
||||
.. |REMOTE_DISTRO| replace:: AlmaLinux
|
||||
.. |REMOTE_DISTRO_VER| replace:: 9
|
||||
"""
|
||||
--
|
||||
2.31.1
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
From 47c3e06b098c7e148c54675588d03b4d2bea40b5 Mon Sep 17 00:00:00 2001
|
||||
From: Chris Lumens <clumens@redhat.com>
|
||||
Date: Mon, 22 Jun 2020 16:20:01 -0400
|
||||
Subject: [PATCH] Fix: libpacemaker: Don't allow a potential NULL in a format
|
||||
string.
|
||||
|
||||
This is only tripping up F32 s390x builds, but I don't suppose there's
|
||||
any reason it couldn't come up elsewhere later.
|
||||
---
|
||||
lib/pacemaker/pcmk_sched_constraints.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/lib/pacemaker/pcmk_sched_constraints.c b/lib/pacemaker/pcmk_sched_constraints.c
|
||||
index 9c3a88d..d8c3e69 100644
|
||||
--- a/lib/pacemaker/pcmk_sched_constraints.c
|
||||
+++ b/lib/pacemaker/pcmk_sched_constraints.c
|
||||
@@ -1595,8 +1595,8 @@ custom_action_order(pe_resource_t * lh_rsc, char *lh_action_task, pe_action_t *
|
||||
order = calloc(1, sizeof(pe__ordering_t));
|
||||
|
||||
crm_trace("Creating[%d] %s %s %s - %s %s %s", data_set->order_id,
|
||||
- lh_rsc?lh_rsc->id:"NA", lh_action_task, lh_action?lh_action->uuid:"NA",
|
||||
- rh_rsc?rh_rsc->id:"NA", rh_action_task, rh_action?rh_action->uuid:"NA");
|
||||
+ lh_rsc?lh_rsc->id:"NA", lh_action_task?lh_action_task:"NA", lh_action?lh_action->uuid:"NA",
|
||||
+ rh_rsc?rh_rsc->id:"NA", rh_action_task?rh_action_task:"NA", rh_action?rh_action->uuid:"NA");
|
||||
|
||||
/* CRM_ASSERT(data_set->order_id != 291); */
|
||||
|
||||
--
|
||||
1.8.3.1
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -1,27 +0,0 @@
|
|||
From 7ed7675615ada7d0be5654e0dcb26de60cf5b5e9 Mon Sep 17 00:00:00 2001
|
||||
From: Ken Gaillot <kgaillot@redhat.com>
|
||||
Date: Mon, 22 Jun 2020 20:03:56 -0500
|
||||
Subject: [PATCH] Test: scheduler: explicitly disable concurrent-fencing in
|
||||
on_fail_demote4
|
||||
|
||||
... so the expected output is the same regardless of what default the build was
|
||||
compiled with
|
||||
---
|
||||
cts/scheduler/on_fail_demote4.xml | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/cts/scheduler/on_fail_demote4.xml b/cts/scheduler/on_fail_demote4.xml
|
||||
index eb4c4cc..1082266 100644
|
||||
--- a/cts/scheduler/on_fail_demote4.xml
|
||||
+++ b/cts/scheduler/on_fail_demote4.xml
|
||||
@@ -8,6 +8,7 @@
|
||||
<nvpair id="cts-shutdown-escalation" name="shutdown-escalation" value="5min"/>
|
||||
<nvpair id="cts-batch-limit" name="batch-limit" value="10"/>
|
||||
<nvpair id="cts-dc-deadtime" name="dc-deadtime" value="5s"/>
|
||||
+ <nvpair id="cts-concurrent-fencing" name="concurrent-fencing" value="false"/>
|
||||
<nvpair id="cib-bootstrap-options-have-watchdog" name="have-watchdog" value="false"/>
|
||||
<nvpair id="cib-bootstrap-options-dc-version" name="dc-version" value="2.0.4-578.6e1b582.git.el7_8-6e1b582"/>
|
||||
<nvpair id="cib-bootstrap-options-cluster-infrastructure" name="cluster-infrastructure" value="corosync"/>
|
||||
--
|
||||
1.8.3.1
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -1,32 +0,0 @@
|
|||
From 85040eb19b9405464b01a7e67eb6769d2a03c611 Mon Sep 17 00:00:00 2001
|
||||
From: Ken Gaillot <kgaillot@redhat.com>
|
||||
Date: Fri, 19 Jun 2020 17:49:22 -0500
|
||||
Subject: [PATCH] Doc: sysconfig: remove outdated reference to wildcards in
|
||||
PCMK_trace_files
|
||||
|
||||
Wildcards stopped working when the log filtering implementation changed in
|
||||
1.1.8 to support PCMK_trace_tags. It's not worth the effort to fix at this
|
||||
point, so just update the comment in the sysconfig file.
|
||||
---
|
||||
daemons/pacemakerd/pacemaker.sysconfig | 5 ++---
|
||||
1 file changed, 2 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/daemons/pacemakerd/pacemaker.sysconfig b/daemons/pacemakerd/pacemaker.sysconfig
|
||||
index c7745d8..e4a5c4d 100644
|
||||
--- a/daemons/pacemakerd/pacemaker.sysconfig
|
||||
+++ b/daemons/pacemakerd/pacemaker.sysconfig
|
||||
@@ -34,9 +34,8 @@
|
||||
# Log all messages from a comma-separated list of functions.
|
||||
# PCMK_trace_functions=function1,function2,function3
|
||||
|
||||
-# Log all messages from a comma-separated list of files (no path).
|
||||
-# Wildcards are supported, e.g. PCMK_trace_files=prefix*.c
|
||||
-# PCMK_trace_files=file.c,other.h
|
||||
+# Log all messages from a comma-separated list of file names (without path).
|
||||
+# PCMK_trace_files=file1.c,file2.c
|
||||
|
||||
# Log all messages matching comma-separated list of formats.
|
||||
# PCMK_trace_formats="Sent delete %d"
|
||||
--
|
||||
1.8.3.1
|
||||
|
|
@ -0,0 +1,276 @@
|
|||
From d50bbafc32428e873c0052a9defcf93d2e52667e Mon Sep 17 00:00:00 2001
|
||||
From: Chris Lumens <clumens@redhat.com>
|
||||
Date: Wed, 10 Jan 2024 11:35:11 -0500
|
||||
Subject: [PATCH 1/3] Refactor: libcrmcommon: Split feature set check into its
|
||||
own function.
|
||||
|
||||
---
|
||||
include/crm/common/cib_internal.h | 4 +++-
|
||||
lib/cib/cib_utils.c | 12 ++++++------
|
||||
lib/common/cib.c | 18 +++++++++++++++++-
|
||||
3 files changed, 26 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/include/crm/common/cib_internal.h b/include/crm/common/cib_internal.h
|
||||
index c41c12e..fa65e58 100644
|
||||
--- a/include/crm/common/cib_internal.h
|
||||
+++ b/include/crm/common/cib_internal.h
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
- * Copyright 2023 the Pacemaker project contributors
|
||||
+ * Copyright 2023-2024 the Pacemaker project contributors
|
||||
*
|
||||
* The version control history for this file may have further details.
|
||||
*
|
||||
@@ -16,6 +16,8 @@ extern "C" {
|
||||
|
||||
const char *pcmk__cib_abs_xpath_for(const char *element);
|
||||
|
||||
+int pcmk__check_feature_set(const char *cib_version);
|
||||
+
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
diff --git a/lib/cib/cib_utils.c b/lib/cib/cib_utils.c
|
||||
index 0082eef..bf2982c 100644
|
||||
--- a/lib/cib/cib_utils.c
|
||||
+++ b/lib/cib/cib_utils.c
|
||||
@@ -353,7 +353,6 @@ cib_perform_op(const char *op, int call_options, cib__op_fn_t fn, bool is_query,
|
||||
xmlNode *patchset_cib = NULL;
|
||||
xmlNode *local_diff = NULL;
|
||||
|
||||
- const char *new_version = NULL;
|
||||
const char *user = crm_element_value(req, F_CIB_USER);
|
||||
bool with_digest = false;
|
||||
|
||||
@@ -470,12 +469,13 @@ cib_perform_op(const char *op, int call_options, cib__op_fn_t fn, bool is_query,
|
||||
}
|
||||
|
||||
if (scratch) {
|
||||
- new_version = crm_element_value(scratch, XML_ATTR_CRM_VERSION);
|
||||
+ const char *new_version = crm_element_value(scratch, XML_ATTR_CRM_VERSION);
|
||||
|
||||
- if (new_version && compare_version(new_version, CRM_FEATURE_SET) > 0) {
|
||||
- crm_err("Discarding update with feature set '%s' greater than our own '%s'",
|
||||
- new_version, CRM_FEATURE_SET);
|
||||
- rc = -EPROTONOSUPPORT;
|
||||
+ rc = pcmk__check_feature_set(new_version);
|
||||
+ if (rc != pcmk_rc_ok) {
|
||||
+ pcmk__config_err("Discarding update with feature set '%s' greater than our own '%s'",
|
||||
+ new_version, CRM_FEATURE_SET);
|
||||
+ rc = pcmk_rc2legacy(rc);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
diff --git a/lib/common/cib.c b/lib/common/cib.c
|
||||
index fee7881..cbebc2e 100644
|
||||
--- a/lib/common/cib.c
|
||||
+++ b/lib/common/cib.c
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Original copyright 2004 International Business Machines
|
||||
- * Later changes copyright 2008-2023 the Pacemaker project contributors
|
||||
+ * Later changes copyright 2008-2024 the Pacemaker project contributors
|
||||
*
|
||||
* The version control history for this file may have further details.
|
||||
*
|
||||
@@ -173,3 +173,19 @@ pcmk_find_cib_element(xmlNode *cib, const char *element_name)
|
||||
{
|
||||
return get_xpath_object(pcmk_cib_xpath_for(element_name), cib, LOG_TRACE);
|
||||
}
|
||||
+
|
||||
+/*!
|
||||
+ * \internal
|
||||
+ * \brief Check that the feature set in the CIB is supported on this node
|
||||
+ *
|
||||
+ * \param[in] new_version XML_ATTR_CRM_VERSION attribute from the CIB
|
||||
+ */
|
||||
+int
|
||||
+pcmk__check_feature_set(const char *cib_version)
|
||||
+{
|
||||
+ if (cib_version && compare_version(cib_version, CRM_FEATURE_SET) > 0) {
|
||||
+ return EPROTONOSUPPORT;
|
||||
+ }
|
||||
+
|
||||
+ return pcmk_rc_ok;
|
||||
+}
|
||||
--
|
||||
2.31.1
|
||||
|
||||
From d89fd8336ae47d892201513c99773705d57f15f0 Mon Sep 17 00:00:00 2001
|
||||
From: Chris Lumens <clumens@redhat.com>
|
||||
Date: Wed, 10 Jan 2024 13:46:42 -0500
|
||||
Subject: [PATCH 2/3] Feature: scheduler: Check the CIB feature set in
|
||||
cluster_status.
|
||||
|
||||
This adds the check that was previously only in cib_perform_op to the
|
||||
scheduler code, ensuring that any daemon or tool that calls the
|
||||
scheduler will check that the feature set in the CIB is supported.
|
||||
---
|
||||
lib/pengine/status.c | 10 ++++++++++
|
||||
1 file changed, 10 insertions(+)
|
||||
|
||||
diff --git a/lib/pengine/status.c b/lib/pengine/status.c
|
||||
index e6ec237..1294803 100644
|
||||
--- a/lib/pengine/status.c
|
||||
+++ b/lib/pengine/status.c
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <crm/crm.h>
|
||||
#include <crm/msg_xml.h>
|
||||
#include <crm/common/xml.h>
|
||||
+#include <crm/common/cib_internal.h>
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
@@ -70,12 +71,21 @@ pe_free_working_set(pcmk_scheduler_t *scheduler)
|
||||
gboolean
|
||||
cluster_status(pcmk_scheduler_t * scheduler)
|
||||
{
|
||||
+ const char *new_version = NULL;
|
||||
xmlNode *section = NULL;
|
||||
|
||||
if ((scheduler == NULL) || (scheduler->input == NULL)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
+ new_version = crm_element_value(scheduler->input, XML_ATTR_CRM_VERSION);
|
||||
+
|
||||
+ if (pcmk__check_feature_set(new_version) != pcmk_rc_ok) {
|
||||
+ pcmk__config_err("Can't process CIB with feature set '%s' greater than our own '%s'",
|
||||
+ new_version, CRM_FEATURE_SET);
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+
|
||||
crm_trace("Beginning unpack");
|
||||
|
||||
if (scheduler->failed != NULL) {
|
||||
--
|
||||
2.31.1
|
||||
|
||||
From a3428926d37af506014a6b462d1308d8541c5932 Mon Sep 17 00:00:00 2001
|
||||
From: Chris Lumens <clumens@redhat.com>
|
||||
Date: Wed, 10 Jan 2024 14:56:36 -0500
|
||||
Subject: [PATCH 3/3] Low: libcib: Do not check CIB feature set for files in
|
||||
cib_perform_op.
|
||||
|
||||
This is related to the previous feature for transferring schema files to
|
||||
older remote nodes. In that case, the newer schema files may also have
|
||||
a newer feature set than the node supports, so the transferred files are
|
||||
still not usable.
|
||||
|
||||
However, the feature set only matters for the scheduler, not for most
|
||||
command line tools (obviously, crm_simulate would still care). So in
|
||||
those cases, we can just disable the feature set check if the CIB was
|
||||
read in from a file. For the scheduler, the check is still performed as
|
||||
part of cluster_status.
|
||||
---
|
||||
cts/cli/regression.tools.exp | 2 +-
|
||||
daemons/based/based_callbacks.c | 4 ++--
|
||||
include/crm/cib/internal.h | 4 ++--
|
||||
lib/cib/cib_file.c | 2 +-
|
||||
lib/cib/cib_utils.c | 15 +++++++++------
|
||||
5 files changed, 15 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/cts/cli/regression.tools.exp b/cts/cli/regression.tools.exp
|
||||
index 417b5cd..c81c420 100644
|
||||
--- a/cts/cli/regression.tools.exp
|
||||
+++ b/cts/cli/regression.tools.exp
|
||||
@@ -7939,7 +7939,7 @@ unpack_config warning: Blind faith: not fencing unseen nodes
|
||||
=#=#=#= End test: Verbosely verify a file-specified invalid configuration, outputting as xml - Invalid configuration (78) =#=#=#=
|
||||
* Passed: crm_verify - Verbosely verify a file-specified invalid configuration, outputting as xml
|
||||
=#=#=#= Begin test: Verbosely verify another file-specified invalid configuration, outputting as xml =#=#=#=
|
||||
-(cluster_status@status.c:113) warning: Fencing and resource management disabled due to lack of quorum
|
||||
+(cluster_status@status.c:123) warning: Fencing and resource management disabled due to lack of quorum
|
||||
<pacemaker-result api-version="X" request="crm_verify_invalid_no_stonith.xml --output-as=xml --verbose">
|
||||
<status code="78" message="Invalid configuration">
|
||||
<errors>
|
||||
diff --git a/daemons/based/based_callbacks.c b/daemons/based/based_callbacks.c
|
||||
index 5f3dc62..f16e4d9 100644
|
||||
--- a/daemons/based/based_callbacks.c
|
||||
+++ b/daemons/based/based_callbacks.c
|
||||
@@ -1362,7 +1362,7 @@ cib_process_command(xmlNode *request, const cib__operation_t *operation,
|
||||
input = prepare_input(request, operation->type, §ion);
|
||||
|
||||
if (!pcmk_is_set(operation->flags, cib__op_attr_modifies)) {
|
||||
- rc = cib_perform_op(op, call_options, op_function, true, section,
|
||||
+ rc = cib_perform_op(NULL, op, call_options, op_function, true, section,
|
||||
request, input, false, &config_changed, &the_cib,
|
||||
&result_cib, NULL, &output);
|
||||
|
||||
@@ -1395,7 +1395,7 @@ cib_process_command(xmlNode *request, const cib__operation_t *operation,
|
||||
}
|
||||
|
||||
// result_cib must not be modified after cib_perform_op() returns
|
||||
- rc = cib_perform_op(op, call_options, op_function, false, section,
|
||||
+ rc = cib_perform_op(NULL, op, call_options, op_function, false, section,
|
||||
request, input, manage_counters, &config_changed,
|
||||
&the_cib, &result_cib, cib_diff, &output);
|
||||
|
||||
diff --git a/include/crm/cib/internal.h b/include/crm/cib/internal.h
|
||||
index 9d54d52..b6d6871 100644
|
||||
--- a/include/crm/cib/internal.h
|
||||
+++ b/include/crm/cib/internal.h
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
- * Copyright 2004-2023 the Pacemaker project contributors
|
||||
+ * Copyright 2004-2024 the Pacemaker project contributors
|
||||
*
|
||||
* The version control history for this file may have further details.
|
||||
*
|
||||
@@ -206,7 +206,7 @@ int cib__get_notify_patchset(const xmlNode *msg, const xmlNode **patchset);
|
||||
|
||||
bool cib__element_in_patchset(const xmlNode *patchset, const char *element);
|
||||
|
||||
-int cib_perform_op(const char *op, int call_options, cib__op_fn_t fn,
|
||||
+int cib_perform_op(cib_t *cib, const char *op, int call_options, cib__op_fn_t fn,
|
||||
bool is_query, const char *section, xmlNode *req,
|
||||
xmlNode *input, bool manage_counters, bool *config_changed,
|
||||
xmlNode **current_cib, xmlNode **result_cib, xmlNode **diff,
|
||||
diff --git a/lib/cib/cib_file.c b/lib/cib/cib_file.c
|
||||
index a279823..9dd952c 100644
|
||||
--- a/lib/cib/cib_file.c
|
||||
+++ b/lib/cib/cib_file.c
|
||||
@@ -245,7 +245,7 @@ cib_file_process_request(cib_t *cib, xmlNode *request, xmlNode **output)
|
||||
data = pcmk_find_cib_element(data, section);
|
||||
}
|
||||
|
||||
- rc = cib_perform_op(op, call_options, op_function, read_only, section,
|
||||
+ rc = cib_perform_op(cib, op, call_options, op_function, read_only, section,
|
||||
request, data, true, &changed, &private->cib_xml,
|
||||
&result_cib, &cib_diff, output);
|
||||
|
||||
diff --git a/lib/cib/cib_utils.c b/lib/cib/cib_utils.c
|
||||
index bf2982c..9c3f9f1 100644
|
||||
--- a/lib/cib/cib_utils.c
|
||||
+++ b/lib/cib/cib_utils.c
|
||||
@@ -339,11 +339,10 @@ should_copy_cib(const char *op, const char *section, int call_options)
|
||||
}
|
||||
|
||||
int
|
||||
-cib_perform_op(const char *op, int call_options, cib__op_fn_t fn, bool is_query,
|
||||
- const char *section, xmlNode *req, xmlNode *input,
|
||||
- bool manage_counters, bool *config_changed,
|
||||
- xmlNode **current_cib, xmlNode **result_cib, xmlNode **diff,
|
||||
- xmlNode **output)
|
||||
+cib_perform_op(cib_t *cib, const char *op, int call_options, cib__op_fn_t fn,
|
||||
+ bool is_query, const char *section, xmlNode *req, xmlNode *input,
|
||||
+ bool manage_counters, bool *config_changed, xmlNode **current_cib,
|
||||
+ xmlNode **result_cib, xmlNode **diff, xmlNode **output)
|
||||
{
|
||||
int rc = pcmk_ok;
|
||||
bool check_schema = true;
|
||||
@@ -468,7 +467,11 @@ cib_perform_op(const char *op, int call_options, cib__op_fn_t fn, bool is_query,
|
||||
goto done;
|
||||
}
|
||||
|
||||
- if (scratch) {
|
||||
+ /* If the CIB is from a file, we don't need to check that the feature set is
|
||||
+ * supported. All we care about in that case is the schema version, which
|
||||
+ * is checked elsewhere.
|
||||
+ */
|
||||
+ if (scratch && (cib == NULL || cib->variant != cib_file)) {
|
||||
const char *new_version = crm_element_value(scratch, XML_ATTR_CRM_VERSION);
|
||||
|
||||
rc = pcmk__check_feature_set(new_version);
|
||||
--
|
||||
2.31.1
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,373 @@
|
|||
From 4823643bef8801b33688167b159bb531bcdf8911 Mon Sep 17 00:00:00 2001
|
||||
From: Ken Gaillot <kgaillot@redhat.com>
|
||||
Date: Thu, 4 Jan 2024 17:10:08 -0600
|
||||
Subject: [PATCH 1/5] Refactor: pacemaker-attrd: drop redundant argument from
|
||||
update_attr_on_host()
|
||||
|
||||
It can check for a force-write via its xml argument, to simplify the caller
|
||||
---
|
||||
daemons/attrd/attrd_corosync.c | 13 +++++++------
|
||||
1 file changed, 7 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/daemons/attrd/attrd_corosync.c b/daemons/attrd/attrd_corosync.c
|
||||
index 158d82f..1b56923 100644
|
||||
--- a/daemons/attrd/attrd_corosync.c
|
||||
+++ b/daemons/attrd/attrd_corosync.c
|
||||
@@ -266,7 +266,7 @@ record_peer_nodeid(attribute_value_t *v, const char *host)
|
||||
static void
|
||||
update_attr_on_host(attribute_t *a, const crm_node_t *peer, const xmlNode *xml,
|
||||
const char *attr, const char *value, const char *host,
|
||||
- bool filter, int is_force_write)
|
||||
+ bool filter)
|
||||
{
|
||||
attribute_value_t *v = NULL;
|
||||
|
||||
@@ -309,6 +309,10 @@ update_attr_on_host(attribute_t *a, const crm_node_t *peer, const xmlNode *xml,
|
||||
}
|
||||
|
||||
} else {
|
||||
+ int is_force_write = 0;
|
||||
+
|
||||
+ crm_element_value_int(xml, PCMK__XA_ATTR_FORCE, &is_force_write);
|
||||
+
|
||||
if (is_force_write == 1 && a->timeout_ms && a->timer) {
|
||||
/* Save forced writing and set change flag. */
|
||||
/* The actual attribute is written by Writer after election. */
|
||||
@@ -338,15 +342,12 @@ attrd_peer_update_one(const crm_node_t *peer, xmlNode *xml, bool filter)
|
||||
const char *attr = crm_element_value(xml, PCMK__XA_ATTR_NAME);
|
||||
const char *value = crm_element_value(xml, PCMK__XA_ATTR_VALUE);
|
||||
const char *host = crm_element_value(xml, PCMK__XA_ATTR_NODE_NAME);
|
||||
- int is_force_write = 0;
|
||||
|
||||
if (attr == NULL) {
|
||||
crm_warn("Could not update attribute: peer did not specify name");
|
||||
return;
|
||||
}
|
||||
|
||||
- crm_element_value_int(xml, PCMK__XA_ATTR_FORCE, &is_force_write);
|
||||
-
|
||||
a = attrd_populate_attribute(xml, attr);
|
||||
if (a == NULL) {
|
||||
return;
|
||||
@@ -361,12 +362,12 @@ attrd_peer_update_one(const crm_node_t *peer, xmlNode *xml, bool filter)
|
||||
g_hash_table_iter_init(&vIter, a->values);
|
||||
|
||||
while (g_hash_table_iter_next(&vIter, (gpointer *) & host, NULL)) {
|
||||
- update_attr_on_host(a, peer, xml, attr, value, host, filter, is_force_write);
|
||||
+ update_attr_on_host(a, peer, xml, attr, value, host, filter);
|
||||
}
|
||||
|
||||
} else {
|
||||
// Update attribute value for the given host
|
||||
- update_attr_on_host(a, peer, xml, attr, value, host, filter, is_force_write);
|
||||
+ update_attr_on_host(a, peer, xml, attr, value, host, filter);
|
||||
}
|
||||
|
||||
/* If this is a message from some attrd instance broadcasting its protocol
|
||||
--
|
||||
2.31.1
|
||||
|
||||
From c7a1ab819b25e3225c185c1630a7139a96fb5c71 Mon Sep 17 00:00:00 2001
|
||||
From: Ken Gaillot <kgaillot@redhat.com>
|
||||
Date: Tue, 9 Jan 2024 16:48:37 -0600
|
||||
Subject: [PATCH 2/5] Refactor: pacemaker-attrd: drop unused argument from
|
||||
attrd_peer_sync()
|
||||
|
||||
---
|
||||
daemons/attrd/attrd_corosync.c | 10 ++++++++--
|
||||
daemons/attrd/attrd_elections.c | 2 +-
|
||||
daemons/attrd/attrd_messages.c | 2 +-
|
||||
daemons/attrd/pacemaker-attrd.h | 2 +-
|
||||
4 files changed, 11 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/daemons/attrd/attrd_corosync.c b/daemons/attrd/attrd_corosync.c
|
||||
index 1b56923..088f00c 100644
|
||||
--- a/daemons/attrd/attrd_corosync.c
|
||||
+++ b/daemons/attrd/attrd_corosync.c
|
||||
@@ -233,7 +233,7 @@ attrd_peer_change_cb(enum crm_status_type kind, crm_node_t *peer, const void *da
|
||||
*/
|
||||
if (attrd_election_won()
|
||||
&& !pcmk_is_set(peer->flags, crm_remote_node)) {
|
||||
- attrd_peer_sync(peer, NULL);
|
||||
+ attrd_peer_sync(peer);
|
||||
}
|
||||
} else {
|
||||
// Remove all attribute values associated with lost nodes
|
||||
@@ -535,8 +535,14 @@ attrd_peer_remove(const char *host, bool uncache, const char *source)
|
||||
}
|
||||
}
|
||||
|
||||
+/*!
|
||||
+ * \internal
|
||||
+ * \brief Send all known attributes and values to a peer
|
||||
+ *
|
||||
+ * \param[in] peer Peer to send sync to (if NULL, broadcast to all peers)
|
||||
+ */
|
||||
void
|
||||
-attrd_peer_sync(crm_node_t *peer, xmlNode *xml)
|
||||
+attrd_peer_sync(crm_node_t *peer)
|
||||
{
|
||||
GHashTableIter aIter;
|
||||
GHashTableIter vIter;
|
||||
diff --git a/daemons/attrd/attrd_elections.c b/daemons/attrd/attrd_elections.c
|
||||
index 82fbe8a..9dbf133 100644
|
||||
--- a/daemons/attrd/attrd_elections.c
|
||||
+++ b/daemons/attrd/attrd_elections.c
|
||||
@@ -23,7 +23,7 @@ attrd_election_cb(gpointer user_data)
|
||||
attrd_declare_winner();
|
||||
|
||||
/* Update the peers after an election */
|
||||
- attrd_peer_sync(NULL, NULL);
|
||||
+ attrd_peer_sync(NULL);
|
||||
|
||||
/* After winning an election, update the CIB with the values of all
|
||||
* attributes as the winner knows them.
|
||||
diff --git a/daemons/attrd/attrd_messages.c b/daemons/attrd/attrd_messages.c
|
||||
index 5525d4b..13ac01f 100644
|
||||
--- a/daemons/attrd/attrd_messages.c
|
||||
+++ b/daemons/attrd/attrd_messages.c
|
||||
@@ -180,7 +180,7 @@ handle_sync_request(pcmk__request_t *request)
|
||||
crm_node_t *peer = pcmk__get_node(0, request->peer, NULL,
|
||||
pcmk__node_search_cluster);
|
||||
|
||||
- attrd_peer_sync(peer, request->xml);
|
||||
+ attrd_peer_sync(peer);
|
||||
pcmk__set_result(&request->result, CRM_EX_OK, PCMK_EXEC_DONE, NULL);
|
||||
return NULL;
|
||||
} else {
|
||||
diff --git a/daemons/attrd/pacemaker-attrd.h b/daemons/attrd/pacemaker-attrd.h
|
||||
index 7384188..bacaad6 100644
|
||||
--- a/daemons/attrd/pacemaker-attrd.h
|
||||
+++ b/daemons/attrd/pacemaker-attrd.h
|
||||
@@ -175,7 +175,7 @@ extern GHashTable *peer_protocol_vers;
|
||||
int attrd_cluster_connect(void);
|
||||
void attrd_peer_update(const crm_node_t *peer, xmlNode *xml, const char *host,
|
||||
bool filter);
|
||||
-void attrd_peer_sync(crm_node_t *peer, xmlNode *xml);
|
||||
+void attrd_peer_sync(crm_node_t *peer);
|
||||
void attrd_peer_remove(const char *host, bool uncache, const char *source);
|
||||
void attrd_peer_clear_failure(pcmk__request_t *request);
|
||||
void attrd_peer_sync_response(const crm_node_t *peer, bool peer_won,
|
||||
--
|
||||
2.31.1
|
||||
|
||||
From abafae0068e10abb135b0496086947728365299a Mon Sep 17 00:00:00 2001
|
||||
From: Ken Gaillot <kgaillot@redhat.com>
|
||||
Date: Thu, 11 Jan 2024 17:31:17 -0600
|
||||
Subject: [PATCH 3/5] Refactor: pacemaker-attrd: de-functionize
|
||||
attrd_lookup_or_create_value()
|
||||
|
||||
... to make planned changes easier
|
||||
---
|
||||
daemons/attrd/attrd_corosync.c | 62 +++++++++++++---------------------
|
||||
1 file changed, 24 insertions(+), 38 deletions(-)
|
||||
|
||||
diff --git a/daemons/attrd/attrd_corosync.c b/daemons/attrd/attrd_corosync.c
|
||||
index 088f00c..59e6a26 100644
|
||||
--- a/daemons/attrd/attrd_corosync.c
|
||||
+++ b/daemons/attrd/attrd_corosync.c
|
||||
@@ -168,40 +168,6 @@ broadcast_local_value(const attribute_t *a)
|
||||
|
||||
#define state_text(state) pcmk__s((state), "in unknown state")
|
||||
|
||||
-/*!
|
||||
- * \internal
|
||||
- * \brief Return a node's value from hash table (creating one if needed)
|
||||
- *
|
||||
- * \param[in,out] values Hash table of values
|
||||
- * \param[in] node_name Name of node to look up
|
||||
- * \param[in] xml XML describing the attribute
|
||||
- *
|
||||
- * \return Pointer to new or existing hash table entry
|
||||
- */
|
||||
-static attribute_value_t *
|
||||
-attrd_lookup_or_create_value(GHashTable *values, const char *node_name,
|
||||
- const xmlNode *xml)
|
||||
-{
|
||||
- attribute_value_t *v = g_hash_table_lookup(values, node_name);
|
||||
- int is_remote = 0;
|
||||
-
|
||||
- if (v == NULL) {
|
||||
- v = calloc(1, sizeof(attribute_value_t));
|
||||
- CRM_ASSERT(v != NULL);
|
||||
-
|
||||
- pcmk__str_update(&v->nodename, node_name);
|
||||
- g_hash_table_replace(values, v->nodename, v);
|
||||
- }
|
||||
-
|
||||
- crm_element_value_int(xml, PCMK__XA_ATTR_IS_REMOTE, &is_remote);
|
||||
- if (is_remote) {
|
||||
- attrd_set_value_flags(v, attrd_value_remote);
|
||||
- CRM_ASSERT(crm_remote_peer_get(node_name) != NULL);
|
||||
- }
|
||||
-
|
||||
- return(v);
|
||||
-}
|
||||
-
|
||||
static void
|
||||
attrd_peer_change_cb(enum crm_status_type kind, crm_node_t *peer, const void *data)
|
||||
{
|
||||
@@ -268,18 +234,38 @@ update_attr_on_host(attribute_t *a, const crm_node_t *peer, const xmlNode *xml,
|
||||
const char *attr, const char *value, const char *host,
|
||||
bool filter)
|
||||
{
|
||||
+ int is_remote = 0;
|
||||
+ bool changed = false;
|
||||
attribute_value_t *v = NULL;
|
||||
|
||||
- v = attrd_lookup_or_create_value(a->values, host, xml);
|
||||
+ // Create entry for value if not already existing
|
||||
+ v = g_hash_table_lookup(a->values, host);
|
||||
+ if (v == NULL) {
|
||||
+ v = calloc(1, sizeof(attribute_value_t));
|
||||
+ CRM_ASSERT(v != NULL);
|
||||
+
|
||||
+ pcmk__str_update(&v->nodename, host);
|
||||
+ g_hash_table_replace(a->values, v->nodename, v);
|
||||
+ }
|
||||
+
|
||||
+ // If value is for a Pacemaker Remote node, remember that
|
||||
+ crm_element_value_int(xml, PCMK__XA_ATTR_IS_REMOTE, &is_remote);
|
||||
+ if (is_remote) {
|
||||
+ attrd_set_value_flags(v, attrd_value_remote);
|
||||
+ CRM_ASSERT(crm_remote_peer_get(host) != NULL);
|
||||
+ }
|
||||
+
|
||||
+ // Check whether the value changed
|
||||
+ changed = !pcmk__str_eq(v->current, value, pcmk__str_casei);
|
||||
|
||||
- if (filter && !pcmk__str_eq(v->current, value, pcmk__str_casei)
|
||||
- && pcmk__str_eq(host, attrd_cluster->uname, pcmk__str_casei)) {
|
||||
+ if (changed && filter && pcmk__str_eq(host, attrd_cluster->uname,
|
||||
+ pcmk__str_casei)) {
|
||||
|
||||
crm_notice("%s[%s]: local value '%s' takes priority over '%s' from %s",
|
||||
attr, host, v->current, value, peer->uname);
|
||||
v = broadcast_local_value(a);
|
||||
|
||||
- } else if (!pcmk__str_eq(v->current, value, pcmk__str_casei)) {
|
||||
+ } else if (changed) {
|
||||
crm_notice("Setting %s[%s]%s%s: %s -> %s "
|
||||
CRM_XS " from %s with %s write delay",
|
||||
attr, host, a->set_type ? " in " : "",
|
||||
--
|
||||
2.31.1
|
||||
|
||||
From 72529ec512fb4938bd8dbbd2caf44bbb1a616826 Mon Sep 17 00:00:00 2001
|
||||
From: Ken Gaillot <kgaillot@redhat.com>
|
||||
Date: Thu, 11 Jan 2024 18:04:33 -0600
|
||||
Subject: [PATCH 4/5] Refactor: pacemaker-attrd: minor shuffling to make
|
||||
planned changes easier
|
||||
|
||||
---
|
||||
daemons/attrd/attrd_cib.c | 19 +++++++++++--------
|
||||
1 file changed, 11 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/daemons/attrd/attrd_cib.c b/daemons/attrd/attrd_cib.c
|
||||
index bdc0a10..481fea7 100644
|
||||
--- a/daemons/attrd/attrd_cib.c
|
||||
+++ b/daemons/attrd/attrd_cib.c
|
||||
@@ -51,6 +51,7 @@ attrd_cib_updated_cb(const char *event, xmlNode *msg)
|
||||
{
|
||||
const xmlNode *patchset = NULL;
|
||||
const char *client_name = NULL;
|
||||
+ bool status_changed = false;
|
||||
|
||||
if (attrd_shutting_down(true)) {
|
||||
return;
|
||||
@@ -64,20 +65,22 @@ attrd_cib_updated_cb(const char *event, xmlNode *msg)
|
||||
mainloop_set_trigger(attrd_config_read);
|
||||
}
|
||||
|
||||
- if (!attrd_election_won()) {
|
||||
- // Don't write attributes if we're not the writer
|
||||
- return;
|
||||
- }
|
||||
+ status_changed = cib__element_in_patchset(patchset, XML_CIB_TAG_STATUS);
|
||||
|
||||
client_name = crm_element_value(msg, F_CIB_CLIENTNAME);
|
||||
if (!cib__client_triggers_refresh(client_name)) {
|
||||
- // The CIB is still accurate
|
||||
+ /* This change came from a source that ensured the CIB is consistent
|
||||
+ * with our attributes table, so we don't need to write anything out.
|
||||
+ */
|
||||
return;
|
||||
}
|
||||
|
||||
- if (cib__element_in_patchset(patchset, XML_CIB_TAG_NODES)
|
||||
- || cib__element_in_patchset(patchset, XML_CIB_TAG_STATUS)) {
|
||||
-
|
||||
+ if (!attrd_election_won()) {
|
||||
+ // Don't write attributes if we're not the writer
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (status_changed || cib__element_in_patchset(patchset, XML_CIB_TAG_NODES)) {
|
||||
/* An unsafe client modified the nodes or status section. Write
|
||||
* transient attributes to ensure they're up-to-date in the CIB.
|
||||
*/
|
||||
--
|
||||
2.31.1
|
||||
|
||||
From b83c2567fb450eec5b18882ded16403831d2c3c0 Mon Sep 17 00:00:00 2001
|
||||
From: Ken Gaillot <kgaillot@redhat.com>
|
||||
Date: Thu, 11 Jan 2024 17:53:55 -0600
|
||||
Subject: [PATCH 5/5] Log: pacemaker-attrd: make sure we don't try to log NULL
|
||||
|
||||
---
|
||||
daemons/attrd/attrd_corosync.c | 15 +++++++++++----
|
||||
1 file changed, 11 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/daemons/attrd/attrd_corosync.c b/daemons/attrd/attrd_corosync.c
|
||||
index 59e6a26..b348d52 100644
|
||||
--- a/daemons/attrd/attrd_corosync.c
|
||||
+++ b/daemons/attrd/attrd_corosync.c
|
||||
@@ -229,6 +229,11 @@ record_peer_nodeid(attribute_value_t *v, const char *host)
|
||||
}
|
||||
}
|
||||
|
||||
+#define readable_value(rv_v) pcmk__s((rv_v)->current, "(unset)")
|
||||
+
|
||||
+#define readable_peer(p) \
|
||||
+ (((p) == NULL)? "all peers" : pcmk__s((p)->uname, "unknown peer"))
|
||||
+
|
||||
static void
|
||||
update_attr_on_host(attribute_t *a, const crm_node_t *peer, const xmlNode *xml,
|
||||
const char *attr, const char *value, const char *host,
|
||||
@@ -262,14 +267,14 @@ update_attr_on_host(attribute_t *a, const crm_node_t *peer, const xmlNode *xml,
|
||||
pcmk__str_casei)) {
|
||||
|
||||
crm_notice("%s[%s]: local value '%s' takes priority over '%s' from %s",
|
||||
- attr, host, v->current, value, peer->uname);
|
||||
+ attr, host, readable_value(v), value, peer->uname);
|
||||
v = broadcast_local_value(a);
|
||||
|
||||
} else if (changed) {
|
||||
crm_notice("Setting %s[%s]%s%s: %s -> %s "
|
||||
CRM_XS " from %s with %s write delay",
|
||||
attr, host, a->set_type ? " in " : "",
|
||||
- pcmk__s(a->set_type, ""), pcmk__s(v->current, "(unset)"),
|
||||
+ pcmk__s(a->set_type, ""), readable_value(v),
|
||||
pcmk__s(value, "(unset)"), peer->uname,
|
||||
(a->timeout_ms == 0)? "no" : pcmk__readable_interval(a->timeout_ms));
|
||||
pcmk__str_update(&v->current, value);
|
||||
@@ -543,12 +548,14 @@ attrd_peer_sync(crm_node_t *peer)
|
||||
while (g_hash_table_iter_next(&aIter, NULL, (gpointer *) & a)) {
|
||||
g_hash_table_iter_init(&vIter, a->values);
|
||||
while (g_hash_table_iter_next(&vIter, NULL, (gpointer *) & v)) {
|
||||
- crm_debug("Syncing %s[%s] = %s to %s", a->id, v->nodename, v->current, peer?peer->uname:"everyone");
|
||||
+ crm_debug("Syncing %s[%s]='%s' to %s",
|
||||
+ a->id, v->nodename, readable_value(v),
|
||||
+ readable_peer(peer));
|
||||
attrd_add_value_xml(sync, a, v, false);
|
||||
}
|
||||
}
|
||||
|
||||
- crm_debug("Syncing values to %s", peer?peer->uname:"everyone");
|
||||
+ crm_debug("Syncing values to %s", readable_peer(peer));
|
||||
attrd_send_message(peer, sync, false);
|
||||
free_xml(sync);
|
||||
}
|
||||
--
|
||||
2.31.1
|
||||
|
|
@ -1,685 +0,0 @@
|
|||
From e01a1178fd8f5b99895683b3af9998e9485d12a4 Mon Sep 17 00:00:00 2001
|
||||
From: Ken Gaillot <kgaillot@redhat.com>
|
||||
Date: Fri, 24 Apr 2020 16:42:02 -0500
|
||||
Subject: [PATCH 1/3] Feature: controller: add new IPC API command for getting
|
||||
node list
|
||||
|
||||
This is based on and will replace the corresponding functionality in
|
||||
pacemakerd.
|
||||
---
|
||||
daemons/controld/controld_messages.c | 44 ++++++++++++++++++++++++++++--
|
||||
include/crm/common/ipc_controld.h | 13 +++++++++
|
||||
include/crm_internal.h | 1 +
|
||||
lib/common/ipc_controld.c | 53 ++++++++++++++++++++++++++++++++++++
|
||||
4 files changed, 109 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/daemons/controld/controld_messages.c b/daemons/controld/controld_messages.c
|
||||
index 0be04d0..423f006 100644
|
||||
--- a/daemons/controld/controld_messages.c
|
||||
+++ b/daemons/controld/controld_messages.c
|
||||
@@ -375,10 +375,11 @@ relay_message(xmlNode * msg, gboolean originated_locally)
|
||||
is_local = 0;
|
||||
|
||||
} else if (is_for_crm) {
|
||||
- if (safe_str_eq(task, CRM_OP_NODE_INFO)) {
|
||||
+ if (safe_str_eq(task, CRM_OP_NODE_INFO)
|
||||
+ || safe_str_eq(task, PCMK__CONTROLD_CMD_NODES)) {
|
||||
/* Node info requests do not specify a host, which is normally
|
||||
* treated as "all hosts", because the whole point is that the
|
||||
- * client doesn't know the local node name. Always handle these
|
||||
+ * client may not know the local node name. Always handle these
|
||||
* requests locally.
|
||||
*/
|
||||
is_local = 1;
|
||||
@@ -784,6 +785,42 @@ handle_ping(xmlNode *msg)
|
||||
}
|
||||
|
||||
/*!
|
||||
+ * \brief Handle a PCMK__CONTROLD_CMD_NODES message
|
||||
+ *
|
||||
+ * \return Next FSA input
|
||||
+ */
|
||||
+static enum crmd_fsa_input
|
||||
+handle_node_list(xmlNode *request)
|
||||
+{
|
||||
+ GHashTableIter iter;
|
||||
+ crm_node_t *node = NULL;
|
||||
+ xmlNode *reply = NULL;
|
||||
+ xmlNode *reply_data = NULL;
|
||||
+
|
||||
+ // Create message data for reply
|
||||
+ reply_data = create_xml_node(NULL, XML_CIB_TAG_NODES);
|
||||
+ g_hash_table_iter_init(&iter, crm_peer_cache);
|
||||
+ while (g_hash_table_iter_next(&iter, NULL, (gpointer *) & node)) {
|
||||
+ xmlNode *xml = create_xml_node(reply_data, XML_CIB_TAG_NODE);
|
||||
+
|
||||
+ crm_xml_add_ll(xml, XML_ATTR_ID, (long long) node->id); // uint32_t
|
||||
+ crm_xml_add(xml, XML_ATTR_UNAME, node->uname);
|
||||
+ crm_xml_add(xml, XML_NODE_IN_CLUSTER, node->state);
|
||||
+ }
|
||||
+
|
||||
+ // Create and send reply
|
||||
+ reply = create_reply(request, reply_data);
|
||||
+ free_xml(reply_data);
|
||||
+ if (reply) {
|
||||
+ (void) relay_message(reply, TRUE);
|
||||
+ free_xml(reply);
|
||||
+ }
|
||||
+
|
||||
+ // Nothing further to do
|
||||
+ return I_NULL;
|
||||
+}
|
||||
+
|
||||
+/*!
|
||||
* \brief Handle a CRM_OP_NODE_INFO request
|
||||
*
|
||||
* \param[in] msg Message XML
|
||||
@@ -1080,6 +1117,9 @@ handle_request(xmlNode *stored_msg, enum crmd_fsa_cause cause)
|
||||
|
||||
remote_ra_process_maintenance_nodes(xml);
|
||||
|
||||
+ } else if (strcmp(op, PCMK__CONTROLD_CMD_NODES) == 0) {
|
||||
+ return handle_node_list(stored_msg);
|
||||
+
|
||||
/*========== (NOT_DC)-Only Actions ==========*/
|
||||
} else if (!AM_I_DC) {
|
||||
|
||||
diff --git a/include/crm/common/ipc_controld.h b/include/crm/common/ipc_controld.h
|
||||
index 0ebabfc..b817357 100644
|
||||
--- a/include/crm/common/ipc_controld.h
|
||||
+++ b/include/crm/common/ipc_controld.h
|
||||
@@ -22,6 +22,7 @@ extern "C" {
|
||||
*/
|
||||
|
||||
#include <stdbool.h> // bool
|
||||
+#include <glib.h> // GList
|
||||
#include <libxml/tree.h> // xmlNode
|
||||
#include <crm/common/ipc.h> // pcmk_ipc_api_t
|
||||
|
||||
@@ -32,8 +33,16 @@ enum pcmk_controld_api_reply {
|
||||
pcmk_controld_reply_info,
|
||||
pcmk_controld_reply_resource,
|
||||
pcmk_controld_reply_ping,
|
||||
+ pcmk_controld_reply_nodes,
|
||||
};
|
||||
|
||||
+// Node information passed with pcmk_controld_reply_nodes
|
||||
+typedef struct {
|
||||
+ uint32_t id;
|
||||
+ const char *uname;
|
||||
+ const char *state;
|
||||
+} pcmk_controld_api_node_t;
|
||||
+
|
||||
/*!
|
||||
* Controller reply passed to event callback
|
||||
*
|
||||
@@ -72,6 +81,9 @@ typedef struct {
|
||||
const char *fsa_state;
|
||||
const char *result;
|
||||
} ping;
|
||||
+
|
||||
+ // pcmk_controld_reply_nodes
|
||||
+ GList *nodes; // list of pcmk_controld_api_node_t *
|
||||
} data;
|
||||
} pcmk_controld_api_reply_t;
|
||||
|
||||
@@ -88,6 +100,7 @@ int pcmk_controld_api_refresh(pcmk_ipc_api_t *api, const char *target_node,
|
||||
const char *provider, const char *type,
|
||||
bool cib_only);
|
||||
int pcmk_controld_api_ping(pcmk_ipc_api_t *api, const char *node_name);
|
||||
+int pcmk_controld_api_list_nodes(pcmk_ipc_api_t *api);
|
||||
int pcmk_controld_api_shutdown(pcmk_ipc_api_t *api, const char *node_name);
|
||||
int pcmk_controld_api_start_election(pcmk_ipc_api_t *api);
|
||||
unsigned int pcmk_controld_api_replies_expected(pcmk_ipc_api_t *api);
|
||||
diff --git a/include/crm_internal.h b/include/crm_internal.h
|
||||
index fd56fc6..cf8999f 100644
|
||||
--- a/include/crm_internal.h
|
||||
+++ b/include/crm_internal.h
|
||||
@@ -122,6 +122,7 @@ pid_t pcmk_locate_sbd(void);
|
||||
#define PCMK__ATTRD_CMD_SYNC_RESPONSE "sync-response"
|
||||
#define PCMK__ATTRD_CMD_CLEAR_FAILURE "clear-failure"
|
||||
|
||||
+#define PCMK__CONTROLD_CMD_NODES "list-nodes"
|
||||
|
||||
/*
|
||||
* Environment variables used by Pacemaker
|
||||
diff --git a/lib/common/ipc_controld.c b/lib/common/ipc_controld.c
|
||||
index 22bb733..a733dd3 100644
|
||||
--- a/lib/common/ipc_controld.c
|
||||
+++ b/lib/common/ipc_controld.c
|
||||
@@ -120,6 +120,28 @@ set_ping_data(pcmk_controld_api_reply_t *data, xmlNode *msg_data)
|
||||
data->data.ping.result = crm_element_value(msg_data, XML_PING_ATTR_STATUS);
|
||||
}
|
||||
|
||||
+static void
|
||||
+set_nodes_data(pcmk_controld_api_reply_t *data, xmlNode *msg_data)
|
||||
+{
|
||||
+ pcmk_controld_api_node_t *node_info;
|
||||
+
|
||||
+ data->reply_type = pcmk_controld_reply_nodes;
|
||||
+ for (xmlNode *node = first_named_child(msg_data, XML_CIB_TAG_NODE);
|
||||
+ node != NULL; node = crm_next_same_xml(node)) {
|
||||
+
|
||||
+ long long id_ll = 0;
|
||||
+
|
||||
+ node_info = calloc(1, sizeof(pcmk_controld_api_node_t));
|
||||
+ crm_element_value_ll(node, XML_ATTR_ID, &id_ll);
|
||||
+ if (id_ll > 0) {
|
||||
+ node_info->id = id_ll;
|
||||
+ }
|
||||
+ node_info->uname = crm_element_value(node, XML_ATTR_UNAME);
|
||||
+ node_info->state = crm_element_value(node, XML_NODE_IN_CLUSTER);
|
||||
+ data->data.nodes = g_list_prepend(data->data.nodes, node_info);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static bool
|
||||
reply_expected(pcmk_ipc_api_t *api, xmlNode *request)
|
||||
{
|
||||
@@ -201,6 +223,9 @@ dispatch(pcmk_ipc_api_t *api, xmlNode *reply)
|
||||
} else if (!strcmp(value, CRM_OP_PING)) {
|
||||
set_ping_data(&reply_data, msg_data);
|
||||
|
||||
+ } else if (!strcmp(value, PCMK__CONTROLD_CMD_NODES)) {
|
||||
+ set_nodes_data(&reply_data, msg_data);
|
||||
+
|
||||
} else {
|
||||
crm_debug("Unrecognizable controller message: unknown command '%s'",
|
||||
value);
|
||||
@@ -210,6 +235,11 @@ dispatch(pcmk_ipc_api_t *api, xmlNode *reply)
|
||||
}
|
||||
|
||||
pcmk__call_ipc_callback(api, pcmk_ipc_event_reply, status, &reply_data);
|
||||
+
|
||||
+ // Free any reply data that was allocated
|
||||
+ if (safe_str_eq(value, PCMK__CONTROLD_CMD_NODES)) {
|
||||
+ g_list_free_full(reply_data.data.nodes, free);
|
||||
+ }
|
||||
}
|
||||
|
||||
pcmk__ipc_methods_t *
|
||||
@@ -376,6 +406,29 @@ pcmk_controld_api_ping(pcmk_ipc_api_t *api, const char *node_name)
|
||||
}
|
||||
|
||||
/*!
|
||||
+ * \brief Ask the controller for cluster information
|
||||
+ *
|
||||
+ * \param[in] api Controller connection
|
||||
+ *
|
||||
+ * \return Standard Pacemaker return code
|
||||
+ * \note Event callback will get a reply of type pcmk_controld_reply_nodes.
|
||||
+ */
|
||||
+int
|
||||
+pcmk_controld_api_list_nodes(pcmk_ipc_api_t *api)
|
||||
+{
|
||||
+ xmlNode *request;
|
||||
+ int rc = EINVAL;
|
||||
+
|
||||
+ request = create_controller_request(api, PCMK__CONTROLD_CMD_NODES, NULL,
|
||||
+ NULL);
|
||||
+ if (request != NULL) {
|
||||
+ rc = send_controller_request(api, request, true);
|
||||
+ free_xml(request);
|
||||
+ }
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+/*!
|
||||
* \internal
|
||||
* \brief Ask the controller to shut down
|
||||
*
|
||||
--
|
||||
1.8.3.1
|
||||
|
||||
|
||||
From 74e2d8d18bf534c1ec6f0e0f44a90772d393a553 Mon Sep 17 00:00:00 2001
|
||||
From: Ken Gaillot <kgaillot@redhat.com>
|
||||
Date: Thu, 2 Jul 2020 11:51:56 -0500
|
||||
Subject: [PATCH 2/3] Refactor: functionize numeric comparisons of strings
|
||||
|
||||
This moves the guts of sort_node_uname() from libpe_status to a new function,
|
||||
pcmk_numeric_strcasecmp(), in libcrmcommon, so it can be used with strings and
|
||||
not just pe_node_t objects.
|
||||
---
|
||||
include/crm/common/util.h | 1 +
|
||||
lib/common/strings.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++
|
||||
lib/pengine/utils.c | 50 ++----------------------------------
|
||||
3 files changed, 68 insertions(+), 48 deletions(-)
|
||||
|
||||
diff --git a/include/crm/common/util.h b/include/crm/common/util.h
|
||||
index 67d74d2..bb97b0a 100644
|
||||
--- a/include/crm/common/util.h
|
||||
+++ b/include/crm/common/util.h
|
||||
@@ -59,6 +59,7 @@ gboolean crm_strcase_equal(gconstpointer a, gconstpointer b);
|
||||
char *crm_strdup_printf(char const *format, ...) __attribute__ ((__format__ (__printf__, 1, 2)));
|
||||
int pcmk__parse_ll_range(const char *srcstring, long long *start, long long *end);
|
||||
gboolean pcmk__str_in_list(GList *lst, const gchar *s);
|
||||
+int pcmk_numeric_strcasecmp(const char *s1, const char *s2);
|
||||
|
||||
# define safe_str_eq(a, b) crm_str_eq(a, b, FALSE)
|
||||
# define crm_str_hash g_str_hash_traditional
|
||||
diff --git a/lib/common/strings.c b/lib/common/strings.c
|
||||
index 4562738..bd68ccf 100644
|
||||
--- a/lib/common/strings.c
|
||||
+++ b/lib/common/strings.c
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
+#include <ctype.h>
|
||||
#include <limits.h>
|
||||
#include <bzlib.h>
|
||||
#include <sys/types.h>
|
||||
@@ -715,3 +716,67 @@ pcmk__str_none_of(const char *s, ...)
|
||||
|
||||
return g_list_find_custom(lst, s, (GCompareFunc) strcmp) != NULL;
|
||||
}
|
||||
+
|
||||
+/*
|
||||
+ * \brief Sort strings, with numeric portions sorted numerically
|
||||
+ *
|
||||
+ * Sort two strings case-insensitively like strcasecmp(), but with any numeric
|
||||
+ * portions of the string sorted numerically. This is particularly useful for
|
||||
+ * node names (for example, "node10" will sort higher than "node9" but lower
|
||||
+ * than "remotenode9").
|
||||
+ *
|
||||
+ * \param[in] s1 First string to compare (must not be NULL)
|
||||
+ * \param[in] s2 Second string to compare (must not be NULL)
|
||||
+ *
|
||||
+ * \retval -1 \p s1 comes before \p s2
|
||||
+ * \retval 0 \p s1 and \p s2 are equal
|
||||
+ * \retval 1 \p s1 comes after \p s2
|
||||
+ */
|
||||
+int
|
||||
+pcmk_numeric_strcasecmp(const char *s1, const char *s2)
|
||||
+{
|
||||
+ while (*s1 && *s2) {
|
||||
+ if (isdigit(*s1) && isdigit(*s2)) {
|
||||
+ // If node names contain a number, sort numerically
|
||||
+
|
||||
+ char *end1 = NULL;
|
||||
+ char *end2 = NULL;
|
||||
+ long num1 = strtol(s1, &end1, 10);
|
||||
+ long num2 = strtol(s2, &end2, 10);
|
||||
+
|
||||
+ // allow ordering e.g. 007 > 7
|
||||
+ size_t len1 = end1 - s1;
|
||||
+ size_t len2 = end2 - s2;
|
||||
+
|
||||
+ if (num1 < num2) {
|
||||
+ return -1;
|
||||
+ } else if (num1 > num2) {
|
||||
+ return 1;
|
||||
+ } else if (len1 < len2) {
|
||||
+ return -1;
|
||||
+ } else if (len1 > len2) {
|
||||
+ return 1;
|
||||
+ }
|
||||
+ s1 = end1;
|
||||
+ s2 = end2;
|
||||
+ } else {
|
||||
+ // Compare non-digits case-insensitively
|
||||
+ int lower1 = tolower(*s1);
|
||||
+ int lower2 = tolower(*s2);
|
||||
+
|
||||
+ if (lower1 < lower2) {
|
||||
+ return -1;
|
||||
+ } else if (lower1 > lower2) {
|
||||
+ return 1;
|
||||
+ }
|
||||
+ ++s1;
|
||||
+ ++s2;
|
||||
+ }
|
||||
+ }
|
||||
+ if (!*s1 && *s2) {
|
||||
+ return -1;
|
||||
+ } else if (*s1 && !*s2) {
|
||||
+ return 1;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
diff --git a/lib/pengine/utils.c b/lib/pengine/utils.c
|
||||
index ce3c260..584def4 100644
|
||||
--- a/lib/pengine/utils.c
|
||||
+++ b/lib/pengine/utils.c
|
||||
@@ -13,7 +13,6 @@
|
||||
#include <crm/common/xml.h>
|
||||
#include <crm/common/util.h>
|
||||
|
||||
-#include <ctype.h>
|
||||
#include <glib.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
@@ -214,53 +213,8 @@ pe__node_list2table(GList *list)
|
||||
gint
|
||||
sort_node_uname(gconstpointer a, gconstpointer b)
|
||||
{
|
||||
- const char *name_a = ((const pe_node_t *) a)->details->uname;
|
||||
- const char *name_b = ((const pe_node_t *) b)->details->uname;
|
||||
-
|
||||
- while (*name_a && *name_b) {
|
||||
- if (isdigit(*name_a) && isdigit(*name_b)) {
|
||||
- // If node names contain a number, sort numerically
|
||||
-
|
||||
- char *end_a = NULL;
|
||||
- char *end_b = NULL;
|
||||
- long num_a = strtol(name_a, &end_a, 10);
|
||||
- long num_b = strtol(name_b, &end_b, 10);
|
||||
-
|
||||
- // allow ordering e.g. 007 > 7
|
||||
- size_t len_a = end_a - name_a;
|
||||
- size_t len_b = end_b - name_b;
|
||||
-
|
||||
- if (num_a < num_b) {
|
||||
- return -1;
|
||||
- } else if (num_a > num_b) {
|
||||
- return 1;
|
||||
- } else if (len_a < len_b) {
|
||||
- return -1;
|
||||
- } else if (len_a > len_b) {
|
||||
- return 1;
|
||||
- }
|
||||
- name_a = end_a;
|
||||
- name_b = end_b;
|
||||
- } else {
|
||||
- // Compare non-digits case-insensitively
|
||||
- int lower_a = tolower(*name_a);
|
||||
- int lower_b = tolower(*name_b);
|
||||
-
|
||||
- if (lower_a < lower_b) {
|
||||
- return -1;
|
||||
- } else if (lower_a > lower_b) {
|
||||
- return 1;
|
||||
- }
|
||||
- ++name_a;
|
||||
- ++name_b;
|
||||
- }
|
||||
- }
|
||||
- if (!*name_a && *name_b) {
|
||||
- return -1;
|
||||
- } else if (*name_a && !*name_b) {
|
||||
- return 1;
|
||||
- }
|
||||
- return 0;
|
||||
+ return pcmk_numeric_strcasecmp(((const pe_node_t *) a)->details->uname,
|
||||
+ ((const pe_node_t *) b)->details->uname);
|
||||
}
|
||||
|
||||
/*!
|
||||
--
|
||||
1.8.3.1
|
||||
|
||||
|
||||
From 8461509158e06365122dc741c527c83c94e966ce Mon Sep 17 00:00:00 2001
|
||||
From: Ken Gaillot <kgaillot@redhat.com>
|
||||
Date: Fri, 24 Apr 2020 19:35:19 -0500
|
||||
Subject: [PATCH 3/3] Fix: tools: crm_node -l and -p now work from Pacemaker
|
||||
Remote nodes
|
||||
|
||||
crm_node now asks the controller for the cluster node list, instead of
|
||||
pacemakerd. This allows it to work from Pacemaker Remote nodes, since
|
||||
controller IPC is proxied but pacemakerd IPC is not.
|
||||
---
|
||||
tools/crm_node.c | 176 +++++++++++++++++++++----------------------------------
|
||||
1 file changed, 67 insertions(+), 109 deletions(-)
|
||||
|
||||
diff --git a/tools/crm_node.c b/tools/crm_node.c
|
||||
index 57c2ee5..146454d 100644
|
||||
--- a/tools/crm_node.c
|
||||
+++ b/tools/crm_node.c
|
||||
@@ -130,6 +130,16 @@ remove_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError *
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
+static gint
|
||||
+sort_node(gconstpointer a, gconstpointer b)
|
||||
+{
|
||||
+ const pcmk_controld_api_node_t *node_a = a;
|
||||
+ const pcmk_controld_api_node_t *node_b = b;
|
||||
+
|
||||
+ return pcmk_numeric_strcasecmp((node_a->uname? node_a->uname : ""),
|
||||
+ (node_b->uname? node_b->uname : ""));
|
||||
+}
|
||||
+
|
||||
static void
|
||||
controller_event_cb(pcmk_ipc_api_t *controld_api,
|
||||
enum pcmk_ipc_event event_type, crm_exit_t status,
|
||||
@@ -157,15 +167,16 @@ controller_event_cb(pcmk_ipc_api_t *controld_api,
|
||||
crm_exit_str(status));
|
||||
goto done;
|
||||
}
|
||||
- if (reply->reply_type != pcmk_controld_reply_info) {
|
||||
- fprintf(stderr, "error: Unknown reply type %d from controller\n",
|
||||
- reply->reply_type);
|
||||
- goto done;
|
||||
- }
|
||||
|
||||
// Parse desired info from reply and display to user
|
||||
switch (options.command) {
|
||||
case 'i':
|
||||
+ if (reply->reply_type != pcmk_controld_reply_info) {
|
||||
+ fprintf(stderr,
|
||||
+ "error: Unknown reply type %d from controller\n",
|
||||
+ reply->reply_type);
|
||||
+ goto done;
|
||||
+ }
|
||||
if (reply->data.node_info.id == 0) {
|
||||
fprintf(stderr,
|
||||
"error: Controller reply did not contain node ID\n");
|
||||
@@ -177,6 +188,12 @@ controller_event_cb(pcmk_ipc_api_t *controld_api,
|
||||
|
||||
case 'n':
|
||||
case 'N':
|
||||
+ if (reply->reply_type != pcmk_controld_reply_info) {
|
||||
+ fprintf(stderr,
|
||||
+ "error: Unknown reply type %d from controller\n",
|
||||
+ reply->reply_type);
|
||||
+ goto done;
|
||||
+ }
|
||||
if (reply->data.node_info.uname == NULL) {
|
||||
fprintf(stderr, "Node is not known to cluster\n");
|
||||
exit_code = CRM_EX_NOHOST;
|
||||
@@ -186,6 +203,12 @@ controller_event_cb(pcmk_ipc_api_t *controld_api,
|
||||
break;
|
||||
|
||||
case 'q':
|
||||
+ if (reply->reply_type != pcmk_controld_reply_info) {
|
||||
+ fprintf(stderr,
|
||||
+ "error: Unknown reply type %d from controller\n",
|
||||
+ reply->reply_type);
|
||||
+ goto done;
|
||||
+ }
|
||||
printf("%d\n", reply->data.node_info.have_quorum);
|
||||
if (!(reply->data.node_info.have_quorum)) {
|
||||
exit_code = CRM_EX_QUORUM;
|
||||
@@ -193,6 +216,36 @@ controller_event_cb(pcmk_ipc_api_t *controld_api,
|
||||
}
|
||||
break;
|
||||
|
||||
+ case 'l':
|
||||
+ case 'p':
|
||||
+ if (reply->reply_type != pcmk_controld_reply_nodes) {
|
||||
+ fprintf(stderr,
|
||||
+ "error: Unknown reply type %d from controller\n",
|
||||
+ reply->reply_type);
|
||||
+ goto done;
|
||||
+ }
|
||||
+ reply->data.nodes = g_list_sort(reply->data.nodes, sort_node);
|
||||
+ for (GList *node_iter = reply->data.nodes;
|
||||
+ node_iter != NULL; node_iter = node_iter->next) {
|
||||
+
|
||||
+ pcmk_controld_api_node_t *node = node_iter->data;
|
||||
+ const char *uname = (node->uname? node->uname : "");
|
||||
+ const char *state = (node->state? node->state : "");
|
||||
+
|
||||
+ if (options.command == 'l') {
|
||||
+ printf("%lu %s %s\n",
|
||||
+ (unsigned long) node->id, uname, state);
|
||||
+
|
||||
+ // i.e. CRM_NODE_MEMBER, but we don't want to include cluster.h
|
||||
+ } else if (!strcmp(state, "member")) {
|
||||
+ printf("%s ", uname);
|
||||
+ }
|
||||
+ }
|
||||
+ if (options.command == 'p') {
|
||||
+ printf("\n");
|
||||
+ }
|
||||
+ break;
|
||||
+
|
||||
default:
|
||||
fprintf(stderr, "internal error: Controller reply not expected\n");
|
||||
exit_code = CRM_EX_SOFTWARE;
|
||||
@@ -207,7 +260,7 @@ done:
|
||||
}
|
||||
|
||||
static void
|
||||
-run_controller_mainloop(uint32_t nodeid)
|
||||
+run_controller_mainloop(uint32_t nodeid, bool list_nodes)
|
||||
{
|
||||
pcmk_ipc_api_t *controld_api = NULL;
|
||||
int rc;
|
||||
@@ -233,7 +286,11 @@ run_controller_mainloop(uint32_t nodeid)
|
||||
return;
|
||||
}
|
||||
|
||||
- rc = pcmk_controld_api_node_info(controld_api, nodeid);
|
||||
+ if (list_nodes) {
|
||||
+ rc = pcmk_controld_api_list_nodes(controld_api);
|
||||
+ } else {
|
||||
+ rc = pcmk_controld_api_node_info(controld_api, nodeid);
|
||||
+ }
|
||||
if (rc != pcmk_rc_ok) {
|
||||
fprintf(stderr, "error: Could not ping controller: %s\n",
|
||||
pcmk_rc_str(rc));
|
||||
@@ -263,7 +320,7 @@ print_node_name(void)
|
||||
|
||||
} else {
|
||||
// Otherwise ask the controller
|
||||
- run_controller_mainloop(0);
|
||||
+ run_controller_mainloop(0, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -444,105 +501,6 @@ remove_node(const char *target_uname)
|
||||
exit_code = CRM_EX_OK;
|
||||
}
|
||||
|
||||
-static gint
|
||||
-compare_node_xml(gconstpointer a, gconstpointer b)
|
||||
-{
|
||||
- const char *a_name = crm_element_value((xmlNode*) a, "uname");
|
||||
- const char *b_name = crm_element_value((xmlNode*) b, "uname");
|
||||
-
|
||||
- return strcmp((a_name? a_name : ""), (b_name? b_name : ""));
|
||||
-}
|
||||
-
|
||||
-static int
|
||||
-node_mcp_dispatch(const char *buffer, ssize_t length, gpointer userdata)
|
||||
-{
|
||||
- GList *nodes = NULL;
|
||||
- xmlNode *node = NULL;
|
||||
- xmlNode *msg = string2xml(buffer);
|
||||
- const char *uname;
|
||||
- const char *state;
|
||||
-
|
||||
- if (msg == NULL) {
|
||||
- fprintf(stderr, "error: Could not understand pacemakerd response\n");
|
||||
- exit_code = CRM_EX_PROTOCOL;
|
||||
- g_main_loop_quit(mainloop);
|
||||
- return 0;
|
||||
- }
|
||||
-
|
||||
- crm_log_xml_trace(msg, "message");
|
||||
-
|
||||
- for (node = __xml_first_child(msg); node != NULL; node = __xml_next(node)) {
|
||||
- nodes = g_list_insert_sorted(nodes, node, compare_node_xml);
|
||||
- }
|
||||
-
|
||||
- for (GList *iter = nodes; iter; iter = iter->next) {
|
||||
- node = (xmlNode*) iter->data;
|
||||
- uname = crm_element_value(node, "uname");
|
||||
- state = crm_element_value(node, "state");
|
||||
-
|
||||
- if (options.command == 'l') {
|
||||
- int id = 0;
|
||||
-
|
||||
- crm_element_value_int(node, "id", &id);
|
||||
- printf("%d %s %s\n", id, (uname? uname : ""), (state? state : ""));
|
||||
-
|
||||
- // This is CRM_NODE_MEMBER but we don't want to include cluster header
|
||||
- } else if ((options.command == 'p') && safe_str_eq(state, "member")) {
|
||||
- printf("%s ", (uname? uname : ""));
|
||||
- }
|
||||
- }
|
||||
- if (options.command == 'p') {
|
||||
- fprintf(stdout, "\n");
|
||||
- }
|
||||
-
|
||||
- free_xml(msg);
|
||||
- exit_code = CRM_EX_OK;
|
||||
- g_main_loop_quit(mainloop);
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-static void
|
||||
-lost_pacemakerd(gpointer user_data)
|
||||
-{
|
||||
- fprintf(stderr, "error: Lost connection to cluster\n");
|
||||
- exit_code = CRM_EX_DISCONNECT;
|
||||
- g_main_loop_quit(mainloop);
|
||||
-}
|
||||
-
|
||||
-static void
|
||||
-run_pacemakerd_mainloop(void)
|
||||
-{
|
||||
- crm_ipc_t *ipc = NULL;
|
||||
- xmlNode *poke = NULL;
|
||||
- mainloop_io_t *source = NULL;
|
||||
-
|
||||
- struct ipc_client_callbacks ipc_callbacks = {
|
||||
- .dispatch = node_mcp_dispatch,
|
||||
- .destroy = lost_pacemakerd
|
||||
- };
|
||||
-
|
||||
- source = mainloop_add_ipc_client(CRM_SYSTEM_MCP, G_PRIORITY_DEFAULT, 0,
|
||||
- NULL, &ipc_callbacks);
|
||||
- ipc = mainloop_get_ipc_client(source);
|
||||
- if (ipc == NULL) {
|
||||
- fprintf(stderr,
|
||||
- "error: Could not connect to cluster (is it running?)\n");
|
||||
- exit_code = CRM_EX_DISCONNECT;
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
- // Sending anything will get us a list of nodes
|
||||
- poke = create_xml_node(NULL, "poke");
|
||||
- crm_ipc_send(ipc, poke, 0, 0, NULL);
|
||||
- free_xml(poke);
|
||||
-
|
||||
- // Handle reply via node_mcp_dispatch()
|
||||
- mainloop = g_main_loop_new(NULL, FALSE);
|
||||
- g_main_loop_run(mainloop);
|
||||
- g_main_loop_unref(mainloop);
|
||||
- mainloop = NULL;
|
||||
-}
|
||||
-
|
||||
static GOptionContext *
|
||||
build_arg_context(pcmk__common_args_t *args, GOptionGroup *group) {
|
||||
GOptionContext *context = NULL;
|
||||
@@ -627,11 +585,11 @@ main(int argc, char **argv)
|
||||
case 'i':
|
||||
case 'q':
|
||||
case 'N':
|
||||
- run_controller_mainloop(options.nodeid);
|
||||
+ run_controller_mainloop(options.nodeid, false);
|
||||
break;
|
||||
case 'l':
|
||||
case 'p':
|
||||
- run_pacemakerd_mainloop();
|
||||
+ run_controller_mainloop(0, true);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
--
|
||||
1.8.3.1
|
||||
|
|
@ -0,0 +1,385 @@
|
|||
From 84d4a0d5f562df91baa0fece45d06ad3732f941c Mon Sep 17 00:00:00 2001
|
||||
From: Ken Gaillot <kgaillot@redhat.com>
|
||||
Date: Tue, 16 Jan 2024 11:20:53 -0600
|
||||
Subject: [PATCH 1/5] Low: pacemaker-attrd: properly validate attribute set
|
||||
type
|
||||
|
||||
The sense of the test was accidentally reversed in 26471a52689
|
||||
---
|
||||
daemons/attrd/attrd_attributes.c | 6 +++---
|
||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/daemons/attrd/attrd_attributes.c b/daemons/attrd/attrd_attributes.c
|
||||
index 8f32988..f059059 100644
|
||||
--- a/daemons/attrd/attrd_attributes.c
|
||||
+++ b/daemons/attrd/attrd_attributes.c
|
||||
@@ -40,9 +40,9 @@ attrd_create_attribute(xmlNode *xml)
|
||||
* attributes are not written.
|
||||
*/
|
||||
crm_element_value_int(xml, PCMK__XA_ATTR_IS_PRIVATE, &is_private);
|
||||
- if ((is_private != 0)
|
||||
- && !pcmk__str_any_of(set_type, XML_TAG_ATTR_SETS, XML_TAG_UTILIZATION,
|
||||
- NULL)) {
|
||||
+ if (!is_private && !pcmk__str_any_of(set_type,
|
||||
+ XML_TAG_ATTR_SETS,
|
||||
+ XML_TAG_UTILIZATION, NULL)) {
|
||||
crm_warn("Ignoring attribute %s with invalid set type %s",
|
||||
pcmk__s(name, "(unidentified)"), set_type);
|
||||
return NULL;
|
||||
--
|
||||
2.31.1
|
||||
|
||||
From d0d0511e71fe983a2d89589c39810b79fb48a8ca Mon Sep 17 00:00:00 2001
|
||||
From: Ken Gaillot <kgaillot@redhat.com>
|
||||
Date: Tue, 16 Jan 2024 12:13:42 -0600
|
||||
Subject: [PATCH 2/5] Fix: pacemaker-attrd: sync utilization attributes to
|
||||
peers correctly
|
||||
|
||||
Include the set type with attribute syncs.
|
||||
|
||||
Previously, utilization attributes would have the correct set_type on the node
|
||||
where they were set, but peers would store it as a regular node attribute. If
|
||||
one of those peers became writer, the attribute would get written to the wrong
|
||||
set.
|
||||
---
|
||||
daemons/attrd/attrd_attributes.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/daemons/attrd/attrd_attributes.c b/daemons/attrd/attrd_attributes.c
|
||||
index f059059..0ad9630 100644
|
||||
--- a/daemons/attrd/attrd_attributes.c
|
||||
+++ b/daemons/attrd/attrd_attributes.c
|
||||
@@ -139,6 +139,7 @@ attrd_add_value_xml(xmlNode *parent, const attribute_t *a,
|
||||
xmlNode *xml = create_xml_node(parent, __func__);
|
||||
|
||||
crm_xml_add(xml, PCMK__XA_ATTR_NAME, a->id);
|
||||
+ crm_xml_add(xml, PCMK__XA_ATTR_SET_TYPE, a->set_type);
|
||||
crm_xml_add(xml, PCMK__XA_ATTR_SET, a->set_id);
|
||||
crm_xml_add(xml, PCMK__XA_ATTR_UUID, a->uuid);
|
||||
crm_xml_add(xml, PCMK__XA_ATTR_USER, a->user);
|
||||
--
|
||||
2.31.1
|
||||
|
||||
From 4479ff8507dd69f5946d31cf83c7e47fe15d3bdb Mon Sep 17 00:00:00 2001
|
||||
From: Ken Gaillot <kgaillot@redhat.com>
|
||||
Date: Tue, 16 Jan 2024 12:18:40 -0600
|
||||
Subject: [PATCH 3/5] Refactor: pacemaker-attrd: functionize getting attribute
|
||||
set ID
|
||||
|
||||
... for future reuse
|
||||
---
|
||||
daemons/attrd/attrd_attributes.c | 38 ++++++++++++++++++++++++++++++++
|
||||
daemons/attrd/attrd_cib.c | 9 +-------
|
||||
daemons/attrd/pacemaker-attrd.h | 3 ++-
|
||||
3 files changed, 41 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/daemons/attrd/attrd_attributes.c b/daemons/attrd/attrd_attributes.c
|
||||
index 0ad9630..5727ab8 100644
|
||||
--- a/daemons/attrd/attrd_attributes.c
|
||||
+++ b/daemons/attrd/attrd_attributes.c
|
||||
@@ -210,3 +210,41 @@ attrd_populate_attribute(xmlNode *xml, const char *attr)
|
||||
|
||||
return a;
|
||||
}
|
||||
+
|
||||
+/*!
|
||||
+ * \internal
|
||||
+ * \brief Get the XML ID used to write out an attribute set
|
||||
+ *
|
||||
+ * \param[in] attr Attribute to get set ID for
|
||||
+ * \param[in] node_state_id XML ID of node state that attribute value is for
|
||||
+ *
|
||||
+ * \return Newly allocated string with XML ID to use for \p attr set
|
||||
+ */
|
||||
+char *
|
||||
+attrd_set_id(const attribute_t *attr, const char *node_state_id)
|
||||
+{
|
||||
+ char *set_id = NULL;
|
||||
+
|
||||
+ CRM_ASSERT((attr != NULL) && (node_state_id != NULL));
|
||||
+
|
||||
+ if (attr->set_id == NULL) {
|
||||
+ /* @COMPAT This should really take the set type into account. Currently
|
||||
+ * we use the same XML ID for transient attributes and utilization
|
||||
+ * attributes. It doesn't cause problems because the status section is
|
||||
+ * not limited by the schema in any way, but it's still unfortunate.
|
||||
+ * For backward compatibility reasons, we can't change this.
|
||||
+ */
|
||||
+ set_id = crm_strdup_printf("%s-%s", XML_CIB_TAG_STATUS, node_state_id);
|
||||
+ } else {
|
||||
+ /* @COMPAT When the user specifies a set ID for an attribute, it is the
|
||||
+ * same for every node. That is less than ideal, but again, the schema
|
||||
+ * doesn't enforce anything for the status section. We couldn't change
|
||||
+ * it without allowing the set ID to vary per value rather than per
|
||||
+ * attribute, which would break backward compatibility, pose design
|
||||
+ * challenges, and potentially cause problems in rolling upgrades.
|
||||
+ */
|
||||
+ pcmk__str_update(&set_id, attr->set_id);
|
||||
+ }
|
||||
+ crm_xml_sanitize_id(set_id);
|
||||
+ return set_id;
|
||||
+}
|
||||
diff --git a/daemons/attrd/attrd_cib.c b/daemons/attrd/attrd_cib.c
|
||||
index 481fea7..08d3425 100644
|
||||
--- a/daemons/attrd/attrd_cib.c
|
||||
+++ b/daemons/attrd/attrd_cib.c
|
||||
@@ -423,17 +423,10 @@ add_unset_attr_update(const attribute_t *attr, const char *attr_id,
|
||||
static int
|
||||
add_attr_update(const attribute_t *attr, const char *value, const char *node_id)
|
||||
{
|
||||
- char *set_id = NULL;
|
||||
+ char *set_id = attrd_set_id(attr, node_id);
|
||||
char *attr_id = NULL;
|
||||
int rc = pcmk_rc_ok;
|
||||
|
||||
- if (attr->set_id != NULL) {
|
||||
- pcmk__str_update(&set_id, attr->set_id);
|
||||
- } else {
|
||||
- set_id = crm_strdup_printf("%s-%s", XML_CIB_TAG_STATUS, node_id);
|
||||
- }
|
||||
- crm_xml_sanitize_id(set_id);
|
||||
-
|
||||
if (attr->uuid != NULL) {
|
||||
pcmk__str_update(&attr_id, attr->uuid);
|
||||
} else {
|
||||
diff --git a/daemons/attrd/pacemaker-attrd.h b/daemons/attrd/pacemaker-attrd.h
|
||||
index bacaad6..3da7f8d 100644
|
||||
--- a/daemons/attrd/pacemaker-attrd.h
|
||||
+++ b/daemons/attrd/pacemaker-attrd.h
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
- * Copyright 2013-2023 the Pacemaker project contributors
|
||||
+ * Copyright 2013-2024 the Pacemaker project contributors
|
||||
*
|
||||
* The version control history for this file may have further details.
|
||||
*
|
||||
@@ -195,6 +195,7 @@ void attrd_clear_value_seen(void);
|
||||
void attrd_free_attribute(gpointer data);
|
||||
void attrd_free_attribute_value(gpointer data);
|
||||
attribute_t *attrd_populate_attribute(xmlNode *xml, const char *attr);
|
||||
+char *attrd_set_id(const attribute_t *attr, const char *node_state_id);
|
||||
|
||||
enum attrd_write_options {
|
||||
attrd_write_changed = 0,
|
||||
--
|
||||
2.31.1
|
||||
|
||||
From eee2169ac348b8ed26ac0b78cb11ddc5cef9384e Mon Sep 17 00:00:00 2001
|
||||
From: Ken Gaillot <kgaillot@redhat.com>
|
||||
Date: Tue, 16 Jan 2024 12:25:59 -0600
|
||||
Subject: [PATCH 4/5] Refactor: pacemaker-attrd: functionize getting attribute
|
||||
nvpair ID
|
||||
|
||||
... for future reuse
|
||||
---
|
||||
daemons/attrd/attrd_attributes.c | 28 ++++++++++++++++++++++++++++
|
||||
daemons/attrd/attrd_cib.c | 17 +++++------------
|
||||
daemons/attrd/pacemaker-attrd.h | 1 +
|
||||
3 files changed, 34 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/daemons/attrd/attrd_attributes.c b/daemons/attrd/attrd_attributes.c
|
||||
index 5727ab8..23de2e2 100644
|
||||
--- a/daemons/attrd/attrd_attributes.c
|
||||
+++ b/daemons/attrd/attrd_attributes.c
|
||||
@@ -248,3 +248,31 @@ attrd_set_id(const attribute_t *attr, const char *node_state_id)
|
||||
crm_xml_sanitize_id(set_id);
|
||||
return set_id;
|
||||
}
|
||||
+
|
||||
+/*!
|
||||
+ * \internal
|
||||
+ * \brief Get the XML ID used to write out an attribute value
|
||||
+ *
|
||||
+ * \param[in] attr Attribute to get value XML ID for
|
||||
+ * \param[in] node_state_id UUID of node that attribute value is for
|
||||
+ *
|
||||
+ * \return Newly allocated string with XML ID of \p attr value
|
||||
+ */
|
||||
+char *
|
||||
+attrd_nvpair_id(const attribute_t *attr, const char *node_state_id)
|
||||
+{
|
||||
+ char *nvpair_id = NULL;
|
||||
+
|
||||
+ if (attr->uuid != NULL) {
|
||||
+ pcmk__str_update(&nvpair_id, attr->uuid);
|
||||
+
|
||||
+ } else if (attr->set_id != NULL) {
|
||||
+ nvpair_id = crm_strdup_printf("%s-%s", attr->set_id, attr->id);
|
||||
+
|
||||
+ } else {
|
||||
+ nvpair_id = crm_strdup_printf(XML_CIB_TAG_STATUS "-%s-%s",
|
||||
+ node_state_id, attr->id);
|
||||
+ }
|
||||
+ crm_xml_sanitize_id(nvpair_id);
|
||||
+ return nvpair_id;
|
||||
+}
|
||||
diff --git a/daemons/attrd/attrd_cib.c b/daemons/attrd/attrd_cib.c
|
||||
index 08d3425..d42345f 100644
|
||||
--- a/daemons/attrd/attrd_cib.c
|
||||
+++ b/daemons/attrd/attrd_cib.c
|
||||
@@ -424,23 +424,16 @@ static int
|
||||
add_attr_update(const attribute_t *attr, const char *value, const char *node_id)
|
||||
{
|
||||
char *set_id = attrd_set_id(attr, node_id);
|
||||
- char *attr_id = NULL;
|
||||
+ char *nvpair_id = attrd_nvpair_id(attr, node_id);
|
||||
int rc = pcmk_rc_ok;
|
||||
|
||||
- if (attr->uuid != NULL) {
|
||||
- pcmk__str_update(&attr_id, attr->uuid);
|
||||
+ if (value == NULL) {
|
||||
+ rc = add_unset_attr_update(attr, nvpair_id, node_id, set_id);
|
||||
} else {
|
||||
- attr_id = crm_strdup_printf("%s-%s", set_id, attr->id);
|
||||
- }
|
||||
- crm_xml_sanitize_id(attr_id);
|
||||
-
|
||||
- if (value != NULL) {
|
||||
- rc = add_set_attr_update(attr, attr_id, node_id, set_id, value);
|
||||
- } else {
|
||||
- rc = add_unset_attr_update(attr, attr_id, node_id, set_id);
|
||||
+ rc = add_set_attr_update(attr, nvpair_id, node_id, set_id, value);
|
||||
}
|
||||
free(set_id);
|
||||
- free(attr_id);
|
||||
+ free(nvpair_id);
|
||||
return rc;
|
||||
}
|
||||
|
||||
diff --git a/daemons/attrd/pacemaker-attrd.h b/daemons/attrd/pacemaker-attrd.h
|
||||
index 3da7f8d..deec790 100644
|
||||
--- a/daemons/attrd/pacemaker-attrd.h
|
||||
+++ b/daemons/attrd/pacemaker-attrd.h
|
||||
@@ -196,6 +196,7 @@ void attrd_free_attribute(gpointer data);
|
||||
void attrd_free_attribute_value(gpointer data);
|
||||
attribute_t *attrd_populate_attribute(xmlNode *xml, const char *attr);
|
||||
char *attrd_set_id(const attribute_t *attr, const char *node_state_id);
|
||||
+char *attrd_nvpair_id(const attribute_t *attr, const char *node_state_id);
|
||||
|
||||
enum attrd_write_options {
|
||||
attrd_write_changed = 0,
|
||||
--
|
||||
2.31.1
|
||||
|
||||
From 2abde6cb87d2e3d31a370c74656f6f7c0818c185 Mon Sep 17 00:00:00 2001
|
||||
From: Ken Gaillot <kgaillot@redhat.com>
|
||||
Date: Thu, 18 Jan 2024 10:01:56 -0600
|
||||
Subject: [PATCH 5/5] Log: pacemaker-attrd: improve some messages for debugging
|
||||
|
||||
---
|
||||
daemons/attrd/attrd_attributes.c | 8 +++++---
|
||||
daemons/attrd/attrd_cib.c | 13 +++++++++----
|
||||
daemons/attrd/attrd_corosync.c | 10 ++++++----
|
||||
3 files changed, 20 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/daemons/attrd/attrd_attributes.c b/daemons/attrd/attrd_attributes.c
|
||||
index 23de2e2..68b9585 100644
|
||||
--- a/daemons/attrd/attrd_attributes.c
|
||||
+++ b/daemons/attrd/attrd_attributes.c
|
||||
@@ -60,13 +60,10 @@ attrd_create_attribute(xmlNode *xml)
|
||||
a->values = pcmk__strikey_table(NULL, attrd_free_attribute_value);
|
||||
|
||||
a->user = crm_element_value_copy(xml, PCMK__XA_ATTR_USER);
|
||||
- crm_trace("Performing all %s operations as user '%s'", a->id, a->user);
|
||||
|
||||
if (dampen_s != NULL) {
|
||||
dampen = crm_get_msec(dampen_s);
|
||||
}
|
||||
- crm_trace("Created attribute %s with %s write delay", a->id,
|
||||
- (a->timeout_ms == 0)? "no" : pcmk__readable_interval(a->timeout_ms));
|
||||
|
||||
if(dampen > 0) {
|
||||
a->timeout_ms = dampen;
|
||||
@@ -75,6 +72,11 @@ attrd_create_attribute(xmlNode *xml)
|
||||
crm_warn("Ignoring invalid delay %s for attribute %s", dampen_s, a->id);
|
||||
}
|
||||
|
||||
+ crm_trace("Created attribute %s with %s write delay and %s CIB user",
|
||||
+ a->id,
|
||||
+ ((dampen > 0)? pcmk__readable_interval(a->timeout_ms) : "no"),
|
||||
+ pcmk__s(a->user, "default"));
|
||||
+
|
||||
g_hash_table_replace(attributes, a->id, a);
|
||||
return a;
|
||||
}
|
||||
diff --git a/daemons/attrd/attrd_cib.c b/daemons/attrd/attrd_cib.c
|
||||
index d42345f..cae6846 100644
|
||||
--- a/daemons/attrd/attrd_cib.c
|
||||
+++ b/daemons/attrd/attrd_cib.c
|
||||
@@ -54,6 +54,7 @@ attrd_cib_updated_cb(const char *event, xmlNode *msg)
|
||||
bool status_changed = false;
|
||||
|
||||
if (attrd_shutting_down(true)) {
|
||||
+ crm_debug("Ignoring CIB change during shutdown");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -278,11 +279,13 @@ attrd_cib_callback(xmlNode *msg, int call_id, int rc, xmlNode *output, void *use
|
||||
|
||||
g_hash_table_iter_init(&iter, a->values);
|
||||
while (g_hash_table_iter_next(&iter, (gpointer *) & peer, (gpointer *) & v)) {
|
||||
- do_crm_log(level, "* %s[%s]=%s",
|
||||
- a->id, peer, pcmk__s(v->requested, "(null)"));
|
||||
if (rc == pcmk_ok) {
|
||||
+ crm_info("* Wrote %s[%s]=%s",
|
||||
+ a->id, peer, pcmk__s(v->requested, "(unset)"));
|
||||
pcmk__str_update(&(v->requested), NULL);
|
||||
} else {
|
||||
+ do_crm_log(level, "* Could not write %s[%s]=%s",
|
||||
+ a->id, peer, pcmk__s(v->requested, "(unset)"));
|
||||
a->changed = true; // Reattempt write below if we are still writer
|
||||
}
|
||||
}
|
||||
@@ -292,6 +295,7 @@ attrd_cib_callback(xmlNode *msg, int call_id, int rc, xmlNode *output, void *use
|
||||
/* We deferred a write of a new update because this update was in
|
||||
* progress. Write out the new value without additional delay.
|
||||
*/
|
||||
+ crm_debug("Pending update for %s can be written now", a->id);
|
||||
write_attribute(a, false);
|
||||
|
||||
/* We're re-attempting a write because the original failed; delay
|
||||
@@ -593,8 +597,9 @@ write_attribute(attribute_t *a, bool ignore_delay)
|
||||
continue;
|
||||
}
|
||||
|
||||
- crm_debug("Updating %s[%s]=%s (node uuid=%s id=%" PRIu32 ")",
|
||||
- a->id, v->nodename, v->current, uuid, v->nodeid);
|
||||
+ crm_debug("Writing %s[%s]=%s (node-state-id=%s node-id=%" PRIu32 ")",
|
||||
+ a->id, v->nodename, pcmk__s(v->current, "(unset)"),
|
||||
+ uuid, v->nodeid);
|
||||
cib_updates++;
|
||||
|
||||
/* Preservation of the attribute to transmit alert */
|
||||
diff --git a/daemons/attrd/attrd_corosync.c b/daemons/attrd/attrd_corosync.c
|
||||
index b348d52..6fb847b 100644
|
||||
--- a/daemons/attrd/attrd_corosync.c
|
||||
+++ b/daemons/attrd/attrd_corosync.c
|
||||
@@ -293,7 +293,8 @@ update_attr_on_host(attribute_t *a, const crm_node_t *peer, const xmlNode *xml,
|
||||
|
||||
// Write out new value or start dampening timer
|
||||
if (a->timeout_ms && a->timer) {
|
||||
- crm_trace("Delayed write out (%dms) for %s", a->timeout_ms, attr);
|
||||
+ crm_trace("Delaying write of %s %s for dampening",
|
||||
+ attr, pcmk__readable_interval(a->timeout_ms));
|
||||
mainloop_timer_start(a->timer);
|
||||
} else {
|
||||
attrd_write_or_elect_attribute(a);
|
||||
@@ -307,11 +308,12 @@ update_attr_on_host(attribute_t *a, const crm_node_t *peer, const xmlNode *xml,
|
||||
if (is_force_write == 1 && a->timeout_ms && a->timer) {
|
||||
/* Save forced writing and set change flag. */
|
||||
/* The actual attribute is written by Writer after election. */
|
||||
- crm_trace("Unchanged %s[%s] from %s is %s(Set the forced write flag)",
|
||||
- attr, host, peer->uname, value);
|
||||
+ crm_trace("%s[%s] from %s is unchanged (%s), forcing write",
|
||||
+ attr, host, peer->uname, pcmk__s(value, "unset"));
|
||||
a->force_write = TRUE;
|
||||
} else {
|
||||
- crm_trace("Unchanged %s[%s] from %s is %s", attr, host, peer->uname, value);
|
||||
+ crm_trace("%s[%s] from %s is unchanged (%s)",
|
||||
+ attr, host, peer->uname, pcmk__s(value, "unset"));
|
||||
}
|
||||
}
|
||||
|
||||
--
|
||||
2.31.1
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
From b542a8f667002519fbc07693a796553746c43c12 Mon Sep 17 00:00:00 2001
|
||||
From: Reid Wahl <nrwahl@protonmail.com>
|
||||
Date: Sat, 11 Jul 2020 18:31:55 -0700
|
||||
Subject: [PATCH] Log: controld: Show action timer plus cluster-delay in
|
||||
action_timer cb
|
||||
|
||||
`action_timer_callback()` prints a misleading error message. If it
|
||||
times out waiting for an action result, the error message prints the
|
||||
timeout value followed by "(action timeout plus cluster-delay)".
|
||||
However, only the `action->timeout` value is displayed. `cluster-delay`
|
||||
is not added in.
|
||||
|
||||
Resolves: RHBZ#1856035
|
||||
---
|
||||
daemons/controld/controld_te_callbacks.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/daemons/controld/controld_te_callbacks.c b/daemons/controld/controld_te_callbacks.c
|
||||
index 8506f26..6ddaffe 100644
|
||||
--- a/daemons/controld/controld_te_callbacks.c
|
||||
+++ b/daemons/controld/controld_te_callbacks.c
|
||||
@@ -697,7 +697,8 @@ action_timer_callback(gpointer data)
|
||||
crm_err("Node %s did not send %s result (via %s) within %dms "
|
||||
"(action timeout plus cluster-delay)",
|
||||
(on_node? on_node : ""), (task? task : "unknown action"),
|
||||
- (via_node? via_node : "controller"), timer->timeout);
|
||||
+ (via_node? via_node : "controller"),
|
||||
+ timer->timeout + transition_graph->network_delay);
|
||||
print_action(LOG_ERR, "Aborting transition, action lost: ", timer->action);
|
||||
|
||||
timer->action->failed = TRUE;
|
||||
--
|
||||
1.8.3.1
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
From 9c13ce6fe95812308443c188ace8f897e6bce942 Mon Sep 17 00:00:00 2001
|
||||
From: Reid Wahl <nrwahl@protonmail.com>
|
||||
Date: Mon, 29 Jan 2024 11:14:25 -0800
|
||||
Subject: [PATCH] Fix: tools: crm_attribute emits garbage for --node localhost
|
||||
or auto
|
||||
|
||||
This happens because pcmk__node_attr_target() returns its argument if
|
||||
its argument is NULL, "auto", or "localhost" and no relevant environment
|
||||
variables are found. Then crm_attribute frees the return value, makes a
|
||||
copy of it, and assigns it back to options.dest_uname.
|
||||
|
||||
The fix is to check whether the return value is equal to the argument.
|
||||
|
||||
Fixes RHEL-23065
|
||||
|
||||
Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
|
||||
---
|
||||
tools/crm_attribute.c | 19 +++++++++++++++++--
|
||||
1 file changed, 17 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/tools/crm_attribute.c b/tools/crm_attribute.c
|
||||
index d221ab85d..636d03dbd 100644
|
||||
--- a/tools/crm_attribute.c
|
||||
+++ b/tools/crm_attribute.c
|
||||
@@ -766,8 +766,23 @@ main(int argc, char **argv)
|
||||
const char *target = pcmk__node_attr_target(options.dest_uname);
|
||||
|
||||
if (target != NULL) {
|
||||
- g_free(options.dest_uname);
|
||||
- options.dest_uname = g_strdup(target);
|
||||
+ /* If options.dest_uname is "auto" or "localhost", then
|
||||
+ * pcmk__node_attr_target() may return it, depending on environment
|
||||
+ * variables. In that case, attribute lookups will fail for "auto"
|
||||
+ * (unless there's a node named "auto"). attrd maps "localhost" to
|
||||
+ * the true local node name for queries.
|
||||
+ *
|
||||
+ * @TODO
|
||||
+ * * Investigate whether "localhost" is mapped to a real node name
|
||||
+ * for non-query commands. If not, possibly modify it so that it
|
||||
+ * is.
|
||||
+ * * Map "auto" to "localhost" (probably).
|
||||
+ */
|
||||
+ if (target != (const char *) options.dest_uname) {
|
||||
+ g_free(options.dest_uname);
|
||||
+ options.dest_uname = g_strdup(target);
|
||||
+ }
|
||||
+
|
||||
} else if (getenv("CIB_file") != NULL && options.dest_uname == NULL) {
|
||||
get_node_name_from_local();
|
||||
}
|
||||
--
|
||||
2.41.0
|
||||
|
|
@ -1,476 +0,0 @@
|
|||
From 7056ae08bfa5cafeec9c454cb40aefa7553af6df Mon Sep 17 00:00:00 2001
|
||||
From: Chris Lumens <clumens@redhat.com>
|
||||
Date: Thu, 16 Jul 2020 12:53:24 -0400
|
||||
Subject: [PATCH 1/4] Fix: libcrmcommon: Set out->priv to NULL in free_priv.
|
||||
|
||||
init won't do anything if priv is not NULL, so when the private data is
|
||||
freed, also set it to NULL. This prevents segfaults when reset is
|
||||
called.
|
||||
---
|
||||
lib/common/output_html.c | 1 +
|
||||
lib/common/output_log.c | 1 +
|
||||
lib/common/output_text.c | 1 +
|
||||
lib/common/output_xml.c | 1 +
|
||||
tools/crm_mon_curses.c | 1 +
|
||||
5 files changed, 5 insertions(+)
|
||||
|
||||
diff --git a/lib/common/output_html.c b/lib/common/output_html.c
|
||||
index c8f0088..fc06641 100644
|
||||
--- a/lib/common/output_html.c
|
||||
+++ b/lib/common/output_html.c
|
||||
@@ -72,6 +72,7 @@ html_free_priv(pcmk__output_t *out) {
|
||||
g_queue_free(priv->parent_q);
|
||||
g_slist_free(priv->errors);
|
||||
free(priv);
|
||||
+ out->priv = NULL;
|
||||
}
|
||||
|
||||
static bool
|
||||
diff --git a/lib/common/output_log.c b/lib/common/output_log.c
|
||||
index 5b45ce4..0208046 100644
|
||||
--- a/lib/common/output_log.c
|
||||
+++ b/lib/common/output_log.c
|
||||
@@ -44,6 +44,7 @@ log_free_priv(pcmk__output_t *out) {
|
||||
|
||||
g_queue_free(priv->prefixes);
|
||||
free(priv);
|
||||
+ out->priv = NULL;
|
||||
}
|
||||
|
||||
static bool
|
||||
diff --git a/lib/common/output_text.c b/lib/common/output_text.c
|
||||
index 54c409a..8f15849 100644
|
||||
--- a/lib/common/output_text.c
|
||||
+++ b/lib/common/output_text.c
|
||||
@@ -43,6 +43,7 @@ text_free_priv(pcmk__output_t *out) {
|
||||
|
||||
g_queue_free(priv->parent_q);
|
||||
free(priv);
|
||||
+ out->priv = NULL;
|
||||
}
|
||||
|
||||
static bool
|
||||
diff --git a/lib/common/output_xml.c b/lib/common/output_xml.c
|
||||
index 8565bfe..858da3f 100644
|
||||
--- a/lib/common/output_xml.c
|
||||
+++ b/lib/common/output_xml.c
|
||||
@@ -54,6 +54,7 @@ xml_free_priv(pcmk__output_t *out) {
|
||||
g_queue_free(priv->parent_q);
|
||||
g_slist_free(priv->errors);
|
||||
free(priv);
|
||||
+ out->priv = NULL;
|
||||
}
|
||||
|
||||
static bool
|
||||
diff --git a/tools/crm_mon_curses.c b/tools/crm_mon_curses.c
|
||||
index d93b847..e9cc023 100644
|
||||
--- a/tools/crm_mon_curses.c
|
||||
+++ b/tools/crm_mon_curses.c
|
||||
@@ -46,6 +46,7 @@ curses_free_priv(pcmk__output_t *out) {
|
||||
|
||||
g_queue_free(priv->parent_q);
|
||||
free(priv);
|
||||
+ out->priv = NULL;
|
||||
}
|
||||
|
||||
static bool
|
||||
--
|
||||
1.8.3.1
|
||||
|
||||
|
||||
From 3779152993ca0e88dc407c918882568217f1b630 Mon Sep 17 00:00:00 2001
|
||||
From: Chris Lumens <clumens@redhat.com>
|
||||
Date: Thu, 16 Jul 2020 13:50:24 -0400
|
||||
Subject: [PATCH 2/4] Fix: libcrmcommon: Make reset and finish work more
|
||||
similarly.
|
||||
|
||||
When finish is called for HTML and XML output formats, various extra
|
||||
nodes and headers are added, errors are added, etc. None of this stuff
|
||||
happens on reset. For the HTML format, this also means things like the
|
||||
CGI headers and title don't get added when reset is called. Make these
|
||||
two functions much more similar.
|
||||
|
||||
Regression in 2.0.3.
|
||||
|
||||
See: rhbz#1857728
|
||||
---
|
||||
lib/common/output_html.c | 26 ++++++++++++++++----------
|
||||
lib/common/output_xml.c | 30 ++++++++++++++++--------------
|
||||
2 files changed, 32 insertions(+), 24 deletions(-)
|
||||
|
||||
diff --git a/lib/common/output_html.c b/lib/common/output_html.c
|
||||
index fc06641..6127df2 100644
|
||||
--- a/lib/common/output_html.c
|
||||
+++ b/lib/common/output_html.c
|
||||
@@ -113,18 +113,11 @@ add_error_node(gpointer data, gpointer user_data) {
|
||||
}
|
||||
|
||||
static void
|
||||
-html_finish(pcmk__output_t *out, crm_exit_t exit_status, bool print, void **copy_dest) {
|
||||
+finish_reset_common(pcmk__output_t *out, crm_exit_t exit_status, bool print) {
|
||||
private_data_t *priv = out->priv;
|
||||
htmlNodePtr head_node = NULL;
|
||||
htmlNodePtr charset_node = NULL;
|
||||
|
||||
- /* If root is NULL, html_init failed and we are being called from pcmk__output_free
|
||||
- * in the pcmk__output_new path.
|
||||
- */
|
||||
- if (priv == NULL || priv->root == NULL) {
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
if (cgi_output && print) {
|
||||
fprintf(out->dest, "Content-Type: text/html\n\n");
|
||||
}
|
||||
@@ -174,6 +167,20 @@ html_finish(pcmk__output_t *out, crm_exit_t exit_status, bool print, void **copy
|
||||
if (print) {
|
||||
htmlDocDump(out->dest, priv->root->doc);
|
||||
}
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+html_finish(pcmk__output_t *out, crm_exit_t exit_status, bool print, void **copy_dest) {
|
||||
+ private_data_t *priv = out->priv;
|
||||
+
|
||||
+ /* If root is NULL, html_init failed and we are being called from pcmk__output_free
|
||||
+ * in the pcmk__output_new path.
|
||||
+ */
|
||||
+ if (priv == NULL || priv->root == NULL) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ finish_reset_common(out, exit_status, print);
|
||||
|
||||
if (copy_dest != NULL) {
|
||||
*copy_dest = copy_xml(priv->root);
|
||||
@@ -185,8 +192,7 @@ html_reset(pcmk__output_t *out) {
|
||||
CRM_ASSERT(out != NULL);
|
||||
|
||||
if (out->priv != NULL) {
|
||||
- private_data_t *priv = out->priv;
|
||||
- htmlDocDump(out->dest, priv->root->doc);
|
||||
+ finish_reset_common(out, CRM_EX_OK, true);
|
||||
}
|
||||
|
||||
html_free_priv(out);
|
||||
diff --git a/lib/common/output_xml.c b/lib/common/output_xml.c
|
||||
index 858da3f..b64a71d 100644
|
||||
--- a/lib/common/output_xml.c
|
||||
+++ b/lib/common/output_xml.c
|
||||
@@ -106,17 +106,10 @@ add_error_node(gpointer data, gpointer user_data) {
|
||||
}
|
||||
|
||||
static void
|
||||
-xml_finish(pcmk__output_t *out, crm_exit_t exit_status, bool print, void **copy_dest) {
|
||||
+finish_reset_common(pcmk__output_t *out, crm_exit_t exit_status, bool print) {
|
||||
xmlNodePtr node;
|
||||
private_data_t *priv = out->priv;
|
||||
|
||||
- /* If root is NULL, xml_init failed and we are being called from pcmk__output_free
|
||||
- * in the pcmk__output_new path.
|
||||
- */
|
||||
- if (priv == NULL || priv->root == NULL) {
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
if (legacy_xml) {
|
||||
GSList *node = priv->errors;
|
||||
|
||||
@@ -148,6 +141,20 @@ xml_finish(pcmk__output_t *out, crm_exit_t exit_status, bool print, void **copy_
|
||||
fprintf(out->dest, "%s", buf);
|
||||
free(buf);
|
||||
}
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+xml_finish(pcmk__output_t *out, crm_exit_t exit_status, bool print, void **copy_dest) {
|
||||
+ private_data_t *priv = out->priv;
|
||||
+
|
||||
+ /* If root is NULL, xml_init failed and we are being called from pcmk__output_free
|
||||
+ * in the pcmk__output_new path.
|
||||
+ */
|
||||
+ if (priv == NULL || priv->root == NULL) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ finish_reset_common(out, exit_status, print);
|
||||
|
||||
if (copy_dest != NULL) {
|
||||
*copy_dest = copy_xml(priv->root);
|
||||
@@ -156,15 +163,10 @@ xml_finish(pcmk__output_t *out, crm_exit_t exit_status, bool print, void **copy_
|
||||
|
||||
static void
|
||||
xml_reset(pcmk__output_t *out) {
|
||||
- char *buf = NULL;
|
||||
-
|
||||
CRM_ASSERT(out != NULL);
|
||||
|
||||
if (out->priv != NULL) {
|
||||
- private_data_t *priv = out->priv;
|
||||
- buf = dump_xml_formatted_with_text(priv->root);
|
||||
- fprintf(out->dest, "%s", buf);
|
||||
- free(buf);
|
||||
+ finish_reset_common(out, CRM_EX_OK, true);
|
||||
}
|
||||
|
||||
xml_free_priv(out);
|
||||
--
|
||||
1.8.3.1
|
||||
|
||||
|
||||
From 0f8e4ca5d9a429c934f1e91a1bdf572efd07e0db Mon Sep 17 00:00:00 2001
|
||||
From: Chris Lumens <clumens@redhat.com>
|
||||
Date: Thu, 16 Jul 2020 16:09:08 -0400
|
||||
Subject: [PATCH 3/4] Fix: tools, libcrmcommon: Reopen the output dest on
|
||||
reset.
|
||||
|
||||
This is needed when running crm_mon as a daemon. When we do a reset,
|
||||
we need to clear out any existing output destination and start writing
|
||||
again from the beginning. This really only matters when the destination
|
||||
is a file.
|
||||
|
||||
The extra freopen at the end of crm_mon is to handle when crm_mon is
|
||||
killed. We need to reset the output file to its beginning before
|
||||
calling finish.
|
||||
---
|
||||
lib/common/output_html.c | 3 +++
|
||||
lib/common/output_log.c | 3 +++
|
||||
lib/common/output_text.c | 3 +++
|
||||
lib/common/output_xml.c | 3 +++
|
||||
tools/crm_mon.c | 9 +++++++++
|
||||
5 files changed, 21 insertions(+)
|
||||
|
||||
diff --git a/lib/common/output_html.c b/lib/common/output_html.c
|
||||
index 6127df2..6e21031 100644
|
||||
--- a/lib/common/output_html.c
|
||||
+++ b/lib/common/output_html.c
|
||||
@@ -191,6 +191,9 @@ static void
|
||||
html_reset(pcmk__output_t *out) {
|
||||
CRM_ASSERT(out != NULL);
|
||||
|
||||
+ out->dest = freopen(NULL, "w", out->dest);
|
||||
+ CRM_ASSERT(out->dest != NULL);
|
||||
+
|
||||
if (out->priv != NULL) {
|
||||
finish_reset_common(out, CRM_EX_OK, true);
|
||||
}
|
||||
diff --git a/lib/common/output_log.c b/lib/common/output_log.c
|
||||
index 0208046..8422ac2 100644
|
||||
--- a/lib/common/output_log.c
|
||||
+++ b/lib/common/output_log.c
|
||||
@@ -72,6 +72,9 @@ static void
|
||||
log_reset(pcmk__output_t *out) {
|
||||
CRM_ASSERT(out != NULL);
|
||||
|
||||
+ out->dest = freopen(NULL, "w", out->dest);
|
||||
+ CRM_ASSERT(out->dest != NULL);
|
||||
+
|
||||
log_free_priv(out);
|
||||
log_init(out);
|
||||
}
|
||||
diff --git a/lib/common/output_text.c b/lib/common/output_text.c
|
||||
index 8f15849..2f7e5b0 100644
|
||||
--- a/lib/common/output_text.c
|
||||
+++ b/lib/common/output_text.c
|
||||
@@ -75,6 +75,9 @@ static void
|
||||
text_reset(pcmk__output_t *out) {
|
||||
CRM_ASSERT(out != NULL);
|
||||
|
||||
+ out->dest = freopen(NULL, "w", out->dest);
|
||||
+ CRM_ASSERT(out->dest != NULL);
|
||||
+
|
||||
text_free_priv(out);
|
||||
text_init(out);
|
||||
}
|
||||
diff --git a/lib/common/output_xml.c b/lib/common/output_xml.c
|
||||
index b64a71d..9f8e01b 100644
|
||||
--- a/lib/common/output_xml.c
|
||||
+++ b/lib/common/output_xml.c
|
||||
@@ -165,6 +165,9 @@ static void
|
||||
xml_reset(pcmk__output_t *out) {
|
||||
CRM_ASSERT(out != NULL);
|
||||
|
||||
+ out->dest = freopen(NULL, "w", out->dest);
|
||||
+ CRM_ASSERT(out->dest != NULL);
|
||||
+
|
||||
if (out->priv != NULL) {
|
||||
finish_reset_common(out, CRM_EX_OK, true);
|
||||
}
|
||||
diff --git a/tools/crm_mon.c b/tools/crm_mon.c
|
||||
index b2e143b..10624c1 100644
|
||||
--- a/tools/crm_mon.c
|
||||
+++ b/tools/crm_mon.c
|
||||
@@ -2014,6 +2014,10 @@ mon_refresh_display(gpointer user_data)
|
||||
break;
|
||||
}
|
||||
|
||||
+ if (options.daemonize) {
|
||||
+ out->reset(out);
|
||||
+ }
|
||||
+
|
||||
stonith_history_free(stonith_history);
|
||||
stonith_history = NULL;
|
||||
pe_reset_working_set(mon_data_set);
|
||||
@@ -2179,6 +2183,11 @@ clean_up(crm_exit_t exit_code)
|
||||
* crm_mon to be able to do so.
|
||||
*/
|
||||
if (out != NULL) {
|
||||
+ if (options.daemonize) {
|
||||
+ out->dest = freopen(NULL, "w", out->dest);
|
||||
+ CRM_ASSERT(out->dest != NULL);
|
||||
+ }
|
||||
+
|
||||
switch (output_format) {
|
||||
case mon_output_cgi:
|
||||
case mon_output_html:
|
||||
--
|
||||
1.8.3.1
|
||||
|
||||
|
||||
From b655c039414d2c7af77c3532222b04684ef1f3d0 Mon Sep 17 00:00:00 2001
|
||||
From: Chris Lumens <clumens@redhat.com>
|
||||
Date: Fri, 17 Jul 2020 10:58:32 -0400
|
||||
Subject: [PATCH 4/4] Fix: tools: Add the http-equiv header to crm_mon at the
|
||||
right time.
|
||||
|
||||
This header is only getting added on termination, which is not a lot of
|
||||
help if you're running crm_mon in daemonize mode. Putting this header
|
||||
in at the right time requires a couple changes:
|
||||
|
||||
* pcmk__html_add_header doesn't need a parent argument. It was not
|
||||
being used in the first place.
|
||||
|
||||
* The extra_headers list in output_html.c should not be freed in the
|
||||
reset function. This means it would get freed after every time the
|
||||
daemonized output is refreshed, which means the header would have to be
|
||||
added every time too. extra_headers will now only be freed when the
|
||||
program exits. This is a behavior change, but I can't see why it's
|
||||
going to be a problem.
|
||||
|
||||
* To support that, we need to copy each item in the extra_headers list
|
||||
when it gets added to the output XML document. This prevents segfaults
|
||||
when we later free that document.
|
||||
|
||||
* handle_html_output no longer needs to exist. That function only
|
||||
existed to add the http-equiv header at the end, which is wrong.
|
||||
---
|
||||
include/crm/common/output.h | 5 ++---
|
||||
lib/common/output_html.c | 7 ++++---
|
||||
tools/crm_mon.c | 26 +++++++-------------------
|
||||
3 files changed, 13 insertions(+), 25 deletions(-)
|
||||
|
||||
diff --git a/include/crm/common/output.h b/include/crm/common/output.h
|
||||
index e7c9417..186bcfe 100644
|
||||
--- a/include/crm/common/output.h
|
||||
+++ b/include/crm/common/output.h
|
||||
@@ -703,15 +703,14 @@ pcmk__output_create_html_node(pcmk__output_t *out, const char *element_name, con
|
||||
* the following code would generate the tag "<meta http-equiv='refresh' content='19'>":
|
||||
*
|
||||
* \code
|
||||
- * pcmk__html_add_header(parent, "meta", "http-equiv", "refresh", "content", "19", NULL);
|
||||
+ * pcmk__html_add_header("meta", "http-equiv", "refresh", "content", "19", NULL);
|
||||
* \endcode
|
||||
*
|
||||
- * \param[in,out] parent The node that will be the parent of the new node.
|
||||
* \param[in] name The HTML tag for the new node.
|
||||
* \param[in] ... A NULL-terminated key/value list of attributes.
|
||||
*/
|
||||
void
|
||||
-pcmk__html_add_header(xmlNodePtr parent, const char *name, ...)
|
||||
+pcmk__html_add_header(const char *name, ...)
|
||||
G_GNUC_NULL_TERMINATED;
|
||||
|
||||
#ifdef __cplusplus
|
||||
diff --git a/lib/common/output_html.c b/lib/common/output_html.c
|
||||
index 6e21031..259e412 100644
|
||||
--- a/lib/common/output_html.c
|
||||
+++ b/lib/common/output_html.c
|
||||
@@ -139,7 +139,7 @@ finish_reset_common(pcmk__output_t *out, crm_exit_t exit_status, bool print) {
|
||||
|
||||
/* Add any extra header nodes the caller might have created. */
|
||||
for (int i = 0; i < g_slist_length(extra_headers); i++) {
|
||||
- xmlAddChild(head_node, g_slist_nth_data(extra_headers, i));
|
||||
+ xmlAddChild(head_node, xmlCopyNode(g_slist_nth_data(extra_headers, i), 1));
|
||||
}
|
||||
|
||||
/* Stylesheets are included two different ways. The first is via a built-in
|
||||
@@ -185,6 +185,8 @@ html_finish(pcmk__output_t *out, crm_exit_t exit_status, bool print, void **copy
|
||||
if (copy_dest != NULL) {
|
||||
*copy_dest = copy_xml(priv->root);
|
||||
}
|
||||
+
|
||||
+ g_slist_free_full(extra_headers, (GDestroyNotify) xmlFreeNode);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -199,7 +201,6 @@ html_reset(pcmk__output_t *out) {
|
||||
}
|
||||
|
||||
html_free_priv(out);
|
||||
- g_slist_free_full(extra_headers, (GDestroyNotify) xmlFreeNode);
|
||||
html_init(out);
|
||||
}
|
||||
|
||||
@@ -412,7 +413,7 @@ pcmk__output_create_html_node(pcmk__output_t *out, const char *element_name, con
|
||||
}
|
||||
|
||||
void
|
||||
-pcmk__html_add_header(xmlNodePtr parent, const char *name, ...) {
|
||||
+pcmk__html_add_header(const char *name, ...) {
|
||||
htmlNodePtr header_node;
|
||||
va_list ap;
|
||||
|
||||
diff --git a/tools/crm_mon.c b/tools/crm_mon.c
|
||||
index 10624c1..7fd2b9c 100644
|
||||
--- a/tools/crm_mon.c
|
||||
+++ b/tools/crm_mon.c
|
||||
@@ -1346,6 +1346,12 @@ main(int argc, char **argv)
|
||||
options.mon_ops |= mon_op_print_timing | mon_op_inactive_resources;
|
||||
}
|
||||
|
||||
+ if ((output_format == mon_output_html || output_format == mon_output_cgi) &&
|
||||
+ out->dest != stdout) {
|
||||
+ pcmk__html_add_header("meta", "http-equiv", "refresh", "content",
|
||||
+ crm_itoa(options.reconnect_msec/1000), NULL);
|
||||
+ }
|
||||
+
|
||||
crm_info("Starting %s", crm_system_name);
|
||||
|
||||
if (cib) {
|
||||
@@ -2106,15 +2112,6 @@ clean_up_connections(void)
|
||||
}
|
||||
}
|
||||
|
||||
-static void
|
||||
-handle_html_output(crm_exit_t exit_code) {
|
||||
- xmlNodePtr html = NULL;
|
||||
-
|
||||
- pcmk__html_add_header(html, "meta", "http-equiv", "refresh", "content",
|
||||
- crm_itoa(options.reconnect_msec/1000), NULL);
|
||||
- out->finish(out, exit_code, true, (void **) &html);
|
||||
-}
|
||||
-
|
||||
/*
|
||||
* De-init ncurses, disconnect from the CIB manager, disconnect fencing,
|
||||
* deallocate memory and show usage-message if requested.
|
||||
@@ -2188,16 +2185,7 @@ clean_up(crm_exit_t exit_code)
|
||||
CRM_ASSERT(out->dest != NULL);
|
||||
}
|
||||
|
||||
- switch (output_format) {
|
||||
- case mon_output_cgi:
|
||||
- case mon_output_html:
|
||||
- handle_html_output(exit_code);
|
||||
- break;
|
||||
-
|
||||
- default:
|
||||
- out->finish(out, exit_code, true, NULL);
|
||||
- break;
|
||||
- }
|
||||
+ out->finish(out, exit_code, true, NULL);
|
||||
|
||||
pcmk__output_free(out);
|
||||
pcmk__unregister_formats();
|
||||
--
|
||||
1.8.3.1
|
||||
|
|
@ -1,270 +0,0 @@
|
|||
From 4e190ebc5460563bae2586b28afb0415f2eb3d1a Mon Sep 17 00:00:00 2001
|
||||
From: Ken Gaillot <kgaillot@redhat.com>
|
||||
Date: Wed, 1 Jul 2020 20:38:16 -0500
|
||||
Subject: [PATCH 1/4] Test: CTS: libqb shared memory creates directories now
|
||||
|
||||
... so use "rm -rf" instead of "rm -f"
|
||||
---
|
||||
cts/CTS.py.in | 2 +-
|
||||
cts/CTSaudits.py | 2 +-
|
||||
2 files changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/cts/CTS.py.in b/cts/CTS.py.in
|
||||
index c418318..091bb1f 100644
|
||||
--- a/cts/CTS.py.in
|
||||
+++ b/cts/CTS.py.in
|
||||
@@ -546,7 +546,7 @@ class ClusterManager(UserDict):
|
||||
if self.rsh(node, self.templates["StopCmd"]) == 0:
|
||||
# Make sure we can continue even if corosync leaks
|
||||
# fdata-* is the old name
|
||||
- #self.rsh(node, "rm -f /dev/shm/qb-* /dev/shm/fdata-*")
|
||||
+ #self.rsh(node, "rm -rf /dev/shm/qb-* /dev/shm/fdata-*")
|
||||
self.ShouldBeStatus[node] = "down"
|
||||
self.cluster_stable(self.Env["DeadTime"])
|
||||
return 1
|
||||
diff --git a/cts/CTSaudits.py b/cts/CTSaudits.py
|
||||
index b7e0827..cc82171 100755
|
||||
--- a/cts/CTSaudits.py
|
||||
+++ b/cts/CTSaudits.py
|
||||
@@ -233,7 +233,7 @@ class FileAudit(ClusterAudit):
|
||||
for line in lsout:
|
||||
self.CM.debug("ps[%s]: %s" % (node, line))
|
||||
|
||||
- self.CM.rsh(node, "rm -f /dev/shm/qb-*")
|
||||
+ self.CM.rsh(node, "rm -rf /dev/shm/qb-*")
|
||||
|
||||
else:
|
||||
self.CM.debug("Skipping %s" % node)
|
||||
--
|
||||
1.8.3.1
|
||||
|
||||
|
||||
From 4316507d50d51c7864d8d34aac1da31a232b9f42 Mon Sep 17 00:00:00 2001
|
||||
From: Ken Gaillot <kgaillot@redhat.com>
|
||||
Date: Thu, 2 Jul 2020 16:09:20 -0500
|
||||
Subject: [PATCH 2/4] Test: CTS: ignore error logged by recent pcs versions
|
||||
|
||||
... because it is expected when a node is fenced, and we should already see
|
||||
pacemaker errors if a node is unexpectedly fenced
|
||||
---
|
||||
cts/patterns.py | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/cts/patterns.py b/cts/patterns.py
|
||||
index 96d6471..7eed90c 100644
|
||||
--- a/cts/patterns.py
|
||||
+++ b/cts/patterns.py
|
||||
@@ -21,6 +21,10 @@ class BasePatterns(object):
|
||||
|
||||
# Logging bug in some versions of libvirtd
|
||||
r"libvirtd.*: internal error: Failed to parse PCI config address",
|
||||
+
|
||||
+ # pcs can log this when node is fenced, but fencing is OK in some
|
||||
+ # tests (and we will catch it in pacemaker logs when not OK)
|
||||
+ r"pcs.daemon:No response from: .* request: get_configs, error:",
|
||||
]
|
||||
self.BadNews = []
|
||||
self.components = {}
|
||||
--
|
||||
1.8.3.1
|
||||
|
||||
|
||||
From 598ae0f65bad6ed16978d1ab6e24e8e358e0a1a4 Mon Sep 17 00:00:00 2001
|
||||
From: Ken Gaillot <kgaillot@redhat.com>
|
||||
Date: Thu, 2 Jul 2020 20:40:00 -0500
|
||||
Subject: [PATCH 3/4] Low: libcrmcommon: avoid assertion on controller protocol
|
||||
errors
|
||||
|
||||
Previously, after a protocol error, we would set reply to NULL and then try to
|
||||
call crm_element_value() on it, which would log an assertion.
|
||||
---
|
||||
lib/common/ipc_controld.c | 46 ++++++++++++++++++++++------------------------
|
||||
1 file changed, 22 insertions(+), 24 deletions(-)
|
||||
|
||||
diff --git a/lib/common/ipc_controld.c b/lib/common/ipc_controld.c
|
||||
index 5917cc5..22cb9e0 100644
|
||||
--- a/lib/common/ipc_controld.c
|
||||
+++ b/lib/common/ipc_controld.c
|
||||
@@ -187,53 +187,51 @@ dispatch(pcmk_ipc_api_t *api, xmlNode *reply)
|
||||
crm_debug("Unrecognizable controller message: invalid message type '%s'",
|
||||
crm_str(value));
|
||||
status = CRM_EX_PROTOCOL;
|
||||
- reply = NULL;
|
||||
+ goto done;
|
||||
}
|
||||
|
||||
if (crm_element_value(reply, XML_ATTR_REFERENCE) == NULL) {
|
||||
crm_debug("Unrecognizable controller message: no reference");
|
||||
status = CRM_EX_PROTOCOL;
|
||||
- reply = NULL;
|
||||
+ goto done;
|
||||
}
|
||||
|
||||
value = crm_element_value(reply, F_CRM_TASK);
|
||||
if (value == NULL) {
|
||||
crm_debug("Unrecognizable controller message: no command name");
|
||||
status = CRM_EX_PROTOCOL;
|
||||
- reply = NULL;
|
||||
+ goto done;
|
||||
}
|
||||
|
||||
// Parse useful info from reply
|
||||
|
||||
- if (reply != NULL) {
|
||||
- reply_data.feature_set = crm_element_value(reply, XML_ATTR_VERSION);
|
||||
- reply_data.host_from = crm_element_value(reply, F_CRM_HOST_FROM);
|
||||
- msg_data = get_message_xml(reply, F_CRM_DATA);
|
||||
+ reply_data.feature_set = crm_element_value(reply, XML_ATTR_VERSION);
|
||||
+ reply_data.host_from = crm_element_value(reply, F_CRM_HOST_FROM);
|
||||
+ msg_data = get_message_xml(reply, F_CRM_DATA);
|
||||
|
||||
- if (!strcmp(value, CRM_OP_REPROBE)) {
|
||||
- reply_data.reply_type = pcmk_controld_reply_reprobe;
|
||||
+ if (!strcmp(value, CRM_OP_REPROBE)) {
|
||||
+ reply_data.reply_type = pcmk_controld_reply_reprobe;
|
||||
|
||||
- } else if (!strcmp(value, CRM_OP_NODE_INFO)) {
|
||||
- set_node_info_data(&reply_data, msg_data);
|
||||
+ } else if (!strcmp(value, CRM_OP_NODE_INFO)) {
|
||||
+ set_node_info_data(&reply_data, msg_data);
|
||||
|
||||
- } else if (!strcmp(value, CRM_OP_INVOKE_LRM)) {
|
||||
- reply_data.reply_type = pcmk_controld_reply_resource;
|
||||
- reply_data.data.resource.node_state = msg_data;
|
||||
+ } else if (!strcmp(value, CRM_OP_INVOKE_LRM)) {
|
||||
+ reply_data.reply_type = pcmk_controld_reply_resource;
|
||||
+ reply_data.data.resource.node_state = msg_data;
|
||||
|
||||
- } else if (!strcmp(value, CRM_OP_PING)) {
|
||||
- set_ping_data(&reply_data, msg_data);
|
||||
+ } else if (!strcmp(value, CRM_OP_PING)) {
|
||||
+ set_ping_data(&reply_data, msg_data);
|
||||
|
||||
- } else if (!strcmp(value, PCMK__CONTROLD_CMD_NODES)) {
|
||||
- set_nodes_data(&reply_data, msg_data);
|
||||
+ } else if (!strcmp(value, PCMK__CONTROLD_CMD_NODES)) {
|
||||
+ set_nodes_data(&reply_data, msg_data);
|
||||
|
||||
- } else {
|
||||
- crm_debug("Unrecognizable controller message: unknown command '%s'",
|
||||
- value);
|
||||
- status = CRM_EX_PROTOCOL;
|
||||
- reply = NULL;
|
||||
- }
|
||||
+ } else {
|
||||
+ crm_debug("Unrecognizable controller message: unknown command '%s'",
|
||||
+ value);
|
||||
+ status = CRM_EX_PROTOCOL;
|
||||
}
|
||||
|
||||
+done:
|
||||
pcmk__call_ipc_callback(api, pcmk_ipc_event_reply, status, &reply_data);
|
||||
|
||||
// Free any reply data that was allocated
|
||||
--
|
||||
1.8.3.1
|
||||
|
||||
|
||||
From 5ae4101b60f8c0cd96eb2097a65a59aaa1750d73 Mon Sep 17 00:00:00 2001
|
||||
From: Ken Gaillot <kgaillot@redhat.com>
|
||||
Date: Fri, 17 Jul 2020 17:20:23 -0500
|
||||
Subject: [PATCH 4/4] Log: fencer: don't log assertion if unable to create full
|
||||
request reply
|
||||
|
||||
Previously, we would log an assertion and a warning if asked to create a reply
|
||||
to a NULL request. However there is a possible sequence for this to happen:
|
||||
|
||||
- Some nodes are up and some down at cluster start-up
|
||||
- One node is elected DC and schedules fencing of the down nodes
|
||||
- Fencing is initiated for one of the down nodes
|
||||
- One of the other down nodes comes up and is elected DC
|
||||
- The fencing result comes back and all peers (including new DC) are notified
|
||||
- New DC tries to create a notification for its client (the controller)
|
||||
but doesn't know anything about the initial request
|
||||
|
||||
For now, just log a warning and drop the assertion. Longer term, maybe we
|
||||
should synchronize in-flight request information when a fencer joins the
|
||||
process group.
|
||||
---
|
||||
daemons/fenced/fenced_commands.c | 55 +++++++++++++++++++++++-----------------
|
||||
1 file changed, 32 insertions(+), 23 deletions(-)
|
||||
|
||||
diff --git a/daemons/fenced/fenced_commands.c b/daemons/fenced/fenced_commands.c
|
||||
index 05c5437..9c27d61 100644
|
||||
--- a/daemons/fenced/fenced_commands.c
|
||||
+++ b/daemons/fenced/fenced_commands.c
|
||||
@@ -2336,22 +2336,8 @@ stonith_fence(xmlNode * msg)
|
||||
xmlNode *
|
||||
stonith_construct_reply(xmlNode * request, const char *output, xmlNode * data, int rc)
|
||||
{
|
||||
- int lpc = 0;
|
||||
xmlNode *reply = NULL;
|
||||
|
||||
- const char *name = NULL;
|
||||
- const char *value = NULL;
|
||||
-
|
||||
- const char *names[] = {
|
||||
- F_STONITH_OPERATION,
|
||||
- F_STONITH_CALLID,
|
||||
- F_STONITH_CLIENTID,
|
||||
- F_STONITH_CLIENTNAME,
|
||||
- F_STONITH_REMOTE_OP_ID,
|
||||
- F_STONITH_CALLOPTS
|
||||
- };
|
||||
-
|
||||
- crm_trace("Creating a basic reply");
|
||||
reply = create_xml_node(NULL, T_STONITH_REPLY);
|
||||
|
||||
crm_xml_add(reply, "st_origin", __FUNCTION__);
|
||||
@@ -2359,16 +2345,39 @@ stonith_construct_reply(xmlNode * request, const char *output, xmlNode * data, i
|
||||
crm_xml_add(reply, "st_output", output);
|
||||
crm_xml_add_int(reply, F_STONITH_RC, rc);
|
||||
|
||||
- CRM_CHECK(request != NULL, crm_warn("Can't create a sane reply"); return reply);
|
||||
- for (lpc = 0; lpc < DIMOF(names); lpc++) {
|
||||
- name = names[lpc];
|
||||
- value = crm_element_value(request, name);
|
||||
- crm_xml_add(reply, name, value);
|
||||
- }
|
||||
+ if (request == NULL) {
|
||||
+ /* Most likely, this is the result of a stonith operation that was
|
||||
+ * initiated before we came up. Unfortunately that means we lack enough
|
||||
+ * information to provide clients with a full result.
|
||||
+ *
|
||||
+ * @TODO Maybe synchronize this information at start-up?
|
||||
+ */
|
||||
+ crm_warn("Missing request information for client notifications for "
|
||||
+ "operation with result %d (initiated before we came up?)", rc);
|
||||
|
||||
- if (data != NULL) {
|
||||
- crm_trace("Attaching reply output");
|
||||
- add_message_xml(reply, F_STONITH_CALLDATA, data);
|
||||
+ } else {
|
||||
+ const char *name = NULL;
|
||||
+ const char *value = NULL;
|
||||
+
|
||||
+ const char *names[] = {
|
||||
+ F_STONITH_OPERATION,
|
||||
+ F_STONITH_CALLID,
|
||||
+ F_STONITH_CLIENTID,
|
||||
+ F_STONITH_CLIENTNAME,
|
||||
+ F_STONITH_REMOTE_OP_ID,
|
||||
+ F_STONITH_CALLOPTS
|
||||
+ };
|
||||
+
|
||||
+ crm_trace("Creating a result reply with%s reply output (rc=%d)",
|
||||
+ (data? "" : "out"), rc);
|
||||
+ for (int lpc = 0; lpc < DIMOF(names); lpc++) {
|
||||
+ name = names[lpc];
|
||||
+ value = crm_element_value(request, name);
|
||||
+ crm_xml_add(reply, name, value);
|
||||
+ }
|
||||
+ if (data != NULL) {
|
||||
+ add_message_xml(reply, F_STONITH_CALLDATA, data);
|
||||
+ }
|
||||
}
|
||||
return reply;
|
||||
}
|
||||
--
|
||||
1.8.3.1
|
||||
|
|
@ -1,85 +0,0 @@
|
|||
From f7389ac6f67804f20393951462a59a0b505dfe03 Mon Sep 17 00:00:00 2001
|
||||
From: Ken Gaillot <kgaillot@redhat.com>
|
||||
Date: Tue, 21 Jul 2020 16:41:18 -0500
|
||||
Subject: [PATCH] Fix: executor: only send executor notifications to executor
|
||||
clients
|
||||
|
||||
This bug has existed since Pacemaker Remote was first implemented, but was
|
||||
hidden until crm_node -l/-p was recently modified to go through controller IPC,
|
||||
because other command-line IPC API clients either fire-and-forget IPC requests
|
||||
or merely count replies, rather than parse the content of replies.
|
||||
|
||||
Previously, when the executor sent notifications of results, it broadcast the
|
||||
notification to all IPC clients. Normally this behavior makes sense, but for
|
||||
the executor in particular, it may be running as pacemaker-remoted, in which
|
||||
case its IPC clients include not only clients that connected to the executor
|
||||
IPC, but clients that connected via proxy to other IPC APIs on the cluster node
|
||||
hosting the remote connection.
|
||||
|
||||
With crm_node -l/-p, this meant that it was possible for an executor API
|
||||
notification to arrive while crm_node was waiting for a controller IPC reply.
|
||||
It would not find the information it needed and would report a protocol
|
||||
violation error.
|
||||
|
||||
The fix is to send executor notifications only to executor clients.
|
||||
---
|
||||
daemons/execd/execd_commands.c | 9 +++++++++
|
||||
daemons/execd/remoted_proxy.c | 5 +++++
|
||||
include/crm/common/ipc_internal.h | 5 +++--
|
||||
3 files changed, 17 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/daemons/execd/execd_commands.c b/daemons/execd/execd_commands.c
|
||||
index aaf2976..685fcc7 100644
|
||||
--- a/daemons/execd/execd_commands.c
|
||||
+++ b/daemons/execd/execd_commands.c
|
||||
@@ -507,6 +507,15 @@ send_client_notify(gpointer key, gpointer value, gpointer user_data)
|
||||
crm_trace("Skipping notification to client without name");
|
||||
return;
|
||||
}
|
||||
+ if (is_set(client->flags, pcmk__client_to_proxy)) {
|
||||
+ /* We only want to notify clients of the executor IPC API. If we are
|
||||
+ * running as Pacemaker Remote, we may have clients proxied to other
|
||||
+ * IPC services in the cluster, so skip those.
|
||||
+ */
|
||||
+ crm_trace("Skipping executor API notification to %s IPC client",
|
||||
+ client->name);
|
||||
+ return;
|
||||
+ }
|
||||
|
||||
rc = lrmd_server_send_notify(client, update_msg);
|
||||
if (rc == pcmk_rc_ok) {
|
||||
diff --git a/daemons/execd/remoted_proxy.c b/daemons/execd/remoted_proxy.c
|
||||
index dda7eed..5c58de4 100644
|
||||
--- a/daemons/execd/remoted_proxy.c
|
||||
+++ b/daemons/execd/remoted_proxy.c
|
||||
@@ -88,6 +88,11 @@ ipc_proxy_accept(qb_ipcs_connection_t * c, uid_t uid, gid_t gid, const char *ipc
|
||||
client->userdata = strdup(ipc_proxy->id);
|
||||
client->name = crm_strdup_printf("proxy-%s-%d-%.8s", ipc_channel, client->pid, client->id);
|
||||
|
||||
+ /* Allow remote executor to distinguish between proxied local clients and
|
||||
+ * actual executor API clients
|
||||
+ */
|
||||
+ set_bit(client->flags, pcmk__client_to_proxy);
|
||||
+
|
||||
g_hash_table_insert(ipc_clients, client->id, client);
|
||||
|
||||
msg = create_xml_node(NULL, T_LRMD_IPC_PROXY);
|
||||
diff --git a/include/crm/common/ipc_internal.h b/include/crm/common/ipc_internal.h
|
||||
index 6a1fcf3..91b3435 100644
|
||||
--- a/include/crm/common/ipc_internal.h
|
||||
+++ b/include/crm/common/ipc_internal.h
|
||||
@@ -121,8 +121,9 @@ struct pcmk__remote_s {
|
||||
};
|
||||
|
||||
enum pcmk__client_flags {
|
||||
- pcmk__client_proxied = 0x00001, /* ipc_proxy code only */
|
||||
- pcmk__client_privileged = 0x00002, /* root or cluster user */
|
||||
+ pcmk__client_proxied = (1 << 0), // Remote client behind proxy
|
||||
+ pcmk__client_privileged = (1 << 1), // root or cluster user
|
||||
+ pcmk__client_to_proxy = (1 << 2), // Local client to be proxied
|
||||
};
|
||||
|
||||
struct pcmk__client_s {
|
||||
--
|
||||
1.8.3.1
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,123 +0,0 @@
|
|||
From 2e7a40570d6b21534ec0215ac5ebc174796cf17c Mon Sep 17 00:00:00 2001
|
||||
From: Ken Gaillot <kgaillot@redhat.com>
|
||||
Date: Thu, 20 Aug 2020 10:02:20 -0500
|
||||
Subject: [PATCH 1/2] Refactor: tools: rename function in cibsecret to be more
|
||||
clear
|
||||
|
||||
It led me to initially misdiagnose a problem.
|
||||
---
|
||||
tools/cibsecret.in | 26 +++++++++++++-------------
|
||||
1 file changed, 13 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/tools/cibsecret.in b/tools/cibsecret.in
|
||||
index 9b74ba3..dabbfc0 100644
|
||||
--- a/tools/cibsecret.in
|
||||
+++ b/tools/cibsecret.in
|
||||
@@ -162,28 +162,28 @@ check_env() {
|
||||
}
|
||||
|
||||
# This must be called (and return success) before calling $rsh or $rcp_to_from
|
||||
-get_live_nodes() {
|
||||
- # Get a list of all cluster nodes
|
||||
+get_live_peers() {
|
||||
+ # Get a list of all other cluster nodes
|
||||
GLN_ALL_NODES="$(crm_node -l | awk '{print $2}' | grep -v "$(uname -n)")"
|
||||
|
||||
# Make a list of those that respond to pings
|
||||
if [ "$(id -u)" = "0" ] && which fping >/dev/null 2>&1; then
|
||||
- LIVE_NODES=$(fping -a $GLN_ALL_NODES 2>/dev/null)
|
||||
+ LIVE_NODES=$(fping -a $GLP_ALL_PEERS 2>/dev/null)
|
||||
else
|
||||
LIVE_NODES=""
|
||||
- for GLN_NODE in $GLN_ALL_NODES; do \
|
||||
- ping -c 2 -q "$GLN_NODE" >/dev/null 2>&1 &&
|
||||
- LIVE_NODES="$LIVE_NODES $GLN_NODE"
|
||||
+ for GLP_NODE in $GLP_ALL_PEERS; do \
|
||||
+ ping -c 2 -q "$GLP_NODE" >/dev/null 2>&1 &&
|
||||
+ LIVE_NODES="$LIVE_NODES $GLP_NODE"
|
||||
done
|
||||
fi
|
||||
|
||||
# Warn the user about any that didn't respond to pings
|
||||
- GLN_DOWN="$( (for GLN_NODE in $LIVE_NODES $GLN_ALL_NODES; do echo "$GLN_NODE"; done) | sort | uniq -u)"
|
||||
- if [ "$(echo "$GLN_DOWN" | wc -w)" = "1" ]; then
|
||||
- warn "node $GLN_DOWN is down"
|
||||
+ GLP_DOWN="$( (for GLP_NODE in $LIVE_NODES $GLP_ALL_PEERS; do echo "$GLP_NODE"; done) | sort | uniq -u)"
|
||||
+ if [ "$(echo "$GLP_DOWN" | wc -w)" = "1" ]; then
|
||||
+ warn "node $GLP_DOWN is down"
|
||||
warn "you'll need to update it using \"$PROG sync\" later"
|
||||
- elif [ -n "$GLN_DOWN" ]; then
|
||||
- warn "nodes $(echo "$GLN_DOWN" | tr '\n' ' ')are down"
|
||||
+ elif [ -n "$GLP_DOWN" ]; then
|
||||
+ warn "nodes $(echo "$GLP_DOWN" | tr '\n' ' ')are down"
|
||||
warn "you'll need to update them using \"$PROG sync\" later"
|
||||
fi
|
||||
|
||||
@@ -235,7 +235,7 @@ scp_fun() {
|
||||
# TODO: this procedure should be replaced with csync2
|
||||
# provided that csync2 has already been configured
|
||||
sync_files() {
|
||||
- get_live_nodes || return
|
||||
+ get_live_peers || return
|
||||
info "syncing $LRM_CIBSECRETS to $(echo "$LIVE_NODES" | tr '\n' ' ') ..."
|
||||
$rsh rm -rf "$LRM_CIBSECRETS" &&
|
||||
$rsh mkdir -p "$(dirname "$LRM_CIBSECRETS")" &&
|
||||
@@ -244,7 +244,7 @@ sync_files() {
|
||||
|
||||
sync_one() {
|
||||
SO_FILE="$1"
|
||||
- get_live_nodes || return
|
||||
+ get_live_peers || return
|
||||
info "syncing $SO_FILE to $(echo "$LIVE_NODES" | tr '\n' ' ') ..."
|
||||
$rsh mkdir -p "$(dirname "$SO_FILE")" &&
|
||||
if [ -f "$SO_FILE" ]; then
|
||||
--
|
||||
1.8.3.1
|
||||
|
||||
|
||||
From 9c1517e6a681f35d62b4714e854b258c17ab5e59 Mon Sep 17 00:00:00 2001
|
||||
From: Ken Gaillot <kgaillot@redhat.com>
|
||||
Date: Thu, 20 Aug 2020 10:03:23 -0500
|
||||
Subject: [PATCH 2/2] Fix: tools: properly detect local node name
|
||||
|
||||
cibsecret had two serious problems when generating a list of other nodes to
|
||||
sync secrets to:
|
||||
|
||||
* It used `uname -n` to remove the local node from the list. If the local node
|
||||
name is different from its uname, this could cause local secrets to be
|
||||
removed from the local node rather than synced to other nodes.
|
||||
|
||||
* It removed not just the local node name, but any node name that contained
|
||||
the local node name as a substring (e.g. "node1" and "node10"). This could
|
||||
cause secrets to not be synced to such nodes.
|
||||
|
||||
Now, use `crm_node -n` to determine the local node name, check crm_node for
|
||||
errors to get better error messages, and remove only the node name that matches
|
||||
the local node name in its entirety.
|
||||
---
|
||||
tools/cibsecret.in | 8 +++++++-
|
||||
1 file changed, 7 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/tools/cibsecret.in b/tools/cibsecret.in
|
||||
index dabbfc0..568833c 100644
|
||||
--- a/tools/cibsecret.in
|
||||
+++ b/tools/cibsecret.in
|
||||
@@ -163,8 +163,14 @@ check_env() {
|
||||
|
||||
# This must be called (and return success) before calling $rsh or $rcp_to_from
|
||||
get_live_peers() {
|
||||
+ # Get local node name
|
||||
+ GLP_LOCAL_NODE="$(crm_node -n)"
|
||||
+ [ $? -eq 0 ] || fatal "couldn't get local node name"
|
||||
+
|
||||
# Get a list of all other cluster nodes
|
||||
- GLN_ALL_NODES="$(crm_node -l | awk '{print $2}' | grep -v "$(uname -n)")"
|
||||
+ GLP_ALL_PEERS="$(crm_node -l)"
|
||||
+ [ $? -eq 0 ] || fatal "couldn't determine cluster nodes"
|
||||
+ GLP_ALL_PEERS="$(echo "$GLP_ALL_PEERS" | awk '{print $2}' | grep -v "^${GLP_LOCAL_NODE}$")"
|
||||
|
||||
# Make a list of those that respond to pings
|
||||
if [ "$(id -u)" = "0" ] && which fping >/dev/null 2>&1; then
|
||||
--
|
||||
1.8.3.1
|
||||
|
|
@ -1,513 +0,0 @@
|
|||
From 3aa33bcc9c70d197b5ed0760b12d65dfab4d4da5 Mon Sep 17 00:00:00 2001
|
||||
From: Ken Gaillot <kgaillot@redhat.com>
|
||||
Date: Fri, 9 Oct 2020 09:56:03 -0500
|
||||
Subject: [PATCH 1/7] Log: executor: show CRM_OP_REGISTER rc in debug message
|
||||
|
||||
Previously, process_lrmd_signon() would add the rc to the client reply
|
||||
but not pass it back to process_lrmd_message(), which would always log "OK" in
|
||||
its debug message, even if the sign-on was rejected.
|
||||
---
|
||||
daemons/execd/execd_commands.c | 21 +++++++++++----------
|
||||
1 file changed, 11 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/daemons/execd/execd_commands.c b/daemons/execd/execd_commands.c
|
||||
index 4d0e457..8487dd4 100644
|
||||
--- a/daemons/execd/execd_commands.c
|
||||
+++ b/daemons/execd/execd_commands.c
|
||||
@@ -1494,10 +1494,10 @@ free_rsc(gpointer data)
|
||||
free(rsc);
|
||||
}
|
||||
|
||||
-static xmlNode *
|
||||
-process_lrmd_signon(pcmk__client_t *client, xmlNode *request, int call_id)
|
||||
+static int
|
||||
+process_lrmd_signon(pcmk__client_t *client, xmlNode *request, int call_id,
|
||||
+ xmlNode **reply)
|
||||
{
|
||||
- xmlNode *reply = NULL;
|
||||
int rc = pcmk_ok;
|
||||
const char *is_ipc_provider = crm_element_value(request, F_LRMD_IS_IPC_PROVIDER);
|
||||
const char *protocol_version = crm_element_value(request, F_LRMD_PROTOCOL_VERSION);
|
||||
@@ -1508,18 +1508,19 @@ process_lrmd_signon(pcmk__client_t *client, xmlNode *request, int call_id)
|
||||
rc = -EPROTO;
|
||||
}
|
||||
|
||||
- reply = create_lrmd_reply(__FUNCTION__, rc, call_id);
|
||||
- crm_xml_add(reply, F_LRMD_OPERATION, CRM_OP_REGISTER);
|
||||
- crm_xml_add(reply, F_LRMD_CLIENTID, client->id);
|
||||
- crm_xml_add(reply, F_LRMD_PROTOCOL_VERSION, LRMD_PROTOCOL_VERSION);
|
||||
-
|
||||
if (crm_is_true(is_ipc_provider)) {
|
||||
// This is a remote connection from a cluster node's controller
|
||||
#ifdef SUPPORT_REMOTE
|
||||
ipc_proxy_add_provider(client);
|
||||
#endif
|
||||
}
|
||||
- return reply;
|
||||
+
|
||||
+ *reply = create_lrmd_reply(__func__, rc, call_id);
|
||||
+ crm_xml_add(*reply, F_LRMD_OPERATION, CRM_OP_REGISTER);
|
||||
+ crm_xml_add(*reply, F_LRMD_CLIENTID, client->id);
|
||||
+ crm_xml_add(*reply, F_LRMD_PROTOCOL_VERSION, LRMD_PROTOCOL_VERSION);
|
||||
+
|
||||
+ return rc;
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -1832,7 +1833,7 @@ process_lrmd_message(pcmk__client_t *client, uint32_t id, xmlNode *request)
|
||||
#endif
|
||||
do_reply = 1;
|
||||
} else if (crm_str_eq(op, CRM_OP_REGISTER, TRUE)) {
|
||||
- reply = process_lrmd_signon(client, request, call_id);
|
||||
+ rc = process_lrmd_signon(client, request, call_id, &reply);
|
||||
do_reply = 1;
|
||||
} else if (crm_str_eq(op, LRMD_OP_RSC_REG, TRUE)) {
|
||||
rc = process_lrmd_rsc_register(client, id, request);
|
||||
--
|
||||
1.8.3.1
|
||||
|
||||
|
||||
From d0002343faa4595e42b790119b7f3037db1130c4 Mon Sep 17 00:00:00 2001
|
||||
From: Ken Gaillot <kgaillot@redhat.com>
|
||||
Date: Fri, 9 Oct 2020 15:16:39 -0500
|
||||
Subject: [PATCH 2/7] Low: executor: mark controller connections to
|
||||
pacemaker-remoted as privileged
|
||||
|
||||
Previously, pcmk__client_privileged was only set when local clients connected
|
||||
(as root or hacluster). Now, set it when pacemaker-remoted successfully
|
||||
completes the TLS handshake with a remote client (i.e., the controller on a
|
||||
cluster node).
|
||||
|
||||
This has no effect as of this commit but will with later commits.
|
||||
---
|
||||
daemons/execd/remoted_tls.c | 5 +++++
|
||||
1 file changed, 5 insertions(+)
|
||||
|
||||
diff --git a/daemons/execd/remoted_tls.c b/daemons/execd/remoted_tls.c
|
||||
index 1a1f8b2..c835549 100644
|
||||
--- a/daemons/execd/remoted_tls.c
|
||||
+++ b/daemons/execd/remoted_tls.c
|
||||
@@ -72,6 +72,11 @@ remoted__read_handshake_data(pcmk__client_t *client)
|
||||
client->remote->tls_handshake_complete = TRUE;
|
||||
crm_notice("Remote client connection accepted");
|
||||
|
||||
+ /* Only a client with access to the TLS key can connect, so we can treat
|
||||
+ * it as privileged.
|
||||
+ */
|
||||
+ set_bit(client->flags, pcmk__client_privileged);
|
||||
+
|
||||
// Alert other clients of the new connection
|
||||
notify_of_new_client(client);
|
||||
return 0;
|
||||
--
|
||||
1.8.3.1
|
||||
|
||||
|
||||
From 3db100d775aee214fff8f54eae0076a5fcc41c56 Mon Sep 17 00:00:00 2001
|
||||
From: Ken Gaillot <kgaillot@redhat.com>
|
||||
Date: Thu, 15 Oct 2020 15:33:13 -0500
|
||||
Subject: [PATCH 3/7] Low: executor: return appropriate error code when no
|
||||
remote support
|
||||
|
||||
---
|
||||
daemons/execd/execd_commands.c | 6 +++++-
|
||||
1 file changed, 5 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/daemons/execd/execd_commands.c b/daemons/execd/execd_commands.c
|
||||
index 8487dd4..41c8169 100644
|
||||
--- a/daemons/execd/execd_commands.c
|
||||
+++ b/daemons/execd/execd_commands.c
|
||||
@@ -1509,9 +1509,11 @@ process_lrmd_signon(pcmk__client_t *client, xmlNode *request, int call_id,
|
||||
}
|
||||
|
||||
if (crm_is_true(is_ipc_provider)) {
|
||||
- // This is a remote connection from a cluster node's controller
|
||||
#ifdef SUPPORT_REMOTE
|
||||
+ // This is a remote connection from a cluster node's controller
|
||||
ipc_proxy_add_provider(client);
|
||||
+#else
|
||||
+ rc = -EPROTONOSUPPORT;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1830,6 +1832,8 @@ process_lrmd_message(pcmk__client_t *client, uint32_t id, xmlNode *request)
|
||||
if (crm_str_eq(op, CRM_OP_IPC_FWD, TRUE)) {
|
||||
#ifdef SUPPORT_REMOTE
|
||||
ipc_proxy_forward_client(client, request);
|
||||
+#else
|
||||
+ rc = -EPROTONOSUPPORT;
|
||||
#endif
|
||||
do_reply = 1;
|
||||
} else if (crm_str_eq(op, CRM_OP_REGISTER, TRUE)) {
|
||||
--
|
||||
1.8.3.1
|
||||
|
||||
|
||||
From f273f1c16f21ff96983797ed5ceb2978dafe545a Mon Sep 17 00:00:00 2001
|
||||
From: Ken Gaillot <kgaillot@redhat.com>
|
||||
Date: Thu, 15 Oct 2020 15:33:57 -0500
|
||||
Subject: [PATCH 4/7] High: executor: restrict certain IPC requests to
|
||||
Pacemaker daemons
|
||||
|
||||
The executor IPC API allows clients to register resources, request agent
|
||||
execution, and so forth.
|
||||
|
||||
If ACLs are enabled, this could allow an ACL-restricted user to bypass ACLs and
|
||||
execute any code as root. (If ACLs are not enabled, users in the haclient group
|
||||
have full access to the CIB, which already gives them that ability, so there is
|
||||
no additional exposure in that case.)
|
||||
|
||||
When ACLs are supported, this commit effectively disables the executor IPC API
|
||||
for clients that aren't connecting as root or hacluster. Such clients can only
|
||||
register and poke now.
|
||||
---
|
||||
daemons/execd/execd_commands.c | 91 +++++++++++++++++++++++++++++++++---------
|
||||
1 file changed, 73 insertions(+), 18 deletions(-)
|
||||
|
||||
diff --git a/daemons/execd/execd_commands.c b/daemons/execd/execd_commands.c
|
||||
index 41c8169..207eb6a 100644
|
||||
--- a/daemons/execd/execd_commands.c
|
||||
+++ b/daemons/execd/execd_commands.c
|
||||
@@ -1510,8 +1510,12 @@ process_lrmd_signon(pcmk__client_t *client, xmlNode *request, int call_id,
|
||||
|
||||
if (crm_is_true(is_ipc_provider)) {
|
||||
#ifdef SUPPORT_REMOTE
|
||||
- // This is a remote connection from a cluster node's controller
|
||||
- ipc_proxy_add_provider(client);
|
||||
+ if ((client->remote != NULL) && client->remote->tls_handshake_complete) {
|
||||
+ // This is a remote connection from a cluster node's controller
|
||||
+ ipc_proxy_add_provider(client);
|
||||
+ } else {
|
||||
+ rc = -EACCES;
|
||||
+ }
|
||||
#else
|
||||
rc = -EPROTONOSUPPORT;
|
||||
#endif
|
||||
@@ -1826,12 +1830,26 @@ process_lrmd_message(pcmk__client_t *client, uint32_t id, xmlNode *request)
|
||||
int do_notify = 0;
|
||||
xmlNode *reply = NULL;
|
||||
|
||||
+ bool allowed = true;
|
||||
+
|
||||
+#if ENABLE_ACL
|
||||
+ /* Certain IPC commands may be done only by privileged users (i.e. root or
|
||||
+ * hacluster) when ACLs are enabled, because they would otherwise provide a
|
||||
+ * means of bypassing ACLs.
|
||||
+ */
|
||||
+ allowed = is_set(client->flags, pcmk__client_privileged);
|
||||
+#endif
|
||||
+
|
||||
crm_trace("Processing %s operation from %s", op, client->id);
|
||||
crm_element_value_int(request, F_LRMD_CALLID, &call_id);
|
||||
|
||||
if (crm_str_eq(op, CRM_OP_IPC_FWD, TRUE)) {
|
||||
#ifdef SUPPORT_REMOTE
|
||||
- ipc_proxy_forward_client(client, request);
|
||||
+ if (allowed) {
|
||||
+ ipc_proxy_forward_client(client, request);
|
||||
+ } else {
|
||||
+ rc = -EACCES;
|
||||
+ }
|
||||
#else
|
||||
rc = -EPROTONOSUPPORT;
|
||||
#endif
|
||||
@@ -1840,38 +1858,70 @@ process_lrmd_message(pcmk__client_t *client, uint32_t id, xmlNode *request)
|
||||
rc = process_lrmd_signon(client, request, call_id, &reply);
|
||||
do_reply = 1;
|
||||
} else if (crm_str_eq(op, LRMD_OP_RSC_REG, TRUE)) {
|
||||
- rc = process_lrmd_rsc_register(client, id, request);
|
||||
- do_notify = 1;
|
||||
+ if (allowed) {
|
||||
+ rc = process_lrmd_rsc_register(client, id, request);
|
||||
+ do_notify = 1;
|
||||
+ } else {
|
||||
+ rc = -EACCES;
|
||||
+ }
|
||||
do_reply = 1;
|
||||
} else if (crm_str_eq(op, LRMD_OP_RSC_INFO, TRUE)) {
|
||||
- reply = process_lrmd_get_rsc_info(request, call_id);
|
||||
+ if (allowed) {
|
||||
+ reply = process_lrmd_get_rsc_info(request, call_id);
|
||||
+ } else {
|
||||
+ rc = -EACCES;
|
||||
+ }
|
||||
do_reply = 1;
|
||||
} else if (crm_str_eq(op, LRMD_OP_RSC_UNREG, TRUE)) {
|
||||
- rc = process_lrmd_rsc_unregister(client, id, request);
|
||||
- /* don't notify anyone about failed un-registers */
|
||||
- if (rc == pcmk_ok || rc == -EINPROGRESS) {
|
||||
- do_notify = 1;
|
||||
+ if (allowed) {
|
||||
+ rc = process_lrmd_rsc_unregister(client, id, request);
|
||||
+ /* don't notify anyone about failed un-registers */
|
||||
+ if (rc == pcmk_ok || rc == -EINPROGRESS) {
|
||||
+ do_notify = 1;
|
||||
+ }
|
||||
+ } else {
|
||||
+ rc = -EACCES;
|
||||
}
|
||||
do_reply = 1;
|
||||
} else if (crm_str_eq(op, LRMD_OP_RSC_EXEC, TRUE)) {
|
||||
- rc = process_lrmd_rsc_exec(client, id, request);
|
||||
+ if (allowed) {
|
||||
+ rc = process_lrmd_rsc_exec(client, id, request);
|
||||
+ } else {
|
||||
+ rc = -EACCES;
|
||||
+ }
|
||||
do_reply = 1;
|
||||
} else if (crm_str_eq(op, LRMD_OP_RSC_CANCEL, TRUE)) {
|
||||
- rc = process_lrmd_rsc_cancel(client, id, request);
|
||||
+ if (allowed) {
|
||||
+ rc = process_lrmd_rsc_cancel(client, id, request);
|
||||
+ } else {
|
||||
+ rc = -EACCES;
|
||||
+ }
|
||||
do_reply = 1;
|
||||
} else if (crm_str_eq(op, LRMD_OP_POKE, TRUE)) {
|
||||
do_notify = 1;
|
||||
do_reply = 1;
|
||||
} else if (crm_str_eq(op, LRMD_OP_CHECK, TRUE)) {
|
||||
- xmlNode *data = get_message_xml(request, F_LRMD_CALLDATA);
|
||||
- const char *timeout = crm_element_value(data, F_LRMD_WATCHDOG);
|
||||
- CRM_LOG_ASSERT(data != NULL);
|
||||
- pcmk__valid_sbd_timeout(timeout);
|
||||
+ if (allowed) {
|
||||
+ xmlNode *data = get_message_xml(request, F_LRMD_CALLDATA);
|
||||
+
|
||||
+ CRM_LOG_ASSERT(data != NULL);
|
||||
+ pcmk__valid_sbd_timeout(crm_element_value(data, F_LRMD_WATCHDOG));
|
||||
+ } else {
|
||||
+ rc = -EACCES;
|
||||
+ }
|
||||
} else if (crm_str_eq(op, LRMD_OP_ALERT_EXEC, TRUE)) {
|
||||
- rc = process_lrmd_alert_exec(client, id, request);
|
||||
+ if (allowed) {
|
||||
+ rc = process_lrmd_alert_exec(client, id, request);
|
||||
+ } else {
|
||||
+ rc = -EACCES;
|
||||
+ }
|
||||
do_reply = 1;
|
||||
} else if (crm_str_eq(op, LRMD_OP_GET_RECURRING, TRUE)) {
|
||||
- reply = process_lrmd_get_recurring(request, call_id);
|
||||
+ if (allowed) {
|
||||
+ reply = process_lrmd_get_recurring(request, call_id);
|
||||
+ } else {
|
||||
+ rc = -EACCES;
|
||||
+ }
|
||||
do_reply = 1;
|
||||
} else {
|
||||
rc = -EOPNOTSUPP;
|
||||
@@ -1879,6 +1929,11 @@ process_lrmd_message(pcmk__client_t *client, uint32_t id, xmlNode *request)
|
||||
crm_err("Unknown IPC request '%s' from %s", op, client->name);
|
||||
}
|
||||
|
||||
+ if (rc == -EACCES) {
|
||||
+ crm_warn("Rejecting IPC request '%s' from unprivileged client %s",
|
||||
+ op, pcmk__client_name(client));
|
||||
+ }
|
||||
+
|
||||
crm_debug("Processed %s operation from %s: rc=%d, reply=%d, notify=%d",
|
||||
op, client->id, rc, do_reply, do_notify);
|
||||
|
||||
--
|
||||
1.8.3.1
|
||||
|
||||
|
||||
From f13759f6971402dac3bea1aac45214a84d838728 Mon Sep 17 00:00:00 2001
|
||||
From: Ken Gaillot <kgaillot@redhat.com>
|
||||
Date: Fri, 9 Oct 2020 11:16:43 -0500
|
||||
Subject: [PATCH 5/7] Low: pacemakerd: check client for NULL before using it
|
||||
|
||||
... to guard against bugs in client tracking
|
||||
---
|
||||
daemons/pacemakerd/pacemakerd.c | 5 ++++-
|
||||
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/daemons/pacemakerd/pacemakerd.c b/daemons/pacemakerd/pacemakerd.c
|
||||
index 5ed4626..573ea5a 100644
|
||||
--- a/daemons/pacemakerd/pacemakerd.c
|
||||
+++ b/daemons/pacemakerd/pacemakerd.c
|
||||
@@ -553,9 +553,12 @@ pcmk_ipc_dispatch(qb_ipcs_connection_t * qbc, void *data, size_t size)
|
||||
uint32_t id = 0;
|
||||
uint32_t flags = 0;
|
||||
const char *task = NULL;
|
||||
+ xmlNode *msg = NULL;
|
||||
pcmk__client_t *c = pcmk__find_client(qbc);
|
||||
- xmlNode *msg = pcmk__client_data2xml(c, data, &id, &flags);
|
||||
|
||||
+ CRM_CHECK(c != NULL, return 0);
|
||||
+
|
||||
+ msg = pcmk__client_data2xml(c, data, &id, &flags);
|
||||
pcmk__ipc_send_ack(c, id, flags, "ack");
|
||||
if (msg == NULL) {
|
||||
return 0;
|
||||
--
|
||||
1.8.3.1
|
||||
|
||||
|
||||
From 021081c1e28b254a0f68143fa55e517f0fcc4edb Mon Sep 17 00:00:00 2001
|
||||
From: Ken Gaillot <kgaillot@redhat.com>
|
||||
Date: Fri, 9 Oct 2020 11:17:18 -0500
|
||||
Subject: [PATCH 6/7] High: pacemakerd: ignore shutdown requests from
|
||||
unprivileged users
|
||||
|
||||
The pacemakerd IPC API supports a shutdown request, along with a
|
||||
command-line interface for using it (pacemakerd --shutdown).
|
||||
|
||||
Only the haclient group has access to the IPC. Without ACLs, that group can
|
||||
already shut down Pacemaker via the CIB, so there's no security implication.
|
||||
|
||||
However, it might not be desired to allow ACL-restricted users to shut down
|
||||
Pacemaker, so block users other than root or hacluster if ACLs are supported.
|
||||
---
|
||||
daemons/pacemakerd/pacemakerd.c | 24 ++++++++++++++++++++----
|
||||
1 file changed, 20 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/daemons/pacemakerd/pacemakerd.c b/daemons/pacemakerd/pacemakerd.c
|
||||
index 573ea5a..2e69bd1 100644
|
||||
--- a/daemons/pacemakerd/pacemakerd.c
|
||||
+++ b/daemons/pacemakerd/pacemakerd.c
|
||||
@@ -566,9 +566,26 @@ pcmk_ipc_dispatch(qb_ipcs_connection_t * qbc, void *data, size_t size)
|
||||
|
||||
task = crm_element_value(msg, F_CRM_TASK);
|
||||
if (crm_str_eq(task, CRM_OP_QUIT, TRUE)) {
|
||||
- crm_notice("Shutting down in response to IPC request %s from %s",
|
||||
- crm_element_value(msg, F_CRM_REFERENCE), crm_element_value(msg, F_CRM_ORIGIN));
|
||||
- pcmk_shutdown(15);
|
||||
+ bool allowed = true;
|
||||
+
|
||||
+#if ENABLE_ACL
|
||||
+ /* Only allow privileged users (i.e. root or hacluster)
|
||||
+ * to shut down Pacemaker from the command line (or direct IPC).
|
||||
+ *
|
||||
+ * We only check when ACLs are enabled, because without them, any client
|
||||
+ * with IPC access could shut down Pacemaker via the CIB anyway.
|
||||
+ */
|
||||
+ allowed = is_set(c->flags, pcmk__client_privileged);
|
||||
+#endif
|
||||
+ if (allowed) {
|
||||
+ crm_notice("Shutting down in response to IPC request %s from %s",
|
||||
+ crm_element_value(msg, F_CRM_REFERENCE),
|
||||
+ crm_element_value(msg, F_CRM_ORIGIN));
|
||||
+ pcmk_shutdown(15);
|
||||
+ } else {
|
||||
+ crm_warn("Ignoring shutdown request from unprivileged client %s",
|
||||
+ pcmk__client_name(c));
|
||||
+ }
|
||||
|
||||
} else if (crm_str_eq(task, CRM_OP_RM_NODE_CACHE, TRUE)) {
|
||||
crm_trace("Ignoring IPC request to purge node "
|
||||
--
|
||||
1.8.3.1
|
||||
|
||||
|
||||
From 80eb5ddfd529be02214f38669f1b177535186fbc Mon Sep 17 00:00:00 2001
|
||||
From: Ken Gaillot <kgaillot@redhat.com>
|
||||
Date: Fri, 9 Oct 2020 11:55:26 -0500
|
||||
Subject: [PATCH 7/7] Fix: fencer: restrict certain IPC requests to privileged
|
||||
users
|
||||
|
||||
The fencer IPC API allows clients to register fence devices.
|
||||
|
||||
If ACLs are enabled, this could allow an ACL-restricted user to bypass ACLs to
|
||||
configure fencing. If the user is able to install executables to the standard
|
||||
fencing agent locations, have arbitrary code executed as root (the standard
|
||||
locations generally require root for write access, so that is unlikely to be an
|
||||
issue).
|
||||
|
||||
If ACLs are not enabled, users in the haclient group have full access to the
|
||||
CIB, which already gives them these capabilities, so there is no additional
|
||||
exposure in that case.
|
||||
|
||||
This commit does not restrict unprivileged users from using other fencing API,
|
||||
such as requesting actual fencing.
|
||||
---
|
||||
daemons/fenced/fenced_commands.c | 41 ++++++++++++++++++++++++++++++++++++----
|
||||
1 file changed, 37 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/daemons/fenced/fenced_commands.c b/daemons/fenced/fenced_commands.c
|
||||
index 859e7b7..a8c90a6 100644
|
||||
--- a/daemons/fenced/fenced_commands.c
|
||||
+++ b/daemons/fenced/fenced_commands.c
|
||||
@@ -2531,6 +2531,18 @@ handle_request(pcmk__client_t *client, uint32_t id, uint32_t flags,
|
||||
const char *op = crm_element_value(request, F_STONITH_OPERATION);
|
||||
const char *client_id = crm_element_value(request, F_STONITH_CLIENTID);
|
||||
|
||||
+ bool allowed = true;
|
||||
+
|
||||
+#if ENABLE_ACL
|
||||
+ /* IPC commands related to fencing configuration may be done only by
|
||||
+ * privileged users (i.e. root or hacluster) when ACLs are supported,
|
||||
+ * because all other users should go through the CIB to have ACLs applied.
|
||||
+ */
|
||||
+ if (client != NULL) {
|
||||
+ allowed = is_set(client->flags, pcmk__client_privileged);
|
||||
+ }
|
||||
+#endif
|
||||
+
|
||||
crm_element_value_int(request, F_STONITH_CALLOPTS, &call_options);
|
||||
|
||||
if (is_set(call_options, st_opt_sync_call)) {
|
||||
@@ -2687,27 +2699,43 @@ handle_request(pcmk__client_t *client, uint32_t id, uint32_t flags,
|
||||
} else if (crm_str_eq(op, STONITH_OP_DEVICE_ADD, TRUE)) {
|
||||
const char *device_id = NULL;
|
||||
|
||||
- rc = stonith_device_register(request, &device_id, FALSE);
|
||||
+ if (allowed) {
|
||||
+ rc = stonith_device_register(request, &device_id, FALSE);
|
||||
+ } else {
|
||||
+ rc = -EACCES;
|
||||
+ }
|
||||
do_stonith_notify_device(call_options, op, rc, device_id);
|
||||
|
||||
} else if (crm_str_eq(op, STONITH_OP_DEVICE_DEL, TRUE)) {
|
||||
xmlNode *dev = get_xpath_object("//" F_STONITH_DEVICE, request, LOG_ERR);
|
||||
const char *device_id = crm_element_value(dev, XML_ATTR_ID);
|
||||
|
||||
- rc = stonith_device_remove(device_id, FALSE);
|
||||
+ if (allowed) {
|
||||
+ rc = stonith_device_remove(device_id, FALSE);
|
||||
+ } else {
|
||||
+ rc = -EACCES;
|
||||
+ }
|
||||
do_stonith_notify_device(call_options, op, rc, device_id);
|
||||
|
||||
} else if (crm_str_eq(op, STONITH_OP_LEVEL_ADD, TRUE)) {
|
||||
char *device_id = NULL;
|
||||
|
||||
- rc = stonith_level_register(request, &device_id);
|
||||
+ if (allowed) {
|
||||
+ rc = stonith_level_register(request, &device_id);
|
||||
+ } else {
|
||||
+ rc = -EACCES;
|
||||
+ }
|
||||
do_stonith_notify_level(call_options, op, rc, device_id);
|
||||
free(device_id);
|
||||
|
||||
} else if (crm_str_eq(op, STONITH_OP_LEVEL_DEL, TRUE)) {
|
||||
char *device_id = NULL;
|
||||
|
||||
- rc = stonith_level_remove(request, &device_id);
|
||||
+ if (allowed) {
|
||||
+ rc = stonith_level_remove(request, &device_id);
|
||||
+ } else {
|
||||
+ rc = -EACCES;
|
||||
+ }
|
||||
do_stonith_notify_level(call_options, op, rc, device_id);
|
||||
|
||||
} else if(safe_str_eq(op, CRM_OP_RM_NODE_CACHE)) {
|
||||
@@ -2727,6 +2755,11 @@ handle_request(pcmk__client_t *client, uint32_t id, uint32_t flags,
|
||||
|
||||
done:
|
||||
|
||||
+ if (rc == -EACCES) {
|
||||
+ crm_warn("Rejecting IPC request '%s' from unprivileged client %s",
|
||||
+ crm_str(op), pcmk__client_name(client));
|
||||
+ }
|
||||
+
|
||||
/* Always reply unless the request is in process still.
|
||||
* If in progress, a reply will happen async after the request
|
||||
* processing is finished */
|
||||
--
|
||||
1.8.3.1
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue