diff --git a/configure.ac b/configure.ac index 02e2678..266e66a 100644 --- a/configure.ac +++ b/configure.ac @@ -81,6 +81,7 @@ AC_CHECK_LIB(crmcluster, crm_peer_init, , missing="yes") AC_CHECK_LIB(uuid, uuid_unparse, , missing="yes") AC_CHECK_LIB(cmap, cmap_initialize, , HAVE_cmap=0) AC_CHECK_LIB(votequorum, votequorum_getinfo, , HAVE_votequorum=0) +AC_CHECK_LIB(crmcommon, pacemakerd_api_new, HAVE_pacemakerd_api=1, HAVE_pacemakerd_api=0) dnl pacemaker >= 1.1.8 AC_CHECK_HEADERS(crm/cluster.h) @@ -125,6 +126,9 @@ AM_CONDITIONAL(CHECK_TWO_NODE, test "$HAVE_cmap" = "1") AC_DEFINE_UNQUOTED(CHECK_VOTEQUORUM_HANDLE, $HAVE_votequorum, Turn on periodic checking of votequorum-handle) AM_CONDITIONAL(CHECK_VOTEQUORUM_HANDLE, test "$HAVE_votequorum" = "1") +AC_DEFINE_UNQUOTED(USE_PACEMAKERD_API, $HAVE_pacemakerd_api, Turn on synchronization between sbd & pacemakerd) +AM_CONDITIONAL(USE_PACEMAKERD_API, test "$HAVE_pacemakerd_api" = "1") + CONFIGDIR="" AC_ARG_WITH(configdir, [ --with-configdir=DIR diff --git a/src/sbd-pacemaker.c b/src/sbd-pacemaker.c index 11e104d..3f9cec0 100644 --- a/src/sbd-pacemaker.c +++ b/src/sbd-pacemaker.c @@ -83,6 +83,43 @@ pe_free_working_set(pe_working_set_t *data_set) #endif +static void clean_up(int rc); + +#if USE_PACEMAKERD_API +#include +static char *admin_uuid = NULL; +static pacemakerd_t *pacemakerd_api = NULL; +time_t last_ok = (time_t) 0; + +static void +ping_pacemakerd(void) +{ + pacemakerd_api->cmds->ping(pacemakerd_api, + crm_system_name, admin_uuid, 0); +} + +static void +ping_callback(pacemakerd_t *pacemakerd, + time_t last_good, + enum pacemakerd_state state, + int rc, gpointer userdata) +{ + if ((last_good != (time_t) 0) && (rc == pcmk_ok)) { + switch (state) { + case pacemakerd_state_running: + case pacemakerd_state_shutting_down: + last_ok = last_good; + break; + case pacemakerd_state_shutdown_complete: + clean_up(EXIT_PCMK_SERVANT_GRACEFUL_SHUTDOWN); + break; + default: + break; + } + } +} +#endif + extern int disk_count; static void clean_up(int rc); @@ -133,10 +170,13 @@ mon_cib_connection_destroy(gpointer user_data) cib->cmds->signoff(cib); /* retrigger as last one might have been skipped */ mon_refresh_state(NULL); + +#if !USE_PACEMAKERD_API if (pcmk_clean_shutdown) { /* assume a graceful pacemaker-shutdown */ clean_up(EXIT_PCMK_SERVANT_GRACEFUL_SHUTDOWN); } +#endif /* getting here we aren't sure about the pacemaker-state so try to use the timeout to reconnect and get everything sorted out again @@ -196,6 +236,13 @@ mon_timer_notify(gpointer data) g_source_remove(timer_id_notify); } +#if USE_PACEMAKERD_API + { + time_t now = time(NULL); + + if ((last_ok <= now) && (now - last_ok < timeout_watchdog)) { +#endif + if (cib_connected) { if (counter == counter_max) { mon_retrieve_current_cib(); @@ -207,6 +254,13 @@ mon_timer_notify(gpointer data) counter++; } } + +#if USE_PACEMAKERD_API + } + } + ping_pacemakerd(); +#endif + timer_id_notify = g_timeout_add(timeout_loop * 1000, mon_timer_notify, NULL); return FALSE; } @@ -517,6 +571,13 @@ clean_up(int rc) cib = NULL; } +#if USE_PACEMAKERD_API + if (pacemakerd_api != NULL) { + pacemakerd_api->cmds->free(pacemakerd_api); + pacemakerd_api = NULL; + } +#endif + if (rc >= 0) { exit(rc); } @@ -526,11 +587,11 @@ clean_up(int rc) int servant_pcmk(const char *diskname, int mode, const void* argp) { - int exit_code = 0; + int exit_code = 0; - crm_system_name = strdup("sbd:pcmk"); - cl_log(LOG_NOTICE, "Monitoring Pacemaker health"); - set_proc_title("sbd: watcher: Pacemaker"); + crm_system_name = strdup("sbd:pcmk"); + cl_log(LOG_NOTICE, "Monitoring Pacemaker health"); + set_proc_title("sbd: watcher: Pacemaker"); setenv("PCMK_watchdog", "true", 1); if(debug == 0) { @@ -539,12 +600,34 @@ servant_pcmk(const char *diskname, int mode, const void* argp) } - if (data_set == NULL) { - data_set = pe_new_working_set(); - } - if (data_set == NULL) { - return -1; - } + if (data_set == NULL) { + data_set = pe_new_working_set(); + } + if (data_set == NULL) { + return -1; + } + +#if USE_PACEMAKERD_API + admin_uuid = crm_strdup_printf("%lu", (unsigned long) getpid()); + pacemakerd_api = pacemakerd_api_new(); + if (pacemakerd_api == NULL) { + return -1; + } + pacemakerd_api->cmds->set_ping_callback(pacemakerd_api, + ping_callback, NULL); + do { + pacemakerd_api->cmds->connect(pacemakerd_api, crm_system_name); + if (pacemakerd_api->conn_state == pacemakerd_conn_disconnected) { + sleep(reconnect_msec / 1000); + } + } while (pacemakerd_api->conn_state == pacemakerd_conn_disconnected); + /* send a ping to pacemakerd to wake it up */ + ping_pacemakerd(); + /* cib should come up now as well so it's time + * to have the inquisitor have a closer look + */ + notify_parent(); +#endif if (current_cib == NULL) { cib = cib_new();