pacemaker 3.0.1-16e74fc4da
Scalable High-Availability cluster resource manager
Loading...
Searching...
No Matches
ipc_schedulerd.c
Go to the documentation of this file.
1/*
2 * Copyright 2021-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
12#include <stdlib.h>
13#include <time.h>
14
15#include <crm/crm.h>
16#include <crm/common/xml.h>
17#include <crm/common/ipc.h>
20#include "crmcommon_private.h"
21
22typedef struct schedulerd_api_private_s {
23 char *client_uuid;
25
26// \return Standard Pacemaker return code
27static int
28new_data(pcmk_ipc_api_t *api)
29{
30 struct schedulerd_api_private_s *private = NULL;
31
32 api->api_data = calloc(1, sizeof(struct schedulerd_api_private_s));
33
34 if (api->api_data == NULL) {
35 return errno;
36 }
37
38 private = api->api_data;
39 /* See comments in ipc_pacemakerd.c. */
40 private->client_uuid = pcmk__getpid_s();
41
42 return pcmk_rc_ok;
43}
44
45static void
46free_data(void *data)
47{
48 free(((struct schedulerd_api_private_s *) data)->client_uuid);
49 free(data);
50}
51
52// \return Standard Pacemaker return code
53static int
54post_connect(pcmk_ipc_api_t *api)
55{
56 if (api->api_data == NULL) {
57 return EINVAL;
58 }
59
60 return pcmk_rc_ok;
61}
62
63static bool
64reply_expected(pcmk_ipc_api_t *api, const xmlNode *request)
65{
66 const char *command = crm_element_value(request, PCMK__XA_CRM_TASK);
67
68 if (command == NULL) {
69 return false;
70 }
71
72 // We only need to handle commands that functions in this file can send
73 return pcmk__str_any_of(command, CRM_OP_PECALC, NULL);
74}
75
76static bool
77dispatch(pcmk_ipc_api_t *api, xmlNode *reply)
78{
79 crm_exit_t status = CRM_EX_OK;
80 xmlNode *wrapper = NULL;
81 xmlNode *msg_data = NULL;
82 pcmk_schedulerd_api_reply_t reply_data = {
84 };
85 const char *value = NULL;
86
87 if (pcmk__xe_is(reply, PCMK__XE_ACK)) {
88 return false;
89 }
90
91 value = crm_element_value(reply, PCMK__XA_T);
93 crm_info("Unrecognizable message from schedulerd: "
94 "unexpected message type '%s'",
95 pcmk__s(value, ""));
96 status = CRM_EX_PROTOCOL;
97 goto done;
98 }
99
100 value = crm_element_value(reply, PCMK__XA_SUBT);
101 if (!pcmk__str_eq(value, PCMK__VALUE_RESPONSE, pcmk__str_none)) {
102 crm_info("Unrecognizable message from schedulerd: "
103 "message type '%s' not '" PCMK__VALUE_RESPONSE "'",
104 pcmk__s(value, ""));
105 status = CRM_EX_PROTOCOL;
106 goto done;
107 }
108
109 if (pcmk__str_empty(crm_element_value(reply, PCMK_XA_REFERENCE))) {
110 crm_info("Unrecognizable message from schedulerd: no reference");
111 status = CRM_EX_PROTOCOL;
112 goto done;
113 }
114
115 // Parse useful info from reply
116 wrapper = pcmk__xe_first_child(reply, PCMK__XE_CRM_XML, NULL, NULL);
117 msg_data = pcmk__xe_first_child(wrapper, NULL, NULL, NULL);
118
119 value = crm_element_value(reply, PCMK__XA_CRM_TASK);
120
121 if (pcmk__str_eq(value, CRM_OP_PECALC, pcmk__str_none)) {
123 reply_data.data.graph.reference = crm_element_value(reply,
125 reply_data.data.graph.input = crm_element_value(reply,
127 reply_data.data.graph.tgraph = msg_data;
128 } else {
129 crm_info("Unrecognizable message from schedulerd: "
130 "unknown command '%s'", pcmk__s(value, ""));
131 status = CRM_EX_PROTOCOL;
132 goto done;
133 }
134
135done:
136 pcmk__call_ipc_callback(api, pcmk_ipc_event_reply, status, &reply_data);
137 return false;
138}
139
142{
143 pcmk__ipc_methods_t *cmds = calloc(1, sizeof(pcmk__ipc_methods_t));
144
145 if (cmds != NULL) {
146 cmds->new_data = new_data;
147 cmds->free_data = free_data;
148 cmds->post_connect = post_connect;
149 cmds->reply_expected = reply_expected;
150 cmds->dispatch = dispatch;
151 }
152 return cmds;
153}
154
155static int
156do_schedulerd_api_call(pcmk_ipc_api_t *api, const char *task, xmlNode *cib, char **ref)
157{
159 xmlNode *cmd = NULL;
160 int rc;
161 char *sender_system = NULL;
162
163 if (!pcmk_ipc_is_connected(api)) {
164 return ENOTCONN;
165 }
166
167 private = api->api_data;
168 pcmk__assert(private != NULL);
169
170 sender_system = crm_strdup_printf("%s_%s", private->client_uuid,
171 pcmk__s(crm_system_name, "client"));
172 cmd = pcmk__new_request(pcmk_ipc_schedulerd, sender_system, NULL,
173 CRM_SYSTEM_PENGINE, task, cib);
174 free(sender_system);
175
176 if (cmd) {
177 rc = pcmk__send_ipc_request(api, cmd);
178 if (rc != pcmk_rc_ok) {
179 crm_debug("Couldn't send request to schedulerd: %s rc=%d",
180 pcmk_rc_str(rc), rc);
181 }
182
183 *ref = strdup(crm_element_value(cmd, PCMK_XA_REFERENCE));
184 pcmk__xml_free(cmd);
185 } else {
186 rc = ENOMSG;
187 }
188
189 return rc;
190}
191
192int
193pcmk_schedulerd_api_graph(pcmk_ipc_api_t *api, xmlNode *cib, char **ref)
194{
195 return do_schedulerd_api_call(api, CRM_OP_PECALC, cib, ref);
196}
char data[0]
Definition cpg.c:10
A dumping ground.
#define CRM_OP_PECALC
Definition crm.h:118
char * crm_system_name
Definition utils.c:45
#define CRM_SYSTEM_PENGINE
Definition crm.h:86
G_GNUC_INTERNAL int pcmk__send_ipc_request(pcmk_ipc_api_t *api, const xmlNode *request)
Definition ipc_client.c:684
G_GNUC_INTERNAL void pcmk__call_ipc_callback(pcmk_ipc_api_t *api, enum pcmk_ipc_event event_type, crm_exit_t status, void *event_data)
Definition ipc_client.c:144
IPC interface to Pacemaker daemons.
@ pcmk_ipc_event_reply
Daemon's reply to client IPC request.
Definition ipc.h:68
@ pcmk_ipc_schedulerd
Scheduler.
Definition ipc.h:56
bool pcmk_ipc_is_connected(pcmk_ipc_api_t *api)
Check whether an IPC API connection is active.
Definition ipc_client.c:271
int pcmk_schedulerd_api_graph(pcmk_ipc_api_t *api, xmlNode *cib, char **ref)
Make an IPC request to the scheduler for the transition graph.
struct schedulerd_api_private_s schedulerd_api_private_t
pcmk__ipc_methods_t * pcmk__schedulerd_api_methods(void)
IPC commands for Schedulerd.
@ pcmk_schedulerd_reply_graph
@ pcmk_schedulerd_reply_unknown
#define crm_info(fmt, args...)
Definition logging.h:365
#define crm_debug(fmt, args...)
Definition logging.h:368
#define pcmk__new_request(server, sender_system, recipient_node, recipient_system, task, data)
#define PCMK__VALUE_RESPONSE
const char * pcmk_rc_str(int rc)
Get a user-friendly description of a return code.
Definition results.c:617
@ CRM_EX_PROTOCOL
Protocol violated.
Definition results.h:259
@ CRM_EX_OK
Success.
Definition results.h:233
@ pcmk_rc_ok
Definition results.h:159
enum crm_exit_e crm_exit_t
Exit status codes for tools and daemons.
#define pcmk__assert(expr)
enum pcmk_ipc_server pcmk__parse_server(const char *text)
Definition servers.c:178
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
@ pcmk__str_none
bool pcmk__str_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
Definition strings.c:1053
int(* new_data)(pcmk_ipc_api_t *api)
bool(* reply_expected)(pcmk_ipc_api_t *api, const xmlNode *request)
void(* free_data)(void *api_data)
bool(* dispatch)(pcmk_ipc_api_t *api, xmlNode *msg)
int(* post_connect)(pcmk_ipc_api_t *api)
enum pcmk_schedulerd_api_reply reply_type
union pcmk_schedulerd_api_reply_t::@8 data
struct pcmk_schedulerd_api_reply_t::@8::@9 graph
Wrappers for and extensions to libxml2.
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
xmlNode * pcmk__xe_first_child(const xmlNode *parent, const char *node_name, const char *attr_n, const char *attr_v)
Definition xml_element.c:43
void pcmk__xml_free(xmlNode *xml)
Definition xml.c:816
#define PCMK_XA_REFERENCE
Definition xml_names.h:372
#define PCMK__XA_CRM_TASK
#define PCMK__XA_T
#define PCMK__XA_SUBT
#define PCMK__XE_ACK
#define PCMK__XA_CRM_TGRAPH_IN
#define PCMK__XE_CRM_XML