root/lib/pengine/remote.c

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

DEFINITIONS

This source file includes following definitions.
  1. pe__resource_is_remote_conn
  2. pe__is_remote_node
  3. pe__is_guest_node
  4. pe__is_guest_or_remote_node
  5. pe__is_bundle_node
  6. pe__resource_contains_guest_node
  7. xml_contains_remote_node
  8. pe_foreach_guest_node
  9. pe_create_remote_xml
  10. pe__add_param_check
  11. pe__foreach_param_check
  12. pe__free_param_checks

   1 /*
   2  * Copyright 2013-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 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/msg_xml.h>
  12 #include <crm/common/xml.h>
  13 #include <crm/common/scheduler_internal.h>
  14 #include <crm/pengine/internal.h>
  15 #include <glib.h>
  16 
  17 bool
  18 pe__resource_is_remote_conn(const pcmk_resource_t *rsc)
     /* [previous][next][first][last][top][bottom][index][help] */
  19 {
  20     return (rsc != NULL) && rsc->is_remote_node
  21            && pe__is_remote_node(pe_find_node(rsc->cluster->nodes, rsc->id));
  22 }
  23 
  24 bool
  25 pe__is_remote_node(const pcmk_node_t *node)
     /* [previous][next][first][last][top][bottom][index][help] */
  26 {
  27     return (node != NULL) && (node->details->type == pcmk_node_variant_remote)
  28            && ((node->details->remote_rsc == NULL)
  29                || (node->details->remote_rsc->container == NULL));
  30 }
  31 
  32 bool
  33 pe__is_guest_node(const pcmk_node_t *node)
     /* [previous][next][first][last][top][bottom][index][help] */
  34 {
  35     return (node != NULL) && (node->details->type == pcmk_node_variant_remote)
  36            && (node->details->remote_rsc != NULL)
  37            && (node->details->remote_rsc->container != NULL);
  38 }
  39 
  40 bool
  41 pe__is_guest_or_remote_node(const pcmk_node_t *node)
     /* [previous][next][first][last][top][bottom][index][help] */
  42 {
  43     return (node != NULL) && (node->details->type == pcmk_node_variant_remote);
  44 }
  45 
  46 bool
  47 pe__is_bundle_node(const pcmk_node_t *node)
     /* [previous][next][first][last][top][bottom][index][help] */
  48 {
  49     return pe__is_guest_node(node)
  50            && pe_rsc_is_bundled(node->details->remote_rsc);
  51 }
  52 
  53 /*!
  54  * \internal
  55  * \brief Check whether a resource creates a guest node
  56  *
  57  * If a given resource contains a filler resource that is a remote connection,
  58  * return that filler resource (or NULL if none is found).
  59  *
  60  * \param[in] scheduler  Scheduler data
  61  * \param[in] rsc        Resource to check
  62  *
  63  * \return Filler resource with remote connection, or NULL if none found
  64  */
  65 pcmk_resource_t *
  66 pe__resource_contains_guest_node(const pcmk_scheduler_t *scheduler,
     /* [previous][next][first][last][top][bottom][index][help] */
  67                                  const pcmk_resource_t *rsc)
  68 {
  69     if ((rsc != NULL) && (scheduler != NULL)
  70         && pcmk_is_set(scheduler->flags, pcmk_sched_have_remote_nodes)) {
  71 
  72         for (GList *gIter = rsc->fillers; gIter != NULL; gIter = gIter->next) {
  73             pcmk_resource_t *filler = gIter->data;
  74 
  75             if (filler->is_remote_node) {
  76                 return filler;
  77             }
  78         }
  79     }
  80     return NULL;
  81 }
  82 
  83 bool
  84 xml_contains_remote_node(xmlNode *xml)
     /* [previous][next][first][last][top][bottom][index][help] */
  85 {
  86     const char *value = NULL;
  87 
  88     if (xml == NULL) {
  89         return false;
  90     }
  91 
  92     value = crm_element_value(xml, XML_ATTR_TYPE);
  93     if (!pcmk__str_eq(value, "remote", pcmk__str_casei)) {
  94         return false;
  95     }
  96 
  97     value = crm_element_value(xml, XML_AGENT_ATTR_CLASS);
  98     if (!pcmk__str_eq(value, PCMK_RESOURCE_CLASS_OCF, pcmk__str_casei)) {
  99         return false;
 100     }
 101 
 102     value = crm_element_value(xml, XML_AGENT_ATTR_PROVIDER);
 103     if (!pcmk__str_eq(value, "pacemaker", pcmk__str_casei)) {
 104         return false;
 105     }
 106 
 107     return true;
 108 }
 109 
 110 /*!
 111  * \internal
 112  * \brief Execute a supplied function for each guest node running on a host
 113  *
 114  * \param[in]     scheduler  Scheduler data
 115  * \param[in]     host       Host node to check
 116  * \param[in]     helper     Function to call for each guest node
 117  * \param[in,out] user_data  Pointer to pass to helper function
 118  */
 119 void
 120 pe_foreach_guest_node(const pcmk_scheduler_t *scheduler,
     /* [previous][next][first][last][top][bottom][index][help] */
 121                       const pcmk_node_t *host,
 122                       void (*helper)(const pcmk_node_t*, void*),
 123                       void *user_data)
 124 {
 125     GList *iter;
 126 
 127     CRM_CHECK(scheduler && host && host->details && helper, return);
 128     if (!pcmk_is_set(scheduler->flags, pcmk_sched_have_remote_nodes)) {
 129         return;
 130     }
 131     for (iter = host->details->running_rsc; iter != NULL; iter = iter->next) {
 132         pcmk_resource_t *rsc = (pcmk_resource_t *) iter->data;
 133 
 134         if (rsc->is_remote_node && (rsc->container != NULL)) {
 135             pcmk_node_t *guest_node = pe_find_node(scheduler->nodes, rsc->id);
 136 
 137             if (guest_node) {
 138                 (*helper)(guest_node, user_data);
 139             }
 140         }
 141     }
 142 }
 143 
 144 /*!
 145  * \internal
 146  * \brief Create CIB XML for an implicit remote connection
 147  *
 148  * \param[in,out] parent           If not NULL, use as parent XML element
 149  * \param[in]     uname            Name of Pacemaker Remote node
 150  * \param[in]     container        If not NULL, use this as connection container
 151  * \param[in]     migrateable      If not NULL, use as allow-migrate value
 152  * \param[in]     is_managed       If not NULL, use as is-managed value
 153  * \param[in]     start_timeout    If not NULL, use as remote connect timeout
 154  * \param[in]     server           If not NULL, use as remote server value
 155  * \param[in]     port             If not NULL, use as remote port value
 156  *
 157  * \return Newly created XML
 158  */
 159 xmlNode *
 160 pe_create_remote_xml(xmlNode *parent, const char *uname,
     /* [previous][next][first][last][top][bottom][index][help] */
 161                      const char *container_id, const char *migrateable,
 162                      const char *is_managed, const char *start_timeout,
 163                      const char *server, const char *port)
 164 {
 165     xmlNode *remote;
 166     xmlNode *xml_sub;
 167 
 168     remote = create_xml_node(parent, XML_CIB_TAG_RESOURCE);
 169 
 170     // Add identity
 171     crm_xml_add(remote, XML_ATTR_ID, uname);
 172     crm_xml_add(remote, XML_AGENT_ATTR_CLASS, PCMK_RESOURCE_CLASS_OCF);
 173     crm_xml_add(remote, XML_AGENT_ATTR_PROVIDER, "pacemaker");
 174     crm_xml_add(remote, XML_ATTR_TYPE, "remote");
 175 
 176     // Add meta-attributes
 177     xml_sub = create_xml_node(remote, XML_TAG_META_SETS);
 178     crm_xml_set_id(xml_sub, "%s-%s", uname, XML_TAG_META_SETS);
 179     crm_create_nvpair_xml(xml_sub, NULL,
 180                           XML_RSC_ATTR_INTERNAL_RSC, XML_BOOLEAN_TRUE);
 181     if (container_id) {
 182         crm_create_nvpair_xml(xml_sub, NULL,
 183                               XML_RSC_ATTR_CONTAINER, container_id);
 184     }
 185     if (migrateable) {
 186         crm_create_nvpair_xml(xml_sub, NULL,
 187                               XML_OP_ATTR_ALLOW_MIGRATE, migrateable);
 188     }
 189     if (is_managed) {
 190         crm_create_nvpair_xml(xml_sub, NULL, XML_RSC_ATTR_MANAGED, is_managed);
 191     }
 192 
 193     // Add instance attributes
 194     if (port || server) {
 195         xml_sub = create_xml_node(remote, XML_TAG_ATTR_SETS);
 196         crm_xml_set_id(xml_sub, "%s-%s", uname, XML_TAG_ATTR_SETS);
 197         if (server) {
 198             crm_create_nvpair_xml(xml_sub, NULL, XML_RSC_ATTR_REMOTE_RA_ADDR,
 199                                   server);
 200         }
 201         if (port) {
 202             crm_create_nvpair_xml(xml_sub, NULL, "port", port);
 203         }
 204     }
 205 
 206     // Add operations
 207     xml_sub = create_xml_node(remote, "operations");
 208     crm_create_op_xml(xml_sub, uname, PCMK_ACTION_MONITOR, "30s", "30s");
 209     if (start_timeout) {
 210         crm_create_op_xml(xml_sub, uname, PCMK_ACTION_START, "0",
 211                           start_timeout);
 212     }
 213     return remote;
 214 }
 215 
 216 // History entry to be checked for fail count clearing
 217 struct check_op {
 218     const xmlNode *rsc_op;  // History entry XML
 219     pcmk_resource_t *rsc;   // Known resource corresponding to history entry
 220     pcmk_node_t *node;      // Known node corresponding to history entry
 221     enum pcmk__check_parameters check_type; // What needs checking
 222 };
 223 
 224 void
 225 pe__add_param_check(const xmlNode *rsc_op, pcmk_resource_t *rsc,
     /* [previous][next][first][last][top][bottom][index][help] */
 226                     pcmk_node_t *node, enum pcmk__check_parameters flag,
 227                     pcmk_scheduler_t *scheduler)
 228 {
 229     struct check_op *check_op = NULL;
 230 
 231     CRM_CHECK(scheduler && rsc_op && rsc && node, return);
 232 
 233     check_op = calloc(1, sizeof(struct check_op));
 234     CRM_ASSERT(check_op != NULL);
 235 
 236     crm_trace("Deferring checks of %s until after allocation", ID(rsc_op));
 237     check_op->rsc_op = rsc_op;
 238     check_op->rsc = rsc;
 239     check_op->node = node;
 240     check_op->check_type = flag;
 241     scheduler->param_check = g_list_prepend(scheduler->param_check, check_op);
 242 }
 243 
 244 /*!
 245  * \internal
 246  * \brief Call a function for each action to be checked for addr substitution
 247  *
 248  * \param[in,out] scheduler  Scheduler data
 249  * \param[in]     cb         Function to be called
 250  */
 251 void
 252 pe__foreach_param_check(pcmk_scheduler_t *scheduler,
     /* [previous][next][first][last][top][bottom][index][help] */
 253                        void (*cb)(pcmk_resource_t*, pcmk_node_t*,
 254                                   const xmlNode*, enum pcmk__check_parameters))
 255 {
 256     CRM_CHECK(scheduler && cb, return);
 257 
 258     for (GList *item = scheduler->param_check;
 259          item != NULL; item = item->next) {
 260         struct check_op *check_op = item->data;
 261 
 262         cb(check_op->rsc, check_op->node, check_op->rsc_op,
 263            check_op->check_type);
 264     }
 265 }
 266 
 267 void
 268 pe__free_param_checks(pcmk_scheduler_t *scheduler)
     /* [previous][next][first][last][top][bottom][index][help] */
 269 {
 270     if (scheduler && scheduler->param_check) {
 271         g_list_free_full(scheduler->param_check, free);
 272         scheduler->param_check = NULL;
 273     }
 274 }

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