diff --git a/SOURCES/bz1057697-pcmk-dbus_use_native_function_for_adding_arguments_to_messages.patch b/SOURCES/bz1057697-pcmk-dbus_use_native_function_for_adding_arguments_to_messages.patch new file mode 100644 index 0000000..fe35e42 --- /dev/null +++ b/SOURCES/bz1057697-pcmk-dbus_use_native_function_for_adding_arguments_to_messages.patch @@ -0,0 +1,77 @@ +commit 04d86af8d57dd8c16283ea6acc6d6798053cf2a0 +Author: Andrew Beekhof +Date: Wed Feb 5 10:56:51 2014 +1100 + + Refactor: dbus: Use native function for adding arguments to messages + + (cherry picked from commit bab144c83e90785c7df01423d3b239cbd4a2cd55) + +diff --git a/lib/services/dbus.c b/lib/services/dbus.c +index 66a98a0..b424c0b 100644 +--- a/lib/services/dbus.c ++++ b/lib/services/dbus.c +@@ -33,19 +33,6 @@ void pcmk_dbus_disconnect(DBusConnection *connection) + { + } + +-bool pcmk_dbus_append_arg(DBusMessage *msg, int dtype, const void *value) +-{ +- DBusMessageIter args; +- +- dbus_message_iter_init_append(msg, &args); +- if (!dbus_message_iter_append_basic(&args, dtype, value)) { +- crm_err("dbus_message_iter_append_basic(%c) failed", dtype); +- return FALSE; +- } +- +- return TRUE; +-} +- + bool + pcmk_dbus_find_error(const char *method, DBusPendingCall* pending, DBusMessage *reply, DBusError *ret) + { +@@ -235,7 +222,7 @@ pcmk_dbus_get_property( + return NULL; + } + +- pcmk_dbus_append_arg(msg, DBUS_TYPE_STRING, &iface); ++ CRM_LOG_ASSERT(dbus_message_append_args(msg, DBUS_TYPE_STRING, &iface, DBUS_TYPE_INVALID)); + + reply = pcmk_dbus_send_recv(msg, connection, &error); + dbus_message_unref(msg); +diff --git a/lib/services/pcmk-dbus.h b/lib/services/pcmk-dbus.h +index c8d2234..3b7a598 100644 +--- a/lib/services/pcmk-dbus.h ++++ b/lib/services/pcmk-dbus.h +@@ -5,7 +5,6 @@ void pcmk_dbus_disconnect(DBusConnection *connection); + bool pcmk_dbus_send(DBusMessage *msg, DBusConnection *connection, + void(*done)(DBusPendingCall *pending, void *user_data), void *user_data); + DBusMessage *pcmk_dbus_send_recv(DBusMessage *msg, DBusConnection *connection, DBusError *error); +-bool pcmk_dbus_append_arg(DBusMessage *msg, int dtype, const void *value); + 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); + +diff --git a/lib/services/systemd.c b/lib/services/systemd.c +index b461c5f..374a03e 100644 +--- a/lib/services/systemd.c ++++ b/lib/services/systemd.c +@@ -146,7 +146,7 @@ systemd_unit_by_name(const gchar * arg_name, gchar ** out_unit) + msg = systemd_new_method(BUS_NAME".Manager", method); + CRM_ASSERT(msg != NULL); + +- pcmk_dbus_append_arg(msg, DBUS_TYPE_STRING, &name); ++ CRM_LOG_ASSERT(dbus_message_append_args(msg, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID)); + + dbus_error_init(&error); + reply = pcmk_dbus_send_recv(msg, systemd_proxy, &error); +@@ -477,8 +477,8 @@ systemd_unit_exec(svc_action_t * op, gboolean synchronous) + CRM_ASSERT(msg != NULL); + + /* (ss) */ +- pcmk_dbus_append_arg(msg, DBUS_TYPE_STRING, &name); +- pcmk_dbus_append_arg(msg, DBUS_TYPE_STRING, &replace_s); ++ CRM_LOG_ASSERT(dbus_message_append_args(msg, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID)); ++ CRM_LOG_ASSERT(dbus_message_append_args(msg, DBUS_TYPE_STRING, &replace_s, DBUS_TYPE_INVALID)); + + if (synchronous == FALSE) { + free(unit); diff --git a/SOURCES/bz1057697-pcmk-portability_use_basic_types_for_dbus_compatability_struct.patch b/SOURCES/bz1057697-pcmk-portability_use_basic_types_for_dbus_compatability_struct.patch new file mode 100644 index 0000000..e5e1c29 --- /dev/null +++ b/SOURCES/bz1057697-pcmk-portability_use_basic_types_for_dbus_compatability_struct.patch @@ -0,0 +1,53 @@ +commit 6080e33737a133d080eb0f86a7b66f3af04f4c91 +Author: Andrew Beekhof +Date: Mon Feb 3 14:59:18 2014 +1100 + + Fix: Portability: Use basic types for DBus compatability struct + + (cherry picked from commit 73a40012cc03336fb9753bc6e47bace7bc44a794) + +diff --git a/include/portability.h b/include/portability.h +index 29d1177..4eb6eaa 100644 +--- a/include/portability.h ++++ b/include/portability.h +@@ -178,6 +178,7 @@ g_list_free_full(GList * list, GDestroyNotify free_func) + # endif + + # ifndef HAVE_DBUSBASICVALUE ++# include + # include + /** + * An 8-byte struct you could use to access int64 without having +@@ -185,8 +186,8 @@ g_list_free_full(GList * list, GDestroyNotify free_func) + */ + typedef struct + { +- dbus_uint32_t first32; /**< first 32 bits in the 8 bytes (beware endian issues) */ +- dbus_uint32_t second32; /**< second 32 bits in the 8 bytes (beware endian issues) */ ++ uint32_t first32; /**< first 32 bits in the 8 bytes (beware endian issues) */ ++ uint32_t second32; /**< second 32 bits in the 8 bytes (beware endian issues) */ + } DBus8ByteStruct; + + /** +@@ -202,14 +203,14 @@ typedef struct + typedef union + { + unsigned char bytes[8]; /**< as 8 individual bytes */ +- dbus_int16_t i16; /**< as int16 */ +- dbus_uint16_t u16; /**< as int16 */ +- dbus_int32_t i32; /**< as int32 */ +- dbus_uint32_t u32; /**< as int32 */ +- dbus_bool_t bool_val; /**< as boolean */ ++ int16_t i16; /**< as int16 */ ++ uint16_t u16; /**< as int16 */ ++ int32_t i32; /**< as int32 */ ++ uint32_t u32; /**< as int32 */ ++ uint32_t bool_val; /**< as boolean */ + # ifdef DBUS_HAVE_INT64 +- dbus_int64_t i64; /**< as int64 */ +- dbus_uint64_t u64; /**< as int64 */ ++ int64_t i64; /**< as int64 */ ++ uint64_t u64; /**< as int64 */ + # endif + DBus8ByteStruct eight; /**< as 8-byte struct */ + double dbl; /**< as double */ diff --git a/SOURCES/bz1057697-pcmk-services_detect_missing_agents_and_permission_errors_before_forking.patch b/SOURCES/bz1057697-pcmk-services_detect_missing_agents_and_permission_errors_before_forking.patch new file mode 100644 index 0000000..bfa676e --- /dev/null +++ b/SOURCES/bz1057697-pcmk-services_detect_missing_agents_and_permission_errors_before_forking.patch @@ -0,0 +1,271 @@ +commit 385cb2b6a11d967145d8034fd5c05574a6594a4f +Author: Andrew Beekhof +Date: Thu Aug 8 11:21:03 2013 +1000 + + Feature: services: Detect missing agents and permission errors before forking + + Also set the operation status to distinguish between the agent being + missing and something the agent needs being missing. + + (cherry picked from commit 20eee043d376ed03edf5e4bb4cc4639f8697e44a) + +diff --git a/crmd/te_actions.c b/crmd/te_actions.c +index 63d15bb..4e3bc22 100644 +--- a/crmd/te_actions.c ++++ b/crmd/te_actions.c +@@ -465,7 +465,7 @@ te_rsc_command(crm_graph_t * graph, crm_action_t * action) + && safe_str_neq(task, CRMD_ACTION_DELETE)) { + /* write a "pending" entry to the CIB, inhibit notification */ + crm_debug("Recording pending op %s in the CIB", task_uuid); +- cib_action_update(action, PCMK_LRM_OP_PENDING, PCMK_OCF_STATUS_UNKNOWN); ++ cib_action_update(action, PCMK_LRM_OP_PENDING, PCMK_OCF_UNKNOWN); + } + + return TRUE; +diff --git a/crmd/te_callbacks.c b/crmd/te_callbacks.c +index c0360b4..4b8aac5 100644 +--- a/crmd/te_callbacks.c ++++ b/crmd/te_callbacks.c +@@ -548,7 +548,6 @@ action_timer_callback(gpointer data) + } + + if (send_update) { +- /* cib_action_update(timer->action, PCMK_LRM_OP_PENDING, PCMK_OCF_STATUS_UNKNOWN); */ + cib_action_update(timer->action, PCMK_LRM_OP_TIMEOUT, PCMK_OCF_UNKNOWN_ERROR); + } + } +diff --git a/include/crm/services.h b/include/crm/services.h +index 0c0cca9..9fe9d37 100644 +--- a/include/crm/services.h ++++ b/include/crm/services.h +@@ -88,9 +88,10 @@ enum ocf_exitcode { + PCMK_OCF_RUNNING_MASTER = 8, + PCMK_OCF_FAILED_MASTER = 9, + +- PCMK_OCF_STATUS_UNKNOWN = 14, /* Already in use */ + + /* 150-199 reserved for application use */ ++ PCMK_OCF_EXEC_ERROR = 192, /* Generic problem invoking the agent */ ++ PCMK_OCF_UNKNOWN = 193, /* State of the service is unknown - used for recording in-flight operations */ + PCMK_OCF_SIGNAL = 194, + PCMK_OCF_NOT_SUPPORTED = 195, + PCMK_OCF_PENDING = 196, +@@ -106,6 +107,7 @@ enum op_status { + PCMK_LRM_OP_TIMEOUT, + PCMK_LRM_OP_NOTSUPPORTED, + PCMK_LRM_OP_ERROR, ++ PCMK_LRM_OP_NOT_INSTALLED, + }; + + enum nagios_exitcode { +@@ -263,6 +265,7 @@ enum nagios_exitcode { + case PCMK_LRM_OP_TIMEOUT:return "Timed Out"; + case PCMK_LRM_OP_NOTSUPPORTED:return "NOT SUPPORTED"; + case PCMK_LRM_OP_ERROR:return "Error"; ++ case PCMK_LRM_OP_NOT_INSTALLED:return "Not installed"; + default:return "UNKNOWN!"; + }} static inline const char *services_ocf_exitcode_str(enum ocf_exitcode code) { + switch (code) { +diff --git a/lib/services/services_linux.c b/lib/services/services_linux.c +index 868dc5b..ac0138f 100644 +--- a/lib/services/services_linux.c ++++ b/lib/services/services_linux.c +@@ -307,14 +307,62 @@ operation_finished(mainloop_child_t * p, pid_t pid, int core, int signo, int exi + operation_finalize(op); + } + ++static void ++services_handle_exec_error(svc_action_t * op, int error) ++{ ++ op->stdout_data = NULL; ++ op->stderr_data = NULL; ++ ++ /* Need to mimic the return codes for each standard as thats what we'll convert back from in get_uniform_rc() */ ++ if (safe_str_eq(op->standard, "lsb") && safe_str_eq(op->action, "status")) { ++ switch (errno) { /* see execve(2) */ ++ case ENOENT: /* No such file or directory */ ++ case EISDIR: /* Is a directory */ ++ op->rc = PCMK_LSB_STATUS_NOT_INSTALLED; ++ op->status = PCMK_LRM_OP_NOT_INSTALLED; ++ break; ++ case EACCES: /* permission denied (various errors) */ ++ /* LSB status ops don't support 'not installed' */ ++ break; ++ } ++ ++#if SUPPORT_NAGIOS ++ } else if (safe_str_eq(op->standard, "nagios")) { ++ switch (errno) { ++ case ENOENT: /* No such file or directory */ ++ case EISDIR: /* Is a directory */ ++ op->rc = NAGIOS_NOT_INSTALLED; ++ op->status = PCMK_LRM_OP_NOT_INSTALLED; ++ break; ++ case EACCES: /* permission denied (various errors) */ ++ op->rc = NAGIOS_INSUFFICIENT_PRIV; ++ break; ++ } ++#endif ++ ++ } else { ++ switch (errno) { ++ case ENOENT: /* No such file or directory */ ++ case EISDIR: /* Is a directory */ ++ op->rc = PCMK_OCF_NOT_INSTALLED; /* Valid for LSB */ ++ op->status = PCMK_LRM_OP_NOT_INSTALLED; ++ break; ++ case EACCES: /* permission denied (various errors) */ ++ op->rc = PCMK_OCF_INSUFFICIENT_PRIV; /* Valid for LSB */ ++ break; ++ } ++ } ++} ++ + gboolean + services_os_action_execute(svc_action_t * op, gboolean synchronous) + { +- int rc, lpc; ++ int lpc; + int stdout_fd[2]; + int stderr_fd[2]; + sigset_t mask; + sigset_t old_mask; ++ struct stat st; + + if (pipe(stdout_fd) < 0) { + crm_err("pipe() failed"); +@@ -324,6 +372,13 @@ services_os_action_execute(svc_action_t * op, gboolean synchronous) + crm_err("pipe() failed"); + } + ++ /* Fail fast */ ++ if(stat(op->opaque->exec, &st) != 0) { ++ crm_warn("Cannot execute '%s': %s (%d)", op->opaque->exec, pcmk_strerror(errno), errno); ++ services_handle_exec_error(op, errno); ++ return FALSE; ++ } ++ + if (synchronous) { + sigemptyset(&mask); + sigaddset(&mask, SIGCHLD); +@@ -337,11 +392,14 @@ services_os_action_execute(svc_action_t * op, gboolean synchronous) + op->pid = fork(); + switch (op->pid) { + case -1: +- crm_err("fork() failed"); ++ crm_err("Could not execute '%s': %s (%d)", op->opaque->exec, pcmk_strerror(errno), errno); ++ + close(stdout_fd[0]); + close(stdout_fd[1]); + close(stderr_fd[0]); + close(stderr_fd[1]); ++ ++ services_handle_exec_error(op, errno); + return FALSE; + + case 0: /* Child */ +@@ -390,29 +448,9 @@ services_os_action_execute(svc_action_t * op, gboolean synchronous) + /* execute the RA */ + execvp(op->opaque->exec, op->opaque->args); + +- switch (errno) { /* see execve(2) */ +- case ENOENT: /* No such file or directory */ +- case EISDIR: /* Is a directory */ +- rc = PCMK_OCF_NOT_INSTALLED; +-#if SUPPORT_NAGIOS +- if (safe_str_eq(op->standard, "nagios")) { +- rc = NAGIOS_NOT_INSTALLED; +- } +-#endif +- break; +- case EACCES: /* permission denied (various errors) */ +- rc = PCMK_OCF_INSUFFICIENT_PRIV; +-#if SUPPORT_NAGIOS +- if (safe_str_eq(op->standard, "nagios")) { +- rc = NAGIOS_INSUFFICIENT_PRIV; +- } +-#endif +- break; +- default: +- rc = PCMK_OCF_UNKNOWN_ERROR; +- break; +- } +- _exit(rc); ++ /* Most cases should have been already handled by stat() */ ++ services_handle_exec_error(op, errno); ++ _exit(op->rc); + } + + /* Only the parent reaches here */ +diff --git a/lib/services/systemd.c b/lib/services/systemd.c +index 783caca..ea804c8 100644 +--- a/lib/services/systemd.c ++++ b/lib/services/systemd.c +@@ -385,6 +385,7 @@ systemd_unit_exec_done(GObject * source_object, GAsyncResult * res, gpointer use + + } else { + op->rc = PCMK_OCF_NOT_INSTALLED; ++ op->status = PCMK_LRM_OP_NOT_INSTALLED; + } + + } else { +@@ -441,6 +442,7 @@ systemd_unit_exec(svc_action_t * op, gboolean synchronous) + error ? error->message : "unknown"); + if (error && strstr(error->message, "systemd1.NoSuchUnit")) { + op->rc = PCMK_OCF_NOT_INSTALLED; ++ op->status = PCMK_LRM_OP_NOT_INSTALLED; + } + if(error) { + g_error_free(error); +diff --git a/lib/services/upstart.c b/lib/services/upstart.c +index daeb398..831e7cf 100644 +--- a/lib/services/upstart.c ++++ b/lib/services/upstart.c +@@ -446,6 +446,7 @@ upstart_job_exec(svc_action_t * op, gboolean synchronous) + op->rc = PCMK_OCF_OK; + } else { + op->rc = PCMK_OCF_NOT_INSTALLED; ++ op->status = PCMK_LRM_OP_NOT_INSTALLED; + } + goto cleanup; + } +diff --git a/lrmd/regression.py.in b/lrmd/regression.py.in +index 8d5fea4..9009e1c 100755 +--- a/lrmd/regression.py.in ++++ b/lrmd/regression.py.in +@@ -629,7 +629,7 @@ if __name__ == "__main__": + test.add_cmd("-c register_rsc -r \"test_rsc\" -C systemd -T this_is_fake1234 -t 3000 " + "-l \"NEW_EVENT event_type:register rsc_id:test_rsc action:none rc:ok op_status:complete\" ") + test.add_cmd("-c exec -r \"test_rsc\" -a \"start\" -t 3000 " +- "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:not installed op_status:complete\" ") ++ "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:not installed op_status:Not installed\" ") + test.add_cmd("-c unregister_rsc -r \"test_rsc\" -t 3000 " + "-l \"NEW_EVENT event_type:unregister rsc_id:test_rsc action:none rc:ok op_status:complete\" ") + +@@ -638,7 +638,7 @@ if __name__ == "__main__": + test.add_cmd("-c register_rsc -r \"test_rsc\" -C upstart -T this_is_fake1234 -t 3000 " + "-l \"NEW_EVENT event_type:register rsc_id:test_rsc action:none rc:ok op_status:complete\" ") + test.add_cmd("-c exec -r \"test_rsc\" -a \"start\" -t 3000 " +- "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:not installed op_status:complete\" ") ++ "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:not installed op_status:Not installed\" ") + test.add_cmd("-c unregister_rsc -r \"test_rsc\" -t 3000 " + "-l \"NEW_EVENT event_type:unregister rsc_id:test_rsc action:none rc:ok op_status:complete\" ") + +@@ -647,7 +647,7 @@ if __name__ == "__main__": + test.add_cmd("-c register_rsc -r \"test_rsc\" -C ocf -P pacemaker -T this_is_fake1234 -t 3000 " + "-l \"NEW_EVENT event_type:register rsc_id:test_rsc action:none rc:ok op_status:complete\" ") + test.add_cmd("-c exec -r \"test_rsc\" -a \"start\" -t 3000 " +- "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:not installed op_status:complete\" ") ++ "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:not installed op_status:Not installed\" ") + test.add_cmd("-c unregister_rsc -r \"test_rsc\" -t 3000 " + "-l \"NEW_EVENT event_type:unregister rsc_id:test_rsc action:none rc:ok op_status:complete\" ") + +@@ -656,7 +656,7 @@ if __name__ == "__main__": + test.add_cmd("-c register_rsc -r \"test_rsc\" -C ocf -P pancakes -T Dummy -t 3000 " + "-l \"NEW_EVENT event_type:register rsc_id:test_rsc action:none rc:ok op_status:complete\" ") + test.add_cmd("-c exec -r \"test_rsc\" -a \"start\" -t 3000 " +- "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:not installed op_status:complete\" ") ++ "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:not installed op_status:Not installed\" ") + test.add_cmd("-c unregister_rsc -r \"test_rsc\" -t 3000 " + "-l \"NEW_EVENT event_type:unregister rsc_id:test_rsc action:none rc:ok op_status:complete\" ") + diff --git a/SOURCES/bz1057697-pcmk-services_keep_dbus_build_support_optional.patch b/SOURCES/bz1057697-pcmk-services_keep_dbus_build_support_optional.patch new file mode 100644 index 0000000..eebd849 --- /dev/null +++ b/SOURCES/bz1057697-pcmk-services_keep_dbus_build_support_optional.patch @@ -0,0 +1,55 @@ +commit 719498e7cfbceffa01eff37263c55ceaf1623379 +Author: David Vossel +Date: Wed Feb 5 17:42:01 2014 -0600 + + Low: services: Keep dbus build support optional + + (cherry picked from commit e4d030a6d278fb3a43aa9c7eb359b488673f504a) + +diff --git a/configure.ac b/configure.ac +index f90ccdc..cad5190 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -1162,6 +1162,8 @@ HAVE_upstart=0 + HAVE_systemd=0 + PKG_CHECK_MODULES(DBUS, dbus-1, ,HAVE_dbus=0) + ++AM_CONDITIONAL(BUILD_DBUS, test $HAVE_dbus = 1) ++ + if test $HAVE_dbus = 1; then + CFLAGS="$CFLAGS `$PKGCONFIG --cflags dbus-1`" + fi +diff --git a/include/portability.h b/include/portability.h +index 4eb6eaa..b1302d2 100644 +--- a/include/portability.h ++++ b/include/portability.h +@@ -177,7 +177,7 @@ g_list_free_full(GList * list, GDestroyNotify free_func) + } + # endif + +-# ifndef HAVE_DBUSBASICVALUE ++# if defined(BUILD_DBUS) && !defined(HAVE_DBUSBASICVALUE) + # include + # include + /** +diff --git a/lib/services/Makefile.am b/lib/services/Makefile.am +index 6ed4d01..96ccdb0 100644 +--- a/lib/services/Makefile.am ++++ b/lib/services/Makefile.am +@@ -23,11 +23,15 @@ INCLUDES = -I$(top_builddir)/include + lib_LTLIBRARIES = libcrmservice.la + noinst_HEADERS = upstart.h systemd.h services_private.h + +-libcrmservice_la_SOURCES = services.c services_linux.c dbus.c ++libcrmservice_la_SOURCES = services.c services_linux.c + libcrmservice_la_LDFLAGS = -version-info 1:0:0 + libcrmservice_la_CFLAGS = $(GIO_CFLAGS) -DOCF_ROOT_DIR=\"@OCF_ROOT_DIR@\" + libcrmservice_la_LIBADD = $(GIO_LIBS) $(top_builddir)/lib/common/libcrmcommon.la $(DBUS_LIBS) + ++if BUILD_DBUS ++libcrmservice_la_SOURCES += dbus.c ++endif ++ + if BUILD_UPSTART + libcrmservice_la_SOURCES += upstart.c + endif diff --git a/SOURCES/bz1057697-pcmk-systemd_simplify_dbus_api_usage.patch b/SOURCES/bz1057697-pcmk-systemd_simplify_dbus_api_usage.patch new file mode 100644 index 0000000..f24694a --- /dev/null +++ b/SOURCES/bz1057697-pcmk-systemd_simplify_dbus_api_usage.patch @@ -0,0 +1,160 @@ +commit 5be9e5b63815cb632b4944f00dd67f6f9dcbff70 +Author: Andrew Beekhof +Date: Mon Feb 3 14:43:38 2014 +1100 + + Refactor: systemd: Simplify dbus API usage + + (cherry picked from commit e3aa2f12bb4f00d4b0d8a38f1dd5727de2eba351) + +diff --git a/lib/services/dbus.c b/lib/services/dbus.c +index a3286f2..a9b1eba 100644 +--- a/lib/services/dbus.c ++++ b/lib/services/dbus.c +@@ -179,7 +179,22 @@ bool pcmk_dbus_send(DBusMessage *msg, DBusConnection *connection, + + bool pcmk_dbus_type_check(DBusMessage *msg, DBusMessageIter *field, int expected, const char *function, int line) + { +- int dtype = dbus_message_iter_get_arg_type(field); ++ int dtype = 0; ++ DBusMessageIter lfield; ++ ++ if(field == NULL) { ++ if(dbus_message_iter_init(msg, &lfield)) { ++ field = &lfield; ++ } ++ } ++ ++ if(field == NULL) { ++ do_crm_log_alias(LOG_ERR, __FILE__, function, line, ++ "Empty parameter list in reply expecting '%c'", expected); ++ return FALSE; ++ } ++ ++ dtype = dbus_message_iter_get_arg_type(field); + + if(dtype != expected) { + DBusMessageIter args; +diff --git a/lib/services/systemd.c b/lib/services/systemd.c +index a06d547..b461c5f 100644 +--- a/lib/services/systemd.c ++++ b/lib/services/systemd.c +@@ -119,7 +119,6 @@ static gboolean + systemd_unit_by_name(const gchar * arg_name, gchar ** out_unit) + { + DBusMessage *msg; +- DBusMessageIter args; + DBusMessage *reply = NULL; + const char *method = "GetUnit"; + char *name = NULL; +@@ -137,6 +136,10 @@ systemd_unit_by_name(const gchar * arg_name, gchar ** out_unit) + + */ + ++ if (systemd_init() == FALSE) { ++ return FALSE; ++ } ++ + name = systemd_service_name(arg_name); + + while(*out_unit == NULL) { +@@ -152,17 +155,19 @@ systemd_unit_by_name(const gchar * arg_name, gchar ** out_unit) + if(error.name) { + crm_info("Call to %s failed: %s", method, error.name); + +- } else if (dbus_message_iter_init(reply, &args)) { ++ } else if(pcmk_dbus_type_check(reply, NULL, DBUS_TYPE_OBJECT_PATH, __FUNCTION__, __LINE__)) { ++ if(out_unit) { ++ char *path = NULL; + +- if(pcmk_dbus_type_check(reply, &args, DBUS_TYPE_OBJECT_PATH, __FUNCTION__, __LINE__)) { +- DBusBasicValue value; ++ dbus_message_get_args (reply, NULL, ++ DBUS_TYPE_OBJECT_PATH, &path, ++ DBUS_TYPE_INVALID); + +- dbus_message_iter_get_basic(&args, &value); +- *out_unit = strdup(value.str); +- dbus_message_unref(reply); +- free(name); +- return TRUE; ++ *out_unit = strdup(path); + } ++ dbus_message_unref(reply); ++ free(name); ++ return TRUE; + } + + if(strcmp(method, "LoadUnit") != 0) { +@@ -171,6 +176,7 @@ systemd_unit_by_name(const gchar * arg_name, gchar ** out_unit) + systemd_daemon_reload(); + if(reply) { + dbus_message_unref(reply); ++ reply = NULL; + } + + } else { +@@ -264,20 +270,7 @@ systemd_unit_listall(void) + gboolean + systemd_unit_exists(const char *name) + { +- char *path = NULL; +- gboolean pass = FALSE; +- +- if (systemd_init() == FALSE) { +- return FALSE; +- } +- +- if(systemd_unit_by_name(name, &path) && path) { +- crm_trace("Got %s", path); +- pass = TRUE; +- } +- +- free(path); +- return pass; ++ return systemd_unit_by_name(name, NULL); + } + + static char * +@@ -360,12 +353,7 @@ systemd_async_dispatch(DBusPendingCall *pending, void *user_data) + } + + } else { +- DBusMessageIter args; +- +- if(!dbus_message_iter_init(reply, &args)) { +- crm_err("Call to %s failed: no arguments", op->action); +- +- } else if(!pcmk_dbus_type_check(reply, &args, DBUS_TYPE_OBJECT_PATH, __FUNCTION__, __LINE__)) { ++ if(!pcmk_dbus_type_check(reply, NULL, DBUS_TYPE_OBJECT_PATH, __FUNCTION__, __LINE__)) { + crm_warn("Call to %s passed but return type was unexpected", op->action); + op->rc = PCMK_OCF_OK; + +@@ -403,7 +391,6 @@ systemd_unit_exec(svc_action_t * op, gboolean synchronous) + char *name = systemd_service_name(op->agent); + DBusMessage *msg = NULL; + DBusMessage *reply = NULL; +- DBusMessageIter args; + + dbus_error_init(&error); + op->rc = PCMK_OCF_UNKNOWN_ERROR; +@@ -499,6 +486,7 @@ systemd_unit_exec(svc_action_t * op, gboolean synchronous) + return pcmk_dbus_send(msg, systemd_proxy, systemd_async_dispatch, op); + } + ++ dbus_error_init(&error); + reply = pcmk_dbus_send_recv(msg, systemd_proxy, &error); + + if(error.name) { +@@ -508,11 +496,7 @@ systemd_unit_exec(svc_action_t * op, gboolean synchronous) + } + goto cleanup; + +- } else if(!dbus_message_iter_init(reply, &args)) { +- crm_err("Call to %s failed: no arguments", method); +- goto cleanup; +- +- } else if(!pcmk_dbus_type_check(reply, &args, DBUS_TYPE_OBJECT_PATH, __FUNCTION__, __LINE__)) { ++ } else if(!pcmk_dbus_type_check(reply, NULL, DBUS_TYPE_OBJECT_PATH, __FUNCTION__, __LINE__)) { + crm_warn("Call to %s passed but return type was unexpected", op->action); + op->rc = PCMK_OCF_OK; + diff --git a/SOURCES/bz1057697-pcmk-use_native_dbus_library_for_systemd_async_support_to_avoid_problematic_use_of_threads.patch b/SOURCES/bz1057697-pcmk-use_native_dbus_library_for_systemd_async_support_to_avoid_problematic_use_of_threads.patch new file mode 100644 index 0000000..aac073c --- /dev/null +++ b/SOURCES/bz1057697-pcmk-use_native_dbus_library_for_systemd_async_support_to_avoid_problematic_use_of_threads.patch @@ -0,0 +1,622 @@ +commit c7ca5eccb5709c75797579f508c3f9ae968cd55e +Author: Andrew Beekhof +Date: Fri Jan 31 10:53:35 2014 +1100 + + Fix: Bug rhbz#1057697 - Use native DBus library for systemd async support to avoid problematic use of threads + + (cherry picked from commit 2f90aad962c63eba313ed466580703434c80bd1a) + +diff --git a/lib/services/dbus.c b/lib/services/dbus.c +index 69ea6ac..a3286f2 100644 +--- a/lib/services/dbus.c ++++ b/lib/services/dbus.c +@@ -4,6 +4,9 @@ + #include + #include + ++#define BUS_PROPERTY_IFACE "org.freedesktop.DBus.Properties" ++ ++ + static bool pcmk_dbus_error_check(DBusError *err, const char *prefix, const char *function, int line) + { + if (err && dbus_error_is_set(err)) { +@@ -43,36 +46,18 @@ bool pcmk_dbus_append_arg(DBusMessage *msg, int dtype, const void *value) + return TRUE; + } + +-DBusMessage *pcmk_dbus_send_recv(DBusMessage *msg, DBusConnection *connection, char **e) ++bool ++pcmk_dbus_find_error(const char *method, DBusPendingCall* pending, DBusMessage *reply, DBusError *ret) + { + DBusError error; +- const char *method = NULL; +- DBusMessage *reply = NULL; +- DBusPendingCall* pending = NULL; + + dbus_error_init(&error); + +- CRM_ASSERT(dbus_message_get_type (msg) == DBUS_MESSAGE_TYPE_METHOD_CALL); +- method = dbus_message_get_member (msg); ++ if(pending == NULL) { ++ error.name = "org.clusterlabs.pacemaker.NoRequest"; ++ error.message = "No request sent"; + +- // send message and get a handle for a reply +- if (!dbus_connection_send_with_reply (connection, msg, &pending, -1)) { // -1 is default timeout +- crm_err("Send with reply failed"); +- return NULL; +- } +- if (NULL == pending) { +- crm_err("No pending call found"); +- return NULL; +- } +- +- dbus_connection_flush(connection); +- +- /* block until we receive a reply */ +- dbus_pending_call_block(pending); +- +- /* get the reply message */ +- reply = dbus_pending_call_steal_reply(pending); +- if(reply == NULL) { ++ } else if(reply == NULL) { + error.name = "org.clusterlabs.pacemaker.NoReply"; + error.message = "No reply"; + +@@ -80,7 +65,6 @@ DBusMessage *pcmk_dbus_send_recv(DBusMessage *msg, DBusConnection *connection, c + DBusMessageIter args; + int dtype = dbus_message_get_type(reply); + +- + switch(dtype) { + case DBUS_MESSAGE_TYPE_METHOD_RETURN: + dbus_message_iter_init(reply, &args); +@@ -104,7 +88,7 @@ DBusMessage *pcmk_dbus_send_recv(DBusMessage *msg, DBusConnection *connection, c + + case DBUS_MESSAGE_TYPE_ERROR: + dbus_set_error_from_message (&error, reply); +- crm_err("%s error '%s': %s", method, error.name, error.message); ++ crm_info("%s error '%s': %s", method, error.name, error.message); + break; + default: + error.message = "Unknown reply type"; +@@ -113,23 +97,86 @@ DBusMessage *pcmk_dbus_send_recv(DBusMessage *msg, DBusConnection *connection, c + } + } + +- if(error.name) { +- if(e) { +- *e = strdup(error.name); ++ if(ret && (error.name || error.message)) { ++ *ret = error; ++ return TRUE; ++ } ++ ++ return FALSE; ++} ++ ++DBusMessage *pcmk_dbus_send_recv(DBusMessage *msg, DBusConnection *connection, DBusError *error) ++{ ++ const char *method = NULL; ++ DBusMessage *reply = NULL; ++ DBusPendingCall* pending = NULL; ++ ++ CRM_ASSERT(dbus_message_get_type (msg) == DBUS_MESSAGE_TYPE_METHOD_CALL); ++ method = dbus_message_get_member (msg); ++ ++ // send message and get a handle for a reply ++ if (!dbus_connection_send_with_reply (connection, msg, &pending, -1)) { // -1 is default timeout ++ if(error) { ++ error->message = "Call to dbus_connection_send_with_reply() failed"; ++ error->name = "org.clusterlabs.pacemaker.SendFailed"; + } ++ crm_err("Error sending %s request", method); ++ return NULL; ++ } ++ ++ dbus_connection_flush(connection); ++ ++ if(pending) { ++ /* block until we receive a reply */ ++ dbus_pending_call_block(pending); ++ ++ /* get the reply message */ ++ reply = dbus_pending_call_steal_reply(pending); ++ } ++ ++ if(pcmk_dbus_find_error(method, pending, reply, error)) { ++ crm_trace("Was error: '%s' '%s'", error->name, error->message); + if(reply) { + dbus_message_unref(reply); + reply = NULL; + } +- } else if(e) { +- *e = NULL; ++ } ++ crm_trace("Was error: '%s' '%s'", error->name, error->message); ++ ++ if(pending) { ++ /* free the pending message handle */ ++ dbus_pending_call_unref(pending); + } + +- /* free the pending message handle */ +- dbus_pending_call_unref(pending); + return reply; + } + ++bool pcmk_dbus_send(DBusMessage *msg, DBusConnection *connection, ++ void(*done)(DBusPendingCall *pending, void *user_data), void *user_data) ++{ ++ DBusError error; ++ const char *method = NULL; ++ DBusPendingCall* pending = NULL; ++ ++ dbus_error_init(&error); ++ ++ CRM_ASSERT(dbus_message_get_type (msg) == DBUS_MESSAGE_TYPE_METHOD_CALL); ++ method = dbus_message_get_member (msg); ++ ++ // send message and get a handle for a reply ++ if (!dbus_connection_send_with_reply (connection, msg, &pending, -1)) { // -1 is default timeout ++ crm_err("Send with reply failed for %s", method); ++ return FALSE; ++ ++ } else if (pending == NULL) { ++ crm_err("No pending call found for %s", method); ++ return FALSE; ++ ++ } ++ CRM_ASSERT(dbus_pending_call_set_notify(pending, done, user_data, NULL)); ++ return TRUE; ++} ++ + bool pcmk_dbus_type_check(DBusMessage *msg, DBusMessageIter *field, int expected, const char *function, int line) + { + int dtype = dbus_message_iter_get_arg_type(field); +@@ -147,8 +194,6 @@ bool pcmk_dbus_type_check(DBusMessage *msg, DBusMessageIter *field, int expected + return TRUE; + } + +-#define BUS_PROPERTY_IFACE "org.freedesktop.DBus.Properties" +- + char * + pcmk_dbus_get_property( + DBusConnection *connection, const char *target, const char *obj, const gchar * iface, const char *name) +@@ -160,10 +205,11 @@ pcmk_dbus_get_property( + /* DBusBasicValue value; */ + const char *method = "GetAll"; + char *output = NULL; +- char *error = NULL; ++ DBusError error; + + /* desc = systemd_unit_property(path, BUS_NAME ".Unit", "Description"); */ + ++ dbus_error_init(&error); + crm_info("Calling: %s on %s", method, target); + msg = dbus_message_new_method_call(target, // target for the method call + obj, // object to call on +@@ -180,7 +226,7 @@ pcmk_dbus_get_property( + reply = pcmk_dbus_send_recv(msg, connection, &error); + dbus_message_unref(msg); + +- if(reply == NULL) { ++ if(error.name) { + crm_err("Call to %s for %s failed: No reply", method, iface); + return NULL; + +@@ -242,20 +288,105 @@ pcmk_dbus_get_property( + return output; + } + ++static void pcmk_dbus_connection_dispatch(DBusConnection *connection, DBusDispatchStatus new_status, void *data){ ++ crm_trace("status %d for %p", new_status, data); ++ if (new_status == DBUS_DISPATCH_DATA_REMAINS){ ++ dbus_connection_dispatch(connection); ++ } ++} ++ ++static int ++pcmk_dbus_watch_dispatch(gpointer userdata) ++{ ++ DBusWatch *watch = userdata; ++ int flags = dbus_watch_get_flags(watch); + ++ crm_trace("Dispatching %p with flags %d", watch, flags); ++ if(flags & DBUS_WATCH_READABLE) { ++ dbus_watch_handle(watch, DBUS_WATCH_READABLE); ++ } else { ++ dbus_watch_handle(watch, DBUS_WATCH_ERROR); ++ } ++ return 0; ++} ++ ++static void ++pcmk_dbus_watch_destroy(gpointer userdata) ++{ ++ crm_trace("Destroyed %p", userdata); ++} + + ++struct mainloop_fd_callbacks pcmk_dbus_cb = { ++ .dispatch = pcmk_dbus_watch_dispatch, ++ .destroy = pcmk_dbus_watch_destroy, ++}; + +-int dbus_watch_get_unix_fd ( DBusWatch * watch ); ++static dbus_bool_t ++pcmk_dbus_watch_add(DBusWatch *watch, void *data){ ++ int fd = dbus_watch_get_unix_fd(watch); + ++ mainloop_io_t *client = mainloop_add_fd( ++ "dbus", G_PRIORITY_DEFAULT, fd, watch, &pcmk_dbus_cb); + +-/* http://dbus.freedesktop.org/doc/api/html/group__DBusConnection.html#gaebf031eb444b4f847606aa27daa3d8e6 */ +- +-DBUS_EXPORT dbus_bool_t dbus_connection_set_watch_functions( +- DBusConnection * connection, +- DBusAddWatchFunction add_function, +- DBusRemoveWatchFunction remove_function, +- DBusWatchToggledFunction toggled_function, +- void * data, +- DBusFreeFunction free_data_function +- ); ++ crm_trace("Added %p with fd=%d", watch, fd); ++ dbus_watch_set_data(watch, client, NULL); ++ return TRUE; ++} ++ ++static void ++pcmk_dbus_watch_remove(DBusWatch *watch, void *data){ ++ mainloop_io_t *client = dbus_watch_get_data(watch); ++ ++ crm_trace("Removed %p", watch); ++ mainloop_del_fd(client); ++} ++ ++static gboolean ++pcmk_dbus_timeout_dispatch(gpointer data) ++{ ++ crm_trace("Timeout for %p"); ++ dbus_timeout_handle(data); ++ return FALSE; ++} ++ ++static dbus_bool_t ++pcmk_dbus_timeout_add(DBusTimeout *timeout, void *data){ ++ guint id = g_timeout_add(dbus_timeout_get_interval(timeout), pcmk_dbus_timeout_dispatch, timeout); ++ ++ if(id) { ++ dbus_timeout_set_data(timeout, GUINT_TO_POINTER(id), NULL); ++ } ++ return TRUE; ++} ++ ++static void ++pcmk_dbus_timeout_remove(DBusTimeout *timeout, void *data){ ++ void *vid = dbus_timeout_get_data(timeout); ++ guint id = GPOINTER_TO_UINT(vid); ++ ++ if(id) { ++ g_source_remove(id); ++ dbus_timeout_set_data(timeout, 0, NULL); ++ } ++} ++ ++static void ++pcmk_dbus_timeout_toggle(DBusTimeout *timeout, void *data){ ++ if(dbus_timeout_get_enabled(timeout)) { ++ pcmk_dbus_timeout_add(timeout, data); ++ } else { ++ pcmk_dbus_timeout_remove(timeout, data); ++ } ++} ++ ++/* Inspired by http://www.kolej.mff.cuni.cz/~vesej3am/devel/dbus-select.c */ ++ ++void pcmk_dbus_connection_setup_with_select(DBusConnection *c){ ++ dbus_connection_set_timeout_functions( ++ c, pcmk_dbus_timeout_add, pcmk_dbus_timeout_remove, pcmk_dbus_timeout_toggle, NULL, NULL); ++ dbus_connection_set_watch_functions(c, pcmk_dbus_watch_add, pcmk_dbus_watch_remove, NULL, NULL, NULL); ++ dbus_connection_set_dispatch_status_function(c, pcmk_dbus_connection_dispatch, NULL, NULL); ++ ++ pcmk_dbus_connection_dispatch(c, dbus_connection_get_dispatch_status(c), NULL); ++} +diff --git a/lib/services/pcmk-dbus.h b/lib/services/pcmk-dbus.h +index 27ac737..c8d2234 100644 +--- a/lib/services/pcmk-dbus.h ++++ b/lib/services/pcmk-dbus.h +@@ -1,7 +1,13 @@ + DBusConnection *pcmk_dbus_connect(void); ++void pcmk_dbus_connection_setup_with_select(DBusConnection *c); + void pcmk_dbus_disconnect(DBusConnection *connection); + +-DBusMessage *pcmk_dbus_send_recv(DBusMessage *msg, DBusConnection *connection, char **error); ++bool pcmk_dbus_send(DBusMessage *msg, DBusConnection *connection, ++ void(*done)(DBusPendingCall *pending, void *user_data), void *user_data); ++DBusMessage *pcmk_dbus_send_recv(DBusMessage *msg, DBusConnection *connection, DBusError *error); + bool pcmk_dbus_append_arg(DBusMessage *msg, int dtype, const void *value); + 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); ++ ++bool pcmk_dbus_find_error(const char *method, DBusPendingCall* pending, DBusMessage *reply, DBusError *error); ++ +diff --git a/lib/services/systemd.c b/lib/services/systemd.c +index 9aa5b03..a06d547 100644 +--- a/lib/services/systemd.c ++++ b/lib/services/systemd.c +@@ -69,6 +69,7 @@ systemd_init(void) + if (need_init) { + need_init = 0; + systemd_proxy = pcmk_dbus_connect(); ++ pcmk_dbus_connection_setup_with_select(systemd_proxy); + } + if (systemd_proxy == NULL) { + return FALSE; +@@ -122,7 +123,7 @@ systemd_unit_by_name(const gchar * arg_name, gchar ** out_unit) + DBusMessage *reply = NULL; + const char *method = "GetUnit"; + char *name = NULL; +- char *error = NULL; ++ DBusError error; + + /* + +@@ -144,13 +145,12 @@ systemd_unit_by_name(const gchar * arg_name, gchar ** out_unit) + + pcmk_dbus_append_arg(msg, DBUS_TYPE_STRING, &name); + ++ dbus_error_init(&error); + reply = pcmk_dbus_send_recv(msg, systemd_proxy, &error); + dbus_message_unref(msg); + +- if(error) { +- crm_info("Call to %s failed: %s", method, error); +- free(error); +- error = NULL; ++ if(error.name) { ++ crm_info("Call to %s failed: %s", method, error.name); + + } else if (dbus_message_iter_init(reply, &args)) { + +@@ -192,7 +192,7 @@ systemd_unit_listall(void) + DBusMessage *msg = NULL; + DBusMessage *reply = NULL; + const char *method = "ListUnits"; +- char *error = NULL; ++ DBusError error; + + if (systemd_init() == FALSE) { + return NULL; +@@ -204,15 +204,15 @@ systemd_unit_listall(void) + " \n" \ + */ + ++ dbus_error_init(&error); + msg = systemd_new_method(BUS_NAME".Manager", method); + CRM_ASSERT(msg != NULL); + + reply = pcmk_dbus_send_recv(msg, systemd_proxy, &error); + dbus_message_unref(msg); + +- if(error) { +- crm_err("Call to %s failed: %s", method, error); +- free(error); ++ if(error.name) { ++ crm_err("Call to %s failed: %s", method, error.name); + return NULL; + + } else if (!dbus_message_iter_init(reply, &args)) { +@@ -318,64 +318,84 @@ systemd_unit_metadata(const char *name) + return meta; + } + +-#if 0 ++static bool ++systemd_mask_error(svc_action_t *op, const char *error) ++{ ++ crm_trace("Could not issue %s for %s: %s", op->action, op->rsc, error); ++ if(strstr(error, "org.freedesktop.systemd1.InvalidName") ++ || strstr(error, "org.freedesktop.systemd1.LoadFailed") ++ || strstr(error, "org.freedesktop.systemd1.NoSuchUnit")) { ++ ++ if (safe_str_eq(op->action, "stop")) { ++ crm_trace("Masking %s failure for %s: unknown services are stopped", op->action, op->rsc); ++ op->rc = PCMK_OCF_OK; ++ ++ } else { ++ crm_trace("Mapping %s failure for %s: unknown services are not installed", op->action, op->rsc); ++ op->rc = PCMK_OCF_NOT_INSTALLED; ++ op->status = PCMK_LRM_OP_NOT_INSTALLED; ++ } ++ return TRUE; ++ } ++ ++ return FALSE; ++} ++ + static void +-systemd_unit_exec_done(GObject * source_object, GAsyncResult * res, gpointer user_data) ++systemd_async_dispatch(DBusPendingCall *pending, void *user_data) + { +- GError *error = NULL; +- GVariant *_ret = NULL; ++ DBusError error; ++ DBusMessage *reply = NULL; + svc_action_t *op = user_data; +- GDBusProxy *proxy = G_DBUS_PROXY(source_object); + +- /* Obtain rc and stderr/out */ +- _ret = g_dbus_proxy_call_finish(proxy, res, &error); ++ dbus_error_init(&error); ++ if(pending) { ++ reply = dbus_pending_call_steal_reply(pending); ++ } ++ if(pcmk_dbus_find_error(op->action, pending, reply, &error)) { + +- if (error) { + /* ignore "already started" or "not running" errors */ +- crm_trace("Could not issue %s for %s: %s", op->action, op->rsc, error->message); +- if (strstr(error->message, "systemd1.LoadFailed") +- || strstr(error->message, "systemd1.InvalidName")) { ++ if (!systemd_mask_error(op, error.name)) { ++ crm_err("%s for %s: %s", op->action, op->rsc, error.message); ++ } + +- if (safe_str_eq(op->action, "stop")) { +- crm_trace("Masking Stop failure for %s: unknown services are stopped", op->rsc); +- op->rc = PCMK_OCF_OK; ++ } else { ++ DBusMessageIter args; + +- } else { +- op->rc = PCMK_OCF_NOT_INSTALLED; +- op->status = PCMK_LRM_OP_NOT_INSTALLED; +- } ++ if(!dbus_message_iter_init(reply, &args)) { ++ crm_err("Call to %s failed: no arguments", op->action); + +- } else { +- crm_err("Could not issue %s for %s: %s", op->action, op->rsc, error->message); +- } +- g_error_free(error); +- +- } else if(g_variant_is_of_type (_ret, G_VARIANT_TYPE("(o)"))) { +- char *path = NULL; ++ } else if(!pcmk_dbus_type_check(reply, &args, DBUS_TYPE_OBJECT_PATH, __FUNCTION__, __LINE__)) { ++ crm_warn("Call to %s passed but return type was unexpected", op->action); ++ op->rc = PCMK_OCF_OK; + +- g_variant_get(_ret, "(o)", &path); +- crm_info("Call to %s passed: type '%s' %s", op->action, g_variant_get_type_string(_ret), +- path); +- op->rc = PCMK_OCF_OK; ++ } else { ++ const char *path = NULL; + +- } else { +- crm_err("Call to %s passed but return type was '%s' not '(o)'", op->action, g_variant_get_type_string(_ret)); +- op->rc = PCMK_OCF_OK; ++ dbus_message_get_args (reply, NULL, ++ DBUS_TYPE_OBJECT_PATH, &path, ++ DBUS_TYPE_INVALID); ++ crm_info("Call to %s passed: %s", op->action, path); ++ op->rc = PCMK_OCF_OK; ++ } + } + + operation_finalize(op); +- if (_ret) { +- g_variant_unref(_ret); ++ ++ if(pending) { ++ dbus_pending_call_unref(pending); ++ } ++ if(reply) { ++ dbus_message_unref(reply); + } + } +-#endif + + #define SYSTEMD_OVERRIDE_ROOT "/run/systemd/system/" + + gboolean + systemd_unit_exec(svc_action_t * op, gboolean synchronous) + { +- char *error = NULL; ++ DBusError error; + char *unit = NULL; + const char *replace_s = "replace"; + gboolean pass = FALSE; +@@ -384,7 +404,8 @@ systemd_unit_exec(svc_action_t * op, gboolean synchronous) + DBusMessage *msg = NULL; + DBusMessage *reply = NULL; + DBusMessageIter args; +- ++ ++ dbus_error_init(&error); + op->rc = PCMK_OCF_UNKNOWN_ERROR; + CRM_ASSERT(systemd_init()); + +@@ -465,16 +486,6 @@ systemd_unit_exec(svc_action_t * op, gboolean synchronous) + + crm_debug("Calling %s for %s: %s", method, op->rsc, unit); + +-#if 0 +- if (synchronous == FALSE) { +- g_dbus_proxy_call(systemd_proxy, method, g_variant_new("(ss)", name, "replace"), +- G_DBUS_CALL_FLAGS_NONE, op->timeout, NULL, systemd_unit_exec_done, op); +- free(unit); +- free(name); +- return TRUE; +- } +-#endif +- + msg = systemd_new_method(BUS_NAME".Manager", method); + CRM_ASSERT(msg != NULL); + +@@ -482,43 +493,47 @@ systemd_unit_exec(svc_action_t * op, gboolean synchronous) + pcmk_dbus_append_arg(msg, DBUS_TYPE_STRING, &name); + pcmk_dbus_append_arg(msg, DBUS_TYPE_STRING, &replace_s); + ++ if (synchronous == FALSE) { ++ free(unit); ++ free(name); ++ return pcmk_dbus_send(msg, systemd_proxy, systemd_async_dispatch, op); ++ } ++ + reply = pcmk_dbus_send_recv(msg, systemd_proxy, &error); +- dbus_message_unref(msg); + +- if(error) { ++ if(error.name) { + /* ignore "already started" or "not running" errors */ +- if (safe_str_eq(op->action, "stop") +- && (strstr(error, "org.freedesktop.systemd1.InvalidName") +- || strstr(error, "org.freedesktop.systemd1.NoSuchUnit"))) { +- crm_trace("Masking Stop failure for %s: unknown services are stopped", op->rsc); +- op->rc = PCMK_OCF_OK; +- } else { +- crm_err("Could not issue %s for %s: %s (%s)", method, op->rsc, error, unit); ++ if(!systemd_mask_error(op, error.name)) { ++ crm_err("Could not issue %s for %s: %s (%s)", method, op->rsc, error.name, unit); + } + goto cleanup; + + } else if(!dbus_message_iter_init(reply, &args)) { + crm_err("Call to %s failed: no arguments", method); + goto cleanup; +- } + +- /* (o) */ +- if(!pcmk_dbus_type_check(reply, &args, DBUS_TYPE_OBJECT_PATH, __FUNCTION__, __LINE__)) { +- crm_err("Call to %s failed: Message has invalid arguments", method); ++ } else if(!pcmk_dbus_type_check(reply, &args, DBUS_TYPE_OBJECT_PATH, __FUNCTION__, __LINE__)) { ++ crm_warn("Call to %s passed but return type was unexpected", op->action); ++ op->rc = PCMK_OCF_OK; + + } else { +- DBusBasicValue value; ++ const char *path = NULL; + +- dbus_message_iter_get_basic(&args, &value); +- crm_info("Call to %s passed: %s", op->action, value.str); ++ dbus_message_get_args (reply, NULL, ++ DBUS_TYPE_OBJECT_PATH, &path, ++ DBUS_TYPE_INVALID); ++ crm_info("Call to %s passed: %s", op->action, path); + op->rc = PCMK_OCF_OK; + } + + cleanup: +- free(error); + free(unit); + free(name); + ++ if(msg) { ++ dbus_message_unref(msg); ++ } ++ + if(reply) { + dbus_message_unref(reply); + } diff --git a/SOURCES/bz1057697-pcmk-use_native_dbus_library_for_systemd_support_to_avoid_problematic_use_of_threads.patch b/SOURCES/bz1057697-pcmk-use_native_dbus_library_for_systemd_support_to_avoid_problematic_use_of_threads.patch new file mode 100644 index 0000000..b5cb93b --- /dev/null +++ b/SOURCES/bz1057697-pcmk-use_native_dbus_library_for_systemd_support_to_avoid_problematic_use_of_threads.patch @@ -0,0 +1,1012 @@ +commit 6b3f1e2e65db9d6fe229ccda22567a80d14efc3c +Author: Andrew Beekhof +Date: Thu Jan 30 08:23:35 2014 +1100 + + Fix: Bug rhbz#1057697 - Use native DBus library for systemd support to avoid problematic use of threads + + (cherry picked from commit 24404bfa83f32357e8fa2d7e80b1dd7c6a893244) + +diff --git a/configure.ac b/configure.ac +index b94c26e..628f46f 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -1157,20 +1157,22 @@ AC_DEFINE_UNQUOTED(BUILD_VERSION, "$BUILD_VERSION", Build version) + AC_SUBST(BUILD_VERSION) + + +-HAVE_gio=1 ++HAVE_dbus=1 + HAVE_upstart=0 + HAVE_systemd=0 +-PKG_CHECK_MODULES(GIO, gio-2.0, ,HAVE_gio=0) ++PKG_CHECK_MODULES(DBUS, dbus-1, ,HAVE_dbus=0) + +-AC_CHECK_TYPE([GDBusProxy],,,[[#include ]]) +- +-if test x$ac_cv_type_GDBusProxy != xyes; then +- HAVE_gio=0 +- AC_MSG_WARN(Unable to support systemd/upstart. You need to use glib >= 2.26) ++if test $HAVE_dbus = 1; then ++ CFLAGS="$CFLAGS `$PKGCONFIG --cflags dbus-1`" + fi + +-if test $HAVE_gio = 1 -a "x${enable_upstart}" != xno; then +- HAVE_upstart=1 ++DBUS_LIBS="$CFLAGS `$PKGCONFIG --libs dbus-1`" ++AC_SUBST(DBUS_LIBS) ++ ++AC_CHECK_TYPES([DBusBasicValue],,,[[#include ]]) ++ ++if test $HAVE_dbus = 1 -a "x${enable_upstart}" != xno; then ++ HAVE_upstart=0 + PCMK_FEATURES="$PCMK_FEATURES upstart" + fi + +@@ -1186,7 +1188,7 @@ else + enable_systemd=no + fi + +-if test $HAVE_gio = 1 -a "x${enable_systemd}" != xno; then ++if test $HAVE_dbus = 1 -a "x${enable_systemd}" != xno; then + if test -n "$systemdunitdir" -a "x$systemdunitdir" != xno; then + HAVE_systemd=1 + PCMK_FEATURES="$PCMK_FEATURES systemd" +diff --git a/include/portability.h b/include/portability.h +index b0f9f1c..29d1177 100644 +--- a/include/portability.h ++++ b/include/portability.h +@@ -177,6 +177,48 @@ g_list_free_full(GList * list, GDestroyNotify free_func) + } + # endif + ++# ifndef HAVE_DBUSBASICVALUE ++# include ++/** ++ * An 8-byte struct you could use to access int64 without having ++ * int64 support ++ */ ++typedef struct ++{ ++ dbus_uint32_t first32; /**< first 32 bits in the 8 bytes (beware endian issues) */ ++ dbus_uint32_t second32; /**< second 32 bits in the 8 bytes (beware endian issues) */ ++} DBus8ByteStruct; ++ ++/** ++ * A simple value union that lets you access bytes as if they ++ * were various types; useful when dealing with basic types via ++ * void pointers and varargs. ++ * ++ * This union also contains a pointer member (which can be used ++ * to retrieve a string from dbus_message_iter_get_basic(), for ++ * instance), so on future platforms it could conceivably be larger ++ * than 8 bytes. ++ */ ++typedef union ++{ ++ unsigned char bytes[8]; /**< as 8 individual bytes */ ++ dbus_int16_t i16; /**< as int16 */ ++ dbus_uint16_t u16; /**< as int16 */ ++ dbus_int32_t i32; /**< as int32 */ ++ dbus_uint32_t u32; /**< as int32 */ ++ dbus_bool_t bool_val; /**< as boolean */ ++# ifdef DBUS_HAVE_INT64 ++ dbus_int64_t i64; /**< as int64 */ ++ dbus_uint64_t u64; /**< as int64 */ ++# endif ++ DBus8ByteStruct eight; /**< as 8-byte struct */ ++ double dbl; /**< as double */ ++ unsigned char byt; /**< as byte */ ++ char *str; /**< as char* (string, object path or signature) */ ++ int fd; /**< as Unix file descriptor */ ++} DBusBasicValue; ++# endif ++ + /* Replacement error codes for non-linux */ + # ifndef ENOTUNIQ + # define ENOTUNIQ 190 +diff --git a/lib/services/Makefile.am b/lib/services/Makefile.am +index 67d7237..6ed4d01 100644 +--- a/lib/services/Makefile.am ++++ b/lib/services/Makefile.am +@@ -23,10 +23,10 @@ INCLUDES = -I$(top_builddir)/include + lib_LTLIBRARIES = libcrmservice.la + noinst_HEADERS = upstart.h systemd.h services_private.h + +-libcrmservice_la_SOURCES = services.c services_linux.c ++libcrmservice_la_SOURCES = services.c services_linux.c dbus.c + libcrmservice_la_LDFLAGS = -version-info 1:0:0 + libcrmservice_la_CFLAGS = $(GIO_CFLAGS) -DOCF_ROOT_DIR=\"@OCF_ROOT_DIR@\" +-libcrmservice_la_LIBADD = $(GIO_LIBS) $(top_builddir)/lib/common/libcrmcommon.la ++libcrmservice_la_LIBADD = $(GIO_LIBS) $(top_builddir)/lib/common/libcrmcommon.la $(DBUS_LIBS) + + if BUILD_UPSTART + libcrmservice_la_SOURCES += upstart.c +diff --git a/lib/services/dbus.c b/lib/services/dbus.c +new file mode 100644 +index 0000000..69ea6ac +--- /dev/null ++++ b/lib/services/dbus.c +@@ -0,0 +1,261 @@ ++#include ++#include ++#include ++#include ++#include ++ ++static bool pcmk_dbus_error_check(DBusError *err, const char *prefix, const char *function, int line) ++{ ++ if (err && dbus_error_is_set(err)) { ++ do_crm_log_alias(LOG_ERR, __FILE__, function, line, "%s: DBus error '%s'", prefix, err->message); ++ dbus_error_free(err); ++ return TRUE; ++ } ++ return FALSE; ++} ++ ++DBusConnection *pcmk_dbus_connect(void) ++{ ++ DBusError err; ++ DBusConnection *connection; ++ ++ dbus_error_init(&err); ++ connection = dbus_bus_get(DBUS_BUS_SYSTEM, &err); ++ pcmk_dbus_error_check(&err, "Could not connect to System DBus", __FUNCTION__, __LINE__); ++ ++ return connection; ++} ++ ++void pcmk_dbus_disconnect(DBusConnection *connection) ++{ ++} ++ ++bool pcmk_dbus_append_arg(DBusMessage *msg, int dtype, const void *value) ++{ ++ DBusMessageIter args; ++ ++ dbus_message_iter_init_append(msg, &args); ++ if (!dbus_message_iter_append_basic(&args, dtype, value)) { ++ crm_err("dbus_message_iter_append_basic(%c) failed", dtype); ++ return FALSE; ++ } ++ ++ return TRUE; ++} ++ ++DBusMessage *pcmk_dbus_send_recv(DBusMessage *msg, DBusConnection *connection, char **e) ++{ ++ DBusError error; ++ const char *method = NULL; ++ DBusMessage *reply = NULL; ++ DBusPendingCall* pending = NULL; ++ ++ dbus_error_init(&error); ++ ++ CRM_ASSERT(dbus_message_get_type (msg) == DBUS_MESSAGE_TYPE_METHOD_CALL); ++ method = dbus_message_get_member (msg); ++ ++ // send message and get a handle for a reply ++ if (!dbus_connection_send_with_reply (connection, msg, &pending, -1)) { // -1 is default timeout ++ crm_err("Send with reply failed"); ++ return NULL; ++ } ++ if (NULL == pending) { ++ crm_err("No pending call found"); ++ return NULL; ++ } ++ ++ dbus_connection_flush(connection); ++ ++ /* block until we receive a reply */ ++ dbus_pending_call_block(pending); ++ ++ /* get the reply message */ ++ reply = dbus_pending_call_steal_reply(pending); ++ if(reply == NULL) { ++ error.name = "org.clusterlabs.pacemaker.NoReply"; ++ error.message = "No reply"; ++ ++ } else { ++ DBusMessageIter args; ++ int dtype = dbus_message_get_type(reply); ++ ++ ++ switch(dtype) { ++ case DBUS_MESSAGE_TYPE_METHOD_RETURN: ++ dbus_message_iter_init(reply, &args); ++ crm_trace("Call to %s returned '%s'", method, dbus_message_iter_get_signature(&args)); ++ break; ++ case DBUS_MESSAGE_TYPE_INVALID: ++ error.message = "Invalid reply"; ++ error.name = "org.clusterlabs.pacemaker.InvalidReply"; ++ crm_err("Error processing %s response: %s", method, error.message); ++ break; ++ case DBUS_MESSAGE_TYPE_METHOD_CALL: ++ error.message = "Invalid reply (method call)"; ++ error.name = "org.clusterlabs.pacemaker.InvalidReply.Method"; ++ crm_err("Error processing %s response: %s", method, error.message); ++ break; ++ case DBUS_MESSAGE_TYPE_SIGNAL: ++ error.message = "Invalid reply (signal)"; ++ error.name = "org.clusterlabs.pacemaker.InvalidReply.Signal"; ++ crm_err("Error processing %s response: %s", method, error.message); ++ break; ++ ++ case DBUS_MESSAGE_TYPE_ERROR: ++ dbus_set_error_from_message (&error, reply); ++ crm_err("%s error '%s': %s", method, error.name, error.message); ++ break; ++ default: ++ error.message = "Unknown reply type"; ++ error.name = "org.clusterlabs.pacemaker.InvalidReply.Type"; ++ crm_err("Error processing %s response: %s (%d)", method, error.message, dtype); ++ } ++ } ++ ++ if(error.name) { ++ if(e) { ++ *e = strdup(error.name); ++ } ++ if(reply) { ++ dbus_message_unref(reply); ++ reply = NULL; ++ } ++ } else if(e) { ++ *e = NULL; ++ } ++ ++ /* free the pending message handle */ ++ dbus_pending_call_unref(pending); ++ return reply; ++} ++ ++bool pcmk_dbus_type_check(DBusMessage *msg, DBusMessageIter *field, int expected, const char *function, int line) ++{ ++ int dtype = dbus_message_iter_get_arg_type(field); ++ ++ if(dtype != expected) { ++ DBusMessageIter args; ++ ++ dbus_message_iter_init(msg, &args); ++ do_crm_log_alias(LOG_ERR, __FILE__, function, line, ++ "Unexepcted DBus type, expected %c instead of %c in '%s'", ++ expected, dtype, dbus_message_iter_get_signature(&args)); ++ return FALSE; ++ } ++ ++ return TRUE; ++} ++ ++#define BUS_PROPERTY_IFACE "org.freedesktop.DBus.Properties" ++ ++char * ++pcmk_dbus_get_property( ++ DBusConnection *connection, const char *target, const char *obj, const gchar * iface, const char *name) ++{ ++ DBusMessage *msg; ++ DBusMessageIter args; ++ DBusMessageIter dict; ++ DBusMessage *reply = NULL; ++ /* DBusBasicValue value; */ ++ const char *method = "GetAll"; ++ char *output = NULL; ++ char *error = NULL; ++ ++ /* desc = systemd_unit_property(path, BUS_NAME ".Unit", "Description"); */ ++ ++ crm_info("Calling: %s on %s", method, target); ++ msg = dbus_message_new_method_call(target, // target for the method call ++ obj, // object to call on ++ BUS_PROPERTY_IFACE, // interface to call on ++ method); // method name ++ ++ if (NULL == msg) { ++ crm_err("Call to %s failed: No message", method); ++ return NULL; ++ } ++ ++ pcmk_dbus_append_arg(msg, DBUS_TYPE_STRING, &iface); ++ ++ reply = pcmk_dbus_send_recv(msg, connection, &error); ++ dbus_message_unref(msg); ++ ++ if(reply == NULL) { ++ crm_err("Call to %s for %s failed: No reply", method, iface); ++ return NULL; ++ ++ } else if (!dbus_message_iter_init(reply, &args)) { ++ crm_err("Cannot get properties for %s from %s", obj, iface); ++ return NULL; ++ } ++ ++ if(!pcmk_dbus_type_check(reply, &args, DBUS_TYPE_ARRAY, __FUNCTION__, __LINE__)) { ++ crm_err("Call to %s failed: Message has invalid arguments", method); ++ dbus_message_unref(reply); ++ return NULL; ++ } ++ ++ dbus_message_iter_recurse(&args, &dict); ++ while (dbus_message_iter_get_arg_type (&dict) != DBUS_TYPE_INVALID) { ++ DBusMessageIter sv; ++ DBusMessageIter v; ++ DBusBasicValue value; ++ ++ if(!pcmk_dbus_type_check(reply, &dict, DBUS_TYPE_DICT_ENTRY, __FUNCTION__, __LINE__)) { ++ dbus_message_iter_next (&dict); ++ continue; ++ } ++ ++ dbus_message_iter_recurse(&dict, &sv); ++ while (dbus_message_iter_get_arg_type (&sv) != DBUS_TYPE_INVALID) { ++ int dtype = dbus_message_iter_get_arg_type(&sv); ++ ++ switch(dtype) { ++ case DBUS_TYPE_STRING: ++ dbus_message_iter_get_basic(&sv, &value); ++ ++ crm_trace("Got: %s", value.str); ++ if(strcmp(value.str, name) != 0) { ++ dbus_message_iter_next (&sv); /* Skip the value */ ++ } ++ break; ++ case DBUS_TYPE_VARIANT: ++ dbus_message_iter_recurse(&sv, &v); ++ if(pcmk_dbus_type_check(reply, &v, DBUS_TYPE_STRING, __FUNCTION__, __LINE__)) { ++ dbus_message_iter_get_basic(&v, &value); ++ ++ crm_trace("Result: %s", value.str); ++ output = strdup(value.str); ++ } ++ break; ++ default: ++ pcmk_dbus_type_check(reply, &sv, DBUS_TYPE_STRING, __FUNCTION__, __LINE__); ++ } ++ dbus_message_iter_next (&sv); ++ } ++ ++ dbus_message_iter_next (&dict); ++ } ++ ++ ++ crm_trace("Property %s[%s] is '%s'", obj, name, output); ++ return output; ++} ++ ++ ++ ++ ++ ++int dbus_watch_get_unix_fd ( DBusWatch * watch ); ++ ++ ++/* http://dbus.freedesktop.org/doc/api/html/group__DBusConnection.html#gaebf031eb444b4f847606aa27daa3d8e6 */ ++ ++DBUS_EXPORT dbus_bool_t dbus_connection_set_watch_functions( ++ DBusConnection * connection, ++ DBusAddWatchFunction add_function, ++ DBusRemoveWatchFunction remove_function, ++ DBusWatchToggledFunction toggled_function, ++ void * data, ++ DBusFreeFunction free_data_function ++ ); +diff --git a/lib/services/pcmk-dbus.h b/lib/services/pcmk-dbus.h +new file mode 100644 +index 0000000..27ac737 +--- /dev/null ++++ b/lib/services/pcmk-dbus.h +@@ -0,0 +1,7 @@ ++DBusConnection *pcmk_dbus_connect(void); ++void pcmk_dbus_disconnect(DBusConnection *connection); ++ ++DBusMessage *pcmk_dbus_send_recv(DBusMessage *msg, DBusConnection *connection, char **error); ++bool pcmk_dbus_append_arg(DBusMessage *msg, int dtype, const void *value); ++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); +diff --git a/lib/services/systemd.c b/lib/services/systemd.c +index ea804c8..9aa5b03 100644 +--- a/lib/services/systemd.c ++++ b/lib/services/systemd.c +@@ -24,6 +24,8 @@ + #include + #include + #include ++#include ++#include + + #define BUS_NAME "org.freedesktop.systemd1" + #define BUS_PATH "/org/freedesktop/systemd1" +@@ -47,42 +49,26 @@ struct unit_info { + const char *job_path; + }; + +-static GDBusProxy *systemd_proxy = NULL; +- +-static GDBusProxy * +-get_proxy(const char *path, const char *interface) ++static DBusMessage *systemd_new_method(const char *iface, const char *method) + { +- GError *error = NULL; +- GDBusProxy *proxy = NULL; +- +-#ifndef GLIB_DEPRECATED_IN_2_36 +- g_type_init(); +-#endif +- +- if (path == NULL) { +- path = BUS_PATH; +- } +- +- proxy = g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, NULL, /* GDBusInterfaceInfo */ +- BUS_NAME, path, interface, +- NULL, /* GCancellable */ &error); +- +- if (error) { +- crm_err("Can't connect obtain proxy to %s interface: %s", interface, error->message); +- g_error_free(error); +- proxy = NULL; +- } +- return proxy; ++ crm_trace("Calling: %s on %s", method, iface); ++ return dbus_message_new_method_call(BUS_NAME, // target for the method call ++ BUS_PATH, // object to call on ++ iface, // interface to call on ++ method); // method name + } + ++ ++static DBusConnection* systemd_proxy = NULL; + static gboolean + systemd_init(void) + { + static int need_init = 1; ++ /* http://dbus.freedesktop.org/doc/api/html/group__DBusConnection.html */ + + if (need_init) { + need_init = 0; +- systemd_proxy = get_proxy(NULL, BUS_NAME ".Manager"); ++ systemd_proxy = pcmk_dbus_connect(); + } + if (systemd_proxy == NULL) { + return FALSE; +@@ -94,7 +80,7 @@ void + systemd_cleanup(void) + { + if (systemd_proxy) { +- g_object_unref(systemd_proxy); ++ pcmk_dbus_disconnect(systemd_proxy); + systemd_proxy = NULL; + } + } +@@ -112,130 +98,87 @@ systemd_service_name(const char *name) + return g_strdup_printf("%s.service", name); + } + +-static void +-systemd_daemon_reload(GDBusProxy * proxy, GError ** error) ++static bool ++systemd_daemon_reload(void) + { +- GVariant *_ret = g_dbus_proxy_call_sync(proxy, "Reload", g_variant_new("()"), +- G_DBUS_CALL_FLAGS_NONE, -1, NULL, error); +- +- if (_ret) { +- g_variant_unref(_ret); ++ const char *method = "Reload"; ++ DBusMessage *reply = NULL; ++ DBusMessage *msg = systemd_new_method(BUS_NAME".Manager", method); ++ ++ CRM_ASSERT(msg != NULL); ++ reply = pcmk_dbus_send_recv(msg, systemd_proxy, NULL); ++ dbus_message_unref(msg); ++ if(reply) { ++ dbus_message_unref(reply); + } ++ return TRUE; + } + + static gboolean +-systemd_unit_by_name(GDBusProxy * proxy, +- const gchar * arg_name, +- gchar ** out_unit, GCancellable * cancellable, GError ** error) ++systemd_unit_by_name(const gchar * arg_name, gchar ** out_unit) + { +- GError *reload_error = NULL; +- GVariant *_ret = NULL; ++ DBusMessage *msg; ++ DBusMessageIter args; ++ DBusMessage *reply = NULL; ++ const char *method = "GetUnit"; + char *name = NULL; +- int retry = 0; ++ char *error = NULL; + + /* +- " \n" \ +- " \n" \ +- " \n" \ +- " \n" \ +-*/ +- +- name = systemd_service_name(arg_name); +- crm_debug("Calling GetUnit"); +- _ret = g_dbus_proxy_call_sync(proxy, "GetUnit", g_variant_new("(s)", name), +- G_DBUS_CALL_FLAGS_NONE, -1, cancellable, error); +- +- if (_ret) { +- crm_debug("Checking output"); +- g_variant_get(_ret, "(o)", out_unit); +- crm_debug("%s = %s", arg_name, *out_unit); +- g_variant_unref(_ret); +- goto done; +- } +- +- crm_debug("Reloading the systemd manager configuration"); +- systemd_daemon_reload(proxy, &reload_error); +- retry++; +- +- if (reload_error) { +- crm_err("Cannot reload the systemd manager configuration: %s", reload_error->message); +- g_error_free(reload_error); +- goto done; +- } +- +- if (*error) { +- crm_debug("Cannot find %s: %s", name, (*error)->message); +- g_error_free(*error); +- *error = NULL; +- } ++ ++ ++ ++ + +-/* + + + + + */ +- crm_debug("Calling LoadUnit"); +- _ret = g_dbus_proxy_call_sync(proxy, "LoadUnit", g_variant_new("(s)", name), +- G_DBUS_CALL_FLAGS_NONE, -1, cancellable, error); + +- if (_ret) { +- crm_debug("Checking output"); +- g_variant_get(_ret, "(o)", out_unit); +- crm_debug("%s = %s", arg_name, *out_unit); +- g_variant_unref(_ret); +- } ++ name = systemd_service_name(arg_name); + +- done: +- free(name); +- return _ret != NULL; +-} ++ while(*out_unit == NULL) { ++ msg = systemd_new_method(BUS_NAME".Manager", method); ++ CRM_ASSERT(msg != NULL); + +-static char * +-systemd_unit_property(const char *obj, const gchar * iface, const char *name) +-{ +- GError *error = NULL; +- GDBusProxy *proxy; +- GVariant *asv = NULL; +- GVariant *value = NULL; +- GVariant *_ret = NULL; +- char *output = NULL; ++ pcmk_dbus_append_arg(msg, DBUS_TYPE_STRING, &name); + +- crm_trace("Calling GetAll on %s", obj); +- proxy = get_proxy(obj, BUS_PROPERTY_IFACE); ++ reply = pcmk_dbus_send_recv(msg, systemd_proxy, &error); ++ dbus_message_unref(msg); + +- if (!proxy) { +- return NULL; +- } ++ if(error) { ++ crm_info("Call to %s failed: %s", method, error); ++ free(error); ++ error = NULL; + +- _ret = g_dbus_proxy_call_sync(proxy, "GetAll", g_variant_new("(s)", iface), +- G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); ++ } else if (dbus_message_iter_init(reply, &args)) { + +- if (error) { +- crm_err("Cannot get properties for %s: %s", g_dbus_proxy_get_object_path(proxy), +- error->message); +- g_error_free(error); +- g_object_unref(proxy); +- return NULL; +- } +- crm_debug("Call to GetAll passed: type '%s' %d\n", g_variant_get_type_string(_ret), +- g_variant_n_children(_ret)); ++ if(pcmk_dbus_type_check(reply, &args, DBUS_TYPE_OBJECT_PATH, __FUNCTION__, __LINE__)) { ++ DBusBasicValue value; + +- asv = g_variant_get_child_value(_ret, 0); +- crm_trace("asv type '%s' %d\n", g_variant_get_type_string(asv), g_variant_n_children(asv)); ++ dbus_message_iter_get_basic(&args, &value); ++ *out_unit = strdup(value.str); ++ dbus_message_unref(reply); ++ free(name); ++ return TRUE; ++ } ++ } + +- value = g_variant_lookup_value(asv, name, NULL); +- if (value && g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)) { +- crm_info("Got value '%s' for %s[%s]", g_variant_get_string(value, NULL), obj, name); +- output = g_variant_dup_string(value, NULL); ++ if(strcmp(method, "LoadUnit") != 0) { ++ method = "LoadUnit"; ++ crm_debug("Cannot find %s, reloading the systemd manager configuration", name); ++ systemd_daemon_reload(); ++ if(reply) { ++ dbus_message_unref(reply); ++ } + +- } else { +- crm_info("No value for %s[%s]", obj, name); ++ } else { ++ free(name); ++ return FALSE; ++ } + } +- +- g_object_unref(proxy); +- g_variant_unref(_ret); +- return output; ++ return FALSE; + } + + GList * +@@ -243,11 +186,13 @@ systemd_unit_listall(void) + { + int lpc = 0; + GList *units = NULL; +- GError *error = NULL; +- GVariant *out_units = NULL; +- GVariantIter iter; +- struct unit_info u; +- GVariant *_ret = NULL; ++ DBusMessageIter args; ++ DBusMessageIter unit; ++ DBusMessageIter elem; ++ DBusMessage *msg = NULL; ++ DBusMessage *reply = NULL; ++ const char *method = "ListUnits"; ++ char *error = NULL; + + if (systemd_init() == FALSE) { + return NULL; +@@ -259,40 +204,60 @@ systemd_unit_listall(void) + " \n" \ + */ + +- _ret = g_dbus_proxy_call_sync(systemd_proxy, "ListUnits", g_variant_new("()"), +- G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); ++ msg = systemd_new_method(BUS_NAME".Manager", method); ++ CRM_ASSERT(msg != NULL); + +- if (error || _ret == NULL) { +- crm_info("Call to ListUnits failed: %s", error ? error->message : "unknown"); +- if(error) { +- g_error_free(error); +- } ++ reply = pcmk_dbus_send_recv(msg, systemd_proxy, &error); ++ dbus_message_unref(msg); ++ ++ if(error) { ++ crm_err("Call to %s failed: %s", method, error); ++ free(error); ++ return NULL; ++ ++ } else if (!dbus_message_iter_init(reply, &args)) { ++ crm_err("Call to %s failed: Message has no arguments", method); ++ dbus_message_unref(reply); + return NULL; + } + +- g_variant_get(_ret, "(@a(ssssssouso))", &out_units); +- +- g_variant_iter_init(&iter, out_units); +- while (g_variant_iter_loop(&iter, "(ssssssouso)", +- &u.id, +- &u.description, +- &u.load_state, +- &u.active_state, +- &u.sub_state, +- &u.following, &u.unit_path, &u.job_id, &u.job_type, &u.job_path)) { +- char *match = strstr(u.id, ".service"); +- +- if (match) { +- lpc++; +- match[0] = 0; +- crm_trace("Got %s[%s] = %s", u.id, u.active_state, u.description); +- units = g_list_append(units, strdup(u.id)); ++ if(!pcmk_dbus_type_check(reply, &args, DBUS_TYPE_ARRAY, __FUNCTION__, __LINE__)) { ++ crm_err("Call to %s failed: Message has invalid arguments", method); ++ dbus_message_unref(reply); ++ return NULL; ++ } ++ ++ dbus_message_iter_recurse(&args, &unit); ++ while (dbus_message_iter_get_arg_type (&unit) != DBUS_TYPE_INVALID) { ++ DBusBasicValue value; ++ ++ if(!pcmk_dbus_type_check(reply, &unit, DBUS_TYPE_STRUCT, __FUNCTION__, __LINE__)) { ++ continue; + } ++ ++ dbus_message_iter_recurse(&unit, &elem); ++ if(!pcmk_dbus_type_check(reply, &elem, DBUS_TYPE_STRING, __FUNCTION__, __LINE__)) { ++ continue; ++ } ++ ++ dbus_message_iter_get_basic(&elem, &value); ++ crm_trace("Got: %s", value.str); ++ if(value.str) { ++ char *match = strstr(value.str, ".service"); ++ ++ if (match) { ++ lpc++; ++ match[0] = 0; ++ ++ units = g_list_append(units, strdup(value.str)); ++ } ++ } ++ dbus_message_iter_next (&unit); + } + +- crm_info("Call to ListUnits passed: type '%s' count %d", g_variant_get_type_string(out_units), +- lpc); +- g_variant_unref(_ret); ++ dbus_message_unref(reply); ++ ++ crm_trace("Found %d systemd services", lpc); + return units; + } + +@@ -300,26 +265,18 @@ gboolean + systemd_unit_exists(const char *name) + { + char *path = NULL; +- GError *error = NULL; + gboolean pass = FALSE; + + if (systemd_init() == FALSE) { + return FALSE; + } + +- pass = systemd_unit_by_name(systemd_proxy, name, &path, NULL, &error); +- +- if (error || pass == FALSE) { +- pass = FALSE; +- crm_err("Call to ListUnits failed: %s", error ? error->message : "unknown"); +- if(error) { +- g_error_free(error); +- } +- +- } else { ++ if(systemd_unit_by_name(name, &path) && path) { + crm_trace("Got %s", path); ++ pass = TRUE; + } +- /* free(path) */ ++ ++ free(path); + return pass; + } + +@@ -329,11 +286,10 @@ systemd_unit_metadata(const char *name) + char *path = NULL; + char *meta = NULL; + char *desc = NULL; +- GError *error = NULL; + + CRM_ASSERT(systemd_init()); +- if (systemd_unit_by_name(systemd_proxy, name, &path, NULL, &error)) { +- desc = systemd_unit_property(path, BUS_NAME ".Unit", "Description"); ++ if (systemd_unit_by_name(name, &path)) { ++ desc = pcmk_dbus_get_property(systemd_proxy, BUS_NAME, path, BUS_NAME ".Unit", "Description"); + } else { + desc = g_strdup_printf("systemd unit file for %s", name); + } +@@ -362,6 +318,7 @@ systemd_unit_metadata(const char *name) + return meta; + } + ++#if 0 + static void + systemd_unit_exec_done(GObject * source_object, GAsyncResult * res, gpointer user_data) + { +@@ -411,19 +368,23 @@ systemd_unit_exec_done(GObject * source_object, GAsyncResult * res, gpointer use + g_variant_unref(_ret); + } + } ++#endif + + #define SYSTEMD_OVERRIDE_ROOT "/run/systemd/system/" + + gboolean + systemd_unit_exec(svc_action_t * op, gboolean synchronous) + { ++ char *error = NULL; + char *unit = NULL; +- GError *error = NULL; ++ const char *replace_s = "replace"; + gboolean pass = FALSE; +- GVariant *_ret = NULL; +- const char *action = op->action; ++ const char *method = op->action; + char *name = systemd_service_name(op->agent); +- ++ DBusMessage *msg = NULL; ++ DBusMessage *reply = NULL; ++ DBusMessageIter args; ++ + op->rc = PCMK_OCF_UNKNOWN_ERROR; + CRM_ASSERT(systemd_init()); + +@@ -436,22 +397,20 @@ systemd_unit_exec(svc_action_t * op, gboolean synchronous) + goto cleanup; + } + +- pass = systemd_unit_by_name(systemd_proxy, op->agent, &unit, NULL, &error); +- if (error || pass == FALSE) { +- crm_debug("Could not obtain unit named '%s': %s", op->agent, +- error ? error->message : "unknown"); ++ pass = systemd_unit_by_name(op->agent, &unit); ++ if (pass == FALSE) { ++ crm_debug("Could not obtain unit named '%s'", op->agent); ++#if 0 + if (error && strstr(error->message, "systemd1.NoSuchUnit")) { + op->rc = PCMK_OCF_NOT_INSTALLED; + op->status = PCMK_LRM_OP_NOT_INSTALLED; + } +- if(error) { +- g_error_free(error); +- } ++#endif + goto cleanup; + } + +- if (safe_str_eq(op->action, "monitor") || safe_str_eq(action, "status")) { +- char *state = systemd_unit_property(unit, BUS_NAME ".Unit", "ActiveState"); ++ if (safe_str_eq(op->action, "monitor") || safe_str_eq(method, "status")) { ++ char *state = pcmk_dbus_get_property(systemd_proxy, BUS_NAME, unit, BUS_NAME ".Unit", "ActiveState"); + + if (g_strcmp0(state, "active") == 0) { + op->rc = PCMK_OCF_OK; +@@ -462,12 +421,12 @@ systemd_unit_exec(svc_action_t * op, gboolean synchronous) + free(state); + goto cleanup; + +- } else if (g_strcmp0(action, "start") == 0) { ++ } else if (g_strcmp0(method, "start") == 0) { + FILE *file_strm = NULL; + char *override_dir = g_strdup_printf("%s/%s", SYSTEMD_OVERRIDE_ROOT, unit); + char *override_file = g_strdup_printf("%s/50-pacemaker.conf", override_dir); + +- action = "StartUnit"; ++ method = "StartUnit"; + crm_build_path(override_dir, 0755); + + file_strm = fopen(override_file, "w"); +@@ -485,74 +444,85 @@ systemd_unit_exec(svc_action_t * op, gboolean synchronous) + fflush(file_strm); + fclose(file_strm); + } +- systemd_daemon_reload(systemd_proxy, &error); +- if(error) { +- g_error_free(error); +- } ++ systemd_daemon_reload(); + free(override_file); + free(override_dir); + +- } else if (g_strcmp0(action, "stop") == 0) { ++ } else if (g_strcmp0(method, "stop") == 0) { + char *override_file = g_strdup_printf("%s/%s/50-pacemaker.conf", SYSTEMD_OVERRIDE_ROOT, unit); + +- action = "StopUnit"; ++ method = "StopUnit"; + unlink(override_file); + free(override_file); +- systemd_daemon_reload(systemd_proxy, &error); +- if(error) { +- g_error_free(error); +- } ++ systemd_daemon_reload(); + +- } else if (g_strcmp0(action, "restart") == 0) { +- action = "RestartUnit"; ++ } else if (g_strcmp0(method, "restart") == 0) { ++ method = "RestartUnit"; + } else { + op->rc = PCMK_OCF_UNIMPLEMENT_FEATURE; + goto cleanup; + } + +- crm_debug("Calling %s for %s: %s", action, op->rsc, unit); ++ crm_debug("Calling %s for %s: %s", method, op->rsc, unit); ++ ++#if 0 + if (synchronous == FALSE) { +- g_dbus_proxy_call(systemd_proxy, action, g_variant_new("(ss)", name, "replace"), ++ g_dbus_proxy_call(systemd_proxy, method, g_variant_new("(ss)", name, "replace"), + G_DBUS_CALL_FLAGS_NONE, op->timeout, NULL, systemd_unit_exec_done, op); + free(unit); + free(name); + return TRUE; + } ++#endif + +- _ret = g_dbus_proxy_call_sync(systemd_proxy, action, g_variant_new("(ss)", name, "replace"), +- G_DBUS_CALL_FLAGS_NONE, op->timeout, NULL, &error); ++ msg = systemd_new_method(BUS_NAME".Manager", method); ++ CRM_ASSERT(msg != NULL); + +- if (error) { ++ /* (ss) */ ++ pcmk_dbus_append_arg(msg, DBUS_TYPE_STRING, &name); ++ pcmk_dbus_append_arg(msg, DBUS_TYPE_STRING, &replace_s); ++ ++ reply = pcmk_dbus_send_recv(msg, systemd_proxy, &error); ++ dbus_message_unref(msg); ++ ++ if(error) { + /* ignore "already started" or "not running" errors */ + if (safe_str_eq(op->action, "stop") +- && strstr(error->message, "systemd1.InvalidName")) { ++ && (strstr(error, "org.freedesktop.systemd1.InvalidName") ++ || strstr(error, "org.freedesktop.systemd1.NoSuchUnit"))) { + crm_trace("Masking Stop failure for %s: unknown services are stopped", op->rsc); + op->rc = PCMK_OCF_OK; + } else { +- crm_err("Could not issue %s for %s: %s (%s)", action, op->rsc, error->message, unit); ++ crm_err("Could not issue %s for %s: %s (%s)", method, op->rsc, error, unit); + } +- g_error_free(error); ++ goto cleanup; + +- } else if(g_variant_is_of_type (_ret, G_VARIANT_TYPE("(o)"))) { +- char *path = NULL; ++ } else if(!dbus_message_iter_init(reply, &args)) { ++ crm_err("Call to %s failed: no arguments", method); ++ goto cleanup; ++ } + +- g_variant_get(_ret, "(o)", &path); +- crm_info("Call to %s passed: type '%s' %s", op->action, g_variant_get_type_string(_ret), +- path); +- op->rc = PCMK_OCF_OK; ++ /* (o) */ ++ if(!pcmk_dbus_type_check(reply, &args, DBUS_TYPE_OBJECT_PATH, __FUNCTION__, __LINE__)) { ++ crm_err("Call to %s failed: Message has invalid arguments", method); + + } else { +- crm_err("Call to %s passed but return type was '%s' not '(o)'", op->action, g_variant_get_type_string(_ret)); ++ DBusBasicValue value; ++ ++ dbus_message_iter_get_basic(&args, &value); ++ crm_info("Call to %s passed: %s", op->action, value.str); + op->rc = PCMK_OCF_OK; + } + + cleanup: ++ free(error); + free(unit); + free(name); + +- if (_ret) { +- g_variant_unref(_ret); ++ if(reply) { ++ dbus_message_unref(reply); + } ++ + if (synchronous == FALSE) { + operation_finalize(op); + return TRUE; diff --git a/SOURCES/bz1057697-pcmk-use_native_dbus_library_for_upstart_support_to_avoid_problematic_use_of_threads.patch b/SOURCES/bz1057697-pcmk-use_native_dbus_library_for_upstart_support_to_avoid_problematic_use_of_threads.patch new file mode 100644 index 0000000..eae4e0a --- /dev/null +++ b/SOURCES/bz1057697-pcmk-use_native_dbus_library_for_upstart_support_to_avoid_problematic_use_of_threads.patch @@ -0,0 +1,36 @@ +commit c12446403e348c3d6f2763bcd370cea3e6b601d1 +Author: Andrew Beekhof +Date: Mon Feb 3 14:44:51 2014 +1100 + + Fix: Bug rhbz#1057697 - Use native DBus library for upstart support to avoid problematic use of threads + + (cherry picked from commit d7996e792844b98021061bd8ae74ab929f9b8ba7) + + Conflicts: + lib/services/upstart.c + +diff --git a/configure.ac b/configure.ac +index 628f46f..f90ccdc 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -1173,7 +1173,7 @@ AC_CHECK_TYPES([DBusBasicValue],,,[[#include ]]) + + if test $HAVE_dbus = 1 -a "x${enable_upstart}" != xno; then + HAVE_upstart=0 +- PCMK_FEATURES="$PCMK_FEATURES upstart" ++ dnl PCMK_FEATURES="$PCMK_FEATURES upstart" + fi + + AC_DEFINE_UNQUOTED(SUPPORT_UPSTART, $HAVE_upstart, Support upstart based system services) +diff --git a/lib/services/dbus.c b/lib/services/dbus.c +index a9b1eba..66a98a0 100644 +--- a/lib/services/dbus.c ++++ b/lib/services/dbus.c +@@ -141,7 +141,6 @@ DBusMessage *pcmk_dbus_send_recv(DBusMessage *msg, DBusConnection *connection, D + reply = NULL; + } + } +- crm_trace("Was error: '%s' '%s'", error->name, error->message); + + if(pending) { + /* free the pending message handle */ diff --git a/SOURCES/bz1060205-pcmk-mcp_tell_systemd_not_to_respawn_us_if_we_return_100.patch b/SOURCES/bz1060205-pcmk-mcp_tell_systemd_not_to_respawn_us_if_we_return_100.patch new file mode 100644 index 0000000..e503a3c --- /dev/null +++ b/SOURCES/bz1060205-pcmk-mcp_tell_systemd_not_to_respawn_us_if_we_return_100.patch @@ -0,0 +1,18 @@ +commit 8e0d074cd9dac515a95e49af23331e5d06b66fae +Author: Andrew Beekhof +Date: Wed Feb 12 23:10:16 2014 +1100 + + Fix: mcp: Tell systemd not to respawn us if we return 100 + +diff --git a/mcp/pacemaker.service.in b/mcp/pacemaker.service.in +index 4d7e308..b5f1ffc 100644 +--- a/mcp/pacemaker.service.in ++++ b/mcp/pacemaker.service.in +@@ -17,6 +17,7 @@ Type=simple + KillMode=process + NotifyAccess=main + SysVStartPriority=99 ++SuccessExitStatus=100 + EnvironmentFile=-@sysconfdir@/sysconfig/pacemaker + + ExecStart=@sbindir@/pacemakerd -f diff --git a/SOURCES/bz1064519-pcmk-controld-handles-dlm-startup-fencing.patch b/SOURCES/bz1064519-pcmk-controld-handles-dlm-startup-fencing.patch new file mode 100644 index 0000000..371dda0 --- /dev/null +++ b/SOURCES/bz1064519-pcmk-controld-handles-dlm-startup-fencing.patch @@ -0,0 +1,97 @@ +commit 1b0fa29aa0e52fa5cb28ef80139e657119b15fca +Author: David Vossel +Date: Mon Feb 17 15:19:27 2014 -0600 + + High: controld: handling startup fencing within the controld agent, not the dlm + + Resolves: rhbz#1064519 + (cherry picked from commit 11160a94b76ada9844c277128054719445acf22f) + +diff --git a/extra/resources/controld b/extra/resources/controld +index bdd31bb..bf5466d 100644 +--- a/extra/resources/controld ++++ b/extra/resources/controld +@@ -34,6 +34,12 @@ + + ####################################################################### + ++if [ -e "$OCF_ROOT/resource.d/heartbeat/controld" ]; then ++ ocf_log info "Using heartbeat controld agent" ++ $OCF_ROOT/resource.d/heartbeat/controld $1 ++ exit $? ++fi ++ + meta_data() { + cat < +@@ -89,6 +95,8 @@ END + + ####################################################################### + ++DLM_SYSFS_DIR="/sys/kernel/dlm" ++ + controld_usage() { + cat <&1) ++ if [ $? -eq 0 ]; then ++ if [ -n "$tmp" ]; then ++ ++ ocf_log err "Uncontrolled lockspace exists, system must reboot. Executing suicide fencing" ++ stonith_admin --reboot=$(crm_node -n) --tag controld ++ ++ exit $OCF_ERR_GENERIC ++ fi ++ fi ++} ++ + controld_start() { + controld_monitor; rc=$? + +@@ -180,13 +203,22 @@ controld_stop() { + } + + controld_monitor() { ++ local rc + killall -0 ${OCF_RESKEY_daemon} >/dev/null 2>&1 ; rc=$? + + case $rc in +- 0) return $OCF_SUCCESS;; +- 1) return $OCF_NOT_RUNNING;; +- *) return $OCF_ERR_GENERIC;; ++ 0) rc=$OCF_SUCCESS;; ++ 1) rc=$OCF_NOT_RUNNING;; ++ *) rc=$OCF_ERR_GENERIC;; + esac ++ ++ # if the dlm is not successfully running, but ++ # dlm lockspace bits are left over, we self must fence. ++ if [ $rc -ne $OCF_SUCCESS ]; then ++ check_uncontrolled_locks ++ fi ++ ++ return $rc + } + + controld_validate() { +@@ -219,11 +251,11 @@ case "$OCF_RESOURCE_INSTANCE" in + : ${OCF_RESKEY_daemon=gfs_controld${daemon_ext}} + ;; + *[dD][lL][mM]*) +- : ${OCF_RESKEY_args=-q 0} ++ : ${OCF_RESKEY_args=-q 0 -s 0} + : ${OCF_RESKEY_daemon=dlm_controld${daemon_ext}} + ;; + *) +- : ${OCF_RESKEY_args=-q 0} ++ : ${OCF_RESKEY_args=-q 0 -s 0} + : ${OCF_RESKEY_daemon=dlm_controld${daemon_ext}} + esac + diff --git a/SOURCES/bz1064519-pcmk-remove_q_0_from_default_dlm_controld_arguments.patch b/SOURCES/bz1064519-pcmk-remove_q_0_from_default_dlm_controld_arguments.patch new file mode 100644 index 0000000..c3d2ef0 --- /dev/null +++ b/SOURCES/bz1064519-pcmk-remove_q_0_from_default_dlm_controld_arguments.patch @@ -0,0 +1,39 @@ +commit 2c3992bd6ad2dbcde5a39f8e02059cd99271fabd +Author: David Vossel +Date: Tue Mar 25 16:34:02 2014 -0500 + + Low: controld: Remove '-q 0' from default dlm_controld arguments + + The '-q 0' argument allows the dlm to fence nodes even when + quorum is lost. This is not a desired default. + + Resolves: rhbz#1064519 + (cherry picked from commit 20472946f54b0f6f07d286d96e5fb17baaf230ef) + +diff --git a/extra/resources/controld b/extra/resources/controld +index 2cc5f4d..a58d4ec 100644 +--- a/extra/resources/controld ++++ b/extra/resources/controld +@@ -61,7 +61,7 @@ In most cases, it should be run as an anonymous clone. + Any additional options to start the dlm_controld service with + + DLM Options +- ++ + + + +@@ -251,11 +251,11 @@ case "$OCF_RESOURCE_INSTANCE" in + : ${OCF_RESKEY_daemon=gfs_controld${daemon_ext}} + ;; + *[dD][lL][mM]*) +- : ${OCF_RESKEY_args=-q 0 -s 0} ++ : ${OCF_RESKEY_args=-s 0} + : ${OCF_RESKEY_daemon=dlm_controld${daemon_ext}} + ;; + *) +- : ${OCF_RESKEY_args=-q 0 -s 0} ++ : ${OCF_RESKEY_args=-s 0} + : ${OCF_RESKEY_daemon=dlm_controld${daemon_ext}} + esac + diff --git a/SOURCES/bz1067536-pcmk-controld-wait-for-address-list.patch b/SOURCES/bz1067536-pcmk-controld-wait-for-address-list.patch new file mode 100644 index 0000000..3090f14 --- /dev/null +++ b/SOURCES/bz1067536-pcmk-controld-wait-for-address-list.patch @@ -0,0 +1,23 @@ +commit cd08b68161a541965a68433979ed6bb188fe39ec +Author: David Vossel +Date: Thu Feb 20 17:47:47 2014 -0500 + + Fix: controld: Do not consider the dlm up until the address list is present + + (cherry picked from commit 84c45113eadf321d69b13a5c34529d7234c26c0f) + +diff --git a/extra/resources/controld b/extra/resources/controld +index bf5466d..2cc5f4d 100644 +--- a/extra/resources/controld ++++ b/extra/resources/controld +@@ -159,8 +159,8 @@ controld_start() { + controld_monitor; rc=$? + case $rc in + $OCF_SUCCESS) +- check_dir=/sys/kernel/config/dlm/cluster/comms +- if grep 1 $check_dir/*/local >/dev/null 2>&1; then ++ local addr_list=$(cat /sys/kernel/config/dlm/cluster/comms/*/addr_list 2>/dev/null) ++ if [ $? -eq 0 ] && [ -n "$addr_list" ]; then + return $OCF_SUCCESS + fi + ;; diff --git a/SOURCES/bz1069284-pcmk-prevent_resources_in_an_anti_colocation_from_even_temporarily_running_on_a_same_node.patch b/SOURCES/bz1069284-pcmk-prevent_resources_in_an_anti_colocation_from_even_temporarily_running_on_a_same_node.patch new file mode 100644 index 0000000..becd90e --- /dev/null +++ b/SOURCES/bz1069284-pcmk-prevent_resources_in_an_anti_colocation_from_even_temporarily_running_on_a_same_node.patch @@ -0,0 +1,70 @@ +commit 79759709fd71a2d0b9f4d0167ba9697257a9653c +Author: Gao,Yan +Date: Thu Feb 20 01:24:46 2014 +0800 + + Fix: pengine: cl#5187 - Prevent resources in an anti-colocation from even temporarily running on a same node + + (cherry picked from commit 9f9ed87e01bfafec0ddeee6592eb07e81bef963e) + +diff --git a/include/crm/pengine/status.h b/include/crm/pengine/status.h +index eb52464..158a562 100644 +--- a/include/crm/pengine/status.h ++++ b/include/crm/pengine/status.h +@@ -338,6 +338,7 @@ enum pe_ordering { + pe_order_asymmetrical = 0x100000, /* Indicates asymmetrical one way ordering constraint. */ + pe_order_load = 0x200000, /* Only relevant if... */ + pe_order_one_or_more = 0x400000, /* 'then' is only runnable if one or more of it's dependancies are too */ ++ pe_order_anti_colocation = 0x800000, + + pe_order_trace = 0x4000000 /* test marker */ + }; +diff --git a/pengine/constraints.c b/pengine/constraints.c +index 594d630..3b4370d 100644 +--- a/pengine/constraints.c ++++ b/pengine/constraints.c +@@ -689,6 +689,13 @@ rsc_colocation_new(const char *id, const char *node_attr, int score, + + data_set->colocation_constraints = g_list_append(data_set->colocation_constraints, new_con); + ++ if (score <= -INFINITY) { ++ new_rsc_order(rsc_lh, CRMD_ACTION_STOP, rsc_rh, CRMD_ACTION_START, ++ pe_order_anti_colocation, data_set); ++ new_rsc_order(rsc_rh, CRMD_ACTION_STOP, rsc_lh, CRMD_ACTION_START, ++ pe_order_anti_colocation, data_set); ++ } ++ + return TRUE; + } + +diff --git a/pengine/graph.c b/pengine/graph.c +index 9c1bc15..779f0e0 100644 +--- a/pengine/graph.c ++++ b/pengine/graph.c +@@ -991,6 +991,27 @@ should_dump_input(int last_action, action_t * action, action_wrapper_t * wrapper + return FALSE; + } + ++ } else if (wrapper->type == pe_order_anti_colocation) { ++ crm_trace("check anti-colocation filter %s.%s -> %s.%s", ++ wrapper->action->uuid, ++ wrapper->action->node ? wrapper->action->node->details->uname : "", ++ action->uuid, ++ action->node ? action->node->details->uname : ""); ++ ++ if (wrapper->action->node && action->node ++ && wrapper->action->node->details != action->node->details) { ++ /* Check if the actions are for the same node, ignore otherwise */ ++ crm_trace("anti-colocation filter - node"); ++ wrapper->type = pe_order_none; ++ return FALSE; ++ ++ } else if (is_set(wrapper->action->flags, pe_action_optional)) { ++ /* Check if the pre-req is optional, ignore if so */ ++ crm_trace("anti-colocation filter - optional"); ++ wrapper->type = pe_order_none; ++ return FALSE; ++ } ++ + } else if (wrapper->action->rsc + && wrapper->action->rsc != action->rsc + && is_set(wrapper->action->rsc->flags, pe_rsc_failed) diff --git a/SOURCES/bz1070916-pcmk-api_time_helper_now_returns_when_the_most_recent_fencing_operation_completed.patch b/SOURCES/bz1070916-pcmk-api_time_helper_now_returns_when_the_most_recent_fencing_operation_completed.patch new file mode 100644 index 0000000..2ef051c --- /dev/null +++ b/SOURCES/bz1070916-pcmk-api_time_helper_now_returns_when_the_most_recent_fencing_operation_completed.patch @@ -0,0 +1,26 @@ +commit 893a7468b83b8323ee343903617bbc72a7c3205b +Author: David Vossel +Date: Thu Feb 27 11:50:32 2014 -0600 + + Fix: stonith_api_time_helper now returns when the most recent fencing operation completed + + (cherry picked from commit 054fedfe70867c6f333b61e68fb64bf68e71c90b) + + Conflicts: + lib/fencing/st_client.c + +diff --git a/lib/fencing/st_client.c b/lib/fencing/st_client.c +index 02f2836..4deb71f 100644 +--- a/lib/fencing/st_client.c ++++ b/lib/fencing/st_client.c +@@ -2458,7 +2458,9 @@ stonith_api_time(uint32_t nodeid, const char *uname, bool in_progress) + + } else if (hp->state == st_done) { + completed++; +- when = hp->completed; ++ if (hp->completed > when) { ++ when = hp->completed; ++ } + } + } + diff --git a/SOURCES/bz1070916-pcmk-crm_report_additional_dlm_detail.patch b/SOURCES/bz1070916-pcmk-crm_report_additional_dlm_detail.patch new file mode 100644 index 0000000..029b43a --- /dev/null +++ b/SOURCES/bz1070916-pcmk-crm_report_additional_dlm_detail.patch @@ -0,0 +1,37 @@ +commit 062630f5823635f7be31965738b9b1a4c0e29f10 +Author: Andrew Beekhof +Date: Tue Feb 25 10:21:08 2014 +1100 + + Fix: crm_report: Additional dlm detail + + (cherry picked from commit 3cafe4b9b44fc3faea72d5738a428d2a7fcda53c) + +diff --git a/tools/report.collector b/tools/report.collector +index 62cbe8b..f40dc01 100644 +--- a/tools/report.collector ++++ b/tools/report.collector +@@ -491,15 +491,18 @@ sys_stats() { + + dlm_dump() { + if which dlm_tool >/dev/null 2>&1 ; then +- echo NOTICE - Lockspace overview: +- dlm_tool ls ++ echo "--- Lockspace overview:" ++ dlm_tool ls -n ++ ++ echo "---Lockspace history:" ++ dlm_tool dump ++ + dlm_tool ls | grep name | + while read X N ; do +- echo NOTICE - Lockspace $N: +- dlm_tool lockdump $N ++ echo "--- Lockspace $N:" ++ dlm_tool lockdump "$N" ++ dlm_tool lockdebug -svw "$N" + done +- echo NOTICE - Lockspace history: +- dlm_tool dump + fi + } + diff --git a/SOURCES/bz1070916-pcmk-crm_report_allow_ssh_alternatives_to_be_used.patch b/SOURCES/bz1070916-pcmk-crm_report_allow_ssh_alternatives_to_be_used.patch new file mode 100644 index 0000000..893851b --- /dev/null +++ b/SOURCES/bz1070916-pcmk-crm_report_allow_ssh_alternatives_to_be_used.patch @@ -0,0 +1,53 @@ +commit b7e8996ed0ecf7dd46c0cc2adf630f8c3f1ce9a3 +Author: Andrew Beekhof +Date: Mon Feb 24 14:17:48 2014 +1100 + + Feature: crm_report: Allow ssh alternatives to be used + + (cherry picked from commit 334f4f7c2863424f2461c13880621fb1e7e26ebb) + +diff --git a/tools/crm_report.in b/tools/crm_report.in +index 3af1b3f..0607ebf 100755 +--- a/tools/crm_report.in ++++ b/tools/crm_report.in +@@ -20,12 +20,12 @@ + + # Note the quotes around `$TEMP': they are essential! + TEMP=`getopt \ +- -o hv?xl:f:t:n:T:Lp:c:dSACHu:D:MVs \ +- --long help,cts:,cts-log:,dest:,node:,nodes:,from:,to:logfile:,as-directory,single-node,cluster:,user:,max-depth:,version,features \ ++ -o hv?xl:f:t:n:T:Lp:c:dSACHu:D:MVse: \ ++ --long help,cts:,cts-log:,dest:,node:,nodes:,from:,to:logfile:,as-directory,single-node,cluster:,user:,max-depth:,version,features,rsh: \ + -n 'crm_report' -- "$@"` + eval set -- "$TEMP" + +- ++rsh="ssh -T" + times="" + tests="" + nodes="" +@@ -72,6 +72,7 @@ Options: + -H, --heartbeat force the cluster type to be Heartbeat + -u, --user user ssh username for cluster nodes (default: root) + -D, --depth search depth to use when attempting to locate files ++ -e, --rsh specify the remote shell to use (default: ssh -T) + --dest a custom destination directory/file + dest a custom destination directory/file + +@@ -115,6 +116,7 @@ while true; do + -C|--corosync) cluster="corosync"; shift;; + -H|--heartbeat) cluster="heartbeat"; shift;; + -c|--cluster) cluster="$2"; shift; shift;; ++ -e|--rsh) rsh="$2"; shift; shift;; + -u|--user) ssh_user="$2"; shift; shift;; + -D|--max-depth) maxdepth="$2"; shift; shift;; + -M) search_logs=0; shift;; +@@ -184,7 +186,7 @@ EOF + bash $l_base/collector + else + cat $l_base/.env $report_data/report.common $report_data/report.collector \ +- | ssh -l $ssh_user -T $node -- "mkdir -p $r_base; cat > $r_base/collector; bash $r_base/collector" | (cd $l_base && tar mxf -) ++ | $rsh -l $ssh_user $node -- "mkdir -p $r_base; cat > $r_base/collector; bash $r_base/collector" | (cd $l_base && tar mxf -) + fi + done + diff --git a/SOURCES/bz1070916-pcmk-crm_report_only_gather_dlm_data_if_dlm_controld_is_running.patch b/SOURCES/bz1070916-pcmk-crm_report_only_gather_dlm_data_if_dlm_controld_is_running.patch new file mode 100644 index 0000000..702e0fd --- /dev/null +++ b/SOURCES/bz1070916-pcmk-crm_report_only_gather_dlm_data_if_dlm_controld_is_running.patch @@ -0,0 +1,30 @@ +commit 03e9a30a4d42d0495bcff45fc6c9df84615c6070 +Author: Andrew Beekhof +Date: Fri Feb 28 08:41:58 2014 +1100 + + Fix: crm_report: Only gather dlm data if dlm_controld is running + + (cherry picked from commit 837763e9abe258baf8b916f5744c07b7ff348871) + +diff --git a/tools/report.collector b/tools/report.collector +index f40dc01..d17ce5f 100644 +--- a/tools/report.collector ++++ b/tools/report.collector +@@ -491,6 +491,9 @@ sys_stats() { + + dlm_dump() { + if which dlm_tool >/dev/null 2>&1 ; then ++ if ++ ps -ef | egrep -qs '[d]lm_controld' ++ then + echo "--- Lockspace overview:" + dlm_tool ls -n + +@@ -503,6 +506,7 @@ dlm_dump() { + dlm_tool lockdump "$N" + dlm_tool lockdebug -svw "$N" + done ++ fi + fi + } + diff --git a/SOURCES/bz1070916-pcmk-crm_resource_prevent_use_of_null.patch b/SOURCES/bz1070916-pcmk-crm_resource_prevent_use_of_null.patch new file mode 100644 index 0000000..ca34199 --- /dev/null +++ b/SOURCES/bz1070916-pcmk-crm_resource_prevent_use_of_null.patch @@ -0,0 +1,19 @@ +commit a59501c3e87e795c7295654e0172b5075639f143 +Author: Andrew Beekhof +Date: Fri Feb 28 14:03:23 2014 +1100 + + crm_resource: Prevent use-of-NULL + +diff --git a/tools/crm_resource.c b/tools/crm_resource.c +index 2f0e282..1fcb2a2 100644 +--- a/tools/crm_resource.c ++++ b/tools/crm_resource.c +@@ -807,7 +807,7 @@ delete_lrm_rsc(cib_t *cib_conn, crm_ipc_t * crmd_channel, const char *host_uname + const char *id = rsc->id; + node_t *node = pe_find_node(data_set->nodes, host_uname); + +- if(node->details->remote_rsc == NULL) { ++ if(node && node->details->remote_rsc == NULL) { + crmd_replies_needed++; + } + if (rsc->clone_name) { diff --git a/SOURCES/bz1070916-pcmk-crmd_gracefully_handle_actions_that_cannot_be_initiated.patch b/SOURCES/bz1070916-pcmk-crmd_gracefully_handle_actions_that_cannot_be_initiated.patch new file mode 100644 index 0000000..c4d7420 --- /dev/null +++ b/SOURCES/bz1070916-pcmk-crmd_gracefully_handle_actions_that_cannot_be_initiated.patch @@ -0,0 +1,28 @@ +commit d7874e2b5e9072faac3655196f20a3f5d4880d36 +Author: Andrew Beekhof +Date: Wed Aug 7 09:10:15 2013 +1000 + + Fix: crmd: Gracefully handle actions that cannot be initiated + + (cherry picked from commit f02d6676bad129bee7175f31e810cf15f4786b70) + +diff --git a/lib/transition/graph.c b/lib/transition/graph.c +index 401a976..1965dde 100644 +--- a/lib/transition/graph.c ++++ b/lib/transition/graph.c +@@ -363,8 +363,13 @@ run_graph(crm_graph_t * graph) + } else if (should_fire_synapse(synapse)) { + crm_trace("Synapse %d fired", synapse->id); + graph->fired++; +- CRM_CHECK(fire_synapse(graph, synapse), stat_log_level = LOG_ERR; +- graph->abort_priority = INFINITY; graph->incomplete++; graph->fired--); ++ if(fire_synapse(graph, synapse) == FALSE) { ++ crm_err("Synapse %d failed to fire", synapse->id); ++ stat_log_level = LOG_ERR; ++ graph->abort_priority = INFINITY; ++ graph->incomplete++; ++ graph->fired--; ++ } + + if (synapse->confirmed == FALSE) { + graph->pending++; diff --git a/SOURCES/bz1070916-pcmk-fencing_pass_the_correct_options_when_looking_up_the_history_by_node_name.patch b/SOURCES/bz1070916-pcmk-fencing_pass_the_correct_options_when_looking_up_the_history_by_node_name.patch new file mode 100644 index 0000000..a95c7b9 --- /dev/null +++ b/SOURCES/bz1070916-pcmk-fencing_pass_the_correct_options_when_looking_up_the_history_by_node_name.patch @@ -0,0 +1,21 @@ +commit f50f6e73625bab6c6feee82acf94f84bede0137c +Author: Andrew Beekhof +Date: Thu Feb 27 11:28:35 2014 +1100 + + Fix: Fencing: Pass the correct options when looking up the history by node name + + (cherry picked from commit d9921e5783ef7a33bcacf844a4268bd08e583a93) + +diff --git a/lib/fencing/st_client.c b/lib/fencing/st_client.c +index 7f2204f..02f2836 100644 +--- a/lib/fencing/st_client.c ++++ b/lib/fencing/st_client.c +@@ -2446,7 +2446,7 @@ stonith_api_time(uint32_t nodeid, const char *uname, bool in_progress) + int progress = 0; + int completed = 0; + +- rc = st->cmds->history(st, st_opt_sync_call | st_opt_cs_nodeid, name, &history, 120); ++ rc = st->cmds->history(st, opts, name, &history, 120); + + for (hp = history; hp; hp = hp->next) { + entries++; diff --git a/SOURCES/bz1070916-pcmk-fencing_remove_shadow_definition_and_use_of_variable_progress.patch b/SOURCES/bz1070916-pcmk-fencing_remove_shadow_definition_and_use_of_variable_progress.patch new file mode 100644 index 0000000..c9d4bb0 --- /dev/null +++ b/SOURCES/bz1070916-pcmk-fencing_remove_shadow_definition_and_use_of_variable_progress.patch @@ -0,0 +1,40 @@ +commit 29d542447da8bd120072a7fa8dd6df832f0856eb +Author: Andrew Beekhof +Date: Fri Feb 28 14:11:23 2014 +1100 + + Fix: Fencing: Remove shadow definition and use of variable 'progress' + + (cherry picked from commit 0debc914b1dda2c4d04f4a33a3b38fbb4d873b1b) + +diff --git a/lib/fencing/st_client.c b/lib/fencing/st_client.c +index 4deb71f..95ea0f7 100644 +--- a/lib/fencing/st_client.c ++++ b/lib/fencing/st_client.c +@@ -2420,7 +2420,6 @@ stonith_api_time(uint32_t nodeid, const char *uname, bool in_progress) + char *name = NULL; + + time_t when = 0; +- time_t progress = 0; + stonith_t *st = NULL; + stonith_history_t *history, *hp = NULL; + enum stonith_call_options opts = st_opt_sync_call; +@@ -2453,7 +2452,7 @@ stonith_api_time(uint32_t nodeid, const char *uname, bool in_progress) + if (in_progress) { + progress++; + if (hp->state != st_done && hp->state != st_failed) { +- progress = time(NULL); ++ when = time(NULL); + } + + } else if (hp->state == st_done) { +@@ -2471,10 +2470,6 @@ stonith_api_time(uint32_t nodeid, const char *uname, bool in_progress) + } + } + +- if (progress) { +- when = progress; +- } +- + if (st) { + st->cmds->disconnect(st); + stonith_api_delete(st); diff --git a/SOURCES/bz1070916-pcmk-pe_gracefully_handle_bad_values_for_xml_attr_transition_magic.patch b/SOURCES/bz1070916-pcmk-pe_gracefully_handle_bad_values_for_xml_attr_transition_magic.patch new file mode 100644 index 0000000..c56bad6 --- /dev/null +++ b/SOURCES/bz1070916-pcmk-pe_gracefully_handle_bad_values_for_xml_attr_transition_magic.patch @@ -0,0 +1,54 @@ +commit 5882024877d6c22f0663160a3f7278a421f31819 +Author: Andrew Beekhof +Date: Wed Aug 7 09:03:43 2013 +1000 + + Fix: PE: Gracefully handle bad values for XML_ATTR_TRANSITION_MAGIC + + (cherry picked from commit 164ca366c14c914794f9230acd7646426641e6b2) + +diff --git a/lib/common/utils.c b/lib/common/utils.c +index 4e18039..7543464 100644 +--- a/lib/common/utils.c ++++ b/lib/common/utils.c +@@ -885,15 +885,13 @@ decode_transition_magic(const char *magic, char **uuid, int *transition_id, int + key = calloc(1, strlen(magic) + 1); + res = sscanf(magic, "%d:%d;%s", op_status, op_rc, key); + if (res != 3) { +- crm_crit("Only found %d items in: %s", res, magic); +- result = FALSE; +- goto bail; ++ crm_warn("Only found %d items in: '%s'", res, magic); ++ free(key); ++ return FALSE; + } + +- CRM_CHECK(decode_transition_key(key, uuid, transition_id, action_id, target_rc), result = FALSE; +- goto bail;); ++ CRM_CHECK(decode_transition_key(key, uuid, transition_id, action_id, target_rc), result = FALSE); + +- bail: + free(key); + return result; + } +diff --git a/lib/pengine/utils.c b/lib/pengine/utils.c +index e9997a2..1e827e0 100644 +--- a/lib/pengine/utils.c ++++ b/lib/pengine/utils.c +@@ -1332,11 +1332,12 @@ sort_op_by_callid(gconstpointer a, gconstpointer b) + const char *b_magic = crm_element_value_const(xml_b, XML_ATTR_TRANSITION_MAGIC); + + CRM_CHECK(a_magic != NULL && b_magic != NULL, sort_return(0, "No magic")); +- CRM_CHECK(decode_transition_magic(a_magic, &a_uuid, &a_id, &dummy, &dummy, &dummy, &dummy), +- sort_return(0, "bad magic a")); +- CRM_CHECK(decode_transition_magic(b_magic, &b_uuid, &b_id, &dummy, &dummy, &dummy, &dummy), +- sort_return(0, "bad magic b")); +- ++ if(!decode_transition_magic(a_magic, &a_uuid, &a_id, &dummy, &dummy, &dummy, &dummy)) { ++ sort_return(0, "bad magic a"); ++ } ++ if(!decode_transition_magic(b_magic, &b_uuid, &b_id, &dummy, &dummy, &dummy, &dummy)) { ++ sort_return(0, "bad magic b"); ++ } + /* try and determin the relative age of the operation... + * some pending operations (ie. a start) may have been supuerceeded + * by a subsequent stop diff --git a/SOURCES/bz1070916-pcmk-pengine_update_regression_tests.patch b/SOURCES/bz1070916-pcmk-pengine_update_regression_tests.patch new file mode 100644 index 0000000..c73b4f9 --- /dev/null +++ b/SOURCES/bz1070916-pcmk-pengine_update_regression_tests.patch @@ -0,0 +1,137 @@ +commit d4c8712bfcf95eeb746887f1fc3de73ca878528a +Author: Andrew Beekhof +Date: Fri Feb 28 11:03:10 2014 +1100 + + Update regression tests for bz1069284 fix + +diff --git a/pengine/test10/bug-lf-2435.dot b/pengine/test10/bug-lf-2435.dot +index 2313c38..2d0b65d 100644 +--- a/pengine/test10/bug-lf-2435.dot ++++ b/pengine/test10/bug-lf-2435.dot +@@ -5,6 +5,7 @@ digraph "g" { + "dummy2_stop_0 c20.chepkov.lan" -> "dummy2_start_0 c21.chepkov.lan" [ style = bold] + "dummy2_stop_0 c20.chepkov.lan" [ style=bold color="green" fontcolor="black" ] + "dummy3_stop_0 c21.chepkov.lan" -> "all_stopped" [ style = bold] ++"dummy3_stop_0 c21.chepkov.lan" -> "dummy2_start_0 c21.chepkov.lan" [ style = bold] + "dummy3_stop_0 c21.chepkov.lan" [ style=bold color="green" fontcolor="black" ] + "dummy4_monitor_0 c19.chepkov.lan" -> "probe_complete c19.chepkov.lan" [ style = bold] + "dummy4_monitor_0 c19.chepkov.lan" [ style=bold color="green" fontcolor="black" ] +diff --git a/pengine/test10/bug-lf-2435.exp b/pengine/test10/bug-lf-2435.exp +index 046dd97..7255127 100644 +--- a/pengine/test10/bug-lf-2435.exp ++++ b/pengine/test10/bug-lf-2435.exp +@@ -10,6 +10,9 @@ + + + ++ ++ ++ + + + +diff --git a/pengine/test10/simple6.dot b/pengine/test10/simple6.dot +index ac3c495..3fac608 100644 +--- a/pengine/test10/simple6.dot ++++ b/pengine/test10/simple6.dot +@@ -6,6 +6,7 @@ + "probe_complete" -> "rsc2_start_0 node1" [ style = bold] + "probe_complete" [ style=bold color="green" fontcolor="orange" ] + "rsc1_stop_0 node1" -> "all_stopped" [ style = bold] ++"rsc1_stop_0 node1" -> "rsc2_start_0 node1" [ style = bold] + "rsc1_stop_0 node1" [ style=bold color="green" fontcolor="black" ] + "rsc2_monitor_0 node1" -> "probe_complete node1" [ style = bold] + "rsc2_monitor_0 node1" [ style=bold color="green" fontcolor="black" ] +diff --git a/pengine/test10/simple6.exp b/pengine/test10/simple6.exp +index 590e64b..79d230d 100644 +--- a/pengine/test10/simple6.exp ++++ b/pengine/test10/simple6.exp +@@ -10,6 +10,9 @@ + + + ++ ++ ++ + + + +diff --git a/pengine/test10/simple6.summary b/pengine/test10/simple6.summary +index 2c4079b..42dde4a 100644 +--- a/pengine/test10/simple6.summary ++++ b/pengine/test10/simple6.summary +@@ -12,9 +12,9 @@ Transition Summary: + Executing cluster transition: + * Resource action: rsc2 monitor on node1 + * Pseudo action: probe_complete +- * Resource action: rsc2 start on node1 + * Resource action: rsc1 stop on node1 + * Pseudo action: all_stopped ++ * Resource action: rsc2 start on node1 + + Revised cluster status: + Online: [ node1 ] +diff --git a/tools/regression.exp b/tools/regression.exp +index ef27353..1682f72 100755 +--- a/tools/regression.exp ++++ b/tools/regression.exp +@@ -1317,7 +1317,7 @@ WARNING: Creating rsc_location constraint 'cli-ban-dummy-on-node1' with a score + + + +- ++ + + + +@@ -2027,7 +2027,7 @@ WARNING: Creating rsc_location constraint 'cli-ban-dummy-on-node1' with a score + + + +- ++ + + + +@@ -2113,8 +2113,8 @@ WARNING: Creating rsc_location constraint 'cli-ban-dummy-on-node2' with a score + + + +- +- ++ ++ + + + +@@ -2217,8 +2217,8 @@ Online: [ node1 node2 node3 ] + + + +- +- ++ ++ + + + +@@ -2300,8 +2300,8 @@ Online: [ node1 node2 node3 ] + + + +- +- ++ ++ + + + +@@ -2383,7 +2383,7 @@ Online: [ node1 node2 node3 ] + + + +- ++ + + + diff --git a/SOURCES/bz1070916-pcmk-send_details_of_stonith_api_time_and_stonith_api_kick_to_syslog.patch b/SOURCES/bz1070916-pcmk-send_details_of_stonith_api_time_and_stonith_api_kick_to_syslog.patch new file mode 100644 index 0000000..846bbd6 --- /dev/null +++ b/SOURCES/bz1070916-pcmk-send_details_of_stonith_api_time_and_stonith_api_kick_to_syslog.patch @@ -0,0 +1,146 @@ +commit 02bc6c85f814e85b5840f75e198a29d86ac6f2f2 +Author: Andrew Beekhof +Date: Thu Feb 27 11:27:30 2014 +1100 + + Log: Fencing: Send details of stonith_api_time() and stonith_api_kick() to syslog + + (cherry picked from commit b0a8876fe230f5e3e5770734f78e36284c0bae62) + +diff --git a/include/crm/stonith-ng.h b/include/crm/stonith-ng.h +index 35f6e5a..7f6938a 100644 +--- a/include/crm/stonith-ng.h ++++ b/include/crm/stonith-ng.h +@@ -348,8 +348,8 @@ void stonith_key_value_freeall(stonith_key_value_t * kvp, int keys, int values); + * + * At least one of nodeid and uname are required + */ +-int stonith_api_kick(int nodeid, const char *uname, int timeout, bool off); +-time_t stonith_api_time(int nodeid, const char *uname, bool in_progress); ++int stonith_api_kick(uint32_t nodeid, const char *uname, int timeout, bool off); ++time_t stonith_api_time(uint32_t nodeid, const char *uname, bool in_progress); + + /* + * Helpers for using the above functions without install-time dependancies +@@ -394,7 +394,7 @@ time_t stonith_api_time(int nodeid, const char *uname, bool in_progress); + # define STONITH_LIBRARY "libstonithd.so.2" + + static inline int +-stonith_api_kick_helper(int nodeid, int timeout, bool off) ++stonith_api_kick_helper(uint32_t nodeid, int timeout, bool off) + { + static void *st_library = NULL; + static int (*st_kick_fn) (int nodeid, const char *uname, int timeout, bool off) = NULL; +@@ -413,7 +413,7 @@ stonith_api_kick_helper(int nodeid, int timeout, bool off) + } + + static inline time_t +-stonith_api_time_helper(int nodeid, bool in_progress) ++stonith_api_time_helper(uint32_t nodeid, bool in_progress) + { + static void *st_library = NULL; + static time_t(*st_time_fn) (int nodeid, const char *uname, bool in_progress) = NULL; +diff --git a/lib/fencing/st_client.c b/lib/fencing/st_client.c +index 3c6a7e7..7f2204f 100644 +--- a/lib/fencing/st_client.c ++++ b/lib/fencing/st_client.c +@@ -2361,8 +2361,11 @@ stonith_key_value_freeall(stonith_key_value_t * head, int keys, int values) + } + } + ++#define api_log_open() openlog("stonith-api", LOG_CONS | LOG_NDELAY | LOG_PID, LOG_DAEMON) ++#define api_log(level, fmt, args...) syslog(level, "%s: "fmt, __FUNCTION__, args) ++ + int +-stonith_api_kick(int nodeid, const char *uname, int timeout, bool off) ++stonith_api_kick(uint32_t nodeid, const char *uname, int timeout, bool off) + { + char *name = NULL; + const char *action = "reboot"; +@@ -2371,9 +2374,13 @@ stonith_api_kick(int nodeid, const char *uname, int timeout, bool off) + stonith_t *st = NULL; + enum stonith_call_options opts = st_opt_sync_call | st_opt_allow_suicide; + ++ api_log_open(); + st = stonith_api_new(); + if (st) { + rc = st->cmds->connect(st, "stonith-api", NULL); ++ if(rc != pcmk_ok) { ++ api_log(LOG_ERR, "Connection failed, could not kick (%s) node %u/%s : %s (%d)", action, nodeid, uname, pcmk_strerror(rc), rc); ++ } + } + + if (uname != NULL) { +@@ -2390,6 +2397,11 @@ stonith_api_kick(int nodeid, const char *uname, int timeout, bool off) + + if (rc == pcmk_ok) { + rc = st->cmds->fence(st, opts, name, action, timeout, 0); ++ if(rc != pcmk_ok) { ++ api_log(LOG_ERR, "Could not kick (%s) node %u/%s : %s (%d)", action, nodeid, uname, pcmk_strerror(rc), rc); ++ } else { ++ api_log(LOG_NOTICE, "Node %u/%s kicked: %s ", nodeid, uname, action); ++ } + } + + if (st) { +@@ -2402,7 +2414,7 @@ stonith_api_kick(int nodeid, const char *uname, int timeout, bool off) + } + + time_t +-stonith_api_time(int nodeid, const char *uname, bool in_progress) ++stonith_api_time(uint32_t nodeid, const char *uname, bool in_progress) + { + int rc = 0; + char *name = NULL; +@@ -2416,6 +2428,9 @@ stonith_api_time(int nodeid, const char *uname, bool in_progress) + st = stonith_api_new(); + if (st) { + rc = st->cmds->connect(st, "stonith-api", NULL); ++ if(rc != pcmk_ok) { ++ api_log(LOG_NOTICE, "Connection failed: %s (%d)", pcmk_strerror(rc), rc); ++ } + } + + if (uname != NULL) { +@@ -2427,18 +2442,31 @@ stonith_api_time(int nodeid, const char *uname, bool in_progress) + } + + if (st && rc == pcmk_ok) { +- st->cmds->history(st, st_opt_sync_call | st_opt_cs_nodeid, name, &history, 120); ++ int entries = 0; ++ int progress = 0; ++ int completed = 0; ++ ++ rc = st->cmds->history(st, st_opt_sync_call | st_opt_cs_nodeid, name, &history, 120); + + for (hp = history; hp; hp = hp->next) { ++ entries++; + if (in_progress) { ++ progress++; + if (hp->state != st_done && hp->state != st_failed) { + progress = time(NULL); + } + + } else if (hp->state == st_done) { ++ completed++; + when = hp->completed; + } + } ++ ++ if(rc == pcmk_ok) { ++ api_log(LOG_INFO, "Found %d entries for %u/%s: %d in progress, %d completed", entries, nodeid, uname, progress, completed); ++ } else { ++ api_log(LOG_ERR, "Could not retrieve fence history for %u/%s: %s (%d)", nodeid, uname, pcmk_strerror(rc), rc); ++ } + } + + if (progress) { +@@ -2450,6 +2478,9 @@ stonith_api_time(int nodeid, const char *uname, bool in_progress) + stonith_api_delete(st); + } + ++ if(when) { ++ api_log(LOG_INFO, "Node %u/%s last kicked at: %ld", nodeid, uname, (long int)when); ++ } + free(name); + return when; + } diff --git a/SOURCES/bz1070916-pcmk-systemd_prevent_use_of_null_when_determining_if_an_agent_exists.patch b/SOURCES/bz1070916-pcmk-systemd_prevent_use_of_null_when_determining_if_an_agent_exists.patch new file mode 100644 index 0000000..cd22bff --- /dev/null +++ b/SOURCES/bz1070916-pcmk-systemd_prevent_use_of_null_when_determining_if_an_agent_exists.patch @@ -0,0 +1,21 @@ +commit 4d52d269e3022a693155fd1b443990f5956057d7 +Author: Andrew Beekhof +Date: Fri Feb 28 14:11:15 2014 +1100 + + Fix: systemd: Prevent use-of-NULL when determining if an agent exists + + (cherry picked from commit 0597697bf408690a5b52e1dfb128888ef974bfe7) + +diff --git a/lib/services/systemd.c b/lib/services/systemd.c +index 374a03e..a28ae14 100644 +--- a/lib/services/systemd.c ++++ b/lib/services/systemd.c +@@ -142,7 +142,7 @@ systemd_unit_by_name(const gchar * arg_name, gchar ** out_unit) + + name = systemd_service_name(arg_name); + +- while(*out_unit == NULL) { ++ while(TRUE) { + msg = systemd_new_method(BUS_NAME".Manager", method); + CRM_ASSERT(msg != NULL); + diff --git a/SOURCES/bz1070916-pcmk-test_tools_set_up_override_for_local_schema_file_locations.patch b/SOURCES/bz1070916-pcmk-test_tools_set_up_override_for_local_schema_file_locations.patch new file mode 100644 index 0000000..14876f7 --- /dev/null +++ b/SOURCES/bz1070916-pcmk-test_tools_set_up_override_for_local_schema_file_locations.patch @@ -0,0 +1,25 @@ +commit 87b04358f7024ee1263f6baaa5a7df7f31b18028 +Author: Andrew Beekhof +Date: Tue Feb 4 12:22:37 2014 +1100 + + Test: tools: Set up override for local schema file locations + + (cherry picked from commit 3d43ec1aa27420e23b8a5c9a921e9fab57669eb1) + +diff --git a/tools/regression.sh b/tools/regression.sh +index 12e2bcf..8c9a4d4 100755 +--- a/tools/regression.sh ++++ b/tools/regression.sh +@@ -60,8 +60,10 @@ while test "$done" = "0"; do + done + + if [ "x$VALGRIND_CMD" = "x" -a -x $test_home/crm_simulate ]; then +- echo "Using local binaries from: $test_home" +- PATH="$test_home:$PATH" ++ xml_home=`dirname ${test_home}` ++ echo "Using local binaries from: $test_home, schemas from $xml_home" ++ export PATH="$test_home:$PATH" ++ export PCMK_schema_directory=${xml_home}/xml + fi + + function test_tools() { diff --git a/SOURCES/bz1078504-pcmk-pengine_fixes_invalid_transition_caused_by_clones_with_more_than_10_instances.patch b/SOURCES/bz1078504-pcmk-pengine_fixes_invalid_transition_caused_by_clones_with_more_than_10_instances.patch new file mode 100644 index 0000000..3a22f2d --- /dev/null +++ b/SOURCES/bz1078504-pcmk-pengine_fixes_invalid_transition_caused_by_clones_with_more_than_10_instances.patch @@ -0,0 +1,93 @@ +commit ce507c2a598086b16bfbc1d937c656de4e73ffa6 +Author: David Vossel +Date: Wed Mar 19 21:43:43 2014 -0400 + + Fix: pengine: fixes invalid transition caused by clones with more than 10 instances + + (cherry picked from commit 9e0b496b269ce0e792370e9c2b22446dfaf3e64a) + +diff --git a/pengine/clone.c b/pengine/clone.c +index 9113e9d..52a84df 100644 +--- a/pengine/clone.c ++++ b/pengine/clone.c +@@ -28,6 +28,18 @@ + gint sort_clone_instance(gconstpointer a, gconstpointer b, gpointer data_set); + static void append_parent_colocation(resource_t * rsc, resource_t * child, gboolean all); + ++static gint ++sort_rsc_id(gconstpointer a, gconstpointer b) ++{ ++ const resource_t *resource1 = (const resource_t *)a; ++ const resource_t *resource2 = (const resource_t *)b; ++ ++ CRM_ASSERT(resource1 != NULL); ++ CRM_ASSERT(resource2 != NULL); ++ ++ return strcmp(resource1->id, resource2->id); ++} ++ + static node_t * + parent_node_instance(const resource_t * rsc, node_t * node) + { +@@ -749,7 +761,7 @@ child_ordering_constraints(resource_t * rsc, pe_working_set_t * data_set) + action_t *start = NULL; + action_t *last_stop = NULL; + action_t *last_start = NULL; +- GListPtr gIter = rsc->children; ++ GListPtr gIter = NULL; + gboolean active_only = TRUE; /* change to false to get the old behavior */ + clone_variant_data_t *clone_data = NULL; + +@@ -758,8 +770,10 @@ child_ordering_constraints(resource_t * rsc, pe_working_set_t * data_set) + if (clone_data->ordered == FALSE) { + return; + } ++ /* we have to maintain a consistent sorted child list when building order constraints */ ++ rsc->children = g_list_sort(rsc->children, sort_rsc_id); + +- for (; gIter != NULL; gIter = gIter->next) { ++ for (gIter = rsc->children; gIter != NULL; gIter = gIter->next) { + resource_t *child = (resource_t *) gIter->data; + + key = stop_key(child); +@@ -857,7 +871,7 @@ void + clone_internal_constraints(resource_t * rsc, pe_working_set_t * data_set) + { + resource_t *last_rsc = NULL; +- GListPtr gIter = rsc->children; ++ GListPtr gIter; + clone_variant_data_t *clone_data = NULL; + + get_clone_variant_data(clone_data, rsc); +@@ -872,7 +886,11 @@ clone_internal_constraints(resource_t * rsc, pe_working_set_t * data_set) + new_rsc_order(rsc, RSC_STARTED, rsc, RSC_PROMOTE, pe_order_runnable_left, data_set); + } + +- for (; gIter != NULL; gIter = gIter->next) { ++ if (clone_data->ordered) { ++ /* we have to maintain a consistent sorted child list when building order constraints */ ++ rsc->children = g_list_sort(rsc->children, sort_rsc_id); ++ } ++ for (gIter = rsc->children; gIter != NULL; gIter = gIter->next) { + resource_t *child_rsc = (resource_t *) gIter->data; + + child_rsc->cmds->internal_constraints(child_rsc, data_set); +@@ -1400,18 +1418,6 @@ clone_expand(resource_t * rsc, pe_working_set_t * data_set) + clone_data->promote_notify = NULL; + } + +-static gint +-sort_rsc_id(gconstpointer a, gconstpointer b) +-{ +- const resource_t *resource1 = (const resource_t *)a; +- const resource_t *resource2 = (const resource_t *)b; +- +- CRM_ASSERT(resource1 != NULL); +- CRM_ASSERT(resource2 != NULL); +- +- return strcmp(resource1->id, resource2->id); +-} +- + node_t * + rsc_known_on(resource_t * rsc, GListPtr * list) + { diff --git a/SOURCES/bz720543-pcmk-corosync_attempt_to_retrieve_a_peer_s_node_name_if_it_is_not_already_known.patch b/SOURCES/bz720543-pcmk-corosync_attempt_to_retrieve_a_peer_s_node_name_if_it_is_not_already_known.patch new file mode 100644 index 0000000..f07c89d --- /dev/null +++ b/SOURCES/bz720543-pcmk-corosync_attempt_to_retrieve_a_peer_s_node_name_if_it_is_not_already_known.patch @@ -0,0 +1,41 @@ +commit bcd7ef60b00462c6a55ae1ce2f3ea45391059368 +Author: Andrew Beekhof +Date: Thu Nov 14 11:25:20 2013 +1100 + + Bug cl#5179 - Corosync: Attempt to retrieve a peer's node name if it is not already known + + (cherry picked from commit 441978e42a41fcfca3f4b41a1458d8a9c171dd63) + +diff --git a/lib/cluster/membership.c b/lib/cluster/membership.c +index e7d5b69..b4c8ba7 100644 +--- a/lib/cluster/membership.c ++++ b/lib/cluster/membership.c +@@ -270,6 +270,7 @@ crm_get_peer(unsigned int id, const char *uname) + crm_node_t *node = NULL; + crm_node_t *by_id = NULL; + crm_node_t *by_name = NULL; ++ char *uname_lookup = NULL; + + CRM_ASSERT(id > 0 || uname != NULL); + +@@ -357,6 +358,12 @@ crm_get_peer(unsigned int id, const char *uname) + g_hash_table_replace(crm_peer_cache, uniqueid, node); + } + ++ if(id && uname == NULL && node->uname == NULL) { ++ uname_lookup = get_node_name(id); ++ uname = uname_lookup; ++ crm_trace("Inferred a name of '%s' for node %u", uname, id); ++ } ++ + if(id > 0 && uname && (node->id == 0 || node->uname == NULL)) { + crm_info("Node %u is now known as %s", id, uname); + } +@@ -393,6 +400,7 @@ crm_get_peer(unsigned int id, const char *uname) + } + } + ++ free(uname_lookup); + return node; + } + diff --git a/SOURCES/bz720543-pcmk-removes_unnecessary_newlines_in_crm_resource_o_output.patch b/SOURCES/bz720543-pcmk-removes_unnecessary_newlines_in_crm_resource_o_output.patch new file mode 100644 index 0000000..9d1e7cc --- /dev/null +++ b/SOURCES/bz720543-pcmk-removes_unnecessary_newlines_in_crm_resource_o_output.patch @@ -0,0 +1,64 @@ +commit 0c88fc0aa260dcd50e654275cc9fdd68e27a2617 +Author: David Vossel +Date: Wed Dec 4 17:04:52 2013 -0600 + + Fix: Removes unnecessary newlines in crm_resource -O output + + Resolves: rhbz#1038155 + (cherry picked from commit cd56faa1c9168811b64be9f7eea73ad600261844) + +diff --git a/include/crm/common/util.h b/include/crm/common/util.h +index f0dca36..9092708 100644 +--- a/include/crm/common/util.h ++++ b/include/crm/common/util.h +@@ -67,6 +67,8 @@ gboolean decode_transition_key(const char *key, char **uuid, int *action, int *t + gboolean decode_transition_magic(const char *magic, char **uuid, int *transition_id, int *action_id, + int *op_status, int *op_rc, int *target_rc); + ++char * crm_strip_trailing_newline(char *str); ++ + # define safe_str_eq(a, b) crm_str_eq(a, b, FALSE) + gboolean crm_str_eq(const char *a, const char *b, gboolean use_case); + gboolean safe_str_neq(const char *a, const char *b); +diff --git a/lib/common/utils.c b/lib/common/utils.c +index 527c9e0..4e18039 100644 +--- a/lib/common/utils.c ++++ b/lib/common/utils.c +@@ -1550,6 +1550,22 @@ crm_is_writable(const char *dir, const char *file, + return pass; + } + ++char * ++crm_strip_trailing_newline(char *str) ++{ ++ int len; ++ ++ if (str == NULL) { ++ return str; ++ } ++ ++ for (len = strlen(str) - 1; len >= 0 && str[len] == '\n'; len--) { ++ str[len] = '\0'; ++ } ++ ++ return str; ++} ++ + gboolean + crm_str_eq(const char *a, const char *b, gboolean use_case) + { +diff --git a/tools/crm_resource.c b/tools/crm_resource.c +index c03501d..2f0e282 100644 +--- a/tools/crm_resource.c ++++ b/tools/crm_resource.c +@@ -1119,8 +1119,8 @@ list_resource_operations(const char *rsc_id, const char *host_uname, gboolean ac + if (last) { + time_t run_at = crm_parse_int(last, "0"); + +- fprintf(stdout, ", last-rc-change=%s, exec=%sms\n", +- ctime(&run_at), crm_element_value(xml_op, XML_RSC_OP_T_EXEC)); ++ fprintf(stdout, ", last-rc-change=%s, exec=%sms", ++ crm_strip_trailing_newline(ctime(&run_at)), crm_element_value(xml_op, XML_RSC_OP_T_EXEC)); + } + fprintf(stdout, "): %s\n", services_lrm_status_str(status)); + } diff --git a/SOURCES/bz720543-pcmk-tools_fixes_formatting_of_remote_nodes_in_crm_mon_and_crm_simulate.patch b/SOURCES/bz720543-pcmk-tools_fixes_formatting_of_remote_nodes_in_crm_mon_and_crm_simulate.patch new file mode 100644 index 0000000..ddbfc43 --- /dev/null +++ b/SOURCES/bz720543-pcmk-tools_fixes_formatting_of_remote_nodes_in_crm_mon_and_crm_simulate.patch @@ -0,0 +1,356 @@ +commit 27adba1575f508166e7203225a3ff6d580842dfd +Author: David Vossel +Date: Tue Aug 27 17:46:28 2013 -0500 + + Fix: tools: Fixes formatting of remote-nodes in crm_mon and crm_simulate + + (cherry picked from commit b32b60ec6d0963ea3767196f0fdd50746d27fafa) + + Conflicts: + pengine/test10/whitebox-ms-ordering.summary + +diff --git a/pengine/test10/whitebox-asymmetric.summary b/pengine/test10/whitebox-asymmetric.summary +index c4a8e0a..1a68802 100644 +--- a/pengine/test10/whitebox-asymmetric.summary ++++ b/pengine/test10/whitebox-asymmetric.summary +@@ -1,7 +1,6 @@ + + Current cluster status: + Online: [ 18builder ] +-OFFLINE: [ 18node2:container2 ] + + fence_false (stonith:fence_false): Stopped + container2 (ocf::pacemaker:Dummy): Started 18builder +@@ -22,7 +21,8 @@ Executing cluster transition: + * Resource action: nfs_mount monitor=10000 on 18node2 + + Revised cluster status: +-Online: [ 18builder 18node2:container2 ] ++Online: [ 18builder ] ++Containers: [ 18node2:container2 ] + + fence_false (stonith:fence_false): Stopped + container2 (ocf::pacemaker:Dummy): Started 18builder +diff --git a/pengine/test10/whitebox-fail1.summary b/pengine/test10/whitebox-fail1.summary +index 02d0f8e..5e5887b 100644 +--- a/pengine/test10/whitebox-fail1.summary ++++ b/pengine/test10/whitebox-fail1.summary +@@ -1,7 +1,7 @@ + + Current cluster status: +-Online: [ 18node1 18node2 18node3 lxc2:container2 ] +-OFFLINE: [ lxc1:container1 ] ++Online: [ 18node1 18node2 18node3 ] ++Containers: [ lxc2:container2 ] + + container1 (ocf::heartbeat:VirtualDomain): FAILED 18node2 + container2 (ocf::heartbeat:VirtualDomain): Started 18node2 +@@ -38,7 +38,8 @@ Executing cluster transition: + * Resource action: B monitor=10000 on lxc1 + + Revised cluster status: +-Online: [ 18node1 18node2 18node3 lxc1:container1 lxc2:container2 ] ++Online: [ 18node1 18node2 18node3 ] ++Containers: [ lxc1:container1 lxc2:container2 ] + + container1 (ocf::heartbeat:VirtualDomain): Started 18node2 + container2 (ocf::heartbeat:VirtualDomain): Started 18node2 +diff --git a/pengine/test10/whitebox-fail2.summary b/pengine/test10/whitebox-fail2.summary +index 0e53524..338173d 100644 +--- a/pengine/test10/whitebox-fail2.summary ++++ b/pengine/test10/whitebox-fail2.summary +@@ -1,7 +1,7 @@ + + Current cluster status: +-Online: [ 18node1 18node2 18node3 lxc2:container2 ] +-OFFLINE: [ lxc1:container1 ] ++Online: [ 18node1 18node2 18node3 ] ++Containers: [ lxc2:container2 ] + + container1 (ocf::heartbeat:VirtualDomain): FAILED 18node2 + container2 (ocf::heartbeat:VirtualDomain): Started 18node2 +@@ -38,7 +38,8 @@ Executing cluster transition: + * Resource action: B monitor=10000 on lxc1 + + Revised cluster status: +-Online: [ 18node1 18node2 18node3 lxc1:container1 lxc2:container2 ] ++Online: [ 18node1 18node2 18node3 ] ++Containers: [ lxc1:container1 lxc2:container2 ] + + container1 (ocf::heartbeat:VirtualDomain): Started 18node2 + container2 (ocf::heartbeat:VirtualDomain): Started 18node2 +diff --git a/pengine/test10/whitebox-fail3.summary b/pengine/test10/whitebox-fail3.summary +index 1d25724..395d218 100644 +--- a/pengine/test10/whitebox-fail3.summary ++++ b/pengine/test10/whitebox-fail3.summary +@@ -1,7 +1,6 @@ + + Current cluster status: + Online: [ dvossel-laptop2 ] +-OFFLINE: [ 18builder:vm 18node1:vm2 ] + + vm (ocf::heartbeat:VirtualDomain): Stopped + vm2 (ocf::heartbeat:VirtualDomain): Stopped +@@ -39,8 +38,8 @@ Executing cluster transition: + * Resource action: X monitor=10000 on 18builder + + Revised cluster status: +-Online: [ 18builder:vm dvossel-laptop2 ] +-OFFLINE: [ 18node1:vm2 ] ++Online: [ dvossel-laptop2 ] ++Containers: [ 18builder:vm ] + + vm (ocf::heartbeat:VirtualDomain): Started dvossel-laptop2 + vm2 (ocf::heartbeat:VirtualDomain): Stopped +diff --git a/pengine/test10/whitebox-move.summary b/pengine/test10/whitebox-move.summary +index 6dc2f6f..3422ac7 100644 +--- a/pengine/test10/whitebox-move.summary ++++ b/pengine/test10/whitebox-move.summary +@@ -1,6 +1,7 @@ + + Current cluster status: +-Online: [ 18node1 18node2 18node3 lxc1:container1 lxc2:container2 ] ++Online: [ 18node1 18node2 18node3 ] ++Containers: [ lxc1:container1 lxc2:container2 ] + + container1 (ocf::heartbeat:VirtualDomain): Started 18node1 + container2 (ocf::heartbeat:VirtualDomain): Started 18node2 +@@ -34,7 +35,8 @@ Executing cluster transition: + * Resource action: lxc1 monitor=30000 on 18node2 + + Revised cluster status: +-Online: [ 18node1 18node2 18node3 lxc1:container1 lxc2:container2 ] ++Online: [ 18node1 18node2 18node3 ] ++Containers: [ lxc1:container1 lxc2:container2 ] + + container1 (ocf::heartbeat:VirtualDomain): Started 18node2 + container2 (ocf::heartbeat:VirtualDomain): Started 18node2 +diff --git a/pengine/test10/whitebox-start.summary b/pengine/test10/whitebox-start.summary +index e5d654b..2801abe 100644 +--- a/pengine/test10/whitebox-start.summary ++++ b/pengine/test10/whitebox-start.summary +@@ -1,7 +1,7 @@ + + Current cluster status: +-Online: [ 18node1 18node2 18node3 lxc2:container2 ] +-OFFLINE: [ lxc1:container1 ] ++Online: [ 18node1 18node2 18node3 ] ++Containers: [ lxc2:container2 ] + + container1 (ocf::heartbeat:VirtualDomain): Stopped + container2 (ocf::heartbeat:VirtualDomain): Started 18node2 +@@ -29,7 +29,8 @@ Executing cluster transition: + * Resource action: M monitor=10000 on lxc1 + + Revised cluster status: +-Online: [ 18node1 18node2 18node3 lxc1:container1 lxc2:container2 ] ++Online: [ 18node1 18node2 18node3 ] ++Containers: [ lxc1:container1 lxc2:container2 ] + + container1 (ocf::heartbeat:VirtualDomain): Started 18node1 + container2 (ocf::heartbeat:VirtualDomain): Started 18node2 +diff --git a/pengine/test10/whitebox-stop.summary b/pengine/test10/whitebox-stop.summary +index 4116571..51357b9 100644 +--- a/pengine/test10/whitebox-stop.summary ++++ b/pengine/test10/whitebox-stop.summary +@@ -1,6 +1,7 @@ + + Current cluster status: +-Online: [ 18node1 18node2 18node3 lxc1:container1 lxc2:container2 ] ++Online: [ 18node1 18node2 18node3 ] ++Containers: [ lxc1:container1 lxc2:container2 ] + + container1 (ocf::heartbeat:VirtualDomain): Started 18node2 + container2 (ocf::heartbeat:VirtualDomain): Started 18node2 +@@ -30,8 +31,8 @@ Executing cluster transition: + * Pseudo action: all_stopped + + Revised cluster status: +-Online: [ 18node1 18node2 18node3 lxc2:container2 ] +-OFFLINE: [ lxc1:container1 ] ++Online: [ 18node1 18node2 18node3 ] ++Containers: [ lxc2:container2 ] + + container1 (ocf::heartbeat:VirtualDomain): Stopped + container2 (ocf::heartbeat:VirtualDomain): Started 18node2 +diff --git a/tools/crm_mon.c b/tools/crm_mon.c +index 7c6e495..599df02 100644 +--- a/tools/crm_mon.c ++++ b/tools/crm_mon.c +@@ -1153,7 +1153,10 @@ print_status(pe_working_set_t * data_set) + node_t *dc = NULL; + char *since_epoch = NULL; + char *online_nodes = NULL; ++ char *online_remote_nodes = NULL; ++ char *online_remote_containers = NULL; + char *offline_nodes = NULL; ++ char *offline_remote_nodes = NULL; + const char *stack_s = NULL; + xmlNode *dc_version = NULL; + xmlNode *quorum_node = NULL; +@@ -1246,7 +1249,7 @@ print_status(pe_working_set_t * data_set) + const char *node_mode = NULL; + char *node_name = NULL; + +- if(node->details->remote_rsc) { ++ if (node->details->remote_rsc && node->details->remote_rsc->container) { + node_name = g_strdup_printf("%s:%s", node->details->uname, node->details->remote_rsc->container->id); + } else { + node_name = g_strdup_printf("%s", node->details->uname); +@@ -1286,23 +1289,37 @@ print_status(pe_working_set_t * data_set) + } else if (node->details->online) { + node_mode = "online"; + if (group_by_node == FALSE) { +- online_nodes = add_list_element(online_nodes, node_name); ++ if (node->details->remote_rsc && node->details->remote_rsc->container) { ++ online_remote_containers = add_list_element(online_remote_containers, node_name); ++ } else if (node->details->remote_rsc) { ++ online_remote_nodes = add_list_element(online_remote_nodes, node_name); ++ } else { ++ online_nodes = add_list_element(online_nodes, node_name); ++ } + continue; + } +- + } else { + node_mode = "OFFLINE"; + if (group_by_node == FALSE) { +- offline_nodes = add_list_element(offline_nodes, node_name); ++ ++ if (node->details->remote_rsc) { ++ if (node->details->remote_rsc->container == NULL) { ++ offline_remote_nodes = add_list_element(offline_remote_nodes, node_name); ++ } else { ++ /* ignore displaying offline container nodes */ ++ } ++ } else { ++ offline_nodes = add_list_element(offline_nodes, node_name); ++ } + continue; + } + } + +- if(node->details->remote_rsc) { +- online_nodes = add_list_element(online_nodes, node->details->remote_rsc->id); +- } +- +- if (safe_str_eq(node->details->uname, node->details->id)) { ++ if (node->details->remote_rsc && node->details->remote_rsc->container) { ++ print_as("ContainerNode %s: %s\n", node_name, node_mode); ++ } else if (node->details->remote_rsc) { ++ print_as("RemoteNode %s: %s\n", node_name, node_mode); ++ } else if (safe_str_eq(node->details->uname, node->details->id)) { + print_as("Node %s: %s\n", node_name, node_mode); + } else { + print_as("Node %s (%s): %s\n", node_name, node->details->id, node_mode); +@@ -1328,6 +1345,18 @@ print_status(pe_working_set_t * data_set) + print_as("OFFLINE: [%s ]\n", offline_nodes); + free(offline_nodes); + } ++ if (online_remote_nodes) { ++ print_as("RemoteOnline: [%s ]\n", online_remote_nodes); ++ free(online_remote_nodes); ++ } ++ if (offline_remote_nodes) { ++ print_as("RemoteOFFLINE: [%s ]\n", offline_remote_nodes); ++ free(offline_remote_nodes); ++ } ++ if (online_remote_containers) { ++ print_as("Containers: [%s ]\n", online_remote_containers); ++ free(online_remote_containers); ++ } + + if (group_by_node == FALSE && inactive_resources) { + print_as("\nFull list of resources:\n"); +diff --git a/tools/crm_simulate.c b/tools/crm_simulate.c +index 0d95e53..78cab50 100644 +--- a/tools/crm_simulate.c ++++ b/tools/crm_simulate.c +@@ -530,7 +530,10 @@ static void + print_cluster_status(pe_working_set_t * data_set) + { + char *online_nodes = NULL; ++ char *online_remote_nodes = NULL; ++ char *online_remote_containers = NULL; + char *offline_nodes = NULL; ++ char *offline_remote_nodes = NULL; + + GListPtr gIter = NULL; + +@@ -539,7 +542,7 @@ print_cluster_status(pe_working_set_t * data_set) + const char *node_mode = NULL; + char *node_name = NULL; + +- if(node->details->remote_rsc) { ++ if (node->details->remote_rsc && node->details->remote_rsc->container) { + node_name = g_strdup_printf("%s:%s", node->details->uname, node->details->remote_rsc->container->id); + } else { + node_name = g_strdup_printf("%s", node->details->uname); +@@ -576,24 +579,45 @@ print_cluster_status(pe_working_set_t * data_set) + node_mode = "OFFLINE (maintenance)"; + } + ++ ++ + } else if (node->details->online) { + node_mode = "online"; +- online_nodes = add_list_element(online_nodes, node_name); ++ if (node->details->remote_rsc && node->details->remote_rsc->container) { ++ online_remote_containers = add_list_element(online_remote_containers, node_name); ++ } else if (node->details->remote_rsc) { ++ online_remote_nodes = add_list_element(online_remote_nodes, node_name); ++ } else { ++ online_nodes = add_list_element(online_nodes, node_name); ++ } + free(node_name); + continue; + + } else { + node_mode = "OFFLINE"; +- offline_nodes = add_list_element(offline_nodes, node_name); ++ if (node->details->remote_rsc) { ++ if (node->details->remote_rsc->container == NULL) { ++ offline_remote_nodes = add_list_element(offline_remote_nodes, node_name); ++ } else { ++ /* ignore displaying offline container nodes */ ++ } ++ } else { ++ offline_nodes = add_list_element(offline_nodes, node_name); ++ } + free(node_name); + continue; + } + +- if (safe_str_eq(node_name, node->details->id)) { ++ if (node->details->remote_rsc && node->details->remote_rsc->container) { ++ printf("ContainerNode %s: %s\n", node_name, node_mode); ++ } else if (node->details->remote_rsc) { ++ printf("RemoteNode %s: %s\n", node_name, node_mode); ++ } else if (safe_str_eq(node->details->uname, node->details->id)) { + printf("Node %s: %s\n", node_name, node_mode); + } else { + printf("Node %s (%s): %s\n", node_name, node->details->id, node_mode); + } ++ + free(node_name); + } + +@@ -605,6 +629,18 @@ print_cluster_status(pe_working_set_t * data_set) + printf("OFFLINE: [%s ]\n", offline_nodes); + free(offline_nodes); + } ++ if (online_remote_nodes) { ++ printf("RemoteOnline: [%s ]\n", online_remote_nodes); ++ free(online_remote_nodes); ++ } ++ if (offline_remote_nodes) { ++ printf("RemoteOFFLINE: [%s ]\n", offline_remote_nodes); ++ free(offline_remote_nodes); ++ } ++ if (online_remote_containers) { ++ printf("Containers: [%s ]\n", online_remote_containers); ++ free(online_remote_containers); ++ } + + fprintf(stdout, "\n"); + for (gIter = data_set->resources; gIter != NULL; gIter = gIter->next) { diff --git a/SPECS/pacemaker.spec b/SPECS/pacemaker.spec index b41aece..ca0820d 100644 --- a/SPECS/pacemaker.spec +++ b/SPECS/pacemaker.spec @@ -2,7 +2,7 @@ %global uname hacluster %global pcmk_docdir %{_docdir}/%{name} -%global specversion 19 +%global specversion 29 %global upstream_prefix pacemaker %global upstream_version Pacemaker-1.1.10 @@ -118,6 +118,36 @@ Patch55: bz720543-pcmk-command_line_tools_should_stop_after_an_assertion_ Patch56: bz720543-pcmk-pe_probe_containers_not_expected_to_be_up.patch Patch57: bz720543-pcmk-pcmk_remote_ipv6_support.patch Patch58: bz1028627-pcmk-fix_controld_use_corosync2_dlm_variant.patch +Patch59: bz720543-pcmk-tools_fixes_formatting_of_remote_nodes_in_crm_mon_and_crm_simulate.patch +Patch60: bz720543-pcmk-corosync_attempt_to_retrieve_a_peer_s_node_name_if_it_is_not_already_known.patch +Patch61: bz720543-pcmk-removes_unnecessary_newlines_in_crm_resource_o_output.patch +Patch62: bz1057697-pcmk-services_detect_missing_agents_and_permission_errors_before_forking.patch +Patch63: bz1057697-pcmk-use_native_dbus_library_for_systemd_support_to_avoid_problematic_use_of_threads.patch +Patch64: bz1057697-pcmk-use_native_dbus_library_for_systemd_async_support_to_avoid_problematic_use_of_threads.patch +Patch65: bz1057697-pcmk-systemd_simplify_dbus_api_usage.patch +Patch66: bz1057697-pcmk-portability_use_basic_types_for_dbus_compatability_struct.patch +Patch67: bz1057697-pcmk-use_native_dbus_library_for_upstart_support_to_avoid_problematic_use_of_threads.patch +Patch68: bz1057697-pcmk-dbus_use_native_function_for_adding_arguments_to_messages.patch +Patch69: bz1057697-pcmk-services_keep_dbus_build_support_optional.patch +Patch70: bz1060205-pcmk-mcp_tell_systemd_not_to_respawn_us_if_we_return_100.patch +Patch71: bz1064519-pcmk-controld-handles-dlm-startup-fencing.patch +Patch72: bz1067536-pcmk-controld-wait-for-address-list.patch +Patch73: bz1069284-pcmk-prevent_resources_in_an_anti_colocation_from_even_temporarily_running_on_a_same_node.patch +Patch74: bz1070916-pcmk-send_details_of_stonith_api_time_and_stonith_api_kick_to_syslog.patch +Patch75: bz1070916-pcmk-fencing_pass_the_correct_options_when_looking_up_the_history_by_node_name.patch +Patch76: bz1070916-pcmk-api_time_helper_now_returns_when_the_most_recent_fencing_operation_completed.patch +Patch77: bz1070916-pcmk-crm_report_allow_ssh_alternatives_to_be_used.patch +Patch78: bz1070916-pcmk-crm_report_additional_dlm_detail.patch +Patch79: bz1070916-pcmk-crm_report_only_gather_dlm_data_if_dlm_controld_is_running.patch +Patch80: bz1070916-pcmk-pe_gracefully_handle_bad_values_for_xml_attr_transition_magic.patch +Patch81: bz1070916-pcmk-crmd_gracefully_handle_actions_that_cannot_be_initiated.patch +Patch82: bz1070916-pcmk-test_tools_set_up_override_for_local_schema_file_locations.patch +Patch83: bz1070916-pcmk-pengine_update_regression_tests.patch +Patch84: bz1070916-pcmk-crm_resource_prevent_use_of_null.patch +Patch85: bz1070916-pcmk-systemd_prevent_use_of_null_when_determining_if_an_agent_exists.patch +Patch86: bz1070916-pcmk-fencing_remove_shadow_definition_and_use_of_variable_progress.patch +Patch87: bz1078504-pcmk-pengine_fixes_invalid_transition_caused_by_clones_with_more_than_10_instances.patch +Patch88: bz1064519-pcmk-remove_q_0_from_default_dlm_controld_arguments.patch BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX) AutoReqProv: on @@ -151,7 +181,7 @@ Requires: libqb > 0.11.0 # Enables optional functionality BuildRequires: ncurses-devel openssl-devel libselinux-devel docbook-style-xsl -BuildRequires: bison byacc flex help2man gnutls-devel +BuildRequires: bison byacc flex help2man gnutls-devel dbus-devel %if %{defined _unitdir} BuildRequires: systemd-devel @@ -364,6 +394,36 @@ manager for Corosync, CMAN and/or Linux-HA. %patch56 -p1 %patch57 -p1 %patch58 -p1 +%patch59 -p1 +%patch60 -p1 +%patch61 -p1 +%patch62 -p1 +%patch63 -p1 +%patch64 -p1 +%patch65 -p1 +%patch66 -p1 +%patch67 -p1 +%patch68 -p1 +%patch69 -p1 +%patch70 -p1 +%patch71 -p1 +%patch72 -p1 +%patch73 -p1 +%patch74 -p1 +%patch75 -p1 +%patch76 -p1 +%patch77 -p1 +%patch78 -p1 +%patch79 -p1 +%patch80 -p1 +%patch81 -p1 +%patch82 -p1 +%patch83 -p1 +%patch84 -p1 +%patch85 -p1 +%patch86 -p1 +%patch87 -p1 +%patch88 -p1 # Force the local time # @@ -393,6 +453,9 @@ sed -i 's|^runpath_var=LD_RUN_PATH|runpath_var=DIE_RPATH_DIE|g' libtool make %{_smp_mflags} V=1 docdir=%{pcmk_docdir} all +%check +./BasicSanity.sh -V pengine cli + %install rm -rf %{buildroot} make DESTDIR=%{buildroot} docdir=%{pcmk_docdir} V=1 install @@ -422,6 +485,8 @@ find %{buildroot} -name '*.la' -type f -print0 | xargs -0 rm -f # Do not package these either rm -f %{buildroot}/%{_libdir}/service_crm.so +rm -f %{buildroot}/%{_sbindir}/fence_legacy +rm -f %{buildroot}/%{_mandir}/man8/fence_legacy.* find %{buildroot} -name 'o2cb*' -type f -print0 | xargs -0 rm -f # Don't ship init scripts for systemd based platforms @@ -500,7 +565,6 @@ exit 0 %{_sbindir}/crm_master %{_sbindir}/crm_node %{_sbindir}/attrd_updater -%{_sbindir}/fence_legacy %{_sbindir}/fence_pcmk %{_sbindir}/stonith_admin @@ -516,7 +580,6 @@ exit 0 %doc %{_mandir}/man8/crm_node.* %doc %{_mandir}/man8/crm_master.* %doc %{_mandir}/man8/fence_pcmk.* -%doc %{_mandir}/man8/fence_legacy.* %doc %{_mandir}/man8/pacemakerd.* %doc %{_mandir}/man8/stonith_admin.* @@ -636,6 +699,67 @@ exit 0 %doc AUTHORS %changelog +* Tue Mar 25 2014 David Vossel - 1.1.10-29 + +- Low: controld: Remove '-q 0' from default dlm_controld arguments + Resolves: rhbz#1064519 + +* Tue Mar 25 2014 David Vossel - 1.1.10-28 + +- Fix: pengine: fixes invalid transition caused by clones with more than 10 instances + Resolves: rhbz#1078504 + +* Fri Feb 28 2014 Andrew Beekhof - 1.1.10-27 + +- crm_resource: Prevent use-of-NULL +- systemd: Prevent use-of-NULL when determining if an agent exists +- Fencing: Remove shadow definition and use of variable 'progress' + Resolves: rhbz#1070916 + +* Thu Feb 27 2014 Andrew Beekhof - 1.1.10-26 + +- Run automated regression tests after every build +- Fencing: Send details of stonith_api_time() and stonith_api_kick() to syslog +- Fencing: Pass the correct options when looking up the history by node name +- Fencing: stonith_api_time_helper now returns when the most recent fencing operation completed +- crm_report: Additional dlm detail if dlm_controld is running +- crmd: Gracefully handle actions that cannot be initiated +- pengine: Gracefully handle bad values for XML_ATTR_TRANSITION_MAGIC + Resolves: rhbz#1070916 + +* Tue Feb 25 2014 David Vossel - 1.1.10-25 + +- pengine: cl#5187 - Prevent resources in an anti-colocation from even temporarily running on a same node + Resolves: rhbz#1069284 + +* Thu Feb 20 2014 David Vossel - 1.1.10-24 + +- controld: handling startup fencing within the controld agent, not the dlm + Resolves: rhbz#1064519 +- controld: Do not consider the dlm up until the address list is present + Resolves: rhbz#1067536 + +* Wed Feb 12 2014 Andrew Beekhof - 1.1.10-23 + +- mcp: Tell systemd not to respawn us if we return 100 +- services: Detect missing agents and permission errors before forking +- Use native DBus library for systemd support to avoid problematic use of threads + Resolves: rhbz#720543 (aka. 1057697) + +* Fri Dec 27 2013 Daniel Mach - 1.1.10-22 +- Mass rebuild 2013-12-27 + +* Wed Dec 04 2013 David Vossel - 1.1.10-21 + +- Fix: Removes unnecessary newlines in crm_resource -O output + Resolves: rhbz#720543 + +* Thu Nov 14 2013 Andrew Beekhof - 1.1.10-20 + +- Fix: tools: Fixes formatting of remote-nodes in crm_mon and crm_simulate +- Fix: Corosync: Attempt to retrieve a peers node name if it is not already known + Resolves: rhbz#720543 + * Thu Nov 14 2013 David Vossel - 1.1.10-19 - Fix: controld: Use the correct variant of dlm_controld for corosync-2 clusters @@ -647,7 +771,7 @@ exit 0 - High: remote: Add support for ipv6 into pacemaker_remote daemon Resolves: rhbz#720543 -* Wed Nov 06 2013 Andrew Beekhof - 1.1.10-17 +* Wed Nov 06 2013 Andrew Beekhof - 1.1.10-17 Resolves: rhbz#720543 @@ -675,7 +799,7 @@ exit 0 - Fix: remote: Handle endian changes between client and server and improve forward compatibility Resolves: rhbz#720543 -* Mon Oct 07 2013 Andrew Beekhof - 1.1.10-16 +* Mon Oct 07 2013 Andrew Beekhof - 1.1.10-16 - Remove unsupported resource agent - Log: crmd: Supply arguments in the correct order