23 #include <dbus/dbus.h> 29 #define BUS_NAME "com.ubuntu.Upstart" 30 #define BUS_PATH "/com/ubuntu/Upstart" 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" 39 static DBusConnection *upstart_proxy = NULL;
77 static int need_init = 1;
83 if (upstart_proxy == NULL) {
110 object_path_for_job(
const gchar *arg_name,
char **
path,
int timeout)
117 DBusMessage *reply = NULL;
124 if (!upstart_init()) {
127 msg = dbus_message_new_method_call(
BUS_NAME,
132 dbus_error_init(&error);
133 CRM_LOG_ASSERT(dbus_message_append_args(msg, DBUS_TYPE_STRING, &arg_name,
136 dbus_message_unref(msg);
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);
144 __func__, __LINE__)) {
145 crm_err(
"Could not get DBus object path for %s: Invalid return type",
150 dbus_message_get_args(reply, NULL, DBUS_TYPE_OBJECT_PATH,
path,
160 dbus_message_unref(reply);
166 fix(
char *
input,
const char *search,
char replace)
169 int shuffle = strlen(search) - 1;
174 match = strstr(
input, search);
180 len = strlen(match) - shuffle;
181 for (lpc = 1; lpc <= len; lpc++) {
182 match[lpc] = match[lpc + shuffle];
188 fix_upstart_name(
const char *
input)
190 char *output = strdup(
input);
192 fix(output,
"_2b",
'+');
193 fix(output,
"_2c",
',');
194 fix(output,
"_2d",
'-');
195 fix(output,
"_2e",
'.');
196 fix(output,
"_40",
'@');
197 fix(output,
"_5f",
'_');
205 DBusMessageIter args;
206 DBusMessageIter unit;
207 DBusMessage *msg = NULL;
208 DBusMessage *reply = NULL;
209 const char *method =
"GetAllJobs";
213 if (upstart_init() == FALSE) {
221 dbus_error_init(&error);
222 msg = dbus_message_new_method_call(
BUS_NAME,
229 dbus_message_unref(msg);
231 if (dbus_error_is_set(&error)) {
232 crm_err(
"Call to %s failed: %s", method, error.message);
233 dbus_error_free(&error);
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);
243 crm_err(
"Call to %s failed: Message has invalid arguments", method);
244 dbus_message_unref(reply);
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;
255 crm_warn(
"Skipping Upstart reply argument with unexpected type");
259 dbus_message_iter_get_basic(&unit, &value);
265 while (
path[llpc] != 0) {
266 if (
path[llpc] ==
'/') {
267 job =
path + llpc + 1;
273 units = g_list_append(units, fix_upstart_name(job));
275 dbus_message_iter_next (&unit);
278 dbus_message_unref(reply);
290 get_first_instance(
const gchar * job,
int timeout)
292 char *instance = NULL;
293 const char *method =
"GetAllInstances";
297 DBusMessageIter args;
298 DBusMessageIter unit;
300 dbus_error_init(&error);
301 msg = dbus_message_new_method_call(
BUS_NAME,
307 dbus_message_append_args(msg, DBUS_TYPE_INVALID);
309 dbus_message_unref(msg);
311 if (dbus_error_is_set(&error)) {
312 crm_info(
"Call to %s failed: %s", method, error.message);
313 dbus_error_free(&error);
316 }
else if(reply == NULL) {
317 crm_info(
"Call to %s failed: no reply", method);
320 }
else if (!dbus_message_iter_init(reply, &args)) {
321 crm_info(
"Call to %s failed: Message has no arguments", method);
326 crm_info(
"Call to %s failed: Message has invalid arguments", method);
330 dbus_message_iter_recurse(&args, &unit);
332 DBusBasicValue value;
334 dbus_message_iter_get_basic(&unit, &value);
337 instance = strdup(value.str);
344 dbus_message_unref(reply);
358 parse_status_result(
const char *
name,
const char *state,
void *userdata)
369 services_set_op_pending(op, NULL);
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" 408 upstart_job_metadata(
const char *
name)
421 set_result_from_method_error(
svc_action_t *op,
const DBusError *error)
424 "Unable to invoke Upstart DBus method");
426 if (strstr(error->name,
UPSTART_06_API ".Error.UnknownInstance")) {
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"));
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"));
448 crm_info(
"DBus request for %s of Upstart job %s for resource %s failed: %s",
461 job_method_complete(DBusPendingCall *pending,
void *user_data)
464 DBusMessage *reply = NULL;
468 if (pending != NULL) {
469 reply = dbus_pending_call_steal_reply(pending);
473 dbus_error_init(&error);
475 set_result_from_method_error(op, &error);
476 dbus_error_free(&error);
480 crm_debug(
"DBus request for stop of %s succeeded",
481 pcmk__s(op->
rsc,
"unknown resource"));
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"));
492 const char *
path = NULL;
494 dbus_message_get_args(reply, NULL, DBUS_TYPE_OBJECT_PATH, &
path,
496 crm_debug(
"DBus request for %s of %s using %s succeeded",
503 services_set_op_pending(op, NULL);
508 dbus_message_unref(reply);
533 const char *arg_env =
"pacemaker=1";
537 DBusMessage *msg = NULL;
538 DBusMessage *reply = NULL;
539 DBusMessageIter iter, array_iter;
545 "Bug in action caller");
549 if (!upstart_init()) {
551 "No DBus connection");
561 if (!object_path_for_job(op->
agent, &job, op->
timeout)) {
567 "Upstart job not found");
581 DBusPendingCall *pending = NULL;
586 "No Upstart job instances found");
599 parse_status_result(
"state", state, op);
602 }
else if (pending == NULL) {
604 "Could not get job state from DBus");
608 services_set_op_pending(op, pending);
627 "Action not implemented for Upstart resources");
633 "Bug in service library");
636 action, pcmk__s(op->
rsc,
"unknown resource"), job);
638 msg = dbus_message_new_method_call(
BUS_NAME,
644 dbus_message_iter_init_append (msg, &iter);
647 DBUS_TYPE_STRING_AS_STRING,
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,
657 job_method_complete, op,
660 if (pending == NULL) {
662 "Unable to send DBus message");
667 services_set_op_pending(op, pending);
675 dbus_error_init(&error);
678 if (dbus_error_is_set(&error)) {
679 set_result_from_method_error(op, &error);
680 dbus_error_free(&error);
687 __func__, __LINE__)) {
688 crm_info(
"Call to %s passed but return type was unexpected",
693 const char *
path = NULL;
695 dbus_message_get_args(reply, NULL, DBUS_TYPE_OBJECT_PATH, &
path,
704 dbus_message_unref(msg);
707 dbus_message_unref(reply);
int rc
Exit status of action (set by library upon completion)
ocf_exitcode
Exit status codes for resource agents.
bool pcmk__strcase_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
gboolean upstart_job_exists(const char *name)
enum ocf_exitcode services__upstart2ocf(int exit_status)
void pcmk_dbus_disconnect(DBusConnection *connection)
#define DBUS_TIMEOUT_USE_DEFAULT
#define PCMK_ACTION_META_DATA
#define PCMK_ACTION_MONITOR
char * rsc
XML ID of resource being executed for resource actions, otherwise NULL.
#define CRM_LOG_ASSERT(expr)
int timeout
Action timeout (in milliseconds)
Execution failed, do not retry on node.
void upstart_cleanup(void)
Wrappers for and extensions to glib mainloop.
#define PCMK_ACTION_STATUS
#define crm_warn(fmt, args...)
svc_action_private_t * opaque
This field should be treated as internal to Pacemaker.
GList * upstart_job_listall(void)
#define crm_debug(fmt, args...)
char * stdout_data
Action stdout (set by library)
Parameter invalid (inherently)
#define crm_trace(fmt, args...)
int services__finalize_async_op(svc_action_t *op)
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
Object for executing external actions.
#define PCMK_ACTION_START
char * agent
Resource agent name for resource actions, otherwise NULL.
void services__set_result(svc_action_t *action, int agent_status, enum pcmk_exec_status exec_status, const char *exit_reason)
Wrappers for and extensions to libxml2.
Action completed, result is known.
Execution failed, do not retry anywhere.
Dependencies not available locally.
int services__upstart_prepare(svc_action_t *op)
int services__execute_upstart(svc_action_t *op)
DBusPendingCall * pcmk_dbus_send(DBusMessage *msg, DBusConnection *connection, void(*done)(DBusPendingCall *pending, void *user_data), void *user_data, int timeout)
DBusConnection * pcmk_dbus_connect(void)
void services_add_inflight_op(svc_action_t *op)
Requested action not implemented.
char * action
Name of action being executed for resource actions, otherwise NULL.
#define crm_err(fmt, args...)
int status
Execution status (enum pcmk_exec_status set by library)
#define UPSTART_JOB_IFACE
bool pcmk_dbus_type_check(DBusMessage *msg, DBusMessageIter *field, int expected, const char *function, int line)
Agent or dependency not available locally.
bool pcmk_dbus_find_error(const DBusPendingCall *pending, DBusMessage *reply, DBusError *ret)
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)
DBusMessage * pcmk_dbus_send_recv(DBusMessage *msg, DBusConnection *connection, DBusError *error, int timeout)
Execution failed, may be retried.
#define crm_info(fmt, args...)