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

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

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