LCOV - code coverage report
Current view: top level - pengine - remote.c (source / functions) Hit Total Coverage
Test: Pacemaker code coverage Lines: 0 80 0.0 %
Date: 2024-05-07 11:09:47 Functions: 0 7 0.0 %

          Line data    Source code
       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           0 : pe__resource_contains_guest_node(const pcmk_scheduler_t *scheduler,
      30             :                                  const pcmk_resource_t *rsc)
      31             : {
      32           0 :     if ((rsc != NULL) && (scheduler != NULL)
      33           0 :         && pcmk_is_set(scheduler->flags, pcmk_sched_have_remote_nodes)) {
      34             : 
      35           0 :         for (GList *gIter = rsc->fillers; gIter != NULL; gIter = gIter->next) {
      36           0 :             pcmk_resource_t *filler = gIter->data;
      37             : 
      38           0 :             if (filler->is_remote_node) {
      39           0 :                 return filler;
      40             :             }
      41             :         }
      42             :     }
      43           0 :     return NULL;
      44             : }
      45             : 
      46             : bool
      47           0 : xml_contains_remote_node(xmlNode *xml)
      48             : {
      49           0 :     const char *value = NULL;
      50             : 
      51           0 :     if (xml == NULL) {
      52           0 :         return false;
      53             :     }
      54             : 
      55           0 :     value = crm_element_value(xml, PCMK_XA_TYPE);
      56           0 :     if (!pcmk__str_eq(value, "remote", pcmk__str_casei)) {
      57           0 :         return false;
      58             :     }
      59             : 
      60           0 :     value = crm_element_value(xml, PCMK_XA_CLASS);
      61           0 :     if (!pcmk__str_eq(value, PCMK_RESOURCE_CLASS_OCF, pcmk__str_casei)) {
      62           0 :         return false;
      63             :     }
      64             : 
      65           0 :     value = crm_element_value(xml, PCMK_XA_PROVIDER);
      66           0 :     if (!pcmk__str_eq(value, "pacemaker", pcmk__str_casei)) {
      67           0 :         return false;
      68             :     }
      69             : 
      70           0 :     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           0 : pe_foreach_guest_node(const pcmk_scheduler_t *scheduler,
      84             :                       const pcmk_node_t *host,
      85             :                       void (*helper)(const pcmk_node_t*, void*),
      86             :                       void *user_data)
      87             : {
      88             :     GList *iter;
      89             : 
      90           0 :     CRM_CHECK(scheduler && host && host->details && helper, return);
      91           0 :     if (!pcmk_is_set(scheduler->flags, pcmk_sched_have_remote_nodes)) {
      92           0 :         return;
      93             :     }
      94           0 :     for (iter = host->details->running_rsc; iter != NULL; iter = iter->next) {
      95           0 :         pcmk_resource_t *rsc = (pcmk_resource_t *) iter->data;
      96             : 
      97           0 :         if (rsc->is_remote_node && (rsc->container != NULL)) {
      98           0 :             pcmk_node_t *guest_node = pcmk_find_node(scheduler, rsc->id);
      99             : 
     100           0 :             if (guest_node) {
     101           0 :                 (*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           0 : pe_create_remote_xml(xmlNode *parent, const char *uname,
     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           0 :     remote = pcmk__xe_create(parent, PCMK_XE_PRIMITIVE);
     134             : 
     135             :     // Add identity
     136           0 :     crm_xml_add(remote, PCMK_XA_ID, uname);
     137           0 :     crm_xml_add(remote, PCMK_XA_CLASS, PCMK_RESOURCE_CLASS_OCF);
     138           0 :     crm_xml_add(remote, PCMK_XA_PROVIDER, "pacemaker");
     139           0 :     crm_xml_add(remote, PCMK_XA_TYPE, "remote");
     140             : 
     141             :     // Add meta-attributes
     142           0 :     xml_sub = pcmk__xe_create(remote, PCMK_XE_META_ATTRIBUTES);
     143           0 :     crm_xml_set_id(xml_sub, "%s-%s", uname, PCMK_XE_META_ATTRIBUTES);
     144           0 :     crm_create_nvpair_xml(xml_sub, NULL,
     145             :                           PCMK__META_INTERNAL_RSC, PCMK_VALUE_TRUE);
     146           0 :     if (container_id) {
     147           0 :         crm_create_nvpair_xml(xml_sub, NULL,
     148             :                               PCMK__META_CONTAINER, container_id);
     149             :     }
     150           0 :     if (migrateable) {
     151           0 :         crm_create_nvpair_xml(xml_sub, NULL,
     152             :                               PCMK_META_ALLOW_MIGRATE, migrateable);
     153             :     }
     154           0 :     if (is_managed) {
     155           0 :         crm_create_nvpair_xml(xml_sub, NULL, PCMK_META_IS_MANAGED, is_managed);
     156             :     }
     157             : 
     158             :     // Add instance attributes
     159           0 :     if (port || server) {
     160           0 :         xml_sub = pcmk__xe_create(remote, PCMK_XE_INSTANCE_ATTRIBUTES);
     161           0 :         crm_xml_set_id(xml_sub, "%s-%s", uname, PCMK_XE_INSTANCE_ATTRIBUTES);
     162           0 :         if (server) {
     163           0 :             crm_create_nvpair_xml(xml_sub, NULL, PCMK_REMOTE_RA_ADDR, server);
     164             :         }
     165           0 :         if (port) {
     166           0 :             crm_create_nvpair_xml(xml_sub, NULL, PCMK_REMOTE_RA_PORT, port);
     167             :         }
     168             :     }
     169             : 
     170             :     // Add operations
     171           0 :     xml_sub = pcmk__xe_create(remote, PCMK_XE_OPERATIONS);
     172           0 :     crm_create_op_xml(xml_sub, uname, PCMK_ACTION_MONITOR, "30s", "30s");
     173           0 :     if (start_timeout) {
     174           0 :         crm_create_op_xml(xml_sub, uname, PCMK_ACTION_START, "0",
     175             :                           start_timeout);
     176             :     }
     177           0 :     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           0 : pe__add_param_check(const xmlNode *rsc_op, pcmk_resource_t *rsc,
     190             :                     pcmk_node_t *node, enum pcmk__check_parameters flag,
     191             :                     pcmk_scheduler_t *scheduler)
     192             : {
     193           0 :     struct check_op *check_op = NULL;
     194             : 
     195           0 :     CRM_CHECK(scheduler && rsc_op && rsc && node, return);
     196             : 
     197           0 :     check_op = pcmk__assert_alloc(1, sizeof(struct check_op));
     198             : 
     199           0 :     crm_trace("Deferring checks of %s until after allocation",
     200             :               pcmk__xe_id(rsc_op));
     201           0 :     check_op->rsc_op = rsc_op;
     202           0 :     check_op->rsc = rsc;
     203           0 :     check_op->node = node;
     204           0 :     check_op->check_type = flag;
     205           0 :     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           0 : pe__foreach_param_check(pcmk_scheduler_t *scheduler,
     217             :                        void (*cb)(pcmk_resource_t*, pcmk_node_t*,
     218             :                                   const xmlNode*, enum pcmk__check_parameters))
     219             : {
     220           0 :     CRM_CHECK(scheduler && cb, return);
     221             : 
     222           0 :     for (GList *item = scheduler->param_check;
     223           0 :          item != NULL; item = item->next) {
     224           0 :         struct check_op *check_op = item->data;
     225             : 
     226           0 :         cb(check_op->rsc, check_op->node, check_op->rsc_op,
     227             :            check_op->check_type);
     228             :     }
     229             : }
     230             : 
     231             : void
     232           0 : pe__free_param_checks(pcmk_scheduler_t *scheduler)
     233             : {
     234           0 :     if (scheduler && scheduler->param_check) {
     235           0 :         g_list_free_full(scheduler->param_check, free);
     236           0 :         scheduler->param_check = NULL;
     237             :     }
     238           0 : }

Generated by: LCOV version 1.14