root/daemons/schedulerd/schedulerd_messages.c

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

DEFINITIONS

This source file includes following definitions.
  1. init_working_set
  2. handle_pecalc_op
  3. process_pe_message
  4. pe_ipc_accept
  5. pe_ipc_dispatch
  6. pe_ipc_closed
  7. pe_ipc_destroy

   1 /*
   2  * Copyright 2004-2022 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 <crm/msg_xml.h>
  13 #include <pacemaker-internal.h>
  14 
  15 #include <stdbool.h>
  16 #include <sys/stat.h>
  17 #include <sys/types.h>
  18 #include <unistd.h>
  19 
  20 #include "pacemaker-schedulerd.h"
  21 
  22 static pe_working_set_t *
  23 init_working_set(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  24 {
  25     pe_working_set_t *data_set = pe_new_working_set();
  26 
  27     CRM_ASSERT(data_set != NULL);
  28 
  29     crm_config_error = FALSE;
  30     crm_config_warning = FALSE;
  31 
  32     was_processing_error = FALSE;
  33     was_processing_warning = FALSE;
  34 
  35     data_set->priv = logger_out;
  36     return data_set;
  37 }
  38 
  39 static void
  40 handle_pecalc_op(xmlNode *msg, xmlNode *xml_data, pcmk__client_t *sender)
     /* [previous][next][first][last][top][bottom][index][help] */
  41 {
  42     static struct series_s {
  43         const char *name;
  44         const char *param;
  45 
  46         /* Maximum number of inputs of this kind to save to disk.
  47          * If -1, save all; if 0, save none.
  48          */
  49         int wrap;
  50     } series[] = {
  51         { "pe-error", "pe-error-series-max", -1 },
  52         { "pe-warn",  "pe-warn-series-max",  5000 },
  53         { "pe-input", "pe-input-series-max", 4000 },
  54     };
  55     static char *last_digest = NULL;
  56     static char *filename = NULL;
  57 
  58     unsigned int seq;
  59     int series_id = 0;
  60     int series_wrap = 0;
  61     char *digest = NULL;
  62     const char *value = NULL;
  63     time_t execution_date = time(NULL);
  64     xmlNode *converted = NULL;
  65     xmlNode *reply = NULL;
  66     bool is_repoke = false;
  67     bool process = true;
  68     pe_working_set_t *data_set = init_working_set();
  69 
  70     digest = calculate_xml_versioned_digest(xml_data, FALSE, FALSE,
  71                                             CRM_FEATURE_SET);
  72     converted = copy_xml(xml_data);
  73     if (!cli_config_update(&converted, NULL, TRUE)) {
  74         data_set->graph = create_xml_node(NULL, XML_TAG_GRAPH);
  75         crm_xml_add_int(data_set->graph, "transition_id", 0);
  76         crm_xml_add_int(data_set->graph, "cluster-delay", 0);
  77         process = false;
  78         free(digest);
  79 
  80     } else if (pcmk__str_eq(digest, last_digest, pcmk__str_casei)) {
  81         is_repoke = true;
  82         free(digest);
  83 
  84     } else {
  85         free(last_digest);
  86         last_digest = digest;
  87     }
  88 
  89     if (process) {
  90         pcmk__schedule_actions(converted,
  91                                pe_flag_no_counts
  92                                |pe_flag_no_compat
  93                                |pe_flag_show_utilization, data_set);
  94     }
  95 
  96     // Get appropriate index into series[] array
  97     if (was_processing_error) {
  98         series_id = 0;
  99     } else if (was_processing_warning) {
 100         series_id = 1;
 101     } else {
 102         series_id = 2;
 103     }
 104 
 105     value = pe_pref(data_set->config_hash, series[series_id].param);
 106     if ((value == NULL)
 107         || (pcmk__scan_min_int(value, &series_wrap, -1) != pcmk_rc_ok)) {
 108         series_wrap = series[series_id].wrap;
 109     }
 110 
 111     if (pcmk__read_series_sequence(PE_STATE_DIR, series[series_id].name,
 112                                    &seq) != pcmk_rc_ok) {
 113         // @TODO maybe handle errors better ...
 114         seq = 0;
 115     }
 116     crm_trace("Series %s: wrap=%d, seq=%u, pref=%s",
 117               series[series_id].name, series_wrap, seq, value);
 118 
 119     data_set->input = NULL;
 120     reply = create_reply(msg, data_set->graph);
 121     CRM_ASSERT(reply != NULL);
 122 
 123     if (series_wrap == 0) { // Don't save any inputs of this kind
 124         free(filename);
 125         filename = NULL;
 126 
 127     } else if (!is_repoke) { // Input changed, save to disk
 128         free(filename);
 129         filename = pcmk__series_filename(PE_STATE_DIR,
 130                                          series[series_id].name, seq, true);
 131     }
 132 
 133     crm_xml_add(reply, F_CRM_TGRAPH_INPUT, filename);
 134     crm_xml_add_int(reply, "graph-errors", was_processing_error);
 135     crm_xml_add_int(reply, "graph-warnings", was_processing_warning);
 136     crm_xml_add_int(reply, "config-errors", crm_config_error);
 137     crm_xml_add_int(reply, "config-warnings", crm_config_warning);
 138 
 139     if (pcmk__ipc_send_xml(sender, 0, reply,
 140                            crm_ipc_server_event) != pcmk_rc_ok) {
 141         int graph_file_fd = 0;
 142         char *graph_file = NULL;
 143         umask(S_IWGRP | S_IWOTH | S_IROTH);
 144 
 145         graph_file = crm_strdup_printf("%s/pengine.graph.XXXXXX",
 146                                        PE_STATE_DIR);
 147         graph_file_fd = mkstemp(graph_file);
 148 
 149         crm_err("Couldn't send transition graph to peer, writing to %s instead",
 150                 graph_file);
 151 
 152         crm_xml_add(reply, F_CRM_TGRAPH, graph_file);
 153         write_xml_fd(data_set->graph, graph_file, graph_file_fd, FALSE);
 154 
 155         free(graph_file);
 156         free_xml(first_named_child(reply, F_CRM_DATA));
 157         CRM_ASSERT(pcmk__ipc_send_xml(sender, 0, reply,
 158                                       crm_ipc_server_event) == pcmk_rc_ok);
 159     }
 160 
 161     free_xml(reply);
 162     pcmk__log_transition_summary(filename);
 163 
 164     if (series_wrap == 0) {
 165         crm_debug("Not saving input to disk (disabled by configuration)");
 166 
 167     } else if (is_repoke) {
 168         crm_info("Input has not changed since last time, not saving to disk");
 169 
 170     } else {
 171         unlink(filename);
 172         crm_xml_add_ll(xml_data, "execution-date", (long long) execution_date);
 173         write_xml_file(xml_data, filename, TRUE);
 174         pcmk__write_series_sequence(PE_STATE_DIR, series[series_id].name,
 175                                     ++seq, series_wrap);
 176     }
 177 
 178     free_xml(converted);
 179     pe_free_working_set(data_set);
 180 }
 181 
 182 static void
 183 process_pe_message(xmlNode *msg, xmlNode *xml_data, pcmk__client_t *sender)
     /* [previous][next][first][last][top][bottom][index][help] */
 184 {
 185     const char *sys_to = crm_element_value(msg, F_CRM_SYS_TO);
 186     const char *op = crm_element_value(msg, F_CRM_TASK);
 187     const char *ref = crm_element_value(msg, F_CRM_REFERENCE);
 188 
 189     crm_trace("Processing %s op (ref=%s)...", op, ref);
 190 
 191     if (op == NULL) {
 192         /* error */
 193 
 194     } else if (strcasecmp(op, CRM_OP_HELLO) == 0) {
 195         /* ignore */
 196 
 197     } else if (pcmk__str_eq(crm_element_value(msg, F_CRM_MSG_TYPE), XML_ATTR_RESPONSE, pcmk__str_casei)) {
 198         /* ignore */
 199 
 200     } else if (sys_to == NULL || strcasecmp(sys_to, CRM_SYSTEM_PENGINE) != 0) {
 201         crm_trace("Bad sys-to %s", crm_str(sys_to));
 202 
 203     } else if (strcasecmp(op, CRM_OP_PECALC) == 0) {
 204         handle_pecalc_op(msg, xml_data, sender);
 205     }
 206 }
 207 
 208 static int32_t
 209 pe_ipc_accept(qb_ipcs_connection_t * c, uid_t uid, gid_t gid)
     /* [previous][next][first][last][top][bottom][index][help] */
 210 {
 211     crm_trace("Connection %p", c);
 212     if (pcmk__new_client(c, uid, gid) == NULL) {
 213         return -EIO;
 214     }
 215     return 0;
 216 }
 217 
 218 static int32_t
 219 pe_ipc_dispatch(qb_ipcs_connection_t * qbc, void *data, size_t size)
     /* [previous][next][first][last][top][bottom][index][help] */
 220 {
 221     uint32_t id = 0;
 222     uint32_t flags = 0;
 223     pcmk__client_t *c = pcmk__find_client(qbc);
 224     xmlNode *msg = pcmk__client_data2xml(c, data, &id, &flags);
 225 
 226     pcmk__ipc_send_ack(c, id, flags, "ack", CRM_EX_INDETERMINATE);
 227     if (msg != NULL) {
 228         xmlNode *data_xml = get_message_xml(msg, F_CRM_DATA);
 229 
 230         process_pe_message(msg, data_xml, c);
 231         free_xml(msg);
 232     }
 233     return 0;
 234 }
 235 
 236 /* Error code means? */
 237 static int32_t
 238 pe_ipc_closed(qb_ipcs_connection_t * c)
     /* [previous][next][first][last][top][bottom][index][help] */
 239 {
 240     pcmk__client_t *client = pcmk__find_client(c);
 241 
 242     if (client == NULL) {
 243         return 0;
 244     }
 245     crm_trace("Connection %p", c);
 246     pcmk__free_client(client);
 247     return 0;
 248 }
 249 
 250 static void
 251 pe_ipc_destroy(qb_ipcs_connection_t * c)
     /* [previous][next][first][last][top][bottom][index][help] */
 252 {
 253     crm_trace("Connection %p", c);
 254     pe_ipc_closed(c);
 255 }
 256 
 257 struct qb_ipcs_service_handlers ipc_callbacks = {
 258     .connection_accept = pe_ipc_accept,
 259     .connection_created = NULL,
 260     .msg_process = pe_ipc_dispatch,
 261     .connection_closed = pe_ipc_closed,
 262     .connection_destroyed = pe_ipc_destroy
 263 };

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