Page Menu
Home
ClusterLabs Projects
Search
Configure Global Search
Log In
Files
F5519293
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
28 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/cts/cts-attrd.in b/cts/cts-attrd.in
index b594ac3c3d..c9a219d326 100644
--- a/cts/cts-attrd.in
+++ b/cts/cts-attrd.in
@@ -1,367 +1,367 @@
#!@PYTHON@
""" Regression tests for Pacemaker's attribute daemon
"""
# pylint doesn't like the module name "cts-attrd" which is an invalid complaint for this file
# but probably something we want to continue warning about elsewhere
# pylint: disable=invalid-name
# pacemaker imports need to come after we modify sys.path, which pylint will complain about.
# pylint: disable=wrong-import-position
__copyright__ = "Copyright 2023 the Pacemaker project contributors"
__license__ = "GNU General Public License version 2 or later (GPLv2+) WITHOUT ANY WARRANTY"
import argparse
import os
import subprocess
import sys
import tempfile
# These imports allow running from a source checkout after running `make`.
# Note that while this doesn't necessarily mean it will successfully run tests,
# but being able to see --help output can be useful.
if os.path.exists("@abs_top_srcdir@/python"):
sys.path.insert(0, "@abs_top_srcdir@/python")
# pylint: disable=comparison-of-constants,comparison-with-itself,condition-evals-to-constant
if os.path.exists("@abs_top_builddir@/python") and "@abs_top_builddir@" != "@abs_top_srcdir@":
sys.path.insert(0, "@abs_top_builddir@/python")
from pacemaker.buildoptions import BuildOptions
from pacemaker.exitstatus import ExitStatus
from pacemaker._cts.corosync import Corosync
from pacemaker._cts.process import killall, exit_if_proc_running
from pacemaker._cts.test import Test, Tests
TEST_DIR = sys.path[0]
def update_path():
""" Set the PATH environment variable appropriately for the tests """
new_path = os.environ['PATH']
if os.path.exists("%s/cts-attrd.in" % TEST_DIR):
# pylint: disable=protected-access
print("Running tests from the source tree: %s (%s)" % (BuildOptions._BUILD_DIR, TEST_DIR))
# For pacemaker-attrd
new_path = "%s/daemons/attrd:%s" % (BuildOptions._BUILD_DIR, new_path)
else:
print("Running tests from the install tree: %s (not %s)" % (BuildOptions.DAEMON_DIR, TEST_DIR))
# For pacemaker-attrd
new_path = "%s:%s" % (BuildOptions.DAEMON_DIR, new_path)
print('Using PATH="%s"' % new_path)
os.environ['PATH'] = new_path
class AttributeTest(Test):
""" Executor for a single test """
def __init__(self, name, description, **kwargs):
Test.__init__(self, name, description, **kwargs)
self._daemon_location = "pacemaker-attrd"
self._enable_corosync = True
def _kill_daemons(self):
killall([self._daemon_location])
def _start_daemons(self):
if self.verbose:
print("Starting %s" % self._daemon_location)
cmd = [self._daemon_location, "-s", "-l", self.logpath]
# pylint: disable=consider-using-with
self._daemon_process = subprocess.Popen(cmd)
class AttributeTests(Tests):
""" Collection of all attribute regression tests """
def __init__(self, **kwargs):
Tests.__init__(self, **kwargs)
self._corosync = Corosync(self.verbose, self.logdir, "cts-attrd")
def new_test(self, name, description):
""" Create a named test """
test = AttributeTest(name, description, verbose=self.verbose, logdir=self.logdir)
self._tests.append(test)
return test
def setup_environment(self, use_corosync):
""" Prepare the host before executing any tests """
if use_corosync:
self._corosync.start(kill_first=True)
def cleanup_environment(self, use_corosync):
""" Clean up the host after executing desired tests """
if use_corosync:
self._corosync.stop()
def build_basic_tests(self):
""" Add basic tests - setting, querying, updating, and deleting attributes """
test = self.new_test("set_attr_1",
"Set and query an attribute")
test.add_cmd("attrd_updater", "--name AAA -U 111 --output-as=xml")
test.add_cmd_check_stdout("attrd_updater", "--name AAA -Q --output-as=xml",
"name=\"AAA\" value=\"111\"")
test.add_log_pattern(r"Setting AAA\[.*\] in instance_attributes: \(unset\) -> 111",
regex=True)
# Setting the delay on an attribute that doesn't exist fails, but the failure is
# not passed back to attrd_updater.
test = self.new_test("set_attr_2",
"Set an attribute's delay")
test.add_cmd("attrd_updater", "--name AAA -Y -d 5 --output-as=xml")
test.add_log_pattern(r"Processed update-delay request from client .*: Error \(Attribute AAA does not exist\)",
regex=True)
test = self.new_test("set_attr_3",
"Set and query an attribute's delay and value")
test.add_cmd("attrd_updater", "--name AAA -B 111 -d 5 --output-as=xml")
test.add_cmd_check_stdout("attrd_updater", "--name AAA -Q --output-as=xml",
"name=\"AAA\" value=\"111\"")
test.add_log_pattern(r"Setting AAA\[.*\] in instance_attributes: \(unset\) -> 111 \| from .* with 5s write delay",
regex=True)
test = self.new_test("set_attr_4",
"Update an attribute that does not exist with a delay")
test.add_cmd("attrd_updater", "--name BBB -U 999 -d 10 --output-as=xml")
test.add_cmd_check_stdout("attrd_updater", "--name BBB -Q --output-as=xml",
"name=\"BBB\" value=\"999\"")
test.add_log_pattern(r"Setting BBB\[.*\] in instance_attributes: \(unset\) -> 999 \| from .* with 10s write delay",
regex=True)
test = self.new_test("update_attr_1",
"Update an attribute that already exists")
test.add_cmd("attrd_updater", "--name BBB -U 222 --output-as=xml")
test.add_cmd("attrd_updater", "--name BBB -U 333 --output-as=xml")
test.add_cmd_check_stdout("attrd_updater", "--name BBB -Q --output-as=xml",
"name=\"BBB\" value=\"333\"")
test.add_log_pattern(r"Setting BBB\[.*\] in instance_attributes: \(unset\) -> 222",
regex=True)
test.add_log_pattern(r"Setting BBB\[.*\] in instance_attributes: 222 -> 333",
regex=True)
test = self.new_test("update_attr_2",
"Update an attribute using a delay other than its default")
test.add_cmd("attrd_updater", "--name BBB -U 777 -d 10 --output-as=xml")
test.add_cmd("attrd_updater", "--name BBB -U 888 -d 7 --output-as=xml")
test.add_log_pattern(r"Setting BBB\[.*\] in instance_attributes: 777 -> 888 \| from .* with 10s write delay",
regex=True)
test = self.new_test("update_attr_delay_1",
"Update the delay of an attribute that already exists")
test.add_cmd("attrd_updater", "--name BBB -U 222 --output-as=xml")
test.add_cmd("attrd_updater", "--name BBB -Y -d 5 --output-as=xml")
test.add_log_pattern(r"Setting BBB\[.*\] in instance_attributes: \(unset\) -> 222",
regex=True)
test.add_log_pattern("Update attribute BBB delay to 5000ms (5)")
test = self.new_test("update_attr_delay_2",
"Update the delay and value of an attribute that already exists")
test.add_cmd("attrd_updater", "--name BBB -U 222 --output-as=xml")
test.add_cmd("attrd_updater", "--name BBB -B 333 -d 5 --output-as=xml")
test.add_log_pattern(r"Setting BBB\[.*\] in instance_attributes: \(unset\) -> 222",
regex=True)
test.add_log_pattern("Update attribute BBB delay to 5000ms (5)")
test.add_log_pattern(r"Setting BBB\[.*\] in instance_attributes: 222 -> 333",
regex=True)
test = self.new_test("missing_attr_1",
"Query an attribute that does not exist")
test.add_cmd_expected_fail("attrd_updater", "--name NOSUCH --output-as=xml",
ExitStatus.CONFIG)
test = self.new_test("delete_attr_1",
"Delete an existing attribute")
test.add_cmd("attrd_updater", "--name CCC -U 444 --output-as=xml")
test.add_cmd("attrd_updater", "--name CCC -D --output-as=xml")
test.add_log_pattern(r"Setting CCC\[.*\] in instance_attributes: \(unset\) -> 444",
regex=True)
test.add_log_pattern(r"Setting CCC\[.*\] in instance_attributes: 444 -> \(unset\)",
regex=True)
test = self.new_test("missing_attr_2",
"Delete an attribute that does not exist")
test.add_cmd("attrd_updater", "--name NOSUCH2 -D --output-as=xml")
test = self.new_test("attr_in_set_1",
"Set and query an attribute in a specific set")
test.add_cmd("attrd_updater", "--name DDD -U 555 --set=foo --output-as=xml")
test.add_cmd_check_stdout("attrd_updater", "--name DDD -Q --output-as=xml",
"name=\"DDD\" value=\"555\"")
- test.add_log_pattern("Processed 1 private change for DDD, id=n/a, set=foo")
+ test.add_log_pattern("Processed 1 private change for DDD (set foo)")
def build_multiple_query_tests(self):
""" Add tests that set and query an attribute across multiple nodes """
# NOTE: These tests make use of the fact that nothing in attrd actually
# cares about whether a node exists when you set or query an attribute.
# It just keeps creating new hash tables for each node you ask it about.
test = self.new_test("multi_query_1",
"Query an attribute set across multiple nodes")
test.add_cmd("attrd_updater", "--name AAA -U 111 --node cluster1 --output-as=xml")
test.add_cmd("attrd_updater", "--name AAA -U 222 --node cluster2 --output-as=xml")
test.add_cmd_check_stdout("attrd_updater", "--name AAA -QA --output-as=xml",
r"""<attribute name="AAA" value="111" host="cluster1"/>\n.*<attribute name="AAA" value="222" host="cluster2"/>""")
test.add_cmd_check_stdout("attrd_updater", "--name AAA -Q --node=cluster1 --output-as=xml",
"""<attribute name="AAA" value="111" host="cluster1"/>""")
test.add_cmd_check_stdout("attrd_updater", "--name AAA -Q --node=cluster2 --output-as=xml",
"""<attribute name="AAA" value="222" host="cluster2"/>""")
test.add_cmd_check_stdout("attrd_updater", "--name AAA -QA --output-as=xml",
r"""<attribute name="AAA" value="111" host="cluster1"/>\n.*<attribute name="AAA" value="222" host="cluster2"/>""",
env={"OCF_RESKEY_CRM_meta_on_node": "cluster1"})
test.add_cmd_check_stdout("attrd_updater", "--name AAA -Q --output-as=xml",
"""<attribute name="AAA" value="111" host="cluster1"/>""",
env={"OCF_RESKEY_CRM_meta_on_node": "cluster1"})
test.add_cmd_check_stdout("attrd_updater", "--name AAA -Q --node=cluster2 --output-as=xml",
"""<attribute name="AAA" value="222" host="cluster2"/>""",
env={"OCF_RESKEY_CRM_meta_on_node": "cluster1"})
def build_regex_tests(self):
""" Add tests that use regexes """
test = self.new_test("regex_update_1",
"Update attributes using a regex")
test.add_cmd("attrd_updater", "--name AAA -U 111 --output-as=xml")
test.add_cmd("attrd_updater", "--name ABB -U 222 --output-as=xml")
test.add_cmd("attrd_updater", "-P 'A.*' -U 333 --output-as=xml")
test.add_cmd_check_stdout("attrd_updater", "--name AAA -Q --output-as=xml",
"name=\"AAA\" value=\"333\"")
test.add_cmd_check_stdout("attrd_updater", "--name ABB -Q --output-as=xml",
"name=\"ABB\" value=\"333\"")
test.add_log_pattern(r"Setting AAA\[.*\] in instance_attributes: \(unset\) -> 111",
regex=True)
test.add_log_pattern(r"Setting ABB\[.*\] in instance_attributes: \(unset\) -> 222",
regex=True)
test.add_log_pattern(r"Setting ABB\[.*\] in instance_attributes: 222 -> 333",
regex=True)
test.add_log_pattern(r"Setting AAA\[.*\] in instance_attributes: 111 -> 333",
regex=True)
test = self.new_test("regex_delete_1",
"Delete attributes using a regex")
test.add_cmd("attrd_updater", "--name XAX -U 444 --output-as=xml")
test.add_cmd("attrd_updater", "--name XBX -U 555 --output-as=xml")
test.add_cmd("attrd_updater", "-P 'X[A|B]X' -D --output-as=xml")
test.add_log_pattern(r"Setting XAX\[.*\] in instance_attributes: \(unset\) -> 444",
regex=True)
test.add_log_pattern(r"Setting XBX\[.*\] in instance_attributes: \(unset\) -> 555",
regex=True)
test.add_log_pattern(r"Setting XBX\[.*\] in instance_attributes: 555 -> \(unset\)",
regex=True)
test.add_log_pattern(r"Setting XAX\[.*\] in instance_attributes: 444 -> \(unset\)",
regex=True)
def build_utilization_tests(self):
""" Add tests that involve utilization attributes """
test = self.new_test("utilization_1",
"Set and query a utilization attribute")
test.add_cmd("attrd_updater", "--name AAA -U ABC -z --output-as=xml")
test.add_cmd_check_stdout("attrd_updater", "--name AAA -Q --output-as=xml",
"name=\"AAA\" value=\"ABC\"")
test.add_log_pattern(r"Setting AAA\[.*\] in utilization: \(unset\) -> ABC",
regex=True)
def build_sync_point_tests(self):
""" Add tests that involve sync points """
test = self.new_test("local_sync_point",
"Wait for a local sync point")
test.add_cmd("attrd_updater", "--name AAA -U 123 --wait=local --output-as=xml")
test.add_cmd_check_stdout("attrd_updater", "--name AAA -Q --output-as=xml",
"name=\"AAA\" value=\"123\"")
test.add_log_pattern(r"Alerting client .* for reached local sync point",
regex=True)
test = self.new_test("cluster_sync_point",
"Wait for a cluster-wide sync point")
test.add_cmd("attrd_updater", "--name BBB -U 456 --wait=cluster --output-as=xml")
test.add_cmd_check_stdout("attrd_updater", "--name BBB -Q --output-as=xml",
"name=\"BBB\" value=\"456\"")
test.add_log_pattern(r"Alerting client .* for reached cluster sync point",
regex=True)
def build_options():
""" Handle command line arguments """
parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter,
description="Run pacemaker-attrd regression tests",
epilog="Example: Run only the test 'start_stop'\n"
"\t " + sys.argv[0] + " --run-only start_stop\n\n"
"Example: Run only the tests with the string 'systemd' present in them\n"
"\t " + sys.argv[0] + " --run-only-pattern systemd")
parser.add_argument("-l", "--list-tests", action="store_true",
help="Print out all registered tests")
parser.add_argument("-p", "--run-only-pattern", metavar='PATTERN',
help="Run only tests matching the given pattern")
parser.add_argument("-r", "--run-only", metavar='TEST',
help="Run a specific test")
parser.add_argument("-V", "--verbose", action="store_true",
help="Verbose output")
args = parser.parse_args()
return args
def main():
""" Run attrd regression tests as specified by arguments """
update_path()
# Ensure all command output is in portable locale for comparison
os.environ['LC_ALL'] = "C"
opts = build_options()
exit_if_proc_running("pacemaker-attrd")
# Create a temporary directory for log files (the directory and its
# contents will automatically be erased when done)
with tempfile.TemporaryDirectory(prefix="cts-attrd-") as logdir:
tests = AttributeTests(verbose=opts.verbose, logdir=logdir)
tests.build_basic_tests()
tests.build_multiple_query_tests()
tests.build_regex_tests()
tests.build_utilization_tests()
tests.build_sync_point_tests()
if opts.list_tests:
tests.print_list()
sys.exit(ExitStatus.OK)
print("Starting ...")
try:
tests.setup_environment(True)
except TimeoutError:
print("corosync did not start in time, exiting")
sys.exit(ExitStatus.TIMEOUT)
if opts.run_only_pattern:
tests.run_tests_matching(opts.run_only_pattern)
tests.print_results()
elif opts.run_only:
tests.run_single(opts.run_only)
tests.print_results()
else:
tests.run_tests()
tests.print_results()
tests.cleanup_environment(True)
tests.exit()
if __name__ == "__main__":
main()
diff --git a/daemons/attrd/pacemaker-attrd.h b/daemons/attrd/pacemaker-attrd.h
index 57ce93d429..2e05919bc3 100644
--- a/daemons/attrd/pacemaker-attrd.h
+++ b/daemons/attrd/pacemaker-attrd.h
@@ -1,255 +1,253 @@
/*
* Copyright 2013-2024 the Pacemaker project contributors
*
* The version control history for this file may have further details.
*
* This source code is licensed under the GNU General Public License version 2
* or later (GPLv2+) WITHOUT ANY WARRANTY.
*/
#ifndef PACEMAKER_ATTRD__H
# define PACEMAKER_ATTRD__H
#include <regex.h>
#include <glib.h>
#include <crm/crm.h>
#include <crm/cluster.h>
#include <crm/cluster/election_internal.h>
#include <crm/common/messages_internal.h>
#include <crm/cib/cib_types.h>
/*
* Legacy attrd (all pre-1.1.11 Pacemaker versions, plus all versions when used
* with the no-longer-supported CMAN or corosync-plugin stacks) is unversioned.
*
* With atomic attrd, each attrd will send ATTRD_PROTOCOL_VERSION with every
* peer request and reply. As of Pacemaker 2.0.0, at start-up each attrd will
* also set a private attribute for itself with its version, so any attrd can
* determine the minimum version supported by all peers.
*
* Protocol Pacemaker Significant changes
* -------- --------- -------------------
* 1 1.1.11 PCMK__ATTRD_CMD_UPDATE (PCMK__XA_ATTR_NAME only),
* PCMK__ATTRD_CMD_PEER_REMOVE, PCMK__ATTRD_CMD_REFRESH,
* PCMK__ATTRD_CMD_FLUSH, PCMK__ATTRD_CMD_SYNC_RESPONSE
* 1 1.1.13 PCMK__ATTRD_CMD_UPDATE (with PCMK__XA_ATTR_REGEX),
* PCMK__ATTRD_CMD_QUERY
* 1 1.1.15 PCMK__ATTRD_CMD_UPDATE_BOTH,
* PCMK__ATTRD_CMD_UPDATE_DELAY
* 2 1.1.17 PCMK__ATTRD_CMD_CLEAR_FAILURE
* 3 2.1.1 PCMK__ATTRD_CMD_SYNC_RESPONSE indicates remote nodes
* 4 2.1.5 Multiple attributes can be updated in a single IPC
* message
* 5 2.1.5 Peers can request confirmation of a sent message
* 6 2.1.7 PCMK__ATTRD_CMD_PEER_REMOVE supports PCMK__XA_REAP
*/
#define ATTRD_PROTOCOL_VERSION "6"
#define ATTRD_SUPPORTS_MULTI_MESSAGE(x) ((x) >= 4)
#define ATTRD_SUPPORTS_CONFIRMATION(x) ((x) >= 5)
#define attrd_send_ack(client, id, flags) \
pcmk__ipc_send_ack((client), (id), (flags), PCMK__XE_ACK, \
ATTRD_PROTOCOL_VERSION, CRM_EX_INDETERMINATE)
void attrd_init_mainloop(void);
void attrd_run_mainloop(void);
void attrd_set_requesting_shutdown(void);
void attrd_clear_requesting_shutdown(void);
void attrd_free_waitlist(void);
bool attrd_shutting_down(bool if_requested);
void attrd_shutdown(int nsig);
void attrd_init_ipc(void);
void attrd_ipc_fini(void);
int attrd_cib_connect(int max_retry);
void attrd_cib_disconnect(void);
void attrd_cib_init(void);
void attrd_cib_erase_transient_attrs(const char *node);
bool attrd_value_needs_expansion(const char *value);
int attrd_expand_value(const char *value, const char *old_value);
/* regular expression to clear failures of all resources */
#define ATTRD_RE_CLEAR_ALL \
"^(" PCMK__FAIL_COUNT_PREFIX "|" PCMK__LAST_FAILURE_PREFIX ")-"
/* regular expression to clear failure of all operations for one resource
* (format takes resource name)
*
* @COMPAT attributes set < 1.1.17:
* also match older attributes that do not have the operation part
*/
#define ATTRD_RE_CLEAR_ONE ATTRD_RE_CLEAR_ALL "%s(#.+_[0-9]+)?$"
/* regular expression to clear failure of one operation for one resource
* (format takes resource name, operation name, and interval)
*
* @COMPAT attributes set < 1.1.17:
* also match older attributes that do not have the operation part
*/
#define ATTRD_RE_CLEAR_OP ATTRD_RE_CLEAR_ALL "%s(#%s_%u)?$"
int attrd_failure_regex(regex_t *regex, const char *rsc, const char *op,
guint interval_ms);
extern cib_t *the_cib;
extern crm_exit_t attrd_exit_status;
/* Alerts */
extern lrmd_t *the_lrmd;
extern crm_trigger_t *attrd_config_read;
void attrd_lrmd_disconnect(void);
gboolean attrd_read_options(gpointer user_data);
int attrd_send_attribute_alert(const char *node, int nodeid,
const char *attr, const char *value);
// Elections
void attrd_election_init(void);
void attrd_election_fini(void);
void attrd_start_election_if_needed(void);
bool attrd_election_won(void);
void attrd_handle_election_op(const crm_node_t *peer, xmlNode *xml);
bool attrd_check_for_new_writer(const crm_node_t *peer, const xmlNode *xml);
void attrd_declare_winner(void);
void attrd_remove_voter(const crm_node_t *peer);
void attrd_xml_add_writer(xmlNode *xml);
enum attrd_attr_flags {
attrd_attr_none = 0U,
attrd_attr_changed = (1U << 0), // Attribute value has changed since last write
attrd_attr_uuid_missing = (1U << 1), // Whether we know we're missing a peer UUID
attrd_attr_is_private = (1U << 2), // Whether to keep this attribute out of the CIB
attrd_attr_force_write = (1U << 3), // Update attribute by ignoring delay
};
typedef struct attribute_s {
- char *id;
- char *set_id;
- char *set_type;
- GHashTable *values;
- int update;
- int timeout_ms;
- uint32_t flags;
-
- mainloop_timer_t *timer;
-
- char *user;
+ char *id; // Attribute name
+ char *set_type; // PCMK_XE_INSTANCE_ATTRIBUTES or PCMK_XE_UTILIZATION
+ char *set_id; // Set's XML ID to use when writing
+ char *user; // ACL user to use for CIB writes
+ int update; // Call ID of pending write
+ int timeout_ms; // How long to wait for more changes before writing
+ uint32_t flags; // Group of enum attrd_attr_flags
+ GHashTable *values; // Key: node name, value: attribute_value_t
+ mainloop_timer_t *timer; // Timer to use for timeout_ms
} attribute_t;
#define attrd_set_attr_flags(attr, flags_to_set) do { \
(attr)->flags = pcmk__set_flags_as(__func__, __LINE__, \
LOG_TRACE, "Value for attribute", (attr)->id, \
(attr)->flags, (flags_to_set), #flags_to_set); \
} while (0)
#define attrd_clear_attr_flags(attr, flags_to_clear) do { \
(attr)->flags = pcmk__clear_flags_as(__func__, __LINE__, \
LOG_TRACE, "Value for attribute", (attr)->id, \
(attr)->flags, (flags_to_clear), #flags_to_clear); \
} while (0)
enum attrd_value_flags {
attrd_value_none = 0U,
attrd_value_remote = (1U << 0), // Value is for Pacemaker Remote node
attrd_value_from_peer = (1U << 1), // Value is from peer sync response
};
typedef struct attribute_value_s {
- uint32_t nodeid;
- char *nodename;
- char *current;
- char *requested;
- uint32_t flags; // Group of attrd_value_flags
+ char *nodename; // Node that this value is for
+ char *current; // Attribute value
+ char *requested; // Value specified in pending CIB write, if any
+ uint32_t nodeid; // Cluster node ID of node that this value is for
+ uint32_t flags; // Group of attrd_value_flags
} attribute_value_t;
#define attrd_set_value_flags(attr_value, flags_to_set) do { \
(attr_value)->flags = pcmk__set_flags_as(__func__, __LINE__, \
LOG_TRACE, "Value for node", (attr_value)->nodename, \
(attr_value)->flags, (flags_to_set), #flags_to_set); \
} while (0)
#define attrd_clear_value_flags(attr_value, flags_to_clear) do { \
(attr_value)->flags = pcmk__clear_flags_as(__func__, __LINE__, \
LOG_TRACE, "Value for node", (attr_value)->nodename, \
(attr_value)->flags, (flags_to_clear), #flags_to_clear); \
} while (0)
extern crm_cluster_t *attrd_cluster;
extern GHashTable *attributes;
extern GHashTable *peer_protocol_vers;
#define CIB_OP_TIMEOUT_S 120
int attrd_cluster_connect(void);
void attrd_broadcast_value(const attribute_t *a, const attribute_value_t *v);
void attrd_peer_update(const crm_node_t *peer, xmlNode *xml, const char *host,
bool filter);
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,
xmlNode *xml);
void attrd_broadcast_protocol(void);
xmlNode *attrd_client_peer_remove(pcmk__request_t *request);
xmlNode *attrd_client_clear_failure(pcmk__request_t *request);
xmlNode *attrd_client_update(pcmk__request_t *request);
xmlNode *attrd_client_refresh(pcmk__request_t *request);
xmlNode *attrd_client_query(pcmk__request_t *request);
gboolean attrd_send_message(crm_node_t *node, xmlNode *data, bool confirm);
xmlNode *attrd_add_value_xml(xmlNode *parent, const attribute_t *a,
const attribute_value_t *v, bool force_write);
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);
char *attrd_nvpair_id(const attribute_t *attr, const char *node_state_id);
enum attrd_write_options {
attrd_write_changed = 0,
attrd_write_all = (1 << 0),
attrd_write_no_delay = (1 << 1),
};
void attrd_write_attributes(uint32_t options);
void attrd_write_or_elect_attribute(attribute_t *a);
extern int minimum_protocol_version;
void attrd_remove_peer_protocol_ver(const char *host);
void attrd_update_minimum_protocol_ver(const char *host, const char *value);
mainloop_timer_t *attrd_add_timer(const char *id, int timeout_ms, attribute_t *attr);
void attrd_unregister_handlers(void);
void attrd_handle_request(pcmk__request_t *request);
enum attrd_sync_point {
attrd_sync_point_local,
attrd_sync_point_cluster,
};
typedef int (*attrd_confirmation_action_fn)(xmlNode *);
void attrd_add_client_to_waitlist(pcmk__request_t *request);
void attrd_ack_waitlist_clients(enum attrd_sync_point sync_point, const xmlNode *xml);
int attrd_cluster_sync_point_update(xmlNode *xml);
void attrd_do_not_expect_from_peer(const char *host);
void attrd_do_not_wait_for_client(pcmk__client_t *client);
void attrd_expect_confirmations(pcmk__request_t *request, attrd_confirmation_action_fn fn);
void attrd_free_confirmations(void);
void attrd_handle_confirmation(int callid, const char *host);
void attrd_remove_client_from_waitlist(pcmk__client_t *client);
const char *attrd_request_sync_point(xmlNode *xml);
bool attrd_request_has_sync_point(xmlNode *xml);
void attrd_copy_xml_attributes(xmlNode *src, xmlNode *dest);
extern gboolean stand_alone;
#endif /* PACEMAKER_ATTRD__H */
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Fri, Sep 5, 9:20 AM (9 h, 9 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2291044
Default Alt Text
(28 KB)
Attached To
Mode
rP Pacemaker
Attached
Detach File
Event Timeline
Log In to Comment