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-2023 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 *rclass = NULL;
 119     const char *agent = NULL;
 120     const char *rsc_provides = NULL;
 121     stonith_key_value_t *params = NULL;
 122 
 123     // If this is a collective resource, check children instead
 124     if (rsc->children != NULL) {
 125         for (GList *iter = rsc->children; iter != NULL; iter = iter->next) {
 126             register_if_fencing_device(iter->data, NULL);
 127             if (pe_rsc_is_clone(rsc)) {
 128                 return; // Only one instance needs to be checked for clones
 129             }
 130         }
 131         return;
 132     }
 133 
 134     rclass = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS);
 135     if (!pcmk__str_eq(rclass, PCMK_RESOURCE_CLASS_STONITH, pcmk__str_casei)) {
 136         return; // Not a fencing device
 137     }
 138 
 139     if (pe__resource_is_disabled(rsc)) {
 140         crm_info("Ignoring fencing device %s because it is disabled", rsc->id);
 141         return;
 142     }
 143 
 144     if ((stonith_watchdog_timeout_ms <= 0) &&
 145         pcmk__str_eq(rsc->id, STONITH_WATCHDOG_ID, pcmk__str_none)) {
 146         crm_info("Ignoring fencing device %s "
 147                  "because watchdog fencing is disabled", rsc->id);
 148         return;
 149     }
 150 
 151     // Check whether local node is allowed to run resource
 152     node = local_node_allowed_for(rsc);
 153     if (node == NULL) {
 154         crm_info("Ignoring fencing device %s "
 155                  "because local node is not allowed to run it", rsc->id);
 156         return;
 157     }
 158     if (node->weight < 0) {
 159         crm_info("Ignoring fencing device %s "
 160                  "because local node has preference %s for it",
 161                  rsc->id, pcmk_readable_score(node->weight));
 162         return;
 163     }
 164 
 165     // If device is in a group, check whether local node is allowed for group
 166     if ((rsc->parent != NULL)
 167         && (rsc->parent->variant == pcmk_rsc_variant_group)) {
 168         pcmk_node_t *group_node = local_node_allowed_for(rsc->parent);
 169 
 170         if ((group_node != NULL) && (group_node->weight < 0)) {
 171             crm_info("Ignoring fencing device %s "
 172                      "because local node has preference %s for its group",
 173                      rsc->id, pcmk_readable_score(group_node->weight));
 174             return;
 175         }
 176     }
 177 
 178     crm_debug("Reloading configuration of fencing device %s", rsc->id);
 179 
 180     agent = crm_element_value(rsc->xml, XML_EXPR_ATTR_TYPE);
 181 
 182     get_meta_attributes(rsc->meta, rsc, node, scheduler);
 183     rsc_provides = g_hash_table_lookup(rsc->meta, PCMK_STONITH_PROVIDES);
 184 
 185     g_hash_table_iter_init(&hash_iter, pe_rsc_params(rsc, node, scheduler));
 186     while (g_hash_table_iter_next(&hash_iter, (gpointer *) &name,
 187                                   (gpointer *) &value)) {
 188         if ((name == NULL) || (value == NULL)) {
 189             continue;
 190         }
 191         params = stonith_key_value_add(params, name, value);
 192     }
 193 
 194     xml = create_device_registration_xml(pcmk__s(rsc->clone_name, rsc->id),
 195                                          st_namespace_any, agent, params,
 196                                          rsc_provides);
 197     stonith_key_value_freeall(params, 1, 1);
 198     CRM_ASSERT(stonith_device_register(xml, TRUE) == pcmk_ok);
 199     free_xml(xml);
 200 }
 201 
 202 /*!
 203  * \internal
 204  * \brief Run the scheduler for fencer purposes
 205  *
 206  * \param[in] cib  Cluster's current CIB
 207  */
 208 void
 209 fenced_scheduler_run(xmlNode *cib)
     /* [previous][next][first][last][top][bottom][index][help] */
 210 {
 211     CRM_CHECK((cib != NULL) && (scheduler != NULL), return);
 212 
 213     if (scheduler->now != NULL) {
 214         crm_time_free(scheduler->now);
 215         scheduler->now = NULL;
 216     }
 217     scheduler->localhost = stonith_our_uname;
 218     pcmk__schedule_actions(cib, pcmk_sched_location_only
 219                                 |pcmk_sched_no_compat
 220                                 |pcmk_sched_no_counts, scheduler);
 221     g_list_foreach(scheduler->resources, register_if_fencing_device, NULL);
 222 
 223     scheduler->input = NULL; // Wasn't a copy, so don't let API free it
 224     pe_reset_working_set(scheduler);
 225 }

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