pacemaker 2.1.8-2.1.8
Scalable High-Availability cluster resource manager
Loading...
Searching...
No Matches
upstart.c
Go to the documentation of this file.
1/*
2 * Original copyright 2010 Senko Rasic <senko.rasic@dobarkod.hr>
3 * and Ante Karamatic <ivoks@init.hr>
4 * Later changes copyright 2012-2024 the Pacemaker project contributors
5 *
6 * The version control history for this file may have further details.
7 *
8 * This source code is licensed under the GNU Lesser General Public License
9 * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
10 */
11
12#include <crm_internal.h>
13
14#include <stdio.h>
15
16#include <crm/crm.h>
17#include <crm/common/xml.h>
18#include <crm/services.h>
19#include <crm/common/mainloop.h>
20
21#include <services_private.h>
22#include <upstart.h>
23#include <dbus/dbus.h>
24#include <pcmk-dbus.h>
25
26#include <glib.h>
27#include <gio/gio.h>
28
29#define BUS_NAME "com.ubuntu.Upstart"
30#define BUS_PATH "/com/ubuntu/Upstart"
31
32#define UPSTART_06_API BUS_NAME"0_6"
33#define UPSTART_JOB_IFACE UPSTART_06_API".Job"
34#define BUS_PROPERTY_IFACE "org.freedesktop.DBus.Properties"
35
36/*
37 http://upstart.ubuntu.com/wiki/DBusInterface
38*/
39static DBusConnection *upstart_proxy = NULL;
40
49int
51{
52 op->opaque->exec = strdup("upstart-dbus");
53 if (op->opaque->exec == NULL) {
54 return ENOMEM;
55 }
56 return pcmk_rc_ok;
57}
58
67enum ocf_exitcode
68services__upstart2ocf(int exit_status)
69{
70 // This library uses OCF codes for Upstart actions
71 return (enum ocf_exitcode) exit_status;
72}
73
74static gboolean
75upstart_init(void)
76{
77 static int need_init = 1;
78
79 if (need_init) {
80 need_init = 0;
81 upstart_proxy = pcmk_dbus_connect();
82 }
83 if (upstart_proxy == NULL) {
84 return FALSE;
85 }
86 return TRUE;
87}
88
89void
91{
92 if (upstart_proxy) {
93 pcmk_dbus_disconnect(upstart_proxy);
94 upstart_proxy = NULL;
95 }
96}
97
109static bool
110object_path_for_job(const gchar *arg_name, char **path, int timeout)
111{
112 /*
113 com.ubuntu.Upstart0_6.GetJobByName (in String name, out ObjectPath job)
114 */
115 DBusError error;
116 DBusMessage *msg;
117 DBusMessage *reply = NULL;
118 bool rc = false;
119
120 if (path != NULL) {
121 *path = NULL;
122 }
123
124 if (!upstart_init()) {
125 return false;
126 }
127 msg = dbus_message_new_method_call(BUS_NAME, // target for the method call
128 BUS_PATH, // object to call on
129 UPSTART_06_API, // interface to call on
130 "GetJobByName"); // method name
131
132 dbus_error_init(&error);
133 CRM_LOG_ASSERT(dbus_message_append_args(msg, DBUS_TYPE_STRING, &arg_name,
134 DBUS_TYPE_INVALID));
135 reply = pcmk_dbus_send_recv(msg, upstart_proxy, &error, timeout);
136 dbus_message_unref(msg);
137
138 if (dbus_error_is_set(&error)) {
139 crm_err("Could not get DBus object path for %s: %s",
140 arg_name, error.message);
141 dbus_error_free(&error);
142
143 } else if (!pcmk_dbus_type_check(reply, NULL, DBUS_TYPE_OBJECT_PATH,
144 __func__, __LINE__)) {
145 crm_err("Could not get DBus object path for %s: Invalid return type",
146 arg_name);
147
148 } else {
149 if (path != NULL) {
150 dbus_message_get_args(reply, NULL, DBUS_TYPE_OBJECT_PATH, path,
151 DBUS_TYPE_INVALID);
152 if (*path != NULL) {
153 *path = strdup(*path);
154 }
155 }
156 rc = true;
157 }
158
159 if (reply != NULL) {
160 dbus_message_unref(reply);
161 }
162 return rc;
163}
164
165static void
166fix(char *input, const char *search, char replace)
167{
168 char *match = NULL;
169 int shuffle = strlen(search) - 1;
170
171 while (TRUE) {
172 int len, lpc;
173
174 match = strstr(input, search);
175 if (match == NULL) {
176 break;
177 }
178 crm_trace("Found: %s", match);
179 match[0] = replace;
180 len = strlen(match) - shuffle;
181 for (lpc = 1; lpc <= len; lpc++) {
182 match[lpc] = match[lpc + shuffle];
183 }
184 }
185}
186
187static char *
188fix_upstart_name(const char *input)
189{
190 char *output = strdup(input);
191
192 fix(output, "_2b", '+');
193 fix(output, "_2c", ',');
194 fix(output, "_2d", '-');
195 fix(output, "_2e", '.');
196 fix(output, "_40", '@');
197 fix(output, "_5f", '_');
198 return output;
199}
200
201GList *
203{
204 GList *units = NULL;
205 DBusMessageIter args;
206 DBusMessageIter unit;
207 DBusMessage *msg = NULL;
208 DBusMessage *reply = NULL;
209 const char *method = "GetAllJobs";
210 DBusError error;
211 int lpc = 0;
212
213 if (upstart_init() == FALSE) {
214 return NULL;
215 }
216
217/*
218 com.ubuntu.Upstart0_6.GetAllJobs (out <Array of ObjectPath> jobs)
219*/
220
221 dbus_error_init(&error);
222 msg = dbus_message_new_method_call(BUS_NAME, // target for the method call
223 BUS_PATH, // object to call on
224 UPSTART_06_API, // interface to call on
225 method); // method name
226 CRM_ASSERT(msg != NULL);
227
228 reply = pcmk_dbus_send_recv(msg, upstart_proxy, &error, DBUS_TIMEOUT_USE_DEFAULT);
229 dbus_message_unref(msg);
230
231 if (dbus_error_is_set(&error)) {
232 crm_err("Call to %s failed: %s", method, error.message);
233 dbus_error_free(&error);
234 return NULL;
235
236 } else if (!dbus_message_iter_init(reply, &args)) {
237 crm_err("Call to %s failed: Message has no arguments", method);
238 dbus_message_unref(reply);
239 return NULL;
240 }
241
242 if(!pcmk_dbus_type_check(reply, &args, DBUS_TYPE_ARRAY, __func__, __LINE__)) {
243 crm_err("Call to %s failed: Message has invalid arguments", method);
244 dbus_message_unref(reply);
245 return NULL;
246 }
247
248 dbus_message_iter_recurse(&args, &unit);
249 while (dbus_message_iter_get_arg_type (&unit) != DBUS_TYPE_INVALID) {
250 DBusBasicValue value;
251 const char *job = NULL;
252 char *path = NULL;
253
254 if(!pcmk_dbus_type_check(reply, &unit, DBUS_TYPE_OBJECT_PATH, __func__, __LINE__)) {
255 crm_warn("Skipping Upstart reply argument with unexpected type");
256 continue;
257 }
258
259 dbus_message_iter_get_basic(&unit, &value);
260
261 if(value.str) {
262 int llpc = 0;
263 path = value.str;
264 job = value.str;
265 while (path[llpc] != 0) {
266 if (path[llpc] == '/') {
267 job = path + llpc + 1;
268 }
269 llpc++;
270 }
271 lpc++;
272 crm_trace("%s -> %s", path, job);
273 units = g_list_append(units, fix_upstart_name(job));
274 }
275 dbus_message_iter_next (&unit);
276 }
277
278 dbus_message_unref(reply);
279 crm_trace("Found %d upstart jobs", lpc);
280 return units;
281}
282
283gboolean
285{
286 return object_path_for_job(name, NULL, DBUS_TIMEOUT_USE_DEFAULT);
287}
288
289static char *
290get_first_instance(const gchar * job, int timeout)
291{
292 char *instance = NULL;
293 const char *method = "GetAllInstances";
294 DBusError error;
295 DBusMessage *msg;
296 DBusMessage *reply;
297 DBusMessageIter args;
298 DBusMessageIter unit;
299
300 dbus_error_init(&error);
301 msg = dbus_message_new_method_call(BUS_NAME, // target for the method call
302 job, // object to call on
303 UPSTART_JOB_IFACE, // interface to call on
304 method); // method name
305 CRM_ASSERT(msg != NULL);
306
307 dbus_message_append_args(msg, DBUS_TYPE_INVALID);
308 reply = pcmk_dbus_send_recv(msg, upstart_proxy, &error, timeout);
309 dbus_message_unref(msg);
310
311 if (dbus_error_is_set(&error)) {
312 crm_info("Call to %s failed: %s", method, error.message);
313 dbus_error_free(&error);
314 goto done;
315
316 } else if(reply == NULL) {
317 crm_info("Call to %s failed: no reply", method);
318 goto done;
319
320 } else if (!dbus_message_iter_init(reply, &args)) {
321 crm_info("Call to %s failed: Message has no arguments", method);
322 goto done;
323 }
324
325 if(!pcmk_dbus_type_check(reply, &args, DBUS_TYPE_ARRAY, __func__, __LINE__)) {
326 crm_info("Call to %s failed: Message has invalid arguments", method);
327 goto done;
328 }
329
330 dbus_message_iter_recurse(&args, &unit);
331 if(pcmk_dbus_type_check(reply, &unit, DBUS_TYPE_OBJECT_PATH, __func__, __LINE__)) {
332 DBusBasicValue value;
333
334 dbus_message_iter_get_basic(&unit, &value);
335
336 if(value.str) {
337 instance = strdup(value.str);
338 crm_trace("Result: %s", instance);
339 }
340 }
341
342 done:
343 if(reply) {
344 dbus_message_unref(reply);
345 }
346 return instance;
347}
348
357static void
358parse_status_result(const char *name, const char *state, void *userdata)
359{
360 svc_action_t *op = userdata;
361
362 if (pcmk__str_eq(state, "running", pcmk__str_none)) {
364 } else {
366 }
367
368 if (!(op->synchronous)) {
369 services_set_op_pending(op, NULL);
371 }
372}
373
374// @TODO Use XML string constants and maybe a real XML object
375#define METADATA_FORMAT \
376 "<?xml " PCMK_XA_VERSION "=\"1.0\"?>\n" \
377 "<" PCMK_XE_RESOURCE_AGENT " " \
378 PCMK_XA_NAME "=\"%s\" " \
379 PCMK_XA_VERSION "=\"" PCMK_DEFAULT_AGENT_VERSION "\">\n" \
380 " <" PCMK_XE_VERSION ">1.1</" PCMK_XE_VERSION ">\n" \
381 " <" PCMK_XE_LONGDESC " " PCMK_XA_LANG "=\"" PCMK__VALUE_EN "\">\n" \
382 " Upstart agent for controlling the system %s service\n" \
383 " </" PCMK_XE_LONGDESC ">\n" \
384 " <" PCMK_XE_SHORTDESC " " PCMK_XA_LANG "=\"" PCMK__VALUE_EN "\">" \
385 "Upstart job for %s" \
386 "</" PCMK_XE_SHORTDESC ">\n" \
387 " <" PCMK_XE_PARAMETERS "/>\n" \
388 " <" PCMK_XE_ACTIONS ">\n" \
389 " <" PCMK_XE_ACTION " " PCMK_XA_NAME "=\"" PCMK_ACTION_START "\"" \
390 " " PCMK_META_TIMEOUT "=\"15s\" />\n" \
391 " <" PCMK_XE_ACTION " " PCMK_XA_NAME "=\"" PCMK_ACTION_STOP "\"" \
392 " " PCMK_META_TIMEOUT "=\"15s\" />\n" \
393 " <" PCMK_XE_ACTION " " PCMK_XA_NAME "=\"" PCMK_ACTION_STATUS "\"" \
394 " " PCMK_META_TIMEOUT "=\"15s\" />\n" \
395 " <" PCMK_XE_ACTION " " PCMK_XA_NAME "=\"restart\"" \
396 " " PCMK_META_TIMEOUT "=\"15s\" />\n" \
397 " <" PCMK_XE_ACTION " " PCMK_XA_NAME "=\"" PCMK_ACTION_MONITOR "\"" \
398 " " PCMK_META_TIMEOUT "=\"15s\"" \
399 " " PCMK_META_INTERVAL "=\"15s\"" \
400 " " PCMK_META_START_DELAY "=\"15s\" />\n" \
401 " <" PCMK_XE_ACTION " " PCMK_XA_NAME "=\"" PCMK_ACTION_META_DATA "\"" \
402 " " PCMK_META_TIMEOUT "=\"5s\" />\n" \
403 " </" PCMK_XE_ACTIONS ">\n" \
404 " <" PCMK_XE_SPECIAL " " PCMK_XA_TAG "=\"upstart\"/>\n" \
405 "</" PCMK_XE_RESOURCE_AGENT ">\n"
406
407static char *
408upstart_job_metadata(const char *name)
409{
411}
412
420static void
421set_result_from_method_error(svc_action_t *op, const DBusError *error)
422{
424 "Unable to invoke Upstart DBus method");
425
426 if (strstr(error->name, UPSTART_06_API ".Error.UnknownInstance")) {
427
428 if (pcmk__str_eq(op->action, PCMK_ACTION_STOP, pcmk__str_casei)) {
429 crm_trace("Masking stop failure (%s) for %s "
430 "because unknown service can be considered stopped",
431 error->name, pcmk__s(op->rsc, "unknown resource"));
433 return;
434 }
435
437 PCMK_EXEC_NOT_INSTALLED, "Upstart job not found");
438
439 } else if (pcmk__str_eq(op->action, PCMK_ACTION_START, pcmk__str_casei)
440 && strstr(error->name, UPSTART_06_API ".Error.AlreadyStarted")) {
441 crm_trace("Masking start failure (%s) for %s "
442 "because already started resource is OK",
443 error->name, pcmk__s(op->rsc, "unknown resource"));
445 return;
446 }
447
448 crm_info("DBus request for %s of Upstart job %s for resource %s failed: %s",
449 op->action, op->agent, pcmk__s(op->rsc, "with unknown name"),
450 error->message);
451}
452
460static void
461job_method_complete(DBusPendingCall *pending, void *user_data)
462{
463 DBusError error;
464 DBusMessage *reply = NULL;
465 svc_action_t *op = user_data;
466
467 // Grab the reply
468 if (pending != NULL) {
469 reply = dbus_pending_call_steal_reply(pending);
470 }
471
472 // Determine result
473 dbus_error_init(&error);
474 if (pcmk_dbus_find_error(pending, reply, &error)) {
475 set_result_from_method_error(op, &error);
476 dbus_error_free(&error);
477
478 } else if (pcmk__str_eq(op->action, PCMK_ACTION_STOP, pcmk__str_none)) {
479 // Call has no return value
480 crm_debug("DBus request for stop of %s succeeded",
481 pcmk__s(op->rsc, "unknown resource"));
483
484 } else if (!pcmk_dbus_type_check(reply, NULL, DBUS_TYPE_OBJECT_PATH,
485 __func__, __LINE__)) {
486 crm_info("DBus request for %s of %s succeeded but "
487 "return type was unexpected", op->action,
488 pcmk__s(op->rsc, "unknown resource"));
490
491 } else {
492 const char *path = NULL;
493
494 dbus_message_get_args(reply, NULL, DBUS_TYPE_OBJECT_PATH, &path,
495 DBUS_TYPE_INVALID);
496 crm_debug("DBus request for %s of %s using %s succeeded",
497 op->action, pcmk__s(op->rsc, "unknown resource"), path);
499 }
500
501 // The call is no longer pending
502 CRM_LOG_ASSERT(pending == op->opaque->pending);
503 services_set_op_pending(op, NULL);
504
505 // Finalize action
507 if (reply != NULL) {
508 dbus_message_unref(reply);
509 }
510}
511
528int
530{
531 char *job = NULL;
532 int arg_wait = TRUE;
533 const char *arg_env = "pacemaker=1";
534 const char *action = op->action;
535
536 DBusError error;
537 DBusMessage *msg = NULL;
538 DBusMessage *reply = NULL;
539 DBusMessageIter iter, array_iter;
540
541 CRM_ASSERT(op != NULL);
542
543 if ((op->action == NULL) || (op->agent == NULL)) {
545 "Bug in action caller");
546 goto cleanup;
547 }
548
549 if (!upstart_init()) {
551 "No DBus connection");
552 goto cleanup;
553 }
554
555 if (pcmk__str_eq(op->action, PCMK_ACTION_META_DATA, pcmk__str_casei)) {
556 op->stdout_data = upstart_job_metadata(op->agent);
558 goto cleanup;
559 }
560
561 if (!object_path_for_job(op->agent, &job, op->timeout)) {
562 if (pcmk__str_eq(action, PCMK_ACTION_STOP, pcmk__str_none)) {
564 } else {
567 "Upstart job not found");
568 }
569 goto cleanup;
570 }
571
572 if (job == NULL) {
573 // Shouldn't normally be possible -- maybe a memory error
576 goto cleanup;
577 }
578
580 PCMK_ACTION_STATUS, NULL)) {
581 DBusPendingCall *pending = NULL;
582 char *state = NULL;
583 char *path = get_first_instance(job, op->timeout);
584
586 "No Upstart job instances found");
587 if (path == NULL) {
588 goto cleanup;
589 }
590 state = pcmk_dbus_get_property(upstart_proxy, BUS_NAME, path,
591 UPSTART_06_API ".Instance", "state",
592 op->synchronous? NULL : parse_status_result,
593 op,
594 op->synchronous? NULL : &pending,
595 op->timeout);
596 free(path);
597
598 if (op->synchronous) {
599 parse_status_result("state", state, op);
600 free(state);
601
602 } else if (pending == NULL) {
604 "Could not get job state from DBus");
605
606 } else { // Successfully initiated async op
607 free(job);
608 services_set_op_pending(op, pending);
610 return pcmk_rc_ok;
611 }
612
613 goto cleanup;
614
615 } else if (pcmk__str_eq(action, PCMK_ACTION_START, pcmk__str_none)) {
616 action = "Start";
617
618 } else if (pcmk__str_eq(action, PCMK_ACTION_STOP, pcmk__str_none)) {
619 action = "Stop";
620
621 } else if (pcmk__str_eq(action, "restart", pcmk__str_none)) {
622 action = "Restart";
623
624 } else {
627 "Action not implemented for Upstart resources");
628 goto cleanup;
629 }
630
631 // Initialize rc/status in case called functions don't set them
633 "Bug in service library");
634
635 crm_debug("Calling %s for %s on %s",
636 action, pcmk__s(op->rsc, "unknown resource"), job);
637
638 msg = dbus_message_new_method_call(BUS_NAME, // target for the method call
639 job, // object to call on
640 UPSTART_JOB_IFACE, // interface to call on
641 action); // method name
642 CRM_ASSERT(msg != NULL);
643
644 dbus_message_iter_init_append (msg, &iter);
645 CRM_LOG_ASSERT(dbus_message_iter_open_container(&iter,
646 DBUS_TYPE_ARRAY,
647 DBUS_TYPE_STRING_AS_STRING,
648 &array_iter));
649 CRM_LOG_ASSERT(dbus_message_iter_append_basic(&array_iter,
650 DBUS_TYPE_STRING, &arg_env));
651 CRM_LOG_ASSERT(dbus_message_iter_close_container(&iter, &array_iter));
652 CRM_LOG_ASSERT(dbus_message_append_args(msg, DBUS_TYPE_BOOLEAN, &arg_wait,
653 DBUS_TYPE_INVALID));
654
655 if (!(op->synchronous)) {
656 DBusPendingCall *pending = pcmk_dbus_send(msg, upstart_proxy,
657 job_method_complete, op,
658 op->timeout);
659
660 if (pending == NULL) {
662 "Unable to send DBus message");
663 goto cleanup;
664
665 } else { // Successfully initiated async op
666 free(job);
667 services_set_op_pending(op, pending);
669 return pcmk_rc_ok;
670 }
671 }
672
673 // Synchronous call
674
675 dbus_error_init(&error);
676 reply = pcmk_dbus_send_recv(msg, upstart_proxy, &error, op->timeout);
677
678 if (dbus_error_is_set(&error)) {
679 set_result_from_method_error(op, &error);
680 dbus_error_free(&error);
681
682 } else if (pcmk__str_eq(op->action, PCMK_ACTION_STOP, pcmk__str_none)) {
683 // DBus call does not return a value
685
686 } else if (!pcmk_dbus_type_check(reply, NULL, DBUS_TYPE_OBJECT_PATH,
687 __func__, __LINE__)) {
688 crm_info("Call to %s passed but return type was unexpected",
689 op->action);
691
692 } else {
693 const char *path = NULL;
694
695 dbus_message_get_args(reply, NULL, DBUS_TYPE_OBJECT_PATH, &path,
696 DBUS_TYPE_INVALID);
697 crm_debug("Call to %s passed: %s", op->action, path);
699 }
700
701cleanup:
702 free(job);
703 if (msg != NULL) {
704 dbus_message_unref(msg);
705 }
706 if (reply != NULL) {
707 dbus_message_unref(reply);
708 }
709
710 if (op->synchronous) {
711 return (op->rc == PCMK_OCF_OK)? pcmk_rc_ok : pcmk_rc_error;
712 } else {
714 }
715}
#define PCMK_ACTION_STATUS
Definition actions.h:73
#define PCMK_ACTION_STOP
Definition actions.h:75
#define PCMK_ACTION_META_DATA
Definition actions.h:56
#define PCMK_ACTION_START
Definition actions.h:72
#define PCMK_ACTION_MONITOR
Definition actions.h:60
const char * path
Definition cib.c:28
const char * name
Definition cib.c:26
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
A dumping ground.
char * pcmk_dbus_get_property(DBusConnection *connection, const char *target, const char *obj, const gchar *iface, const char *name, property_callback_func callback, void *userdata, DBusPendingCall **pending, int timeout)
Definition dbus.c:695
DBusConnection * pcmk_dbus_connect(void)
Definition dbus.c:259
DBusMessage * pcmk_dbus_send_recv(DBusMessage *msg, DBusConnection *connection, DBusError *error, int timeout)
Definition dbus.c:412
bool pcmk_dbus_find_error(const DBusPendingCall *pending, DBusMessage *reply, DBusError *ret)
Definition dbus.c:330
DBusPendingCall * pcmk_dbus_send(DBusMessage *msg, DBusConnection *connection, void(*done)(DBusPendingCall *pending, void *user_data), void *user_data, int timeout)
Definition dbus.c:476
bool pcmk_dbus_type_check(DBusMessage *msg, DBusMessageIter *field, int expected, const char *function, int line)
Definition dbus.c:516
void pcmk_dbus_disconnect(DBusConnection *connection)
Definition dbus.c:295
#define crm_info(fmt, args...)
Definition logging.h:397
#define crm_warn(fmt, args...)
Definition logging.h:392
#define CRM_LOG_ASSERT(expr)
Definition logging.h:228
#define crm_debug(fmt, args...)
Definition logging.h:400
#define crm_err(fmt, args...)
Definition logging.h:389
#define crm_trace(fmt, args...)
Definition logging.h:402
Wrappers for and extensions to glib mainloop.
xmlNode * input
#define DBUS_TIMEOUT_USE_DEFAULT
Definition pcmk-dbus.h:16
unsigned int timeout
Definition pcmk_fence.c:32
const char * action
Definition pcmk_fence.c:30
#define CRM_ASSERT(expr)
Definition results.h:42
ocf_exitcode
Exit status codes for resource agents.
Definition results.h:177
@ PCMK_OCF_UNIMPLEMENT_FEATURE
Requested action not implemented.
Definition results.h:184
@ PCMK_OCF_NOT_CONFIGURED
Parameter invalid (inherently)
Definition results.h:187
@ PCMK_OCF_NOT_INSTALLED
Dependencies not available locally.
Definition results.h:186
@ PCMK_OCF_UNKNOWN_ERROR
Unspecified error.
Definition results.h:181
@ PCMK_OCF_NOT_RUNNING
Service safely stopped.
Definition results.h:190
@ PCMK_OCF_OK
Success.
Definition results.h:178
@ pcmk_rc_ok
Definition results.h:162
@ pcmk_rc_error
Definition results.h:157
@ PCMK_EXEC_ERROR_FATAL
Execution failed, do not retry anywhere.
Definition results.h:339
@ PCMK_EXEC_NOT_INSTALLED
Agent or dependency not available locally.
Definition results.h:340
@ PCMK_EXEC_DONE
Action completed, result is known.
Definition results.h:333
@ PCMK_EXEC_ERROR
Execution failed, may be retried.
Definition results.h:337
@ PCMK_EXEC_ERROR_HARD
Execution failed, do not retry on node.
Definition results.h:338
void services_add_inflight_op(svc_action_t *op)
Definition services.c:833
Services API.
void services__set_result(svc_action_t *action, int agent_status, enum pcmk_exec_status exec_status, const char *exit_reason)
Definition services.c:1269
int services__finalize_async_op(svc_action_t *op)
bool pcmk__strcase_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
Definition strings.c:1026
@ pcmk__str_none
@ pcmk__str_casei
Object for executing external actions.
Definition services.h:122
char * agent
Resource agent name for resource actions, otherwise NULL.
Definition services.h:144
int rc
Exit status of action (set by library upon completion)
Definition services.h:155
char * rsc
XML ID of resource being executed for resource actions, otherwise NULL.
Definition services.h:129
char * action
Name of action being executed for resource actions, otherwise NULL.
Definition services.h:132
int synchronous
Definition services.h:173
int timeout
Action timeout (in milliseconds)
Definition services.h:146
char * stdout_data
Action stdout (set by library)
Definition services.h:178
int status
Execution status (enum pcmk_exec_status set by library)
Definition services.h:163
svc_action_private_t * opaque
This field should be treated as internal to Pacemaker.
Definition services.h:182
GList * upstart_job_listall(void)
Definition upstart.c:202
#define BUS_PATH
Definition upstart.c:30
#define METADATA_FORMAT
Definition upstart.c:375
#define UPSTART_JOB_IFACE
Definition upstart.c:33
void upstart_cleanup(void)
Definition upstart.c:90
#define BUS_NAME
Definition upstart.c:29
int services__upstart_prepare(svc_action_t *op)
Definition upstart.c:50
int services__execute_upstart(svc_action_t *op)
Definition upstart.c:529
gboolean upstart_job_exists(const char *name)
Definition upstart.c:284
#define UPSTART_06_API
Definition upstart.c:32
enum ocf_exitcode services__upstart2ocf(int exit_status)
Definition upstart.c:68
Wrappers for and extensions to libxml2.