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. attrd_update_delegate
  4. attrd_clear_delegate
  5. attrd_get_target

   1 /*
   2  * Copyright (C) 2011-2017 Andrew Beekhof <andrew@beekhof.net>
   3  *
   4  * This source code is licensed under the GNU Lesser General Public License
   5  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
   6  */
   7 
   8 
   9 #ifndef _GNU_SOURCE
  10 #  define _GNU_SOURCE
  11 #endif
  12 
  13 #include <crm_internal.h>
  14 
  15 #include <stdio.h>
  16 
  17 #include <crm/crm.h>
  18 #include <crm/msg_xml.h>
  19 #include <crm/attrd.h>
  20 
  21 /*!
  22  * \internal
  23  * \brief Create a generic attrd operation
  24  *
  25  * \param[in] user_name  If not NULL, ACL user to set for operation
  26  *
  27  * \return XML of attrd operation
  28  */
  29 static xmlNode *
  30 create_attrd_op(const char *user_name)
     /* [previous][next][first][last][top][bottom][index][help] */
  31 {
  32     xmlNode *attrd_op = create_xml_node(NULL, __FUNCTION__);
  33 
  34     crm_xml_add(attrd_op, F_TYPE, T_ATTRD);
  35     crm_xml_add(attrd_op, F_ORIG, (crm_system_name? crm_system_name: "unknown"));
  36 #if ENABLE_ACL
  37     crm_xml_add(attrd_op, F_ATTRD_USER, user_name);
  38 #endif
  39 
  40     return attrd_op;
  41 }
  42 
  43 /*!
  44  * \internal
  45  * \brief Send an operation to attrd via IPC
  46  *
  47  * \param[in] ipc       Connection to attrd (or NULL to use a local connection)
  48  * \param[in] attrd_op  XML of attrd operation to send
  49  *
  50  * \return pcmk_ok on success, -errno otherwise
  51  */
  52 static int
  53 send_attrd_op(crm_ipc_t *ipc, xmlNode *attrd_op)
     /* [previous][next][first][last][top][bottom][index][help] */
  54 {
  55     int rc = -ENOTCONN;
  56     int max = 5;
  57 
  58     static gboolean connected = TRUE;
  59     static crm_ipc_t *local_ipc = NULL;
  60     static enum crm_ipc_flags flags = crm_ipc_flags_none;
  61 
  62     if (ipc == NULL && local_ipc == NULL) {
  63         local_ipc = crm_ipc_new(T_ATTRD, 0);
  64         flags |= crm_ipc_client_response;
  65         connected = FALSE;
  66     }
  67 
  68     if (ipc == NULL) {
  69         ipc = local_ipc;
  70     }
  71 
  72     while (max > 0) {
  73         if (connected == FALSE) {
  74             crm_info("Connecting to cluster... %d retries remaining", max);
  75             connected = crm_ipc_connect(ipc);
  76         }
  77 
  78         if (connected) {
  79             rc = crm_ipc_send(ipc, attrd_op, flags, 0, NULL);
  80         } else {
  81             crm_perror(LOG_INFO, "Connection to cluster attribute manager failed");
  82         }
  83 
  84         if (ipc != local_ipc) {
  85             break;
  86 
  87         } else if (rc > 0) {
  88             break;
  89 
  90         } else if (rc == -EAGAIN || rc == -EALREADY) {
  91             sleep(5 - max);
  92             max--;
  93 
  94         } else {
  95             crm_ipc_close(ipc);
  96             connected = FALSE;
  97             sleep(5 - max);
  98             max--;
  99         }
 100     }
 101 
 102     if (rc > 0) {
 103         rc = pcmk_ok;
 104     }
 105     return rc;
 106 }
 107 
 108 /*!
 109  * \brief Send a request to attrd
 110  *
 111  * \param[in] ipc      Connection to attrd (or NULL to use a local connection)
 112  * \param[in] command  A character indicating the type of 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 attrd
 128  * \param[in] options  Bitmask that may include:
 129  *                     attrd_opt_remote: host is a Pacemaker Remote node
 130  *                     attrd_opt_private: attribute is private (not kept in CIB)
 131  *
 132  * \return pcmk_ok if request was successfully submitted to attrd, else -errno
 133  */
 134 int
 135 attrd_update_delegate(crm_ipc_t *ipc, char command, const char *host,
     /* [previous][next][first][last][top][bottom][index][help] */
 136                       const char *name, const char *value, const char *section,
 137                       const char *set, const char *dampen,
 138                       const char *user_name, int options)
 139 {
 140     int rc = pcmk_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 (safe_str_eq(section, "reboot")) {
 149         section = XML_CIB_TAG_STATUS;
 150 
 151     } else if (safe_str_eq(section, "forever")) {
 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 = ATTRD_OP_UPDATE;
 162             name_as = F_ATTRD_REGEX;
 163             break;
 164         case 'D':
 165         case 'U':
 166         case 'v':
 167             task = ATTRD_OP_UPDATE;
 168             name_as = F_ATTRD_ATTRIBUTE;
 169             break;
 170         case 'R':
 171             task = ATTRD_OP_REFRESH;
 172             display_command = "refresh";
 173             break;
 174         case 'B':
 175             task = ATTRD_OP_UPDATE_BOTH;
 176             name_as = F_ATTRD_ATTRIBUTE;
 177             break;
 178         case 'Y':
 179             task = ATTRD_OP_UPDATE_DELAY;
 180             name_as = F_ATTRD_ATTRIBUTE;
 181             break;
 182         case 'Q':
 183             task = ATTRD_OP_QUERY;
 184             name_as = F_ATTRD_ATTRIBUTE;
 185             break;
 186         case 'C':
 187             task = ATTRD_OP_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, F_ATTRD_TASK, task);
 201     crm_xml_add(update, F_ATTRD_VALUE, value);
 202     crm_xml_add(update, F_ATTRD_DAMPEN, dampen);
 203     crm_xml_add(update, F_ATTRD_SECTION, section);
 204     crm_xml_add(update, F_ATTRD_HOST, host);
 205     crm_xml_add(update, F_ATTRD_SET, set);
 206     crm_xml_add_int(update, F_ATTRD_IS_REMOTE, is_set(options, attrd_opt_remote));
 207     crm_xml_add_int(update, F_ATTRD_IS_PRIVATE, is_set(options, attrd_opt_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 attrd to %s %s: %s (%d)",
 216                   display_command, display_host, pcmk_strerror(rc), rc);
 217     } else {
 218         crm_debug("Asked attrd to update %s=%s for %s: %s (%d)",
 219                   name, value, display_host, pcmk_strerror(rc), rc);
 220     }
 221     return rc;
 222 }
 223 
 224 /*!
 225  * \brief Send a request to attrd to clear resource failure
 226  *
 227  * \param[in] ipc       Connection to attrd (or NULL to use a local connection)
 228  * \param[in] host      Affect only this host (or NULL for all hosts)
 229  * \param[in] name      Name of resource to clear
 230  * \param[in] user_name ACL user to pass to attrd
 231  * \param[in] options   attrd_opt_remote if host is a Pacemaker Remote node
 232  *
 233  * \return pcmk_ok if request was successfully submitted to attrd, else -errno
 234  */
 235 int
 236 attrd_clear_delegate(crm_ipc_t *ipc, const char *host, const char *resource,
     /* [previous][next][first][last][top][bottom][index][help] */
 237                      const char *operation, const char *interval,
 238                      const char *user_name, int options)
 239 {
 240     int rc = pcmk_ok;
 241     xmlNode *clear_op = create_attrd_op(user_name);
 242 
 243     crm_xml_add(clear_op, F_ATTRD_TASK, ATTRD_OP_CLEAR_FAILURE);
 244     crm_xml_add(clear_op, F_ATTRD_HOST, host);
 245     crm_xml_add(clear_op, F_ATTRD_RESOURCE, resource);
 246     crm_xml_add(clear_op, F_ATTRD_OPERATION, operation);
 247     crm_xml_add(clear_op, F_ATTRD_INTERVAL, interval);
 248     crm_xml_add_int(clear_op, F_ATTRD_IS_REMOTE, is_set(options, attrd_opt_remote));
 249 
 250     rc = send_attrd_op(ipc, clear_op);
 251     free_xml(clear_op);
 252 
 253     crm_debug("Asked attrd to clear failure of %s (interval %s) for %s on %s: %s (%d)",
 254               (operation? operation : "all operations"),
 255               (interval? interval : "0"),
 256               (resource? resource : "all resources"),
 257               (host? host : "all nodes"), pcmk_strerror(rc), rc);
 258     return rc;
 259 }
 260 
 261 #define LRM_TARGET_ENV "OCF_RESKEY_" CRM_META "_" XML_LRM_ATTR_TARGET
 262 
 263 const char *
 264 attrd_get_target(const char *name)
     /* [previous][next][first][last][top][bottom][index][help] */
 265 {
 266     if(safe_str_eq(name, "auto") || safe_str_eq(name, "localhost")) {
 267         name = NULL;
 268     }
 269 
 270     if(name != NULL) {
 271         return name;
 272 
 273     } else {
 274         char *target_var = crm_meta_name(XML_RSC_ATTR_TARGET);
 275         char *phys_var = crm_meta_name(PCMK_ENV_PHYSICAL_HOST);
 276         const char *target = getenv(target_var);
 277         const char *host_physical = getenv(phys_var);
 278 
 279         /* It is important we use the names by which the PE knows us */
 280         if (host_physical && safe_str_eq(target, "host")) {
 281             name = host_physical;
 282 
 283         } else {
 284             const char *host_pcmk = getenv(LRM_TARGET_ENV);
 285 
 286             if (host_pcmk) {
 287                 name = host_pcmk;
 288             }
 289         }
 290         free(target_var);
 291         free(phys_var);
 292     }
 293 
 294     // TODO? Call get_local_node_name() if name == NULL
 295     // (currently would require linkage against libcrmcluster)
 296     return name;
 297 }

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