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

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