root/lib/pacemaker/pcmk_status.c

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

DEFINITIONS

This source file includes following definitions.
  1. fencing_connect
  2. pcmk__output_cluster_status
  3. pcmk_status
  4. pcmk__status

   1 /*
   2  * Copyright 2004-2025 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 <stdint.h>
  14 
  15 #include <crm/cib/internal.h>
  16 #include <crm/common/output.h>
  17 #include <crm/common/results.h>
  18 #include <crm/fencing/internal.h>
  19 #include <crm/pengine/internal.h>
  20 #include <crm/stonith-ng.h> // stonith__register_messages()
  21 #include <pacemaker.h>
  22 #include <pacemaker-internal.h>
  23 
  24 static stonith_t *
  25 fencing_connect(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  26 {
  27     stonith_t *st = stonith__api_new();
  28     int rc = pcmk_rc_ok;
  29 
  30     if (st == NULL) {
  31         return NULL;
  32     }
  33 
  34     rc = st->cmds->connect(st, crm_system_name, NULL);
  35     if (rc == pcmk_rc_ok) {
  36         return st;
  37     } else {
  38         stonith__api_free(st);
  39         return NULL;
  40     }
  41 }
  42 
  43 /*!
  44  * \internal
  45  * \brief Output the cluster status given a fencer and CIB connection
  46  *
  47  * \param[in,out] scheduler            Scheduler object (will be reset)
  48  * \param[in,out] stonith              Fencer connection
  49  * \param[in,out] cib                  CIB connection
  50  * \param[in]     current_cib          Current CIB XML
  51  * \param[in]     pcmkd_state          \p pacemakerd state
  52  * \param[in]     fence_history        How much of the fencing history to output
  53  * \param[in]     show                 Group of \p pcmk_section_e flags
  54  * \param[in]     show_opts            Group of \p pcmk_show_opt_e flags
  55  * \param[in]     only_node            If a node name or tag, include only the
  56  *                                     matching node(s) (if any) in the output.
  57  *                                     If \p "*" or \p NULL, include all nodes
  58  *                                     in the output.
  59  * \param[in]     only_rsc             If a resource ID or tag, include only the
  60  *                                     matching resource(s) (if any) in the
  61  *                                     output. If \p "*" or \p NULL, include all
  62  *                                     resources in the output.
  63  * \param[in]     neg_location_prefix  Prefix denoting a ban in a constraint ID
  64  *
  65  * \return Standard Pacemaker return code
  66  */
  67 int
  68 pcmk__output_cluster_status(pcmk_scheduler_t *scheduler, stonith_t *stonith,
     /* [previous][next][first][last][top][bottom][index][help] */
  69                             cib_t *cib, xmlNode *current_cib,
  70                             enum pcmk_pacemakerd_state pcmkd_state,
  71                             enum pcmk__fence_history fence_history,
  72                             uint32_t show, uint32_t show_opts,
  73                             const char *only_node, const char *only_rsc,
  74                             const char *neg_location_prefix)
  75 {
  76     xmlNode *cib_copy = pcmk__xml_copy(NULL, current_cib);
  77     stonith_history_t *stonith_history = NULL;
  78     int history_rc = 0;
  79     GList *unames = NULL;
  80     GList *resources = NULL;
  81     pcmk__output_t *out = NULL;
  82 
  83     int rc = pcmk_rc_ok;
  84 
  85     if ((scheduler == NULL) || (scheduler->priv->out == NULL)) {
  86         return EINVAL;
  87     }
  88     out = scheduler->priv->out;
  89 
  90     rc = pcmk__update_configured_schema(&cib_copy, false);
  91     if (rc != pcmk_rc_ok) {
  92         cib__clean_up_connection(&cib);
  93         pcmk__xml_free(cib_copy);
  94         out->err(out, "Upgrade failed: %s", pcmk_rc_str(rc));
  95         return rc;
  96     }
  97 
  98     /* get the stonith-history if there is evidence we need it */
  99     if (fence_history != pcmk__fence_history_none) {
 100         history_rc = pcmk__get_fencing_history(stonith, &stonith_history,
 101                                                fence_history);
 102     }
 103 
 104     pcmk_reset_scheduler(scheduler);
 105     scheduler->input = cib_copy;
 106     cluster_status(scheduler);
 107 
 108     /* Unpack constraints if any section will need them
 109      * (tickets may be referenced in constraints but not granted yet,
 110      * and bans need negative location constraints) */
 111     if (pcmk_is_set(show, pcmk_section_bans)
 112         || pcmk_is_set(show, pcmk_section_tickets)) {
 113         pcmk__unpack_constraints(scheduler);
 114     }
 115 
 116     unames = pe__build_node_name_list(scheduler, only_node);
 117     resources = pe__build_rsc_list(scheduler, only_rsc);
 118 
 119     /* Always print DC if NULL. */
 120     if (scheduler->dc_node == NULL) {
 121         show |= pcmk_section_dc;
 122     }
 123 
 124     out->message(out, "cluster-status",
 125                  scheduler, pcmkd_state, pcmk_rc2exitc(history_rc),
 126                  stonith_history, fence_history, show, show_opts,
 127                  neg_location_prefix, unames, resources);
 128 
 129     g_list_free_full(unames, free);
 130     g_list_free_full(resources, free);
 131 
 132     stonith__history_free(stonith_history);
 133     stonith_history = NULL;
 134     return rc;
 135 }
 136 
 137 int
 138 pcmk_status(xmlNodePtr *xml)
     /* [previous][next][first][last][top][bottom][index][help] */
 139 {
 140     cib_t *cib = NULL;
 141     pcmk__output_t *out = NULL;
 142     int rc = pcmk_rc_ok;
 143 
 144     uint32_t show_opts = pcmk_show_pending
 145                          |pcmk_show_inactive_rscs
 146                          |pcmk_show_timing;
 147 
 148     cib = cib_new();
 149 
 150     if (cib == NULL) {
 151         return pcmk_rc_cib_corrupt;
 152     }
 153 
 154     rc = pcmk__xml_output_new(&out, xml);
 155     if (rc != pcmk_rc_ok) {
 156         cib_delete(cib);
 157         return rc;
 158     }
 159 
 160     pcmk__register_lib_messages(out);
 161     pe__register_messages(out);
 162     stonith__register_messages(out);
 163 
 164     rc = pcmk__status(out, cib, pcmk__fence_history_full, pcmk_section_all,
 165                       show_opts, NULL, NULL, NULL, 0);
 166     pcmk__xml_output_finish(out, pcmk_rc2exitc(rc), xml);
 167 
 168     cib_delete(cib);
 169     return rc;
 170 }
 171 
 172 /*!
 173  * \internal
 174  * \brief Query and output the cluster status
 175  *
 176  * The operation is considered a success if we're able to get the \p pacemakerd
 177  * state. If possible, we'll also try to connect to the fencer and CIB and
 178  * output their respective status information.
 179  *
 180  * \param[in,out] out                  Output object
 181  * \param[in,out] cib                  CIB connection
 182  * \param[in]     fence_history        How much of the fencing history to output
 183  * \param[in]     show                 Group of \p pcmk_section_e flags
 184  * \param[in]     show_opts            Group of \p pcmk_show_opt_e flags
 185  * \param[in]     only_node            If a node name or tag, include only the
 186  *                                     matching node(s) (if any) in the output.
 187  *                                     If \p "*" or \p NULL, include all nodes
 188  *                                     in the output.
 189  * \param[in]     only_rsc             If a resource ID or tag, include only the
 190  *                                     matching resource(s) (if any) in the
 191  *                                     output. If \p "*" or \p NULL, include all
 192  *                                     resources in the output.
 193  * \param[in]     neg_location_prefix  Prefix denoting a ban in a constraint ID
 194  * \param[in]     timeout_ms           How long to wait for a reply from the
 195  *                                     \p pacemakerd API. If 0,
 196  *                                     \p pcmk_ipc_dispatch_sync will be used.
 197  *                                     If positive, \p pcmk_ipc_dispatch_main
 198  *                                     will be used, and a new mainloop will be
 199  *                                     created for this purpose (freed before
 200  *                                     return).
 201  *
 202  * \return Standard Pacemaker return code
 203  */
 204 int
 205 pcmk__status(pcmk__output_t *out, cib_t *cib,
     /* [previous][next][first][last][top][bottom][index][help] */
 206              enum pcmk__fence_history fence_history, uint32_t show,
 207              uint32_t show_opts, const char *only_node, const char *only_rsc,
 208              const char *neg_location_prefix, unsigned int timeout_ms)
 209 {
 210     xmlNode *current_cib = NULL;
 211     int rc = pcmk_rc_ok;
 212     stonith_t *stonith = NULL;
 213     enum pcmk_pacemakerd_state pcmkd_state = pcmk_pacemakerd_state_invalid;
 214     time_t last_updated = 0;
 215     pcmk_scheduler_t *scheduler = NULL;
 216 
 217     if (cib == NULL) {
 218         return ENOTCONN;
 219     }
 220 
 221     if (cib->variant == cib_native) {
 222         rc = pcmk__pacemakerd_status(out, crm_system_name, timeout_ms, false,
 223                                      &pcmkd_state);
 224         if (rc != pcmk_rc_ok) {
 225             return rc;
 226         }
 227 
 228         last_updated = time(NULL);
 229 
 230         switch (pcmkd_state) {
 231             case pcmk_pacemakerd_state_running:
 232             case pcmk_pacemakerd_state_shutting_down:
 233             case pcmk_pacemakerd_state_remote:
 234                 /* Fencer and CIB may still be available while shutting down or
 235                  * running on a Pacemaker Remote node
 236                  */
 237                 break;
 238             default:
 239                 // Fencer and CIB are definitely unavailable
 240                 out->message(out, "pacemakerd-health",
 241                              NULL, pcmkd_state, NULL, last_updated);
 242                 return rc;
 243         }
 244 
 245         if (fence_history != pcmk__fence_history_none) {
 246             stonith = fencing_connect();
 247         }
 248     }
 249 
 250     rc = cib__signon_query(out, &cib, &current_cib);
 251     if (rc != pcmk_rc_ok) {
 252         if (pcmkd_state != pcmk_pacemakerd_state_invalid) {
 253             // Invalid at this point means we didn't query the pcmkd state
 254             out->message(out, "pacemakerd-health",
 255                          NULL, pcmkd_state, NULL, last_updated);
 256         }
 257         goto done;
 258     }
 259 
 260     scheduler = pcmk_new_scheduler();
 261     pcmk__mem_assert(scheduler);
 262     scheduler->priv->out = out;
 263 
 264     if ((cib->variant == cib_native) && pcmk_is_set(show, pcmk_section_times)) {
 265         // Currently used only in the times section
 266         pcmk__query_node_name(out, 0, &(scheduler->priv->local_node_name), 0);
 267     }
 268 
 269     rc = pcmk__output_cluster_status(scheduler, stonith, cib, current_cib,
 270                                      pcmkd_state, fence_history, show,
 271                                      show_opts, only_node, only_rsc,
 272                                      neg_location_prefix);
 273     if (rc != pcmk_rc_ok) {
 274         out->err(out, "Error outputting status info from the fencer or CIB");
 275     }
 276 
 277 done:
 278     pcmk_free_scheduler(scheduler);
 279     stonith__api_free(stonith);
 280     pcmk__xml_free(current_cib);
 281     return pcmk_rc_ok;
 282 }

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