37 #include <dbus/dbus.h>
43 #define BUS_NAME "com.ubuntu.Upstart"
44 #define BUS_PATH "/com/ubuntu/Upstart"
46 #define UPSTART_06_API BUS_NAME"0_6"
47 #define UPSTART_JOB_IFACE UPSTART_06_API".Job"
48 #define BUS_PROPERTY_IFACE "org.freedesktop.DBus.Properties"
53 static DBusConnection *upstart_proxy = NULL;
58 static int need_init = 1;
64 if (upstart_proxy == NULL) {
80 upstart_job_by_name(
const gchar * arg_name, gchar ** out_unit,
int timeout)
87 DBusMessage *reply = NULL;
88 const char *method =
"GetJobByName";
90 if(upstart_init() == FALSE) {
93 msg = dbus_message_new_method_call(
BUS_NAME,
98 dbus_error_init(&error);
99 CRM_LOG_ASSERT(dbus_message_append_args(msg, DBUS_TYPE_STRING, &arg_name, DBUS_TYPE_INVALID));
101 dbus_message_unref(msg);
105 crm_err(
"Could not issue %s for %s: %s", method, arg_name, error.name);
108 crm_err(
"Invalid return type for %s", method);
114 dbus_message_get_args (reply, NULL,
115 DBUS_TYPE_OBJECT_PATH, &path,
118 *out_unit = strdup(path);
120 dbus_message_unref(reply);
125 dbus_message_unref(reply);
131 fix(
char *input,
const char *search,
char replace)
134 int shuffle = strlen(search) - 1;
139 match = strstr(input, search);
145 len = strlen(match) - shuffle;
146 for (lpc = 1; lpc <= len; lpc++) {
147 match[lpc] = match[lpc + shuffle];
153 fix_upstart_name(
const char *input)
155 char *output = strdup(input);
157 fix(output,
"_2b",
'+');
158 fix(output,
"_2c",
',');
159 fix(output,
"_2d",
'-');
160 fix(output,
"_2e",
'.');
161 fix(output,
"_40",
'@');
162 fix(output,
"_5f",
'_');
170 DBusMessageIter args;
171 DBusMessageIter unit;
172 DBusMessage *msg = NULL;
173 DBusMessage *reply = NULL;
174 const char *method =
"GetAllJobs";
178 if (upstart_init() == FALSE) {
186 dbus_error_init(&error);
187 msg = dbus_message_new_method_call(
BUS_NAME,
194 dbus_message_unref(msg);
197 crm_err(
"Call to %s failed: %s", method, error.name);
200 }
else if (!dbus_message_iter_init(reply, &args)) {
201 crm_err(
"Call to %s failed: Message has no arguments", method);
202 dbus_message_unref(reply);
207 crm_err(
"Call to %s failed: Message has invalid arguments", method);
208 dbus_message_unref(reply);
212 dbus_message_iter_recurse(&args, &unit);
213 while (dbus_message_iter_get_arg_type (&unit) != DBUS_TYPE_INVALID) {
214 DBusBasicValue value;
215 const char *job = NULL;
222 dbus_message_iter_get_basic(&unit, &value);
228 while (path[llpc] != 0) {
229 if (path[llpc] ==
'/') {
230 job = path + llpc + 1;
236 units = g_list_append(units, fix_upstart_name(job));
238 dbus_message_iter_next (&unit);
241 dbus_message_unref(reply);
253 get_first_instance(
const gchar * job,
int timeout)
255 char *instance = NULL;
256 const char *method =
"GetAllInstances";
260 DBusMessageIter args;
261 DBusMessageIter unit;
263 dbus_error_init(&error);
264 msg = dbus_message_new_method_call(
BUS_NAME,
270 dbus_message_append_args(msg, DBUS_TYPE_INVALID);
272 dbus_message_unref(msg);
275 crm_err(
"Call to %s failed: %s", method, error.name);
278 }
else if(reply == NULL) {
279 crm_err(
"Call to %s failed: no reply", method);
282 }
else if (!dbus_message_iter_init(reply, &args)) {
283 crm_err(
"Call to %s failed: Message has no arguments", method);
288 crm_err(
"Call to %s failed: Message has invalid arguments", method);
292 dbus_message_iter_recurse(&args, &unit);
294 DBusBasicValue value;
296 dbus_message_iter_get_basic(&unit, &value);
299 instance = strdup(value.str);
306 dbus_message_unref(reply);
312 upstart_job_check(
const char *name,
const char *state,
void *userdata)
316 if (state && g_strcmp0(state,
"running") == 0) {
325 services_set_op_pending(op, NULL);
331 upstart_job_metadata(
const char *name)
334 "<!DOCTYPE resource-agent SYSTEM \"ra-api-1.dtd\">\n"
335 "<resource-agent name=\"%s\" version=\"0.1\">\n"
336 " <version>1.0</version>\n"
337 " <longdesc lang=\"en\">\n"
338 " Upstart agent for controlling the system %s service\n"
340 " <shortdesc lang=\"en\">%s upstart agent</shortdesc>\n"
344 " <action name=\"start\" timeout=\"15\" />\n"
345 " <action name=\"stop\" timeout=\"15\" />\n"
346 " <action name=\"status\" timeout=\"15\" />\n"
347 " <action name=\"restart\" timeout=\"15\" />\n"
348 " <action name=\"monitor\" timeout=\"15\" interval=\"15\" start-delay=\"15\" />\n"
349 " <action name=\"meta-data\" timeout=\"5\" />\n"
351 " <special tag=\"upstart\">\n"
352 " </special>\n" "</resource-agent>\n", name, name, name);
361 crm_trace(
"Masking %s failure for %s: unknown services are stopped", op->
action, op->
rsc);
365 crm_trace(
"Mapping %s failure for %s: unknown services are not installed", op->
action, op->
rsc);
373 crm_trace(
"Mapping %s failure for %s: starting a started resource is allowed", op->
action, op->
rsc);
382 upstart_async_dispatch(DBusPendingCall *pending,
void *user_data)
385 DBusMessage *reply = NULL;
388 dbus_error_init(&error);
390 reply = dbus_pending_call_steal_reply(pending);
396 if (!upstart_mask_error(op, error.name)) {
400 }
else if (!g_strcmp0(op->
action,
"stop")) {
406 crm_warn(
"Call to %s passed but return type was unexpected", op->
action);
410 const char *path = NULL;
412 dbus_message_get_args (reply, NULL,
413 DBUS_TYPE_OBJECT_PATH, &path,
421 services_set_op_pending(op, NULL);
425 dbus_message_unref(reply);
436 const char *arg_env =
"pacemaker=1";
437 const char *action = op->
action;
440 DBusMessage *msg = NULL;
441 DBusMessage *reply = NULL;
442 DBusMessageIter iter, array_iter;
453 if(!upstart_job_by_name(op->
agent, &job, op->
timeout)) {
454 crm_debug(
"Could not obtain job named '%s' to %s", op->
agent, action);
455 if (!g_strcmp0(action,
"stop")) {
467 char *path = get_first_instance(job, op->
timeout);
471 DBusPendingCall *pending = NULL;
481 upstart_job_check(
"state", state, op);
484 }
else if (pending) {
485 services_set_op_pending(op, pending);
493 }
else if (!g_strcmp0(action,
"start")) {
495 }
else if (!g_strcmp0(action,
"stop")) {
497 }
else if (!g_strcmp0(action,
"restart")) {
504 crm_debug(
"Calling %s for %s on %s", action, op->
rsc, job);
506 msg = dbus_message_new_method_call(
BUS_NAME,
512 dbus_message_iter_init_append (msg, &iter);
516 DBUS_TYPE_STRING_AS_STRING,
519 CRM_LOG_ASSERT(dbus_message_iter_append_basic (&array_iter, DBUS_TYPE_STRING, &arg_env));
520 CRM_LOG_ASSERT(dbus_message_iter_close_container (&iter, &array_iter));
522 CRM_LOG_ASSERT(dbus_message_append_args(msg, DBUS_TYPE_BOOLEAN, &arg_wait, DBUS_TYPE_INVALID));
525 DBusPendingCall* pending =
pcmk_dbus_send(msg, upstart_proxy, upstart_async_dispatch, op, op->
timeout);
529 services_set_op_pending(op, pending);
536 dbus_error_init(&error);
540 if(!upstart_mask_error(op, error.name)) {
541 crm_err(
"Could not issue %s for %s: %s (%s)", action, op->
rsc, error.name, job);
544 }
else if (!g_strcmp0(op->
action,
"stop")) {
549 crm_warn(
"Call to %s passed but return type was unexpected", op->
action);
553 const char *path = NULL;
555 dbus_message_get_args (reply, NULL,
556 DBUS_TYPE_OBJECT_PATH, &path,
566 dbus_message_unref(msg);
570 dbus_message_unref(reply);
gboolean upstart_job_exists(const char *name)
void pcmk_dbus_disconnect(DBusConnection *connection)
#define DBUS_TIMEOUT_USE_DEFAULT
#define CRM_LOG_ASSERT(expr)
void upstart_cleanup(void)
Wrappers for and extensions to glib mainloop.
gboolean upstart_job_exec(svc_action_t *op, gboolean synchronous)
#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 * pcmk_dbus_get_property(DBusConnection *connection, const char *target, const char *obj, const gchar *iface, const char *name, void(*callback)(const char *name, const char *value, void *userdata), void *userdata, DBusPendingCall **pending, int timeout)
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
bool pcmk_dbus_type_check(DBusMessage *msg, DBusMessageIter *field, int expected, const char *function, int line)
#define safe_str_eq(a, b)
char * crm_strdup_printf(char const *format,...) __attribute__((__format__(__printf__
DBusMessage * pcmk_dbus_send_recv(DBusMessage *msg, DBusConnection *connection, DBusError *error, int timeout)
#define crm_info(fmt, args...)
bool pcmk_dbus_find_error(const char *method, DBusPendingCall *pending, DBusMessage *reply, DBusError *ret)