root/daemons/attrd/attrd_utils.c

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

DEFINITIONS

This source file includes following definitions.
  1. attrd_set_requesting_shutdown
  2. attrd_clear_requesting_shutdown
  3. attrd_requesting_shutdown
  4. attrd_shutting_down
  5. attrd_shutdown
  6. attrd_init_mainloop
  7. attrd_run_mainloop
  8. attrd_cib_disconnect
  9. attrd_cib_replaced_cb
  10. attrd_value_needs_expansion
  11. attrd_expand_value
  12. attrd_failure_regex
  13. attrd_free_attribute_value
  14. attrd_free_attribute
  15. attrd_update_minimum_protocol_ver

   1 /*
   2  * Copyright 2004-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 <stdio.h>
  13 #include <stdbool.h>
  14 #include <errno.h>
  15 #include <glib.h>
  16 #include <regex.h>
  17 #include <sys/types.h>
  18 
  19 #include <crm/crm.h>
  20 #include <crm/common/ipc_internal.h>
  21 #include <crm/common/mainloop.h>
  22 #include <crm/msg_xml.h>
  23 
  24 #include "pacemaker-attrd.h"
  25 
  26 cib_t *the_cib = NULL;
  27 
  28 static bool requesting_shutdown = false;
  29 static bool shutting_down = false;
  30 static GMainLoop *mloop = NULL;
  31 
  32 /*!
  33  * \internal
  34  * \brief  Set requesting_shutdown state
  35  */
  36 void
  37 attrd_set_requesting_shutdown(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  38 {
  39     requesting_shutdown = true;
  40 }
  41 
  42 /*!
  43  * \internal
  44  * \brief  Clear requesting_shutdown state
  45  */
  46 void
  47 attrd_clear_requesting_shutdown(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  48 {
  49     requesting_shutdown = false;
  50 }
  51 
  52 /*!
  53  * \internal
  54  * \brief Check whether we're currently requesting shutdown
  55  *
  56  * \return true if requesting shutdown, false otherwise
  57  */
  58 bool
  59 attrd_requesting_shutdown(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  60 {
  61     return requesting_shutdown;
  62 }
  63 
  64 /*!
  65  * \internal
  66  * \brief Check whether we're currently shutting down
  67  *
  68  * \return true if shutting down, false otherwise
  69  */
  70 bool
  71 attrd_shutting_down(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  72 {
  73     return shutting_down;
  74 }
  75 
  76 /*!
  77  * \internal
  78  * \brief  Exit (using mainloop or not, as appropriate)
  79  *
  80  * \param[in] nsig  Ignored
  81  */
  82 void
  83 attrd_shutdown(int nsig)
     /* [previous][next][first][last][top][bottom][index][help] */
  84 {
  85     // Tell various functions not to do anthing
  86     shutting_down = true;
  87 
  88     // Don't respond to signals while shutting down
  89     mainloop_destroy_signal(SIGTERM);
  90     mainloop_destroy_signal(SIGCHLD);
  91     mainloop_destroy_signal(SIGPIPE);
  92     mainloop_destroy_signal(SIGUSR1);
  93     mainloop_destroy_signal(SIGUSR2);
  94     mainloop_destroy_signal(SIGTRAP);
  95 
  96     if ((mloop == NULL) || !g_main_loop_is_running(mloop)) {
  97         /* If there's no main loop active, just exit. This should be possible
  98          * only if we get SIGTERM in brief windows at start-up and shutdown.
  99          */
 100         crm_exit(CRM_EX_OK);
 101     } else {
 102         g_main_loop_quit(mloop);
 103         g_main_loop_unref(mloop);
 104     }
 105 }
 106 
 107 /*!
 108  * \internal
 109  * \brief Create a main loop for attrd
 110  */
 111 void
 112 attrd_init_mainloop(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 113 {
 114     mloop = g_main_loop_new(NULL, FALSE);
 115 }
 116 
 117 /*!
 118  * \internal
 119  * \brief Run attrd main loop
 120  */
 121 void
 122 attrd_run_mainloop(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 123 {
 124     g_main_loop_run(mloop);
 125 }
 126 
 127 void
 128 attrd_cib_disconnect(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 129 {
 130     CRM_CHECK(the_cib != NULL, return);
 131     the_cib->cmds->del_notify_callback(the_cib, T_CIB_REPLACE_NOTIFY, attrd_cib_replaced_cb);
 132     the_cib->cmds->del_notify_callback(the_cib, T_CIB_DIFF_NOTIFY, attrd_cib_updated_cb);
 133     cib__clean_up_connection(&the_cib);
 134 }
 135 
 136 void
 137 attrd_cib_replaced_cb(const char *event, xmlNode * msg)
     /* [previous][next][first][last][top][bottom][index][help] */
 138 {
 139     int change_section = cib_change_section_nodes | cib_change_section_status | cib_change_section_alerts;
 140 
 141     if (attrd_requesting_shutdown() || attrd_shutting_down()) {
 142         return;
 143     }
 144 
 145     crm_element_value_int(msg, F_CIB_CHANGE_SECTION, &change_section);
 146 
 147     if (attrd_election_won()) {
 148         if (change_section & (cib_change_section_nodes | cib_change_section_status)) {
 149             crm_notice("Updating all attributes after %s event", event);
 150             attrd_write_attributes(true, false);
 151         }
 152     }
 153 
 154     if (change_section & cib_change_section_alerts) {
 155         // Check for changes in alerts
 156         mainloop_set_trigger(attrd_config_read);
 157     }
 158 }
 159 
 160 /* strlen("value") */
 161 #define plus_plus_len (5)
 162 
 163 /*!
 164  * \internal
 165  * \brief  Check whether an attribute value should be expanded
 166  *
 167  * \param[in] value  Attribute value to check
 168  *
 169  * \return true if value needs expansion, false otherwise
 170  */
 171 bool
 172 attrd_value_needs_expansion(const char *value)
     /* [previous][next][first][last][top][bottom][index][help] */
 173 {
 174     return ((strlen(value) >= (plus_plus_len + 2))
 175            && (value[plus_plus_len] == '+')
 176            && ((value[plus_plus_len + 1] == '+')
 177                || (value[plus_plus_len + 1] == '=')));
 178 }
 179 
 180 /*!
 181  * \internal
 182  * \brief Expand an increment expression into an integer
 183  *
 184  * \param[in] value      Attribute increment expression to expand
 185  * \param[in] old_value  Previous value of attribute
 186  *
 187  * \return Expanded value
 188  */
 189 int
 190 attrd_expand_value(const char *value, const char *old_value)
     /* [previous][next][first][last][top][bottom][index][help] */
 191 {
 192     int offset = 1;
 193     int int_value = char2score(old_value);
 194 
 195     if (value[plus_plus_len + 1] != '+') {
 196         const char *offset_s = value + (plus_plus_len + 2);
 197 
 198         offset = char2score(offset_s);
 199     }
 200     int_value += offset;
 201 
 202     if (int_value > INFINITY) {
 203         int_value = INFINITY;
 204     }
 205     return int_value;
 206 }
 207 
 208 /*!
 209  * \internal
 210  * \brief Create regular expression matching failure-related attributes
 211  *
 212  * \param[out] regex  Where to store created regular expression
 213  * \param[in]  rsc    Name of resource to clear (or NULL for all)
 214  * \param[in]  op     Operation to clear if rsc is specified (or NULL for all)
 215  * \param[in]  interval_ms  Interval of operation to clear if op is specified
 216  *
 217  * \return pcmk_ok on success, -EINVAL if arguments are invalid
 218  *
 219  * \note The caller is responsible for freeing the result with regfree().
 220  */
 221 int
 222 attrd_failure_regex(regex_t *regex, const char *rsc, const char *op,
     /* [previous][next][first][last][top][bottom][index][help] */
 223                     guint interval_ms)
 224 {
 225     char *pattern = NULL;
 226     int rc;
 227 
 228     /* Create a pattern that matches desired attributes */
 229 
 230     if (rsc == NULL) {
 231         pattern = strdup(ATTRD_RE_CLEAR_ALL);
 232     } else if (op == NULL) {
 233         pattern = crm_strdup_printf(ATTRD_RE_CLEAR_ONE, rsc);
 234     } else {
 235         pattern = crm_strdup_printf(ATTRD_RE_CLEAR_OP, rsc, op, interval_ms);
 236     }
 237 
 238     /* Compile pattern into regular expression */
 239     crm_trace("Clearing attributes matching %s", pattern);
 240     rc = regcomp(regex, pattern, REG_EXTENDED|REG_NOSUB);
 241     free(pattern);
 242 
 243     return (rc == 0)? pcmk_ok : -EINVAL;
 244 }
 245 
 246 void
 247 attrd_free_attribute_value(gpointer data)
     /* [previous][next][first][last][top][bottom][index][help] */
 248 {
 249     attribute_value_t *v = data;
 250 
 251     free(v->nodename);
 252     free(v->current);
 253     free(v->requested);
 254     free(v);
 255 }
 256 
 257 void
 258 attrd_free_attribute(gpointer data)
     /* [previous][next][first][last][top][bottom][index][help] */
 259 {
 260     attribute_t *a = data;
 261     if(a) {
 262         free(a->id);
 263         free(a->set);
 264         free(a->uuid);
 265         free(a->user);
 266 
 267         mainloop_timer_del(a->timer);
 268         g_hash_table_destroy(a->values);
 269 
 270         free(a);
 271     }
 272 }
 273 
 274 void
 275 attrd_update_minimum_protocol_ver(const char *value)
     /* [previous][next][first][last][top][bottom][index][help] */
 276 {
 277     int ver;
 278 
 279     pcmk__scan_min_int(value, &ver, 0);
 280 
 281     if (ver > 0 && (minimum_protocol_version == -1 || ver < minimum_protocol_version)) {
 282         minimum_protocol_version = ver;
 283         crm_trace("Set minimum attrd protocol version to %d",
 284                   minimum_protocol_version);
 285     }
 286 }

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