19 #include <dbus/dbus.h>
25 #define BUS_NAME "com.ubuntu.Upstart"
26 #define BUS_PATH "/com/ubuntu/Upstart"
28 #define UPSTART_06_API BUS_NAME"0_6"
29 #define UPSTART_JOB_IFACE UPSTART_06_API".Job"
30 #define BUS_PROPERTY_IFACE "org.freedesktop.DBus.Properties"
35 static DBusConnection *upstart_proxy = NULL;
40 static int need_init = 1;
46 if (upstart_proxy == NULL) {
62 upstart_job_by_name(
const gchar * arg_name, gchar ** out_unit,
int timeout)
69 DBusMessage *reply = NULL;
70 const char *method =
"GetJobByName";
72 if(upstart_init() == FALSE) {
75 msg = dbus_message_new_method_call(
BUS_NAME,
80 dbus_error_init(&error);
81 CRM_LOG_ASSERT(dbus_message_append_args(msg, DBUS_TYPE_STRING, &arg_name, DBUS_TYPE_INVALID));
83 dbus_message_unref(msg);
85 if (dbus_error_is_set(&error)) {
86 crm_err(
"Could not issue %s for %s: %s", method, arg_name, error.message);
87 dbus_error_free(&error);
90 crm_err(
"Invalid return type for %s", method);
96 dbus_message_get_args (reply, NULL,
97 DBUS_TYPE_OBJECT_PATH, &path,
100 *out_unit = strdup(path);
102 dbus_message_unref(reply);
107 dbus_message_unref(reply);
113 fix(
char *input,
const char *search,
char replace)
116 int shuffle = strlen(search) - 1;
121 match = strstr(input, search);
127 len = strlen(match) - shuffle;
128 for (lpc = 1; lpc <= len; lpc++) {
129 match[lpc] = match[lpc + shuffle];
135 fix_upstart_name(
const char *input)
137 char *output = strdup(input);
139 fix(output,
"_2b",
'+');
140 fix(output,
"_2c",
',');
141 fix(output,
"_2d",
'-');
142 fix(output,
"_2e",
'.');
143 fix(output,
"_40",
'@');
144 fix(output,
"_5f",
'_');
152 DBusMessageIter args;
153 DBusMessageIter unit;
154 DBusMessage *msg = NULL;
155 DBusMessage *reply = NULL;
156 const char *method =
"GetAllJobs";
160 if (upstart_init() == FALSE) {
168 dbus_error_init(&error);
169 msg = dbus_message_new_method_call(
BUS_NAME,
176 dbus_message_unref(msg);
178 if (dbus_error_is_set(&error)) {
179 crm_err(
"Call to %s failed: %s", method, error.message);
180 dbus_error_free(&error);
183 }
else if (!dbus_message_iter_init(reply, &args)) {
184 crm_err(
"Call to %s failed: Message has no arguments", method);
185 dbus_message_unref(reply);
190 crm_err(
"Call to %s failed: Message has invalid arguments", method);
191 dbus_message_unref(reply);
195 dbus_message_iter_recurse(&args, &unit);
196 while (dbus_message_iter_get_arg_type (&unit) != DBUS_TYPE_INVALID) {
197 DBusBasicValue value;
198 const char *job = NULL;
202 crm_warn(
"Skipping Upstart reply argument with unexpected type");
206 dbus_message_iter_get_basic(&unit, &value);
212 while (path[llpc] != 0) {
213 if (path[llpc] ==
'/') {
214 job = path + llpc + 1;
220 units = g_list_append(units, fix_upstart_name(job));
222 dbus_message_iter_next (&unit);
225 dbus_message_unref(reply);
237 get_first_instance(
const gchar * job,
int timeout)
239 char *instance = NULL;
240 const char *method =
"GetAllInstances";
244 DBusMessageIter args;
245 DBusMessageIter unit;
247 dbus_error_init(&error);
248 msg = dbus_message_new_method_call(
BUS_NAME,
254 dbus_message_append_args(msg, DBUS_TYPE_INVALID);
256 dbus_message_unref(msg);
258 if (dbus_error_is_set(&error)) {
259 crm_err(
"Call to %s failed: %s", method, error.message);
260 dbus_error_free(&error);
263 }
else if(reply == NULL) {
264 crm_err(
"Call to %s failed: no reply", method);
267 }
else if (!dbus_message_iter_init(reply, &args)) {
268 crm_err(
"Call to %s failed: Message has no arguments", method);
273 crm_err(
"Call to %s failed: Message has invalid arguments", method);
277 dbus_message_iter_recurse(&args, &unit);
279 DBusBasicValue value;
281 dbus_message_iter_get_basic(&unit, &value);
284 instance = strdup(value.str);
291 dbus_message_unref(reply);
297 upstart_job_check(
const char *
name,
const char *state,
void *userdata)
301 if (state && g_strcmp0(state,
"running") == 0) {
310 services_set_op_pending(op, NULL);
316 upstart_job_metadata(
const char *name)
319 "<!DOCTYPE resource-agent SYSTEM \"ra-api-1.dtd\">\n"
321 " <version>1.0</version>\n"
322 " <longdesc lang=\"en\">\n"
323 " Upstart agent for controlling the system %s service\n"
325 " <shortdesc lang=\"en\">%s upstart agent</shortdesc>\n"
329 " <action name=\"start\" timeout=\"15\" />\n"
330 " <action name=\"stop\" timeout=\"15\" />\n"
331 " <action name=\"status\" timeout=\"15\" />\n"
332 " <action name=\"restart\" timeout=\"15\" />\n"
333 " <action name=\"monitor\" timeout=\"15\" interval=\"15\" start-delay=\"15\" />\n"
334 " <action name=\"meta-data\" timeout=\"5\" />\n"
336 " <special tag=\"upstart\">\n"
337 " </special>\n" "</resource-agent>\n", name, name, name);
346 crm_trace(
"Masking %s failure for %s: unknown services are stopped", op->
action, op->
rsc);
350 crm_trace(
"Mapping %s failure for %s: unknown services are not installed", op->
action, op->
rsc);
358 crm_trace(
"Mapping %s failure for %s: starting a started resource is allowed", op->
action, op->
rsc);
367 upstart_async_dispatch(DBusPendingCall *pending,
void *user_data)
370 DBusMessage *reply = NULL;
373 dbus_error_init(&error);
375 reply = dbus_pending_call_steal_reply(pending);
381 if (!upstart_mask_error(op, error.name)) {
384 dbus_error_free(&error);
386 }
else if (!g_strcmp0(op->
action,
"stop")) {
392 crm_warn(
"Call to %s passed but return type was unexpected", op->
action);
396 const char *path = NULL;
398 dbus_message_get_args (reply, NULL,
399 DBUS_TYPE_OBJECT_PATH, &path,
407 services_set_op_pending(op, NULL);
411 dbus_message_unref(reply);
422 const char *arg_env =
"pacemaker=1";
426 DBusMessage *msg = NULL;
427 DBusMessage *reply = NULL;
428 DBusMessageIter iter, array_iter;
439 if(!upstart_job_by_name(op->
agent, &job, op->
timeout)) {
440 crm_debug(
"Could not obtain job named '%s' to %s", op->
agent, action);
441 if (!g_strcmp0(action,
"stop")) {
452 char *path = get_first_instance(job, op->
timeout);
456 DBusPendingCall *pending = NULL;
466 upstart_job_check(
"state", state, op);
469 }
else if (pending) {
470 services_set_op_pending(op, pending);
478 }
else if (!g_strcmp0(action,
"start")) {
480 }
else if (!g_strcmp0(action,
"stop")) {
482 }
else if (!g_strcmp0(action,
"restart")) {
489 crm_debug(
"Calling %s for %s on %s", action, op->
rsc, job);
491 msg = dbus_message_new_method_call(
BUS_NAME,
497 dbus_message_iter_init_append (msg, &iter);
501 DBUS_TYPE_STRING_AS_STRING,
504 CRM_LOG_ASSERT(dbus_message_iter_append_basic (&array_iter, DBUS_TYPE_STRING, &arg_env));
505 CRM_LOG_ASSERT(dbus_message_iter_close_container (&iter, &array_iter));
507 CRM_LOG_ASSERT(dbus_message_append_args(msg, DBUS_TYPE_BOOLEAN, &arg_wait, DBUS_TYPE_INVALID));
510 DBusPendingCall* pending =
pcmk_dbus_send(msg, upstart_proxy, upstart_async_dispatch, op, op->
timeout);
514 services_set_op_pending(op, pending);
521 dbus_error_init(&error);
524 if (dbus_error_is_set(&error)) {
525 if(!upstart_mask_error(op, error.name)) {
526 crm_err(
"Could not issue %s for %s: %s (%s)",
527 action, op->
rsc, error.message, job);
529 dbus_error_free(&error);
531 }
else if (!g_strcmp0(op->
action,
"stop")) {
536 crm_warn(
"Call to %s passed but return type was unexpected", op->
action);
540 const char *path = NULL;
542 dbus_message_get_args (reply, NULL,
543 DBUS_TYPE_OBJECT_PATH, &path,
553 dbus_message_unref(msg);
557 dbus_message_unref(reply);
bool pcmk__strcase_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
gboolean upstart_job_exists(const char *name)
void pcmk_dbus_disconnect(DBusConnection *connection)
#define DBUS_TIMEOUT_USE_DEFAULT
#define CRM_LOG_ASSERT(expr)
gboolean upstart_job_exec(svc_action_t *op)
void upstart_cleanup(void)
Wrappers for and extensions to glib mainloop.
bool pcmk_dbus_find_error(DBusPendingCall *pending, DBusMessage *reply, DBusError *ret)
#define crm_warn(fmt, args...)
svc_action_private_t * opaque
GList * upstart_job_listall(void)
#define crm_debug(fmt, args...)
gboolean operation_finalize(svc_action_t *op)
#define crm_trace(fmt, args...)
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
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)
#define crm_err(fmt, args...)
#define UPSTART_JOB_IFACE
#define PCMK_DEFAULT_AGENT_VERSION
bool pcmk_dbus_type_check(DBusMessage *msg, DBusMessageIter *field, int expected, const char *function, int line)
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)
#define crm_info(fmt, args...)