root/lib/pacemaker/pcmk_status.c

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

DEFINITIONS

This source file includes following definitions.
  1. cib_connect
  2. fencing_connect
  3. pacemakerd_event_cb
  4. pacemakerd_status
  5. pcmk__output_cluster_status
  6. pcmk_status
  7. pcmk__status
  8. pcmk__output_simple_status

   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 <stdbool.h>
  13 #include <stddef.h>
  14 #include <stdint.h>
  15 
  16 #include <crm/cib/internal.h>
  17 #include <crm/common/output.h>
  18 #include <crm/common/results.h>
  19 #include <crm/fencing/internal.h>
  20 #include <crm/stonith-ng.h>
  21 #include <pacemaker.h>
  22 #include <pacemaker-internal.h>
  23 
  24 static int
  25 cib_connect(pcmk__output_t *out, cib_t *cib, xmlNode **current_cib)
     /* [previous][next][first][last][top][bottom][index][help] */
  26 {
  27     int rc = pcmk_rc_ok;
  28 
  29     CRM_CHECK(cib != NULL, return EINVAL);
  30 
  31     if (cib->state == cib_connected_query ||
  32         cib->state == cib_connected_command) {
  33         return rc;
  34     }
  35 
  36     crm_trace("Connecting to the CIB");
  37 
  38     rc = cib->cmds->signon(cib, crm_system_name, cib_query);
  39     rc = pcmk_legacy2rc(rc);
  40 
  41     if (rc != pcmk_rc_ok) {
  42         out->err(out, "Could not connect to the CIB: %s",
  43                  pcmk_rc_str(rc));
  44         return rc;
  45     }
  46 
  47     rc = cib->cmds->query(cib, NULL, current_cib,
  48                           cib_scope_local | cib_sync_call);
  49     rc = pcmk_legacy2rc(rc);
  50 
  51     return rc;
  52 }
  53 
  54 static stonith_t *
  55 fencing_connect(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  56 {
  57     stonith_t *st = stonith_api_new();
  58     int rc = pcmk_rc_ok;
  59 
  60     if (st == NULL) {
  61         return NULL;
  62     }
  63 
  64     rc = st->cmds->connect(st, crm_system_name, NULL);
  65     if (rc == pcmk_rc_ok) {
  66         return st;
  67     } else {
  68         stonith_api_delete(st);
  69         return NULL;
  70     }
  71 }
  72 
  73 static void
  74 pacemakerd_event_cb(pcmk_ipc_api_t *pacemakerd_api,
     /* [previous][next][first][last][top][bottom][index][help] */
  75                     enum pcmk_ipc_event event_type, crm_exit_t status,
  76                     void *event_data, void *user_data)
  77 {
  78     pcmk_pacemakerd_api_reply_t *reply = event_data;
  79     enum pcmk_pacemakerd_state *state =
  80         (enum pcmk_pacemakerd_state *) user_data;
  81 
  82     /* we are just interested in the latest reply */
  83     *state = pcmk_pacemakerd_state_invalid;
  84 
  85     if (event_type != pcmk_ipc_event_reply || status != CRM_EX_OK) {
  86         return;
  87     }
  88 
  89     if (reply->reply_type == pcmk_pacemakerd_reply_ping &&
  90         reply->data.ping.last_good != (time_t) 0 &&
  91         reply->data.ping.status == pcmk_rc_ok) {
  92         *state = reply->data.ping.state;
  93     }
  94 }
  95 
  96 static int
  97 pacemakerd_status(pcmk__output_t *out)
     /* [previous][next][first][last][top][bottom][index][help] */
  98 {
  99     int rc = pcmk_rc_ok;
 100     pcmk_ipc_api_t *pacemakerd_api = NULL;
 101     enum pcmk_pacemakerd_state state = pcmk_pacemakerd_state_invalid;
 102 
 103     rc = pcmk_new_ipc_api(&pacemakerd_api, pcmk_ipc_pacemakerd);
 104     if (pacemakerd_api == NULL) {
 105         out->err(out, "Could not connect to pacemakerd: %s",
 106                  pcmk_rc_str(rc));
 107         return rc;
 108     }
 109 
 110     pcmk_register_ipc_callback(pacemakerd_api, pacemakerd_event_cb, (void *) &state);
 111 
 112     rc = pcmk_connect_ipc(pacemakerd_api, pcmk_ipc_dispatch_sync);
 113     if (rc == EREMOTEIO) {
 114         return pcmk_rc_ok;
 115     } else if (rc != pcmk_rc_ok) {
 116         out->err(out, "Could not connect to pacemakerd: %s",
 117                  pcmk_rc_str(rc));
 118         pcmk_free_ipc_api(pacemakerd_api);
 119         return rc;
 120     }
 121 
 122     rc = pcmk_pacemakerd_api_ping(pacemakerd_api, crm_system_name);
 123 
 124     if (rc != pcmk_rc_ok) {
 125         /* Got some error from pcmk_pacemakerd_api_ping, so return it. */
 126     } else if (state == pcmk_pacemakerd_state_running) {
 127         rc = pcmk_rc_ok;
 128     } else if (state == pcmk_pacemakerd_state_shutting_down) {
 129         rc = ENOTCONN;
 130     } else {
 131         rc = EAGAIN;
 132     }
 133 
 134     pcmk_free_ipc_api(pacemakerd_api);
 135     return rc;
 136 }
 137 
 138 int
 139 pcmk__output_cluster_status(pcmk__output_t *out, stonith_t *st, cib_t *cib,
     /* [previous][next][first][last][top][bottom][index][help] */
 140                             xmlNode *current_cib, enum pcmk__fence_history fence_history,
 141                             uint32_t show, uint32_t show_opts, char *only_node,
 142                             char *only_rsc, char *neg_location_prefix, bool simple_output)
 143 {
 144     xmlNode *cib_copy = copy_xml(current_cib);
 145     stonith_history_t *stonith_history = NULL;
 146     int history_rc = 0;
 147     pe_working_set_t *data_set = NULL;
 148     GList *unames = NULL;
 149     GList *resources = NULL;
 150 
 151     int rc = pcmk_rc_ok;
 152 
 153     if (cli_config_update(&cib_copy, NULL, FALSE) == FALSE) {
 154         cib__clean_up_connection(&cib);
 155         rc = pcmk_rc_schema_validation;
 156         out->err(out, "Upgrade failed: %s", pcmk_rc_str(rc));
 157         return rc;
 158     }
 159 
 160     /* get the stonith-history if there is evidence we need it */
 161     if (fence_history != pcmk__fence_history_none) {
 162         history_rc = pcmk__get_fencing_history(st, &stonith_history, fence_history);
 163     }
 164 
 165     data_set = pe_new_working_set();
 166     CRM_ASSERT(data_set != NULL);
 167     pe__set_working_set_flags(data_set, pe_flag_no_compat);
 168 
 169     data_set->input = cib_copy;
 170     data_set->priv = out;
 171     cluster_status(data_set);
 172 
 173     /* Unpack constraints if any section will need them
 174      * (tickets may be referenced in constraints but not granted yet,
 175      * and bans need negative location constraints) */
 176     if (pcmk_is_set(show, pcmk_section_bans) || pcmk_is_set(show, pcmk_section_tickets)) {
 177         pcmk__unpack_constraints(data_set);
 178     }
 179 
 180     unames = pe__build_node_name_list(data_set, only_node);
 181     resources = pe__build_rsc_list(data_set, only_rsc);
 182 
 183     /* Always print DC if NULL. */
 184     if (data_set->dc_node == NULL) {
 185         show |= pcmk_section_dc;
 186     }
 187 
 188     if (simple_output) {
 189         rc = pcmk__output_simple_status(out, data_set);
 190     } else {
 191         out->message(out, "cluster-status", data_set, pcmk_rc2exitc(history_rc),
 192                      stonith_history, fence_history, show, show_opts,
 193                      neg_location_prefix, unames, resources);
 194     }
 195 
 196     g_list_free_full(unames, free);
 197     g_list_free_full(resources, free);
 198 
 199     stonith_history_free(stonith_history);
 200     stonith_history = NULL;
 201     pe_reset_working_set(data_set);
 202     return rc;
 203 }
 204 
 205 int
 206 pcmk_status(xmlNodePtr *xml)
     /* [previous][next][first][last][top][bottom][index][help] */
 207 {
 208     cib_t *cib = NULL;
 209     pcmk__output_t *out = NULL;
 210     int rc = pcmk_rc_ok;
 211 
 212     uint32_t show_opts = pcmk_show_pending | pcmk_show_inactive_rscs | pcmk_show_timing;
 213 
 214     cib = cib_new();
 215 
 216     if (cib == NULL) {
 217         return pcmk_rc_cib_corrupt;
 218     }
 219 
 220     rc = pcmk__out_prologue(&out, xml);
 221     if (rc != pcmk_rc_ok) {
 222         cib_delete(cib);
 223         return rc;
 224     }
 225 
 226     pcmk__register_lib_messages(out);
 227     pe__register_messages(out);
 228     stonith__register_messages(out);
 229 
 230     rc = pcmk__status(out, cib, pcmk__fence_history_full, pcmk_section_all,
 231                       show_opts, NULL, NULL, NULL, false);
 232     pcmk__out_epilogue(out, xml, rc);
 233 
 234     cib_delete(cib);
 235     return rc;
 236 }
 237 
 238 int
 239 pcmk__status(pcmk__output_t *out, cib_t *cib, enum pcmk__fence_history fence_history,
     /* [previous][next][first][last][top][bottom][index][help] */
 240              uint32_t show, uint32_t show_opts, char *only_node, char *only_rsc,
 241              char *neg_location_prefix, bool simple_output)
 242 {
 243     xmlNode *current_cib = NULL;
 244     int rc = pcmk_rc_ok;
 245     stonith_t *st = NULL;
 246 
 247     if (cib == NULL) {
 248         return ENOTCONN;
 249     }
 250 
 251     if (cib->variant == cib_native) {
 252         if (cib->state == cib_connected_query || cib->state == cib_connected_command) {
 253             rc = pcmk_rc_ok;
 254         } else {
 255             rc = pacemakerd_status(out);
 256         }
 257     }
 258 
 259     if (rc != pcmk_rc_ok) {
 260         return rc;
 261     }
 262 
 263     if (fence_history != pcmk__fence_history_none && cib->variant == cib_native) {
 264         st = fencing_connect();
 265 
 266         if (st == NULL) {
 267             return ENOTCONN;
 268         }
 269     }
 270 
 271     rc = cib_connect(out, cib, &current_cib);
 272     if (rc != pcmk_rc_ok) {
 273         goto done;
 274     }
 275 
 276     rc = pcmk__output_cluster_status(out, st, cib, current_cib, fence_history, show, show_opts,
 277                                      only_node, only_rsc, neg_location_prefix, simple_output);
 278 
 279 done:
 280     if (st != NULL) {
 281         if (st->state != stonith_disconnected) {
 282             st->cmds->remove_notification(st, NULL);
 283             st->cmds->disconnect(st);
 284         }
 285 
 286         stonith_api_delete(st);
 287     }
 288 
 289     return rc;
 290 }
 291 
 292 /* This is an internal-only function that is planned to be deprecated and removed.
 293  * It should only ever be called from crm_mon.
 294  */
 295 int
 296 pcmk__output_simple_status(pcmk__output_t *out, pe_working_set_t *data_set)
     /* [previous][next][first][last][top][bottom][index][help] */
 297 {
 298     int nodes_online = 0;
 299     int nodes_standby = 0;
 300     int nodes_maintenance = 0;
 301     char *offline_nodes = NULL;
 302     size_t offline_nodes_len = 0;
 303     bool no_dc = false;
 304     bool offline = false;
 305     bool has_warnings = false;
 306 
 307     if (data_set->dc_node == NULL) {
 308         has_warnings = true;
 309         no_dc = true;
 310     }
 311 
 312     for (GList *iter = data_set->nodes; iter != NULL; iter = iter->next) {
 313         pe_node_t *node = (pe_node_t *) iter->data;
 314 
 315         if (node->details->standby && node->details->online) {
 316             nodes_standby++;
 317         } else if (node->details->maintenance && node->details->online) {
 318             nodes_maintenance++;
 319         } else if (node->details->online) {
 320             nodes_online++;
 321         } else {
 322             char *s = crm_strdup_printf("offline node: %s", node->details->uname);
 323             /* coverity[leaked_storage] False positive */
 324             pcmk__add_word(&offline_nodes, &offline_nodes_len, s);
 325             free(s);
 326             has_warnings = true;
 327             offline = true;
 328         }
 329     }
 330 
 331     if (has_warnings) {
 332         out->info(out, "CLUSTER WARN: %s%s%s",
 333                   no_dc ? "No DC" : "",
 334                   no_dc && offline ? ", " : "",
 335                   (offline? offline_nodes : ""));
 336         free(offline_nodes);
 337     } else {
 338         char *nodes_standby_s = NULL;
 339         char *nodes_maint_s = NULL;
 340 
 341         if (nodes_standby > 0) {
 342             nodes_standby_s = crm_strdup_printf(", %d standby node%s", nodes_standby,
 343                                                 pcmk__plural_s(nodes_standby));
 344         }
 345 
 346         if (nodes_maintenance > 0) {
 347             nodes_maint_s = crm_strdup_printf(", %d maintenance node%s",
 348                                               nodes_maintenance,
 349                                               pcmk__plural_s(nodes_maintenance));
 350         }
 351 
 352         out->info(out, "CLUSTER OK: %d node%s online%s%s, "
 353                        "%d resource instance%s configured",
 354                   nodes_online, pcmk__plural_s(nodes_online),
 355                   nodes_standby_s != NULL ? nodes_standby_s : "",
 356                   nodes_maint_s != NULL ? nodes_maint_s : "",
 357                   data_set->ninstances, pcmk__plural_s(data_set->ninstances));
 358 
 359         free(nodes_standby_s);
 360         free(nodes_maint_s);
 361     }
 362 
 363     if (has_warnings) {
 364         return pcmk_rc_error;
 365     } else {
 366         return pcmk_rc_ok;
 367     }
 368     /* coverity[leaked_storage] False positive */
 369 }

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