diff --git a/daemons/controld/controld_metadata.c b/daemons/controld/controld_metadata.c index b33e358d84..b4b9a3ba9e 100644 --- a/daemons/controld/controld_metadata.c +++ b/daemons/controld/controld_metadata.c @@ -1,271 +1,271 @@ /* - * Copyright 2017-2019 the Pacemaker project contributors + * Copyright 2017-2020 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 #include #include #include #include #include #include #if ENABLE_VERSIONED_ATTRS static regex_t *version_format_regex = NULL; #endif 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() { return g_hash_table_new_full(crm_str_hash, g_str_equal, 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); } } #if ENABLE_VERSIONED_ATTRS static gboolean valid_version_format(const char *version) { if (version == NULL) { return FALSE; } if (version_format_regex == NULL) { /* The OCF standard allows free-form versioning, but for our purposes of * versioned resource and operation attributes, we constrain it to * dot-separated numbers. Agents are still free to use other schemes, * but we can't determine attributes based on them. */ const char *regex_string = "^[[:digit:]]+([.][[:digit:]]+)*$"; version_format_regex = calloc(1, sizeof(regex_t)); regcomp(version_format_regex, regex_string, REG_EXTENDED | REG_NOSUB); /* If our regex doesn't compile, it's a bug on our side, so CRM_CHECK() * will give us a core dump to catch it. Pretend the version is OK * because we don't want our mistake to break versioned attributes * (which should only ever happen in a development branch anyway). */ CRM_CHECK(version_format_regex != NULL, return TRUE); } return regexec(version_format_regex, version, 0, NULL, 0) == 0; } #endif void metadata_cache_fini() { #if ENABLE_VERSIONED_ATTRS if (version_format_regex) { regfree(version_format_regex); free(version_format_regex); version_format_regex = NULL; } #endif } #if ENABLE_VERSIONED_ATTRS static char * ra_version_from_xml(xmlNode *metadata_xml, const lrmd_rsc_info_t *rsc) { const char *version = crm_element_value(metadata_xml, XML_ATTR_VERSION); if (version == NULL) { crm_debug("Metadata for %s:%s:%s does not specify a version", rsc->standard, rsc->provider, rsc->type); version = PCMK_DEFAULT_AGENT_VERSION; } else if (!valid_version_format(version)) { crm_notice("%s:%s:%s metadata version has unrecognized format", rsc->standard, rsc->provider, rsc->type); version = PCMK_DEFAULT_AGENT_VERSION; } else { crm_debug("Metadata for %s:%s:%s has version %s", rsc->standard, rsc->provider, rsc->type, version); } return strdup(version); } #endif static struct ra_param_s * ra_param_from_xml(xmlNode *param_xml) { const char *param_name = crm_element_value(param_xml, "name"); const char *value; struct ra_param_s *p; p = calloc(1, sizeof(struct ra_param_s)); if (p == NULL) { crm_crit("Could not allocate memory for resource metadata"); return NULL; } p->rap_name = strdup(param_name); if (p->rap_name == NULL) { crm_crit("Could not allocate memory for resource metadata"); free(p); return NULL; } value = crm_element_value(param_xml, "unique"); if (crm_is_true(value)) { - set_bit(p->rap_flags, ra_param_unique); + controld_set_ra_param_flags(p, ra_param_unique); } value = crm_element_value(param_xml, "private"); if (crm_is_true(value)) { - set_bit(p->rap_flags, ra_param_private); + controld_set_ra_param_flags(p, ra_param_private); } return p; } struct ra_metadata_s * metadata_cache_update(GHashTable *mdc, lrmd_rsc_info_t *rsc, const char *metadata_str) { char *key = NULL; xmlNode *metadata = NULL; xmlNode *match = NULL; struct ra_metadata_s *md = NULL; CRM_CHECK(mdc && rsc && metadata_str, return NULL); key = crm_generate_ra_key(rsc->standard, rsc->provider, rsc->type); if (!key) { crm_crit("Could not allocate memory for resource metadata"); goto err; } metadata = string2xml(metadata_str); if (!metadata) { crm_err("Metadata for %s:%s:%s is not valid XML", rsc->standard, rsc->provider, rsc->type); goto err; } md = calloc(1, sizeof(struct ra_metadata_s)); if (md == NULL) { crm_crit("Could not allocate memory for resource metadata"); goto err; } #if ENABLE_VERSIONED_ATTRS md->ra_version = ra_version_from_xml(metadata, rsc); #endif // 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, "reload", pcmk__str_casei)) { - set_bit(md->ra_flags, ra_supports_reload); + controld_set_ra_flags(md, key, ra_supports_reload); break; // since this is the only action we currently care about } } // 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) { goto err; } if (is_set(p->rap_flags, ra_param_private)) { - set_bit(md->ra_flags, ra_uses_private); + controld_set_ra_flags(md, key, ra_uses_private); } md->ra_params = g_list_prepend(md->ra_params, p); } } g_hash_table_replace(mdc, key, md); free_xml(metadata); return md; err: free(key); free_xml(metadata); metadata_free(md); return NULL; } struct ra_metadata_s * metadata_cache_get(GHashTable *mdc, lrmd_rsc_info_t *rsc) { char *key = NULL; struct ra_metadata_s *metadata = NULL; CRM_CHECK(mdc && rsc, return NULL); key = crm_generate_ra_key(rsc->standard, rsc->provider, rsc->type); if (key) { metadata = g_hash_table_lookup(mdc, key); free(key); } return metadata; } diff --git a/daemons/controld/controld_metadata.h b/daemons/controld/controld_metadata.h index 2381a322c5..471ed0da29 100644 --- a/daemons/controld/controld_metadata.h +++ b/daemons/controld/controld_metadata.h @@ -1,55 +1,69 @@ -#ifndef CRMD_METADATA_H -#define CRMD_METADATA_H - /* - * Copyright (C) 2017 Andrew Beekhof + * Copyright 2017-2020 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 + enum ra_flags_e { ra_supports_reload = 0x01, ra_uses_private = 0x02, }; enum ra_param_flags_e { ra_param_unique = 0x01, ra_param_private = 0x02, }; 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(__FUNCTION__, __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(__FUNCTION__, __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); void metadata_cache_fini(void); struct ra_metadata_s *metadata_cache_update(GHashTable *mdc, lrmd_rsc_info_t *rsc, const char *metadata_str); struct ra_metadata_s *metadata_cache_get(GHashTable *mdc, lrmd_rsc_info_t *rsc); static inline const char * ra_param_flag2text(enum ra_param_flags_e flag) { switch (flag) { case ra_param_unique: return "unique"; case ra_param_private: return "private"; default: return "unknown"; } } #endif