root/daemons/based/pacemaker-based.c

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

DEFINITIONS

This source file includes following definitions.
  1. cib_enable_writes
  2. main
  3. cib_cleanup
  4. cib_cs_dispatch
  5. cib_cs_destroy
  6. cib_peer_update_callback
  7. cib_init
  8. startCib

   1 /*
   2  * Copyright 2004-2022 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 General Public License version 2
   7  * or later (GPLv2+) WITHOUT ANY WARRANTY.
   8  */
   9 
  10 #include <crm_internal.h>
  11 
  12 #include <stdio.h>
  13 #include <stdlib.h>
  14 #include <pwd.h>
  15 #include <grp.h>
  16 #include <bzlib.h>
  17 #include <sys/types.h>
  18 
  19 #include <libxml/parser.h>
  20 
  21 #include <crm/crm.h>
  22 #include <crm/cib/internal.h>
  23 #include <crm/msg_xml.h>
  24 #include <crm/cluster/internal.h>
  25 #include <crm/common/xml.h>
  26 #include <crm/common/mainloop.h>
  27 
  28 #include <pacemaker-based.h>
  29 
  30 extern int init_remote_listener(int port, gboolean encrypted);
  31 gboolean cib_shutdown_flag = FALSE;
  32 int cib_status = pcmk_ok;
  33 
  34 crm_cluster_t crm_cluster;
  35 
  36 GMainLoop *mainloop = NULL;
  37 const char *cib_root = NULL;
  38 char *cib_our_uname = NULL;
  39 static gboolean preserve_status = FALSE;
  40 
  41 gboolean cib_writes_enabled = TRUE;
  42 
  43 int remote_fd = 0;
  44 int remote_tls_fd = 0;
  45 
  46 GHashTable *config_hash = NULL;
  47 GHashTable *local_notify_queue = NULL;
  48 
  49 static void cib_init(void);
  50 void cib_shutdown(int nsig);
  51 static bool startCib(const char *filename);
  52 extern int write_cib_contents(gpointer p);
  53 void cib_cleanup(void);
  54 
  55 static void
  56 cib_enable_writes(int nsig)
     /* [previous][next][first][last][top][bottom][index][help] */
  57 {
  58     crm_info("(Re)enabling disk writes");
  59     cib_writes_enabled = TRUE;
  60 }
  61 
  62 static pcmk__cli_option_t long_options[] = {
  63     // long option, argument type, storage, short option, description, flags
  64     {
  65         "help", no_argument, 0, '?',
  66         "\tThis text", pcmk__option_default
  67     },
  68     {
  69         "verbose", no_argument, NULL, 'V',
  70         "\tIncrease debug output", pcmk__option_default
  71     },
  72     {
  73         "stand-alone", no_argument, NULL, 's',
  74         "\tAdvanced use only", pcmk__option_default
  75     },
  76     {
  77         "disk-writes", no_argument, NULL, 'w',
  78         "\tAdvanced use only", pcmk__option_default
  79     },
  80     {
  81         "cib-root", required_argument, NULL, 'r',
  82         "\tAdvanced use only", pcmk__option_default
  83     },
  84     { 0, 0, 0, 0 }
  85 };
  86 
  87 int
  88 main(int argc, char **argv)
     /* [previous][next][first][last][top][bottom][index][help] */
  89 {
  90     int flag;
  91     int rc = 0;
  92     int index = 0;
  93     int argerr = 0;
  94     struct passwd *pwentry = NULL;
  95     crm_ipc_t *old_instance = NULL;
  96 
  97     crm_log_preinit(NULL, argc, argv);
  98     pcmk__set_cli_options(NULL, "[options]", long_options,
  99                           "daemon for managing the configuration "
 100                           "of a Pacemaker cluster");
 101 
 102     mainloop_add_signal(SIGTERM, cib_shutdown);
 103     mainloop_add_signal(SIGPIPE, cib_enable_writes);
 104 
 105     cib_writer = mainloop_add_trigger(G_PRIORITY_LOW, write_cib_contents, NULL);
 106 
 107     while (1) {
 108         flag = pcmk__next_cli_option(argc, argv, &index, NULL);
 109         if (flag == -1)
 110             break;
 111 
 112         switch (flag) {
 113             case 'V':
 114                 crm_bump_log_level(argc, argv);
 115                 break;
 116             case 's':
 117                 stand_alone = TRUE;
 118                 preserve_status = TRUE;
 119                 cib_writes_enabled = FALSE;
 120 
 121                 pwentry = getpwnam(CRM_DAEMON_USER);
 122                 CRM_CHECK(pwentry != NULL,
 123                           crm_perror(LOG_ERR, "Invalid uid (%s) specified", CRM_DAEMON_USER);
 124                           return CRM_EX_FATAL);
 125 
 126                 rc = setgid(pwentry->pw_gid);
 127                 if (rc < 0) {
 128                     crm_perror(LOG_ERR, "Could not set group to %d", pwentry->pw_gid);
 129                     return CRM_EX_FATAL;
 130                 }
 131 
 132                 rc = initgroups(CRM_DAEMON_USER, pwentry->pw_gid);
 133                 if (rc < 0) {
 134                     crm_perror(LOG_ERR, "Could not setup groups for user %d", pwentry->pw_uid);
 135                     return CRM_EX_FATAL;
 136                 }
 137 
 138                 rc = setuid(pwentry->pw_uid);
 139                 if (rc < 0) {
 140                     crm_perror(LOG_ERR, "Could not set user to %d", pwentry->pw_uid);
 141                     return CRM_EX_FATAL;
 142                 }
 143                 break;
 144             case '?':          /* Help message */
 145                 pcmk__cli_help(flag, CRM_EX_OK);
 146                 break;
 147             case 'w':
 148                 cib_writes_enabled = TRUE;
 149                 break;
 150             case 'r':
 151                 cib_root = optarg;
 152                 break;
 153             case 'm':
 154                 cib_metadata();
 155                 return CRM_EX_OK;
 156             default:
 157                 ++argerr;
 158                 break;
 159         }
 160     }
 161     if (argc - optind == 1 && pcmk__str_eq("metadata", argv[optind], pcmk__str_casei)) {
 162         cib_metadata();
 163         return CRM_EX_OK;
 164     }
 165 
 166     if (optind > argc) {
 167         ++argerr;
 168     }
 169 
 170     if (argerr) {
 171         pcmk__cli_help('?', CRM_EX_USAGE);
 172     }
 173 
 174     crm_log_init(NULL, LOG_INFO, TRUE, FALSE, argc, argv, FALSE);
 175 
 176     crm_notice("Starting Pacemaker CIB manager");
 177 
 178     old_instance = crm_ipc_new(PCMK__SERVER_BASED_RO, 0);
 179     if (crm_ipc_connect(old_instance)) {
 180         /* IPC end-point already up */
 181         crm_ipc_close(old_instance);
 182         crm_ipc_destroy(old_instance);
 183         crm_err("pacemaker-based is already active, aborting startup");
 184         crm_exit(CRM_EX_OK);
 185     } else {
 186         /* not up or not authentic, we'll proceed either way */
 187         crm_ipc_destroy(old_instance);
 188         old_instance = NULL;
 189     }
 190 
 191     if (cib_root == NULL) {
 192         cib_root = CRM_CONFIG_DIR;
 193     } else {
 194         crm_notice("Using custom config location: %s", cib_root);
 195     }
 196 
 197     if (pcmk__daemon_can_write(cib_root, NULL) == FALSE) {
 198         crm_err("Terminating due to bad permissions on %s", cib_root);
 199         fprintf(stderr, "ERROR: Bad permissions on %s (see logs for details)\n",
 200                 cib_root);
 201         fflush(stderr);
 202         return CRM_EX_FATAL;
 203     }
 204 
 205     crm_peer_init();
 206 
 207     // Read initial CIB, connect to cluster, and start IPC servers
 208     cib_init();
 209 
 210     // Run the main loop
 211     mainloop = g_main_loop_new(NULL, FALSE);
 212     crm_notice("Pacemaker CIB manager successfully started and accepting connections");
 213     g_main_loop_run(mainloop);
 214 
 215     /* If main loop returned, clean up and exit. We disconnect in case
 216      * terminate_cib() was called with fast=-1.
 217      */
 218     crm_cluster_disconnect(&crm_cluster);
 219     pcmk__stop_based_ipc(ipcs_ro, ipcs_rw, ipcs_shm);
 220     crm_exit(CRM_EX_OK);
 221 }
 222 
 223 void
 224 cib_cleanup(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 225 {
 226     crm_peer_destroy();
 227     if (local_notify_queue) {
 228         g_hash_table_destroy(local_notify_queue);
 229     }
 230     pcmk__client_cleanup();
 231     g_hash_table_destroy(config_hash);
 232     free(cib_our_uname);
 233 }
 234 
 235 #if SUPPORT_COROSYNC
 236 static void
 237 cib_cs_dispatch(cpg_handle_t handle,
     /* [previous][next][first][last][top][bottom][index][help] */
 238                  const struct cpg_name *groupName,
 239                  uint32_t nodeid, uint32_t pid, void *msg, size_t msg_len)
 240 {
 241     uint32_t kind = 0;
 242     xmlNode *xml = NULL;
 243     const char *from = NULL;
 244     char *data = pcmk_message_common_cs(handle, nodeid, pid, msg, &kind, &from);
 245 
 246     if(data == NULL) {
 247         return;
 248     }
 249     if (kind == crm_class_cluster) {
 250         xml = string2xml(data);
 251         if (xml == NULL) {
 252             crm_err("Invalid XML: '%.120s'", data);
 253             free(data);
 254             return;
 255         }
 256         crm_xml_add(xml, F_ORIG, from);
 257         /* crm_xml_add_int(xml, F_SEQ, wrapper->id); */
 258         cib_peer_callback(xml, NULL);
 259     }
 260 
 261     free_xml(xml);
 262     free(data);
 263 }
 264 
 265 static void
 266 cib_cs_destroy(gpointer user_data)
     /* [previous][next][first][last][top][bottom][index][help] */
 267 {
 268     if (cib_shutdown_flag) {
 269         crm_info("Corosync disconnection complete");
 270     } else {
 271         crm_crit("Lost connection to cluster layer, shutting down");
 272         terminate_cib(__func__, CRM_EX_DISCONNECT);
 273     }
 274 }
 275 #endif
 276 
 277 static void
 278 cib_peer_update_callback(enum crm_status_type type, crm_node_t * node, const void *data)
     /* [previous][next][first][last][top][bottom][index][help] */
 279 {
 280     switch (type) {
 281         case crm_status_processes:
 282             if (cib_legacy_mode()
 283                 && !pcmk_is_set(node->processes, crm_get_cluster_proc())) {
 284 
 285                 uint32_t old = data? *(const uint32_t *)data : 0;
 286 
 287                 if ((node->processes ^ old) & crm_proc_cpg) {
 288                     crm_info("Attempting to disable legacy mode after %s left the cluster",
 289                              node->uname);
 290                     legacy_mode = FALSE;
 291                 }
 292             }
 293             break;
 294 
 295         case crm_status_uname:
 296         case crm_status_nstate:
 297             if (cib_shutdown_flag && (crm_active_peers() < 2)
 298                 && (pcmk__ipc_client_count() == 0)) {
 299 
 300                 crm_info("No more peers");
 301                 terminate_cib(__func__, -1);
 302             }
 303             break;
 304     }
 305 }
 306 
 307 static void
 308 cib_init(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 309 {
 310     if (is_corosync_cluster()) {
 311 #if SUPPORT_COROSYNC
 312         crm_cluster.destroy = cib_cs_destroy;
 313         crm_cluster.cpg.cpg_deliver_fn = cib_cs_dispatch;
 314         crm_cluster.cpg.cpg_confchg_fn = pcmk_cpg_membership;
 315 #endif
 316     }
 317 
 318     config_hash = pcmk__strkey_table(free, free);
 319 
 320     if (startCib("cib.xml") == FALSE) {
 321         crm_crit("Cannot start CIB... terminating");
 322         crm_exit(CRM_EX_NOINPUT);
 323     }
 324 
 325     if (stand_alone == FALSE) {
 326         if (is_corosync_cluster()) {
 327             crm_set_status_callback(&cib_peer_update_callback);
 328         }
 329 
 330         if (crm_cluster_connect(&crm_cluster) == FALSE) {
 331             crm_crit("Cannot sign in to the cluster... terminating");
 332             crm_exit(CRM_EX_FATAL);
 333         }
 334         cib_our_uname = crm_cluster.uname;
 335 
 336     } else {
 337         cib_our_uname = strdup("localhost");
 338     }
 339 
 340     pcmk__serve_based_ipc(&ipcs_ro, &ipcs_rw, &ipcs_shm, &ipc_ro_callbacks,
 341                           &ipc_rw_callbacks);
 342 
 343     if (stand_alone) {
 344         based_is_primary = true;
 345     }
 346 }
 347 
 348 static bool
 349 startCib(const char *filename)
     /* [previous][next][first][last][top][bottom][index][help] */
 350 {
 351     gboolean active = FALSE;
 352     xmlNode *cib = readCibXmlFile(cib_root, filename, !preserve_status);
 353 
 354     if (activateCibXml(cib, TRUE, "start") == 0) {
 355         int port = 0;
 356 
 357         active = TRUE;
 358 
 359         cib_read_config(config_hash, cib);
 360 
 361         pcmk__scan_port(crm_element_value(cib, "remote-tls-port"), &port);
 362         if (port >= 0) {
 363             remote_tls_fd = init_remote_listener(port, TRUE);
 364         }
 365 
 366         pcmk__scan_port(crm_element_value(cib, "remote-clear-port"), &port);
 367         if (port >= 0) {
 368             remote_fd = init_remote_listener(port, FALSE);
 369         }
 370     }
 371     return active;
 372 }

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