diff --git a/Makefile.am b/Makefile.am index 0b425fc70f..8296a4bf83 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,86 +1,78 @@ # # Pacemaker code # # Copyright (C) 2004 Andrew Beekhof # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # EXTRA_DIST = autogen.sh ConfigureMe README.in libltdl.tar m4/gnulib-cache.m4 MAINTAINERCLEANFILES = Makefile.in aclocal.m4 configure DRF/config-h.in \ DRF/stamp-h.in libtool.m4 ltdl.m4 libltdl.tar CORE = $(LIBLTDL_DIR) replace include lib mcp attrd pengine cib crmd fencing lrmd tools xml SUBDIRS = $(CORE) cts extra doc doc_DATA = AUTHORS COPYING COPYING.LIB noinst_PROGRAMS = scratch AUTOMAKE_OPTIONS = foreign ACLOCAL_AMFLAGS = -I m4 testdir = $(datadir)/$(PACKAGE)/tests/ test_SCRIPTS = coverage.sh BasicSanity.sh test_DATA = valgrind-pcmk.suppressions # Scratch file for ad-hoc testing scratch_SOURCES = scratch.c scratch_LDADD = $(top_builddir)/lib/common/libcrmcommon.la -lm core: @echo "Building only core components: $(CORE)" list='$(CORE)'; for subdir in $$list; do echo "Building $$subdir"; $(MAKE) -C $$subdir all || exit 1; done core-install: @echo "Installing only core components: $(CORE)" list='$(CORE)'; for subdir in $$list; do echo "Installing $$subdir"; $(MAKE) -C $$subdir install || exit 1; done core-clean: @echo "Cleaning only core components: $(CORE)" list='$(CORE)'; for subdir in $$list; do echo "Cleaning $$subdir"; $(MAKE) -C $$subdir clean || exit 1; done install-exec-local: $(INSTALL) -d $(DESTDIR)/$(LCRSODIR) $(INSTALL) -d -m 750 $(DESTDIR)/$(CRM_CONFIG_DIR) $(INSTALL) -d -m 750 $(DESTDIR)/$(CRM_STATE_DIR) $(INSTALL) -d -m 750 $(DESTDIR)/$(CRM_BLACKBOX_DIR) -chown $(CRM_DAEMON_USER):$(CRM_DAEMON_GROUP) $(DESTDIR)/$(CRM_CONFIG_DIR) -chown $(CRM_DAEMON_USER):$(CRM_DAEMON_GROUP) $(DESTDIR)/$(CRM_STATE_DIR) -chown $(CRM_DAEMON_USER):$(CRM_DAEMON_GROUP) $(DESTDIR)/$(CRM_BLACKBOX_DIR) if BUILD_CS_PLUGIN rm -f $(DESTDIR)$(LCRSODIR)/pacemaker.lcrso $(DESTDIR)$(LCRSODIR)/service_crm.so cp $(DESTDIR)$(libdir)/service_crm.so $(DESTDIR)$(LCRSODIR)/pacemaker.lcrso endif -if BUILD_HEARTBEAT_SUPPORT - $(INSTALL) -d $(DESTDIR)/$(HB_DAEMON_DIR) - ln -sf $(CRM_DAEMON_DIR)/attrd $(DESTDIR)$(HB_DAEMON_DIR)/ - ln -sf $(CRM_DAEMON_DIR)/cib $(DESTDIR)$(HB_DAEMON_DIR)/ - ln -sf $(CRM_DAEMON_DIR)/crmd $(DESTDIR)$(HB_DAEMON_DIR)/ - ln -sf $(CRM_DAEMON_DIR)/pengine $(DESTDIR)$(HB_DAEMON_DIR)/ - ln -sf $(CRM_DAEMON_DIR)/stonithd $(DESTDIR)$(HB_DAEMON_DIR)/ -endif # Use chown because the user/group may not exist clean-generic: rm -f $(TARFILE) *.tar.bz2 *.sed dist-clean-local: rm -f autoconf automake autoheader maintainer-clean-local: rm -f libltdl.tar .PHONY: rpm pkg handy handy-copy diff --git a/cib/callbacks.c b/cib/callbacks.c index 9fb2de9f99..681602843f 100644 --- a/cib/callbacks.c +++ b/cib/callbacks.c @@ -1,1613 +1,1621 @@ /* * Copyright (C) 2004 Andrew Beekhof * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "common.h" typedef struct cib_local_notify_s { xmlNode *notify_src; char *client_id; gboolean from_peer; gboolean sync_reply; } cib_local_notify_t; int next_client_id = 0; gboolean legacy_mode = FALSE; qb_ipcs_service_t *ipcs_ro = NULL; qb_ipcs_service_t *ipcs_rw = NULL; qb_ipcs_service_t *ipcs_shm = NULL; gint cib_GCompareFunc(gconstpointer a, gconstpointer b); gboolean can_write(int flags); void send_cib_replace(const xmlNode * sync_request, const char *host); void cib_process_request(xmlNode * request, gboolean privileged, gboolean force_synchronous, gboolean from_peer, crm_client_t * cib_client); int cib_process_command(xmlNode * request, xmlNode ** reply, xmlNode ** cib_diff, gboolean privileged); gboolean cib_common_callback(qb_ipcs_connection_t * c, void *data, size_t size, gboolean privileged); static gboolean cib_read_legacy_mode(void) { static gboolean init = TRUE; static gboolean legacy = FALSE; if(init) { init = FALSE; legacy = daemon_option_enabled("cib", "legacy"); if(legacy) { crm_notice("Enabled legacy mode"); } } return legacy; } static gboolean cib_legacy_mode(void) { if(cib_read_legacy_mode()) { return TRUE; } return legacy_mode; } static int32_t cib_ipc_accept(qb_ipcs_connection_t * c, uid_t uid, gid_t gid) { crm_trace("Connection %p", c); if (cib_shutdown_flag) { crm_info("Ignoring new client [%d] during shutdown", crm_ipcs_client_pid(c)); return -EPERM; } if (crm_client_new(c, uid, gid) == NULL) { return -EIO; } return 0; } static void cib_ipc_created(qb_ipcs_connection_t * c) { crm_trace("Connection %p", c); } static int32_t cib_ipc_dispatch_rw(qb_ipcs_connection_t * c, void *data, size_t size) { crm_client_t *client = crm_client_get(c); crm_trace("%p message from %s", c, client->id); return cib_common_callback(c, data, size, TRUE); } static int32_t cib_ipc_dispatch_ro(qb_ipcs_connection_t * c, void *data, size_t size) { crm_client_t *client = crm_client_get(c); crm_trace("%p message from %s", c, client->id); return cib_common_callback(c, data, size, FALSE); } /* Error code means? */ static int32_t cib_ipc_closed(qb_ipcs_connection_t * c) { crm_client_t *client = crm_client_get(c); if (client == NULL) { return 0; } crm_trace("Connection %p", c); crm_client_destroy(client); return 0; } static void cib_ipc_destroy(qb_ipcs_connection_t * c) { crm_trace("Connection %p", c); cib_ipc_closed(c); if (cib_shutdown_flag) { cib_shutdown(0); } } struct qb_ipcs_service_handlers ipc_ro_callbacks = { .connection_accept = cib_ipc_accept, .connection_created = cib_ipc_created, .msg_process = cib_ipc_dispatch_ro, .connection_closed = cib_ipc_closed, .connection_destroyed = cib_ipc_destroy }; struct qb_ipcs_service_handlers ipc_rw_callbacks = { .connection_accept = cib_ipc_accept, .connection_created = cib_ipc_created, .msg_process = cib_ipc_dispatch_rw, .connection_closed = cib_ipc_closed, .connection_destroyed = cib_ipc_destroy }; void cib_common_callback_worker(uint32_t id, uint32_t flags, xmlNode * op_request, crm_client_t * cib_client, gboolean privileged) { const char *op = crm_element_value(op_request, F_CIB_OPERATION); if (crm_str_eq(op, CRM_OP_REGISTER, TRUE)) { if (flags & crm_ipc_client_response) { xmlNode *ack = create_xml_node(NULL, __FUNCTION__); crm_xml_add(ack, F_CIB_OPERATION, CRM_OP_REGISTER); crm_xml_add(ack, F_CIB_CLIENTID, cib_client->id); crm_ipcs_send(cib_client, id, ack, flags); cib_client->request_id = 0; free_xml(ack); } return; } else if (crm_str_eq(op, T_CIB_NOTIFY, TRUE)) { /* Update the notify filters for this client */ int on_off = 0; long long bit = 0; const char *type = crm_element_value(op_request, F_CIB_NOTIFY_TYPE); crm_element_value_int(op_request, F_CIB_NOTIFY_ACTIVATE, &on_off); crm_debug("Setting %s callbacks for %s (%s): %s", type, cib_client->name, cib_client->id, on_off ? "on" : "off"); if (safe_str_eq(type, T_CIB_POST_NOTIFY)) { bit = cib_notify_post; } else if (safe_str_eq(type, T_CIB_PRE_NOTIFY)) { bit = cib_notify_pre; } else if (safe_str_eq(type, T_CIB_UPDATE_CONFIRM)) { bit = cib_notify_confirm; } else if (safe_str_eq(type, T_CIB_DIFF_NOTIFY)) { bit = cib_notify_diff; } else if (safe_str_eq(type, T_CIB_REPLACE_NOTIFY)) { bit = cib_notify_replace; } if (on_off) { set_bit(cib_client->options, bit); } else { clear_bit(cib_client->options, bit); } if (flags & crm_ipc_client_response) { /* TODO - include rc */ crm_ipcs_send_ack(cib_client, id, flags, "ack", __FUNCTION__, __LINE__); } return; } cib_process_request(op_request, FALSE, privileged, FALSE, cib_client); } int32_t cib_common_callback(qb_ipcs_connection_t * c, void *data, size_t size, gboolean privileged) { uint32_t id = 0; uint32_t flags = 0; int call_options = 0; crm_client_t *cib_client = crm_client_get(c); xmlNode *op_request = crm_ipcs_recv(cib_client, data, size, &id, &flags); if (op_request) { crm_element_value_int(op_request, F_CIB_CALLOPTS, &call_options); } if (op_request == NULL) { crm_trace("Invalid message from %p", c); crm_ipcs_send_ack(cib_client, id, flags, "nack", __FUNCTION__, __LINE__); return 0; } else if(cib_client == NULL) { crm_trace("Invalid client %p", c); return 0; } if (is_set(call_options, cib_sync_call)) { CRM_ASSERT(flags & crm_ipc_client_response); CRM_LOG_ASSERT(cib_client->request_id == 0); /* This means the client has two synchronous events in-flight */ cib_client->request_id = id; /* Reply only to the last one */ } if (cib_client->name == NULL) { const char *value = crm_element_value(op_request, F_CIB_CLIENTNAME); if (value == NULL) { cib_client->name = crm_itoa(cib_client->pid); } else { cib_client->name = strdup(value); } } crm_xml_add(op_request, F_CIB_CLIENTID, cib_client->id); crm_xml_add(op_request, F_CIB_CLIENTNAME, cib_client->name); #if ENABLE_ACL CRM_ASSERT(cib_client->user != NULL); crm_acl_get_set_user(op_request, F_CIB_USER, cib_client->user); #endif crm_log_xml_trace(op_request, "Client[inbound]"); cib_common_callback_worker(id, flags, op_request, cib_client, privileged); free_xml(op_request); return 0; } static uint64_t ping_seq = 0; static char *ping_digest = NULL; static bool ping_modified_since = FALSE; int sync_our_cib(xmlNode * request, gboolean all); static gboolean cib_digester_cb(gpointer data) { if (cib_is_master) { char buffer[32]; xmlNode *ping = create_xml_node(NULL, "ping"); ping_seq++; free(ping_digest); ping_digest = NULL; ping_modified_since = FALSE; snprintf(buffer, 32, U64T, ping_seq); crm_trace("Requesting peer digests (%s)", buffer); crm_xml_add(ping, F_TYPE, "cib"); crm_xml_add(ping, F_CIB_OPERATION, CRM_OP_PING); crm_xml_add(ping, F_CIB_PING_ID, buffer); crm_xml_add(ping, XML_ATTR_CRM_VERSION, CRM_FEATURE_SET); send_cluster_message(NULL, crm_msg_cib, ping, TRUE); free_xml(ping); } return FALSE; } static void process_ping_reply(xmlNode *reply) { uint64_t seq = 0; const char *host = crm_element_value(reply, F_ORIG); xmlNode *pong = get_message_xml(reply, F_CIB_CALLDATA); const char *seq_s = crm_element_value(pong, F_CIB_PING_ID); const char *digest = crm_element_value(pong, XML_ATTR_DIGEST); if (seq_s) { seq = crm_int_helper(seq_s, NULL); } if(digest == NULL) { crm_trace("Ignoring ping reply %s from %s with no digest", seq_s, host); } else if(seq != ping_seq) { crm_trace("Ignoring out of sequence ping reply %s from %s", seq_s, host); } else if(ping_modified_since) { crm_trace("Ignoring ping reply %s from %s: cib updated since", seq_s, host); } else { const char *version = crm_element_value(pong, XML_ATTR_CRM_VERSION); if(ping_digest == NULL) { crm_trace("Calculating new digest"); ping_digest = calculate_xml_versioned_digest(the_cib, FALSE, TRUE, version); } crm_trace("Processing ping reply %s from %s (%s)", seq_s, host, digest); if(safe_str_eq(ping_digest, digest) == FALSE) { xmlNode *remote_cib = get_message_xml(pong, F_CIB_CALLDATA); crm_notice("Local CIB %s.%s.%s.%s differs from %s: %s.%s.%s.%s %p", crm_element_value(the_cib, XML_ATTR_GENERATION_ADMIN), crm_element_value(the_cib, XML_ATTR_GENERATION), crm_element_value(the_cib, XML_ATTR_NUMUPDATES), ping_digest, host, remote_cib?crm_element_value(remote_cib, XML_ATTR_GENERATION_ADMIN):"_", remote_cib?crm_element_value(remote_cib, XML_ATTR_GENERATION):"_", remote_cib?crm_element_value(remote_cib, XML_ATTR_NUMUPDATES):"_", digest, remote_cib); if(remote_cib && remote_cib->children) { /* Additional debug */ xml_calculate_changes(the_cib, remote_cib); xml_log_changes(LOG_INFO, __FUNCTION__, remote_cib); crm_trace("End of differences"); } free_xml(remote_cib); sync_our_cib(reply, FALSE); } } } static void do_local_notify(xmlNode * notify_src, const char *client_id, gboolean sync_reply, gboolean from_peer) { /* send callback to originating child */ crm_client_t *client_obj = NULL; int local_rc = pcmk_ok; int call_id = 0; crm_element_value_int(notify_src, F_CIB_CALLID, &call_id); if (client_id != NULL) { client_obj = crm_client_get_by_id(client_id); } if (client_obj == NULL) { local_rc = -ECONNRESET; crm_trace("No client to sent response %d to, F_CIB_CLIENTID not set.", call_id); } else { int rid = 0; if (sync_reply) { if (client_obj->ipcs) { CRM_LOG_ASSERT(client_obj->request_id); rid = client_obj->request_id; client_obj->request_id = 0; crm_trace("Sending response %d to %s %s", rid, client_obj->name, from_peer ? "(originator of delegated request)" : ""); } else { crm_trace("Sending response [call %d] to %s %s", call_id, client_obj->name, from_peer ? "(originator of delegated request)" : ""); } } else { crm_trace("Sending event %d to %s %s", call_id, client_obj->name, from_peer ? "(originator of delegated request)" : ""); } switch (client_obj->kind) { case CRM_CLIENT_IPC: if (crm_ipcs_send(client_obj, rid, notify_src, sync_reply?crm_ipc_flags_none:crm_ipc_server_event) < 0) { local_rc = -ENOMSG; } break; #ifdef HAVE_GNUTLS_GNUTLS_H case CRM_CLIENT_TLS: #endif case CRM_CLIENT_TCP: crm_remote_send(client_obj->remote, notify_src); break; default: crm_err("Unknown transport %d for %s", client_obj->kind, client_obj->name); } } if (local_rc != pcmk_ok && client_obj != NULL) { crm_warn("%sSync reply to %s failed: %s", sync_reply ? "" : "A-", client_obj ? client_obj->name : "", pcmk_strerror(local_rc)); } } static void parse_local_options_v1(crm_client_t * cib_client, int call_type, int call_options, const char *host, const char *op, gboolean * local_notify, gboolean * needs_reply, gboolean * process, gboolean * needs_forward) { if (cib_op_modifies(call_type) && !(call_options & cib_inhibit_bcast)) { /* we need to send an update anyway */ *needs_reply = TRUE; } else { *needs_reply = FALSE; } if (host == NULL && (call_options & cib_scope_local)) { crm_trace("Processing locally scoped %s op from %s", op, cib_client->name); *local_notify = TRUE; } else if (host == NULL && cib_is_master) { crm_trace("Processing master %s op locally from %s", op, cib_client->name); *local_notify = TRUE; } else if (safe_str_eq(host, cib_our_uname)) { crm_trace("Processing locally addressed %s op from %s", op, cib_client->name); *local_notify = TRUE; } else if (stand_alone) { *needs_forward = FALSE; *local_notify = TRUE; *process = TRUE; } else { crm_trace("%s op from %s needs to be forwarded to %s", op, cib_client->name, host ? host : "the master instance"); *needs_forward = TRUE; *process = FALSE; } } static void parse_local_options_v2(crm_client_t * cib_client, int call_type, int call_options, const char *host, const char *op, gboolean * local_notify, gboolean * needs_reply, gboolean * process, gboolean * needs_forward) { if (cib_op_modifies(call_type)) { if(safe_str_eq(op, CIB_OP_MASTER) || safe_str_eq(op, CIB_OP_SLAVE)) { /* Always handle these locally */ *process = TRUE; *needs_reply = FALSE; *local_notify = TRUE; *needs_forward = FALSE; return; } else { /* Redirect all other updates via CPG */ *needs_reply = TRUE; *needs_forward = TRUE; *process = FALSE; crm_trace("%s op from %s needs to be forwarded to %s", op, cib_client->name, host ? host : "the master instance"); return; } } *process = TRUE; *needs_reply = FALSE; *local_notify = TRUE; *needs_forward = FALSE; if (stand_alone) { crm_trace("Processing %s op from %s (stand-alone)", op, cib_client->name); } else if (host == NULL) { crm_trace("Processing unaddressed %s op from %s", op, cib_client->name); } else if (safe_str_eq(host, cib_our_uname)) { crm_trace("Processing locally addressed %s op from %s", op, cib_client->name); } else { crm_trace("%s op from %s needs to be forwarded to %s", op, cib_client->name, host); *needs_forward = TRUE; *process = FALSE; } } static void parse_local_options(crm_client_t * cib_client, int call_type, int call_options, const char *host, const char *op, gboolean * local_notify, gboolean * needs_reply, gboolean * process, gboolean * needs_forward) { if(cib_legacy_mode()) { parse_local_options_v1(cib_client, call_type, call_options, host, op, local_notify, needs_reply, process, needs_forward); } else { parse_local_options_v2(cib_client, call_type, call_options, host, op, local_notify, needs_reply, process, needs_forward); } } static gboolean parse_peer_options_v1(int call_type, xmlNode * request, gboolean * local_notify, gboolean * needs_reply, gboolean * process, gboolean * needs_forward) { const char *op = NULL; const char *host = NULL; const char *delegated = NULL; const char *originator = crm_element_value(request, F_ORIG); const char *reply_to = crm_element_value(request, F_CIB_ISREPLY); const char *update = crm_element_value(request, F_CIB_GLOBAL_UPDATE); gboolean is_reply = safe_str_eq(reply_to, cib_our_uname); if (crm_is_true(update)) { *needs_reply = FALSE; if (is_reply) { *local_notify = TRUE; crm_trace("Processing global/peer update from %s" " that originated from us", originator); } else { crm_trace("Processing global/peer update from %s", originator); } return TRUE; } crm_trace("Processing %s request sent by %s", op, originator); op = crm_element_value(request, F_CIB_OPERATION); if (safe_str_eq(op, "cib_shutdown_req")) { /* Always process these */ *local_notify = FALSE; if (reply_to == NULL || is_reply) { *process = TRUE; } if (is_reply) { *needs_reply = FALSE; } return *process; } if (is_reply && safe_str_eq(op, CRM_OP_PING)) { process_ping_reply(request); return FALSE; } if (is_reply) { crm_trace("Forward reply sent from %s to local clients", originator); *process = FALSE; *needs_reply = FALSE; *local_notify = TRUE; return TRUE; } host = crm_element_value(request, F_CIB_HOST); if (host != NULL && safe_str_eq(host, cib_our_uname)) { crm_trace("Processing %s request sent to us from %s", op, originator); return TRUE; } else if(is_reply == FALSE && safe_str_eq(op, CRM_OP_PING)) { crm_trace("Processing %s request sent to %s by %s", op, host?host:"everyone", originator); *needs_reply = TRUE; return TRUE; } else if (host == NULL && cib_is_master == TRUE) { crm_trace("Processing %s request sent to master instance from %s", op, originator); return TRUE; } delegated = crm_element_value(request, F_CIB_DELEGATED); if (delegated != NULL) { crm_trace("Ignoring msg for master instance"); } else if (host != NULL) { /* this is for a specific instance and we're not it */ crm_trace("Ignoring msg for instance on %s", crm_str(host)); } else if (reply_to == NULL && cib_is_master == FALSE) { /* this is for the master instance and we're not it */ crm_trace("Ignoring reply to %s", crm_str(reply_to)); } else if (safe_str_eq(op, "cib_shutdown_req")) { if (reply_to != NULL) { crm_debug("Processing %s from %s", op, host); *needs_reply = FALSE; } else { crm_debug("Processing %s reply from %s", op, host); } return TRUE; } else { crm_err("Nothing for us to do?"); crm_log_xml_err(request, "Peer[inbound]"); } return FALSE; } static gboolean parse_peer_options_v2(int call_type, xmlNode * request, gboolean * local_notify, gboolean * needs_reply, gboolean * process, gboolean * needs_forward) { const char *host = NULL; const char *delegated = crm_element_value(request, F_CIB_DELEGATED); const char *op = crm_element_value(request, F_CIB_OPERATION); const char *originator = crm_element_value(request, F_ORIG); const char *reply_to = crm_element_value(request, F_CIB_ISREPLY); const char *update = crm_element_value(request, F_CIB_GLOBAL_UPDATE); gboolean is_reply = safe_str_eq(reply_to, cib_our_uname); if(safe_str_eq(op, CIB_OP_REPLACE)) { /* sync_our_cib() sets F_CIB_ISREPLY */ if (reply_to) { delegated = reply_to; } goto skip_is_reply; } else if(safe_str_eq(op, CIB_OP_SYNC)) { } else if (is_reply && safe_str_eq(op, CRM_OP_PING)) { process_ping_reply(request); return FALSE; } else if (safe_str_eq(op, CIB_OP_UPGRADE)) { /* Only the DC (node with the oldest software) should process * this operation if F_CIB_SCHEMA_MAX is unset * * If the DC is happy it will then send out another * CIB_OP_UPGRADE which will tell all nodes to do the actual * upgrade. * * Except this time F_CIB_SCHEMA_MAX will be set which puts a * limit on how far newer nodes will go */ const char *max = crm_element_value(request, F_CIB_SCHEMA_MAX); crm_trace("Parsing %s operation%s for %s with max=%s", op, is_reply?" reply":"", cib_is_master?"master":"slave", max); if(max == NULL && cib_is_master) { /* We are the DC, check if this upgrade is allowed */ goto skip_is_reply; } else if(max) { /* Ok, go ahead and upgrade to 'max' */ goto skip_is_reply; } else { return FALSE; /* Ignore */ } } else if (crm_is_true(update)) { crm_info("Detected legacy %s global update from %s", op, originator); send_sync_request(NULL); legacy_mode = TRUE; return FALSE; } else if (is_reply && cib_op_modifies(call_type)) { crm_trace("Ignoring legacy %s reply sent from %s to local clients", op, originator); return FALSE; } else if (safe_str_eq(op, "cib_shutdown_req")) { /* Legacy handling */ crm_debug("Legacy handling of %s message from %s", op, originator); *local_notify = FALSE; if (reply_to == NULL) { *process = TRUE; } return *process; } if(is_reply) { crm_trace("Handling %s reply sent from %s to local clients", op, originator); *process = FALSE; *needs_reply = FALSE; *local_notify = TRUE; return TRUE; } skip_is_reply: *process = TRUE; *needs_reply = FALSE; if(safe_str_eq(delegated, cib_our_uname)) { *local_notify = TRUE; } else { *local_notify = FALSE; } host = crm_element_value(request, F_CIB_HOST); if (host != NULL && safe_str_eq(host, cib_our_uname)) { crm_trace("Processing %s request sent to us from %s", op, originator); *needs_reply = TRUE; return TRUE; } else if (host != NULL) { /* this is for a specific instance and we're not it */ crm_trace("Ignoring %s operation for instance on %s", op, crm_str(host)); return FALSE; } else if(is_reply == FALSE && safe_str_eq(op, CRM_OP_PING)) { *needs_reply = TRUE; } crm_trace("Processing %s request sent to everyone by %s/%s on %s %s", op, crm_element_value(request, F_CIB_CLIENTNAME), crm_element_value(request, F_CIB_CALLID), originator, (*local_notify)?"(notify)":""); return TRUE; } static gboolean parse_peer_options(int call_type, xmlNode * request, gboolean * local_notify, gboolean * needs_reply, gboolean * process, gboolean * needs_forward) { /* TODO: What happens when an update comes in after node A * requests the CIB from node B, but before it gets the reply (and * sends out the replace operation) */ if(cib_legacy_mode()) { return parse_peer_options_v1( call_type, request, local_notify, needs_reply, process, needs_forward); } else { return parse_peer_options_v2( call_type, request, local_notify, needs_reply, process, needs_forward); } } static void forward_request(xmlNode * request, crm_client_t * cib_client, int call_options) { const char *op = crm_element_value(request, F_CIB_OPERATION); const char *host = crm_element_value(request, F_CIB_HOST); crm_xml_add(request, F_CIB_DELEGATED, cib_our_uname); if (host != NULL) { crm_trace("Forwarding %s op to %s", op, host); send_cluster_message(crm_get_peer(0, host), crm_msg_cib, request, FALSE); } else { crm_trace("Forwarding %s op to master instance", op); send_cluster_message(NULL, crm_msg_cib, request, FALSE); } /* Return the request to its original state */ xml_remove_prop(request, F_CIB_DELEGATED); if (call_options & cib_discard_reply) { crm_trace("Client not interested in reply"); } } static gboolean send_peer_reply(xmlNode * msg, xmlNode * result_diff, const char *originator, gboolean broadcast) { CRM_ASSERT(msg != NULL); if (broadcast) { /* this (successful) call modified the CIB _and_ the * change needs to be broadcast... * send via HA to other nodes */ int diff_add_updates = 0; int diff_add_epoch = 0; int diff_add_admin_epoch = 0; int diff_del_updates = 0; int diff_del_epoch = 0; int diff_del_admin_epoch = 0; const char *digest = NULL; CRM_LOG_ASSERT(result_diff != NULL); digest = crm_element_value(result_diff, XML_ATTR_DIGEST); cib_diff_version_details(result_diff, &diff_add_admin_epoch, &diff_add_epoch, &diff_add_updates, &diff_del_admin_epoch, &diff_del_epoch, &diff_del_updates); crm_trace("Sending update diff %d.%d.%d -> %d.%d.%d %s", diff_del_admin_epoch, diff_del_epoch, diff_del_updates, diff_add_admin_epoch, diff_add_epoch, diff_add_updates, digest); crm_xml_add(msg, F_CIB_ISREPLY, originator); crm_xml_add(msg, F_CIB_GLOBAL_UPDATE, XML_BOOLEAN_TRUE); crm_xml_add(msg, F_CIB_OPERATION, CIB_OP_APPLY_DIFF); CRM_ASSERT(digest != NULL); add_message_xml(msg, F_CIB_UPDATE_DIFF, result_diff); crm_log_xml_explicit(msg, "copy"); return send_cluster_message(NULL, crm_msg_cib, msg, TRUE); } else if (originator != NULL) { /* send reply via HA to originating node */ crm_trace("Sending request result to %s only", originator); crm_xml_add(msg, F_CIB_ISREPLY, originator); return send_cluster_message(crm_get_peer(0, originator), crm_msg_cib, msg, FALSE); } return FALSE; } void cib_process_request(xmlNode * request, gboolean force_synchronous, gboolean privileged, gboolean unused, crm_client_t * cib_client) { int call_type = 0; int call_options = 0; gboolean process = TRUE; gboolean is_update = TRUE; gboolean from_peer = TRUE; gboolean needs_reply = TRUE; gboolean local_notify = FALSE; gboolean needs_forward = FALSE; gboolean global_update = crm_is_true(crm_element_value(request, F_CIB_GLOBAL_UPDATE)); xmlNode *op_reply = NULL; xmlNode *result_diff = NULL; int rc = pcmk_ok; const char *op = crm_element_value(request, F_CIB_OPERATION); const char *originator = crm_element_value(request, F_ORIG); const char *host = crm_element_value(request, F_CIB_HOST); const char *target = NULL; const char *call_id = crm_element_value(request, F_CIB_CALLID); const char *client_id = crm_element_value(request, F_CIB_CLIENTID); const char *client_name = crm_element_value(request, F_CIB_CLIENTNAME); const char *reply_to = crm_element_value(request, F_CIB_ISREPLY); if (cib_client) { from_peer = FALSE; } cib_num_ops++; if (cib_num_ops == 0) { cib_num_fail = 0; cib_num_local = 0; cib_num_updates = 0; crm_info("Stats wrapped around"); } crm_element_value_int(request, F_CIB_CALLOPTS, &call_options); if (force_synchronous) { call_options |= cib_sync_call; } if (host != NULL && strlen(host) == 0) { host = NULL; } if (host) { target = host; } else if (call_options & cib_scope_local) { target = "local host"; } else { target = "master"; } if (from_peer) { crm_trace("Processing peer %s operation from %s/%s on %s intended for %s (reply=%s)", op, client_name, call_id, originator, target, reply_to); } else { crm_xml_add(request, F_ORIG, cib_our_uname); crm_trace("Processing local %s operation from %s/%s intended for %s", op, client_name, call_id, target); } rc = cib_get_operation_id(op, &call_type); if (rc != pcmk_ok) { /* TODO: construct error reply? */ crm_err("Pre-processing of command failed: %s", pcmk_strerror(rc)); return; } if (from_peer == FALSE) { parse_local_options(cib_client, call_type, call_options, host, op, &local_notify, &needs_reply, &process, &needs_forward); } else if (parse_peer_options(call_type, request, &local_notify, &needs_reply, &process, &needs_forward) == FALSE) { return; } is_update = cib_op_modifies(call_type); if (is_update) { cib_num_updates++; } if (call_options & cib_discard_reply) { needs_reply = is_update; local_notify = FALSE; } if (needs_forward) { const char *host = crm_element_value(request, F_CIB_HOST); const char *section = crm_element_value(request, F_CIB_SECTION); crm_info("Forwarding %s operation for section %s to %s (origin=%s/%s/%s)", op, section ? section : "'all'", host ? host : "master", originator ? originator : "local", client_name, call_id); forward_request(request, cib_client, call_options); return; } if (cib_status != pcmk_ok) { const char *call = crm_element_value(request, F_CIB_CALLID); rc = cib_status; crm_err("Operation ignored, cluster configuration is invalid." " Please repair and restart: %s", pcmk_strerror(cib_status)); op_reply = create_xml_node(NULL, "cib-reply"); crm_xml_add(op_reply, F_TYPE, T_CIB); crm_xml_add(op_reply, F_CIB_OPERATION, op); crm_xml_add(op_reply, F_CIB_CALLID, call); crm_xml_add(op_reply, F_CIB_CLIENTID, client_id); crm_xml_add_int(op_reply, F_CIB_CALLOPTS, call_options); crm_xml_add_int(op_reply, F_CIB_RC, rc); crm_trace("Attaching reply output"); add_message_xml(op_reply, F_CIB_CALLDATA, the_cib); crm_log_xml_explicit(op_reply, "cib:reply"); } else if (process) { time_t finished = 0; int now = time(NULL); int level = LOG_INFO; const char *section = crm_element_value(request, F_CIB_SECTION); cib_num_local++; rc = cib_process_command(request, &op_reply, &result_diff, privileged); if (is_update == FALSE) { level = LOG_TRACE; } else if (global_update) { switch (rc) { case pcmk_ok: level = LOG_INFO; break; case -pcmk_err_old_data: case -pcmk_err_diff_resync: case -pcmk_err_diff_failed: level = LOG_TRACE; break; default: level = LOG_ERR; } } else if (rc != pcmk_ok && is_update) { cib_num_fail++; level = LOG_WARNING; } do_crm_log(level, "Completed %s operation for section %s: %s (rc=%d, origin=%s/%s/%s, version=%s.%s.%s)", op, section ? section : "'all'", pcmk_strerror(rc), rc, originator ? originator : "local", client_name, call_id, the_cib ? crm_element_value(the_cib, XML_ATTR_GENERATION_ADMIN) : "0", the_cib ? crm_element_value(the_cib, XML_ATTR_GENERATION) : "0", the_cib ? crm_element_value(the_cib, XML_ATTR_NUMUPDATES) : "0"); finished = time(NULL); if (finished - now > 3) { crm_trace("%s operation took %ds to complete", op, finished - now); crm_write_blackbox(0, NULL); } if (op_reply == NULL && (needs_reply || local_notify)) { crm_err("Unexpected NULL reply to message"); crm_log_xml_err(request, "null reply"); needs_reply = FALSE; local_notify = FALSE; } } /* from now on we are the server */ if(is_update && cib_legacy_mode() == FALSE) { crm_trace("Completed pre-sync update from %s/%s/%s%s", originator ? originator : "local", client_name, call_id, local_notify?" with local notification":""); } else if (needs_reply == FALSE || stand_alone) { /* nothing more to do... * this was a non-originating slave update */ crm_trace("Completed slave update"); } else if (call_options & cib_discard_reply) { crm_trace("Caller isn't interested in reply"); } else if (from_peer) { if (is_update == FALSE || result_diff == NULL) { crm_trace("Request not broadcast: R/O call"); } else if (call_options & cib_inhibit_bcast) { crm_trace("Request not broadcast: inhibited"); } else if (rc != pcmk_ok) { crm_trace("Request not broadcast: call failed: %s", pcmk_strerror(rc)); } else { crm_trace("Directing reply to %s", originator); } send_peer_reply(op_reply, result_diff, originator, FALSE); } if (local_notify && client_id) { crm_trace("Performing local %ssync notification for %s", (call_options & cib_sync_call) ? "" : "a-", client_id); if (process == FALSE) { do_local_notify(request, client_id, call_options & cib_sync_call, from_peer); } else { do_local_notify(op_reply, client_id, call_options & cib_sync_call, from_peer); } } free_xml(op_reply); free_xml(result_diff); return; } int cib_process_command(xmlNode * request, xmlNode ** reply, xmlNode ** cib_diff, gboolean privileged) { xmlNode *input = NULL; xmlNode *output = NULL; xmlNode *result_cib = NULL; xmlNode *current_cib = NULL; int call_type = 0; int call_options = 0; const char *op = NULL; const char *section = NULL; const char *call_id = crm_element_value(request, F_CIB_CALLID); int rc = pcmk_ok; int rc2 = pcmk_ok; gboolean send_r_notify = FALSE; gboolean global_update = FALSE; gboolean config_changed = FALSE; gboolean manage_counters = TRUE; static mainloop_timer_t *digest_timer = NULL; CRM_ASSERT(cib_status == pcmk_ok); if(digest_timer == NULL) { digest_timer = mainloop_timer_add("digester", 5000, FALSE, cib_digester_cb, NULL); } *reply = NULL; *cib_diff = NULL; current_cib = the_cib; /* Start processing the request... */ op = crm_element_value(request, F_CIB_OPERATION); crm_element_value_int(request, F_CIB_CALLOPTS, &call_options); rc = cib_get_operation_id(op, &call_type); if (rc == pcmk_ok && privileged == FALSE) { rc = cib_op_can_run(call_type, call_options, privileged, global_update); } rc2 = cib_op_prepare(call_type, request, &input, §ion); if (rc == pcmk_ok) { rc = rc2; } if (rc != pcmk_ok) { crm_trace("Call setup failed: %s", pcmk_strerror(rc)); goto done; } else if (cib_op_modifies(call_type) == FALSE) { rc = cib_perform_op(op, call_options, cib_op_func(call_type), TRUE, section, request, input, FALSE, &config_changed, current_cib, &result_cib, NULL, &output); CRM_CHECK(result_cib == NULL, free_xml(result_cib)); goto done; } /* Handle a valid write action */ global_update = crm_is_true(crm_element_value(request, F_CIB_GLOBAL_UPDATE)); if (global_update) { /* legacy code */ manage_counters = FALSE; call_options |= cib_force_diff; crm_trace("Global update detected"); CRM_CHECK(call_type == 3 || call_type == 4, crm_err("Call type: %d", call_type); crm_log_xml_err(request, "bad op")); } if (rc == pcmk_ok) { ping_modified_since = TRUE; if (call_options & cib_inhibit_bcast) { /* skip */ crm_trace("Skipping update: inhibit broadcast"); manage_counters = FALSE; } if (is_not_set(call_options, cib_dryrun) && safe_str_eq(section, XML_CIB_TAG_STATUS)) { /* Copying large CIBs accounts for a huge percentage of our CIB usage */ call_options |= cib_zero_copy; } else { clear_bit(call_options, cib_zero_copy); } /* result_cib must not be modified after cib_perform_op() returns */ rc = cib_perform_op(op, call_options, cib_op_func(call_type), FALSE, section, request, input, manage_counters, &config_changed, current_cib, &result_cib, cib_diff, &output); if (manage_counters == FALSE) { /* Legacy code * If the diff is NULL at this point, its because nothing changed */ config_changed = cib_config_changed(NULL, NULL, cib_diff); } /* Always write to disk for replace ops, * this also negates the need to detect ordering changes */ if (crm_str_eq(CIB_OP_REPLACE, op, TRUE)) { config_changed = TRUE; } } if (rc == pcmk_ok && is_not_set(call_options, cib_dryrun)) { if(is_not_set(call_options, cib_zero_copy)) { rc = activateCibXml(result_cib, config_changed, op); } if (rc == pcmk_ok && cib_internal_config_changed(*cib_diff)) { cib_read_config(config_hash, result_cib); } if (crm_str_eq(CIB_OP_REPLACE, op, TRUE)) { if (section == NULL) { send_r_notify = TRUE; } else if (safe_str_eq(section, XML_TAG_CIB)) { send_r_notify = TRUE; } else if (safe_str_eq(section, XML_CIB_TAG_NODES)) { send_r_notify = TRUE; } else if (safe_str_eq(section, XML_CIB_TAG_STATUS)) { send_r_notify = TRUE; } } else if (crm_str_eq(CIB_OP_ERASE, op, TRUE)) { send_r_notify = TRUE; } mainloop_timer_stop(digest_timer); mainloop_timer_start(digest_timer); } else if (rc == -pcmk_err_schema_validation) { CRM_ASSERT(is_not_set(call_options, cib_zero_copy)); if (output != NULL) { crm_log_xml_info(output, "cib:output"); free_xml(output); } output = result_cib; } else { if(is_not_set(call_options, cib_zero_copy)) { free_xml(result_cib); } } if ((call_options & cib_inhibit_notify) == 0) { const char *client = crm_element_value(request, F_CIB_CLIENTNAME); crm_trace("Sending notifications"); cib_diff_notify(call_options, client, call_id, op, input, rc, *cib_diff); } if (send_r_notify) { const char *origin = crm_element_value(request, F_ORIG); cib_replace_notify(origin, the_cib, rc, *cib_diff); } xml_log_patchset(LOG_TRACE, "cib:diff", *cib_diff); done: if ((call_options & cib_discard_reply) == 0) { const char *caller = crm_element_value(request, F_CIB_CLIENTID); *reply = create_xml_node(NULL, "cib-reply"); crm_xml_add(*reply, F_TYPE, T_CIB); crm_xml_add(*reply, F_CIB_OPERATION, op); crm_xml_add(*reply, F_CIB_CALLID, call_id); crm_xml_add(*reply, F_CIB_CLIENTID, caller); crm_xml_add_int(*reply, F_CIB_CALLOPTS, call_options); crm_xml_add_int(*reply, F_CIB_RC, rc); if (output != NULL) { crm_trace("Attaching reply output"); add_message_xml(*reply, F_CIB_CALLDATA, output); } crm_log_xml_explicit(*reply, "cib:reply"); } crm_trace("cleanup"); if (cib_op_modifies(call_type) == FALSE && output != current_cib) { free_xml(output); output = NULL; } if (call_type >= 0) { cib_op_cleanup(call_type, call_options, &input, &output); } crm_trace("done"); return rc; } gint cib_GCompareFunc(gconstpointer a, gconstpointer b) { const xmlNode *a_msg = a; const xmlNode *b_msg = b; int msg_a_id = 0; int msg_b_id = 0; const char *value = NULL; value = crm_element_value_const(a_msg, F_CIB_CALLID); msg_a_id = crm_parse_int(value, NULL); value = crm_element_value_const(b_msg, F_CIB_CALLID); msg_b_id = crm_parse_int(value, NULL); if (msg_a_id == msg_b_id) { return 0; } else if (msg_a_id < msg_b_id) { return -1; } return 1; } #if SUPPORT_HEARTBEAT void cib_ha_peer_callback(HA_Message * msg, void *private_data) { xmlNode *xml = convert_ha_message(NULL, msg, __FUNCTION__); cib_peer_callback(xml, private_data); free_xml(xml); } #endif void cib_peer_callback(xmlNode * msg, void *private_data) { const char *reason = NULL; const char *originator = crm_element_value(msg, F_ORIG); if (cib_legacy_mode() && (originator == NULL || crm_str_eq(originator, cib_our_uname, TRUE))) { /* message is from ourselves */ return; } else if (crm_peer_cache == NULL) { reason = "membership not established"; goto bail; } if (crm_element_value(msg, F_CIB_CLIENTNAME) == NULL) { crm_xml_add(msg, F_CIB_CLIENTNAME, originator); } /* crm_log_xml_trace("Peer[inbound]", msg); */ cib_process_request(msg, FALSE, TRUE, TRUE, NULL); return; bail: if (reason) { const char *seq = crm_element_value(msg, F_SEQ); const char *op = crm_element_value(msg, F_CIB_OPERATION); crm_warn("Discarding %s message (%s) from %s: %s", op, seq, originator, reason); } } #if SUPPORT_HEARTBEAT extern oc_ev_t *cib_ev_token; static void *ccm_library = NULL; int (*ccm_api_callback_done) (void *cookie) = NULL; int (*ccm_api_handle_event) (const oc_ev_t * token) = NULL; void cib_client_status_callback(const char *node, const char *client, const char *status, void *private) { crm_node_t *peer = NULL; if (safe_str_eq(client, CRM_SYSTEM_CIB)) { + peer = crm_get_peer(0, node); + if (safe_str_neq(peer->state, CRM_NODE_MEMBER)) { + crm_warn("This peer is not a ccm member (yet). " + "Status ignored: Client %s/%s announced status [%s]", + node, client, status); + return; + } + crm_info("Status update: Client %s/%s now has status [%s]", node, client, status); if (safe_str_eq(status, JOINSTATUS)) { status = ONLINESTATUS; } else if (safe_str_eq(status, LEAVESTATUS)) { status = OFFLINESTATUS; } - peer = crm_get_peer(0, node); crm_update_peer_proc(__FUNCTION__, peer, crm_proc_cib, status); } return; } int cib_ccm_dispatch(gpointer user_data) { int rc = 0; oc_ev_t *ccm_token = (oc_ev_t *) user_data; crm_trace("received callback"); if (ccm_api_handle_event == NULL) { ccm_api_handle_event = find_library_function(&ccm_library, CCM_LIBRARY, "oc_ev_handle_event", 1); } rc = (*ccm_api_handle_event) (ccm_token); if (0 == rc) { return 0; } crm_err("CCM connection appears to have failed: rc=%d.", rc); /* eventually it might be nice to recover and reconnect... but until then... */ crm_err("Exiting to recover from CCM connection failure"); return crm_exit(ENOTCONN); } int current_instance = 0; void cib_ccm_msg_callback(oc_ed_t event, void *cookie, size_t size, const void *data) { gboolean update_id = FALSE; const oc_ev_membership_t *membership = data; CRM_ASSERT(membership != NULL); crm_info("Processing CCM event=%s (id=%d)", ccm_event_name(event), membership->m_instance); if (current_instance > membership->m_instance) { crm_err("Membership instance ID went backwards! %d->%d", current_instance, membership->m_instance); CRM_ASSERT(current_instance <= membership->m_instance); } switch (event) { case OC_EV_MS_NEW_MEMBERSHIP: case OC_EV_MS_INVALID: update_id = TRUE; break; case OC_EV_MS_PRIMARY_RESTORED: update_id = TRUE; break; case OC_EV_MS_NOT_PRIMARY: crm_trace("Ignoring transitional CCM event: %s", ccm_event_name(event)); break; case OC_EV_MS_EVICTED: crm_err("Evicted from CCM: %s", ccm_event_name(event)); break; default: crm_err("Unknown CCM event: %d", event); } if (update_id) { unsigned int lpc = 0; CRM_CHECK(membership != NULL, return); current_instance = membership->m_instance; for (lpc = 0; lpc < membership->m_n_out; lpc++) { crm_update_ccm_node(membership, lpc + membership->m_out_idx, CRM_NODE_LOST, current_instance); } for (lpc = 0; lpc < membership->m_n_member; lpc++) { - crm_update_ccm_node(membership, lpc + membership->m_memb_idx, CRM_NODE_ACTIVE, + crm_update_ccm_node(membership, lpc + membership->m_memb_idx, CRM_NODE_MEMBER, current_instance); } + heartbeat_cluster->llc_ops->client_status(heartbeat_cluster, NULL, crm_system_name, 0); } if (ccm_api_callback_done == NULL) { ccm_api_callback_done = find_library_function(&ccm_library, CCM_LIBRARY, "oc_ev_callback_done", 1); } (*ccm_api_callback_done) (cookie); return; } #endif gboolean can_write(int flags) { return TRUE; } static gboolean cib_force_exit(gpointer data) { crm_notice("Forcing exit!"); terminate_cib(__FUNCTION__, TRUE); return FALSE; } static void disconnect_remote_client(gpointer key, gpointer value, gpointer user_data) { crm_client_t *a_client = value; crm_err("Disconnecting %s... Not implemented", crm_str(a_client->name)); } void cib_shutdown(int nsig) { struct qb_ipcs_stats srv_stats; if (cib_shutdown_flag == FALSE) { int disconnects = 0; qb_ipcs_connection_t *c = NULL; cib_shutdown_flag = TRUE; c = qb_ipcs_connection_first_get(ipcs_rw); while (c != NULL) { qb_ipcs_connection_t *last = c; c = qb_ipcs_connection_next_get(ipcs_rw, last); crm_debug("Disconnecting r/w client %p...", last); qb_ipcs_disconnect(last); qb_ipcs_connection_unref(last); disconnects++; } c = qb_ipcs_connection_first_get(ipcs_ro); while (c != NULL) { qb_ipcs_connection_t *last = c; c = qb_ipcs_connection_next_get(ipcs_ro, last); crm_debug("Disconnecting r/o client %p...", last); qb_ipcs_disconnect(last); qb_ipcs_connection_unref(last); disconnects++; } c = qb_ipcs_connection_first_get(ipcs_shm); while (c != NULL) { qb_ipcs_connection_t *last = c; c = qb_ipcs_connection_next_get(ipcs_shm, last); crm_debug("Disconnecting non-blocking r/w client %p...", last); qb_ipcs_disconnect(last); qb_ipcs_connection_unref(last); disconnects++; } disconnects += crm_hash_table_size(client_connections); crm_debug("Disconnecting %d remote clients", crm_hash_table_size(client_connections)); g_hash_table_foreach(client_connections, disconnect_remote_client, NULL); crm_info("Disconnected %d clients", disconnects); } qb_ipcs_stats_get(ipcs_rw, &srv_stats, QB_FALSE); if (crm_hash_table_size(client_connections) == 0) { crm_info("All clients disconnected (%d)", srv_stats.active_connections); initiate_exit(); } else { crm_info("Waiting on %d clients to disconnect (%d)", crm_hash_table_size(client_connections), srv_stats.active_connections); } } void initiate_exit(void) { int active = 0; xmlNode *leaving = NULL; active = crm_active_peers(); if (active < 2) { terminate_cib(__FUNCTION__, FALSE); return; } crm_info("Sending disconnect notification to %d peers...", active); leaving = create_xml_node(NULL, "exit-notification"); crm_xml_add(leaving, F_TYPE, "cib"); crm_xml_add(leaving, F_CIB_OPERATION, "cib_shutdown_req"); send_cluster_message(NULL, crm_msg_cib, leaving, TRUE); free_xml(leaving); g_timeout_add(crm_get_msec("5s"), cib_force_exit, NULL); } extern int remote_fd; extern int remote_tls_fd; void terminate_cib(const char *caller, gboolean fast) { if (remote_fd > 0) { close(remote_fd); remote_fd = 0; } if (remote_tls_fd > 0) { close(remote_tls_fd); remote_tls_fd = 0; } if (!fast) { crm_info("%s: Disconnecting from cluster infrastructure", caller); crm_cluster_disconnect(&crm_cluster); } uninitializeCib(); crm_info("%s: Exiting%s...", caller, fast ? " fast" : mainloop ? " from mainloop" : ""); if (fast == FALSE && mainloop != NULL && g_main_is_running(mainloop)) { g_main_quit(mainloop); } else { qb_ipcs_destroy(ipcs_ro); qb_ipcs_destroy(ipcs_rw); qb_ipcs_destroy(ipcs_shm); if (fast) { crm_exit(EINVAL); } else { crm_exit(pcmk_ok); } } } diff --git a/configure.ac b/configure.ac index a45af59a55..e0c39a60cd 100644 --- a/configure.ac +++ b/configure.ac @@ -1,1920 +1,1921 @@ dnl dnl autoconf for Pacemaker dnl dnl License: GNU General Public License (GPL) dnl =============================================== dnl Bootstrap dnl =============================================== AC_PREREQ(2.59) dnl Suggested structure: dnl information on the package dnl checks for programs dnl checks for libraries dnl checks for header files dnl checks for types dnl checks for structures dnl checks for compiler characteristics dnl checks for library functions dnl checks for system services m4_include([version.m4]) AC_INIT([pacemaker], VERSION_NUMBER, pacemaker@oss.clusterlabs.org,pacemaker,http://clusterlabs.org) PCMK_FEATURES="" HB_PKG=heartbeat AC_CONFIG_AUX_DIR(.) AC_CANONICAL_HOST dnl Where #defines go (e.g. `AC_CHECK_HEADERS' below) dnl dnl Internal header: include/config.h dnl - Contains ALL defines dnl - include/config.h.in is generated automatically by autoheader dnl - NOT to be included in any header files except lha_internal.h dnl (which is also not to be included in any other header files) dnl dnl External header: include/crm_config.h dnl - Contains a subset of defines checked here dnl - Manually edit include/crm_config.h.in to have configure include dnl new defines dnl - Should not include HAVE_* defines dnl - Safe to include anywhere AM_CONFIG_HEADER(include/config.h include/crm_config.h) ALL_LINGUAS="en fr" AC_ARG_WITH(version, [ --with-version=version Override package version (if you're a packager needing to pretend) ], [ PACKAGE_VERSION="$withval" ]) AC_ARG_WITH(pkg-name, [ --with-pkg-name=name Override package name (if you're a packager needing to pretend) ], [ PACKAGE_NAME="$withval" ]) dnl Older distros may need: AM_INIT_AUTOMAKE($PACKAGE_NAME, $PACKAGE_VERSION) AM_INIT_AUTOMAKE AC_DEFINE_UNQUOTED(PACEMAKER_VERSION, "$PACKAGE_VERSION", Current pacemaker version) PACKAGE_SERIES=`echo $PACKAGE_VERSION | awk -F. '{ print $1"."$2 }'` AC_SUBST(PACKAGE_SERIES) AC_SUBST(PACKAGE_VERSION) dnl automake >= 1.11 offers --enable-silent-rules for suppressing the output from dnl normal compilation. When a failure occurs, it will then display the full dnl command line dnl Wrap in m4_ifdef to avoid breaking on older platforms m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])]) dnl Example 2.4. Silent Custom Rule to Generate a File dnl %-bar.pc: %.pc dnl $(AM_V_GEN)$(LN_S) $(notdir $^) $@ CC_IN_CONFIGURE=yes export CC_IN_CONFIGURE LDD=ldd BUILD_ATOMIC_ATTRD=1 dnl ======================================================================== dnl Compiler characteristics dnl ======================================================================== AC_PROG_CC dnl Can force other with environment variable "CC". AM_PROG_CC_C_O AC_PROG_CC_STDC gl_EARLY gl_INIT AC_LIBTOOL_DLOPEN dnl Enable dlopen support... AC_LIBLTDL_CONVENIENCE dnl make libltdl a convenience lib AC_PROG_LIBTOOL AC_PROG_YACC AM_PROG_LEX AC_C_STRINGIZE AC_TYPE_SIZE_T AC_CHECK_SIZEOF(char) AC_CHECK_SIZEOF(short) AC_CHECK_SIZEOF(int) AC_CHECK_SIZEOF(long) AC_CHECK_SIZEOF(long long) AC_STRUCT_TIMEZONE dnl =============================================== dnl Helpers dnl =============================================== cc_supports_flag() { local CFLAGS="-Werror $@" AC_MSG_CHECKING(whether $CC supports "$@") AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ ]], [[ ]])], [RC=0; AC_MSG_RESULT(yes)],[RC=1; AC_MSG_RESULT(no)]) return $RC } try_extract_header_define() { AC_MSG_CHECKING(if $2 in $1 exists) Cfile=$srcdir/extract_define.$2.${$} printf "#include \n" > ${Cfile}.c printf "#include <%s>\n" $1 >> ${Cfile}.c printf "int main(int argc, char **argv) {\n" >> ${Cfile}.c printf "#ifdef %s\n" $2 >> ${Cfile}.c printf "printf(\"%%s\", %s);\n" $2 >> ${Cfile}.c printf "#endif \n return 0; }\n" >> ${Cfile}.c $CC $CFLAGS ${Cfile}.c -o ${Cfile} 2>/dev/null value= if test -x ${Cfile}; then value=`${Cfile} 2>/dev/null` fi if test x"${value}" == x""; then value=$3 AC_MSG_RESULT(default: $value) else AC_MSG_RESULT($value) fi printf $value rm -rf ${Cfile}.c ${Cfile} ${Cfile}.dSYM ${Cfile}.gcno } extract_header_define() { AC_MSG_CHECKING(for $2 in $1) Cfile=$srcdir/extract_define.$2.${$} printf "#include \n" > ${Cfile}.c printf "#include <%s>\n" $1 >> ${Cfile}.c printf "int main(int argc, char **argv) { printf(\"%%s\", %s); return 0; }\n" $2 >> ${Cfile}.c $CC $CFLAGS ${Cfile}.c -o ${Cfile} value=`${Cfile}` AC_MSG_RESULT($value) printf $value rm -rf ${Cfile}.c ${Cfile} ${Cfile}.dSYM ${Cfile}.gcno } dnl =============================================== dnl Configure Options dnl =============================================== dnl Some systems, like Solaris require a custom package name AC_ARG_WITH(pkgname, [ --with-pkgname=name name for pkg (typically for Solaris) ], [ PKGNAME="$withval" ], [ PKGNAME="LXHAhb" ], ) AC_SUBST(PKGNAME) AC_ARG_ENABLE([ansi], [ --enable-ansi force GCC to compile to ANSI/ANSI standard for older compilers. [default=no]]) AC_ARG_ENABLE([fatal-warnings], [ --enable-fatal-warnings very pedantic and fatal warnings for gcc [default=yes]]) AC_ARG_ENABLE([quiet], [ --enable-quiet Supress make output unless there is an error [default=no]]) AC_ARG_ENABLE([thread-safe], [ --enable-thread-safe Enable some client libraries to be thread safe. [default=no]]) AC_ARG_ENABLE([bundled-ltdl], [ --enable-bundled-ltdl Configure, build and install the standalone ltdl library bundled with ${PACKAGE} [default=no]]) LTDL_LIBS="" AC_ARG_ENABLE([no-stack], [ --enable-no-stack Only build the Policy Engine and pieces needed to support it [default=no]]) AC_ARG_ENABLE([upstart], [ --enable-upstart Do not build support for the Upstart init system [default=yes]]) AC_ARG_ENABLE([systemd], [ --enable-systemd Do not build support for the Systemd init system [default=yes]]) AC_ARG_WITH(ais, [ --with-ais Support the Corosync messaging and membership layer ], [ SUPPORT_CS=$withval ], [ SUPPORT_CS=try ], ) AC_ARG_WITH(corosync, [ --with-corosync Support the Corosync messaging and membership layer ], [ SUPPORT_CS=$withval ] dnl initialized in AC_ARG_WITH(ais...) already, dnl don't reset to try if it was given as --without-ais ) AC_ARG_WITH(heartbeat, [ --with-heartbeat Support the Heartbeat messaging and membership layer ], [ SUPPORT_HEARTBEAT=$withval ], [ SUPPORT_HEARTBEAT=try ], ) AC_ARG_WITH(cman, [ --with-cman Support the consumption of membership and quorum from cman ], [ SUPPORT_CMAN=$withval ], [ SUPPORT_CMAN=try ], ) AC_ARG_WITH(cpg, [ --with-cs-quorum Support the consumption of membership and quorum from corosync ], [ SUPPORT_CS_QUORUM=$withval ], [ SUPPORT_CS_QUORUM=try ], ) AC_ARG_WITH(nagios, [ --with-nagios Support nagios remote monitoring ], [ SUPPORT_NAGIOS=$withval ], [ SUPPORT_NAGIOS=try ], ) AC_ARG_WITH(nagios-plugin-dir, [ --with-nagios-plugin-dir=DIR Directory for nagios plugins [${NAGIOS_PLUGIN_DIR}]], [ NAGIOS_PLUGIN_DIR="$withval" ] ) AC_ARG_WITH(nagios-metadata-dir, [ --with-nagios-metadata-dir=DIR Directory for nagios plugins metadata [${NAGIOS_METADATA_DIR}]], [ NAGIOS_METADATA_DIR="$withval" ] ) AC_ARG_WITH(snmp, [ --with-snmp Support the SNMP protocol ], [ SUPPORT_SNMP=$withval ], [ SUPPORT_SNMP=try ], ) AC_ARG_WITH(esmtp, [ --with-esmtp Support the sending mail notifications with the esmtp library ], [ SUPPORT_ESMTP=$withval ], [ SUPPORT_ESMTP=try ], ) AC_ARG_WITH(acl, [ --with-acl Support CIB ACL ], [ SUPPORT_ACL=$withval ], [ SUPPORT_ACL=yes ], ) AC_ARG_WITH(cibsecrets, [ --with-cibsecrets Support CIB secrets ], [ SUPPORT_CIBSECRETS=$withval ], [ SUPPORT_CIBSECRETS=no ], ) CSPREFIX="" AC_ARG_WITH(ais-prefix, [ --with-ais-prefix=DIR Prefix used when Corosync was installed [$prefix]], [ CSPREFIX=$withval ], [ CSPREFIX=$prefix ]) LCRSODIR="" AC_ARG_WITH(lcrso-dir, [ --with-lcrso-dir=DIR Corosync lcrso files. ], [ LCRSODIR="$withval" ]) INITDIR="" AC_ARG_WITH(initdir, [ --with-initdir=DIR directory for init (rc) scripts [${INITDIR}]], [ INITDIR="$withval" ]) SUPPORT_PROFILING=0 AC_ARG_WITH(profiling, [ --with-profiling Disable optimizations for effective profiling ], [ SUPPORT_PROFILING=$withval ]) AC_ARG_WITH(coverage, [ --with-coverage Disable optimizations for effective profiling ], [ SUPPORT_COVERAGE=$withval ]) PUBLICAN_BRAND="common" AC_ARG_WITH(brand, [ --with-brand=brand Brand to use for generated documentation [$PUBLICAN_BRAND]], [ PUBLICAN_BRAND="$withval" ]) AC_SUBST(PUBLICAN_BRAND) ASCIIDOC_CLI_TYPE="pcs" AC_ARG_WITH(doc-cli, [ --with-doc-cli=cli_type CLI type to use for generated documentation. [$ASCIIDOC_CLI_TYPE]], [ ASCIIDOC_CLI_TYPE="$withval" ]) AC_SUBST(ASCIIDOC_CLI_TYPE) dnl =============================================== dnl General Processing dnl =============================================== AC_SUBST(HB_PKG) INIT_EXT="" echo Our Host OS: $host_os/$host AC_MSG_NOTICE(Sanitizing prefix: ${prefix}) case $prefix in NONE) prefix=/usr dnl Fix default variables - "prefix" variable if not specified if test "$localstatedir" = "\${prefix}/var"; then localstatedir="/var" fi if test "$sysconfdir" = "\${prefix}/etc"; then sysconfdir="/etc" fi ;; esac AC_MSG_NOTICE(Sanitizing exec_prefix: ${exec_prefix}) case $exec_prefix in dnl For consistency with Heartbeat, map NONE->$prefix NONE) exec_prefix=$prefix;; prefix) exec_prefix=$prefix;; esac AC_MSG_NOTICE(Sanitizing ais_prefix: ${CSPREFIX}) case $CSPREFIX in dnl For consistency with Heartbeat, map NONE->$prefix NONE) CSPREFIX=$prefix;; prefix) CSPREFIX=$prefix;; esac AC_MSG_NOTICE(Sanitizing INITDIR: ${INITDIR}) case $INITDIR in prefix) INITDIR=$prefix;; "") AC_MSG_CHECKING(which init (rc) directory to use) for initdir in /etc/init.d /etc/rc.d/init.d /sbin/init.d \ /usr/local/etc/rc.d /etc/rc.d do if test -d $initdir then INITDIR=$initdir break fi done AC_MSG_RESULT($INITDIR);; esac AC_SUBST(INITDIR) AC_MSG_NOTICE(Sanitizing libdir: ${libdir}) case $libdir in dnl For consistency with Heartbeat, map NONE->$prefix *prefix*|NONE) AC_MSG_CHECKING(which lib directory to use) for aDir in lib64 lib do trydir="${exec_prefix}/${aDir}" if test -d ${trydir} then libdir=${trydir} break fi done AC_MSG_RESULT($libdir); ;; esac dnl Expand autoconf variables so that we dont end up with '${prefix}' dnl in #defines and python scripts dnl NOTE: Autoconf deliberately leaves them unexpanded to allow dnl make exec_prefix=/foo install dnl No longer being able to do this seems like no great loss to me... eval prefix="`eval echo ${prefix}`" eval exec_prefix="`eval echo ${exec_prefix}`" eval bindir="`eval echo ${bindir}`" eval sbindir="`eval echo ${sbindir}`" eval libexecdir="`eval echo ${libexecdir}`" eval datadir="`eval echo ${datadir}`" eval sysconfdir="`eval echo ${sysconfdir}`" eval sharedstatedir="`eval echo ${sharedstatedir}`" eval localstatedir="`eval echo ${localstatedir}`" eval libdir="`eval echo ${libdir}`" eval includedir="`eval echo ${includedir}`" eval oldincludedir="`eval echo ${oldincludedir}`" eval infodir="`eval echo ${infodir}`" eval mandir="`eval echo ${mandir}`" dnl Home-grown variables eval INITDIR="${INITDIR}" eval docdir="`eval echo ${docdir}`" if test x"${docdir}" = x""; then docdir=${datadir}/doc/${PACKAGE}-${VERSION} #docdir=${datadir}/doc/packages/${PACKAGE} fi AC_SUBST(docdir) for j in prefix exec_prefix bindir sbindir libexecdir datadir sysconfdir \ sharedstatedir localstatedir libdir includedir oldincludedir infodir \ mandir INITDIR docdir do dirname=`eval echo '${'${j}'}'` if test ! -d "$dirname" then AC_MSG_WARN([$j directory ($dirname) does not exist!]) fi done dnl This OS-based decision-making is poor autotools practice; dnl feature-based mechanisms are strongly preferred. dnl dnl So keep this section to a bare minimum; regard as a "necessary evil". case "$host_os" in *bsd*) AC_DEFINE_UNQUOTED(ON_BSD, 1, Compiling for BSD platform) LIBS="-L/usr/local/lib" CPPFLAGS="$CPPFLAGS -I/usr/local/include" INIT_EXT=".sh" ;; *solaris*) AC_DEFINE_UNQUOTED(ON_SOLARIS, 1, Compiling for Solaris platform) ;; *linux*) AC_DEFINE_UNQUOTED(ON_LINUX, 1, Compiling for Linux platform) CFLAGS="$CFLAGS -I${prefix}/include" ;; darwin*) AC_DEFINE_UNQUOTED(ON_DARWIN, 1, Compiling for Darwin platform) LIBS="$LIBS -L${prefix}/lib" CFLAGS="$CFLAGS -I${prefix}/include" ;; esac dnl Eventually remove this CFLAGS="$CFLAGS -I${prefix}/include/heartbeat" AC_SUBST(INIT_EXT) AC_MSG_NOTICE(Host CPU: $host_cpu) case "$host_cpu" in ppc64|powerpc64) case $CFLAGS in *powerpc64*) ;; *) if test "$GCC" = yes; then CFLAGS="$CFLAGS -m64" fi ;; esac esac AC_MSG_CHECKING(which format is needed to print uint64_t) ac_save_CFLAGS=$CFLAGS CFLAGS="-Wall -Werror" AC_COMPILE_IFELSE( [AC_LANG_PROGRAM( [ #include #include #include ], [ int max = 512; uint64_t bignum = 42; char *buffer = malloc(max); const char *random = "random"; snprintf(buffer, max-1, "", bignum, random); fprintf(stderr, "Result: %s\n", buffer); ] )], [U64T="%lu"], [U64T="%llu"] ) CFLAGS=$ac_save_CFLAGS AC_MSG_RESULT($U64T) AC_DEFINE_UNQUOTED(U64T, "$U64T", Correct printf format for logging uint64_t) dnl =============================================== dnl Program Paths dnl =============================================== PATH="$PATH:/sbin:/usr/sbin:/usr/local/sbin:/usr/local/bin" export PATH dnl Replacing AC_PROG_LIBTOOL with AC_CHECK_PROG because LIBTOOL dnl was NOT being expanded all the time thus causing things to fail. AC_CHECK_PROGS(LIBTOOL, glibtool libtool libtool15 libtool13) AM_PATH_PYTHON AC_CHECK_PROGS(MAKE, gmake make) AC_PATH_PROGS(HTML2TXT, lynx w3m) AC_PATH_PROGS(HELP2MAN, help2man) AC_PATH_PROGS(POD2MAN, pod2man, pod2man) AC_PATH_PROGS(ASCIIDOC, asciidoc) AC_PATH_PROGS(PUBLICAN, publican) AC_PATH_PROGS(INKSCAPE, inkscape) AC_PATH_PROGS(XSLTPROC, xsltproc) AC_PATH_PROGS(FOP, fop) AC_PATH_PROGS(SSH, ssh, /usr/bin/ssh) AC_PATH_PROGS(SCP, scp, /usr/bin/scp) AC_PATH_PROGS(TAR, tar) AC_PATH_PROGS(MD5, md5) AC_PATH_PROGS(TEST, test) AC_PATH_PROGS(PKGCONFIG, pkg-config) AC_PATH_PROGS(XML2CONFIG, xml2-config) AC_PATH_PROGS(VALGRIND_BIN, valgrind, /usr/bin/valgrind) AC_DEFINE_UNQUOTED(VALGRIND_BIN, "$VALGRIND_BIN", Valgrind command) dnl Disable these until we decide if the stonith config file should be supported dnl AC_PATH_PROGS(BISON, bison) dnl AC_PATH_PROGS(FLEX, flex) dnl AC_PATH_PROGS(HAVE_YACC, $YACC) if test x"${LIBTOOL}" = x""; then AC_MSG_ERROR(You need (g)libtool installed in order to build ${PACKAGE}) fi if test x"${MAKE}" = x""; then AC_MSG_ERROR(You need (g)make installed in order to build ${PACKAGE}) fi AM_CONDITIONAL(BUILD_HELP, test x"${HELP2MAN}" != x"") if test x"${HELP2MAN}" != x""; then PCMK_FEATURES="$PCMK_FEATURES generated-manpages" fi MANPAGE_XSLT="" if test x"${XSLTPROC}" != x""; then AC_MSG_CHECKING(docbook to manpage transform) XSLT=`find ${datadir} -name docbook.xsl` for xsl in $XSLT; do dname=`dirname $xsl` bname=`basename $dname` if test "$bname" = "manpages"; then MANPAGE_XSLT="$xsl" break fi done fi AC_MSG_RESULT($MANPAGE_XSLT) AC_SUBST(MANPAGE_XSLT) AM_CONDITIONAL(BUILD_XML_HELP, test x"${MANPAGE_XSLT}" != x"") if test x"${MANPAGE_XSLT}" != x""; then PCMK_FEATURES="$PCMK_FEATURES agent-manpages" fi AM_CONDITIONAL(BUILD_ASCIIDOC, test x"${ASCIIDOC}" != x"") if test x"${ASCIIDOC}" != x""; then PCMK_FEATURES="$PCMK_FEATURES ascii-docs" fi SUPPORT_STONITH_CONFIG=0 if test x"${HAVE_YACC}" != x"" -a x"${FLEX}" != x"" -a x"${BISON}" != x""; then SUPPORT_STONITH_CONFIG=1 PCMK_FEATURES="$PCMK_FEATURES st-conf" fi AM_CONDITIONAL(BUILD_STONITH_CONFIG, test $SUPPORT_STONITH_CONFIG = 1) AC_DEFINE_UNQUOTED(SUPPORT_STONITH_CONFIG, $SUPPORT_STONITH_CONFIG, Support a stand-alone stonith config file in addition to the CIB) AM_CONDITIONAL(BUILD_DOCBOOK, test x"${PUBLICAN}" != x"" -a x"${INKSCAPE}" != x"") if test x"${PUBLICAN}" != x"" -a x"${INKSCAPE}" != x""; then AC_MSG_NOTICE(Enabling publican) PCMK_FEATURES="$PCMK_FEATURES publican-docs" fi dnl ======================================================================== dnl checks for library functions to replace them dnl dnl NoSuchFunctionName: dnl is a dummy function which no system supplies. It is here to make dnl the system compile semi-correctly on OpenBSD which doesn't know dnl how to create an empty archive dnl dnl scandir: Only on BSD. dnl System-V systems may have it, but hidden and/or deprecated. dnl A replacement function is supplied for it. dnl dnl setenv: is some bsdish function that should also be avoided (use dnl putenv instead) dnl On the other hand, putenv doesn't provide the right API for the dnl code and has memory leaks designed in (sigh...) Fortunately this dnl A replacement function is supplied for it. dnl dnl strerror: returns a string that corresponds to an errno. dnl A replacement function is supplied for it. dnl dnl strnlen: is a gnu function similar to strlen, but safer. dnl We wrote a tolearably-fast replacement function for it. dnl dnl strndup: is a gnu function similar to strdup, but safer. dnl We wrote a tolearably-fast replacement function for it. AC_REPLACE_FUNCS(alphasort NoSuchFunctionName scandir setenv strerror strchrnul unsetenv strnlen strndup) dnl =============================================== dnl Libraries dnl =============================================== AC_CHECK_LIB(socket, socket) dnl -lsocket AC_CHECK_LIB(c, dlopen) dnl if dlopen is in libc... AC_CHECK_LIB(dl, dlopen) dnl -ldl (for Linux) AC_CHECK_LIB(rt, sched_getscheduler) dnl -lrt (for Tru64) AC_CHECK_LIB(gnugetopt, getopt_long) dnl -lgnugetopt ( if available ) AC_CHECK_LIB(pam, pam_start) dnl -lpam (if available) AC_CHECK_FUNCS([sched_setscheduler]) AC_CHECK_LIB(uuid, uuid_parse) dnl load the library if necessary AC_CHECK_FUNCS(uuid_unparse) dnl OSX ships uuid_* as standard functions AC_CHECK_HEADERS(uuid/uuid.h) if test "x$ac_cv_func_uuid_unparse" != xyes; then AC_MSG_ERROR(You do not have the libuuid development package installed) fi if test x"${PKGCONFIG}" = x""; then AC_MSG_ERROR(You need pkgconfig installed in order to build ${PACKAGE}) fi if test "x${enable_thread_safe}" = "xyes"; then GPKGNAME="gthread-2.0" else GPKGNAME="glib-2.0" fi if $PKGCONFIG --exists $GPKGNAME then GLIBCONFIG="$PKGCONFIG $GPKGNAME" else set -x echo PKG_CONFIG_PATH=$PKG_CONFIG_PATH $PKGCONFIG --exists $GPKGNAME; echo $? $PKGCONFIG --cflags $GPKGNAME; echo $? $PKGCONFIG $GPKGNAME; echo $? set +x AC_MSG_ERROR(You need glib2-devel installed in order to build ${PACKAGE}) fi AC_MSG_RESULT(using $GLIBCONFIG) # # Where is dlopen? # if test "$ac_cv_lib_c_dlopen" = yes; then LIBADD_DL="" elif test "$ac_cv_lib_dl_dlopen" = yes; then LIBADD_DL=-ldl else LIBADD_DL=${lt_cv_dlopen_libs} fi dnl dnl Check for location of gettext dnl dnl On at least Solaris 2.x, where it is in libc, specifying lintl causes dnl grief. Ensure minimal result, not the sum of all possibilities. dnl And do libc first. dnl Known examples: dnl c: Linux, Solaris 2.6+ dnl intl: BSD, AIX AC_CHECK_LIB(c, gettext) if test x$ac_cv_lib_c_gettext != xyes; then AC_CHECK_LIB(intl, gettext) fi if test x$ac_cv_lib_c_gettext != xyes -a x$ac_cv_lib_intl_gettext != xyes; then AC_MSG_ERROR(You need gettext installed in order to build ${PACKAGE}) fi if test "X$GLIBCONFIG" != X; then AC_MSG_CHECKING(for special glib includes: ) GLIBHEAD=`$GLIBCONFIG --cflags` AC_MSG_RESULT($GLIBHEAD) CPPFLAGS="$CPPFLAGS $GLIBHEAD" AC_MSG_CHECKING(for glib library flags) GLIBLIB=`$GLIBCONFIG --libs` AC_MSG_RESULT($GLIBLIB) LIBS="$LIBS $GLIBLIB" fi dnl FreeBSD needs -lcompat for ftime() used by lrmd.c AC_CHECK_LIB([compat], [ftime], [COMPAT_LIBS='-lcompat']) AC_SUBST(COMPAT_LIBS) dnl ======================================================================== dnl Headers dnl ======================================================================== AC_HEADER_STDC AC_CHECK_HEADERS(arpa/inet.h) AC_CHECK_HEADERS(asm/types.h) AC_CHECK_HEADERS(assert.h) AC_CHECK_HEADERS(auth-client.h) AC_CHECK_HEADERS(ctype.h) AC_CHECK_HEADERS(dirent.h) AC_CHECK_HEADERS(errno.h) AC_CHECK_HEADERS(fcntl.h) AC_CHECK_HEADERS(getopt.h) AC_CHECK_HEADERS(glib.h) AC_CHECK_HEADERS(grp.h) AC_CHECK_HEADERS(limits.h) AC_CHECK_HEADERS(linux/errqueue.h) AC_CHECK_HEADERS(linux/swab.h) AC_CHECK_HEADERS(malloc.h) AC_CHECK_HEADERS(netdb.h) AC_CHECK_HEADERS(netinet/in.h) AC_CHECK_HEADERS(netinet/ip.h) AC_CHECK_HEADERS(pam/pam_appl.h) AC_CHECK_HEADERS(pthread.h) AC_CHECK_HEADERS(pwd.h) AC_CHECK_HEADERS(security/pam_appl.h) AC_CHECK_HEADERS(sgtty.h) AC_CHECK_HEADERS(signal.h) AC_CHECK_HEADERS(stdarg.h) AC_CHECK_HEADERS(stddef.h) AC_CHECK_HEADERS(stdio.h) AC_CHECK_HEADERS(stdlib.h) AC_CHECK_HEADERS(string.h) AC_CHECK_HEADERS(strings.h) AC_CHECK_HEADERS(sys/dir.h) AC_CHECK_HEADERS(sys/ioctl.h) AC_CHECK_HEADERS(sys/param.h) AC_CHECK_HEADERS(sys/poll.h) AC_CHECK_HEADERS(sys/reboot.h) AC_CHECK_HEADERS(sys/resource.h) AC_CHECK_HEADERS(sys/select.h) AC_CHECK_HEADERS(sys/socket.h) AC_CHECK_HEADERS(sys/signalfd.h) AC_CHECK_HEADERS(sys/sockio.h) AC_CHECK_HEADERS(sys/stat.h) AC_CHECK_HEADERS(sys/time.h) AC_CHECK_HEADERS(sys/timeb.h) AC_CHECK_HEADERS(sys/types.h) AC_CHECK_HEADERS(sys/uio.h) AC_CHECK_HEADERS(sys/un.h) AC_CHECK_HEADERS(sys/utsname.h) AC_CHECK_HEADERS(sys/wait.h) AC_CHECK_HEADERS(time.h) AC_CHECK_HEADERS(unistd.h) AC_CHECK_HEADERS(winsock.h) dnl These headers need prerequisits before the tests will pass dnl AC_CHECK_HEADERS(net/if.h) dnl AC_CHECK_HEADERS(netinet/icmp6.h) dnl AC_CHECK_HEADERS(netinet/ip6.h) dnl AC_CHECK_HEADERS(netinet/ip_icmp.h) AC_MSG_CHECKING(for special libxml2 includes) if test "x$XML2CONFIG" = "x"; then AC_MSG_ERROR(libxml2 config not found) else XML2HEAD="`$XML2CONFIG --cflags`" AC_MSG_RESULT($XML2HEAD) AC_CHECK_LIB(xml2, xmlReadMemory) AC_CHECK_LIB(xslt, xsltApplyStylesheet) fi CPPFLAGS="$CPPFLAGS $XML2HEAD" AC_CHECK_HEADERS(libxml/xpath.h) AC_CHECK_HEADERS(libxslt/xslt.h) if test "$ac_cv_header_libxml_xpath_h" != "yes"; then AC_MSG_ERROR(The libxml developement headers were not found) fi if test "$ac_cv_header_libxslt_xslt_h" != "yes"; then AC_MSG_ERROR(The libxslt developement headers were not found) fi dnl ======================================================================== dnl Structures dnl ======================================================================== AC_CHECK_MEMBERS([struct tm.tm_gmtoff],,,[[#include ]]) AC_CHECK_MEMBERS([lrm_op_t.rsc_deleted],,,[[#include ]]) AC_CHECK_MEMBER([struct dirent.d_type], AC_DEFINE(HAVE_STRUCT_DIRENT_D_TYPE,1,[Define this if struct dirent has d_type]),, [#include ]) dnl ======================================================================== dnl Functions dnl ======================================================================== AC_CHECK_FUNCS(g_log_set_default_handler) AC_CHECK_FUNCS(getopt, AC_DEFINE(HAVE_DECL_GETOPT, 1, [Have getopt function])) AC_CHECK_FUNCS(nanosleep, AC_DEFINE(HAVE_DECL_NANOSLEEP, 1, [Have nanosleep function])) dnl ======================================================================== dnl ltdl dnl ======================================================================== AC_CHECK_LIB(ltdl, lt_dlopen, [LTDL_foo=1]) if test "x${enable_bundled_ltdl}" = "xyes"; then if test $ac_cv_lib_ltdl_lt_dlopen = yes; then AC_MSG_NOTICE([Disabling usage of installed ltdl]) fi ac_cv_lib_ltdl_lt_dlopen=no fi LIBLTDL_DIR="" if test $ac_cv_lib_ltdl_lt_dlopen != yes ; then AC_MSG_NOTICE([Installing local ltdl]) LIBLTDL_DIR=libltdl ( cd $srcdir ; $TAR -xvf libltdl.tar ) if test "$?" -ne 0; then AC_MSG_ERROR([$TAR of libltdl.tar in $srcdir failed]) fi AC_CONFIG_SUBDIRS(libltdl) else LIBS="$LIBS -lltdl" AC_MSG_NOTICE([Using installed ltdl]) INCLTDL="" LIBLTDL="" fi AC_SUBST(INCLTDL) AC_SUBST(LIBLTDL) AC_SUBST(LIBLTDL_DIR) dnl ======================================================================== dnl bzip2 dnl ======================================================================== AC_CHECK_HEADERS(bzlib.h) AC_CHECK_LIB(bz2, BZ2_bzBuffToBuffCompress) if test x$ac_cv_lib_bz2_BZ2_bzBuffToBuffCompress != xyes ; then AC_MSG_ERROR(BZ2 libraries not found) fi if test x$ac_cv_header_bzlib_h != xyes; then AC_MSG_ERROR(BZ2 Development headers not found) fi dnl ======================================================================== dnl sighandler_t is missing from Illumos, Solaris11 systems dnl ======================================================================== AC_MSG_CHECKING([for sighandler_t]) AC_TRY_COMPILE([#include ],[sighandler_t *f;], has_sighandler_t=yes,has_sighandler_t=no) AC_MSG_RESULT($has_sighandler_t) if test "$has_sighandler_t" = "yes" ; then AC_DEFINE( HAVE_SIGHANDLER_T, 1, [Define if sighandler_t available] ) fi dnl ======================================================================== dnl ncurses dnl ======================================================================== dnl dnl A few OSes (e.g. Linux) deliver a default "ncurses" alongside "curses". dnl Many non-Linux deliver "curses"; sites may add "ncurses". dnl dnl However, the source-code recommendation for both is to #include "curses.h" dnl (i.e. "ncurses" still wants the include to be simple, no-'n', "curses.h"). dnl dnl ncurse takes precedence. dnl AC_CHECK_HEADERS(curses.h) AC_CHECK_HEADERS(curses/curses.h) AC_CHECK_HEADERS(ncurses.h) AC_CHECK_HEADERS(ncurses/ncurses.h) dnl Although n-library is preferred, only look for it if the n-header was found. CURSESLIBS='' if test "$ac_cv_header_ncurses_h" = "yes"; then AC_CHECK_LIB(ncurses, printw, [AC_DEFINE(HAVE_LIBNCURSES,1, have ncurses library)] ) CURSESLIBS=`$PKGCONFIG --libs ncurses` || CURSESLIBS='-lncurses' fi if test "$ac_cv_header_ncurses_ncurses_h" = "yes"; then AC_CHECK_LIB(ncurses, printw, [AC_DEFINE(HAVE_LIBNCURSES,1, have ncurses library)] ) CURSESLIBS=`$PKGCONFIG --libs ncurses` || CURSESLIBS='-lncurses' fi dnl Only look for non-n-library if there was no n-library. if test X"$CURSESLIBS" = X"" -a "$ac_cv_header_curses_h" = "yes"; then AC_CHECK_LIB(curses, printw, [CURSESLIBS='-lcurses'; AC_DEFINE(HAVE_LIBCURSES,1, have curses library)] ) fi dnl Only look for non-n-library if there was no n-library. if test X"$CURSESLIBS" = X"" -a "$ac_cv_header_curses_curses_h" = "yes"; then AC_CHECK_LIB(curses, printw, [CURSESLIBS='-lcurses'; AC_DEFINE(HAVE_LIBCURSES,1, have curses library)] ) fi if test "x$CURSESLIBS" != "x"; then PCMK_FEATURES="$PCMK_FEATURES ncurses" fi dnl Check for printw() prototype compatibility if test X"$CURSESLIBS" != X"" && cc_supports_flag -Wcast-qual && cc_supports_flag -Werror; then AC_MSG_CHECKING(whether printw() requires argument of "const char *") ac_save_LIBS=$LIBS LIBS="$CURSESLIBS $LIBS" ac_save_CFLAGS=$CFLAGS CFLAGS="-Wcast-qual -Werror" AC_LINK_IFELSE( [AC_LANG_PROGRAM( [ #if defined(HAVE_NCURSES_H) # include #elif defined(HAVE_NCURSES_NCURSES_H) # include #elif defined(HAVE_CURSES_H) # include #endif ], [printw((const char *)"Test");] )], [ac_cv_compatible_printw=yes], [ac_cv_compatible_printw=no] ) LIBS=$ac_save_LIBS CFLAGS=$ac_save_CFLAGS AC_MSG_RESULT([$ac_cv_compatible_printw]) if test "$ac_cv_compatible_printw" = no; then AC_MSG_WARN([The printw() function of your ncurses or curses library is old, we will disable usage of the library. If you want to use this library anyway, please update to newer version of the library, ncurses 5.4 or later is recommended. You can get the library from http://www.gnu.org/software/ncurses/.]) AC_MSG_NOTICE([Disabling curses]) AC_DEFINE(HAVE_INCOMPATIBLE_PRINTW, 1, [Do we have incompatible printw() in curses library?]) fi fi AC_SUBST(CURSESLIBS) dnl ======================================================================== dnl Profiling and GProf dnl ======================================================================== AC_MSG_NOTICE(Old CFLAGS: $CFLAGS) case $SUPPORT_COVERAGE in 1|yes|true) SUPPORT_PROFILING=1 PCMK_FEATURES="$PCMK_FEATURES coverage" CFLAGS="$CFLAGS -fprofile-arcs -ftest-coverage" dnl During linking, make sure to specify -lgcov or -coverage dnl Enable gprof #LIBS="$LIBS -pg" #CFLAGS="$CFLAGS -pg" ;; esac case $SUPPORT_PROFILING in 1|yes|true) SUPPORT_PROFILING=1 dnl Disable various compiler optimizations CFLAGS="$CFLAGS -fno-omit-frame-pointer -fno-inline -fno-builtin " dnl CFLAGS="$CFLAGS -fno-inline-functions -fno-default-inline -fno-inline-functions-called-once -fno-optimize-sibling-calls" dnl Turn off optimization so tools can get accurate line numbers CFLAGS=`echo $CFLAGS | sed -e 's/-O.\ //g' -e 's/-Wp,-D_FORTIFY_SOURCE=.\ //g' -e 's/-D_FORTIFY_SOURCE=.\ //g'` CFLAGS="$CFLAGS -O0 -g3 -gdwarf-2" dnl Update features PCMK_FEATURES="$PCMK_FEATURES profile" ;; *) SUPPORT_PROFILING=0;; esac AC_MSG_NOTICE(New CFLAGS: $CFLAGS) AC_DEFINE_UNQUOTED(SUPPORT_PROFILING, $SUPPORT_PROFILING, Support for profiling) dnl ======================================================================== dnl Cluster infrastructure - Heartbeat / LibQB dnl ======================================================================== dnl Compatability checks AC_CHECK_MEMBERS([struct lrm_ops.fail_rsc],,,[[#include ]]) if test x${enable_no_stack} = xyes; then SUPPORT_HEARTBEAT=no SUPPORT_CS=no fi PKG_CHECK_MODULES(libqb, libqb, HAVE_libqb=1, HAVE_libqb=0) AC_CHECK_HEADERS(qb/qbipc_common.h) AC_CHECK_LIB(qb, qb_ipcs_connection_auth_set) LIBQB_LOG=1 PCMK_FEATURES="$PCMK_FEATURES libqb-logging libqb-ipc" AC_CHECK_FUNCS(qb_ipcs_connection_get_buffer_size, AC_DEFINE(HAVE_IPCS_GET_BUFFER_SIZE, 1, [Have qb_ipcc_get_buffer_size function])) if ! pkg-config --atleast-version 0.13 libqb then AC_MSG_FAILURE(Version of libqb is too old: v0.13 or greater requried) fi LIBS="$LIBS $libqb_LIBS" AC_CHECK_HEADERS(heartbeat/hb_config.h) AC_CHECK_HEADERS(heartbeat/glue_config.h) AC_CHECK_HEADERS(stonith/stonith.h) AC_CHECK_HEADERS(agent_config.h) GLUE_HEADER=none HAVE_GLUE=0 if test "$ac_cv_header_heartbeat_glue_config_h" = "yes"; then GLUE_HEADER=glue_config.h HAVE_GLUE=1 elif test "$ac_cv_header_heartbeat_hb_config_h" = "yes"; then GLUE_HEADER=hb_config.h HAVE_GLUE=1 else AC_MSG_WARN(cluster-glue development headers were not found) fi if test "$ac_cv_header_stonith_stonith_h" = "yes"; then PCMK_FEATURES="$PCMK_FEATURES lha-fencing" fi if test $HAVE_GLUE = 1; then dnl On Debian, AC_CHECK_LIBS fail if a library has any unresolved symbols dnl So check for all the depenancies (so they're added to LIBS) before checking for -lplumb AC_CHECK_LIB(pils, PILLoadPlugin) AC_CHECK_LIB(plumb, G_main_add_IPC_Channel) fi dnl =============================================== dnl Variables needed for substitution dnl =============================================== CRM_DTD_DIRECTORY="${datadir}/pacemaker" AC_DEFINE_UNQUOTED(CRM_DTD_DIRECTORY,"$CRM_DTD_DIRECTORY", Location for the Pacemaker Relax-NG Schema) AC_SUBST(CRM_DTD_DIRECTORY) CRM_CORE_DIR=`try_extract_header_define $GLUE_HEADER HA_COREDIR ${localstatedir}/lib/pacemaker/cores` AC_DEFINE_UNQUOTED(CRM_CORE_DIR,"$CRM_CORE_DIR", Location to store core files produced by Pacemaker daemons) AC_SUBST(CRM_CORE_DIR) CRM_DAEMON_USER=`try_extract_header_define $GLUE_HEADER HA_CCMUSER hacluster` AC_DEFINE_UNQUOTED(CRM_DAEMON_USER,"$CRM_DAEMON_USER", User to run Pacemaker daemons as) AC_SUBST(CRM_DAEMON_USER) CRM_DAEMON_GROUP=`try_extract_header_define $GLUE_HEADER HA_APIGROUP haclient` AC_DEFINE_UNQUOTED(CRM_DAEMON_GROUP,"$CRM_DAEMON_GROUP", Group to run Pacemaker daemons as) AC_SUBST(CRM_DAEMON_GROUP) CRM_STATE_DIR=${localstatedir}/run/crm AC_DEFINE_UNQUOTED(CRM_STATE_DIR,"$CRM_STATE_DIR", Where to keep state files and sockets) AC_SUBST(CRM_STATE_DIR) CRM_BLACKBOX_DIR=${localstatedir}/lib/pacemaker/blackbox AC_DEFINE_UNQUOTED(CRM_BLACKBOX_DIR,"$CRM_BLACKBOX_DIR", Where to keep blackbox dumps) AC_SUBST(CRM_BLACKBOX_DIR) PE_STATE_DIR="${localstatedir}/lib/pacemaker/pengine" AC_DEFINE_UNQUOTED(PE_STATE_DIR,"$PE_STATE_DIR", Where to keep PEngine outputs) AC_SUBST(PE_STATE_DIR) CRM_CONFIG_DIR="${localstatedir}/lib/pacemaker/cib" AC_DEFINE_UNQUOTED(CRM_CONFIG_DIR,"$CRM_CONFIG_DIR", Where to keep configuration files) AC_SUBST(CRM_CONFIG_DIR) CRM_CONFIG_CTS="${localstatedir}/lib/pacemaker/cts" AC_DEFINE_UNQUOTED(CRM_CONFIG_CTS,"$CRM_CONFIG_CTS", Where to keep cts stateful data) AC_SUBST(CRM_CONFIG_CTS) CRM_LEGACY_CONFIG_DIR="${localstatedir}/lib/heartbeat/crm" AC_DEFINE_UNQUOTED(CRM_LEGACY_CONFIG_DIR,"$CRM_LEGACY_CONFIG_DIR", Where Pacemaker used to keep configuration files) AC_SUBST(CRM_LEGACY_CONFIG_DIR) CRM_DAEMON_DIR="${libexecdir}/pacemaker" AC_DEFINE_UNQUOTED(CRM_DAEMON_DIR,"$CRM_DAEMON_DIR", Location for Pacemaker daemons) AC_SUBST(CRM_DAEMON_DIR) HB_DAEMON_DIR=`try_extract_header_define $GLUE_HEADER HA_LIBHBDIR $libdir/heartbeat` AC_DEFINE_UNQUOTED(HB_DAEMON_DIR,"$HB_DAEMON_DIR", Location Heartbeat expects Pacemaker daemons to be in) AC_SUBST(HB_DAEMON_DIR) dnl Needed so that the Corosync plugin can clear out the directory as Heartbeat does HA_STATE_DIR=`try_extract_header_define $GLUE_HEADER HA_VARRUNDIR ${localstatedir}/run` AC_DEFINE_UNQUOTED(HA_STATE_DIR,"$HA_STATE_DIR", Where Heartbeat keeps state files and sockets) AC_SUBST(HA_STATE_DIR) CRM_RSCTMP_DIR=`try_extract_header_define agent_config.h HA_RSCTMPDIR $HA_STATE_DIR/resource-agents` AC_MSG_CHECKING(Scratch dir for resource agents) AC_MSG_RESULT($CRM_RSCTMP_DIR) AC_DEFINE_UNQUOTED(CRM_RSCTMP_DIR,"$CRM_RSCTMP_DIR", Where resource agents should keep state files) AC_SUBST(CRM_RSCTMP_DIR) dnl Needed for the location of hostcache in CTS.py HA_VARLIBHBDIR=`try_extract_header_define $GLUE_HEADER HA_VARLIBHBDIR ${localstatedir}/lib/heartbeat` AC_SUBST(HA_VARLIBHBDIR) AC_DEFINE_UNQUOTED(UUID_FILE,"$localstatedir/lib/heartbeat/hb_uuid", Location of Heartbeat's UUID file) OCF_ROOT_DIR=`try_extract_header_define $GLUE_HEADER OCF_ROOT_DIR /usr/lib/ocf` if test "X$OCF_ROOT_DIR" = X; then AC_MSG_ERROR(Could not locate OCF directory) fi AC_SUBST(OCF_ROOT_DIR) OCF_RA_DIR=`try_extract_header_define $GLUE_HEADER OCF_RA_DIR $OCF_ROOT_DIR/resource.d` AC_DEFINE_UNQUOTED(OCF_RA_DIR,"$OCF_RA_DIR", Location for OCF RAs) AC_SUBST(OCF_RA_DIR) RH_STONITH_DIR="$sbindir" AC_DEFINE_UNQUOTED(RH_STONITH_DIR,"$RH_STONITH_DIR", Location for Red Hat Stonith agents) RH_STONITH_PREFIX="fence_" AC_DEFINE_UNQUOTED(RH_STONITH_PREFIX,"$RH_STONITH_PREFIX", Prefix for Red Hat Stonith agents) AC_PATH_PROGS(GIT, git false) AC_MSG_CHECKING(build version) BUILD_VERSION=$Format:%h$ if test $BUILD_VERSION != ":%h$"; then AC_MSG_RESULT(archive hash: $BUILD_VERSION) elif test -x $GIT -a -d .git; then BUILD_VERSION=`$GIT log --pretty="format:%h" -n 1` AC_MSG_RESULT(git hash: $BUILD_VERSION) else # The current directory name make a reasonable default # Most generated archives will include the hash or tag BASE=`basename $PWD` BUILD_VERSION=`echo $BASE | sed s:.*[[Pp]]acemaker-::` AC_MSG_RESULT(directory based hash: $BUILD_VERSION) fi AC_DEFINE_UNQUOTED(BUILD_VERSION, "$BUILD_VERSION", Build version) AC_SUBST(BUILD_VERSION) HAVE_dbus=1 HAVE_upstart=0 HAVE_systemd=0 PKG_CHECK_MODULES(DBUS, dbus-1, ,HAVE_dbus=0) AC_DEFINE_UNQUOTED(SUPPORT_DBUS, $HAVE_dbus, Support dbus) AM_CONDITIONAL(BUILD_DBUS, test $HAVE_dbus = 1) if test $HAVE_dbus = 1; then CFLAGS="$CFLAGS `$PKGCONFIG --cflags dbus-1`" fi 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=1 PCMK_FEATURES="$PCMK_FEATURES upstart" fi AC_DEFINE_UNQUOTED(SUPPORT_UPSTART, $HAVE_upstart, Support upstart based system services) AM_CONDITIONAL(BUILD_UPSTART, test $HAVE_upstart = 1) if $PKGCONFIG --exists systemd then systemdunitdir=`$PKGCONFIG --variable=systemdsystemunitdir systemd` AC_SUBST(systemdunitdir) else enable_systemd=no fi 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" fi fi AC_DEFINE_UNQUOTED(SUPPORT_SYSTEMD, $HAVE_systemd, Support systemd based system services) AM_CONDITIONAL(BUILD_SYSTEMD, test $HAVE_systemd = 1) case $SUPPORT_NAGIOS in 1|yes|true|try) SUPPORT_NAGIOS=1;; *) SUPPORT_NAGIOS=0;; esac if test $SUPPORT_NAGIOS = 1; then PCMK_FEATURES="$PCMK_FEATURES nagios" fi AC_DEFINE_UNQUOTED(SUPPORT_NAGIOS, $SUPPORT_NAGIOS, Support nagios plugins) AM_CONDITIONAL(BUILD_NAGIOS, test $SUPPORT_NAGIOS = 1) if test x"$NAGIOS_PLUGIN_DIR" = x""; then NAGIOS_PLUGIN_DIR="${libexecdir}/nagios/plugins" fi AC_DEFINE_UNQUOTED(NAGIOS_PLUGIN_DIR, "$NAGIOS_PLUGIN_DIR", Directory for nagios plugins) AC_SUBST(NAGIOS_PLUGIN_DIR) if test x"$NAGIOS_METADATA_DIR" = x""; then NAGIOS_METADATA_DIR="${datadir}/nagios/plugins-metadata" fi AC_DEFINE_UNQUOTED(NAGIOS_METADATA_DIR, "$NAGIOS_METADATA_DIR", Directory for nagios plugins metadata) AC_SUBST(NAGIOS_METADATA_DIR) STACKS="" CLUSTERLIBS="" dnl ======================================================================== dnl Cluster stack - Heartbeat dnl ======================================================================== case $SUPPORT_HEARTBEAT in 1|yes|true|try) AC_MSG_CHECKING(for heartbeat support) AC_CHECK_LIB(hbclient, ll_cluster_new, [SUPPORT_HEARTBEAT=1], [if test $SUPPORT_HEARTBEAT != try; then AC_MSG_FAILURE(Unable to support Heartbeat: client libraries not found) fi]) if test $SUPPORT_HEARTBEAT = 1 ; then STACKS="$STACKS heartbeat" dnl objdump -x ${libdir}/libccmclient.so | grep SONAME | awk '{print $2}' AC_DEFINE_UNQUOTED(CCM_LIBRARY, "libccmclient.so.1", Library to load for ccm support) AC_DEFINE_UNQUOTED(HEARTBEAT_LIBRARY, "libhbclient.so.1", Library to load for heartbeat support) BUILD_ATOMIC_ATTRD=0 else SUPPORT_HEARTBEAT=0 fi ;; *) SUPPORT_HEARTBEAT=0;; esac AM_CONDITIONAL(BUILD_HEARTBEAT_SUPPORT, test $SUPPORT_HEARTBEAT = 1) AC_DEFINE_UNQUOTED(SUPPORT_HEARTBEAT, $SUPPORT_HEARTBEAT, Support the Heartbeat messaging and membership layer) AC_SUBST(SUPPORT_HEARTBEAT) dnl ======================================================================== dnl Cluster stack - Corosync dnl ======================================================================== dnl Normalize the values case $SUPPORT_CS in 1|yes|true) SUPPORT_CS=yes missingisfatal=1;; try) missingisfatal=0;; *) SUPPORT_CS=no;; esac AC_MSG_CHECKING(for native corosync) COROSYNC_LIBS="" CS_USES_LIBQB=0 PCMK_SERVICE_ID=9 LCRSODIR="$libdir" if test $SUPPORT_CS = no; then AC_MSG_RESULT(no (disabled)) SUPPORT_CS=0 else AC_MSG_RESULT($SUPPORT_CS, with '$CSPREFIX') PKG_CHECK_MODULES(cpg, libcpg) dnl Fatal PKG_CHECK_MODULES(cfg, libcfg) dnl Fatal PKG_CHECK_MODULES(cmap, libcmap, HAVE_cmap=1, HAVE_cmap=0) PKG_CHECK_MODULES(cman, libcman, HAVE_cman=1, HAVE_cman=0) PKG_CHECK_MODULES(confdb, libconfdb, HAVE_confdb=1, HAVE_confdb=0) PKG_CHECK_MODULES(fenced, libfenced, HAVE_fenced=1, HAVE_fenced=0) PKG_CHECK_MODULES(quorum, libquorum, HAVE_quorum=1, HAVE_quorum=0) PKG_CHECK_MODULES(oldipc, libcoroipcc, HAVE_oldipc=1, HAVE_oldipc=0) if test $HAVE_oldipc = 1; then SUPPORT_CS=1 CFLAGS="$CFLAGS $oldipc_FLAGS $cpg_FLAGS $cfg_FLAGS" COROSYNC_LIBS="$COROSYNC_LIBS $oldipc_LIBS $cpg_LIBS $cfg_LIBS" elif test $HAVE_libqb = 1; then SUPPORT_CS=1 CS_USES_LIBQB=1 CFLAGS="$CFLAGS $libqb_FLAGS $cpg_FLAGS $cfg_FLAGS" COROSYNC_LIBS="$COROSYNC_LIBS $libqb_LIBS $cpg_LIBS $cfg_LIBS" AC_CHECK_LIB(corosync_common, cs_strerror) else aisreason="corosync/libqb IPC libraries not found by pkg_config" fi AC_DEFINE_UNQUOTED(HAVE_CONFDB, $HAVE_confdb, Have the old herarchial Corosync config API) AC_DEFINE_UNQUOTED(HAVE_CMAP, $HAVE_cmap, Have the new non-herarchial Corosync config API) fi if test $SUPPORT_CS = 1 -a x$HAVE_oldipc = x0 ; then dnl Support for plugins was removed about the time the IPC was dnl moved to libqb. dnl The only option now is the built-in quorum API CFLAGS="$CFLAGS $cmap_CFLAGS $quorum_CFLAGS" COROSYNC_LIBS="$COROSYNC_LIBS $cmap_LIBS $quorum_LIBS" STACKS="$STACKS corosync-native" AC_DEFINE_UNQUOTED(SUPPORT_CS_QUORUM, 1, Support the consumption of membership and quorum from corosync) fi SUPPORT_PLUGIN=0 if test $SUPPORT_CS = 1 -a x$HAVE_confdb = x1; then dnl Need confdb to support cman and the plugins SUPPORT_PLUGIN=1 BUILD_ATOMIC_ATTRD=0 LCRSODIR=`$PKGCONFIG corosync --variable=lcrsodir` STACKS="$STACKS corosync-plugin" COROSYNC_LIBS="$COROSYNC_LIBS $confdb_LIBS" if test $SUPPORT_CMAN != no; then if test $HAVE_cman = 1 -a $HAVE_fenced = 1; then SUPPORT_CMAN=1 STACKS="$STACKS cman" CFLAGS="$CFLAGS $cman_FLAGS $fenced_FLAGS" COROSYNC_LIBS="$COROSYNC_LIBS $cman_LIBS $fenced_LIBS" fi fi fi dnl Normalize SUPPORT_CS and SUPPORT_CMAN for use with #if directives if test $SUPPORT_CMAN != 1; then SUPPORT_CMAN=0 fi if test $SUPPORT_CS = 1; then CLUSTERLIBS="$CLUSTERLIBS $COROSYNC_LIBS" elif test $SUPPORT_CS != 0; then SUPPORT_CS=0 if test $missingisfatal = 0; then AC_MSG_WARN(Unable to support Corosync: $aisreason) else AC_MSG_FAILURE(Unable to support Corosync: $aisreason) fi fi AC_DEFINE_UNQUOTED(SUPPORT_COROSYNC, $SUPPORT_CS, Support the Corosync messaging and membership layer) AC_DEFINE_UNQUOTED(SUPPORT_CMAN, $SUPPORT_CMAN, Support the consumption of membership and quorum from cman) AC_DEFINE_UNQUOTED(CS_USES_LIBQB, $CS_USES_LIBQB, Does corosync use libqb for its ipc) AC_DEFINE_UNQUOTED(PCMK_SERVICE_ID, $PCMK_SERVICE_ID, Corosync service number) AC_DEFINE_UNQUOTED(SUPPORT_PLUGIN, $SUPPORT_PLUGIN, Support the Pacemaker plugin for Corosync) AM_CONDITIONAL(BUILD_CS_SUPPORT, test $SUPPORT_CS = 1) AM_CONDITIONAL(BUILD_CS_PLUGIN, test $SUPPORT_PLUGIN = 1) AM_CONDITIONAL(BUILD_CMAN, test $SUPPORT_CMAN = 1) AM_CONDITIONAL(BUILD_ATOMIC_ATTRD, test $BUILD_ATOMIC_ATTRD = 1) AC_DEFINE_UNQUOTED(HAVE_ATOMIC_ATTRD, $BUILD_ATOMIC_ATTRD, Support the new atomic attrd) AC_SUBST(SUPPORT_CMAN) AC_SUBST(SUPPORT_CS) dnl dnl Cluster stack - Sanity dnl if test x${enable_no_stack} = xyes; then AC_MSG_NOTICE(No cluster stack supported. Just building the Policy Engine) PCMK_FEATURES="$PCMK_FEATURES no-cluster-stack" else AC_MSG_CHECKING(for supported stacks) if test x"$STACKS" = x; then AC_MSG_FAILURE(You must support at least one cluster stack (heartbeat or corosync) ) fi AC_MSG_RESULT($STACKS) PCMK_FEATURES="$PCMK_FEATURES $STACKS" fi if test ${BUILD_ATOMIC_ATTRD} = 1; then PCMK_FEATURES="$PCMK_FEATURES atomic-attrd" fi AC_SUBST(CLUSTERLIBS) AC_SUBST(LCRSODIR) dnl ======================================================================== dnl SNMP dnl ======================================================================== case $SUPPORT_SNMP in 1|yes|true) missingisfatal=1;; try) missingisfatal=0;; *) SUPPORT_SNMP=no;; esac SNMPLIBS="" AC_MSG_CHECKING(for snmp support) if test $SUPPORT_SNMP = no; then AC_MSG_RESULT(no (disabled)) SUPPORT_SNMP=0 else SNMPCONFIG="" AC_MSG_RESULT($SUPPORT_SNMP) AC_CHECK_HEADERS(net-snmp/net-snmp-config.h) if test "x${ac_cv_header_net_snmp_net_snmp_config_h}" != "xyes"; then SUPPORT_SNMP="no" fi if test $SUPPORT_SNMP != no; then AC_PATH_PROGS(SNMPCONFIG, net-snmp-config) if test "X${SNMPCONFIG}" = "X"; then AC_MSG_RESULT(You need the net_snmp development package to continue.) SUPPORT_SNMP=no fi fi if test $SUPPORT_SNMP != no; then AC_MSG_CHECKING(for special snmp libraries) SNMPLIBS=`$SNMPCONFIG --agent-libs` AC_MSG_RESULT($SNMPLIBS) fi if test $SUPPORT_SNMP != no; then savedLibs=$LIBS LIBS="$LIBS $SNMPLIBS" dnl On many systems libcrypto is needed when linking against libsnmp. dnl Check to see if it exists, and if so use it. dnl AC_CHECK_LIB(crypto, CRYPTO_free, CRYPTOLIB="-lcrypto",) dnl AC_SUBST(CRYPTOLIB) AC_CHECK_FUNCS(netsnmp_transport_open_client) if test $ac_cv_func_netsnmp_transport_open_client != yes; then AC_CHECK_FUNCS(netsnmp_tdomain_transport) if test $ac_cv_func_netsnmp_tdomain_transport != yes; then SUPPORT_SNMP=no else AC_DEFINE_UNQUOTED(NETSNMPV53, 1, [Use the older 5.3 version of the net-snmp API]) fi fi LIBS=$savedLibs fi if test $SUPPORT_SNMP = no; then SNMPLIBS="" SUPPORT_SNMP=0 if test $missingisfatal = 0; then AC_MSG_WARN(Unable to support SNMP) else AC_MSG_FAILURE(Unable to support SNMP) fi else SUPPORT_SNMP=1 fi fi if test $SUPPORT_SNMP = 1; then PCMK_FEATURES="$PCMK_FEATURES snmp" fi AC_SUBST(SNMPLIBS) AM_CONDITIONAL(ENABLE_SNMP, test "$SUPPORT_SNMP" = "1") AC_DEFINE_UNQUOTED(ENABLE_SNMP, $SUPPORT_SNMP, Build in support for sending SNMP traps) dnl ======================================================================== dnl ESMTP dnl ======================================================================== case $SUPPORT_ESMTP in 1|yes|true) missingisfatal=1;; try) missingisfatal=0;; *) SUPPORT_ESMTP=no;; esac ESMTPLIB="" AC_MSG_CHECKING(for esmtp support) if test $SUPPORT_ESMTP = no; then AC_MSG_RESULT(no (disabled)) SUPPORT_ESMTP=0 else ESMTPCONFIG="" AC_MSG_RESULT($SUPPORT_ESMTP) AC_CHECK_HEADERS(libesmtp.h) if test "x${ac_cv_header_libesmtp_h}" != "xyes"; then ENABLE_ESMTP="no" fi if test $SUPPORT_ESMTP != no; then AC_PATH_PROGS(ESMTPCONFIG, libesmtp-config) if test "X${ESMTPCONFIG}" = "X"; then AC_MSG_RESULT(You need the libesmtp development package to continue.) SUPPORT_ESMTP=no fi fi if test $SUPPORT_ESMTP != no; then AC_MSG_CHECKING(for special esmtp libraries) ESMTPLIBS=`$ESMTPCONFIG --libs | tr '\n' ' '` AC_MSG_RESULT($ESMTPLIBS) fi if test $SUPPORT_ESMTP = no; then SUPPORT_ESMTP=0 if test $missingisfatal = 0; then AC_MSG_WARN(Unable to support ESMTP) else AC_MSG_FAILURE(Unable to support ESMTP) fi else SUPPORT_ESMTP=1 PCMK_FEATURES="$PCMK_FEATURES libesmtp" fi fi AC_SUBST(ESMTPLIBS) AM_CONDITIONAL(ENABLE_ESMTP, test "$SUPPORT_ESMTP" = "1") AC_DEFINE_UNQUOTED(ENABLE_ESMTP, $SUPPORT_ESMTP, Build in support for sending mail notifications with ESMTP) dnl ======================================================================== dnl ACL dnl ======================================================================== case $SUPPORT_ACL in 1|yes|true) missingisfatal=1;; try) missingisfatal=0;; *) SUPPORT_ACL=no;; esac AC_MSG_CHECKING(for acl support) if test $SUPPORT_ACL = no; then AC_MSG_RESULT(no (disabled)) SUPPORT_ACL=0 else AC_MSG_RESULT($SUPPORT_ACL) SUPPORT_ACL=1 AC_CHECK_LIB(qb, qb_ipcs_connection_auth_set) if test $ac_cv_lib_qb_qb_ipcs_connection_auth_set != yes; then SUPPORT_ACL=0 fi if test $SUPPORT_ACL = 0; then if test $missingisfatal = 0; then AC_MSG_WARN(Unable to support ACL. You need to use libqb > 0.13.0) else AC_MSG_FAILURE(Unable to support ACL. You need to use libqb > 0.13.0) fi fi fi if test $SUPPORT_ACL = 1; then PCMK_FEATURES="$PCMK_FEATURES acls" fi AM_CONDITIONAL(ENABLE_ACL, test "$SUPPORT_ACL" = "1") AC_DEFINE_UNQUOTED(ENABLE_ACL, $SUPPORT_ACL, Build in support for CIB ACL) dnl ======================================================================== dnl CIB secrets dnl ======================================================================== case $SUPPORT_CIBSECRETS in 1|yes|true|try) SUPPORT_CIBSECRETS=1;; *) SUPPORT_CIBSECRETS=0;; esac AC_DEFINE_UNQUOTED(SUPPORT_CIBSECRETS, $SUPPORT_CIBSECRETS, Support CIB secrets) AM_CONDITIONAL(BUILD_CIBSECRETS, test $SUPPORT_CIBSECRETS = 1) if test $SUPPORT_CIBSECRETS = 1; then PCMK_FEATURES="$PCMK_FEATURES cibsecrets" LRM_CIBSECRETS_DIR="${localstatedir}/lib/pacemaker/lrm/secrets" AC_DEFINE_UNQUOTED(LRM_CIBSECRETS_DIR,"$LRM_CIBSECRETS_DIR", Location for CIB secrets) AC_SUBST(LRM_CIBSECRETS_DIR) LRM_LEGACY_CIBSECRETS_DIR="${localstatedir}/lib/heartbeat/lrm/secrets" AC_DEFINE_UNQUOTED(LRM_LEGACY_CIBSECRETS_DIR,"$LRM_LEGACY_CIBSECRETS_DIR", Legacy location for CIB secrets) AC_SUBST(LRM_LEGACY_CIBSECRETS_DIR) fi dnl ======================================================================== dnl GnuTLS dnl ======================================================================== AC_CHECK_HEADERS(gnutls/gnutls.h) AC_CHECK_HEADERS(security/pam_appl.h pam/pam_appl.h) dnl GNUTLS library: Attempt to determine by 'libgnutls-config' program. dnl If no 'libgnutls-config', try traditional autoconf means. AC_PATH_PROGS(LIBGNUTLS_CONFIG, libgnutls-config) if test -n "$LIBGNUTLS_CONFIG"; then AC_MSG_CHECKING(for gnutls header flags) GNUTLSHEAD="`$LIBGNUTLS_CONFIG --cflags`"; AC_MSG_RESULT($GNUTLSHEAD) AC_MSG_CHECKING(for gnutls library flags) GNUTLSLIBS="`$LIBGNUTLS_CONFIG --libs`"; AC_MSG_RESULT($GNUTLSLIBS) fi AC_CHECK_LIB(gnutls, gnutls_init) AC_CHECK_FUNCS(gnutls_priority_set_direct) AC_SUBST(GNUTLSHEAD) AC_SUBST(GNUTLSLIBS) dnl ======================================================================== dnl System Health dnl ======================================================================== dnl Check if servicelog development package is installed SERVICELOG=servicelog-1 SERVICELOG_EXISTS="no" AC_MSG_CHECKING(for $SERVICELOG packages) if $PKGCONFIG --exists $SERVICELOG then PKG_CHECK_MODULES([SERVICELOG], [servicelog-1]) SERVICELOG_EXISTS="yes" fi AC_MSG_RESULT($SERVICELOG_EXISTS) AM_CONDITIONAL(BUILD_SERVICELOG, test "$SERVICELOG_EXISTS" = "yes") dnl Check if OpenIMPI packages and servicelog are installed OPENIPMI="OpenIPMI OpenIPMIposix" OPENIPMI_SERVICELOG_EXISTS="no" AC_MSG_CHECKING(for $SERVICELOG $OPENIPMI packages) if $PKGCONFIG --exists $OPENIPMI $SERVICELOG then PKG_CHECK_MODULES([OPENIPMI_SERVICELOG],[OpenIPMI OpenIPMIposix]) OPENIPMI_SERVICELOG_EXISTS="yes" fi AC_MSG_RESULT($OPENIPMI_SERVICELOG_EXISTS) AM_CONDITIONAL(BUILD_OPENIPMI_SERVICELOG, test "$OPENIPMI_SERVICELOG_EXISTS" = "yes") dnl ======================================================================== dnl Compiler flags dnl ======================================================================== dnl Make sure that CFLAGS is not exported. If the user did dnl not have CFLAGS in their environment then this should have dnl no effect. However if CFLAGS was exported from the user's dnl environment, then the new CFLAGS will also be exported dnl to sub processes. CC_ERRORS="" CC_EXTRAS="" if export | fgrep " CFLAGS=" > /dev/null; then SAVED_CFLAGS="$CFLAGS" unset CFLAGS CFLAGS="$SAVED_CFLAGS" unset SAVED_CFLAGS fi if test "$GCC" != yes; then CFLAGS="$CFLAGS -g" enable_fatal_warnings=no else CFLAGS="$CFLAGS -ggdb" # We had to eliminate -Wnested-externs because of libtool changes EXTRA_FLAGS="-fgnu89-inline -Wall -Waggregate-return -Wbad-function-cast -Wcast-align -Wdeclaration-after-statement -Wendif-labels -Wfloat-equal -Wformat=2 -Wformat-security -Wformat-nonliteral -Wmissing-prototypes -Wmissing-declarations -Wnested-externs -Wno-long-long -Wno-strict-aliasing -Wpointer-arith -Wstrict-prototypes -Wwrite-strings -Wunused-but-set-variable -Wunsigned-char" # Additional warnings it might be nice to enable one day # -Wshadow # -Wunreachable-code case "$host_os" in *solaris*) ;; *) EXTRA_FLAGS="$EXTRA_FLAGS -fstack-protector-all" ;; esac for j in $EXTRA_FLAGS do if cc_supports_flag $j then CC_EXTRAS="$CC_EXTRAS $j" fi done dnl In lib/ais/Makefile.am there's a gcc option available as of v4.x GCC_MAJOR=`gcc -v 2>&1 | awk 'END{print $3}' | sed 's/[.].*//'` AM_CONDITIONAL(GCC_4, test "${GCC_MAJOR}" = 4) dnl System specific options case "$host_os" in *linux*|*bsd*) if test "${enable_fatal_warnings}" = "unknown"; then enable_fatal_warnings=yes fi ;; esac if test "x${enable_fatal_warnings}" != xno && cc_supports_flag -Werror ; then enable_fatal_warnings=yes else enable_fatal_warnings=no fi if test "x${enable_ansi}" = xyes && cc_supports_flag -std=iso9899:199409 ; then AC_MSG_NOTICE(Enabling ANSI Compatibility) CC_EXTRAS="$CC_EXTRAS -ansi -D_GNU_SOURCE -DANSI_ONLY" fi AC_MSG_NOTICE(Activated additional gcc flags: ${CC_EXTRAS}) fi CFLAGS="$CFLAGS $CC_EXTRAS" NON_FATAL_CFLAGS="$CFLAGS" AC_SUBST(NON_FATAL_CFLAGS) dnl dnl We reset CFLAGS to include our warnings *after* all function dnl checking goes on, so that our warning flags don't keep the dnl AC_*FUNCS() calls above from working. In particular, -Werror will dnl *always* cause us troubles if we set it before here. dnl dnl if test "x${enable_fatal_warnings}" = xyes ; then AC_MSG_NOTICE(Enabling Fatal Warnings) CFLAGS="$CFLAGS -Werror" fi AC_SUBST(CFLAGS) dnl This is useful for use in Makefiles that need to remove one specific flag CFLAGS_COPY="$CFLAGS" AC_SUBST(CFLAGS_COPY) AC_SUBST(LIBADD_DL) dnl extra flags for dynamic linking libraries AC_SUBST(LIBADD_INTL) dnl extra flags for GNU gettext stuff... AC_SUBST(LOCALE) dnl Options for cleaning up the compiler output QUIET_LIBTOOL_OPTS="" QUIET_MAKE_OPTS="" if test "x${enable_quiet}" = "xyes"; then QUIET_LIBTOOL_OPTS="--quiet" QUIET_MAKE_OPTS="--quiet" fi AC_MSG_RESULT(Supress make details: ${enable_quiet}) dnl Put the above variables to use LIBTOOL="${LIBTOOL} --tag=CC \$(QUIET_LIBTOOL_OPTS)" MAKE="${MAKE} \$(QUIET_MAKE_OPTS)" AC_SUBST(CC) AC_SUBST(MAKE) AC_SUBST(LIBTOOL) AC_SUBST(QUIET_MAKE_OPTS) AC_SUBST(QUIET_LIBTOOL_OPTS) AC_DEFINE_UNQUOTED(CRM_FEATURES, "$PCMK_FEATURES", Set of enabled features) AC_SUBST(PCMK_FEATURES) dnl The Makefiles and shell scripts we output AC_CONFIG_FILES(Makefile \ Doxyfile \ coverage.sh \ cts/Makefile \ cts/CTSvars.py \ cts/LSBDummy \ + cts/HBDummy \ cts/benchmark/Makefile \ cts/benchmark/clubench \ cts/lxc_autogen.sh \ cib/Makefile \ attrd/Makefile \ crmd/Makefile \ pengine/Makefile \ pengine/regression.core.sh \ doc/Makefile \ doc/Pacemaker_Explained/publican.cfg \ doc/Clusters_from_Scratch/publican.cfg \ doc/Pacemaker_Remote/publican.cfg \ include/Makefile \ include/crm/Makefile \ include/crm/cib/Makefile \ include/crm/common/Makefile \ include/crm/cluster/Makefile \ include/crm/fencing/Makefile \ include/crm/pengine/Makefile \ replace/Makefile \ lib/Makefile \ lib/pacemaker.pc \ lib/pacemaker-cib.pc \ lib/pacemaker-lrmd.pc \ lib/pacemaker-service.pc \ lib/pacemaker-pengine.pc \ lib/pacemaker-fencing.pc \ lib/pacemaker-cluster.pc \ lib/ais/Makefile \ lib/common/Makefile \ lib/cluster/Makefile \ lib/cib/Makefile \ lib/pengine/Makefile \ lib/transition/Makefile \ lib/fencing/Makefile \ lib/lrmd/Makefile \ lib/services/Makefile \ mcp/Makefile \ mcp/pacemaker \ mcp/pacemaker.service \ mcp/pacemaker.upstart \ mcp/pacemaker.combined.upstart \ fencing/Makefile \ fencing/regression.py \ lrmd/Makefile \ lrmd/regression.py \ lrmd/pacemaker_remote.service \ lrmd/pacemaker_remote \ extra/Makefile \ extra/resources/Makefile \ extra/rgmanager/Makefile \ extra/logrotate/Makefile \ extra/logrotate/pacemaker \ tools/Makefile \ tools/crm_report \ tools/report.common \ tools/cibsecret \ tools/crm_mon.upstart \ xml/Makefile \ lib/gnu/Makefile \ ) dnl Now process the entire list of files added by previous dnl calls to AC_CONFIG_FILES() AC_OUTPUT() dnl ***************** dnl Configure summary dnl ***************** AC_MSG_RESULT([]) AC_MSG_RESULT([$PACKAGE configuration:]) AC_MSG_RESULT([ Version = ${VERSION} (Build: $BUILD_VERSION)]) AC_MSG_RESULT([ Features =${PCMK_FEATURES}]) AC_MSG_RESULT([]) AC_MSG_RESULT([ Prefix = ${prefix}]) AC_MSG_RESULT([ Executables = ${sbindir}]) AC_MSG_RESULT([ Man pages = ${mandir}]) AC_MSG_RESULT([ Libraries = ${libdir}]) AC_MSG_RESULT([ Header files = ${includedir}]) AC_MSG_RESULT([ Arch-independent files = ${datadir}]) AC_MSG_RESULT([ State information = ${localstatedir}]) AC_MSG_RESULT([ System configuration = ${sysconfdir}]) AC_MSG_RESULT([ Corosync Plugins = ${LCRSODIR}]) AC_MSG_RESULT([]) AC_MSG_RESULT([ Use system LTDL = ${ac_cv_lib_ltdl_lt_dlopen}]) AC_MSG_RESULT([]) AC_MSG_RESULT([ HA group name = ${CRM_DAEMON_GROUP}]) AC_MSG_RESULT([ HA user name = ${CRM_DAEMON_USER}]) AC_MSG_RESULT([]) AC_MSG_RESULT([ CFLAGS = ${CFLAGS}]) AC_MSG_RESULT([ Libraries = ${LIBS}]) AC_MSG_RESULT([ Stack Libraries = ${CLUSTERLIBS}]) diff --git a/crmd/control.c b/crmd/control.c index 8cc1cfaa63..68255adc38 100644 --- a/crmd/control.c +++ b/crmd/control.c @@ -1,1086 +1,1104 @@ /* * Copyright (C) 2004 Andrew Beekhof * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include qb_ipcs_service_t *ipcs = NULL; extern gboolean crm_connect_corosync(crm_cluster_t * cluster); extern void crmd_ha_connection_destroy(gpointer user_data); void crm_shutdown(int nsig); gboolean crm_read_options(gpointer user_data); gboolean fsa_has_quorum = FALSE; crm_trigger_t *fsa_source = NULL; crm_trigger_t *config_read = NULL; bool no_quorum_suicide_escalation = FALSE; static gboolean election_timeout_popped(gpointer data) { /* Not everyone voted */ crm_info("Election failed: Declaring ourselves the winner"); register_fsa_input(C_TIMER_POPPED, I_ELECTION_DC, NULL); return FALSE; } /* A_HA_CONNECT */ void do_ha_control(long long action, enum crmd_fsa_cause cause, enum crmd_fsa_state cur_state, enum crmd_fsa_input current_input, fsa_data_t * msg_data) { gboolean registered = FALSE; static crm_cluster_t *cluster = NULL; if (cluster == NULL) { cluster = calloc(1, sizeof(crm_cluster_t)); } if (action & A_HA_DISCONNECT) { crm_cluster_disconnect(cluster); crm_info("Disconnected from the cluster"); set_bit(fsa_input_register, R_HA_DISCONNECTED); } if (action & A_HA_CONNECT) { crm_set_status_callback(&peer_update_callback); if (is_openais_cluster()) { #if SUPPORT_COROSYNC registered = crm_connect_corosync(cluster); #endif } else if (is_heartbeat_cluster()) { #if SUPPORT_HEARTBEAT cluster->destroy = crmd_ha_connection_destroy; cluster->hb_dispatch = crmd_ha_msg_callback; registered = crm_cluster_connect(cluster); fsa_cluster_conn = cluster->hb_conn; crm_trace("Be informed of Node Status changes"); if (registered && fsa_cluster_conn->llc_ops->set_nstatus_callback(fsa_cluster_conn, crmd_ha_status_callback, fsa_cluster_conn) != HA_OK) { crm_err("Cannot set nstatus callback: %s", fsa_cluster_conn->llc_ops->errmsg(fsa_cluster_conn)); registered = FALSE; } crm_trace("Be informed of CRM Client Status changes"); if (registered && fsa_cluster_conn->llc_ops->set_cstatus_callback(fsa_cluster_conn, crmd_client_status_callback, fsa_cluster_conn) != HA_OK) { crm_err("Cannot set cstatus callback: %s", fsa_cluster_conn->llc_ops->errmsg(fsa_cluster_conn)); registered = FALSE; } if (registered) { crm_trace("Requesting an initial dump of CRMD client_status"); fsa_cluster_conn->llc_ops->client_status(fsa_cluster_conn, NULL, CRM_SYSTEM_CRMD, -1); } #endif } fsa_election = election_init(NULL, cluster->uname, 60000/*60s*/, election_timeout_popped); fsa_our_uname = cluster->uname; fsa_our_uuid = cluster->uuid; if(cluster->uuid == NULL) { crm_err("Could not obtain local uuid"); registered = FALSE; } if (registered == FALSE) { set_bit(fsa_input_register, R_HA_DISCONNECTED); register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL); return; } populate_cib_nodes(node_update_none, __FUNCTION__); clear_bit(fsa_input_register, R_HA_DISCONNECTED); crm_info("Connected to the cluster"); } if (action & ~(A_HA_CONNECT | A_HA_DISCONNECT)) { crm_err("Unexpected action %s in %s", fsa_action2string(action), __FUNCTION__); } } +static bool +need_spawn_pengine_from_crmd(void) +{ + static int result = -1; + + if (result != -1) + return result; + if (!is_heartbeat_cluster()) { + result = 0; + return result; + } + + /* NULL, or "strange" value: rather spawn from here. */ + result = TRUE; + crm_str_to_boolean(daemon_option("crmd_spawns_pengine"), &result); + return result; +} + /* A_SHUTDOWN */ void do_shutdown(long long action, enum crmd_fsa_cause cause, enum crmd_fsa_state cur_state, enum crmd_fsa_input current_input, fsa_data_t * msg_data) { /* just in case */ set_bit(fsa_input_register, R_SHUTDOWN); - if (is_heartbeat_cluster()) { + if (need_spawn_pengine_from_crmd()) { if (is_set(fsa_input_register, pe_subsystem->flag_connected)) { crm_info("Terminating the %s", pe_subsystem->name); if (stop_subsystem(pe_subsystem, TRUE) == FALSE) { /* its gone... */ crm_err("Faking %s exit", pe_subsystem->name); clear_bit(fsa_input_register, pe_subsystem->flag_connected); } else { crm_info("Waiting for subsystems to exit"); crmd_fsa_stall(FALSE); } } crm_info("All subsystems stopped, continuing"); } if (stonith_api) { /* Prevent it from comming up again */ clear_bit(fsa_input_register, R_ST_REQUIRED); crm_info("Disconnecting STONITH..."); stonith_api->cmds->disconnect(stonith_api); } } /* A_SHUTDOWN_REQ */ void do_shutdown_req(long long action, enum crmd_fsa_cause cause, enum crmd_fsa_state cur_state, enum crmd_fsa_input current_input, fsa_data_t * msg_data) { xmlNode *msg = NULL; crm_info("Sending shutdown request to %s", crm_str(fsa_our_dc)); msg = create_request(CRM_OP_SHUTDOWN_REQ, NULL, NULL, CRM_SYSTEM_DC, CRM_SYSTEM_CRMD, NULL); /* set_bit(fsa_input_register, R_STAYDOWN); */ if (send_cluster_message(NULL, crm_msg_crmd, msg, TRUE) == FALSE) { register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL); } free_xml(msg); } extern crm_ipc_t *attrd_ipc; extern char *max_generation_from; extern xmlNode *max_generation_xml; extern GHashTable *resource_history; extern GHashTable *voted; extern GHashTable *reload_hash; extern char *te_client_id; void log_connected_client(gpointer key, gpointer value, gpointer user_data); void log_connected_client(gpointer key, gpointer value, gpointer user_data) { crm_client_t *client = value; crm_err("%s is still connected at exit", crm_client_name(client)); } int crmd_fast_exit(int rc) { if (is_set(fsa_input_register, R_STAYDOWN)) { crm_warn("Inhibiting respawn: %d -> %d", rc, 100); rc = 100; } if (rc == pcmk_ok && is_set(fsa_input_register, R_IN_RECOVERY)) { crm_err("Could not recover from internal error"); rc = pcmk_err_generic; } return crm_exit(rc); } int crmd_exit(int rc) { GListPtr gIter = NULL; GMainLoop *mloop = crmd_mainloop; static bool in_progress = FALSE; if(in_progress && rc == 0) { crm_debug("Exit is already in progress"); return rc; } else if(in_progress) { crm_notice("Error during shutdown process, terminating now: %s (%d)", pcmk_strerror(rc), rc); crm_write_blackbox(SIGTRAP, NULL); crmd_fast_exit(rc); } in_progress = TRUE; crm_trace("Preparing to exit: %d", rc); /* Suppress secondary errors resulting from us disconnecting everything */ set_bit(fsa_input_register, R_HA_DISCONNECTED); /* Close all IPC servers and clients to ensure any and all shared memory files are cleaned up */ if(ipcs) { crm_trace("Closing IPC server"); mainloop_del_ipc_server(ipcs); ipcs = NULL; } if (attrd_ipc) { crm_trace("Closing attrd connection"); crm_ipc_close(attrd_ipc); crm_ipc_destroy(attrd_ipc); attrd_ipc = NULL; } if (pe_subsystem && pe_subsystem->client && pe_subsystem->client->ipcs) { crm_trace("Disconnecting Policy Engine"); qb_ipcs_disconnect(pe_subsystem->client->ipcs); } if(stonith_api) { crm_trace("Disconnecting fencing API"); clear_bit(fsa_input_register, R_ST_REQUIRED); stonith_api->cmds->free(stonith_api); stonith_api = NULL; } if (rc == pcmk_ok && crmd_mainloop == NULL) { crm_debug("No mainloop detected"); rc = EPROTO; } /* On an error, just get out. * * Otherwise, make the effort to have mainloop exit gracefully so * that it (mostly) cleans up after itself and valgrind has less * to report on - allowing real errors stand out */ if(rc != pcmk_ok) { crm_notice("Forcing immediate exit: %s (%d)", pcmk_strerror(rc), rc); crm_write_blackbox(SIGTRAP, NULL); return crmd_fast_exit(rc); } /* Clean up as much memory as possible for valgrind */ for (gIter = fsa_message_queue; gIter != NULL; gIter = gIter->next) { fsa_data_t *fsa_data = gIter->data; crm_info("Dropping %s: [ state=%s cause=%s origin=%s ]", fsa_input2string(fsa_data->fsa_input), fsa_state2string(fsa_state), fsa_cause2string(fsa_data->fsa_cause), fsa_data->origin); delete_fsa_input(fsa_data); } clear_bit(fsa_input_register, R_MEMBERSHIP); g_list_free(fsa_message_queue); fsa_message_queue = NULL; free(pe_subsystem); pe_subsystem = NULL; free(te_subsystem); te_subsystem = NULL; free(cib_subsystem); cib_subsystem = NULL; if (reload_hash) { crm_trace("Destroying reload cache with %d members", g_hash_table_size(reload_hash)); g_hash_table_destroy(reload_hash); reload_hash = NULL; } election_fini(fsa_election); fsa_election = NULL; cib_delete(fsa_cib_conn); fsa_cib_conn = NULL; verify_stopped(fsa_state, LOG_WARNING); clear_bit(fsa_input_register, R_LRM_CONNECTED); lrm_state_destroy_all(); /* This basically will not work, since mainloop has a reference to it */ mainloop_destroy_trigger(fsa_source); fsa_source = NULL; mainloop_destroy_trigger(config_read); config_read = NULL; mainloop_destroy_trigger(stonith_reconnect); stonith_reconnect = NULL; mainloop_destroy_trigger(transition_trigger); transition_trigger = NULL; crm_client_cleanup(); crm_peer_destroy(); crm_timer_stop(transition_timer); crm_timer_stop(integration_timer); crm_timer_stop(finalization_timer); crm_timer_stop(election_trigger); election_timeout_stop(fsa_election); crm_timer_stop(shutdown_escalation_timer); crm_timer_stop(wait_timer); crm_timer_stop(recheck_timer); free(transition_timer); transition_timer = NULL; free(integration_timer); integration_timer = NULL; free(finalization_timer); finalization_timer = NULL; free(election_trigger); election_trigger = NULL; election_fini(fsa_election); free(shutdown_escalation_timer); shutdown_escalation_timer = NULL; free(wait_timer); wait_timer = NULL; free(recheck_timer); recheck_timer = NULL; free(fsa_our_dc_version); fsa_our_dc_version = NULL; free(fsa_our_uname); fsa_our_uname = NULL; free(fsa_our_uuid); fsa_our_uuid = NULL; free(fsa_our_dc); fsa_our_dc = NULL; free(fsa_cluster_name); fsa_cluster_name = NULL; free(te_uuid); te_uuid = NULL; free(te_client_id); te_client_id = NULL; free(fsa_pe_ref); fsa_pe_ref = NULL; free(failed_stop_offset); failed_stop_offset = NULL; free(failed_start_offset); failed_start_offset = NULL; free(max_generation_from); max_generation_from = NULL; free_xml(max_generation_xml); max_generation_xml = NULL; mainloop_destroy_signal(SIGPIPE); mainloop_destroy_signal(SIGUSR1); mainloop_destroy_signal(SIGTERM); mainloop_destroy_signal(SIGTRAP); mainloop_destroy_signal(SIGCHLD); if (mloop) { int lpc = 0; GMainContext *ctx = g_main_loop_get_context(crmd_mainloop); /* Don't re-enter this block */ crmd_mainloop = NULL; crm_trace("Draining mainloop %d %d", g_main_loop_is_running(mloop), g_main_context_pending(ctx)); while(g_main_context_pending(ctx) && lpc < 10) { lpc++; crm_trace("Iteration %d", lpc); g_main_context_dispatch(ctx); } crm_trace("Closing mainloop %d %d", g_main_loop_is_running(mloop), g_main_context_pending(ctx)); g_main_loop_quit(mloop); #if SUPPORT_HEARTBEAT /* Do this only after g_main_loop_quit(). * * This interface was broken (incomplete) since it was introduced. * ->delete() does cleanup and free most of it, but it does not * actually remove and destroy the corresponding GSource, so the next * prepare/check iteratioin would find a corrupt (because partially * freed) GSource, and segfault. * * Apparently one was supposed to store the GSource as returned by * G_main_add_ll_cluster(), and g_source_destroy() that "by hand". * * But no-one ever did this, not even in the old hb code when this was * introduced. * * Note that fsa_cluster_conn was set as an "alias" to cluster->hb_conn * in do_ha_control() right after crm_cluster_connect(), and only * happens to still point at that object, because do_ha_control() does * not reset it to NULL after crm_cluster_disconnect() above does * reset cluster->hb_conn to NULL. * Not sure if that's something to cleanup, too. * * I'll try to fix this up in heartbeat proper, so ->delete * will actually remove, and destroy, and unref, and free this thing. * Doing so after g_main_loop_quit() is valid with both old, * and eventually fixed heartbeat. * * If we introduce the "by hand" destroy/remove/unref, * this may break again once heartbeat is fixed :-( * * -- Lars Ellenberg */ if (fsa_cluster_conn) { crm_trace("Deleting heartbeat api object"); fsa_cluster_conn->llc_ops->delete(fsa_cluster_conn); fsa_cluster_conn = NULL; } #endif /* Won't do anything yet, since we're inside it now */ g_main_loop_unref(mloop); crm_trace("Done %d", rc); } /* Graceful */ return rc; } /* A_EXIT_0, A_EXIT_1 */ void do_exit(long long action, enum crmd_fsa_cause cause, enum crmd_fsa_state cur_state, enum crmd_fsa_input current_input, fsa_data_t * msg_data) { int exit_code = pcmk_ok; int log_level = LOG_INFO; const char *exit_type = "gracefully"; if (action & A_EXIT_1) { /* exit_code = pcmk_err_generic; */ log_level = LOG_ERR; exit_type = "forcefully"; exit_code = pcmk_err_generic; } verify_stopped(cur_state, LOG_ERR); do_crm_log(log_level, "Performing %s - %s exiting the CRMd", fsa_action2string(action), exit_type); crm_info("[%s] stopped (%d)", crm_system_name, exit_code); crmd_exit(exit_code); } static void sigpipe_ignore(int nsig) { return; } /* A_STARTUP */ void do_startup(long long action, enum crmd_fsa_cause cause, enum crmd_fsa_state cur_state, enum crmd_fsa_input current_input, fsa_data_t * msg_data) { int was_error = 0; crm_debug("Registering Signal Handlers"); mainloop_add_signal(SIGTERM, crm_shutdown); mainloop_add_signal(SIGPIPE, sigpipe_ignore); fsa_source = mainloop_add_trigger(G_PRIORITY_HIGH, crm_fsa_trigger, NULL); config_read = mainloop_add_trigger(G_PRIORITY_HIGH, crm_read_options, NULL); transition_trigger = mainloop_add_trigger(G_PRIORITY_LOW, te_graph_trigger, NULL); crm_debug("Creating CIB and LRM objects"); fsa_cib_conn = cib_new(); lrm_state_init_local(); /* set up the timers */ transition_timer = calloc(1, sizeof(fsa_timer_t)); integration_timer = calloc(1, sizeof(fsa_timer_t)); finalization_timer = calloc(1, sizeof(fsa_timer_t)); election_trigger = calloc(1, sizeof(fsa_timer_t)); shutdown_escalation_timer = calloc(1, sizeof(fsa_timer_t)); wait_timer = calloc(1, sizeof(fsa_timer_t)); recheck_timer = calloc(1, sizeof(fsa_timer_t)); if (election_trigger != NULL) { election_trigger->source_id = 0; election_trigger->period_ms = -1; election_trigger->fsa_input = I_DC_TIMEOUT; election_trigger->callback = crm_timer_popped; election_trigger->repeat = FALSE; } else { was_error = TRUE; } if (transition_timer != NULL) { transition_timer->source_id = 0; transition_timer->period_ms = -1; transition_timer->fsa_input = I_PE_CALC; transition_timer->callback = crm_timer_popped; transition_timer->repeat = FALSE; } else { was_error = TRUE; } if (integration_timer != NULL) { integration_timer->source_id = 0; integration_timer->period_ms = -1; integration_timer->fsa_input = I_INTEGRATED; integration_timer->callback = crm_timer_popped; integration_timer->repeat = FALSE; } else { was_error = TRUE; } if (finalization_timer != NULL) { finalization_timer->source_id = 0; finalization_timer->period_ms = -1; finalization_timer->fsa_input = I_FINALIZED; finalization_timer->callback = crm_timer_popped; finalization_timer->repeat = FALSE; /* for possible enabling... a bug in the join protocol left * a slave in S_PENDING while we think its in S_NOT_DC * * raising I_FINALIZED put us into a transition loop which is * never resolved. * in this loop we continually send probes which the node * NACK's because its in S_PENDING * * if we have nodes where heartbeat is active but the * CRM is not... then this will be handled in the * integration phase */ finalization_timer->fsa_input = I_ELECTION; } else { was_error = TRUE; } if (shutdown_escalation_timer != NULL) { shutdown_escalation_timer->source_id = 0; shutdown_escalation_timer->period_ms = -1; shutdown_escalation_timer->fsa_input = I_STOP; shutdown_escalation_timer->callback = crm_timer_popped; shutdown_escalation_timer->repeat = FALSE; } else { was_error = TRUE; } if (wait_timer != NULL) { wait_timer->source_id = 0; wait_timer->period_ms = 2000; wait_timer->fsa_input = I_NULL; wait_timer->callback = crm_timer_popped; wait_timer->repeat = FALSE; } else { was_error = TRUE; } if (recheck_timer != NULL) { recheck_timer->source_id = 0; recheck_timer->period_ms = -1; recheck_timer->fsa_input = I_PE_CALC; recheck_timer->callback = crm_timer_popped; recheck_timer->repeat = FALSE; } else { was_error = TRUE; } /* set up the sub systems */ cib_subsystem = calloc(1, sizeof(struct crm_subsystem_s)); te_subsystem = calloc(1, sizeof(struct crm_subsystem_s)); pe_subsystem = calloc(1, sizeof(struct crm_subsystem_s)); if (cib_subsystem != NULL) { cib_subsystem->pid = -1; cib_subsystem->name = CRM_SYSTEM_CIB; cib_subsystem->flag_connected = R_CIB_CONNECTED; cib_subsystem->flag_required = R_CIB_REQUIRED; } else { was_error = TRUE; } if (te_subsystem != NULL) { te_subsystem->pid = -1; te_subsystem->name = CRM_SYSTEM_TENGINE; te_subsystem->flag_connected = R_TE_CONNECTED; te_subsystem->flag_required = R_TE_REQUIRED; } else { was_error = TRUE; } if (pe_subsystem != NULL) { pe_subsystem->pid = -1; pe_subsystem->path = CRM_DAEMON_DIR; pe_subsystem->name = CRM_SYSTEM_PENGINE; pe_subsystem->command = CRM_DAEMON_DIR "/" CRM_SYSTEM_PENGINE; pe_subsystem->args = NULL; pe_subsystem->flag_connected = R_PE_CONNECTED; pe_subsystem->flag_required = R_PE_REQUIRED; } else { was_error = TRUE; } - if (was_error == FALSE && is_heartbeat_cluster()) { + if (was_error == FALSE && need_spawn_pengine_from_crmd()) { if (start_subsystem(pe_subsystem) == FALSE) { was_error = TRUE; } } if (was_error) { register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL); } } static int32_t crmd_ipc_accept(qb_ipcs_connection_t * c, uid_t uid, gid_t gid) { crm_trace("Connection %p", c); if (crm_client_new(c, uid, gid) == NULL) { return -EIO; } return 0; } static void crmd_ipc_created(qb_ipcs_connection_t * c) { crm_trace("Connection %p", c); } static int32_t crmd_ipc_dispatch(qb_ipcs_connection_t * c, void *data, size_t size) { uint32_t id = 0; uint32_t flags = 0; crm_client_t *client = crm_client_get(c); xmlNode *msg = crm_ipcs_recv(client, data, size, &id, &flags); crm_trace("Invoked: %s", crm_client_name(client)); crm_ipcs_send_ack(client, id, flags, "ack", __FUNCTION__, __LINE__); if (msg == NULL) { return 0; } #if ENABLE_ACL CRM_ASSERT(client->user != NULL); crm_acl_get_set_user(msg, F_CRM_USER, client->user); #endif crm_trace("Processing msg from %s", crm_client_name(client)); crm_log_xml_trace(msg, "CRMd[inbound]"); crm_xml_add(msg, F_CRM_SYS_FROM, client->id); if (crmd_authorize_message(msg, client, NULL)) { route_message(C_IPC_MESSAGE, msg); } trigger_fsa(fsa_source); free_xml(msg); return 0; } static int32_t crmd_ipc_closed(qb_ipcs_connection_t * c) { crm_client_t *client = crm_client_get(c); struct crm_subsystem_s *the_subsystem = NULL; if (client == NULL) { return 0; } crm_trace("Connection %p", c); if (client->userdata == NULL) { crm_trace("Client hadn't registered with us yet"); } else if (strcasecmp(CRM_SYSTEM_PENGINE, client->userdata) == 0) { the_subsystem = pe_subsystem; } else if (strcasecmp(CRM_SYSTEM_TENGINE, client->userdata) == 0) { the_subsystem = te_subsystem; } else if (strcasecmp(CRM_SYSTEM_CIB, client->userdata) == 0) { the_subsystem = cib_subsystem; } if (the_subsystem != NULL) { the_subsystem->source = NULL; the_subsystem->client = NULL; crm_info("Received HUP from %s:[%d]", the_subsystem->name, the_subsystem->pid); } else { /* else that was a transient client */ crm_trace("Received HUP from transient client"); } crm_trace("Disconnecting client %s (%p)", crm_client_name(client), client); free(client->userdata); crm_client_destroy(client); trigger_fsa(fsa_source); return 0; } static void crmd_ipc_destroy(qb_ipcs_connection_t * c) { crm_trace("Connection %p", c); crmd_ipc_closed(c); } /* A_STOP */ void do_stop(long long action, enum crmd_fsa_cause cause, enum crmd_fsa_state cur_state, enum crmd_fsa_input current_input, fsa_data_t * msg_data) { crm_trace("Closing IPC server"); mainloop_del_ipc_server(ipcs); ipcs = NULL; register_fsa_input(C_FSA_INTERNAL, I_TERMINATE, NULL); } /* A_STARTED */ void do_started(long long action, enum crmd_fsa_cause cause, enum crmd_fsa_state cur_state, enum crmd_fsa_input current_input, fsa_data_t * msg_data) { static struct qb_ipcs_service_handlers crmd_callbacks = { .connection_accept = crmd_ipc_accept, .connection_created = crmd_ipc_created, .msg_process = crmd_ipc_dispatch, .connection_closed = crmd_ipc_closed, .connection_destroyed = crmd_ipc_destroy }; if (cur_state != S_STARTING) { crm_err("Start cancelled... %s", fsa_state2string(cur_state)); return; } else if (is_set(fsa_input_register, R_MEMBERSHIP) == FALSE) { crm_info("Delaying start, no membership data (%.16llx)", R_MEMBERSHIP); crmd_fsa_stall(TRUE); return; } else if (is_set(fsa_input_register, R_LRM_CONNECTED) == FALSE) { crm_info("Delaying start, LRM not connected (%.16llx)", R_LRM_CONNECTED); crmd_fsa_stall(TRUE); return; } else if (is_set(fsa_input_register, R_CIB_CONNECTED) == FALSE) { crm_info("Delaying start, CIB not connected (%.16llx)", R_CIB_CONNECTED); crmd_fsa_stall(TRUE); return; } else if (is_set(fsa_input_register, R_READ_CONFIG) == FALSE) { crm_info("Delaying start, Config not read (%.16llx)", R_READ_CONFIG); crmd_fsa_stall(TRUE); return; } else if (is_set(fsa_input_register, R_PEER_DATA) == FALSE) { /* try reading from HA */ crm_info("Delaying start, No peer data (%.16llx)", R_PEER_DATA); #if SUPPORT_HEARTBEAT if (is_heartbeat_cluster()) { HA_Message *msg = NULL; crm_trace("Looking for a HA message"); msg = fsa_cluster_conn->llc_ops->readmsg(fsa_cluster_conn, 0); if (msg != NULL) { crm_trace("There was a HA message"); ha_msg_del(msg); } } #endif crmd_fsa_stall(TRUE); return; } crm_debug("Init server comms"); ipcs = crmd_ipc_server_init(&crmd_callbacks); if (ipcs == NULL) { crm_err("Failed to create IPC server: shutting down and inhibiting respawn"); register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL); } if (stonith_reconnect == NULL) { int dummy; stonith_reconnect = mainloop_add_trigger(G_PRIORITY_LOW, te_connect_stonith, &dummy); } set_bit(fsa_input_register, R_ST_REQUIRED); mainloop_set_trigger(stonith_reconnect); crm_notice("The local CRM is operational"); clear_bit(fsa_input_register, R_STARTING); register_fsa_input(msg_data->fsa_cause, I_PENDING, NULL); } /* A_RECOVER */ void do_recover(long long action, enum crmd_fsa_cause cause, enum crmd_fsa_state cur_state, enum crmd_fsa_input current_input, fsa_data_t * msg_data) { set_bit(fsa_input_register, R_IN_RECOVERY); crm_warn("Fast-tracking shutdown in response to errors"); register_fsa_input(C_FSA_INTERNAL, I_TERMINATE, NULL); } /* *INDENT-OFF* */ pe_cluster_option crmd_opts[] = { /* name, old-name, validate, default, description */ { "dc-version", NULL, "string", NULL, "none", NULL, "Version of Pacemaker on the cluster's DC.", "Includes the hash which identifies the exact Mercurial changeset it was built from. Used for diagnostic purposes." }, { "cluster-infrastructure", NULL, "string", NULL, "heartbeat", NULL, "The messaging stack on which Pacemaker is currently running.", "Used for informational and diagnostic purposes." }, { XML_CONFIG_ATTR_DC_DEADTIME, "dc_deadtime", "time", NULL, "20s", &check_time, "How long to wait for a response from other nodes during startup.", "The \"correct\" value will depend on the speed/load of your network and the type of switches used." }, { XML_CONFIG_ATTR_RECHECK, "cluster_recheck_interval", "time", "Zero disables polling. Positive values are an interval in seconds (unless other SI units are specified. eg. 5min)", "15min", &check_timer, "Polling interval for time based changes to options, resource parameters and constraints.", "The Cluster is primarily event driven, however the configuration can have elements that change based on time." " To ensure these changes take effect, we can optionally poll the cluster's status for changes." }, { "load-threshold", NULL, "percentage", NULL, "80%", &check_utilization, "The maximum amount of system resources that should be used by nodes in the cluster", "The cluster will slow down its recovery process when the amount of system resources used" " (currently CPU) approaches this limit", }, { "node-action-limit", NULL, "integer", NULL, "0", &check_number, "The maximum number of jobs that can be scheduled per node. Defaults to 2x cores"}, { XML_CONFIG_ATTR_ELECTION_FAIL, "election_timeout", "time", NULL, "2min", &check_timer, "*** Advanced Use Only ***.", "If need to adjust this value, it probably indicates the presence of a bug." }, { XML_CONFIG_ATTR_FORCE_QUIT, "shutdown_escalation", "time", NULL, "20min", &check_timer, "*** Advanced Use Only ***.", "If need to adjust this value, it probably indicates the presence of a bug." }, { "crmd-integration-timeout", NULL, "time", NULL, "3min", &check_timer, "*** Advanced Use Only ***.", "If need to adjust this value, it probably indicates the presence of a bug." }, { "crmd-finalization-timeout", NULL, "time", NULL, "30min", &check_timer, "*** Advanced Use Only ***.", "If you need to adjust this value, it probably indicates the presence of a bug." }, { "crmd-transition-delay", NULL, "time", NULL, "0s", &check_timer, "*** Advanced Use Only ***\nEnabling this option will slow down cluster recovery under all conditions", "Delay cluster recovery for the configured interval to allow for additional/related events to occur.\nUseful if your configuration is sensitive to the order in which ping updates arrive." }, { "stonith-watchdog-timeout", NULL, "time", NULL, NULL, &check_timer, "How long to wait before we can assume nodes are safely down", NULL }, { "no-quorum-policy", "no_quorum_policy", "enum", "stop, freeze, ignore, suicide", "stop", &check_quorum, NULL, NULL }, #if SUPPORT_PLUGIN { XML_ATTR_EXPECTED_VOTES, NULL, "integer", NULL, "2", &check_number, "The number of nodes expected to be in the cluster", "Used to calculate quorum in openais based clusters." }, #endif }; /* *INDENT-ON* */ void crmd_metadata(void) { config_metadata("CRM Daemon", "1.0", "CRM Daemon Options", "This is a fake resource that details the options that can be configured for the CRM Daemon.", crmd_opts, DIMOF(crmd_opts)); } static void verify_crmd_options(GHashTable * options) { verify_all_options(options, crmd_opts, DIMOF(crmd_opts)); } static const char * crmd_pref(GHashTable * options, const char *name) { return get_cluster_pref(options, crmd_opts, DIMOF(crmd_opts), name); } static void config_query_callback(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data) { const char *value = NULL; GHashTable *config_hash = NULL; crm_time_t *now = crm_time_new(NULL); long st_timeout = 0; long sbd_timeout = 0; if (rc != pcmk_ok) { fsa_data_t *msg_data = NULL; crm_err("Local CIB query resulted in an error: %s", pcmk_strerror(rc)); register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL); if (rc == -EACCES || rc == -pcmk_err_schema_validation) { crm_err("The cluster is mis-configured - shutting down and staying down"); set_bit(fsa_input_register, R_STAYDOWN); } goto bail; } crm_debug("Call %d : Parsing CIB options", call_id); config_hash = g_hash_table_new_full(crm_str_hash, g_str_equal, g_hash_destroy_str, g_hash_destroy_str); unpack_instance_attributes(output, output, XML_CIB_TAG_PROPSET, NULL, config_hash, CIB_OPTIONS_FIRST, FALSE, now); verify_crmd_options(config_hash); value = crmd_pref(config_hash, XML_CONFIG_ATTR_DC_DEADTIME); election_trigger->period_ms = crm_get_msec(value); value = crmd_pref(config_hash, "node-action-limit"); /* Also checks migration-limit */ throttle_update_job_max(value); value = crmd_pref(config_hash, "load-threshold"); if(value) { throttle_load_target = strtof(value, NULL) / 100; } value = getenv("SBD_WATCHDOG_TIMEOUT"); sbd_timeout = crm_get_msec(value); value = crmd_pref(config_hash, "stonith-watchdog-timeout"); st_timeout = crm_get_msec(value); if(st_timeout > 0 && !daemon_option_enabled(crm_system_name, "watchdog")) { do_crm_log_always(LOG_EMERG, "Shutting down pacemaker, no watchdog device configured"); crmd_exit(DAEMON_RESPAWN_STOP); } else if(!daemon_option_enabled(crm_system_name, "watchdog")) { crm_trace("Watchdog disabled"); } else if(value == NULL && sbd_timeout > 0) { char *timeout = NULL; st_timeout = 2 * sbd_timeout / 1000; timeout = g_strdup_printf("%lds", st_timeout); crm_notice("Setting stonith-watchdog-timeout=%s", timeout); update_attr_delegate(fsa_cib_conn, cib_none, XML_CIB_TAG_CRMCONFIG, NULL, NULL, NULL, NULL, "stonith-watchdog-timeout", timeout, FALSE, NULL, NULL); free(timeout); } else if(st_timeout <= 0) { crm_notice("Watchdog enabled but stonith-watchdog-timeout is disabled"); } else if(st_timeout < sbd_timeout) { do_crm_log_always(LOG_EMERG, "Shutting down pacemaker, stonith-watchdog-timeout (%ldms) is too short (must be greater than %ldms)", st_timeout, sbd_timeout); crmd_exit(DAEMON_RESPAWN_STOP); } value = crmd_pref(config_hash, "no-quorum-policy"); if (safe_str_eq(value, "suicide") && daemon_option_enabled(crm_system_name, "watchdog")) { no_quorum_suicide_escalation = TRUE; } value = crmd_pref(config_hash, XML_CONFIG_ATTR_FORCE_QUIT); shutdown_escalation_timer->period_ms = crm_get_msec(value); /* How long to declare an election over - even if not everyone voted */ crm_debug("Shutdown escalation occurs after: %dms", shutdown_escalation_timer->period_ms); value = crmd_pref(config_hash, XML_CONFIG_ATTR_ELECTION_FAIL); election_timeout_set_period(fsa_election, crm_get_msec(value)); value = crmd_pref(config_hash, XML_CONFIG_ATTR_RECHECK); recheck_timer->period_ms = crm_get_msec(value); crm_debug("Checking for expired actions every %dms", recheck_timer->period_ms); value = crmd_pref(config_hash, "crmd-transition-delay"); transition_timer->period_ms = crm_get_msec(value); value = crmd_pref(config_hash, "crmd-integration-timeout"); integration_timer->period_ms = crm_get_msec(value); value = crmd_pref(config_hash, "crmd-finalization-timeout"); finalization_timer->period_ms = crm_get_msec(value); #if SUPPORT_COROSYNC if (is_classic_ais_cluster()) { value = crmd_pref(config_hash, XML_ATTR_EXPECTED_VOTES); crm_debug("Sending expected-votes=%s to corosync", value); send_cluster_text(crm_class_quorum, value, TRUE, NULL, crm_msg_ais); } #endif free(fsa_cluster_name); fsa_cluster_name = NULL; value = g_hash_table_lookup(config_hash, "cluster-name"); if (value) { fsa_cluster_name = strdup(value); } set_bit(fsa_input_register, R_READ_CONFIG); crm_trace("Triggering FSA: %s", __FUNCTION__); mainloop_set_trigger(fsa_source); g_hash_table_destroy(config_hash); bail: crm_time_free(now); } gboolean crm_read_options(gpointer user_data) { int call_id = fsa_cib_conn->cmds->query(fsa_cib_conn, XML_CIB_TAG_CRMCONFIG, NULL, cib_scope_local); fsa_register_cib_callback(call_id, FALSE, NULL, config_query_callback); crm_trace("Querying the CIB... call %d", call_id); return TRUE; } /* A_READCONFIG */ void do_read_config(long long action, enum crmd_fsa_cause cause, enum crmd_fsa_state cur_state, enum crmd_fsa_input current_input, fsa_data_t * msg_data) { throttle_init(); mainloop_set_trigger(config_read); } void crm_shutdown(int nsig) { if (crmd_mainloop != NULL && g_main_is_running(crmd_mainloop)) { if (is_set(fsa_input_register, R_SHUTDOWN)) { crm_err("Escalating the shutdown"); register_fsa_input_before(C_SHUTDOWN, I_ERROR, NULL); } else { set_bit(fsa_input_register, R_SHUTDOWN); register_fsa_input(C_SHUTDOWN, I_SHUTDOWN, NULL); if (shutdown_escalation_timer->period_ms < 1) { const char *value = crmd_pref(NULL, XML_CONFIG_ATTR_FORCE_QUIT); int msec = crm_get_msec(value); crm_debug("Using default shutdown escalation: %dms", msec); shutdown_escalation_timer->period_ms = msec; } /* cant rely on this... */ crm_notice("Requesting shutdown, upper limit is %dms", shutdown_escalation_timer->period_ms); crm_timer_start(shutdown_escalation_timer); } } else { crm_info("exit from shutdown"); crmd_exit(pcmk_ok); } } diff --git a/crmd/heartbeat.c b/crmd/heartbeat.c index 1d63190803..4726c0b345 100644 --- a/crmd/heartbeat.c +++ b/crmd/heartbeat.c @@ -1,531 +1,548 @@ /* * Copyright (C) 2004 Andrew Beekhof * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* put these first so that uuid_t is defined without conflicts */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include void oc_ev_special(const oc_ev_t *, oc_ev_class_t, int); void ccm_event_detail(const oc_ev_membership_t * oc, oc_ed_t event); gboolean crmd_ha_msg_dispatch(ll_cluster_t * cluster_conn, gpointer user_data); void crmd_ccm_msg_callback(oc_ed_t event, void *cookie, size_t size, const void *data); int ccm_dispatch(gpointer user_data); #define CCM_EVENT_DETAIL 0 #define CCM_EVENT_DETAIL_PARTIAL 0 int (*ccm_api_callback_done) (void *cookie) = NULL; int (*ccm_api_handle_event) (const oc_ev_t * token) = NULL; static oc_ev_t *fsa_ev_token; static void *ccm_library = NULL; static int num_ccm_register_fails = 0; static int max_ccm_register_fails = 30; static void ccm_connection_destroy(void *userdata) { } /* A_CCM_CONNECT */ void do_ccm_control(long long action, enum crmd_fsa_cause cause, enum crmd_fsa_state cur_state, enum crmd_fsa_input current_input, fsa_data_t * msg_data) { static struct mainloop_fd_callbacks ccm_fd_callbacks = { .dispatch = ccm_dispatch, .destroy = ccm_connection_destroy, }; if (is_heartbeat_cluster()) { int (*ccm_api_register) (oc_ev_t ** token) = find_library_function(&ccm_library, CCM_LIBRARY, "oc_ev_register", 1); int (*ccm_api_set_callback) (const oc_ev_t * token, oc_ev_class_t class, oc_ev_callback_t * fn, oc_ev_callback_t ** prev_fn) = find_library_function(&ccm_library, CCM_LIBRARY, "oc_ev_set_callback", 1); void (*ccm_api_special) (const oc_ev_t *, oc_ev_class_t, int) = find_library_function(&ccm_library, CCM_LIBRARY, "oc_ev_special", 1); int (*ccm_api_activate) (const oc_ev_t * token, int *fd) = find_library_function(&ccm_library, CCM_LIBRARY, "oc_ev_activate", 1); int (*ccm_api_unregister) (oc_ev_t * token) = find_library_function(&ccm_library, CCM_LIBRARY, "oc_ev_unregister", 1); if (action & A_CCM_DISCONNECT) { set_bit(fsa_input_register, R_CCM_DISCONNECTED); (*ccm_api_unregister) (fsa_ev_token); } if (action & A_CCM_CONNECT) { int ret; int fsa_ev_fd; gboolean did_fail = FALSE; crm_trace("Registering with CCM"); clear_bit(fsa_input_register, R_CCM_DISCONNECTED); ret = (*ccm_api_register) (&fsa_ev_token); if (ret != 0) { crm_warn("CCM registration failed"); did_fail = TRUE; } if (did_fail == FALSE) { crm_trace("Setting up CCM callbacks"); ret = (*ccm_api_set_callback) (fsa_ev_token, OC_EV_MEMB_CLASS, crmd_ccm_msg_callback, NULL); if (ret != 0) { crm_warn("CCM callback not set"); did_fail = TRUE; } } if (did_fail == FALSE) { (*ccm_api_special) (fsa_ev_token, OC_EV_MEMB_CLASS, 0 /*don't care */ ); crm_trace("Activating CCM token"); ret = (*ccm_api_activate) (fsa_ev_token, &fsa_ev_fd); if (ret != 0) { crm_warn("CCM Activation failed"); did_fail = TRUE; } } if (did_fail) { num_ccm_register_fails++; (*ccm_api_unregister) (fsa_ev_token); if (num_ccm_register_fails < max_ccm_register_fails) { crm_warn("CCM Connection failed" " %d times (%d max)", num_ccm_register_fails, max_ccm_register_fails); crm_timer_start(wait_timer); crmd_fsa_stall(FALSE); return; } else { crm_err("CCM Activation failed %d (max) times", num_ccm_register_fails); register_fsa_error(C_FSA_INTERNAL, I_FAIL, NULL); return; } } crm_info("CCM connection established... waiting for first callback"); mainloop_add_fd("heartbeat-ccm", G_PRIORITY_HIGH, fsa_ev_fd, fsa_ev_token, &ccm_fd_callbacks); } } if (action & ~(A_CCM_CONNECT | A_CCM_DISCONNECT)) { crm_err("Unexpected action %s in %s", fsa_action2string(action), __FUNCTION__); } } void ccm_event_detail(const oc_ev_membership_t * oc, oc_ed_t event) { int lpc; gboolean member = FALSE; member = FALSE; crm_trace("-----------------------"); crm_info("%s: trans=%d, nodes=%d, new=%d, lost=%d n_idx=%d, " "new_idx=%d, old_idx=%d", ccm_event_name(event), oc->m_instance, oc->m_n_member, oc->m_n_in, oc->m_n_out, oc->m_memb_idx, oc->m_in_idx, oc->m_out_idx); #if !CCM_EVENT_DETAIL_PARTIAL for (lpc = 0; lpc < oc->m_n_member; lpc++) { crm_info("\tCURRENT: %s [nodeid=%d, born=%d]", oc->m_array[oc->m_memb_idx + lpc].node_uname, oc->m_array[oc->m_memb_idx + lpc].node_id, oc->m_array[oc->m_memb_idx + lpc].node_born_on); if (safe_str_eq(fsa_our_uname, oc->m_array[oc->m_memb_idx + lpc].node_uname)) { member = TRUE; } } if (member == FALSE) { crm_warn("MY NODE IS NOT IN CCM THE MEMBERSHIP LIST"); } #endif for (lpc = 0; lpc < (int)oc->m_n_in; lpc++) { crm_info("\tNEW: %s [nodeid=%d, born=%d]", oc->m_array[oc->m_in_idx + lpc].node_uname, oc->m_array[oc->m_in_idx + lpc].node_id, oc->m_array[oc->m_in_idx + lpc].node_born_on); } for (lpc = 0; lpc < (int)oc->m_n_out; lpc++) { crm_info("\tLOST: %s [nodeid=%d, born=%d]", oc->m_array[oc->m_out_idx + lpc].node_uname, oc->m_array[oc->m_out_idx + lpc].node_id, oc->m_array[oc->m_out_idx + lpc].node_born_on); } crm_trace("-----------------------"); } /* A_CCM_UPDATE_CACHE */ /* * Take the opportunity to update the node status in the CIB as well */ void do_ccm_update_cache(enum crmd_fsa_cause cause, enum crmd_fsa_state cur_state, oc_ed_t event, const oc_ev_membership_t * oc, xmlNode * xml) { unsigned long long instance = 0; unsigned int lpc = 0; if (is_heartbeat_cluster()) { CRM_ASSERT(oc != NULL); instance = oc->m_instance; } CRM_ASSERT(crm_peer_seq <= instance); switch (cur_state) { case S_STOPPING: case S_TERMINATE: case S_HALT: crm_debug("Ignoring %s CCM event %llu, we're in state %s", ccm_event_name(event), instance, fsa_state2string(cur_state)); return; case S_ELECTION: register_fsa_action(A_ELECTION_CHECK); break; default: break; } if (is_heartbeat_cluster()) { ccm_event_detail(oc, event); /*--*-- Recently Dead Member Nodes --*--*/ for (lpc = 0; lpc < oc->m_n_out; lpc++) { crm_update_ccm_node(oc, lpc + oc->m_out_idx, CRM_NODE_LOST, instance); } /*--*-- All Member Nodes --*--*/ for (lpc = 0; lpc < oc->m_n_member; lpc++) { - crm_update_ccm_node(oc, lpc + oc->m_memb_idx, CRM_NODE_ACTIVE, instance); + crm_update_ccm_node(oc, lpc + oc->m_memb_idx, CRM_NODE_MEMBER, instance); } + heartbeat_cluster->llc_ops->client_status(heartbeat_cluster, NULL, crm_system_name, 0); } if (event == OC_EV_MS_EVICTED) { crm_node_t *peer = crm_get_peer(0, fsa_our_uname); crm_update_peer_state(__FUNCTION__, peer, CRM_NODE_EVICTED, 0); /* todo: drop back to S_PENDING instead */ /* get out... NOW! * * go via the error recovery process so that HA will * restart us if required */ register_fsa_error_adv(cause, I_ERROR, NULL, NULL, __FUNCTION__); } post_cache_update(instance); return; } int ccm_dispatch(gpointer user_data) { int rc = 0; oc_ev_t *ccm_token = (oc_ev_t *) user_data; gboolean was_error = FALSE; crm_trace("Invoked"); if (ccm_api_handle_event == NULL) { ccm_api_handle_event = find_library_function(&ccm_library, CCM_LIBRARY, "oc_ev_handle_event", 1); } rc = (*ccm_api_handle_event) (ccm_token); if (rc != 0) { if (is_set(fsa_input_register, R_CCM_DISCONNECTED) == FALSE) { /* we signed out, so this is expected */ register_fsa_input(C_CCM_CALLBACK, I_ERROR, NULL); crm_err("CCM connection appears to have failed: rc=%d.", rc); } was_error = TRUE; } trigger_fsa(fsa_source); if (was_error) { return -1; } return 0; } void crmd_ccm_msg_callback(oc_ed_t event, void *cookie, size_t size, const void *data) { gboolean update_cache = FALSE; const oc_ev_membership_t *membership = data; gboolean update_quorum = FALSE; crm_trace("Invoked"); CRM_ASSERT(data != NULL); crm_info("Quorum %s after event=%s (id=%d)", ccm_have_quorum(event) ? "(re)attained" : "lost", ccm_event_name(event), membership->m_instance); if (crm_peer_seq > membership->m_instance) { crm_err("Membership instance ID went backwards! %llu->%d", crm_peer_seq, membership->m_instance); CRM_ASSERT(crm_peer_seq <= membership->m_instance); return; } /* * OC_EV_MS_NEW_MEMBERSHIP: membership with quorum * OC_EV_MS_MS_INVALID: membership without quorum * OC_EV_MS_NOT_PRIMARY: previous membership no longer valid * OC_EV_MS_PRIMARY_RESTORED: previous membership restored * OC_EV_MS_EVICTED: the client is evicted from ccm. */ switch (event) { case OC_EV_MS_NEW_MEMBERSHIP: case OC_EV_MS_INVALID: update_cache = TRUE; update_quorum = TRUE; break; case OC_EV_MS_NOT_PRIMARY: break; case OC_EV_MS_PRIMARY_RESTORED: update_cache = TRUE; crm_peer_seq = membership->m_instance; break; case OC_EV_MS_EVICTED: update_quorum = TRUE; register_fsa_input(C_FSA_INTERNAL, I_STOP, NULL); crm_err("Shutting down after CCM event: %s", ccm_event_name(event)); break; default: crm_err("Unknown CCM event: %d", event); } if (update_quorum) { crm_have_quorum = ccm_have_quorum(event); if (crm_have_quorum == FALSE) { /* did we just loose quorum? */ if (fsa_has_quorum) { crm_info("Quorum lost: %s", ccm_event_name(event)); } } crm_update_quorum(crm_have_quorum, FALSE); } if (update_cache) { crm_trace("Updating cache after event %s", ccm_event_name(event)); do_ccm_update_cache(C_CCM_CALLBACK, fsa_state, event, data, NULL); } else if (event != OC_EV_MS_NOT_PRIMARY) { crm_peer_seq = membership->m_instance; register_fsa_action(A_TE_CANCEL); } if (ccm_api_callback_done == NULL) { ccm_api_callback_done = find_library_function(&ccm_library, CCM_LIBRARY, "oc_ev_callback_done", 1); } (*ccm_api_callback_done) (cookie); return; } void crmd_ha_status_callback(const char *node, const char *status, void *private) { xmlNode *update = NULL; crm_node_t *peer = NULL; crm_notice("Status update: Node %s now has status [%s]", node, status); peer = crm_get_peer(0, node); if (safe_str_eq(status, PINGSTATUS)) { return; } if (safe_str_eq(status, DEADSTATUS)) { /* this node is toast */ - crm_update_peer_proc(__FUNCTION__, peer, crm_proc_heartbeat, OFFLINESTATUS); + crm_update_peer_proc(__FUNCTION__, peer, crm_proc_crmd|crm_proc_heartbeat, OFFLINESTATUS); } else { crm_update_peer_proc(__FUNCTION__, peer, crm_proc_heartbeat, ONLINESTATUS); } trigger_fsa(fsa_source); if (AM_I_DC) { update = do_update_node_cib(peer, node_update_cluster, NULL, __FUNCTION__); fsa_cib_anon_update(XML_CIB_TAG_STATUS, update, cib_scope_local | cib_quorum_override | cib_can_create); free_xml(update); } } void crmd_client_status_callback(const char *node, const char *client, const char *status, void *private) { crm_node_t *peer = NULL; crm_trace("Invoked"); if (safe_str_neq(client, CRM_SYSTEM_CRMD)) { return; } + peer = crm_get_peer(0, node); + + if (safe_str_neq(peer->state, CRM_NODE_MEMBER)) { + crm_warn("This peer is not a ccm member (yet). " + "Status ignored: Client %s/%s announced status [%s] (DC=%s)", + node, client, status, AM_I_DC ? "true" : "false"); + return; + } + set_bit(fsa_input_register, R_PEER_DATA); crm_notice("Status update: Client %s/%s now has status [%s] (DC=%s)", node, client, status, AM_I_DC ? "true" : "false"); - peer = crm_get_peer(0, node); + /* rest of the code, especially crm_update_peer_proc, + * does not know about JOINSTATUS, but expects ONLINESTATUS. + * See also cib/callbacks.c */ + if (safe_str_eq(status, JOINSTATUS)) { + status = ONLINESTATUS; + } else if (safe_str_eq(status, LEAVESTATUS)) { + status = OFFLINESTATUS; + } if (safe_str_eq(status, ONLINESTATUS)) { /* remove the cached value in case it changed */ crm_trace("Uncaching UUID for %s", node); free(peer->uuid); peer->uuid = NULL; } crm_update_peer_proc(__FUNCTION__, peer, crm_proc_crmd, status); if (AM_I_DC) { xmlNode *update = NULL; crm_trace("Got client status callback"); update = do_update_node_cib(peer, node_update_peer, NULL, __FUNCTION__); fsa_cib_anon_update(XML_CIB_TAG_STATUS, update, cib_scope_local | cib_quorum_override | cib_can_create); free_xml(update); } } void crmd_ha_msg_callback(HA_Message * hamsg, void *private_data) { int level = LOG_DEBUG; crm_node_t *from_node = NULL; xmlNode *msg = convert_ha_message(NULL, hamsg, __FUNCTION__); const char *from = crm_element_value(msg, F_ORIG); const char *op = crm_element_value(msg, F_CRM_TASK); const char *sys_from = crm_element_value(msg, F_CRM_SYS_FROM); CRM_CHECK(from != NULL, crm_log_xml_err(msg, "anon"); goto bail); crm_trace("HA[inbound]: %s from %s", op, from); if (crm_peer_cache == NULL || crm_active_peers() == 0) { crm_debug("Ignoring HA messages until we are" " connected to the CCM (%s op from %s)", op, from); crm_log_xml_trace(msg, "HA[inbound]: Ignore (No CCM)"); goto bail; } from_node = crm_get_peer(0, from); if (crm_is_peer_active(from_node) == FALSE) { if (safe_str_eq(op, CRM_OP_VOTE)) { level = LOG_WARNING; } else if (AM_I_DC && safe_str_eq(op, CRM_OP_JOIN_ANNOUNCE)) { level = LOG_WARNING; } else if (safe_str_eq(sys_from, CRM_SYSTEM_DC)) { level = LOG_WARNING; } do_crm_log(level, "Ignoring HA message (op=%s) from %s: not in our" " membership list (size=%d)", op, from, crm_active_peers()); crm_log_xml_trace(msg, "HA[inbound]: CCM Discard"); } else { crmd_ha_msg_filter(msg); } bail: free_xml(msg); return; } gboolean crmd_ha_msg_dispatch(ll_cluster_t * cluster_conn, gpointer user_data) { IPC_Channel *channel = NULL; gboolean stay_connected = TRUE; crm_trace("Invoked"); if (cluster_conn != NULL) { channel = cluster_conn->llc_ops->ipcchan(cluster_conn); } CRM_CHECK(cluster_conn != NULL,;); CRM_CHECK(channel != NULL,;); if (channel != NULL && IPC_ISRCONN(channel)) { if (cluster_conn->llc_ops->msgready(cluster_conn) == 0) { crm_trace("no message ready yet"); } /* invoke the callbacks but dont block */ cluster_conn->llc_ops->rcvmsg(cluster_conn, 0); } if (channel == NULL || channel->ch_status != IPC_CONNECT) { if (is_set(fsa_input_register, R_HA_DISCONNECTED) == FALSE) { crm_crit("Lost connection to heartbeat service."); } else { crm_info("Lost connection to heartbeat service."); } trigger_fsa(fsa_source); stay_connected = FALSE; } return stay_connected; } diff --git a/crmd/membership.c b/crmd/membership.c index e1414dff92..447e6a8ae4 100644 --- a/crmd/membership.c +++ b/crmd/membership.c @@ -1,438 +1,438 @@ /* * Copyright (C) 2004 Andrew Beekhof * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* put these first so that uuid_t is defined without conflicts */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include gboolean membership_flux_hack = FALSE; void post_cache_update(int instance); int last_peer_update = 0; guint highest_born_on = -1; extern gboolean check_join_state(enum crmd_fsa_state cur_state, const char *source); static void reap_dead_nodes(gpointer key, gpointer value, gpointer user_data) { crm_node_t *node = value; if (crm_is_peer_active(node) == FALSE) { crm_update_peer_join(__FUNCTION__, node, crm_join_none); if(node && node->uname) { election_remove(fsa_election, node->uname); if (safe_str_eq(fsa_our_uname, node->uname)) { crm_err("We're not part of the cluster anymore"); register_fsa_input(C_FSA_INTERNAL, I_ERROR, NULL); } else if (AM_I_DC == FALSE && safe_str_eq(node->uname, fsa_our_dc)) { crm_warn("Our DC node (%s) left the cluster", node->uname); register_fsa_input(C_FSA_INTERNAL, I_ELECTION, NULL); } } if (fsa_state == S_INTEGRATION || fsa_state == S_FINALIZE_JOIN) { check_join_state(fsa_state, __FUNCTION__); } if(node && node->uuid) { fail_incompletable_actions(transition_graph, node->uuid); } } } gboolean ever_had_quorum = FALSE; void post_cache_update(int instance) { xmlNode *no_op = NULL; crm_peer_seq = instance; crm_debug("Updated cache after membership event %d.", instance); g_hash_table_foreach(crm_peer_cache, reap_dead_nodes, NULL); set_bit(fsa_input_register, R_MEMBERSHIP); if (AM_I_DC) { populate_cib_nodes(node_update_quick | node_update_cluster | node_update_peer | node_update_expected, __FUNCTION__); } /* * If we lost nodes, we should re-check the election status * Safe to call outside of an election */ register_fsa_action(A_ELECTION_CHECK); /* Membership changed, remind everyone we're here. * This will aid detection of duplicate DCs */ no_op = create_request(CRM_OP_NOOP, NULL, NULL, CRM_SYSTEM_CRMD, AM_I_DC ? CRM_SYSTEM_DC : CRM_SYSTEM_CRMD, NULL); send_cluster_message(NULL, crm_msg_crmd, no_op, FALSE); free_xml(no_op); } static void crmd_node_update_complete(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data) { fsa_data_t *msg_data = NULL; last_peer_update = 0; if (rc == pcmk_ok) { crm_trace("Node update %d complete", call_id); } else if(call_id < pcmk_ok) { crm_err("Node update failed: %s (%d)", pcmk_strerror(call_id), call_id); crm_log_xml_debug(msg, "failed"); register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL); } else { crm_err("Node update %d failed: %s (%d)", call_id, pcmk_strerror(rc), rc); crm_log_xml_debug(msg, "failed"); register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL); } } xmlNode * do_update_node_cib(crm_node_t * node, int flags, xmlNode * parent, const char *source) { const char *value = NULL; xmlNode *node_state; if (is_set(node->flags, crm_remote_node)) { return simple_remote_node_status(node->uname, parent, source); } if (!node->state) { crm_info("Node update for %s cancelled: no state, not seen yet", node->uname); return NULL; } node_state = create_xml_node(parent, XML_CIB_TAG_STATE); set_uuid(node_state, XML_ATTR_UUID, node); if (crm_element_value(node_state, XML_ATTR_UUID) == NULL) { crm_info("Node update for %s cancelled: no id", node->uname); free_xml(node_state); return NULL; } crm_xml_add(node_state, XML_ATTR_UNAME, node->uname); if (flags & node_update_cluster) { - if (safe_str_eq(node->state, CRM_NODE_ACTIVE)) { + if (safe_str_eq(node->state, CRM_NODE_MEMBER)) { value = XML_BOOLEAN_YES; } else if (node->state) { value = XML_BOOLEAN_NO; } else { value = NULL; } crm_xml_add(node_state, XML_NODE_IN_CLUSTER, value); } if (flags & node_update_peer) { value = OFFLINESTATUS; if (node->processes & proc_flags) { value = ONLINESTATUS; } crm_xml_add(node_state, XML_NODE_IS_PEER, value); } if (flags & node_update_join) { if(node->join <= crm_join_none) { value = CRMD_JOINSTATE_DOWN; } else { value = CRMD_JOINSTATE_MEMBER; } crm_xml_add(node_state, XML_NODE_JOIN_STATE, value); } if (flags & node_update_expected) { crm_xml_add(node_state, XML_NODE_EXPECTED, node->expected); } crm_xml_add(node_state, XML_ATTR_ORIGIN, source); return node_state; } static void remove_conflicting_node_callback(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data) { char *node_uuid = user_data; do_crm_log_unlikely(rc == 0 ? LOG_DEBUG : LOG_NOTICE, "Deletion of the unknown conflicting node \"%s\": %s (rc=%d)", node_uuid, pcmk_strerror(rc), rc); free(node_uuid); } static void search_conflicting_node_callback(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data) { char *new_node_uuid = user_data; xmlNode *node_xml = NULL; if (rc != pcmk_ok) { if (rc != -ENXIO) { crm_notice("Searching conflicting nodes for %s failed: %s (%d)", new_node_uuid, pcmk_strerror(rc), rc); } free(new_node_uuid); return; } else if (output == NULL) { free(new_node_uuid); return; } if (safe_str_eq(crm_element_name(output), XML_CIB_TAG_NODE)) { node_xml = output; } else { node_xml = __xml_first_child(output); } for (; node_xml != NULL; node_xml = __xml_next(node_xml)) { const char *node_uuid = NULL; const char *node_uname = NULL; GHashTableIter iter; crm_node_t *node = NULL; gboolean known = FALSE; if (safe_str_neq(crm_element_name(node_xml), XML_CIB_TAG_NODE)) { continue; } node_uuid = crm_element_value(node_xml, XML_ATTR_ID); node_uname = crm_element_value(node_xml, XML_ATTR_UNAME); if (node_uuid == NULL || node_uname == NULL) { continue; } g_hash_table_iter_init(&iter, crm_peer_cache); while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &node)) { if (node->uuid && safe_str_eq(node->uuid, node_uuid) && node->uname && safe_str_eq(node->uname, node_uname)) { known = TRUE; break; } } if (known == FALSE) { int delete_call_id = 0; xmlNode *node_state_xml = NULL; crm_notice("Deleting unknown node %s/%s which has conflicting uname with %s", node_uuid, node_uname, new_node_uuid); delete_call_id = fsa_cib_conn->cmds->delete(fsa_cib_conn, XML_CIB_TAG_NODES, node_xml, cib_scope_local | cib_quorum_override); fsa_register_cib_callback(delete_call_id, FALSE, strdup(node_uuid), remove_conflicting_node_callback); node_state_xml = create_xml_node(NULL, XML_CIB_TAG_STATE); crm_xml_add(node_state_xml, XML_ATTR_ID, node_uuid); crm_xml_add(node_state_xml, XML_ATTR_UNAME, node_uname); delete_call_id = fsa_cib_conn->cmds->delete(fsa_cib_conn, XML_CIB_TAG_STATUS, node_state_xml, cib_scope_local | cib_quorum_override); fsa_register_cib_callback(delete_call_id, FALSE, strdup(node_uuid), remove_conflicting_node_callback); free_xml(node_state_xml); } } free(new_node_uuid); } static void node_list_update_callback(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data) { fsa_data_t *msg_data = NULL; if(call_id < pcmk_ok) { crm_err("Node list update failed: %s (%d)", pcmk_strerror(call_id), call_id); crm_log_xml_debug(msg, "update:failed"); register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL); } else if(rc < pcmk_ok) { crm_err("Node update %d failed: %s (%d)", call_id, pcmk_strerror(rc), rc); crm_log_xml_debug(msg, "update:failed"); register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL); } } #define NODE_PATH_MAX 512 void populate_cib_nodes(enum node_update_flags flags, const char *source) { int call_id = 0; gboolean from_hashtable = TRUE; int call_options = cib_scope_local | cib_quorum_override; xmlNode *node_list = create_xml_node(NULL, XML_CIB_TAG_NODES); #if SUPPORT_HEARTBEAT if (is_not_set(flags, node_update_quick) && is_heartbeat_cluster()) { from_hashtable = heartbeat_initialize_nodelist(fsa_cluster_conn, FALSE, node_list); } #endif #if SUPPORT_COROSYNC # if !SUPPORT_PLUGIN if (is_not_set(flags, node_update_quick) && is_corosync_cluster()) { from_hashtable = corosync_initialize_nodelist(NULL, FALSE, node_list); } # endif #endif if (from_hashtable) { GHashTableIter iter; crm_node_t *node = NULL; g_hash_table_iter_init(&iter, crm_peer_cache); while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &node)) { xmlNode *new_node = NULL; crm_trace("Creating node entry for %s/%s", node->uname, node->uuid); if(node->uuid && node->uname) { char xpath[NODE_PATH_MAX]; /* We need both to be valid */ new_node = create_xml_node(node_list, XML_CIB_TAG_NODE); crm_xml_add(new_node, XML_ATTR_ID, node->uuid); crm_xml_add(new_node, XML_ATTR_UNAME, node->uname); /* Search and remove unknown nodes with the conflicting uname from CIB */ snprintf(xpath, NODE_PATH_MAX, "/" XML_TAG_CIB "/" XML_CIB_TAG_CONFIGURATION "/" XML_CIB_TAG_NODES "/" XML_CIB_TAG_NODE "[@uname='%s'][@id!='%s']", node->uname, node->uuid); call_id = fsa_cib_conn->cmds->query(fsa_cib_conn, xpath, NULL, cib_scope_local | cib_xpath); fsa_register_cib_callback(call_id, FALSE, strdup(node->uuid), search_conflicting_node_callback); } } } crm_trace("Populating section from %s", from_hashtable ? "hashtable" : "cluster"); fsa_cib_update(XML_CIB_TAG_NODES, node_list, call_options, call_id, NULL); fsa_register_cib_callback(call_id, FALSE, NULL, node_list_update_callback); free_xml(node_list); if (call_id >= pcmk_ok && crm_peer_cache != NULL && AM_I_DC) { /* * There is no need to update the local CIB with our values if * we've not seen valid membership data */ GHashTableIter iter; crm_node_t *node = NULL; node_list = create_xml_node(NULL, XML_CIB_TAG_STATUS); g_hash_table_iter_init(&iter, crm_peer_cache); while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &node)) { do_update_node_cib(node, flags, node_list, source); } if (crm_remote_peer_cache) { g_hash_table_iter_init(&iter, crm_remote_peer_cache); while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &node)) { do_update_node_cib(node, flags, node_list, source); } } fsa_cib_update(XML_CIB_TAG_STATUS, node_list, call_options, call_id, NULL); fsa_register_cib_callback(call_id, FALSE, NULL, crmd_node_update_complete); last_peer_update = call_id; free_xml(node_list); } } static void cib_quorum_update_complete(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data) { fsa_data_t *msg_data = NULL; if (rc == pcmk_ok) { crm_trace("Quorum update %d complete", call_id); } else { crm_err("Quorum update %d failed: %s (%d)", call_id, pcmk_strerror(rc), rc); crm_log_xml_debug(msg, "failed"); register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL); } } void crm_update_quorum(gboolean quorum, gboolean force_update) { ever_had_quorum |= quorum; if(ever_had_quorum && quorum == FALSE && no_quorum_suicide_escalation) { pcmk_panic(__FUNCTION__); } if (AM_I_DC && (force_update || fsa_has_quorum != quorum)) { int call_id = 0; xmlNode *update = NULL; int call_options = cib_scope_local | cib_quorum_override; update = create_xml_node(NULL, XML_TAG_CIB); crm_xml_add_int(update, XML_ATTR_HAVE_QUORUM, quorum); crm_xml_add(update, XML_ATTR_DC_UUID, fsa_our_uuid); fsa_cib_update(XML_TAG_CIB, update, call_options, call_id, NULL); crm_debug("Updating quorum status to %s (call=%d)", quorum ? "true" : "false", call_id); fsa_register_cib_callback(call_id, FALSE, NULL, cib_quorum_update_complete); free_xml(update); } fsa_has_quorum = quorum; } diff --git a/crmd/te_utils.c b/crmd/te_utils.c index 69c22e3487..312d013458 100644 --- a/crmd/te_utils.c +++ b/crmd/te_utils.c @@ -1,542 +1,546 @@ /* * Copyright (C) 2004 Andrew Beekhof * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include crm_trigger_t *stonith_reconnect = NULL; GListPtr stonith_cleanup_list = NULL; static gboolean fail_incompletable_stonith(crm_graph_t * graph) { GListPtr lpc = NULL; const char *task = NULL; xmlNode *last_action = NULL; if (graph == NULL) { return FALSE; } for (lpc = graph->synapses; lpc != NULL; lpc = lpc->next) { GListPtr lpc2 = NULL; synapse_t *synapse = (synapse_t *) lpc->data; if (synapse->confirmed) { continue; } for (lpc2 = synapse->actions; lpc2 != NULL; lpc2 = lpc2->next) { crm_action_t *action = (crm_action_t *) lpc2->data; if (action->type != action_type_crm || action->confirmed) { continue; } task = crm_element_value(action->xml, XML_LRM_ATTR_TASK); if (task && safe_str_eq(task, CRM_OP_FENCE)) { action->failed = TRUE; last_action = action->xml; update_graph(graph, action); crm_notice("Failing action %d (%s): STONITHd terminated", action->id, ID(action->xml)); } } } if (last_action != NULL) { crm_warn("STONITHd failure resulted in un-runnable actions"); abort_transition(INFINITY, tg_restart, "Stonith failure", last_action); return TRUE; } return FALSE; } static void tengine_stonith_connection_destroy(stonith_t * st, stonith_event_t * e) { if (is_set(fsa_input_register, R_ST_REQUIRED)) { crm_crit("Fencing daemon connection failed"); mainloop_set_trigger(stonith_reconnect); } else { crm_info("Fencing daemon disconnected"); } /* cbchan will be garbage at this point, arrange for it to be reset */ if(stonith_api) { stonith_api->state = stonith_disconnected; } if (AM_I_DC) { fail_incompletable_stonith(transition_graph); trigger_graph(); } } #if SUPPORT_CMAN # include #endif char *te_client_id = NULL; #ifdef HAVE_SYS_REBOOT_H # include # include #endif static void tengine_stonith_notify(stonith_t * st, stonith_event_t * st_event) { if(te_client_id == NULL) { te_client_id = g_strdup_printf("%s.%d", crm_system_name, getpid()); } if (st_event == NULL) { crm_err("Notify data not found"); return; } if (st_event->result == pcmk_ok && safe_str_eq("on", st_event->action)) { crm_notice("%s was successfully unfenced by %s (at the request of %s)", st_event->target, st_event->executioner ? st_event->executioner : "", st_event->origin); /* TODO: Hook up st_event->device */ return; } else if (safe_str_eq("on", st_event->action)) { crm_err("Unfencing of %s by %s failed: %s (%d)", st_event->target, st_event->executioner ? st_event->executioner : "", pcmk_strerror(st_event->result), st_event->result); return; } else if (st_event->result == pcmk_ok && crm_str_eq(st_event->target, fsa_our_uname, TRUE)) { crm_crit("We were allegedly just fenced by %s for %s!", st_event->executioner ? st_event->executioner : "", st_event->origin); /* Dumps blackbox if enabled */ qb_log_fini(); /* Try to get the above log message to disk - somehow */ /* Get out ASAP and do not come back up. * * Triggering a reboot is also not the worst idea either since * the rest of the cluster thinks we're safely down */ #ifdef RB_HALT_SYSTEM reboot(RB_HALT_SYSTEM); #endif /* * If reboot() fails or is not supported, coming back up will * probably lead to a situation where the other nodes set our * status to 'lost' because of the fencing callback and will * discard subsequent election votes with: * * Election 87 (current: 5171, owner: 103): Processed vote from east-03 (Peer is not part of our cluster) * * So just stay dead, something is seriously messed up anyway. * */ exit(100); /* None of our wrappers since we already called qb_log_fini() */ return; } if (st_event->result == pcmk_ok && safe_str_eq(st_event->operation, T_STONITH_NOTIFY_FENCE)) { st_fail_count_reset(st_event->target); } crm_notice("Peer %s was%s terminated (%s) by %s for %s: %s (ref=%s) by client %s", st_event->target, st_event->result == pcmk_ok ? "" : " not", st_event->action, st_event->executioner ? st_event->executioner : "", st_event->origin, pcmk_strerror(st_event->result), st_event->id, st_event->client_origin ? st_event->client_origin : ""); #if SUPPORT_CMAN if (st_event->result == pcmk_ok && is_cman_cluster()) { int local_rc = 0; int confirm = 0; char *target_copy = strdup(st_event->target); /* In case fenced hasn't noticed yet * * Any fencing that has been inititated will be completed by way of the fence_pcmk redirect */ local_rc = fenced_external(target_copy); if (local_rc != 0) { crm_err("Could not notify CMAN that '%s' is now fenced: %d", st_event->target, local_rc); } else { crm_notice("Notified CMAN that '%s' is now fenced", st_event->target); } /* In case fenced is already trying to shoot it */ confirm = open("/var/run/cluster/fenced_override", O_NONBLOCK|O_WRONLY); if (confirm > 0) { int ignore = 0; int len = strlen(target_copy); errno = 0; local_rc = write(confirm, target_copy, len); ignore = write(confirm, "\n", 1); if(ignore < 0 && errno == EBADF) { crm_trace("CMAN not expecting %s to be fenced (yet)", st_event->target); } else if (local_rc < len) { crm_perror(LOG_ERR, "Confirmation of CMAN fencing event for '%s' failed: %d", st_event->target, local_rc); } else { fsync(confirm); crm_notice("Confirmed CMAN fencing event for '%s'", st_event->target); } close(confirm); } free(target_copy); } #endif if (st_event->result == pcmk_ok) { crm_node_t *peer = crm_find_peer_full(0, st_event->target, CRM_GET_PEER_REMOTE | CRM_GET_PEER_CLUSTER); const char *uuid = NULL; gboolean we_are_executioner = safe_str_eq(st_event->executioner, fsa_our_uname); if (peer == NULL) { return; } uuid = crm_peer_uuid(peer); crm_trace("target=%s dc=%s", st_event->target, fsa_our_dc); if(AM_I_DC) { /* The DC always sends updates */ send_stonith_update(NULL, st_event->target, uuid); if (st_event->client_origin && safe_str_neq(st_event->client_origin, te_client_id)) { /* Abort the current transition graph if it wasn't us * that invoked stonith to fence someone */ crm_info("External fencing operation from %s fenced %s", st_event->client_origin, st_event->target); abort_transition(INFINITY, tg_restart, "External Fencing Operation", NULL); } /* Assume it was our leader if we dont currently have one */ } else if (fsa_our_dc == NULL || safe_str_eq(fsa_our_dc, st_event->target)) { crm_notice("Target %s our leader %s (recorded: %s)", fsa_our_dc ? "was" : "may have been", st_event->target, fsa_our_dc ? fsa_our_dc : ""); /* Given the CIB resyncing that occurs around elections, * have one node update the CIB now and, if the new DC is different, * have them do so too after the election */ if (we_are_executioner) { send_stonith_update(NULL, st_event->target, uuid); } stonith_cleanup_list = g_list_append(stonith_cleanup_list, strdup(st_event->target)); } crmd_peer_down(peer, TRUE); } } gboolean te_connect_stonith(gpointer user_data) { int lpc = 0; int rc = pcmk_ok; if (stonith_api == NULL) { stonith_api = stonith_api_new(); } if (stonith_api->state != stonith_disconnected) { crm_trace("Still connected"); return TRUE; } for (lpc = 0; lpc < 30; lpc++) { crm_debug("Attempting connection to fencing daemon..."); sleep(1); rc = stonith_api->cmds->connect(stonith_api, crm_system_name, NULL); if (rc == pcmk_ok) { break; } if (user_data != NULL) { - crm_err("Sign-in failed: triggered a retry"); - mainloop_set_trigger(stonith_reconnect); + if (is_set(fsa_input_register, R_ST_REQUIRED)) { + crm_err("Sign-in failed: triggered a retry"); + mainloop_set_trigger(stonith_reconnect); + } else { + crm_info("Sign-in failed, but no longer required"); + } return TRUE; } crm_err("Sign-in failed: pausing and trying again in 2s..."); sleep(1); } CRM_CHECK(rc == pcmk_ok, return TRUE); /* If not, we failed 30 times... just get out */ stonith_api->cmds->register_notification(stonith_api, T_STONITH_NOTIFY_DISCONNECT, tengine_stonith_connection_destroy); stonith_api->cmds->register_notification(stonith_api, T_STONITH_NOTIFY_FENCE, tengine_stonith_notify); crm_trace("Connected"); return TRUE; } gboolean stop_te_timer(crm_action_timer_t * timer) { const char *timer_desc = "action timer"; if (timer == NULL) { return FALSE; } if (timer->reason == timeout_abort) { timer_desc = "global timer"; crm_trace("Stopping %s", timer_desc); } if (timer->source_id != 0) { crm_trace("Stopping %s", timer_desc); g_source_remove(timer->source_id); timer->source_id = 0; } else { crm_trace("%s was already stopped", timer_desc); return FALSE; } return TRUE; } gboolean te_graph_trigger(gpointer user_data) { enum transition_status graph_rc = -1; if (transition_graph == NULL) { crm_debug("Nothing to do"); return TRUE; } crm_trace("Invoking graph %d in state %s", transition_graph->id, fsa_state2string(fsa_state)); switch (fsa_state) { case S_STARTING: case S_PENDING: case S_NOT_DC: case S_HALT: case S_ILLEGAL: case S_STOPPING: case S_TERMINATE: return TRUE; break; default: break; } if (transition_graph->complete == FALSE) { int limit = transition_graph->batch_limit; transition_graph->batch_limit = throttle_get_total_job_limit(limit); graph_rc = run_graph(transition_graph); transition_graph->batch_limit = limit; /* Restore the configured value */ /* significant overhead... */ /* print_graph(LOG_DEBUG_3, transition_graph); */ if (graph_rc == transition_active) { crm_trace("Transition not yet complete"); return TRUE; } else if (graph_rc == transition_pending) { crm_trace("Transition not yet complete - no actions fired"); return TRUE; } if (graph_rc != transition_complete) { crm_warn("Transition failed: %s", transition_status(graph_rc)); print_graph(LOG_NOTICE, transition_graph); } } crm_debug("Transition %d is now complete", transition_graph->id); transition_graph->complete = TRUE; notify_crmd(transition_graph); return TRUE; } void trigger_graph_processing(const char *fn, int line) { crm_trace("%s:%d - Triggered graph processing", fn, line); mainloop_set_trigger(transition_trigger); } void abort_transition_graph(int abort_priority, enum transition_action abort_action, const char *abort_text, xmlNode * reason, const char *fn, int line) { int add[] = { 0, 0, 0 }; int del[] = { 0, 0, 0 }; int level = LOG_INFO; xmlNode *diff = NULL; xmlNode *change = NULL; CRM_CHECK(transition_graph != NULL, return); switch (fsa_state) { case S_STARTING: case S_PENDING: case S_NOT_DC: case S_HALT: case S_ILLEGAL: case S_STOPPING: case S_TERMINATE: crm_info("Abort %s suppressed: state=%s (complete=%d)", abort_text, fsa_state2string(fsa_state), transition_graph->complete); return; default: break; } /* Make sure any queued calculations are discarded ASAP */ free(fsa_pe_ref); fsa_pe_ref = NULL; if (transition_graph->complete == FALSE) { if(update_abort_priority(transition_graph, abort_priority, abort_action, abort_text)) { level = LOG_NOTICE; } } if(reason) { xmlNode *search = NULL; for(search = reason; search; search = search->parent) { if (safe_str_eq(XML_TAG_DIFF, TYPE(search))) { diff = search; break; } } if(diff) { xml_patch_versions(diff, add, del); for(search = reason; search; search = search->parent) { if (safe_str_eq(XML_DIFF_CHANGE, TYPE(search))) { change = search; break; } } } } if(reason == NULL) { do_crm_log(level, "Transition aborted: %s (source=%s:%d, %d)", abort_text, fn, line, transition_graph->complete); } else if(change == NULL) { char *local_path = xml_get_path(reason); do_crm_log(level, "Transition aborted by %s.%s: %s (cib=%d.%d.%d, source=%s:%d, path=%s, %d)", TYPE(reason), ID(reason), abort_text, add[0], add[1], add[2], fn, line, local_path, transition_graph->complete); free(local_path); } else { const char *kind = NULL; const char *op = crm_element_value(change, XML_DIFF_OP); const char *path = crm_element_value(change, XML_DIFF_PATH); if(change == reason) { if(strcmp(op, "create") == 0) { reason = reason->children; } else if(strcmp(op, "modify") == 0) { reason = first_named_child(reason, XML_DIFF_RESULT); if(reason) { reason = reason->children; } } } kind = TYPE(reason); if(strcmp(op, "delete") == 0) { const char *shortpath = strrchr(path, '/'); do_crm_log(level, "Transition aborted by deletion of %s: %s (cib=%d.%d.%d, source=%s:%d, path=%s, %d)", shortpath?shortpath+1:path, abort_text, add[0], add[1], add[2], fn, line, path, transition_graph->complete); } else if (safe_str_eq(XML_CIB_TAG_NVPAIR, kind)) { do_crm_log(level, "Transition aborted by %s, %s=%s: %s (%s cib=%d.%d.%d, source=%s:%d, path=%s, %d)", crm_element_value(reason, XML_ATTR_ID), crm_element_value(reason, XML_NVPAIR_ATTR_NAME), crm_element_value(reason, XML_NVPAIR_ATTR_VALUE), abort_text, op, add[0], add[1], add[2], fn, line, path, transition_graph->complete); } else if (safe_str_eq(XML_LRM_TAG_RSC_OP, kind)) { const char *magic = crm_element_value(reason, XML_ATTR_TRANSITION_MAGIC); do_crm_log(level, "Transition aborted by %s '%s' on %s: %s (magic=%s, cib=%d.%d.%d, source=%s:%d, %d)", crm_element_value(reason, XML_LRM_ATTR_TASK_KEY), op, crm_element_value(reason, XML_LRM_ATTR_TARGET), abort_text, magic, add[0], add[1], add[2], fn, line, transition_graph->complete); } else if (safe_str_eq(XML_CIB_TAG_STATE, kind) || safe_str_eq(XML_CIB_TAG_NODE, kind)) { const char *uname = crm_peer_uname(ID(reason)); do_crm_log(level, "Transition aborted by %s '%s' on %s: %s (cib=%d.%d.%d, source=%s:%d, %d)", kind, op, uname ? uname : ID(reason), abort_text, add[0], add[1], add[2], fn, line, transition_graph->complete); } else { do_crm_log(level, "Transition aborted by %s.%s '%s': %s (cib=%d.%d.%d, source=%s:%d, path=%s, %d)", TYPE(reason), ID(reason), op?op:"change", abort_text, add[0], add[1], add[2], fn, line, path, transition_graph->complete); } } if (transition_graph->complete) { if (transition_timer->period_ms > 0) { crm_timer_stop(transition_timer); crm_timer_start(transition_timer); } else { register_fsa_input(C_FSA_INTERNAL, I_PE_CALC, NULL); } return; } mainloop_set_trigger(transition_trigger); } diff --git a/cts/HBDummy.in b/cts/HBDummy.in new file mode 100755 index 0000000000..4960dd2572 --- /dev/null +++ b/cts/HBDummy.in @@ -0,0 +1,127 @@ +#!/bin/sh +# +# +# Dummy Heartbeat RA. Does nothing but touch and remove a state file +# +# Copyright (c) 2015 Lars Ellenberg +# +# Based on LSBDummy, +# Copyright (c) 2010 Andrew Beekhof +# All Rights Reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of version 2 of the GNU General Public License as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it would be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# +# Further, this software is distributed without any warranty that it is +# free of the rightful claim of any third person regarding infringement +# or the like. Any license provided herein, whether implied or +# otherwise, applies only to this software file. Patent licenses, if +# any, provided herein do not apply to combinations of this program with +# other software, or any other product whatsoever. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. +# + +####################################################################### +# Initialization: + +desc="Dummy Heartbeat service" +. @OCF_ROOT_DIR@/resource.d/heartbeat/.ocf-directories +: ${HA_VARRUN=/tmp} # Backup in case .ocf-directories doesn't exist + +####################################################################### + +success() +{ + echo -ne "[ OK ]\r" +} + +failure() +{ + echo -ne "[FAILED]\r" +} + +# rpm based distros +if [ -d @sysconfdir@/sysconfig ]; then + [ -f @INITDIR@/functions ] && . @INITDIR@/functions + [ -f @sysconfdir@/sysconfig/pacemaker ] && . @sysconfdir@/sysconfig/pacemaker + [ -z "$LOCK_FILE" ] && LOCK_FILE="@localstatedir@/lock/subsys/pacemaker" +fi + +# deb based distros +if [ -d @sysconfdir@/default ]; then + [ -f @sysconfdir@/default/pacemaker ] && . @sysconfdir@/default/pacemaker + [ -z "$LOCK_FILE" ] && LOCK_FILE="@localstatedir@/lock/pacemaker" +fi + +dummy_usage() { + cat < $cts_root/CTSvars.py class CTSvars: CTS_home="$local_root/cts" Fencing_home="$local_root/fencing" CRM_CONFIG_DIR="/var/lib/pacemaker/cib" CRM_DAEMON_USER="hacluster" CRM_DAEMON_DIR="/usr/libexec/pacemaker" OCF_ROOT_DIR="/usr/lib/ocf" EOF files="extra/cluster-init extra/cluster-helper extra/cluster-clean tools/crm_report.in" for f in $files; do cp $local_root/$f $cts_root/ done cp $local_root/tools/report.common.in $local_root/tools/report.common sed -i.sed s:@localstatedir@:/var: $local_root/tools/report.common cp $cts_root/crm_report.in $cts_root/crm_report sed -i.sed s:@datadir@/@PACKAGE@:$local_root/tools: $cts_root/crm_report chmod +x $cts_root/crm_report cp $cts_root/LSBDummy.in $cts_root/LSBDummy + cp $cts_root/HBDummy.in $cts_root/HBDummy chmod +x $local_root/fencing/fence_* - sed -i.sed s:@OCF_ROOT_DIR@:/usr/lib/ocf: $cts_root/LSBDummy + sed -i.sed s:@OCF_ROOT_DIR@:/usr/lib/ocf: $cts_root/LSBDummy $cts_root/HBDummy echo "Make sure you add $cts_root to your PATH and set a value for \$cluster_name in .bashrc" exit 0 ;; --wget) files="cluster-helper cluster-clean" for f in $files; do rm -f $cts_root/$f echo "Downloading helper script $f from GitHub" wget -O $cts_root/$f https://raw.github.com/ClusterLabs/pacemaker/master/extra/$f chmod +x $cts_root/$f done shift ;; --) shift; tests="$tests $*"; break;; "") break;; *) echo "Unknown argument: $1"; exit 1;; esac done # Add the location of this script export PATH="$PATH:$cts_root" which cluster-helper &>/dev/null if [ $? != 0 ]; then echo $0 needs the cluster-helper script to be in your path echo You can obtain it from: https://raw.github.com/ClusterLabs/pacemaker/master/extra/cluster-helper exit 1 fi which cluster-clean &>/dev/null if [ $? != 0 ]; then echo $0 needs the cluster-clean script to be in your path echo You can obtain it from: https://raw.github.com/ClusterLabs/pacemaker/master/extra/cluster-clean exit 1 fi if [ "x$cluster_name" = x -o "x$cluster_name" = xpick ]; then clusters=`ls -1 ~/.dsh/group/[a-z]+[0-9] | sed s/.*group.// | tr '\n' ' ' ` echo "custom) interactively define a cluster" for i in $clusters; do echo "$i) `cluster-helper --list short -g $i`" done read -p "Choose a cluster [custom]: " cluster_name echo fi if [ -z $cluster_name ]; then cluster_name=custom fi case $cluster_name in *) cluster_hosts=`cluster-helper --list short -g $cluster_name` cluster_log=~/cluster-$cluster_name.log; ;; custom) read -p "Cluster name: " cluster_name read -p "Cluster hosts: " cluster_hosts read -p "Cluster log file: " cluster_log ;; esac if [ x$cmd != x ]; then config=/etc/sysconfig/pacemaker case $cmd in trace-ls|tls) cluster-helper -g $cluster_name -- grep PCMK_trace_functions $config ;; trace-add|tadd) echo "Adding $trace to PCMK_trace_functions" cluster-helper -g $cluster_name -- sed -i "s/.*PCMK_trace_functions=/PCMK_trace_functions=$trace,/" $config ;; trace-rm|trm) echo "Removing $trace from PCMK_trace_functions" cluster-helper -g $cluster_name -- sed -i "s/.*PCMK_trace_functions=\\\\\\(.*\\\\\\)$trace,\\\\\\(.*\\\\\\)/PCMK_trace_functions=\\\\\\1\\\\\\2/" $config ;; trace-set|tset) echo "Setting PCMK_trace_functions to '$trace'" cluster-helper -g $cluster_name -- sed -i "s/.*PCMK_trace_functions.*/PCMK_trace_functions=$trace/" $config ;; esac exit 0 fi if [ $build = 1 -a $run = 1 ]; then install=1 clean=1 fi if [ $build = 1 ]; then which build-pcmk if [ $? != 0 ]; then echo "You'll need to write/obtain build-pcmk in order to build pacemaker from here. Skipping" else build-pcmk r7 rc=$? if [ $rc != 0 ]; then echo "Build failed: $rc" exit $rc fi fi fi if [ $clean = 1 ]; then rm -f $cluster_log; cluster-clean -g $cluster_name --kill elif [ $kill = 1 ]; then cluster-clean -g $cluster_name --kill-only exit 0 fi if [ $install = 1 ]; then cluster-helper -g $cluster_name -- yum install -y pacemaker pacemaker-debuginfo pacemaker-cts libqb libqb-debuginfo fi if [ $boot = 1 ]; then $cts_root/CTSlab.py -r -c -g $cluster_name --boot rc=$? if [ $rc = 0 ]; then echo "The cluster is ready..." fi exit $rc elif [ $run = 1 ]; then $cts_root/CTSlab.py -r -c -g $cluster_name 500 $* exit $? elif [ $setup = 1 ]; then cluster-init -g $cluster_name $target -u --test exit 0 elif [ $clean = 1 ]; then exit 0 fi screen -ls | grep cts-$cluster_name &>/dev/null active=$? if [ ! -z $custom_log ]; then cluster_log=$custom_log fi if [ "x$tests" != x -a "x$tests" != "x " ]; then for t in $tests; do echo "crm_report --cts-log $cluster_log -d -T $t" crm_report --cts-log $cluster_log -d -T $t done elif [ $logfile = 1 ]; then echo $cluster_log elif [ $summary = 1 ]; then files=$cluster_log if [ $saved = 1 ]; then files=`ls -1tr ~/CTS-*/cluster-log.txt` fi for f in $files; do echo $f case $verbose in 0) cat -n $f | grep $patterns | grep -v "CTS: debug:" ;; 1) cat -n $f | grep $patterns | grep -v "CTS:.* cmd:" ;; *) cat -n $f | grep $patterns ;; esac echo "" done elif [ $watch = 1 ]; then case $verbose in 0) tail -F $cluster_log | grep $patterns | grep -v "CTS: debug:" ;; 1) tail -F $cluster_log | grep $patterns | grep -v "CTS:.* cmd:" ;; *) tail -F $cluster_log | grep $patterns ;; esac elif [ $active = 0 ]; then screen -x cts-$cluster_name else touch $cluster_log # . ~/.bashrc # . $BASH_FILES/.heartbeat export cluster_name cluster_hosts cluster_log screen -S cts-$cluster_name bash fi diff --git a/doc/Clusters_from_Scratch/ro-RO/Ch-Apache.po b/doc/Clusters_from_Scratch/ro-RO/Ch-Apache.po index 6032e87383..228390d3e9 100644 --- a/doc/Clusters_from_Scratch/ro-RO/Ch-Apache.po +++ b/doc/Clusters_from_Scratch/ro-RO/Ch-Apache.po @@ -1,1186 +1,1186 @@ # # AUTHOR , YEAR. # msgid "" msgstr "" "Project-Id-Version: Clusters from Scratch 1.1\n" "POT-Creation-Date: 2012-10-17T05:19:03\n" "PO-Revision-Date: 2011-11-24 00:51+0200\n" "Last-Translator: Dan Frîncu \n" "Language-Team: None\n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: application/x-publican; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #. Tag: title #, no-c-format msgid "Apache - Adding More Services" msgstr "Apache - Adăugarea mai Multor Servicii" #. Tag: title #, no-c-format msgid "Forward" msgstr "" #. Tag: para #, fuzzy, no-c-format msgid "Now that we have a basic but functional active/passive two-node cluster, we’re ready to add some real services. We’re going to start with Apache because its a feature of many clusters and relatively simple to configure." msgstr "Acum că avem un cluster de bază, funcÈ›ional, activ/pasiv format din două noduri, suntem pregătiÈ›i să adăugăm câteva servicii reale. O să începem cu Apache deoarece este o caracteristică a multor clustere È™i este relativ simplu de configurat." #. Tag: title #, no-c-format msgid "Installation" msgstr "Instalare" #. Tag: para #, fuzzy, no-c-format msgid "Before continuing, we need to make sure Apache is installed on both hosts. We also need the wget tool in order for the cluster to be able to check the status of the Apache server." msgstr "De asemenea, avem nevoie de utilitarul wget pentru ca È™i clusterul să fie capabil să verifice status-ul serverului Apache." #. Tag: programlisting #, no-c-format msgid "# yum install -y httpd wget" msgstr "" #. Tag: literallayout #, no-c-format msgid "" "Loaded plugins: langpacks, presto, refresh-packagekit\n" "fedora/metalink | 2.6 kB 00:00\n" "updates/metalink | 3.2 kB 00:00\n" "updates-testing/metalink | 41 kB 00:00\n" "Resolving Dependencies\n" "--> Running transaction check\n" "---> Package httpd.x86_64 0:2.2.22-3.fc17 will be installed\n" "--> Processing Dependency: httpd-tools = 2.2.22-3.fc17 for package: httpd-2.2.22-3.fc17.x86_64\n" "--> Processing Dependency: apr-util-ldap for package: httpd-2.2.22-3.fc17.x86_64\n" "--> Processing Dependency: libaprutil-1.so.0()(64bit) for package: httpd-2.2.22-3.fc17.x86_64\n" "--> Processing Dependency: libapr-1.so.0()(64bit) for package: httpd-2.2.22-3.fc17.x86_64\n" "--> Running transaction check\n" "---> Package apr.x86_64 0:1.4.6-1.fc17 will be installed\n" "---> Package apr-util.x86_64 0:1.4.1-2.fc17 will be installed\n" "---> Package apr-util-ldap.x86_64 0:1.4.1-2.fc17 will be installed\n" "---> Package httpd-tools.x86_64 0:2.2.22-3.fc17 will be installed\n" "--> Finished Dependency Resolution\n" "\n" "Dependencies Resolved\n" "\n" "=====================================================================================\n" " Package Arch Version Repository Size\n" "=====================================================================================\n" "Installing:\n" " httpd x86_64 2.2.22-3.fc17 updates-testing 823 k\n" " wget x86_64 1.13.4-2.fc17 fedora 495 k\n" "Installing for dependencies:\n" " apr x86_64 1.4.6-1.fc17 fedora 99 k\n" " apr-util x86_64 1.4.1-2.fc17 fedora 78 k\n" " apr-util-ldap x86_64 1.4.1-2.fc17 fedora 17 k\n" " httpd-tools x86_64 2.2.22-3.fc17 updates-testing 74 k\n" "\n" "Transaction Summary\n" "=====================================================================================\n" "Install 1 Package (+4 Dependent packages)\n" "\n" "Total download size: 1.1 M\n" "Installed size: 3.5 M\n" "Downloading Packages:\n" "(1/6): apr-1.4.6-1.fc17.x86_64.rpm | 99 kB 00:00\n" "(2/6): apr-util-1.4.1-2.fc17.x86_64.rpm | 78 kB 00:00\n" "(3/6): apr-util-ldap-1.4.1-2.fc17.x86_64.rpm | 17 kB 00:00\n" "(4/6): httpd-2.2.22-3.fc17.x86_64.rpm | 823 kB 00:01\n" "(5/6): httpd-tools-2.2.22-3.fc17.x86_64.rpm | 74 kB 00:00\n" "(6/6): wget-1.13.4-2.fc17.x86_64.rpm | 495 kB 00:01\n" "-------------------------------------------------------------------------------------\n" "Total 238 kB/s | 1.1 MB 00:04\n" "Running Transaction Check\n" "Running Transaction Test\n" "Transaction Test Succeeded\n" "Running Transaction\n" " Installing : apr-1.4.6-1.fc17.x86_64 1/6\n" " Installing : apr-util-1.4.1-2.fc17.x86_64 2/6\n" " Installing : apr-util-ldap-1.4.1-2.fc17.x86_64 3/6\n" " Installing : httpd-tools-2.2.22-3.fc17.x86_64 4/6\n" " Installing : httpd-2.2.22-3.fc17.x86_64 5/6\n" " Installing : wget-1.13.4-2.fc17.x86_64 6/6\n" " Verifying : apr-util-ldap-1.4.1-2.fc17.x86_64 1/6\n" " Verifying : httpd-tools-2.2.22-3.fc17.x86_64 2/6\n" " Verifying : apr-util-1.4.1-2.fc17.x86_64 3/6\n" " Verifying : apr-1.4.6-1.fc17.x86_64 4/6\n" " Verifying : httpd-2.2.22-3.fc17.x86_64 5/6\n" " Verifying : wget-1.13.4-2.fc17.x86_64 6/6\n" "\n" "Installed:\n" " httpd.x86_64 0:2.2.22-3.fc17 wget.x86_64 0:1.13.4-2.fc17\n" "\n" "Dependency Installed:\n" " apr.x86_64 0:1.4.6-1.fc17 apr-util.x86_64 0:1.4.1-2.fc17\n" " apr-util-ldap.x86_64 0:1.4.1-2.fc17 httpd-tools.x86_64 0:2.2.22-3.fc17\n" "\n" "Complete!" msgstr "" #. Tag: title #, no-c-format msgid "Preparation" msgstr "Pregătire" #. Tag: para #, no-c-format msgid "First we need to create a page for Apache to serve up. On Fedora the default Apache docroot is /var/www/html, so we’ll create an index file there." msgstr "Mai întâi trebuie să creem o pagină pe care Apache să o servească. Pe Fedora docroot-ul implicit al Apache-ului este în /var/www/html, aÈ™a că vom crea un fiÈ™ier index acolo." #. Tag: programlisting #, fuzzy, no-c-format msgid "" "# cat <<-END >/var/www/html/index.html\n" " <html>\n" " <body>My Test Site - pcmk-1</body>\n" " </html>\n" "END" msgstr "" "\n" "[root@pcmk-1 ~]# cat <<-END >/var/www/html/index.html\n" " <html>\n" " <body>My Test Site - pcmk-1</body>\n" " </html>\n" " END\n" "[root@pcmk-1 ~]#\n" #. Tag: para #, no-c-format msgid "For the moment, we will simplify things by serving up only a static site and manually sync the data between the two nodes. So run the command again on pcmk-2." msgstr "Pentru moment, vom simplifica lucrurile servind doar un site static È™i vom sincroniza manual datele între cele două noduri. AÈ™a că rulaÈ›i comanda din nou pe pcmk-2." #. Tag: programlisting #, fuzzy, no-c-format msgid "" "[root@pcmk-2 ~]# cat <<-END >/var/www/html/index.html <html>\n" " <body>My Test Site - pcmk-2</body>\n" " </html>\n" " END" msgstr "" "\n" "[root@pcmk-2 ~]# cat <<-END >/var/www/html/index.html\n" " <html>\n" " <body>My Test Site - pcmk-2</body>\n" " </html>\n" " END\n" "[root@pcmk-2 ~]#\n" #. Tag: title #, no-c-format msgid "Enable the Apache status URL" msgstr "ActivaÈ›i status URL-ul Apache-ului" #. Tag: para #, fuzzy, no-c-format msgid "In order to monitor the health of your Apache instance, and recover it if it fails, the resource agent used by Pacemaker assumes the server-status URL is available. Look for the following in /etc/httpd/conf/httpd.conf and make sure it is not disabled or commented out:" msgstr "Pentru a monitoriza sănătatea instanÈ›ei voastre de Apache È™i pentru a o recupera dacă eÈ™uează, agentul de resursă folosit de Pacemaker presupune că URL-ul server-status este disponibil. UitaÈ›i-vă după următoarele în /etc/httpd/conf/httpd.conf È™i asiguraÈ›i-vă că nu este dezactivat sau comentat." #. Tag: programlisting #, fuzzy, no-c-format msgid "" "<Location /server-status>\n" " SetHandler server-status\n" " Order deny,allow\n" " Deny from all\n" " Allow from 127.0.0.1\n" "</Location>" msgstr "" "\n" "<Location /server-status>\n" " SetHandler server-status\n" " Order deny,allow\n" " Deny from all\n" " Allow from 127.0.0.1\n" "</Location>\n" "\t " #. Tag: title #, no-c-format msgid "Update the Configuration" msgstr "Actualizarea ConfiguraÈ›iei" #. Tag: para #, fuzzy, no-c-format msgid "At this point, Apache is ready to go, all that needs to be done is to add it to the cluster. Lets call the resource WebSite. We need to use an OCF script called apache in the heartbeat namespace Compare the key used here ocf:heartbeat:apache with the one we used earlier for the IP address: ocf:heartbeat:IPaddr2 , the only required parameter is the path to the main Apache configuration file and we’ll tell the cluster to check once a minute that apache is still running." -msgstr "La acest punct, Apache este gata de pornire, tot ce trebuie făcut este să îl adăugăm la cluster. Să denumim resursa WebSite. Avem nevoie să folosim un script OCF numit apache din namespace-ul ComparaÈ›i cheia folosită aici, ocf:heartbeart:apache, cu cea folosită anterior pentru adresa IP: ocf:heartbeat:IPaddr2 heartbeat, singurul parametru necesar este calea către fiÈ™ierul principal de configurare al Apache È™i vom spune clusterului să verifice o dată pe minut că apache încă funcÈ›ionează." +msgstr "La acest punct, Apache este gata de pornire, tot ce trebuie făcut este să îl adăugăm la cluster. Să denumim resursa WebSite. Avem nevoie să folosim un script OCF numit apache din namespace-ul ComparaÈ›i cheia folosită aici, ocf:heartbeat:apache, cu cea folosită anterior pentru adresa IP: ocf:heartbeat:IPaddr2 heartbeat, singurul parametru necesar este calea către fiÈ™ierul principal de configurare al Apache È™i vom spune clusterului să verifice o dată pe minut că apache încă funcÈ›ionează." #. Tag: screen #, no-c-format msgid "" "pcs resource create WebSite ocf:heartbeat:apache \\\n" " configfile=/etc/httpd/conf/httpd.conf \\\n" " statusurl=\"http://localhost/server-status\" op monitor interval=1min" msgstr "" #. Tag: para #, no-c-format msgid "By default, the operation timeout for all resource’s start, stop, and monitor operations is 20 seconds. In many cases this timeout period is less than the advised timeout period. For the purposes of this tutorial, we will adjust the global operation timeout default to 240 seconds." msgstr "" #. Tag: programlisting #, no-c-format msgid "" "# pcs resource op defaults timeout=240s\n" "# pcs resource op defaults\n" "timeout: 240s" msgstr "" #. Tag: para #, no-c-format msgid "After a short delay, we should see the cluster start apache" msgstr "După o scurtă întârziere, ar trebui să vedem clusterul pornind apache-ul" #. Tag: programlisting #, fuzzy, no-c-format msgid "" "# pcs status\n" "\n" "Last updated: Fri Sep 14 10:51:27 2012\n" "Last change: Fri Sep 14 10:50:46 2012 via crm_attribute on pcmk-1\n" "Stack: corosync\n" "Current DC: pcmk-2 (2) - partition with quorum\n" "Version: 1.1.8-1.el7-60a19ed12fdb4d5c6a6b6767f52e5391e447fec0\n" "2 Nodes configured, unknown expected votes\n" "2 Resources configured.\n" "\n" "Online: [ pcmk-1 pcmk-2 ]\n" "\n" "Full list of resources:\n" "\n" " ClusterIP (ocf::heartbeat:IPaddr2): Started pcmk-2\n" " WebSite (ocf::heartbeat:apache): Started pcmk-1" msgstr "" "\n" "[root@pcmk-1 ~]# crm_mon\n" "============\n" "Last updated: Fri Aug 28 16:12:49 2009\n" "Stack: openais\n" "Current DC: pcmk-2 - partition with quorum\n" "Version: 1.1.5-bdd89e69ba545404d02445be1f3d72e6a203ba2f\n" "2 Nodes configured, 2 expected votes\n" "2 Resources configured.\n" "============\n" "\n" "Online: [ pcmk-1 pcmk-2 ]\n" "\n" "ClusterIP        (ocf::heartbeat:IPaddr):        Started pcmk-2\n" "WebSite        (ocf::heartbeat:apache):        Started pcmk-1\n" #. Tag: para #, no-c-format msgid "Wait a moment, the WebSite resource isn’t running on the same host as our IP address!" msgstr "AÈ™teptaÈ›i un moment, resursa WebSite nu rulează pe aceeaÈ™i gazdă ca È™i adresa noastră IP!" #. Tag: para #, no-c-format msgid "If, in the pcs status output, you see the WebSite resource has failed to start, then you’ve likely not enabled the status URL correctly. You can check if this is the problem by running:" msgstr "" #. Tag: literallayout #, no-c-format msgid "wget http://127.0.0.1/server-status" msgstr "" #. Tag: para #, no-c-format msgid "If you see Connection refused in the output, then this is indeed the problem. Check to ensure that Allow from 127.0.0.1 is present for the <Location /server-status> block." msgstr "" #. Tag: title #, no-c-format msgid "Ensuring Resources Run on the Same Host" msgstr "Asigurarea că Resursele Rulează pe AceeaÈ™i Gazdă" #. Tag: para #, no-c-format msgid "To reduce the load on any one machine, Pacemaker will generally try to spread the configured resources across the cluster nodes. However we can tell the cluster that two resources are related and need to run on the same host (or not at all). Here we instruct the cluster that WebSite can only run on the host that ClusterIP is active on." msgstr "Pentru a reduce nivelul de încărcare pe oricare din maÈ™ini, Pacemaker va încerca în mod general să împrăștie resursele configurate de-a lungul nodurilor din cluster. TotuÈ™i putem spune clusterului că două resurse au legătura una cu cealaltă È™i trebuie să ruleze pe aceeaÈ™i gazdă (sau să nu ruleze deloc). Aici instruim clusterul că WebSite poate rula numar pe o gazdă pe care este activ ClusterIP." #. Tag: para #, no-c-format msgid "To achieve this we use a colocation constraint that indicates it is mandatory for WebSite to run on the same node as ClusterIP. The \"mandatory\" part of the colocation constraint is indicated by using a score of INFINITY. The INFINITY score also means that if ClusterIP is not active anywhere, WebSite will not be permitted to run." msgstr "" #. Tag: para #, no-c-format msgid "If ClusterIP is not active anywhere, WebSite will not be permitted to run anywhere." msgstr "Dacă ClusterIP nu este activ nicăieri, lui WebSite nu i se va permite să ruleze nicăieri." #. Tag: para #, fuzzy, no-c-format msgid "Colocation constraints are \"directional\", in that they imply certain things about the order in which the two resources will have a location chosen. In this case we’re saying WebSite needs to be placed on the same machine as ClusterIP, this implies that we must know the location of ClusterIP before choosing a location for WebSite." msgstr "RestricÈ›iile de colocare sunt \"direcÈ›ionale\", în sensul că implică anumite lucruri despre ordinea în care celor două resurse li se va alege o locaÈ›ie. ÃŽn acest caz spunem că WebSite are nevoie să fie plasat pe aceeaÈ™i maÈ™ină ca È™i ClusterIP, acest lucru implică faptul că noi trebuie să È™tim locaÈ›ia lui ClusterIP înainte de a alege o locaÈ›ie pentru WebSite." #. Tag: programlisting #, no-c-format msgid "" "# pcs constraint colocation add WebSite ClusterIP INFINITY\n" "# pcs constraint\n" "Location Constraints:\n" "Ordering Constraints:\n" "Colocation Constraints:\n" " WebSite with ClusterIP\n" "# pcs status\n" "\n" "Last updated: Fri Sep 14 11:00:44 2012\n" "Last change: Fri Sep 14 11:00:25 2012 via cibadmin on pcmk-1\n" "Stack: corosync\n" "Current DC: pcmk-2 (2) - partition with quorum\n" "Version: 1.1.8-1.el7-60a19ed12fdb4d5c6a6b6767f52e5391e447fec0\n" "2 Nodes configured, unknown expected votes\n" "2 Resources configured.\n" "\n" "Online: [ pcmk-1 pcmk-2 ]\n" "\n" "Full list of resources:\n" "\n" " ClusterIP (ocf::heartbeat:IPaddr2): Started pcmk-2\n" " WebSite (ocf::heartbeat:apache): Started pcmk-2" msgstr "" #. Tag: title #, no-c-format msgid "Controlling Resource Start/Stop Ordering" msgstr "Controlarea Ordinii de Pornire/Oprire a Resursei" #. Tag: para #, fuzzy, no-c-format msgid "When Apache starts, it binds to the available IP addresses. It doesn’t know about any addresses we add afterwards, so not only do they need to run on the same node, but we need to make sure ClusterIP is already active before we start WebSite. We do this by adding an ordering constraint." msgstr "Când porneÈ™te Apache, se ataÈ™ează de adresa IP disponibilă. Nu È™tie de alte adrese pe care le adăugăm ulterior, aÈ™a nu trebuie doar să ruleze pe acelaÈ™i nod, dar trebuie să ne asigurăm că ClusterIP este activ deja înainte să pornim WebSite. Realizăm acest lucru prin adăugarea unei restricÈ›ii de ordonare. Trebuie să îi dăm un nume (alegeÈ›i ceva descriptiv precum apache-after-ip), să indicăm faptul că este obligatorie (astfel încât orice recuperare a ClusterIP va declanÈ™a recuperarea WebSite-ului) È™i să listăm cele două resurse în ordinea în care avem nevoie să le pornim." #. Tag: para #, no-c-format msgid "By default all order constraints are mandatory constraints unless otherwise configured. This means that the recovery of ClusterIP will also trigger the recovery of WebSite." msgstr "" #. Tag: programlisting #, no-c-format msgid "" "# pcs constraint order ClusterIP then WebSite\n" "Adding ClusterIP WebSite (kind: Mandatory) (Options: first-action=start then-action=start)\n" "# pcs constraint\n" "Location Constraints:\n" "Ordering Constraints:\n" " start ClusterIP then start WebSite\n" "Colocation Constraints:\n" " WebSite with ClusterIP" msgstr "" #. Tag: title #, no-c-format msgid "Specifying a Preferred Location" msgstr "Specificarea unei LocaÈ›ii Preferate" #. Tag: para #, fuzzy, no-c-format msgid "Pacemaker does not rely on any sort of hardware symmetry between nodes, so it may well be that one machine is more powerful than the other. In such cases it makes sense to host the resources there if it is available. To do this we create a location constraint." msgstr "Pacemaker nu se bazează pe nici un fel de simetrie hardware între noduri, aÈ™a că ar putea foarte bine ca o maÈ™ină să fie mai puternică decât cealaltă. ÃŽn astfel de cazuri are logică să găzduim resursele acolo dacă este disponibilă. Pentru a face acest lucru creăm o restricÈ›ie de locaÈ›ie. Din nou îi dăm un nume descriptiv (prefer-pcmk-1), specificăm resursa pe care vrem să o rulăm acolo (WebSite), cât de mult am dori ca aceasta să ruleze acolo (vom folosi 50 momentan, dar într-o situaÈ›ie cu două noduri aproape orice valoare mai mare ca 0 este suficientă) È™i numele gazdei." #. Tag: para #, no-c-format msgid "In the location constraint below, we are saying the WebSite resource prefers the node pcmk-1 with a score of 50. The score here indicates how badly we’d like the resource to run somewhere." msgstr "" #. Tag: programlisting #, no-c-format msgid "" "# pcs constraint location WebSite prefers pcmk-1=50\n" "# pcs constraint\n" "Location Constraints:\n" " Resource: WebSite\n" " Enabled on: pcmk-1 (score:50)\n" "Ordering Constraints:\n" " start ClusterIP then start WebSite\n" "Colocation Constraints:\n" " WebSite with ClusterIP\n" "# pcs status\n" "Last updated: Fri Sep 14 11:06:37 2012\n" "Last change: Fri Sep 14 11:06:26 2012 via cibadmin on pcmk-1\n" "Stack: corosync\n" "Current DC: pcmk-2 (2) - partition with quorum\n" "Version: 1.1.8-1.el7-60a19ed12fdb4d5c6a6b6767f52e5391e447fec0\n" "2 Nodes configured, unknown expected votes\n" "2 Resources configured.\n" "\n" "Online: [ pcmk-1 pcmk-2 ]\n" "\n" "Full list of resources:\n" "\n" " ClusterIP (ocf::heartbeat:IPaddr2): Started pcmk-2\n" " WebSite (ocf::heartbeat:apache): Started pcmk-2" msgstr "" #. Tag: para #, no-c-format msgid "Wait a minute, the resources are still on pcmk-2!" msgstr "AÈ™teptaÈ›i o clipă, resursele sunt încă pe pcmk-2!" #. Tag: para #, no-c-format msgid "Even though we now prefer pcmk-1 over pcmk-2, that preference is (intentionally) less than the resource stickiness (how much we preferred not to have unnecessary downtime)." msgstr "Chiar dacă acum preferăm pcmk-1 în favoarea pcmk-2, această preferință este (în mod intenÈ›ionat) mai mică decât adezivitatea resursei (cât de mult am preferat să nu avem nefuncÈ›ionare inutilă)." #. Tag: para #, fuzzy, no-c-format msgid "To see the current placement scores, you can use a tool called crm_simulate" msgstr "Pentru a vedea scorurile curente de plasament, puteÈ›i folosi un utilitar numit ptest" #. Tag: programlisting #, no-c-format msgid "" "# crm_simulate -sL\n" "Current cluster status:\n" "Online: [ pcmk-1 pcmk-2 ]\n" "\n" " ClusterIP (ocf:heartbeat:IPaddr2): Started pcmk-2\n" " WebSite (ocf:heartbeat:apache): Started pcmk-2\n" "\n" "Allocation scores:\n" "native_color: ClusterIP allocation score on pcmk-1: 50\n" "native_color: ClusterIP allocation score on pcmk-2: 200\n" "native_color: WebSite allocation score on pcmk-1: -INFINITY\n" "native_color: WebSite allocation score on pcmk-2: 100\n" "\n" "Transition Summary:" msgstr "" #. Tag: title #, no-c-format msgid "Manually Moving Resources Around the Cluster" msgstr "Mutarea Manuală a Resurselor Prin Jurul Clusterului" #. Tag: para #, fuzzy, no-c-format msgid "There are always times when an administrator needs to override the cluster and force resources to move to a specific location. By updating our previous location constraint with a score of INFINITY, WebSite will be forced to move to pcmk-1." msgstr "Sunt întotdeauna momente când un administrator are nevoie să preia controlul clusterului È™i să forÈ›eze resursele să se mute într-o locaÈ›ie specifică. Dedesupt folosim restricÈ›ii de locaÈ›ie precum cea pe care am creat-o mai sus, dar în mod fericit nu trebuie să vă pese. Doar furnizaÈ›i numele resursei È™i locaÈ›ia dorită, iar noi vom face restul." #. Tag: programlisting #, no-c-format msgid "" "# pcs constraint location WebSite prefers pcmk-1=INFINITY\n" "# pcs constraint all\n" "Location Constraints:\n" " Resource: WebSite\n" " Enabled on: pcmk-1 (score:INFINITY) (id:location-WebSite-pcmk-1-INFINITY)\n" "Ordering Constraints:\n" " start ClusterIP then start WebSite (Mandatory) (id:order-ClusterIP-WebSite-mandatory)\n" "Colocation Constraints:\n" " WebSite with ClusterIP (INFINITY) (id:colocation-WebSite-ClusterIP-INFINITY)\n" "# pcs status\n" "\n" "Last updated: Fri Sep 14 11:16:26 2012\n" "Last change: Fri Sep 14 11:16:18 2012 via cibadmin on pcmk-1\n" "Stack: corosync\n" "Current DC: pcmk-2 (2) - partition with quorum\n" "Version: 1.1.8-1.el7-60a19ed12fdb4d5c6a6b6767f52e5391e447fec0\n" "2 Nodes configured, unknown expected votes\n" "2 Resources configured.\n" "\n" "Online: [ pcmk-1 pcmk-2 ]\n" "\n" "Full list of resources:\n" "\n" " ClusterIP (ocf::heartbeat:IPaddr2): Started pcmk-1\n" " WebSite (ocf::heartbeat:apache): Started pcmk-1" msgstr "" #. Tag: title #, no-c-format msgid "Giving Control Back to the Cluster" msgstr "Returnarea Controlului ÃŽnapoi Clusterului" #. Tag: para #, no-c-format msgid "Once we’ve finished whatever activity that required us to move the resources to pcmk-1, in our case nothing, we can then allow the cluster to resume normal operation with the unmove command. Since we previously configured a default stickiness, the resources will remain on pcmk-1." msgstr "Odată ce am terminat oricare activitate ce ne-a cerut să mutăm resursele pe pcmk-1, în cazul nostru nimic, putem mai apoi să permitem clusterului să reia operaÈ›iunile normale prin comanda unmove. Din moment ce am configurat anterior o adezivitate implicită, resursele vor rămâne pe pcmk-1." #. Tag: programlisting #, no-c-format msgid "" "# pcs constraint all\n" "Location Constraints:\n" " Resource: WebSite\n" " Enabled on: pcmk-1 (score:INFINITY) (id:location-WebSite-pcmk-1-INFINITY)\n" "Ordering Constraints:\n" " start ClusterIP then start WebSite (Mandatory) (id:order-ClusterIP-WebSite-mandatory)\n" "Colocation Constraints:\n" " WebSite with ClusterIP (INFINITY) (id:colocation-WebSite-ClusterIP-INFINITY)\n" "# pcs constraint rm location-WebSite-pcmk-1-INFINITY\n" "# pcs constraint\n" "Location Constraints:\n" "Ordering Constraints:\n" " start ClusterIP then start WebSite\n" "Colocation Constraints:\n" " WebSite with ClusterIP" msgstr "" #. Tag: para #, fuzzy, no-c-format msgid "Note that the constraint is now gone. If we check the cluster status, we can also see that as expected the resources are still active on pcmk-1." msgstr "ObservaÈ›i că restricÈ›ia automată acum nu mai există. Dacă verificăm status-ul clusterului, putem vedea că aÈ™a cum ne aÈ™teptam resursele sunt în continuare active pe pcmk-1." #. Tag: programlisting #, fuzzy, no-c-format msgid "" "# pcs status\n" "\n" "Last updated: Fri Sep 14 11:57:12 2012\n" "Last change: Fri Sep 14 11:57:03 2012 via cibadmin on pcmk-1\n" "Stack: corosync\n" "Current DC: pcmk-2 (2) - partition with quorum\n" "Version: 1.1.8-1.el7-60a19ed12fdb4d5c6a6b6767f52e5391e447fec0\n" "2 Nodes configured, unknown expected votes\n" "2 Resources configured.\n" "\n" "Online: [ pcmk-1 pcmk-2 ]\n" "\n" "Full list of resources:\n" "\n" " ClusterIP (ocf::heartbeat:IPaddr2): Started pcmk-1\n" " WebSite (ocf::heartbeat:apache): Started pcmk-1" msgstr "" "\n" "[root@pcmk-1 ~]# crm_mon\n" "============\n" "Last updated: Fri Aug 28 16:12:49 2009\n" "Stack: openais\n" "Current DC: pcmk-2 - partition with quorum\n" "Version: 1.1.5-bdd89e69ba545404d02445be1f3d72e6a203ba2f\n" "2 Nodes configured, 2 expected votes\n" "2 Resources configured.\n" "============\n" "\n" "Online: [ pcmk-1 pcmk-2 ]\n" "\n" "ClusterIP        (ocf::heartbeat:IPaddr):        Started pcmk-2\n" "WebSite        (ocf::heartbeat:apache):        Started pcmk-1\n" #~ msgid "Before continuing, we need to make sure Apache is installed on both hosts." #~ msgstr "ÃŽnainte de a continua, trebuie să ne asigurăm că Apache este înstalat pe ambele gazde." #~ msgid "" #~ "\n" #~ "[root@ppcmk-1 ~]# yum install -y httpd\n" #~ "Setting up Install Process\n" #~ "Resolving Dependencies\n" #~ "--> Running transaction check\n" #~ "---> Package httpd.x86_64 0:2.2.13-2.fc12 set to be updated\n" #~ "--> Processing Dependency: httpd-tools = 2.2.13-2.fc12 for package: httpd-2.2.13-2.fc12.x86_64\n" #~ "--> Processing Dependency: apr-util-ldap for package: httpd-2.2.13-2.fc12.x86_64\n" #~ "--> Processing Dependency: /etc/mime.types for package: httpd-2.2.13-2.fc12.x86_64\n" #~ "--> Processing Dependency: libaprutil-1.so.0()(64bit) for package: httpd-2.2.13-2.fc12.x86_64\n" #~ "--> Processing Dependency: libapr-1.so.0()(64bit) for package: httpd-2.2.13-2.fc12.x86_64\n" #~ "--> Running transaction check\n" #~ "---> Package apr.x86_64 0:1.3.9-2.fc12 set to be updated\n" #~ "---> Package apr-util.x86_64 0:1.3.9-2.fc12 set to be updated\n" #~ "---> Package apr-util-ldap.x86_64 0:1.3.9-2.fc12 set to be updated\n" #~ "---> Package httpd-tools.x86_64 0:2.2.13-2.fc12 set to be updated\n" #~ "---> Package mailcap.noarch 0:2.1.30-1.fc12 set to be updated\n" #~ "--> Finished Dependency Resolution\n" #~ "\n" #~ "Dependencies Resolved\n" #~ "\n" #~ "=======================================================================================\n" #~ " Package               Arch             Version                Repository         Size\n" #~ "=======================================================================================\n" #~ "Installing:\n" #~ " httpd               x86_64           2.2.13-2.fc12            rawhide           735 k\n" #~ "Installing for dependencies:\n" #~ " apr                 x86_64           1.3.9-2.fc12             rawhide           117 k\n" #~ " apr-util            x86_64           1.3.9-2.fc12             rawhide            84 k\n" #~ " apr-util-ldap       x86_64           1.3.9-2.fc12             rawhide            15 k\n" #~ " httpd-tools         x86_64           2.2.13-2.fc12            rawhide            63 k\n" #~ " mailcap             noarch           2.1.30-1.fc12            rawhide            25 k\n" #~ "\n" #~ "Transaction Summary\n" #~ "=======================================================================================\n" #~ "Install       6 Package(s)\n" #~ "Upgrade       0 Package(s)\n" #~ "\n" #~ "Total download size: 1.0 M\n" #~ "Downloading Packages:\n" #~ "(1/6): apr-1.3.9-2.fc12.x86_64.rpm                                   | 117 kB     00:00     \n" #~ "(2/6): apr-util-1.3.9-2.fc12.x86_64.rpm                             |  84 kB     00:00     \n" #~ "(3/6): apr-util-ldap-1.3.9-2.fc12.x86_64.rpm                         |  15 kB     00:00     \n" #~ "(4/6): httpd-2.2.13-2.fc12.x86_64.rpm                               | 735 kB     00:00     \n" #~ "(5/6): httpd-tools-2.2.13-2.fc12.x86_64.rpm                         |  63 kB     00:00     \n" #~ "(6/6): mailcap-2.1.30-1.fc12.noarch.rpm                             |  25 kB     00:00     \n" #~ "----------------------------------------------------------------------------------------\n" #~ "Total                                                       875 kB/s | 1.0 MB     00:01     \n" #~ "Running rpm_check_debug\n" #~ "Running Transaction Test\n" #~ "Finished Transaction Test\n" #~ "Transaction Test Succeeded\n" #~ "Running Transaction\n" #~ "  Installing     : apr-1.3.9-2.fc12.x86_64                                         1/6 \n" #~ "  Installing     : apr-util-1.3.9-2.fc12.x86_64                                     2/6 \n" #~ "  Installing     : apr-util-ldap-1.3.9-2.fc12.x86_64                               3/6 \n" #~ "  Installing     : httpd-tools-2.2.13-2.fc12.x86_64                                 4/6 \n" #~ "  Installing     : mailcap-2.1.30-1.fc12.noarch                                     5/6 \n" #~ "  Installing     : httpd-2.2.13-2.fc12.x86_64                                       6/6 \n" #~ "\n" #~ "Installed:\n" #~ "  httpd.x86_64 0:2.2.13-2.fc12                                                         \n" #~ "\n" #~ "Dependency Installed:\n" #~ "  apr.x86_64 0:1.3.9-2.fc12            apr-util.x86_64 0:1.3.9-2.fc12\n" #~ "  apr-util-ldap.x86_64 0:1.3.9-2.fc12  httpd-tools.x86_64 0:2.2.13-2.fc12\n" #~ "  mailcap.noarch 0:2.1.30-1.fc12  \n" #~ "\n" #~ "Complete!\n" #~ "[root@pcmk-1 ~]#\n" #~ msgstr "" #~ "\n" #~ "[root@ppcmk-1 ~]# yum install -y httpd\n" #~ "Setting up Install Process\n" #~ "Resolving Dependencies\n" #~ "--> Running transaction check\n" #~ "---> Package httpd.x86_64 0:2.2.13-2.fc12 set to be updated\n" #~ "--> Processing Dependency: httpd-tools = 2.2.13-2.fc12 for package: httpd-2.2.13-2.fc12.x86_64\n" #~ "--> Processing Dependency: apr-util-ldap for package: httpd-2.2.13-2.fc12.x86_64\n" #~ "--> Processing Dependency: /etc/mime.types for package: httpd-2.2.13-2.fc12.x86_64\n" #~ "--> Processing Dependency: libaprutil-1.so.0()(64bit) for package: httpd-2.2.13-2.fc12.x86_64\n" #~ "--> Processing Dependency: libapr-1.so.0()(64bit) for package: httpd-2.2.13-2.fc12.x86_64\n" #~ "--> Running transaction check\n" #~ "---> Package apr.x86_64 0:1.3.9-2.fc12 set to be updated\n" #~ "---> Package apr-util.x86_64 0:1.3.9-2.fc12 set to be updated\n" #~ "---> Package apr-util-ldap.x86_64 0:1.3.9-2.fc12 set to be updated\n" #~ "---> Package httpd-tools.x86_64 0:2.2.13-2.fc12 set to be updated\n" #~ "---> Package mailcap.noarch 0:2.1.30-1.fc12 set to be updated\n" #~ "--> Finished Dependency Resolution\n" #~ "\n" #~ "Dependencies Resolved\n" #~ "\n" #~ "=======================================================================================\n" #~ " Package               Arch             Version                Repository         Size\n" #~ "=======================================================================================\n" #~ "Installing:\n" #~ " httpd               x86_64           2.2.13-2.fc12            rawhide           735 k\n" #~ "Installing for dependencies:\n" #~ " apr                 x86_64           1.3.9-2.fc12             rawhide           117 k\n" #~ " apr-util            x86_64           1.3.9-2.fc12             rawhide            84 k\n" #~ " apr-util-ldap       x86_64           1.3.9-2.fc12             rawhide            15 k\n" #~ " httpd-tools         x86_64           2.2.13-2.fc12            rawhide            63 k\n" #~ " mailcap             noarch           2.1.30-1.fc12            rawhide            25 k\n" #~ "\n" #~ "Transaction Summary\n" #~ "=======================================================================================\n" #~ "Install       6 Package(s)\n" #~ "Upgrade       0 Package(s)\n" #~ "\n" #~ "Total download size: 1.0 M\n" #~ "Downloading Packages:\n" #~ "(1/6): apr-1.3.9-2.fc12.x86_64.rpm                                   | 117 kB     00:00     \n" #~ "(2/6): apr-util-1.3.9-2.fc12.x86_64.rpm                             |  84 kB     00:00     \n" #~ "(3/6): apr-util-ldap-1.3.9-2.fc12.x86_64.rpm                         |  15 kB     00:00     \n" #~ "(4/6): httpd-2.2.13-2.fc12.x86_64.rpm                               | 735 kB     00:00     \n" #~ "(5/6): httpd-tools-2.2.13-2.fc12.x86_64.rpm                         |  63 kB     00:00     \n" #~ "(6/6): mailcap-2.1.30-1.fc12.noarch.rpm                             |  25 kB     00:00     \n" #~ "----------------------------------------------------------------------------------------\n" #~ "Total                                                       875 kB/s | 1.0 MB     00:01     \n" #~ "Running rpm_check_debug\n" #~ "Running Transaction Test\n" #~ "Finished Transaction Test\n" #~ "Transaction Test Succeeded\n" #~ "Running Transaction\n" #~ "  Installing     : apr-1.3.9-2.fc12.x86_64                                         1/6 \n" #~ "  Installing     : apr-util-1.3.9-2.fc12.x86_64                                     2/6 \n" #~ "  Installing     : apr-util-ldap-1.3.9-2.fc12.x86_64                               3/6 \n" #~ "  Installing     : httpd-tools-2.2.13-2.fc12.x86_64                                 4/6 \n" #~ "  Installing     : mailcap-2.1.30-1.fc12.noarch                                     5/6 \n" #~ "  Installing     : httpd-2.2.13-2.fc12.x86_64                                       6/6 \n" #~ "\n" #~ "Installed:\n" #~ "  httpd.x86_64 0:2.2.13-2.fc12                                                         \n" #~ "\n" #~ "Dependency Installed:\n" #~ "  apr.x86_64 0:1.3.9-2.fc12            apr-util.x86_64 0:1.3.9-2.fc12\n" #~ "  apr-util-ldap.x86_64 0:1.3.9-2.fc12  httpd-tools.x86_64 0:2.2.13-2.fc12\n" #~ "  mailcap.noarch 0:2.1.30-1.fc12  \n" #~ "\n" #~ "Complete!\n" #~ "[root@pcmk-1 ~]#\n" #~ msgid "" #~ "\n" #~ "[root@pcmk-1 ~]# yum install -y wget\n" #~ "Setting up Install Process\n" #~ "Resolving Dependencies\n" #~ "--> Running transaction check\n" #~ "---> Package wget.x86_64 0:1.11.4-5.fc12 set to be updated\n" #~ "--> Finished Dependency Resolution\n" #~ "\n" #~ "Dependencies Resolved\n" #~ "\n" #~ "===========================================================================================\n" #~ " Package        Arch             Version                      Repository               Size\n" #~ "===========================================================================================\n" #~ "Installing:\n" #~ " wget         x86_64          1.11.4-5.fc12                   rawhide                393 k\n" #~ "\n" #~ "Transaction Summary\n" #~ "===========================================================================================\n" #~ "Install       1 Package(s)\n" #~ "Upgrade       0 Package(s)\n" #~ "\n" #~ "Total download size: 393 k\n" #~ "Downloading Packages:\n" #~ "wget-1.11.4-5.fc12.x86_64.rpm                                            | 393 kB     00:00     \n" #~ "Running rpm_check_debug\n" #~ "Running Transaction Test\n" #~ "Finished Transaction Test\n" #~ "Transaction Test Succeeded\n" #~ "Running Transaction\n" #~ "  Installing     : wget-1.11.4-5.fc12.x86_64                                            1/1 \n" #~ "\n" #~ "Installed:\n" #~ "  wget.x86_64 0:1.11.4-5.fc12\n" #~ "\n" #~ "Complete!\n" #~ "[root@pcmk-1 ~]#\n" #~ msgstr "" #~ "\n" #~ "[root@pcmk-1 ~]# yum install -y wget\n" #~ "Setting up Install Process\n" #~ "Resolving Dependencies\n" #~ "--> Running transaction check\n" #~ "---> Package wget.x86_64 0:1.11.4-5.fc12 set to be updated\n" #~ "--> Finished Dependency Resolution\n" #~ "\n" #~ "Dependencies Resolved\n" #~ "\n" #~ "===========================================================================================\n" #~ " Package        Arch             Version                      Repository               Size\n" #~ "===========================================================================================\n" #~ "Installing:\n" #~ " wget         x86_64          1.11.4-5.fc12                   rawhide                393 k\n" #~ "\n" #~ "Transaction Summary\n" #~ "===========================================================================================\n" #~ "Install       1 Package(s)\n" #~ "Upgrade       0 Package(s)\n" #~ "\n" #~ "Total download size: 393 k\n" #~ "Downloading Packages:\n" #~ "wget-1.11.4-5.fc12.x86_64.rpm                                            | 393 kB     00:00     \n" #~ "Running rpm_check_debug\n" #~ "Running Transaction Test\n" #~ "Finished Transaction Test\n" #~ "Transaction Test Succeeded\n" #~ "Running Transaction\n" #~ "  Installing     : wget-1.11.4-5.fc12.x86_64                                            1/1 \n" #~ "\n" #~ "Installed:\n" #~ "  wget.x86_64 0:1.11.4-5.fc12\n" #~ "\n" #~ "Complete!\n" #~ "[root@pcmk-1 ~]#\n" #~ msgid "" #~ "\n" #~ "[root@pcmk-1 ~]# crm configure primitive WebSite ocf:heartbeat:apache params configfile=/etc/httpd/conf/httpd.conf op monitor interval=1min\n" #~ "[root@pcmk-1 ~]# crm configure show\n" #~ "node pcmk-1\n" #~ "node pcmk-2\n" #~ "primitive WebSite ocf:heartbeat:apache \\\n" #~ " params configfile=\"/etc/httpd/conf/httpd.conf\" \\\n" #~ " op monitor interval=\"1min\"\n" #~ "primitive ClusterIP ocf:heartbeat:IPaddr2 \\\n" #~ "        params ip=\"192.168.122.101\" cidr_netmask=\"32\" \\\n" #~ "        op monitor interval=\"30s\"\n" #~ "property $id=\"cib-bootstrap-options\" \\\n" #~ "        dc-version=\"1.1.5-bdd89e69ba545404d02445be1f3d72e6a203ba2f\" \\\n" #~ "        cluster-infrastructure=\"openais\" \\\n" #~ "        expected-quorum-votes=\"2\" \\\n" #~ "        stonith-enabled=\"false\" \\\n" #~ "        no-quorum-policy=\"ignore\"\n" #~ "rsc_defaults $id=\"rsc-options\" \\\n" #~ "        resource-stickiness=\"100\"\n" #~ msgstr "" #~ "\n" #~ "[root@pcmk-1 ~]# crm configure primitive WebSite ocf:heartbeat:apache params configfile=/etc/httpd/conf/httpd.conf op monitor interval=1min\n" #~ "[root@pcmk-1 ~]# crm configure show\n" #~ "node pcmk-1\n" #~ "node pcmk-2\n" #~ "primitive WebSite ocf:heartbeat:apache \\\n" #~ " params configfile=\"/etc/httpd/conf/httpd.conf\" \\\n" #~ " op monitor interval=\"1min\"\n" #~ "primitive ClusterIP ocf:heartbeat:IPaddr2 \\\n" #~ "        params ip=\"192.168.122.101\" cidr_netmask=\"32\" \\\n" #~ "        op monitor interval=\"30s\"\n" #~ "property $id=\"cib-bootstrap-options\" \\\n" #~ "        dc-version=\"1.1.5-bdd89e69ba545404d02445be1f3d72e6a203ba2f\" \\\n" #~ "        cluster-infrastructure=\"openais\" \\\n" #~ "        expected-quorum-votes=\"2\" \\\n" #~ "        stonith-enabled=\"false\" \\\n" #~ "        no-quorum-policy=\"ignore\"\n" #~ "rsc_defaults $id=\"rsc-options\" \\\n" #~ "        resource-stickiness=\"100\"\n" #~ msgid "For the constraint, we need a name (choose something descriptive like website-with-ip), indicate that it's mandatory (so that if ClusterIP is not active anywhere, WebSite will not be permitted to run anywhere either) by specifying a score of INFINITY and finally list the two resources." #~ msgstr "Pentru restricÈ›ie, ne trebuie un nume (alegeÈ›i ceva descriptiv precum website-with-ip), să indicăm că este obligatorie (astfel încât dacă ClusterIP nu este activ nicăieri, nici lui WebSite nu i se va permite să ruleze nicăieri) specificând un scor cu valoarea INFINITY È™i la sfârÈ™it vom lista cele două resurse." #~ msgid "" #~ "\n" #~ "[root@pcmk-1 ~]# crm configure colocation website-with-ip INFINITY: WebSite ClusterIP\n" #~ "[root@pcmk-1 ~]# crm configure show\n" #~ "node pcmk-1\n" #~ "node pcmk-2\n" #~ "primitive WebSite ocf:heartbeat:apache \\\n" #~ "        params configfile=\"/etc/httpd/conf/httpd.conf\" \\\n" #~ "        op monitor interval=\"1min\"\n" #~ "primitive ClusterIP ocf:heartbeat:IPaddr2 \\\n" #~ "        params ip=\"192.168.122.101\" cidr_netmask=\"32\" \\\n" #~ "        op monitor interval=\"30s\"\n" #~ "colocation website-with-ip inf: WebSite ClusterIP\n" #~ "property $id=\"cib-bootstrap-options\" \\\n" #~ "        dc-version=\"1.1.5-bdd89e69ba545404d02445be1f3d72e6a203ba2f\" \\\n" #~ "        cluster-infrastructure=\"openais\" \\\n" #~ "        expected-quorum-votes=\"2\" \\\n" #~ "        stonith-enabled=\"false\" \\\n" #~ "        no-quorum-policy=\"ignore\"\n" #~ "rsc_defaults $id=\"rsc-options\" \\\n" #~ "        resource-stickiness=\"100\"\n" #~ "[root@pcmk-1 ~]# crm_mon\n" #~ "============\n" #~ "Last updated: Fri Aug 28 16:14:34 2009\n" #~ "Stack: openais\n" #~ "Current DC: pcmk-2 - partition with quorum\n" #~ "Version: 1.1.5-bdd89e69ba545404d02445be1f3d72e6a203ba2f\n" #~ "2 Nodes configured, 2 expected votes\n" #~ "2 Resources configured.\n" #~ "============\n" #~ "\n" #~ "Online: [ pcmk-1 pcmk-2 ]\n" #~ "\n" #~ "ClusterIP        (ocf::heartbeat:IPaddr):        Started pcmk-2\n" #~ "WebSite        (ocf::heartbeat:apache):        Started pcmk-2\n" #~ msgstr "" #~ "\n" #~ "[root@pcmk-1 ~]# crm configure colocation website-with-ip INFINITY: WebSite ClusterIP\n" #~ "[root@pcmk-1 ~]# crm configure show\n" #~ "node pcmk-1\n" #~ "node pcmk-2\n" #~ "primitive WebSite ocf:heartbeat:apache \\\n" #~ "        params configfile=\"/etc/httpd/conf/httpd.conf\" \\\n" #~ "        op monitor interval=\"1min\"\n" #~ "primitive ClusterIP ocf:heartbeat:IPaddr2 \\\n" #~ "        params ip=\"192.168.122.101\" cidr_netmask=\"32\" \\\n" #~ "        op monitor interval=\"30s\"\n" #~ "colocation website-with-ip inf: WebSite ClusterIP\n" #~ "property $id=\"cib-bootstrap-options\" \\\n" #~ "        dc-version=\"1.1.5-bdd89e69ba545404d02445be1f3d72e6a203ba2f\" \\\n" #~ "        cluster-infrastructure=\"openais\" \\\n" #~ "        expected-quorum-votes=\"2\" \\\n" #~ "        stonith-enabled=\"false\" \\\n" #~ "        no-quorum-policy=\"ignore\"\n" #~ "rsc_defaults $id=\"rsc-options\" \\\n" #~ "        resource-stickiness=\"100\"\n" #~ "[root@pcmk-1 ~]# crm_mon\n" #~ "============\n" #~ "Last updated: Fri Aug 28 16:14:34 2009\n" #~ "Stack: openais\n" #~ "Current DC: pcmk-2 - partition with quorum\n" #~ "Version: 1.1.5-bdd89e69ba545404d02445be1f3d72e6a203ba2f\n" #~ "2 Nodes configured, 2 expected votes\n" #~ "2 Resources configured.\n" #~ "============\n" #~ "\n" #~ "Online: [ pcmk-1 pcmk-2 ]\n" #~ "\n" #~ "ClusterIP        (ocf::heartbeat:IPaddr):        Started pcmk-2\n" #~ "WebSite        (ocf::heartbeat:apache):        Started pcmk-2\n" #~ msgid "" #~ "\n" #~ "[root@pcmk-1 ~]# crm configure order apache-after-ip mandatory: ClusterIP WebSite\n" #~ "[root@pcmk-1 ~]# crm configure show\n" #~ "node pcmk-1\n" #~ "node pcmk-2\n" #~ "primitive WebSite ocf:heartbeat:apache \\\n" #~ "        params configfile=\"/etc/httpd/conf/httpd.conf\" \\\n" #~ "        op monitor interval=\"1min\"\n" #~ "primitive ClusterIP ocf:heartbeat:IPaddr2 \\\n" #~ "        params ip=\"192.168.122.101\" cidr_netmask=\"32\" \\\n" #~ "        op monitor interval=\"30s\"\n" #~ "colocation website-with-ip inf: WebSite ClusterIP\n" #~ "order apache-after-ip inf: ClusterIP WebSite\n" #~ "property $id=\"cib-bootstrap-options\" \\\n" #~ "        dc-version=\"1.1.5-bdd89e69ba545404d02445be1f3d72e6a203ba2f\" \\\n" #~ "        cluster-infrastructure=\"openais\" \\\n" #~ "        expected-quorum-votes=\"2\" \\\n" #~ "        stonith-enabled=\"false\" \\\n" #~ "        no-quorum-policy=\"ignore\"\n" #~ "rsc_defaults $id=\"rsc-options\" \\\n" #~ "        resource-stickiness=\"100\"\n" #~ msgstr "" #~ "\n" #~ "[root@pcmk-1 ~]# crm configure order apache-after-ip mandatory: ClusterIP WebSite\n" #~ "[root@pcmk-1 ~]# crm configure show\n" #~ "node pcmk-1\n" #~ "node pcmk-2\n" #~ "primitive WebSite ocf:heartbeat:apache \\\n" #~ "        params configfile=\"/etc/httpd/conf/httpd.conf\" \\\n" #~ "        op monitor interval=\"1min\"\n" #~ "primitive ClusterIP ocf:heartbeat:IPaddr2 \\\n" #~ "        params ip=\"192.168.122.101\" cidr_netmask=\"32\" \\\n" #~ "        op monitor interval=\"30s\"\n" #~ "colocation website-with-ip inf: WebSite ClusterIP\n" #~ "order apache-after-ip inf: ClusterIP WebSite\n" #~ "property $id=\"cib-bootstrap-options\" \\\n" #~ "        dc-version=\"1.1.5-bdd89e69ba545404d02445be1f3d72e6a203ba2f\" \\\n" #~ "        cluster-infrastructure=\"openais\" \\\n" #~ "        expected-quorum-votes=\"2\" \\\n" #~ "        stonith-enabled=\"false\" \\\n" #~ "        no-quorum-policy=\"ignore\"\n" #~ "rsc_defaults $id=\"rsc-options\" \\\n" #~ "        resource-stickiness=\"100\"\n" #~ msgid "" #~ "\n" #~ "[root@pcmk-1 ~]# crm configure location prefer-pcmk-1 WebSite 50: pcmk-1\n" #~ "[root@pcmk-1 ~]# crm configure show\n" #~ "node pcmk-1\n" #~ "node pcmk-2\n" #~ "primitive WebSite ocf:heartbeat:apache \\\n" #~ "        params configfile=\"/etc/httpd/conf/httpd.conf\" \\\n" #~ "        op monitor interval=\"1min\"\n" #~ "primitive ClusterIP ocf:heartbeat:IPaddr2 \\\n" #~ "        params ip=\"192.168.122.101\" cidr_netmask=\"32\" \\\n" #~ "        op monitor interval=\"30s\"\n" #~ "location prefer-pcmk-1 WebSite 50: pcmk-1\n" #~ "colocation website-with-ip inf: WebSite ClusterIP\n" #~ "property $id=\"cib-bootstrap-options\" \\\n" #~ "        dc-version=\"1.1.5-bdd89e69ba545404d02445be1f3d72e6a203ba2f\" \\\n" #~ "        cluster-infrastructure=\"openais\" \\\n" #~ "        expected-quorum-votes=\"2\" \\\n" #~ "        stonith-enabled=\"false\" \\\n" #~ "        no-quorum-policy=\"ignore\"\n" #~ "rsc_defaults $id=\"rsc-options\" \\\n" #~ "        resource-stickiness=\"100\"\n" #~ "[root@pcmk-1 ~]# crm_mon\n" #~ "============\n" #~ "Last updated: Fri Aug 28 16:17:35 2009\n" #~ "Stack: openais\n" #~ "Current DC: pcmk-2 - partition with quorum\n" #~ "Version: 1.1.5-bdd89e69ba545404d02445be1f3d72e6a203ba2f\n" #~ "2 Nodes configured, 2 expected votes\n" #~ "2 Resources configured.\n" #~ "============\n" #~ "\n" #~ "Online: [ pcmk-1 pcmk-2 ]\n" #~ "\n" #~ "ClusterIP        (ocf::heartbeat:IPaddr):        Started pcmk-2\n" #~ "WebSite        (ocf::heartbeat:apache):        Started pcmk-2\n" #~ msgstr "" #~ "\n" #~ "[root@pcmk-1 ~]# crm configure location prefer-pcmk-1 WebSite 50: pcmk-1\n" #~ "[root@pcmk-1 ~]# crm configure show\n" #~ "node pcmk-1\n" #~ "node pcmk-2\n" #~ "primitive WebSite ocf:heartbeat:apache \\\n" #~ "        params configfile=\"/etc/httpd/conf/httpd.conf\" \\\n" #~ "        op monitor interval=\"1min\"\n" #~ "primitive ClusterIP ocf:heartbeat:IPaddr2 \\\n" #~ "        params ip=\"192.168.122.101\" cidr_netmask=\"32\" \\\n" #~ "        op monitor interval=\"30s\"\n" #~ "location prefer-pcmk-1 WebSite 50: pcmk-1\n" #~ "colocation website-with-ip inf: WebSite ClusterIP\n" #~ "property $id=\"cib-bootstrap-options\" \\\n" #~ "        dc-version=\"1.1.5-bdd89e69ba545404d02445be1f3d72e6a203ba2f\" \\\n" #~ "        cluster-infrastructure=\"openais\" \\\n" #~ "        expected-quorum-votes=\"2\" \\\n" #~ "        stonith-enabled=\"false\" \\\n" #~ "        no-quorum-policy=\"ignore\"\n" #~ "rsc_defaults $id=\"rsc-options\" \\\n" #~ "        resource-stickiness=\"100\"\n" #~ "[root@pcmk-1 ~]# crm_mon\n" #~ "============\n" #~ "Last updated: Fri Aug 28 16:17:35 2009\n" #~ "Stack: openais\n" #~ "Current DC: pcmk-2 - partition with quorum\n" #~ "Version: 1.1.5-bdd89e69ba545404d02445be1f3d72e6a203ba2f\n" #~ "2 Nodes configured, 2 expected votes\n" #~ "2 Resources configured.\n" #~ "============\n" #~ "\n" #~ "Online: [ pcmk-1 pcmk-2 ]\n" #~ "\n" #~ "ClusterIP        (ocf::heartbeat:IPaddr):        Started pcmk-2\n" #~ "WebSite        (ocf::heartbeat:apache):        Started pcmk-2\n" #~ msgid "ptest -sL" #~ msgstr "ptest -sL" #~ msgid "Include output" #~ msgstr "Include rezultatul de ieÈ™ire" #~ msgid "There is a way to force them to move though..." #~ msgstr "Există o cale să le forțăm să se mute totuÈ™i ..." #~ msgid "" #~ "\n" #~ "[root@pcmk-1 ~]# crm resource move WebSite pcmk-1\n" #~ "[root@pcmk-1 ~]# crm_mon\n" #~ "============\n" #~ "Last updated: Fri Aug 28 16:19:24 2009\n" #~ "Stack: openais\n" #~ "Current DC: pcmk-2 - partition with quorum\n" #~ "Version: 1.1.5-bdd89e69ba545404d02445be1f3d72e6a203ba2f\n" #~ "2 Nodes configured, 2 expected votes\n" #~ "2 Resources configured.\n" #~ "============\n" #~ "\n" #~ "Online: [ pcmk-1 pcmk-2 ]\n" #~ "\n" #~ "ClusterIP        (ocf::heartbeat:IPaddr):        Started pcmk-1\n" #~ "WebSite        (ocf::heartbeat:apache):        Started pcmk-1\n" #~ "Notice how the colocation rule we created has ensured that ClusterIP was also moved to pcmk-1.\n" #~ "For the curious, we can see the effect of this command by examining the configuration\n" #~ "crm configure show\n" #~ "[root@pcmk-1 ~]# crm configure show\n" #~ "node pcmk-1\n" #~ "node pcmk-2\n" #~ "primitive WebSite ocf:heartbeat:apache \\\n" #~ "        params configfile=\"/etc/httpd/conf/httpd.conf\" \\\n" #~ "        op monitor interval=\"1min\"\n" #~ "primitive ClusterIP ocf:heartbeat:IPaddr2 \\\n" #~ "        params ip=\"192.168.122.101\" cidr_netmask=\"32\" \\\n" #~ "        op monitor interval=\"30s\"\n" #~ "location cli-prefer-WebSite WebSite \\\n" #~ " rule $id=\"cli-prefer-rule-WebSite\" inf: #uname eq pcmk-1\n" #~ "location prefer-pcmk-1 WebSite 50: pcmk-1\n" #~ "colocation website-with-ip inf: WebSite ClusterIP\n" #~ "property $id=\"cib-bootstrap-options\" \\\n" #~ "        dc-version=\"1.1.5-bdd89e69ba545404d02445be1f3d72e6a203ba2f\" \\\n" #~ "        cluster-infrastructure=\"openais\" \\\n" #~ "        expected-quorum-votes=\"2\" \\\n" #~ "        stonith-enabled=\"false\" \\\n" #~ "        no-quorum-policy=\"ignore\"\n" #~ "rsc_defaults $id=\"rsc-options\" \\\n" #~ "        resource-stickiness=\"100\"\n" #~ msgstr "" #~ "\n" #~ "[root@pcmk-1 ~]# crm resource move WebSite pcmk-1\n" #~ "[root@pcmk-1 ~]# crm_mon\n" #~ "============\n" #~ "Last updated: Fri Aug 28 16:19:24 2009\n" #~ "Stack: openais\n" #~ "Current DC: pcmk-2 - partition with quorum\n" #~ "Version: 1.1.5-bdd89e69ba545404d02445be1f3d72e6a203ba2f\n" #~ "2 Nodes configured, 2 expected votes\n" #~ "2 Resources configured.\n" #~ "============\n" #~ "\n" #~ "Online: [ pcmk-1 pcmk-2 ]\n" #~ "\n" #~ "ClusterIP        (ocf::heartbeat:IPaddr):        Started pcmk-1\n" #~ "WebSite        (ocf::heartbeat:apache):        Started pcmk-1\n" #~ "Notice how the colocation rule we created has ensured that ClusterIP was also moved to pcmk-1.\n" #~ "For the curious, we can see the effect of this command by examining the configuration\n" #~ "crm configure show\n" #~ "[root@pcmk-1 ~]# crm configure show\n" #~ "node pcmk-1\n" #~ "node pcmk-2\n" #~ "primitive WebSite ocf:heartbeat:apache \\\n" #~ "        params configfile=\"/etc/httpd/conf/httpd.conf\" \\\n" #~ "        op monitor interval=\"1min\"\n" #~ "primitive ClusterIP ocf:heartbeat:IPaddr2 \\\n" #~ "        params ip=\"192.168.122.101\" cidr_netmask=\"32\" \\\n" #~ "        op monitor interval=\"30s\"\n" #~ "location cli-prefer-WebSite WebSite \\\n" #~ " rule $id=\"cli-prefer-rule-WebSite\" inf: #uname eq pcmk-1\n" #~ "location prefer-pcmk-1 WebSite 50: pcmk-1\n" #~ "colocation website-with-ip inf: WebSite ClusterIP\n" #~ "property $id=\"cib-bootstrap-options\" \\\n" #~ "        dc-version=\"1.1.5-bdd89e69ba545404d02445be1f3d72e6a203ba2f\" \\\n" #~ "        cluster-infrastructure=\"openais\" \\\n" #~ "        expected-quorum-votes=\"2\" \\\n" #~ "        stonith-enabled=\"false\" \\\n" #~ "        no-quorum-policy=\"ignore\"\n" #~ "rsc_defaults $id=\"rsc-options\" \\\n" #~ "        resource-stickiness=\"100\"\n" #~ msgid "Highlighted is the automated constraint used to move the resources to pcmk-1" #~ msgstr "Subliniată este restricÈ›ia automată folosită pentru a muta resursele pe pcmk-1" #~ msgid "" #~ "\n" #~ "[root@pcmk-1 ~]# crm resource unmove WebSite\n" #~ "[root@pcmk-1 ~]# crm configure show\n" #~ "node pcmk-1\n" #~ "node pcmk-2\n" #~ "primitive WebSite ocf:heartbeat:apache \\\n" #~ "        params configfile=\"/etc/httpd/conf/httpd.conf\" \\\n" #~ "        op monitor interval=\"1min\"\n" #~ "primitive ClusterIP ocf:heartbeat:IPaddr2 \\\n" #~ "        params ip=\"192.168.122.101\" cidr_netmask=\"32\" \\\n" #~ "        op monitor interval=\"30s\"\n" #~ "location prefer-pcmk-1 WebSite 50: pcmk-1\n" #~ "colocation website-with-ip inf: WebSite ClusterIP\n" #~ "property $id=\"cib-bootstrap-options\" \\\n" #~ "        dc-version=\"1.1.5-bdd89e69ba545404d02445be1f3d72e6a203ba2f\" \\\n" #~ "        cluster-infrastructure=\"openais\" \\\n" #~ "        expected-quorum-votes=\"2\" \\\n" #~ "        stonith-enabled=\"false\" \\\n" #~ "        no-quorum-policy=\"ignore\"\n" #~ "rsc_defaults $id=\"rsc-options\" \\\n" #~ "        resource-stickiness=\"100\"\n" #~ msgstr "" #~ "\n" #~ "[root@pcmk-1 ~]# crm resource unmove WebSite\n" #~ "[root@pcmk-1 ~]# crm configure show\n" #~ "node pcmk-1\n" #~ "node pcmk-2\n" #~ "primitive WebSite ocf:heartbeat:apache \\\n" #~ "        params configfile=\"/etc/httpd/conf/httpd.conf\" \\\n" #~ "        op monitor interval=\"1min\"\n" #~ "primitive ClusterIP ocf:heartbeat:IPaddr2 \\\n" #~ "        params ip=\"192.168.122.101\" cidr_netmask=\"32\" \\\n" #~ "        op monitor interval=\"30s\"\n" #~ "location prefer-pcmk-1 WebSite 50: pcmk-1\n" #~ "colocation website-with-ip inf: WebSite ClusterIP\n" #~ "property $id=\"cib-bootstrap-options\" \\\n" #~ "        dc-version=\"1.1.5-bdd89e69ba545404d02445be1f3d72e6a203ba2f\" \\\n" #~ "        cluster-infrastructure=\"openais\" \\\n" #~ "        expected-quorum-votes=\"2\" \\\n" #~ "        stonith-enabled=\"false\" \\\n" #~ "        no-quorum-policy=\"ignore\"\n" #~ "rsc_defaults $id=\"rsc-options\" \\\n" #~ "        resource-stickiness=\"100\"\n" #~ msgid "" #~ "\n" #~ "[root@pcmk-1 ~]# crm_mon\n" #~ "============\n" #~ "Last updated: Fri Aug 28 16:20:53 2009\n" #~ "Stack: openais\n" #~ "Current DC: pcmk-2 - partition with quorum\n" #~ "Version: 1.1.5-bdd89e69ba545404d02445be1f3d72e6a203ba2f\n" #~ "2 Nodes configured, 2 expected votes\n" #~ "2 Resources configured.\n" #~ "============\n" #~ "\n" #~ "Online: [ pcmk-1 pcmk-2 ]\n" #~ "\n" #~ " ClusterIP        (ocf::heartbeat:IPaddr):        Started pcmk-1\n" #~ " WebSite        (ocf::heartbeat:apache):        Started pcmk-1\n" #~ msgstr "" #~ "\n" #~ "[root@pcmk-1 ~]# crm_mon\n" #~ "============\n" #~ "Last updated: Fri Aug 28 16:20:53 2009\n" #~ "Stack: openais\n" #~ "Current DC: pcmk-2 - partition with quorum\n" #~ "Version: 1.1.5-bdd89e69ba545404d02445be1f3d72e6a203ba2f\n" #~ "2 Nodes configured, 2 expected votes\n" #~ "2 Resources configured.\n" #~ "============\n" #~ "\n" #~ "Online: [ pcmk-1 pcmk-2 ]\n" #~ "\n" #~ " ClusterIP        (ocf::heartbeat:IPaddr):        Started pcmk-1\n" #~ " WebSite        (ocf::heartbeat:apache):        Started pcmk-1\n" diff --git a/fencing/main.c b/fencing/main.c index 70b5bdeea9..0d01b12f1a 100644 --- a/fencing/main.c +++ b/fencing/main.c @@ -1,1423 +1,1444 @@ /* * Copyright (C) 2009 Andrew Beekhof * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include char *stonith_our_uname = NULL; char *stonith_our_uuid = NULL; long stonith_watchdog_timeout_ms = 0; GMainLoop *mainloop = NULL; gboolean stand_alone = FALSE; gboolean no_cib_connect = FALSE; gboolean stonith_shutdown_flag = FALSE; qb_ipcs_service_t *ipcs = NULL; xmlNode *local_cib = NULL; static cib_t *cib_api = NULL; static void *cib_library = NULL; static void stonith_shutdown(int nsig); static void stonith_cleanup(void); static int32_t st_ipc_accept(qb_ipcs_connection_t * c, uid_t uid, gid_t gid) { if (stonith_shutdown_flag) { crm_info("Ignoring new client [%d] during shutdown", crm_ipcs_client_pid(c)); return -EPERM; } if (crm_client_new(c, uid, gid) == NULL) { return -EIO; } return 0; } static void st_ipc_created(qb_ipcs_connection_t * c) { crm_trace("Connection created for %p", c); } /* Exit code means? */ static int32_t st_ipc_dispatch(qb_ipcs_connection_t * qbc, void *data, size_t size) { uint32_t id = 0; uint32_t flags = 0; int call_options = 0; xmlNode *request = NULL; crm_client_t *c = crm_client_get(qbc); const char *op = NULL; if (c == NULL) { crm_info("Invalid client: %p", qbc); return 0; } request = crm_ipcs_recv(c, data, size, &id, &flags); if (request == NULL) { crm_ipcs_send_ack(c, id, flags, "nack", __FUNCTION__, __LINE__); return 0; } op = crm_element_value(request, F_CRM_TASK); if(safe_str_eq(op, CRM_OP_RM_NODE_CACHE)) { crm_xml_add(request, F_TYPE, T_STONITH_NG); crm_xml_add(request, F_STONITH_OPERATION, op); crm_xml_add(request, F_STONITH_CLIENTID, c->id); crm_xml_add(request, F_STONITH_CLIENTNAME, crm_client_name(c)); crm_xml_add(request, F_STONITH_CLIENTNODE, stonith_our_uname); send_cluster_message(NULL, crm_msg_stonith_ng, request, FALSE); free_xml(request); return 0; } if (c->name == NULL) { const char *value = crm_element_value(request, F_STONITH_CLIENTNAME); if (value == NULL) { value = "unknown"; } c->name = g_strdup_printf("%s.%u", value, c->pid); } crm_element_value_int(request, F_STONITH_CALLOPTS, &call_options); crm_trace("Flags %u/%u for command %u from %s", flags, call_options, id, crm_client_name(c)); if (is_set(call_options, st_opt_sync_call)) { CRM_ASSERT(flags & crm_ipc_client_response); CRM_LOG_ASSERT(c->request_id == 0); /* This means the client has two synchronous events in-flight */ c->request_id = id; /* Reply only to the last one */ } crm_xml_add(request, F_STONITH_CLIENTID, c->id); crm_xml_add(request, F_STONITH_CLIENTNAME, crm_client_name(c)); crm_xml_add(request, F_STONITH_CLIENTNODE, stonith_our_uname); crm_log_xml_trace(request, "Client[inbound]"); stonith_command(c, id, flags, request, NULL); free_xml(request); return 0; } /* Error code means? */ static int32_t st_ipc_closed(qb_ipcs_connection_t * c) { crm_client_t *client = crm_client_get(c); if (client == NULL) { return 0; } crm_trace("Connection %p closed", c); crm_client_destroy(client); /* 0 means: yes, go ahead and destroy the connection */ return 0; } static void st_ipc_destroy(qb_ipcs_connection_t * c) { crm_trace("Connection %p destroyed", c); st_ipc_closed(c); } static void stonith_peer_callback(xmlNode * msg, void *private_data) { const char *remote_peer = crm_element_value(msg, F_ORIG); const char *op = crm_element_value(msg, F_STONITH_OPERATION); if (crm_str_eq(op, "poke", TRUE)) { return; } crm_log_xml_trace(msg, "Peer[inbound]"); stonith_command(NULL, 0, 0, msg, remote_peer); } #if SUPPORT_HEARTBEAT static void stonith_peer_hb_callback(HA_Message * msg, void *private_data) { xmlNode *xml = convert_ha_message(NULL, msg, __FUNCTION__); stonith_peer_callback(xml, private_data); free_xml(xml); } static void stonith_peer_hb_destroy(gpointer user_data) { if (stonith_shutdown_flag) { crm_info("Heartbeat disconnection complete... exiting"); } else { crm_err("Heartbeat connection lost! Exiting."); } stonith_shutdown(0); } #endif #if SUPPORT_COROSYNC static void stonith_peer_ais_callback(cpg_handle_t handle, const struct cpg_name *groupName, uint32_t nodeid, uint32_t pid, void *msg, size_t msg_len) { uint32_t kind = 0; xmlNode *xml = NULL; const char *from = NULL; char *data = pcmk_message_common_cs(handle, nodeid, pid, msg, &kind, &from); if(data == NULL) { return; } if (kind == crm_class_cluster) { xml = string2xml(data); if (xml == NULL) { crm_err("Invalid XML: '%.120s'", data); free(data); return; } crm_xml_add(xml, F_ORIG, from); /* crm_xml_add_int(xml, F_SEQ, wrapper->id); */ stonith_peer_callback(xml, NULL); } free_xml(xml); free(data); return; } static void stonith_peer_cs_destroy(gpointer user_data) { crm_err("Corosync connection terminated"); stonith_shutdown(0); } #endif void do_local_reply(xmlNode * notify_src, const char *client_id, gboolean sync_reply, gboolean from_peer) { /* send callback to originating child */ crm_client_t *client_obj = NULL; int local_rc = pcmk_ok; crm_trace("Sending response"); client_obj = crm_client_get_by_id(client_id); crm_trace("Sending callback to request originator"); if (client_obj == NULL) { local_rc = -1; crm_trace("No client to sent the response to. F_STONITH_CLIENTID not set."); } else { int rid = 0; if (sync_reply) { CRM_LOG_ASSERT(client_obj->request_id); rid = client_obj->request_id; client_obj->request_id = 0; crm_trace("Sending response %d to %s %s", rid, client_obj->name, from_peer ? "(originator of delegated request)" : ""); } else { crm_trace("Sending an event to %s %s", client_obj->name, from_peer ? "(originator of delegated request)" : ""); } local_rc = crm_ipcs_send(client_obj, rid, notify_src, sync_reply?crm_ipc_flags_none:crm_ipc_server_event); } if (local_rc < pcmk_ok && client_obj != NULL) { crm_warn("%sSync reply to %s failed: %s", sync_reply ? "" : "A-", client_obj ? client_obj->name : "", pcmk_strerror(local_rc)); } } long long get_stonith_flag(const char *name) { if (safe_str_eq(name, T_STONITH_NOTIFY_FENCE)) { return 0x01; } else if (safe_str_eq(name, STONITH_OP_DEVICE_ADD)) { return 0x04; } else if (safe_str_eq(name, STONITH_OP_DEVICE_DEL)) { return 0x10; } return 0; } static void stonith_notify_client(gpointer key, gpointer value, gpointer user_data) { xmlNode *update_msg = user_data; crm_client_t *client = value; const char *type = NULL; CRM_CHECK(client != NULL, return); CRM_CHECK(update_msg != NULL, return); type = crm_element_value(update_msg, F_SUBTYPE); CRM_CHECK(type != NULL, crm_log_xml_err(update_msg, "notify"); return); if (client->ipcs == NULL) { crm_trace("Skipping client with NULL channel"); return; } if (client->options & get_stonith_flag(type)) { int rc = crm_ipcs_send(client, 0, update_msg, crm_ipc_server_event | crm_ipc_server_error); if (rc <= 0) { crm_warn("%s notification of client %s.%.6s failed: %s (%d)", type, crm_client_name(client), client->id, pcmk_strerror(rc), rc); } else { crm_trace("Sent %s notification to client %s.%.6s", type, crm_client_name(client), client->id); } } } void do_stonith_async_timeout_update(const char *client_id, const char *call_id, int timeout) { crm_client_t *client = NULL; xmlNode *notify_data = NULL; if (!timeout || !call_id || !client_id) { return; } client = crm_client_get_by_id(client_id); if (!client) { return; } notify_data = create_xml_node(NULL, T_STONITH_TIMEOUT_VALUE); crm_xml_add(notify_data, F_TYPE, T_STONITH_TIMEOUT_VALUE); crm_xml_add(notify_data, F_STONITH_CALLID, call_id); crm_xml_add_int(notify_data, F_STONITH_TIMEOUT, timeout); crm_trace("timeout update is %d for client %s and call id %s", timeout, client_id, call_id); if (client) { crm_ipcs_send(client, 0, notify_data, crm_ipc_server_event); } free_xml(notify_data); } void do_stonith_notify(int options, const char *type, int result, xmlNode * data) { /* TODO: Standardize the contents of data */ xmlNode *update_msg = create_xml_node(NULL, "notify"); CRM_CHECK(type != NULL,;); crm_xml_add(update_msg, F_TYPE, T_STONITH_NOTIFY); crm_xml_add(update_msg, F_SUBTYPE, type); crm_xml_add(update_msg, F_STONITH_OPERATION, type); crm_xml_add_int(update_msg, F_STONITH_RC, result); if (data != NULL) { add_message_xml(update_msg, F_STONITH_CALLDATA, data); } crm_trace("Notifying clients"); g_hash_table_foreach(client_connections, stonith_notify_client, update_msg); free_xml(update_msg); crm_trace("Notify complete"); } static stonith_key_value_t * parse_device_list(const char *devices) { int lpc = 0; int max = 0; int last = 0; stonith_key_value_t *output = NULL; if (devices == NULL) { return output; } max = strlen(devices); for (lpc = 0; lpc <= max; lpc++) { if (devices[lpc] == ',' || devices[lpc] == 0) { char *line = NULL; line = calloc(1, 2 + lpc - last); snprintf(line, 1 + lpc - last, "%s", devices + last); output = stonith_key_value_add(output, NULL, line); free(line); last = lpc + 1; } } return output; } static void topology_remove_helper(const char *node, int level) { int rc; char *desc = NULL; xmlNode *data = create_xml_node(NULL, F_STONITH_LEVEL); xmlNode *notify_data = create_xml_node(NULL, STONITH_OP_LEVEL_DEL); crm_xml_add(data, F_STONITH_ORIGIN, __FUNCTION__); crm_xml_add_int(data, XML_ATTR_ID, level); crm_xml_add(data, F_STONITH_TARGET, node); rc = stonith_level_remove(data, &desc); crm_xml_add(notify_data, F_STONITH_DEVICE, desc); crm_xml_add_int(notify_data, F_STONITH_ACTIVE, g_hash_table_size(topology)); do_stonith_notify(0, STONITH_OP_LEVEL_DEL, rc, notify_data); free_xml(notify_data); free_xml(data); free(desc); } static void topology_register_helper(const char *node, int level, stonith_key_value_t * device_list) { int rc; char *desc = NULL; xmlNode *notify_data = create_xml_node(NULL, STONITH_OP_LEVEL_ADD); xmlNode *data = create_level_registration_xml(node, level, device_list); rc = stonith_level_register(data, &desc); crm_xml_add(notify_data, F_STONITH_DEVICE, desc); crm_xml_add_int(notify_data, F_STONITH_ACTIVE, g_hash_table_size(topology)); do_stonith_notify(0, STONITH_OP_LEVEL_ADD, rc, notify_data); free_xml(notify_data); free_xml(data); free(desc); } static void remove_cib_device(xmlXPathObjectPtr xpathObj) { int max = numXpathResults(xpathObj), lpc = 0; for (lpc = 0; lpc < max; lpc++) { const char *rsc_id = NULL; const char *standard = NULL; xmlNode *match = getXpathResult(xpathObj, lpc); CRM_LOG_ASSERT(match != NULL); if(match != NULL) { standard = crm_element_value(match, XML_AGENT_ATTR_CLASS); } if (safe_str_neq(standard, "stonith")) { continue; } rsc_id = crm_element_value(match, XML_ATTR_ID); stonith_device_remove(rsc_id, TRUE); } } static void handle_topology_change(xmlNode *match, bool remove) { CRM_LOG_ASSERT(match != NULL); if(match) { int index = 0; const char *target; const char *dev_list; stonith_key_value_t *devices = NULL; crm_element_value_int(match, XML_ATTR_STONITH_INDEX, &index); target = crm_element_value(match, XML_ATTR_STONITH_TARGET); dev_list = crm_element_value(match, XML_ATTR_STONITH_DEVICES); devices = parse_device_list(dev_list); crm_trace("Updating %s[%d] (%s) to %s", target, index, ID(match), dev_list); if(remove) { topology_remove_helper(target, index); } topology_register_helper(target, index, devices); stonith_key_value_freeall(devices, 1, 1); } } static void remove_fencing_topology(xmlXPathObjectPtr xpathObj) { int max = numXpathResults(xpathObj), lpc = 0; for (lpc = 0; lpc < max; lpc++) { xmlNode *match = getXpathResult(xpathObj, lpc); CRM_LOG_ASSERT(match != NULL); if (match && crm_element_value(match, XML_DIFF_MARKER)) { /* Deletion */ int index = 0; const char *target = crm_element_value(match, XML_ATTR_STONITH_TARGET); crm_element_value_int(match, XML_ATTR_STONITH_INDEX, &index); if (target == NULL) { crm_err("Invalid fencing target in element %s", ID(match)); } else if (index <= 0) { crm_err("Invalid level for %s in element %s", target, ID(match)); } else { topology_remove_helper(target, index); } /* } else { Deal with modifications during the 'addition' stage */ } } } static void register_fencing_topology(xmlXPathObjectPtr xpathObj, gboolean force) { int max = numXpathResults(xpathObj), lpc = 0; for (lpc = 0; lpc < max; lpc++) { xmlNode *match = getXpathResult(xpathObj, lpc); handle_topology_change(match, TRUE); } } /* Fencing */ static void fencing_topology_init(xmlNode * msg) { xmlXPathObjectPtr xpathObj = NULL; const char *xpath = "//" XML_TAG_FENCING_LEVEL; crm_trace("Full topology refresh"); if(topology) { g_hash_table_destroy(topology); topology = g_hash_table_new_full(crm_str_hash, g_str_equal, NULL, free_topology_entry); } /* Grab everything */ xpathObj = xpath_search(local_cib, xpath); register_fencing_topology(xpathObj, TRUE); freeXpathObject(xpathObj); } #define rsc_name(x) x->clone_name?x->clone_name:x->id static void cib_device_update(resource_t *rsc, pe_working_set_t *data_set) { node_t *node = NULL; const char *value = NULL; const char *rclass = NULL; node_t *parent = NULL; gboolean remove = TRUE; /* TODO: Mark each installed device and remove if untouched when this process finishes */ if(rsc->children) { GListPtr gIter = NULL; for (gIter = rsc->children; gIter != NULL; gIter = gIter->next) { cib_device_update(gIter->data, data_set); if(rsc->variant == pe_clone || rsc->variant == pe_master) { crm_trace("Only processing one copy of the clone %s", rsc->id); break; } } return; } rclass = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS); if(safe_str_neq(rclass, "stonith")) { return; } value = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_TARGET_ROLE); if(value && strcmp(RSC_STOPPED, value) == 0) { crm_info("Device %s has been disabled", rsc->id); goto update_done; } else if(stonith_our_uname) { GHashTableIter iter; g_hash_table_iter_init(&iter, rsc->allowed_nodes); while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) { if(node && strcmp(node->details->uname, stonith_our_uname) == 0) { break; } node = NULL; } } if (rsc->parent && rsc->parent->variant == pe_group && stonith_our_uname) { GHashTableIter iter; g_hash_table_iter_init(&iter, rsc->parent->allowed_nodes); while (g_hash_table_iter_next(&iter, NULL, (void **)&parent)) { if(parent && strcmp(parent->details->uname, stonith_our_uname) == 0) { break; } parent = NULL; } } if(node == NULL) { GHashTableIter iter; crm_info("Device %s has been disabled on %s: unknown", rsc->id, stonith_our_uname); g_hash_table_iter_init(&iter, rsc->allowed_nodes); while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) { crm_trace("Available: %s = %d", node->details->uname, node->weight); } goto update_done; } else if(node->weight < 0 || (parent && parent->weight < 0)) { char *score = score2char((node->weight < 0) ? node->weight : parent->weight); crm_info("Device %s has been disabled on %s: score=%s", rsc->id, stonith_our_uname, score); free(score); goto update_done; } else { xmlNode *data; GHashTableIter gIter; stonith_key_value_t *params = NULL; const char *name = NULL; const char *agent = crm_element_value(rsc->xml, XML_EXPR_ATTR_TYPE); const char *provider = crm_element_value(rsc->xml, XML_AGENT_ATTR_PROVIDER); const char *rsc_provides = NULL; crm_debug("Device %s is allowed on %s: score=%d", rsc->id, stonith_our_uname, node->weight); get_rsc_attributes(rsc->parameters, rsc, node, data_set); get_meta_attributes(rsc->meta, rsc, node, data_set); rsc_provides = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_PROVIDES); g_hash_table_iter_init(&gIter, rsc->parameters); while (g_hash_table_iter_next(&gIter, (gpointer *) & name, (gpointer *) & value)) { if (!name || !value) { continue; } params = stonith_key_value_add(params, name, value); crm_trace(" %s=%s", name, value); } remove = FALSE; data = create_device_registration_xml(rsc_name(rsc), provider, agent, params, rsc_provides); stonith_device_register(data, NULL, TRUE); stonith_key_value_freeall(params, 1, 1); free_xml(data); } update_done: if(remove && g_hash_table_lookup(device_list, rsc_name(rsc))) { stonith_device_remove(rsc_name(rsc), TRUE); } } extern xmlNode *do_calculations(pe_working_set_t * data_set, xmlNode * xml_input, crm_time_t * now); extern node_t *create_node(const char *id, const char *uname, const char *type, const char *score, pe_working_set_t * data_set); static void cib_devices_update(void) { GListPtr gIter = NULL; pe_working_set_t data_set; crm_info("Updating devices to version %s.%s.%s", crm_element_value(local_cib, XML_ATTR_GENERATION_ADMIN), crm_element_value(local_cib, XML_ATTR_GENERATION), crm_element_value(local_cib, XML_ATTR_NUMUPDATES)); set_working_set_defaults(&data_set); data_set.input = local_cib; data_set.now = crm_time_new(NULL); data_set.flags |= pe_flag_quick_location; data_set.localhost = stonith_our_uname; cluster_status(&data_set); do_calculations(&data_set, NULL, NULL); for (gIter = data_set.resources; gIter != NULL; gIter = gIter->next) { cib_device_update(gIter->data, &data_set); } data_set.input = NULL; /* Wasn't a copy */ cleanup_alloc_calculations(&data_set); } static void update_cib_stonith_devices_v2(const char *event, xmlNode * msg) { xmlNode *change = NULL; char *reason = NULL; bool needs_update = FALSE; xmlNode *patchset = get_message_xml(msg, F_CIB_UPDATE_RESULT); for (change = __xml_first_child(patchset); change != NULL; change = __xml_next(change)) { const char *op = crm_element_value(change, XML_DIFF_OP); const char *xpath = crm_element_value(change, XML_DIFF_PATH); const char *shortpath = NULL; if(op == NULL || strcmp(op, "move") == 0) { continue; } else if(safe_str_eq(op, "delete") && strstr(xpath, XML_CIB_TAG_RESOURCE)) { const char *rsc_id = NULL; char *search = NULL; char *mutable = strdup(xpath); rsc_id = strstr(mutable, "primitive[@id=\'") + strlen("primitive[@id=\'"); search = strchr(rsc_id, '\''); search[0] = 0; stonith_device_remove(rsc_id, TRUE); free(mutable); } else if(strstr(xpath, "/"XML_CIB_TAG_RESOURCES)) { shortpath = strrchr(xpath, '/'); CRM_ASSERT(shortpath); reason = g_strdup_printf("%s %s", op, shortpath+1); needs_update = TRUE; break; } else if(strstr(xpath, XML_CONS_TAG_RSC_LOCATION)) { shortpath = strrchr(xpath, '/'); CRM_ASSERT(shortpath); reason = g_strdup_printf("%s %s", op, shortpath+1); needs_update = TRUE; break; } } if(needs_update) { crm_info("Updating device list from the cib: %s", reason); cib_devices_update(); } free(reason); } static void update_cib_stonith_devices_v1(const char *event, xmlNode * msg) { const char *reason = "none"; gboolean needs_update = FALSE; xmlXPathObjectPtr xpath_obj = NULL; /* process new constraints */ xpath_obj = xpath_search(msg, "//" F_CIB_UPDATE_RESULT "//" XML_CONS_TAG_RSC_LOCATION); if (numXpathResults(xpath_obj) > 0) { int max = numXpathResults(xpath_obj), lpc = 0; /* Safest and simplest to always recompute */ needs_update = TRUE; reason = "new location constraint"; for (lpc = 0; lpc < max; lpc++) { xmlNode *match = getXpathResult(xpath_obj, lpc); crm_log_xml_trace(match, "new constraint"); } } freeXpathObject(xpath_obj); /* process deletions */ xpath_obj = xpath_search(msg, "//" F_CIB_UPDATE_RESULT "//" XML_TAG_DIFF_REMOVED "//" XML_CIB_TAG_RESOURCE); if (numXpathResults(xpath_obj) > 0) { remove_cib_device(xpath_obj); } freeXpathObject(xpath_obj); /* process additions */ xpath_obj = xpath_search(msg, "//" F_CIB_UPDATE_RESULT "//" XML_TAG_DIFF_ADDED "//" XML_CIB_TAG_RESOURCE); if (numXpathResults(xpath_obj) > 0) { int max = numXpathResults(xpath_obj), lpc = 0; for (lpc = 0; lpc < max; lpc++) { const char *rsc_id = NULL; const char *standard = NULL; xmlNode *match = getXpathResult(xpath_obj, lpc); rsc_id = crm_element_value(match, XML_ATTR_ID); standard = crm_element_value(match, XML_AGENT_ATTR_CLASS); if (safe_str_neq(standard, "stonith")) { continue; } crm_trace("Fencing resource %s was added or modified", rsc_id); reason = "new resource"; needs_update = TRUE; } } freeXpathObject(xpath_obj); if(needs_update) { crm_info("Updating device list from the cib: %s", reason); cib_devices_update(); } } static void update_cib_stonith_devices(const char *event, xmlNode * msg) { int format = 1; xmlNode *patchset = get_message_xml(msg, F_CIB_UPDATE_RESULT); CRM_ASSERT(patchset); crm_element_value_int(patchset, "format", &format); switch(format) { case 1: update_cib_stonith_devices_v1(event, msg); break; case 2: update_cib_stonith_devices_v2(event, msg); break; default: crm_warn("Unknown patch format: %d", format); } } static void update_fencing_topology(const char *event, xmlNode * msg) { int format = 1; const char *xpath; xmlXPathObjectPtr xpathObj = NULL; xmlNode *patchset = get_message_xml(msg, F_CIB_UPDATE_RESULT); CRM_ASSERT(patchset); crm_element_value_int(patchset, "format", &format); if(format == 1) { /* Process deletions (only) */ xpath = "//" F_CIB_UPDATE_RESULT "//" XML_TAG_DIFF_REMOVED "//" XML_TAG_FENCING_LEVEL; xpathObj = xpath_search(msg, xpath); remove_fencing_topology(xpathObj); freeXpathObject(xpathObj); /* Process additions and changes */ xpath = "//" F_CIB_UPDATE_RESULT "//" XML_TAG_DIFF_ADDED "//" XML_TAG_FENCING_LEVEL; xpathObj = xpath_search(msg, xpath); register_fencing_topology(xpathObj, FALSE); freeXpathObject(xpathObj); } else if(format == 2) { xmlNode *change = NULL; for (change = __xml_first_child(patchset); change != NULL; change = __xml_next(change)) { const char *op = crm_element_value(change, XML_DIFF_OP); const char *xpath = crm_element_value(change, XML_DIFF_PATH); xmlNode *f_topology = get_message_xml(change, XML_TAG_FENCING_TOPOLOGY); if(op == NULL) { continue; } else if (strstr(xpath, "/" XML_TAG_CIB "/" XML_CIB_TAG_CONFIGURATION) && f_topology != NULL) { if(strcmp(op, "delete") == 0 || strcmp(op, "create") == 0) { crm_info("Re-initializing fencing topology after top-level %s operation", op); fencing_topology_init(NULL); } return; } else if (strstr(xpath, "/" XML_TAG_FENCING_TOPOLOGY "/") == NULL) { continue; } else if(strstr(xpath, "/" XML_TAG_FENCING_LEVEL "/") == NULL) { if(strcmp(op, "delete") == 0 || strcmp(op, "create") == 0) { crm_info("Re-initializing fencing topology after top-level %s operation", op); fencing_topology_init(NULL); } return; } crm_trace("Handling %s operation for %s", op, xpath); if(strcmp(op, "move") == 0) { continue; } else if(strcmp(op, "create") == 0) { handle_topology_change(change->children, FALSE); } else if(strcmp(op, "modify") == 0) { xmlNode *match = first_named_child(change, XML_DIFF_RESULT); if(match) { handle_topology_change(match->children, TRUE); } } else if(strcmp(op, "delete") == 0) { /* Nuclear option, all we have is the path and an id... not enough to remove a specific entry */ crm_info("Re-initializing fencing topology after %s operation", op); fencing_topology_init(NULL); return; } } } else { crm_warn("Unknown patch format: %d", format); } } static bool have_cib_devices = FALSE; static void update_cib_cache_cb(const char *event, xmlNode * msg) { int rc = pcmk_ok; xmlNode *stonith_enabled_xml = NULL; xmlNode *stonith_watchdog_xml = NULL; const char *stonith_enabled_s = NULL; static gboolean stonith_enabled_saved = TRUE; if(!have_cib_devices) { crm_trace("Skipping updates until we get a full dump"); return; } else if(msg == NULL) { crm_trace("Missing %s update", event); return; } /* Maintain a local copy of the CIB so that we have full access to the device definitions and location constraints */ if (local_cib != NULL) { int rc = pcmk_ok; xmlNode *patchset = NULL; crm_element_value_int(msg, F_CIB_RC, &rc); if (rc != pcmk_ok) { return; } patchset = get_message_xml(msg, F_CIB_UPDATE_RESULT); xml_log_patchset(LOG_TRACE, "Config update", patchset); rc = xml_apply_patchset(local_cib, patchset, TRUE); switch (rc) { case pcmk_ok: case -pcmk_err_old_data: break; case -pcmk_err_diff_resync: case -pcmk_err_diff_failed: crm_notice("[%s] Patch aborted: %s (%d)", event, pcmk_strerror(rc), rc); free_xml(local_cib); local_cib = NULL; break; default: crm_warn("[%s] ABORTED: %s (%d)", event, pcmk_strerror(rc), rc); free_xml(local_cib); local_cib = NULL; } } if (local_cib == NULL) { crm_trace("Re-requesting the full cib"); rc = cib_api->cmds->query(cib_api, NULL, &local_cib, cib_scope_local | cib_sync_call); if(rc != pcmk_ok) { crm_err("Couldnt retrieve the CIB: %s (%d)", pcmk_strerror(rc), rc); return; } CRM_ASSERT(local_cib != NULL); stonith_enabled_saved = FALSE; /* Trigger a full refresh below */ } stonith_enabled_xml = get_xpath_object("//nvpair[@name='stonith-enabled']", local_cib, LOG_TRACE); if (stonith_enabled_xml) { stonith_enabled_s = crm_element_value(stonith_enabled_xml, XML_NVPAIR_ATTR_VALUE); } if(daemon_option_enabled(crm_system_name, "watchdog")) { const char *value = NULL; long timeout_ms = 0; if(value == NULL) { stonith_watchdog_xml = get_xpath_object("//nvpair[@name='stonith-watchdog-timeout']", local_cib, LOG_TRACE); if (stonith_watchdog_xml) { value = crm_element_value(stonith_watchdog_xml, XML_NVPAIR_ATTR_VALUE); } } if(value) { timeout_ms = crm_get_msec(value); } if(timeout_ms != stonith_watchdog_timeout_ms) { crm_notice("New watchdog timeout %lds (was %lds)", timeout_ms/1000, stonith_watchdog_timeout_ms/1000); stonith_watchdog_timeout_ms = timeout_ms; } } if (stonith_enabled_s && crm_is_true(stonith_enabled_s) == FALSE) { crm_trace("Ignoring cib updates while stonith is disabled"); stonith_enabled_saved = FALSE; return; } else if (stonith_enabled_saved == FALSE) { crm_info("Updating stonith device and topology lists now that stonith is enabled"); stonith_enabled_saved = TRUE; fencing_topology_init(NULL); cib_devices_update(); } else { update_fencing_topology(event, msg); update_cib_stonith_devices(event, msg); } } static void init_cib_cache_cb(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data) { crm_info("Updating device list from the cib: init"); have_cib_devices = TRUE; local_cib = copy_xml(output); fencing_topology_init(msg); cib_devices_update(); } static void stonith_shutdown(int nsig) { stonith_shutdown_flag = TRUE; crm_info("Terminating with %d clients", crm_hash_table_size(client_connections)); if (mainloop != NULL && g_main_is_running(mainloop)) { g_main_quit(mainloop); } else { stonith_cleanup(); crm_exit(pcmk_ok); } } static void cib_connection_destroy(gpointer user_data) { if (stonith_shutdown_flag) { crm_info("Connection to the CIB closed."); return; } else { crm_notice("Connection to the CIB terminated. Shutting down."); } if (cib_api) { cib_api->cmds->signoff(cib_api); } stonith_shutdown(0); } static void stonith_cleanup(void) { if (cib_api) { cib_api->cmds->signoff(cib_api); } if (ipcs) { qb_ipcs_destroy(ipcs); } crm_peer_destroy(); crm_client_cleanup(); free(stonith_our_uname); free_xml(local_cib); } /* *INDENT-OFF* */ static struct crm_option long_options[] = { {"stand-alone", 0, 0, 's'}, {"stand-alone-w-cpg", 0, 0, 'c'}, {"logfile", 1, 0, 'l'}, {"verbose", 0, 0, 'V'}, {"version", 0, 0, '$'}, {"help", 0, 0, '?'}, {0, 0, 0, 0} }; /* *INDENT-ON* */ static void setup_cib(void) { int rc, retries = 0; static cib_t *(*cib_new_fn) (void) = NULL; if (cib_new_fn == NULL) { cib_new_fn = find_library_function(&cib_library, CIB_LIBRARY, "cib_new", TRUE); } if (cib_new_fn != NULL) { cib_api = (*cib_new_fn) (); } if (cib_api == NULL) { crm_err("No connection to the CIB"); return; } do { sleep(retries); rc = cib_api->cmds->signon(cib_api, CRM_SYSTEM_CRMD, cib_command); } while (rc == -ENOTCONN && ++retries < 5); if (rc != pcmk_ok) { crm_err("Could not connect to the CIB service: %s (%d)", pcmk_strerror(rc), rc); } else if (pcmk_ok != cib_api->cmds->add_notify_callback(cib_api, T_CIB_DIFF_NOTIFY, update_cib_cache_cb)) { crm_err("Could not set CIB notification callback"); } else { rc = cib_api->cmds->query(cib_api, NULL, NULL, cib_scope_local); cib_api->cmds->register_callback(cib_api, rc, 120, FALSE, NULL, "init_cib_cache_cb", init_cib_cache_cb); cib_api->cmds->set_connection_dnotify(cib_api, cib_connection_destroy); crm_notice("Watching for stonith topology changes"); } } struct qb_ipcs_service_handlers ipc_callbacks = { .connection_accept = st_ipc_accept, .connection_created = st_ipc_created, .msg_process = st_ipc_dispatch, .connection_closed = st_ipc_closed, .connection_destroyed = st_ipc_destroy }; static void st_peer_update_callback(enum crm_status_type type, crm_node_t * node, const void *data) { /* * This is a hack until we can send to a nodeid and/or we fix node name lookups * These messages are ignored in stonith_peer_callback() */ xmlNode *query = create_xml_node(NULL, "stonith_command"); crm_xml_add(query, F_XML_TAGNAME, "stonith_command"); crm_xml_add(query, F_TYPE, T_STONITH_NG); crm_xml_add(query, F_STONITH_OPERATION, "poke"); crm_debug("Broadcasting our uname because of node %u", node->id); send_cluster_message(NULL, crm_msg_stonith_ng, query, FALSE); free_xml(query); } int main(int argc, char **argv) { int flag; int rc = 0; int lpc = 0; int argerr = 0; int option_index = 0; crm_cluster_t cluster; const char *actions[] = { "reboot", "off", "list", "monitor", "status" }; crm_log_preinit("stonith-ng", argc, argv); crm_set_options(NULL, "mode [options]", long_options, "Provides a summary of cluster's current state." "\n\nOutputs varying levels of detail in a number of different formats.\n"); while (1) { flag = crm_get_option(argc, argv, &option_index); if (flag == -1) { break; } switch (flag) { case 'V': crm_bump_log_level(argc, argv); break; case 'l': crm_add_logfile(optarg); break; case 's': stand_alone = TRUE; break; case 'c': stand_alone = FALSE; no_cib_connect = TRUE; break; case '$': case '?': crm_help(flag, EX_OK); break; default: ++argerr; break; } } if (argc - optind == 1 && safe_str_eq("metadata", argv[optind])) { printf("\n"); printf("\n"); printf(" 1.0\n"); printf (" This is a fake resource that details the instance attributes handled by stonithd.\n"); printf(" Options available for all stonith resources\n"); printf(" \n"); printf(" \n"); printf (" How long to wait for the STONITH action to complete per a stonith device.\n"); printf (" Overrides the stonith-timeout cluster property\n"); printf(" \n"); printf(" \n"); printf(" \n"); printf (" The priority of the stonith resource. Devices are tried in order of highest priority to lowest.\n"); printf(" \n"); printf(" \n"); printf(" \n", STONITH_ATTR_HOSTARG); printf (" Advanced use only: An alternate parameter to supply instead of 'port'\n"); printf (" Some devices do not support the standard 'port' parameter or may provide additional ones.\n" "Use this to specify an alternate, device-specific, parameter that should indicate the machine to be fenced.\n" "A value of 'none' can be used to tell the cluster not to supply any additional parameters.\n" " \n"); printf(" \n"); printf(" \n"); printf(" \n", STONITH_ATTR_HOSTMAP); printf (" A mapping of host names to ports numbers for devices that do not support host names.\n"); printf (" Eg. node1:1;node2:2,3 would tell the cluster to use port 1 for node1 and ports 2 and 3 for node2\n"); printf(" \n"); printf(" \n"); printf(" \n", STONITH_ATTR_HOSTLIST); printf (" A list of machines controlled by this device (Optional unless %s=static-list).\n", STONITH_ATTR_HOSTCHECK); printf(" \n"); printf(" \n"); printf(" \n", STONITH_ATTR_HOSTCHECK); printf (" How to determine which machines are controlled by the device.\n"); printf (" Allowed values: dynamic-list (query the device), static-list (check the %s attribute), none (assume every device can fence every machine)\n", STONITH_ATTR_HOSTLIST); printf(" \n"); printf(" \n"); for (lpc = 0; lpc < DIMOF(actions); lpc++) { printf(" \n", actions[lpc]); printf (" Advanced use only: An alternate command to run instead of '%s'\n", actions[lpc]); printf (" Some devices do not support the standard commands or may provide additional ones.\n" "Use this to specify an alternate, device-specific, command that implements the '%s' action.\n", actions[lpc]); printf(" \n", actions[lpc]); printf(" \n"); printf(" \n", actions[lpc]); printf (" Advanced use only: Specify an alternate timeout to use for %s actions instead of stonith-timeout\n", actions[lpc]); printf (" Some devices need much more/less time to complete than normal.\n" "Use this to specify an alternate, device-specific, timeout for '%s' actions.\n", actions[lpc]); printf(" \n"); printf(" \n"); printf(" \n", actions[lpc]); printf (" Advanced use only: The maximum number of times to retry the '%s' command within the timeout period\n", actions[lpc]); printf(" Some devices do not support multiple connections." " Operations may 'fail' if the device is busy with another task so Pacemaker will automatically retry the operation, if there is time remaining." " Use this option to alter the number of times Pacemaker retries '%s' actions before giving up." "\n", actions[lpc]); printf(" \n"); printf(" \n"); } printf(" \n"); printf("\n"); return 0; } if (optind != argc) { ++argerr; } if (argerr) { crm_help('?', EX_USAGE); } crm_log_init("stonith-ng", LOG_INFO, TRUE, FALSE, argc, argv, FALSE); mainloop_add_signal(SIGTERM, stonith_shutdown); crm_peer_init(); if (stand_alone == FALSE) { #if SUPPORT_HEARTBEAT cluster.hb_conn = NULL; cluster.hb_dispatch = stonith_peer_hb_callback; cluster.destroy = stonith_peer_hb_destroy; #endif if (is_openais_cluster()) { #if SUPPORT_COROSYNC cluster.destroy = stonith_peer_cs_destroy; cluster.cpg.cpg_deliver_fn = stonith_peer_ais_callback; cluster.cpg.cpg_confchg_fn = pcmk_cpg_membership; #endif } if (crm_cluster_connect(&cluster) == FALSE) { crm_crit("Cannot sign in to the cluster... terminating"); crm_exit(DAEMON_RESPAWN_STOP); } stonith_our_uname = cluster.uname; stonith_our_uuid = cluster.uuid; +#if SUPPORT_HEARTBEAT + if (is_heartbeat_cluster()) { + /* crm_cluster_connect() registered us for crm_system_name, which + * usually is the only F_TYPE used by the respective sub system. + * Stonith needs to register two additional F_TYPE callbacks, + * because it can :-/ */ + if (HA_OK != + cluster.hb_conn->llc_ops->set_msg_callback(cluster.hb_conn, T_STONITH_NOTIFY, + cluster.hb_dispatch, cluster.hb_conn)) { + crm_crit("Cannot set msg callback %s: %s", T_STONITH_NOTIFY, cluster.hb_conn->llc_ops->errmsg(cluster.hb_conn)); + crm_exit(DAEMON_RESPAWN_STOP); + } + if (HA_OK != + cluster.hb_conn->llc_ops->set_msg_callback(cluster.hb_conn, T_STONITH_TIMEOUT_VALUE, + cluster.hb_dispatch, cluster.hb_conn)) { + crm_crit("Cannot set msg callback %s: %s", T_STONITH_TIMEOUT_VALUE, cluster.hb_conn->llc_ops->errmsg(cluster.hb_conn)); + crm_exit(DAEMON_RESPAWN_STOP); + } + } +#endif + if (no_cib_connect == FALSE) { setup_cib(); } } else { stonith_our_uname = strdup("localhost"); } crm_set_status_callback(&st_peer_update_callback); device_list = g_hash_table_new_full(crm_str_hash, g_str_equal, NULL, free_device); topology = g_hash_table_new_full(crm_str_hash, g_str_equal, NULL, free_topology_entry); if(daemon_option_enabled(crm_system_name, "watchdog")) { xmlNode *xml; stonith_key_value_t *params = NULL; params = stonith_key_value_add(params, STONITH_ATTR_HOSTLIST, stonith_our_uname); xml = create_device_registration_xml("watchdog", "internal", STONITH_WATCHDOG_AGENT, params, NULL); stonith_device_register(xml, NULL, FALSE); stonith_key_value_freeall(params, 1, 1); free_xml(xml); } stonith_ipc_server_init(&ipcs, &ipc_callbacks); #if SUPPORT_STONITH_CONFIG if (((stand_alone == TRUE)) && !(standalone_cfg_read_file(STONITH_NG_CONF_FILE))) { standalone_cfg_commit(); } #endif /* Create the mainloop and run it... */ mainloop = g_main_new(FALSE); crm_info("Starting %s mainloop", crm_system_name); g_main_run(mainloop); stonith_cleanup(); #if SUPPORT_HEARTBEAT if (cluster.hb_conn) { cluster.hb_conn->llc_ops->delete(cluster.hb_conn); } #endif crm_info("Done"); return crm_exit(rc); } diff --git a/include/crm/cluster/internal.h b/include/crm/cluster/internal.h index b7edfebef0..0834be2e15 100644 --- a/include/crm/cluster/internal.h +++ b/include/crm/cluster/internal.h @@ -1,448 +1,449 @@ /* * Copyright (C) 2004 Andrew Beekhof * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef CRM_CLUSTER_INTERNAL__H # define CRM_CLUSTER_INTERNAL__H # include # define AIS_IPC_NAME "ais-crm-ipc" # define AIS_IPC_MESSAGE_SIZE 8192*128 # define CRM_MESSAGE_IPC_ACK 0 # ifndef INTERFACE_MAX # define INTERFACE_MAX 2 /* from the private coroapi.h header */ # endif typedef struct crm_ais_host_s AIS_Host; typedef struct crm_ais_msg_s AIS_Message; struct crm_ais_host_s { uint32_t id; uint32_t pid; gboolean local; enum crm_ais_msg_types type; uint32_t size; char uname[MAX_NAME]; } __attribute__ ((packed)); struct crm_ais_msg_s { cs_ipc_header_response_t header __attribute__ ((aligned(8))); uint32_t id; gboolean is_compressed; AIS_Host host; AIS_Host sender; uint32_t size; uint32_t compressed_size; /* 584 bytes */ char data[0]; } __attribute__ ((packed)); struct crm_ais_nodeid_resp_s { cs_ipc_header_response_t header __attribute__ ((aligned(8))); uint32_t id; uint32_t counter; char uname[MAX_NAME]; char cname[MAX_NAME]; } __attribute__ ((packed)); struct crm_ais_quorum_resp_s { cs_ipc_header_response_t header __attribute__ ((aligned(8))); uint64_t id; uint32_t votes; uint32_t expected_votes; uint32_t quorate; } __attribute__ ((packed)); /* *INDENT-OFF* */ enum crm_proc_flag { crm_proc_none = 0x00000001, /* These values are sent over the network by the legacy plugin * Therefor changing any of these values is going to break compatability * * So don't */ /* 3 messaging types */ crm_proc_heartbeat = 0x01000000, crm_proc_plugin = 0x00000002, crm_proc_cpg = 0x04000000, crm_proc_lrmd = 0x00000010, crm_proc_cib = 0x00000100, crm_proc_crmd = 0x00000200, crm_proc_attrd = 0x00001000, crm_proc_stonithd = 0x00002000, crm_proc_stonith_ng= 0x00100000, crm_proc_pe = 0x00010000, crm_proc_te = 0x00020000, crm_proc_mgmtd = 0x00040000, }; /* *INDENT-ON* */ static inline const char * peer2text(enum crm_proc_flag proc) { const char *text = "unknown"; - if (proc == (crm_proc_cpg | crm_proc_crmd)) { + if (proc == (crm_proc_cpg | crm_proc_crmd) + || proc == (crm_proc_heartbeat | crm_proc_crmd)) { return "peer"; } switch (proc) { case crm_proc_none: text = "none"; break; case crm_proc_plugin: text = "ais"; break; case crm_proc_heartbeat: text = "heartbeat"; break; case crm_proc_cib: text = "cib"; break; case crm_proc_crmd: text = "crmd"; break; case crm_proc_pe: text = "pengine"; break; case crm_proc_te: text = "tengine"; break; case crm_proc_lrmd: text = "lrmd"; break; case crm_proc_attrd: text = "attrd"; break; case crm_proc_stonithd: text = "stonithd"; break; case crm_proc_stonith_ng: text = "stonith-ng"; break; case crm_proc_mgmtd: text = "mgmtd"; break; case crm_proc_cpg: text = "corosync-cpg"; break; } return text; } static inline enum crm_proc_flag text2proc(const char *proc) { /* We only care about these two so far */ if (proc && strcmp(proc, "cib") == 0) { return crm_proc_cib; } else if (proc && strcmp(proc, "crmd") == 0) { return crm_proc_crmd; } return crm_proc_none; } static inline const char * ais_dest(const struct crm_ais_host_s *host) { if (host->local) { return "local"; } else if (host->size > 0) { return host->uname; } else { return ""; } } # define ais_data_len(msg) (msg->is_compressed?msg->compressed_size:msg->size) static inline AIS_Message * ais_msg_copy(const AIS_Message * source) { AIS_Message *target = malloc(sizeof(AIS_Message) + ais_data_len(source)); if(target) { memcpy(target, source, sizeof(AIS_Message)); memcpy(target->data, source->data, ais_data_len(target)); } return target; } /* typedef enum { CS_OK = 1, CS_ERR_LIBRARY = 2, CS_ERR_VERSION = 3, CS_ERR_INIT = 4, CS_ERR_TIMEOUT = 5, CS_ERR_TRY_AGAIN = 6, CS_ERR_INVALID_PARAM = 7, CS_ERR_NO_MEMORY = 8, CS_ERR_BAD_HANDLE = 9, CS_ERR_BUSY = 10, CS_ERR_ACCESS = 11, CS_ERR_NOT_EXIST = 12, CS_ERR_NAME_TOO_LONG = 13, CS_ERR_EXIST = 14, CS_ERR_NO_SPACE = 15, CS_ERR_INTERRUPT = 16, CS_ERR_NAME_NOT_FOUND = 17, CS_ERR_NO_RESOURCES = 18, CS_ERR_NOT_SUPPORTED = 19, CS_ERR_BAD_OPERATION = 20, CS_ERR_FAILED_OPERATION = 21, CS_ERR_MESSAGE_ERROR = 22, CS_ERR_QUEUE_FULL = 23, CS_ERR_QUEUE_NOT_AVAILABLE = 24, CS_ERR_BAD_FLAGS = 25, CS_ERR_TOO_BIG = 26, CS_ERR_NO_SECTIONS = 27, CS_ERR_CONTEXT_NOT_FOUND = 28, CS_ERR_TOO_MANY_GROUPS = 30, CS_ERR_SECURITY = 100 } cs_error_t; */ static inline const char * ais_error2text(int error) { const char *text = "unknown"; # if SUPPORT_COROSYNC switch (error) { case CS_OK: text = "OK"; break; case CS_ERR_LIBRARY: text = "Library error"; break; case CS_ERR_VERSION: text = "Version error"; break; case CS_ERR_INIT: text = "Initialization error"; break; case CS_ERR_TIMEOUT: text = "Timeout"; break; case CS_ERR_TRY_AGAIN: text = "Try again"; break; case CS_ERR_INVALID_PARAM: text = "Invalid parameter"; break; case CS_ERR_NO_MEMORY: text = "No memory"; break; case CS_ERR_BAD_HANDLE: text = "Bad handle"; break; case CS_ERR_BUSY: text = "Busy"; break; case CS_ERR_ACCESS: text = "Access error"; break; case CS_ERR_NOT_EXIST: text = "Doesn't exist"; break; case CS_ERR_NAME_TOO_LONG: text = "Name too long"; break; case CS_ERR_EXIST: text = "Exists"; break; case CS_ERR_NO_SPACE: text = "No space"; break; case CS_ERR_INTERRUPT: text = "Interrupt"; break; case CS_ERR_NAME_NOT_FOUND: text = "Name not found"; break; case CS_ERR_NO_RESOURCES: text = "No resources"; break; case CS_ERR_NOT_SUPPORTED: text = "Not supported"; break; case CS_ERR_BAD_OPERATION: text = "Bad operation"; break; case CS_ERR_FAILED_OPERATION: text = "Failed operation"; break; case CS_ERR_MESSAGE_ERROR: text = "Message error"; break; case CS_ERR_QUEUE_FULL: text = "Queue full"; break; case CS_ERR_QUEUE_NOT_AVAILABLE: text = "Queue not available"; break; case CS_ERR_BAD_FLAGS: text = "Bad flags"; break; case CS_ERR_TOO_BIG: text = "To big"; break; case CS_ERR_NO_SECTIONS: text = "No sections"; break; } # endif return text; } static inline const char * msg_type2text(enum crm_ais_msg_types type) { const char *text = "unknown"; switch (type) { case crm_msg_none: text = "unknown"; break; case crm_msg_ais: text = "ais"; break; case crm_msg_cib: text = "cib"; break; case crm_msg_crmd: text = "crmd"; break; case crm_msg_pe: text = "pengine"; break; case crm_msg_te: text = "tengine"; break; case crm_msg_lrmd: text = "lrmd"; break; case crm_msg_attrd: text = "attrd"; break; case crm_msg_stonithd: text = "stonithd"; break; case crm_msg_stonith_ng: text = "stonith-ng"; break; } return text; } enum crm_ais_msg_types text2msg_type(const char *text); char *get_ais_data(const AIS_Message * msg); gboolean check_message_sanity(const AIS_Message * msg, const char *data); # if SUPPORT_HEARTBEAT extern ll_cluster_t *heartbeat_cluster; gboolean send_ha_message(ll_cluster_t * hb_conn, xmlNode * msg, const char *node, gboolean force_ordered); gboolean ha_msg_dispatch(ll_cluster_t * cluster_conn, gpointer user_data); gboolean register_heartbeat_conn(crm_cluster_t * cluster); xmlNode *convert_ha_message(xmlNode * parent, HA_Message * msg, const char *field); gboolean ccm_have_quorum(oc_ed_t event); const char *ccm_event_name(oc_ed_t event); crm_node_t *crm_update_ccm_node(const oc_ev_membership_t * oc, int offset, const char *state, uint64_t seq); gboolean heartbeat_initialize_nodelist(void *cluster, gboolean force_member, xmlNode * xml_parent); # endif # if SUPPORT_COROSYNC gboolean send_cpg_iov(struct iovec * iov); # if SUPPORT_PLUGIN char *classic_node_name(uint32_t nodeid); void plugin_handle_membership(AIS_Message *msg); bool send_plugin_text(int class, struct iovec *iov); # else char *corosync_node_name(uint64_t /*cmap_handle_t */ cmap_handle, uint32_t nodeid); char *corosync_cluster_name(void); int corosync_cmap_has_config(const char *prefix); # endif gboolean corosync_initialize_nodelist(void *cluster, gboolean force_member, xmlNode * xml_parent); gboolean send_cluster_message_cs(xmlNode * msg, gboolean local, crm_node_t * node, enum crm_ais_msg_types dest); enum cluster_type_e find_corosync_variant(void); void terminate_cs_connection(crm_cluster_t * cluster); gboolean init_cs_connection(crm_cluster_t * cluster); gboolean init_cs_connection_once(crm_cluster_t * cluster); # endif # ifdef SUPPORT_CMAN char *cman_node_name(uint32_t nodeid); # endif enum crm_quorum_source { crm_quorum_cman, crm_quorum_corosync, crm_quorum_pacemaker, }; int get_corosync_id(int id, const char *uuid); char *get_corosync_uuid(crm_node_t *peer); enum crm_quorum_source get_quorum_source(void); void crm_update_peer_proc(const char *source, crm_node_t * peer, uint32_t flag, const char *status); crm_node_t *crm_update_peer(const char *source, unsigned int id, uint64_t born, uint64_t seen, int32_t votes, uint32_t children, const char *uuid, const char *uname, const char *addr, const char *state); void crm_update_peer_expected(const char *source, crm_node_t * node, const char *expected); void crm_update_peer_state(const char *source, crm_node_t * node, const char *state, int membership); gboolean init_cman_connection(gboolean(*dispatch) (unsigned long long, gboolean), void (*destroy) (gpointer)); gboolean cluster_connect_quorum(gboolean(*dispatch) (unsigned long long, gboolean), void (*destroy) (gpointer)); void set_node_uuid(const char *uname, const char *uuid); gboolean node_name_is_valid(const char *key, const char *name); crm_node_t * crm_find_peer_full(unsigned int id, const char *uname, int flags); crm_node_t * crm_find_peer(unsigned int id, const char *uname); #endif diff --git a/lib/cluster/heartbeat.c b/lib/cluster/heartbeat.c index 6f6a3885ea..3e8cfffd74 100644 --- a/lib/cluster/heartbeat.c +++ b/lib/cluster/heartbeat.c @@ -1,625 +1,657 @@ /* * Copyright (C) 2004 Andrew Beekhof * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include #include #include #if HAVE_BZLIB_H # include #endif #if SUPPORT_HEARTBEAT ll_cluster_t *heartbeat_cluster = NULL; static void convert_ha_field(xmlNode * parent, void *msg_v, int lpc) { int type = 0; const char *name = NULL; const char *value = NULL; xmlNode *xml = NULL; HA_Message *msg = msg_v; int rc = BZ_OK; size_t orig_len = 0; unsigned int used = 0; char *uncompressed = NULL; char *compressed = NULL; int size = orig_len * 10; CRM_CHECK(parent != NULL, return); CRM_CHECK(msg != NULL, return); name = msg->names[lpc]; type = cl_get_type(msg, name); switch (type) { case FT_STRUCT: convert_ha_message(parent, msg->values[lpc], name); break; case FT_COMPRESS: case FT_UNCOMPRESS: convert_ha_message(parent, cl_get_struct(msg, name), name); break; case FT_STRING: value = msg->values[lpc]; CRM_CHECK(value != NULL, return); crm_trace("Converting %s/%d/%s", name, type, value[0] == '<' ? "xml" : "field"); if (value[0] != '<') { crm_xml_add(parent, name, value); break; } /* unpack xml string */ xml = string2xml(value); if (xml == NULL) { crm_err("Conversion of field '%s' failed", name); return; } add_node_nocopy(parent, NULL, xml); break; case FT_BINARY: value = cl_get_binary(msg, name, &orig_len); size = orig_len * 10 + 1; /* +1 because an exact 10x compression factor happens occasionally */ if (orig_len < 3 || value[0] != 'B' || value[1] != 'Z' || value[2] != 'h') { if (strstr(name, "uuid") == NULL) { crm_err("Skipping non-bzip binary field: %s", name); } return; } compressed = calloc(1, orig_len); memcpy(compressed, value, orig_len); crm_trace("Trying to decompress %d bytes", (int)orig_len); retry: uncompressed = realloc_safe(uncompressed, size); memset(uncompressed, 0, size); used = size - 1; /* always leave room for a trailing '\0' * BZ2_bzBuffToBuffDecompress wont say anything if * the uncompressed data is exactly 'size' bytes */ rc = BZ2_bzBuffToBuffDecompress(uncompressed, &used, compressed, orig_len, 1, 0); if (rc == BZ_OUTBUFF_FULL) { size = size * 2; /* dont try to allocate more memory than we have */ if (size > 0) { goto retry; } } if (rc != BZ_OK) { crm_err("Decompression of %s (%d bytes) into %d failed: %d", name, (int)orig_len, size, rc); } else if (used >= size) { CRM_ASSERT(used < size); } else { CRM_LOG_ASSERT(uncompressed[used] == 0); uncompressed[used] = 0; xml = string2xml(uncompressed); } if (xml != NULL) { add_node_copy(parent, xml); free_xml(xml); } free(uncompressed); free(compressed); break; } } xmlNode * convert_ha_message(xmlNode * parent, HA_Message * msg, const char *field) { int lpc = 0; xmlNode *child = NULL; const char *tag = NULL; CRM_CHECK(msg != NULL, crm_err("Empty message for %s", field); return parent); tag = cl_get_string(msg, F_XML_TAGNAME); if (tag == NULL) { tag = field; } else if (parent && safe_str_neq(field, tag)) { /* For compatability with 0.6.x */ crm_debug("Creating intermediate parent %s between %s and %s", field, crm_element_name(parent), tag); parent = create_xml_node(parent, field); } if (parent == NULL) { parent = create_xml_node(NULL, tag); child = parent; } else { child = create_xml_node(parent, tag); } for (lpc = 0; lpc < msg->nfields; lpc++) { convert_ha_field(child, msg, lpc); } return parent; } static void add_ha_nocopy(HA_Message * parent, HA_Message * child, const char *field) { int next = parent->nfields; if (parent->nfields >= parent->nalloc && ha_msg_expand(parent) != HA_OK) { crm_err("Parent expansion failed"); return; } parent->names[next] = strdup(field); parent->nlens[next] = strlen(field); parent->values[next] = child; parent->vlens[next] = sizeof(HA_Message); parent->types[next] = FT_UNCOMPRESS; parent->nfields++; } static HA_Message * convert_xml_message_struct(HA_Message * parent, xmlNode * src_node, const char *field) { xmlNode *child = NULL; xmlNode *__crm_xml_iter = src_node->children; xmlAttrPtr prop_iter = src_node->properties; const char *name = NULL; const char *value = NULL; HA_Message *result = ha_msg_new(3); ha_msg_add(result, F_XML_TAGNAME, (const char *)src_node->name); while (prop_iter != NULL) { name = (const char *)prop_iter->name; value = (const char *)xmlGetProp(src_node, prop_iter->name); prop_iter = prop_iter->next; ha_msg_add(result, name, value); } while (__crm_xml_iter != NULL) { child = __crm_xml_iter; __crm_xml_iter = __crm_xml_iter->next; convert_xml_message_struct(result, child, NULL); } if (parent == NULL) { return result; } if (field) { HA_Message *holder = ha_msg_new(3); CRM_ASSERT(holder != NULL); ha_msg_add(holder, F_XML_TAGNAME, field); add_ha_nocopy(holder, result, (const char *)src_node->name); ha_msg_addstruct_compress(parent, field, holder); ha_msg_del(holder); } else { add_ha_nocopy(parent, result, (const char *)src_node->name); } return result; } static void convert_xml_child(HA_Message * msg, xmlNode * xml) { int orig = 0; int rc = BZ_OK; unsigned int len = 0; char *buffer = NULL; char *compressed = NULL; const char *name = NULL; name = (const char *)xml->name; buffer = dump_xml_unformatted(xml); orig = strlen(buffer); if (orig < CRM_BZ2_THRESHOLD) { ha_msg_add(msg, name, buffer); goto done; } len = (orig * 1.1) + 600; /* recomended size */ compressed = malloc(len); rc = BZ2_bzBuffToBuffCompress(compressed, &len, buffer, orig, CRM_BZ2_BLOCKS, 0, CRM_BZ2_WORK); if (rc != BZ_OK) { crm_err("Compression failed: %d", rc); free(compressed); convert_xml_message_struct(msg, xml, name); goto done; } free(buffer); buffer = compressed; crm_trace("Compression details: %d -> %d", orig, len); ha_msg_addbin(msg, name, buffer, len); done: free(buffer); # if 0 { unsigned int used = orig; char *uncompressed = NULL; crm_debug("Trying to decompress %d bytes", len); uncompressed = calloc(1, orig); rc = BZ2_bzBuffToBuffDecompress(uncompressed, &used, compressed, len, 1, 0); CRM_CHECK(rc == BZ_OK,; ); CRM_CHECK(used == orig,; ); crm_debug("rc=%d, used=%d", rc, used); if (rc != BZ_OK) { crm_exit(DAEMON_RESPAWN_STOP); } crm_debug("Original %s, decompressed %s", buffer, uncompressed); free(uncompressed); } # endif } static HA_Message * convert_xml_message(xmlNode * xml) { xmlNode *child = NULL; xmlAttrPtr pIter = NULL; HA_Message *result = NULL; result = ha_msg_new(3); ha_msg_add(result, F_XML_TAGNAME, (const char *)xml->name); for (pIter = xml->properties; pIter != NULL; pIter = pIter->next) { const char *p_name = (const char *)pIter->name; if (pIter->children) { const char *p_value = (const char *)pIter->children->content; ha_msg_add(result, p_name, p_value); } } for (child = __xml_first_child(xml); child != NULL; child = __xml_next(child)) { convert_xml_child(result, child); } return result; } gboolean crm_is_heartbeat_peer_active(const crm_node_t * node) { enum crm_proc_flag proc = text2proc(crm_system_name); if (node == NULL) { crm_trace("NULL"); return FALSE; } else if (safe_str_neq(node->state, CRM_NODE_MEMBER)) { crm_trace("%s: state=%s", node->uname, node->state); return FALSE; } else if ((node->processes & crm_proc_heartbeat) == 0) { crm_trace("%s: processes=%.16x", node->uname, node->processes); return FALSE; } else if (proc == crm_proc_none) { return TRUE; } else if ((node->processes & proc) == 0) { crm_trace("%s: proc %.16x not in %.16x", node->uname, proc, node->processes); return FALSE; } return TRUE; } crm_node_t * crm_update_ccm_node(const oc_ev_membership_t * oc, int offset, const char *state, uint64_t seq) { + enum crm_proc_flag this_proc = text2proc(crm_system_name); crm_node_t *peer = NULL; const char *uuid = NULL; CRM_CHECK(oc->m_array[offset].node_uname != NULL, return NULL); peer = crm_get_peer(0, oc->m_array[offset].node_uname); uuid = crm_peer_uuid(peer); crm_update_peer(__FUNCTION__, oc->m_array[offset].node_id, oc->m_array[offset].node_born_on, seq, -1, 0, uuid, oc->m_array[offset].node_uname, NULL, state); - if (safe_str_eq(CRM_NODE_ACTIVE, state)) { - /* Heartbeat doesn't send status notifications for nodes that were already part of the cluster */ - crm_update_peer_proc(__FUNCTION__, peer, crm_proc_heartbeat, ONLINESTATUS); - - /* Nor does it send status notifications for processes that were already active */ - crm_update_peer_proc(__FUNCTION__, peer, crm_proc_crmd, ONLINESTATUS); + if (safe_str_eq(CRM_NODE_MEMBER, state)) { + /* Heartbeat doesn't send status notifications for nodes that were already part of the cluster. + * Nor does it send status notifications for processes that were already active. + * Do not optimistically assume the peer client process to be online as well. + * We ask for cluster wide updated client status for crm_system_name + * directly in the ccm status callback, which will then tell us. + * For ourselves, we know. */ + enum crm_proc_flag flags = crm_proc_heartbeat; + const char *const_uname = heartbeat_cluster->llc_ops->get_mynodeid(heartbeat_cluster); + if (safe_str_eq(const_uname, peer->uname)) { + flags |= this_proc; + } + crm_update_peer_proc(__FUNCTION__, peer, flags, ONLINESTATUS); + } else { + /* crm_update_peer_proc(__FUNCTION__, peer, crm_proc_heartbeat, OFFLINESTATUS); */ + /* heartbeat may well be still alive. peer client process apparently vanished, though ... */ + crm_update_peer_proc(__FUNCTION__, peer, this_proc, OFFLINESTATUS); } return peer; } gboolean send_ha_message(ll_cluster_t * hb_conn, xmlNode * xml, const char *node, gboolean force_ordered) { gboolean all_is_good = TRUE; HA_Message *msg = convert_xml_message(xml); if (msg == NULL) { crm_err("cant send NULL message"); all_is_good = FALSE; } else if (hb_conn == NULL) { crm_err("No heartbeat connection specified"); all_is_good = FALSE; } else if (hb_conn->llc_ops->chan_is_connected(hb_conn) == FALSE) { crm_err("Not connected to Heartbeat"); all_is_good = FALSE; } else if (node != NULL) { char *host_lowercase = g_ascii_strdown(node, -1); if (hb_conn->llc_ops->send_ordered_nodemsg(hb_conn, msg, host_lowercase) != HA_OK) { all_is_good = FALSE; crm_err("Send failed"); } free(host_lowercase); } else if (force_ordered) { if (hb_conn->llc_ops->send_ordered_clustermsg(hb_conn, msg) != HA_OK) { all_is_good = FALSE; crm_err("Broadcast Send failed"); } } else { if (hb_conn->llc_ops->sendclustermsg(hb_conn, msg) != HA_OK) { all_is_good = FALSE; crm_err("Broadcast Send failed"); } } if (all_is_good == FALSE && hb_conn != NULL) { IPC_Channel *ipc = NULL; IPC_Queue *send_q = NULL; if (hb_conn->llc_ops->chan_is_connected(hb_conn) != HA_OK) { ipc = hb_conn->llc_ops->ipcchan(hb_conn); } if (ipc != NULL) { /* ipc->ops->resume_io(ipc); */ send_q = ipc->send_queue; } if (send_q != NULL) { CRM_CHECK(send_q->current_qlen < send_q->max_qlen,; ); } } if (all_is_good) { crm_log_xml_trace(xml, "outbound"); } else { crm_log_xml_warn(xml, "outbound"); } if (msg != NULL) { ha_msg_del(msg); } return all_is_good; } gboolean ha_msg_dispatch(ll_cluster_t * cluster_conn, gpointer user_data) { IPC_Channel *channel = NULL; crm_trace("Invoked"); if (cluster_conn != NULL) { channel = cluster_conn->llc_ops->ipcchan(cluster_conn); } CRM_CHECK(cluster_conn != NULL, return FALSE); CRM_CHECK(channel != NULL, return FALSE); if (channel != NULL && IPC_ISRCONN(channel)) { + struct ha_msg *msg; if (cluster_conn->llc_ops->msgready(cluster_conn) == 0) { crm_trace("no message ready yet"); } - /* invoke the callbacks but dont block */ - cluster_conn->llc_ops->rcvmsg(cluster_conn, 0); + /* invoke the callbacks but dont block. + * cluster_conn->llc_ops->rcvmsg(cluster_conn, 0); */ + msg = cluster_conn->llc_ops->readmsg(cluster_conn, 0); + if (msg) { + /* Message core refuses to pass on messages with F_TYPE not set. + * Messages with no specific F_TOID are notifications delivered to all. + */ + const char *msg_type = ha_msg_value(msg, F_TYPE) ?: "[type not set]"; + const char *msg_to_id = ha_msg_value(msg, F_TOID); + if (safe_str_eq(msg_to_id, crm_system_name)) { + crm_err("Ignored incoming message. Please set_msg_callback on %s", msg_type); + } else if (msg_to_id) { + /* Message core will not deliver messages addressed to someone else to us. + * Are we not registered as crm_system_name? */ + crm_notice("Ignored incoming message %s=%s %s=%s, please set_msg_callback", + F_TOID, msg_to_id, F_TYPE, msg_type); + } else { + crm_debug("Ignored incoming message %s=%s", F_TYPE, msg_type); + } + ha_msg_del(msg); + } } if (channel == NULL || channel->ch_status != IPC_CONNECT) { crm_info("Lost connection to heartbeat service."); return FALSE; } return TRUE; } gboolean register_heartbeat_conn(crm_cluster_t * cluster) { crm_node_t *peer = NULL; const char *const_uuid = NULL; const char *const_uname = NULL; crm_debug("Signing in with Heartbeat"); if (cluster->hb_conn->llc_ops->signon(cluster->hb_conn, crm_system_name) != HA_OK) { crm_err("Cannot sign on with heartbeat: %s", cluster->hb_conn->llc_ops->errmsg(cluster->hb_conn)); return FALSE; } if (HA_OK != cluster->hb_conn->llc_ops->set_msg_callback(cluster->hb_conn, crm_system_name, cluster->hb_dispatch, cluster->hb_conn)) { crm_err("Cannot set msg callback: %s", cluster->hb_conn->llc_ops->errmsg(cluster->hb_conn)); return FALSE; } else { void *handle = NULL; GLLclusterSource *(*g_main_add_cluster) (int priority, ll_cluster_t * api, gboolean can_recurse, gboolean(*dispatch) (ll_cluster_t * source_data, gpointer user_data), gpointer userdata, GDestroyNotify notify) = find_library_function(&handle, HEARTBEAT_LIBRARY, "G_main_add_ll_cluster", 1); (*g_main_add_cluster) (G_PRIORITY_HIGH, cluster->hb_conn, FALSE, ha_msg_dispatch, cluster->hb_conn, cluster->destroy); dlclose(handle); } const_uname = cluster->hb_conn->llc_ops->get_mynodeid(cluster->hb_conn); CRM_CHECK(const_uname != NULL, return FALSE); peer = crm_get_peer(0, const_uname); const_uuid = crm_peer_uuid(peer); CRM_CHECK(const_uuid != NULL, return FALSE); crm_info("Hostname: %s", const_uname); crm_info("UUID: %s", const_uuid); cluster->uname = strdup(const_uname); cluster->uuid = strdup(const_uuid); return TRUE; } gboolean ccm_have_quorum(oc_ed_t event) { if (event == OC_EV_MS_NEW_MEMBERSHIP || event == OC_EV_MS_PRIMARY_RESTORED) { return TRUE; } return FALSE; } const char * ccm_event_name(oc_ed_t event) { if (event == OC_EV_MS_NEW_MEMBERSHIP) { return "NEW MEMBERSHIP"; } else if (event == OC_EV_MS_NOT_PRIMARY) { return "NOT PRIMARY"; } else if (event == OC_EV_MS_PRIMARY_RESTORED) { return "PRIMARY RESTORED"; } else if (event == OC_EV_MS_EVICTED) { return "EVICTED"; } else if (event == OC_EV_MS_INVALID) { return "INVALID"; } return "NO QUORUM MEMBERSHIP"; } gboolean heartbeat_initialize_nodelist(void *cluster, gboolean force_member, xmlNode * xml_parent) { const char *ha_node = NULL; ll_cluster_t *conn = cluster; if (conn == NULL) { crm_debug("Not connected"); return FALSE; } /* Async get client status information in the cluster */ crm_info("Requesting the list of configured nodes"); conn->llc_ops->init_nodewalk(conn); do { xmlNode *node = NULL; crm_node_t *peer = NULL; const char *ha_node_type = NULL; const char *ha_node_uuid = NULL; ha_node = conn->llc_ops->nextnode(conn); if (ha_node == NULL) { continue; } ha_node_type = conn->llc_ops->node_type(conn, ha_node); if (safe_str_neq(NORMALNODE, ha_node_type)) { crm_debug("Node %s: skipping '%s'", ha_node, ha_node_type); continue; } peer = crm_get_peer(0, ha_node); ha_node_uuid = crm_peer_uuid(peer); if (ha_node_uuid == NULL) { crm_warn("Node %s: no uuid found", ha_node); continue; } crm_debug("Node: %s (uuid: %s)", ha_node, ha_node_uuid); node = create_xml_node(xml_parent, XML_CIB_TAG_NODE); crm_xml_add(node, XML_ATTR_ID, ha_node_uuid); crm_xml_add(node, XML_ATTR_UNAME, ha_node); crm_xml_add(node, XML_ATTR_TYPE, ha_node_type); } while (ha_node != NULL); conn->llc_ops->end_nodewalk(conn); return TRUE; } #endif diff --git a/lib/cluster/membership.c b/lib/cluster/membership.c index 70a03215fe..cb49f15f88 100644 --- a/lib/cluster/membership.c +++ b/lib/cluster/membership.c @@ -1,744 +1,744 @@ /* * Copyright (C) 2004 Andrew Beekhof * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #ifndef _GNU_SOURCE # define _GNU_SOURCE #endif #include #include #include #include #include #include #include #include #include #include GHashTable *crm_peer_cache = NULL; GHashTable *crm_remote_peer_cache = NULL; unsigned long long crm_peer_seq = 0; gboolean crm_have_quorum = FALSE; int crm_remote_peer_cache_size(void) { if (crm_remote_peer_cache == NULL) { return 0; } return g_hash_table_size(crm_remote_peer_cache); } void crm_remote_peer_cache_add(const char *node_name) { crm_node_t *node = g_hash_table_lookup(crm_remote_peer_cache, node_name); if (node == NULL) { crm_trace("added %s to remote cache", node_name); node = calloc(1, sizeof(crm_node_t)); node->flags = crm_remote_node; CRM_ASSERT(node); node->uname = strdup(node_name); node->uuid = strdup(node_name); node->state = strdup(CRM_NODE_MEMBER); g_hash_table_replace(crm_remote_peer_cache, node->uname, node); } } void crm_remote_peer_cache_remove(const char *node_name) { g_hash_table_remove(crm_remote_peer_cache, node_name); } static void remote_cache_refresh_helper(xmlNode *cib, const char *xpath, const char *field, int flags) { const char *remote = NULL; crm_node_t *node = NULL; xmlXPathObjectPtr xpathObj = NULL; int max = 0; int lpc = 0; xpathObj = xpath_search(cib, xpath); max = numXpathResults(xpathObj); for (lpc = 0; lpc < max; lpc++) { xmlNode *xml = getXpathResult(xpathObj, lpc); CRM_LOG_ASSERT(xml != NULL); if(xml != NULL) { remote = crm_element_value(xml, field); } if (remote) { crm_trace("added %s to remote cache", remote); node = calloc(1, sizeof(crm_node_t)); node->flags = flags; CRM_ASSERT(node); node->uname = strdup(remote); node->uuid = strdup(remote); node->state = strdup(CRM_NODE_MEMBER); g_hash_table_replace(crm_remote_peer_cache, node->uname, node); } } freeXpathObject(xpathObj); } void crm_remote_peer_cache_refresh(xmlNode *cib) { const char *xpath = NULL; g_hash_table_remove_all(crm_remote_peer_cache); /* remote nodes associated with a cluster resource */ xpath = "//" XML_TAG_CIB "//" XML_CIB_TAG_CONFIGURATION "//" XML_CIB_TAG_RESOURCE "//" XML_TAG_META_SETS "//" XML_CIB_TAG_NVPAIR "[@name='remote-node']"; remote_cache_refresh_helper(cib, xpath, "value", crm_remote_node | crm_remote_container); /* baremetal nodes defined by connection resources*/ xpath = "//" XML_TAG_CIB "//" XML_CIB_TAG_CONFIGURATION "//" XML_CIB_TAG_RESOURCE "[@type='remote'][@provider='pacemaker']"; remote_cache_refresh_helper(cib, xpath, "id", crm_remote_node | crm_remote_baremetal); /* baremetal nodes we have seen in the config that may or may not have connection * resources associated with them anymore */ xpath = "//" XML_TAG_CIB "//" XML_CIB_TAG_STATUS "//" XML_CIB_TAG_STATE "[@remote_node='true']"; remote_cache_refresh_helper(cib, xpath, "id", crm_remote_node | crm_remote_baremetal); } gboolean crm_is_peer_active(const crm_node_t * node) { if(node == NULL) { return FALSE; } if (is_set(node->flags, crm_remote_node)) { /* remote nodes are never considered active members. This * guarantees they will never be considered for DC membership.*/ return FALSE; } #if SUPPORT_COROSYNC if (is_openais_cluster()) { return crm_is_corosync_peer_active(node); } #endif #if SUPPORT_HEARTBEAT if (is_heartbeat_cluster()) { return crm_is_heartbeat_peer_active(node); } #endif crm_err("Unhandled cluster type: %s", name_for_cluster_type(get_cluster_type())); return FALSE; } static gboolean crm_reap_dead_member(gpointer key, gpointer value, gpointer user_data) { crm_node_t *node = value; crm_node_t *search = user_data; if (search == NULL) { return FALSE; } else if (search->id && node->id != search->id) { return FALSE; } else if (search->id == 0 && safe_str_neq(node->uname, search->uname)) { return FALSE; } else if (crm_is_peer_active(value) == FALSE) { crm_notice("Removing %s/%u from the membership list", node->uname, node->id); return TRUE; } return FALSE; } guint reap_crm_member(uint32_t id, const char *name) { int matches = 0; crm_node_t search; if (crm_peer_cache == NULL) { crm_trace("Nothing to do, cache not initialized"); return 0; } search.id = id; search.uname = name ? strdup(name) : NULL; matches = g_hash_table_foreach_remove(crm_peer_cache, crm_reap_dead_member, &search); if(matches) { crm_notice("Purged %d peers with id=%u and/or uname=%s from the membership cache", matches, search.id, search.uname); } else { crm_info("No peers with id=%u and/or uname=%s exist", id, name); } free(search.uname); return matches; } static void crm_count_peer(gpointer key, gpointer value, gpointer user_data) { guint *count = user_data; crm_node_t *node = value; if (crm_is_peer_active(node)) { *count = *count + 1; } } guint crm_active_peers(void) { guint count = 0; if (crm_peer_cache) { g_hash_table_foreach(crm_peer_cache, crm_count_peer, &count); } return count; } static void destroy_crm_node(gpointer data) { crm_node_t *node = data; crm_trace("Destroying entry for node %u: %s", node->id, node->uname); free(node->addr); free(node->uname); free(node->state); free(node->uuid); free(node->expected); free(node); } void crm_peer_init(void) { if (crm_peer_cache == NULL) { crm_peer_cache = g_hash_table_new_full(crm_strcase_hash, crm_strcase_equal, free, destroy_crm_node); } if (crm_remote_peer_cache == NULL) { crm_remote_peer_cache = g_hash_table_new_full(crm_strcase_hash, crm_strcase_equal, NULL, destroy_crm_node); } } void crm_peer_destroy(void) { if (crm_peer_cache != NULL) { crm_trace("Destroying peer cache with %d members", g_hash_table_size(crm_peer_cache)); g_hash_table_destroy(crm_peer_cache); crm_peer_cache = NULL; } if (crm_remote_peer_cache != NULL) { crm_trace("Destroying remote peer cache with %d members", g_hash_table_size(crm_remote_peer_cache)); g_hash_table_destroy(crm_remote_peer_cache); crm_remote_peer_cache = NULL; } } void (*crm_status_callback) (enum crm_status_type, crm_node_t *, const void *) = NULL; void crm_set_status_callback(void (*dispatch) (enum crm_status_type, crm_node_t *, const void *)) { crm_status_callback = dispatch; } static void crm_dump_peer_hash(int level, const char *caller) { GHashTableIter iter; const char *id = NULL; crm_node_t *node = NULL; g_hash_table_iter_init(&iter, crm_peer_cache); while (g_hash_table_iter_next(&iter, (gpointer *) &id, (gpointer *) &node)) { do_crm_log(level, "%s: Node %u/%s = %p - %s", caller, node->id, node->uname, node, id); } } static gboolean crm_hash_find_by_data(gpointer key, gpointer value, gpointer user_data) { if(value == user_data) { return TRUE; } return FALSE; } crm_node_t * crm_find_peer_full(unsigned int id, const char *uname, int flags) { crm_node_t *node = NULL; CRM_ASSERT(id > 0 || uname != NULL); crm_peer_init(); if (flags & CRM_GET_PEER_REMOTE) { node = g_hash_table_lookup(crm_remote_peer_cache, uname); } if (node == NULL && (flags & CRM_GET_PEER_CLUSTER)) { node = crm_find_peer(id, uname); } return node; } crm_node_t * crm_get_peer_full(unsigned int id, const char *uname, int flags) { crm_node_t *node = NULL; CRM_ASSERT(id > 0 || uname != NULL); crm_peer_init(); if (flags & CRM_GET_PEER_REMOTE) { node = g_hash_table_lookup(crm_remote_peer_cache, uname); } if (node == NULL && (flags & CRM_GET_PEER_CLUSTER)) { node = crm_get_peer(id, uname); } return node; } crm_node_t * crm_find_peer(unsigned int id, const char *uname) { GHashTableIter iter; crm_node_t *node = NULL; crm_node_t *by_id = NULL; crm_node_t *by_name = NULL; CRM_ASSERT(id > 0 || uname != NULL); crm_peer_init(); if (uname != NULL) { g_hash_table_iter_init(&iter, crm_peer_cache); while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &node)) { if(node->uname && strcasecmp(node->uname, uname) == 0) { crm_trace("Name match: %s = %p", node->uname, node); by_name = node; break; } } } if (id > 0) { g_hash_table_iter_init(&iter, crm_peer_cache); while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &node)) { if(node->id == id) { crm_trace("ID match: %u = %p", node->id, node); by_id = node; break; } } } node = by_id; /* Good default */ if(by_id == by_name) { /* Nothing to do if they match (both NULL counts) */ crm_trace("Consistent: %p for %u/%s", by_id, id, uname); } else if(by_id == NULL && by_name) { crm_trace("Only one: %p for %u/%s", by_name, id, uname); if(id && by_name->id) { crm_dump_peer_hash(LOG_WARNING, __FUNCTION__); crm_crit("Node %u and %u share the same name '%s'", id, by_name->id, uname); node = NULL; /* Create a new one */ } else { node = by_name; } } else if(by_name == NULL && by_id) { crm_trace("Only one: %p for %u/%s", by_id, id, uname); if(uname && by_id->uname) { crm_dump_peer_hash(LOG_WARNING, __FUNCTION__); crm_crit("Node '%s' and '%s' share the same cluster nodeid %u: assuming '%s' is correct", uname, by_id->uname, id, uname); } } else if(uname && by_id->uname) { if(safe_str_eq(uname, by_id->uname)) { crm_notice("Node '%s' has changed its ID from %u to %u", by_id->uname, by_name->id, by_id->id); g_hash_table_foreach_remove(crm_peer_cache, crm_hash_find_by_data, by_name); } else { crm_warn("Node '%s' and '%s' share the same cluster nodeid: %u %s", by_id->uname, by_name->uname, id, uname); crm_dump_peer_hash(LOG_INFO, __FUNCTION__); crm_abort(__FILE__, __FUNCTION__, __LINE__, "member weirdness", TRUE, TRUE); } } else if(id && by_name->id) { crm_warn("Node %u and %u share the same name: '%s'", by_id->id, by_name->id, uname); } else { /* Simple merge */ /* Only corosync based clusters use nodeid's * * The functions that call crm_update_peer_state() only know nodeid * so 'by_id' is authorative when merging * * Same for crm_update_peer_proc() */ crm_dump_peer_hash(LOG_DEBUG, __FUNCTION__); crm_info("Merging %p into %p", by_name, by_id); g_hash_table_foreach_remove(crm_peer_cache, crm_hash_find_by_data, by_name); } return node; } #if SUPPORT_COROSYNC static guint crm_remove_conflicting_peer(crm_node_t *node) { int matches = 0; GHashTableIter iter; crm_node_t *existing_node = NULL; if (node->id == 0 || node->uname == NULL) { return 0; } # if !SUPPORT_PLUGIN if (corosync_cmap_has_config("nodelist") != 0) { return 0; } # endif g_hash_table_iter_init(&iter, crm_peer_cache); while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &existing_node)) { if (existing_node->id > 0 && existing_node->id != node->id && existing_node->uname != NULL && strcasecmp(existing_node->uname, node->uname) == 0) { if (crm_is_peer_active(existing_node)) { continue; } crm_warn("Removing cached offline node %u/%s which has conflicting uname with %u", existing_node->id, existing_node->uname, node->id); g_hash_table_iter_remove(&iter); matches++; } } return matches; } #endif /* coverity[-alloc] Memory is referenced in one or both hashtables */ crm_node_t * crm_get_peer(unsigned int id, const char *uname) { crm_node_t *node = NULL; char *uname_lookup = NULL; CRM_ASSERT(id > 0 || uname != NULL); crm_peer_init(); node = crm_find_peer(id, uname); /* if uname wasn't provided, and find_peer did not turn up a uname based on id. * we need to do a lookup of the node name using the id in the cluster membership. */ if ((node == NULL || node->uname == NULL) && (uname == NULL)) { uname_lookup = get_node_name(id); } if (uname_lookup) { crm_trace("Inferred a name of '%s' for node %u", uname, id); uname = uname_lookup; /* try to turn up the node one more time now that we know the uname. */ if (node == NULL) { node = crm_find_peer(id, uname); } } if (node == NULL) { char *uniqueid = crm_generate_uuid(); node = calloc(1, sizeof(crm_node_t)); CRM_ASSERT(node); crm_info("Created entry %s/%p for node %s/%u (%d total)", uniqueid, node, uname, id, 1 + g_hash_table_size(crm_peer_cache)); g_hash_table_replace(crm_peer_cache, uniqueid, node); } if(id > 0 && uname && (node->id == 0 || node->uname == NULL)) { crm_info("Node %u is now known as %s", id, uname); } if(id > 0 && node->id == 0) { node->id = id; } if(uname && node->uname == NULL) { int lpc, len = strlen(uname); for (lpc = 0; lpc < len; lpc++) { if (uname[lpc] >= 'A' && uname[lpc] <= 'Z') { crm_warn("Node names with capitals are discouraged, consider changing '%s' to something else", uname); break; } } node->uname = strdup(uname); if (crm_status_callback) { crm_status_callback(crm_status_uname, node, NULL); } #if SUPPORT_COROSYNC if (is_openais_cluster()) { crm_remove_conflicting_peer(node); } #endif } if(node->uuid == NULL) { const char *uuid = crm_peer_uuid(node); if (uuid) { crm_info("Node %u has uuid %s", id, uuid); } else { crm_info("Cannot obtain a UUID for node %u/%s", id, node->uname); } } free(uname_lookup); return node; } crm_node_t * crm_update_peer(const char *source, unsigned int id, uint64_t born, uint64_t seen, int32_t votes, uint32_t children, const char *uuid, const char *uname, const char *addr, const char *state) { #if SUPPORT_PLUGIN gboolean addr_changed = FALSE; gboolean votes_changed = FALSE; #endif crm_node_t *node = NULL; id = get_corosync_id(id, uuid); node = crm_get_peer(id, uname); CRM_ASSERT(node != NULL); if (node->uuid == NULL) { if (is_openais_cluster()) { /* Yes, overrule whatever was passed in */ crm_peer_uuid(node); } else if (uuid != NULL) { node->uuid = strdup(uuid); } } if (children > 0) { crm_update_peer_proc(source, node, children, state); } if (state != NULL) { crm_update_peer_state(source, node, state, seen); } #if SUPPORT_HEARTBEAT if (born != 0) { node->born = born; } #endif #if SUPPORT_PLUGIN /* These were only used by the plugin */ if (born != 0) { node->born = born; } if (votes > 0 && node->votes != votes) { votes_changed = TRUE; node->votes = votes; } if (addr != NULL) { if (node->addr == NULL || crm_str_eq(node->addr, addr, FALSE) == FALSE) { addr_changed = TRUE; free(node->addr); node->addr = strdup(addr); } } if (addr_changed || votes_changed) { crm_info("%s: Node %s: id=%u state=%s addr=%s%s votes=%d%s born=" U64T " seen=" U64T " proc=%.32x", source, node->uname, node->id, node->state, node->addr, addr_changed ? " (new)" : "", node->votes, votes_changed ? " (new)" : "", node->born, node->last_seen, node->processes); } #endif return node; } void crm_update_peer_proc(const char *source, crm_node_t * node, uint32_t flag, const char *status) { uint32_t last = 0; gboolean changed = FALSE; CRM_CHECK(node != NULL, crm_err("%s: Could not set %s to %s for NULL", source, peer2text(flag), status); return); last = node->processes; if (status == NULL) { node->processes = flag; if (node->processes != last) { changed = TRUE; } } else if (safe_str_eq(status, ONLINESTATUS)) { - if ((node->processes & flag) == 0) { + if ((node->processes & flag) != flag) { set_bit(node->processes, flag); changed = TRUE; } #if SUPPORT_PLUGIN } else if (safe_str_eq(status, CRM_NODE_MEMBER)) { if (flag > 0 && node->processes != flag) { node->processes = flag; changed = TRUE; } #endif } else if (node->processes & flag) { clear_bit(node->processes, flag); changed = TRUE; } if (changed) { if (status == NULL && flag <= crm_proc_none) { crm_info("%s: Node %s[%u] - all processes are now offline", source, node->uname, node->id); } else { crm_info("%s: Node %s[%u] - %s is now %s", source, node->uname, node->id, peer2text(flag), status); } if (crm_status_callback) { crm_status_callback(crm_status_processes, node, &last); } } else { crm_trace("%s: Node %s[%u] - %s is unchanged (%s)", source, node->uname, node->id, peer2text(flag), status); } } void crm_update_peer_expected(const char *source, crm_node_t * node, const char *expected) { char *last = NULL; gboolean changed = FALSE; CRM_CHECK(node != NULL, crm_err("%s: Could not set 'expected' to %s", source, expected); return); last = node->expected; if (expected != NULL && safe_str_neq(node->expected, expected)) { node->expected = strdup(expected); changed = TRUE; } if (changed) { crm_info("%s: Node %s[%u] - expected state is now %s (was %s)", source, node->uname, node->id, expected, last); free(last); } else { crm_trace("%s: Node %s[%u] - expected state is unchanged (%s)", source, node->uname, node->id, expected); } } void crm_update_peer_state(const char *source, crm_node_t * node, const char *state, int membership) { char *last = NULL; gboolean changed = FALSE; CRM_CHECK(node != NULL, crm_err("%s: Could not set 'state' to %s", source, state); return); last = node->state; if (state != NULL && safe_str_neq(node->state, state)) { node->state = strdup(state); changed = TRUE; } if (membership != 0 && safe_str_eq(node->state, CRM_NODE_MEMBER)) { node->last_seen = membership; } if (changed) { crm_notice("%s: Node %s[%u] - state is now %s (was %s)", source, node->uname, node->id, state, last); if (crm_status_callback) { enum crm_status_type status_type = crm_status_nstate; if (is_set(node->flags, crm_remote_node)) { status_type = crm_status_rstate; } crm_status_callback(status_type, node, last); } free(last); } else { crm_trace("%s: Node %s[%u] - state is unchanged (%s)", source, node->uname, node->id, state); } } int crm_terminate_member(int nodeid, const char *uname, void *unused) { /* Always use the synchronous, non-mainloop version */ return stonith_api_kick(nodeid, uname, 120, TRUE); } int crm_terminate_member_no_mainloop(int nodeid, const char *uname, int *connection) { return stonith_api_kick(nodeid, uname, 120, TRUE); } diff --git a/lib/lrmd/lrmd_client.c b/lib/lrmd/lrmd_client.c index 74bd69299c..60f9d5142b 100644 --- a/lib/lrmd/lrmd_client.c +++ b/lib/lrmd/lrmd_client.c @@ -1,2070 +1,2165 @@ /* * Copyright (c) 2012 David Vossel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_GNUTLS_GNUTLS_H # undef KEYFILE # include #endif #include #include #include #include #include CRM_TRACE_INIT_DATA(lrmd); static int lrmd_api_disconnect(lrmd_t * lrmd); static int lrmd_api_is_connected(lrmd_t * lrmd); /* IPC proxy functions */ int lrmd_internal_proxy_send(lrmd_t * lrmd, xmlNode *msg); static void lrmd_internal_proxy_dispatch(lrmd_t *lrmd, xmlNode *msg); void lrmd_internal_set_proxy_callback(lrmd_t * lrmd, void *userdata, void (*callback)(lrmd_t *lrmd, void *userdata, xmlNode *msg)); #ifdef HAVE_GNUTLS_GNUTLS_H # define LRMD_CLIENT_HANDSHAKE_TIMEOUT 5000 /* 5 seconds */ gnutls_psk_client_credentials_t psk_cred_s; int lrmd_tls_set_key(gnutls_datum_t * key); static void lrmd_tls_disconnect(lrmd_t * lrmd); static int global_remote_msg_id = 0; int lrmd_tls_send_msg(crm_remote_t * session, xmlNode * msg, uint32_t id, const char *msg_type); static void lrmd_tls_connection_destroy(gpointer userdata); #endif typedef struct lrmd_private_s { enum client_type type; char *token; mainloop_io_t *source; /* IPC parameters */ crm_ipc_t *ipc; crm_remote_t *remote; /* Extra TLS parameters */ char *remote_nodename; #ifdef HAVE_GNUTLS_GNUTLS_H char *server; int port; gnutls_psk_client_credentials_t psk_cred_c; /* while the async connection is occuring, this is the id * of the connection timeout timer. */ int async_timer; int sock; /* since tls requires a round trip across the network for a * request/reply, there are times where we just want to be able * to send a request from the client and not wait around (or even care * about) what the reply is. */ int expected_late_replies; GList *pending_notify; crm_trigger_t *process_notify; #endif lrmd_event_callback callback; /* Internal IPC proxy msg passing for remote guests */ void (*proxy_callback)(lrmd_t *lrmd, void *userdata, xmlNode *msg); void *proxy_callback_userdata; } lrmd_private_t; static lrmd_list_t * lrmd_list_add(lrmd_list_t * head, const char *value) { lrmd_list_t *p, *end; p = calloc(1, sizeof(lrmd_list_t)); p->val = strdup(value); end = head; while (end && end->next) { end = end->next; } if (end) { end->next = p; } else { head = p; } return head; } void lrmd_list_freeall(lrmd_list_t * head) { lrmd_list_t *p; while (head) { char *val = (char *)head->val; p = head->next; free(val); free(head); head = p; } } lrmd_key_value_t * lrmd_key_value_add(lrmd_key_value_t * head, const char *key, const char *value) { lrmd_key_value_t *p, *end; p = calloc(1, sizeof(lrmd_key_value_t)); p->key = strdup(key); p->value = strdup(value); end = head; while (end && end->next) { end = end->next; } if (end) { end->next = p; } else { head = p; } return head; } void lrmd_key_value_freeall(lrmd_key_value_t * head) { lrmd_key_value_t *p; while (head) { p = head->next; free(head->key); free(head->value); free(head); head = p; } } static void dup_attr(gpointer key, gpointer value, gpointer user_data) { g_hash_table_replace(user_data, strdup(key), strdup(value)); } lrmd_event_data_t * lrmd_copy_event(lrmd_event_data_t * event) { lrmd_event_data_t *copy = NULL; copy = calloc(1, sizeof(lrmd_event_data_t)); /* This will get all the int values. * we just have to be careful not to leave any * dangling pointers to strings. */ memcpy(copy, event, sizeof(lrmd_event_data_t)); copy->rsc_id = event->rsc_id ? strdup(event->rsc_id) : NULL; copy->op_type = event->op_type ? strdup(event->op_type) : NULL; copy->user_data = event->user_data ? strdup(event->user_data) : NULL; copy->output = event->output ? strdup(event->output) : NULL; copy->exit_reason = event->exit_reason ? strdup(event->exit_reason) : NULL; copy->remote_nodename = event->remote_nodename ? strdup(event->remote_nodename) : NULL; if (event->params) { copy->params = g_hash_table_new_full(crm_str_hash, g_str_equal, g_hash_destroy_str, g_hash_destroy_str); if (copy->params != NULL) { g_hash_table_foreach(event->params, dup_attr, copy->params); } } return copy; } void lrmd_free_event(lrmd_event_data_t * event) { if (!event) { return; } /* free gives me grief if i try to cast */ free((char *)event->rsc_id); free((char *)event->op_type); free((char *)event->user_data); free((char *)event->output); free((char *)event->exit_reason); free((char *)event->remote_nodename); if (event->params) { g_hash_table_destroy(event->params); } free(event); } static int lrmd_dispatch_internal(lrmd_t * lrmd, xmlNode * msg) { const char *type; const char *proxy_session = crm_element_value(msg, F_LRMD_IPC_SESSION); lrmd_private_t *native = lrmd->private; lrmd_event_data_t event = { 0, }; if (proxy_session != NULL) { /* this is proxy business */ lrmd_internal_proxy_dispatch(lrmd, msg); return 1; } else if (!native->callback) { /* no callback set */ crm_trace("notify event received but client has not set callback"); return 1; } event.remote_nodename = native->remote_nodename; type = crm_element_value(msg, F_LRMD_OPERATION); crm_element_value_int(msg, F_LRMD_CALLID, &event.call_id); event.rsc_id = crm_element_value(msg, F_LRMD_RSC_ID); if (crm_str_eq(type, LRMD_OP_RSC_REG, TRUE)) { event.type = lrmd_event_register; } else if (crm_str_eq(type, LRMD_OP_RSC_UNREG, TRUE)) { event.type = lrmd_event_unregister; } else if (crm_str_eq(type, LRMD_OP_RSC_EXEC, TRUE)) { crm_element_value_int(msg, F_LRMD_TIMEOUT, &event.timeout); crm_element_value_int(msg, F_LRMD_RSC_INTERVAL, &event.interval); crm_element_value_int(msg, F_LRMD_RSC_START_DELAY, &event.start_delay); crm_element_value_int(msg, F_LRMD_EXEC_RC, (int *)&event.rc); crm_element_value_int(msg, F_LRMD_OP_STATUS, &event.op_status); crm_element_value_int(msg, F_LRMD_RSC_DELETED, &event.rsc_deleted); crm_element_value_int(msg, F_LRMD_RSC_RUN_TIME, (int *)&event.t_run); crm_element_value_int(msg, F_LRMD_RSC_RCCHANGE_TIME, (int *)&event.t_rcchange); crm_element_value_int(msg, F_LRMD_RSC_EXEC_TIME, (int *)&event.exec_time); crm_element_value_int(msg, F_LRMD_RSC_QUEUE_TIME, (int *)&event.queue_time); event.op_type = crm_element_value(msg, F_LRMD_RSC_ACTION); event.user_data = crm_element_value(msg, F_LRMD_RSC_USERDATA_STR); event.output = crm_element_value(msg, F_LRMD_RSC_OUTPUT); event.exit_reason = crm_element_value(msg, F_LRMD_RSC_EXIT_REASON); event.type = lrmd_event_exec_complete; event.params = xml2list(msg); } else if (crm_str_eq(type, LRMD_OP_NEW_CLIENT, TRUE)) { event.type = lrmd_event_new_client; } else if (crm_str_eq(type, LRMD_OP_POKE, TRUE)) { event.type = lrmd_event_poke; } else { return 1; } crm_trace("op %s notify event received", type); native->callback(&event); if (event.params) { g_hash_table_destroy(event.params); } return 1; } static int lrmd_ipc_dispatch(const char *buffer, ssize_t length, gpointer userdata) { lrmd_t *lrmd = userdata; lrmd_private_t *native = lrmd->private; xmlNode *msg; int rc; if (!native->callback) { /* no callback set */ return 1; } msg = string2xml(buffer); rc = lrmd_dispatch_internal(lrmd, msg); free_xml(msg); return rc; } #ifdef HAVE_GNUTLS_GNUTLS_H static void lrmd_free_xml(gpointer userdata) { free_xml((xmlNode *) userdata); } static int lrmd_tls_connected(lrmd_t * lrmd) { lrmd_private_t *native = lrmd->private; if (native->remote->tls_session) { return TRUE; } return FALSE; } static int lrmd_tls_dispatch(gpointer userdata) { lrmd_t *lrmd = userdata; lrmd_private_t *native = lrmd->private; xmlNode *xml = NULL; int rc = 0; int disconnected = 0; if (lrmd_tls_connected(lrmd) == FALSE) { crm_trace("tls dispatch triggered after disconnect"); return 0; } crm_trace("tls_dispatch triggered"); /* First check if there are any pending notifies to process that came * while we were waiting for replies earlier. */ if (native->pending_notify) { GList *iter = NULL; crm_trace("Processing pending notifies"); for (iter = native->pending_notify; iter; iter = iter->next) { lrmd_dispatch_internal(lrmd, iter->data); } g_list_free_full(native->pending_notify, lrmd_free_xml); native->pending_notify = NULL; } /* Next read the current buffer and see if there are any messages to handle. */ rc = crm_remote_ready(native->remote, 0); if (rc == 0) { /* nothing to read, see if any full messages are already in buffer. */ xml = crm_remote_parse_buffer(native->remote); } else if (rc < 0) { disconnected = 1; } else { crm_remote_recv(native->remote, -1, &disconnected); xml = crm_remote_parse_buffer(native->remote); } while (xml) { const char *msg_type = crm_element_value(xml, F_LRMD_REMOTE_MSG_TYPE); if (safe_str_eq(msg_type, "notify")) { lrmd_dispatch_internal(lrmd, xml); } else if (safe_str_eq(msg_type, "reply")) { if (native->expected_late_replies > 0) { native->expected_late_replies--; } else { int reply_id = 0; crm_element_value_int(xml, F_LRMD_CALLID, &reply_id); /* if this happens, we want to know about it */ crm_err("Got outdated reply %d", reply_id); } } free_xml(xml); xml = crm_remote_parse_buffer(native->remote); } if (disconnected) { crm_info("Server disconnected while reading remote server msg."); lrmd_tls_disconnect(lrmd); return 0; } return 1; } #endif /* Not used with mainloop */ int lrmd_poll(lrmd_t * lrmd, int timeout) { lrmd_private_t *native = lrmd->private; switch (native->type) { case CRM_CLIENT_IPC: return crm_ipc_ready(native->ipc); #ifdef HAVE_GNUTLS_GNUTLS_H case CRM_CLIENT_TLS: if (native->pending_notify) { return 1; } return crm_remote_ready(native->remote, 0); #endif default: crm_err("Unsupported connection type: %d", native->type); } return 0; } /* Not used with mainloop */ bool lrmd_dispatch(lrmd_t * lrmd) { lrmd_private_t *private = NULL; CRM_ASSERT(lrmd != NULL); private = lrmd->private; switch (private->type) { case CRM_CLIENT_IPC: while (crm_ipc_ready(private->ipc)) { if (crm_ipc_read(private->ipc) > 0) { const char *msg = crm_ipc_buffer(private->ipc); lrmd_ipc_dispatch(msg, strlen(msg), lrmd); } } break; #ifdef HAVE_GNUTLS_GNUTLS_H case CRM_CLIENT_TLS: lrmd_tls_dispatch(lrmd); break; #endif default: crm_err("Unsupported connection type: %d", private->type); } if (lrmd_api_is_connected(lrmd) == FALSE) { crm_err("Connection closed"); return FALSE; } return TRUE; } static xmlNode * lrmd_create_op(const char *token, const char *op, xmlNode * data, enum lrmd_call_options options) { xmlNode *op_msg = create_xml_node(NULL, "lrmd_command"); CRM_CHECK(op_msg != NULL, return NULL); CRM_CHECK(token != NULL, return NULL); crm_xml_add(op_msg, F_XML_TAGNAME, "lrmd_command"); crm_xml_add(op_msg, F_TYPE, T_LRMD); crm_xml_add(op_msg, F_LRMD_CALLBACK_TOKEN, token); crm_xml_add(op_msg, F_LRMD_OPERATION, op); crm_trace("Sending call options: %.8lx, %d", (long)options, options); crm_xml_add_int(op_msg, F_LRMD_CALLOPTS, options); if (data != NULL) { add_message_xml(op_msg, F_LRMD_CALLDATA, data); } return op_msg; } static void lrmd_ipc_connection_destroy(gpointer userdata) { lrmd_t *lrmd = userdata; lrmd_private_t *native = lrmd->private; crm_info("IPC connection destroyed"); /* Prevent these from being cleaned up in lrmd_api_disconnect() */ native->ipc = NULL; native->source = NULL; if (native->callback) { lrmd_event_data_t event = { 0, }; event.type = lrmd_event_disconnect; event.remote_nodename = native->remote_nodename; native->callback(&event); } } #ifdef HAVE_GNUTLS_GNUTLS_H static void lrmd_tls_connection_destroy(gpointer userdata) { lrmd_t *lrmd = userdata; lrmd_private_t *native = lrmd->private; crm_info("TLS connection destroyed"); if (native->remote->tls_session) { gnutls_bye(*native->remote->tls_session, GNUTLS_SHUT_RDWR); gnutls_deinit(*native->remote->tls_session); gnutls_free(native->remote->tls_session); } if (native->psk_cred_c) { gnutls_psk_free_client_credentials(native->psk_cred_c); } if (native->sock) { close(native->sock); } if (native->process_notify) { mainloop_destroy_trigger(native->process_notify); native->process_notify = NULL; } if (native->pending_notify) { g_list_free_full(native->pending_notify, lrmd_free_xml); native->pending_notify = NULL; } free(native->remote->buffer); native->remote->buffer = NULL; native->source = 0; native->sock = 0; native->psk_cred_c = NULL; native->remote->tls_session = NULL; native->sock = 0; if (native->callback) { lrmd_event_data_t event = { 0, }; event.remote_nodename = native->remote_nodename; event.type = lrmd_event_disconnect; native->callback(&event); } return; } int lrmd_tls_send_msg(crm_remote_t * session, xmlNode * msg, uint32_t id, const char *msg_type) { int rc = -1; crm_xml_add_int(msg, F_LRMD_REMOTE_MSG_ID, id); crm_xml_add(msg, F_LRMD_REMOTE_MSG_TYPE, msg_type); rc = crm_remote_send(session, msg); if (rc < 0) { crm_err("Failed to send remote lrmd tls msg, rc = %d", rc); return rc; } return rc; } static xmlNode * lrmd_tls_recv_reply(lrmd_t * lrmd, int total_timeout, int expected_reply_id, int *disconnected) { lrmd_private_t *native = lrmd->private; xmlNode *xml = NULL; time_t start = time(NULL); const char *msg_type = NULL; int reply_id = 0; int remaining_timeout = 0; /* A timeout of 0 here makes no sense. We have to wait a period of time * for the response to come back. If -1 or 0, default to 10 seconds. */ if (total_timeout <= 0) { total_timeout = 10000; } while (!xml) { xml = crm_remote_parse_buffer(native->remote); if (!xml) { /* read some more off the tls buffer if we still have time left. */ if (remaining_timeout) { remaining_timeout = remaining_timeout - ((time(NULL) - start) * 1000); } else { remaining_timeout = total_timeout; } if (remaining_timeout <= 0) { crm_err("Never received the expected reply during the timeout period, disconnecting."); *disconnected = TRUE; return NULL; } crm_remote_recv(native->remote, remaining_timeout, disconnected); xml = crm_remote_parse_buffer(native->remote); if (!xml) { crm_err("Unable to receive expected reply, disconnecting."); *disconnected = TRUE; return NULL; } else if (*disconnected) { return NULL; } } CRM_ASSERT(xml != NULL); crm_element_value_int(xml, F_LRMD_REMOTE_MSG_ID, &reply_id); msg_type = crm_element_value(xml, F_LRMD_REMOTE_MSG_TYPE); if (!msg_type) { crm_err("Empty msg type received while waiting for reply"); free_xml(xml); xml = NULL; } else if (safe_str_eq(msg_type, "notify")) { /* got a notify while waiting for reply, trigger the notify to be processed later */ crm_info("queueing notify"); native->pending_notify = g_list_append(native->pending_notify, xml); if (native->process_notify) { crm_info("notify trigger set."); mainloop_set_trigger(native->process_notify); } xml = NULL; } else if (safe_str_neq(msg_type, "reply")) { /* msg isn't a reply, make some noise */ crm_err("Expected a reply, got %s", msg_type); free_xml(xml); xml = NULL; } else if (reply_id != expected_reply_id) { if (native->expected_late_replies > 0) { native->expected_late_replies--; } else { crm_err("Got outdated reply, expected id %d got id %d", expected_reply_id, reply_id); } free_xml(xml); xml = NULL; } } if (native->remote->buffer && native->process_notify) { mainloop_set_trigger(native->process_notify); } return xml; } static int lrmd_tls_send(lrmd_t * lrmd, xmlNode * msg) { int rc = 0; lrmd_private_t *native = lrmd->private; global_remote_msg_id++; if (global_remote_msg_id <= 0) { global_remote_msg_id = 1; } rc = lrmd_tls_send_msg(native->remote, msg, global_remote_msg_id, "request"); if (rc <= 0) { crm_err("Remote lrmd send failed, disconnecting"); lrmd_tls_disconnect(lrmd); return -ENOTCONN; } return pcmk_ok; } static int lrmd_tls_send_recv(lrmd_t * lrmd, xmlNode * msg, int timeout, xmlNode ** reply) { int rc = 0; int disconnected = 0; xmlNode *xml = NULL; if (lrmd_tls_connected(lrmd) == FALSE) { return -1; } rc = lrmd_tls_send(lrmd, msg); if (rc < 0) { return rc; } xml = lrmd_tls_recv_reply(lrmd, timeout, global_remote_msg_id, &disconnected); if (disconnected) { crm_err("Remote lrmd server disconnected while waiting for reply with id %d. ", global_remote_msg_id); lrmd_tls_disconnect(lrmd); rc = -ENOTCONN; } else if (!xml) { crm_err("Remote lrmd never received reply for request id %d. timeout: %dms ", global_remote_msg_id, timeout); rc = -ECOMM; } if (reply) { *reply = xml; } else { free_xml(xml); } return rc; } #endif static int lrmd_send_xml(lrmd_t * lrmd, xmlNode * msg, int timeout, xmlNode ** reply) { int rc = -1; lrmd_private_t *native = lrmd->private; switch (native->type) { case CRM_CLIENT_IPC: rc = crm_ipc_send(native->ipc, msg, crm_ipc_client_response, timeout, reply); break; #ifdef HAVE_GNUTLS_GNUTLS_H case CRM_CLIENT_TLS: rc = lrmd_tls_send_recv(lrmd, msg, timeout, reply); break; #endif default: crm_err("Unsupported connection type: %d", native->type); } return rc; } static int lrmd_send_xml_no_reply(lrmd_t * lrmd, xmlNode * msg) { int rc = -1; lrmd_private_t *native = lrmd->private; switch (native->type) { case CRM_CLIENT_IPC: rc = crm_ipc_send(native->ipc, msg, crm_ipc_flags_none, 0, NULL); break; #ifdef HAVE_GNUTLS_GNUTLS_H case CRM_CLIENT_TLS: rc = lrmd_tls_send(lrmd, msg); if (rc == pcmk_ok) { /* we don't want to wait around for the reply, but * since the request/reply protocol needs to behave the same * as libqb, a reply will eventually come later anyway. */ native->expected_late_replies++; } break; #endif default: crm_err("Unsupported connection type: %d", native->type); } return rc; } static int lrmd_api_is_connected(lrmd_t * lrmd) { lrmd_private_t *native = lrmd->private; switch (native->type) { case CRM_CLIENT_IPC: return crm_ipc_connected(native->ipc); break; #ifdef HAVE_GNUTLS_GNUTLS_H case CRM_CLIENT_TLS: return lrmd_tls_connected(lrmd); break; #endif default: crm_err("Unsupported connection type: %d", native->type); } return 0; } static int lrmd_send_command(lrmd_t * lrmd, const char *op, xmlNode * data, xmlNode ** output_data, int timeout, /* ms. defaults to 1000 if set to 0 */ enum lrmd_call_options options, gboolean expect_reply) { /* TODO we need to reduce usage of this boolean */ int rc = pcmk_ok; int reply_id = -1; lrmd_private_t *native = lrmd->private; xmlNode *op_msg = NULL; xmlNode *op_reply = NULL; if (!lrmd_api_is_connected(lrmd)) { return -ENOTCONN; } if (op == NULL) { crm_err("No operation specified"); return -EINVAL; } CRM_CHECK(native->token != NULL,; ); crm_trace("sending %s op to lrmd", op); op_msg = lrmd_create_op(native->token, op, data, options); if (op_msg == NULL) { return -EINVAL; } crm_xml_add_int(op_msg, F_LRMD_TIMEOUT, timeout); if (expect_reply) { rc = lrmd_send_xml(lrmd, op_msg, timeout, &op_reply); } else { rc = lrmd_send_xml_no_reply(lrmd, op_msg); goto done; } if (rc < 0) { crm_perror(LOG_ERR, "Couldn't perform %s operation (timeout=%d): %d", op, timeout, rc); rc = -ECOMM; goto done; } else if(op_reply == NULL) { rc = -ENOMSG; goto done; } rc = pcmk_ok; crm_element_value_int(op_reply, F_LRMD_CALLID, &reply_id); crm_trace("%s op reply received", op); if (crm_element_value_int(op_reply, F_LRMD_RC, &rc) != 0) { rc = -ENOMSG; goto done; } crm_log_xml_trace(op_reply, "Reply"); if (output_data) { *output_data = op_reply; op_reply = NULL; /* Prevent subsequent free */ } done: if (lrmd_api_is_connected(lrmd) == FALSE) { crm_err("LRMD disconnected"); } free_xml(op_msg); free_xml(op_reply); return rc; } static int lrmd_api_poke_connection(lrmd_t * lrmd) { int rc; xmlNode *data = create_xml_node(NULL, F_LRMD_RSC); crm_xml_add(data, F_LRMD_ORIGIN, __FUNCTION__); rc = lrmd_send_command(lrmd, LRMD_OP_POKE, data, NULL, 0, 0, FALSE); free_xml(data); return rc; } static int lrmd_handshake(lrmd_t * lrmd, const char *name) { int rc = pcmk_ok; lrmd_private_t *native = lrmd->private; xmlNode *reply = NULL; xmlNode *hello = create_xml_node(NULL, "lrmd_command"); crm_xml_add(hello, F_TYPE, T_LRMD); crm_xml_add(hello, F_LRMD_OPERATION, CRM_OP_REGISTER); crm_xml_add(hello, F_LRMD_CLIENTNAME, name); crm_xml_add(hello, F_LRMD_PROTOCOL_VERSION, LRMD_PROTOCOL_VERSION); /* advertise that we are a proxy provider */ if (native->proxy_callback) { crm_xml_add(hello, F_LRMD_IS_IPC_PROVIDER, "true"); } rc = lrmd_send_xml(lrmd, hello, -1, &reply); if (rc < 0) { crm_perror(LOG_DEBUG, "Couldn't complete registration with the lrmd API: %d", rc); rc = -ECOMM; } else if (reply == NULL) { crm_err("Did not receive registration reply"); rc = -EPROTO; } else { const char *msg_type = crm_element_value(reply, F_LRMD_OPERATION); const char *tmp_ticket = crm_element_value(reply, F_LRMD_CLIENTID); crm_element_value_int(reply, F_LRMD_RC, &rc); if (rc == -EPROTO) { crm_err("LRMD protocol mismatch client version %s, server version %s", LRMD_PROTOCOL_VERSION, crm_element_value(reply, F_LRMD_PROTOCOL_VERSION)); crm_log_xml_err(reply, "Protocol Error"); } else if (safe_str_neq(msg_type, CRM_OP_REGISTER)) { crm_err("Invalid registration message: %s", msg_type); crm_log_xml_err(reply, "Bad reply"); rc = -EPROTO; } else if (tmp_ticket == NULL) { crm_err("No registration token provided"); crm_log_xml_err(reply, "Bad reply"); rc = -EPROTO; } else { crm_trace("Obtained registration token: %s", tmp_ticket); native->token = strdup(tmp_ticket); rc = pcmk_ok; } } free_xml(reply); free_xml(hello); if (rc != pcmk_ok) { lrmd_api_disconnect(lrmd); } return rc; } static int lrmd_ipc_connect(lrmd_t * lrmd, int *fd) { int rc = pcmk_ok; lrmd_private_t *native = lrmd->private; static struct ipc_client_callbacks lrmd_callbacks = { .dispatch = lrmd_ipc_dispatch, .destroy = lrmd_ipc_connection_destroy }; crm_info("Connecting to lrmd"); if (fd) { /* No mainloop */ native->ipc = crm_ipc_new(CRM_SYSTEM_LRMD, 0); if (native->ipc && crm_ipc_connect(native->ipc)) { *fd = crm_ipc_get_fd(native->ipc); } else if (native->ipc) { rc = -ENOTCONN; } } else { native->source = mainloop_add_ipc_client(CRM_SYSTEM_LRMD, G_PRIORITY_HIGH, 0, lrmd, &lrmd_callbacks); native->ipc = mainloop_get_ipc_client(native->source); } if (native->ipc == NULL) { crm_debug("Could not connect to the LRMD API"); rc = -ENOTCONN; } return rc; } #ifdef HAVE_GNUTLS_GNUTLS_H static int set_key(gnutls_datum_t * key, const char *location) { FILE *stream; int read_len = 256; int cur_len = 0; int buf_len = read_len; static char *key_cache = NULL; static size_t key_cache_len = 0; static time_t key_cache_updated; if (location == NULL) { return -1; } if (key_cache) { time_t now = time(NULL); if ((now - key_cache_updated) < 60) { key->data = gnutls_malloc(key_cache_len + 1); key->size = key_cache_len; memcpy(key->data, key_cache, key_cache_len); crm_debug("using cached LRMD key"); return 0; } else { key_cache_len = 0; key_cache_updated = 0; free(key_cache); key_cache = NULL; crm_debug("clearing lrmd key cache"); } } stream = fopen(location, "r"); if (!stream) { return -1; } key->data = gnutls_malloc(read_len); while (!feof(stream)) { int next; if (cur_len == buf_len) { buf_len = cur_len + read_len; key->data = gnutls_realloc(key->data, buf_len); } next = fgetc(stream); if (next == EOF && feof(stream)) { break; } key->data[cur_len] = next; cur_len++; } fclose(stream); key->size = cur_len; if (!cur_len) { gnutls_free(key->data); key->data = 0; return -1; } if (!key_cache) { key_cache = calloc(1, key->size + 1); memcpy(key_cache, key->data, key->size); key_cache_len = key->size; key_cache_updated = time(NULL); } return 0; } int lrmd_tls_set_key(gnutls_datum_t * key) { int rc = 0; const char *specific_location = getenv("PCMK_authkey_location"); if (set_key(key, specific_location) == 0) { crm_debug("Using custom authkey location %s", specific_location); return 0; } if (set_key(key, DEFAULT_REMOTE_KEY_LOCATION)) { rc = set_key(key, ALT_REMOTE_KEY_LOCATION); } if (rc) { crm_err("No lrmd remote key found"); return -1; } return rc; } static void lrmd_gnutls_global_init(void) { static int gnutls_init = 0; if (!gnutls_init) { crm_gnutls_global_init(); } gnutls_init = 1; } #endif static void report_async_connection_result(lrmd_t * lrmd, int rc) { lrmd_private_t *native = lrmd->private; if (native->callback) { lrmd_event_data_t event = { 0, }; event.type = lrmd_event_connect; event.remote_nodename = native->remote_nodename; event.connection_rc = rc; native->callback(&event); } } #ifdef HAVE_GNUTLS_GNUTLS_H static void lrmd_tcp_connect_cb(void *userdata, int sock) { lrmd_t *lrmd = userdata; lrmd_private_t *native = lrmd->private; char name[256] = { 0, }; static struct mainloop_fd_callbacks lrmd_tls_callbacks = { .dispatch = lrmd_tls_dispatch, .destroy = lrmd_tls_connection_destroy, }; int rc = sock; gnutls_datum_t psk_key = { NULL, 0 }; native->async_timer = 0; if (rc < 0) { lrmd_tls_connection_destroy(lrmd); crm_info("remote lrmd connect to %s at port %d failed", native->server, native->port); report_async_connection_result(lrmd, rc); return; } /* TODO continue with tls stuff now that tcp connect passed. make this async as well soon * to avoid all blocking code in the client. */ native->sock = sock; if (lrmd_tls_set_key(&psk_key) != 0) { lrmd_tls_connection_destroy(lrmd); return; } gnutls_psk_allocate_client_credentials(&native->psk_cred_c); gnutls_psk_set_client_credentials(native->psk_cred_c, DEFAULT_REMOTE_USERNAME, &psk_key, GNUTLS_PSK_KEY_RAW); gnutls_free(psk_key.data); native->remote->tls_session = create_psk_tls_session(sock, GNUTLS_CLIENT, native->psk_cred_c); if (crm_initiate_client_tls_handshake(native->remote, LRMD_CLIENT_HANDSHAKE_TIMEOUT) != 0) { crm_warn("Client tls handshake failed for server %s:%d. Disconnecting", native->server, native->port); gnutls_deinit(*native->remote->tls_session); gnutls_free(native->remote->tls_session); native->remote->tls_session = NULL; lrmd_tls_connection_destroy(lrmd); report_async_connection_result(lrmd, -1); return; } crm_info("Remote lrmd client TLS connection established with server %s:%d", native->server, native->port); snprintf(name, 128, "remote-lrmd-%s:%d", native->server, native->port); native->process_notify = mainloop_add_trigger(G_PRIORITY_HIGH, lrmd_tls_dispatch, lrmd); native->source = mainloop_add_fd(name, G_PRIORITY_HIGH, native->sock, lrmd, &lrmd_tls_callbacks); rc = lrmd_handshake(lrmd, name); report_async_connection_result(lrmd, rc); return; } static int lrmd_tls_connect_async(lrmd_t * lrmd, int timeout /*ms */ ) { int rc = -1; int sock = 0; int timer_id = 0; lrmd_private_t *native = lrmd->private; lrmd_gnutls_global_init(); sock = crm_remote_tcp_connect_async(native->server, native->port, timeout, &timer_id, lrmd, lrmd_tcp_connect_cb); if (sock != -1) { native->sock = sock; rc = 0; native->async_timer = timer_id; } return rc; } static int lrmd_tls_connect(lrmd_t * lrmd, int *fd) { static struct mainloop_fd_callbacks lrmd_tls_callbacks = { .dispatch = lrmd_tls_dispatch, .destroy = lrmd_tls_connection_destroy, }; lrmd_private_t *native = lrmd->private; int sock; gnutls_datum_t psk_key = { NULL, 0 }; lrmd_gnutls_global_init(); sock = crm_remote_tcp_connect(native->server, native->port); if (sock < 0) { crm_warn("Could not establish remote lrmd connection to %s", native->server); lrmd_tls_connection_destroy(lrmd); return -ENOTCONN; } native->sock = sock; if (lrmd_tls_set_key(&psk_key) != 0) { lrmd_tls_connection_destroy(lrmd); return -1; } gnutls_psk_allocate_client_credentials(&native->psk_cred_c); gnutls_psk_set_client_credentials(native->psk_cred_c, DEFAULT_REMOTE_USERNAME, &psk_key, GNUTLS_PSK_KEY_RAW); gnutls_free(psk_key.data); native->remote->tls_session = create_psk_tls_session(sock, GNUTLS_CLIENT, native->psk_cred_c); if (crm_initiate_client_tls_handshake(native->remote, LRMD_CLIENT_HANDSHAKE_TIMEOUT) != 0) { crm_err("Session creation for %s:%d failed", native->server, native->port); gnutls_deinit(*native->remote->tls_session); gnutls_free(native->remote->tls_session); native->remote->tls_session = NULL; lrmd_tls_connection_destroy(lrmd); return -1; } crm_info("Remote lrmd client TLS connection established with server %s:%d", native->server, native->port); if (fd) { *fd = sock; } else { char name[256] = { 0, }; snprintf(name, 128, "remote-lrmd-%s:%d", native->server, native->port); native->process_notify = mainloop_add_trigger(G_PRIORITY_HIGH, lrmd_tls_dispatch, lrmd); native->source = mainloop_add_fd(name, G_PRIORITY_HIGH, native->sock, lrmd, &lrmd_tls_callbacks); } return pcmk_ok; } #endif static int lrmd_api_connect(lrmd_t * lrmd, const char *name, int *fd) { int rc = -ENOTCONN; lrmd_private_t *native = lrmd->private; switch (native->type) { case CRM_CLIENT_IPC: rc = lrmd_ipc_connect(lrmd, fd); break; #ifdef HAVE_GNUTLS_GNUTLS_H case CRM_CLIENT_TLS: rc = lrmd_tls_connect(lrmd, fd); break; #endif default: crm_err("Unsupported connection type: %d", native->type); } if (rc == pcmk_ok) { rc = lrmd_handshake(lrmd, name); } return rc; } static int lrmd_api_connect_async(lrmd_t * lrmd, const char *name, int timeout) { int rc = 0; lrmd_private_t *native = lrmd->private; if (!native->callback) { crm_err("Async connect not possible, no lrmd client callback set."); return -1; } switch (native->type) { case CRM_CLIENT_IPC: /* fake async connection with ipc. it should be fast * enough that we gain very little from async */ rc = lrmd_api_connect(lrmd, name, NULL); if (!rc) { report_async_connection_result(lrmd, rc); } break; #ifdef HAVE_GNUTLS_GNUTLS_H case CRM_CLIENT_TLS: rc = lrmd_tls_connect_async(lrmd, timeout); if (rc) { /* connection failed, report rc now */ report_async_connection_result(lrmd, rc); } break; #endif default: crm_err("Unsupported connection type: %d", native->type); } return rc; } static void lrmd_ipc_disconnect(lrmd_t * lrmd) { lrmd_private_t *native = lrmd->private; if (native->source != NULL) { /* Attached to mainloop */ mainloop_del_ipc_client(native->source); native->source = NULL; native->ipc = NULL; } else if (native->ipc) { /* Not attached to mainloop */ crm_ipc_t *ipc = native->ipc; native->ipc = NULL; crm_ipc_close(ipc); crm_ipc_destroy(ipc); } } #ifdef HAVE_GNUTLS_GNUTLS_H static void lrmd_tls_disconnect(lrmd_t * lrmd) { lrmd_private_t *native = lrmd->private; if (native->remote->tls_session) { gnutls_bye(*native->remote->tls_session, GNUTLS_SHUT_RDWR); gnutls_deinit(*native->remote->tls_session); gnutls_free(native->remote->tls_session); native->remote->tls_session = 0; } if (native->async_timer) { g_source_remove(native->async_timer); native->async_timer = 0; } if (native->source != NULL) { /* Attached to mainloop */ mainloop_del_ipc_client(native->source); native->source = NULL; } else if (native->sock) { close(native->sock); } if (native->pending_notify) { g_list_free_full(native->pending_notify, lrmd_free_xml); native->pending_notify = NULL; } } #endif static int lrmd_api_disconnect(lrmd_t * lrmd) { lrmd_private_t *native = lrmd->private; crm_info("Disconnecting from lrmd service"); switch (native->type) { case CRM_CLIENT_IPC: lrmd_ipc_disconnect(lrmd); break; #ifdef HAVE_GNUTLS_GNUTLS_H case CRM_CLIENT_TLS: lrmd_tls_disconnect(lrmd); break; #endif default: crm_err("Unsupported connection type: %d", native->type); } free(native->token); native->token = NULL; return 0; } static int lrmd_api_register_rsc(lrmd_t * lrmd, const char *rsc_id, const char *class, const char *provider, const char *type, enum lrmd_call_options options) { int rc = pcmk_ok; xmlNode *data = NULL; if (!class || !type || !rsc_id) { return -EINVAL; } if (safe_str_eq(class, "ocf") && !provider) { return -EINVAL; } data = create_xml_node(NULL, F_LRMD_RSC); crm_xml_add(data, F_LRMD_ORIGIN, __FUNCTION__); crm_xml_add(data, F_LRMD_RSC_ID, rsc_id); crm_xml_add(data, F_LRMD_CLASS, class); crm_xml_add(data, F_LRMD_PROVIDER, provider); crm_xml_add(data, F_LRMD_TYPE, type); rc = lrmd_send_command(lrmd, LRMD_OP_RSC_REG, data, NULL, 0, options, TRUE); free_xml(data); return rc; } static int lrmd_api_unregister_rsc(lrmd_t * lrmd, const char *rsc_id, enum lrmd_call_options options) { int rc = pcmk_ok; xmlNode *data = create_xml_node(NULL, F_LRMD_RSC); crm_xml_add(data, F_LRMD_ORIGIN, __FUNCTION__); crm_xml_add(data, F_LRMD_RSC_ID, rsc_id); rc = lrmd_send_command(lrmd, LRMD_OP_RSC_UNREG, data, NULL, 0, options, TRUE); free_xml(data); return rc; } lrmd_rsc_info_t * lrmd_copy_rsc_info(lrmd_rsc_info_t * rsc_info) { lrmd_rsc_info_t *copy = NULL; copy = calloc(1, sizeof(lrmd_rsc_info_t)); copy->id = strdup(rsc_info->id); copy->type = strdup(rsc_info->type); copy->class = strdup(rsc_info->class); if (rsc_info->provider) { copy->provider = strdup(rsc_info->provider); } return copy; } void lrmd_free_rsc_info(lrmd_rsc_info_t * rsc_info) { if (!rsc_info) { return; } free(rsc_info->id); free(rsc_info->type); free(rsc_info->class); free(rsc_info->provider); free(rsc_info); } static lrmd_rsc_info_t * lrmd_api_get_rsc_info(lrmd_t * lrmd, const char *rsc_id, enum lrmd_call_options options) { lrmd_rsc_info_t *rsc_info = NULL; xmlNode *data = create_xml_node(NULL, F_LRMD_RSC); xmlNode *output = NULL; const char *class = NULL; const char *provider = NULL; const char *type = NULL; crm_xml_add(data, F_LRMD_ORIGIN, __FUNCTION__); crm_xml_add(data, F_LRMD_RSC_ID, rsc_id); lrmd_send_command(lrmd, LRMD_OP_RSC_INFO, data, &output, 30000, options, TRUE); free_xml(data); if (!output) { return NULL; } class = crm_element_value(output, F_LRMD_CLASS); provider = crm_element_value(output, F_LRMD_PROVIDER); type = crm_element_value(output, F_LRMD_TYPE); if (!class || !type) { free_xml(output); return NULL; } else if (safe_str_eq(class, "ocf") && !provider) { free_xml(output); return NULL; } rsc_info = calloc(1, sizeof(lrmd_rsc_info_t)); rsc_info->id = strdup(rsc_id); rsc_info->class = strdup(class); if (provider) { rsc_info->provider = strdup(provider); } rsc_info->type = strdup(type); free_xml(output); return rsc_info; } static void lrmd_api_set_callback(lrmd_t * lrmd, lrmd_event_callback callback) { lrmd_private_t *native = lrmd->private; native->callback = callback; } void lrmd_internal_set_proxy_callback(lrmd_t * lrmd, void *userdata, void (*callback)(lrmd_t *lrmd, void *userdata, xmlNode *msg)) { lrmd_private_t *native = lrmd->private; native->proxy_callback = callback; native->proxy_callback_userdata = userdata; } void lrmd_internal_proxy_dispatch(lrmd_t *lrmd, xmlNode *msg) { lrmd_private_t *native = lrmd->private; if (native->proxy_callback) { crm_log_xml_trace(msg, "PROXY_INBOUND"); native->proxy_callback(lrmd, native->proxy_callback_userdata, msg); } } int lrmd_internal_proxy_send(lrmd_t * lrmd, xmlNode *msg) { if (lrmd == NULL) { return -ENOTCONN; } crm_xml_add(msg, F_LRMD_OPERATION, CRM_OP_IPC_FWD); crm_log_xml_trace(msg, "PROXY_OUTBOUND"); return lrmd_send_xml_no_reply(lrmd, msg); } static int stonith_get_metadata(const char *provider, const char *type, char **output) { int rc = pcmk_ok; stonith_t *stonith_api = stonith_api_new(); if(stonith_api) { stonith_api->cmds->metadata(stonith_api, st_opt_sync_call, type, provider, output, 0); stonith_api->cmds->free(stonith_api); } if (*output == NULL) { rc = -EIO; } return rc; } #define lsb_metadata_template \ "\n" \ "\n" \ "\n" \ " 1.0\n" \ " \n" \ " %s\n" \ " \n" \ " %s\n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " %s\n" \ " %s\n" \ " %s\n" \ " %s\n" \ " %s\n" \ " %s\n" \ " %s\n" \ " \n" \ "\n" #define LSB_INITSCRIPT_INFOBEGIN_TAG "### BEGIN INIT INFO" #define LSB_INITSCRIPT_INFOEND_TAG "### END INIT INFO" #define PROVIDES "# Provides:" #define REQ_START "# Required-Start:" #define REQ_STOP "# Required-Stop:" #define SHLD_START "# Should-Start:" #define SHLD_STOP "# Should-Stop:" #define DFLT_START "# Default-Start:" #define DFLT_STOP "# Default-Stop:" #define SHORT_DSCR "# Short-Description:" #define DESCRIPTION "# Description:" #define lsb_meta_helper_free_value(m) \ if ((m) != NULL) { \ xmlFree(m); \ (m) = NULL; \ } #define lsb_meta_helper_get_value(buffer, ptr, keyword) \ if (!ptr && !strncasecmp(buffer, keyword, strlen(keyword))) { \ (ptr) = (char *)xmlEncodeEntitiesReentrant(NULL, BAD_CAST buffer+strlen(keyword)); \ continue; \ } static int lsb_get_metadata(const char *type, char **output) { char ra_pathname[PATH_MAX] = { 0, }; FILE *fp; GString *meta_data = NULL; char buffer[1024]; char *provides = NULL; char *req_start = NULL; char *req_stop = NULL; char *shld_start = NULL; char *shld_stop = NULL; char *dflt_start = NULL; char *dflt_stop = NULL; char *s_dscrpt = NULL; char *xml_l_dscrpt = NULL; GString *l_dscrpt = NULL; if(type[0] == '/') { snprintf(ra_pathname, sizeof(ra_pathname), "%s", type); } else { snprintf(ra_pathname, sizeof(ra_pathname), "%s/%s", LSB_ROOT_DIR, type); } crm_trace("Looking into %s", ra_pathname); if (!(fp = fopen(ra_pathname, "r"))) { return -errno; } /* Enter into the lsb-compliant comment block */ while (fgets(buffer, sizeof(buffer), fp)) { /* Now suppose each of the following eight arguments contain only one line */ lsb_meta_helper_get_value(buffer, provides, PROVIDES) lsb_meta_helper_get_value(buffer, req_start, REQ_START) lsb_meta_helper_get_value(buffer, req_stop, REQ_STOP) lsb_meta_helper_get_value(buffer, shld_start, SHLD_START) lsb_meta_helper_get_value(buffer, shld_stop, SHLD_STOP) lsb_meta_helper_get_value(buffer, dflt_start, DFLT_START) lsb_meta_helper_get_value(buffer, dflt_stop, DFLT_STOP) lsb_meta_helper_get_value(buffer, s_dscrpt, SHORT_DSCR) /* Long description may cross multiple lines */ if ((l_dscrpt == NULL) && (0 == strncasecmp(buffer, DESCRIPTION, strlen(DESCRIPTION)))) { l_dscrpt = g_string_new(buffer + strlen(DESCRIPTION)); /* Between # and keyword, more than one space, or a tab character, * indicates the continuation line. Extracted from LSB init script standard */ while (fgets(buffer, sizeof(buffer), fp)) { if (!strncmp(buffer, "# ", 3) || !strncmp(buffer, "#\t", 2)) { buffer[0] = ' '; l_dscrpt = g_string_append(l_dscrpt, buffer); } else { fputs(buffer, fp); break; /* Long description ends */ } } continue; } if (l_dscrpt) { xml_l_dscrpt = (char *)xmlEncodeEntitiesReentrant(NULL, BAD_CAST(l_dscrpt->str)); } if (!strncasecmp(buffer, LSB_INITSCRIPT_INFOEND_TAG, strlen(LSB_INITSCRIPT_INFOEND_TAG))) { /* Get to the out border of LSB comment block */ break; } if (buffer[0] != '#') { break; /* Out of comment block in the beginning */ } } fclose(fp); meta_data = g_string_new(""); g_string_sprintf(meta_data, lsb_metadata_template, type, (xml_l_dscrpt == NULL) ? type : xml_l_dscrpt, (s_dscrpt == NULL) ? type : s_dscrpt, (provides == NULL) ? "" : provides, (req_start == NULL) ? "" : req_start, (req_stop == NULL) ? "" : req_stop, (shld_start == NULL) ? "" : shld_start, (shld_stop == NULL) ? "" : shld_stop, (dflt_start == NULL) ? "" : dflt_start, (dflt_stop == NULL) ? "" : dflt_stop); lsb_meta_helper_free_value(xml_l_dscrpt); lsb_meta_helper_free_value(s_dscrpt); lsb_meta_helper_free_value(provides); lsb_meta_helper_free_value(req_start); lsb_meta_helper_free_value(req_stop); lsb_meta_helper_free_value(shld_start); lsb_meta_helper_free_value(shld_stop); lsb_meta_helper_free_value(dflt_start); lsb_meta_helper_free_value(dflt_stop); if (l_dscrpt) { g_string_free(l_dscrpt, TRUE); } *output = strdup(meta_data->str); g_string_free(meta_data, TRUE); crm_trace("Created fake metadata: %d", strlen(*output)); return pcmk_ok; } #if SUPPORT_NAGIOS static int nagios_get_metadata(const char *type, char **output) { int rc = pcmk_ok; FILE *file_strm = NULL; int start = 0, length = 0, read_len = 0; char *metadata_file = NULL; int len = 36; len += strlen(NAGIOS_METADATA_DIR); len += strlen(type); metadata_file = calloc(1, len); CRM_CHECK(metadata_file != NULL, return -ENOMEM); sprintf(metadata_file, "%s/%s.xml", NAGIOS_METADATA_DIR, type); file_strm = fopen(metadata_file, "r"); if (file_strm == NULL) { crm_err("Metadata file %s does not exist", metadata_file); free(metadata_file); return -EIO; } /* see how big the file is */ start = ftell(file_strm); fseek(file_strm, 0L, SEEK_END); length = ftell(file_strm); fseek(file_strm, 0L, start); CRM_ASSERT(length >= 0); CRM_ASSERT(start == ftell(file_strm)); if (length <= 0) { crm_info("%s was not valid", metadata_file); free(*output); *output = NULL; rc = -EIO; } else { crm_trace("Reading %d bytes from file", length); *output = calloc(1, (length + 1)); read_len = fread(*output, 1, length, file_strm); if (read_len != length) { crm_err("Calculated and read bytes differ: %d vs. %d", length, read_len); free(*output); *output = NULL; rc = -EIO; } } fclose(file_strm); free(metadata_file); return rc; } #endif +#if SUPPORT_HEARTBEAT +/* strictly speaking, support for class=heartbeat style scripts + * does not require "heartbeat support" to be enabled. + * But since those scripts are part of the "heartbeat" package usually, + * and are very unlikely to be present in any other deployment, + * I leave it inside this ifdef. + * + * Yes, I know, these are legacy and should die, + * or at least be rewritten to be a proper OCF style agent. + * But they exist, and custom scripts following these rules do, too. + * + * Taken from the old "glue" lrmd, see + * http://hg.linux-ha.org/glue/file/0a7add1d9996/lib/plugins/lrm/raexechb.c#l49 + * http://hg.linux-ha.org/glue/file/0a7add1d9996/lib/plugins/lrm/raexechb.c#l393 + */ + +static const char hb_metadata_template[] = +"\n" +"\n" +"\n" +"1.0\n" +"\n" +"%s" +"\n" +"%s\n" +"\n" +"\n" +"\n" +"This argument will be passed as the first argument to the " +"heartbeat resource agent (assuming it supports one)\n" +"\n" +"argv[1]\n" +"\n" +"\n" +"\n" +"\n" +"This argument will be passed as the second argument to the " +"heartbeat resource agent (assuming it supports one)\n" +"\n" +"argv[2]\n" +"\n" +"\n" +"\n" +"\n" +"This argument will be passed as the third argument to the " +"heartbeat resource agent (assuming it supports one)\n" +"\n" +"argv[3]\n" +"\n" +"\n" +"\n" +"\n" +"This argument will be passed as the fourth argument to the " +"heartbeat resource agent (assuming it supports one)\n" +"\n" +"argv[4]\n" +"\n" +"\n" +"\n" +"\n" +"This argument will be passed as the fifth argument to the " +"heartbeat resource agent (assuming it supports one)\n" +"\n" +"argv[5]\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n"; + +static int +heartbeat_get_metadata(const char *type, char **output) +{ + GString * meta_data; + meta_data = g_string_new(""); + g_string_sprintf(meta_data, hb_metadata_template, type, type, type); + *output = strdup(meta_data->str); + g_string_free(meta_data, TRUE); + crm_trace("Created fake metadata: %d", strlen(*output)); + return pcmk_ok; +} +#endif + static int generic_get_metadata(const char *standard, const char *provider, const char *type, char **output) { svc_action_t *action = resources_action_create(type, standard, provider, type, "meta-data", 0, 30000, NULL); if (!(services_action_sync(action))) { crm_err("Failed to retrieve meta-data for %s:%s:%s", standard, provider, type); services_action_free(action); return -EIO; } if (!action->stdout_data) { crm_err("Failed to retrieve meta-data for %s:%s:%s", standard, provider, type); services_action_free(action); return -EIO; } *output = strdup(action->stdout_data); services_action_free(action); return pcmk_ok; } static int lrmd_api_get_metadata(lrmd_t * lrmd, const char *class, const char *provider, const char *type, char **output, enum lrmd_call_options options) { if (!class || !type) { return -EINVAL; } if (safe_str_eq(class, "service")) { class = resources_find_service_class(type); } if (safe_str_eq(class, "stonith")) { return stonith_get_metadata(provider, type, output); } else if (safe_str_eq(class, "lsb")) { return lsb_get_metadata(type, output); #if SUPPORT_NAGIOS } else if (safe_str_eq(class, "nagios")) { return nagios_get_metadata(type, output); +#endif +#if SUPPORT_HEARTBEAT + } else if (safe_str_eq(class, "heartbeat")) { + return heartbeat_get_metadata(type, output); #endif } return generic_get_metadata(class, provider, type, output); } static int lrmd_api_exec(lrmd_t * lrmd, const char *rsc_id, const char *action, const char *userdata, int interval, /* ms */ int timeout, /* ms */ int start_delay, /* ms */ enum lrmd_call_options options, lrmd_key_value_t * params) { int rc = pcmk_ok; xmlNode *data = create_xml_node(NULL, F_LRMD_RSC); xmlNode *args = create_xml_node(data, XML_TAG_ATTRS); lrmd_key_value_t *tmp = NULL; crm_xml_add(data, F_LRMD_ORIGIN, __FUNCTION__); crm_xml_add(data, F_LRMD_RSC_ID, rsc_id); crm_xml_add(data, F_LRMD_RSC_ACTION, action); crm_xml_add(data, F_LRMD_RSC_USERDATA_STR, userdata); crm_xml_add_int(data, F_LRMD_RSC_INTERVAL, interval); crm_xml_add_int(data, F_LRMD_TIMEOUT, timeout); crm_xml_add_int(data, F_LRMD_RSC_START_DELAY, start_delay); for (tmp = params; tmp; tmp = tmp->next) { - hash2field((gpointer) tmp->key, (gpointer) tmp->value, args); + hash2smartfield((gpointer) tmp->key, (gpointer) tmp->value, args); } rc = lrmd_send_command(lrmd, LRMD_OP_RSC_EXEC, data, NULL, timeout, options, TRUE); free_xml(data); lrmd_key_value_freeall(params); return rc; } static int lrmd_api_cancel(lrmd_t * lrmd, const char *rsc_id, const char *action, int interval) { int rc = pcmk_ok; xmlNode *data = create_xml_node(NULL, F_LRMD_RSC); crm_xml_add(data, F_LRMD_ORIGIN, __FUNCTION__); crm_xml_add(data, F_LRMD_RSC_ACTION, action); crm_xml_add(data, F_LRMD_RSC_ID, rsc_id); crm_xml_add_int(data, F_LRMD_RSC_INTERVAL, interval); rc = lrmd_send_command(lrmd, LRMD_OP_RSC_CANCEL, data, NULL, 0, 0, TRUE); free_xml(data); return rc; } static int list_stonith_agents(lrmd_list_t ** resources) { int rc = 0; stonith_t *stonith_api = stonith_api_new(); stonith_key_value_t *stonith_resources = NULL; stonith_key_value_t *dIter = NULL; if(stonith_api) { stonith_api->cmds->list_agents(stonith_api, st_opt_sync_call, NULL, &stonith_resources, 0); stonith_api->cmds->free(stonith_api); } for (dIter = stonith_resources; dIter; dIter = dIter->next) { rc++; if (resources) { *resources = lrmd_list_add(*resources, dIter->value); } } stonith_key_value_freeall(stonith_resources, 1, 0); return rc; } static int lrmd_api_list_agents(lrmd_t * lrmd, lrmd_list_t ** resources, const char *class, const char *provider) { int rc = 0; if (safe_str_eq(class, "stonith")) { rc += list_stonith_agents(resources); } else { GListPtr gIter = NULL; GList *agents = resources_list_agents(class, provider); for (gIter = agents; gIter != NULL; gIter = gIter->next) { *resources = lrmd_list_add(*resources, (const char *)gIter->data); rc++; } g_list_free_full(agents, free); if (!class) { rc += list_stonith_agents(resources); } } if (rc == 0) { crm_notice("No agents found for class %s", class); rc = -EPROTONOSUPPORT; } return rc; } static int does_provider_have_agent(const char *agent, const char *provider, const char *class) { int found = 0; GList *agents = NULL; GListPtr gIter2 = NULL; agents = resources_list_agents(class, provider); for (gIter2 = agents; gIter2 != NULL; gIter2 = gIter2->next) { if (safe_str_eq(agent, gIter2->data)) { found = 1; } } g_list_free_full(agents, free); return found; } static int lrmd_api_list_ocf_providers(lrmd_t * lrmd, const char *agent, lrmd_list_t ** providers) { int rc = pcmk_ok; char *provider = NULL; GList *ocf_providers = NULL; GListPtr gIter = NULL; ocf_providers = resources_list_providers("ocf"); for (gIter = ocf_providers; gIter != NULL; gIter = gIter->next) { provider = gIter->data; if (!agent || does_provider_have_agent(agent, provider, "ocf")) { *providers = lrmd_list_add(*providers, (const char *)gIter->data); rc++; } } g_list_free_full(ocf_providers, free); return rc; } static int lrmd_api_list_standards(lrmd_t * lrmd, lrmd_list_t ** supported) { int rc = 0; GList *standards = NULL; GListPtr gIter = NULL; standards = resources_list_standards(); for (gIter = standards; gIter != NULL; gIter = gIter->next) { *supported = lrmd_list_add(*supported, (const char *)gIter->data); rc++; } if (list_stonith_agents(NULL) > 0) { *supported = lrmd_list_add(*supported, "stonith"); rc++; } g_list_free_full(standards, free); return rc; } lrmd_t * lrmd_api_new(void) { lrmd_t *new_lrmd = NULL; lrmd_private_t *pvt = NULL; new_lrmd = calloc(1, sizeof(lrmd_t)); pvt = calloc(1, sizeof(lrmd_private_t)); pvt->remote = calloc(1, sizeof(crm_remote_t)); new_lrmd->cmds = calloc(1, sizeof(lrmd_api_operations_t)); pvt->type = CRM_CLIENT_IPC; new_lrmd->private = pvt; new_lrmd->cmds->connect = lrmd_api_connect; new_lrmd->cmds->connect_async = lrmd_api_connect_async; new_lrmd->cmds->is_connected = lrmd_api_is_connected; new_lrmd->cmds->poke_connection = lrmd_api_poke_connection; new_lrmd->cmds->disconnect = lrmd_api_disconnect; new_lrmd->cmds->register_rsc = lrmd_api_register_rsc; new_lrmd->cmds->unregister_rsc = lrmd_api_unregister_rsc; new_lrmd->cmds->get_rsc_info = lrmd_api_get_rsc_info; new_lrmd->cmds->set_callback = lrmd_api_set_callback; new_lrmd->cmds->get_metadata = lrmd_api_get_metadata; new_lrmd->cmds->exec = lrmd_api_exec; new_lrmd->cmds->cancel = lrmd_api_cancel; new_lrmd->cmds->list_agents = lrmd_api_list_agents; new_lrmd->cmds->list_ocf_providers = lrmd_api_list_ocf_providers; new_lrmd->cmds->list_standards = lrmd_api_list_standards; return new_lrmd; } lrmd_t * lrmd_remote_api_new(const char *nodename, const char *server, int port) { #ifdef HAVE_GNUTLS_GNUTLS_H lrmd_t *new_lrmd = lrmd_api_new(); lrmd_private_t *native = new_lrmd->private; if (!nodename && !server) { lrmd_api_delete(new_lrmd); return NULL; } native->type = CRM_CLIENT_TLS; native->remote_nodename = nodename ? strdup(nodename) : strdup(server); native->server = server ? strdup(server) : strdup(nodename); native->port = port; if (native->port == 0) { const char *remote_port_str = getenv("PCMK_remote_port"); native->port = remote_port_str ? atoi(remote_port_str) : DEFAULT_REMOTE_PORT; } return new_lrmd; #else crm_err("GNUTLS is not enabled for this build, remote LRMD client can not be created"); return NULL; #endif } void lrmd_api_delete(lrmd_t * lrmd) { if (!lrmd) { return; } lrmd->cmds->disconnect(lrmd); /* no-op if already disconnected */ free(lrmd->cmds); if (lrmd->private) { lrmd_private_t *native = lrmd->private; #ifdef HAVE_GNUTLS_GNUTLS_H free(native->server); #endif free(native->remote_nodename); free(native->remote); } free(lrmd->private); free(lrmd); } diff --git a/lib/pengine/native.c b/lib/pengine/native.c index 3569f6a913..5c427e6a58 100644 --- a/lib/pengine/native.c +++ b/lib/pengine/native.c @@ -1,851 +1,868 @@ /* * Copyright (C) 2004 Andrew Beekhof * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #define VARIANT_NATIVE 1 #include "./variant.h" void native_add_running(resource_t * rsc, node_t * node, pe_working_set_t * data_set) { GListPtr gIter = rsc->running_on; CRM_CHECK(node != NULL, return); for (; gIter != NULL; gIter = gIter->next) { node_t *a_node = (node_t *) gIter->data; CRM_CHECK(a_node != NULL, return); if (safe_str_eq(a_node->details->id, node->details->id)) { return; } } pe_rsc_trace(rsc, "Adding %s to %s %s", rsc->id, node->details->uname, is_set(rsc->flags, pe_rsc_managed)?"":"(unmanaged)"); rsc->running_on = g_list_append(rsc->running_on, node); if (rsc->variant == pe_native) { node->details->running_rsc = g_list_append(node->details->running_rsc, rsc); } if (rsc->variant == pe_native && node->details->maintenance) { clear_bit(rsc->flags, pe_rsc_managed); } if (is_not_set(rsc->flags, pe_rsc_managed)) { resource_t *p = rsc->parent; pe_rsc_info(rsc, "resource %s isnt managed", rsc->id); resource_location(rsc, node, INFINITY, "not_managed_default", data_set); while(p && node->details->online) { /* add without the additional location constraint */ p->running_on = g_list_append(p->running_on, node); p = p->parent; } return; } if (rsc->variant == pe_native && g_list_length(rsc->running_on) > 1) { switch (rsc->recovery_type) { case recovery_stop_only: { GHashTableIter gIter; node_t *local_node = NULL; /* make sure it doesnt come up again */ g_hash_table_destroy(rsc->allowed_nodes); rsc->allowed_nodes = node_hash_from_list(data_set->nodes); g_hash_table_iter_init(&gIter, rsc->allowed_nodes); while (g_hash_table_iter_next(&gIter, NULL, (void **)&local_node)) { local_node->weight = -INFINITY; } } break; case recovery_stop_start: break; case recovery_block: clear_bit(rsc->flags, pe_rsc_managed); set_bit(rsc->flags, pe_rsc_block); break; } crm_debug("%s is active on %d nodes including %s: %s", rsc->id, g_list_length(rsc->running_on), node->details->uname, recovery2text(rsc->recovery_type)); } else { pe_rsc_trace(rsc, "Resource %s is active on: %s", rsc->id, node->details->uname); } if (rsc->parent != NULL) { native_add_running(rsc->parent, node, data_set); } } extern void force_non_unique_clone(resource_t * rsc, const char *rid, pe_working_set_t * data_set); gboolean native_unpack(resource_t * rsc, pe_working_set_t * data_set) { resource_t *parent = uber_parent(rsc); native_variant_data_t *native_data = NULL; const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS); pe_rsc_trace(rsc, "Processing resource %s...", rsc->id); native_data = calloc(1, sizeof(native_variant_data_t)); rsc->variant_opaque = native_data; if (is_set(rsc->flags, pe_rsc_unique) && rsc->parent) { if (safe_str_eq(class, "lsb")) { resource_t *top = uber_parent(rsc); force_non_unique_clone(top, rsc->id, data_set); } } if (safe_str_eq(class, "ocf") == FALSE) { const char *stateful = g_hash_table_lookup(parent->meta, "stateful"); if (safe_str_eq(stateful, XML_BOOLEAN_TRUE)) { pe_err ("Resource %s is of type %s and therefore cannot be used as a master/slave resource", rsc->id, class); return FALSE; } } return TRUE; } resource_t * native_find_rsc(resource_t * rsc, const char *id, node_t * on_node, int flags) { gboolean match = FALSE; resource_t *result = NULL; GListPtr gIter = rsc->children; CRM_ASSERT(id != NULL); if (flags & pe_find_clone) { const char *rid = ID(rsc->xml); if (rsc->parent == NULL) { match = FALSE; } else if (safe_str_eq(rsc->id, id)) { match = TRUE; } else if (safe_str_eq(rid, id)) { match = TRUE; } } else { if (strcmp(rsc->id, id) == 0) { match = TRUE; } else if (is_set(flags, pe_find_renamed) && rsc->clone_name && strcmp(rsc->clone_name, id) == 0) { match = TRUE; } } if (match && on_node) { pe_rsc_trace(rsc, "Now checking %s is on %s", rsc->id, on_node->details->uname); if (is_set(flags, pe_find_current) && rsc->running_on) { GListPtr gIter = rsc->running_on; for (; gIter != NULL; gIter = gIter->next) { node_t *loc = (node_t *) gIter->data; if (loc->details == on_node->details) { return rsc; } } } else if (is_set(flags, pe_find_inactive) && rsc->running_on == NULL) { return rsc; } else if (is_not_set(flags, pe_find_current) && rsc->allocated_to && rsc->allocated_to->details == on_node->details) { return rsc; } } else if (match) { return rsc; } for (; gIter != NULL; gIter = gIter->next) { resource_t *child = (resource_t *) gIter->data; result = rsc->fns->find_rsc(child, id, on_node, flags); if (result) { return result; } } return NULL; } char * native_parameter(resource_t * rsc, node_t * node, gboolean create, const char *name, pe_working_set_t * data_set) { char *value_copy = NULL; const char *value = NULL; GHashTable *hash = rsc->parameters; GHashTable *local_hash = NULL; CRM_CHECK(rsc != NULL, return NULL); CRM_CHECK(name != NULL && strlen(name) != 0, return NULL); pe_rsc_trace(rsc, "Looking up %s in %s", name, rsc->id); if (create || g_hash_table_size(rsc->parameters) == 0) { if (node != NULL) { pe_rsc_trace(rsc, "Creating hash with node %s", node->details->uname); } else { pe_rsc_trace(rsc, "Creating default hash"); } local_hash = g_hash_table_new_full(crm_str_hash, g_str_equal, g_hash_destroy_str, g_hash_destroy_str); get_rsc_attributes(local_hash, rsc, node, data_set); hash = local_hash; } value = g_hash_table_lookup(hash, name); if (value == NULL) { /* try meta attributes instead */ value = g_hash_table_lookup(rsc->meta, name); } if (value != NULL) { value_copy = strdup(value); } if (local_hash != NULL) { g_hash_table_destroy(local_hash); } return value_copy; } gboolean native_active(resource_t * rsc, gboolean all) { GListPtr gIter = rsc->running_on; for (; gIter != NULL; gIter = gIter->next) { node_t *a_node = (node_t *) gIter->data; if (a_node->details->unclean) { crm_debug("Resource %s: node %s is unclean", rsc->id, a_node->details->uname); return TRUE; } else if (a_node->details->online == FALSE) { crm_debug("Resource %s: node %s is offline", rsc->id, a_node->details->uname); } else { crm_debug("Resource %s active on %s", rsc->id, a_node->details->uname); return TRUE; } } return FALSE; } struct print_data_s { long options; void *print_data; }; static void native_print_attr(gpointer key, gpointer value, gpointer user_data) { long options = ((struct print_data_s *)user_data)->options; void *print_data = ((struct print_data_s *)user_data)->print_data; status_print("Option: %s = %s\n", (char *)key, (char *)value); } static const char * native_pending_state(resource_t * rsc) { const char *pending_state = NULL; if (safe_str_eq(rsc->pending_task, CRMD_ACTION_START)) { pending_state = "Starting"; } else if (safe_str_eq(rsc->pending_task, CRMD_ACTION_STOP)) { pending_state = "Stopping"; } else if (safe_str_eq(rsc->pending_task, CRMD_ACTION_MIGRATE)) { pending_state = "Migrating"; } else if (safe_str_eq(rsc->pending_task, CRMD_ACTION_MIGRATED)) { /* Work might be done in here. */ pending_state = "Migrating"; } else if (safe_str_eq(rsc->pending_task, CRMD_ACTION_PROMOTE)) { pending_state = "Promoting"; } else if (safe_str_eq(rsc->pending_task, CRMD_ACTION_DEMOTE)) { pending_state = "Demoting"; } return pending_state; } static const char * native_pending_task(resource_t * rsc) { const char *pending_task = NULL; if (safe_str_eq(rsc->pending_task, CRMD_ACTION_NOTIFY)) { /* "Notifying" is not very useful to be shown. */ pending_task = NULL; } else if (safe_str_eq(rsc->pending_task, CRMD_ACTION_STATUS)) { pending_task = "Monitoring"; /* Comment this out until someone requests it */ /* } else if (safe_str_eq(rsc->pending_task, "probe")) { pending_task = "Checking"; */ } return pending_task; } static void native_print_xml(resource_t * rsc, const char *pre_text, long options, void *print_data) { enum rsc_role_e role = rsc->role; const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS); const char *prov = crm_element_value(rsc->xml, XML_AGENT_ATTR_PROVIDER); const char *rsc_state = NULL; if(role == RSC_ROLE_STARTED && uber_parent(rsc)->variant == pe_master) { role = RSC_ROLE_SLAVE; } /* resource information. */ status_print("%sxml, XML_ATTR_TYPE)); if (options & pe_print_pending) { rsc_state = native_pending_state(rsc); } if (rsc_state == NULL) { rsc_state = role2text(role); } status_print("role=\"%s\" ", rsc_state); status_print("active=\"%s\" ", rsc->fns->active(rsc, TRUE) ? "true" : "false"); status_print("orphaned=\"%s\" ", is_set(rsc->flags, pe_rsc_orphan) ? "true" : "false"); status_print("managed=\"%s\" ", is_set(rsc->flags, pe_rsc_managed) ? "true" : "false"); status_print("failed=\"%s\" ", is_set(rsc->flags, pe_rsc_failed) ? "true" : "false"); status_print("failure_ignored=\"%s\" ", is_set(rsc->flags, pe_rsc_failure_ignored) ? "true" : "false"); status_print("nodes_running_on=\"%d\" ", g_list_length(rsc->running_on)); if (options & pe_print_pending) { const char *pending_task = native_pending_task(rsc); if (pending_task) { status_print("pending=\"%s\" ", pending_task); } } if (options & pe_print_dev) { status_print("provisional=\"%s\" ", is_set(rsc->flags, pe_rsc_provisional) ? "true" : "false"); status_print("runnable=\"%s\" ", is_set(rsc->flags, pe_rsc_runnable) ? "true" : "false"); status_print("priority=\"%f\" ", (double)rsc->priority); status_print("variant=\"%s\" ", crm_element_name(rsc->xml)); } /* print out the nodes this resource is running on */ if (options & pe_print_rsconly) { status_print("/>\n"); /* do nothing */ } else if (g_list_length(rsc->running_on) > 0) { GListPtr gIter = rsc->running_on; status_print(">\n"); for (; gIter != NULL; gIter = gIter->next) { node_t *node = (node_t *) gIter->data; status_print("%s \n", pre_text, node->details->uname, node->details->id, node->details->online ? "false" : "true"); } status_print("%s\n", pre_text); } else { status_print("/>\n"); } } void native_print(resource_t * rsc, const char *pre_text, long options, void *print_data) { node_t *node = NULL; const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS); const char *kind = crm_element_value(rsc->xml, XML_ATTR_TYPE); + const char *target_role = NULL; int offset = 0; char buffer[LINE_MAX]; CRM_ASSERT(rsc->variant == pe_native); CRM_ASSERT(kind != NULL); if (rsc->meta) { const char *is_internal = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_INTERNAL_RSC); if (crm_is_true(is_internal)) { crm_trace("skipping print of internal resource %s", rsc->id); return; } + target_role = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_TARGET_ROLE); } if (pre_text == NULL && (options & pe_print_printf)) { pre_text = " "; } if (options & pe_print_xml) { native_print_xml(rsc, pre_text, options, print_data); return; } if (rsc->running_on != NULL) { node = rsc->running_on->data; } if ((options & pe_print_rsconly) || g_list_length(rsc->running_on) > 1) { node = NULL; } if (options & pe_print_html) { if (is_not_set(rsc->flags, pe_rsc_managed)) { status_print(""); } else if (is_set(rsc->flags, pe_rsc_failed)) { status_print(""); } else if (rsc->variant == pe_native && g_list_length(rsc->running_on) == 0) { status_print(""); } else if (g_list_length(rsc->running_on) > 1) { status_print(""); } else if (is_set(rsc->flags, pe_rsc_failure_ignored)) { status_print(""); } else { status_print(""); } } if(pre_text) { offset += snprintf(buffer + offset, LINE_MAX - offset, "%s", pre_text); } offset += snprintf(buffer + offset, LINE_MAX - offset, "%s", rsc_printable_id(rsc)); offset += snprintf(buffer + offset, LINE_MAX - offset, "\t(%s", class); if (safe_str_eq(class, "ocf")) { const char *prov = crm_element_value(rsc->xml, XML_AGENT_ATTR_PROVIDER); offset += snprintf(buffer + offset, LINE_MAX - offset, "::%s", prov); } offset += snprintf(buffer + offset, LINE_MAX - offset, ":%s):\t", kind); if(is_set(rsc->flags, pe_rsc_orphan)) { offset += snprintf(buffer + offset, LINE_MAX - offset, " ORPHANED "); } if(rsc->role > RSC_ROLE_SLAVE && is_set(rsc->flags, pe_rsc_failed)) { offset += snprintf(buffer + offset, LINE_MAX - offset, "FAILED %s ", role2text(rsc->role)); } else if(is_set(rsc->flags, pe_rsc_failed)) { offset += snprintf(buffer + offset, LINE_MAX - offset, "FAILED "); } else { const char *rsc_state = NULL; if (options & pe_print_pending) { rsc_state = native_pending_state(rsc); } if (rsc_state == NULL) { rsc_state = role2text(rsc->role); } + if (target_role) { + enum rsc_role_e target_role_e = text2role(target_role); + + /* Ignore target role Started, as it is the default anyways + * (and would also allow a Master to be Master). + * Show if current role differs from target role, + * or if target role limits our abilities. */ + if (target_role_e != RSC_ROLE_STARTED && ( + target_role_e == RSC_ROLE_SLAVE || + target_role_e == RSC_ROLE_STOPPED || + safe_str_neq(target_role, rsc_state))) + { + offset += snprintf(buffer + offset, LINE_MAX - offset, "(target-role:%s) ", target_role); + } + } offset += snprintf(buffer + offset, LINE_MAX - offset, "%s ", rsc_state); } if(node) { offset += snprintf(buffer + offset, LINE_MAX - offset, "%s ", node->details->uname); } if (options & pe_print_pending) { const char *pending_task = native_pending_task(rsc); if (pending_task) { offset += snprintf(buffer + offset, LINE_MAX - offset, "(%s) ", pending_task); } } if(is_not_set(rsc->flags, pe_rsc_managed)) { offset += snprintf(buffer + offset, LINE_MAX - offset, "(unmanaged) "); } if(is_set(rsc->flags, pe_rsc_failure_ignored)) { offset += snprintf(buffer + offset, LINE_MAX - offset, "(failure ignored)"); } if ((options & pe_print_rsconly) || g_list_length(rsc->running_on) > 1) { const char *desc = crm_element_value(rsc->xml, XML_ATTR_DESC); if(desc) { offset += snprintf(buffer + offset, LINE_MAX - offset, "%s", desc); } } CRM_LOG_ASSERT(offset > 0); status_print("%s", buffer); #if CURSES_ENABLED if ((options & pe_print_rsconly) || g_list_length(rsc->running_on) > 1) { /* Done */ } else if (options & pe_print_ncurses) { /* coverity[negative_returns] False positive */ move(-1, 0); } #endif if (options & pe_print_html) { status_print(" "); } if ((options & pe_print_rsconly)) { } else if (g_list_length(rsc->running_on) > 1) { GListPtr gIter = rsc->running_on; int counter = 0; if (options & pe_print_html) { status_print("
    \n"); } else if ((options & pe_print_printf) || (options & pe_print_ncurses)) { status_print("["); } for (; gIter != NULL; gIter = gIter->next) { node_t *node = (node_t *) gIter->data; counter++; if (options & pe_print_html) { status_print("
  • \n%s", node->details->uname); } else if ((options & pe_print_printf) || (options & pe_print_ncurses)) { status_print(" %s", node->details->uname); } else if ((options & pe_print_log)) { status_print("\t%d : %s", counter, node->details->uname); } else { status_print("%s", node->details->uname); } if (options & pe_print_html) { status_print("
  • \n"); } } if (options & pe_print_html) { status_print("
\n"); } else if ((options & pe_print_printf) || (options & pe_print_ncurses)) { status_print(" ]"); } } if (options & pe_print_html) { status_print("
\n"); } else if (options & pe_print_suppres_nl) { /* nothing */ } else if ((options & pe_print_printf) || (options & pe_print_ncurses)) { status_print("\n"); } if (options & pe_print_details) { struct print_data_s pdata; pdata.options = options; pdata.print_data = print_data; g_hash_table_foreach(rsc->parameters, native_print_attr, &pdata); } if (options & pe_print_dev) { GHashTableIter iter; node_t *node = NULL; status_print("%s\t(%s%svariant=%s, priority=%f)", pre_text, is_set(rsc->flags, pe_rsc_provisional) ? "provisional, " : "", is_set(rsc->flags, pe_rsc_runnable) ? "" : "non-startable, ", crm_element_name(rsc->xml), (double)rsc->priority); status_print("%s\tAllowed Nodes", pre_text); g_hash_table_iter_init(&iter, rsc->allowed_nodes); while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) { status_print("%s\t * %s %d", pre_text, node->details->uname, node->weight); } } if (options & pe_print_max_details) { GHashTableIter iter; node_t *node = NULL; status_print("%s\t=== Allowed Nodes\n", pre_text); g_hash_table_iter_init(&iter, rsc->allowed_nodes); while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) { print_node("\t", node, FALSE); } } } void native_free(resource_t * rsc) { pe_rsc_trace(rsc, "Freeing resource action list (not the data)"); common_free(rsc); } enum rsc_role_e native_resource_state(const resource_t * rsc, gboolean current) { enum rsc_role_e role = rsc->next_role; if (current) { role = rsc->role; } pe_rsc_trace(rsc, "%s state: %s", rsc->id, role2text(role)); return role; } node_t * native_location(resource_t * rsc, GListPtr * list, gboolean current) { node_t *one = NULL; GListPtr result = NULL; if (rsc->children) { GListPtr gIter = rsc->children; for (; gIter != NULL; gIter = gIter->next) { resource_t *child = (resource_t *) gIter->data; child->fns->location(child, &result, current); } } else if (current && rsc->running_on) { result = g_list_copy(rsc->running_on); } else if (current == FALSE && rsc->allocated_to) { result = g_list_append(NULL, rsc->allocated_to); } if (result && g_list_length(result) == 1) { one = g_list_nth_data(result, 0); } if (list) { GListPtr gIter = result; for (; gIter != NULL; gIter = gIter->next) { node_t *node = (node_t *) gIter->data; if (*list == NULL || pe_find_node_id(*list, node->details->id) == NULL) { *list = g_list_append(*list, node); } } } g_list_free(result); return one; } static void get_rscs_brief(GListPtr rsc_list, GHashTable * rsc_table, GHashTable * active_table) { GListPtr gIter = rsc_list; for (; gIter != NULL; gIter = gIter->next) { resource_t *rsc = (resource_t *) gIter->data; const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS); const char *kind = crm_element_value(rsc->xml, XML_ATTR_TYPE); int offset = 0; char buffer[LINE_MAX]; int *rsc_counter = NULL; int *active_counter = NULL; if (rsc->variant != pe_native) { continue; } offset += snprintf(buffer + offset, LINE_MAX - offset, "%s", class); if (safe_str_eq(class, "ocf")) { const char *prov = crm_element_value(rsc->xml, XML_AGENT_ATTR_PROVIDER); offset += snprintf(buffer + offset, LINE_MAX - offset, "::%s", prov); } offset += snprintf(buffer + offset, LINE_MAX - offset, ":%s", kind); CRM_LOG_ASSERT(offset > 0); if (rsc_table) { rsc_counter = g_hash_table_lookup(rsc_table, buffer); if (rsc_counter == NULL) { rsc_counter = calloc(1, sizeof(int)); *rsc_counter = 0; g_hash_table_insert(rsc_table, strdup(buffer), rsc_counter); } (*rsc_counter)++; } if (active_table) { GListPtr gIter2 = rsc->running_on; for (; gIter2 != NULL; gIter2 = gIter2->next) { node_t *node = (node_t *) gIter2->data; GHashTable *node_table = NULL; if (node->details->unclean == FALSE && node->details->online == FALSE) { continue; } node_table = g_hash_table_lookup(active_table, node->details->uname); if (node_table == NULL) { node_table = g_hash_table_new_full(crm_str_hash, g_str_equal, free, free); g_hash_table_insert(active_table, strdup(node->details->uname), node_table); } active_counter = g_hash_table_lookup(node_table, buffer); if (active_counter == NULL) { active_counter = calloc(1, sizeof(int)); *active_counter = 0; g_hash_table_insert(node_table, strdup(buffer), active_counter); } (*active_counter)++; } } } } static void destroy_node_table(gpointer data) { GHashTable *node_table = data; if (node_table) { g_hash_table_destroy(node_table); } } void print_rscs_brief(GListPtr rsc_list, const char *pre_text, long options, void *print_data, gboolean print_all) { GHashTable *rsc_table = g_hash_table_new_full(crm_str_hash, g_str_equal, free, free); GHashTable *active_table = g_hash_table_new_full(crm_str_hash, g_str_equal, free, destroy_node_table); GHashTableIter hash_iter; char *type = NULL; int *rsc_counter = NULL; get_rscs_brief(rsc_list, rsc_table, active_table); g_hash_table_iter_init(&hash_iter, rsc_table); while (g_hash_table_iter_next(&hash_iter, (gpointer *)&type, (gpointer *)&rsc_counter)) { GHashTableIter hash_iter2; char *node_name = NULL; GHashTable *node_table = NULL; int active_counter_all = 0; g_hash_table_iter_init(&hash_iter2, active_table); while (g_hash_table_iter_next(&hash_iter2, (gpointer *)&node_name, (gpointer *)&node_table)) { int *active_counter = g_hash_table_lookup(node_table, type); if (active_counter == NULL || *active_counter == 0) { continue; } else { active_counter_all += *active_counter; } if (options & pe_print_rsconly) { node_name = NULL; } if (options & pe_print_html) { status_print("
  • \n"); } if (print_all) { status_print("%s%d/%d\t(%s):\tActive %s\n", pre_text ? pre_text : "", active_counter ? *active_counter : 0, rsc_counter ? *rsc_counter : 0, type, active_counter && (*active_counter > 0) && node_name ? node_name : ""); } else { status_print("%s%d\t(%s):\tActive %s\n", pre_text ? pre_text : "", active_counter ? *active_counter : 0, type, active_counter && (*active_counter > 0) && node_name ? node_name : ""); } if (options & pe_print_html) { status_print("
  • \n"); } } if (print_all && active_counter_all == 0) { if (options & pe_print_html) { status_print("
  • \n"); } status_print("%s%d/%d\t(%s):\tActive\n", pre_text ? pre_text : "", active_counter_all, rsc_counter ? *rsc_counter : 0, type); if (options & pe_print_html) { status_print("
  • \n"); } } } if (rsc_table) { g_hash_table_destroy(rsc_table); rsc_table = NULL; } if (active_table) { g_hash_table_destroy(active_table); active_table = NULL; } } diff --git a/lib/services/services.c b/lib/services/services.c index c7b6c89f68..1d7e2aef43 100644 --- a/lib/services/services.c +++ b/lib/services/services.c @@ -1,676 +1,728 @@ /* * Copyright (C) 2010 Andrew Beekhof * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #ifndef _GNU_SOURCE # define _GNU_SOURCE #endif #include #include #include #include #include #include #include #include #include #include #include #include "services_private.h" #if SUPPORT_UPSTART # include #endif #if SUPPORT_SYSTEMD # include #endif /* TODO: Develop a rollover strategy */ static int operations = 0; GHashTable *recurring_actions = NULL; svc_action_t * services_action_create(const char *name, const char *action, int interval, int timeout) { return resources_action_create(name, "lsb", NULL, name, action, interval, timeout, NULL); } const char * resources_find_service_class(const char *agent) { /* Priority is: * - lsb * - systemd * - upstart */ int rc = 0; struct stat st; char *path = NULL; #ifdef LSB_ROOT_DIR rc = asprintf(&path, "%s/%s", LSB_ROOT_DIR, agent); if (rc > 0 && stat(path, &st) == 0) { free(path); return "lsb"; } free(path); #endif #if SUPPORT_SYSTEMD if (systemd_unit_exists(agent)) { return "systemd"; } #endif #if SUPPORT_UPSTART if (upstart_job_exists(agent)) { return "upstart"; } #endif return NULL; } svc_action_t * resources_action_create(const char *name, const char *standard, const char *provider, const char *agent, const char *action, int interval, int timeout, GHashTable * params) { svc_action_t *op = NULL; /* * Do some up front sanity checks before we go off and * build the svc_action_t instance. */ if (crm_strlen_zero(name)) { crm_err("A service or resource action must have a name."); goto return_error; } if (crm_strlen_zero(standard)) { crm_err("A service action must have a valid standard."); goto return_error; } if (!strcasecmp(standard, "ocf") && crm_strlen_zero(provider)) { crm_err("An OCF resource action must have a provider."); goto return_error; } if (crm_strlen_zero(agent)) { crm_err("A service or resource action must have an agent."); goto return_error; } if (crm_strlen_zero(action)) { crm_err("A service or resource action must specify an action."); goto return_error; } - if (safe_str_eq(action, "monitor") - && (safe_str_eq(standard, "lsb") || safe_str_eq(standard, "service"))) { + if (safe_str_eq(action, "monitor") && ( +#if SUPPORT_HEARTBEAT + safe_str_eq(standard, "heartbeat") || +#endif + safe_str_eq(standard, "lsb") || safe_str_eq(standard, "service"))) { action = "status"; } /* * Sanity checks passed, proceed! */ op = calloc(1, sizeof(svc_action_t)); op->opaque = calloc(1, sizeof(svc_action_private_t)); op->rsc = strdup(name); op->action = strdup(action); op->interval = interval; op->timeout = timeout; op->standard = strdup(standard); op->agent = strdup(agent); op->sequence = ++operations; if (asprintf(&op->id, "%s_%s_%d", name, action, interval) == -1) { goto return_error; } if (strcasecmp(op->standard, "service") == 0) { const char *expanded = resources_find_service_class(op->agent); if(expanded) { crm_debug("Found a %s agent for %s/%s", expanded, op->rsc, op->agent); free(op->standard); op->standard = strdup(expanded); } else { crm_info("Cannot determine the standard for %s (%s)", op->rsc, op->agent); free(op->standard); op->standard = strdup("lsb"); } CRM_ASSERT(op->standard); } if (strcasecmp(op->standard, "ocf") == 0) { op->provider = strdup(provider); op->params = params; params = NULL; if (asprintf(&op->opaque->exec, "%s/resource.d/%s/%s", OCF_ROOT_DIR, provider, agent) == -1) { crm_err("Internal error: cannot create agent path"); goto return_error; } op->opaque->args[0] = strdup(op->opaque->exec); op->opaque->args[1] = strdup(action); } else if (strcasecmp(op->standard, "lsb") == 0) { if (op->agent[0] == '/') { /* if given an absolute path, use that instead * of tacking on the LSB_ROOT_DIR path to the front */ op->opaque->exec = strdup(op->agent); } else if (asprintf(&op->opaque->exec, "%s/%s", LSB_ROOT_DIR, op->agent) == -1) { crm_err("Internal error: cannot create agent path"); goto return_error; } op->opaque->args[0] = strdup(op->opaque->exec); op->opaque->args[1] = strdup(op->action); op->opaque->args[2] = NULL; +#if SUPPORT_HEARTBEAT + } else if (strcasecmp(op->standard, "heartbeat") == 0) { + int index; + int param_num; + char buf_tmp[20]; + void *value_tmp; + + if (op->agent[0] == '/') { + /* if given an absolute path, use that instead + * of tacking on the HB_RA_DIR path to the front */ + op->opaque->exec = strdup(op->agent); + } else if (asprintf(&op->opaque->exec, "%s/%s", HB_RA_DIR, op->agent) == -1) { + crm_err("Internal error: cannot create agent path"); + goto return_error; + } + op->opaque->args[0] = strdup(op->opaque->exec); + /* The "heartbeat" agent class only has positional arguments, + * which we keyed by their decimal position number. */ + param_num = 1; + for (index = 1; index <= MAX_ARGC - 3; index++ ) { + snprintf(buf_tmp, sizeof(buf_tmp), "%d", index); + value_tmp = g_hash_table_lookup(params, buf_tmp); + if (value_tmp == NULL) { + /* maybe: strdup("") ?? + * But the old lrmd did simply continue as well. */ + continue; + } + op->opaque->args[param_num++] = strdup(value_tmp); + } + + /* Add operation code as the last argument, */ + /* and the teminating NULL pointer */ + op->opaque->args[param_num++] = strdup(op->action); + op->opaque->args[param_num] = NULL; +#endif #if SUPPORT_SYSTEMD } else if (strcasecmp(op->standard, "systemd") == 0) { op->opaque->exec = strdup("systemd-dbus"); #endif #if SUPPORT_UPSTART } else if (strcasecmp(op->standard, "upstart") == 0) { op->opaque->exec = strdup("upstart-dbus"); #endif } else if (strcasecmp(op->standard, "service") == 0) { op->opaque->exec = strdup(SERVICE_SCRIPT); op->opaque->args[0] = strdup(SERVICE_SCRIPT); op->opaque->args[1] = strdup(agent); op->opaque->args[2] = strdup(action); #if SUPPORT_NAGIOS } else if (strcasecmp(op->standard, "nagios") == 0) { int index = 0; if (op->agent[0] == '/') { /* if given an absolute path, use that instead * of tacking on the NAGIOS_PLUGIN_DIR path to the front */ op->opaque->exec = strdup(op->agent); } else if (asprintf(&op->opaque->exec, "%s/%s", NAGIOS_PLUGIN_DIR, op->agent) == -1) { crm_err("Internal error: cannot create agent path"); goto return_error; } op->opaque->args[0] = strdup(op->opaque->exec); index = 1; if (safe_str_eq(op->action, "monitor") && op->interval == 0) { /* Invoke --version for a nagios probe */ op->opaque->args[index] = strdup("--version"); index++; } else if (params) { GHashTableIter iter; char *key = NULL; char *value = NULL; static int args_size = sizeof(op->opaque->args) / sizeof(char *); g_hash_table_iter_init(&iter, params); while (g_hash_table_iter_next(&iter, (gpointer *) & key, (gpointer *) & value) && index <= args_size - 3) { int len = 3; char *long_opt = NULL; if (safe_str_eq(key, XML_ATTR_CRM_VERSION) || strstr(key, CRM_META "_")) { continue; } len += strlen(key); long_opt = calloc(1, len); sprintf(long_opt, "--%s", key); long_opt[len - 1] = 0; op->opaque->args[index] = long_opt; op->opaque->args[index + 1] = strdup(value); index += 2; } } op->opaque->args[index] = NULL; #endif } else { crm_err("Unknown resource standard: %s", op->standard); services_action_free(op); op = NULL; } if(params) { g_hash_table_destroy(params); } return op; return_error: if(params) { g_hash_table_destroy(params); } services_action_free(op); return NULL; } svc_action_t * services_action_create_generic(const char *exec, const char *args[]) { svc_action_t *op; unsigned int cur_arg; op = calloc(1, sizeof(*op)); op->opaque = calloc(1, sizeof(svc_action_private_t)); op->opaque->exec = strdup(exec); op->opaque->args[0] = strdup(exec); for (cur_arg = 1; args && args[cur_arg - 1]; cur_arg++) { op->opaque->args[cur_arg] = strdup(args[cur_arg - 1]); if (cur_arg == DIMOF(op->opaque->args) - 1) { crm_err("svc_action_t args list not long enough for '%s' execution request.", exec); break; } } return op; } void services_action_cleanup(svc_action_t * op) { #if SUPPORT_DBUS if(op->opaque->timerid != 0) { crm_trace("Removing timer for call %s to %s", op->action, op->rsc); g_source_remove(op->opaque->timerid); op->opaque->timerid = 0; } if(op->opaque->pending) { crm_trace("Cleaning up pending dbus call %p %s for %s", op->opaque->pending, op->action, op->rsc); if(dbus_pending_call_get_completed(op->opaque->pending)) { crm_warn("Pending dbus call %s for %s did not complete", op->action, op->rsc); } dbus_pending_call_cancel(op->opaque->pending); dbus_pending_call_unref(op->opaque->pending); op->opaque->pending = NULL; } if (op->opaque->stderr_gsource) { mainloop_del_fd(op->opaque->stderr_gsource); op->opaque->stderr_gsource = NULL; } if (op->opaque->stdout_gsource) { mainloop_del_fd(op->opaque->stdout_gsource); op->opaque->stdout_gsource = NULL; } #endif } void services_action_free(svc_action_t * op) { unsigned int i; if (op == NULL) { return; } services_action_cleanup(op); if (op->opaque->repeat_timer) { g_source_remove(op->opaque->repeat_timer); op->opaque->repeat_timer = 0; } free(op->id); free(op->opaque->exec); for (i = 0; i < DIMOF(op->opaque->args); i++) { free(op->opaque->args[i]); } free(op->opaque); free(op->rsc); free(op->action); free(op->standard); free(op->agent); free(op->provider); free(op->stdout_data); free(op->stderr_data); if (op->params) { g_hash_table_destroy(op->params); op->params = NULL; } free(op); } gboolean cancel_recurring_action(svc_action_t * op) { crm_info("Cancelling operation %s", op->id); if (recurring_actions) { g_hash_table_remove(recurring_actions, op->id); } if (op->opaque->repeat_timer) { g_source_remove(op->opaque->repeat_timer); op->opaque->repeat_timer = 0; } return TRUE; } gboolean services_action_cancel(const char *name, const char *action, int interval) { svc_action_t *op = NULL; char id[512]; snprintf(id, sizeof(id), "%s_%s_%d", name, action, interval); if (!(op = g_hash_table_lookup(recurring_actions, id))) { return FALSE; } /* Always kill the recurring timer */ cancel_recurring_action(op); if (op->pid == 0) { op->status = PCMK_LRM_OP_CANCELLED; if (op->opaque->callback) { op->opaque->callback(op); } services_action_free(op); } else { crm_info("Cancelling in-flight op: performing early termination of %s (pid=%d)", id, op->pid); op->cancel = 1; if (mainloop_child_kill(op->pid) == FALSE) { /* even though the early termination failed, * the op will be marked as cancelled once it completes. */ crm_err("Termination of %s (pid=%d) failed", id, op->pid); return FALSE; } } return TRUE; } gboolean services_action_kick(const char *name, const char *action, int interval /* ms */) { svc_action_t * op = NULL; char *id = NULL; if (asprintf(&id, "%s_%s_%d", name, action, interval) == -1) { return FALSE; } op = g_hash_table_lookup(recurring_actions, id); free(id); if (op == NULL) { return FALSE; } if (op->pid) { return TRUE; } else { if (op->opaque->repeat_timer) { g_source_remove(op->opaque->repeat_timer); op->opaque->repeat_timer = 0; } recurring_action_timer(op); return TRUE; } } /* add new recurring operation, check for duplicates. * - if duplicate found, return TRUE, immediately reschedule op. * - if no dup, return FALSE, inserve into recurring op list.*/ static gboolean handle_duplicate_recurring(svc_action_t * op, void (*action_callback) (svc_action_t *)) { svc_action_t * dup = NULL; if (recurring_actions == NULL) { recurring_actions = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL); return FALSE; } /* check for duplicates */ dup = g_hash_table_lookup(recurring_actions, op->id); if (dup && (dup != op)) { /* update user data */ if (op->opaque->callback) { dup->opaque->callback = op->opaque->callback; dup->cb_data = op->cb_data; op->cb_data = NULL; } /* immediately execute the next interval */ if (dup->pid != 0) { if (op->opaque->repeat_timer) { g_source_remove(op->opaque->repeat_timer); op->opaque->repeat_timer = 0; } recurring_action_timer(dup); } /* free the dup. */ services_action_free(op); return TRUE; } return FALSE; } gboolean services_action_async(svc_action_t * op, void (*action_callback) (svc_action_t *)) { op->synchronous = false; if (action_callback) { op->opaque->callback = action_callback; } if (op->interval > 0) { if (handle_duplicate_recurring(op, action_callback) == TRUE) { /* entry rescheduled, dup freed */ return TRUE; } g_hash_table_replace(recurring_actions, op->id, op); } if (op->standard && strcasecmp(op->standard, "upstart") == 0) { #if SUPPORT_UPSTART return upstart_job_exec(op, FALSE); #endif } if (op->standard && strcasecmp(op->standard, "systemd") == 0) { #if SUPPORT_SYSTEMD return systemd_unit_exec(op); #endif } return services_os_action_execute(op, FALSE); } gboolean services_action_sync(svc_action_t * op) { gboolean rc = TRUE; if (op == NULL) { crm_trace("No operation to execute"); return FALSE; } op->synchronous = true; if (op->standard && strcasecmp(op->standard, "upstart") == 0) { #if SUPPORT_UPSTART rc = upstart_job_exec(op, TRUE); #endif } else if (op->standard && strcasecmp(op->standard, "systemd") == 0) { #if SUPPORT_SYSTEMD rc = systemd_unit_exec(op); #endif } else { rc = services_os_action_execute(op, TRUE); } crm_trace(" > %s_%s_%d: %s = %d", op->rsc, op->action, op->interval, op->opaque->exec, op->rc); if (op->stdout_data) { crm_trace(" > stdout: %s", op->stdout_data); } if (op->stderr_data) { crm_trace(" > stderr: %s", op->stderr_data); } return rc; } GList * get_directory_list(const char *root, gboolean files, gboolean executable) { return services_os_get_directory_list(root, files, executable); } GList * services_list(void) { return resources_list_agents("lsb", NULL); } +static GList * +resources_os_list_hb_agents(void) +{ + return services_os_get_directory_list(HB_RA_DIR, TRUE, TRUE); +} + GList * resources_list_standards(void) { GList *standards = NULL; GList *agents = NULL; standards = g_list_append(standards, strdup("ocf")); standards = g_list_append(standards, strdup("lsb")); standards = g_list_append(standards, strdup("service")); #if SUPPORT_SYSTEMD agents = systemd_unit_listall(); #else agents = NULL; #endif if (agents) { standards = g_list_append(standards, strdup("systemd")); g_list_free_full(agents, free); } #if SUPPORT_UPSTART agents = upstart_job_listall(); #else agents = NULL; #endif if (agents) { standards = g_list_append(standards, strdup("upstart")); g_list_free_full(agents, free); } #if SUPPORT_NAGIOS agents = resources_os_list_nagios_agents(); if (agents) { standards = g_list_append(standards, strdup("nagios")); g_list_free_full(agents, free); } #endif +#if SUPPORT_HEARTBEAT + standards = g_list_append(standards, strdup("heartbeat")); +#endif + return standards; } GList * resources_list_providers(const char *standard) { if (strcasecmp(standard, "ocf") == 0) { return resources_os_list_ocf_providers(); } return NULL; } GList * resources_list_agents(const char *standard, const char *provider) { if (standard == NULL || strcasecmp(standard, "service") == 0) { GList *tmp1; GList *tmp2; GList *result = resources_os_list_lsb_agents(); if (standard == NULL) { tmp1 = result; tmp2 = resources_os_list_ocf_agents(NULL); if (tmp2) { result = g_list_concat(tmp1, tmp2); } } #if SUPPORT_SYSTEMD tmp1 = result; tmp2 = systemd_unit_listall(); if (tmp2) { result = g_list_concat(tmp1, tmp2); } #endif #if SUPPORT_UPSTART tmp1 = result; tmp2 = upstart_job_listall(); if (tmp2) { result = g_list_concat(tmp1, tmp2); } #endif return result; } else if (strcasecmp(standard, "ocf") == 0) { return resources_os_list_ocf_agents(provider); } else if (strcasecmp(standard, "lsb") == 0) { return resources_os_list_lsb_agents(); +#if SUPPORT_HEARTBEAT + } else if (strcasecmp(standard, "heartbeat") == 0) { + return resources_os_list_hb_agents(); +#endif #if SUPPORT_SYSTEMD } else if (strcasecmp(standard, "systemd") == 0) { return systemd_unit_listall(); #endif #if SUPPORT_UPSTART } else if (strcasecmp(standard, "upstart") == 0) { return upstart_job_listall(); #endif #if SUPPORT_NAGIOS } else if (strcasecmp(standard, "nagios") == 0) { return resources_os_list_nagios_agents(); #endif } return NULL; } diff --git a/lib/services/services_private.h b/lib/services/services_private.h index bcf882c485..f3094e39e3 100644 --- a/lib/services/services_private.h +++ b/lib/services/services_private.h @@ -1,61 +1,62 @@ /* * Copyright (C) 2010 - 2011, Red Hat, Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef __MH_SERVICES_PRIVATE_H__ # define __MH_SERVICES_PRIVATE_H__ #if SUPPORT_DBUS # include #endif +#define MAX_ARGC 255 struct svc_action_private_s { char *exec; - char *args[255]; + char *args[MAX_ARGC]; guint repeat_timer; void (*callback) (svc_action_t * op); int stderr_fd; mainloop_io_t *stderr_gsource; int stdout_fd; mainloop_io_t *stdout_gsource; #if SUPPORT_DBUS DBusPendingCall* pending; unsigned timerid; #endif }; GList *services_os_get_directory_list(const char *root, gboolean files, gboolean executable); gboolean services_os_action_execute(svc_action_t * op, gboolean synchronous); GList *resources_os_list_lsb_agents(void); GList *resources_os_list_ocf_providers(void); GList *resources_os_list_ocf_agents(const char *provider); GList *resources_os_list_nagios_agents(void); gboolean cancel_recurring_action(svc_action_t * op); gboolean recurring_action_timer(gpointer data); gboolean operation_finalize(svc_action_t * op); #endif /* __MH_SERVICES_PRIVATE_H__ */ diff --git a/lrmd/lrmd.c b/lrmd/lrmd.c index 0f5f529897..f40710460f 100644 --- a/lrmd/lrmd.c +++ b/lrmd/lrmd.c @@ -1,1567 +1,1633 @@ /* * Copyright (c) 2012 David Vossel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * */ #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_SYS_TIMEB_H # include #endif #define EXIT_REASON_MAX_LEN 128 GHashTable *rsc_list = NULL; typedef struct lrmd_cmd_s { int timeout; int interval; int start_delay; int timeout_orig; int call_id; int exec_rc; int lrmd_op_status; int call_opts; /* Timer ids, must be removed on cmd destruction. */ int delay_id; int stonith_recurring_id; int rsc_deleted; char *client_id; char *origin; char *rsc_id; char *action; char *real_action; char *exit_reason; char *output; char *userdata_str; #ifdef HAVE_SYS_TIMEB_H /* Timestamp of when op first ran */ struct timeb t_first_run; /* Timestamp of when op ran */ struct timeb t_run; /* Timestamp of when op was queued */ struct timeb t_queue; /* Timestamp of last rc change */ struct timeb t_rcchange; #endif int first_notify_sent; int last_notify_rc; int last_notify_op_status; int last_pid; GHashTable *params; } lrmd_cmd_t; static void cmd_finalize(lrmd_cmd_t * cmd, lrmd_rsc_t * rsc); static gboolean lrmd_rsc_dispatch(gpointer user_data); static void cancel_all_recurring(lrmd_rsc_t * rsc, const char *client_id); static void log_finished(lrmd_cmd_t * cmd, int exec_time, int queue_time) { char pid_str[32] = { 0, }; int log_level = LOG_INFO; if (cmd->last_pid) { snprintf(pid_str, 32, "%d", cmd->last_pid); } if (safe_str_eq(cmd->action, "monitor")) { log_level = LOG_DEBUG; } #ifdef HAVE_SYS_TIMEB_H do_crm_log(log_level, "finished - rsc:%s action:%s call_id:%d %s%s exit-code:%d exec-time:%dms queue-time:%dms", cmd->rsc_id, cmd->action, cmd->call_id, cmd->last_pid ? "pid:" : "", pid_str, cmd->exec_rc, exec_time, queue_time); #else do_crm_log(log_level, "finished - rsc:%s action:%s call_id:%d %s%s exit-code:%d", cmd->rsc_id, cmd->action, cmd->call_id, cmd->last_pid ? "pid:" : "", pid_str, cmd->exec_rc); #endif } static void log_execute(lrmd_cmd_t * cmd) { int log_level = LOG_INFO; if (safe_str_eq(cmd->action, "monitor")) { log_level = LOG_DEBUG; } do_crm_log(log_level, "executing - rsc:%s action:%s call_id:%d", cmd->rsc_id, cmd->action, cmd->call_id); } static const char * normalize_action_name(lrmd_rsc_t * rsc, const char *action) { if (safe_str_eq(action, "monitor") && (safe_str_eq(rsc->class, "lsb") || safe_str_eq(rsc->class, "service") || safe_str_eq(rsc->class, "systemd"))) { return "status"; } return action; } static lrmd_rsc_t * build_rsc_from_xml(xmlNode * msg) { xmlNode *rsc_xml = get_xpath_object("//" F_LRMD_RSC, msg, LOG_ERR); lrmd_rsc_t *rsc = NULL; rsc = calloc(1, sizeof(lrmd_rsc_t)); crm_element_value_int(msg, F_LRMD_CALLOPTS, &rsc->call_opts); rsc->rsc_id = crm_element_value_copy(rsc_xml, F_LRMD_RSC_ID); rsc->class = crm_element_value_copy(rsc_xml, F_LRMD_CLASS); rsc->provider = crm_element_value_copy(rsc_xml, F_LRMD_PROVIDER); rsc->type = crm_element_value_copy(rsc_xml, F_LRMD_TYPE); rsc->work = mainloop_add_trigger(G_PRIORITY_HIGH, lrmd_rsc_dispatch, rsc); return rsc; } static lrmd_cmd_t * create_lrmd_cmd(xmlNode * msg, crm_client_t * client) { int call_options = 0; xmlNode *rsc_xml = get_xpath_object("//" F_LRMD_RSC, msg, LOG_ERR); lrmd_cmd_t *cmd = NULL; cmd = calloc(1, sizeof(lrmd_cmd_t)); crm_element_value_int(msg, F_LRMD_CALLOPTS, &call_options); cmd->call_opts = call_options; cmd->client_id = strdup(client->id); crm_element_value_int(msg, F_LRMD_CALLID, &cmd->call_id); crm_element_value_int(rsc_xml, F_LRMD_RSC_INTERVAL, &cmd->interval); crm_element_value_int(rsc_xml, F_LRMD_TIMEOUT, &cmd->timeout); crm_element_value_int(rsc_xml, F_LRMD_RSC_START_DELAY, &cmd->start_delay); cmd->timeout_orig = cmd->timeout; cmd->origin = crm_element_value_copy(rsc_xml, F_LRMD_ORIGIN); cmd->action = crm_element_value_copy(rsc_xml, F_LRMD_RSC_ACTION); cmd->userdata_str = crm_element_value_copy(rsc_xml, F_LRMD_RSC_USERDATA_STR); cmd->rsc_id = crm_element_value_copy(rsc_xml, F_LRMD_RSC_ID); cmd->params = xml2list(rsc_xml); return cmd; } static void free_lrmd_cmd(lrmd_cmd_t * cmd) { if (cmd->stonith_recurring_id) { g_source_remove(cmd->stonith_recurring_id); } if (cmd->delay_id) { g_source_remove(cmd->delay_id); } if (cmd->params) { g_hash_table_destroy(cmd->params); } free(cmd->origin); free(cmd->action); free(cmd->userdata_str); free(cmd->rsc_id); free(cmd->output); free(cmd->exit_reason); free(cmd->client_id); free(cmd); } static gboolean stonith_recurring_op_helper(gpointer data) { lrmd_cmd_t *cmd = data; lrmd_rsc_t *rsc; cmd->stonith_recurring_id = 0; if (!cmd->rsc_id) { return FALSE; } rsc = g_hash_table_lookup(rsc_list, cmd->rsc_id); CRM_ASSERT(rsc != NULL); /* take it out of recurring_ops list, and put it in the pending ops * to be executed */ rsc->recurring_ops = g_list_remove(rsc->recurring_ops, cmd); rsc->pending_ops = g_list_append(rsc->pending_ops, cmd); #ifdef HAVE_SYS_TIMEB_H ftime(&cmd->t_queue); #endif mainloop_set_trigger(rsc->work); return FALSE; } static gboolean start_delay_helper(gpointer data) { lrmd_cmd_t *cmd = data; lrmd_rsc_t *rsc = NULL; cmd->delay_id = 0; rsc = cmd->rsc_id ? g_hash_table_lookup(rsc_list, cmd->rsc_id) : NULL; if (rsc) { mainloop_set_trigger(rsc->work); } return FALSE; } static gboolean merge_recurring_duplicate(lrmd_rsc_t * rsc, lrmd_cmd_t * cmd) { GListPtr gIter = NULL; lrmd_cmd_t * dup = NULL; gboolean dup_pending = FALSE; if (cmd->interval == 0) { return 0; } for (gIter = rsc->pending_ops; gIter != NULL; gIter = gIter->next) { dup = gIter->data; if (safe_str_eq(cmd->action, dup->action) && cmd->interval == dup->interval) { dup_pending = TRUE; goto merge_dup; } } /* if dup is in recurring_ops list, that means it has already executed * and is in the interval loop. we can't just remove it in this case. */ for (gIter = rsc->recurring_ops; gIter != NULL; gIter = gIter->next) { dup = gIter->data; if (safe_str_eq(cmd->action, dup->action) && cmd->interval == dup->interval) { goto merge_dup; } } return FALSE; merge_dup: /* This should not occur, if it does we need to investigate in the crmd * how something like this is possible */ crm_warn("Duplicate recurring op entry detected (%s_%s_%d), merging with previous op entry", rsc->rsc_id, normalize_action_name(rsc, dup->action), dup->interval); /* merge */ dup->first_notify_sent = 0; free(dup->userdata_str); dup->userdata_str = cmd->userdata_str; cmd->userdata_str = NULL; dup->call_id = cmd->call_id; if (safe_str_eq(rsc->class, "stonith")) { /* if we are waiting for the next interval, kick it off now */ if (dup_pending == TRUE) { g_source_remove(cmd->stonith_recurring_id); cmd->stonith_recurring_id = 0; stonith_recurring_op_helper(cmd); } } else if (dup_pending == FALSE) { /* if we've already handed this to the service lib, kick off an early execution */ services_action_kick(rsc->rsc_id, normalize_action_name(rsc, dup->action), dup->interval); } free_lrmd_cmd(cmd); return TRUE; } static void schedule_lrmd_cmd(lrmd_rsc_t * rsc, lrmd_cmd_t * cmd) { gboolean dup_processed = FALSE; CRM_CHECK(cmd != NULL, return); CRM_CHECK(rsc != NULL, return); crm_trace("Scheduling %s on %s", cmd->action, rsc->rsc_id); dup_processed = merge_recurring_duplicate(rsc, cmd); if (dup_processed) { /* duplicate recurring cmd found, cmds merged */ return; } /* crmd expects lrmd to automatically cancel recurring ops before rsc stops. */ if (rsc && safe_str_eq(cmd->action, "stop")) { cancel_all_recurring(rsc, NULL); } rsc->pending_ops = g_list_append(rsc->pending_ops, cmd); #ifdef HAVE_SYS_TIMEB_H ftime(&cmd->t_queue); #endif mainloop_set_trigger(rsc->work); if (cmd->start_delay) { cmd->delay_id = g_timeout_add(cmd->start_delay, start_delay_helper, cmd); } } static void send_reply(crm_client_t * client, int rc, uint32_t id, int call_id) { int send_rc = 0; xmlNode *reply = NULL; reply = create_xml_node(NULL, T_LRMD_REPLY); crm_xml_add(reply, F_LRMD_ORIGIN, __FUNCTION__); crm_xml_add_int(reply, F_LRMD_RC, rc); crm_xml_add_int(reply, F_LRMD_CALLID, call_id); send_rc = lrmd_server_send_reply(client, id, reply); free_xml(reply); if (send_rc < 0) { crm_warn("LRMD reply to %s failed: %d", client->name, send_rc); } } static void send_client_notify(gpointer key, gpointer value, gpointer user_data) { xmlNode *update_msg = user_data; crm_client_t *client = value; if (client == NULL) { crm_err("Asked to send event to NULL client"); return; } else if (client->name == NULL) { crm_trace("Asked to send event to client with no name"); return; } if (lrmd_server_send_notify(client, update_msg) <= 0) { crm_warn("Notification of client %s/%s failed", client->name, client->id); } } #ifdef HAVE_SYS_TIMEB_H static int time_diff_ms(struct timeb *now, struct timeb *old) { int sec = difftime(now->time, old->time); int ms = now->millitm - old->millitm; if (old->time == 0) { return 0; } return (sec * 1000) + ms; } #endif static void send_cmd_complete_notify(lrmd_cmd_t * cmd) { int exec_time = 0; int queue_time = 0; xmlNode *notify = NULL; #ifdef HAVE_SYS_TIMEB_H struct timeb now = { 0, }; ftime(&now); exec_time = time_diff_ms(&now, &cmd->t_run); queue_time = time_diff_ms(&cmd->t_run, &cmd->t_queue); #endif log_finished(cmd, exec_time, queue_time); /* if the first notify result for a cmd has already been sent earlier, and the * the option to only send notifies on result changes is set. Check to see * if the last result is the same as the new one. If so, suppress this update */ if (cmd->first_notify_sent && (cmd->call_opts & lrmd_opt_notify_changes_only)) { if (cmd->last_notify_rc == cmd->exec_rc && cmd->last_notify_op_status == cmd->lrmd_op_status) { /* only send changes */ return; } } cmd->first_notify_sent = 1; cmd->last_notify_rc = cmd->exec_rc; cmd->last_notify_op_status = cmd->lrmd_op_status; notify = create_xml_node(NULL, T_LRMD_NOTIFY); crm_xml_add(notify, F_LRMD_ORIGIN, __FUNCTION__); crm_xml_add_int(notify, F_LRMD_TIMEOUT, cmd->timeout); crm_xml_add_int(notify, F_LRMD_RSC_INTERVAL, cmd->interval); crm_xml_add_int(notify, F_LRMD_RSC_START_DELAY, cmd->start_delay); crm_xml_add_int(notify, F_LRMD_EXEC_RC, cmd->exec_rc); crm_xml_add_int(notify, F_LRMD_OP_STATUS, cmd->lrmd_op_status); crm_xml_add_int(notify, F_LRMD_CALLID, cmd->call_id); crm_xml_add_int(notify, F_LRMD_RSC_DELETED, cmd->rsc_deleted); #ifdef HAVE_SYS_TIMEB_H crm_xml_add_int(notify, F_LRMD_RSC_RUN_TIME, cmd->t_run.time); crm_xml_add_int(notify, F_LRMD_RSC_RCCHANGE_TIME, cmd->t_rcchange.time); crm_xml_add_int(notify, F_LRMD_RSC_EXEC_TIME, exec_time); crm_xml_add_int(notify, F_LRMD_RSC_QUEUE_TIME, queue_time); #endif crm_xml_add(notify, F_LRMD_OPERATION, LRMD_OP_RSC_EXEC); crm_xml_add(notify, F_LRMD_RSC_ID, cmd->rsc_id); if(cmd->real_action) { crm_xml_add(notify, F_LRMD_RSC_ACTION, cmd->real_action); } else { crm_xml_add(notify, F_LRMD_RSC_ACTION, cmd->action); } crm_xml_add(notify, F_LRMD_RSC_USERDATA_STR, cmd->userdata_str); crm_xml_add(notify, F_LRMD_RSC_OUTPUT, cmd->output); crm_xml_add(notify, F_LRMD_RSC_EXIT_REASON, cmd->exit_reason); if (cmd->params) { char *key = NULL; char *value = NULL; GHashTableIter iter; xmlNode *args = create_xml_node(notify, XML_TAG_ATTRS); g_hash_table_iter_init(&iter, cmd->params); while (g_hash_table_iter_next(&iter, (gpointer *) & key, (gpointer *) & value)) { - hash2field((gpointer) key, (gpointer) value, args); + hash2smartfield((gpointer) key, (gpointer) value, args); } } if (cmd->client_id && (cmd->call_opts & lrmd_opt_notify_orig_only)) { crm_client_t *client = crm_client_get_by_id(cmd->client_id); if (client) { send_client_notify(client->id, client, notify); } } else { g_hash_table_foreach(client_connections, send_client_notify, notify); } free_xml(notify); } static void send_generic_notify(int rc, xmlNode * request) { int call_id = 0; xmlNode *notify = NULL; xmlNode *rsc_xml = get_xpath_object("//" F_LRMD_RSC, request, LOG_ERR); const char *rsc_id = crm_element_value(rsc_xml, F_LRMD_RSC_ID); const char *op = crm_element_value(request, F_LRMD_OPERATION); crm_element_value_int(request, F_LRMD_CALLID, &call_id); notify = create_xml_node(NULL, T_LRMD_NOTIFY); crm_xml_add(notify, F_LRMD_ORIGIN, __FUNCTION__); crm_xml_add_int(notify, F_LRMD_RC, rc); crm_xml_add_int(notify, F_LRMD_CALLID, call_id); crm_xml_add(notify, F_LRMD_OPERATION, op); crm_xml_add(notify, F_LRMD_RSC_ID, rsc_id); g_hash_table_foreach(client_connections, send_client_notify, notify); free_xml(notify); } static void cmd_reset(lrmd_cmd_t * cmd) { cmd->lrmd_op_status = 0; cmd->last_pid = 0; memset(&cmd->t_run, 0, sizeof(cmd->t_run)); memset(&cmd->t_queue, 0, sizeof(cmd->t_queue)); free(cmd->exit_reason); cmd->exit_reason = NULL; free(cmd->output); cmd->output = NULL; } static void cmd_finalize(lrmd_cmd_t * cmd, lrmd_rsc_t * rsc) { crm_trace("Resource operation rsc:%s action:%s completed (%p %p)", cmd->rsc_id, cmd->action, rsc ? rsc->active : NULL, cmd); if (rsc && (rsc->active == cmd)) { rsc->active = NULL; mainloop_set_trigger(rsc->work); } if (!rsc) { cmd->rsc_deleted = 1; } send_cmd_complete_notify(cmd); if (cmd->interval && (cmd->lrmd_op_status == PCMK_LRM_OP_CANCELLED)) { if (rsc) { rsc->recurring_ops = g_list_remove(rsc->recurring_ops, cmd); rsc->pending_ops = g_list_remove(rsc->pending_ops, cmd); } free_lrmd_cmd(cmd); } else if (cmd->interval == 0) { if (rsc) { rsc->pending_ops = g_list_remove(rsc->pending_ops, cmd); } free_lrmd_cmd(cmd); } else { /* Clear all the values pertaining just to the last iteration of a recurring op. */ cmd_reset(cmd); } } static int lsb2uniform_rc(const char *action, int rc) { if (rc < 0) { return PCMK_OCF_UNKNOWN_ERROR; } /* status has different return codes that everything else. */ if (!safe_str_eq(action, "status") && !safe_str_eq(action, "monitor")) { if (rc > PCMK_LSB_NOT_RUNNING) { return PCMK_OCF_UNKNOWN_ERROR; } return rc; } switch (rc) { case PCMK_LSB_STATUS_OK: return PCMK_OCF_OK; case PCMK_LSB_STATUS_NOT_INSTALLED: return PCMK_OCF_NOT_INSTALLED; case PCMK_LSB_STATUS_VAR_PID: case PCMK_LSB_STATUS_VAR_LOCK: case PCMK_LSB_STATUS_NOT_RUNNING: return PCMK_OCF_NOT_RUNNING; default: return PCMK_OCF_UNKNOWN_ERROR; } return PCMK_OCF_UNKNOWN_ERROR; } +#if SUPPORT_HEARTBEAT +static int pattern_matched(const char *pat, const char *str) +{ + if (g_pattern_match_simple(pat, str)) { + crm_debug("RA output matched stopped pattern [%s]", pat); + return TRUE; + } + return FALSE; +} + +static int +hb2uniform_rc(const char *action, int rc, const char *stdout_data) +{ + const char *stop_pattern[] = { "*stopped*", "*not*running*" }; + const char *running_pattern[] = { "*running*", "*OK*" }; + char *lower_std_output = NULL; + int result; + + + if (rc < 0) { + return PCMK_OCF_UNKNOWN_ERROR; + } + + /* Treat class heartbeat the same as class lsb. */ + if (!safe_str_eq(action, "status") && !safe_str_eq(action, "monitor")) { + return lsb2uniform_rc(action, rc); + } + + /* for status though, exit code is ignored, + * and the stdout is scanned for specific strings */ + if (stdout_data == NULL) { + crm_warn("No status output from the (hb) resource agent, assuming stopped"); + return PCMK_OCF_NOT_RUNNING; + } + + lower_std_output = g_ascii_strdown(stdout_data, -1); + + if (pattern_matched(stop_pattern[0], lower_std_output) || + pattern_matched(stop_pattern[1], lower_std_output)) { + result = PCMK_OCF_NOT_RUNNING; + } else if (pattern_matched(running_pattern[0], lower_std_output) || + pattern_matched(running_pattern[1], stdout_data)) { + /* "OK" is matched case sensitive */ + result = PCMK_OCF_OK; + } else { + /* It didn't say it was running - must be stopped */ + crm_debug("RA output did not match any pattern, assuming stopped"); + result = PCMK_OCF_NOT_RUNNING; + } + g_free(lower_std_output); + return result; +} +#endif + static int ocf2uniform_rc(int rc) { if (rc < 0 || rc > PCMK_OCF_FAILED_MASTER) { return PCMK_OCF_UNKNOWN_ERROR; } return rc; } static int stonith2uniform_rc(const char *action, int rc) { if (rc == -ENODEV) { if (safe_str_eq(action, "stop")) { rc = PCMK_OCF_OK; } else if (safe_str_eq(action, "start")) { rc = PCMK_OCF_NOT_INSTALLED; } else { rc = PCMK_OCF_NOT_RUNNING; } } else if (rc != 0) { rc = PCMK_OCF_UNKNOWN_ERROR; } return rc; } #if SUPPORT_NAGIOS static int nagios2uniform_rc(const char *action, int rc) { if (rc < 0) { return PCMK_OCF_UNKNOWN_ERROR; } switch (rc) { case NAGIOS_STATE_OK: return PCMK_OCF_OK; case NAGIOS_INSUFFICIENT_PRIV: return PCMK_OCF_INSUFFICIENT_PRIV; case NAGIOS_NOT_INSTALLED: return PCMK_OCF_NOT_INSTALLED; case NAGIOS_STATE_WARNING: case NAGIOS_STATE_CRITICAL: case NAGIOS_STATE_UNKNOWN: case NAGIOS_STATE_DEPENDENT: default: return PCMK_OCF_UNKNOWN_ERROR; } return PCMK_OCF_UNKNOWN_ERROR; } #endif static int get_uniform_rc(const char *standard, const char *action, int rc) { if (safe_str_eq(standard, "ocf")) { return ocf2uniform_rc(rc); } else if (safe_str_eq(standard, "stonith")) { return stonith2uniform_rc(action, rc); } else if (safe_str_eq(standard, "systemd")) { return rc; } else if (safe_str_eq(standard, "upstart")) { return rc; #if SUPPORT_NAGIOS } else if (safe_str_eq(standard, "nagios")) { return nagios2uniform_rc(action, rc); #endif } else { return lsb2uniform_rc(action, rc); } } +static int +action_get_uniform_rc(svc_action_t * action) +{ + lrmd_cmd_t *cmd = action->cb_data; +#if SUPPORT_HEARTBEAT + if (safe_str_eq(action->standard, "heartbeat")) { + return hb2uniform_rc(cmd->action, action->rc, action->stdout_data); + } +#endif + return get_uniform_rc(action->standard, cmd->action, action->rc); +} + void notify_of_new_client(crm_client_t *new_client) { crm_client_t *client = NULL; GHashTableIter iter; xmlNode *notify = NULL; char *key = NULL; notify = create_xml_node(NULL, T_LRMD_NOTIFY); crm_xml_add(notify, F_LRMD_ORIGIN, __FUNCTION__); crm_xml_add(notify, F_LRMD_OPERATION, LRMD_OP_NEW_CLIENT); g_hash_table_iter_init(&iter, client_connections); while (g_hash_table_iter_next(&iter, (gpointer *) & key, (gpointer *) & client)) { if (safe_str_eq(client->id, new_client->id)) { continue; } send_client_notify((gpointer) key, (gpointer) client, (gpointer) notify); } free_xml(notify); } static char * parse_exit_reason(const char *output) { const char *cur = NULL; const char *last = NULL; char *reason = NULL; static int cookie_len = 0; char *eol = NULL; if (output == NULL) { return NULL; } if (!cookie_len) { cookie_len = strlen(PCMK_OCF_REASON_PREFIX); } cur = strstr(output, PCMK_OCF_REASON_PREFIX); for (; cur != NULL; cur = strstr(cur, PCMK_OCF_REASON_PREFIX)) { /* skip over the cookie delimiter string */ cur += cookie_len; last = cur; } if (last == NULL) { return NULL; } /* make our own copy */ reason = calloc(1, (EXIT_REASON_MAX_LEN+1)); CRM_ASSERT(reason); /* limit reason string size */ strncpy(reason, last, EXIT_REASON_MAX_LEN); /* truncate everything after a new line */ eol = strchr(reason, '\n'); if (eol != NULL) { *eol = '\0'; } return reason; } void client_disconnect_cleanup(const char *client_id) { GHashTableIter iter; lrmd_rsc_t *rsc = NULL; char *key = NULL; g_hash_table_iter_init(&iter, rsc_list); while (g_hash_table_iter_next(&iter, (gpointer *) & key, (gpointer *) & rsc)) { if (rsc->call_opts & lrmd_opt_drop_recurring) { /* This client is disconnecting, drop any recurring operations * it may have initiated on the resource */ cancel_all_recurring(rsc, client_id); } } } static void action_complete(svc_action_t * action) { lrmd_rsc_t *rsc; lrmd_cmd_t *cmd = action->cb_data; const char *rclass = NULL; bool goagain = false; if (!cmd) { crm_err("LRMD action (%s) completed does not match any known operations.", action->id); return; } #ifdef HAVE_SYS_TIMEB_H if (cmd->exec_rc != action->rc) { ftime(&cmd->t_rcchange); } #endif cmd->last_pid = action->pid; - cmd->exec_rc = get_uniform_rc(action->standard, cmd->action, action->rc); + cmd->exec_rc = action_get_uniform_rc(action); cmd->lrmd_op_status = action->status; rsc = cmd->rsc_id ? g_hash_table_lookup(rsc_list, cmd->rsc_id) : NULL; if(rsc && safe_str_eq(rsc->class, "service")) { rclass = resources_find_service_class(rsc->class); } else if(rsc) { rclass = rsc->class; } if (safe_str_eq(rclass, "systemd")) { if(cmd->exec_rc == PCMK_OCF_OK && safe_str_eq(cmd->action, "start")) { /* systemd I curse thee! * * systemd returns from start actions after the start _begins_ * not after it completes. * * So we have to jump through a few hoops so that we don't * report 'complete' to the rest of pacemaker until, you know, * its actually done. */ goagain = true; cmd->real_action = cmd->action; cmd->action = strdup("monitor"); } else if(cmd->exec_rc == PCMK_OCF_OK && safe_str_eq(cmd->action, "stop")) { goagain = true; cmd->real_action = cmd->action; cmd->action = strdup("monitor"); } else if(cmd->real_action) { /* Ok, so this is the follow up monitor action to check if start actually completed */ if(cmd->lrmd_op_status == PCMK_LRM_OP_DONE && cmd->exec_rc == PCMK_OCF_PENDING) { goagain = true; } else { int time_sum = 0; int timeout_left = 0; struct timeb now = { 0, }; ftime(&now); time_sum = time_diff_ms(&now, &cmd->t_first_run); timeout_left = cmd->timeout_orig - time_sum; crm_debug("%s %s is now complete (elapsed=%dms, remaining=%dms): %s (%d)", cmd->rsc_id, cmd->real_action, time_sum, timeout_left, services_ocf_exitcode_str(cmd->exec_rc), cmd->exec_rc); if(cmd->lrmd_op_status == PCMK_LRM_OP_DONE && cmd->exec_rc == PCMK_OCF_NOT_RUNNING && safe_str_eq(cmd->real_action, "stop")) { cmd->exec_rc = PCMK_OCF_OK; } } } } #if SUPPORT_NAGIOS if (rsc && safe_str_eq(rsc->class, "nagios")) { if (safe_str_eq(cmd->action, "monitor") && cmd->interval == 0 && cmd->exec_rc == PCMK_OCF_OK) { /* Successfully executed --version for the nagios plugin */ cmd->exec_rc = PCMK_OCF_NOT_RUNNING; } else if (safe_str_eq(cmd->action, "start") && cmd->exec_rc != PCMK_OCF_OK) { goagain = true; } } #endif if(goagain) { int time_sum = 0; int timeout_left = 0; int delay = cmd->timeout_orig / 10; # ifdef HAVE_SYS_TIMEB_H struct timeb now = { 0, }; ftime(&now); time_sum = time_diff_ms(&now, &cmd->t_first_run); timeout_left = cmd->timeout_orig - time_sum; if(delay >= timeout_left && timeout_left > 20) { delay = timeout_left/2; } delay = QB_MIN(2000, delay); if (delay < timeout_left) { cmd->start_delay = delay; cmd->timeout = timeout_left; if(cmd->exec_rc == PCMK_OCF_OK) { crm_debug("%s %s may still be in progress: re-scheduling (elapsed=%dms, remaining=%dms, start_delay=%dms)", cmd->rsc_id, cmd->real_action, time_sum, timeout_left, delay); } else if(cmd->exec_rc == PCMK_OCF_PENDING) { crm_info("%s %s is still in progress: re-scheduling (elapsed=%dms, remaining=%dms, start_delay=%dms)", cmd->rsc_id, cmd->action, time_sum, timeout_left, delay); } else { crm_notice("%s %s failed '%s' (%d): re-scheduling (elapsed=%dms, remaining=%dms, start_delay=%dms)", cmd->rsc_id, cmd->action, services_ocf_exitcode_str(cmd->exec_rc), cmd->exec_rc, time_sum, timeout_left, delay); } cmd_reset(cmd); if(rsc) { rsc->active = NULL; } schedule_lrmd_cmd(rsc, cmd); return; } else { crm_notice("Giving up on %s %s (rc=%d): timeout (elapsed=%dms, remaining=%dms)", cmd->rsc_id, cmd->action, cmd->exec_rc, time_sum, timeout_left); cmd->lrmd_op_status = PCMK_LRM_OP_TIMEOUT; cmd->exec_rc = PCMK_OCF_TIMEOUT; } # endif } if (action->stderr_data) { cmd->output = strdup(action->stderr_data); cmd->exit_reason = parse_exit_reason(action->stderr_data); } else if (action->stdout_data) { cmd->output = strdup(action->stdout_data); } cmd_finalize(cmd, rsc); } static void stonith_action_complete(lrmd_cmd_t * cmd, int rc) { int recurring = cmd->interval; lrmd_rsc_t *rsc = NULL; cmd->exec_rc = get_uniform_rc("stonith", cmd->action, rc); rsc = g_hash_table_lookup(rsc_list, cmd->rsc_id); if (cmd->lrmd_op_status == PCMK_LRM_OP_CANCELLED) { recurring = 0; /* do nothing */ } else if (rc == -ENODEV && safe_str_eq(cmd->action, "monitor")) { /* Not registered == inactive */ cmd->lrmd_op_status = PCMK_LRM_OP_DONE; cmd->exec_rc = PCMK_OCF_NOT_RUNNING; } else if (rc) { /* Attempt to map return codes to op status if possible */ switch (rc) { case -EPROTONOSUPPORT: cmd->lrmd_op_status = PCMK_LRM_OP_NOTSUPPORTED; break; case -ETIME: cmd->lrmd_op_status = PCMK_LRM_OP_TIMEOUT; break; default: /* TODO: This looks wrong. Status should be _DONE and exec_rc set to an error */ cmd->lrmd_op_status = PCMK_LRM_OP_ERROR; } } else { /* command successful */ cmd->lrmd_op_status = PCMK_LRM_OP_DONE; if (safe_str_eq(cmd->action, "start") && rsc) { rsc->stonith_started = 1; } } if (recurring && rsc) { if (cmd->stonith_recurring_id) { g_source_remove(cmd->stonith_recurring_id); } cmd->stonith_recurring_id = g_timeout_add(cmd->interval, stonith_recurring_op_helper, cmd); } cmd_finalize(cmd, rsc); } static void lrmd_stonith_callback(stonith_t * stonith, stonith_callback_data_t * data) { stonith_action_complete(data->userdata, data->rc); } void stonith_connection_failed(void) { GHashTableIter iter; GList *cmd_list = NULL; GList *cmd_iter = NULL; lrmd_rsc_t *rsc = NULL; char *key = NULL; g_hash_table_iter_init(&iter, rsc_list); while (g_hash_table_iter_next(&iter, (gpointer *) & key, (gpointer *) & rsc)) { if (safe_str_eq(rsc->class, "stonith")) { if (rsc->recurring_ops) { cmd_list = g_list_concat(cmd_list, rsc->recurring_ops); } if (rsc->pending_ops) { cmd_list = g_list_concat(cmd_list, rsc->pending_ops); } rsc->pending_ops = rsc->recurring_ops = NULL; } } if (!cmd_list) { return; } crm_err("STONITH connection failed, finalizing %d pending operations.", g_list_length(cmd_list)); for (cmd_iter = cmd_list; cmd_iter; cmd_iter = cmd_iter->next) { stonith_action_complete(cmd_iter->data, -ENOTCONN); } g_list_free(cmd_list); } static int lrmd_rsc_execute_stonith(lrmd_rsc_t * rsc, lrmd_cmd_t * cmd) { int rc = 0; int do_monitor = 0; stonith_t *stonith_api = get_stonith_connection(); if (!stonith_api) { cmd->exec_rc = get_uniform_rc("stonith", cmd->action, -ENOTCONN); cmd->lrmd_op_status = PCMK_LRM_OP_ERROR; cmd_finalize(cmd, rsc); return -EUNATCH; } if (safe_str_eq(cmd->action, "start")) { char *key = NULL; char *value = NULL; stonith_key_value_t *device_params = NULL; if (cmd->params) { GHashTableIter iter; g_hash_table_iter_init(&iter, cmd->params); while (g_hash_table_iter_next(&iter, (gpointer *) & key, (gpointer *) & value)) { device_params = stonith_key_value_add(device_params, key, value); } } /* Stonith automatically registers devices from the IPC when changes occur, * but to avoid a possible race condition between stonith receiving the IPC update * and the lrmd requesting that resource, the lrmd still registers the device as well. * Stonith knows how to handle duplicate device registrations correctly. */ rc = stonith_api->cmds->register_device(stonith_api, st_opt_sync_call, cmd->rsc_id, rsc->provider, rsc->type, device_params); stonith_key_value_freeall(device_params, 1, 1); if (rc == 0) { do_monitor = 1; } } else if (safe_str_eq(cmd->action, "stop")) { rc = stonith_api->cmds->remove_device(stonith_api, st_opt_sync_call, cmd->rsc_id); rsc->stonith_started = 0; } else if (safe_str_eq(cmd->action, "monitor")) { if (cmd->interval) { do_monitor = 1; } else { rc = rsc->stonith_started ? 0 : -ENODEV; } } if (!do_monitor) { goto cleanup_stonith_exec; } rc = stonith_api->cmds->monitor(stonith_api, 0, cmd->rsc_id, cmd->timeout / 1000); rc = stonith_api->cmds->register_callback(stonith_api, rc, 0, 0, cmd, "lrmd_stonith_callback", lrmd_stonith_callback); /* don't cleanup yet, we will find out the result of the monitor later */ if (rc > 0) { rsc->active = cmd; return rc; } else if (rc == 0) { rc = -1; } cleanup_stonith_exec: stonith_action_complete(cmd, rc); return rc; } static void dup_attr(gpointer key, gpointer value, gpointer user_data) { g_hash_table_replace(user_data, strdup(key), strdup(value)); } static int lrmd_rsc_execute_service_lib(lrmd_rsc_t * rsc, lrmd_cmd_t * cmd) { svc_action_t *action = NULL; GHashTable *params_copy = NULL; CRM_ASSERT(rsc); CRM_ASSERT(cmd); crm_trace("Creating action, resource:%s action:%s class:%s provider:%s agent:%s", rsc->rsc_id, cmd->action, rsc->class, rsc->provider, rsc->type); #if SUPPORT_NAGIOS /* Recurring operations are cancelled anyway for a stop operation */ if (safe_str_eq(rsc->class, "nagios") && safe_str_eq(cmd->action, "stop")) { cmd->exec_rc = PCMK_OCF_OK; goto exec_done; } #endif if (cmd->params) { params_copy = g_hash_table_new_full(crm_str_hash, g_str_equal, g_hash_destroy_str, g_hash_destroy_str); if (params_copy != NULL) { g_hash_table_foreach(cmd->params, dup_attr, params_copy); } } action = resources_action_create(rsc->rsc_id, rsc->class, rsc->provider, rsc->type, normalize_action_name(rsc, cmd->action), cmd->interval, cmd->timeout, params_copy); if (!action) { crm_err("Failed to create action, action:%s on resource %s", cmd->action, rsc->rsc_id); cmd->lrmd_op_status = PCMK_LRM_OP_ERROR; goto exec_done; } action->cb_data = cmd; /* 'cmd' may not be valid after this point if * services_action_async() returned TRUE * * Upstart and systemd both synchronously determine monitor/status * results and call action_complete (which may free 'cmd') if necessary. */ if (services_action_async(action, action_complete)) { return TRUE; } cmd->exec_rc = action->rc; if(action->status != PCMK_LRM_OP_DONE) { cmd->lrmd_op_status = action->status; } else { cmd->lrmd_op_status = PCMK_LRM_OP_ERROR; } services_action_free(action); action = NULL; exec_done: cmd_finalize(cmd, rsc); return TRUE; } static gboolean lrmd_rsc_execute(lrmd_rsc_t * rsc) { lrmd_cmd_t *cmd = NULL; CRM_CHECK(rsc != NULL, return FALSE); if (rsc->active) { crm_trace("%s is still active", rsc->rsc_id); return TRUE; } if (rsc->pending_ops) { GList *first = rsc->pending_ops; cmd = first->data; if (cmd->delay_id) { crm_trace ("Command %s %s was asked to run too early, waiting for start_delay timeout of %dms", cmd->rsc_id, cmd->action, cmd->start_delay); return TRUE; } rsc->pending_ops = g_list_remove_link(rsc->pending_ops, first); g_list_free_1(first); #ifdef HAVE_SYS_TIMEB_H if (cmd->t_first_run.time == 0) { ftime(&cmd->t_first_run); } ftime(&cmd->t_run); #endif } if (!cmd) { crm_trace("Nothing further to do for %s", rsc->rsc_id); return TRUE; } rsc->active = cmd; /* only one op at a time for a rsc */ if (cmd->interval) { rsc->recurring_ops = g_list_append(rsc->recurring_ops, cmd); } log_execute(cmd); if (safe_str_eq(rsc->class, "stonith")) { lrmd_rsc_execute_stonith(rsc, cmd); } else { lrmd_rsc_execute_service_lib(rsc, cmd); } return TRUE; } static gboolean lrmd_rsc_dispatch(gpointer user_data) { return lrmd_rsc_execute(user_data); } void free_rsc(gpointer data) { GListPtr gIter = NULL; lrmd_rsc_t *rsc = data; int is_stonith = safe_str_eq(rsc->class, "stonith"); for (gIter = rsc->pending_ops; gIter != NULL; gIter = gIter->next) { lrmd_cmd_t *cmd = gIter->data; /* command was never executed */ cmd->lrmd_op_status = PCMK_LRM_OP_CANCELLED; cmd_finalize(cmd, NULL); } /* frees list, but not list elements. */ g_list_free(rsc->pending_ops); for (gIter = rsc->recurring_ops; gIter != NULL; gIter = gIter->next) { lrmd_cmd_t *cmd = gIter->data; if (is_stonith) { cmd->lrmd_op_status = PCMK_LRM_OP_CANCELLED; cmd_finalize(cmd, NULL); } else { /* This command is already handed off to service library, * let service library cancel it and tell us via the callback * when it is cancelled. The rsc can be safely destroyed * even if we are waiting for the cancel result */ services_action_cancel(rsc->rsc_id, normalize_action_name(rsc, cmd->action), cmd->interval); } } /* frees list, but not list elements. */ g_list_free(rsc->recurring_ops); free(rsc->rsc_id); free(rsc->class); free(rsc->provider); free(rsc->type); mainloop_destroy_trigger(rsc->work); free(rsc); } static int process_lrmd_signon(crm_client_t * client, uint32_t id, xmlNode * request) { xmlNode *reply = create_xml_node(NULL, "reply"); const char *is_ipc_provider = crm_element_value(request, F_LRMD_IS_IPC_PROVIDER); const char *protocol_version = crm_element_value(request, F_LRMD_PROTOCOL_VERSION); if (safe_str_neq(protocol_version, LRMD_PROTOCOL_VERSION)) { crm_xml_add_int(reply, F_LRMD_RC, -EPROTO); crm_xml_add(reply, F_LRMD_PROTOCOL_VERSION, LRMD_PROTOCOL_VERSION); } crm_xml_add(reply, F_LRMD_OPERATION, CRM_OP_REGISTER); crm_xml_add(reply, F_LRMD_CLIENTID, client->id); lrmd_server_send_reply(client, id, reply); if (crm_is_true(is_ipc_provider)) { /* this is a remote connection from a cluster nodes crmd */ #ifdef SUPPORT_REMOTE ipc_proxy_add_provider(client); #endif } free_xml(reply); return pcmk_ok; } static int process_lrmd_rsc_register(crm_client_t * client, uint32_t id, xmlNode * request) { int rc = pcmk_ok; lrmd_rsc_t *rsc = build_rsc_from_xml(request); lrmd_rsc_t *dup = g_hash_table_lookup(rsc_list, rsc->rsc_id); if (dup && safe_str_eq(rsc->class, dup->class) && safe_str_eq(rsc->provider, dup->provider) && safe_str_eq(rsc->type, dup->type)) { crm_warn("Can't add, RSC '%s' already present in the rsc list (%d active resources)", rsc->rsc_id, g_hash_table_size(rsc_list)); free_rsc(rsc); return rc; } g_hash_table_replace(rsc_list, rsc->rsc_id, rsc); crm_info("Added '%s' to the rsc list (%d active resources)", rsc->rsc_id, g_hash_table_size(rsc_list)); return rc; } static void process_lrmd_get_rsc_info(crm_client_t * client, uint32_t id, xmlNode * request) { int rc = pcmk_ok; int send_rc = 0; int call_id = 0; xmlNode *rsc_xml = get_xpath_object("//" F_LRMD_RSC, request, LOG_ERR); const char *rsc_id = crm_element_value(rsc_xml, F_LRMD_RSC_ID); xmlNode *reply = NULL; lrmd_rsc_t *rsc = NULL; crm_element_value_int(request, F_LRMD_CALLID, &call_id); if (!rsc_id) { rc = -ENODEV; goto get_rsc_done; } if (!(rsc = g_hash_table_lookup(rsc_list, rsc_id))) { crm_info("Resource '%s' not found (%d active resources)", rsc_id, g_hash_table_size(rsc_list)); rc = -ENODEV; goto get_rsc_done; } get_rsc_done: reply = create_xml_node(NULL, T_LRMD_REPLY); crm_xml_add(reply, F_LRMD_ORIGIN, __FUNCTION__); crm_xml_add_int(reply, F_LRMD_RC, rc); crm_xml_add_int(reply, F_LRMD_CALLID, call_id); if (rsc) { crm_xml_add(reply, F_LRMD_RSC_ID, rsc->rsc_id); crm_xml_add(reply, F_LRMD_CLASS, rsc->class); crm_xml_add(reply, F_LRMD_PROVIDER, rsc->provider); crm_xml_add(reply, F_LRMD_TYPE, rsc->type); } send_rc = lrmd_server_send_reply(client, id, reply); if (send_rc < 0) { crm_warn("LRMD reply to %s failed: %d", client->name, send_rc); } free_xml(reply); } static int process_lrmd_rsc_unregister(crm_client_t * client, uint32_t id, xmlNode * request) { int rc = pcmk_ok; lrmd_rsc_t *rsc = NULL; xmlNode *rsc_xml = get_xpath_object("//" F_LRMD_RSC, request, LOG_ERR); const char *rsc_id = crm_element_value(rsc_xml, F_LRMD_RSC_ID); if (!rsc_id) { return -ENODEV; } if (!(rsc = g_hash_table_lookup(rsc_list, rsc_id))) { crm_info("Resource '%s' not found (%d active resources)", rsc_id, g_hash_table_size(rsc_list)); return pcmk_ok; } if (rsc->active) { /* let the caller know there are still active ops on this rsc to watch for */ crm_trace("Operation still in progress: %p", rsc->active); rc = -EINPROGRESS; } g_hash_table_remove(rsc_list, rsc_id); return rc; } static int process_lrmd_rsc_exec(crm_client_t * client, uint32_t id, xmlNode * request) { lrmd_rsc_t *rsc = NULL; lrmd_cmd_t *cmd = NULL; xmlNode *rsc_xml = get_xpath_object("//" F_LRMD_RSC, request, LOG_ERR); const char *rsc_id = crm_element_value(rsc_xml, F_LRMD_RSC_ID); int call_id; if (!rsc_id) { return -EINVAL; } if (!(rsc = g_hash_table_lookup(rsc_list, rsc_id))) { crm_info("Resource '%s' not found (%d active resources)", rsc_id, g_hash_table_size(rsc_list)); return -ENODEV; } cmd = create_lrmd_cmd(request, client); call_id = cmd->call_id; /* Don't reference cmd after handing it off to be scheduled. * The cmd could get merged and freed. */ schedule_lrmd_cmd(rsc, cmd); return call_id; } static int cancel_op(const char *rsc_id, const char *action, int interval) { GListPtr gIter = NULL; lrmd_rsc_t *rsc = g_hash_table_lookup(rsc_list, rsc_id); /* How to cancel an action. * 1. Check pending ops list, if it hasn't been handed off * to the service library or stonith recurring list remove * it there and that will stop it. * 2. If it isn't in the pending ops list, then its either a * recurring op in the stonith recurring list, or the service * library's recurring list. Stop it there * 3. If not found in any lists, then this operation has either * been executed already and is not a recurring operation, or * never existed. */ if (!rsc) { return -ENODEV; } for (gIter = rsc->pending_ops; gIter != NULL; gIter = gIter->next) { lrmd_cmd_t *cmd = gIter->data; if (safe_str_eq(cmd->action, action) && cmd->interval == interval) { cmd->lrmd_op_status = PCMK_LRM_OP_CANCELLED; cmd_finalize(cmd, rsc); return pcmk_ok; } } if (safe_str_eq(rsc->class, "stonith")) { /* The service library does not handle stonith operations. * We have to handle recurring stonith opereations ourselves. */ for (gIter = rsc->recurring_ops; gIter != NULL; gIter = gIter->next) { lrmd_cmd_t *cmd = gIter->data; if (safe_str_eq(cmd->action, action) && cmd->interval == interval) { cmd->lrmd_op_status = PCMK_LRM_OP_CANCELLED; if (rsc->active != cmd) { cmd_finalize(cmd, rsc); } return pcmk_ok; } } } else if (services_action_cancel(rsc_id, normalize_action_name(rsc, action), interval) == TRUE) { /* The service library will tell the action_complete callback function * this action was cancelled, which will destroy the cmd and remove * it from the recurring_op list. Do not do that in this function * if the service library says it cancelled it. */ return pcmk_ok; } return -EOPNOTSUPP; } static void cancel_all_recurring(lrmd_rsc_t * rsc, const char *client_id) { GList *cmd_list = NULL; GList *cmd_iter = NULL; /* Notice a copy of each list is created when concat is called. * This prevents odd behavior from occurring when the cmd_list * is iterated through later on. It is possible the cancel_op * function may end up modifying the recurring_ops and pending_ops * lists. If we did not copy those lists, our cmd_list iteration * could get messed up.*/ if (rsc->recurring_ops) { cmd_list = g_list_concat(cmd_list, g_list_copy(rsc->recurring_ops)); } if (rsc->pending_ops) { cmd_list = g_list_concat(cmd_list, g_list_copy(rsc->pending_ops)); } if (!cmd_list) { return; } for (cmd_iter = cmd_list; cmd_iter; cmd_iter = cmd_iter->next) { lrmd_cmd_t *cmd = cmd_iter->data; if (cmd->interval == 0) { continue; } if (client_id && safe_str_neq(cmd->client_id, client_id)) { continue; } cancel_op(rsc->rsc_id, cmd->action, cmd->interval); } /* frees only the copied list data, not the cmds */ g_list_free(cmd_list); } static int process_lrmd_rsc_cancel(crm_client_t * client, uint32_t id, xmlNode * request) { xmlNode *rsc_xml = get_xpath_object("//" F_LRMD_RSC, request, LOG_ERR); const char *rsc_id = crm_element_value(rsc_xml, F_LRMD_RSC_ID); const char *action = crm_element_value(rsc_xml, F_LRMD_RSC_ACTION); int interval = 0; crm_element_value_int(rsc_xml, F_LRMD_RSC_INTERVAL, &interval); if (!rsc_id || !action) { return -EINVAL; } return cancel_op(rsc_id, action, interval); } void process_lrmd_message(crm_client_t * client, uint32_t id, xmlNode * request) { int rc = pcmk_ok; int call_id = 0; const char *op = crm_element_value(request, F_LRMD_OPERATION); int do_reply = 0; int do_notify = 0; crm_trace("Processing %s operation from %s", op, client->id); crm_element_value_int(request, F_LRMD_CALLID, &call_id); if (crm_str_eq(op, CRM_OP_IPC_FWD, TRUE)) { #ifdef SUPPORT_REMOTE ipc_proxy_forward_client(client, request); #endif do_reply = 1; } else if (crm_str_eq(op, CRM_OP_REGISTER, TRUE)) { rc = process_lrmd_signon(client, id, request); } else if (crm_str_eq(op, LRMD_OP_RSC_REG, TRUE)) { rc = process_lrmd_rsc_register(client, id, request); do_notify = 1; do_reply = 1; } else if (crm_str_eq(op, LRMD_OP_RSC_INFO, TRUE)) { process_lrmd_get_rsc_info(client, id, request); } else if (crm_str_eq(op, LRMD_OP_RSC_UNREG, TRUE)) { rc = process_lrmd_rsc_unregister(client, id, request); /* don't notify anyone about failed un-registers */ if (rc == pcmk_ok || rc == -EINPROGRESS) { do_notify = 1; } do_reply = 1; } else if (crm_str_eq(op, LRMD_OP_RSC_EXEC, TRUE)) { rc = process_lrmd_rsc_exec(client, id, request); do_reply = 1; } else if (crm_str_eq(op, LRMD_OP_RSC_CANCEL, TRUE)) { rc = process_lrmd_rsc_cancel(client, id, request); do_reply = 1; } else if (crm_str_eq(op, LRMD_OP_POKE, TRUE)) { do_notify = 1; do_reply = 1; } else { rc = -EOPNOTSUPP; do_reply = 1; crm_err("Unknown %s from %s", op, client->name); crm_log_xml_warn(request, "UnknownOp"); } crm_debug("Processed %s operation from %s: rc=%d, reply=%d, notify=%d, exit=%d", op, client->id, rc, do_reply, do_notify, exit); if (do_reply) { send_reply(client, rc, id, call_id); } if (do_notify) { send_generic_notify(rc, request); } } diff --git a/lrmd/regression.py.in b/lrmd/regression.py.in index 50e975e4c8..118950eba7 100755 --- a/lrmd/regression.py.in +++ b/lrmd/regression.py.in @@ -1,1071 +1,1107 @@ #!/usr/bin/python # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. import os import sys import subprocess import shlex import time # Where to find test binaries # Prefer the source tree if available build_dir="@abs_top_builddir@" test_dir=sys.path[0] new_path=os.environ['PATH'] if os.path.exists("%s/regression.py.in" % test_dir): print "Running tests from the source tree: %s (%s)" % (build_dir, test_dir) new_path = "%s/lrmd:%s" % (build_dir, new_path) # For lrmd, lrmd_test and pacemaker_remoted new_path = "%s/tools:%s" % (build_dir, new_path) # For crm_resource new_path = "%s/fencing:%s" % (build_dir, new_path) # For stonithd else: print "Running tests from the install tree: @CRM_DAEMON_DIR@ (not %s)" % test_dir new_path = "@CRM_DAEMON_DIR@:%s" % (new_path) # For stonithd, lrmd, lrmd_test and pacemaker_remoted print new_path os.environ['PATH']=new_path def output_from_command(command, no_wait=0): test = subprocess.Popen(shlex.split(command), stdout=subprocess.PIPE) if no_wait == 0: test.wait() else: return 0 return test.communicate()[0].split("\n") class Test: def __init__(self, name, description, verbose = 0, tls = 0): self.name = name self.description = description self.cmds = [] if tls: self.daemon_location = "pacemaker_remoted" else: self.daemon_location = "lrmd" self.test_tool_location = "lrmd_test" self.verbose = verbose self.tls = tls self.result_txt = "" self.cmd_tool_output = "" self.result_exitcode = 0; self.lrmd_process = None self.stonith_process = None self.executed = 0 def __new_cmd(self, cmd, args, exitcode, stdout_match = "", no_wait = 0, stdout_negative_match = "", kill=None): if self.verbose and cmd == self.test_tool_location: args = args + " -V " if (cmd == self.test_tool_location) and self.tls: args = args + " -S " self.cmds.append( { "cmd" : cmd, "kill" : kill, "args" : args, "expected_exitcode" : exitcode, "stdout_match" : stdout_match, "stdout_negative_match" : stdout_negative_match, "no_wait" : no_wait, "cmd_output" : "", } ) def start_environment(self): ### make sure we are in full control here ### cmd = shlex.split("killall -q -9 stonithd lt-stonithd lrmd lt-lrmd lrmd_test lt-lrmd_test pacemaker_remoted") test = subprocess.Popen(cmd, stdout=subprocess.PIPE) test.wait() additional_args = "" if self.tls == 0: self.stonith_process = subprocess.Popen(shlex.split("stonithd -s")) if self.verbose: additional_args = additional_args + " -V" self.lrmd_process = subprocess.Popen(shlex.split("%s %s -l /tmp/lrmd-regression.log" % (self.daemon_location, additional_args))) time.sleep(1) def clean_environment(self): if self.lrmd_process: self.lrmd_process.terminate() self.lrmd_process.wait() if self.verbose: print "Daemon output" f = open('/tmp/lrmd-regression.log', 'r') for line in f.readlines(): print line.strip() os.remove('/tmp/lrmd-regression.log') if self.stonith_process: self.stonith_process.terminate() self.stonith_process.wait() self.lrmd_process = None self.stonith_process = None def add_sys_cmd(self, cmd, args): self.__new_cmd(cmd, args, 0, "") def add_sys_cmd_no_wait(self, cmd, args): self.__new_cmd(cmd, args, 0, "", 1) def add_cmd_check_stdout(self, args, match, no_match = ""): self.__new_cmd(self.test_tool_location, args, 0, match, 0, no_match) def add_cmd(self, args): self.__new_cmd(self.test_tool_location, args, 0, "") def add_cmd_and_kill(self, killProc, args): self.__new_cmd(self.test_tool_location, args, 0, "", kill=killProc) def add_expected_fail_cmd(self, args): self.__new_cmd(self.test_tool_location, args, 1, "") def get_exitcode(self): return self.result_exitcode def print_result(self, filler): print "%s%s" % (filler, self.result_txt) def run_cmd(self, args): cmd = shlex.split(args['args']) cmd.insert(0, args['cmd']) if self.verbose: print "\n\nRunning: "+" ".join(cmd) test = subprocess.Popen(cmd, stdout=subprocess.PIPE) if args['kill']: if self.verbose: print "Also running: "+args['kill'] ### Typically the kill argument is used to detect some sort of ### failure. Without yeilding for a few seconds here the process ### launched earlier that is listening for the failure may not have time ### to connect to the lrmd. time.sleep(2) subprocess.Popen(shlex.split(args['kill'])) if args['no_wait'] == 0: test.wait() else: return 0 output = test.communicate()[0] if args['stdout_match'] != "" and output.count(args['stdout_match']) == 0: test.returncode = -2 print "STDOUT string '%s' was not found in cmd output" % (args['stdout_match']) if args['stdout_negative_match'] != "" and output.count(args['stdout_negative_match']) != 0: test.returncode = -2 print "STDOUT string '%s' was found in cmd output" % (args['stdout_negative_match']) args['cmd_output'] = output return test.returncode; def run(self): res = 0 i = 1 if self.tls and self.name.count("stonith") != 0: self.result_txt = "SKIPPED - '%s' - disabled when testing pacemaker_remote" % (self.name) print self.result_txt return res self.start_environment() if self.verbose: print "\n--- START TEST - %s" % self.name self.result_txt = "SUCCESS - '%s'" % (self.name) self.result_exitcode = 0 for cmd in self.cmds: res = self.run_cmd(cmd) if res != cmd['expected_exitcode']: print cmd['cmd_output'] print "Step %d FAILED - command returned %d, expected %d" % (i, res, cmd['expected_exitcode']) self.result_txt = "FAILURE - '%s' failed at step %d. Command: lrmd_test %s" % (self.name, i, cmd['args']) self.result_exitcode = -1 break else: if self.verbose: print cmd['cmd_output'].strip() print "Step %d SUCCESS" % (i) i = i + 1 self.clean_environment() print self.result_txt if self.verbose: print "--- END TEST - %s\n" % self.name self.executed = 1 return res class Tests: def __init__(self, verbose = 0, tls = 0): self.tests = [] self.verbose = verbose self.tls = tls; self.rsc_classes = output_from_command("crm_resource --list-standards") self.rsc_classes = self.rsc_classes[:-1] # Strip trailing empty line self.need_authkey = 0 self.action_timeout = " -t 5000 " if self.tls: self.rsc_classes.remove("stonith") if "systemd" in self.rsc_classes: # the lrmd_dummy_daemon requires this, we are importing it # here just to guarantee it is installed before allowing this # script to run. Otherwise, running without this import being # available will make all the systemd tests look like they fail, # which is really scary looking. I'd rather see the import fail. import systemd.daemon print "Testing "+repr(self.rsc_classes) self.common_cmds = { "ocf_reg_line" : "-c register_rsc -r ocf_test_rsc "+self.action_timeout+" -C ocf -P pacemaker -T Dummy", "ocf_reg_event" : "-l \"NEW_EVENT event_type:register rsc_id:ocf_test_rsc action:none rc:ok op_status:complete\"", "ocf_unreg_line" : "-c unregister_rsc -r \"ocf_test_rsc\" "+self.action_timeout, "ocf_unreg_event" : "-l \"NEW_EVENT event_type:unregister rsc_id:ocf_test_rsc action:none rc:ok op_status:complete\"", "ocf_start_line" : "-c exec -r \"ocf_test_rsc\" -a \"start\" "+self.action_timeout, "ocf_start_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:ocf_test_rsc action:start rc:ok op_status:complete\" ", "ocf_stop_line" : "-c exec -r \"ocf_test_rsc\" -a \"stop\" "+self.action_timeout, "ocf_stop_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:ocf_test_rsc action:stop rc:ok op_status:complete\" ", "ocf_monitor_line" : "-c exec -r \"ocf_test_rsc\" -a \"monitor\" -i \"2000\" "+self.action_timeout, "ocf_monitor_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:ocf_test_rsc action:monitor rc:ok op_status:complete\" "+self.action_timeout, "ocf_cancel_line" : "-c cancel -r \"ocf_test_rsc\" -a \"monitor\" -i \"2000\" -t \"3000\" ", "ocf_cancel_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:ocf_test_rsc action:monitor rc:ok op_status:Cancelled\" ", "systemd_reg_line" : "-c register_rsc -r systemd_test_rsc "+self.action_timeout+" -C systemd -T lrmd_dummy_daemon", "systemd_reg_event" : "-l \"NEW_EVENT event_type:register rsc_id:systemd_test_rsc action:none rc:ok op_status:complete\"", "systemd_unreg_line" : "-c unregister_rsc -r \"systemd_test_rsc\" "+self.action_timeout, "systemd_unreg_event" : "-l \"NEW_EVENT event_type:unregister rsc_id:systemd_test_rsc action:none rc:ok op_status:complete\"", "systemd_start_line" : "-c exec -r \"systemd_test_rsc\" -a \"start\" "+self.action_timeout, "systemd_start_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:systemd_test_rsc action:start rc:ok op_status:complete\" ", "systemd_stop_line" : "-c exec -r \"systemd_test_rsc\" -a \"stop\" "+self.action_timeout, "systemd_stop_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:systemd_test_rsc action:stop rc:ok op_status:complete\" ", "systemd_monitor_line" : "-c exec -r \"systemd_test_rsc\" -a \"monitor\" -i \"2000\" "+self.action_timeout, "systemd_monitor_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:systemd_test_rsc action:monitor rc:ok op_status:complete\" "+self.action_timeout, "systemd_cancel_line" : "-c cancel -r \"systemd_test_rsc\" -a \"monitor\" -i \"2000\" -t \"3000\" ", "systemd_cancel_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:systemd_test_rsc action:monitor rc:ok op_status:Cancelled\" ", "upstart_reg_line" : "-c register_rsc -r upstart_test_rsc "+self.action_timeout+" -C upstart -T lrmd_dummy_daemon", "upstart_reg_event" : "-l \"NEW_EVENT event_type:register rsc_id:upstart_test_rsc action:none rc:ok op_status:complete\"", "upstart_unreg_line" : "-c unregister_rsc -r \"upstart_test_rsc\" "+self.action_timeout, "upstart_unreg_event" : "-l \"NEW_EVENT event_type:unregister rsc_id:upstart_test_rsc action:none rc:ok op_status:complete\"", "upstart_start_line" : "-c exec -r \"upstart_test_rsc\" -a \"start\" "+self.action_timeout, "upstart_start_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:upstart_test_rsc action:start rc:ok op_status:complete\" ", "upstart_stop_line" : "-c exec -r \"upstart_test_rsc\" -a \"stop\" "+self.action_timeout, "upstart_stop_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:upstart_test_rsc action:stop rc:ok op_status:complete\" ", "upstart_monitor_line" : "-c exec -r \"upstart_test_rsc\" -a \"monitor\" -i \"2000\" "+self.action_timeout, "upstart_monitor_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:upstart_test_rsc action:monitor rc:ok op_status:complete\" "+self.action_timeout, "upstart_cancel_line" : "-c cancel -r \"upstart_test_rsc\" -a \"monitor\" -i \"2000\" -t \"3000\" ", "upstart_cancel_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:upstart_test_rsc action:monitor rc:ok op_status:Cancelled\" ", "service_reg_line" : "-c register_rsc -r service_test_rsc "+self.action_timeout+" -C service -T LSBDummy", "service_reg_event" : "-l \"NEW_EVENT event_type:register rsc_id:service_test_rsc action:none rc:ok op_status:complete\"", "service_unreg_line" : "-c unregister_rsc -r \"service_test_rsc\" "+self.action_timeout, "service_unreg_event" : "-l \"NEW_EVENT event_type:unregister rsc_id:service_test_rsc action:none rc:ok op_status:complete\"", "service_start_line" : "-c exec -r \"service_test_rsc\" -a \"start\" "+self.action_timeout, "service_start_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:service_test_rsc action:start rc:ok op_status:complete\" ", "service_stop_line" : "-c exec -r \"service_test_rsc\" -a \"stop\" "+self.action_timeout, "service_stop_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:service_test_rsc action:stop rc:ok op_status:complete\" ", "service_monitor_line" : "-c exec -r \"service_test_rsc\" -a \"monitor\" -i \"2000\" "+self.action_timeout, "service_monitor_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:service_test_rsc action:monitor rc:ok op_status:complete\" "+self.action_timeout, "service_cancel_line" : "-c cancel -r \"service_test_rsc\" -a \"monitor\" -i \"2000\" -t \"3000\" ", "service_cancel_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:service_test_rsc action:monitor rc:ok op_status:Cancelled\" ", "lsb_reg_line" : "-c register_rsc -r lsb_test_rsc "+self.action_timeout+" -C lsb -T LSBDummy", "lsb_reg_event" : "-l \"NEW_EVENT event_type:register rsc_id:lsb_test_rsc action:none rc:ok op_status:complete\" ", "lsb_unreg_line" : "-c unregister_rsc -r \"lsb_test_rsc\" "+self.action_timeout, "lsb_unreg_event" : "-l \"NEW_EVENT event_type:unregister rsc_id:lsb_test_rsc action:none rc:ok op_status:complete\"", "lsb_start_line" : "-c exec -r \"lsb_test_rsc\" -a \"start\" "+self.action_timeout, "lsb_start_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:lsb_test_rsc action:start rc:ok op_status:complete\" ", "lsb_stop_line" : "-c exec -r \"lsb_test_rsc\" -a \"stop\" "+self.action_timeout, "lsb_stop_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:lsb_test_rsc action:stop rc:ok op_status:complete\" ", "lsb_monitor_line" : "-c exec -r \"lsb_test_rsc\" -a status -i \"2000\" "+self.action_timeout, "lsb_monitor_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:lsb_test_rsc action:status rc:ok op_status:complete\" "+self.action_timeout, "lsb_cancel_line" : "-c cancel -r \"lsb_test_rsc\" -a \"status\" -i \"2000\" -t \"3000\" ", "lsb_cancel_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:lsb_test_rsc action:status rc:ok op_status:Cancelled\" ", + "heartbeat_reg_line" : "-c register_rsc -r hb_test_rsc "+self.action_timeout+" -C heartbeat -T HBDummy", + "heartbeat_reg_event" : "-l \"NEW_EVENT event_type:register rsc_id:hb_test_rsc action:none rc:ok op_status:complete\" ", + "heartbeat_unreg_line" : "-c unregister_rsc -r \"hb_test_rsc\" "+self.action_timeout, + "heartbeat_unreg_event" : "-l \"NEW_EVENT event_type:unregister rsc_id:hb_test_rsc action:none rc:ok op_status:complete\"", + "heartbeat_start_line" : "-c exec -r \"hb_test_rsc\" -a \"start\" -k 1 -v a -k 2 -v b "+self.action_timeout, + "heartbeat_start_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:hb_test_rsc action:start rc:ok op_status:complete\" ", + "heartbeat_stop_line" : "-c exec -r \"hb_test_rsc\" -a \"stop\" -k 1 -v a -k 2 -v b "+self.action_timeout, + "heartbeat_stop_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:hb_test_rsc action:stop rc:ok op_status:complete\" ", + "heartbeat_monitor_line" : "-c exec -r \"hb_test_rsc\" -a status -k 1 -v a -k 2 -v b -i \"2000\" "+self.action_timeout, + "heartbeat_monitor_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:hb_test_rsc action:status rc:ok op_status:complete\" "+self.action_timeout, + "heartbeat_cancel_line" : "-c cancel -r \"hb_test_rsc\" -a \"status\" -k 1 -v a -k 2 -v b -i \"2000\" -t \"3000\" ", + "heartbeat_cancel_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:hb_test_rsc action:status rc:ok op_status:Cancelled\" ", + "stonith_reg_line" : "-c register_rsc -r stonith_test_rsc "+self.action_timeout+" -C stonith -P pacemaker -T fence_dummy_monitor", "stonith_reg_event" : "-l \"NEW_EVENT event_type:register rsc_id:stonith_test_rsc action:none rc:ok op_status:complete\" ", "stonith_unreg_line" : "-c unregister_rsc -r \"stonith_test_rsc\" "+self.action_timeout, "stonith_unreg_event" : "-l \"NEW_EVENT event_type:unregister rsc_id:stonith_test_rsc action:none rc:ok op_status:complete\"", "stonith_start_line" : "-c exec -r \"stonith_test_rsc\" -a \"start\" -t 8000 ", "stonith_start_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:stonith_test_rsc action:start rc:ok op_status:complete\" ", "stonith_stop_line" : "-c exec -r \"stonith_test_rsc\" -a \"stop\" "+self.action_timeout, "stonith_stop_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:stonith_test_rsc action:stop rc:ok op_status:complete\" ", "stonith_monitor_line" : "-c exec -r \"stonith_test_rsc\" -a \"monitor\" -i \"2000\" "+self.action_timeout, "stonith_monitor_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:stonith_test_rsc action:monitor rc:ok op_status:complete\" "+self.action_timeout, "stonith_cancel_line" : "-c cancel -r \"stonith_test_rsc\" -a \"monitor\" -i \"2000\" -t \"3000\" ", "stonith_cancel_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:stonith_test_rsc action:monitor rc:ok op_status:Cancelled\" ", } def new_test(self, name, description): test = Test(name, description, self.verbose, self.tls) self.tests.append(test) return test def setup_test_environment(self): os.system("service pacemaker_remote stop") self.cleanup_test_environment() if self.tls and not os.path.isfile("/etc/pacemaker/authkey"): self.need_authkey = 1 os.system("mkdir -p /etc/pacemaker") os.system("dd if=/dev/urandom of=/etc/pacemaker/authkey bs=4096 count=1") ### Make fake systemd daemon and unit file ### dummy_daemon = """#!/bin/python import time, systemd.daemon time.sleep(3) systemd.daemon.notify("READY=1") while True: time.sleep(5) """ dummy_service_file = """ [Unit] Description=Dummy resource that takes a while to start [Service] Type=notify ExecStart=/usr/sbin/lrmd_dummy_daemon """ dummy_upstart_job = (""" description "Dummy service for regression tests" exec dd if=/dev/random of=/dev/null """) dummy_fence_sleep_agent = ("""#!/usr/bin/python import sys import time def main(): for line in sys.stdin.readlines(): if line.count("monitor") > 0: time.sleep(30000) sys.exit(0) sys.exit(-1) if __name__ == "__main__": main() """) dummy_fence_agent = ("""#!/usr/bin/python import sys def main(): for line in sys.stdin.readlines(): if line.count("monitor") > 0: sys.exit(0) if line.count("metadata") > 0: print '' print ' dummy description.' print ' http://www.example.com' print ' ' print ' ' print ' ' print ' ' print ' Fencing Action' print ' ' print ' ' print ' ' print ' ' print ' Physical plug number or name of virtual machine' print ' ' print ' ' print ' ' print ' ' print ' ' print ' ' print ' ' print ' ' print '' sys.exit(0) sys.exit(-1) if __name__ == "__main__": main() """) os.system("cat <<-END >>/etc/init/lrmd_dummy_daemon.conf\n%s\nEND" % (dummy_upstart_job)) os.system("cat <<-END >>/usr/sbin/lrmd_dummy_daemon\n%s\nEND" % (dummy_daemon)) os.system("cat <<-END >>/lib/systemd/system/lrmd_dummy_daemon.service\n%s\nEND" % (dummy_service_file)) os.system("chmod a+x /usr/sbin/lrmd_dummy_daemon") os.system("cat <<-END >>/usr/sbin/fence_dummy_sleep\n%s\nEND" % (dummy_fence_sleep_agent)) os.system("chmod 711 /usr/sbin/fence_dummy_sleep") os.system("cat <<-END >>/usr/sbin/fence_dummy_monitor\n%s\nEND" % (dummy_fence_agent)) os.system("chmod 711 /usr/sbin/fence_dummy_monitor") if os.path.exists("%s/cts/LSBDummy" % build_dir): print "Using %s/cts/LSBDummy" % build_dir os.system("cp %s/cts/LSBDummy /etc/init.d/LSBDummy" % build_dir) if not os.path.exists("@OCF_RA_DIR@/pacemaker"): os.system("mkdir -p @OCF_RA_DIR@/pacemaker/") # Install helper OCF agents for ra in [ "Dummy", "Stateful", "ping" ]: os.system("cp %s/extra/resources/%s @OCF_RA_DIR@/pacemaker/%s" % (build_dir, ra, ra)) os.system("chmod a+x @OCF_RA_DIR@/pacemaker/%s" % (ra)) else: # Assume it's installed print "Using @datadir@/@PACKAGE@/tests/cts/LSBDummy" os.system("cp @datadir@/@PACKAGE@/tests/cts/LSBDummy /etc/init.d/LSBDummy") os.system("chmod a+x /etc/init.d/LSBDummy") os.system("ls -al /etc/init.d/LSBDummy") os.system("mkdir -p @CRM_CORE_DIR@/root") + os.system("mkdir -p /etc/ha.d/resource.d") + if os.path.exists("%s/cts/HBDummy" % build_dir): + print "Using %s/cts/HBDummy" % build_dir + os.system("cp %s/cts/HBDummy /etc/ha.d/resource.d/HBDummy" % build_dir) + else: + # Assume it's installed + print "Using @datadir@/@PACKAGE@/tests/cts/HBDummy" + os.system("cp @datadir@/@PACKAGE@/tests/cts/HBDummy /etc/ha.d/resource.d/HBDummy") + + os.system("chmod a+x /etc/ha.d/resource.d/HBDummy") + os.system("ls -al /etc/ha.d/resource.d/HBDummy") + if os.path.exists("/bin/systemctl"): os.system("systemctl daemon-reload") def cleanup_test_environment(self): if self.need_authkey: os.system("rm -f /etc/pacemaker/authkey") os.system("rm -f /etc/init.d/LSBDummy") + os.system("rm -f /etc/ha.d/resource.d/HBDummy") os.system("rm -f /lib/systemd/system/lrmd_dummy_daemon.service") os.system("rm -f /usr/sbin/lrmd_dummy_daemon") os.system("rm -f /usr/sbin/fence_dummy_monitor") os.system("rm -f /usr/sbin/fence_dummy_sleep") if os.path.exists("/bin/systemctl"): os.system("systemctl daemon-reload") ### These are tests that should apply to all resource classes ### def build_generic_tests(self): common_cmds = self.common_cmds ### register/unregister tests ### for rsc in self.rsc_classes: test = self.new_test("generic_registration_%s" % (rsc), "Simple resource registration test for %s standard" % (rsc)) test.add_cmd(common_cmds["%s_reg_line" % (rsc)] + " " + common_cmds["%s_reg_event" % (rsc)]) test.add_cmd(common_cmds["%s_unreg_line" % (rsc)] + " " + common_cmds["%s_unreg_event" % (rsc)]) ### start/stop tests ### for rsc in self.rsc_classes: test = self.new_test("generic_start_stop_%s" % (rsc), "Simple start and stop test for %s standard" % (rsc)) test.add_cmd(common_cmds["%s_reg_line" % (rsc)] + " " + common_cmds["%s_reg_event" % (rsc)]) test.add_cmd(common_cmds["%s_start_line" % (rsc)] + " " + common_cmds["%s_start_event" % (rsc)]) test.add_cmd(common_cmds["%s_stop_line" % (rsc)] + " " + common_cmds["%s_stop_event" % (rsc)]) test.add_cmd(common_cmds["%s_unreg_line" % (rsc)] + " " + common_cmds["%s_unreg_event" % (rsc)]) ### monitor cancel test ### for rsc in self.rsc_classes: test = self.new_test("generic_monitor_cancel_%s" % (rsc), "Simple monitor cancel test for %s standard" % (rsc)) test.add_cmd(common_cmds["%s_reg_line" % (rsc)] + " " + common_cmds["%s_reg_event" % (rsc)]) test.add_cmd(common_cmds["%s_start_line" % (rsc)] + " " + common_cmds["%s_start_event" % (rsc)]) test.add_cmd(common_cmds["%s_monitor_line" % (rsc)] + " " + common_cmds["%s_monitor_event" % (rsc)]) test.add_cmd(common_cmds["%s_monitor_event" % (rsc)]) ### If this fails, that means the monitor may not be getting rescheduled #### test.add_cmd(common_cmds["%s_monitor_event" % (rsc)]) ### If this fails, that means the monitor may not be getting rescheduled #### test.add_cmd(common_cmds["%s_cancel_line" % (rsc)] + " " + common_cmds["%s_cancel_event" % (rsc)]) test.add_expected_fail_cmd(common_cmds["%s_monitor_event" % (rsc)]) ### If this happens the monitor did not actually cancel correctly. ### test.add_expected_fail_cmd(common_cmds["%s_monitor_event" % (rsc)]) ### If this happens the monitor did not actually cancel correctly. ### test.add_cmd(common_cmds["%s_stop_line" % (rsc)] + " " + common_cmds["%s_stop_event" % (rsc)]) test.add_cmd(common_cmds["%s_unreg_line" % (rsc)] + " " + common_cmds["%s_unreg_event" % (rsc)]) ### monitor duplicate test ### for rsc in self.rsc_classes: test = self.new_test("generic_monitor_duplicate_%s" % (rsc), "Test creation and canceling of duplicate monitors for %s standard" % (rsc)) test.add_cmd(common_cmds["%s_reg_line" % (rsc)] + " " + common_cmds["%s_reg_event" % (rsc)]) test.add_cmd(common_cmds["%s_start_line" % (rsc)] + " " + common_cmds["%s_start_event" % (rsc)]) test.add_cmd(common_cmds["%s_monitor_line" % (rsc)] + " " + common_cmds["%s_monitor_event" % (rsc)]) test.add_cmd(common_cmds["%s_monitor_event" % (rsc)]) ### If this fails, that means the monitor may not be getting rescheduled #### test.add_cmd(common_cmds["%s_monitor_event" % (rsc)]) ### If this fails, that means the monitor may not be getting rescheduled #### # Add the duplicate monitors. test.add_cmd(common_cmds["%s_monitor_line" % (rsc)] + " " + common_cmds["%s_monitor_event" % (rsc)]) test.add_cmd(common_cmds["%s_monitor_line" % (rsc)] + " " + common_cmds["%s_monitor_event" % (rsc)]) test.add_cmd(common_cmds["%s_monitor_line" % (rsc)] + " " + common_cmds["%s_monitor_event" % (rsc)]) test.add_cmd(common_cmds["%s_monitor_line" % (rsc)] + " " + common_cmds["%s_monitor_event" % (rsc)]) # verify we still get update events test.add_cmd(common_cmds["%s_monitor_event" % (rsc)]) ### If this fails, that means the monitor may not be getting rescheduled #### # cancel the monitor, if the duplicate merged with the original, we should no longer see monitor updates test.add_cmd(common_cmds["%s_cancel_line" % (rsc)] + " " + common_cmds["%s_cancel_event" % (rsc)]) test.add_expected_fail_cmd(common_cmds["%s_monitor_event" % (rsc)]) ### If this happens the monitor did not actually cancel correctly. ### test.add_expected_fail_cmd(common_cmds["%s_monitor_event" % (rsc)]) ### If this happens the monitor did not actually cancel correctly. ### test.add_cmd(common_cmds["%s_stop_line" % (rsc)] + " " + common_cmds["%s_stop_event" % (rsc)]) test.add_cmd(common_cmds["%s_unreg_line" % (rsc)] + " " + common_cmds["%s_unreg_event" % (rsc)]) ### stop implies cancel test ### for rsc in self.rsc_classes: test = self.new_test("generic_stop_implies_cancel_%s" % (rsc), "Verify stopping a resource implies cancel of recurring ops for %s standard" % (rsc)) test.add_cmd(common_cmds["%s_reg_line" % (rsc)] + " " + common_cmds["%s_reg_event" % (rsc)]) test.add_cmd(common_cmds["%s_start_line" % (rsc)] + " " + common_cmds["%s_start_event" % (rsc)]) test.add_cmd(common_cmds["%s_monitor_line" % (rsc)] + " " + common_cmds["%s_monitor_event" % (rsc)]) test.add_cmd(common_cmds["%s_monitor_event" % (rsc)]) ### If this fails, that means the monitor may not be getting rescheduled #### test.add_cmd(common_cmds["%s_monitor_event" % (rsc)]) ### If this fails, that means the monitor may not be getting rescheduled #### test.add_cmd(common_cmds["%s_stop_line" % (rsc)] + " " + common_cmds["%s_stop_event" % (rsc)]) test.add_expected_fail_cmd(common_cmds["%s_monitor_event" % (rsc)]) ### If this happens the monitor did not actually cancel correctly. ### test.add_expected_fail_cmd(common_cmds["%s_monitor_event" % (rsc)]) ### If this happens the monitor did not actually cancel correctly. ### test.add_cmd(common_cmds["%s_unreg_line" % (rsc)] + " " + common_cmds["%s_unreg_event" % (rsc)]) ### These are complex tests that involve managing multiple resouces of different types ### def build_multi_rsc_tests(self): common_cmds = self.common_cmds # do not use service and systemd at the same time, it is the same resource. ### register start monitor stop unregister resources of each type at the same time. ### test = self.new_test("multi_rsc_start_stop_all", "Start, monitor, and stop resources of multiple types and classes") for rsc in self.rsc_classes: test.add_cmd(common_cmds["%s_reg_line" % (rsc)] + " " + common_cmds["%s_reg_event" % (rsc)]) for rsc in self.rsc_classes: test.add_cmd(common_cmds["%s_start_line" % (rsc)] + " " + common_cmds["%s_start_event" % (rsc)]) for rsc in self.rsc_classes: test.add_cmd(common_cmds["%s_monitor_line" % (rsc)] + " " + common_cmds["%s_monitor_event" % (rsc)]) for rsc in self.rsc_classes: test.add_cmd(common_cmds["%s_monitor_event" % (rsc)]) ### If this fails, that means the monitor is not being rescheduled #### for rsc in self.rsc_classes: test.add_cmd(common_cmds["%s_cancel_line" % (rsc)] + " " + common_cmds["%s_cancel_event" % (rsc)]) for rsc in self.rsc_classes: test.add_cmd(common_cmds["%s_stop_line" % (rsc)] + " " + common_cmds["%s_stop_event" % (rsc)]) for rsc in self.rsc_classes: test.add_cmd(common_cmds["%s_unreg_line" % (rsc)] + " " + common_cmds["%s_unreg_event" % (rsc)]) ### These are tests related to how the lrmd handles failures. ### def build_negative_tests(self): ### ocf start timeout test ### test = self.new_test("ocf_start_timeout", "Force start timeout to occur, verify start failure.") test.add_cmd("-c register_rsc -r \"test_rsc\" -C \"ocf\" -P \"pacemaker\" -T \"Dummy\" "+self.action_timeout+ "-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\" -k \"op_sleep\" -v \"5\" -t 1000 -w") # -t must be less than self.action_timeout test.add_cmd("-l " "\"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:unknown error op_status:Timed Out\" "+self.action_timeout) test.add_cmd("-c exec -r test_rsc -a stop "+self.action_timeout+ "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:stop rc:ok op_status:complete\" ") test.add_cmd("-c unregister_rsc -r test_rsc "+self.action_timeout+ "-l \"NEW_EVENT event_type:unregister rsc_id:test_rsc action:none rc:ok op_status:complete\" ") ### stonith start timeout test ### test = self.new_test("stonith_start_timeout", "Force start timeout to occur, verify start failure.") test.add_cmd("-c register_rsc -r \"test_rsc\" -C \"stonith\" -P \"pacemaker\" -T \"fence_dummy_sleep\" "+self.action_timeout+ "-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 1000 -w") # -t must be less than self.action_timeout test.add_cmd("-l " "\"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:unknown error op_status:Timed Out\" "+self.action_timeout) test.add_cmd("-c exec -r test_rsc -a stop "+self.action_timeout+ "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:stop rc:ok op_status:complete\" ") test.add_cmd("-c unregister_rsc -r test_rsc "+self.action_timeout+ "-l \"NEW_EVENT event_type:unregister rsc_id:test_rsc action:none rc:ok op_status:complete\" ") ### stonith component fail ### common_cmds = self.common_cmds test = self.new_test("stonith_component_fail", "Kill stonith component after lrmd connects") test.add_cmd(common_cmds["stonith_reg_line"] + " " + common_cmds["stonith_reg_event"]) test.add_cmd(common_cmds["stonith_start_line"] + " " + common_cmds["stonith_start_event"]) test.add_cmd("-c exec -r \"stonith_test_rsc\" -a \"monitor\" -i \"600000\" " "-l \"NEW_EVENT event_type:exec_complete rsc_id:stonith_test_rsc action:monitor rc:ok op_status:complete\" "+self.action_timeout) test.add_cmd_and_kill("killall -9 -q stonithd lt-stonithd" ,"-l \"NEW_EVENT event_type:exec_complete rsc_id:stonith_test_rsc action:monitor rc:unknown error op_status:error\" -t 15000") test.add_cmd(common_cmds["stonith_unreg_line"] + " " + common_cmds["stonith_unreg_event"]) ### monitor fail for ocf resources ### test = self.new_test("monitor_fail_ocf", "Force ocf monitor to fail, verify failure is reported.") test.add_cmd("-c register_rsc -r \"test_rsc\" -C \"ocf\" -P \"pacemaker\" -T \"Dummy\" "+self.action_timeout+ "-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\" "+self.action_timeout+ "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:ok op_status:complete\" ") test.add_cmd("-c exec -r \"test_rsc\" -a \"start\" "+self.action_timeout+ "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:ok op_status:complete\" ") test.add_cmd("-c exec -r \"test_rsc\" -a \"monitor\" -i \"100\" "+self.action_timeout+ "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:ok op_status:complete\" ") test.add_cmd("-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:ok op_status:complete\" "+self.action_timeout) test.add_cmd("-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:ok op_status:complete\" "+self.action_timeout) test.add_cmd_and_kill("rm -f @localstatedir@/run/Dummy-test_rsc.state", "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:not running op_status:complete\" -t 6000") test.add_cmd("-c cancel -r \"test_rsc\" -a \"monitor\" -i \"100\" -t \"3000\" " "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:not running op_status:Cancelled\" ") test.add_expected_fail_cmd("-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:not running op_status:complete\" "+self.action_timeout) test.add_expected_fail_cmd("-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:ok op_status:complete\" "+self.action_timeout) test.add_cmd("-c unregister_rsc -r \"test_rsc\" "+self.action_timeout+ "-l \"NEW_EVENT event_type:unregister rsc_id:test_rsc action:none rc:ok op_status:complete\" ") ### verify notify changes only for monitor operation. ### test = self.new_test("monitor_changes_only", "Verify when flag is set, only monitor changes are notified.") test.add_cmd("-c register_rsc -r \"test_rsc\" -C \"ocf\" -P \"pacemaker\" -T \"Dummy\" "+self.action_timeout+ "-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\" "+self.action_timeout+" -o " "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:ok op_status:complete\" ") test.add_cmd("-c exec -r \"test_rsc\" -a \"monitor\" -i \"100\" "+self.action_timeout+" -o " "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:ok op_status:complete\" ") test.add_expected_fail_cmd("-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:ok op_status:complete\" "+self.action_timeout) test.add_cmd_and_kill("rm -f @localstatedir@/run/Dummy-test_rsc.state", "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:not running op_status:complete\" -t 6000") test.add_cmd("-c cancel -r \"test_rsc\" -a \"monitor\" -i \"100\" -t \"3000\" " "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:not running op_status:Cancelled\" ") test.add_expected_fail_cmd("-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:not running op_status:complete\" "+self.action_timeout) test.add_expected_fail_cmd("-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:ok op_status:complete\" "+self.action_timeout) test.add_cmd("-c unregister_rsc -r \"test_rsc\" "+self.action_timeout+ "-l \"NEW_EVENT event_type:unregister rsc_id:test_rsc action:none rc:ok op_status:complete\" ") ### monitor fail for systemd resource ### if "systemd" in self.rsc_classes: test = self.new_test("monitor_fail_systemd", "Force systemd monitor to fail, verify failure is reported..") test.add_cmd("-c register_rsc -r \"test_rsc\" -C systemd -T lrmd_dummy_daemon "+self.action_timeout+ "-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\" "+self.action_timeout+ "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:ok op_status:complete\" ") test.add_cmd("-c exec -r \"test_rsc\" -a \"start\" "+self.action_timeout+ "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:ok op_status:complete\" ") test.add_cmd("-c exec -r \"test_rsc\" -a \"monitor\" -i \"100\" "+self.action_timeout+ "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:ok op_status:complete\" ") test.add_cmd("-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:ok op_status:complete\" "+self.action_timeout) test.add_cmd("-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:ok op_status:complete\" "+self.action_timeout) test.add_cmd_and_kill("killall -9 -q lrmd_dummy_daemon", "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:not running op_status:complete\" -t 8000") test.add_cmd("-c cancel -r \"test_rsc\" -a \"monitor\" -i \"100\" -t \"3000\" " "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:not running op_status:Cancelled\" ") test.add_expected_fail_cmd("-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:not running op_status:complete\" "+self.action_timeout) test.add_expected_fail_cmd("-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:ok op_status:complete\" "+self.action_timeout) test.add_cmd("-c unregister_rsc -r \"test_rsc\" "+self.action_timeout+ "-l \"NEW_EVENT event_type:unregister rsc_id:test_rsc action:none rc:ok op_status:complete\" ") ### monitor fail for upstart resource ### if "upstart" in self.rsc_classes: test = self.new_test("monitor_fail_upstart", "Force upstart monitor to fail, verify failure is reported..") test.add_cmd("-c register_rsc -r \"test_rsc\" -C upstart -T lrmd_dummy_daemon "+self.action_timeout+ "-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\" "+self.action_timeout+ "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:ok op_status:complete\" ") test.add_cmd("-c exec -r \"test_rsc\" -a \"start\" "+self.action_timeout+ "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:ok op_status:complete\" ") test.add_cmd("-c exec -r \"test_rsc\" -a \"monitor\" -i \"100\" "+self.action_timeout+ "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:ok op_status:complete\" ") test.add_cmd("-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:ok op_status:complete\" "+self.action_timeout) test.add_cmd("-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:ok op_status:complete\" "+self.action_timeout) test.add_cmd_and_kill("killall -9 -q dd", "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:not running op_status:complete\" -t 8000") test.add_cmd("-c cancel -r \"test_rsc\" -a \"monitor\" -i \"100\" -t \"3000\" " "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:not running op_status:Cancelled\" ") test.add_expected_fail_cmd("-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:not running op_status:complete\" "+self.action_timeout) test.add_expected_fail_cmd("-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:ok op_status:complete\" "+self.action_timeout) test.add_cmd("-c unregister_rsc -r \"test_rsc\" "+self.action_timeout+ "-l \"NEW_EVENT event_type:unregister rsc_id:test_rsc action:none rc:ok op_status:complete\" ") ### Cancel non-existent operation on a resource ### test = self.new_test("cancel_non_existent_op", "Attempt to cancel the wrong monitor operation, verify expected failure") test.add_cmd("-c register_rsc -r \"test_rsc\" -C \"ocf\" -P \"pacemaker\" -T \"Dummy\" "+self.action_timeout+ "-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\" "+self.action_timeout+ "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:ok op_status:complete\" ") test.add_cmd("-c exec -r \"test_rsc\" -a \"start\" "+self.action_timeout+ "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:ok op_status:complete\" ") test.add_cmd("-c exec -r \"test_rsc\" -a \"monitor\" -i \"100\" "+self.action_timeout+ "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:ok op_status:complete\" ") test.add_cmd("-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:ok op_status:complete\" "+self.action_timeout) test.add_expected_fail_cmd("-c cancel -r test_rsc -a \"monitor\" -i 1234 -t \"3000\" " ### interval is wrong, should fail "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:not running op_status:Cancelled\" ") test.add_expected_fail_cmd("-c cancel -r test_rsc -a stop -i 100 -t \"3000\" " ### action name is wrong, should fail "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:not running op_status:Cancelled\" ") test.add_cmd("-c unregister_rsc -r \"test_rsc\" "+self.action_timeout+ "-l \"NEW_EVENT event_type:unregister rsc_id:test_rsc action:none rc:ok op_status:complete\" ") ### Attempt to invoke non-existent rsc id ### test = self.new_test("invoke_non_existent_rsc", "Attempt to perform operations on a non-existent rsc id.") test.add_expected_fail_cmd("-c exec -r \"test_rsc\" -a \"start\" "+self.action_timeout+ "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:unknown error op_status:complete\" ") test.add_expected_fail_cmd("-c exec -r test_rsc -a stop "+self.action_timeout+ "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:stop rc:ok op_status:complete\" ") test.add_expected_fail_cmd("-c exec -r test_rsc -a monitor -i 3000 "+self.action_timeout+ "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:ok op_status:complete\" ") test.add_expected_fail_cmd("-c cancel -r test_rsc -a start "+self.action_timeout+ "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:ok op_status:Cancelled\" ") test.add_cmd("-c unregister_rsc -r \"test_rsc\" "+self.action_timeout+ "-l \"NEW_EVENT event_type:unregister rsc_id:test_rsc action:none rc:ok op_status:complete\" ") ### Register and start a resource that doesn't exist, systemd ### if "systemd" in self.rsc_classes: test = self.new_test("start_uninstalled_systemd", "Register uninstalled systemd agent, try to start, verify expected failure") test.add_cmd("-c register_rsc -r \"test_rsc\" -C systemd -T this_is_fake1234 "+self.action_timeout+ "-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\" "+self.action_timeout+ "-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\" "+self.action_timeout+ "-l \"NEW_EVENT event_type:unregister rsc_id:test_rsc action:none rc:ok op_status:complete\" ") if "upstart" in self.rsc_classes: test = self.new_test("start_uninstalled_upstart", "Register uninstalled upstart agent, try to start, verify expected failure") test.add_cmd("-c register_rsc -r \"test_rsc\" -C upstart -T this_is_fake1234 "+self.action_timeout+ "-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\" "+self.action_timeout+ "-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\" "+self.action_timeout+ "-l \"NEW_EVENT event_type:unregister rsc_id:test_rsc action:none rc:ok op_status:complete\" ") ### Register and start a resource that doesn't exist, ocf ### test = self.new_test("start_uninstalled_ocf", "Register uninstalled ocf agent, try to start, verify expected failure.") test.add_cmd("-c register_rsc -r \"test_rsc\" -C ocf -P pacemaker -T this_is_fake1234 "+self.action_timeout+ "-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\" "+self.action_timeout+ "-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\" "+self.action_timeout+ "-l \"NEW_EVENT event_type:unregister rsc_id:test_rsc action:none rc:ok op_status:complete\" ") ### Register ocf with non-existent provider ### test = self.new_test("start_ocf_bad_provider", "Register ocf agent with a non-existent provider, verify expected failure.") test.add_cmd("-c register_rsc -r \"test_rsc\" -C ocf -P pancakes -T Dummy "+self.action_timeout+ "-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\" "+self.action_timeout+ "-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\" "+self.action_timeout+ "-l \"NEW_EVENT event_type:unregister rsc_id:test_rsc action:none rc:ok op_status:complete\" ") ### Register ocf with empty provider field ### test = self.new_test("start_ocf_no_provider", "Register ocf agent with a no provider, verify expected failure.") test.add_expected_fail_cmd("-c register_rsc -r \"test_rsc\" -C ocf -T Dummy "+self.action_timeout+ "-l \"NEW_EVENT event_type:register rsc_id:test_rsc action:none rc:ok op_status:complete\" ") test.add_expected_fail_cmd("-c exec -r \"test_rsc\" -a \"start\" "+self.action_timeout+ "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:ok op_status:Error\" ") test.add_cmd("-c unregister_rsc -r \"test_rsc\" "+self.action_timeout+ "-l \"NEW_EVENT event_type:unregister rsc_id:test_rsc action:none rc:ok op_status:complete\" ") ### stress tests ### def build_stress_tests(self): timeout = "-t 20000" iterations = 25 test = self.new_test("ocf_stress", "Verify systemd dbus connection works under load") for i in range(iterations): test.add_cmd("-c register_rsc -r rsc_%s %s -C ocf -P heartbeat -T Dummy -l \"NEW_EVENT event_type:register rsc_id:rsc_%s action:none rc:ok op_status:complete\"" % (i, timeout, i)) test.add_cmd("-c exec -r rsc_%s -a start %s -l \"NEW_EVENT event_type:exec_complete rsc_id:rsc_%s action:start rc:ok op_status:complete\"" % (i, timeout, i)) test.add_cmd("-c exec -r rsc_%s -a monitor %s -i 1000 -l \"NEW_EVENT event_type:exec_complete rsc_id:rsc_%s action:monitor rc:ok op_status:complete\"" % (i, timeout, i)) for i in range(iterations): test.add_cmd("-c exec -r rsc_%s -a stop %s -l \"NEW_EVENT event_type:exec_complete rsc_id:rsc_%s action:stop rc:ok op_status:complete\"" % (i, timeout, i)) test.add_cmd("-c unregister_rsc -r rsc_%s %s -l \"NEW_EVENT event_type:unregister rsc_id:rsc_%s action:none rc:ok op_status:complete\"" % (i, timeout, i)) if "systemd" in self.rsc_classes: test = self.new_test("systemd_stress", "Verify systemd dbus connection works under load") for i in range(iterations): test.add_cmd("-c register_rsc -r rsc_%s %s -C systemd -T lrmd_dummy_daemon -l \"NEW_EVENT event_type:register rsc_id:rsc_%s action:none rc:ok op_status:complete\"" % (i, timeout, i)) test.add_cmd("-c exec -r rsc_%s -a start %s -l \"NEW_EVENT event_type:exec_complete rsc_id:rsc_%s action:start rc:ok op_status:complete\"" % (i, timeout, i)) test.add_cmd("-c exec -r rsc_%s -a monitor %s -i 1000 -l \"NEW_EVENT event_type:exec_complete rsc_id:rsc_%s action:monitor rc:ok op_status:complete\"" % (i, timeout, i)) for i in range(iterations): test.add_cmd("-c exec -r rsc_%s -a stop %s -l \"NEW_EVENT event_type:exec_complete rsc_id:rsc_%s action:stop rc:ok op_status:complete\"" % (i, timeout, i)) test.add_cmd("-c unregister_rsc -r rsc_%s %s -l \"NEW_EVENT event_type:unregister rsc_id:rsc_%s action:none rc:ok op_status:complete\"" % (i, timeout, i)) ### These are tests that target specific cases ### def build_custom_tests(self): ### verify resource temporary folder is created and used by heartbeat agents. ### test = self.new_test("rsc_tmp_dir", "Verify creation and use of rsc temporary state directory") test.add_sys_cmd("ls", "-al @CRM_RSCTMP_DIR@") test.add_cmd("-c register_rsc -r test_rsc -P heartbeat -C ocf -T Dummy " "-l \"NEW_EVENT event_type:register rsc_id:test_rsc action:none rc:ok op_status:complete\" "+self.action_timeout) test.add_cmd("-c exec -r test_rsc -a start -t 4000") test.add_sys_cmd("ls", "-al @CRM_RSCTMP_DIR@") test.add_sys_cmd("ls", "@CRM_RSCTMP_DIR@/Dummy-test_rsc.state") test.add_cmd("-c exec -r test_rsc -a stop -t 4000") test.add_cmd("-c unregister_rsc -r test_rsc "+self.action_timeout+ "-l \"NEW_EVENT event_type:unregister rsc_id:test_rsc action:none rc:ok op_status:complete\" ") ### start delay then stop test ### test = self.new_test("start_delay", "Verify start delay works as expected.") test.add_cmd("-c register_rsc -r test_rsc -P pacemaker -C ocf -T Dummy " "-l \"NEW_EVENT event_type:register rsc_id:test_rsc action:none rc:ok op_status:complete\" "+self.action_timeout) test.add_cmd("-c exec -r test_rsc -s 6000 -a start -w -t 6000") test.add_expected_fail_cmd("-l " "\"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:ok op_status:complete\" -t 2000") test.add_cmd("-l " "\"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:ok op_status:complete\" -t 6000") test.add_cmd("-c exec -r test_rsc -a stop "+self.action_timeout+ "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:stop rc:ok op_status:complete\" ") test.add_cmd("-c unregister_rsc -r test_rsc "+self.action_timeout+ "-l \"NEW_EVENT event_type:unregister rsc_id:test_rsc action:none rc:ok op_status:complete\" ") ### start delay, but cancel before it gets a chance to start. ### test = self.new_test("start_delay_cancel", "Using start_delay, start a rsc, but cancel the start op before execution.") test.add_cmd("-c register_rsc -r test_rsc -P pacemaker -C ocf -T Dummy " "-l \"NEW_EVENT event_type:register rsc_id:test_rsc action:none rc:ok op_status:complete\" "+self.action_timeout) test.add_cmd("-c exec -r test_rsc -s 5000 -a start -w -t 4000") test.add_cmd("-c cancel -r test_rsc -a start "+self.action_timeout+ "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:ok op_status:Cancelled\" ") test.add_expected_fail_cmd("-l " "\"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:ok op_status:complete\" -t 5000") test.add_cmd("-c unregister_rsc -r test_rsc "+self.action_timeout+ "-l \"NEW_EVENT event_type:unregister rsc_id:test_rsc action:none rc:ok op_status:complete\" ") ### Register a bunch of resources, verify we can get info on them ### test = self.new_test("verify_get_rsc_info", "Register multiple resources, verify retrieval of rsc info.") if "systemd" in self.rsc_classes: test.add_cmd("-c register_rsc -r rsc1 -C systemd -T lrmd_dummy_daemon "+self.action_timeout) test.add_cmd("-c get_rsc_info -r rsc1 ") test.add_cmd("-c unregister_rsc -r rsc1 "+self.action_timeout) test.add_expected_fail_cmd("-c get_rsc_info -r rsc1 ") if "upstart" in self.rsc_classes: test.add_cmd("-c register_rsc -r rsc1 -C upstart -T lrmd_dummy_daemon "+self.action_timeout) test.add_cmd("-c get_rsc_info -r rsc1 ") test.add_cmd("-c unregister_rsc -r rsc1 "+self.action_timeout) test.add_expected_fail_cmd("-c get_rsc_info -r rsc1 ") test.add_cmd("-c register_rsc -r rsc2 -C ocf -T Dummy -P pacemaker "+self.action_timeout) test.add_cmd("-c get_rsc_info -r rsc2 ") test.add_cmd("-c unregister_rsc -r rsc2 "+self.action_timeout) test.add_expected_fail_cmd("-c get_rsc_info -r rsc2 ") ### Register duplicate, verify only one entry exists and can still be removed. test = self.new_test("duplicate_registration", "Register resource multiple times, verify only one entry exists and can be removed.") test.add_cmd("-c register_rsc -r rsc2 -C ocf -T Dummy -P pacemaker "+self.action_timeout) test.add_cmd_check_stdout("-c get_rsc_info -r rsc2 ", "id:rsc2 class:ocf provider:pacemaker type:Dummy") test.add_cmd("-c register_rsc -r rsc2 -C ocf -T Dummy -P pacemaker "+self.action_timeout) test.add_cmd_check_stdout("-c get_rsc_info -r rsc2 ", "id:rsc2 class:ocf provider:pacemaker type:Dummy") test.add_cmd("-c register_rsc -r rsc2 -C ocf -T Stateful -P pacemaker "+self.action_timeout) test.add_cmd_check_stdout("-c get_rsc_info -r rsc2 ", "id:rsc2 class:ocf provider:pacemaker type:Stateful") test.add_cmd("-c unregister_rsc -r rsc2 "+self.action_timeout) test.add_expected_fail_cmd("-c get_rsc_info -r rsc2 ") ### verify the option to only send notification to the original client. ### test = self.new_test("notify_orig_client_only", "Verify option to only send notifications to the client originating the action.") test.add_cmd("-c register_rsc -r \"test_rsc\" -C \"ocf\" -P \"pacemaker\" -T \"Dummy\" "+self.action_timeout+ "-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\" "+self.action_timeout+ "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:ok op_status:complete\" ") test.add_cmd("-c exec -r \"test_rsc\" -a \"monitor\" -i \"100\" "+self.action_timeout+" -n " "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:ok op_status:complete\" ") # this will fail because the monitor notifications should only go to the original caller, which no longer exists. test.add_expected_fail_cmd("-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:ok op_status:complete\" "+self.action_timeout) test.add_cmd("-c cancel -r \"test_rsc\" -a \"monitor\" -i \"100\" -t \"3000\" ") test.add_cmd("-c unregister_rsc -r \"test_rsc\" "+self.action_timeout+ "-l \"NEW_EVENT event_type:unregister rsc_id:test_rsc action:none rc:ok op_status:complete\" ") ### get metadata ### test = self.new_test("get_ocf_metadata", "Retrieve metadata for a resource") test.add_cmd_check_stdout("-c metadata -C \"ocf\" -P \"pacemaker\" -T \"Dummy\"" ,"resource-agent name=\"Dummy\"") test.add_cmd("-c metadata -C \"ocf\" -P \"pacemaker\" -T \"Stateful\"") test.add_expected_fail_cmd("-c metadata -P \"pacemaker\" -T \"Stateful\"") test.add_expected_fail_cmd("-c metadata -C \"ocf\" -P \"pacemaker\" -T \"fake_agent\"") ### get metadata ### test = self.new_test("get_lsb_metadata", "Retrieve metadata for a resource") test.add_cmd_check_stdout("-c metadata -C \"lsb\" -T \"LSBDummy\"" ,"resource-agent name='LSBDummy'") ### get stonith metadata ### test = self.new_test("get_stonith_metadata", "Retrieve stonith metadata for a resource") test.add_cmd_check_stdout("-c metadata -C \"stonith\" -P \"pacemaker\" -T \"fence_dummy_monitor\"", "resource-agent name=\"fence_dummy_monitor\"") ### get metadata ### if "systemd" in self.rsc_classes: test = self.new_test("get_systemd_metadata", "Retrieve metadata for a resource") test.add_cmd_check_stdout("-c metadata -C \"systemd\" -T \"lrmd_dummy_daemon\"" ,"resource-agent name=\"lrmd_dummy_daemon\"") ### get metadata ### if "upstart" in self.rsc_classes: test = self.new_test("get_upstart_metadata", "Retrieve metadata for a resource") test.add_cmd_check_stdout("-c metadata -C \"upstart\" -T \"lrmd_dummy_daemon\"" ,"resource-agent name=\"lrmd_dummy_daemon\"") + if "heartbeat" in self.rsc_classes: + test = self.new_test("get_heartbeat_metadata", "Retrieve metadata for a resource") + test.add_cmd_check_stdout("-c metadata -C \"heartbeat\" -T \"HBDummy\"" + ,"resource-agent name='HBDummy'") + ### get ocf providers ### test = self.new_test("list_ocf_providers", "Retrieve list of available resource providers, verifies pacemaker is a provider.") test.add_cmd_check_stdout("-c list_ocf_providers ", "pacemaker") test.add_cmd_check_stdout("-c list_ocf_providers -T ping", "pacemaker") ### Verify agents only exist in their lists ### test = self.new_test("verify_agent_lists", "Verify the agent lists contain the right data.") test.add_cmd_check_stdout("-c list_agents ", "Stateful") ### ocf ### test.add_cmd_check_stdout("-c list_agents -C ocf", "Stateful") test.add_cmd_check_stdout("-c list_agents -C lsb", "", "Stateful") ### should not exist test.add_cmd_check_stdout("-c list_agents -C service", "", "Stateful") ### should not exist test.add_cmd_check_stdout("-c list_agents ", "LSBDummy") ### init.d ### test.add_cmd_check_stdout("-c list_agents -C lsb", "LSBDummy") test.add_cmd_check_stdout("-c list_agents -C service", "LSBDummy") test.add_cmd_check_stdout("-c list_agents -C ocf", "", "lrmd_dummy_daemon") ### should not exist test.add_cmd_check_stdout("-c list_agents -C ocf", "", "lrmd_dummy_daemon") ### should not exist test.add_cmd_check_stdout("-c list_agents -C lsb", "", "fence_dummy_monitor") ### should not exist test.add_cmd_check_stdout("-c list_agents -C service", "", "fence_dummy_monitor") ### should not exist test.add_cmd_check_stdout("-c list_agents -C ocf", "", "fence_dummy_monitor") ### should not exist if "systemd" in self.rsc_classes: test.add_cmd_check_stdout("-c list_agents ", "lrmd_dummy_daemon") ### systemd ### test.add_cmd_check_stdout("-c list_agents -C service", "LSBDummy") test.add_cmd_check_stdout("-c list_agents -C systemd", "", "Stateful") ### should not exist test.add_cmd_check_stdout("-c list_agents -C systemd", "lrmd_dummy_daemon") test.add_cmd_check_stdout("-c list_agents -C systemd", "", "fence_dummy_monitor") ### should not exist if "upstart" in self.rsc_classes: test.add_cmd_check_stdout("-c list_agents ", "lrmd_dummy_daemon") ### upstart ### test.add_cmd_check_stdout("-c list_agents -C service", "LSBDummy") test.add_cmd_check_stdout("-c list_agents -C upstart", "", "Stateful") ### should not exist test.add_cmd_check_stdout("-c list_agents -C upstart", "lrmd_dummy_daemon") test.add_cmd_check_stdout("-c list_agents -C upstart", "", "fence_dummy_monitor") ### should not exist if "stonith" in self.rsc_classes: test.add_cmd_check_stdout("-c list_agents -C stonith", "fence_dummy_monitor") ### stonith ### test.add_cmd_check_stdout("-c list_agents -C stonith", "", "lrmd_dummy_daemon") ### should not exist test.add_cmd_check_stdout("-c list_agents -C stonith", "", "Stateful") ### should not exist test.add_cmd_check_stdout("-c list_agents ", "fence_dummy_monitor") + if "heartbeat" in self.rsc_classes: + test.add_cmd_check_stdout("-c list_agents -C heartbeat", "HBDummy") + test.add_cmd_check_stdout("-c list_agents -C heartbeat", "", "LSBDummy") ### should not exist + test.add_cmd_check_stdout("-c list_agents -C service", "", "HBDummy") ### should not exist + def print_list(self): print "\n==== %d TESTS FOUND ====" % (len(self.tests)) print "%35s - %s" % ("TEST NAME", "TEST DESCRIPTION") print "%35s - %s" % ("--------------------", "--------------------") for test in self.tests: print "%35s - %s" % (test.name, test.description) print "==== END OF LIST ====\n" def run_single(self, name): for test in self.tests: if test.name == name: test.run() break; def run_tests_matching(self, pattern): for test in self.tests: if test.name.count(pattern) != 0: test.run() def run_tests(self): for test in self.tests: test.run() def exit(self): for test in self.tests: if test.executed == 0: continue if test.get_exitcode() != 0: sys.exit(-1) sys.exit(0); def print_results(self): failures = 0; success = 0; print "\n\n======= FINAL RESULTS ==========" print "\n--- FAILURE RESULTS:" for test in self.tests: if test.executed == 0: continue if test.get_exitcode() != 0: failures = failures + 1 test.print_result(" ") else: success = success + 1 if failures == 0: print " None" print "\n--- TOTALS\n Pass:%d\n Fail:%d\n" % (success, failures) class TestOptions: def __init__(self): self.options = {} self.options['list-tests'] = 0 self.options['run-all'] = 1 self.options['run-only'] = "" self.options['run-only-pattern'] = "" self.options['verbose'] = 0 self.options['invalid-arg'] = "" self.options['show-usage'] = 0 self.options['pacemaker-remote'] = 0 def build_options(self, argv): args = argv[1:] skip = 0 for i in range(0, len(args)): if skip: skip = 0 continue elif args[i] == "-h" or args[i] == "--help": self.options['show-usage'] = 1 elif args[i] == "-l" or args[i] == "--list-tests": self.options['list-tests'] = 1 elif args[i] == "-V" or args[i] == "--verbose": self.options['verbose'] = 1 elif args[i] == "-R" or args[i] == "--pacemaker-remote": self.options['pacemaker-remote'] = 1 elif args[i] == "-r" or args[i] == "--run-only": self.options['run-only'] = args[i+1] skip = 1 elif args[i] == "-p" or args[i] == "--run-only-pattern": self.options['run-only-pattern'] = args[i+1] skip = 1 def show_usage(self): print "usage: " + sys.argv[0] + " [options]" print "If no options are provided, all tests will run" print "Options:" print "\t [--help | -h] Show usage" print "\t [--list-tests | -l] Print out all registered tests." print "\t [--run-only | -r 'testname'] Run a specific test" print "\t [--verbose | -V] Verbose output" print "\t [--pacemaker-remote | -R Test pacemaker-remote binary instead of lrmd." print "\t [--run-only-pattern | -p 'string'] Run only tests containing the string value" print "\n\tExample: Run only the test 'start_top'" print "\t\t python ./regression.py --run-only start_stop" print "\n\tExample: Run only the tests with the string 'systemd' present in them" print "\t\t python ./regression.py --run-only-pattern systemd" def main(argv): o = TestOptions() o.build_options(argv) tests = Tests(o.options['verbose'], o.options['pacemaker-remote']) tests.build_generic_tests() tests.build_multi_rsc_tests() tests.build_negative_tests() tests.build_custom_tests() tests.build_stress_tests() tests.setup_test_environment() print "Starting ..." if o.options['list-tests']: tests.print_list() elif o.options['show-usage']: o.show_usage() elif o.options['run-only-pattern'] != "": tests.run_tests_matching(o.options['run-only-pattern']) tests.print_results() elif o.options['run-only'] != "": tests.run_single(o.options['run-only']) tests.print_results() else: tests.run_tests() tests.print_results() tests.cleanup_test_environment() tests.exit() if __name__=="__main__": main(sys.argv) diff --git a/pengine/test10/8-am-then-bm-a-migrating-b-stopping.summary b/pengine/test10/8-am-then-bm-a-migrating-b-stopping.summary index 2535d01245..8f4628c6f2 100644 --- a/pengine/test10/8-am-then-bm-a-migrating-b-stopping.summary +++ b/pengine/test10/8-am-then-bm-a-migrating-b-stopping.summary @@ -1,26 +1,26 @@ Current cluster status: Online: [ 18node1 18node2 18node3 ] A (ocf::heartbeat:Dummy): Started 18node1 - B (ocf::heartbeat:Dummy): Started 18node2 + B (ocf::heartbeat:Dummy): (target-role:Stopped) Started 18node2 Transition Summary: * Migrate A (Started 18node1 -> 18node2) * Stop B (18node2) Executing cluster transition: * Resource action: B stop on 18node2 * Resource action: A migrate_to on 18node1 * Resource action: A migrate_from on 18node2 * Resource action: A stop on 18node1 * Pseudo action: all_stopped * Pseudo action: A_start_0 * Resource action: A monitor=60000 on 18node2 Revised cluster status: Online: [ 18node1 18node2 18node3 ] A (ocf::heartbeat:Dummy): Started 18node2 - B (ocf::heartbeat:Dummy): Stopped + B (ocf::heartbeat:Dummy): (target-role:Stopped) Stopped diff --git a/pengine/test10/9-am-then-bm-b-migrating-a-stopping.summary b/pengine/test10/9-am-then-bm-b-migrating-a-stopping.summary index da9908e21e..0dfcc26363 100644 --- a/pengine/test10/9-am-then-bm-b-migrating-a-stopping.summary +++ b/pengine/test10/9-am-then-bm-b-migrating-a-stopping.summary @@ -1,22 +1,22 @@ Current cluster status: Online: [ 18node1 18node2 18node3 ] - A (ocf::heartbeat:Dummy): Started 18node1 + A (ocf::heartbeat:Dummy): (target-role:Stopped) Started 18node1 B (ocf::heartbeat:Dummy): Started 18node2 Transition Summary: * Stop A (18node1) * Stop B (Started 18node2) Executing cluster transition: * Resource action: B stop on 18node2 * Resource action: A stop on 18node1 * Pseudo action: all_stopped Revised cluster status: Online: [ 18node1 18node2 18node3 ] - A (ocf::heartbeat:Dummy): Stopped + A (ocf::heartbeat:Dummy): (target-role:Stopped) Stopped B (ocf::heartbeat:Dummy): Stopped diff --git a/pengine/test10/bug-1718.summary b/pengine/test10/bug-1718.summary index d9a0cccc70..e24d303b1d 100644 --- a/pengine/test10/bug-1718.summary +++ b/pengine/test10/bug-1718.summary @@ -1,41 +1,41 @@ Current cluster status: Online: [ biggame.ds9 heartbeat.ds9 ops.ds9 ] OFFLINE: [ defiant.ds9 warbird.ds9 ] Resource Group: Web_Group Apache_IP (ocf::heartbeat:IPaddr): Started heartbeat.ds9 - resource_IP2 (ocf::heartbeat:IPaddr): Stopped + resource_IP2 (ocf::heartbeat:IPaddr): (target-role:stopped) Stopped resource_dummyweb (ocf::heartbeat:Dummy): Stopped Resource Group: group_fUN resource_IP3 (ocf::heartbeat:IPaddr): Started ops.ds9 resource_dummy (ocf::heartbeat:Dummy): Started ops.ds9 Transition Summary: * Stop resource_IP3 (Started ops.ds9) * Stop resource_dummy (Started ops.ds9) Executing cluster transition: * Pseudo action: group_fUN_stop_0 * Resource action: resource_dummy stop on ops.ds9 * Resource action: OpenVPN_IP delete on ops.ds9 * Resource action: OpenVPN_IP delete on heartbeat.ds9 * Resource action: Apache delete on biggame.ds9 * Resource action: Apache delete on ops.ds9 * Resource action: Apache delete on heartbeat.ds9 * Resource action: resource_IP3 stop on ops.ds9 * Pseudo action: all_stopped * Pseudo action: group_fUN_stopped_0 Revised cluster status: Online: [ biggame.ds9 heartbeat.ds9 ops.ds9 ] OFFLINE: [ defiant.ds9 warbird.ds9 ] Resource Group: Web_Group Apache_IP (ocf::heartbeat:IPaddr): Started heartbeat.ds9 - resource_IP2 (ocf::heartbeat:IPaddr): Stopped + resource_IP2 (ocf::heartbeat:IPaddr): (target-role:stopped) Stopped resource_dummyweb (ocf::heartbeat:Dummy): Stopped Resource Group: group_fUN resource_IP3 (ocf::heartbeat:IPaddr): Stopped resource_dummy (ocf::heartbeat:Dummy): Stopped diff --git a/pengine/test10/bug-5014-A-stop-B-started.summary b/pengine/test10/bug-5014-A-stop-B-started.summary index dcb7646f0b..b2e51721a9 100644 --- a/pengine/test10/bug-5014-A-stop-B-started.summary +++ b/pengine/test10/bug-5014-A-stop-B-started.summary @@ -1,20 +1,20 @@ Current cluster status: Online: [ fc16-builder ] - ClusterIP (ocf::heartbeat:IPaddr2): Started fc16-builder + ClusterIP (ocf::heartbeat:IPaddr2): (target-role:Stopped) Started fc16-builder ClusterIP2 (ocf::heartbeat:IPaddr2): Started fc16-builder Transition Summary: * Stop ClusterIP (fc16-builder) Executing cluster transition: * Resource action: ClusterIP stop on fc16-builder * Pseudo action: all_stopped Revised cluster status: Online: [ fc16-builder ] - ClusterIP (ocf::heartbeat:IPaddr2): Stopped + ClusterIP (ocf::heartbeat:IPaddr2): (target-role:Stopped) Stopped ClusterIP2 (ocf::heartbeat:IPaddr2): Started fc16-builder diff --git a/pengine/test10/bug-5014-A-stopped-B-stopped.summary b/pengine/test10/bug-5014-A-stopped-B-stopped.summary index 49345643ef..ea6a4e7b83 100644 --- a/pengine/test10/bug-5014-A-stopped-B-stopped.summary +++ b/pengine/test10/bug-5014-A-stopped-B-stopped.summary @@ -1,21 +1,21 @@ Current cluster status: Online: [ fc16-builder ] - ClusterIP (ocf::heartbeat:IPaddr2): Stopped + ClusterIP (ocf::heartbeat:IPaddr2): (target-role:Stopped) Stopped ClusterIP2 (ocf::heartbeat:IPaddr2): Stopped Transition Summary: * Start ClusterIP2 (fc16-builder - blocked) Executing cluster transition: * Resource action: ClusterIP monitor on fc16-builder * Resource action: ClusterIP2 monitor on fc16-builder * Pseudo action: probe_complete Revised cluster status: Online: [ fc16-builder ] - ClusterIP (ocf::heartbeat:IPaddr2): Stopped + ClusterIP (ocf::heartbeat:IPaddr2): (target-role:Stopped) Stopped ClusterIP2 (ocf::heartbeat:IPaddr2): Stopped diff --git a/pengine/test10/bug-5014-CthenAthenB-C-stopped.summary b/pengine/test10/bug-5014-CthenAthenB-C-stopped.summary index 75a1a32b94..8d1a1fdd00 100644 --- a/pengine/test10/bug-5014-CthenAthenB-C-stopped.summary +++ b/pengine/test10/bug-5014-CthenAthenB-C-stopped.summary @@ -1,25 +1,25 @@ Current cluster status: Online: [ fc16-builder ] ClusterIP (ocf::heartbeat:IPaddr2): Stopped ClusterIP2 (ocf::heartbeat:IPaddr2): Stopped - ClusterIP3 (ocf::heartbeat:IPaddr2): Stopped + ClusterIP3 (ocf::heartbeat:IPaddr2): (target-role:Stopped) Stopped Transition Summary: * Start ClusterIP (fc16-builder - blocked) * Start ClusterIP2 (fc16-builder - blocked) Executing cluster transition: * Resource action: ClusterIP monitor on fc16-builder * Resource action: ClusterIP2 monitor on fc16-builder * Resource action: ClusterIP3 monitor on fc16-builder * Pseudo action: probe_complete Revised cluster status: Online: [ fc16-builder ] ClusterIP (ocf::heartbeat:IPaddr2): Stopped ClusterIP2 (ocf::heartbeat:IPaddr2): Stopped - ClusterIP3 (ocf::heartbeat:IPaddr2): Stopped + ClusterIP3 (ocf::heartbeat:IPaddr2): (target-role:Stopped) Stopped diff --git a/pengine/test10/bug-5014-GROUP-A-stopped-B-started.summary b/pengine/test10/bug-5014-GROUP-A-stopped-B-started.summary index d4b00b8f88..5571ab81e5 100644 --- a/pengine/test10/bug-5014-GROUP-A-stopped-B-started.summary +++ b/pengine/test10/bug-5014-GROUP-A-stopped-B-started.summary @@ -1,26 +1,26 @@ Current cluster status: Online: [ fc16-builder ] Resource Group: group1 - ClusterIP (ocf::heartbeat:IPaddr2): Started fc16-builder + ClusterIP (ocf::heartbeat:IPaddr2): (target-role:Stopped) Started fc16-builder Resource Group: group2 ClusterIP2 (ocf::heartbeat:IPaddr2): Started fc16-builder Transition Summary: * Stop ClusterIP (fc16-builder) Executing cluster transition: * Pseudo action: group1_stop_0 * Resource action: ClusterIP stop on fc16-builder * Pseudo action: all_stopped * Pseudo action: group1_stopped_0 Revised cluster status: Online: [ fc16-builder ] Resource Group: group1 - ClusterIP (ocf::heartbeat:IPaddr2): Stopped + ClusterIP (ocf::heartbeat:IPaddr2): (target-role:Stopped) Stopped Resource Group: group2 ClusterIP2 (ocf::heartbeat:IPaddr2): Started fc16-builder diff --git a/pengine/test10/bug-5014-GROUP-A-stopped-B-stopped.summary b/pengine/test10/bug-5014-GROUP-A-stopped-B-stopped.summary index a36f7c6f3b..425169a876 100644 --- a/pengine/test10/bug-5014-GROUP-A-stopped-B-stopped.summary +++ b/pengine/test10/bug-5014-GROUP-A-stopped-B-stopped.summary @@ -1,22 +1,22 @@ Current cluster status: Online: [ fc16-builder ] Resource Group: group1 - ClusterIP (ocf::heartbeat:IPaddr2): Stopped + ClusterIP (ocf::heartbeat:IPaddr2): (target-role:Stopped) Stopped Resource Group: group2 ClusterIP2 (ocf::heartbeat:IPaddr2): Stopped Transition Summary: * Start ClusterIP2 (fc16-builder - blocked) Executing cluster transition: Revised cluster status: Online: [ fc16-builder ] Resource Group: group1 - ClusterIP (ocf::heartbeat:IPaddr2): Stopped + ClusterIP (ocf::heartbeat:IPaddr2): (target-role:Stopped) Stopped Resource Group: group2 ClusterIP2 (ocf::heartbeat:IPaddr2): Stopped diff --git a/pengine/test10/bug-5014-ordered-set-symmetrical-false.summary b/pengine/test10/bug-5014-ordered-set-symmetrical-false.summary index 92c68cd1c3..b980cc1f88 100644 --- a/pengine/test10/bug-5014-ordered-set-symmetrical-false.summary +++ b/pengine/test10/bug-5014-ordered-set-symmetrical-false.summary @@ -1,24 +1,24 @@ Current cluster status: Online: [ fc16-builder ] OFFLINE: [ fc16-builder2 ] A (ocf::pacemaker:Dummy): Started fc16-builder B (ocf::pacemaker:Dummy): Started fc16-builder - C (ocf::pacemaker:Dummy): Started fc16-builder + C (ocf::pacemaker:Dummy): (target-role:Stopped) Started fc16-builder Transition Summary: * Stop C (fc16-builder) Executing cluster transition: * Resource action: C stop on fc16-builder * Pseudo action: all_stopped Revised cluster status: Online: [ fc16-builder ] OFFLINE: [ fc16-builder2 ] A (ocf::pacemaker:Dummy): Started fc16-builder B (ocf::pacemaker:Dummy): Started fc16-builder - C (ocf::pacemaker:Dummy): Stopped + C (ocf::pacemaker:Dummy): (target-role:Stopped) Stopped diff --git a/pengine/test10/bug-5014-ordered-set-symmetrical-true.summary b/pengine/test10/bug-5014-ordered-set-symmetrical-true.summary index 4b41b76147..9691ba6895 100644 --- a/pengine/test10/bug-5014-ordered-set-symmetrical-true.summary +++ b/pengine/test10/bug-5014-ordered-set-symmetrical-true.summary @@ -1,26 +1,26 @@ Current cluster status: Online: [ fc16-builder ] OFFLINE: [ fc16-builder2 ] A (ocf::pacemaker:Dummy): Started fc16-builder B (ocf::pacemaker:Dummy): Started fc16-builder - C (ocf::pacemaker:Dummy): Started fc16-builder + C (ocf::pacemaker:Dummy): (target-role:Stopped) Started fc16-builder Transition Summary: * Stop A (Started fc16-builder) * Stop C (fc16-builder) Executing cluster transition: * Resource action: A stop on fc16-builder * Resource action: C stop on fc16-builder * Pseudo action: all_stopped Revised cluster status: Online: [ fc16-builder ] OFFLINE: [ fc16-builder2 ] A (ocf::pacemaker:Dummy): Stopped B (ocf::pacemaker:Dummy): Started fc16-builder - C (ocf::pacemaker:Dummy): Stopped + C (ocf::pacemaker:Dummy): (target-role:Stopped) Stopped diff --git a/pengine/test10/bug-5143-ms-shuffle.summary b/pengine/test10/bug-5143-ms-shuffle.summary index 305695276a..75b65cfbf0 100644 --- a/pengine/test10/bug-5143-ms-shuffle.summary +++ b/pengine/test10/bug-5143-ms-shuffle.summary @@ -1,74 +1,74 @@ Current cluster status: Online: [ hex-1 hex-2 hex-3 ] fencing (stonith:external/sbd): Started hex-1 Clone Set: baseclone [basegrp] Started: [ hex-1 hex-2 hex-3 ] fs-xfs-1 (ocf::heartbeat:Filesystem): Started hex-2 Clone Set: fs2 [fs-ocfs-2] Started: [ hex-1 hex-2 hex-3 ] Master/Slave Set: ms-r0 [drbd-r0] Masters: [ hex-1 ] Slaves: [ hex-2 ] Master/Slave Set: ms-r1 [drbd-r1] Slaves: [ hex-2 hex-3 ] Resource Group: md0-group md0 (ocf::heartbeat:Raid1): Started hex-3 vg-md0 (ocf::heartbeat:LVM): Started hex-3 fs-md0 (ocf::heartbeat:Filesystem): Started hex-3 dummy1 (ocf::heartbeat:Delay): Started hex-3 dummy3 (ocf::heartbeat:Delay): Started hex-1 dummy4 (ocf::heartbeat:Delay): Started hex-2 dummy5 (ocf::heartbeat:Delay): Started hex-1 dummy6 (ocf::heartbeat:Delay): Started hex-2 Resource Group: r0-group - fs-r0 (ocf::heartbeat:Filesystem): Stopped + fs-r0 (ocf::heartbeat:Filesystem): (target-role:Stopped) Stopped dummy2 (ocf::heartbeat:Delay): Stopped Transition Summary: * Promote drbd-r1:1 (Slave -> Master hex-3) Executing cluster transition: * Pseudo action: ms-r1_pre_notify_promote_0 * Resource action: drbd-r1 notify on hex-2 * Resource action: drbd-r1 notify on hex-3 * Pseudo action: ms-r1_confirmed-pre_notify_promote_0 * Pseudo action: ms-r1_promote_0 * Resource action: drbd-r1 promote on hex-3 * Pseudo action: ms-r1_promoted_0 * Pseudo action: ms-r1_post_notify_promoted_0 * Resource action: drbd-r1 notify on hex-2 * Resource action: drbd-r1 notify on hex-3 * Pseudo action: ms-r1_confirmed-post_notify_promoted_0 * Resource action: drbd-r1 monitor=29000 on hex-2 * Resource action: drbd-r1 monitor=31000 on hex-3 Revised cluster status: Online: [ hex-1 hex-2 hex-3 ] fencing (stonith:external/sbd): Started hex-1 Clone Set: baseclone [basegrp] Started: [ hex-1 hex-2 hex-3 ] fs-xfs-1 (ocf::heartbeat:Filesystem): Started hex-2 Clone Set: fs2 [fs-ocfs-2] Started: [ hex-1 hex-2 hex-3 ] Master/Slave Set: ms-r0 [drbd-r0] Masters: [ hex-1 ] Slaves: [ hex-2 ] Master/Slave Set: ms-r1 [drbd-r1] Masters: [ hex-3 ] Slaves: [ hex-2 ] Resource Group: md0-group md0 (ocf::heartbeat:Raid1): Started hex-3 vg-md0 (ocf::heartbeat:LVM): Started hex-3 fs-md0 (ocf::heartbeat:Filesystem): Started hex-3 dummy1 (ocf::heartbeat:Delay): Started hex-3 dummy3 (ocf::heartbeat:Delay): Started hex-1 dummy4 (ocf::heartbeat:Delay): Started hex-2 dummy5 (ocf::heartbeat:Delay): Started hex-1 dummy6 (ocf::heartbeat:Delay): Started hex-2 Resource Group: r0-group - fs-r0 (ocf::heartbeat:Filesystem): Stopped + fs-r0 (ocf::heartbeat:Filesystem): (target-role:Stopped) Stopped dummy2 (ocf::heartbeat:Delay): Stopped diff --git a/pengine/test10/bug-cl-5219.summary b/pengine/test10/bug-cl-5219.summary index c7e06826fb..9e64a9b2e1 100644 --- a/pengine/test10/bug-cl-5219.summary +++ b/pengine/test10/bug-cl-5219.summary @@ -1,40 +1,40 @@ Current cluster status: Online: [ ha1.test.anchor.net.au ha2.test.anchor.net.au ] - child1-service (ocf::pacemaker:Dummy): Started ha2.test.anchor.net.au + child1-service (ocf::pacemaker:Dummy): (target-role:Stopped) Started ha2.test.anchor.net.au child2-service (ocf::pacemaker:Dummy): Started ha2.test.anchor.net.au parent-service (ocf::pacemaker:Dummy): Started ha2.test.anchor.net.au Master/Slave Set: child1 [stateful-child1] Masters: [ ha2.test.anchor.net.au ] Slaves: [ ha1.test.anchor.net.au ] Master/Slave Set: child2 [stateful-child2] Masters: [ ha2.test.anchor.net.au ] Slaves: [ ha1.test.anchor.net.au ] Master/Slave Set: parent [stateful-parent] Masters: [ ha2.test.anchor.net.au ] Slaves: [ ha1.test.anchor.net.au ] Transition Summary: * Stop child1-service (ha2.test.anchor.net.au) Executing cluster transition: * Resource action: child1-service stop on ha2.test.anchor.net.au * Pseudo action: all_stopped Revised cluster status: Online: [ ha1.test.anchor.net.au ha2.test.anchor.net.au ] - child1-service (ocf::pacemaker:Dummy): Stopped + child1-service (ocf::pacemaker:Dummy): (target-role:Stopped) Stopped child2-service (ocf::pacemaker:Dummy): Started ha2.test.anchor.net.au parent-service (ocf::pacemaker:Dummy): Started ha2.test.anchor.net.au Master/Slave Set: child1 [stateful-child1] Masters: [ ha2.test.anchor.net.au ] Slaves: [ ha1.test.anchor.net.au ] Master/Slave Set: child2 [stateful-child2] Masters: [ ha2.test.anchor.net.au ] Slaves: [ ha1.test.anchor.net.au ] Master/Slave Set: parent [stateful-parent] Masters: [ ha2.test.anchor.net.au ] Slaves: [ ha1.test.anchor.net.au ] diff --git a/pengine/test10/bug-lf-2422.summary b/pengine/test10/bug-lf-2422.summary index 760fc2baf4..c78a314581 100644 --- a/pengine/test10/bug-lf-2422.summary +++ b/pengine/test10/bug-lf-2422.summary @@ -1,80 +1,80 @@ Current cluster status: Online: [ qa-suse-1 qa-suse-2 qa-suse-3 qa-suse-4 ] sbd_stonith (stonith:external/sbd): Started qa-suse-2 Clone Set: c-o2stage [o2stage] Started: [ qa-suse-1 qa-suse-2 qa-suse-3 qa-suse-4 ] Clone Set: c-ocfs [ocfs] Started: [ qa-suse-1 qa-suse-2 qa-suse-3 qa-suse-4 ] Transition Summary: * Stop o2cb:0 (qa-suse-1) * Stop cmirror:0 (qa-suse-1) * Stop o2cb:1 (qa-suse-4) * Stop cmirror:1 (qa-suse-4) * Stop o2cb:2 (qa-suse-3) * Stop cmirror:2 (qa-suse-3) * Stop o2cb:3 (qa-suse-2) * Stop cmirror:3 (qa-suse-2) * Stop ocfs:0 (qa-suse-1) * Stop ocfs:1 (qa-suse-4) * Stop ocfs:2 (qa-suse-3) * Stop ocfs:3 (qa-suse-2) Executing cluster transition: * Resource action: sbd_stonith monitor=15000 on qa-suse-2 * Pseudo action: c-ocfs_stop_0 * Resource action: ocfs:3 stop on qa-suse-2 * Resource action: ocfs:2 stop on qa-suse-3 * Resource action: ocfs:0 stop on qa-suse-4 * Resource action: ocfs:1 stop on qa-suse-1 * Pseudo action: c-ocfs_stopped_0 * Pseudo action: c-o2stage_stop_0 * Pseudo action: o2stage:0_stop_0 * Resource action: cmirror:1 stop on qa-suse-1 * Pseudo action: o2stage:1_stop_0 * Resource action: cmirror:0 stop on qa-suse-4 * Pseudo action: o2stage:2_stop_0 * Resource action: cmirror:2 stop on qa-suse-3 * Pseudo action: o2stage:3_stop_0 * Resource action: cmirror:3 stop on qa-suse-2 * Resource action: o2cb:1 stop on qa-suse-1 * Resource action: o2cb:0 stop on qa-suse-4 * Resource action: o2cb:2 stop on qa-suse-3 * Resource action: o2cb:3 stop on qa-suse-2 * Pseudo action: all_stopped * Pseudo action: o2stage:0_stopped_0 * Pseudo action: o2stage:1_stopped_0 * Pseudo action: o2stage:2_stopped_0 * Pseudo action: o2stage:3_stopped_0 * Pseudo action: c-o2stage_stopped_0 Revised cluster status: Online: [ qa-suse-1 qa-suse-2 qa-suse-3 qa-suse-4 ] sbd_stonith (stonith:external/sbd): Started qa-suse-2 Clone Set: c-o2stage [o2stage] Resource Group: o2stage:0 dlm (ocf::pacemaker:controld): Started qa-suse-1 clvm (ocf::lvm2:clvmd): Started qa-suse-1 - o2cb (ocf::ocfs2:o2cb): Stopped + o2cb (ocf::ocfs2:o2cb): (target-role:Stopped) Stopped cmirror (ocf::lvm2:cmirrord): Stopped Resource Group: o2stage:1 dlm (ocf::pacemaker:controld): Started qa-suse-4 clvm (ocf::lvm2:clvmd): Started qa-suse-4 - o2cb (ocf::ocfs2:o2cb): Stopped + o2cb (ocf::ocfs2:o2cb): (target-role:Stopped) Stopped cmirror (ocf::lvm2:cmirrord): Stopped Resource Group: o2stage:2 dlm (ocf::pacemaker:controld): Started qa-suse-3 clvm (ocf::lvm2:clvmd): Started qa-suse-3 - o2cb (ocf::ocfs2:o2cb): Stopped + o2cb (ocf::ocfs2:o2cb): (target-role:Stopped) Stopped cmirror (ocf::lvm2:cmirrord): Stopped Resource Group: o2stage:3 dlm (ocf::pacemaker:controld): Started qa-suse-2 clvm (ocf::lvm2:clvmd): Started qa-suse-2 - o2cb (ocf::ocfs2:o2cb): Stopped + o2cb (ocf::ocfs2:o2cb): (target-role:Stopped) Stopped cmirror (ocf::lvm2:cmirrord): Stopped Clone Set: c-ocfs [ocfs] Stopped: [ qa-suse-1 qa-suse-2 qa-suse-3 qa-suse-4 ] diff --git a/pengine/test10/bug-lf-2606.summary b/pengine/test10/bug-lf-2606.summary index baa0f3b903..435f8f8add 100644 --- a/pengine/test10/bug-lf-2606.summary +++ b/pengine/test10/bug-lf-2606.summary @@ -1,43 +1,43 @@ Current cluster status: Node node2: UNCLEAN (online) Online: [ node1 ] rsc_stonith (stonith:null): Started node1 rsc1 (ocf::pacemaker:Dummy): FAILED node2 rsc2 (ocf::pacemaker:Dummy): Started node2 Master/Slave Set: ms3 [rsc3] Masters: [ node2 ] Slaves: [ node1 ] Transition Summary: * Stop rsc1 (node2) * Move rsc2 (Started node2 -> node1) * Demote rsc3:1 (Master -> Stopped node2) Executing cluster transition: * Pseudo action: ms3_demote_0 * Fencing node2 (reboot) * Pseudo action: stonith_complete * Pseudo action: rsc1_stop_0 * Pseudo action: rsc2_stop_0 * Pseudo action: rsc3:1_demote_0 * Pseudo action: ms3_demoted_0 * Pseudo action: ms3_stop_0 * Resource action: rsc2 start on node1 * Pseudo action: rsc3:1_stop_0 * Pseudo action: ms3_stopped_0 * Pseudo action: all_stopped * Resource action: rsc2 monitor=10000 on node1 Revised cluster status: Online: [ node1 ] OFFLINE: [ node2 ] rsc_stonith (stonith:null): Started node1 - rsc1 (ocf::pacemaker:Dummy): Stopped + rsc1 (ocf::pacemaker:Dummy): (target-role:Stopped) Stopped rsc2 (ocf::pacemaker:Dummy): Started node1 Master/Slave Set: ms3 [rsc3] Slaves: [ node1 ] Stopped: [ node2 ] diff --git a/pengine/test10/bug-rh-1097457.summary b/pengine/test10/bug-rh-1097457.summary index 1ecbc5f5fc..e2f235d007 100644 --- a/pengine/test10/bug-rh-1097457.summary +++ b/pengine/test10/bug-rh-1097457.summary @@ -1,101 +1,101 @@ Current cluster status: Online: [ lama2 lama3 ] Containers: [ lamaVM1:VM1 lamaVM2:VM2 lamaVM3:VM3 ] restofencelama2 (stonith:fence_ipmilan): Started lama3 restofencelama3 (stonith:fence_ipmilan): Started lama2 VM1 (ocf::heartbeat:VirtualDomain): Started lama2 FSlun1 (ocf::heartbeat:Filesystem): Started lamaVM1 FSlun2 (ocf::heartbeat:Filesystem): Started lamaVM1 VM2 (ocf::heartbeat:VirtualDomain): FAILED lama3 VM3 (ocf::heartbeat:VirtualDomain): Started lama3 FSlun3 (ocf::heartbeat:Filesystem): FAILED lamaVM2 FSlun4 (ocf::heartbeat:Filesystem): Started lamaVM3 - FAKE5-IP (ocf::heartbeat:IPaddr2): Stopped - FAKE6-IP (ocf::heartbeat:IPaddr2): Stopped + FAKE5-IP (ocf::heartbeat:IPaddr2): (target-role:stopped) Stopped + FAKE6-IP (ocf::heartbeat:IPaddr2): (target-role:stopped) Stopped FAKE5 (ocf::heartbeat:Dummy): Started lamaVM3 Resource Group: lamaVM1-G1 FAKE1 (ocf::heartbeat:Dummy): Started lamaVM1 FAKE1-IP (ocf::heartbeat:IPaddr2): Started lamaVM1 Resource Group: lamaVM1-G2 FAKE2 (ocf::heartbeat:Dummy): Started lamaVM1 FAKE2-IP (ocf::heartbeat:IPaddr2): Started lamaVM1 Resource Group: lamaVM1-G3 FAKE3 (ocf::heartbeat:Dummy): Started lamaVM1 FAKE3-IP (ocf::heartbeat:IPaddr2): Started lamaVM1 Resource Group: lamaVM2-G4 FAKE4 (ocf::heartbeat:Dummy): Started lamaVM2 FAKE4-IP (ocf::heartbeat:IPaddr2): Started lamaVM2 Clone Set: FAKE6-clone [FAKE6] Started: [ lamaVM1 lamaVM2 lamaVM3 ] Transition Summary: * Recover VM2 (Started lama3) * Recover FSlun3 (Started lamaVM2 -> lama2) * Restart FAKE4 (Started lamaVM2) * Restart FAKE4-IP (Started lamaVM2) * Restart FAKE6:2 (Started lamaVM2) * Restart lamaVM2 (Started lama3) Executing cluster transition: * Pseudo action: lamaVM2-G4_stop_0 * Pseudo action: FAKE6-clone_stop_0 * Resource action: lamaVM2 stop on lama3 * Resource action: VM2 stop on lama3 * Pseudo action: FAKE4-IP_stop_0 * Pseudo action: FAKE6_stop_0 * Pseudo action: FAKE6-clone_stopped_0 * Pseudo action: FAKE6-clone_start_0 * Resource action: VM2 start on lama3 * Resource action: VM2 monitor=10000 on lama3 * Pseudo action: FAKE4_stop_0 * Resource action: lamaVM2 start on lama3 * Resource action: lamaVM2 monitor=30000 on lama3 * Resource action: FSlun3 monitor=10000 on lamaVM2 * Pseudo action: lamaVM2-G4_stopped_0 * Resource action: FAKE6 start on lamaVM2 * Resource action: FAKE6 monitor=30000 on lamaVM2 * Pseudo action: FAKE6-clone_running_0 * Pseudo action: FSlun3_stop_0 * Pseudo action: all_stopped * Resource action: FSlun3 start on lama2 * Pseudo action: lamaVM2-G4_start_0 * Resource action: FAKE4 start on lamaVM2 * Resource action: FAKE4 monitor=30000 on lamaVM2 * Resource action: FAKE4-IP start on lamaVM2 * Resource action: FAKE4-IP monitor=30000 on lamaVM2 * Resource action: FSlun3 monitor=10000 on lama2 * Pseudo action: lamaVM2-G4_running_0 Revised cluster status: Online: [ lama2 lama3 ] Containers: [ lamaVM1:VM1 lamaVM2:VM2 lamaVM3:VM3 ] restofencelama2 (stonith:fence_ipmilan): Started lama3 restofencelama3 (stonith:fence_ipmilan): Started lama2 VM1 (ocf::heartbeat:VirtualDomain): Started lama2 FSlun1 (ocf::heartbeat:Filesystem): Started lamaVM1 FSlun2 (ocf::heartbeat:Filesystem): Started lamaVM1 VM2 (ocf::heartbeat:VirtualDomain): FAILED lama3 VM3 (ocf::heartbeat:VirtualDomain): Started lama3 FSlun3 (ocf::heartbeat:Filesystem): FAILED [ lama2 lamaVM2 ] FSlun4 (ocf::heartbeat:Filesystem): Started lamaVM3 - FAKE5-IP (ocf::heartbeat:IPaddr2): Stopped - FAKE6-IP (ocf::heartbeat:IPaddr2): Stopped + FAKE5-IP (ocf::heartbeat:IPaddr2): (target-role:stopped) Stopped + FAKE6-IP (ocf::heartbeat:IPaddr2): (target-role:stopped) Stopped FAKE5 (ocf::heartbeat:Dummy): Started lamaVM3 Resource Group: lamaVM1-G1 FAKE1 (ocf::heartbeat:Dummy): Started lamaVM1 FAKE1-IP (ocf::heartbeat:IPaddr2): Started lamaVM1 Resource Group: lamaVM1-G2 FAKE2 (ocf::heartbeat:Dummy): Started lamaVM1 FAKE2-IP (ocf::heartbeat:IPaddr2): Started lamaVM1 Resource Group: lamaVM1-G3 FAKE3 (ocf::heartbeat:Dummy): Started lamaVM1 FAKE3-IP (ocf::heartbeat:IPaddr2): Started lamaVM1 Resource Group: lamaVM2-G4 FAKE4 (ocf::heartbeat:Dummy): Started lamaVM2 FAKE4-IP (ocf::heartbeat:IPaddr2): Started lamaVM2 Clone Set: FAKE6-clone [FAKE6] Started: [ lamaVM1 lamaVM2 lamaVM3 ] diff --git a/pengine/test10/bug-suse-707150.summary b/pengine/test10/bug-suse-707150.summary index 6d1fcdf8b6..2468b2865b 100644 --- a/pengine/test10/bug-suse-707150.summary +++ b/pengine/test10/bug-suse-707150.summary @@ -1,72 +1,72 @@ Current cluster status: Online: [ hex-0 hex-9 ] OFFLINE: [ hex-7 hex-8 ] - vm-00 (ocf::heartbeat:Xen): Stopped + vm-00 (ocf::heartbeat:Xen): (target-role:Stopped) Stopped Clone Set: base-clone [base-group] Resource Group: base-group:0 dlm (ocf::pacemaker:controld): Started hex-0 o2cb (ocf::ocfs2:o2cb): Stopped clvm (ocf::lvm2:clvmd): Stopped cmirrord (ocf::lvm2:cmirrord): Stopped - vg1 (ocf::heartbeat:LVM): Stopped + vg1 (ocf::heartbeat:LVM): (target-role:Stopped) Stopped ocfs2-1 (ocf::heartbeat:Filesystem): Stopped Stopped: [ hex-7 hex-8 hex-9 ] vm-01 (ocf::heartbeat:Xen): Stopped fencing-sbd (stonith:external/sbd): Started hex-9 dummy1 (ocf::heartbeat:Dummy): Started hex-0 Transition Summary: * Start o2cb:0 (hex-0) * Start clvm:0 (hex-0) * Start cmirrord:0 (hex-0) * Start dlm:1 (hex-9) * Start o2cb:1 (hex-9) * Start clvm:1 (hex-9) * Start cmirrord:1 (hex-9) * Start vm-01 (hex-9 - blocked) Executing cluster transition: * Resource action: vg1:1 monitor on hex-9 * Pseudo action: base-clone_start_0 * Pseudo action: probe_complete * Pseudo action: load_stopped_hex-9 * Pseudo action: load_stopped_hex-8 * Pseudo action: load_stopped_hex-7 * Pseudo action: load_stopped_hex-0 * Pseudo action: base-group:0_start_0 * Resource action: o2cb:0 start on hex-0 * Resource action: clvm:0 start on hex-0 * Resource action: cmirrord:0 start on hex-0 * Pseudo action: base-group:1_start_0 * Resource action: dlm:1 start on hex-9 * Resource action: o2cb:1 start on hex-9 * Resource action: clvm:1 start on hex-9 * Resource action: cmirrord:1 start on hex-9 Revised cluster status: Online: [ hex-0 hex-9 ] OFFLINE: [ hex-7 hex-8 ] - vm-00 (ocf::heartbeat:Xen): Stopped + vm-00 (ocf::heartbeat:Xen): (target-role:Stopped) Stopped Clone Set: base-clone [base-group] Resource Group: base-group:0 dlm (ocf::pacemaker:controld): Started hex-0 o2cb (ocf::ocfs2:o2cb): Started hex-0 clvm (ocf::lvm2:clvmd): Started hex-0 cmirrord (ocf::lvm2:cmirrord): Started hex-0 - vg1 (ocf::heartbeat:LVM): Stopped + vg1 (ocf::heartbeat:LVM): (target-role:Stopped) Stopped ocfs2-1 (ocf::heartbeat:Filesystem): Stopped Resource Group: base-group:1 dlm (ocf::pacemaker:controld): Started hex-9 o2cb (ocf::ocfs2:o2cb): Started hex-9 clvm (ocf::lvm2:clvmd): Started hex-9 cmirrord (ocf::lvm2:cmirrord): Started hex-9 - vg1 (ocf::heartbeat:LVM): Stopped + vg1 (ocf::heartbeat:LVM): (target-role:Stopped) Stopped ocfs2-1 (ocf::heartbeat:Filesystem): Stopped Stopped: [ hex-7 hex-8 ] vm-01 (ocf::heartbeat:Xen): Stopped fencing-sbd (stonith:external/sbd): Started hex-9 dummy1 (ocf::heartbeat:Dummy): Started hex-0 diff --git a/pengine/test10/coloc-clone-stays-active.summary b/pengine/test10/coloc-clone-stays-active.summary index b5edc92a1f..a0370b5f4e 100644 --- a/pengine/test10/coloc-clone-stays-active.summary +++ b/pengine/test10/coloc-clone-stays-active.summary @@ -1,206 +1,206 @@ Current cluster status: Online: [ s01-0 s01-1 ] stonith-s01-0 (stonith:external/ipmi): Started s01-1 stonith-s01-1 (stonith:external/ipmi): Started s01-0 Resource Group: iscsi-pool-0-target-all iscsi-pool-0-target (ocf::vds-ok:iSCSITarget): Started s01-0 iscsi-pool-0-lun-1 (ocf::vds-ok:iSCSILogicalUnit): Started s01-0 Resource Group: iscsi-pool-0-vips vip-235 (ocf::heartbeat:IPaddr2): Started s01-0 vip-236 (ocf::heartbeat:IPaddr2): Started s01-0 Resource Group: iscsi-pool-1-target-all iscsi-pool-1-target (ocf::vds-ok:iSCSITarget): Started s01-1 iscsi-pool-1-lun-1 (ocf::vds-ok:iSCSILogicalUnit): Started s01-1 Resource Group: iscsi-pool-1-vips vip-237 (ocf::heartbeat:IPaddr2): Started s01-1 vip-238 (ocf::heartbeat:IPaddr2): Started s01-1 Master/Slave Set: ms-drbd-pool-0 [drbd-pool-0] Masters: [ s01-0 ] Slaves: [ s01-1 ] Master/Slave Set: ms-drbd-pool-1 [drbd-pool-1] Masters: [ s01-1 ] Slaves: [ s01-0 ] Master/Slave Set: ms-iscsi-pool-0-vips-fw [iscsi-pool-0-vips-fw] Masters: [ s01-0 ] Slaves: [ s01-1 ] Master/Slave Set: ms-iscsi-pool-1-vips-fw [iscsi-pool-1-vips-fw] Masters: [ s01-1 ] Slaves: [ s01-0 ] Clone Set: cl-o2cb [o2cb] Stopped: [ s01-0 s01-1 ] Master/Slave Set: ms-drbd-s01-service [drbd-s01-service] Masters: [ s01-0 s01-1 ] Clone Set: cl-s01-service-fs [s01-service-fs] Started: [ s01-0 s01-1 ] Clone Set: cl-ietd [ietd] Started: [ s01-0 s01-1 ] Clone Set: cl-dhcpd [dhcpd] Stopped: [ s01-0 s01-1 ] Resource Group: http-server vip-233 (ocf::heartbeat:IPaddr2): Started s01-0 - nginx (lsb:nginx): Stopped + nginx (lsb:nginx): (target-role:Stopped) Stopped Master/Slave Set: ms-drbd-s01-logs [drbd-s01-logs] Masters: [ s01-0 s01-1 ] Clone Set: cl-s01-logs-fs [s01-logs-fs] Started: [ s01-0 s01-1 ] Resource Group: syslog-server vip-234 (ocf::heartbeat:IPaddr2): Started s01-1 syslog-ng (ocf::heartbeat:syslog-ng): Started s01-1 Resource Group: tftp-server vip-232 (ocf::heartbeat:IPaddr2): Stopped tftpd (ocf::heartbeat:Xinetd): Stopped Clone Set: cl-xinetd [xinetd] Started: [ s01-0 s01-1 ] Clone Set: cl-ospf-routing [ospf-routing] Started: [ s01-0 s01-1 ] Clone Set: connected-outer [ping-bmc-and-switch] Started: [ s01-0 s01-1 ] Resource Group: iscsi-vds-dom0-stateless-0-target-all - iscsi-vds-dom0-stateless-0-target (ocf::vds-ok:iSCSITarget): Stopped - iscsi-vds-dom0-stateless-0-lun-1 (ocf::vds-ok:iSCSILogicalUnit): Stopped + iscsi-vds-dom0-stateless-0-target (ocf::vds-ok:iSCSITarget): (target-role:Stopped) Stopped + iscsi-vds-dom0-stateless-0-lun-1 (ocf::vds-ok:iSCSILogicalUnit): (target-role:Stopped) Stopped Resource Group: iscsi-vds-dom0-stateless-0-vips vip-227 (ocf::heartbeat:IPaddr2): Stopped vip-228 (ocf::heartbeat:IPaddr2): Stopped Master/Slave Set: ms-drbd-vds-dom0-stateless-0 [drbd-vds-dom0-stateless-0] Masters: [ s01-0 ] Slaves: [ s01-1 ] Master/Slave Set: ms-iscsi-vds-dom0-stateless-0-vips-fw [iscsi-vds-dom0-stateless-0-vips-fw] Slaves: [ s01-0 s01-1 ] Clone Set: cl-dlm [dlm] Started: [ s01-0 s01-1 ] Master/Slave Set: ms-drbd-vds-tftpboot [drbd-vds-tftpboot] Masters: [ s01-0 s01-1 ] Clone Set: cl-vds-tftpboot-fs [vds-tftpboot-fs] Stopped: [ s01-0 s01-1 ] Clone Set: cl-gfs2 [gfs2] Started: [ s01-0 s01-1 ] Master/Slave Set: ms-drbd-vds-http [drbd-vds-http] Masters: [ s01-0 s01-1 ] Clone Set: cl-vds-http-fs [vds-http-fs] Started: [ s01-0 s01-1 ] Clone Set: cl-clvmd [clvmd] Started: [ s01-0 s01-1 ] Master/Slave Set: ms-drbd-s01-vm-data [drbd-s01-vm-data] Masters: [ s01-0 s01-1 ] Clone Set: cl-s01-vm-data-metadata-fs [s01-vm-data-metadata-fs] Started: [ s01-0 s01-1 ] Clone Set: cl-vg-s01-vm-data [vg-s01-vm-data] Started: [ s01-0 s01-1 ] mgmt-vm (ocf::vds-ok:VirtualDomain): Started s01-0 Clone Set: cl-drbdlinks-s01-service [drbdlinks-s01-service] Started: [ s01-0 s01-1 ] Clone Set: cl-libvirtd [libvirtd] Started: [ s01-0 s01-1 ] Clone Set: cl-s01-vm-data-storage-pool [s01-vm-data-storage-pool] Started: [ s01-0 s01-1 ] Transition Summary: * Migrate mgmt-vm (Started s01-0 -> s01-1) Executing cluster transition: * Resource action: mgmt-vm migrate_to on s01-0 * Resource action: mgmt-vm migrate_from on s01-1 * Resource action: mgmt-vm stop on s01-0 * Pseudo action: all_stopped * Pseudo action: mgmt-vm_start_0 * Resource action: mgmt-vm monitor=10000 on s01-1 Revised cluster status: Online: [ s01-0 s01-1 ] stonith-s01-0 (stonith:external/ipmi): Started s01-1 stonith-s01-1 (stonith:external/ipmi): Started s01-0 Resource Group: iscsi-pool-0-target-all iscsi-pool-0-target (ocf::vds-ok:iSCSITarget): Started s01-0 iscsi-pool-0-lun-1 (ocf::vds-ok:iSCSILogicalUnit): Started s01-0 Resource Group: iscsi-pool-0-vips vip-235 (ocf::heartbeat:IPaddr2): Started s01-0 vip-236 (ocf::heartbeat:IPaddr2): Started s01-0 Resource Group: iscsi-pool-1-target-all iscsi-pool-1-target (ocf::vds-ok:iSCSITarget): Started s01-1 iscsi-pool-1-lun-1 (ocf::vds-ok:iSCSILogicalUnit): Started s01-1 Resource Group: iscsi-pool-1-vips vip-237 (ocf::heartbeat:IPaddr2): Started s01-1 vip-238 (ocf::heartbeat:IPaddr2): Started s01-1 Master/Slave Set: ms-drbd-pool-0 [drbd-pool-0] Masters: [ s01-0 ] Slaves: [ s01-1 ] Master/Slave Set: ms-drbd-pool-1 [drbd-pool-1] Masters: [ s01-1 ] Slaves: [ s01-0 ] Master/Slave Set: ms-iscsi-pool-0-vips-fw [iscsi-pool-0-vips-fw] Masters: [ s01-0 ] Slaves: [ s01-1 ] Master/Slave Set: ms-iscsi-pool-1-vips-fw [iscsi-pool-1-vips-fw] Masters: [ s01-1 ] Slaves: [ s01-0 ] Clone Set: cl-o2cb [o2cb] Stopped: [ s01-0 s01-1 ] Master/Slave Set: ms-drbd-s01-service [drbd-s01-service] Masters: [ s01-0 s01-1 ] Clone Set: cl-s01-service-fs [s01-service-fs] Started: [ s01-0 s01-1 ] Clone Set: cl-ietd [ietd] Started: [ s01-0 s01-1 ] Clone Set: cl-dhcpd [dhcpd] Stopped: [ s01-0 s01-1 ] Resource Group: http-server vip-233 (ocf::heartbeat:IPaddr2): Started s01-0 - nginx (lsb:nginx): Stopped + nginx (lsb:nginx): (target-role:Stopped) Stopped Master/Slave Set: ms-drbd-s01-logs [drbd-s01-logs] Masters: [ s01-0 s01-1 ] Clone Set: cl-s01-logs-fs [s01-logs-fs] Started: [ s01-0 s01-1 ] Resource Group: syslog-server vip-234 (ocf::heartbeat:IPaddr2): Started s01-1 syslog-ng (ocf::heartbeat:syslog-ng): Started s01-1 Resource Group: tftp-server vip-232 (ocf::heartbeat:IPaddr2): Stopped tftpd (ocf::heartbeat:Xinetd): Stopped Clone Set: cl-xinetd [xinetd] Started: [ s01-0 s01-1 ] Clone Set: cl-ospf-routing [ospf-routing] Started: [ s01-0 s01-1 ] Clone Set: connected-outer [ping-bmc-and-switch] Started: [ s01-0 s01-1 ] Resource Group: iscsi-vds-dom0-stateless-0-target-all - iscsi-vds-dom0-stateless-0-target (ocf::vds-ok:iSCSITarget): Stopped - iscsi-vds-dom0-stateless-0-lun-1 (ocf::vds-ok:iSCSILogicalUnit): Stopped + iscsi-vds-dom0-stateless-0-target (ocf::vds-ok:iSCSITarget): (target-role:Stopped) Stopped + iscsi-vds-dom0-stateless-0-lun-1 (ocf::vds-ok:iSCSILogicalUnit): (target-role:Stopped) Stopped Resource Group: iscsi-vds-dom0-stateless-0-vips vip-227 (ocf::heartbeat:IPaddr2): Stopped vip-228 (ocf::heartbeat:IPaddr2): Stopped Master/Slave Set: ms-drbd-vds-dom0-stateless-0 [drbd-vds-dom0-stateless-0] Masters: [ s01-0 ] Slaves: [ s01-1 ] Master/Slave Set: ms-iscsi-vds-dom0-stateless-0-vips-fw [iscsi-vds-dom0-stateless-0-vips-fw] Slaves: [ s01-0 s01-1 ] Clone Set: cl-dlm [dlm] Started: [ s01-0 s01-1 ] Master/Slave Set: ms-drbd-vds-tftpboot [drbd-vds-tftpboot] Masters: [ s01-0 s01-1 ] Clone Set: cl-vds-tftpboot-fs [vds-tftpboot-fs] Stopped: [ s01-0 s01-1 ] Clone Set: cl-gfs2 [gfs2] Started: [ s01-0 s01-1 ] Master/Slave Set: ms-drbd-vds-http [drbd-vds-http] Masters: [ s01-0 s01-1 ] Clone Set: cl-vds-http-fs [vds-http-fs] Started: [ s01-0 s01-1 ] Clone Set: cl-clvmd [clvmd] Started: [ s01-0 s01-1 ] Master/Slave Set: ms-drbd-s01-vm-data [drbd-s01-vm-data] Masters: [ s01-0 s01-1 ] Clone Set: cl-s01-vm-data-metadata-fs [s01-vm-data-metadata-fs] Started: [ s01-0 s01-1 ] Clone Set: cl-vg-s01-vm-data [vg-s01-vm-data] Started: [ s01-0 s01-1 ] mgmt-vm (ocf::vds-ok:VirtualDomain): Started s01-1 Clone Set: cl-drbdlinks-s01-service [drbdlinks-s01-service] Started: [ s01-0 s01-1 ] Clone Set: cl-libvirtd [libvirtd] Started: [ s01-0 s01-1 ] Clone Set: cl-s01-vm-data-storage-pool [s01-vm-data-storage-pool] Started: [ s01-0 s01-1 ] diff --git a/pengine/test10/colocation_constraint_stops_slave.summary b/pengine/test10/colocation_constraint_stops_slave.summary index 77500dccfb..1e5c0f12b4 100644 --- a/pengine/test10/colocation_constraint_stops_slave.summary +++ b/pengine/test10/colocation_constraint_stops_slave.summary @@ -1,33 +1,33 @@ Current cluster status: Online: [ fc16-builder ] OFFLINE: [ fc16-builder2 ] Master/Slave Set: MASTER_RSC_A [NATIVE_RSC_A] Slaves: [ fc16-builder ] - NATIVE_RSC_B (ocf::pacemaker:Dummy): Started fc16-builder + NATIVE_RSC_B (ocf::pacemaker:Dummy): (target-role:Stopped) Started fc16-builder Transition Summary: * Stop NATIVE_RSC_A:0 (fc16-builder) * Stop NATIVE_RSC_B (fc16-builder) Executing cluster transition: * Pseudo action: MASTER_RSC_A_pre_notify_stop_0 * Resource action: NATIVE_RSC_B stop on fc16-builder * Resource action: NATIVE_RSC_A:0 notify on fc16-builder * Pseudo action: MASTER_RSC_A_confirmed-pre_notify_stop_0 * Pseudo action: MASTER_RSC_A_stop_0 * Resource action: NATIVE_RSC_A:0 stop on fc16-builder * Pseudo action: MASTER_RSC_A_stopped_0 * Pseudo action: MASTER_RSC_A_post_notify_stopped_0 * Pseudo action: MASTER_RSC_A_confirmed-post_notify_stopped_0 * Pseudo action: all_stopped Revised cluster status: Online: [ fc16-builder ] OFFLINE: [ fc16-builder2 ] Master/Slave Set: MASTER_RSC_A [NATIVE_RSC_A] Stopped: [ fc16-builder fc16-builder2 ] - NATIVE_RSC_B (ocf::pacemaker:Dummy): Stopped + NATIVE_RSC_B (ocf::pacemaker:Dummy): (target-role:Stopped) Stopped diff --git a/pengine/test10/group11.summary b/pengine/test10/group11.summary index 354152521f..768aa17ef8 100644 --- a/pengine/test10/group11.summary +++ b/pengine/test10/group11.summary @@ -1,29 +1,29 @@ Current cluster status: Online: [ node1 ] Resource Group: group1 rsc1 (heartbeat:apache): Started node1 - rsc2 (heartbeat:apache): Started node1 + rsc2 (heartbeat:apache): (target-role:Stopped) Started node1 rsc3 (heartbeat:apache): Started node1 Transition Summary: * Stop rsc2 (node1) * Stop rsc3 (node1) Executing cluster transition: * Pseudo action: group1_stop_0 * Resource action: rsc3 stop on node1 * Resource action: rsc2 stop on node1 * Pseudo action: all_stopped * Pseudo action: group1_stopped_0 * Pseudo action: group1_start_0 Revised cluster status: Online: [ node1 ] Resource Group: group1 rsc1 (heartbeat:apache): Started node1 - rsc2 (heartbeat:apache): Stopped + rsc2 (heartbeat:apache): (target-role:Stopped) Stopped rsc3 (heartbeat:apache): Stopped diff --git a/pengine/test10/load-stopped-loop.summary b/pengine/test10/load-stopped-loop.summary index e514e82028..feb93fa2a5 100644 --- a/pengine/test10/load-stopped-loop.summary +++ b/pengine/test10/load-stopped-loop.summary @@ -1,334 +1,334 @@ Current cluster status: Online: [ mgmt01 v03-a v03-b ] - stonith-v02-a (stonith:fence_ipmilan): Stopped - stonith-v02-b (stonith:fence_ipmilan): Stopped - stonith-v02-c (stonith:fence_ipmilan): Stopped - stonith-v02-d (stonith:fence_ipmilan): Stopped + stonith-v02-a (stonith:fence_ipmilan): (target-role:Stopped) Stopped + stonith-v02-b (stonith:fence_ipmilan): (target-role:Stopped) Stopped + stonith-v02-c (stonith:fence_ipmilan): (target-role:Stopped) Stopped + stonith-v02-d (stonith:fence_ipmilan): (target-role:Stopped) Stopped stonith-mgmt01 (stonith:fence_xvm): Started v03-b stonith-mgmt02 (stonith:meatware): Started mgmt01 - stonith-v03-c (stonith:fence_ipmilan): Stopped + stonith-v03-c (stonith:fence_ipmilan): (target-role:Stopped) Stopped stonith-v03-a (stonith:fence_ipmilan): Started v03-b stonith-v03-b (stonith:fence_ipmilan): Started v03-a - stonith-v03-d (stonith:fence_ipmilan): Stopped + stonith-v03-d (stonith:fence_ipmilan): (target-role:Stopped) Stopped Clone Set: cl-clvmd [clvmd] Started: [ mgmt01 v03-a v03-b ] Clone Set: cl-dlm [dlm] Started: [ mgmt01 v03-a v03-b ] Clone Set: cl-iscsid [iscsid] Started: [ mgmt01 v03-a v03-b ] Clone Set: cl-libvirtd [libvirtd] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] Clone Set: cl-multipathd [multipathd] Started: [ mgmt01 v03-a v03-b ] Clone Set: cl-node-params [node-params] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] Clone Set: cl-vlan1-if [vlan1-if] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] Clone Set: cl-vlan101-if [vlan101-if] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] Clone Set: cl-vlan102-if [vlan102-if] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] Clone Set: cl-vlan103-if [vlan103-if] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] Clone Set: cl-vlan104-if [vlan104-if] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] Clone Set: cl-vlan3-if [vlan3-if] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] Clone Set: cl-vlan4-if [vlan4-if] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] Clone Set: cl-vlan5-if [vlan5-if] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] Clone Set: cl-vlan900-if [vlan900-if] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] Clone Set: cl-vlan909-if [vlan909-if] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] Clone Set: cl-libvirt-images-fs [libvirt-images-fs] Started: [ mgmt01 v03-a v03-b ] Clone Set: cl-libvirt-install-fs [libvirt-install-fs] Started: [ mgmt01 v03-a v03-b ] Clone Set: cl-vds-ok-pool-0-iscsi [vds-ok-pool-0-iscsi] Started: [ mgmt01 v03-a v03-b ] Clone Set: cl-vds-ok-pool-0-vg [vds-ok-pool-0-vg] Started: [ mgmt01 v03-a v03-b ] Clone Set: cl-vds-ok-pool-1-iscsi [vds-ok-pool-1-iscsi] Started: [ mgmt01 v03-a v03-b ] Clone Set: cl-vds-ok-pool-1-vg [vds-ok-pool-1-vg] Started: [ mgmt01 v03-a v03-b ] Clone Set: cl-libvirt-images-pool [libvirt-images-pool] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] Clone Set: cl-vds-ok-pool-0-pool [vds-ok-pool-0-pool] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] Clone Set: cl-vds-ok-pool-1-pool [vds-ok-pool-1-pool] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] - git.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped + git.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped vd01-a.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Started v03-a vd01-b.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Started v03-a vd01-c.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Started v03-b vd01-d.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vd02-a.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vd02-b.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vd02-c.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vd02-d.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vd03-a.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vd03-b.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vd03-c.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vd03-d.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vd04-a.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vd04-b.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vd04-c.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vd04-d.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped + vd02-a.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vd02-b.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vd02-c.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vd02-d.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vd03-a.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vd03-b.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vd03-c.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vd03-d.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vd04-a.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vd04-b.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vd04-c.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vd04-d.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped f13-x64-devel.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Started v03-b - eu2.ca-pages.com-vm (ocf::vds-ok:VirtualDomain): Stopped - zakaz.transferrus.ru-vm (ocf::vds-ok:VirtualDomain): Stopped + eu2.ca-pages.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + zakaz.transferrus.ru-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped Clone Set: cl-vlan200-if [vlan200-if] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] lenny-x32-devel-vm (ocf::vds-ok:VirtualDomain): Started v03-a - dist.express-consult.org-vm (ocf::vds-ok:VirtualDomain): Stopped - eu1.ca-pages.com-vm (ocf::vds-ok:VirtualDomain): Stopped - gotin-bbb-vm (ocf::vds-ok:VirtualDomain): Stopped - maxb-c55-vm (ocf::vds-ok:VirtualDomain): Stopped - metae.ru-vm (ocf::vds-ok:VirtualDomain): Stopped - rodovoepomestie.ru-vm (ocf::vds-ok:VirtualDomain): Stopped - ubuntu9.10-gotin-vm (ocf::vds-ok:VirtualDomain): Stopped + dist.express-consult.org-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + eu1.ca-pages.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + gotin-bbb-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + maxb-c55-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + metae.ru-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + rodovoepomestie.ru-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + ubuntu9.10-gotin-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped c5-x64-devel.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Started v03-b Clone Set: cl-mcast-test-net [mcast-test-net] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] - dist.fly-uni.org-vm (ocf::vds-ok:VirtualDomain): Stopped + dist.fly-uni.org-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped ktstudio.net-vm (ocf::vds-ok:VirtualDomain): Started v03-a cloudsrv.credo-dialogue.com-vm (ocf::vds-ok:VirtualDomain): Started v03-b c6-x64-devel.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Started v03-a lustre01-right.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Started v03-b lustre02-right.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Started v03-a lustre03-left.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Started v03-b lustre03-right.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Started v03-a lustre04-left.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Started v03-b lustre04-right.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Started v03-a Clone Set: cl-mcast-anbriz-net [mcast-anbriz-net] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] gw.anbriz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Started v03-b license.anbriz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Started v03-b - terminal.anbriz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped + terminal.anbriz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped lustre01-left.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Started v03-a lustre02-left.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Started v03-b test-01.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Started v03-a Clone Set: cl-libvirt-qpid [libvirt-qpid] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] - gw.gleb.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - gw.gotin.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped + gw.gleb.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + gw.gotin.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped terminal0.anbriz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Started v03-a Clone Set: cl-mcast-gleb-net [mcast-gleb-net] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] Transition Summary: * Reload vds-ok-pool-0-iscsi:0 (Started mgmt01) * Reload vds-ok-pool-0-iscsi:1 (Started v03-b) * Reload vds-ok-pool-0-iscsi:2 (Started v03-a) * Reload vds-ok-pool-1-iscsi:0 (Started mgmt01) * Reload vds-ok-pool-1-iscsi:1 (Started v03-b) * Reload vds-ok-pool-1-iscsi:2 (Started v03-a) * Restart stonith-v03-b (Started v03-a) * Restart stonith-v03-a (Started v03-b) * Migrate license.anbriz.vds-ok.com-vm (Started v03-b -> v03-a) * Migrate terminal0.anbriz.vds-ok.com-vm (Started v03-a -> v03-b) * Start vd01-d.cdev.ttc.prague.cz.vds-ok.com-vm (v03-a) Executing cluster transition: * Resource action: vds-ok-pool-0-iscsi:1 reload on mgmt01 * Resource action: vds-ok-pool-0-iscsi:1 monitor=30000 on mgmt01 * Resource action: vds-ok-pool-0-iscsi:0 reload on v03-b * Resource action: vds-ok-pool-0-iscsi:0 monitor=30000 on v03-b * Resource action: vds-ok-pool-0-iscsi:2 reload on v03-a * Resource action: vds-ok-pool-0-iscsi:2 monitor=30000 on v03-a * Resource action: vds-ok-pool-1-iscsi:1 reload on mgmt01 * Resource action: vds-ok-pool-1-iscsi:1 monitor=30000 on mgmt01 * Resource action: vds-ok-pool-1-iscsi:0 reload on v03-b * Resource action: vds-ok-pool-1-iscsi:0 monitor=30000 on v03-b * Resource action: vds-ok-pool-1-iscsi:2 reload on v03-a * Resource action: vds-ok-pool-1-iscsi:2 monitor=30000 on v03-a * Resource action: stonith-v03-b stop on v03-a * Resource action: stonith-v03-b start on v03-a * Resource action: stonith-v03-b monitor=60000 on v03-a * Resource action: stonith-v03-a stop on v03-b * Resource action: stonith-v03-a start on v03-b * Resource action: stonith-v03-a monitor=60000 on v03-b * Resource action: license.anbriz.vds-ok.com-vm migrate_to on v03-b * Resource action: terminal0.anbriz.vds-ok.com-vm migrate_to on v03-a * Pseudo action: load_stopped_mgmt01 * Resource action: license.anbriz.vds-ok.com-vm migrate_from on v03-a * Resource action: license.anbriz.vds-ok.com-vm stop on v03-b * Resource action: terminal0.anbriz.vds-ok.com-vm migrate_from on v03-b * Resource action: terminal0.anbriz.vds-ok.com-vm stop on v03-a * Pseudo action: load_stopped_v03-b * Pseudo action: load_stopped_v03-a * Pseudo action: all_stopped * Pseudo action: license.anbriz.vds-ok.com-vm_start_0 * Pseudo action: terminal0.anbriz.vds-ok.com-vm_start_0 * Resource action: vd01-d.cdev.ttc.prague.cz.vds-ok.com-vm start on v03-a * Resource action: license.anbriz.vds-ok.com-vm monitor=10000 on v03-a * Resource action: terminal0.anbriz.vds-ok.com-vm monitor=10000 on v03-b * Resource action: vd01-d.cdev.ttc.prague.cz.vds-ok.com-vm monitor=10000 on v03-a Revised cluster status: Online: [ mgmt01 v03-a v03-b ] - stonith-v02-a (stonith:fence_ipmilan): Stopped - stonith-v02-b (stonith:fence_ipmilan): Stopped - stonith-v02-c (stonith:fence_ipmilan): Stopped - stonith-v02-d (stonith:fence_ipmilan): Stopped + stonith-v02-a (stonith:fence_ipmilan): (target-role:Stopped) Stopped + stonith-v02-b (stonith:fence_ipmilan): (target-role:Stopped) Stopped + stonith-v02-c (stonith:fence_ipmilan): (target-role:Stopped) Stopped + stonith-v02-d (stonith:fence_ipmilan): (target-role:Stopped) Stopped stonith-mgmt01 (stonith:fence_xvm): Started v03-b stonith-mgmt02 (stonith:meatware): Started mgmt01 - stonith-v03-c (stonith:fence_ipmilan): Stopped + stonith-v03-c (stonith:fence_ipmilan): (target-role:Stopped) Stopped stonith-v03-a (stonith:fence_ipmilan): Started v03-b stonith-v03-b (stonith:fence_ipmilan): Started v03-a - stonith-v03-d (stonith:fence_ipmilan): Stopped + stonith-v03-d (stonith:fence_ipmilan): (target-role:Stopped) Stopped Clone Set: cl-clvmd [clvmd] Started: [ mgmt01 v03-a v03-b ] Clone Set: cl-dlm [dlm] Started: [ mgmt01 v03-a v03-b ] Clone Set: cl-iscsid [iscsid] Started: [ mgmt01 v03-a v03-b ] Clone Set: cl-libvirtd [libvirtd] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] Clone Set: cl-multipathd [multipathd] Started: [ mgmt01 v03-a v03-b ] Clone Set: cl-node-params [node-params] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] Clone Set: cl-vlan1-if [vlan1-if] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] Clone Set: cl-vlan101-if [vlan101-if] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] Clone Set: cl-vlan102-if [vlan102-if] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] Clone Set: cl-vlan103-if [vlan103-if] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] Clone Set: cl-vlan104-if [vlan104-if] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] Clone Set: cl-vlan3-if [vlan3-if] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] Clone Set: cl-vlan4-if [vlan4-if] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] Clone Set: cl-vlan5-if [vlan5-if] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] Clone Set: cl-vlan900-if [vlan900-if] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] Clone Set: cl-vlan909-if [vlan909-if] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] Clone Set: cl-libvirt-images-fs [libvirt-images-fs] Started: [ mgmt01 v03-a v03-b ] Clone Set: cl-libvirt-install-fs [libvirt-install-fs] Started: [ mgmt01 v03-a v03-b ] Clone Set: cl-vds-ok-pool-0-iscsi [vds-ok-pool-0-iscsi] Started: [ mgmt01 v03-a v03-b ] Clone Set: cl-vds-ok-pool-0-vg [vds-ok-pool-0-vg] Started: [ mgmt01 v03-a v03-b ] Clone Set: cl-vds-ok-pool-1-iscsi [vds-ok-pool-1-iscsi] Started: [ mgmt01 v03-a v03-b ] Clone Set: cl-vds-ok-pool-1-vg [vds-ok-pool-1-vg] Started: [ mgmt01 v03-a v03-b ] Clone Set: cl-libvirt-images-pool [libvirt-images-pool] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] Clone Set: cl-vds-ok-pool-0-pool [vds-ok-pool-0-pool] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] Clone Set: cl-vds-ok-pool-1-pool [vds-ok-pool-1-pool] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] - git.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped + git.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped vd01-a.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Started v03-a vd01-b.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Started v03-a vd01-c.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Started v03-b vd01-d.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Started v03-a - vd02-a.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vd02-b.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vd02-c.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vd02-d.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vd03-a.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vd03-b.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vd03-c.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vd03-d.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vd04-a.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vd04-b.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vd04-c.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vd04-d.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped + vd02-a.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vd02-b.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vd02-c.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vd02-d.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vd03-a.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vd03-b.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vd03-c.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vd03-d.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vd04-a.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vd04-b.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vd04-c.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vd04-d.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped f13-x64-devel.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Started v03-b - eu2.ca-pages.com-vm (ocf::vds-ok:VirtualDomain): Stopped - zakaz.transferrus.ru-vm (ocf::vds-ok:VirtualDomain): Stopped + eu2.ca-pages.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + zakaz.transferrus.ru-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped Clone Set: cl-vlan200-if [vlan200-if] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] lenny-x32-devel-vm (ocf::vds-ok:VirtualDomain): Started v03-a - dist.express-consult.org-vm (ocf::vds-ok:VirtualDomain): Stopped - eu1.ca-pages.com-vm (ocf::vds-ok:VirtualDomain): Stopped - gotin-bbb-vm (ocf::vds-ok:VirtualDomain): Stopped - maxb-c55-vm (ocf::vds-ok:VirtualDomain): Stopped - metae.ru-vm (ocf::vds-ok:VirtualDomain): Stopped - rodovoepomestie.ru-vm (ocf::vds-ok:VirtualDomain): Stopped - ubuntu9.10-gotin-vm (ocf::vds-ok:VirtualDomain): Stopped + dist.express-consult.org-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + eu1.ca-pages.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + gotin-bbb-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + maxb-c55-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + metae.ru-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + rodovoepomestie.ru-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + ubuntu9.10-gotin-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped c5-x64-devel.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Started v03-b Clone Set: cl-mcast-test-net [mcast-test-net] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] - dist.fly-uni.org-vm (ocf::vds-ok:VirtualDomain): Stopped + dist.fly-uni.org-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped ktstudio.net-vm (ocf::vds-ok:VirtualDomain): Started v03-a cloudsrv.credo-dialogue.com-vm (ocf::vds-ok:VirtualDomain): Started v03-b c6-x64-devel.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Started v03-a lustre01-right.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Started v03-b lustre02-right.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Started v03-a lustre03-left.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Started v03-b lustre03-right.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Started v03-a lustre04-left.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Started v03-b lustre04-right.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Started v03-a Clone Set: cl-mcast-anbriz-net [mcast-anbriz-net] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] gw.anbriz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Started v03-b license.anbriz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Started v03-a - terminal.anbriz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped + terminal.anbriz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped lustre01-left.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Started v03-a lustre02-left.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Started v03-b test-01.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Started v03-a Clone Set: cl-libvirt-qpid [libvirt-qpid] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] - gw.gleb.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - gw.gotin.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped + gw.gleb.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + gw.gotin.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped terminal0.anbriz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Started v03-b Clone Set: cl-mcast-gleb-net [mcast-gleb-net] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] diff --git a/pengine/test10/master-depend.summary b/pengine/test10/master-depend.summary index f802b4ee19..2a719c90c0 100644 --- a/pengine/test10/master-depend.summary +++ b/pengine/test10/master-depend.summary @@ -1,59 +1,59 @@ Current cluster status: Online: [ vbox4 ] OFFLINE: [ vbox3 ] Master/Slave Set: drbd [drbd0] Stopped: [ vbox3 vbox4 ] Clone Set: cman_clone [cman] Stopped: [ vbox3 vbox4 ] Clone Set: clvmd_clone [clvmd] Stopped: [ vbox3 vbox4 ] vmnci36 (ocf::heartbeat:vm): Stopped - vmnci37 (ocf::heartbeat:vm): Stopped - vmnci38 (ocf::heartbeat:vm): Stopped - vmnci55 (ocf::heartbeat:vm): Stopped + vmnci37 (ocf::heartbeat:vm): (target-role:stopped) Stopped + vmnci38 (ocf::heartbeat:vm): (target-role:stopped) Stopped + vmnci55 (ocf::heartbeat:vm): (target-role:stopped) Stopped Transition Summary: * Start drbd0:0 (vbox4) * Start cman:0 (vbox4) Executing cluster transition: * Resource action: drbd0:0 monitor on vbox4 * Pseudo action: drbd_pre_notify_start_0 * Resource action: cman:0 monitor on vbox4 * Pseudo action: cman_clone_start_0 * Resource action: clvmd:0 monitor on vbox4 * Resource action: vmnci36 monitor on vbox4 * Resource action: vmnci37 monitor on vbox4 * Resource action: vmnci38 monitor on vbox4 * Resource action: vmnci55 monitor on vbox4 * Pseudo action: probe_complete * Pseudo action: drbd_confirmed-pre_notify_start_0 * Pseudo action: drbd_start_0 * Resource action: cman:0 start on vbox4 * Pseudo action: cman_clone_running_0 * Resource action: drbd0:0 start on vbox4 * Pseudo action: drbd_running_0 * Pseudo action: drbd_post_notify_running_0 * Resource action: drbd0:0 notify on vbox4 * Pseudo action: drbd_confirmed-post_notify_running_0 * Resource action: drbd0:0 monitor=60000 on vbox4 Revised cluster status: Online: [ vbox4 ] OFFLINE: [ vbox3 ] Master/Slave Set: drbd [drbd0] Slaves: [ vbox4 ] Stopped: [ vbox3 ] Clone Set: cman_clone [cman] Started: [ vbox4 ] Stopped: [ vbox3 ] Clone Set: clvmd_clone [clvmd] Stopped: [ vbox3 vbox4 ] vmnci36 (ocf::heartbeat:vm): Stopped - vmnci37 (ocf::heartbeat:vm): Stopped - vmnci38 (ocf::heartbeat:vm): Stopped - vmnci55 (ocf::heartbeat:vm): Stopped + vmnci37 (ocf::heartbeat:vm): (target-role:stopped) Stopped + vmnci38 (ocf::heartbeat:vm): (target-role:stopped) Stopped + vmnci55 (ocf::heartbeat:vm): (target-role:stopped) Stopped diff --git a/pengine/test10/master-probed-score.summary b/pengine/test10/master-probed-score.summary index a634efd3b2..b03d8425b3 100644 --- a/pengine/test10/master-probed-score.summary +++ b/pengine/test10/master-probed-score.summary @@ -1,328 +1,328 @@ Current cluster status: Online: [ hypatia-corosync.nevis.columbia.edu orestes-corosync.nevis.columbia.edu ] Master/Slave Set: AdminClone [AdminDrbd] Stopped: [ hypatia-corosync.nevis.columbia.edu orestes-corosync.nevis.columbia.edu ] CronAmbientTemperature (ocf::heartbeat:symlink): Stopped StonithHypatia (stonith:fence_nut): Stopped StonithOrestes (stonith:fence_nut): Stopped Resource Group: DhcpGroup SymlinkDhcpdConf (ocf::heartbeat:symlink): Stopped SymlinkSysconfigDhcpd (ocf::heartbeat:symlink): Stopped SymlinkDhcpdLeases (ocf::heartbeat:symlink): Stopped - Dhcpd (lsb:dhcpd): Stopped + Dhcpd (lsb:dhcpd): (target-role:stopped) Stopped DhcpIP (ocf::heartbeat:IPaddr2): Stopped Clone Set: CupsClone [CupsGroup] Stopped: [ hypatia-corosync.nevis.columbia.edu orestes-corosync.nevis.columbia.edu ] Clone Set: IPClone [IPGroup] (unique) Resource Group: IPGroup:0 ClusterIP:0 (ocf::heartbeat:IPaddr2): Stopped ClusterIPLocal:0 (ocf::heartbeat:IPaddr2): Stopped ClusterIPSandbox:0 (ocf::heartbeat:IPaddr2): Stopped Resource Group: IPGroup:1 ClusterIP:1 (ocf::heartbeat:IPaddr2): Stopped ClusterIPLocal:1 (ocf::heartbeat:IPaddr2): Stopped ClusterIPSandbox:1 (ocf::heartbeat:IPaddr2): Stopped Clone Set: LibvirtdClone [LibvirtdGroup] Stopped: [ hypatia-corosync.nevis.columbia.edu orestes-corosync.nevis.columbia.edu ] Clone Set: TftpClone [TftpGroup] Stopped: [ hypatia-corosync.nevis.columbia.edu orestes-corosync.nevis.columbia.edu ] Clone Set: ExportsClone [ExportsGroup] Stopped: [ hypatia-corosync.nevis.columbia.edu orestes-corosync.nevis.columbia.edu ] Clone Set: FilesystemClone [FilesystemGroup] Stopped: [ hypatia-corosync.nevis.columbia.edu orestes-corosync.nevis.columbia.edu ] KVM-guest (ocf::heartbeat:VirtualDomain): Stopped Proxy (ocf::heartbeat:VirtualDomain): Stopped Transition Summary: * Start AdminDrbd:0 (hypatia-corosync.nevis.columbia.edu) * Promote AdminDrbd:0 (Stopped -> Master hypatia-corosync.nevis.columbia.edu) * Start AdminDrbd:1 (orestes-corosync.nevis.columbia.edu) * Promote AdminDrbd:1 (Stopped -> Master orestes-corosync.nevis.columbia.edu) * Start CronAmbientTemperature (hypatia-corosync.nevis.columbia.edu) * Start StonithHypatia (orestes-corosync.nevis.columbia.edu) * Start StonithOrestes (hypatia-corosync.nevis.columbia.edu) * Start SymlinkDhcpdConf (orestes-corosync.nevis.columbia.edu) * Start SymlinkSysconfigDhcpd (orestes-corosync.nevis.columbia.edu) * Start SymlinkDhcpdLeases (orestes-corosync.nevis.columbia.edu) * Start SymlinkUsrShareCups:0 (hypatia-corosync.nevis.columbia.edu) * Start SymlinkCupsdConf:0 (hypatia-corosync.nevis.columbia.edu) * Start Cups:0 (hypatia-corosync.nevis.columbia.edu) * Start SymlinkUsrShareCups:1 (orestes-corosync.nevis.columbia.edu) * Start SymlinkCupsdConf:1 (orestes-corosync.nevis.columbia.edu) * Start Cups:1 (orestes-corosync.nevis.columbia.edu) * Start ClusterIP:0 (hypatia-corosync.nevis.columbia.edu) * Start ClusterIPLocal:0 (hypatia-corosync.nevis.columbia.edu) * Start ClusterIPSandbox:0 (hypatia-corosync.nevis.columbia.edu) * Start ClusterIP:1 (orestes-corosync.nevis.columbia.edu) * Start ClusterIPLocal:1 (orestes-corosync.nevis.columbia.edu) * Start ClusterIPSandbox:1 (orestes-corosync.nevis.columbia.edu) * Start SymlinkEtcLibvirt:0 (hypatia-corosync.nevis.columbia.edu) * Start Libvirtd:0 (hypatia-corosync.nevis.columbia.edu) * Start SymlinkEtcLibvirt:1 (orestes-corosync.nevis.columbia.edu) * Start Libvirtd:1 (orestes-corosync.nevis.columbia.edu) * Start SymlinkTftp:0 (hypatia-corosync.nevis.columbia.edu) * Start Xinetd:0 (hypatia-corosync.nevis.columbia.edu) * Start SymlinkTftp:1 (orestes-corosync.nevis.columbia.edu) * Start Xinetd:1 (orestes-corosync.nevis.columbia.edu) * Start ExportMail:0 (hypatia-corosync.nevis.columbia.edu) * Start ExportMailInbox:0 (hypatia-corosync.nevis.columbia.edu) * Start ExportMailFolders:0 (hypatia-corosync.nevis.columbia.edu) * Start ExportMailForward:0 (hypatia-corosync.nevis.columbia.edu) * Start ExportMailProcmailrc:0 (hypatia-corosync.nevis.columbia.edu) * Start ExportUsrNevis:0 (hypatia-corosync.nevis.columbia.edu) * Start ExportUsrNevisOffsite:0 (hypatia-corosync.nevis.columbia.edu) * Start ExportWWW:0 (hypatia-corosync.nevis.columbia.edu) * Start ExportMail:1 (orestes-corosync.nevis.columbia.edu) * Start ExportMailInbox:1 (orestes-corosync.nevis.columbia.edu) * Start ExportMailFolders:1 (orestes-corosync.nevis.columbia.edu) * Start ExportMailForward:1 (orestes-corosync.nevis.columbia.edu) * Start ExportMailProcmailrc:1 (orestes-corosync.nevis.columbia.edu) * Start ExportUsrNevis:1 (orestes-corosync.nevis.columbia.edu) * Start ExportUsrNevisOffsite:1 (orestes-corosync.nevis.columbia.edu) * Start ExportWWW:1 (orestes-corosync.nevis.columbia.edu) * Start AdminLvm:0 (hypatia-corosync.nevis.columbia.edu) * Start FSUsrNevis:0 (hypatia-corosync.nevis.columbia.edu) * Start FSVarNevis:0 (hypatia-corosync.nevis.columbia.edu) * Start FSVirtualMachines:0 (hypatia-corosync.nevis.columbia.edu) * Start FSMail:0 (hypatia-corosync.nevis.columbia.edu) * Start FSWork:0 (hypatia-corosync.nevis.columbia.edu) * Start AdminLvm:1 (orestes-corosync.nevis.columbia.edu) * Start FSUsrNevis:1 (orestes-corosync.nevis.columbia.edu) * Start FSVarNevis:1 (orestes-corosync.nevis.columbia.edu) * Start FSVirtualMachines:1 (orestes-corosync.nevis.columbia.edu) * Start FSMail:1 (orestes-corosync.nevis.columbia.edu) * Start FSWork:1 (orestes-corosync.nevis.columbia.edu) * Start KVM-guest (hypatia-corosync.nevis.columbia.edu) * Start Proxy (orestes-corosync.nevis.columbia.edu) Executing cluster transition: * Pseudo action: AdminClone_pre_notify_start_0 * Resource action: StonithHypatia start on orestes-corosync.nevis.columbia.edu * Resource action: StonithOrestes start on hypatia-corosync.nevis.columbia.edu * Resource action: SymlinkEtcLibvirt:0 monitor on hypatia-corosync.nevis.columbia.edu * Resource action: Libvirtd:0 monitor on orestes-corosync.nevis.columbia.edu * Resource action: Libvirtd:0 monitor on hypatia-corosync.nevis.columbia.edu * Resource action: SymlinkTftp:0 monitor on hypatia-corosync.nevis.columbia.edu * Resource action: Xinetd:0 monitor on hypatia-corosync.nevis.columbia.edu * Resource action: SymlinkTftp:1 monitor on orestes-corosync.nevis.columbia.edu * Resource action: Xinetd:1 monitor on orestes-corosync.nevis.columbia.edu * Resource action: ExportMail:0 monitor on hypatia-corosync.nevis.columbia.edu * Resource action: ExportMailInbox:0 monitor on hypatia-corosync.nevis.columbia.edu * Resource action: ExportMailFolders:0 monitor on hypatia-corosync.nevis.columbia.edu * Resource action: ExportMailForward:0 monitor on hypatia-corosync.nevis.columbia.edu * Resource action: ExportMailProcmailrc:0 monitor on hypatia-corosync.nevis.columbia.edu * Resource action: ExportUsrNevis:0 monitor on hypatia-corosync.nevis.columbia.edu * Resource action: ExportUsrNevisOffsite:0 monitor on hypatia-corosync.nevis.columbia.edu * Resource action: ExportWWW:0 monitor on hypatia-corosync.nevis.columbia.edu * Resource action: ExportMail:1 monitor on orestes-corosync.nevis.columbia.edu * Resource action: ExportMailInbox:1 monitor on orestes-corosync.nevis.columbia.edu * Resource action: ExportMailFolders:1 monitor on orestes-corosync.nevis.columbia.edu * Resource action: ExportMailForward:1 monitor on orestes-corosync.nevis.columbia.edu * Resource action: ExportMailProcmailrc:1 monitor on orestes-corosync.nevis.columbia.edu * Resource action: ExportUsrNevis:1 monitor on orestes-corosync.nevis.columbia.edu * Resource action: ExportUsrNevisOffsite:1 monitor on orestes-corosync.nevis.columbia.edu * Resource action: ExportWWW:1 monitor on orestes-corosync.nevis.columbia.edu * Resource action: AdminLvm:0 monitor on hypatia-corosync.nevis.columbia.edu * Resource action: FSUsrNevis:0 monitor on hypatia-corosync.nevis.columbia.edu * Resource action: FSVarNevis:0 monitor on hypatia-corosync.nevis.columbia.edu * Resource action: FSVirtualMachines:0 monitor on hypatia-corosync.nevis.columbia.edu * Resource action: FSMail:0 monitor on hypatia-corosync.nevis.columbia.edu * Resource action: FSWork:0 monitor on hypatia-corosync.nevis.columbia.edu * Resource action: AdminLvm:1 monitor on orestes-corosync.nevis.columbia.edu * Resource action: FSUsrNevis:1 monitor on orestes-corosync.nevis.columbia.edu * Resource action: FSVarNevis:1 monitor on orestes-corosync.nevis.columbia.edu * Resource action: FSVirtualMachines:1 monitor on orestes-corosync.nevis.columbia.edu * Resource action: FSMail:1 monitor on orestes-corosync.nevis.columbia.edu * Resource action: FSWork:1 monitor on orestes-corosync.nevis.columbia.edu * Resource action: KVM-guest monitor on orestes-corosync.nevis.columbia.edu * Resource action: KVM-guest monitor on hypatia-corosync.nevis.columbia.edu * Resource action: Proxy monitor on orestes-corosync.nevis.columbia.edu * Resource action: Proxy monitor on hypatia-corosync.nevis.columbia.edu * Pseudo action: probe_complete * Pseudo action: AdminClone_confirmed-pre_notify_start_0 * Pseudo action: AdminClone_start_0 * Resource action: AdminDrbd:0 start on hypatia-corosync.nevis.columbia.edu * Resource action: AdminDrbd:1 start on orestes-corosync.nevis.columbia.edu * Pseudo action: AdminClone_running_0 * Pseudo action: AdminClone_post_notify_running_0 * Resource action: AdminDrbd:0 notify on hypatia-corosync.nevis.columbia.edu * Resource action: AdminDrbd:1 notify on orestes-corosync.nevis.columbia.edu * Pseudo action: AdminClone_confirmed-post_notify_running_0 * Pseudo action: AdminClone_pre_notify_promote_0 * Resource action: AdminDrbd:0 notify on hypatia-corosync.nevis.columbia.edu * Resource action: AdminDrbd:1 notify on orestes-corosync.nevis.columbia.edu * Pseudo action: AdminClone_confirmed-pre_notify_promote_0 * Pseudo action: AdminClone_promote_0 * Resource action: AdminDrbd:0 promote on hypatia-corosync.nevis.columbia.edu * Resource action: AdminDrbd:1 promote on orestes-corosync.nevis.columbia.edu * Pseudo action: AdminClone_promoted_0 * Pseudo action: AdminClone_post_notify_promoted_0 * Resource action: AdminDrbd:0 notify on hypatia-corosync.nevis.columbia.edu * Resource action: AdminDrbd:1 notify on orestes-corosync.nevis.columbia.edu * Pseudo action: AdminClone_confirmed-post_notify_promoted_0 * Pseudo action: FilesystemClone_start_0 * Resource action: AdminDrbd:0 monitor=59000 on hypatia-corosync.nevis.columbia.edu * Resource action: AdminDrbd:1 monitor=59000 on orestes-corosync.nevis.columbia.edu * Pseudo action: FilesystemGroup:0_start_0 * Resource action: AdminLvm:0 start on hypatia-corosync.nevis.columbia.edu * Resource action: FSUsrNevis:0 start on hypatia-corosync.nevis.columbia.edu * Resource action: FSVarNevis:0 start on hypatia-corosync.nevis.columbia.edu * Resource action: FSVirtualMachines:0 start on hypatia-corosync.nevis.columbia.edu * Resource action: FSMail:0 start on hypatia-corosync.nevis.columbia.edu * Resource action: FSWork:0 start on hypatia-corosync.nevis.columbia.edu * Pseudo action: FilesystemGroup:1_start_0 * Resource action: AdminLvm:1 start on orestes-corosync.nevis.columbia.edu * Resource action: FSUsrNevis:1 start on orestes-corosync.nevis.columbia.edu * Resource action: FSVarNevis:1 start on orestes-corosync.nevis.columbia.edu * Resource action: FSVirtualMachines:1 start on orestes-corosync.nevis.columbia.edu * Resource action: FSMail:1 start on orestes-corosync.nevis.columbia.edu * Resource action: FSWork:1 start on orestes-corosync.nevis.columbia.edu * Pseudo action: FilesystemGroup:0_running_0 * Resource action: AdminLvm:0 monitor=30000 on hypatia-corosync.nevis.columbia.edu * Resource action: FSUsrNevis:0 monitor=20000 on hypatia-corosync.nevis.columbia.edu * Resource action: FSVarNevis:0 monitor=20000 on hypatia-corosync.nevis.columbia.edu * Resource action: FSVirtualMachines:0 monitor=20000 on hypatia-corosync.nevis.columbia.edu * Resource action: FSMail:0 monitor=20000 on hypatia-corosync.nevis.columbia.edu * Resource action: FSWork:0 monitor=20000 on hypatia-corosync.nevis.columbia.edu * Pseudo action: FilesystemGroup:1_running_0 * Resource action: AdminLvm:1 monitor=30000 on orestes-corosync.nevis.columbia.edu * Resource action: FSUsrNevis:1 monitor=20000 on orestes-corosync.nevis.columbia.edu * Resource action: FSVarNevis:1 monitor=20000 on orestes-corosync.nevis.columbia.edu * Resource action: FSVirtualMachines:1 monitor=20000 on orestes-corosync.nevis.columbia.edu * Resource action: FSMail:1 monitor=20000 on orestes-corosync.nevis.columbia.edu * Resource action: FSWork:1 monitor=20000 on orestes-corosync.nevis.columbia.edu * Pseudo action: FilesystemClone_running_0 * Resource action: CronAmbientTemperature start on hypatia-corosync.nevis.columbia.edu * Pseudo action: DhcpGroup_start_0 * Resource action: SymlinkDhcpdConf start on orestes-corosync.nevis.columbia.edu * Resource action: SymlinkSysconfigDhcpd start on orestes-corosync.nevis.columbia.edu * Resource action: SymlinkDhcpdLeases start on orestes-corosync.nevis.columbia.edu * Pseudo action: CupsClone_start_0 * Pseudo action: IPClone_start_0 * Pseudo action: LibvirtdClone_start_0 * Pseudo action: TftpClone_start_0 * Pseudo action: ExportsClone_start_0 * Resource action: CronAmbientTemperature monitor=60000 on hypatia-corosync.nevis.columbia.edu * Resource action: SymlinkDhcpdConf monitor=60000 on orestes-corosync.nevis.columbia.edu * Resource action: SymlinkSysconfigDhcpd monitor=60000 on orestes-corosync.nevis.columbia.edu * Resource action: SymlinkDhcpdLeases monitor=60000 on orestes-corosync.nevis.columbia.edu * Pseudo action: CupsGroup:0_start_0 * Resource action: SymlinkUsrShareCups:0 start on hypatia-corosync.nevis.columbia.edu * Resource action: SymlinkCupsdConf:0 start on hypatia-corosync.nevis.columbia.edu * Resource action: Cups:0 start on hypatia-corosync.nevis.columbia.edu * Pseudo action: CupsGroup:1_start_0 * Resource action: SymlinkUsrShareCups:1 start on orestes-corosync.nevis.columbia.edu * Resource action: SymlinkCupsdConf:1 start on orestes-corosync.nevis.columbia.edu * Resource action: Cups:1 start on orestes-corosync.nevis.columbia.edu * Pseudo action: IPGroup:0_start_0 * Resource action: ClusterIP:0 start on hypatia-corosync.nevis.columbia.edu * Resource action: ClusterIPLocal:0 start on hypatia-corosync.nevis.columbia.edu * Resource action: ClusterIPSandbox:0 start on hypatia-corosync.nevis.columbia.edu * Pseudo action: IPGroup:1_start_0 * Resource action: ClusterIP:1 start on orestes-corosync.nevis.columbia.edu * Resource action: ClusterIPLocal:1 start on orestes-corosync.nevis.columbia.edu * Resource action: ClusterIPSandbox:1 start on orestes-corosync.nevis.columbia.edu * Pseudo action: LibvirtdGroup:0_start_0 * Resource action: SymlinkEtcLibvirt:0 start on hypatia-corosync.nevis.columbia.edu * Resource action: Libvirtd:0 start on hypatia-corosync.nevis.columbia.edu * Pseudo action: LibvirtdGroup:1_start_0 * Resource action: SymlinkEtcLibvirt:1 start on orestes-corosync.nevis.columbia.edu * Resource action: Libvirtd:1 start on orestes-corosync.nevis.columbia.edu * Pseudo action: TftpGroup:0_start_0 * Resource action: SymlinkTftp:0 start on hypatia-corosync.nevis.columbia.edu * Resource action: Xinetd:0 start on hypatia-corosync.nevis.columbia.edu * Pseudo action: TftpGroup:1_start_0 * Resource action: SymlinkTftp:1 start on orestes-corosync.nevis.columbia.edu * Resource action: Xinetd:1 start on orestes-corosync.nevis.columbia.edu * Pseudo action: ExportsGroup:0_start_0 * Resource action: ExportMail:0 start on hypatia-corosync.nevis.columbia.edu * Resource action: ExportMailInbox:0 start on hypatia-corosync.nevis.columbia.edu * Resource action: ExportMailFolders:0 start on hypatia-corosync.nevis.columbia.edu * Resource action: ExportMailForward:0 start on hypatia-corosync.nevis.columbia.edu * Resource action: ExportMailProcmailrc:0 start on hypatia-corosync.nevis.columbia.edu * Resource action: ExportUsrNevis:0 start on hypatia-corosync.nevis.columbia.edu * Resource action: ExportUsrNevisOffsite:0 start on hypatia-corosync.nevis.columbia.edu * Resource action: ExportWWW:0 start on hypatia-corosync.nevis.columbia.edu * Pseudo action: ExportsGroup:1_start_0 * Resource action: ExportMail:1 start on orestes-corosync.nevis.columbia.edu * Resource action: ExportMailInbox:1 start on orestes-corosync.nevis.columbia.edu * Resource action: ExportMailFolders:1 start on orestes-corosync.nevis.columbia.edu * Resource action: ExportMailForward:1 start on orestes-corosync.nevis.columbia.edu * Resource action: ExportMailProcmailrc:1 start on orestes-corosync.nevis.columbia.edu * Resource action: ExportUsrNevis:1 start on orestes-corosync.nevis.columbia.edu * Resource action: ExportUsrNevisOffsite:1 start on orestes-corosync.nevis.columbia.edu * Resource action: ExportWWW:1 start on orestes-corosync.nevis.columbia.edu * Pseudo action: CupsGroup:0_running_0 * Resource action: SymlinkUsrShareCups:0 monitor=60000 on hypatia-corosync.nevis.columbia.edu * Resource action: SymlinkCupsdConf:0 monitor=60000 on hypatia-corosync.nevis.columbia.edu * Resource action: Cups:0 monitor=30000 on hypatia-corosync.nevis.columbia.edu * Pseudo action: CupsGroup:1_running_0 * Resource action: SymlinkUsrShareCups:1 monitor=60000 on orestes-corosync.nevis.columbia.edu * Resource action: SymlinkCupsdConf:1 monitor=60000 on orestes-corosync.nevis.columbia.edu * Resource action: Cups:1 monitor=30000 on orestes-corosync.nevis.columbia.edu * Pseudo action: CupsClone_running_0 * Pseudo action: IPGroup:0_running_0 * Resource action: ClusterIP:0 monitor=30000 on hypatia-corosync.nevis.columbia.edu * Resource action: ClusterIPLocal:0 monitor=31000 on hypatia-corosync.nevis.columbia.edu * Resource action: ClusterIPSandbox:0 monitor=32000 on hypatia-corosync.nevis.columbia.edu * Pseudo action: IPGroup:1_running_0 * Resource action: ClusterIP:1 monitor=30000 on orestes-corosync.nevis.columbia.edu * Resource action: ClusterIPLocal:1 monitor=31000 on orestes-corosync.nevis.columbia.edu * Resource action: ClusterIPSandbox:1 monitor=32000 on orestes-corosync.nevis.columbia.edu * Pseudo action: IPClone_running_0 * Pseudo action: LibvirtdGroup:0_running_0 * Resource action: SymlinkEtcLibvirt:0 monitor=60000 on hypatia-corosync.nevis.columbia.edu * Resource action: Libvirtd:0 monitor=30000 on hypatia-corosync.nevis.columbia.edu * Pseudo action: LibvirtdGroup:1_running_0 * Resource action: SymlinkEtcLibvirt:1 monitor=60000 on orestes-corosync.nevis.columbia.edu * Resource action: Libvirtd:1 monitor=30000 on orestes-corosync.nevis.columbia.edu * Pseudo action: LibvirtdClone_running_0 * Pseudo action: TftpGroup:0_running_0 * Resource action: SymlinkTftp:0 monitor=60000 on hypatia-corosync.nevis.columbia.edu * Pseudo action: TftpGroup:1_running_0 * Resource action: SymlinkTftp:1 monitor=60000 on orestes-corosync.nevis.columbia.edu * Pseudo action: TftpClone_running_0 * Pseudo action: ExportsGroup:0_running_0 * Pseudo action: ExportsGroup:1_running_0 * Pseudo action: ExportsClone_running_0 * Resource action: KVM-guest start on hypatia-corosync.nevis.columbia.edu * Resource action: Proxy start on orestes-corosync.nevis.columbia.edu Revised cluster status: Online: [ hypatia-corosync.nevis.columbia.edu orestes-corosync.nevis.columbia.edu ] Master/Slave Set: AdminClone [AdminDrbd] Masters: [ hypatia-corosync.nevis.columbia.edu orestes-corosync.nevis.columbia.edu ] CronAmbientTemperature (ocf::heartbeat:symlink): Started hypatia-corosync.nevis.columbia.edu StonithHypatia (stonith:fence_nut): Started orestes-corosync.nevis.columbia.edu StonithOrestes (stonith:fence_nut): Started hypatia-corosync.nevis.columbia.edu Resource Group: DhcpGroup SymlinkDhcpdConf (ocf::heartbeat:symlink): Started orestes-corosync.nevis.columbia.edu SymlinkSysconfigDhcpd (ocf::heartbeat:symlink): Started orestes-corosync.nevis.columbia.edu SymlinkDhcpdLeases (ocf::heartbeat:symlink): Started orestes-corosync.nevis.columbia.edu - Dhcpd (lsb:dhcpd): Stopped + Dhcpd (lsb:dhcpd): (target-role:stopped) Stopped DhcpIP (ocf::heartbeat:IPaddr2): Stopped Clone Set: CupsClone [CupsGroup] Started: [ hypatia-corosync.nevis.columbia.edu orestes-corosync.nevis.columbia.edu ] Clone Set: IPClone [IPGroup] (unique) Resource Group: IPGroup:0 ClusterIP:0 (ocf::heartbeat:IPaddr2): Started hypatia-corosync.nevis.columbia.edu ClusterIPLocal:0 (ocf::heartbeat:IPaddr2): Started hypatia-corosync.nevis.columbia.edu ClusterIPSandbox:0 (ocf::heartbeat:IPaddr2): Started hypatia-corosync.nevis.columbia.edu Resource Group: IPGroup:1 ClusterIP:1 (ocf::heartbeat:IPaddr2): Started orestes-corosync.nevis.columbia.edu ClusterIPLocal:1 (ocf::heartbeat:IPaddr2): Started orestes-corosync.nevis.columbia.edu ClusterIPSandbox:1 (ocf::heartbeat:IPaddr2): Started orestes-corosync.nevis.columbia.edu Clone Set: LibvirtdClone [LibvirtdGroup] Started: [ hypatia-corosync.nevis.columbia.edu orestes-corosync.nevis.columbia.edu ] Clone Set: TftpClone [TftpGroup] Started: [ hypatia-corosync.nevis.columbia.edu orestes-corosync.nevis.columbia.edu ] Clone Set: ExportsClone [ExportsGroup] Started: [ hypatia-corosync.nevis.columbia.edu orestes-corosync.nevis.columbia.edu ] Clone Set: FilesystemClone [FilesystemGroup] Started: [ hypatia-corosync.nevis.columbia.edu orestes-corosync.nevis.columbia.edu ] KVM-guest (ocf::heartbeat:VirtualDomain): Started hypatia-corosync.nevis.columbia.edu Proxy (ocf::heartbeat:VirtualDomain): Started orestes-corosync.nevis.columbia.edu diff --git a/pengine/test10/master-promotion-constraint.summary b/pengine/test10/master-promotion-constraint.summary index de479521a3..68b237cd88 100644 --- a/pengine/test10/master-promotion-constraint.summary +++ b/pengine/test10/master-promotion-constraint.summary @@ -1,32 +1,32 @@ Current cluster status: Online: [ hex-13 hex-14 ] fencing-sbd (stonith:external/sbd): Started hex-13 Resource Group: g0 - d0 (ocf::pacemaker:Dummy): Stopped - d1 (ocf::pacemaker:Dummy): Stopped + d0 (ocf::pacemaker:Dummy): (target-role:Stopped) Stopped + d1 (ocf::pacemaker:Dummy): (target-role:Stopped) Stopped Master/Slave Set: ms0 [s0] Masters: [ hex-14 ] Slaves: [ hex-13 ] Transition Summary: * Demote s0:0 (Master -> Slave hex-14) Executing cluster transition: * Resource action: s0:1 cancel=20000 on hex-14 * Pseudo action: ms0_demote_0 * Resource action: s0:1 demote on hex-14 * Pseudo action: ms0_demoted_0 * Resource action: s0:1 monitor=21000 on hex-14 Revised cluster status: Online: [ hex-13 hex-14 ] fencing-sbd (stonith:external/sbd): Started hex-13 Resource Group: g0 - d0 (ocf::pacemaker:Dummy): Stopped - d1 (ocf::pacemaker:Dummy): Stopped + d0 (ocf::pacemaker:Dummy): (target-role:Stopped) Stopped + d1 (ocf::pacemaker:Dummy): (target-role:Stopped) Stopped Master/Slave Set: ms0 [s0] Slaves: [ hex-13 hex-14 ] diff --git a/pengine/test10/novell-251689.summary b/pengine/test10/novell-251689.summary index 3c207e39e3..47ad222f83 100644 --- a/pengine/test10/novell-251689.summary +++ b/pengine/test10/novell-251689.summary @@ -1,38 +1,38 @@ Current cluster status: Online: [ node1 node2 ] Clone Set: stonithcloneset [stonithclone] Started: [ node1 node2 ] Clone Set: evmsdcloneset [evmsdclone] Started: [ node1 node2 ] Clone Set: evmscloneset [evmsclone] Started: [ node1 node2 ] Clone Set: imagestorecloneset [imagestoreclone] Started: [ node1 node2 ] Clone Set: configstorecloneset [configstoreclone] Started: [ node1 node2 ] - sles10 (ocf::heartbeat:Xen): Started node2 + sles10 (ocf::heartbeat:Xen): (target-role:stopped) Started node2 Transition Summary: * Stop sles10 (node2) Executing cluster transition: * Resource action: sles10 stop on node2 * Pseudo action: all_stopped Revised cluster status: Online: [ node1 node2 ] Clone Set: stonithcloneset [stonithclone] Started: [ node1 node2 ] Clone Set: evmsdcloneset [evmsdclone] Started: [ node1 node2 ] Clone Set: evmscloneset [evmsclone] Started: [ node1 node2 ] Clone Set: imagestorecloneset [imagestoreclone] Started: [ node1 node2 ] Clone Set: configstorecloneset [configstoreclone] Started: [ node1 node2 ] - sles10 (ocf::heartbeat:Xen): Stopped + sles10 (ocf::heartbeat:Xen): (target-role:stopped) Stopped diff --git a/pengine/test10/one-or-more-1.summary b/pengine/test10/one-or-more-1.summary index 56ffcab537..edac5d0d8a 100644 --- a/pengine/test10/one-or-more-1.summary +++ b/pengine/test10/one-or-more-1.summary @@ -1,31 +1,31 @@ Current cluster status: Online: [ fc16-builder ] OFFLINE: [ fc16-builder2 ] - A (ocf::pacemaker:Dummy): Stopped + A (ocf::pacemaker:Dummy): (target-role:Stopped) Stopped B (ocf::pacemaker:Dummy): Stopped C (ocf::pacemaker:Dummy): Stopped D (ocf::pacemaker:Dummy): Stopped Transition Summary: * Start B (fc16-builder - blocked) * Start C (fc16-builder - blocked) * Start D (fc16-builder - blocked) Executing cluster transition: * Resource action: A monitor on fc16-builder * Resource action: B monitor on fc16-builder * Resource action: C monitor on fc16-builder * Resource action: D monitor on fc16-builder * Pseudo action: probe_complete Revised cluster status: Online: [ fc16-builder ] OFFLINE: [ fc16-builder2 ] - A (ocf::pacemaker:Dummy): Stopped + A (ocf::pacemaker:Dummy): (target-role:Stopped) Stopped B (ocf::pacemaker:Dummy): Stopped C (ocf::pacemaker:Dummy): Stopped D (ocf::pacemaker:Dummy): Stopped diff --git a/pengine/test10/one-or-more-2.summary b/pengine/test10/one-or-more-2.summary index 9f3a4f1d25..689106bfad 100644 --- a/pengine/test10/one-or-more-2.summary +++ b/pengine/test10/one-or-more-2.summary @@ -1,35 +1,35 @@ Current cluster status: Online: [ fc16-builder ] OFFLINE: [ fc16-builder2 ] A (ocf::pacemaker:Dummy): Stopped - B (ocf::pacemaker:Dummy): Stopped + B (ocf::pacemaker:Dummy): (target-role:Stopped) Stopped C (ocf::pacemaker:Dummy): Stopped D (ocf::pacemaker:Dummy): Stopped Transition Summary: * Start A (fc16-builder) * Start C (fc16-builder) * Start D (fc16-builder) Executing cluster transition: * Resource action: A monitor on fc16-builder * Resource action: B monitor on fc16-builder * Resource action: C monitor on fc16-builder * Resource action: D monitor on fc16-builder * Pseudo action: probe_complete * Resource action: A start on fc16-builder * Resource action: C start on fc16-builder * Pseudo action: one-or-more:require-all-set-1 * Resource action: D start on fc16-builder Revised cluster status: Online: [ fc16-builder ] OFFLINE: [ fc16-builder2 ] A (ocf::pacemaker:Dummy): Started fc16-builder - B (ocf::pacemaker:Dummy): Stopped + B (ocf::pacemaker:Dummy): (target-role:Stopped) Stopped C (ocf::pacemaker:Dummy): Started fc16-builder D (ocf::pacemaker:Dummy): Started fc16-builder diff --git a/pengine/test10/one-or-more-3.summary b/pengine/test10/one-or-more-3.summary index 3ae8ecaa77..2c9982bc56 100644 --- a/pengine/test10/one-or-more-3.summary +++ b/pengine/test10/one-or-more-3.summary @@ -1,31 +1,31 @@ Current cluster status: Online: [ fc16-builder ] OFFLINE: [ fc16-builder2 ] A (ocf::pacemaker:Dummy): Stopped - B (ocf::pacemaker:Dummy): Stopped - C (ocf::pacemaker:Dummy): Stopped + B (ocf::pacemaker:Dummy): (target-role:Stopped) Stopped + C (ocf::pacemaker:Dummy): (target-role:Stopped) Stopped D (ocf::pacemaker:Dummy): Stopped Transition Summary: * Start A (fc16-builder) * Start D (fc16-builder - blocked) Executing cluster transition: * Resource action: A monitor on fc16-builder * Resource action: B monitor on fc16-builder * Resource action: C monitor on fc16-builder * Resource action: D monitor on fc16-builder * Pseudo action: probe_complete * Resource action: A start on fc16-builder Revised cluster status: Online: [ fc16-builder ] OFFLINE: [ fc16-builder2 ] A (ocf::pacemaker:Dummy): Started fc16-builder - B (ocf::pacemaker:Dummy): Stopped - C (ocf::pacemaker:Dummy): Stopped + B (ocf::pacemaker:Dummy): (target-role:Stopped) Stopped + C (ocf::pacemaker:Dummy): (target-role:Stopped) Stopped D (ocf::pacemaker:Dummy): Stopped diff --git a/pengine/test10/one-or-more-4.summary b/pengine/test10/one-or-more-4.summary index f5a574555f..8bc18c4fb4 100644 --- a/pengine/test10/one-or-more-4.summary +++ b/pengine/test10/one-or-more-4.summary @@ -1,35 +1,35 @@ Current cluster status: Online: [ fc16-builder ] OFFLINE: [ fc16-builder2 ] A (ocf::pacemaker:Dummy): Stopped B (ocf::pacemaker:Dummy): Stopped C (ocf::pacemaker:Dummy): Stopped - D (ocf::pacemaker:Dummy): Stopped + D (ocf::pacemaker:Dummy): (target-role:Stopped) Stopped Transition Summary: * Start A (fc16-builder) * Start B (fc16-builder) * Start C (fc16-builder) Executing cluster transition: * Resource action: A monitor on fc16-builder * Resource action: B monitor on fc16-builder * Resource action: C monitor on fc16-builder * Resource action: D monitor on fc16-builder * Pseudo action: probe_complete * Resource action: A start on fc16-builder * Resource action: B start on fc16-builder * Resource action: C start on fc16-builder * Pseudo action: one-or-more:require-all-set-1 Revised cluster status: Online: [ fc16-builder ] OFFLINE: [ fc16-builder2 ] A (ocf::pacemaker:Dummy): Started fc16-builder B (ocf::pacemaker:Dummy): Started fc16-builder C (ocf::pacemaker:Dummy): Started fc16-builder - D (ocf::pacemaker:Dummy): Stopped + D (ocf::pacemaker:Dummy): (target-role:Stopped) Stopped diff --git a/pengine/test10/one-or-more-5.summary b/pengine/test10/one-or-more-5.summary index 48569ab5ed..cecb1b2b40 100644 --- a/pengine/test10/one-or-more-5.summary +++ b/pengine/test10/one-or-more-5.summary @@ -1,44 +1,44 @@ Current cluster status: Online: [ fc16-builder ] OFFLINE: [ fc16-builder2 ] A (ocf::pacemaker:Dummy): Stopped B (ocf::pacemaker:Dummy): Stopped - C (ocf::pacemaker:Dummy): Stopped - D (ocf::pacemaker:Dummy): Stopped + C (ocf::pacemaker:Dummy): (target-role:Stopped) Stopped + D (ocf::pacemaker:Dummy): (target-role:Stopped) Stopped E (ocf::pacemaker:Dummy): Stopped F (ocf::pacemaker:Dummy): Stopped Transition Summary: * Start A (fc16-builder) * Start B (fc16-builder) * Start E (fc16-builder) * Start F (fc16-builder) Executing cluster transition: * Resource action: A monitor on fc16-builder * Resource action: B monitor on fc16-builder * Resource action: C monitor on fc16-builder * Resource action: D monitor on fc16-builder * Resource action: E monitor on fc16-builder * Resource action: F monitor on fc16-builder * Pseudo action: probe_complete * Resource action: B start on fc16-builder * Pseudo action: one-or-more:require-all-set-1 * Resource action: A start on fc16-builder * Resource action: E start on fc16-builder * Pseudo action: one-or-more:require-all-set-3 * Resource action: F start on fc16-builder Revised cluster status: Online: [ fc16-builder ] OFFLINE: [ fc16-builder2 ] A (ocf::pacemaker:Dummy): Started fc16-builder B (ocf::pacemaker:Dummy): Started fc16-builder - C (ocf::pacemaker:Dummy): Stopped - D (ocf::pacemaker:Dummy): Stopped + C (ocf::pacemaker:Dummy): (target-role:Stopped) Stopped + D (ocf::pacemaker:Dummy): (target-role:Stopped) Stopped E (ocf::pacemaker:Dummy): Started fc16-builder F (ocf::pacemaker:Dummy): Started fc16-builder diff --git a/pengine/test10/one-or-more-6.summary b/pengine/test10/one-or-more-6.summary index e1fd0f6f8b..dfdc8c0af2 100644 --- a/pengine/test10/one-or-more-6.summary +++ b/pengine/test10/one-or-more-6.summary @@ -1,24 +1,24 @@ Current cluster status: Online: [ fc16-builder ] OFFLINE: [ fc16-builder2 ] A (ocf::pacemaker:Dummy): Started fc16-builder - B (ocf::pacemaker:Dummy): Started fc16-builder + B (ocf::pacemaker:Dummy): (target-role:Stopped) Started fc16-builder C (ocf::pacemaker:Dummy): Started fc16-builder Transition Summary: * Stop B (fc16-builder) Executing cluster transition: * Resource action: B stop on fc16-builder * Pseudo action: all_stopped Revised cluster status: Online: [ fc16-builder ] OFFLINE: [ fc16-builder2 ] A (ocf::pacemaker:Dummy): Started fc16-builder - B (ocf::pacemaker:Dummy): Stopped + B (ocf::pacemaker:Dummy): (target-role:Stopped) Stopped C (ocf::pacemaker:Dummy): Started fc16-builder diff --git a/pengine/test10/one-or-more-7.summary b/pengine/test10/one-or-more-7.summary index 92c68cd1c3..b980cc1f88 100644 --- a/pengine/test10/one-or-more-7.summary +++ b/pengine/test10/one-or-more-7.summary @@ -1,24 +1,24 @@ Current cluster status: Online: [ fc16-builder ] OFFLINE: [ fc16-builder2 ] A (ocf::pacemaker:Dummy): Started fc16-builder B (ocf::pacemaker:Dummy): Started fc16-builder - C (ocf::pacemaker:Dummy): Started fc16-builder + C (ocf::pacemaker:Dummy): (target-role:Stopped) Started fc16-builder Transition Summary: * Stop C (fc16-builder) Executing cluster transition: * Resource action: C stop on fc16-builder * Pseudo action: all_stopped Revised cluster status: Online: [ fc16-builder ] OFFLINE: [ fc16-builder2 ] A (ocf::pacemaker:Dummy): Started fc16-builder B (ocf::pacemaker:Dummy): Started fc16-builder - C (ocf::pacemaker:Dummy): Stopped + C (ocf::pacemaker:Dummy): (target-role:Stopped) Stopped diff --git a/pengine/test10/order_constraint_stops_master.summary b/pengine/test10/order_constraint_stops_master.summary index 80ebe5e2c9..8b5d7922aa 100644 --- a/pengine/test10/order_constraint_stops_master.summary +++ b/pengine/test10/order_constraint_stops_master.summary @@ -1,41 +1,41 @@ Current cluster status: Online: [ fc16-builder fc16-builder2 ] Master/Slave Set: MASTER_RSC_A [NATIVE_RSC_A] Masters: [ fc16-builder ] - NATIVE_RSC_B (ocf::pacemaker:Dummy): Started fc16-builder2 + NATIVE_RSC_B (ocf::pacemaker:Dummy): (target-role:Stopped) Started fc16-builder2 Transition Summary: * Stop NATIVE_RSC_A:0 (Master fc16-builder) * Stop NATIVE_RSC_B (fc16-builder2) Executing cluster transition: * Pseudo action: MASTER_RSC_A_pre_notify_demote_0 * Resource action: NATIVE_RSC_A:0 notify on fc16-builder * Pseudo action: MASTER_RSC_A_confirmed-pre_notify_demote_0 * Pseudo action: MASTER_RSC_A_demote_0 * Resource action: NATIVE_RSC_A:0 demote on fc16-builder * Pseudo action: MASTER_RSC_A_demoted_0 * Pseudo action: MASTER_RSC_A_post_notify_demoted_0 * Resource action: NATIVE_RSC_A:0 notify on fc16-builder * Pseudo action: MASTER_RSC_A_confirmed-post_notify_demoted_0 * Pseudo action: MASTER_RSC_A_pre_notify_stop_0 * Resource action: NATIVE_RSC_A:0 notify on fc16-builder * Pseudo action: MASTER_RSC_A_confirmed-pre_notify_stop_0 * Pseudo action: MASTER_RSC_A_stop_0 * Resource action: NATIVE_RSC_A:0 stop on fc16-builder * Resource action: NATIVE_RSC_A:0 delete on fc16-builder2 * Pseudo action: MASTER_RSC_A_stopped_0 * Pseudo action: MASTER_RSC_A_post_notify_stopped_0 * Pseudo action: MASTER_RSC_A_confirmed-post_notify_stopped_0 * Resource action: NATIVE_RSC_B stop on fc16-builder2 * Pseudo action: all_stopped Revised cluster status: Online: [ fc16-builder fc16-builder2 ] Master/Slave Set: MASTER_RSC_A [NATIVE_RSC_A] Stopped: [ fc16-builder fc16-builder2 ] - NATIVE_RSC_B (ocf::pacemaker:Dummy): Stopped + NATIVE_RSC_B (ocf::pacemaker:Dummy): (target-role:Stopped) Stopped diff --git a/pengine/test10/order_constraint_stops_slave.summary b/pengine/test10/order_constraint_stops_slave.summary index a99ab758c9..dac04d1652 100644 --- a/pengine/test10/order_constraint_stops_slave.summary +++ b/pengine/test10/order_constraint_stops_slave.summary @@ -1,33 +1,33 @@ Current cluster status: Online: [ fc16-builder ] OFFLINE: [ fc16-builder2 ] Master/Slave Set: MASTER_RSC_A [NATIVE_RSC_A] Slaves: [ fc16-builder ] - NATIVE_RSC_B (ocf::pacemaker:Dummy): Started fc16-builder + NATIVE_RSC_B (ocf::pacemaker:Dummy): (target-role:Stopped) Started fc16-builder Transition Summary: * Stop NATIVE_RSC_A:0 (Slave fc16-builder) * Stop NATIVE_RSC_B (fc16-builder) Executing cluster transition: * Pseudo action: MASTER_RSC_A_pre_notify_stop_0 * Resource action: NATIVE_RSC_A:0 notify on fc16-builder * Pseudo action: MASTER_RSC_A_confirmed-pre_notify_stop_0 * Pseudo action: MASTER_RSC_A_stop_0 * Resource action: NATIVE_RSC_A:0 stop on fc16-builder * Pseudo action: MASTER_RSC_A_stopped_0 * Pseudo action: MASTER_RSC_A_post_notify_stopped_0 * Pseudo action: MASTER_RSC_A_confirmed-post_notify_stopped_0 * Resource action: NATIVE_RSC_B stop on fc16-builder * Pseudo action: all_stopped Revised cluster status: Online: [ fc16-builder ] OFFLINE: [ fc16-builder2 ] Master/Slave Set: MASTER_RSC_A [NATIVE_RSC_A] Stopped: [ fc16-builder fc16-builder2 ] - NATIVE_RSC_B (ocf::pacemaker:Dummy): Stopped + NATIVE_RSC_B (ocf::pacemaker:Dummy): (target-role:Stopped) Stopped diff --git a/pengine/test10/ordered-set-basic-startup.summary b/pengine/test10/ordered-set-basic-startup.summary index e47ed1eac8..30e9cb7596 100644 --- a/pengine/test10/ordered-set-basic-startup.summary +++ b/pengine/test10/ordered-set-basic-startup.summary @@ -1,39 +1,39 @@ Current cluster status: Online: [ fc16-builder ] OFFLINE: [ fc16-builder2 ] A (ocf::pacemaker:Dummy): Stopped B (ocf::pacemaker:Dummy): Stopped - C (ocf::pacemaker:Dummy): Stopped - D (ocf::pacemaker:Dummy): Stopped + C (ocf::pacemaker:Dummy): (target-role:Stopped) Stopped + D (ocf::pacemaker:Dummy): (target-role:Stopped) Stopped E (ocf::pacemaker:Dummy): Stopped F (ocf::pacemaker:Dummy): Stopped Transition Summary: * Start A (fc16-builder - blocked) * Start B (fc16-builder) * Start E (fc16-builder - blocked) * Start F (fc16-builder - blocked) Executing cluster transition: * Resource action: A monitor on fc16-builder * Resource action: B monitor on fc16-builder * Resource action: C monitor on fc16-builder * Resource action: D monitor on fc16-builder * Resource action: E monitor on fc16-builder * Resource action: F monitor on fc16-builder * Pseudo action: probe_complete * Resource action: B start on fc16-builder Revised cluster status: Online: [ fc16-builder ] OFFLINE: [ fc16-builder2 ] A (ocf::pacemaker:Dummy): Stopped B (ocf::pacemaker:Dummy): Started fc16-builder - C (ocf::pacemaker:Dummy): Stopped - D (ocf::pacemaker:Dummy): Stopped + C (ocf::pacemaker:Dummy): (target-role:Stopped) Stopped + D (ocf::pacemaker:Dummy): (target-role:Stopped) Stopped E (ocf::pacemaker:Dummy): Stopped F (ocf::pacemaker:Dummy): Stopped diff --git a/pengine/test10/ordered-set-natural.summary b/pengine/test10/ordered-set-natural.summary index e7ca50bd0a..30f83b7c74 100644 --- a/pengine/test10/ordered-set-natural.summary +++ b/pengine/test10/ordered-set-natural.summary @@ -1,51 +1,51 @@ Current cluster status: Online: [ node1 node2 ] Resource Group: rgroup dummy1-1 (ocf::heartbeat:Dummy): Stopped dummy1-2 (ocf::heartbeat:Dummy): Stopped - dummy1-3 (ocf::heartbeat:Dummy): Stopped + dummy1-3 (ocf::heartbeat:Dummy): (target-role:Stopped) Stopped dummy1-4 (ocf::heartbeat:Dummy): Stopped dummy1-5 (ocf::heartbeat:Dummy): Stopped dummy2-1 (ocf::heartbeat:Dummy): Stopped dummy2-2 (ocf::heartbeat:Dummy): Stopped - dummy2-3 (ocf::heartbeat:Dummy): Stopped + dummy2-3 (ocf::heartbeat:Dummy): (target-role:Stopped) Stopped dummy3-1 (ocf::heartbeat:Dummy): Stopped dummy3-2 (ocf::heartbeat:Dummy): Stopped - dummy3-3 (ocf::heartbeat:Dummy): Stopped + dummy3-3 (ocf::heartbeat:Dummy): (target-role:Stopped) Stopped dummy3-4 (ocf::heartbeat:Dummy): Stopped dummy3-5 (ocf::heartbeat:Dummy): Stopped dummy2-4 (ocf::heartbeat:Dummy): Stopped dummy2-5 (ocf::heartbeat:Dummy): Stopped Transition Summary: * Start dummy1-1 (node1 - blocked) * Start dummy1-2 (node1 - blocked) * Start dummy2-1 (node2 - blocked) * Start dummy2-2 (node2 - blocked) * Start dummy3-4 (node1 - blocked) * Start dummy3-5 (node1 - blocked) Executing cluster transition: Revised cluster status: Online: [ node1 node2 ] Resource Group: rgroup dummy1-1 (ocf::heartbeat:Dummy): Stopped dummy1-2 (ocf::heartbeat:Dummy): Stopped - dummy1-3 (ocf::heartbeat:Dummy): Stopped + dummy1-3 (ocf::heartbeat:Dummy): (target-role:Stopped) Stopped dummy1-4 (ocf::heartbeat:Dummy): Stopped dummy1-5 (ocf::heartbeat:Dummy): Stopped dummy2-1 (ocf::heartbeat:Dummy): Stopped dummy2-2 (ocf::heartbeat:Dummy): Stopped - dummy2-3 (ocf::heartbeat:Dummy): Stopped + dummy2-3 (ocf::heartbeat:Dummy): (target-role:Stopped) Stopped dummy3-1 (ocf::heartbeat:Dummy): Stopped dummy3-2 (ocf::heartbeat:Dummy): Stopped - dummy3-3 (ocf::heartbeat:Dummy): Stopped + dummy3-3 (ocf::heartbeat:Dummy): (target-role:Stopped) Stopped dummy3-4 (ocf::heartbeat:Dummy): Stopped dummy3-5 (ocf::heartbeat:Dummy): Stopped dummy2-4 (ocf::heartbeat:Dummy): Stopped dummy2-5 (ocf::heartbeat:Dummy): Stopped diff --git a/pengine/test10/params-6.summary b/pengine/test10/params-6.summary index 78f98c05fd..49f9787d17 100644 --- a/pengine/test10/params-6.summary +++ b/pengine/test10/params-6.summary @@ -1,375 +1,375 @@ Current cluster status: Online: [ mgmt01 v03-a v03-b ] - stonith-v02-a (stonith:fence_ipmilan): Stopped - stonith-v02-b (stonith:fence_ipmilan): Stopped - stonith-v02-c (stonith:fence_ipmilan): Stopped - stonith-v02-d (stonith:fence_ipmilan): Stopped + stonith-v02-a (stonith:fence_ipmilan): (target-role:Stopped) Stopped + stonith-v02-b (stonith:fence_ipmilan): (target-role:Stopped) Stopped + stonith-v02-c (stonith:fence_ipmilan): (target-role:Stopped) Stopped + stonith-v02-d (stonith:fence_ipmilan): (target-role:Stopped) Stopped stonith-mgmt01 (stonith:fence_xvm): Started v03-a stonith-mgmt02 (stonith:meatware): Started v03-a - stonith-v03-c (stonith:fence_ipmilan): Stopped + stonith-v03-c (stonith:fence_ipmilan): (target-role:Stopped) Stopped stonith-v03-a (stonith:fence_ipmilan): Started v03-b stonith-v03-b (stonith:fence_ipmilan): Started mgmt01 - stonith-v03-d (stonith:fence_ipmilan): Stopped + stonith-v03-d (stonith:fence_ipmilan): (target-role:Stopped) Stopped Clone Set: cl-clvmd [clvmd] Started: [ mgmt01 v03-a v03-b ] Clone Set: cl-dlm [dlm] Started: [ mgmt01 v03-a v03-b ] Clone Set: cl-iscsid [iscsid] Started: [ mgmt01 v03-a v03-b ] Clone Set: cl-libvirtd [libvirtd] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] Clone Set: cl-multipathd [multipathd] Started: [ mgmt01 v03-a v03-b ] Clone Set: cl-node-params [node-params] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] Clone Set: cl-vlan1-if [vlan1-if] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] Clone Set: cl-vlan101-if [vlan101-if] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] Clone Set: cl-vlan102-if [vlan102-if] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] Clone Set: cl-vlan103-if [vlan103-if] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] Clone Set: cl-vlan104-if [vlan104-if] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] Clone Set: cl-vlan3-if [vlan3-if] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] Clone Set: cl-vlan4-if [vlan4-if] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] Clone Set: cl-vlan5-if [vlan5-if] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] Clone Set: cl-vlan900-if [vlan900-if] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] Clone Set: cl-vlan909-if [vlan909-if] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] Clone Set: cl-libvirt-images-fs [libvirt-images-fs] Started: [ mgmt01 v03-a v03-b ] Clone Set: cl-libvirt-install-fs [libvirt-install-fs] Started: [ mgmt01 v03-a v03-b ] Clone Set: cl-vds-ok-pool-0-iscsi [vds-ok-pool-0-iscsi] Started: [ mgmt01 v03-a v03-b ] Clone Set: cl-vds-ok-pool-0-vg [vds-ok-pool-0-vg] Started: [ mgmt01 v03-a v03-b ] Clone Set: cl-vds-ok-pool-1-iscsi [vds-ok-pool-1-iscsi] Started: [ mgmt01 v03-a v03-b ] Clone Set: cl-vds-ok-pool-1-vg [vds-ok-pool-1-vg] Started: [ mgmt01 v03-a v03-b ] Clone Set: cl-libvirt-images-pool [libvirt-images-pool] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] Clone Set: cl-vds-ok-pool-0-pool [vds-ok-pool-0-pool] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] Clone Set: cl-vds-ok-pool-1-pool [vds-ok-pool-1-pool] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] - git.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped + git.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped Clone Set: cl-libvirt-qpid [libvirt-qpid] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] vd01-a.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Started v03-b vd01-b.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Started v03-b vd01-c.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Started v03-a vd01-d.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Started v03-b - vd02-a.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vd02-b.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vd02-c.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vd02-d.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vd03-a.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vd03-b.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vd03-c.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vd03-d.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vd04-a.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vd04-b.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vd04-c.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vd04-d.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped + vd02-a.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vd02-b.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vd02-c.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vd02-d.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vd03-a.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vd03-b.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vd03-c.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vd03-d.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vd04-a.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vd04-b.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vd04-c.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vd04-d.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped f13-x64-devel.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Started v03-a eu2.ca-pages.com-vm (ocf::vds-ok:VirtualDomain): Started v03-b - zakaz.transferrus.ru-vm (ocf::vds-ok:VirtualDomain): Stopped + zakaz.transferrus.ru-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped Clone Set: cl-vlan200-if [vlan200-if] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] - anbriz-gw-vm (ocf::vds-ok:VirtualDomain): Stopped - anbriz-work-vm (ocf::vds-ok:VirtualDomain): Stopped + anbriz-gw-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + anbriz-work-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped lenny-x32-devel-vm (ocf::vds-ok:VirtualDomain): Started v03-a - vptest1.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest2.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest3.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest4.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest5.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest6.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest7.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest8.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest9.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest10.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest11.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest12.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest13.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest14.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest15.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest16.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest17.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest18.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest19.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest20.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest21.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest22.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest23.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest24.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest25.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest26.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest27.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest28.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest29.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest30.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest31.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest32.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest33.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest34.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest35.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest36.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest37.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest38.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest39.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest40.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest41.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest42.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest43.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest44.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest45.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest46.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest47.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest48.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest49.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest50.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest51.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest52.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest53.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest54.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest55.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest56.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest57.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest58.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest59.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest60.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped + vptest1.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest2.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest3.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest4.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest5.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest6.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest7.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest8.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest9.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest10.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest11.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest12.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest13.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest14.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest15.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest16.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest17.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest18.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest19.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest20.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest21.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest22.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest23.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest24.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest25.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest26.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest27.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest28.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest29.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest30.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest31.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest32.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest33.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest34.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest35.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest36.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest37.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest38.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest39.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest40.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest41.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest42.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest43.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest44.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest45.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest46.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest47.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest48.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest49.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest50.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest51.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest52.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest53.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest54.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest55.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest56.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest57.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest58.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest59.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest60.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped sl6-x64-devel.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Started v03-b - dist.express-consult.org-vm (ocf::vds-ok:VirtualDomain): Stopped - eu1.ca-pages.com-vm (ocf::vds-ok:VirtualDomain): Stopped - gotin-bbb-vm (ocf::vds-ok:VirtualDomain): Stopped - maxb-c55-vm (ocf::vds-ok:VirtualDomain): Stopped - metae.ru-vm (ocf::vds-ok:VirtualDomain): Stopped - rodovoepomestie.ru-vm (ocf::vds-ok:VirtualDomain): Stopped - ubuntu9.10-gotin-vm (ocf::vds-ok:VirtualDomain): Stopped + dist.express-consult.org-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + eu1.ca-pages.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + gotin-bbb-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + maxb-c55-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + metae.ru-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + rodovoepomestie.ru-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + ubuntu9.10-gotin-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped c5-x64-devel.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Started v03-a Clone Set: cl-mcast-test-net [mcast-test-net] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] - dist.fly-uni.org-vm (ocf::vds-ok:VirtualDomain): Stopped + dist.fly-uni.org-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped Transition Summary: * Reload c5-x64-devel.vds-ok.com-vm (Started v03-a) Executing cluster transition: * Resource action: vd01-b.cdev.ttc.prague.cz.vds-ok.com-vm monitor=10000 on v03-b * Resource action: vd01-d.cdev.ttc.prague.cz.vds-ok.com-vm monitor=10000 on v03-b * Pseudo action: load_stopped_mgmt01 * Pseudo action: load_stopped_v03-b * Pseudo action: load_stopped_v03-a * Resource action: c5-x64-devel.vds-ok.com-vm reload on v03-a * Resource action: c5-x64-devel.vds-ok.com-vm monitor=10000 on v03-a Revised cluster status: Online: [ mgmt01 v03-a v03-b ] - stonith-v02-a (stonith:fence_ipmilan): Stopped - stonith-v02-b (stonith:fence_ipmilan): Stopped - stonith-v02-c (stonith:fence_ipmilan): Stopped - stonith-v02-d (stonith:fence_ipmilan): Stopped + stonith-v02-a (stonith:fence_ipmilan): (target-role:Stopped) Stopped + stonith-v02-b (stonith:fence_ipmilan): (target-role:Stopped) Stopped + stonith-v02-c (stonith:fence_ipmilan): (target-role:Stopped) Stopped + stonith-v02-d (stonith:fence_ipmilan): (target-role:Stopped) Stopped stonith-mgmt01 (stonith:fence_xvm): Started v03-a stonith-mgmt02 (stonith:meatware): Started v03-a - stonith-v03-c (stonith:fence_ipmilan): Stopped + stonith-v03-c (stonith:fence_ipmilan): (target-role:Stopped) Stopped stonith-v03-a (stonith:fence_ipmilan): Started v03-b stonith-v03-b (stonith:fence_ipmilan): Started mgmt01 - stonith-v03-d (stonith:fence_ipmilan): Stopped + stonith-v03-d (stonith:fence_ipmilan): (target-role:Stopped) Stopped Clone Set: cl-clvmd [clvmd] Started: [ mgmt01 v03-a v03-b ] Clone Set: cl-dlm [dlm] Started: [ mgmt01 v03-a v03-b ] Clone Set: cl-iscsid [iscsid] Started: [ mgmt01 v03-a v03-b ] Clone Set: cl-libvirtd [libvirtd] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] Clone Set: cl-multipathd [multipathd] Started: [ mgmt01 v03-a v03-b ] Clone Set: cl-node-params [node-params] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] Clone Set: cl-vlan1-if [vlan1-if] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] Clone Set: cl-vlan101-if [vlan101-if] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] Clone Set: cl-vlan102-if [vlan102-if] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] Clone Set: cl-vlan103-if [vlan103-if] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] Clone Set: cl-vlan104-if [vlan104-if] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] Clone Set: cl-vlan3-if [vlan3-if] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] Clone Set: cl-vlan4-if [vlan4-if] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] Clone Set: cl-vlan5-if [vlan5-if] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] Clone Set: cl-vlan900-if [vlan900-if] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] Clone Set: cl-vlan909-if [vlan909-if] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] Clone Set: cl-libvirt-images-fs [libvirt-images-fs] Started: [ mgmt01 v03-a v03-b ] Clone Set: cl-libvirt-install-fs [libvirt-install-fs] Started: [ mgmt01 v03-a v03-b ] Clone Set: cl-vds-ok-pool-0-iscsi [vds-ok-pool-0-iscsi] Started: [ mgmt01 v03-a v03-b ] Clone Set: cl-vds-ok-pool-0-vg [vds-ok-pool-0-vg] Started: [ mgmt01 v03-a v03-b ] Clone Set: cl-vds-ok-pool-1-iscsi [vds-ok-pool-1-iscsi] Started: [ mgmt01 v03-a v03-b ] Clone Set: cl-vds-ok-pool-1-vg [vds-ok-pool-1-vg] Started: [ mgmt01 v03-a v03-b ] Clone Set: cl-libvirt-images-pool [libvirt-images-pool] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] Clone Set: cl-vds-ok-pool-0-pool [vds-ok-pool-0-pool] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] Clone Set: cl-vds-ok-pool-1-pool [vds-ok-pool-1-pool] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] - git.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped + git.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped Clone Set: cl-libvirt-qpid [libvirt-qpid] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] vd01-a.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Started v03-b vd01-b.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Started v03-b vd01-c.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Started v03-a vd01-d.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Started v03-b - vd02-a.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vd02-b.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vd02-c.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vd02-d.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vd03-a.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vd03-b.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vd03-c.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vd03-d.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vd04-a.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vd04-b.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vd04-c.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vd04-d.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped + vd02-a.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vd02-b.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vd02-c.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vd02-d.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vd03-a.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vd03-b.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vd03-c.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vd03-d.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vd04-a.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vd04-b.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vd04-c.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vd04-d.cdev.ttc.prague.cz.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped f13-x64-devel.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Started v03-a eu2.ca-pages.com-vm (ocf::vds-ok:VirtualDomain): Started v03-b - zakaz.transferrus.ru-vm (ocf::vds-ok:VirtualDomain): Stopped + zakaz.transferrus.ru-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped Clone Set: cl-vlan200-if [vlan200-if] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] - anbriz-gw-vm (ocf::vds-ok:VirtualDomain): Stopped - anbriz-work-vm (ocf::vds-ok:VirtualDomain): Stopped + anbriz-gw-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + anbriz-work-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped lenny-x32-devel-vm (ocf::vds-ok:VirtualDomain): Started v03-a - vptest1.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest2.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest3.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest4.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest5.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest6.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest7.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest8.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest9.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest10.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest11.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest12.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest13.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest14.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest15.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest16.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest17.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest18.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest19.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest20.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest21.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest22.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest23.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest24.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest25.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest26.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest27.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest28.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest29.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest30.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest31.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest32.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest33.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest34.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest35.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest36.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest37.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest38.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest39.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest40.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest41.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest42.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest43.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest44.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest45.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest46.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest47.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest48.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest49.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest50.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest51.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest52.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest53.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest54.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest55.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest56.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest57.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest58.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest59.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped - vptest60.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Stopped + vptest1.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest2.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest3.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest4.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest5.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest6.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest7.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest8.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest9.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest10.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest11.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest12.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest13.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest14.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest15.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest16.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest17.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest18.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest19.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest20.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest21.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest22.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest23.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest24.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest25.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest26.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest27.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest28.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest29.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest30.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest31.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest32.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest33.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest34.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest35.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest36.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest37.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest38.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest39.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest40.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest41.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest42.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest43.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest44.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest45.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest46.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest47.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest48.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest49.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest50.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest51.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest52.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest53.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest54.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest55.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest56.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest57.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest58.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest59.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + vptest60.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped sl6-x64-devel.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Started v03-b - dist.express-consult.org-vm (ocf::vds-ok:VirtualDomain): Stopped - eu1.ca-pages.com-vm (ocf::vds-ok:VirtualDomain): Stopped - gotin-bbb-vm (ocf::vds-ok:VirtualDomain): Stopped - maxb-c55-vm (ocf::vds-ok:VirtualDomain): Stopped - metae.ru-vm (ocf::vds-ok:VirtualDomain): Stopped - rodovoepomestie.ru-vm (ocf::vds-ok:VirtualDomain): Stopped - ubuntu9.10-gotin-vm (ocf::vds-ok:VirtualDomain): Stopped + dist.express-consult.org-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + eu1.ca-pages.com-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + gotin-bbb-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + maxb-c55-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + metae.ru-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + rodovoepomestie.ru-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped + ubuntu9.10-gotin-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped c5-x64-devel.vds-ok.com-vm (ocf::vds-ok:VirtualDomain): Started v03-a Clone Set: cl-mcast-test-net [mcast-test-net] Started: [ v03-a v03-b ] Stopped: [ mgmt01 ] - dist.fly-uni.org-vm (ocf::vds-ok:VirtualDomain): Stopped + dist.fly-uni.org-vm (ocf::vds-ok:VirtualDomain): (target-role:Stopped) Stopped diff --git a/pengine/test10/remote-disable.summary b/pengine/test10/remote-disable.summary index 0627647743..c7e3a18ad4 100644 --- a/pengine/test10/remote-disable.summary +++ b/pengine/test10/remote-disable.summary @@ -1,32 +1,32 @@ Current cluster status: Online: [ 18builder 18node1 18node2 ] RemoteOnline: [ remote1 ] shooter (stonith:fence_xvm): Started 18node1 - remote1 (ocf::pacemaker:remote): Started 18builder + remote1 (ocf::pacemaker:remote): (target-role:Stopped) Started 18builder FAKE1 (ocf::heartbeat:Dummy): Started 18node2 FAKE2 (ocf::heartbeat:Dummy): Started remote1 FAKE3 (ocf::heartbeat:Dummy): Started 18builder FAKE4 (ocf::heartbeat:Dummy): Started 18node1 Transition Summary: * Stop remote1 (18builder) * Stop FAKE2 (remote1) Executing cluster transition: * Resource action: FAKE2 stop on remote1 * Resource action: remote1 stop on 18builder * Pseudo action: all_stopped Revised cluster status: Online: [ 18builder 18node1 18node2 ] RemoteOFFLINE: [ remote1 ] shooter (stonith:fence_xvm): Started 18node1 - remote1 (ocf::pacemaker:remote): Stopped + remote1 (ocf::pacemaker:remote): (target-role:Stopped) Stopped FAKE1 (ocf::heartbeat:Dummy): Started 18node2 FAKE2 (ocf::heartbeat:Dummy): Stopped FAKE3 (ocf::heartbeat:Dummy): Started 18builder FAKE4 (ocf::heartbeat:Dummy): Started 18node1 diff --git a/pengine/test10/rsc-maintenance.summary b/pengine/test10/rsc-maintenance.summary index ea6b16f2ca..f143e24290 100644 --- a/pengine/test10/rsc-maintenance.summary +++ b/pengine/test10/rsc-maintenance.summary @@ -1,27 +1,27 @@ Current cluster status: Online: [ node1 node2 ] Resource Group: group1 - rsc1 (ocf::pacemaker:Dummy): Started node1 (unmanaged) - rsc2 (ocf::pacemaker:Dummy): Started node1 (unmanaged) + rsc1 (ocf::pacemaker:Dummy): (target-role:Stopped) Started node1 (unmanaged) + rsc2 (ocf::pacemaker:Dummy): (target-role:Stopped) Started node1 (unmanaged) Resource Group: group2 rsc3 (ocf::pacemaker:Dummy): Started node2 rsc4 (ocf::pacemaker:Dummy): Started node2 Transition Summary: Executing cluster transition: * Resource action: rsc1 cancel=10000 on node1 * Resource action: rsc2 cancel=10000 on node1 Revised cluster status: Online: [ node1 node2 ] Resource Group: group1 - rsc1 (ocf::pacemaker:Dummy): Started node1 (unmanaged) - rsc2 (ocf::pacemaker:Dummy): Started node1 (unmanaged) + rsc1 (ocf::pacemaker:Dummy): (target-role:Stopped) Started node1 (unmanaged) + rsc2 (ocf::pacemaker:Dummy): (target-role:Stopped) Started node1 (unmanaged) Resource Group: group2 rsc3 (ocf::pacemaker:Dummy): Started node2 rsc4 (ocf::pacemaker:Dummy): Started node2 diff --git a/pengine/test10/rsc-sets-clone-1.summary b/pengine/test10/rsc-sets-clone-1.summary index 4e2ced145f..909597744a 100644 --- a/pengine/test10/rsc-sets-clone-1.summary +++ b/pengine/test10/rsc-sets-clone-1.summary @@ -1,84 +1,84 @@ Current cluster status: Online: [ sys2 sys3 ] vm1 (ocf::heartbeat:Xen): Started sys2 - vm2 (ocf::heartbeat:Xen): Stopped - vm3 (ocf::heartbeat:Xen): Stopped - vm4 (ocf::heartbeat:Xen): Stopped + vm2 (ocf::heartbeat:Xen): (target-role:stopped) Stopped + vm3 (ocf::heartbeat:Xen): (target-role:stopped) Stopped + vm4 (ocf::heartbeat:Xen): (target-role:stopped) Stopped stonithsys2 (stonith:external/ipmi): Stopped stonithsys3 (stonith:external/ipmi): Started sys2 Clone Set: baseclone [basegrp] Started: [ sys2 ] Stopped: [ sys3 ] Clone Set: fs1 [nfs1] Stopped: [ sys2 sys3 ] Transition Summary: * Restart stonithsys3 (Started sys2) * Start controld:1 (sys3) * Start clvmd:1 (sys3) * Start o2cb:1 (sys3) * Start iscsi1:1 (sys3) * Start iscsi2:1 (sys3) * Start vg1:1 (sys3) * Start vg2:1 (sys3) * Start fs2:1 (sys3) * Start stonithsys2 (sys3) Executing cluster transition: * Resource action: vm1 monitor on sys3 * Resource action: vm2 monitor on sys3 * Resource action: vm3 monitor on sys3 * Resource action: vm4 monitor on sys3 * Resource action: stonithsys3 monitor on sys3 * Resource action: controld:1 monitor on sys3 * Resource action: clvmd:1 monitor on sys3 * Resource action: o2cb:1 monitor on sys3 * Resource action: iscsi1:1 monitor on sys3 * Resource action: iscsi2:1 monitor on sys3 * Resource action: vg1:1 monitor on sys3 * Resource action: vg2:1 monitor on sys3 * Resource action: fs2:1 monitor on sys3 * Pseudo action: baseclone_start_0 * Resource action: nfs1:0 monitor on sys3 * Resource action: stonithsys2 monitor on sys3 * Pseudo action: probe_complete * Pseudo action: load_stopped_sys3 * Pseudo action: load_stopped_sys2 * Resource action: stonithsys3 stop on sys2 * Resource action: stonithsys3 start on sys2 * Resource action: stonithsys3 monitor=15000 on sys2 * Pseudo action: basegrp:1_start_0 * Resource action: controld:1 start on sys3 * Resource action: clvmd:1 start on sys3 * Resource action: o2cb:1 start on sys3 * Resource action: iscsi1:1 start on sys3 * Resource action: iscsi2:1 start on sys3 * Resource action: vg1:1 start on sys3 * Resource action: vg2:1 start on sys3 * Resource action: fs2:1 start on sys3 * Resource action: stonithsys2 start on sys3 * Pseudo action: all_stopped * Pseudo action: basegrp:1_running_0 * Resource action: controld:1 monitor=10000 on sys3 * Resource action: iscsi1:1 monitor=120000 on sys3 * Resource action: iscsi2:1 monitor=120000 on sys3 * Resource action: fs2:1 monitor=20000 on sys3 * Pseudo action: baseclone_running_0 * Resource action: stonithsys2 monitor=15000 on sys3 Revised cluster status: Online: [ sys2 sys3 ] vm1 (ocf::heartbeat:Xen): Started sys2 - vm2 (ocf::heartbeat:Xen): Stopped - vm3 (ocf::heartbeat:Xen): Stopped - vm4 (ocf::heartbeat:Xen): Stopped + vm2 (ocf::heartbeat:Xen): (target-role:stopped) Stopped + vm3 (ocf::heartbeat:Xen): (target-role:stopped) Stopped + vm4 (ocf::heartbeat:Xen): (target-role:stopped) Stopped stonithsys2 (stonith:external/ipmi): Started sys3 stonithsys3 (stonith:external/ipmi): Started sys2 Clone Set: baseclone [basegrp] Started: [ sys2 sys3 ] Clone Set: fs1 [nfs1] Stopped: [ sys2 sys3 ] diff --git a/pengine/test10/stopped-monitor-03.summary b/pengine/test10/stopped-monitor-03.summary index 3bb1756cee..76cf56c3ca 100644 --- a/pengine/test10/stopped-monitor-03.summary +++ b/pengine/test10/stopped-monitor-03.summary @@ -1,19 +1,19 @@ Current cluster status: Online: [ node1 node2 ] - rsc1 (ocf::pacemaker:Dummy): Started node1 + rsc1 (ocf::pacemaker:Dummy): (target-role:Stopped) Started node1 Transition Summary: * Stop rsc1 (node1) Executing cluster transition: * Resource action: rsc1 stop on node1 * Pseudo action: all_stopped * Resource action: rsc1 monitor=20000 on node1 Revised cluster status: Online: [ node1 node2 ] - rsc1 (ocf::pacemaker:Dummy): Stopped + rsc1 (ocf::pacemaker:Dummy): (target-role:Stopped) Stopped diff --git a/pengine/test10/stopped-monitor-11.summary b/pengine/test10/stopped-monitor-11.summary index 1a38ae753c..1cdf2f0c6b 100644 --- a/pengine/test10/stopped-monitor-11.summary +++ b/pengine/test10/stopped-monitor-11.summary @@ -1,15 +1,15 @@ Current cluster status: Online: [ node1 node2 ] - rsc1 (ocf::pacemaker:Dummy): Started node1 (unmanaged) + rsc1 (ocf::pacemaker:Dummy): (target-role:Stopped) Started node1 (unmanaged) Transition Summary: Executing cluster transition: Revised cluster status: Online: [ node1 node2 ] - rsc1 (ocf::pacemaker:Dummy): Started node1 (unmanaged) + rsc1 (ocf::pacemaker:Dummy): (target-role:Stopped) Started node1 (unmanaged) diff --git a/pengine/test10/stopped-monitor-20.summary b/pengine/test10/stopped-monitor-20.summary index 03b4c5b81d..be9e5b0ab8 100644 --- a/pengine/test10/stopped-monitor-20.summary +++ b/pengine/test10/stopped-monitor-20.summary @@ -1,20 +1,20 @@ Current cluster status: Online: [ node1 node2 ] - rsc1 (ocf::pacemaker:Dummy): Stopped + rsc1 (ocf::pacemaker:Dummy): (target-role:Stopped) Stopped Transition Summary: Executing cluster transition: * Resource action: rsc1 monitor on node2 * Resource action: rsc1 monitor on node1 * Pseudo action: probe_complete * Resource action: rsc1 monitor=20000 on node2 * Resource action: rsc1 monitor=20000 on node1 Revised cluster status: Online: [ node1 node2 ] - rsc1 (ocf::pacemaker:Dummy): Stopped + rsc1 (ocf::pacemaker:Dummy): (target-role:Stopped) Stopped diff --git a/pengine/test10/stopped-monitor-21.summary b/pengine/test10/stopped-monitor-21.summary index d2d3852856..49a450aaa3 100644 --- a/pengine/test10/stopped-monitor-21.summary +++ b/pengine/test10/stopped-monitor-21.summary @@ -1,19 +1,19 @@ Current cluster status: Online: [ node1 node2 ] rsc1 (ocf::pacemaker:Dummy): FAILED node1 Transition Summary: * Stop rsc1 (node1) Executing cluster transition: * Resource action: rsc1 stop on node1 * Resource action: rsc1 monitor=20000 on node1 * Pseudo action: all_stopped Revised cluster status: Online: [ node1 node2 ] - rsc1 (ocf::pacemaker:Dummy): Stopped + rsc1 (ocf::pacemaker:Dummy): (target-role:Stopped) Stopped diff --git a/pengine/test10/stopped-monitor-22.summary b/pengine/test10/stopped-monitor-22.summary index 84bf62fe34..d464a2c654 100644 --- a/pengine/test10/stopped-monitor-22.summary +++ b/pengine/test10/stopped-monitor-22.summary @@ -1,22 +1,22 @@ Current cluster status: Online: [ node1 node2 ] rsc1 (ocf::pacemaker:Dummy): FAILED [ node1 node2 ] Transition Summary: * Stop rsc1 (node1) * Stop rsc1 (node2) Executing cluster transition: * Resource action: rsc1 stop on node2 * Resource action: rsc1 monitor=20000 on node2 * Resource action: rsc1 stop on node1 * Resource action: rsc1 monitor=20000 on node1 * Pseudo action: all_stopped Revised cluster status: Online: [ node1 node2 ] - rsc1 (ocf::pacemaker:Dummy): Stopped + rsc1 (ocf::pacemaker:Dummy): (target-role:Stopped) Stopped diff --git a/pengine/test10/stopped-monitor-24.summary b/pengine/test10/stopped-monitor-24.summary index 67b1d43f01..92fdceb135 100644 --- a/pengine/test10/stopped-monitor-24.summary +++ b/pengine/test10/stopped-monitor-24.summary @@ -1,15 +1,15 @@ Current cluster status: Online: [ node1 node2 ] - rsc1 (ocf::pacemaker:Dummy): Stopped (unmanaged) + rsc1 (ocf::pacemaker:Dummy): (target-role:Stopped) Stopped (unmanaged) Transition Summary: Executing cluster transition: Revised cluster status: Online: [ node1 node2 ] - rsc1 (ocf::pacemaker:Dummy): Stopped (unmanaged) + rsc1 (ocf::pacemaker:Dummy): (target-role:Stopped) Stopped (unmanaged) diff --git a/pengine/test10/stopped-monitor-31.summary b/pengine/test10/stopped-monitor-31.summary index 4b08044395..e602b518b3 100644 --- a/pengine/test10/stopped-monitor-31.summary +++ b/pengine/test10/stopped-monitor-31.summary @@ -1,18 +1,18 @@ Current cluster status: Online: [ node1 node2 node3 ] - rsc1 (ocf::pacemaker:Dummy): Stopped + rsc1 (ocf::pacemaker:Dummy): (target-role:Stopped) Stopped Transition Summary: Executing cluster transition: * Resource action: rsc1 monitor on node3 * Pseudo action: probe_complete * Resource action: rsc1 monitor=20000 on node3 Revised cluster status: Online: [ node1 node2 node3 ] - rsc1 (ocf::pacemaker:Dummy): Stopped + rsc1 (ocf::pacemaker:Dummy): (target-role:Stopped) Stopped diff --git a/pengine/test10/target-1.summary b/pengine/test10/target-1.summary index 95ab90028c..f93a8f5984 100644 --- a/pengine/test10/target-1.summary +++ b/pengine/test10/target-1.summary @@ -1,41 +1,41 @@ Current cluster status: Online: [ c001n01 c001n02 c001n03 c001n08 ] DcIPaddr (ocf::heartbeat:IPaddr): Started c001n02 - rsc_c001n08 (ocf::heartbeat:IPaddr): Started c001n08 - rsc_c001n02 (ocf::heartbeat:IPaddr): Started c001n02 + rsc_c001n08 (ocf::heartbeat:IPaddr): (target-role:Stopped) Started c001n08 + rsc_c001n02 (ocf::heartbeat:IPaddr): (target-role:Slave) Started c001n02 Master/Slave Set: promoteme [rsc_c001n03] Slaves: [ c001n03 ] rsc_c001n01 (ocf::heartbeat:IPaddr): Started c001n01 Transition Summary: * Stop rsc_c001n08 (c001n08) Executing cluster transition: * Resource action: DcIPaddr monitor on c001n08 * Resource action: DcIPaddr monitor on c001n03 * Resource action: DcIPaddr monitor on c001n01 * Resource action: rsc_c001n08 monitor on c001n03 * Resource action: rsc_c001n08 monitor on c001n02 * Resource action: rsc_c001n08 monitor on c001n01 * Resource action: rsc_c001n02 monitor on c001n08 * Resource action: rsc_c001n02 monitor on c001n03 * Resource action: rsc_c001n02 monitor on c001n01 * Resource action: rsc_c001n01 monitor on c001n08 * Resource action: rsc_c001n01 monitor on c001n03 * Resource action: rsc_c001n01 monitor on c001n02 * Pseudo action: probe_complete * Resource action: rsc_c001n08 stop on c001n08 * Pseudo action: all_stopped Revised cluster status: Online: [ c001n01 c001n02 c001n03 c001n08 ] DcIPaddr (ocf::heartbeat:IPaddr): Started c001n02 - rsc_c001n08 (ocf::heartbeat:IPaddr): Stopped - rsc_c001n02 (ocf::heartbeat:IPaddr): Started c001n02 + rsc_c001n08 (ocf::heartbeat:IPaddr): (target-role:Stopped) Stopped + rsc_c001n02 (ocf::heartbeat:IPaddr): (target-role:Slave) Started c001n02 Master/Slave Set: promoteme [rsc_c001n03] Slaves: [ c001n03 ] rsc_c001n01 (ocf::heartbeat:IPaddr): Started c001n01 diff --git a/pengine/test10/target-2.summary b/pengine/test10/target-2.summary index 09d94f33d3..7094ae9e5e 100644 --- a/pengine/test10/target-2.summary +++ b/pengine/test10/target-2.summary @@ -1,42 +1,42 @@ Current cluster status: Online: [ c001n01 c001n02 c001n03 c001n08 ] DcIPaddr (ocf::heartbeat:IPaddr): Started c001n02 - rsc_c001n08 (ocf::heartbeat:IPaddr): Started c001n08 - rsc_c001n02 (ocf::heartbeat:IPaddr): Started c001n02 - rsc_c001n03 (ocf::heartbeat:IPaddr): Started c001n03 + rsc_c001n08 (ocf::heartbeat:IPaddr): (target-role:Stopped) Started c001n08 + rsc_c001n02 (ocf::heartbeat:IPaddr): (target-role:Slave) Started c001n02 + rsc_c001n03 (ocf::heartbeat:IPaddr): (target-role:Master) Started c001n03 rsc_c001n01 (ocf::heartbeat:IPaddr): Started c001n01 Transition Summary: * Stop rsc_c001n08 (c001n08) Executing cluster transition: * Resource action: DcIPaddr monitor on c001n08 * Resource action: DcIPaddr monitor on c001n03 * Resource action: DcIPaddr monitor on c001n01 * Resource action: rsc_c001n08 monitor on c001n03 * Resource action: rsc_c001n08 monitor on c001n02 * Resource action: rsc_c001n08 monitor on c001n01 * Resource action: rsc_c001n02 monitor on c001n08 * Resource action: rsc_c001n02 monitor on c001n03 * Resource action: rsc_c001n02 monitor on c001n01 * Resource action: rsc_c001n03 monitor on c001n08 * Resource action: rsc_c001n03 monitor on c001n02 * Resource action: rsc_c001n03 monitor on c001n01 * Resource action: rsc_c001n01 monitor on c001n08 * Resource action: rsc_c001n01 monitor on c001n03 * Resource action: rsc_c001n01 monitor on c001n02 * Pseudo action: probe_complete * Resource action: rsc_c001n08 stop on c001n08 * Pseudo action: all_stopped Revised cluster status: Online: [ c001n01 c001n02 c001n03 c001n08 ] DcIPaddr (ocf::heartbeat:IPaddr): Started c001n02 - rsc_c001n08 (ocf::heartbeat:IPaddr): Stopped - rsc_c001n02 (ocf::heartbeat:IPaddr): Started c001n02 - rsc_c001n03 (ocf::heartbeat:IPaddr): Started c001n03 + rsc_c001n08 (ocf::heartbeat:IPaddr): (target-role:Stopped) Stopped + rsc_c001n02 (ocf::heartbeat:IPaddr): (target-role:Slave) Started c001n02 + rsc_c001n03 (ocf::heartbeat:IPaddr): (target-role:Master) Started c001n03 rsc_c001n01 (ocf::heartbeat:IPaddr): Started c001n01 diff --git a/pengine/test10/template-1.summary b/pengine/test10/template-1.summary index c1229be7e9..17d14c24b9 100644 --- a/pengine/test10/template-1.summary +++ b/pengine/test10/template-1.summary @@ -1,27 +1,27 @@ Current cluster status: Online: [ node1 node2 ] - rsc1 (ocf::pacemaker:Dummy): Stopped + rsc1 (ocf::pacemaker:Dummy): (target-role:Stopped) Stopped rsc2 (ocf::pacemaker:Dummy): Stopped Transition Summary: * Start rsc2 (node1) Executing cluster transition: * Resource action: rsc1 monitor on node2 * Resource action: rsc1 monitor on node1 * Resource action: rsc2 monitor on node2 * Resource action: rsc2 monitor on node1 * Pseudo action: probe_complete * Pseudo action: load_stopped_node1 * Pseudo action: load_stopped_node2 * Resource action: rsc2 start on node1 * Resource action: rsc2 monitor=10000 on node1 Revised cluster status: Online: [ node1 node2 ] - rsc1 (ocf::pacemaker:Dummy): Stopped + rsc1 (ocf::pacemaker:Dummy): (target-role:Stopped) Stopped rsc2 (ocf::pacemaker:Dummy): Started node1 diff --git a/pengine/test10/unmanaged-stop-1.summary b/pengine/test10/unmanaged-stop-1.summary index ebde009a5c..6d1481325a 100644 --- a/pengine/test10/unmanaged-stop-1.summary +++ b/pengine/test10/unmanaged-stop-1.summary @@ -1,18 +1,18 @@ Current cluster status: Online: [ yingying.site ] - rsc1 (ocf::pacemaker:Dummy): Started yingying.site + rsc1 (ocf::pacemaker:Dummy): (target-role:Stopped) Started yingying.site rsc2 (ocf::pacemaker:Dummy): FAILED yingying.site (unmanaged) Transition Summary: * Stop rsc1 (yingying.site - blocked) Executing cluster transition: Revised cluster status: Online: [ yingying.site ] - rsc1 (ocf::pacemaker:Dummy): Started yingying.site + rsc1 (ocf::pacemaker:Dummy): (target-role:Stopped) Started yingying.site rsc2 (ocf::pacemaker:Dummy): FAILED yingying.site (unmanaged) diff --git a/pengine/test10/unmanaged-stop-2.summary b/pengine/test10/unmanaged-stop-2.summary index ebde009a5c..6d1481325a 100644 --- a/pengine/test10/unmanaged-stop-2.summary +++ b/pengine/test10/unmanaged-stop-2.summary @@ -1,18 +1,18 @@ Current cluster status: Online: [ yingying.site ] - rsc1 (ocf::pacemaker:Dummy): Started yingying.site + rsc1 (ocf::pacemaker:Dummy): (target-role:Stopped) Started yingying.site rsc2 (ocf::pacemaker:Dummy): FAILED yingying.site (unmanaged) Transition Summary: * Stop rsc1 (yingying.site - blocked) Executing cluster transition: Revised cluster status: Online: [ yingying.site ] - rsc1 (ocf::pacemaker:Dummy): Started yingying.site + rsc1 (ocf::pacemaker:Dummy): (target-role:Stopped) Started yingying.site rsc2 (ocf::pacemaker:Dummy): FAILED yingying.site (unmanaged) diff --git a/pengine/test10/unmanaged-stop-3.summary b/pengine/test10/unmanaged-stop-3.summary index b37c76ea98..643e93f5b3 100644 --- a/pengine/test10/unmanaged-stop-3.summary +++ b/pengine/test10/unmanaged-stop-3.summary @@ -1,21 +1,21 @@ Current cluster status: Online: [ yingying.site ] Resource Group: group1 - rsc1 (ocf::pacemaker:Dummy): Started yingying.site + rsc1 (ocf::pacemaker:Dummy): (target-role:Stopped) Started yingying.site rsc2 (ocf::pacemaker:Dummy): FAILED yingying.site (unmanaged) Transition Summary: * Stop rsc1 (yingying.site - blocked) Executing cluster transition: * Pseudo action: group1_stop_0 Revised cluster status: Online: [ yingying.site ] Resource Group: group1 - rsc1 (ocf::pacemaker:Dummy): Started yingying.site + rsc1 (ocf::pacemaker:Dummy): (target-role:Stopped) Started yingying.site rsc2 (ocf::pacemaker:Dummy): FAILED yingying.site (unmanaged) diff --git a/pengine/test10/unmanaged-stop-4.summary b/pengine/test10/unmanaged-stop-4.summary index dae6cf38e6..cd81e39223 100644 --- a/pengine/test10/unmanaged-stop-4.summary +++ b/pengine/test10/unmanaged-stop-4.summary @@ -1,23 +1,23 @@ Current cluster status: Online: [ yingying.site ] Resource Group: group1 - rsc1 (ocf::pacemaker:Dummy): Started yingying.site + rsc1 (ocf::pacemaker:Dummy): (target-role:Stopped) Started yingying.site rsc2 (ocf::pacemaker:Dummy): FAILED yingying.site (unmanaged) - rsc3 (ocf::heartbeat:Dummy): Stopped + rsc3 (ocf::heartbeat:Dummy): (target-role:Stopped) Stopped Transition Summary: * Stop rsc1 (yingying.site - blocked) Executing cluster transition: * Pseudo action: group1_stop_0 Revised cluster status: Online: [ yingying.site ] Resource Group: group1 - rsc1 (ocf::pacemaker:Dummy): Started yingying.site + rsc1 (ocf::pacemaker:Dummy): (target-role:Stopped) Started yingying.site rsc2 (ocf::pacemaker:Dummy): FAILED yingying.site (unmanaged) - rsc3 (ocf::heartbeat:Dummy): Stopped + rsc3 (ocf::heartbeat:Dummy): (target-role:Stopped) Stopped diff --git a/pengine/test10/use-after-free-merge.summary b/pengine/test10/use-after-free-merge.summary index c4e9ac66bb..2ca2a36ac0 100644 --- a/pengine/test10/use-after-free-merge.summary +++ b/pengine/test10/use-after-free-merge.summary @@ -1,42 +1,42 @@ Current cluster status: Online: [ hex-13 hex-14 ] fencing-sbd (stonith:external/sbd): Stopped Resource Group: g0 - d0 (ocf::heartbeat:Dummy): Stopped - d1 (ocf::heartbeat:Dummy): Stopped + d0 (ocf::heartbeat:Dummy): (target-role:Stopped) Stopped + d1 (ocf::heartbeat:Dummy): (target-role:Stopped) Stopped Master/Slave Set: ms0 [s0] Stopped: [ hex-13 hex-14 ] Transition Summary: * Start fencing-sbd (hex-14) * Start s0:0 (hex-13) * Start s0:1 (hex-14) Executing cluster transition: * Resource action: fencing-sbd monitor on hex-14 * Resource action: fencing-sbd monitor on hex-13 * Resource action: d0 monitor on hex-14 * Resource action: d0 monitor on hex-13 * Resource action: d1 monitor on hex-14 * Resource action: d1 monitor on hex-13 * Resource action: s0:0 monitor on hex-13 * Resource action: s0:1 monitor on hex-14 * Pseudo action: ms0_start_0 * Pseudo action: probe_complete * Resource action: fencing-sbd start on hex-14 * Resource action: s0:0 start on hex-13 * Resource action: s0:1 start on hex-14 * Pseudo action: ms0_running_0 Revised cluster status: Online: [ hex-13 hex-14 ] fencing-sbd (stonith:external/sbd): Started hex-14 Resource Group: g0 - d0 (ocf::heartbeat:Dummy): Stopped - d1 (ocf::heartbeat:Dummy): Stopped + d0 (ocf::heartbeat:Dummy): (target-role:Stopped) Stopped + d1 (ocf::heartbeat:Dummy): (target-role:Stopped) Stopped Master/Slave Set: ms0 [s0] Slaves: [ hex-13 hex-14 ] diff --git a/pengine/test10/utilization-order4.summary b/pengine/test10/utilization-order4.summary index 124483b8db..931546a11e 100644 --- a/pengine/test10/utilization-order4.summary +++ b/pengine/test10/utilization-order4.summary @@ -1,60 +1,60 @@ Current cluster status: Node deglxen002: standby Online: [ deglxen001 ] degllx62-vm (ocf::heartbeat:Xen): Started deglxen002 - degllx63-vm (ocf::heartbeat:Xen): Stopped + degllx63-vm (ocf::heartbeat:Xen): (target-role:Stopped) Stopped degllx61-vm (ocf::heartbeat:Xen): Started deglxen001 - degllx64-vm (ocf::heartbeat:Xen): Stopped + degllx64-vm (ocf::heartbeat:Xen): (target-role:Stopped) Stopped stonith_sbd (stonith:external/sbd): Started deglxen001 Clone Set: clone-nfs [grp-nfs] Started: [ deglxen001 deglxen002 ] Clone Set: clone-ping [prim-ping] Started: [ deglxen001 deglxen002 ] Transition Summary: * Migrate degllx62-vm (Started deglxen002 -> deglxen001) * Stop degllx61-vm (deglxen001) * Stop nfs-xen_config:1 (deglxen002) * Stop nfs-xen_swapfiles:1 (deglxen002) * Stop nfs-xen_images:1 (deglxen002) * Stop prim-ping:1 (deglxen002) Executing cluster transition: * Resource action: degllx61-vm stop on deglxen001 * Pseudo action: load_stopped_deglxen001 * Resource action: degllx62-vm migrate_to on deglxen002 * Resource action: degllx62-vm migrate_from on deglxen001 * Resource action: degllx62-vm stop on deglxen002 * Pseudo action: clone-nfs_stop_0 * Pseudo action: load_stopped_deglxen002 * Pseudo action: degllx62-vm_start_0 * Pseudo action: grp-nfs:1_stop_0 * Resource action: nfs-xen_images:1 stop on deglxen002 * Resource action: degllx62-vm monitor=30000 on deglxen001 * Resource action: nfs-xen_swapfiles:1 stop on deglxen002 * Resource action: nfs-xen_config:1 stop on deglxen002 * Pseudo action: grp-nfs:1_stopped_0 * Pseudo action: clone-nfs_stopped_0 * Pseudo action: clone-ping_stop_0 * Resource action: prim-ping:0 stop on deglxen002 * Pseudo action: clone-ping_stopped_0 * Pseudo action: all_stopped Revised cluster status: Node deglxen002: standby Online: [ deglxen001 ] degllx62-vm (ocf::heartbeat:Xen): Started deglxen001 - degllx63-vm (ocf::heartbeat:Xen): Stopped + degllx63-vm (ocf::heartbeat:Xen): (target-role:Stopped) Stopped degllx61-vm (ocf::heartbeat:Xen): Stopped deglxen002 - degllx64-vm (ocf::heartbeat:Xen): Stopped + degllx64-vm (ocf::heartbeat:Xen): (target-role:Stopped) Stopped stonith_sbd (stonith:external/sbd): Started deglxen001 Clone Set: clone-nfs [grp-nfs] Started: [ deglxen001 ] Stopped: [ deglxen002 ] Clone Set: clone-ping [prim-ping] Started: [ deglxen001 ] Stopped: [ deglxen002 ] diff --git a/pengine/test10/whitebox-asymmetric.summary b/pengine/test10/whitebox-asymmetric.summary index 1a688022bc..6a562a4855 100644 --- a/pengine/test10/whitebox-asymmetric.summary +++ b/pengine/test10/whitebox-asymmetric.summary @@ -1,34 +1,34 @@ Current cluster status: Online: [ 18builder ] fence_false (stonith:fence_false): Stopped container2 (ocf::pacemaker:Dummy): Started 18builder webserver (ocf::pacemaker:Dummy): Stopped nfs_mount (ocf::pacemaker:Dummy): Stopped Resource Group: mygroup - vg_tags (ocf::heartbeat:LVM): Stopped + vg_tags (ocf::heartbeat:LVM): (target-role:Stopped) Stopped vg_tags_dup (ocf::heartbeat:LVM): Stopped Transition Summary: * Start nfs_mount (18node2) * Start 18node2 (18builder) Executing cluster transition: * Resource action: 18node2 start on 18builder * Resource action: nfs_mount start on 18node2 * Resource action: 18node2 monitor=30000 on 18builder * Resource action: nfs_mount monitor=10000 on 18node2 Revised cluster status: Online: [ 18builder ] Containers: [ 18node2:container2 ] fence_false (stonith:fence_false): Stopped container2 (ocf::pacemaker:Dummy): Started 18builder webserver (ocf::pacemaker:Dummy): Stopped nfs_mount (ocf::pacemaker:Dummy): Started 18node2 Resource Group: mygroup - vg_tags (ocf::heartbeat:LVM): Stopped + vg_tags (ocf::heartbeat:LVM): (target-role:Stopped) Stopped vg_tags_dup (ocf::heartbeat:LVM): Stopped diff --git a/pengine/test10/whitebox-stop.summary b/pengine/test10/whitebox-stop.summary index 51357b9552..7925de1bf9 100644 --- a/pengine/test10/whitebox-stop.summary +++ b/pengine/test10/whitebox-stop.summary @@ -1,47 +1,47 @@ Current cluster status: Online: [ 18node1 18node2 18node3 ] Containers: [ lxc1:container1 lxc2:container2 ] - container1 (ocf::heartbeat:VirtualDomain): Started 18node2 + container1 (ocf::heartbeat:VirtualDomain): (target-role:Stopped) Started 18node2 container2 (ocf::heartbeat:VirtualDomain): Started 18node2 shoot1 (stonith:fence_xvm): Started 18node3 Clone Set: M-clone [M] Started: [ 18node1 18node2 18node3 lxc1 lxc2 ] A (ocf::pacemaker:Dummy): Started 18node1 B (ocf::pacemaker:Dummy): Started lxc1 C (ocf::pacemaker:Dummy): Started lxc2 D (ocf::pacemaker:Dummy): Started 18node1 Transition Summary: * Stop container1 (18node2) * Stop M:4 (lxc1) * Move B (Started lxc1 -> lxc2) * Stop lxc1 (18node2) Executing cluster transition: * Pseudo action: M-clone_stop_0 * Resource action: B stop on lxc1 * Resource action: M stop on lxc1 * Pseudo action: M-clone_stopped_0 * Resource action: B start on lxc2 * Resource action: lxc1 stop on 18node2 * Resource action: container1 stop on 18node2 * Resource action: B monitor=10000 on lxc2 * Pseudo action: all_stopped Revised cluster status: Online: [ 18node1 18node2 18node3 ] Containers: [ lxc2:container2 ] - container1 (ocf::heartbeat:VirtualDomain): Stopped + container1 (ocf::heartbeat:VirtualDomain): (target-role:Stopped) Stopped container2 (ocf::heartbeat:VirtualDomain): Started 18node2 shoot1 (stonith:fence_xvm): Started 18node3 Clone Set: M-clone [M] Started: [ 18node1 18node2 18node3 lxc2 ] Stopped: [ lxc1 ] A (ocf::pacemaker:Dummy): Started 18node1 B (ocf::pacemaker:Dummy): Started lxc2 C (ocf::pacemaker:Dummy): Started lxc2 D (ocf::pacemaker:Dummy): Started 18node1