root/lib/pengine/remote.c

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

DEFINITIONS

This source file includes following definitions.
  1. pe__resource_contains_guest_node
  2. xml_contains_remote_node
  3. pe_foreach_guest_node
  4. pe_create_remote_xml
  5. pe__add_param_check
  6. pe__foreach_param_check
  7. pe__free_param_checks

   1 /*
   2  * Copyright 2013-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 Lesser General Public License
   7  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
   8  */
   9 
  10 #include <crm_internal.h>
  11 #include <crm/common/xml.h>
  12 #include <crm/common/scheduler_internal.h>
  13 #include <crm/pengine/internal.h>
  14 #include <glib.h>
  15 
  16 /*!
  17  * \internal
  18  * \brief Check whether a resource creates a guest node
  19  *
  20  * If a given resource contains a launched resource that is a remote connection,
  21  * return that launched resource (or NULL if none is found).
  22  *
  23  * \param[in] scheduler  Scheduler data
  24  * \param[in] rsc        Resource to check
  25  *
  26  * \return Launched remote connection, or NULL if none found
  27  */
  28 pcmk_resource_t *
  29 pe__resource_contains_guest_node(const pcmk_scheduler_t *scheduler,
     /* [previous][next][first][last][top][bottom][index][help] */
  30                                  const pcmk_resource_t *rsc)
  31 {
  32     if ((rsc != NULL) && (scheduler != NULL)
  33         && pcmk_is_set(scheduler->flags, pcmk__sched_have_remote_nodes)) {
  34 
  35         for (GList *gIter = rsc->priv->launched;
  36              gIter != NULL; gIter = gIter->next) {
  37 
  38             pcmk_resource_t *launched = gIter->data;
  39 
  40             if (pcmk_is_set(launched->flags, pcmk__rsc_is_remote_connection)) {
  41                 return launched;
  42             }
  43         }
  44     }
  45     return NULL;
  46 }
  47 
  48 bool
  49 xml_contains_remote_node(xmlNode *xml)
     /* [previous][next][first][last][top][bottom][index][help] */
  50 {
  51     const char *value = NULL;
  52 
  53     if (xml == NULL) {
  54         return false;
  55     }
  56 
  57     value = crm_element_value(xml, PCMK_XA_TYPE);
  58     if (!pcmk__str_eq(value, "remote", pcmk__str_casei)) {
  59         return false;
  60     }
  61 
  62     value = crm_element_value(xml, PCMK_XA_CLASS);
  63     if (!pcmk__str_eq(value, PCMK_RESOURCE_CLASS_OCF, pcmk__str_casei)) {
  64         return false;
  65     }
  66 
  67     value = crm_element_value(xml, PCMK_XA_PROVIDER);
  68     if (!pcmk__str_eq(value, "pacemaker", pcmk__str_casei)) {
  69         return false;
  70     }
  71 
  72     return true;
  73 }
  74 
  75 /*!
  76  * \internal
  77  * \brief Execute a supplied function for each guest node running on a host
  78  *
  79  * \param[in]     scheduler  Scheduler data
  80  * \param[in]     host       Host node to check
  81  * \param[in]     helper     Function to call for each guest node
  82  * \param[in,out] user_data  Pointer to pass to helper function
  83  */
  84 void
  85 pe_foreach_guest_node(const pcmk_scheduler_t *scheduler,
     /* [previous][next][first][last][top][bottom][index][help] */
  86                       const pcmk_node_t *host,
  87                       void (*helper)(const pcmk_node_t*, void*),
  88                       void *user_data)
  89 {
  90     GList *iter;
  91 
  92     CRM_CHECK(scheduler && host && host->details && helper, return);
  93     if (!pcmk_is_set(scheduler->flags, pcmk__sched_have_remote_nodes)) {
  94         return;
  95     }
  96     for (iter = host->details->running_rsc; iter != NULL; iter = iter->next) {
  97         pcmk_resource_t *rsc = (pcmk_resource_t *) iter->data;
  98 
  99         if (pcmk_is_set(rsc->flags, pcmk__rsc_is_remote_connection)
 100             && (rsc->priv->launcher != NULL)) {
 101             pcmk_node_t *guest_node = pcmk_find_node(scheduler, rsc->id);
 102 
 103             if (guest_node) {
 104                 (*helper)(guest_node, user_data);
 105             }
 106         }
 107     }
 108 }
 109 
 110 /*!
 111  * \internal
 112  * \brief Create CIB XML for an implicit remote connection
 113  *
 114  * \param[in,out] parent         If not \c NULL, use as parent XML element
 115  * \param[in]     uname          Name of Pacemaker Remote node
 116  * \param[in]     container_id   If not \c NULL, use this as connection container
 117  * \param[in]     migrateable    If not \c NULL, use as remote
 118  *                               \c PCMK_META_ALLOW_MIGRATE value
 119  * \param[in]     is_managed     If not \c NULL, use as remote
 120  *                               \c PCMK_META_IS_MANAGED value
 121  * \param[in]     start_timeout  If not \c NULL, use as remote connect timeout
 122  * \param[in]     server         If not \c NULL, use as \c PCMK_REMOTE_RA_ADDR
 123  * \param[in]     port           If not \c NULL, use as \c PCMK_REMOTE_RA_PORT
 124  *
 125  * \return Newly created XML
 126  */
 127 xmlNode *
 128 pe_create_remote_xml(xmlNode *parent, const char *uname,
     /* [previous][next][first][last][top][bottom][index][help] */
 129                      const char *container_id, const char *migrateable,
 130                      const char *is_managed, const char *start_timeout,
 131                      const char *server, const char *port)
 132 {
 133     xmlNode *remote;
 134     xmlNode *xml_sub;
 135 
 136     remote = pcmk__xe_create(parent, PCMK_XE_PRIMITIVE);
 137 
 138     // Add identity
 139     crm_xml_add(remote, PCMK_XA_ID, uname);
 140     crm_xml_add(remote, PCMK_XA_CLASS, PCMK_RESOURCE_CLASS_OCF);
 141     crm_xml_add(remote, PCMK_XA_PROVIDER, "pacemaker");
 142     crm_xml_add(remote, PCMK_XA_TYPE, "remote");
 143 
 144     // Add meta-attributes
 145     xml_sub = pcmk__xe_create(remote, PCMK_XE_META_ATTRIBUTES);
 146     pcmk__xe_set_id(xml_sub, "%s-%s", uname, PCMK_XE_META_ATTRIBUTES);
 147     crm_create_nvpair_xml(xml_sub, NULL,
 148                           PCMK__META_INTERNAL_RSC, PCMK_VALUE_TRUE);
 149     if (container_id) {
 150         crm_create_nvpair_xml(xml_sub, NULL,
 151                               PCMK__META_CONTAINER, container_id);
 152     }
 153     if (migrateable) {
 154         crm_create_nvpair_xml(xml_sub, NULL,
 155                               PCMK_META_ALLOW_MIGRATE, migrateable);
 156     }
 157     if (is_managed) {
 158         crm_create_nvpair_xml(xml_sub, NULL, PCMK_META_IS_MANAGED, is_managed);
 159     }
 160 
 161     // Add instance attributes
 162     if (port || server) {
 163         xml_sub = pcmk__xe_create(remote, PCMK_XE_INSTANCE_ATTRIBUTES);
 164         pcmk__xe_set_id(xml_sub, "%s-%s", uname, PCMK_XE_INSTANCE_ATTRIBUTES);
 165         if (server) {
 166             crm_create_nvpair_xml(xml_sub, NULL, PCMK_REMOTE_RA_ADDR, server);
 167         }
 168         if (port) {
 169             crm_create_nvpair_xml(xml_sub, NULL, PCMK_REMOTE_RA_PORT, port);
 170         }
 171     }
 172 
 173     // Add operations
 174     xml_sub = pcmk__xe_create(remote, PCMK_XE_OPERATIONS);
 175     crm_create_op_xml(xml_sub, uname, PCMK_ACTION_MONITOR, "30s", "30s");
 176     if (start_timeout) {
 177         crm_create_op_xml(xml_sub, uname, PCMK_ACTION_START, "0",
 178                           start_timeout);
 179     }
 180     return remote;
 181 }
 182 
 183 // History entry to be checked for fail count clearing
 184 struct check_op {
 185     const xmlNode *rsc_op;  // History entry XML
 186     pcmk_resource_t *rsc;   // Known resource corresponding to history entry
 187     pcmk_node_t *node;      // Known node corresponding to history entry
 188     enum pcmk__check_parameters check_type; // What needs checking
 189 };
 190 
 191 void
 192 pe__add_param_check(const xmlNode *rsc_op, pcmk_resource_t *rsc,
     /* [previous][next][first][last][top][bottom][index][help] */
 193                     pcmk_node_t *node, enum pcmk__check_parameters flag,
 194                     pcmk_scheduler_t *scheduler)
 195 {
 196     struct check_op *check_op = NULL;
 197 
 198     CRM_CHECK(scheduler && rsc_op && rsc && node, return);
 199 
 200     check_op = pcmk__assert_alloc(1, sizeof(struct check_op));
 201 
 202     crm_trace("Deferring checks of %s until after allocation",
 203               pcmk__xe_id(rsc_op));
 204     check_op->rsc_op = rsc_op;
 205     check_op->rsc = rsc;
 206     check_op->node = node;
 207     check_op->check_type = flag;
 208     scheduler->priv->param_check = g_list_prepend(scheduler->priv->param_check,
 209                                                   check_op);
 210 }
 211 
 212 /*!
 213  * \internal
 214  * \brief Call a function for each action to be checked for addr substitution
 215  *
 216  * \param[in,out] scheduler  Scheduler data
 217  * \param[in]     cb         Function to be called
 218  */
 219 void
 220 pe__foreach_param_check(pcmk_scheduler_t *scheduler,
     /* [previous][next][first][last][top][bottom][index][help] */
 221                        void (*cb)(pcmk_resource_t*, pcmk_node_t*,
 222                                   const xmlNode*, enum pcmk__check_parameters))
 223 {
 224     CRM_CHECK(scheduler && cb, return);
 225 
 226     for (GList *item = scheduler->priv->param_check;
 227          item != NULL; item = item->next) {
 228         struct check_op *check_op = item->data;
 229 
 230         cb(check_op->rsc, check_op->node, check_op->rsc_op,
 231            check_op->check_type);
 232     }
 233 }
 234 
 235 void
 236 pe__free_param_checks(pcmk_scheduler_t *scheduler)
     /* [previous][next][first][last][top][bottom][index][help] */
 237 {
 238     if ((scheduler != NULL) && (scheduler->priv->param_check != NULL)) {
 239         g_list_free_full(scheduler->priv->param_check, free);
 240         scheduler->priv->param_check = NULL;
 241     }
 242 }

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