Page MenuHomeClusterLabs Projects

No OneTemporary

diff --git a/daemons/controld/controld_metadata.c b/daemons/controld/controld_metadata.c
index e3165cba7b..240a978bdc 100644
--- a/daemons/controld/controld_metadata.c
+++ b/daemons/controld/controld_metadata.c
@@ -1,323 +1,320 @@
/*
* Copyright 2017-2022 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.
*/
#include <crm_internal.h>
#include <stdio.h>
#include <glib.h>
#include <regex.h>
#include <crm/crm.h>
#include <crm/lrmd.h>
#include <pacemaker-controld.h>
static void
ra_param_free(void *param)
{
if (param) {
struct ra_param_s *p = (struct ra_param_s *) param;
if (p->rap_name) {
free(p->rap_name);
}
free(param);
}
}
static void
metadata_free(void *metadata)
{
if (metadata) {
struct ra_metadata_s *md = (struct ra_metadata_s *) metadata;
- if (md->ra_version) {
- free(md->ra_version);
- }
g_list_free_full(md->ra_params, ra_param_free);
free(metadata);
}
}
GHashTable *
metadata_cache_new(void)
{
return pcmk__strkey_table(free, metadata_free);
}
void
metadata_cache_free(GHashTable *mdc)
{
if (mdc) {
crm_trace("Destroying metadata cache with %d members", g_hash_table_size(mdc));
g_hash_table_destroy(mdc);
}
}
void
metadata_cache_reset(GHashTable *mdc)
{
if (mdc) {
crm_trace("Resetting metadata cache with %d members",
g_hash_table_size(mdc));
g_hash_table_remove_all(mdc);
}
}
static struct ra_param_s *
ra_param_from_xml(xmlNode *param_xml)
{
const char *param_name = crm_element_value(param_xml, "name");
struct ra_param_s *p;
p = calloc(1, sizeof(struct ra_param_s));
if (p == NULL) {
return NULL;
}
p->rap_name = strdup(param_name);
if (p->rap_name == NULL) {
free(p);
return NULL;
}
if (pcmk__xe_attr_is_true(param_xml, "reloadable")) {
controld_set_ra_param_flags(p, ra_param_reloadable);
}
if (pcmk__xe_attr_is_true(param_xml, "unique")) {
controld_set_ra_param_flags(p, ra_param_unique);
}
if (pcmk__xe_attr_is_true(param_xml, "private")) {
controld_set_ra_param_flags(p, ra_param_private);
}
return p;
}
static void
log_ra_ocf_version(const char *ra_key, const char *ra_ocf_version)
{
if (pcmk__str_empty(ra_ocf_version)) {
crm_warn("%s does not advertise OCF version supported", ra_key);
} else if (compare_version(ra_ocf_version, "2") >= 0) {
crm_warn("%s supports OCF version %s (this Pacemaker version supports "
PCMK_OCF_VERSION " and might not work properly with agent)",
ra_key, ra_ocf_version);
} else if (compare_version(ra_ocf_version, PCMK_OCF_VERSION) > 0) {
crm_info("%s supports OCF version %s (this Pacemaker version supports "
PCMK_OCF_VERSION " and might not use all agent features)",
ra_key, ra_ocf_version);
} else {
crm_debug("%s supports OCF version %s", ra_key, ra_ocf_version);
}
}
struct ra_metadata_s *
controld_cache_metadata(GHashTable *mdc, const lrmd_rsc_info_t *rsc,
const char *metadata_str)
{
char *key = NULL;
const char *reason = NULL;
xmlNode *metadata = NULL;
xmlNode *match = NULL;
struct ra_metadata_s *md = NULL;
bool any_private_params = false;
bool ocf1_1 = false;
CRM_CHECK(mdc && rsc && metadata_str, return NULL);
key = crm_generate_ra_key(rsc->standard, rsc->provider, rsc->type);
if (!key) {
reason = "Invalid resource agent standard or type";
goto err;
}
metadata = string2xml(metadata_str);
if (!metadata) {
reason = "Metadata is not valid XML";
goto err;
}
md = calloc(1, sizeof(struct ra_metadata_s));
if (md == NULL) {
reason = "Could not allocate memory";
goto err;
}
if (strcmp(rsc->standard, PCMK_RESOURCE_CLASS_OCF) == 0) {
xmlChar *content = NULL;
xmlNode *version_element = first_named_child(metadata, "version");
if (version_element != NULL) {
content = xmlNodeGetContent(version_element);
}
log_ra_ocf_version(key, (const char *) content);
if (content != NULL) {
ocf1_1 = (compare_version((const char *) content, "1.1") >= 0);
xmlFree(content);
}
}
// Check supported actions
match = first_named_child(metadata, "actions");
for (match = first_named_child(match, "action"); match != NULL;
match = crm_next_same_xml(match)) {
const char *action_name = crm_element_value(match, "name");
if (pcmk__str_eq(action_name, CRMD_ACTION_RELOAD_AGENT,
pcmk__str_none)) {
if (ocf1_1) {
controld_set_ra_flags(md, key, ra_supports_reload_agent);
} else {
crm_notice("reload-agent action will not be used with %s "
"because it does not support OCF 1.1 or later", key);
}
} else if (!ocf1_1 && pcmk__str_eq(action_name, CRMD_ACTION_RELOAD,
pcmk__str_casei)) {
controld_set_ra_flags(md, key, ra_supports_legacy_reload);
}
}
// Build a parameter list
match = first_named_child(metadata, "parameters");
for (match = first_named_child(match, "parameter"); match != NULL;
match = crm_next_same_xml(match)) {
const char *param_name = crm_element_value(match, "name");
if (param_name == NULL) {
crm_warn("Metadata for %s:%s:%s has parameter without a name",
rsc->standard, rsc->provider, rsc->type);
} else {
struct ra_param_s *p = ra_param_from_xml(match);
if (p == NULL) {
reason = "Could not allocate memory";
goto err;
}
if (pcmk_is_set(p->rap_flags, ra_param_private)) {
any_private_params = true;
}
md->ra_params = g_list_prepend(md->ra_params, p);
}
}
/* Newer resource agents support the "private" parameter attribute to
* indicate sensitive parameters. For backward compatibility with older
* agents, implicitly treat a few common names as private when the agent
* doesn't specify any explicitly.
*/
if (!any_private_params) {
for (GList *iter = md->ra_params; iter != NULL; iter = iter->next) {
struct ra_param_s *p = iter->data;
if (pcmk__str_any_of(p->rap_name, "password", "passwd", "user",
NULL)) {
controld_set_ra_param_flags(p, ra_param_private);
}
}
}
g_hash_table_replace(mdc, key, md);
free_xml(metadata);
return md;
err:
crm_warn("Unable to update metadata for %s (%s%s%s:%s): %s",
rsc->id, rsc->standard, ((rsc->provider == NULL)? "" : ":"),
pcmk__s(rsc->provider, ""), rsc->type, reason);
free(key);
free_xml(metadata);
metadata_free(md);
return NULL;
}
/*!
* \internal
* \brief Get meta-data for a resource
*
* \param[in,out] lrm_state Use meta-data cache from this executor connection
* \param[in] rsc Resource to get meta-data for
* \param[in] source Allowed meta-data sources (bitmask of
* enum controld_metadata_source_e values)
*
* \return Meta-data cache entry for given resource, or NULL if not available
*/
struct ra_metadata_s *
controld_get_rsc_metadata(lrm_state_t *lrm_state, const lrmd_rsc_info_t *rsc,
uint32_t source)
{
struct ra_metadata_s *metadata = NULL;
char *metadata_str = NULL;
char *key = NULL;
int rc = pcmk_ok;
CRM_CHECK((lrm_state != NULL) && (rsc != NULL), return NULL);
if (pcmk_is_set(source, controld_metadata_from_cache)) {
key = crm_generate_ra_key(rsc->standard, rsc->provider, rsc->type);
if (key != NULL) {
metadata = g_hash_table_lookup(lrm_state->metadata_cache, key);
free(key);
}
if (metadata != NULL) {
crm_debug("Retrieved metadata for %s (%s%s%s:%s) from cache",
rsc->id, rsc->standard,
((rsc->provider == NULL)? "" : ":"),
((rsc->provider == NULL)? "" : rsc->provider),
rsc->type);
return metadata;
}
}
if (!pcmk_is_set(source, controld_metadata_from_agent)) {
return NULL;
}
/* For most actions, metadata was cached asynchronously before action
* execution (via metadata_complete()).
*
* However if that failed, and for other actions, retrieve the metadata now
* via a local, synchronous, direct execution of the agent.
*
* This has multiple issues, which is why this is just a fallback: the
* executor should execute agents, not the controller; metadata for
* Pacemaker Remote nodes should be collected on those nodes, not locally;
* the metadata call shouldn't eat into the timeout of the real action being
* performed; and the synchronous call blocks the controller (which also
* means that if the metadata action tries to contact the controller,
* everything will hang until the timeout).
*/
crm_debug("Retrieving metadata for %s (%s%s%s:%s) synchronously",
rsc->id, rsc->standard,
((rsc->provider == NULL)? "" : ":"),
((rsc->provider == NULL)? "" : rsc->provider),
rsc->type);
rc = lrm_state_get_metadata(lrm_state, rsc->standard, rsc->provider,
rsc->type, &metadata_str, 0);
if (rc != pcmk_ok) {
crm_warn("Failed to get metadata for %s (%s%s%s:%s): %s",
rsc->id, rsc->standard,
((rsc->provider == NULL)? "" : ":"),
((rsc->provider == NULL)? "" : rsc->provider),
rsc->type, pcmk_strerror(rc));
return NULL;
}
metadata = controld_cache_metadata(lrm_state->metadata_cache, rsc,
metadata_str);
free(metadata_str);
return metadata;
}
diff --git a/daemons/controld/controld_metadata.h b/daemons/controld/controld_metadata.h
index 593c803017..12ea327e4e 100644
--- a/daemons/controld/controld_metadata.h
+++ b/daemons/controld/controld_metadata.h
@@ -1,97 +1,96 @@
/*
* Copyright 2017-2022 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 CRMD_METADATA_H
#define CRMD_METADATA_H
#include <stdint.h> // uint32_t
#include <glib.h> // GList, GHashTable
#include "controld_lrm.h" // lrm_state_t, lrm_rsc_info_t
/*
* @COMPAT pre-OCF-1.1 resource agents
*
* Pacemaker previously used the "reload" action to reload agent parameters,
* but most agents used it to reload the service configuration. Pacemaker also
* misused the OCF 1.0 "unique" parameter attribute to indicate reloadability.
*
* OCF 1.1 created the "reload-agent" action and "reloadable" parameter
* attribute for the Pacemaker usage.
*
* Pacemaker now supports the OCF 1.1 usage. The old usage is now deprecated,
* but will be supported if the agent does not claim OCF 1.1 or later
* compliance and does not advertise the reload-agent action.
*/
enum ra_flags_e {
ra_supports_legacy_reload = (1 << 0),
ra_supports_reload_agent = (1 << 1),
};
enum ra_param_flags_e {
ra_param_unique = (1 << 0),
ra_param_private = (1 << 1),
ra_param_reloadable = (1 << 2),
};
// Allowed sources of resource agent meta-data when requesting it
enum controld_metadata_source_e {
controld_metadata_from_cache = (1 << 0),
controld_metadata_from_agent = (1 << 1),
};
struct ra_param_s {
char *rap_name;
uint32_t rap_flags; // bitmask of ra_param_flags_s
};
struct ra_metadata_s {
- char *ra_version;
GList *ra_params; // ra_param_s
uint32_t ra_flags; // bitmask of ra_flags_e
};
#define controld_set_ra_flags(ra_md, ra_key, flags_to_set) do { \
(ra_md)->ra_flags = pcmk__set_flags_as(__func__, __LINE__, \
LOG_TRACE, "Resource agent", ra_key, \
(ra_md)->ra_flags, (flags_to_set), #flags_to_set); \
} while (0)
#define controld_set_ra_param_flags(ra_param, flags_to_set) do { \
(ra_param)->rap_flags = pcmk__set_flags_as(__func__, __LINE__, \
LOG_TRACE, "Resource agent parameter", (ra_param)->rap_name, \
(ra_param)->rap_flags, (flags_to_set), #flags_to_set); \
} while (0)
GHashTable *metadata_cache_new(void);
void metadata_cache_free(GHashTable *mdc);
void metadata_cache_reset(GHashTable *mdc);
struct ra_metadata_s *controld_cache_metadata(GHashTable *mdc,
const lrmd_rsc_info_t *rsc,
const char *metadata_str);
struct ra_metadata_s *controld_get_rsc_metadata(lrm_state_t *lrm_state,
const lrmd_rsc_info_t *rsc,
uint32_t source);
static inline const char *
ra_param_flag2text(enum ra_param_flags_e flag)
{
switch (flag) {
case ra_param_reloadable:
return "reloadable";
case ra_param_unique:
return "unique";
case ra_param_private:
return "private";
default:
return "unknown";
}
}
#endif
diff --git a/include/crm/pengine/rules.h b/include/crm/pengine/rules.h
index bb59bfab9e..9959a16a4f 100644
--- a/include/crm/pengine/rules.h
+++ b/include/crm/pengine/rules.h
@@ -1,75 +1,78 @@
/*
* Copyright 2004-2022 the Pacemaker project contributors
*
* The version control history for this file may have further details.
*
* This source code is licensed under the GNU Lesser General Public License
* version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
*/
#ifndef PCMK__CRM_PENGINE_RULES__H
# define PCMK__CRM_PENGINE_RULES__H
# include <glib.h>
# include <crm/crm.h>
# include <crm/common/iso8601.h>
# include <crm/pengine/common.h>
#ifdef __cplusplus
extern "C" {
#endif
enum expression_type {
- not_expr,
- nested_rule,
- attr_expr,
- loc_expr,
- role_expr,
- time_expr,
- version_expr,
- rsc_expr,
- op_expr
+ not_expr = 0,
+ nested_rule = 1,
+ attr_expr = 2,
+ loc_expr = 3,
+ role_expr = 4,
+ time_expr = 5,
+#if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1)
+ //! \deprecated Do not use (will be removed in a future release)
+ version_expr = 6,
+#endif
+ rsc_expr = 7,
+ op_expr = 8,
};
enum expression_type find_expression_type(xmlNode * expr);
gboolean pe_evaluate_rules(xmlNode *ruleset, GHashTable *node_hash,
crm_time_t *now, crm_time_t *next_change);
gboolean pe_test_rule(xmlNode *rule, GHashTable *node_hash,
enum rsc_role_e role, crm_time_t *now,
crm_time_t *next_change, pe_match_data_t *match_data);
gboolean pe_test_expression(xmlNode *expr, GHashTable *node_hash,
enum rsc_role_e role, crm_time_t *now,
crm_time_t *next_change,
pe_match_data_t *match_data);
void pe_eval_nvpairs(xmlNode *top, const xmlNode *xml_obj, const char *set_name,
pe_rule_eval_data_t *rule_data, GHashTable *hash,
const char *always_first, gboolean overwrite,
crm_time_t *next_change);
void pe_unpack_nvpairs(xmlNode *top, xmlNode *xml_obj, const char *set_name,
GHashTable *node_hash, GHashTable *hash,
const char *always_first, gboolean overwrite,
crm_time_t *now, crm_time_t *next_change);
char *pe_expand_re_matches(const char *string, pe_re_match_data_t * match_data);
gboolean pe_eval_rules(xmlNode *ruleset, pe_rule_eval_data_t *rule_data,
crm_time_t *next_change);
gboolean pe_eval_expr(xmlNode *rule, pe_rule_eval_data_t *rule_data,
crm_time_t *next_change);
gboolean pe_eval_subexpr(xmlNode *expr, pe_rule_eval_data_t *rule_data,
crm_time_t *next_change);
#if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1)
#include <crm/pengine/rules_compat.h>
#endif
#ifdef __cplusplus
}
#endif
#endif

File Metadata

Mime Type
text/x-diff
Expires
Thu, Oct 16, 12:26 AM (22 h, 57 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2530859
Default Alt Text
(17 KB)

Event Timeline