root/daemons/controld/controld_based.c

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

DEFINITIONS

This source file includes following definitions.
  1. do_cib_updated
  2. do_cib_replaced
  3. do_cib_control
  4. crmd_cib_smart_opt
  5. controld_action_is_recordable
  6. cib_delete_callback
  7. controld_delete_node_state
  8. controld_delete_resource_history

   1 /*
   2  * Copyright 2004-2020 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 <unistd.h>  /* sleep */
  13 
  14 #include <crm/common/alerts_internal.h>
  15 #include <crm/common/xml.h>
  16 #include <crm/crm.h>
  17 #include <crm/msg_xml.h>
  18 
  19 #include <pacemaker-controld.h>
  20 
  21 int cib_retries = 0;
  22 
  23 void
  24 do_cib_updated(const char *event, xmlNode * msg)
     /* [previous][next][first][last][top][bottom][index][help] */
  25 {
  26     if (pcmk__alert_in_patchset(msg, TRUE)) {
  27         mainloop_set_trigger(config_read);
  28     }
  29 }
  30 
  31 void
  32 do_cib_replaced(const char *event, xmlNode * msg)
     /* [previous][next][first][last][top][bottom][index][help] */
  33 {
  34     crm_debug("Updating the CIB after a replace: DC=%s", pcmk__btoa(AM_I_DC));
  35     if (AM_I_DC == FALSE) {
  36         return;
  37 
  38     } else if ((fsa_state == S_FINALIZE_JOIN)
  39                && pcmk_is_set(fsa_input_register, R_CIB_ASKED)) {
  40         /* no need to restart the join - we asked for this replace op */
  41         return;
  42     }
  43 
  44     /* start the join process again so we get everyone's LRM status */
  45     populate_cib_nodes(node_update_quick|node_update_all, __func__);
  46     register_fsa_input(C_FSA_INTERNAL, I_ELECTION, NULL);
  47 }
  48 
  49 /* A_CIB_STOP, A_CIB_START, O_CIB_RESTART */
  50 void
  51 do_cib_control(long long action,
     /* [previous][next][first][last][top][bottom][index][help] */
  52                enum crmd_fsa_cause cause,
  53                enum crmd_fsa_state cur_state,
  54                enum crmd_fsa_input current_input, fsa_data_t * msg_data)
  55 {
  56     CRM_ASSERT(fsa_cib_conn != NULL);
  57 
  58     if (action & A_CIB_STOP) {
  59 
  60         if (fsa_cib_conn->state != cib_disconnected && last_resource_update != 0) {
  61             crm_info("Waiting for resource update %d to complete", last_resource_update);
  62             crmd_fsa_stall(FALSE);
  63             return;
  64         }
  65 
  66         crm_info("Disconnecting from the CIB manager");
  67         controld_clear_fsa_input_flags(R_CIB_CONNECTED);
  68 
  69         fsa_cib_conn->cmds->del_notify_callback(fsa_cib_conn, T_CIB_REPLACE_NOTIFY, do_cib_replaced);
  70         fsa_cib_conn->cmds->del_notify_callback(fsa_cib_conn, T_CIB_DIFF_NOTIFY, do_cib_updated);
  71 
  72         if (fsa_cib_conn->state != cib_disconnected) {
  73             /* Does not require a set_slave() reply to sign out from based. */
  74             fsa_cib_conn->cmds->set_slave(fsa_cib_conn, cib_scope_local | cib_discard_reply);
  75             fsa_cib_conn->cmds->signoff(fsa_cib_conn);
  76         }
  77         crm_notice("Disconnected from the CIB manager");
  78     }
  79 
  80     if (action & A_CIB_START) {
  81         int rc = pcmk_ok;
  82 
  83         if (cur_state == S_STOPPING) {
  84             crm_err("Ignoring request to connect to the CIB manager after shutdown");
  85             return;
  86         }
  87 
  88         rc = fsa_cib_conn->cmds->signon(fsa_cib_conn, CRM_SYSTEM_CRMD, cib_command_nonblocking);
  89 
  90         if (rc != pcmk_ok) {
  91             /* a short wait that usually avoids stalling the FSA */
  92             sleep(1);
  93             rc = fsa_cib_conn->cmds->signon(fsa_cib_conn, CRM_SYSTEM_CRMD, cib_command_nonblocking);
  94         }
  95 
  96         if (rc != pcmk_ok) {
  97             crm_info("Could not connect to the CIB manager: %s", pcmk_strerror(rc));
  98 
  99         } else if (pcmk_ok !=
 100                    fsa_cib_conn->cmds->set_connection_dnotify(fsa_cib_conn,
 101                                                               crmd_cib_connection_destroy)) {
 102             crm_err("Could not set dnotify callback");
 103 
 104         } else if (pcmk_ok !=
 105                    fsa_cib_conn->cmds->add_notify_callback(fsa_cib_conn, T_CIB_REPLACE_NOTIFY,
 106                                                            do_cib_replaced)) {
 107             crm_err("Could not set CIB notification callback (replace)");
 108 
 109         } else if (pcmk_ok !=
 110                    fsa_cib_conn->cmds->add_notify_callback(fsa_cib_conn, T_CIB_DIFF_NOTIFY,
 111                                                            do_cib_updated)) {
 112             crm_err("Could not set CIB notification callback (update)");
 113 
 114         } else {
 115             controld_set_fsa_input_flags(R_CIB_CONNECTED);
 116             cib_retries = 0;
 117         }
 118 
 119         if (!pcmk_is_set(fsa_input_register, R_CIB_CONNECTED)) {
 120 
 121             cib_retries++;
 122             crm_warn("Couldn't complete CIB registration %d"
 123                      " times... pause and retry", cib_retries);
 124 
 125             if (cib_retries < 30) {
 126                 controld_start_timer(wait_timer);
 127                 crmd_fsa_stall(FALSE);
 128 
 129             } else {
 130                 crm_err("Could not complete CIB"
 131                         " registration  %d times..." " hard error", cib_retries);
 132                 register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL);
 133             }
 134         }
 135     }
 136 }
 137 
 138 /*!
 139  * \internal
 140  * \brief Get CIB call options to use local scope if master unavailable
 141  *
 142  * \return CIB call options
 143  */
 144 int crmd_cib_smart_opt()
     /* [previous][next][first][last][top][bottom][index][help] */
 145 {
 146     int call_opt = cib_quorum_override;
 147 
 148     if (fsa_state == S_ELECTION || fsa_state == S_PENDING) {
 149         crm_info("Sending update to local CIB in state: %s", fsa_state2string(fsa_state));
 150         cib__set_call_options(call_opt, "update", cib_scope_local);
 151     }
 152     return call_opt;
 153 }
 154 
 155 /*!
 156  * \internal
 157  * \brief Check whether an action type should be recorded in the CIB
 158  *
 159  * \param[in] action  Action type
 160  *
 161  * \return TRUE if action should be recorded, FALSE otherwise
 162  */
 163 bool
 164 controld_action_is_recordable(const char *action)
     /* [previous][next][first][last][top][bottom][index][help] */
 165 {
 166     return !pcmk__strcase_any_of(action, CRMD_ACTION_CANCEL, CRMD_ACTION_DELETE,
 167                             CRMD_ACTION_NOTIFY, CRMD_ACTION_METADATA, NULL);
 168 }
 169 
 170 static void
 171 cib_delete_callback(xmlNode *msg, int call_id, int rc, xmlNode *output,
     /* [previous][next][first][last][top][bottom][index][help] */
 172                     void *user_data)
 173 {
 174     char *desc = user_data;
 175 
 176     if (rc == 0) {
 177         crm_debug("Deletion of %s (via CIB call %d) succeeded", desc, call_id);
 178     } else {
 179         crm_warn("Deletion of %s (via CIB call %d) failed: %s " CRM_XS " rc=%d",
 180                  desc, call_id, pcmk_strerror(rc), rc);
 181     }
 182 }
 183 
 184 // Searches for various portions of node_state to delete
 185 
 186 // Match a particular node's node_state (takes node name 1x)
 187 #define XPATH_NODE_STATE        "//" XML_CIB_TAG_STATE "[@" XML_ATTR_UNAME "='%s']"
 188 
 189 // Node's lrm section (name 1x)
 190 #define XPATH_NODE_LRM          XPATH_NODE_STATE "/" XML_CIB_TAG_LRM
 191 
 192 // Node's lrm_rsc_op entries and lrm_resource entries without lock (name 2x)
 193 #define XPATH_NODE_LRM_UNLOCKED XPATH_NODE_STATE "//" XML_LRM_TAG_RSC_OP    \
 194                                 "|" XPATH_NODE_STATE                        \
 195                                 "//" XML_LRM_TAG_RESOURCE                   \
 196                                 "[not(@" XML_CONFIG_ATTR_SHUTDOWN_LOCK ")]"
 197 
 198 // Node's transient_attributes section (name 1x)
 199 #define XPATH_NODE_ATTRS        XPATH_NODE_STATE "/" XML_TAG_TRANSIENT_NODEATTRS
 200 
 201 // Everything under node_state (name 1x)
 202 #define XPATH_NODE_ALL          XPATH_NODE_STATE "/*"
 203 
 204 // Unlocked history + transient attributes (name 3x)
 205 #define XPATH_NODE_ALL_UNLOCKED XPATH_NODE_LRM_UNLOCKED "|" XPATH_NODE_ATTRS
 206 
 207 /*!
 208  * \internal
 209  * \brief Delete subsection of a node's CIB node_state
 210  *
 211  * \param[in] uname    Desired node
 212  * \param[in] section  Subsection of node_state to delete
 213  * \param[in] options  CIB call options to use
 214  */
 215 void
 216 controld_delete_node_state(const char *uname, enum controld_section_e section,
     /* [previous][next][first][last][top][bottom][index][help] */
 217                            int options)
 218 {
 219     char *xpath = NULL;
 220     char *desc = NULL;
 221 
 222     CRM_CHECK(uname != NULL, return);
 223     switch (section) {
 224         case controld_section_lrm:
 225             xpath = crm_strdup_printf(XPATH_NODE_LRM, uname);
 226             desc = crm_strdup_printf("resource history for node %s", uname);
 227             break;
 228         case controld_section_lrm_unlocked:
 229             xpath = crm_strdup_printf(XPATH_NODE_LRM_UNLOCKED, uname, uname);
 230             desc = crm_strdup_printf("resource history (other than shutdown "
 231                                      "locks) for node %s", uname);
 232             break;
 233         case controld_section_attrs:
 234             xpath = crm_strdup_printf(XPATH_NODE_ATTRS, uname);
 235             desc = crm_strdup_printf("transient attributes for node %s", uname);
 236             break;
 237         case controld_section_all:
 238             xpath = crm_strdup_printf(XPATH_NODE_ALL, uname);
 239             desc = crm_strdup_printf("all state for node %s", uname);
 240             break;
 241         case controld_section_all_unlocked:
 242             xpath = crm_strdup_printf(XPATH_NODE_ALL_UNLOCKED,
 243                                       uname, uname, uname);
 244             desc = crm_strdup_printf("all state (other than shutdown locks) "
 245                                      "for node %s", uname);
 246             break;
 247     }
 248 
 249     if (fsa_cib_conn == NULL) {
 250         crm_warn("Unable to delete %s: no CIB connection", desc);
 251         free(desc);
 252     } else {
 253         int call_id;
 254 
 255         cib__set_call_options(options, "node state deletion",
 256                               cib_quorum_override|cib_xpath|cib_multiple);
 257         call_id = fsa_cib_conn->cmds->remove(fsa_cib_conn, xpath, NULL, options);
 258         crm_info("Deleting %s (via CIB call %d) " CRM_XS " xpath=%s",
 259                  desc, call_id, xpath);
 260         fsa_register_cib_callback(call_id, FALSE, desc, cib_delete_callback);
 261         // CIB library handles freeing desc
 262     }
 263     free(xpath);
 264 }
 265 
 266 // Takes node name and resource ID
 267 #define XPATH_RESOURCE_HISTORY "//" XML_CIB_TAG_STATE                       \
 268                                "[@" XML_ATTR_UNAME "='%s']/"                \
 269                                XML_CIB_TAG_LRM "/" XML_LRM_TAG_RESOURCES    \
 270                                "/" XML_LRM_TAG_RESOURCE                     \
 271                                "[@" XML_ATTR_ID "='%s']"
 272 // @TODO could add "and @XML_CONFIG_ATTR_SHUTDOWN_LOCK" to limit to locks
 273 
 274 /*!
 275  * \internal
 276  * \brief Clear resource history from CIB for a given resource and node
 277  *
 278  * \param[in]  rsc_id        ID of resource to be cleared
 279  * \param[in]  node          Node whose resource history should be cleared
 280  * \param[in]  user_name     ACL user name to use
 281  * \param[in]  call_options  CIB call options
 282  *
 283  * \return Standard Pacemaker return code
 284  */
 285 int
 286 controld_delete_resource_history(const char *rsc_id, const char *node,
     /* [previous][next][first][last][top][bottom][index][help] */
 287                                  const char *user_name, int call_options)
 288 {
 289     char *desc = NULL;
 290     char *xpath = NULL;
 291     int rc = pcmk_rc_ok;
 292 
 293     CRM_CHECK((rsc_id != NULL) && (node != NULL), return EINVAL);
 294 
 295     desc = crm_strdup_printf("resource history for %s on %s", rsc_id, node);
 296     if (fsa_cib_conn == NULL) {
 297         crm_err("Unable to clear %s: no CIB connection", desc);
 298         free(desc);
 299         return ENOTCONN;
 300     }
 301 
 302     // Ask CIB to delete the entry
 303     xpath = crm_strdup_printf(XPATH_RESOURCE_HISTORY, node, rsc_id);
 304     rc = cib_internal_op(fsa_cib_conn, CIB_OP_DELETE, NULL, xpath, NULL,
 305                          NULL, call_options|cib_xpath, user_name);
 306 
 307     if (rc < 0) {
 308         rc = pcmk_legacy2rc(rc);
 309         crm_err("Could not delete resource status of %s on %s%s%s: %s "
 310                 CRM_XS " rc=%d", rsc_id, node,
 311                 (user_name? " for user " : ""), (user_name? user_name : ""),
 312                 pcmk_rc_str(rc), rc);
 313         free(desc);
 314         free(xpath);
 315         return rc;
 316     }
 317 
 318     if (pcmk_is_set(call_options, cib_sync_call)) {
 319         if (pcmk_is_set(call_options, cib_dryrun)) {
 320             crm_debug("Deletion of %s would succeed", desc);
 321         } else {
 322             crm_debug("Deletion of %s succeeded", desc);
 323         }
 324         free(desc);
 325 
 326     } else {
 327         crm_info("Clearing %s (via CIB call %d) " CRM_XS " xpath=%s",
 328                  desc, rc, xpath);
 329         fsa_register_cib_callback(rc, FALSE, desc, cib_delete_callback);
 330         // CIB library handles freeing desc
 331     }
 332 
 333     free(xpath);
 334     return pcmk_rc_ok;
 335 }

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