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_set_local_node
  3. fenced_get_local_node
  4. fenced_scheduler_cleanup
  5. local_node_allowed_for
  6. register_if_fencing_device
  7. 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->out = logger;
  50 
  51     return pcmk_rc_ok;
  52 }
  53 
  54 /*!
  55  * \internal
  56  * \brief Set the local node name for scheduling purposes
  57  *
  58  * \param[in] node_name  Name to set as local node name
  59  */
  60 void
  61 fenced_set_local_node(const char *node_name)
     /* [previous][next][first][last][top][bottom][index][help] */
  62 {
  63     pcmk__assert(scheduler != NULL);
  64 
  65     scheduler->priv->local_node_name = pcmk__str_copy(node_name);
  66 }
  67 
  68 /*!
  69  * \internal
  70  * \brief Get the local node name
  71  *
  72  * \return Local node name
  73  */
  74 const char *
  75 fenced_get_local_node(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  76 {
  77     if (scheduler == NULL) {
  78         return NULL;
  79     }
  80     return scheduler->priv->local_node_name;
  81 }
  82 
  83 /*!
  84  * \internal
  85  * \brief Free all scheduler-related resources
  86  */
  87 void
  88 fenced_scheduler_cleanup(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  89 {
  90     if (scheduler != NULL) {
  91         pcmk__output_t *logger = scheduler->priv->out;
  92 
  93         if (logger != NULL) {
  94             logger->finish(logger, CRM_EX_OK, true, NULL);
  95             pcmk__output_free(logger);
  96             scheduler->priv->out = NULL;
  97         }
  98         pe_free_working_set(scheduler);
  99         scheduler = NULL;
 100     }
 101 }
 102 
 103 /*!
 104  * \internal
 105  * \brief Check whether the local node is in a resource's allowed node list
 106  *
 107  * \param[in] rsc  Resource to check
 108  *
 109  * \return Pointer to node if found, otherwise NULL
 110  */
 111 static pcmk_node_t *
 112 local_node_allowed_for(const pcmk_resource_t *rsc)
     /* [previous][next][first][last][top][bottom][index][help] */
 113 {
 114     if ((rsc != NULL) && (scheduler->priv->local_node_name != NULL)) {
 115         GHashTableIter iter;
 116         pcmk_node_t *node = NULL;
 117 
 118         g_hash_table_iter_init(&iter, rsc->priv->allowed_nodes);
 119         while (g_hash_table_iter_next(&iter, NULL, (void **) &node)) {
 120             if (pcmk__str_eq(node->priv->name, scheduler->priv->local_node_name,
 121                              pcmk__str_casei)) {
 122                 return node;
 123             }
 124         }
 125     }
 126     return NULL;
 127 }
 128 
 129 /*!
 130  * \internal
 131  * \brief If a given resource or any of its children are fencing devices,
 132  *        register the devices
 133  *
 134  * \param[in,out] data       Resource to check
 135  * \param[in,out] user_data  Ignored
 136  */
 137 static void
 138 register_if_fencing_device(gpointer data, gpointer user_data)
     /* [previous][next][first][last][top][bottom][index][help] */
 139 {
 140     pcmk_resource_t *rsc = data;
 141     const char *rsc_id = pcmk__s(rsc->priv->history_id, rsc->id);
 142 
 143     xmlNode *xml = NULL;
 144     GHashTableIter hash_iter;
 145     pcmk_node_t *node = NULL;
 146     const char *name = NULL;
 147     const char *value = NULL;
 148     const char *agent = NULL;
 149     const char *rsc_provides = NULL;
 150     stonith_key_value_t *params = NULL;
 151 
 152     // If this is a collective resource, check children instead
 153     if (rsc->priv->children != NULL) {
 154 
 155         for (GList *iter = rsc->priv->children;
 156              iter != NULL; iter = iter->next) {
 157 
 158             register_if_fencing_device(iter->data, NULL);
 159             if (pcmk__is_clone(rsc)) {
 160                 return; // Only one instance needs to be checked for clones
 161             }
 162         }
 163         return;
 164     }
 165 
 166     if (!pcmk_is_set(rsc->flags, pcmk__rsc_fence_device)) {
 167         return; // Not a fencing device
 168     }
 169 
 170     if (pe__resource_is_disabled(rsc)) {
 171         crm_info("Ignoring fencing device %s because it is disabled", rsc->id);
 172         return;
 173     }
 174 
 175     if ((stonith_watchdog_timeout_ms <= 0) &&
 176         pcmk__str_eq(rsc->id, STONITH_WATCHDOG_ID, pcmk__str_none)) {
 177         crm_info("Ignoring fencing device %s "
 178                  "because watchdog fencing is disabled", rsc->id);
 179         return;
 180     }
 181 
 182     // Check whether local node is allowed to run resource
 183     node = local_node_allowed_for(rsc);
 184     if (node == NULL) {
 185         crm_info("Ignoring fencing device %s "
 186                  "because local node is not allowed to run it", rsc->id);
 187         return;
 188     }
 189     if (node->assign->score < 0) {
 190         crm_info("Ignoring fencing device %s "
 191                  "because local node has preference %s for it",
 192                  rsc->id, pcmk_readable_score(node->assign->score));
 193         return;
 194     }
 195 
 196     // If device is in a group, check whether local node is allowed for group
 197     if (pcmk__is_group(rsc->priv->parent)) {
 198         pcmk_node_t *group_node = local_node_allowed_for(rsc->priv->parent);
 199 
 200         if ((group_node != NULL) && (group_node->assign->score < 0)) {
 201             crm_info("Ignoring fencing device %s "
 202                      "because local node has preference %s for its group",
 203                      rsc->id, pcmk_readable_score(group_node->assign->score));
 204             return;
 205         }
 206     }
 207 
 208     crm_debug("Reloading configuration of fencing device %s", rsc->id);
 209 
 210     agent = crm_element_value(rsc->priv->xml, PCMK_XA_TYPE);
 211 
 212     get_meta_attributes(rsc->priv->meta, rsc, NULL, scheduler);
 213     rsc_provides = g_hash_table_lookup(rsc->priv->meta,
 214                                        PCMK_STONITH_PROVIDES);
 215 
 216     g_hash_table_iter_init(&hash_iter, pe_rsc_params(rsc, node, scheduler));
 217     while (g_hash_table_iter_next(&hash_iter, (gpointer *) &name,
 218                                   (gpointer *) &value)) {
 219         if ((name == NULL) || (value == NULL)) {
 220             continue;
 221         }
 222         params = stonith_key_value_add(params, name, value);
 223     }
 224 
 225     xml = create_device_registration_xml(rsc_id, st_namespace_any, agent,
 226                                          params, rsc_provides);
 227     stonith_key_value_freeall(params, 1, 1);
 228     pcmk__assert(stonith_device_register(xml, TRUE) == pcmk_ok);
 229     pcmk__xml_free(xml);
 230 }
 231 
 232 /*!
 233  * \internal
 234  * \brief Run the scheduler for fencer purposes
 235  *
 236  * \param[in] cib  Cluster's current CIB
 237  */
 238 void
 239 fenced_scheduler_run(xmlNode *cib)
     /* [previous][next][first][last][top][bottom][index][help] */
 240 {
 241     CRM_CHECK((cib != NULL) && (scheduler != NULL), return);
 242 
 243     if (scheduler->priv->now != NULL) {
 244         crm_time_free(scheduler->priv->now);
 245         scheduler->priv->now = NULL;
 246     }
 247     pcmk__schedule_actions(cib, pcmk__sched_location_only
 248                                 |pcmk__sched_no_counts, scheduler);
 249     g_list_foreach(scheduler->priv->resources, register_if_fencing_device,
 250                    NULL);
 251 
 252     scheduler->input = NULL; // Wasn't a copy, so don't let API free it
 253     pe_reset_working_set(scheduler);
 254 }

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