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

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