root/daemons/fenced/fenced_scheduler.c

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

DEFINITIONS

This source file includes following definitions.
  1. fenced_scheduler_init
  2. fenced_scheduler_cleanup
  3. local_node_allowed_for
  4. register_if_fencing_device
  5. fenced_scheduler_run

   1 /*
   2  * Copyright 2009-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 <stdio.h>
  13 #include <errno.h>
  14 #include <glib.h>
  15 
  16 #include <crm/pengine/status.h>
  17 #include <crm/pengine/internal.h>
  18 
  19 #include <pacemaker-internal.h>
  20 #include <pacemaker-fenced.h>
  21 
  22 static pcmk_scheduler_t *scheduler = NULL;
  23 
  24 /*!
  25  * \internal
  26  * \brief Initialize scheduler data for fencer purposes
  27  *
  28  * \return Standard Pacemaker return code
  29  */
  30 int
  31 fenced_scheduler_init(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  32 {
  33     pcmk__output_t *logger = NULL;
  34     int rc = pcmk__log_output_new(&logger);
  35 
  36     if (rc != pcmk_rc_ok) {
  37         return rc;
  38     }
  39 
  40     scheduler = pe_new_working_set();
  41     if (scheduler == NULL) {
  42         pcmk__output_free(logger);
  43         return ENOMEM;
  44     }
  45 
  46     pe__register_messages(logger);
  47     pcmk__register_lib_messages(logger);
  48     pcmk__output_set_log_level(logger, LOG_TRACE);
  49     scheduler->priv = logger;
  50 
  51     return pcmk_rc_ok;
  52 }
  53 
  54 /*!
  55  * \internal
  56  * \brief Free all scheduler-related resources
  57  */
  58 void
  59 fenced_scheduler_cleanup(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  60 {
  61     if (scheduler != NULL) {
  62         pcmk__output_t *logger = scheduler->priv;
  63 
  64         if (logger != NULL) {
  65             logger->finish(logger, CRM_EX_OK, true, NULL);
  66             pcmk__output_free(logger);
  67             scheduler->priv = NULL;
  68         }
  69         pe_free_working_set(scheduler);
  70         scheduler = NULL;
  71     }
  72 }
  73 
  74 /*!
  75  * \internal
  76  * \brief Check whether the local node is in a resource's allowed node list
  77  *
  78  * \param[in] rsc  Resource to check
  79  *
  80  * \return Pointer to node if found, otherwise NULL
  81  */
  82 static pcmk_node_t *
  83 local_node_allowed_for(const pcmk_resource_t *rsc)
     /* [previous][next][first][last][top][bottom][index][help] */
  84 {
  85     if ((rsc != NULL) && (stonith_our_uname != NULL)) {
  86         GHashTableIter iter;
  87         pcmk_node_t *node = NULL;
  88 
  89         g_hash_table_iter_init(&iter, rsc->allowed_nodes);
  90         while (g_hash_table_iter_next(&iter, NULL, (void **) &node)) {
  91             if (pcmk__str_eq(node->details->uname, stonith_our_uname,
  92                              pcmk__str_casei)) {
  93                 return node;
  94             }
  95         }
  96     }
  97     return NULL;
  98 }
  99 
 100 /*!
 101  * \internal
 102  * \brief If a given resource or any of its children are fencing devices,
 103  *        register the devices
 104  *
 105  * \param[in,out] data       Resource to check
 106  * \param[in,out] user_data  Ignored
 107  */
 108 static void
 109 register_if_fencing_device(gpointer data, gpointer user_data)
     /* [previous][next][first][last][top][bottom][index][help] */
 110 {
 111     pcmk_resource_t *rsc = data;
 112 
 113     xmlNode *xml = NULL;
 114     GHashTableIter hash_iter;
 115     pcmk_node_t *node = NULL;
 116     const char *name = NULL;
 117     const char *value = NULL;
 118     const char *agent = NULL;
 119     const char *rsc_provides = NULL;
 120     stonith_key_value_t *params = NULL;
 121 
 122     // If this is a collective resource, check children instead
 123     if (rsc->children != NULL) {
 124         for (GList *iter = rsc->children; iter != NULL; iter = iter->next) {
 125             register_if_fencing_device(iter->data, NULL);
 126             if (pcmk__is_clone(rsc)) {
 127                 return; // Only one instance needs to be checked for clones
 128             }
 129         }
 130         return;
 131     }
 132 
 133     if (!pcmk_is_set(rsc->flags, pcmk_rsc_fence_device)) {
 134         return; // Not a fencing device
 135     }
 136 
 137     if (pe__resource_is_disabled(rsc)) {
 138         crm_info("Ignoring fencing device %s because it is disabled", rsc->id);
 139         return;
 140     }
 141 
 142     if ((stonith_watchdog_timeout_ms <= 0) &&
 143         pcmk__str_eq(rsc->id, STONITH_WATCHDOG_ID, pcmk__str_none)) {
 144         crm_info("Ignoring fencing device %s "
 145                  "because watchdog fencing is disabled", rsc->id);
 146         return;
 147     }
 148 
 149     // Check whether local node is allowed to run resource
 150     node = local_node_allowed_for(rsc);
 151     if (node == NULL) {
 152         crm_info("Ignoring fencing device %s "
 153                  "because local node is not allowed to run it", rsc->id);
 154         return;
 155     }
 156     if (node->weight < 0) {
 157         crm_info("Ignoring fencing device %s "
 158                  "because local node has preference %s for it",
 159                  rsc->id, pcmk_readable_score(node->weight));
 160         return;
 161     }
 162 
 163     // If device is in a group, check whether local node is allowed for group
 164     if (pcmk__is_group(rsc->parent)) {
 165         pcmk_node_t *group_node = local_node_allowed_for(rsc->parent);
 166 
 167         if ((group_node != NULL) && (group_node->weight < 0)) {
 168             crm_info("Ignoring fencing device %s "
 169                      "because local node has preference %s for its group",
 170                      rsc->id, pcmk_readable_score(group_node->weight));
 171             return;
 172         }
 173     }
 174 
 175     crm_debug("Reloading configuration of fencing device %s", rsc->id);
 176 
 177     agent = crm_element_value(rsc->xml, PCMK_XA_TYPE);
 178 
 179     /* @COMPAT Support for node attribute expressions in rules for resource
 180      * meta-attributes is deprecated. When we can break behavioral backward
 181      * compatibility, replace node with NULL here.
 182      */
 183     get_meta_attributes(rsc->meta, rsc, node, scheduler);
 184     rsc_provides = g_hash_table_lookup(rsc->meta, PCMK_STONITH_PROVIDES);
 185 
 186     g_hash_table_iter_init(&hash_iter, pe_rsc_params(rsc, node, scheduler));
 187     while (g_hash_table_iter_next(&hash_iter, (gpointer *) &name,
 188                                   (gpointer *) &value)) {
 189         if ((name == NULL) || (value == NULL)) {
 190             continue;
 191         }
 192         params = stonith_key_value_add(params, name, value);
 193     }
 194 
 195     xml = create_device_registration_xml(pcmk__s(rsc->clone_name, rsc->id),
 196                                          st_namespace_any, agent, params,
 197                                          rsc_provides);
 198     stonith_key_value_freeall(params, 1, 1);
 199     pcmk__assert(stonith_device_register(xml, TRUE) == pcmk_ok);
 200     free_xml(xml);
 201 }
 202 
 203 /*!
 204  * \internal
 205  * \brief Run the scheduler for fencer purposes
 206  *
 207  * \param[in] cib  Cluster's current CIB
 208  */
 209 void
 210 fenced_scheduler_run(xmlNode *cib)
     /* [previous][next][first][last][top][bottom][index][help] */
 211 {
 212     CRM_CHECK((cib != NULL) && (scheduler != NULL), return);
 213 
 214     if (scheduler->now != NULL) {
 215         crm_time_free(scheduler->now);
 216         scheduler->now = NULL;
 217     }
 218     scheduler->localhost = stonith_our_uname;
 219     pcmk__schedule_actions(cib, pcmk_sched_location_only
 220                                 |pcmk_sched_no_compat
 221                                 |pcmk_sched_no_counts, scheduler);
 222     g_list_foreach(scheduler->resources, register_if_fencing_device, NULL);
 223 
 224     scheduler->input = NULL; // Wasn't a copy, so don't let API free it
 225     pe_reset_working_set(scheduler);
 226 }

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