pacemaker  2.1.3-ea053b43a
Scalable High-Availability cluster resource manager
messages.c
Go to the documentation of this file.
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 Lesser General Public License
7  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
8  */
9 
10 #include <crm_internal.h>
11 
12 #include <stdio.h>
13 #include <sys/types.h>
14 
15 #include <glib.h>
16 #include <libxml/tree.h>
17 
18 #include <crm/msg_xml.h>
20 
39 xmlNode *
40 create_request_adv(const char *task, xmlNode * msg_data,
41  const char *host_to, const char *sys_to,
42  const char *sys_from, const char *uuid_from,
43  const char *origin)
44 {
45  static uint ref_counter = 0;
46 
47  char *true_from = NULL;
48  xmlNode *request = NULL;
49  char *reference = crm_strdup_printf("%s-%s-%lld-%u",
50  (task? task : "_empty_"),
51  (sys_from? sys_from : "_empty_"),
52  (long long) time(NULL), ref_counter++);
53 
54  if (uuid_from != NULL) {
55  true_from = crm_strdup_printf("%s_%s", uuid_from,
56  (sys_from? sys_from : "none"));
57  } else if (sys_from != NULL) {
58  true_from = strdup(sys_from);
59  } else {
60  crm_err("Cannot create IPC request: No originating system specified");
61  }
62 
63  // host_from will get set for us if necessary by the controller when routed
64  request = create_xml_node(NULL, __func__);
65  crm_xml_add(request, F_CRM_ORIGIN, origin);
66  crm_xml_add(request, F_TYPE, T_CRM);
69  crm_xml_add(request, F_CRM_REFERENCE, reference);
70  crm_xml_add(request, F_CRM_TASK, task);
71  crm_xml_add(request, F_CRM_SYS_TO, sys_to);
72  crm_xml_add(request, F_CRM_SYS_FROM, true_from);
73 
74  /* HOSTTO will be ignored if it is to the DC anyway. */
75  if (host_to != NULL && strlen(host_to) > 0) {
76  crm_xml_add(request, F_CRM_HOST_TO, host_to);
77  }
78 
79  if (msg_data != NULL) {
80  add_message_xml(request, F_CRM_DATA, msg_data);
81  }
82  free(reference);
83  free(true_from);
84 
85  return request;
86 }
87 
101 xmlNode *
102 create_reply_adv(xmlNode *original_request, xmlNode *xml_response_data,
103  const char *origin)
104 {
105  xmlNode *reply = NULL;
106 
107  const char *host_from = crm_element_value(original_request, F_CRM_HOST_FROM);
108  const char *sys_from = crm_element_value(original_request, F_CRM_SYS_FROM);
109  const char *sys_to = crm_element_value(original_request, F_CRM_SYS_TO);
110  const char *type = crm_element_value(original_request, F_CRM_MSG_TYPE);
111  const char *operation = crm_element_value(original_request, F_CRM_TASK);
112  const char *crm_msg_reference = crm_element_value(original_request, F_CRM_REFERENCE);
113 
114  if (type == NULL) {
115  crm_err("Cannot create new_message, no message type in original message");
116  CRM_ASSERT(type != NULL);
117  return NULL;
118 #if 0
119  } else if (strcasecmp(XML_ATTR_REQUEST, type) != 0) {
120  crm_err("Cannot create new_message, original message was not a request");
121  return NULL;
122 #endif
123  }
124  reply = create_xml_node(NULL, __func__);
125  if (reply == NULL) {
126  crm_err("Cannot create new_message, malloc failed");
127  return NULL;
128  }
129 
130  crm_xml_add(reply, F_CRM_ORIGIN, origin);
131  crm_xml_add(reply, F_TYPE, T_CRM);
134  crm_xml_add(reply, F_CRM_REFERENCE, crm_msg_reference);
135  crm_xml_add(reply, F_CRM_TASK, operation);
136 
137  /* since this is a reply, we reverse the from and to */
138  crm_xml_add(reply, F_CRM_SYS_TO, sys_from);
139  crm_xml_add(reply, F_CRM_SYS_FROM, sys_to);
140 
141  /* HOSTTO will be ignored if it is to the DC anyway. */
142  if (host_from != NULL && strlen(host_from) > 0) {
143  crm_xml_add(reply, F_CRM_HOST_TO, host_from);
144  }
145 
146  if (xml_response_data != NULL) {
147  add_message_xml(reply, F_CRM_DATA, xml_response_data);
148  }
149 
150  return reply;
151 }
152 
153 xmlNode *
154 get_message_xml(xmlNode *msg, const char *field)
155 {
156  xmlNode *tmp = first_named_child(msg, field);
157 
158  return pcmk__xml_first_child(tmp);
159 }
160 
161 gboolean
162 add_message_xml(xmlNode *msg, const char *field, xmlNode *xml)
163 {
164  xmlNode *holder = create_xml_node(msg, field);
165 
166  add_node_copy(holder, xml);
167  return TRUE;
168 }
169 
181 const char *
183 {
184  if (name == NULL) {
185  return "unknown";
186 
187  } else if (!strcmp(name, "pacemaker-attrd")) {
188  return "attrd";
189 
190  } else if (!strcmp(name, "pacemaker-based")) {
191  return CRM_SYSTEM_CIB;
192 
193  } else if (!strcmp(name, "pacemaker-controld")) {
194  return CRM_SYSTEM_CRMD;
195 
196  } else if (!strcmp(name, "pacemaker-execd")) {
197  return CRM_SYSTEM_LRMD;
198 
199  } else if (!strcmp(name, "pacemaker-fenced")) {
200  return "stonith-ng";
201 
202  } else if (!strcmp(name, "pacemaker-schedulerd")) {
203  return CRM_SYSTEM_PENGINE;
204 
205  } else {
206  return name;
207  }
208 }
209 
223 GHashTable *
225 {
226  GHashTable *commands = g_hash_table_new(g_str_hash, g_str_equal);
227 
228  if (handlers != NULL) {
229  int i;
230 
231  for (i = 0; handlers[i].command != NULL; ++i) {
232  g_hash_table_insert(commands, (gpointer) handlers[i].command,
233  handlers[i].handler);
234  }
235  if (handlers[i].handler != NULL) {
236  // g_str_hash() can't handle NULL, so use empty string for default
237  g_hash_table_insert(commands, (gpointer) "", handlers[i].handler);
238  }
239  }
240  return commands;
241 }
242 
252 xmlNode *
253 pcmk__process_request(pcmk__request_t *request, GHashTable *handlers)
254 {
255  xmlNode *(*handler)(pcmk__request_t *request) = NULL;
256 
257  CRM_CHECK((request != NULL) && (request->op != NULL) && (handlers != NULL),
258  return NULL);
259 
260  if (pcmk_is_set(request->flags, pcmk__request_sync)
261  && (request->ipc_client != NULL)) {
262  CRM_CHECK(request->ipc_client->request_id == request->ipc_id,
263  return NULL);
264  }
265 
266  handler = g_hash_table_lookup(handlers, request->op);
267  if (handler == NULL) {
268  handler = g_hash_table_lookup(handlers, ""); // Default handler
269  if (handler == NULL) {
270  crm_info("Ignoring %s request from %s %s with no handler",
271  request->op, pcmk__request_origin_type(request),
272  pcmk__request_origin(request));
273  return NULL;
274  }
275  }
276 
277  return (*handler)(request);
278 }
#define F_CRM_TASK
Definition: msg_xml.h:91
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:226
#define F_CRM_REFERENCE
Definition: msg_xml.h:97
gboolean add_message_xml(xmlNode *msg, const char *field, xmlNode *xml)
Definition: messages.c:162
#define F_TYPE
Definition: msg_xml.h:69
const char * pcmk__message_name(const char *name)
Get name to be used as identifier for cluster messages.
Definition: messages.c:182
#define F_CRM_HOST_TO
Definition: msg_xml.h:92
const char * name
Definition: cib.c:24
xmlNode * first_named_child(const xmlNode *parent, const char *name)
Definition: xml.c:2794
#define F_CRM_MSG_TYPE
Definition: msg_xml.h:93
#define CRM_FEATURE_SET
Definition: crm.h:69
#define F_CRM_HOST_FROM
Definition: msg_xml.h:96
#define T_CRM
Definition: msg_xml.h:81
xmlNode * create_reply_adv(xmlNode *original_request, xmlNode *xml_response_data, const char *origin)
Create a Pacemaker reply (for IPC or cluster layer)
Definition: messages.c:102
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.
Definition: nvpair.c:323
pcmk__client_t * ipc_client
enum crm_ais_msg_types type
Definition: cpg.c:48
#define XML_ATTR_REQUEST
Definition: msg_xml.h:154
#define F_CRM_SYS_TO
Definition: msg_xml.h:94
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: nvpair.c:529
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Definition: util.h:122
xmlNode * add_node_copy(xmlNode *new_parent, xmlNode *xml_node)
Definition: xml.c:674
#define CRM_SYSTEM_PENGINE
Definition: crm.h:108
xmlNode * create_xml_node(xmlNode *parent, const char *name)
Definition: xml.c:696
xmlNode * get_message_xml(xmlNode *msg, const char *field)
Definition: messages.c:154
xmlNode * create_request_adv(const char *task, xmlNode *msg_data, const char *host_to, const char *sys_to, const char *sys_from, const char *uuid_from, const char *origin)
Create a Pacemaker request (for IPC or cluster layer)
Definition: messages.c:40
#define CRM_SYSTEM_CRMD
Definition: crm.h:106
#define F_CRM_DATA
Definition: msg_xml.h:90
#define CRM_SYSTEM_CIB
Definition: crm.h:105
#define crm_err(fmt, args...)
Definition: logging.h:358
#define CRM_ASSERT(expr)
Definition: results.h:42
#define F_CRM_SYS_FROM
Definition: msg_xml.h:95
#define CRM_SYSTEM_LRMD
Definition: crm.h:107
#define XML_ATTR_RESPONSE
Definition: msg_xml.h:155
#define F_CRM_ORIGIN
Definition: msg_xml.h:99
xmlNode * pcmk__process_request(pcmk__request_t *request, GHashTable *handlers)
Definition: messages.c:253
#define crm_info(fmt, args...)
Definition: logging.h:361
#define F_CRM_VERSION
Definition: msg_xml.h:98
GHashTable * pcmk__register_handlers(pcmk__server_command_t *handlers)
Definition: messages.c:224