root/daemons/attrd/attrd_attributes.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. attrd_create_attribute
  2. attrd_update_dampening
  3. attrd_add_value_xml
  4. attrd_clear_value_seen
  5. attrd_populate_attribute

   1 /*
   2  * Copyright 2013-2022 the Pacemaker project contributors
   3  *
   4  * The version control history for this file may have further details.
   5  *
   6  * This source code is licensed under the GNU General Public License version 2
   7  * or later (GPLv2+) WITHOUT ANY WARRANTY.
   8  */
   9 
  10 #include <crm_internal.h>
  11 
  12 #include <errno.h>
  13 #include <stdbool.h>
  14 #include <stdlib.h>
  15 #include <glib.h>
  16 
  17 #include <crm/msg_xml.h>
  18 #include <crm/common/logging.h>
  19 #include <crm/common/results.h>
  20 #include <crm/common/strings_internal.h>
  21 #include <crm/common/xml.h>
  22 
  23 #include "pacemaker-attrd.h"
  24 
  25 static attribute_t *
  26 attrd_create_attribute(xmlNode *xml)
     /* [previous][next][first][last][top][bottom][index][help] */
  27 {
  28     int is_private = 0;
  29     int dampen = 0;
  30     const char *name = crm_element_value(xml, PCMK__XA_ATTR_NAME);
  31     const char *set_type = crm_element_value(xml, PCMK__XA_ATTR_SET_TYPE);
  32     const char *dampen_s = crm_element_value(xml, PCMK__XA_ATTR_DAMPENING);
  33     attribute_t *a = NULL;
  34 
  35     if (set_type == NULL) {
  36         set_type = XML_TAG_ATTR_SETS;
  37     }
  38 
  39     /* Set type is meaningful only when writing to the CIB. Private
  40      * attributes are not written.
  41      */
  42     crm_element_value_int(xml, PCMK__XA_ATTR_IS_PRIVATE, &is_private);
  43     if ((is_private != 0)
  44         && !pcmk__str_any_of(set_type, XML_TAG_ATTR_SETS, XML_TAG_UTILIZATION,
  45                              NULL)) {
  46         crm_warn("Ignoring attribute %s with invalid set type %s",
  47                  pcmk__s(name, "(unidentified)"), set_type);
  48         return NULL;
  49     }
  50 
  51     a = calloc(1, sizeof(attribute_t));
  52     CRM_ASSERT(a != NULL);
  53 
  54     a->is_private = is_private;
  55     pcmk__str_update(&a->id, name);
  56     pcmk__str_update(&a->set_type, set_type);
  57 
  58     a->set_id = crm_element_value_copy(xml, PCMK__XA_ATTR_SET);
  59     a->uuid = crm_element_value_copy(xml, PCMK__XA_ATTR_UUID);
  60     a->values = pcmk__strikey_table(NULL, attrd_free_attribute_value);
  61 
  62     a->user = crm_element_value_copy(xml, PCMK__XA_ATTR_USER);
  63     crm_trace("Performing all %s operations as user '%s'", a->id, a->user);
  64 
  65     if (dampen_s != NULL) {
  66         dampen = crm_get_msec(dampen_s);
  67     }
  68     crm_trace("Created attribute %s with %s write delay", a->id,
  69               (a->timeout_ms == 0)? "no" : pcmk__readable_interval(a->timeout_ms));
  70 
  71     if(dampen > 0) {
  72         a->timeout_ms = dampen;
  73         a->timer = attrd_add_timer(a->id, a->timeout_ms, a);
  74     } else if (dampen < 0) {
  75         crm_warn("Ignoring invalid delay %s for attribute %s", dampen_s, a->id);
  76     }
  77 
  78     g_hash_table_replace(attributes, a->id, a);
  79     return a;
  80 }
  81 
  82 static int
  83 attrd_update_dampening(attribute_t *a, xmlNode *xml, const char *attr)
     /* [previous][next][first][last][top][bottom][index][help] */
  84 {
  85     const char *dvalue = crm_element_value(xml, PCMK__XA_ATTR_DAMPENING);
  86     int dampen = 0;
  87 
  88     if (dvalue == NULL) {
  89         crm_warn("Could not update %s: peer did not specify value for delay",
  90                  attr);
  91         return EINVAL;
  92     }
  93 
  94     dampen = crm_get_msec(dvalue);
  95     if (dampen < 0) {
  96         crm_warn("Could not update %s: invalid delay value %dms (%s)",
  97                  attr, dampen, dvalue);
  98         return EINVAL;
  99     }
 100 
 101     if (a->timeout_ms != dampen) {
 102         mainloop_timer_del(a->timer);
 103         a->timeout_ms = dampen;
 104         if (dampen > 0) {
 105             a->timer = attrd_add_timer(attr, a->timeout_ms, a);
 106             crm_info("Update attribute %s delay to %dms (%s)",
 107                      attr, dampen, dvalue);
 108         } else {
 109             a->timer = NULL;
 110             crm_info("Update attribute %s to remove delay", attr);
 111         }
 112 
 113         /* If dampening changed, do an immediate write-out,
 114          * otherwise repeated dampening changes would prevent write-outs
 115          */
 116         attrd_write_or_elect_attribute(a);
 117     }
 118 
 119     return pcmk_rc_ok;
 120 }
 121 
 122 GHashTable *attributes = NULL;
 123 
 124 /*!
 125  * \internal
 126  * \brief Create an XML representation of an attribute for use in peer messages
 127  *
 128  * \param[in,out] parent      Create attribute XML as child element of this
 129  * \param[in]     a           Attribute to represent
 130  * \param[in]     v           Attribute value to represent
 131  * \param[in]     force_write If true, value should be written even if unchanged
 132  *
 133  * \return XML representation of attribute
 134  */
 135 xmlNode *
 136 attrd_add_value_xml(xmlNode *parent, const attribute_t *a,
     /* [previous][next][first][last][top][bottom][index][help] */
 137                     const attribute_value_t *v, bool force_write)
 138 {
 139     xmlNode *xml = create_xml_node(parent, __func__);
 140 
 141     crm_xml_add(xml, PCMK__XA_ATTR_NAME, a->id);
 142     crm_xml_add(xml, PCMK__XA_ATTR_SET, a->set_id);
 143     crm_xml_add(xml, PCMK__XA_ATTR_UUID, a->uuid);
 144     crm_xml_add(xml, PCMK__XA_ATTR_USER, a->user);
 145     pcmk__xe_add_node(xml, v->nodename, v->nodeid);
 146     if (v->is_remote != 0) {
 147         crm_xml_add_int(xml, PCMK__XA_ATTR_IS_REMOTE, 1);
 148     }
 149     crm_xml_add(xml, PCMK__XA_ATTR_VALUE, v->current);
 150     crm_xml_add_int(xml, PCMK__XA_ATTR_DAMPENING, a->timeout_ms / 1000);
 151     crm_xml_add_int(xml, PCMK__XA_ATTR_IS_PRIVATE, a->is_private);
 152     crm_xml_add_int(xml, PCMK__XA_ATTR_FORCE, force_write);
 153 
 154     return xml;
 155 }
 156 
 157 void
 158 attrd_clear_value_seen(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 159 {
 160     GHashTableIter aIter;
 161     GHashTableIter vIter;
 162     attribute_t *a;
 163     attribute_value_t *v = NULL;
 164 
 165     g_hash_table_iter_init(&aIter, attributes);
 166     while (g_hash_table_iter_next(&aIter, NULL, (gpointer *) & a)) {
 167         g_hash_table_iter_init(&vIter, a->values);
 168         while (g_hash_table_iter_next(&vIter, NULL, (gpointer *) & v)) {
 169             v->seen = FALSE;
 170             crm_trace("Clear seen flag %s[%s] = %s.", a->id, v->nodename, v->current);
 171         }
 172     }
 173 }
 174 
 175 attribute_t *
 176 attrd_populate_attribute(xmlNode *xml, const char *attr)
     /* [previous][next][first][last][top][bottom][index][help] */
 177 {
 178     attribute_t *a = NULL;
 179     bool update_both = false;
 180 
 181     const char *op = crm_element_value(xml, PCMK__XA_TASK);
 182 
 183     // NULL because PCMK__ATTRD_CMD_SYNC_RESPONSE has no PCMK__XA_TASK
 184     update_both = pcmk__str_eq(op, PCMK__ATTRD_CMD_UPDATE_BOTH,
 185                                pcmk__str_null_matches);
 186 
 187     // Look up or create attribute entry
 188     a = g_hash_table_lookup(attributes, attr);
 189     if (a == NULL) {
 190         if (update_both || pcmk__str_eq(op, PCMK__ATTRD_CMD_UPDATE, pcmk__str_none)) {
 191             a = attrd_create_attribute(xml);
 192             if (a == NULL) {
 193                 return NULL;
 194             }
 195 
 196         } else {
 197             crm_warn("Could not update %s: attribute not found", attr);
 198             return NULL;
 199         }
 200     }
 201 
 202     // Update attribute dampening
 203     if (update_both || pcmk__str_eq(op, PCMK__ATTRD_CMD_UPDATE_DELAY, pcmk__str_none)) {
 204         int rc = attrd_update_dampening(a, xml, attr);
 205 
 206         if (rc != pcmk_rc_ok || !update_both) {
 207             return NULL;
 208         }
 209     }
 210 
 211     return a;
 212 }

/* [previous][next][first][last][top][bottom][index][help] */