pacemaker  2.1.1-52dc28db4
Scalable High-Availability cluster resource manager
attrd_client.c
Go to the documentation of this file.
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>
21 
30 static xmlNode *
31 create_attrd_op(const char *user_name)
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 
51 static int
52 send_attrd_op(crm_ipc_t *ipc, xmlNode *attrd_op)
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;
60 
61  if (ipc == NULL && local_ipc == NULL) {
62  local_ipc = crm_ipc_new(T_ATTRD, 0);
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 
132 int
133 pcmk__node_attr_request(crm_ipc_t *ipc, char command, const char *host,
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':
170  display_command = "refresh";
171  break;
172  case 'B':
174  name_as = PCMK__XA_ATTR_NAME;
175  break;
176  case 'Y':
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':
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);
203  crm_xml_add(update, PCMK__XA_ATTR_SET, set);
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 
238 int
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 
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);
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 
278 const char *
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 
319 char *
320 pcmk_promotion_score_name(const char *rsc_id)
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 }
pcmk__cpg_host_t host
Definition: cpg.c:49
#define T_ATTRD
Definition: msg_xml.h:79
#define PCMK__XA_ATTR_DAMPENING
Definition: crm_internal.h:51
#define PCMK__ATTRD_CMD_UPDATE_DELAY
Definition: crm_internal.h:88
#define PCMK__XA_ATTR_NAME
Definition: crm_internal.h:56
bool crm_ipc_connect(crm_ipc_t *client)
Establish an IPC connection to a Pacemaker component.
Definition: ipc_client.c:792
A dumping ground.
#define F_TYPE
Definition: msg_xml.h:63
#define PCMK__ATTRD_CMD_UPDATE_BOTH
Definition: crm_internal.h:87
#define PCMK__ATTRD_CMD_PEER_REMOVE
Definition: crm_internal.h:85
bool pcmk__strcase_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
Definition: strings.c:955
#define PCMK__XA_TASK
Definition: crm_internal.h:70
#define LRM_TARGET_ENV
Definition: attrd_client.c:273
const char * crm_xml_add_int(xmlNode *node, const char *name, int value)
Create an XML attribute with specified name and integer value.
Definition: nvpair.c:432
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.
Definition: nvpair.c:324
#define PCMK__XA_ATTR_VALUE
Definition: crm_internal.h:66
char * crm_system_name
Definition: utils.c:54
#define PCMK__XA_ATTR_RESOURCE
Definition: crm_internal.h:61
#define PCMK__ATTRD_CMD_CLEAR_FAILURE
Definition: crm_internal.h:94
const char * pcmk_rc_str(int rc)
Get a user-friendly description of a return code.
Definition: results.c:420
#define XML_CIB_TAG_NODES
Definition: msg_xml.h:181
#define XML_RSC_ATTR_TARGET
Definition: msg_xml.h:221
char * crm_meta_name(const char *field)
Definition: utils.c:511
#define PCMK__XA_ATTR_SECTION
Definition: crm_internal.h:62
int rc
Definition: pcmk_fence.c:35
#define crm_debug(fmt, args...)
Definition: logging.h:355
struct crm_ipc_s crm_ipc_t
Definition: ipc.h:162
#define PCMK__XA_ATTR_OPERATION
Definition: crm_internal.h:59
#define PCMK__ATTRD_CMD_REFRESH
Definition: crm_internal.h:90
int pcmk__node_attr_request_clear(crm_ipc_t *ipc, const char *host, const char *resource, const char *operation, const char *interval_spec, const char *user_name, int options)
Definition: attrd_client.c:239
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Definition: util.h:114
#define PCMK__XA_ATTR_INTERVAL
Definition: crm_internal.h:53
#define PCMK__XA_ATTR_IS_PRIVATE
Definition: crm_internal.h:54
xmlNode * create_xml_node(xmlNode *parent, const char *name)
Definition: xml.c:696
#define PCMK__XA_ATTR_USER
Definition: crm_internal.h:64
#define PCMK__ATTRD_CMD_QUERY
Definition: crm_internal.h:89
int pcmk_legacy2rc(int legacy_rc)
Definition: results.c:450
#define PCMK__ATTRD_CMD_UPDATE
Definition: crm_internal.h:86
#define F_ORIG
Definition: msg_xml.h:51
void free_xml(xmlNode *child)
Definition: xml.c:823
#define PCMK__ENV_PHYSICAL_HOST
Definition: crm_internal.h:102
int pcmk__node_attr_request(crm_ipc_t *ipc, char command, const char *host, const char *name, const char *value, const char *section, const char *set, const char *dampen, const char *user_name, int options)
Definition: attrd_client.c:133
const char * target
Definition: pcmk_fence.c:29
#define PCMK__XA_ATTR_NODE_NAME
Definition: crm_internal.h:58
#define crm_perror(level, fmt, args...)
Send a system error message to both the log and stderr.
Definition: logging.h:301
#define pcmk__set_ipc_flags(ipc_flags, ipc_name, flags_to_set)
Definition: ipc_internal.h:176
int crm_ipc_send(crm_ipc_t *client, xmlNode *message, enum crm_ipc_flags flags, int32_t ms_timeout, xmlNode **reply)
Send an IPC XML message.
Definition: ipc_client.c:1150
crm_ipc_t * crm_ipc_new(const char *name, size_t max_size)
Create a new (legacy) object for using Pacemaker daemon IPC.
Definition: ipc_client.c:745
#define PCMK__XA_ATTR_IS_REMOTE
Definition: crm_internal.h:55
#define pcmk_ok
Definition: results.h:67
#define XML_CIB_TAG_STATUS
Definition: msg_xml.h:179
#define PCMK__XA_ATTR_PATTERN
Definition: crm_internal.h:60
char * pcmk_promotion_score_name(const char *rsc_id)
Return the name of the node attribute used as a promotion score.
Definition: attrd_client.c:320
const char * pcmk__node_attr_target(const char *name)
Definition: attrd_client.c:279
#define PCMK__XA_ATTR_SET
Definition: crm_internal.h:63
char * name
Definition: pcmk_fence.c:31
crm_ipc_flags
Definition: ipc.h:143
void crm_ipc_close(crm_ipc_t *client)
Definition: ipc_client.c:862
#define crm_info(fmt, args...)
Definition: logging.h:353
uint64_t flags
Definition: remote.c:149