root/lib/common/attrd_client.c

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

DEFINITIONS

This source file includes following definitions.
  1. create_attrd_op
  2. send_attrd_op
  3. pcmk__node_attr_request
  4. pcmk__node_attr_request_clear
  5. pcmk__node_attr_target
  6. pcmk_promotion_score_name

   1 /*
   2  * Copyright 2011-2021 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 Lesser General Public License
   7  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
   8  */
   9 
  10 #ifndef _GNU_SOURCE
  11 #  define _GNU_SOURCE
  12 #endif
  13 
  14 #include <crm_internal.h>
  15 
  16 #include <stdio.h>
  17 
  18 #include <crm/crm.h>
  19 #include <crm/msg_xml.h>
  20 #include <crm/common/attrd_internal.h>
  21 
  22 /*!
  23  * \internal
  24  * \brief Create a generic pacemaker-attrd operation
  25  *
  26  * \param[in] user_name  If not NULL, ACL user to set for operation
  27  *
  28  * \return XML of pacemaker-attrd operation
  29  */
  30 static xmlNode *
  31 create_attrd_op(const char *user_name)
     /* [previous][next][first][last][top][bottom][index][help] */
  32 {
  33     xmlNode *attrd_op = create_xml_node(NULL, __func__);
  34 
  35     crm_xml_add(attrd_op, F_TYPE, T_ATTRD);
  36     crm_xml_add(attrd_op, F_ORIG, (crm_system_name? crm_system_name: "unknown"));
  37     crm_xml_add(attrd_op, PCMK__XA_ATTR_USER, user_name);
  38 
  39     return attrd_op;
  40 }
  41 
  42 /*!
  43  * \internal
  44  * \brief Send an operation to pacemaker-attrd via IPC
  45  *
  46  * \param[in] ipc       Connection to pacemaker-attrd (or create one if NULL)
  47  * \param[in] attrd_op  XML of pacemaker-attrd operation to send
  48  *
  49  * \return Standard Pacemaker return code
  50  */
  51 static int
  52 send_attrd_op(crm_ipc_t *ipc, xmlNode *attrd_op)
     /* [previous][next][first][last][top][bottom][index][help] */
  53 {
  54     int rc = -ENOTCONN; // initially handled as legacy return code
  55     int max = 5;
  56 
  57     static gboolean connected = TRUE;
  58     static crm_ipc_t *local_ipc = NULL;
  59     static enum crm_ipc_flags flags = crm_ipc_flags_none;
  60 
  61     if (ipc == NULL && local_ipc == NULL) {
  62         local_ipc = crm_ipc_new(T_ATTRD, 0);
  63         pcmk__set_ipc_flags(flags, "client", crm_ipc_client_response);
  64         connected = FALSE;
  65     }
  66 
  67     if (ipc == NULL) {
  68         ipc = local_ipc;
  69     }
  70 
  71     while (max > 0) {
  72         if (connected == FALSE) {
  73             crm_info("Connecting to cluster... %d retries remaining", max);
  74             connected = crm_ipc_connect(ipc);
  75         }
  76 
  77         if (connected) {
  78             rc = crm_ipc_send(ipc, attrd_op, flags, 0, NULL);
  79         } else {
  80             crm_perror(LOG_INFO, "Connection to cluster attribute manager failed");
  81         }
  82 
  83         if (ipc != local_ipc) {
  84             break;
  85 
  86         } else if (rc > 0) {
  87             break;
  88 
  89         } else if (rc == -EAGAIN || rc == -EALREADY) {
  90             sleep(5 - max);
  91             max--;
  92 
  93         } else {
  94             crm_ipc_close(ipc);
  95             connected = FALSE;
  96             sleep(5 - max);
  97             max--;
  98         }
  99     }
 100 
 101     if (rc > 0) {
 102         rc = pcmk_ok;
 103     }
 104     return pcmk_legacy2rc(rc);
 105 }
 106 
 107 /*!
 108  * \internal
 109  * \brief Send a request to pacemaker-attrd
 110  *
 111  * \param[in] ipc      Connection to pacemaker-attrd (or NULL to use a local connection)
 112  * \param[in] command  A character indicating the type of pacemaker-attrd request:
 113  *                     U or v: update attribute (or refresh if name is NULL)
 114  *                     u: update attributes matching regular expression in name
 115  *                     D: delete attribute (value must be NULL)
 116  *                     R: refresh
 117  *                     B: update both attribute and its dampening
 118  *                     Y: update attribute dampening only
 119  *                     Q: query attribute
 120  *                     C: remove peer specified by host
 121  * \param[in] host     Affect only this host (or NULL for all hosts)
 122  * \param[in] name     Name of attribute to affect
 123  * \param[in] value    Attribute value to set
 124  * \param[in] section  Status or nodes
 125  * \param[in] set      ID of attribute set to use (or NULL to choose first)
 126  * \param[in] dampen   Attribute dampening to use with B/Y, and U/v if creating
 127  * \param[in] user_name ACL user to pass to pacemaker-attrd
 128  * \param[in] options  Bitmask of pcmk__node_attr_opts
 129  *
 130  * \return Standard Pacemaker return code
 131  */
 132 int
 133 pcmk__node_attr_request(crm_ipc_t *ipc, char command, const char *host,
     /* [previous][next][first][last][top][bottom][index][help] */
 134                         const char *name, const char *value,
 135                         const char *section, const char *set,
 136                         const char *dampen, const char *user_name, int options)
 137 {
 138     int rc = pcmk_rc_ok;
 139     const char *task = NULL;
 140     const char *name_as = NULL;
 141     const char *display_host = (host ? host : "localhost");
 142     const char *display_command = NULL; /* for commands without name/value */
 143     xmlNode *update = create_attrd_op(user_name);
 144 
 145     /* remap common aliases */
 146     if (pcmk__str_eq(section, "reboot", pcmk__str_casei)) {
 147         section = XML_CIB_TAG_STATUS;
 148 
 149     } else if (pcmk__str_eq(section, "forever", pcmk__str_casei)) {
 150         section = XML_CIB_TAG_NODES;
 151     }
 152 
 153     if (name == NULL && command == 'U') {
 154         command = 'R';
 155     }
 156 
 157     switch (command) {
 158         case 'u':
 159             task = PCMK__ATTRD_CMD_UPDATE;
 160             name_as = PCMK__XA_ATTR_PATTERN;
 161             break;
 162         case 'D':
 163         case 'U':
 164         case 'v':
 165             task = PCMK__ATTRD_CMD_UPDATE;
 166             name_as = PCMK__XA_ATTR_NAME;
 167             break;
 168         case 'R':
 169             task = PCMK__ATTRD_CMD_REFRESH;
 170             display_command = "refresh";
 171             break;
 172         case 'B':
 173             task = PCMK__ATTRD_CMD_UPDATE_BOTH;
 174             name_as = PCMK__XA_ATTR_NAME;
 175             break;
 176         case 'Y':
 177             task = PCMK__ATTRD_CMD_UPDATE_DELAY;
 178             name_as = PCMK__XA_ATTR_NAME;
 179             break;
 180         case 'Q':
 181             task = PCMK__ATTRD_CMD_QUERY;
 182             name_as = PCMK__XA_ATTR_NAME;
 183             break;
 184         case 'C':
 185             task = PCMK__ATTRD_CMD_PEER_REMOVE;
 186             display_command = "purge";
 187             break;
 188     }
 189 
 190     if (name_as != NULL) {
 191         if (name == NULL) {
 192             rc = EINVAL;
 193             goto done;
 194         }
 195         crm_xml_add(update, name_as, name);
 196     }
 197 
 198     crm_xml_add(update, PCMK__XA_TASK, task);
 199     crm_xml_add(update, PCMK__XA_ATTR_VALUE, value);
 200     crm_xml_add(update, PCMK__XA_ATTR_DAMPENING, dampen);
 201     crm_xml_add(update, PCMK__XA_ATTR_SECTION, section);
 202     crm_xml_add(update, PCMK__XA_ATTR_NODE_NAME, host);
 203     crm_xml_add(update, PCMK__XA_ATTR_SET, set);
 204     crm_xml_add_int(update, PCMK__XA_ATTR_IS_REMOTE,
 205                     pcmk_is_set(options, pcmk__node_attr_remote));
 206     crm_xml_add_int(update, PCMK__XA_ATTR_IS_PRIVATE,
 207                     pcmk_is_set(options, pcmk__node_attr_private));
 208 
 209     rc = send_attrd_op(ipc, update);
 210 
 211 done:
 212     free_xml(update);
 213 
 214     if (display_command) {
 215         crm_debug("Asked pacemaker-attrd to %s %s: %s (%d)",
 216                   display_command, display_host, pcmk_rc_str(rc), rc);
 217     } else {
 218         crm_debug("Asked pacemaker-attrd to update %s=%s for %s: %s (%d)",
 219                   name, value, display_host, pcmk_rc_str(rc), rc);
 220     }
 221     return rc;
 222 }
 223 
 224 /*!
 225  * \internal
 226  * \brief Send a request to pacemaker-attrd to clear resource failure
 227  *
 228  * \param[in] ipc           Connection to pacemaker-attrd (NULL to use local connection)
 229  * \param[in] host          Affect only this host (or NULL for all hosts)
 230  * \param[in] resource      Name of resource to clear (or NULL for all)
 231  * \param[in] operation     Name of operation to clear (or NULL for all)
 232  * \param[in] interval_spec If operation is not NULL, its interval
 233  * \param[in] user_name     ACL user to pass to pacemaker-attrd
 234  * \param[in] options       Bitmask of pcmk__node_attr_opts
 235  *
 236  * \return pcmk_ok if request was successfully submitted to pacemaker-attrd, else -errno
 237  */
 238 int
 239 pcmk__node_attr_request_clear(crm_ipc_t *ipc, const char *host,
     /* [previous][next][first][last][top][bottom][index][help] */
 240                               const char *resource, const char *operation,
 241                               const char *interval_spec, const char *user_name,
 242                               int options)
 243 {
 244     int rc = pcmk_rc_ok;
 245     xmlNode *clear_op = create_attrd_op(user_name);
 246     const char *interval_desc = NULL;
 247     const char *op_desc = NULL;
 248 
 249     crm_xml_add(clear_op, PCMK__XA_TASK, PCMK__ATTRD_CMD_CLEAR_FAILURE);
 250     crm_xml_add(clear_op, PCMK__XA_ATTR_NODE_NAME, host);
 251     crm_xml_add(clear_op, PCMK__XA_ATTR_RESOURCE, resource);
 252     crm_xml_add(clear_op, PCMK__XA_ATTR_OPERATION, operation);
 253     crm_xml_add(clear_op, PCMK__XA_ATTR_INTERVAL, interval_spec);
 254     crm_xml_add_int(clear_op, PCMK__XA_ATTR_IS_REMOTE,
 255                     pcmk_is_set(options, pcmk__node_attr_remote));
 256 
 257     rc = send_attrd_op(ipc, clear_op);
 258     free_xml(clear_op);
 259 
 260     if (operation) {
 261         interval_desc = interval_spec? interval_spec : "nonrecurring";
 262         op_desc = operation;
 263     } else {
 264         interval_desc = "all";
 265         op_desc = "operations";
 266     }
 267     crm_debug("Asked pacemaker-attrd to clear failure of %s %s for %s on %s: %s (%d)",
 268               interval_desc, op_desc, (resource? resource : "all resources"),
 269               (host? host : "all nodes"), pcmk_rc_str(rc), rc);
 270     return rc;
 271 }
 272 
 273 #define LRM_TARGET_ENV "OCF_RESKEY_" CRM_META "_" XML_LRM_ATTR_TARGET
 274 
 275 /*!
 276  * \internal
 277  */
 278 const char *
 279 pcmk__node_attr_target(const char *name)
     /* [previous][next][first][last][top][bottom][index][help] */
 280 {
 281     if (name == NULL || pcmk__strcase_any_of(name, "auto", "localhost", NULL)) {
 282         char *target_var = crm_meta_name(XML_RSC_ATTR_TARGET);
 283         char *phys_var = crm_meta_name(PCMK__ENV_PHYSICAL_HOST);
 284         const char *target = getenv(target_var);
 285         const char *host_physical = getenv(phys_var);
 286 
 287         // It is important to use the name by which the scheduler knows us
 288         if (host_physical && pcmk__str_eq(target, "host", pcmk__str_casei)) {
 289             name = host_physical;
 290 
 291         } else {
 292             const char *host_pcmk = getenv(LRM_TARGET_ENV);
 293 
 294             if (host_pcmk) {
 295                 name = host_pcmk;
 296             }
 297         }
 298         free(target_var);
 299         free(phys_var);
 300 
 301         // TODO? Call get_local_node_name() if name == NULL
 302         // (currently would require linkage against libcrmcluster)
 303         return name;
 304     } else {
 305         return NULL;
 306     }
 307 }
 308 
 309 /*!
 310  * \brief Return the name of the node attribute used as a promotion score
 311  *
 312  * \param[in] rsc_id  Resource ID that promotion score is for (or NULL to
 313  *                    check the OCF_RESOURCE_INSTANCE environment variable)
 314  *
 315  * \return Newly allocated string with the node attribute name (or NULL on
 316  *         error, including no ID or environment variable specified)
 317  * \note It is the caller's responsibility to free() the result.
 318  */
 319 char *
 320 pcmk_promotion_score_name(const char *rsc_id)
     /* [previous][next][first][last][top][bottom][index][help] */
 321 {
 322     if (rsc_id == NULL) {
 323         rsc_id = getenv("OCF_RESOURCE_INSTANCE");
 324         if (rsc_id == NULL) {
 325             return NULL;
 326         }
 327     }
 328     return crm_strdup_printf("master-%s", rsc_id);
 329 }

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