pacemaker  1.1.18-7fdfbbe
Scalable High-Availability cluster resource manager
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
utils.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 #include <crm_internal.h>
20 #include <crm/cluster/internal.h>
21 #include <sys/types.h>
22 #include <stdlib.h>
23 #include <unistd.h>
24 #include <fcntl.h>
25 #include <errno.h>
26 #include <stdio.h>
27 #include <signal.h>
28 #include <sys/types.h>
29 #include <sys/time.h>
30 #include <sys/resource.h>
31 
32 #include <pwd.h>
33 #include <glib.h>
34 #include <bzlib.h>
35 #include <grp.h>
36 
37 #include "./utils.h"
38 #include "./plugin.h"
39 
41 
42 void
43 log_ais_message(int level, const AIS_Message * msg)
44 {
45  char *data = get_ais_data(msg);
46 
47  qb_log_from_external_source(__func__, __FILE__,
48  "Msg[%d] (dest=%s:%s, from=%s:%s.%d, remote=%s, size=%d): %.90s",
49  level, __LINE__, 0,
50  msg->id, ais_dest(&(msg->host)), msg_type2text(msg->host.type),
51  ais_dest(&(msg->sender)), msg_type2text(msg->sender.type),
52  msg->sender.pid,
53  msg->sender.uname == local_uname ? "false" : "true",
54  ais_data_len(msg), data);
55 /* do_ais_log(level, */
56 /* "Msg[%d] (dest=%s:%s, from=%s:%s.%d, remote=%s, size=%d): %.90s", */
57 /* msg->id, ais_dest(&(msg->host)), msg_type2text(msg->host.type), */
58 /* ais_dest(&(msg->sender)), msg_type2text(msg->sender.type), */
59 /* msg->sender.pid, */
60 /* msg->sender.uname==local_uname?"false":"true", */
61 /* ais_data_len(msg), data); */
62  ais_free(data);
63 }
64 
65 /*
66 static gboolean ghash_find_by_uname(gpointer key, gpointer value, gpointer user_data)
67 {
68  crm_node_t *node = value;
69  int id = GPOINTER_TO_INT(user_data);
70 
71  if (node->id == id) {
72  return TRUE;
73  }
74  return FALSE;
75 }
76 */
77 
78 static int
79 ais_string_to_boolean(const char *s)
80 {
81  int rc = 0;
82 
83  if (s == NULL) {
84  return rc;
85  }
86 
87  if (strcasecmp(s, "true") == 0
88  || strcasecmp(s, "on") == 0
89  || strcasecmp(s, "yes") == 0 || strcasecmp(s, "y") == 0 || strcasecmp(s, "1") == 0) {
90  rc = 1;
91  }
92  return rc;
93 }
94 
95 static char *opts_default[] = { NULL, NULL };
96 static char *opts_vgrind[] = { NULL, NULL, NULL, NULL, NULL };
97 
98 static void
99 pcmk_setscheduler(crm_child_t * child)
100 {
101 #if defined(HAVE_SCHED_SETSCHEDULER)
102  int policy = sched_getscheduler(0);
103 
104  if (policy == -1) {
105  ais_perror("Could not get scheduling policy for %s", child->name);
106 
107  } else {
108  int priority = -10;
109 
110  if (policy != SCHED_OTHER) {
111  struct sched_param sp;
112 
113  policy = SCHED_OTHER;
114 # if defined(SCHED_RESET_ON_FORK)
115  policy |= SCHED_RESET_ON_FORK;
116 # endif
117  memset(&sp, 0, sizeof(sp));
118  sp.sched_priority = 0;
119 
120  if (sched_setscheduler(0, policy, &sp) == -1) {
121  ais_perror("Could not reset scheduling policy to SCHED_OTHER for %s", child->name);
122  return;
123  }
124  }
125 
126  if (setpriority(PRIO_PROCESS, 0, priority) == -1) {
127  ais_perror("Could not reset process priority to %d for %s", priority, child->name);
128  }
129  }
130 #else
131  ais_info("The platform is missing process priority setting features. Leaving at default.");
132 #endif
133 }
134 
135 gboolean
137 {
138  int lpc = 0;
139  uid_t uid = 0;
140  gid_t gid = 0;
141  struct rlimit oflimits;
142  gboolean use_valgrind = FALSE;
143  gboolean use_callgrind = FALSE;
144  const char *devnull = "/dev/null";
145  const char *env_valgrind = getenv("PCMK_valgrind_enabled");
146  const char *env_callgrind = getenv("PCMK_callgrind_enabled");
147 
148  if (child->command == NULL) {
149  ais_info("Nothing to do for child \"%s\"", child->name);
150  return TRUE;
151  }
152 
153  if (ais_string_to_boolean(env_callgrind)) {
154  use_callgrind = TRUE;
155  use_valgrind = TRUE;
156 
157  } else if (env_callgrind != NULL && strstr(env_callgrind, child->name)) {
158  use_callgrind = TRUE;
159  use_valgrind = TRUE;
160 
161  } else if (ais_string_to_boolean(env_valgrind)) {
162  use_valgrind = TRUE;
163 
164  } else if (env_valgrind != NULL && strstr(env_valgrind, child->name)) {
165  use_valgrind = TRUE;
166  }
167 
168  if (use_valgrind && strlen(VALGRIND_BIN) == 0) {
169  ais_warn("Cannot enable valgrind for %s:"
170  " The location of the valgrind binary is unknown", child->name);
171  use_valgrind = FALSE;
172  }
173 
174  if (child->uid) {
175  if (pcmk_user_lookup(child->uid, &uid, &gid) < 0) {
176  ais_err("Invalid uid (%s) specified for %s", child->uid, child->name);
177  return FALSE;
178  }
179  ais_info("Using uid=%u and group=%u for process %s", uid, gid, child->name);
180  }
181 
182  child->pid = fork();
183  AIS_ASSERT(child->pid != -1);
184 
185  if (child->pid > 0) {
186  /* parent */
187  ais_info("Forked child %d for process %s%s", child->pid, child->name,
188  use_valgrind ? " (valgrind enabled: " VALGRIND_BIN ")" : "");
189 
190  } else {
191  pcmk_setscheduler(child);
192 
193  /* Setup the two alternate arg arrays */
194  opts_vgrind[0] = ais_strdup(VALGRIND_BIN);
195  if (use_callgrind) {
196  opts_vgrind[1] = ais_strdup("--tool=callgrind");
197  opts_vgrind[2] = ais_strdup("--callgrind-out-file=" CRM_STATE_DIR "/callgrind.out.%p");
198  opts_vgrind[3] = ais_strdup(child->command);
199  opts_vgrind[4] = NULL;
200  } else {
201  opts_vgrind[1] = ais_strdup(child->command);
202  opts_vgrind[2] = NULL;
203  opts_vgrind[3] = NULL;
204  opts_vgrind[4] = NULL;
205  }
206  opts_default[0] = ais_strdup(child->command);
207 
208  if (uid && initgroups(child->uid, gid) < 0) {
209  ais_perror("Cannot initialize groups for %s", child->uid);
210  }
211 
212  if (uid && setuid(uid) < 0) {
213  ais_perror("Could not set user to %d (%s)", uid, child->uid);
214  }
215 
216  /* Close all open file descriptors */
217  getrlimit(RLIMIT_NOFILE, &oflimits);
218  for (; lpc < oflimits.rlim_cur; lpc++) {
219  close(lpc);
220  }
221 
222  (void)open(devnull, O_RDONLY); /* Stdin: fd 0 */
223  (void)open(devnull, O_WRONLY); /* Stdout: fd 1 */
224  (void)open(devnull, O_WRONLY); /* Stderr: fd 2 */
225 
226 /* *INDENT-OFF* */
227  setenv("HA_COMPRESSION", "bz2", 1);
228  setenv("HA_cluster_type", "openais", 1);
229  setenv("HA_debug", pcmk_env.debug, 1);
230  setenv("HA_logfacility", pcmk_env.syslog, 1);
231  setenv("HA_LOGFACILITY", pcmk_env.syslog, 1);
232  setenv("HA_use_logd", pcmk_env.use_logd, 1);
233  setenv("HA_quorum_type", pcmk_env.quorum, 1);
234 /* *INDENT-ON* */
235 
236  if (pcmk_env.logfile) {
237  setenv("HA_logfile", pcmk_env.logfile, 1);
238  }
239 
240  if (use_valgrind) {
241  (void)execvp(VALGRIND_BIN, opts_vgrind);
242  } else {
243  (void)execvp(child->command, opts_default);
244  }
245  ais_perror("FATAL: Cannot exec %s", child->command);
246  exit(100);
247  }
248  return TRUE;
249 }
250 
251 gboolean
252 stop_child(crm_child_t * child, int signal)
253 {
254  if (signal == 0) {
255  signal = SIGTERM;
256  }
257 
258  if (child->command == NULL) {
259  ais_info("Nothing to do for child \"%s\"", child->name);
260  return TRUE;
261  }
262 
263  ais_debug("Stopping CRM child \"%s\"", child->name);
264 
265  if (child->pid <= 0) {
266  ais_trace("Client %s not running", child->name);
267  return TRUE;
268  }
269 
270  errno = 0;
271  if (kill(child->pid, signal) == 0) {
272  ais_notice("Sent -%d to %s: [%d]", signal, child->name, child->pid);
273 
274  } else {
275  ais_perror("Sent -%d to %s: [%d]", signal, child->name, child->pid);
276  }
277 
278  return TRUE;
279 }
280 
281 void
283 {
284  crm_node_t *node = data;
285 
286  ais_info("Destroying entry for node %u", node->id);
287 
288  ais_free(node->addr);
289  ais_free(node->uname);
290  ais_free(node->state);
291  ais_free(node);
292 }
293 
294 int
295 update_member(unsigned int id, uint64_t born, uint64_t seq, int32_t votes,
296  uint32_t procs, const char *uname, const char *state, const char *version)
297 {
298  int changed = 0;
299  crm_node_t *node = NULL;
300 
301  node = g_hash_table_lookup(membership_list, GUINT_TO_POINTER(id));
302 
303  if (node == NULL) {
304  ais_malloc0(node, sizeof(crm_node_t));
305  ais_info("Creating entry for node %u born on " U64T "", id, seq);
306  node->id = id;
307  node->addr = NULL;
308  node->state = ais_strdup("unknown");
309 
310  g_hash_table_insert(membership_list, GUINT_TO_POINTER(id), node);
311  node = g_hash_table_lookup(membership_list, GUINT_TO_POINTER(id));
312  }
313  AIS_ASSERT(node != NULL);
314 
315  if (seq != 0) {
316  node->last_seen = seq;
317  }
318 
319  if (born != 0 && node->born != born) {
320  changed = TRUE;
321  node->born = born;
322  ais_info("%p Node %u (%s) born on: " U64T, node, id, uname, born);
323  }
324 
325  if (version != NULL) {
326  ais_free(node->version);
327  node->version = ais_strdup(version);
328  }
329 
330  if (uname != NULL) {
331  if (node->uname == NULL || ais_str_eq(node->uname, uname) == FALSE) {
332  ais_info("%p Node %u now known as %s (was: %s)", node, id, uname, node->uname);
333  ais_free(node->uname);
334  node->uname = ais_strdup(uname);
335  changed = TRUE;
336  }
337  }
338 
339  if (procs != 0 && procs != node->processes) {
340  ais_info("Node %s now has process list: %.32x (%u)", node->uname, procs, procs);
341  node->processes = procs;
342  changed = TRUE;
343  }
344 
345  if (votes >= 0 && votes != node->votes) {
346  ais_info("Node %s now has %d quorum votes (was %d)", node->uname, votes, node->votes);
347  node->votes = votes;
348  changed = TRUE;
349  }
350 
351  if (state != NULL) {
352  if (node->state == NULL || ais_str_eq(node->state, state) == FALSE) {
353  ais_free(node->state);
354  node->state = ais_strdup(state);
355  ais_info("Node %u/%s is now: %s", id, node->uname ? node->uname : "unknown", state);
356  changed = TRUE;
357  }
358  }
359 
360  return changed;
361 }
362 
363 void
364 delete_member(uint32_t id, const char *uname)
365 {
366  if (uname == NULL) {
367  g_hash_table_remove(membership_list, GUINT_TO_POINTER(id));
368  return;
369  }
370  ais_err("Deleting by uname is not yet supported");
371 }
372 
373 const char *
375 {
376  crm_node_t *node = g_hash_table_lookup(membership_list, GUINT_TO_POINTER(id));
377 
378  if (node == NULL) {
379  return ".unknown.";
380  }
381  if (node->uname == NULL) {
382  return ".pending.";
383  }
384  return node->uname;
385 }
386 
387 char *
389 {
390  int size = 1; /* nul */
391  int offset = 0;
392  static int fixed_len = 4 + 8 + 7 + 6 + 6 + 7 + 11;
393 
394  if (data) {
395  size = strlen(data);
396  }
397  offset = size;
398 
399  size += fixed_len;
400  size += 32; /* node->id */
401  size += 100; /* node->seq, node->born */
402  size += strlen(node->state);
403  if (node->uname) {
404  size += (7 + strlen(node->uname));
405  }
406  if (node->addr) {
407  size += (6 + strlen(node->addr));
408  }
409  if (node->version) {
410  size += (9 + strlen(node->version));
411  }
412  data = realloc_safe(data, size);
413 
414  offset += snprintf(data + offset, size - offset, "<node id=\"%u\" ", node->id);
415  if (node->uname) {
416  offset += snprintf(data + offset, size - offset, "uname=\"%s\" ", node->uname);
417  }
418  offset += snprintf(data + offset, size - offset, "state=\"%s\" ", node->state);
419  offset += snprintf(data + offset, size - offset, "born=\"" U64T "\" ", node->born);
420  offset += snprintf(data + offset, size - offset, "seen=\"" U64T "\" ", node->last_seen);
421  offset += snprintf(data + offset, size - offset, "votes=\"%d\" ", node->votes);
422  offset += snprintf(data + offset, size - offset, "processes=\"%u\" ", node->processes);
423  if (node->addr) {
424  offset += snprintf(data + offset, size - offset, "addr=\"%s\" ", node->addr);
425  }
426  if (node->version) {
427  offset += snprintf(data + offset, size - offset, "version=\"%s\" ", node->version);
428  }
429  offset += snprintf(data + offset, size - offset, "/>");
430 
431  return data;
432 }
433 
434 void
436 {
437  int tmp = 0;
438  char tmp_s[256];
439 
440  tmp = msg->host.type;
441  msg->host.type = msg->sender.type;
442  msg->sender.type = tmp;
443 
444  tmp = msg->host.type;
445  msg->host.size = msg->sender.type;
446  msg->sender.type = tmp;
447 
448  memcpy(tmp_s, msg->host.uname, 256);
449  memcpy(msg->host.uname, msg->sender.uname, 256);
450  memcpy(msg->sender.uname, tmp_s, 256);
451 }
452 
453 char *
455 {
456  int rc = BZ_OK;
457  char *uncompressed = NULL;
458  unsigned int new_size = msg->size + 1;
459 
460  if (msg->is_compressed == FALSE) {
461  uncompressed = strdup(msg->data);
462 
463  } else {
464  ais_malloc0(uncompressed, new_size);
465 
466  rc = BZ2_bzBuffToBuffDecompress(uncompressed, &new_size, (char *)msg->data,
467  msg->compressed_size, 1, 0);
468  if (rc != BZ_OK) {
469  ais_info("rc=%d, new=%u expected=%u", rc, new_size, msg->size);
470  }
471  AIS_ASSERT(rc == BZ_OK);
472  AIS_ASSERT(new_size == msg->size);
473  }
474 
475  return uncompressed;
476 }
477 
478 int
479 send_plugin_msg(enum crm_ais_msg_types type, const char *host, const char *data)
480 {
481  int rc = 0;
482  int data_len = 0;
483  AIS_Message *ais_msg = NULL;
484  int total_size = sizeof(AIS_Message);
485 
486  AIS_ASSERT(local_nodeid != 0);
487 
488  if (data != NULL) {
489  data_len = 1 + strlen(data);
490  total_size += data_len;
491  }
492  ais_malloc0(ais_msg, total_size);
493 
494  ais_msg->header.size = total_size;
495  ais_msg->header.error = CS_OK;
496  ais_msg->header.id = 0;
497 
498  ais_msg->size = data_len;
499  ais_msg->sender.type = crm_msg_ais;
500  if (data != NULL) {
501  memcpy(ais_msg->data, data, data_len);
502  }
503 
504  ais_msg->host.type = type;
505  ais_msg->host.id = 0;
506  if (host) {
507  ais_msg->host.size = strlen(host);
508  memset(ais_msg->host.uname, 0, MAX_NAME);
509  memcpy(ais_msg->host.uname, host, ais_msg->host.size);
510 /* ais_msg->host.id = nodeid_lookup(host); */
511 
512  } else {
513  ais_msg->host.type = type;
514  ais_msg->host.size = 0;
515  memset(ais_msg->host.uname, 0, MAX_NAME);
516  }
517 
518  rc = send_plugin_msg_raw(ais_msg);
519  ais_free(ais_msg);
520 
521  return rc;
522 }
523 
524 extern struct corosync_api_v1 *pcmk_api;
525 
526 int
527 send_client_ipc(void *conn, const AIS_Message * ais_msg)
528 {
529  int rc = -1;
530 
531  if (conn == NULL) {
532  rc = -2;
533 
534  } else if (!libais_connection_active(conn)) {
535  ais_warn("Connection no longer active");
536  rc = -3;
537 
538 /* } else if ((queue->size - 1) == queue->used) { */
539 /* ais_err("Connection is throttled: %d", queue->size); */
540 
541  } else {
542 #if SUPPORT_COROSYNC
543  rc = pcmk_api->ipc_dispatch_send(conn, ais_msg, ais_msg->header.size);
544 #endif
545  }
546  return rc;
547 }
548 
549 int
551  const char *data)
552 {
553  int rc = 0;
554  int data_len = 0;
555  int total_size = sizeof(AIS_Message);
556  AIS_Message *ais_msg = NULL;
557  static int msg_id = 0;
558 
559  AIS_ASSERT(local_nodeid != 0);
560 
561  msg_id++;
562  AIS_ASSERT(msg_id != 0 /* wrap-around */ );
563 
564  if (data != NULL) {
565  data_len = 1 + strlen(data);
566  }
567  total_size += data_len;
568 
569  ais_malloc0(ais_msg, total_size);
570 
571  ais_msg->id = msg_id;
572  ais_msg->header.id = class;
573  ais_msg->header.size = total_size;
574  ais_msg->header.error = CS_OK;
575 
576  ais_msg->size = data_len;
577  if (data != NULL) {
578  memcpy(ais_msg->data, data, data_len);
579  }
580 
581  ais_msg->host.size = 0;
582  ais_msg->host.type = type;
583  memset(ais_msg->host.uname, 0, MAX_NAME);
584  ais_msg->host.id = 0;
585 
586  ais_msg->sender.type = crm_msg_ais;
587  ais_msg->sender.size = local_uname_len;
588  memset(ais_msg->sender.uname, 0, MAX_NAME);
589  memcpy(ais_msg->sender.uname, local_uname, ais_msg->sender.size);
590  ais_msg->sender.id = local_nodeid;
591 
592  rc = send_client_ipc(conn, ais_msg);
593 
594  if (rc != 0) {
595  ais_warn("Sending message to %s failed: %d", msg_type2text(type), rc);
596  log_ais_message(LOG_DEBUG, ais_msg);
597  }
598 
599  ais_free(ais_msg);
600  return rc;
601 }
602 
603 char *
604 ais_concat(const char *prefix, const char *suffix, char join)
605 {
606  int len = 0;
607  char *new_str = NULL;
608 
609  AIS_ASSERT(prefix != NULL);
610  AIS_ASSERT(suffix != NULL);
611  len = strlen(prefix) + strlen(suffix) + 2;
612 
613  ais_malloc0(new_str, (len));
614  sprintf(new_str, "%s%c%s", prefix, join, suffix);
615  new_str[len - 1] = 0;
616  return new_str;
617 }
618 
619 hdb_handle_t
620 config_find_init(struct corosync_api_v1 * config, char *name)
621 {
622  hdb_handle_t local_handle = 0;
623 
624 #if SUPPORT_COROSYNC
625  config->object_find_create(OBJECT_PARENT_HANDLE, name, strlen(name), &local_handle);
626  ais_info("Local handle: %lld for %s", (long long)local_handle, name);
627 #endif
628 
629  return local_handle;
630 }
631 
632 hdb_handle_t
633 config_find_next(struct corosync_api_v1 * config, char *name, hdb_handle_t top_handle)
634 {
635  int rc = 0;
636  hdb_handle_t local_handle = 0;
637 
638 #if SUPPORT_COROSYNC
639  rc = config->object_find_next(top_handle, &local_handle);
640 #endif
641 
642  if (rc < 0) {
643  ais_info("No additional configuration supplied for: %s", name);
644  local_handle = 0;
645  } else {
646  ais_info("Processing additional %s options...", name);
647  }
648  return local_handle;
649 }
650 
651 void
652 config_find_done(struct corosync_api_v1 *config, hdb_handle_t local_handle)
653 {
654 #if SUPPORT_COROSYNC
655  config->object_find_destroy(local_handle);
656 #endif
657 }
658 
659 int
660 get_config_opt(struct corosync_api_v1 *config,
661  hdb_handle_t object_service_handle, char *key, char **value, const char *fallback)
662 {
663  char *env_key = NULL;
664 
665  *value = NULL;
666 
667  if (object_service_handle > 0) {
668  config->object_key_get(object_service_handle, key, strlen(key), (void **)value, NULL);
669  }
670 
671  if (*value) {
672  ais_info("Found '%s' for option: %s", *value, key);
673  return 0;
674  }
675 
676  env_key = ais_concat("HA", key, '_');
677  *value = getenv(env_key);
678  ais_free(env_key);
679 
680  if (*value) {
681  ais_info("Found '%s' in ENV for option: %s", *value, key);
682  return 0;
683  }
684 
685  if (fallback) {
686  ais_info("Defaulting to '%s' for option: %s", fallback, key);
687  *value = ais_strdup(fallback);
688 
689  } else {
690  ais_info("No default for option: %s", key);
691  }
692 
693  return -1;
694 }
695 
696 int
697 ais_get_boolean(const char *value)
698 {
699  if (value == NULL) {
700  return 0;
701 
702  } else if (strcasecmp(value, "true") == 0
703  || strcasecmp(value, "on") == 0
704  || strcasecmp(value, "yes") == 0
705  || strcasecmp(value, "y") == 0 || strcasecmp(value, "1") == 0) {
706  return 1;
707  }
708  return 0;
709 }
710 
711 long long
712 ais_get_int(const char *text, char **end_text)
713 {
714  long long result = -1;
715  char *local_end_text = NULL;
716 
717  errno = 0;
718 
719  if (text != NULL) {
720 #ifdef ANSI_ONLY
721  if (end_text != NULL) {
722  result = strtol(text, end_text, 10);
723  } else {
724  result = strtol(text, &local_end_text, 10);
725  }
726 #else
727  if (end_text != NULL) {
728  result = strtoll(text, end_text, 10);
729  } else {
730  result = strtoll(text, &local_end_text, 10);
731  }
732 #endif
733 
734  if (errno == EINVAL) {
735  ais_err("Conversion of %s failed", text);
736  result = -1;
737 
738  } else if (errno == ERANGE) {
739  ais_err("Conversion of %s was clipped: %lld", text, result);
740 
741  } else if (errno != 0) {
742  ais_perror("Conversion of %s failed:", text);
743  }
744 
745  if (local_end_text != NULL && local_end_text[0] != '\0') {
746  ais_err("Characters left over after parsing '%s': '%s'", text, local_end_text);
747  }
748  }
749  return result;
750 }
751 
752 #define PW_BUFFER_LEN 500
753 
754 int
755 pcmk_user_lookup(const char *name, uid_t * uid, gid_t * gid)
756 {
757  int rc = -1;
758  char *buffer = NULL;
759  struct passwd pwd;
760  struct passwd *pwentry = NULL;
761 
762  ais_malloc0(buffer, PW_BUFFER_LEN);
763  getpwnam_r(name, &pwd, buffer, PW_BUFFER_LEN, &pwentry);
764  if (pwentry) {
765  rc = 0;
766  if (uid) {
767  *uid = pwentry->pw_uid;
768  }
769  if (gid) {
770  *gid = pwentry->pw_gid;
771  }
772  ais_debug("Cluster user %s has uid=%d gid=%d", name, pwentry->pw_uid, pwentry->pw_gid);
773 
774  } else {
775  ais_err("Cluster user %s does not exist", name);
776  }
777 
778  ais_free(buffer);
779  return rc;
780 }
uint32_t votes
Definition: internal.h:50
enum crm_ais_msg_types type
Definition: internal.h:38
char data[0]
Definition: internal.h:55
uint32_t local_nodeid
Definition: plugin.c:65
gboolean is_compressed
Definition: internal.h:47
uint32_t size
Definition: internal.h:52
const char * command
Definition: utils.h:76
crm_ais_msg_types
Definition: cluster.h:128
hdb_handle_t config_find_init(struct corosync_api_v1 *config, char *name)
Definition: utils.c:620
int pcmk_user_lookup(const char *name, uid_t *uid, gid_t *gid)
Definition: utils.c:755
#define PW_BUFFER_LEN
Definition: utils.c:752
uint32_t id
Definition: cluster.h:73
#define VALGRIND_BIN
Definition: config.h:760
long long ais_get_int(const char *text, char **end_text)
Definition: utils.c:712
void log_ais_message(int level, const AIS_Message *msg)
Definition: utils.c:43
uint64_t born
Definition: cluster.h:74
#define ais_notice(fmt, args...)
Definition: utils.h:163
void config_find_done(struct corosync_api_v1 *config, hdb_handle_t local_handle)
Definition: utils.c:652
uint32_t size
Definition: internal.h:52
uint32_t id
Definition: internal.h:35
#define AIS_ASSERT(expr)
Definition: utils.h:183
char * addr
Definition: cluster.h:87
#define ais_perror(fmt, args...)
Definition: utils.h:156
AIS_Host host
Definition: internal.h:52
const char * uid
Definition: utils.h:75
#define ais_info(fmt, args...)
Definition: utils.h:164
const char * use_logd
Definition: utils.h:235
#define ais_trace(fmt, args...)
Definition: utils.h:166
#define ais_malloc0(malloc_obj, length)
Definition: utils.h:168
char version[256]
Definition: plugin.c:84
struct pcmk_env_s pcmk_env
Definition: utils.c:40
int ais_get_boolean(const char *value)
Definition: utils.c:697
char uname[MAX_NAME]
Definition: internal.h:53
int update_member(unsigned int id, uint64_t born, uint64_t seq, int32_t votes, uint32_t procs, const char *uname, const char *state, const char *version)
Definition: utils.c:295
uint32_t processes
Definition: cluster.h:79
int pid
Definition: utils.h:68
struct corosync_api_v1 * pcmk_api
Definition: plugin.c:54
#define ais_free(obj)
Definition: utils.h:176
uint32_t id
Definition: internal.h:48
#define ais_err(fmt, args...)
Definition: utils.h:161
int get_config_opt(struct corosync_api_v1 *config, hdb_handle_t object_service_handle, char *key, char **value, const char *fallback)
Definition: utils.c:660
int setenv(const char *name, const char *value, int why)
int send_plugin_msg(enum crm_ais_msg_types type, const char *host, const char *data)
Definition: utils.c:479
const char * name
Definition: utils.h:74
AIS_Host sender
Definition: internal.h:50
gboolean stop_child(crm_child_t *child, int signal)
Definition: utils.c:252
uint32_t id
Definition: internal.h:46
const char * member_uname(uint32_t id)
Definition: utils.c:374
struct crm_ais_msg_s AIS_Message
Definition: internal.h:32
#define ais_data_len(msg)
Definition: internal.h:208
uint32_t size
Definition: internal.h:39
const char * syslog
Definition: utils.h:233
uint32_t compressed_size
Definition: internal.h:53
#define ais_debug(fmt, args...)
Definition: utils.h:165
#define MAX_NAME
Definition: crm.h:42
char * ais_concat(const char *prefix, const char *suffix, char join)
Definition: utils.c:604
char * version
Definition: cluster.h:88
void swap_sender(AIS_Message *msg)
Definition: utils.c:435
hdb_handle_t config_find_next(struct corosync_api_v1 *config, char *name, hdb_handle_t top_handle)
Definition: utils.c:633
void destroy_ais_node(gpointer data)
Definition: utils.c:282
crm_ais_msg_class
Definition: cluster.h:118
char * local_uname
Definition: plugin.c:61
int send_plugin_msg_raw(const AIS_Message *ais_msg)
Definition: plugin.c:1560
char * get_ais_data(const AIS_Message *msg)
Definition: utils.c:454
#define ais_warn(fmt, args...)
Definition: utils.h:162
char uname[MAX_NAME]
Definition: internal.h:40
gboolean spawn_child(crm_child_t *child)
Definition: utils.c:136
#define uint32_t
Definition: stdint.in.h:158
char data[0]
Definition: internal.h:58
char * state
Definition: cluster.h:84
const char * quorum
Definition: utils.h:236
char * append_member(char *data, crm_node_t *node)
Definition: utils.c:388
#define CRM_STATE_DIR
Definition: config.h:68
void delete_member(uint32_t id, const char *uname)
Definition: utils.c:364
#define U64T
Definition: config.h:754
int32_t votes
Definition: cluster.h:78
int send_client_msg(void *conn, enum crm_ais_msg_class class, enum crm_ais_msg_types type, const char *data)
Definition: utils.c:550
uint32_t pid
Definition: internal.h:36
int send_client_ipc(void *conn, const AIS_Message *ais_msg)
Definition: utils.c:527
char * uname
Definition: cluster.h:82
uint64_t last_seen
Definition: cluster.h:75
AIS_Host host
Definition: internal.h:49
GHashTable * membership_list
Definition: plugin.c:76
const char * logfile
Definition: utils.h:234
enum crm_ais_msg_types type
Definition: internal.h:51
const char * debug
Definition: utils.h:232
#define int32_t
Definition: stdint.in.h:157
int local_uname_len
Definition: plugin.c:62