diff --git a/attrd/commands.c b/attrd/commands.c index 18c0523..c6586c7 100644 --- a/attrd/commands.c +++ b/attrd/commands.c @@ -832,7 +832,6 @@ attrd_cib_callback(xmlNode * msg, int call_id, int rc, xmlNode * output, void *u } } done: - free(name); if(a && a->changed && election_state(writer) == election_won) { write_attribute(a); } @@ -1019,8 +1018,10 @@ write_attribute(attribute_t *a) crm_info("Sent update %d with %d changes for %s, id=%s, set=%s", a->update, cib_updates, a->id, (a->uuid? a->uuid : ""), a->set); - the_cib->cmds->register_callback( - the_cib, a->update, 120, FALSE, strdup(a->id), "attrd_cib_callback", attrd_cib_callback); + the_cib->cmds->register_callback_full(the_cib, a->update, 120, FALSE, + strdup(a->id), + "attrd_cib_callback", + attrd_cib_callback, free); } free_xml(xml_top); } diff --git a/attrd/legacy.c b/attrd/legacy.c index 4aae4c4..8a18c38 100644 --- a/attrd/legacy.c +++ b/attrd/legacy.c @@ -635,6 +635,20 @@ struct attrd_callback_s { char *value; }; +/* + * \internal + * \brief Free an attrd callback structure + */ +static void +free_attrd_callback(void *user_data) +{ + struct attrd_callback_s *data = user_data; + + free(data->attr); + free(data->value); + free(data); +} + static void attrd_cib_callback(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data) { @@ -646,7 +660,7 @@ attrd_cib_callback(xmlNode * msg, int call_id, int rc, xmlNode * output, void *u } else if (call_id < 0) { crm_warn("Update %s=%s failed: %s", data->attr, data->value, pcmk_strerror(call_id)); - goto cleanup; + return; } switch (rc) { @@ -674,10 +688,6 @@ attrd_cib_callback(xmlNode * msg, int call_id, int rc, xmlNode * output, void *u crm_err("Update %d for %s=%s failed: %s", call_id, data->attr, data->value, pcmk_strerror(rc)); } - cleanup: - free(data->value); - free(data->attr); - free(data); } void @@ -749,8 +759,10 @@ attrd_perform_update(attr_hash_entry_t * hash_entry) if (hash_entry->value != NULL) { data->value = strdup(hash_entry->value); } - cib_conn->cmds->register_callback(cib_conn, rc, 120, FALSE, data, "attrd_cib_callback", - attrd_cib_callback); + cib_conn->cmds->register_callback_full(cib_conn, rc, 120, FALSE, data, + "attrd_cib_callback", + attrd_cib_callback, + free_attrd_callback); return; } diff --git a/bumplibs.sh b/bumplibs.sh index 68f2f58..2044efa 100755 --- a/bumplibs.sh +++ b/bumplibs.sh @@ -3,6 +3,7 @@ declare -A headers headers[crmcommon]="include/crm/common include/crm/crm.h" headers[crmcluster]="include/crm/cluster.h" +headers[crmservice]="include/crm/services.h" headers[transitioner]="include/crm/transition.h" headers[cib]="include/crm/cib.h include/crm/cib/util.h" headers[pe_rules]="include/crm/pengine/rules.h" @@ -11,8 +12,17 @@ headers[pengine]="include/crm/pengine/common.h include/crm/pengine/complex.h i headers[stonithd]="include/crm/stonith-ng.h" headers[lrmd]="include/crm/lrmd.h" -LAST_RELEASE=`test -e /Volumes || git tag -l | grep Pacemaker | grep -v rc | sort -Vr | head -n 1` -for lib in crmcommon crmcluster transitioner cib pe_rules pe_status stonithd pengine lrmd; do +if [ ! -z $1 ]; then + LAST_RELEASE=$1 +else + LAST_RELEASE=`test -e /Volumes || git tag -l | grep Pacemaker | grep -v rc | sort -Vr | head -n 1` +fi +libs=$(find . -name "*.am" -exec grep "lib.*_la_LDFLAGS.*version-info" \{\} \; | sed -e s/_la_LDFLAGS.*// -e s/^lib//) +for lib in $libs; do + if [ -z "${headers[$lib]}" ]; then + echo "Unknown headers for lib$lib" + exit 0 + fi git diff -w $LAST_RELEASE..HEAD ${headers[$lib]} echo "" @@ -27,6 +37,7 @@ for lib in crmcommon crmcluster transitioner cib pe_rules pe_status stonithd pen fi sources=`grep "lib${lib}_la_SOURCES" $am | sed s/.*=// | sed 's:$(top_builddir)/::' | sed 's:$(top_srcdir)/::' | sed 's:\\\::' | sed 's:$(libpe_rules_la_SOURCES):rules.c\ common.c:'` + full_sources="" for f in $sources; do if @@ -48,6 +59,11 @@ for lib in crmcommon crmcluster transitioner cib pe_rules pe_status stonithd pen echo "" echo "New arguments to functions or changes to the middle of structs are incompatible additions" echo "" + echo "Where possible:" + echo "- move new fields to the end of structs" + echo "- use bitfields instead of booleans" + echo "- when adding arguments, create new functions that the old version can call" + echo "" read -p "Are the changes to lib$lib: [a]dditions, [i]ncompatible additions, [r]emovals or [f]ixes? [None]: " CHANGE git show $LAST_RELEASE:$am | grep version-info diff --git a/cib/callbacks.c b/cib/callbacks.c index 1452ded..28844b8 100644 --- a/cib/callbacks.c +++ b/cib/callbacks.c @@ -1570,7 +1570,7 @@ static gboolean cib_force_exit(gpointer data) { crm_notice("Forcing exit!"); - terminate_cib(__FUNCTION__, TRUE); + terminate_cib(__FUNCTION__, -1); return FALSE; } @@ -1656,7 +1656,7 @@ initiate_exit(void) active = crm_active_peers(); if (active < 2) { - terminate_cib(__FUNCTION__, FALSE); + terminate_cib(__FUNCTION__, 0); return; } @@ -1675,9 +1675,19 @@ initiate_exit(void) extern int remote_fd; extern int remote_tls_fd; +/* + * \internal + * \brief Close remote sockets, free the global CIB and quit + * + * \param[in] caller Name of calling function (for log message) + * \param[in] fast If 1, skip disconnect; if -1, also exit error + */ void -terminate_cib(const char *caller, gboolean fast) +terminate_cib(const char *caller, int fast) { + crm_info("%s: Exiting%s...", caller, + (fast < 0)? " fast" : mainloop ? " from mainloop" : ""); + if (remote_fd > 0) { close(remote_fd); remote_fd = 0; @@ -1687,27 +1697,29 @@ terminate_cib(const char *caller, gboolean fast) 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 < 0) { + /* Quit fast on error */ + cib_ipc_servers_destroy(ipcs_ro, ipcs_rw, ipcs_shm); + crm_exit(EINVAL); - if (fast == FALSE && mainloop != NULL && g_main_is_running(mainloop)) { + } else if ((mainloop != NULL) && g_main_is_running(mainloop)) { + /* Quit via returning from the main loop. If fast == 1, we skip the + * disconnect here, and it will be done when the main loop returns + * (this allows the peer status callback to avoid messing with the + * peer caches). + */ + if (fast == 0) { + crm_cluster_disconnect(&crm_cluster); + } 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); - } + /* Quit via clean exit. Even the peer status callback can disconnect + * here, because we're not returning control to the caller. */ + crm_cluster_disconnect(&crm_cluster); + cib_ipc_servers_destroy(ipcs_ro, ipcs_rw, ipcs_shm); + crm_exit(pcmk_ok); } } diff --git a/cib/callbacks.h b/cib/callbacks.h index bca9992..a49428e 100644 --- a/cib/callbacks.h +++ b/cib/callbacks.h @@ -71,7 +71,7 @@ extern void cib_common_callback_worker(uint32_t id, uint32_t flags, xmlNode * op void cib_shutdown(int nsig); void initiate_exit(void); -void terminate_cib(const char *caller, gboolean fast); +void terminate_cib(const char *caller, int fast); extern gboolean cib_legacy_mode(void); diff --git a/cib/main.c b/cib/main.c index e20a2b6..cbaf7b5 100644 --- a/cib/main.c +++ b/cib/main.c @@ -71,8 +71,6 @@ gboolean cib_register_ha(ll_cluster_t * hb_cluster, const char *client_name); void *hb_conn = NULL; #endif -extern void terminate_cib(const char *caller, gboolean fast); - GMainLoop *mainloop = NULL; const char *cib_root = NULL; char *cib_our_uname = NULL; @@ -414,7 +412,7 @@ cib_cs_destroy(gpointer user_data) crm_info("Corosync disconnection complete"); } else { crm_err("Corosync connection lost! Exiting."); - terminate_cib(__FUNCTION__, TRUE); + terminate_cib(__FUNCTION__, -1); } } #endif @@ -422,30 +420,29 @@ cib_cs_destroy(gpointer user_data) static void cib_peer_update_callback(enum crm_status_type type, crm_node_t * node, const void *data) { - if ((type == crm_status_processes) && legacy_mode - && is_not_set(node->processes, crm_get_cluster_proc())) { - uint32_t old = 0; - - if (data) { - old = *(const uint32_t *)data; - } + switch (type) { + case crm_status_processes: + if (legacy_mode && is_not_set(node->processes, crm_get_cluster_proc())) { + uint32_t old = data? *(const uint32_t *)data : 0; + + if ((node->processes ^ old) & crm_proc_cpg) { + crm_info("Attempting to disable legacy mode after %s left the cluster", + node->uname); + legacy_mode = FALSE; + } + } + break; - if ((node->processes ^ old) & crm_proc_cpg) { - crm_info("Attempting to disable legacy mode after %s left the cluster", node->uname); - legacy_mode = FALSE; - } - } + case crm_status_uname: + case crm_status_rstate: + case crm_status_nstate: + if (cib_shutdown_flag && (crm_active_peers() < 2) + && crm_hash_table_size(client_connections) == 0) { - if (cib_shutdown_flag && crm_active_peers() < 2 && crm_hash_table_size(client_connections) == 0) { - crm_info("No more peers"); - /* @TODO - * terminate_cib() calls crm_cluster_disconnect() which calls - * crm_peer_destroy() which destroys the peer caches, which a peer - * status callback shouldn't do. For now, there is a workaround in - * crm_update_peer_proc(), but CIB should be refactored to avoid - * destroying the peer caches here. - */ - terminate_cib(__FUNCTION__, FALSE); + crm_info("No more peers"); + terminate_cib(__FUNCTION__, 1); + } + break; } } @@ -455,10 +452,10 @@ cib_ha_connection_destroy(gpointer user_data) { if (cib_shutdown_flag) { crm_info("Heartbeat disconnection complete... exiting"); - terminate_cib(__FUNCTION__, FALSE); + terminate_cib(__FUNCTION__, 0); } else { crm_err("Heartbeat connection lost! Exiting."); - terminate_cib(__FUNCTION__, TRUE); + terminate_cib(__FUNCTION__, -1); } } #endif @@ -541,8 +538,12 @@ cib_init(void) /* Create the mainloop and run it... */ mainloop = g_main_new(FALSE); crm_info("Starting %s mainloop", crm_system_name); - g_main_run(mainloop); + + /* If main loop returned, clean up and exit. We disconnect in case + * terminate_cib() was called with fast=1. + */ + crm_cluster_disconnect(&crm_cluster); cib_ipc_servers_destroy(ipcs_ro, ipcs_rw, ipcs_shm); return crm_exit(pcmk_ok); diff --git a/cib/messages.c b/cib/messages.c index 363562c..eca63b9 100644 --- a/cib/messages.c +++ b/cib/messages.c @@ -87,7 +87,7 @@ cib_process_shutdown_req(const char *op, int options, const char *section, xmlNo } else if (cib_shutdown_flag) { crm_info("Shutdown ACK from %s", host); - terminate_cib(__FUNCTION__, FALSE); + terminate_cib(__FUNCTION__, 0); return pcmk_ok; } else { diff --git a/crmd/crmd_utils.h b/crmd/crmd_utils.h index 78ccad2..78214bf 100644 --- a/crmd/crmd_utils.h +++ b/crmd/crmd_utils.h @@ -102,11 +102,14 @@ gboolean too_many_st_failures(void); void st_fail_count_reset(const char * target); void crmd_peer_down(crm_node_t *peer, bool full); +/* Convenience macro for registering a CIB callback + * (assumes that data can be freed with free()) + */ # define fsa_register_cib_callback(id, flag, data, fn) do { \ CRM_ASSERT(fsa_cib_conn); \ - fsa_cib_conn->cmds->register_callback( \ + fsa_cib_conn->cmds->register_callback_full( \ fsa_cib_conn, id, 10 * (1 + crm_active_peers()), \ - flag, data, #fn, fn); \ + flag, data, #fn, fn, free); \ } while(0) # define start_transition(state) do { \ diff --git a/crmd/join_client.c b/crmd/join_client.c index 286cd92..65e3bed 100644 --- a/crmd/join_client.c +++ b/crmd/join_client.c @@ -116,8 +116,8 @@ do_cl_join_offer_respond(long long action, /* we only ever want the last one */ if (query_call_id > 0) { - /* Calling remove_cib_op_callback() would result in a memory leak of the data field */ crm_trace("Cancelling previous join query: %d", query_call_id); + remove_cib_op_callback(query_call_id, FALSE); query_call_id = 0; } @@ -173,7 +173,6 @@ join_query_callback(xmlNode * msg, int call_id, int rc, xmlNode * output, void * done: free_xml(generation); - free(join_id); } /* A_CL_JOIN_RESULT */ diff --git a/crmd/join_dc.c b/crmd/join_dc.c index f777296..5280b6e 100644 --- a/crmd/join_dc.c +++ b/crmd/join_dc.c @@ -452,8 +452,6 @@ finalize_sync_callback(xmlNode * msg, int call_id, int rc, xmlNode * output, voi crm_debug("No longer the DC in S_FINALIZE_JOIN: %s/%s", AM_I_DC ? "DC" : "CRMd", fsa_state2string(fsa_state)); } - - free(user_data); } static void diff --git a/crmd/lrm_state.c b/crmd/lrm_state.c index 162ad03..c03fa0b 100644 --- a/crmd/lrm_state.c +++ b/crmd/lrm_state.c @@ -490,7 +490,7 @@ remote_proxy_cb(lrmd_t *lrmd, void *userdata, xmlNode *msg) if (remote_proxy_new(lrm_state->node_name, session, channel) == NULL) { remote_proxy_notify_destroy(lrmd, session); } - crm_info("new remote proxy client established to %s, session id %s", channel, session); + crm_trace("new remote proxy client established to %s, session id %s", channel, session); } else if (safe_str_eq(op, "destroy")) { remote_proxy_end_session(session); @@ -534,7 +534,16 @@ remote_proxy_cb(lrmd_t *lrmd, void *userdata, xmlNode *msg) } } else if(is_set(flags, crm_ipc_proxied)) { - int rc = crm_ipc_send(proxy->ipc, request, flags, 5000, NULL); + const char *type = crm_element_value(request, F_TYPE); + int rc = 0; + + if (safe_str_eq(type, T_ATTRD) + && crm_element_value(request, F_ATTRD_HOST) == NULL) { + crm_xml_add(request, F_ATTRD_HOST, proxy->node_name); + crm_xml_add_int(request, F_ATTRD_HOST_ID, get_local_nodeid(0)); + } + + rc = crm_ipc_send(proxy->ipc, request, flags, 5000, NULL); if(rc < 0) { xmlNode *op_reply = create_xml_node(NULL, "nack"); diff --git a/crmd/membership.c b/crmd/membership.c index 447e6a8..27ae710 100644 --- a/crmd/membership.c +++ b/crmd/membership.c @@ -200,7 +200,6 @@ remove_conflicting_node_callback(xmlNode * msg, int call_id, int rc, 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 @@ -215,11 +214,9 @@ search_conflicting_node_callback(xmlNode * msg, int call_id, int rc, 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; } @@ -283,8 +280,6 @@ search_conflicting_node_callback(xmlNode * msg, int call_id, int rc, free_xml(node_state_xml); } } - - free(new_node_uuid); } static void diff --git a/crmd/pengine.c b/crmd/pengine.c index c9544a9..46df648 100644 --- a/crmd/pengine.c +++ b/crmd/pengine.c @@ -77,8 +77,6 @@ save_cib_contents(xmlNode * msg, int call_id, int rc, xmlNode * output, void *us free(filename); } - - free(id); } static void @@ -320,9 +318,10 @@ do_pe_invoke_callback(xmlNode * msg, int call_id, int rc, xmlNode * output, void crm_debug("Discarding PE request in state: %s", fsa_state2string(fsa_state)); return; - } else if (num_cib_op_callbacks() != 0) { - crm_debug("Re-asking for the CIB: %d peer updates still pending", num_cib_op_callbacks()); - + /* this callback counts as 1 */ + } else if (num_cib_op_callbacks() > 1) { + crm_debug("Re-asking for the CIB: %d other peer updates still pending", + (num_cib_op_callbacks() - 1)); sleep(1); register_fsa_action(A_PE_INVOKE); return; diff --git a/crmd/te_callbacks.c b/crmd/te_callbacks.c index 68742c2..c22b273 100644 --- a/crmd/te_callbacks.c +++ b/crmd/te_callbacks.c @@ -294,6 +294,49 @@ static char *get_node_from_xpath(const char *xpath) return nodeid; } +static char *extract_node_uuid(const char *xpath) +{ + char *mutable_path = strdup(xpath); + char *node_uuid = NULL; + char *search = NULL; + char *match = NULL; + + match = strstr(mutable_path, "node_state[@id=\'") + strlen("node_state[@id=\'"); + search = strchr(match, '\''); + search[0] = 0; + + node_uuid = strdup(match); + free(mutable_path); + return node_uuid; +} + +static void abort_unless_down(const char *xpath, const char *op, xmlNode *change, const char *reason) +{ + char *node_uuid = NULL; + crm_action_t *down = NULL; + + if(safe_str_neq(op, "delete")) { + abort_transition(INFINITY, tg_restart, reason, change); + return; + } + + node_uuid = extract_node_uuid(xpath); + if(node_uuid == NULL) { + crm_err("Could not extract node ID from %s", xpath); + abort_transition(INFINITY, tg_restart, reason, change); + return; + } + + down = match_down_event(0, node_uuid, NULL, FALSE); + if(down == NULL || down->executed == false) { + crm_trace("Not expecting %s to be down (%s)", node_uuid, xpath); + abort_transition(INFINITY, tg_restart, reason, change); + } else { + crm_trace("Expecting changes to %s (%s)", node_uuid, xpath); + } + free(node_uuid); +} + void te_update_diff(const char *event, xmlNode * msg) { @@ -388,27 +431,22 @@ te_update_diff(const char *event, xmlNode * msg) break; /* Wont be packaged with any resource operations we may be waiting for */ } else if(strstr(xpath, "/"XML_TAG_TRANSIENT_NODEATTRS"[") || safe_str_eq(name, XML_TAG_TRANSIENT_NODEATTRS)) { - abort_transition(INFINITY, tg_restart, "Transient attribute change", change); + abort_unless_down(xpath, op, change, "Transient attribute change"); break; /* Wont be packaged with any resource operations we may be waiting for */ } else if(strstr(xpath, "/"XML_LRM_TAG_RSC_OP"[") && safe_str_eq(op, "delete")) { crm_action_t *cancel = NULL; char *mutable_key = strdup(xpath); - char *mutable_node = strdup(xpath); char *search = NULL; const char *key = NULL; - const char *node_uuid = NULL; + char *node_uuid = extract_node_uuid(xpath); search = strrchr(mutable_key, '\''); search[0] = 0; key = strrchr(mutable_key, '\'') + 1; - node_uuid = strstr(mutable_node, "node_state[@id=\'") + strlen("node_state[@id=\'"); - search = strchr(node_uuid, '\''); - search[0] = 0; - cancel = get_cancel_action(key, node_uuid); if (cancel == NULL) { abort_transition(INFINITY, tg_restart, "Resource operation removal", change); @@ -422,14 +460,14 @@ te_update_diff(const char *event, xmlNode * msg) trigger_graph(); } - free(mutable_node); free(mutable_key); + free(node_uuid); } else if(strstr(xpath, "/"XML_CIB_TAG_LRM"[") && safe_str_eq(op, "delete")) { - abort_transition(INFINITY, tg_restart, "Resource state removal", change); + abort_unless_down(xpath, op, change, "Resource state removal"); } else if(strstr(xpath, "/"XML_CIB_TAG_STATE"[") && safe_str_eq(op, "delete")) { - abort_transition(INFINITY, tg_restart, "Node state removal", change); + abort_unless_down(xpath, op, change, "Node state removal"); } else if(name == NULL) { crm_debug("No result for %s operation to %s", op, xpath); @@ -717,7 +755,6 @@ cib_fencing_updated(xmlNode * msg, int call_id, int rc, xmlNode * output, void * } else { crm_info("Fencing update %d for %s: complete", call_id, (char *)user_data); } - free(user_data); } void diff --git a/crmd/utils.c b/crmd/utils.c index 5ca4b9d..4fe3a49 100644 --- a/crmd/utils.c +++ b/crmd/utils.c @@ -999,7 +999,6 @@ erase_xpath_callback(xmlNode * msg, int call_id, int rc, xmlNode * output, void do_crm_log_unlikely(rc == 0 ? LOG_DEBUG : LOG_NOTICE, "Deletion of \"%s\": %s (rc=%d)", xpath, pcmk_strerror(rc), rc); - free(xpath); } void diff --git a/cts/CIB.py b/cts/CIB.py index 82d02d7..8fbba6c 100644 --- a/cts/CIB.py +++ b/cts/CIB.py @@ -105,7 +105,7 @@ class CIB11(ConfigBase): if not name: name = "r%s%d" % (self.CM.Env["IPagent"], self.counter) self.counter = self.counter + 1 - r = Resource(self.Factory, name, self.CM.Env["IPagent"], standard) + r = Resource(self.Factory, name, self.CM.Env["IPagent"], standard) r.add_op("monitor", "5s") return r @@ -387,7 +387,7 @@ class ConfigFactory: """register a constructor""" _args = [constructor] _args.extend(args) - setattr(self, methodName, apply(ConfigFactoryItem,_args, kargs)) + setattr(self, methodName, ConfigFactoryItem(*_args, **kargs)) def unregister(self, methodName): """unregister a constructor""" @@ -415,7 +415,6 @@ class ConfigFactory: class ConfigFactoryItem: def __init__(self, function, *args, **kargs): - assert callable(function), "function should be a callable obj" self._function = function self._args = args self._kargs = kargs @@ -426,7 +425,7 @@ class ConfigFactoryItem: _args.extend(args) _kargs = self._kargs.copy() _kargs.update(kargs) - return apply(self._function,_args,_kargs) + return self._function(*_args,**_kargs) # Basic Sanity Testing if __name__ == '__main__': @@ -449,4 +448,4 @@ if __name__ == '__main__': CibFactory = ConfigFactory(manager) cib = CibFactory.createConfig("pacemaker-1.1") - print cib.contents() + print(cib.contents()) diff --git a/cts/CM_ais.py b/cts/CM_ais.py index a34f9b1..d2e2c1f 100644 --- a/cts/CM_ais.py +++ b/cts/CM_ais.py @@ -80,7 +80,7 @@ class crm_ais(crm_lha): # Processes running under valgrind can't be shot with "killall -9 processname", # so don't include them in the returned list vgrind = self.Env["valgrind-procs"].split() - for key in self.fullcomplist.keys(): + for key in list(self.fullcomplist.keys()): if self.Env["valgrind-tests"]: if key in vgrind: self.log("Filtering %s from the component list as it is being profiled by valgrind" % key) diff --git a/cts/CM_lha.py b/cts/CM_lha.py index b192272..28742d9 100755 --- a/cts/CM_lha.py +++ b/cts/CM_lha.py @@ -92,7 +92,7 @@ class crm_lha(ClusterManager): self.log("Node %s is not up." % node) return None - if not self.CIBsync.has_key(node) and self.Env["ClobberCIB"] == 1: + if not node in self.CIBsync and self.Env["ClobberCIB"] == 1: self.CIBsync[node] = 1 self.rsh(node, "rm -f "+CTSvars.CRM_CONFIG_DIR+"/cib*") diff --git a/cts/CTS.py b/cts/CTS.py index 9f9a291..634348a 100644 --- a/cts/CTS.py +++ b/cts/CTS.py @@ -69,7 +69,7 @@ function status() { function start() { # Is it already running? if - status + status then return fi @@ -94,20 +94,20 @@ case $action in nohup $0 $f start >/dev/null 2>&1 > $f - echo " $*" >> $f + uptime | sed s/up.*:/,/ | tr '\\n' ',' >> $f + echo " $*" >> $f start - ;; + ;; *) - echo "Unknown action: $action." - ;; + echo "Unknown action: $action." + ;; esac """ @@ -157,7 +157,7 @@ class CtsLab: self.Env.dump() def has_key(self, key): - return self.Env.has_key(key) + return key in self.Env.keys() def __getitem__(self, key): return self.Env[key] @@ -275,7 +275,7 @@ class ClusterManager(UserDict): None def _finalConditions(self): - for key in self.keys(): + for key in list(self.keys()): if self[key] == None: raise ValueError("Improper derivation: self[" + key + "] must be overridden by subclass.") @@ -299,14 +299,14 @@ class ClusterManager(UserDict): if key == "Name": return self.name - print "FIXME: Getting %s from %s" % (key, repr(self)) - if self.data.has_key(key): + print("FIXME: Getting %s from %s" % (key, repr(self))) + if key in self.data: return self.data[key] return self.templates.get_patterns(self.Env["Name"], key) def __setitem__(self, key, value): - print "FIXME: Setting %s=%s on %s" % (key, value, repr(self)) + print("FIXME: Setting %s=%s on %s" % (key, value, repr(self))) self.data[key] = value def key_for_node(self, node): @@ -333,7 +333,7 @@ class ClusterManager(UserDict): def prepare(self): '''Finish the Initialization process. Prepare to test...''' - print repr(self)+"prepare" + print(repr(self)+"prepare") for node in self.Env["nodes"]: if self.StataCM(node): self.ShouldBeStatus[node] = "up" @@ -387,11 +387,11 @@ class ClusterManager(UserDict): return None if not self.templates["Pat:Fencing_start"]: - print "No start pattern" + print("No start pattern") return None if not self.templates["Pat:Fencing_ok"]: - print "No ok pattern" + print("No ok pattern") return None stonith = None @@ -500,7 +500,7 @@ class ClusterManager(UserDict): else: self.debug("Starting %s on node %s" % (self.templates["Name"], node)) ret = 1 - if not self.ShouldBeStatus.has_key(node): + if not node in self.ShouldBeStatus: self.ShouldBeStatus[node] = "down" if self.ShouldBeStatus[node] != "down": @@ -871,13 +871,13 @@ class ClusterManager(UserDict): for host in self.Env["nodes"]: log_stats_file = "%s/cts-stats.csv" % CTSvars.CRM_DAEMON_DIR - if has_log_stats.has_key(host): + if host in has_log_stats: self.rsh(host, '''bash %s %s stop''' % (log_stats_bin, log_stats_file)) (rc, lines) = self.rsh(host, '''cat %s''' % log_stats_file, stdout=2) self.rsh(host, '''bash %s %s delete''' % (log_stats_bin, log_stats_file)) fname = "cts-stats-%d-nodes-%s.csv" % (len(self.Env["nodes"]), host) - print "Extracted stats: %s" % fname + print("Extracted stats: %s" % fname) fd = open(fname, "a") fd.writelines(lines) fd.close() @@ -891,7 +891,7 @@ class ClusterManager(UserDict): for host in self.Env["nodes"]: log_stats_file = "%s/cts-stats.csv" % CTSvars.CRM_DAEMON_DIR - if not has_log_stats.has_key(host): + if not host in has_log_stats: global log_stats global log_stats_bin @@ -986,7 +986,7 @@ class Process(Component): self.CM = cm self.badnews_ignore = badnews_ignore self.badnews_ignore.extend(common_ignore) - self.triggersreboot = triggersreboot + self.triggersreboot = triggersreboot if process: self.proc = str(process) diff --git a/cts/CTSaudits.py b/cts/CTSaudits.py index 8d52062..e8663f2 100755 --- a/cts/CTSaudits.py +++ b/cts/CTSaudits.py @@ -108,7 +108,7 @@ class LogAudit(ClusterAudit): self.CM.log ("ERROR: Cannot execute remote command [%s] on %s" % (cmd, node)) for k in self.kinds: - if watch.has_key(k): + if k in watch: w = watch[k] if watch_pref == "any": self.CM.log("Testing for %s logs" % (k)) w.lookforall(silent=True) @@ -118,7 +118,7 @@ class LogAudit(ClusterAudit): self.CM.Env["LogWatcher"] = w.kind return 1 - for k in watch.keys(): + for k in list(watch.keys()): w = watch[k] if w.unmatched: for regex in w.unmatched: @@ -226,7 +226,7 @@ class FileAudit(ClusterAudit): self.known.append(line) self.CM.log("Warning: Corosync core file on %s: %s" % (node, line)) - if self.CM.ShouldBeStatus.has_key(node) and self.CM.ShouldBeStatus[node] == "down": + if node in self.CM.ShouldBeStatus and self.CM.ShouldBeStatus[node] == "down": clean = 0 (rc, lsout) = self.CM.rsh(node, "ls -al /dev/shm | grep qb-", None) for line in lsout: @@ -532,7 +532,7 @@ class CrmdStateAudit(ClusterAudit): , "auditfail":0} def has_key(self, key): - return self.Stats.has_key(key) + return key in self.Stats def __setitem__(self, key, value): self.Stats[key] = value @@ -542,7 +542,7 @@ class CrmdStateAudit(ClusterAudit): def incr(self, name): '''Increment (or initialize) the value associated with the given name''' - if not self.Stats.has_key(name): + if not name in self.Stats: self.Stats[name] = 0 self.Stats[name] = self.Stats[name]+1 @@ -601,7 +601,7 @@ class CIBAudit(ClusterAudit): , "auditfail":0} def has_key(self, key): - return self.Stats.has_key(key) + return key in self.Stats def __setitem__(self, key, value): self.Stats[key] = value @@ -611,7 +611,7 @@ class CIBAudit(ClusterAudit): def incr(self, name): '''Increment (or initialize) the value associated with the given name''' - if not self.Stats.has_key(name): + if not name in self.Stats: self.Stats[name] = 0 self.Stats[name] = self.Stats[name]+1 @@ -726,7 +726,7 @@ class PartitionAudit(ClusterAudit): def incr(self, name): '''Increment (or initialize) the value associated with the given name''' - if not self.Stats.has_key(name): + if not name in self.Stats: self.Stats[name] = 0 self.Stats[name] = self.Stats[name]+1 diff --git a/cts/CTSscenarios.py b/cts/CTSscenarios.py index 2f3a69b..cc6e67e 100644 --- a/cts/CTSscenarios.py +++ b/cts/CTSscenarios.py @@ -124,7 +124,7 @@ A partially set up scenario is torn down if it fails during setup. def incr(self, name): '''Increment (or initialize) the value associated with the given name''' - if not self.Stats.has_key(name): + if not name in self.Stats: self.Stats[name] = 0 self.Stats[name] = self.Stats[name]+1 @@ -176,7 +176,7 @@ A partially set up scenario is torn down if it fails during setup. elapsed_time = stoptime - starttime test_time = stoptime - test.get_timer() - if not test.has_key("min_time"): + if not test["min_time"]: test["elapsed_time"] = elapsed_time test["min_time"] = test_time test["max_time"] = test_time @@ -211,7 +211,7 @@ A partially set up scenario is torn down if it fails during setup. } self.ClusterManager.log("Test Summary") for test in self.Tests: - for key in stat_filter.keys(): + for key in list(stat_filter.keys()): stat_filter[key] = test.Stats[key] self.ClusterManager.log(("Test %s: "%test.name).ljust(25) + " %s"%repr(stat_filter)) @@ -387,7 +387,7 @@ According to the manual page for ping: '''Start the PingFest!''' self.PingSize = 1024 - if CM.Env.has_key("PingSize"): + if "PingSize" in CM.Env.keys(): self.PingSize = CM.Env["PingSize"] CM.log("Starting %d byte flood pings" % self.PingSize) @@ -550,7 +550,7 @@ Test a rolling upgrade between two versions of the stack return self.install(node, self.CM.Env["previous-version"]) def SetUp(self, CM): - print repr(self)+"prepare" + print(repr(self)+"prepare") CM.prepare() # Clear out the cobwebs diff --git a/cts/CTStests.py b/cts/CTStests.py index f817004..00fcd13 100644 --- a/cts/CTStests.py +++ b/cts/CTStests.py @@ -97,13 +97,18 @@ class CTSTest: self.logger.debug(args) def has_key(self, key): - return self.Stats.has_key(key) + return key in self.Stats def __setitem__(self, key, value): self.Stats[key] = value def __getitem__(self, key): - return self.Stats[key] + if str(key) == "0": + raise ValueError("Bad call to 'foo in X', should reference 'foo in X.Stats' instead") + + if key in self.Stats: + return self.Stats[key] + return None def log_mark(self, msg): self.debug("MARK: test %s %s %d" % (self.name,msg,time.time())) @@ -128,7 +133,7 @@ class CTSTest: def incr(self, name): '''Increment (or initialize) the value associated with the given name''' - if not self.Stats.has_key(name): + if not name in self.Stats: self.Stats[name] = 0 self.Stats[name] = self.Stats[name]+1 @@ -534,7 +539,7 @@ class StonithdTest(CTSTest): if not self.is_applicable_common(): return 0 - if self.Env.has_key("DoFencing"): + if "DoFencing" in self.Env.keys(): return self.Env["DoFencing"] return 1 @@ -1048,7 +1053,7 @@ class BandwidthTest(CTSTest): T1 = linesplit[0] timesplit = string.split(T1,":") time2split = string.split(timesplit[2],".") - time1 = (long(timesplit[0])*60+long(timesplit[1]))*60+long(time2split[0])+long(time2split[1])*0.000001 + time1 = (int(timesplit[0])*60+int(timesplit[1]))*60+int(time2split[0])+int(time2split[1])*0.000001 break while count < 100: @@ -1070,7 +1075,7 @@ class BandwidthTest(CTSTest): T2 = linessplit[0] timesplit = string.split(T2,":") time2split = string.split(timesplit[2],".") - time2 = (long(timesplit[0])*60+long(timesplit[1]))*60+long(time2split[0])+long(time2split[1])*0.000001 + time2 = (int(timesplit[0])*60+int(timesplit[1]))*60+int(time2split[0])+int(time2split[1])*0.000001 time = time2-time1 if (time <= 0): return 0 @@ -1105,7 +1110,7 @@ class MaintenanceMode(CTSTest): # fail the resource right after turning Maintenance mode on # verify it is not recovered until maintenance mode is turned off if action == "On": - pats.append("pengine.*: warning:.* Processing failed op %s for %s on" % (self.action, self.rid)) + pats.append(r"pengine.*:\s+warning:.*Processing failed op %s for %s on" % (self.action, self.rid)) else: pats.append(self.templates["Pat:RscOpOK"] % (self.rid, "stop_0")) pats.append(self.templates["Pat:RscOpOK"] % (self.rid, "start_0")) @@ -1314,7 +1319,7 @@ class ResourceRecover(CTSTest): self.debug("Shooting %s aka. %s" % (rsc.clone_id, rsc.id)) pats = [] - pats.append(r"pengine.*: warning:.* Processing failed op %s for (%s|%s) on" % (self.action, + pats.append(r"pengine.*:\s+warning:.*Processing failed op %s for (%s|%s) on" % (self.action, rsc.id, rsc.clone_id)) if rsc.managed(): @@ -1574,7 +1579,7 @@ class SplitBrainTest(CTSTest): p_max = len(self.Env["nodes"]) for node in self.Env["nodes"]: p = self.Env.RandomGen.randint(1, p_max) - if not partitions.has_key(p): + if not p in partitions: partitions[p] = [] partitions[p].append(node) p_max = len(partitions.keys()) @@ -1583,13 +1588,13 @@ class SplitBrainTest(CTSTest): # else, try again self.debug("Created %d partitions" % p_max) - for key in partitions.keys(): + for key in list(partitions.keys()): self.debug("Partition["+str(key)+"]:\t"+repr(partitions[key])) # Disabling STONITH to reduce test complexity for now self.rsh(node, "crm_attribute -V -n stonith-enabled -v false") - for key in partitions.keys(): + for key in list(partitions.keys()): self.isolate_partition(partitions[key]) count = 30 @@ -1612,7 +1617,7 @@ class SplitBrainTest(CTSTest): self.CM.partitions_expected = 1 # And heal them again - for key in partitions.keys(): + for key in list(partitions.keys()): self.heal_partition(partitions[key]) # Wait for a single partition to form @@ -2247,11 +2252,11 @@ class RollingUpgradeTest(CTSTest): if not self.is_applicable_common(): return None - if not self.Env.has_key("rpm-dir"): + if not "rpm-dir" in self.Env.keys(): return None - if not self.Env.has_key("current-version"): + if not "current-version" in self.Env.keys(): return None - if not self.Env.has_key("previous-version"): + if not "previous-version" in self.Env.keys(): return None return 1 @@ -2305,7 +2310,7 @@ class BSC_AddResource(CTSTest): if ":" in ip: fields = ip.rpartition(":") fields[2] = str(hex(int(fields[2], 16)+1)) - print str(hex(int(f[2], 16)+1)) + print(str(hex(int(f[2], 16)+1))) else: fields = ip.rpartition('.') fields[2] = str(int(fields[2])+1) @@ -3109,7 +3114,7 @@ class RemoteStonithd(CTSTest): if not self.driver.is_applicable(): return False - if self.Env.has_key("DoFencing"): + if "DoFencing" in self.Env.keys(): return self.Env["DoFencing"] return True diff --git a/cts/OCFIPraTest.py b/cts/OCFIPraTest.py index 9900a62..03d964b 100755 --- a/cts/OCFIPraTest.py +++ b/cts/OCFIPraTest.py @@ -28,13 +28,13 @@ from cts.CTSvars import * def usage(): - print "usage: " + sys.argv[0] \ + print("usage: " + sys.argv[0] \ + " [-2]"\ + " [--ipbase|-i first-test-ip]"\ + " [--ipnum|-n test-ip-num]"\ + " [--help|-h]"\ + " [--perform|-p op]"\ - + " [number-of-iterations]" + + " [number-of-iterations]") sys.exit(1) @@ -71,7 +71,7 @@ def log(towrite): t = time.strftime("%Y/%m/%d_%H:%M:%S\t", time.localtime(time.time())) logstr = t + " "+str(towrite) syslog.syslog(logstr) - print logstr + print(logstr) if __name__ == '__main__': ra = "IPaddr" diff --git a/cts/cib_xml.py b/cts/cib_xml.py index 0bd963b..3d8f8d4 100644 --- a/cts/cib_xml.py +++ b/cts/cib_xml.py @@ -19,7 +19,7 @@ class XmlBase(CibBase): text = '''<%s''' % self.tag if self.name: text += ''' id="%s"''' % (self.name) - for k in self.kwargs.keys(): + for k in list(self.kwargs.keys()): text += ''' %s="%s"''' % (k, self.kwargs[k]) if not self.children: @@ -149,22 +149,22 @@ class Resource(XmlBase): def constraints(self): text = "" - for k in self.scores.keys(): + for k in list(self.scores.keys()): text += '''''' % (k, self.name) text += self.scores[k].show() text += '''''' - for k in self.needs.keys(): + for k in list(self.needs.keys()): text += '''''' - for k in self.coloc.keys(): + for k in list(self.coloc.keys()): text += '''''' @@ -179,13 +179,13 @@ class Resource(XmlBase): if len(self.meta) > 0: text += '''''' % self.name - for p in self.meta.keys(): + for p in list(self.meta.keys()): text += '''''' % (self.name, p, p, self.meta[p]) text += '''''' if len(self.param) > 0: text += '''''' % self.name - for p in self.param.keys(): + for p in list(self.param.keys()): text += '''''' % (self.name, p, p, self.param[p]) text += '''''' @@ -219,7 +219,7 @@ class Group(Resource): if len(self.meta) > 0: text += '''''' % self.name - for p in self.meta.keys(): + for p in list(self.meta.keys()): text += '''''' % (self.name, p, p, self.meta[p]) text += '''''' diff --git a/cts/environment.py b/cts/environment.py index 61d4211..4ed5ced 100644 --- a/cts/environment.py +++ b/cts/environment.py @@ -92,7 +92,7 @@ class Environment: def dump(self): keys = [] - for key in self.data.keys(): + for key in list(self.data.keys()): keys.append(key) keys.sort() @@ -106,16 +106,19 @@ class Environment: if key == "nodes": return True - return self.data.has_key(key) + return key in self.data def __getitem__(self, key): + if str(key) == "0": + raise ValueError("Bad call to 'foo in X', should reference 'foo in X.keys()' instead") + if key == "nodes": return self.Nodes elif key == "Name": return self.get_stack_short() - elif self.data.has_key(key): + elif key in self.data: return self.data[key] else: @@ -175,12 +178,12 @@ class Environment: self.data["Stack"] = "corosync (plugin v0)" else: - print "Unknown stack: "+name + raise ValueError("Unknown stack: "+name) sys.exit(1) def get_stack_short(self): # Create the Cluster Manager object - if not self.data.has_key("Stack"): + if not "Stack" in self.data: return "unknown" elif self.data["Stack"] == "heartbeat": @@ -202,12 +205,12 @@ class Environment: return "crm-plugin-v0" else: - LogFactory().log("Unknown stack: "+self.data["stack"]) - sys.exit(1) + LogFactory().log("Unknown stack: "+self["stack"]) + raise ValueError("Unknown stack: "+self["stack"]) def detect_syslog(self): # Detect syslog variant - if not self.has_key("syslogd"): + if not "syslogd" in self.data: if self["have_systemd"]: # Systemd self["syslogd"] = self.rsh(self.target, "systemctl list-units | grep syslog.*\.service.*active.*running | sed 's:.service.*::'", stdout=1).strip() @@ -215,13 +218,13 @@ class Environment: # SYS-V self["syslogd"] = self.rsh(self.target, "chkconfig --list | grep syslog.*on | awk '{print $1}' | head -n 1", stdout=1).strip() - if not self.has_key("syslogd") or not self["syslogd"]: + if not "syslogd" in self.data or not self["syslogd"]: # default self["syslogd"] = "rsyslog" def detect_at_boot(self): # Detect if the cluster starts at boot - if not self.has_key("at-boot"): + if not "at-boot" in self.data: atboot = 0 if self["have_systemd"]: @@ -237,7 +240,7 @@ class Environment: def detect_ip_offset(self): # Try to determin an offset for IPaddr resources - if self["CIBResource"] and not self.has_key("IPBase"): + if self["CIBResource"] and not "IPBase" in self.data: network=self.rsh(self.target, "ip addr | grep inet | grep -v -e link -e inet6 -e '/32' -e ' lo' | awk '{print $2}'", stdout=1).strip() self["IPBase"] = self.rsh(self.target, "nmap -sn -n %s | grep 'scan report' | awk '{print $NF}' | sed 's:(::' | sed 's:)::' | sort -V | tail -n 1" % network, stdout=1).strip() if not self["IPBase"]: @@ -261,7 +264,7 @@ class Environment: def validate(self): if len(self["nodes"]) < 1: - print "No nodes specified!" + print("No nodes specified!") sys.exit(1) def discover(self): @@ -276,7 +279,7 @@ class Environment: break; self["cts-master"] = master - if not self.has_key("have_systemd"): + if not "have_systemd" in self.data: self["have_systemd"] = not self.rsh(self.target, "systemctl list-units") self.detect_syslog() @@ -390,7 +393,7 @@ class Environment: self["DoStonith"]=1 self["stonith-type"] = "fence_openstack" - print "Obtaining OpenStack credentials from the current environment" + print("Obtaining OpenStack credentials from the current environment") self["stonith-params"] = "region=%s,tenant=%s,auth=%s,user=%s,password=%s" % ( os.environ['OS_REGION_NAME'], os.environ['OS_TENANT_NAME'], @@ -403,7 +406,7 @@ class Environment: self["DoStonith"]=1 self["stonith-type"] = "fence_rhevm" - print "Obtaining RHEV-M credentials from the current environment" + print("Obtaining RHEV-M credentials from the current environment") self["stonith-params"] = "login=%s,passwd=%s,ipaddr=%s,ipport=%s,ssl=1,shell_timeout=10" % ( os.environ['RHEVM_USERNAME'], os.environ['RHEVM_PASSWORD'], @@ -442,7 +445,7 @@ class Environment: try: float(args[i+1]) except ValueError: - print ("--xmit-loss parameter should be float") + print("--xmit-loss parameter should be float") self.usage(args[i+1]) skipthis=1 self["XmitLoss"] = args[i+1] @@ -451,7 +454,7 @@ class Environment: try: float(args[i+1]) except ValueError: - print ("--recv-loss parameter should be float") + print("--recv-loss parameter should be float") self.usage(args[i+1]) skipthis=1 self["RecvLoss"] = args[i+1] @@ -503,7 +506,7 @@ class Environment: self["DoStonith"]=1 self["stonith-type"] = "fence_rhevm" - print "Obtaining RHEV-M credentials from the current environment" + print("Obtaining RHEV-M credentials from the current environment") self["stonith-params"] = "login=%s,passwd=%s,ipaddr=%s,ipport=%s,ssl=1,shell_timeout=10" % ( os.environ['RHEVM_USERNAME'], os.environ['RHEVM_PASSWORD'], @@ -605,7 +608,7 @@ class Environment: skipthis=1 (name, value) = args[i+1].split('=') self[name] = value - print "Setting %s = %s" % (name, value) + print("Setting %s = %s" % (name, value)) elif args[i] == "--help": self.usage(args[i], 0) @@ -622,52 +625,52 @@ class Environment: def usage(self, arg, status=1): if status: - print "Illegal argument %s" % arg - print "usage: " + sys.argv[0] +" [options] number-of-iterations" - print "\nCommon options: " - print "\t [--nodes 'node list'] list of cluster nodes separated by whitespace" - print "\t [--group | -g 'name'] use the nodes listed in the named DSH group (~/.dsh/groups/$name)" - print "\t [--limit-nodes max] only use the first 'max' cluster nodes supplied with --nodes" - print "\t [--stack (v0|v1|cman|corosync|heartbeat|openais)] which cluster stack is installed" - print "\t [--list-tests] list the valid tests" - print "\t [--benchmark] add the timing information" - print "\t " - print "Options that CTS will usually auto-detect correctly: " - print "\t [--logfile path] where should the test software look for logs from cluster nodes" - print "\t [--syslog-facility name] which syslog facility should the test software log to" - print "\t [--at-boot (1|0)] does the cluster software start at boot time" - print "\t [--test-ip-base ip] offset for generated IP address resources" - print "\t " - print "Options for release testing: " - print "\t [--populate-resources | -r] generate a sample configuration" - print "\t [--choose name] run only the named test" - print "\t [--stonith (1 | 0 | yes | no | rhcs | ssh)]" - print "\t [--once] run all valid tests once" - print "\t " - print "Additional (less common) options: " - print "\t [--clobber-cib | -c ] erase any existing configuration" - print "\t [--outputfile path] optional location for the test software to write logs to" - print "\t [--trunc] truncate logfile before starting" - print "\t [--xmit-loss lost-rate(0.0-1.0)]" - print "\t [--recv-loss lost-rate(0.0-1.0)]" - print "\t [--standby (1 | 0 | yes | no)]" - print "\t [--fencing (1 | 0 | yes | no | rhcs | lha | openstack )]" - print "\t [--stonith-type type]" - print "\t [--stonith-args name=value]" - print "\t [--bsc]" - print "\t [--no-loop-tests] dont run looping/time-based tests" - print "\t [--no-unsafe-tests] dont run tests that are unsafe for use with ocfs2/drbd" - print "\t [--valgrind-tests] include tests using valgrind" - print "\t [--experimental-tests] include experimental tests" - print "\t [--container-tests] include pacemaker_remote tests that run in lxc container resources" - print "\t [--oprofile 'node list'] list of cluster nodes to run oprofile on]" - print "\t [--qarsh] use the QARSH backdoor to access nodes instead of SSH" - print "\t [--docker] Indicates nodes are docker nodes." - print "\t [--seed random_seed]" - print "\t [--set option=value]" - print "\t " - print "\t Example: " - print "\t python sys.argv[0] -g virt1 --stack cs -r --stonith ssh --schema pacemaker-1.0 500" + print("Illegal argument %s" % arg) + print("usage: " + sys.argv[0] +" [options] number-of-iterations") + print("\nCommon options: ") + print("\t [--nodes 'node list'] list of cluster nodes separated by whitespace") + print("\t [--group | -g 'name'] use the nodes listed in the named DSH group (~/.dsh/groups/$name)") + print("\t [--limit-nodes max] only use the first 'max' cluster nodes supplied with --nodes") + print("\t [--stack (v0|v1|cman|corosync|heartbeat|openais)] which cluster stack is installed") + print("\t [--list-tests] list the valid tests") + print("\t [--benchmark] add the timing information") + print("\t ") + print("Options that CTS will usually auto-detect correctly: ") + print("\t [--logfile path] where should the test software look for logs from cluster nodes") + print("\t [--syslog-facility name] which syslog facility should the test software log to") + print("\t [--at-boot (1|0)] does the cluster software start at boot time") + print("\t [--test-ip-base ip] offset for generated IP address resources") + print("\t ") + print("Options for release testing: ") + print("\t [--populate-resources | -r] generate a sample configuration") + print("\t [--choose name] run only the named test") + print("\t [--stonith (1 | 0 | yes | no | rhcs | ssh)]") + print("\t [--once] run all valid tests once") + print("\t ") + print("Additional (less common) options: ") + print("\t [--clobber-cib | -c ] erase any existing configuration") + print("\t [--outputfile path] optional location for the test software to write logs to") + print("\t [--trunc] truncate logfile before starting") + print("\t [--xmit-loss lost-rate(0.0-1.0)]") + print("\t [--recv-loss lost-rate(0.0-1.0)]") + print("\t [--standby (1 | 0 | yes | no)]") + print("\t [--fencing (1 | 0 | yes | no | rhcs | lha | openstack )]") + print("\t [--stonith-type type]") + print("\t [--stonith-args name=value]") + print("\t [--bsc]") + print("\t [--no-loop-tests] dont run looping/time-based tests") + print("\t [--no-unsafe-tests] dont run tests that are unsafe for use with ocfs2/drbd") + print("\t [--valgrind-tests] include tests using valgrind") + print("\t [--experimental-tests] include experimental tests") + print("\t [--container-tests] include pacemaker_remote tests that run in lxc container resources") + print("\t [--oprofile 'node list'] list of cluster nodes to run oprofile on]") + print("\t [--qarsh] use the QARSH backdoor to access nodes instead of SSH") + print("\t [--docker] Indicates nodes are docker nodes.") + print("\t [--seed random_seed]") + print("\t [--set option=value]") + print("\t ") + print("\t Example: ") + print("\t python sys.argv[0] -g virt1 --stack cs -r --stonith ssh --schema pacemaker-1.0 500") sys.exit(status) diff --git a/cts/logging.py b/cts/logging.py index 8afa611..08da44a 100644 --- a/cts/logging.py +++ b/cts/logging.py @@ -22,7 +22,7 @@ Licensed under the GNU GPL. # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -import types, string, sys, time, os +import string, sys, time, os class Logger: TimeFormat = "%b %d %H:%M:%S\t" @@ -47,7 +47,7 @@ class StdErrLog(Logger): def __call__(self, lines): t = time.strftime(Logger.TimeFormat, time.localtime(time.time())) - if isinstance(lines, types.StringType): + if isinstance(lines, basestring): sys.__stderr__.writelines([t, lines, "\n"]) else: for line in lines: @@ -71,7 +71,7 @@ class FileLog(Logger): fd = open(self.logfile, "a") t = time.strftime(Logger.TimeFormat, time.localtime(time.time())) - if isinstance(lines, types.StringType): + if isinstance(lines, basestring): fd.writelines([t, self.hostname, self.source, lines, "\n"]) else: for line in lines: diff --git a/cts/patterns.py b/cts/patterns.py index 493b690..3cdce2f 100644 --- a/cts/patterns.py +++ b/cts/patterns.py @@ -67,9 +67,9 @@ class BasePatterns: } def get_component(self, key): - if self.components.has_key(key): + if key in self.components: return self.components[key] - print "Unknown component '%s' for %s" % (key, self.name) + print("Unknown component '%s' for %s" % (key, self.name)) return [] def get_patterns(self, key): @@ -87,12 +87,12 @@ class BasePatterns: def __getitem__(self, key): if key == "Name": return self.name - elif self.commands.has_key(key): + elif key in self.commands: return self.commands[key] - elif self.search.has_key(key): + elif key in self.search: return self.search[key] else: - print "Unknown template '%s' for %s" % (key, self.name) + print("Unknown template '%s' for %s" % (key, self.name)) return None class crm_lha(BasePatterns): @@ -489,9 +489,9 @@ class PatternSelector: crm_mcp_docker(name) def get_variant(self, variant): - if patternvariants.has_key(variant): + if variant in patternvariants: return patternvariants[variant] - print "defaulting to crm-base for %s" % variant + print("defaulting to crm-base for %s" % variant) return self.base def get_patterns(self, variant, kind): @@ -532,7 +532,7 @@ if __name__ == '__main__': template = args[i+1] else: - print "Illegal argument " + args[i] + print("Illegal argument " + args[i]) - print PatternSelector(kind)[template] + print(PatternSelector(kind)[template]) diff --git a/cts/remote.py b/cts/remote.py index b32b028..040b48a 100644 --- a/cts/remote.py +++ b/cts/remote.py @@ -147,7 +147,7 @@ class RemoteExec: sysname = args[0] command = args[1] - #print "sysname: %s, us: %s" % (sysname, self.OurNode) + #print("sysname: %s, us: %s" % (sysname, self.OurNode)) if sysname == None or string.lower(sysname) == self.OurNode or sysname == "localhost": ret = command else: @@ -164,7 +164,7 @@ class RemoteExec: self.logger.debug(args) def call_async(self, node, command, completionDelegate=None): - #if completionDelegate: print "Waiting for %d on %s: %s" % (proc.pid, node, command) + #if completionDelegate: print("Waiting for %d on %s: %s" % (proc.pid, node, command)) aproc = AsyncRemoteCmd(node, self._cmd([node, command]), completionDelegate=completionDelegate) aproc.start() return aproc @@ -186,7 +186,7 @@ class RemoteExec: proc = Popen(self._cmd([node, command]), stdout = PIPE, stderr = PIPE, close_fds = True, shell = True) - #if completionDelegate: print "Waiting for %d on %s: %s" % (proc.pid, node, command) + #if completionDelegate: print("Waiting for %d on %s: %s" % (proc.pid, node, command)) if not synchronous and proc.pid > 0 and not self.silent: aproc = AsyncWaitProc(proc, node, command, completionDelegate=completionDelegate) aproc.start() @@ -257,14 +257,14 @@ class RemoteFactory: return RemoteExec(RemoteFactory.rsh, silent) def enable_docker(self): - print "Using DOCKER backend for connections to cluster nodes" + print("Using DOCKER backend for connections to cluster nodes") RemoteFactory.rsh.Command = "/usr/libexec/phd/docker/phd_docker_remote_cmd " RemoteFactory.rsh.CpCommand = "/usr/libexec/phd/docker/phd_docker_cp" def enable_qarsh(self): # http://nstraz.wordpress.com/2008/12/03/introducing-qarsh/ - print "Using QARSH for connections to cluster nodes" + print("Using QARSH for connections to cluster nodes") RemoteFactory.rsh.Command = "qarsh -t 300 -l root" RemoteFactory.rsh.CpCommand = "qacp -q" diff --git a/cts/watcher.py b/cts/watcher.py index 1182c8b..de032f7 100644 --- a/cts/watcher.py +++ b/cts/watcher.py @@ -73,7 +73,7 @@ for i in range(0, len(args)): skipthis=1 if not os.access(filename, os.R_OK): - print prefix + 'Last read: %d, limit=%d, count=%d - unreadable' % (0, limit, 0) + print(prefix + 'Last read: %d, limit=%d, count=%d - unreadable' % (0, limit, 0)) sys.exit(1) logfile=open(filename, 'r') @@ -85,7 +85,7 @@ if offset != 'EOF': if newsize >= offset: logfile.seek(offset) else: - print prefix + ('File truncated from %d to %d' % (offset, newsize)) + print(prefix + ('File truncated from %d to %d' % (offset, newsize))) if (newsize*1.05) < offset: logfile.seek(0) # else: we probably just lost a few logs after a fencing op @@ -103,10 +103,10 @@ while True: line = logfile.readline() if not line: break - print line.strip() + print(line.strip()) count += 1 -print prefix + 'Last read: %d, limit=%d, count=%d' % (logfile.tell(), limit, count) +print(prefix + 'Last read: %d, limit=%d, count=%d' % (logfile.tell(), limit, count)) logfile.close() """ @@ -158,7 +158,7 @@ class FileObj(SearchObj): SearchObj.__init__(self, filename, host, name) if host is not None: - if not has_log_watcher.has_key(host): + if not host in has_log_watcher: global log_watcher global log_watcher_bin @@ -381,7 +381,7 @@ class LogWatcher(RemoteExec): else: self.file_list.append(FileObj(self.filename)) - # print "%s now has %d files" % (self.name, len(self.file_list)) + # print("%s now has %d files" % (self.name, len(self.file_list))) def __del__(self): if self.debug_level > 1: self.debug("Destroy") @@ -406,7 +406,7 @@ class LogWatcher(RemoteExec): raise ValueError("No sources to read from") pending = [] - #print "%s waiting for %d operations" % (self.name, self.pending) + #print("%s waiting for %d operations" % (self.name, self.pending)) for f in self.file_list: t = f.harvest_async(self) if t: @@ -418,7 +418,7 @@ class LogWatcher(RemoteExec): self.logger.log("%s: Aborting after 20s waiting for %s logging commands" % (self.name, repr(t))) return - #print "Got %d lines" % len(self.line_cache) + #print("Got %d lines" % len(self.line_cache)) def end(self): for f in self.file_list: diff --git a/doc/Pacemaker_Explained/en-US/Ch-Resources.txt b/doc/Pacemaker_Explained/en-US/Ch-Resources.txt index 5d5fa33..b0115fb 100644 --- a/doc/Pacemaker_Explained/en-US/Ch-Resources.txt +++ b/doc/Pacemaker_Explained/en-US/Ch-Resources.txt @@ -643,6 +643,16 @@ indexterm:[Action,Property,on-fail] indexterm:[enabled,Action Property] indexterm:[Action,Property,enabled] +|role +| +|This option only makes sense for recurring operations. It restricts + the operation to a specific role. The truely paranoid can even + specify +role=Stopped+ which allows the cluster to detect an admin + that manually started cluster services. + Allowed values: +Stopped+, +Started+, +Slave+, +Master+. + indexterm:[role,Action Property] + indexterm:[Action,Property,role] + |========================================================= [[s-operation-defaults]] diff --git a/fencing/commands.c b/fencing/commands.c index 0d2d614..bd3b27d 100644 --- a/fencing/commands.c +++ b/fencing/commands.c @@ -124,17 +124,7 @@ static xmlNode *stonith_construct_async_reply(async_command_t * cmd, const char static gboolean is_action_required(const char *action, stonith_device_t *device) { - if(device == NULL) { - return FALSE; - - } else if (device->required_actions == NULL) { - return FALSE; - - } else if (strstr(device->required_actions, action)) { - return TRUE; - } - - return FALSE; + return device && device->automatic_unfencing && safe_str_eq(action, "on"); } static int @@ -449,7 +439,6 @@ free_device(gpointer data) free_xml(device->agent_metadata); free(device->namespace); free(device->on_target_actions); - free(device->required_actions); free(device->agent); free(device->id); free(device); @@ -713,8 +702,6 @@ read_action_metadata(stonith_device_t *device) for (lpc = 0; lpc < max; lpc++) { const char *on_target = NULL; const char *action = NULL; - const char *automatic = NULL; - const char *required = NULL; xmlNode *match = getXpathResult(xpath, lpc); CRM_LOG_ASSERT(match != NULL); @@ -722,8 +709,6 @@ read_action_metadata(stonith_device_t *device) on_target = crm_element_value(match, "on_target"); action = crm_element_value(match, "name"); - automatic = crm_element_value(match, "automatic"); - required = crm_element_value(match, "required"); if(safe_str_eq(action, "list")) { set_bit(device->flags, st_device_supports_list); @@ -731,17 +716,21 @@ read_action_metadata(stonith_device_t *device) set_bit(device->flags, st_device_supports_status); } else if(safe_str_eq(action, "reboot")) { set_bit(device->flags, st_device_supports_reboot); - } else if(safe_str_eq(action, "on") && (crm_is_true(automatic))) { - /* this setting implies required=true for unfencing */ - required = "true"; + } else if (safe_str_eq(action, "on")) { + /* "automatic" means the cluster will unfence node when it joins */ + const char *automatic = crm_element_value(match, "automatic"); + + /* "required" is a deprecated synonym for "automatic" */ + const char *required = crm_element_value(match, "required"); + + if (crm_is_true(automatic) || crm_is_true(required)) { + device->automatic_unfencing = TRUE; + } } if (action && crm_is_true(on_target)) { device->on_target_actions = add_action(device->on_target_actions, action); } - if (action && crm_is_true(required)) { - device->required_actions = add_action(device->required_actions, action); - } } freeXpathObject(xpath); @@ -778,8 +767,7 @@ build_device_from_xml(xmlNode * msg) value = crm_element_value(dev, "rsc_provides"); if (safe_str_eq(value, "unfencing")) { - /* if this agent requires unfencing, 'on' is considered a required action */ - device->required_actions = add_action(device->required_actions, "on"); + device->automatic_unfencing = TRUE; } if (is_action_required("on", device)) { @@ -1224,7 +1212,6 @@ stonith_device_action(xmlNode * msg, char **output) } else if (device) { cmd = create_async_command(msg); if (cmd == NULL) { - free_device(device); return -EPROTO; } diff --git a/fencing/internal.h b/fencing/internal.h index 5fb8f9c..0f418ec 100644 --- a/fencing/internal.h +++ b/fencing/internal.h @@ -26,12 +26,13 @@ typedef struct stonith_device_s { /*! list of actions that must execute on the target node. Used for unfencing */ char *on_target_actions; - char *required_actions; GListPtr targets; time_t targets_age; gboolean has_attr_map; /* should nodeid parameter for victim be included in agent arguments */ gboolean include_nodeid; + /* whether the cluster should automatically unfence nodes with the device */ + gboolean automatic_unfencing; guint priority; guint active_pid; @@ -59,7 +60,8 @@ typedef struct stonith_device_s { enum st_remap_phase { st_phase_requested = 0, st_phase_off = 1, - st_phase_on = 2 + st_phase_on = 2, + st_phase_max = 3 }; typedef struct remote_fencing_op_s { @@ -128,15 +130,9 @@ typedef struct remote_fencing_op_s { /*! The current operation phase being executed */ enum st_remap_phase phase; - /* For phase 0 or 1 (requested action or a remapped "off"), required devices - * will be executed regardless of what topology level is being executed - * currently. For phase 1 (remapped "on"), required devices will not be - * attempted, because the cluster will execute them automatically when the - * node next joins the cluster. - */ - /*! Lists of devices marked as required for each phase */ - GListPtr required_list[3]; - /*! The device list of all the devices at the current executing topology level. */ + /*! Devices with automatic unfencing (always run if "on" requested, never if remapped) */ + GListPtr automatic_list; + /*! List of all devices at the currently executing topology level */ GListPtr devices_list; /*! Current entry in the topology device list */ GListPtr devices; diff --git a/fencing/main.c b/fencing/main.c index 46d7352..c48e12d 100644 --- a/fencing/main.c +++ b/fencing/main.c @@ -553,7 +553,7 @@ remove_fencing_topology(xmlXPathObjectPtr xpathObj) } static void -register_fencing_topology(xmlXPathObjectPtr xpathObj, gboolean force) +register_fencing_topology(xmlXPathObjectPtr xpathObj) { int max = numXpathResults(xpathObj), lpc = 0; @@ -584,7 +584,7 @@ register_fencing_topology(xmlXPathObjectPtr xpathObj, gboolean force) */ static void -fencing_topology_init(xmlNode * msg) +fencing_topology_init() { xmlXPathObjectPtr xpathObj = NULL; const char *xpath = "//" XML_TAG_FENCING_LEVEL; @@ -598,7 +598,7 @@ fencing_topology_init(xmlNode * msg) /* Grab everything */ xpathObj = xpath_search(local_cib, xpath); - register_fencing_topology(xpathObj, TRUE); + register_fencing_topology(xpathObj); freeXpathObject(xpathObj); } @@ -931,7 +931,7 @@ update_fencing_topology(const char *event, xmlNode * msg) xpath = "//" F_CIB_UPDATE_RESULT "//" XML_TAG_DIFF_ADDED "//" XML_TAG_FENCING_LEVEL; xpathObj = xpath_search(msg, xpath); - register_fencing_topology(xpathObj, FALSE); + register_fencing_topology(xpathObj); freeXpathObject(xpathObj); } else if(format == 2) { @@ -969,7 +969,7 @@ update_fencing_topology(const char *event, xmlNode * msg) /* 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 %d.%d.%d for %s", op, add[0], add[1], add[2], xpath); - fencing_topology_init(NULL); + fencing_topology_init(); return; } @@ -977,7 +977,7 @@ update_fencing_topology(const char *event, xmlNode * msg) /* Change to the topology in general */ crm_info("Re-initializing fencing topology after top-level %s operation %d.%d.%d for %s", op, add[0], add[1], add[2], xpath); - fencing_topology_init(NULL); + fencing_topology_init(); return; } else if (strstr(xpath, "/" XML_CIB_TAG_CONFIGURATION)) { @@ -989,7 +989,7 @@ update_fencing_topology(const char *event, xmlNode * msg) } else if(strcmp(op, "delete") == 0 || strcmp(op, "create") == 0) { crm_info("Re-initializing fencing topology after top-level %s operation %d.%d.%d for %s.", op, add[0], add[1], add[2], xpath); - fencing_topology_init(NULL); + fencing_topology_init(); return; } @@ -1098,7 +1098,7 @@ update_cib_cache_cb(const char *event, xmlNode * msg) } 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); + fencing_topology_init(); cib_devices_update(); } else { @@ -1114,7 +1114,7 @@ init_cib_cache_cb(xmlNode * msg, int call_id, int rc, xmlNode * output, void *us have_cib_devices = TRUE; local_cib = copy_xml(output); - fencing_topology_init(msg); + fencing_topology_init(); cib_devices_update(); } @@ -1239,7 +1239,7 @@ st_peer_update_callback(enum crm_status_type type, crm_node_t * node, const void * 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 = query = create_xml_node(NULL, "stonith_command"); + 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); diff --git a/fencing/remote.c b/fencing/remote.c index 2c00b5f..d741672 100644 --- a/fencing/remote.c +++ b/fencing/remote.c @@ -60,13 +60,13 @@ typedef struct device_properties_s { /* The remaining members are indexed by the operation's "phase" */ /* Whether this device has been executed in each phase */ - gboolean executed[3]; + gboolean executed[st_phase_max]; /* Whether this device is disallowed from executing in each phase */ - gboolean disallowed[3]; + gboolean disallowed[st_phase_max]; /* Action-specific timeout for each phase */ - int custom_action_timeout[3]; + int custom_action_timeout[st_phase_max]; /* Action-specific maximum random delay for each phase */ - int delay_max[3]; + int delay_max[st_phase_max]; } device_properties_t; typedef struct st_query_result_s { @@ -207,22 +207,6 @@ grab_peer_device(const remote_fencing_op_t *op, st_query_result_t *peer, return TRUE; } -/* - * \internal - * \brief Free the list of required devices for a particular phase - * - * \param[in,out] op Operation to modify - * \param[in] phase Phase to modify - */ -static void -free_required_list(remote_fencing_op_t *op, enum st_remap_phase phase) -{ - if (op->required_list[phase]) { - g_list_free_full(op->required_list[phase], free); - op->required_list[phase] = NULL; - } -} - static void clear_remote_op_timers(remote_fencing_op_t * op) { @@ -268,9 +252,7 @@ free_remote_op(gpointer data) g_list_free_full(op->devices_list, free); op->devices_list = NULL; } - free_required_list(op, st_phase_requested); - free_required_list(op, st_phase_off); - free_required_list(op, st_phase_on); + g_list_free_full(op->automatic_list, free); free(op); } @@ -323,10 +305,10 @@ op_phase_on(remote_fencing_op_t *op) op->phase = st_phase_on; strcpy(op->action, "on"); - /* Any devices that are required for "on" will be automatically executed by - * the cluster when the node next joins, so we skip them here. + /* Skip devices with automatic unfencing, because the cluster will handle it + * when the node rejoins. */ - for (iter = op->required_list[op->phase]; iter != NULL; iter = iter->next) { + for (iter = op->automatic_list; iter != NULL; iter = iter->next) { GListPtr match = g_list_find_custom(op->devices_list, iter->data, sort_strings); @@ -334,12 +316,8 @@ op_phase_on(remote_fencing_op_t *op) op->devices_list = g_list_remove(op->devices_list, match->data); } } - - /* We know this level will succeed, because phase 1 completed successfully - * and we ignore any errors from phase 2. So we can free the required list, - * which will keep them from being executed after the device list is done. - */ - free_required_list(op, op->phase); + g_list_free_full(op->automatic_list, free); + op->automatic_list = NULL; /* Rewind device list pointer */ op->devices = op->devices_list; @@ -659,28 +637,25 @@ topology_is_empty(stonith_topology_t *tp) /* * \internal - * \brief Add a device to the required list for a particular phase + * \brief Add a device to an operation's automatic unfencing list * * \param[in,out] op Operation to modify - * \param[in] phase Phase to modify * \param[in] device Device ID to add */ static void -add_required_device(remote_fencing_op_t *op, enum st_remap_phase phase, - const char *device) +add_required_device(remote_fencing_op_t *op, const char *device) { - GListPtr match = g_list_find_custom(op->required_list[phase], device, + GListPtr match = g_list_find_custom(op->automatic_list, device, sort_strings); if (!match) { - op->required_list[phase] = g_list_prepend(op->required_list[phase], - strdup(device)); + op->automatic_list = g_list_prepend(op->automatic_list, strdup(device)); } } /* * \internal - * \brief Remove a device from the required list for the current phase + * \brief Remove a device from the automatic unfencing list * * \param[in,out] op Operation to modify * \param[in] device Device ID to remove @@ -688,12 +663,11 @@ add_required_device(remote_fencing_op_t *op, enum st_remap_phase phase, static void remove_required_device(remote_fencing_op_t *op, const char *device) { - GListPtr match = g_list_find_custom(op->required_list[op->phase], device, + GListPtr match = g_list_find_custom(op->automatic_list, device, sort_strings); if (match) { - op->required_list[op->phase] = g_list_remove(op->required_list[op->phase], - match->data); + op->automatic_list = g_list_remove(op->automatic_list, match->data); } } @@ -938,7 +912,7 @@ create_remote_stonith_op(const char *client, xmlNode * request, gboolean peer) op = calloc(1, sizeof(remote_fencing_op_t)); - crm_element_value_int(request, F_STONITH_TIMEOUT, (int *)&(op->base_timeout)); + crm_element_value_int(request, F_STONITH_TIMEOUT, &(op->base_timeout)); if (peer && dev) { op->id = crm_element_value_copy(dev, F_STONITH_REMOTE_OP_ID); @@ -974,7 +948,7 @@ create_remote_stonith_op(const char *client, xmlNode * request, gboolean peer) crm_element_value_int(request, F_STONITH_CALLOPTS, &call_options); op->call_options = call_options; - crm_element_value_int(request, F_STONITH_CALLID, (int *)&(op->client_callid)); + crm_element_value_int(request, F_STONITH_CALLID, &(op->client_callid)); crm_trace("%s new stonith op: %s - %s of %s for %s", (peer @@ -1352,14 +1326,17 @@ advance_op_topology(remote_fencing_op_t *op, const char *device, xmlNode *msg, op->devices = op->devices->next; } - /* If this device was required, it's not anymore */ - remove_required_device(op, device); + /* Handle automatic unfencing if an "on" action was requested */ + if ((op->phase == st_phase_requested) && safe_str_eq(op->action, "on")) { + /* If the device we just executed was required, it's not anymore */ + remove_required_device(op, device); - /* If there are no more devices at this topology level, - * run through any required devices not already executed - */ - if (op->devices == NULL) { - op->devices = op->required_list[op->phase]; + /* If there are no more devices at this topology level, run through any + * remaining devices with automatic unfencing + */ + if (op->devices == NULL) { + op->devices = op->automatic_list; + } } if ((op->devices == NULL) && (op->phase == st_phase_off)) { @@ -1613,8 +1590,6 @@ parse_action_specific(xmlNode *xml, const char *peer, const char *device, const char *action, remote_fencing_op_t *op, enum st_remap_phase phase, device_properties_t *props) { - int required; - props->custom_action_timeout[phase] = 0; crm_element_value_int(xml, F_STONITH_ACTION_TIMEOUT, &props->custom_action_timeout[phase]); @@ -1630,20 +1605,16 @@ parse_action_specific(xmlNode *xml, const char *peer, const char *device, peer, device, props->delay_max[phase], action); } - required = 0; - crm_element_value_int(xml, F_STONITH_DEVICE_REQUIRED, &required); - if (required) { - /* If the action is marked as required, add the device to the - * operation's list of required devices for this phase. We use this - * for unfencing when executing a topology. In phase 0 (requested - * action) or phase 1 (remapped "off"), required devices get executed - * regardless of their topology level; in phase 2 (remapped "on"), - * required devices are not attempted, because the cluster will - * execute them automatically later. - */ - crm_trace("Peer %s requires device %s to execute for action %s", - peer, device, action); - add_required_device(op, phase, device); + /* Handle devices with automatic unfencing */ + if (safe_str_eq(action, "on")) { + int required = 0; + + crm_element_value_int(xml, F_STONITH_DEVICE_REQUIRED, &required); + if (required) { + crm_trace("Peer %s requires device %s to execute for action %s", + peer, device, action); + add_required_device(op, device); + } } /* If a reboot is remapped to off+on, it's possible that a node is allowed diff --git a/include/crm/cib.h b/include/crm/cib.h index cb465bf..306706e 100644 --- a/include/crm/cib.h +++ b/include/crm/cib.h @@ -136,6 +136,13 @@ typedef struct cib_api_operations_s { void *user_data, const char *callback_name, void (*callback) (xmlNode *, int, int, xmlNode *, void *)); + gboolean (*register_callback_full)(cib_t *cib, int call_id, int timeout, + gboolean only_success, void *user_data, + const char *callback_name, + void (*callback)(xmlNode *, int, int, + xmlNode *, void *), + void (*free_func)(void *)); + } cib_api_operations_t; struct cib_s { diff --git a/include/crm/cib/internal.h b/include/crm/cib/internal.h index 431a2bd..adc2faf 100644 --- a/include/crm/cib/internal.h +++ b/include/crm/cib/internal.h @@ -106,7 +106,7 @@ typedef struct cib_callback_client_s { void *user_data; gboolean only_success; struct timer_rec_s *timer; - + void (*free_func)(void *); } cib_callback_client_t; struct timer_rec_s { @@ -137,6 +137,13 @@ int cib_native_register_notification(cib_t * cib, const char *callback, int enab gboolean cib_client_register_callback(cib_t * cib, int call_id, int timeout, gboolean only_success, void *user_data, const char *callback_name, void (*callback) (xmlNode *, int, int, xmlNode *, void *)); +gboolean cib_client_register_callback_full(cib_t *cib, int call_id, + int timeout, gboolean only_success, + void *user_data, + const char *callback_name, + void (*callback)(xmlNode *, int, int, + xmlNode *, void *), + void (*free_func)(void *)); int cib_process_query(const char *op, int options, const char *section, xmlNode * req, xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib, diff --git a/include/crm/common/ipc.h b/include/crm/common/ipc.h index db83b09..d6ceda2 100644 --- a/include/crm/common/ipc.h +++ b/include/crm/common/ipc.h @@ -75,7 +75,7 @@ long crm_ipc_read(crm_ipc_t * client); const char *crm_ipc_buffer(crm_ipc_t * client); uint32_t crm_ipc_buffer_flags(crm_ipc_t * client); const char *crm_ipc_name(crm_ipc_t * client); -int crm_ipc_default_buffer_size(void); +unsigned int crm_ipc_default_buffer_size(void); /* Utils */ xmlNode *create_hello_message(const char *uuid, const char *client_name, diff --git a/include/crm/common/ipcs.h b/include/crm/common/ipcs.h index b43fc53..d825912 100644 --- a/include/crm/common/ipcs.h +++ b/include/crm/common/ipcs.h @@ -110,7 +110,7 @@ void crm_ipcs_send_ack(crm_client_t * c, uint32_t request, uint32_t flags, const char *tag, const char *function, int line); /* when max_send_size is 0, default ipc buffer size is used */ -ssize_t crm_ipc_prepare(uint32_t request, xmlNode * message, struct iovec **result, int32_t max_send_size); +ssize_t crm_ipc_prepare(uint32_t request, xmlNode * message, struct iovec ** result, uint32_t max_send_size); ssize_t crm_ipcs_send(crm_client_t * c, uint32_t request, xmlNode * message, enum crm_ipc_flags flags); ssize_t crm_ipcs_sendv(crm_client_t * c, struct iovec *iov, enum crm_ipc_flags flags); xmlNode *crm_ipcs_recv(crm_client_t * c, void *data, size_t size, uint32_t * id, uint32_t * flags); diff --git a/lib/cib/cib_client.c b/lib/cib/cib_client.c index b13323e..f7a19b8 100644 --- a/lib/cib/cib_client.c +++ b/lib/cib/cib_client.c @@ -198,6 +198,11 @@ cib_destroy_op_callback(gpointer data) g_source_remove(blob->timer->ref); } free(blob->timer); + + if (blob->user_data && blob->free_func) { + blob->free_func(blob->user_data); + } + free(blob); } @@ -327,10 +332,15 @@ cib_new(void) return cib_native_new(); } -/* this is backwards... - cib_*_new should call this not the other way around +/* + * \internal + * \brief Create a generic CIB connection instance + * + * \return Newly allocated and initialized cib_t instance + * + * \note This is called by each variant's cib_*_new() function before setting + * variant-specific values. */ - cib_t * cib_new_variant(void) { @@ -364,6 +374,7 @@ cib_new_variant(void) new_cib->cmds->add_notify_callback = cib_client_add_notify_callback; new_cib->cmds->del_notify_callback = cib_client_del_notify_callback; new_cib->cmds->register_callback = cib_client_register_callback; + new_cib->cmds->register_callback_full = cib_client_register_callback_full; new_cib->cmds->noop = cib_client_noop; new_cib->cmds->ping = cib_client_ping; @@ -545,6 +556,19 @@ cib_client_register_callback(cib_t * cib, int call_id, int timeout, gboolean onl void *user_data, const char *callback_name, void (*callback) (xmlNode *, int, int, xmlNode *, void *)) { + return cib_client_register_callback_full(cib, call_id, timeout, + only_success, user_data, + callback_name, callback, NULL); +} + +gboolean +cib_client_register_callback_full(cib_t *cib, int call_id, int timeout, + gboolean only_success, void *user_data, + const char *callback_name, + void (*callback)(xmlNode *, int, int, + xmlNode *, void *), + void (*free_func)(void *)) +{ cib_callback_client_t *blob = NULL; if (call_id < 0) { @@ -553,6 +577,9 @@ cib_client_register_callback(cib_t * cib, int call_id, int timeout, gboolean onl } else { crm_warn("CIB call failed: %s", pcmk_strerror(call_id)); } + if (user_data && free_func) { + free_func(user_data); + } return FALSE; } @@ -561,6 +588,7 @@ cib_client_register_callback(cib_t * cib, int call_id, int timeout, gboolean onl blob->only_success = only_success; blob->user_data = user_data; blob->callback = callback; + blob->free_func = free_func; if (timeout > 0) { struct timer_rec_s *async_timer = NULL; diff --git a/lib/cib/cib_utils.c b/lib/cib/cib_utils.c index d321517..4dc65aa 100644 --- a/lib/cib/cib_utils.c +++ b/lib/cib/cib_utils.c @@ -624,12 +624,6 @@ cib_native_callback(cib_t * cib, xmlNode * msg, int call_id, int rc) { xmlNode *output = NULL; cib_callback_client_t *blob = NULL; - cib_callback_client_t local_blob; - - local_blob.id = NULL; - local_blob.callback = NULL; - local_blob.user_data = NULL; - local_blob.only_success = FALSE; if (msg != NULL) { crm_element_value_int(msg, F_CIB_RC, &rc); @@ -638,16 +632,8 @@ cib_native_callback(cib_t * cib, xmlNode * msg, int call_id, int rc) } blob = g_hash_table_lookup(cib_op_callback_table, GINT_TO_POINTER(call_id)); - - if (blob != NULL) { - local_blob = *blob; - blob = NULL; - - remove_cib_op_callback(call_id, FALSE); - - } else { + if (blob == NULL) { crm_trace("No callback found for call %d", call_id); - local_blob.callback = NULL; } if (cib == NULL) { @@ -659,15 +645,20 @@ cib_native_callback(cib_t * cib, xmlNode * msg, int call_id, int rc) rc = pcmk_ok; } - if (local_blob.callback != NULL && (rc == pcmk_ok || local_blob.only_success == FALSE)) { - crm_trace("Invoking callback %s for call %d", crm_str(local_blob.id), call_id); - local_blob.callback(msg, call_id, rc, output, local_blob.user_data); + if (blob && blob->callback && (rc == pcmk_ok || blob->only_success == FALSE)) { + crm_trace("Invoking callback %s for call %d", crm_str(blob->id), call_id); + blob->callback(msg, call_id, rc, output, blob->user_data); } else if (cib && cib->op_callback == NULL && rc != pcmk_ok) { crm_warn("CIB command failed: %s", pcmk_strerror(rc)); crm_log_xml_debug(msg, "Failed CIB Update"); } + /* This may free user_data, so do it after the callback */ + if (blob) { + remove_cib_op_callback(call_id, FALSE); + } + if (cib && cib->op_callback != NULL) { crm_trace("Invoking global callback for call %d", call_id); cib->op_callback(msg, call_id, rc, output); diff --git a/lib/cluster/legacy.c b/lib/cluster/legacy.c index d93613d..e9905f6 100644 --- a/lib/cluster/legacy.c +++ b/lib/cluster/legacy.c @@ -52,6 +52,21 @@ void *ais_ipc_ctx = NULL; hdb_handle_t ais_ipc_handle = 0; +static bool valid_cman_name(const char *name, uint32_t nodeid) +{ + bool rc = TRUE; + + /* Yes, %d, because that's what CMAN does */ + char *fakename = crm_strdup_printf("Node%d", nodeid); + + if(crm_str_eq(fakename, name, TRUE)) { + rc = FALSE; + crm_notice("Ignoring inferred name from cman: %s", fakename); + } + free(fakename); + return rc; +} + static gboolean plugin_get_details(uint32_t * id, char **uname) { @@ -361,6 +376,7 @@ cman_event_callback(cman_handle_t handle, void *privdata, int reason, int arg) arg ? "retained" : "still lost"); } + memset(cman_nodes, 0, MAX_NODES * sizeof(cman_node_t)); rc = cman_get_nodes(pcmk_cman_handle, MAX_NODES, &node_count, cman_nodes); if (rc < 0) { crm_err("Couldn't query cman node list: %d %d", rc, errno); @@ -369,6 +385,7 @@ cman_event_callback(cman_handle_t handle, void *privdata, int reason, int arg) for (lpc = 0; lpc < node_count; lpc++) { crm_node_t *peer = NULL; + const char *name = NULL; if (cman_nodes[lpc].cn_nodeid == 0) { /* Never allow node ID 0 to be considered a member #315711 */ @@ -376,7 +393,11 @@ cman_event_callback(cman_handle_t handle, void *privdata, int reason, int arg) continue; } - peer = crm_get_peer(cman_nodes[lpc].cn_nodeid, cman_nodes[lpc].cn_name); + if(valid_cman_name(cman_nodes[lpc].cn_name, cman_nodes[lpc].cn_nodeid)) { + name = cman_nodes[lpc].cn_name; + } + + peer = crm_get_peer(cman_nodes[lpc].cn_nodeid, name); if(cman_nodes[lpc].cn_member) { crm_update_peer_state(__FUNCTION__, peer, CRM_NODE_MEMBER, crm_peer_seq); @@ -631,15 +652,17 @@ cman_node_name(uint32_t nodeid) cman = cman_init(NULL); if (cman != NULL && cman_is_active(cman)) { - us.cn_name[0] = 0; + + memset(&us, 0, sizeof(cman_node_t)); cman_get_node(cman, nodeid, &us); - name = strdup(us.cn_name); - crm_info("Using CMAN node name %s for %u", name, nodeid); - } + if(valid_cman_name(us.cn_name, nodeid)) { + name = strdup(us.cn_name); + crm_info("Using CMAN node name %s for %u", name, nodeid); + } + } cman_finish(cman); # endif - if (name == NULL) { crm_debug("Unable to get node name for nodeid %u", nodeid); } @@ -667,7 +690,6 @@ init_cs_connection_once(crm_cluster_t * cluster) if (cluster_connect_cpg(cluster) == FALSE) { return FALSE; } - cluster->uname = cman_node_name(0 /* CMAN_NODEID_US */ ); break; case pcmk_cluster_heartbeat: crm_info("Could not find an active corosync based cluster"); diff --git a/lib/common/ipc.c b/lib/common/ipc.c index d71c54a..f4188ed 100644 --- a/lib/common/ipc.c +++ b/lib/common/ipc.c @@ -46,8 +46,8 @@ struct crm_ipc_response_header { }; static int hdr_offset = 0; -static int ipc_buffer_max = 0; -static unsigned int pick_ipc_buffer(int max); +static unsigned int ipc_buffer_max = 0; +static unsigned int pick_ipc_buffer(unsigned int max); static inline void crm_ipc_init(void) @@ -60,7 +60,7 @@ crm_ipc_init(void) } } -int +unsigned int crm_ipc_default_buffer_size(void) { return pick_ipc_buffer(0); @@ -91,7 +91,7 @@ generateReference(const char *custom1, const char *custom2) since_epoch = calloc(1, reference_len); if (since_epoch != NULL) { - sprintf(since_epoch, "%s-%s-%ld-%u", + sprintf(since_epoch, "%s-%s-%lu-%u", local_cust1, local_cust2, (unsigned long)time(NULL), ref_counter++); } @@ -431,7 +431,7 @@ crm_ipcs_recv(crm_client_t * c, void *data, size_t size, uint32_t * id, uint32_t unsigned int size_u = 1 + header->size_uncompressed; uncompressed = calloc(1, size_u); - crm_trace("Decompressing message data %d bytes into %d bytes", + crm_trace("Decompressing message data %u bytes into %u bytes", header->size_compressed, size_u); rc = BZ2_bzBuffToBuffDecompress(uncompressed, &size_u, text, header->size_compressed, 1, 0); @@ -531,9 +531,9 @@ crm_ipcs_flush_events(crm_client_t * c) } ssize_t -crm_ipc_prepare(uint32_t request, xmlNode * message, struct iovec ** result, int32_t max_send_size) +crm_ipc_prepare(uint32_t request, xmlNode * message, struct iovec ** result, uint32_t max_send_size) { - static int biggest = 0; + static unsigned int biggest = 0; struct iovec *iov; unsigned int total = 0; char *compressed = NULL; @@ -579,20 +579,18 @@ crm_ipc_prepare(uint32_t request, xmlNode * message, struct iovec ** result, int free(buffer); - if (header->size_compressed > biggest) { - biggest = 2 * QB_MAX(header->size_compressed, biggest); - } + biggest = QB_MAX(header->size_compressed, biggest); } else { ssize_t rc = -EMSGSIZE; crm_log_xml_trace(message, "EMSGSIZE"); - biggest = 2 * QB_MAX(header->size_uncompressed, biggest); + biggest = QB_MAX(header->size_uncompressed, biggest); crm_err - ("Could not compress the message into less than the configured ipc limit (%d bytes)." - "Set PCMK_ipc_buffer to a higher value (%d bytes suggested)", max_send_size, - biggest); + ("Could not compress the message (%u bytes) into less than the configured ipc limit (%u bytes). " + "Set PCMK_ipc_buffer to a higher value (%u bytes suggested)", + header->size_uncompressed, max_send_size, 4 * biggest); free(compressed); free(buffer); @@ -656,7 +654,7 @@ crm_ipcs_sendv(crm_client_t * c, struct iovec * iov, enum crm_ipc_flags flags) rc = qb_ipcs_response_sendv(c->ipcs, iov, 2); if (rc < header->qb.size) { - crm_notice("Response %d to %p[%d] (%d bytes) failed: %s (%d)", + crm_notice("Response %d to %p[%d] (%u bytes) failed: %s (%d)", header->qb.id, c->ipcs, c->pid, header->qb.size, pcmk_strerror(rc), rc); } else { @@ -747,9 +745,9 @@ struct crm_ipc_s { }; static unsigned int -pick_ipc_buffer(int max) +pick_ipc_buffer(unsigned int max) { - static int global_max = 0; + static unsigned int global_max = 0; if(global_max == 0) { const char *env = getenv("PCMK_ipc_buffer"); @@ -925,7 +923,7 @@ crm_ipc_decompress(crm_ipc_t * client) unsigned int new_buf_size = QB_MAX((hdr_offset + size_u), client->max_buf_size); char *uncompressed = calloc(1, new_buf_size); - crm_trace("Decompressing message data %d bytes into %d bytes", + crm_trace("Decompressing message data %u bytes into %u bytes", header->size_compressed, size_u); rc = BZ2_bzBuffToBuffDecompress(uncompressed + hdr_offset, &size_u, @@ -986,7 +984,7 @@ crm_ipc_read(crm_ipc_t * client) return -EBADMSG; } - crm_trace("Received %s event %d, size=%d, rc=%d, text: %.100s", + crm_trace("Received %s event %d, size=%u, rc=%d, text: %.100s", client->name, header->qb.id, header->qb.size, client->msg_size, client->buffer + hdr_offset); @@ -1166,9 +1164,9 @@ crm_ipc_send(crm_ipc_t * client, xmlNode * message, enum crm_ipc_flags flags, in if(header->size_compressed) { if(factor < 10 && (client->max_buf_size / 10) < (rc / factor)) { - crm_notice("Compressed message exceeds %d0%% of the configured ipc limit (%d bytes), " - "consider setting PCMK_ipc_buffer to %d or higher", - factor, client->max_buf_size, 2*client->max_buf_size); + crm_notice("Compressed message exceeds %d0%% of the configured ipc limit (%u bytes), " + "consider setting PCMK_ipc_buffer to %u or higher", + factor, client->max_buf_size, 2 * client->max_buf_size); factor++; } } @@ -1211,7 +1209,7 @@ crm_ipc_send(crm_ipc_t * client, xmlNode * message, enum crm_ipc_flags flags, in if (rc > 0) { struct crm_ipc_response_header *hdr = (struct crm_ipc_response_header *)(void*)client->buffer; - crm_trace("Received response %d, size=%d, rc=%ld, text: %.200s", hdr->qb.id, hdr->qb.size, + crm_trace("Received response %d, size=%u, rc=%ld, text: %.200s", hdr->qb.id, hdr->qb.size, rc, crm_ipc_buffer(client)); if (reply) { diff --git a/lib/common/xml.c b/lib/common/xml.c index 8eed245..299c7bf 100644 --- a/lib/common/xml.c +++ b/lib/common/xml.c @@ -3821,6 +3821,7 @@ crm_xml_dump(xmlNode * data, int options, char **buffer, int *offset, int *max, if(data == NULL) { *offset = 0; *max = 0; + return; } #if 0 if (is_not_set(options, xml_log_option_filtered)) { @@ -5621,7 +5622,7 @@ update_validation(xmlNode ** xml_blob, int *best, int max, gboolean transform, g break; } else if (known_schemas[lpc].transform == NULL) { - crm_notice("%s-style configuration is also valid for %s", + crm_debug("%s-style configuration is also valid for %s", known_schemas[lpc].name, known_schemas[next].name); if (validate_with(xml, next, to_logs)) { diff --git a/lib/lrmd/lrmd_client.c b/lib/lrmd/lrmd_client.c index f5e34ee..42bdf2b 100644 --- a/lib/lrmd/lrmd_client.c +++ b/lib/lrmd/lrmd_client.c @@ -1369,7 +1369,7 @@ lrmd_api_disconnect(lrmd_t * lrmd) { lrmd_private_t *native = lrmd->private; - crm_info("Disconnecting from lrmd service"); + crm_info("Disconnecting from %d lrmd service", native->type); switch (native->type) { case CRM_CLIENT_IPC: lrmd_ipc_disconnect(lrmd); diff --git a/lib/services/dbus.c b/lib/services/dbus.c index e2efecb..d42affe 100644 --- a/lib/services/dbus.c +++ b/lib/services/dbus.c @@ -329,9 +329,6 @@ pcmk_dbus_lookup_cb(DBusPendingCall *pending, void *user_data) pcmk_dbus_lookup_result(reply, user_data); - if(pending) { - dbus_pending_call_unref(pending); - } if(reply) { dbus_message_unref(reply); } diff --git a/lib/services/services.c b/lib/services/services.c index 7e2b9f7..3f40078 100644 --- a/lib/services/services.c +++ b/lib/services/services.c @@ -150,6 +150,7 @@ resources_action_create(const char *name, const char *standard, const char *prov op = calloc(1, sizeof(svc_action_t)); op->opaque = calloc(1, sizeof(svc_action_private_t)); + op->opaque->pending = NULL; op->rsc = strdup(name); op->action = strdup(action); op->interval = interval; @@ -158,6 +159,7 @@ resources_action_create(const char *name, const char *standard, const char *prov op->agent = strdup(agent); op->sequence = ++operations; op->flags = flags; + if (asprintf(&op->id, "%s_%s_%d", name, action, interval) == -1) { goto return_error; } @@ -335,6 +337,7 @@ services_action_create_generic(const char *exec, const char *args[]) op->opaque->exec = strdup(exec); op->opaque->args[0] = strdup(exec); + op->opaque->pending = NULL; for (cur_arg = 1; args && args[cur_arg - 1]; cur_arg++) { op->opaque->args[cur_arg] = strdup(args[cur_arg - 1]); @@ -361,17 +364,17 @@ services_set_op_pending(svc_action_t *op, DBusPendingCall *pending) { if (op->opaque->pending && (op->opaque->pending != pending)) { if (pending) { - crm_info("Lost pending DBus call (%p)", op->opaque->pending); + crm_info("Lost pending %s DBus call (%p)", op->id, op->opaque->pending); } else { - crm_trace("Done with pending DBus call (%p)", op->opaque->pending); + crm_info("Done with pending %s DBus call (%p)", op->id, op->opaque->pending); } dbus_pending_call_unref(op->opaque->pending); } op->opaque->pending = pending; if (pending) { - crm_trace("Updated pending DBus call (%p)", pending); + crm_info("Updated pending %s DBus call (%p)", op->id, pending); } else { - crm_trace("Cleared pending DBus call"); + crm_info("Cleared pending %s DBus call", op->id); } } #endif @@ -457,7 +460,7 @@ services_action_free(svc_action_t * op) gboolean cancel_recurring_action(svc_action_t * op) { - crm_info("Cancelling operation %s", op->id); + crm_info("Cancelling %s operation %s", op->standard, op->id); if (recurring_actions) { g_hash_table_remove(recurring_actions, op->id); diff --git a/lib/services/systemd.c b/lib/services/systemd.c index e1e1bc9..ca56915 100644 --- a/lib/services/systemd.c +++ b/lib/services/systemd.c @@ -189,16 +189,13 @@ systemd_loadunit_cb(DBusPendingCall *pending, void *user_data) reply = dbus_pending_call_steal_reply(pending); } - if(op) { - crm_trace("Got result: %p for %p for %s, %s", reply, pending, op->rsc, op->action); - } else { - crm_trace("Got result: %p for %p", reply, pending); - } + crm_trace("Got result: %p for %p / %p for %s", reply, pending, op->opaque->pending, op->id); + + CRM_LOG_ASSERT(pending == op->opaque->pending); + services_set_op_pending(op, NULL); + systemd_loadunit_result(reply, user_data); - if(pending) { - dbus_pending_call_unref(pending); - } if(reply) { dbus_message_unref(reply); } @@ -209,6 +206,7 @@ systemd_unit_by_name(const gchar * arg_name, svc_action_t *op) { DBusMessage *msg; DBusMessage *reply = NULL; + DBusPendingCall* pending = NULL; char *name = NULL; /* @@ -249,7 +247,11 @@ systemd_unit_by_name(const gchar * arg_name, svc_action_t *op) return munit; } - pcmk_dbus_send(msg, systemd_proxy, systemd_loadunit_cb, op, op? op->timeout : DBUS_TIMEOUT_USE_DEFAULT); + pending = pcmk_dbus_send(msg, systemd_proxy, systemd_loadunit_cb, op, op->timeout); + if(pending) { + services_set_op_pending(op, pending); + } + dbus_message_unref(msg); return NULL; } @@ -459,23 +461,12 @@ systemd_async_dispatch(DBusPendingCall *pending, void *user_data) reply = dbus_pending_call_steal_reply(pending); } - if(op) { - crm_trace("Got result: %p for %p for %s, %s", reply, pending, op->rsc, op->action); - if (pending == op->opaque->pending) { - op->opaque->pending = NULL; - } else { - crm_info("Received unexpected reply for pending DBus call (%p vs %p)", - op->opaque->pending, pending); - } - systemd_exec_result(reply, op); + crm_trace("Got result: %p for %p for %s, %s", reply, pending, op->rsc, op->action); - } else { - crm_trace("Got result: %p for %p", reply, pending); - } + CRM_LOG_ASSERT(pending == op->opaque->pending); + services_set_op_pending(op, NULL); + systemd_exec_result(reply, op); - if(pending) { - dbus_pending_call_unref(pending); - } if(reply) { dbus_message_unref(reply); } @@ -536,7 +527,6 @@ systemd_unit_exec_with_unit(svc_action_t * op, const char *unit) free(state); return op->rc == PCMK_OCF_OK; } else if (pending) { - dbus_pending_call_ref(pending); services_set_op_pending(op, pending); return TRUE; } diff --git a/lib/services/upstart.c b/lib/services/upstart.c index 31b875b..eb8cfa8 100644 --- a/lib/services/upstart.c +++ b/lib/services/upstart.c @@ -322,10 +322,7 @@ upstart_job_check(const char *name, const char *state, void *userdata) } if (op->synchronous == FALSE) { - if (op->opaque->pending) { - dbus_pending_call_unref(op->opaque->pending); - } - op->opaque->pending = NULL; + services_set_op_pending(op, NULL); operation_finalize(op); } } @@ -392,6 +389,7 @@ upstart_async_dispatch(DBusPendingCall *pending, void *user_data) if(pending) { reply = dbus_pending_call_steal_reply(pending); } + if(pcmk_dbus_find_error(op->action, pending, reply, &error)) { /* ignore "already started" or "not running" errors */ @@ -419,11 +417,10 @@ upstart_async_dispatch(DBusPendingCall *pending, void *user_data) } } + CRM_LOG_ASSERT(pending == op->opaque->pending); + services_set_op_pending(op, NULL); operation_finalize(op); - if(pending) { - dbus_pending_call_unref(pending); - } if(reply) { dbus_message_unref(reply); } @@ -483,8 +480,7 @@ upstart_job_exec(svc_action_t * op, gboolean synchronous) free(state); return op->rc == PCMK_OCF_OK; } else if (pending) { - dbus_pending_call_ref(pending); - op->opaque->pending = pending; + services_set_op_pending(op, pending); return TRUE; } return FALSE; @@ -527,8 +523,7 @@ upstart_job_exec(svc_action_t * op, gboolean synchronous) free(job); if(pending) { - dbus_pending_call_ref(pending); - op->opaque->pending = pending; + services_set_op_pending(op, pending); return TRUE; } return FALSE; diff --git a/lrmd/ipc_proxy.c b/lrmd/ipc_proxy.c index 72d83c4..9427393 100644 --- a/lrmd/ipc_proxy.c +++ b/lrmd/ipc_proxy.c @@ -165,14 +165,14 @@ ipc_proxy_forward_client(crm_client_t *ipc_proxy, xmlNode *xml) */ if (safe_str_eq(msg_type, "event")) { - crm_info("Sending event to %s", ipc_client->id); + crm_trace("Sending event to %s", ipc_client->id); rc = crm_ipcs_send(ipc_client, 0, msg, crm_ipc_server_event); } else if (safe_str_eq(msg_type, "response")) { int msg_id = 0; crm_element_value_int(xml, F_LRMD_IPC_MSG_ID, &msg_id); - crm_info("Sending response to %d - %s", ipc_client->request_id, ipc_client->id); + crm_trace("Sending response to %d - %s", ipc_client->request_id, ipc_client->id); rc = crm_ipcs_send(ipc_client, msg_id, msg, FALSE); CRM_LOG_ASSERT(msg_id == ipc_client->request_id); diff --git a/lrmd/pacemaker_remote.service.in b/lrmd/pacemaker_remote.service.in index 7ec42b4..15e61fb 100644 --- a/lrmd/pacemaker_remote.service.in +++ b/lrmd/pacemaker_remote.service.in @@ -9,7 +9,6 @@ WantedBy=multi-user.target Type=simple KillMode=process NotifyAccess=none -SysVStartPriority=99 EnvironmentFile=-/etc/sysconfig/pacemaker ExecStart=@sbindir@/pacemaker_remoted diff --git a/mcp/pacemaker.service.in b/mcp/pacemaker.service.in index 2ef9454..9b0a824 100644 --- a/mcp/pacemaker.service.in +++ b/mcp/pacemaker.service.in @@ -20,7 +20,6 @@ WantedBy=multi-user.target Type=simple KillMode=process NotifyAccess=main -SysVStartPriority=99 EnvironmentFile=-@sysconfdir@/sysconfig/pacemaker EnvironmentFile=-@sysconfdir@/sysconfig/sbd SuccessExitStatus=100 diff --git a/pengine/allocate.c b/pengine/allocate.c index ec5a18d..c2e56f9 100644 --- a/pengine/allocate.c +++ b/pengine/allocate.c @@ -1495,11 +1495,12 @@ stage6(pe_working_set_t * data_set) } } - if (last_stonith) { - order_actions(last_stonith, done, pe_order_implies_then); - } else if (dc_fence) { + if (dc_fence) { order_actions(dc_down, done, pe_order_implies_then); + + } else if (last_stonith) { + order_actions(last_stonith, done, pe_order_implies_then); } order_actions(done, all_stopped, pe_order_implies_then); diff --git a/pengine/test10/rec-node-14.dot b/pengine/test10/rec-node-14.dot index 395fa89..5ceef92 100644 --- a/pengine/test10/rec-node-14.dot +++ b/pengine/test10/rec-node-14.dot @@ -2,9 +2,9 @@ "all_stopped" [ style=bold color="green" fontcolor="orange" ] "stonith 'reboot' node1" -> "stonith 'reboot' node3" [ style = bold] "stonith 'reboot' node1" [ style=bold color="green" fontcolor="black"] +"stonith 'reboot' node2" -> "stonith_complete" [ style = bold] "stonith 'reboot' node2" [ style=bold color="green" fontcolor="black"] "stonith 'reboot' node3" -> "stonith 'reboot' node2" [ style = bold] -"stonith 'reboot' node3" -> "stonith_complete" [ style = bold] "stonith 'reboot' node3" [ style=bold color="green" fontcolor="black"] "stonith_complete" -> "all_stopped" [ style = bold] "stonith_complete" [ style=bold color="green" fontcolor="orange" ] diff --git a/pengine/test10/rec-node-14.exp b/pengine/test10/rec-node-14.exp index 58bb5ca..0e5e163 100644 --- a/pengine/test10/rec-node-14.exp +++ b/pengine/test10/rec-node-14.exp @@ -39,7 +39,7 @@ - + diff --git a/pengine/test10/stonith-0.dot b/pengine/test10/stonith-0.dot index 29cdd59..8ad32fd 100644 --- a/pengine/test10/stonith-0.dot +++ b/pengine/test10/stonith-0.dot @@ -71,13 +71,13 @@ digraph "g" { "stonith 'reboot' c001n03" -> "ocf_192.168.100.181_stop_0 c001n03" [ style = bold] "stonith 'reboot' c001n03" -> "ocf_192.168.100.183_stop_0 c001n03" [ style = bold] "stonith 'reboot' c001n03" -> "rsc_c001n07_stop_0 c001n03" [ style = bold] +"stonith 'reboot' c001n03" -> "stonith_complete" [ style = bold] "stonith 'reboot' c001n03" [ style=bold color="green" fontcolor="black"] "stonith 'reboot' c001n05" -> "group-1_stop_0" [ style = bold] "stonith 'reboot' c001n05" -> "ocf_192.168.100.181_stop_0 c001n05" [ style = bold] "stonith 'reboot' c001n05" -> "ocf_192.168.100.183_stop_0 c001n05" [ style = bold] "stonith 'reboot' c001n05" -> "rsc_c001n05_stop_0 c001n05" [ style = bold] "stonith 'reboot' c001n05" -> "stonith 'reboot' c001n03" [ style = bold] -"stonith 'reboot' c001n05" -> "stonith_complete" [ style = bold] "stonith 'reboot' c001n05" [ style=bold color="green" fontcolor="black"] "stonith_complete" -> "all_stopped" [ style = bold] "stonith_complete" -> "heartbeat_192.168.100.182_start_0 c001n02" [ style = bold] diff --git a/pengine/test10/stonith-0.exp b/pengine/test10/stonith-0.exp index 9d47215..a6695c9 100644 --- a/pengine/test10/stonith-0.exp +++ b/pengine/test10/stonith-0.exp @@ -394,7 +394,7 @@ - + diff --git a/pengine/test10/systemhealth1.dot b/pengine/test10/systemhealth1.dot index 28841b7..a29f519 100644 --- a/pengine/test10/systemhealth1.dot +++ b/pengine/test10/systemhealth1.dot @@ -1,8 +1,8 @@ digraph "g" { "all_stopped" [ style=bold color="green" fontcolor="orange" ] +"stonith 'reboot' hs21c" -> "stonith_complete" [ style = bold] "stonith 'reboot' hs21c" [ style=bold color="green" fontcolor="black"] "stonith 'reboot' hs21d" -> "stonith 'reboot' hs21c" [ style = bold] -"stonith 'reboot' hs21d" -> "stonith_complete" [ style = bold] "stonith 'reboot' hs21d" [ style=bold color="green" fontcolor="black"] "stonith_complete" -> "all_stopped" [ style = bold] "stonith_complete" [ style=bold color="green" fontcolor="orange" ] diff --git a/pengine/test10/systemhealth1.exp b/pengine/test10/systemhealth1.exp index 80a2329..aa2afe1 100644 --- a/pengine/test10/systemhealth1.exp +++ b/pengine/test10/systemhealth1.exp @@ -27,7 +27,7 @@ - + diff --git a/pengine/test10/systemhealthm1.dot b/pengine/test10/systemhealthm1.dot index 28841b7..a29f519 100644 --- a/pengine/test10/systemhealthm1.dot +++ b/pengine/test10/systemhealthm1.dot @@ -1,8 +1,8 @@ digraph "g" { "all_stopped" [ style=bold color="green" fontcolor="orange" ] +"stonith 'reboot' hs21c" -> "stonith_complete" [ style = bold] "stonith 'reboot' hs21c" [ style=bold color="green" fontcolor="black"] "stonith 'reboot' hs21d" -> "stonith 'reboot' hs21c" [ style = bold] -"stonith 'reboot' hs21d" -> "stonith_complete" [ style = bold] "stonith 'reboot' hs21d" [ style=bold color="green" fontcolor="black"] "stonith_complete" -> "all_stopped" [ style = bold] "stonith_complete" [ style=bold color="green" fontcolor="orange" ] diff --git a/pengine/test10/systemhealthm1.exp b/pengine/test10/systemhealthm1.exp index 80a2329..aa2afe1 100644 --- a/pengine/test10/systemhealthm1.exp +++ b/pengine/test10/systemhealthm1.exp @@ -27,7 +27,7 @@ - + diff --git a/pengine/test10/systemhealthn1.dot b/pengine/test10/systemhealthn1.dot index 28841b7..a29f519 100644 --- a/pengine/test10/systemhealthn1.dot +++ b/pengine/test10/systemhealthn1.dot @@ -1,8 +1,8 @@ digraph "g" { "all_stopped" [ style=bold color="green" fontcolor="orange" ] +"stonith 'reboot' hs21c" -> "stonith_complete" [ style = bold] "stonith 'reboot' hs21c" [ style=bold color="green" fontcolor="black"] "stonith 'reboot' hs21d" -> "stonith 'reboot' hs21c" [ style = bold] -"stonith 'reboot' hs21d" -> "stonith_complete" [ style = bold] "stonith 'reboot' hs21d" [ style=bold color="green" fontcolor="black"] "stonith_complete" -> "all_stopped" [ style = bold] "stonith_complete" [ style=bold color="green" fontcolor="orange" ] diff --git a/pengine/test10/systemhealthn1.exp b/pengine/test10/systemhealthn1.exp index 80a2329..aa2afe1 100644 --- a/pengine/test10/systemhealthn1.exp +++ b/pengine/test10/systemhealthn1.exp @@ -27,7 +27,7 @@ - + diff --git a/pengine/test10/systemhealtho1.dot b/pengine/test10/systemhealtho1.dot index 28841b7..a29f519 100644 --- a/pengine/test10/systemhealtho1.dot +++ b/pengine/test10/systemhealtho1.dot @@ -1,8 +1,8 @@ digraph "g" { "all_stopped" [ style=bold color="green" fontcolor="orange" ] +"stonith 'reboot' hs21c" -> "stonith_complete" [ style = bold] "stonith 'reboot' hs21c" [ style=bold color="green" fontcolor="black"] "stonith 'reboot' hs21d" -> "stonith 'reboot' hs21c" [ style = bold] -"stonith 'reboot' hs21d" -> "stonith_complete" [ style = bold] "stonith 'reboot' hs21d" [ style=bold color="green" fontcolor="black"] "stonith_complete" -> "all_stopped" [ style = bold] "stonith_complete" [ style=bold color="green" fontcolor="orange" ] diff --git a/pengine/test10/systemhealtho1.exp b/pengine/test10/systemhealtho1.exp index 80a2329..aa2afe1 100644 --- a/pengine/test10/systemhealtho1.exp +++ b/pengine/test10/systemhealtho1.exp @@ -27,7 +27,7 @@ - + diff --git a/pengine/test10/systemhealthp1.dot b/pengine/test10/systemhealthp1.dot index 28841b7..a29f519 100644 --- a/pengine/test10/systemhealthp1.dot +++ b/pengine/test10/systemhealthp1.dot @@ -1,8 +1,8 @@ digraph "g" { "all_stopped" [ style=bold color="green" fontcolor="orange" ] +"stonith 'reboot' hs21c" -> "stonith_complete" [ style = bold] "stonith 'reboot' hs21c" [ style=bold color="green" fontcolor="black"] "stonith 'reboot' hs21d" -> "stonith 'reboot' hs21c" [ style = bold] -"stonith 'reboot' hs21d" -> "stonith_complete" [ style = bold] "stonith 'reboot' hs21d" [ style=bold color="green" fontcolor="black"] "stonith_complete" -> "all_stopped" [ style = bold] "stonith_complete" [ style=bold color="green" fontcolor="orange" ] diff --git a/pengine/test10/systemhealthp1.exp b/pengine/test10/systemhealthp1.exp index 80a2329..aa2afe1 100644 --- a/pengine/test10/systemhealthp1.exp +++ b/pengine/test10/systemhealthp1.exp @@ -27,7 +27,7 @@ - + diff --git a/tools/1node2heartbeat b/tools/1node2heartbeat deleted file mode 100755 index b63a0c8..0000000 --- a/tools/1node2heartbeat +++ /dev/null @@ -1,326 +0,0 @@ -#!/usr/bin/python -# -# Program to determine current list of enabled services for init state 3 -# and create heartbeat CRM configuration for heartbeat to manage them -# -__copyright__=''' -Author: Alan Robertson -Copyright (C) 2006 International Business Machines -''' - -# 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. -import os,re -# -# Here's the plan: -# Find out the default run level -# Find out what (additional?) services are enabled in that run level -# Figure out which of them start after the network (or heartbeat?) -# Ignore heartbeat :-) -# Figure out which services supply the $services -# Look to see if the SUSE /etc/insserv.conf file exists -# If so, then scan it for who provides the $services -# defined by the LSB -# If we're on Red Hat, then make some Red Hat type assumptions -# (whatever those might be) -# If we're not, then make some generic assumptions... -# Scan the init scripts for their dependencies... -# Eliminate anything at or before 'network'. -# Create resources corresponding to all active services -# Include monitor actions for those services -# that can be started after 'network' -# Add the start-after dependencies -# -# Things to consider doing in the future: -# Constrain them to only run on the local system? -# Put them all in a convenience group (no colocation, no ordering) -# Add start and stop timeouts - -ServiceKeywords = {} -ServiceMap = {} -ProvidesMap = {} -RequiresMap = {} -SkipMap = {'heartbeat': None, 'random': None} -NoMonitor = {'microcode': None} -PreReqs = ['network'] -IgnoreList = [] -sysname = os.uname()[1] -InitDir = "/etc/init.d" - -def service_is_hb_compatible(service): - scriptname = os.path.join(InitDir, service) - command=scriptname + " status >/dev/null 2>&1"; - rc = os.system(command) - return rc == 0 - -def find_ordered_services(dir): - allscripts = os.listdir(dir) - allscripts.sort() - services = [] - for entry in allscripts: - matchobj = re.match("S[0-9]+(.*)", entry) - if not matchobj: - continue - service = matchobj.group(1) - if SkipMap.has_key(service): - continue - if service_is_hb_compatible(service): - services.append(service) - else: - IgnoreList.append(service) - return services - - -def register_services(initdir, services): - for service in services: - if not ServiceMap.has_key(service): - ServiceMap[service] = os.path.join(initdir, service) - for service in services: - script_dependency_scan(service, os.path.join(initdir, service), ServiceMap) - -# -# From the LSB version 3.1: "Comment Conventions for Init Scripts" -# -### BEGIN INIT INFO -### END INIT INFO -# -# The delimiter lines may contain trailing whitespace, which shall be ignored. -# All lines inside the block shall begin with a hash character '#' in the -# first column, so the shell interprets them as comment lines which do not -# affect operation of the script. The lines shall be of the form: -# {keyword}: arg1 [arg2...] -# with exactly one space character between the '#' and the keyword, with a -# single exception. In lines following a line containing the Description -# keyword, and until the next keyword or block ending delimiter is seen, -# a line where the '#' is followed by more than one space or a tab -# character shall be treated as a continuation of the previous line. -# - -# Make this a class to avoid recompiling it for each script we scan. -class pats: - begin=re.compile("###\s+BEGIN\s+INIT\s+INFO") - end=re.compile("###\s+END\s+INIT\s+INFO") - desc=re.compile("# Description:\s*(.*)", re.IGNORECASE) - desc_continue=re.compile("#( +|\t)\s*(.*)") - keyword=re.compile("# ([^\s:]+):\s*(.*)\s*\Z") - -def script_keyword_scan(filename, servicename): - keywords = {} - ST_START=0 - ST_INITINFO=1 - ST_DESCRIPTION=1 - description="" - state=ST_START - - try: - fd = open(filename) - except IOError: - return keywords - - while 1: - line = fd.readline() - if not line: - break - - if state == ST_START: - if pats.begin.match(line): - state = ST_INITINFO - continue - if pats.end.match(line): - break - - if state == ST_DESCRIPTION: - match = pats.desc_continue.match(line) - if match: - description += ("\n" + match.group(2)) - continue - state = ST_INITINFO - - match = pats.desc.match(line) - if match: - state = ST_DESCRIPTION - description = match.group(1) - continue - - match = pats.keyword.match(line) - if match: - keywords[match.group(1)] = match.group(2) - - # Clean up and return - fd.close() - if description != "": - keywords["Description"] = description - keywords["_PATHNAME_"] = filename - keywords["_RESOURCENAME_"] = "R_" + sysname + "_" + servicename - return keywords - -def script_dependency_scan(service, script, servicemap): - keywords=script_keyword_scan(script, service) - ServiceKeywords[service] = keywords - -SysServiceGuesses = { - '$local_fs': ['boot.localfs'], - '$network': ['network'], - '$named': ['named'], - '$portmap': ['portmap'], - '$remote_fs': ['nfs'], - '$syslog': ['syslog'], - '$netdaemons': ['portmap', 'inetd'], - '$time': ['ntp'], -} - -# -# For specific versions of Linux, there are often better ways -# to do this... -# -# (e.g., for SUSE Linux, one should look at /etc/insserv.conf file) -# -def map_sys_services(servicemap): - sysservicemap = {} - for sysserv in SysServiceGuesses.keys(): - servlist = SysServiceGuesses[sysserv] - result = [] - for service in servlist: - if servicemap.has_key(service): - result.append(service) - - sysservicemap[sysserv] = result - return sysservicemap - -# -# -# -def create_service_dependencies(servicekeywords, systemservicemap): - dependencies = {} - for service in servicekeywords.keys(): - if not dependencies.has_key(service): - dependencies[service] = {} - for key in ('Required-Start', 'Should-Start'): - if not servicekeywords[service].has_key(key): - continue - for depserv in servicekeywords[service][key].split(): - if systemservicemap.has_key(depserv): - sysserv = systemservicemap[depserv] - for serv in sysserv: - dependencies[service][serv] = None - else: - if servicekeywords.has_key(depserv): - dependencies[service][depserv] = None - if len(dependencies[service]) == 0: - del dependencies[service] - return dependencies - -# -# Modify the service name map to include all the mappings from -# 'Provides' services to real service script names... -# -def map_script_services(sysservmap, servicekeywords): - for service in servicekeywords.keys(): - if not servicekeywords[service].has_key('Provides'): - continue - for provided in servicekeywords[service]['Provides'].split(): - if not sysservmap.has_key(provided): - sysservmap[provided] = [] - sysservmap[provided].append(service) - return sysservmap - -def create_cib_update(keywords, depmap): - services = keywords.keys() - services.sort() - result = "" - # Create the XML for the resources - result += '\n' - result += '\n' - result += '\n' - result += '\n' - result += '\n' - groupname="G_" + sysname + "_localinit" - result += ' \n' - for service in services: - rid = keywords[service]["_RESOURCENAME_"] - monid = "OPmon_" + sysname + '_' + service - result += \ - ' \n' + \ - ' \n' + \ - ' \n' - if not NoMonitor.has_key(service): - result += \ - ' \n' - result += \ - ' \n' \ - ' \n' - result += ' \n' - result += '\n' - services = depmap.keys() - services.sort() - result += '\n' - for service in services: - rid = keywords[service]["_RESOURCENAME_"] - deps = depmap[service].keys() - deps.sort() - for dep in deps: - if not keywords.has_key(dep): - continue - depid = keywords[dep]["_RESOURCENAME_"] - orderid='O_' + sysname + '_' + service + '_' + dep - result += ' \n' - loc_id="Loc_" + sysname + "_localinit" - rule_id="LocRule_" + sysname + "_localinit" - expr_id="LocExp_" + sysname + "_localinit" - - result += ' \n' - result += ' \n' - result += ' \n' - result += ' \n' - result += ' \n' - result += '\n' - result += '\n' - result += '\n' - result += '\n' - return result - - - -def remove_a_prereq(service, servicemap, keywords, deps): - if deps.has_key(service): - parents = deps[service].keys() - del deps[service] - else: - parents = [] - if servicemap.has_key(service): - del servicemap[service] - if keywords.has_key(service): - del keywords[service] - for parent in parents: - if not deps.has_key(parent): - continue - remove_a_prereq(parent, servicemap, keywords, deps) - - -def remove_important_prereqs(prereqs, servicemap, keywords, deps): - # Find everything these important prereqs need and get rid of them... - for service in prereqs: - remove_a_prereq(service, servicemap, keywords, deps) - -ServiceList = find_ordered_services(os.path.join(InitDir, "rc3.d")) -register_services(InitDir, ServiceList) -SysServiceMap = map_sys_services(ServiceMap) -map_script_services(SysServiceMap, ServiceKeywords) -ServiceDependencies = create_service_dependencies(ServiceKeywords,SysServiceMap) -remove_important_prereqs(PreReqs, SysServiceMap, ServiceKeywords, ServiceDependencies) - -print create_cib_update(ServiceKeywords, ServiceDependencies) diff --git a/tools/crm_commands.py.in b/tools/crm_commands.py.in deleted file mode 100644 index c48d82c..0000000 --- a/tools/crm_commands.py.in +++ /dev/null @@ -1,132 +0,0 @@ -# -# -# pingd OCF Resource Agent -# Records (in the CIB) the current number of ping nodes a -# cluster node can connect to. -# -# Copyright (c) 2006 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. -# -####################################################################### - -import crm_utils as utl - -class HelpRequest(Exception): - """Exception raised when a help listing is required.""" - -class ReparseRequest(Exception): - """Exception raised when a command changed the command-line.""" - -def up(*args, **cmdoptions): - l = len(utl.topic_stack) - if l > 1: - utl.topic_stack.pop() - utl.set_topic(utl.topic_stack[-1]) - else: - utl.log_debug("Already at the top of the stack") - -def toggle_flag(*args, **cmdoptions): - flag = cmdoptions["flag"] - if utl.global_opts[flag]: - utl.global_opts[flag] = 0 - else: - utl.global_opts[flag] = 1 - - return utl.global_opts[flag] - -def cd_(*args, **cmdoptions): - utl.log_dev("args: %s\nopts: %s" % (repr(args), repr(cmdoptions))) - if not cmdoptions["topic"]: - utl.log_err("No topic specified") - return 1 - - if cmdoptions["topic"]: - utl.set_topic(cmdoptions["topic"]) - if args: - raise ReparseRequest() - if utl.crm_topic not in utl.topic_stack: - utl.topic_stack.append(cmdoptions["topic"]) - if not utl.global_opts["interactive"]: - help(cmdoptions["topic"]) - return 0 - -def exit(*args, **cmdoptions): - sys.exit(0) - -def help(*args, **cmdoptions): - if args: - raise HelpRequest(args[0]) - raise HelpRequest(utl.crm_topic) - -def debugstate(*args, **cmdoptions): - utl.log_info("Global Options: ") - for opt in utl.global_opts.keys(): - utl.log_info(" * %s:\t%s" % (opt, utl.global_opts[opt])) - utl.log_info("Stack: "+repr(utl.topic_stack)) - utl.log_info("Stack Head: "+utl.crm_topic) - return 0 - -def do_list(*args, **cmdoptions): - topic = utl.crm_topic - if cmdoptions.has_key("topic") and cmdoptions["topic"]: - topic = cmdoptions["topic"] - - utl.log_debug("Complete '%s' listing" % topic) - if topic == "resources": - utl.os_system("crm_resource -l", True) - elif topic == "nodes": - lines = utl.os_system("cibadmin -Q -o nodes", False) - for line in lines: - if line.find("node ") >= 0: - print line.rstrip() - else: - utl.log_err("%s: Topic %s is not (yet) supported" % ("list", topic)) - return 1 - return 0 - -def do_status(*args, **cmdoptions): - topic = utl.crm_topic - if cmdoptions.has_key("topic") and cmdoptions["topic"]: - topic = cmdoptions["topic"] - - if topic == "resources": - if not args: - utl.os_system("crm_resource -L", True) - for rsc in args: - utl.os_system("crm_resource -W -r %s"%rsc, True) - - elif topic == "nodes": - lines = utl.os_system("cibadmin -Q -o status", False) - for line in lines: - line = line.rstrip() - utl.log_dev("status line: "+line) - if line.find("node_state ") >= 0: - if not args: - print line - for node in args: - if line.find(node) >= 0: - print line - else: - utl.log_err("Topic %s is not (yet) supported" % topic) - return 1 - - return 0 diff --git a/tools/crm_mon.c b/tools/crm_mon.c index 0b71275..46a59d6 100644 --- a/tools/crm_mon.c +++ b/tools/crm_mon.c @@ -2715,6 +2715,7 @@ print_status(pe_working_set_t * data_set) } else { online_nodes = add_list_element(online_nodes, node_name); } + free(node_name); continue; } } else { @@ -2727,6 +2728,7 @@ print_status(pe_working_set_t * data_set) } else { offline_nodes = add_list_element(offline_nodes, node_name); } + free(node_name); continue; } } @@ -3078,6 +3080,7 @@ print_html_status(pe_working_set_t * data_set, const char *filename) fprintf(stream, "\n"); } fprintf(stream, "\n"); + free(node_name); } fprintf(stream, "\n"); diff --git a/tools/crm_node.c b/tools/crm_node.c index c484e17..d0195e3 100644 --- a/tools/crm_node.c +++ b/tools/crm_node.c @@ -470,6 +470,7 @@ try_cman(int command, enum cluster_type_e stack) case 'l': case 'p': + memset(cman_nodes, 0, MAX_NODES * sizeof(cman_node_t)); rc = cman_get_nodes(cman_handle, MAX_NODES, &node_count, cman_nodes); if (rc != 0) { fprintf(stderr, "Couldn't query cman node list: %d %d", rc, errno); @@ -489,6 +490,7 @@ try_cman(int command, enum cluster_type_e stack) break; case 'i': + memset(&node, 0, sizeof(cman_node_t)); rc = cman_get_node(cman_handle, CMAN_NODEID_US, &node); if (rc != 0) { fprintf(stderr, "Couldn't query cman node id: %d %d", rc, errno); diff --git a/tools/crm_primitive.py.in b/tools/crm_primitive.py.in deleted file mode 100644 index cfe0b5c..0000000 --- a/tools/crm_primitive.py.in +++ /dev/null @@ -1,268 +0,0 @@ -#!@PYTHON@ - -'''Create an XML fragment describing a new resource -''' - -__copyright__=''' -Author: Andrew Beekhof -Copyright (C) 2005 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. - -import sys,string,os -import xml.dom.minidom - -print_rsc_only = 0 -rsc_name = None -rsc_class = None -rsc_type = None -rsc_provider = None -start_timeout = None -stop_timeout = None -monitor_interval = None -monitor_timeout = None -rsc_options = [] -rsc_location = [] -rsc_colocation = [] - -def create_cib() : - doc = xml.dom.minidom.Document() - cib = doc.createElement("cib") - doc.appendChild(cib) - - configuration = doc.createElement("configuration") - cib.appendChild(configuration) - - #crm_config = doc.createElement("crm_config") - #configuration.appendChild(crm_config) - - resources = doc.createElement("resources") - configuration.appendChild(resources) - constraints = doc.createElement("constraints") - configuration.appendChild(constraints) - - return doc, resources, constraints - -def cib_resource(doc, id, ra_class, type, provider): - - params = None - - resource = doc.createElement("primitive") - - resource.setAttribute("id", id) - resource.setAttribute("type", type) - resource.setAttribute("class", ra_class) - - if ra_class == "ocf": - if not provider: - provider = "heartbeat" - resource.setAttribute("provider", provider) - - elif ra_class != "lsb" and ra_class != "heartbeat": - print "Unknown resource class: "+ ra_class - return None - - operations = doc.createElement("operations") - resource.appendChild(operations) - - if monitor_interval != None: - op = doc.createElement("op") - operations.appendChild(op) - op.setAttribute("id", id + "_mon_" + monitor_interval) - op.setAttribute("name", "monitor") - op.setAttribute("interval", monitor_interval) - if monitor_timeout != None: - op.setAttribute("timeout", monitor_timeout) - - if start_timeout != None: - op = doc.createElement("op") - operations.appendChild(op) - op.setAttribute("id", id + "_start") - op.setAttribute("name", "start") - op.setAttribute("timeout", start_timeout) - - if stop_timeout != None: - op = doc.createElement("op") - operations.appendChild(op) - op.setAttribute("id", id + "_stop") - op.setAttribute("name", "stop") - op.setAttribute("timeout", stop_timeout) - - instance_attributes = doc.createElement("instance_attributes") - instance_attributes.setAttribute("id", id) - resource.appendChild(instance_attributes) - attributes = doc.createElement("attributes") - instance_attributes.appendChild(attributes) - for i in range(0,len(rsc_options)) : - if rsc_options[i] == None : - continue - - param = string.split(rsc_options[i], "=") - nvpair = doc.createElement("nvpair") - nvpair.setAttribute("id", id + "_" + param[0]) - nvpair.setAttribute("name", param[0]) - nvpair.setAttribute("value", param[1]) - attributes.appendChild(nvpair) - - return resource - -def cib_rsc_location(doc, id, node, score): - rule = doc.createElement("rule") - rule.setAttribute("id", id+"_prefer_"+node+"_rule") - rule.setAttribute("score", score) - expression = doc.createElement("expression") - expression.setAttribute("id",id+"_prefer_"+node+"_expr") - expression.setAttribute("attribute","#uname") - expression.setAttribute("operation","eq") - expression.setAttribute("value", node) - rule.appendChild(expression) - return rule - -def cib_rsc_colocation(doc, id, other_resource, score): - rsc_colocation = doc.createElement("rsc_colocation") - rsc_colocation.setAttribute("id", id+"_colocate_with_"+other_resource) - rsc_colocation.setAttribute("from", id) - rsc_colocation.setAttribute("to", other_resource) - rsc_colocation.setAttribute("score", score) - return rsc_colocation - -def print_usage(): - print "usage: " \ - + sys.argv[0] \ - + " --name "\ - + " --class "\ - + " --type "\ - + " [--provider ]"\ - + "\n\t"\ - + " [--start-timeout ]"\ - + " [--stop-timeout ]"\ - + " [--monitor ]"\ - + " [--monitor-timeout ]"\ - + "\n\t"\ - + " [--rsc-option name=value]*"\ - + " [--rsc-location uname=score]*"\ - + " [--rsc-colocation resource=score]*" - print "Example:\n\t" + sys.argv[0] \ - + " --name cluster_ip_1 --type IPaddr --provider heartbeat --class ocf "\ - + "--rsc-option ip=192.168.1.101 --rsc-location node1=500 | cibadmin -C -p" - sys.exit(1) - -if __name__=="__main__" : - - # Process arguments... - skipthis = None - args = sys.argv[1:] - if len(args) == 0: - print_usage() - - for i in range(0, len(args)) : - if skipthis : - skipthis = None - continue - - elif args[i] == "--name" : - skipthis = True - rsc_name = args[i+1] - - elif args[i] == "--class" : - skipthis = True - rsc_class = args[i+1] - - elif args[i] == "--type" : - skipthis = True - rsc_type = args[i+1] - - elif args[i] == "--provider" : - skipthis = True - rsc_provider = args[i+1] - - elif args[i] == "--start-timeout" : - skipthis = True - start_timeout = args[i+1] - - elif args[i] == "--stop-timeout" : - skipthis = True - stop_timeout = args[i+1] - - elif args[i] == "--monitor" : - skipthis = True - monitor_interval = args[i+1] - - elif args[i] == "--monitor-timeout" : - skipthis = True - monitor_timeout = args[i+1] - - elif args[i] == "--rsc-option" : - skipthis = True - params = string.split(args[i+1], "=") - if params[1] != None: - rsc_options.append(args[i+1]) - else: - print "option '"+args[i+1]+"' must be of the form name=value" - - elif args[i] == "--rsc-location" : - skipthis = True - params = string.split(args[i+1], "=") - if params[1] != None: - rsc_location.append(args[i+1]) - else: - print "option '"+args[i+1]+"' must be of the form host=score" - - elif args[i] == "--rsc-colocation" : - skipthis = True - params = string.split(args[i+1], "=") - if params[1] != None: - rsc_colocation.append(args[i+1]) - else: - print "option '"+args[i+1]+"' must be of the form resource=score" - - elif args[i] == "--rsc-only" : - print_rsc_only = 1 - else: - print "Unknown argument: "+ args[i] - print_usage() - - cib = create_cib() - pre_line = "" - id_index = 1 - resource = cib_resource(cib[0], rsc_name, rsc_class, rsc_type, rsc_provider) - - if print_rsc_only: - print resource.toprettyxml() - sys.exit(0) - - cib[1].appendChild(resource) - - if rsc_location != None : - rsc_loc = cib[0].createElement("rsc_location") - rsc_loc.setAttribute("id", rsc_name+"_preferences") - rsc_loc.setAttribute("rsc", rsc_name) - for i in range(0, len(rsc_location)) : - param = string.split(rsc_location[i], "=") - location_rule = cib_rsc_location(cib[0], rsc_name, param[0], param[1]) - rsc_loc.appendChild(location_rule) - cib[2].appendChild(rsc_loc) - - for i in range(0, len(rsc_colocation)) : - if rsc_location[i] == None : - continue - - param = string.split(rsc_colocation[i], "=") - colocation_rule = cib_rsc_colocation(cib[0], rsc_name, param[0], param[1]) - cib[2].appendChild(colocation_rule) - - print cib[0].toprettyxml() diff --git a/tools/crm_resource.c b/tools/crm_resource.c index 31136ef..2fce3b7 100644 --- a/tools/crm_resource.c +++ b/tools/crm_resource.c @@ -853,6 +853,7 @@ main(int argc, char **argv) rc = -ENXIO; goto bail; } + rc = cli_resource_print_attribute(rsc_id, prop_name, &data_set); } else if (rsc_cmd == 'p') { @@ -883,6 +884,10 @@ main(int argc, char **argv) } else if (rsc_cmd == 'C' && rsc_id) { resource_t *rsc = pe_find_resource(data_set.resources, rsc_id); + if(do_force == FALSE) { + rsc = uber_parent(rsc); + } + crm_debug("Re-checking the state of %s on %s", rsc_id, host_uname); if(rsc) { crmd_replies_needed = 0; @@ -891,6 +896,11 @@ main(int argc, char **argv) rc = -ENODEV; } + if(rc == pcmk_ok && BE_QUIET == FALSE) { + /* Now check XML_RSC_ATTR_TARGET_ROLE and XML_RSC_ATTR_MANAGED */ + cli_resource_check(cib_conn, rsc); + } + if (rc == pcmk_ok) { start_mainloop(); } diff --git a/tools/crm_resource.h b/tools/crm_resource.h index 49b6138..5a206e0 100644 --- a/tools/crm_resource.h +++ b/tools/crm_resource.h @@ -68,6 +68,7 @@ int cli_resource_print_property(const char *rsc, const char *attr, pe_working_se int cli_resource_print_operations(const char *rsc_id, const char *host_uname, bool active, pe_working_set_t * data_set); /* runtime */ +void cli_resource_check(cib_t * cib, resource_t *rsc); int cli_resource_fail(crm_ipc_t * crmd_channel, const char *host_uname, const char *rsc_id, pe_working_set_t * data_set); int cli_resource_search(const char *rsc, pe_working_set_t * data_set); int cli_resource_delete(cib_t *cib_conn, crm_ipc_t * crmd_channel, const char *host_uname, resource_t * rsc, pe_working_set_t * data_set); diff --git a/tools/crm_resource_print.c b/tools/crm_resource_print.c index 9c3711c..946b9e3 100644 --- a/tools/crm_resource_print.c +++ b/tools/crm_resource_print.c @@ -352,8 +352,11 @@ cli_resource_print_attribute(const char *rsc, const char *attr, pe_working_set_t if (safe_str_eq(attr_set_type, XML_TAG_ATTR_SETS)) { get_rsc_attributes(params, the_rsc, current, data_set); + } else if (safe_str_eq(attr_set_type, XML_TAG_META_SETS)) { + /* No need to redirect to the parent */ get_meta_attributes(params, the_rsc, current, data_set); + } else { unpack_instance_attributes(data_set->input, the_rsc->xml, XML_TAG_UTILIZATION, NULL, params, NULL, FALSE, data_set->now); diff --git a/tools/crm_resource_runtime.c b/tools/crm_resource_runtime.c index 006ec08..a270cbf 100644 --- a/tools/crm_resource_runtime.c +++ b/tools/crm_resource_runtime.c @@ -198,6 +198,7 @@ cli_resource_update_attribute(const char *rsc_id, const char *attr_set, const ch int rc = pcmk_ok; static bool need_init = TRUE; + char *lookup_id = NULL; char *local_attr_id = NULL; char *local_attr_set = NULL; @@ -212,14 +213,39 @@ cli_resource_update_attribute(const char *rsc_id, const char *attr_set, const ch } if (safe_str_eq(attr_set_type, XML_TAG_ATTR_SETS)) { - rc = find_resource_attr(cib, XML_ATTR_ID, rsc_id, XML_TAG_META_SETS, attr_set, attr_id, + rc = find_resource_attr(cib, XML_ATTR_ID, uber_parent(rsc)->id, XML_TAG_META_SETS, attr_set, attr_id, attr_name, &local_attr_id); - if (rc == pcmk_ok) { - printf("WARNING: There is already a meta attribute called %s (id=%s)\n", attr_name, - local_attr_id); + if(rc == pcmk_ok && do_force == FALSE) { + if (BE_QUIET == FALSE) { + printf("WARNING: There is already a meta attribute for '%s' called '%s' (id=%s)\n", + uber_parent(rsc)->id, attr_name, local_attr_id); + printf(" Delete '%s' first or use --force to override\n", local_attr_id); + } + return -ENOTUNIQ; + } + + } else if(rsc->parent) { + + switch(rsc->parent->variant) { + case pe_group: + if (BE_QUIET == FALSE) { + printf("Updating '%s' for '%s' will not apply to its peers in '%s'\n", attr_name, rsc_id, rsc->parent->id); + } + break; + case pe_master: + case pe_clone: + rsc = rsc->parent; + if (BE_QUIET == FALSE) { + printf("Updating '%s' for '%s'...\n", rsc->id, rsc_id); + } + break; + default: + break; } } - rc = find_resource_attr(cib, XML_ATTR_ID, rsc_id, attr_set_type, attr_set, attr_id, attr_name, + + lookup_id = clone_strip(rsc->id); /* Could be a cloned group! */ + rc = find_resource_attr(cib, XML_ATTR_ID, lookup_id, attr_set_type, attr_set, attr_id, attr_name, &local_attr_id); if (rc == pcmk_ok) { @@ -227,6 +253,7 @@ cli_resource_update_attribute(const char *rsc_id, const char *attr_set, const ch attr_id = local_attr_id; } else if (rc != -ENXIO) { + free(lookup_id); free(local_attr_id); return rc; @@ -250,7 +277,7 @@ cli_resource_update_attribute(const char *rsc_id, const char *attr_set, const ch free_xml(cib_top); if (attr_set == NULL) { - local_attr_set = crm_concat(rsc_id, attr_set_type, '-'); + local_attr_set = crm_concat(lookup_id, attr_set_type, '-'); attr_set = local_attr_set; } if (attr_id == NULL) { @@ -263,7 +290,7 @@ cli_resource_update_attribute(const char *rsc_id, const char *attr_set, const ch } xml_top = create_xml_node(NULL, tag); - crm_xml_add(xml_top, XML_ATTR_ID, rsc_id); + crm_xml_add(xml_top, XML_ATTR_ID, lookup_id); xml_obj = create_xml_node(xml_top, attr_set_type); crm_xml_add(xml_obj, XML_ATTR_ID, attr_set); @@ -285,7 +312,15 @@ cli_resource_update_attribute(const char *rsc_id, const char *attr_set, const ch crm_log_xml_debug(xml_top, "Update"); rc = cib->cmds->modify(cib, XML_CIB_TAG_RESOURCES, xml_top, cib_options); + if (rc == pcmk_ok && BE_QUIET == FALSE) { + printf("Set '%s' option: id=%s%s%s%s%s=%s\n", lookup_id, local_attr_id, + attr_set ? " set=" : "", attr_set ? attr_set : "", + attr_name ? " name=" : "", attr_name ? attr_name : "", attr_value); + } + free_xml(xml_top); + + free(lookup_id); free(local_attr_id); free(local_attr_set); @@ -330,6 +365,7 @@ cli_resource_delete_attribute(const char *rsc_id, const char *attr_set, const ch xmlNode *xml_obj = NULL; int rc = pcmk_ok; + char *lookup_id = NULL; char *local_attr_id = NULL; resource_t *rsc = find_rsc_or_clone(rsc_id, data_set); @@ -337,7 +373,29 @@ cli_resource_delete_attribute(const char *rsc_id, const char *attr_set, const ch return -ENXIO; } - rc = find_resource_attr(cib, XML_ATTR_ID, rsc_id, attr_set_type, attr_set, attr_id, attr_name, + if(rsc->parent && safe_str_eq(attr_set_type, XML_TAG_META_SETS)) { + + switch(rsc->parent->variant) { + case pe_group: + if (BE_QUIET == FALSE) { + printf("Removing '%s' for '%s' will not apply to its peers in '%s'\n", attr_name, rsc_id, rsc->parent->id); + } + break; + case pe_master: + case pe_clone: + rsc = rsc->parent; + if (BE_QUIET == FALSE) { + printf("Removing '%s' from '%s' for '%s'...\n", attr_name, rsc->id, rsc_id); + } + break; + default: + break; + } + + } + + lookup_id = clone_strip(rsc->id); + rc = find_resource_attr(cib, XML_ATTR_ID, lookup_id, attr_set_type, attr_set, attr_id, attr_name, &local_attr_id); if (rc == -ENXIO) { @@ -360,8 +418,8 @@ cli_resource_delete_attribute(const char *rsc_id, const char *attr_set, const ch CRM_ASSERT(cib); rc = cib->cmds->delete(cib, XML_CIB_TAG_RESOURCES, xml_obj, cib_options); - if (rc == pcmk_ok) { - printf("Deleted %s option: id=%s%s%s%s%s\n", rsc_id, local_attr_id, + if (rc == pcmk_ok && BE_QUIET == FALSE) { + printf("Deleted '%s' option: id=%s%s%s%s%s\n", lookup_id, local_attr_id, attr_set ? " set=" : "", attr_set ? attr_set : "", attr_name ? " name=" : "", attr_name ? attr_name : ""); } @@ -493,7 +551,10 @@ cli_resource_delete(cib_t *cib_conn, crm_ipc_t * crmd_channel, const char *host_ for (lpc = rsc->children; lpc != NULL; lpc = lpc->next) { resource_t *child = (resource_t *) lpc->data; - cli_resource_delete(cib_conn, crmd_channel, host_uname, child, data_set); + rc = cli_resource_delete(cib_conn, crmd_channel, host_uname, child, data_set); + if(rc != pcmk_ok || is_not_set(rsc->flags, pe_rsc_unique)) { + return rc; + } } return pcmk_ok; @@ -514,31 +575,78 @@ cli_resource_delete(cib_t *cib_conn, crm_ipc_t * crmd_channel, const char *host_ node = pe_find_node(data_set->nodes, host_uname); if (node && node->details->rsc_discovery_enabled) { - printf("Cleaning up %s on %s\n", rsc->id, host_uname); + printf("Cleaning up %s on %s", rsc->id, host_uname); rc = send_lrm_rsc_op(crmd_channel, CRM_OP_LRM_DELETE, host_uname, rsc->id, TRUE, data_set); } else { printf("Resource discovery disabled on %s. Unable to delete lrm state.\n", host_uname); + rc = -EOPNOTSUPP; } if (rc == pcmk_ok) { char *attr_name = NULL; - const char *id = rsc->id; if(node && node->details->remote_rsc == NULL && node->details->rsc_discovery_enabled) { crmd_replies_needed++; } - if (rsc->clone_name) { - id = rsc->clone_name; + + if(is_not_set(rsc->flags, pe_rsc_unique)) { + char *id = clone_strip(rsc->id); + attr_name = crm_strdup_printf("fail-count-%s", id); + free(id); + + } else if (rsc->clone_name) { + attr_name = crm_strdup_printf("fail-count-%s", rsc->clone_name); + + } else { + attr_name = crm_strdup_printf("fail-count-%s", rsc->id); } - attr_name = crm_concat("fail-count", id, '-'); + printf(", removing %s\n", attr_name); rc = attrd_update_delegate(NULL, 'D', host_uname, attr_name, NULL, XML_CIB_TAG_STATUS, NULL, NULL, NULL, node ? is_remote_node(node) : FALSE); free(attr_name); + + } else if(rc != -EOPNOTSUPP) { + printf(" - FAILED\n"); } + return rc; } +void +cli_resource_check(cib_t * cib_conn, resource_t *rsc) +{ + + char *role_s = NULL; + char *managed = NULL; + resource_t *parent = uber_parent(rsc); + + find_resource_attr(cib_conn, XML_ATTR_ID, parent->id, + XML_TAG_META_SETS, NULL, NULL, XML_RSC_ATTR_MANAGED, &managed); + + find_resource_attr(cib_conn, XML_ATTR_ID, parent->id, + XML_TAG_META_SETS, NULL, NULL, XML_RSC_ATTR_TARGET_ROLE, &role_s); + + if(managed == NULL) { + managed = strdup("1"); + } + if(crm_is_true(managed) == FALSE) { + printf("\n\t*Resource %s is configured to not be managed by the cluster\n", parent->id); + } + if(role_s) { + enum rsc_role_e role = text2role(role_s); + if(role == RSC_ROLE_UNKNOWN) { + // Treated as if unset + + } else if(role == RSC_ROLE_STOPPED) { + printf("\n\t* The configuration specifies that '%s' should remain stopped\n", parent->id); + + } else if(parent->variant > pe_clone && role != RSC_ROLE_MASTER) { + printf("\n\t* The configuration specifies that '%s' should not be promoted\n", parent->id); + } + } +} + int cli_resource_fail(crm_ipc_t * crmd_channel, const char *host_uname, const char *rsc_id, pe_working_set_t * data_set) diff --git a/tools/crm_simulate.c b/tools/crm_simulate.c index 0051112..7d0a8eb 100644 --- a/tools/crm_simulate.c +++ b/tools/crm_simulate.c @@ -59,8 +59,11 @@ char *use_date = NULL; static void get_date(pe_working_set_t * data_set) { + int value = 0; time_t original_date = 0; - crm_element_value_int(data_set->input, "execution-date", (int*)&original_date); + + crm_element_value_int(data_set->input, "execution-date", &value); + original_date = value; if (use_date) { data_set->now = crm_time_new(use_date); diff --git a/tools/crm_utils.py.in b/tools/crm_utils.py.in deleted file mode 100644 index 67d6918..0000000 --- a/tools/crm_utils.py.in +++ /dev/null @@ -1,188 +0,0 @@ -#!/bin/env python -# -# -# pingd OCF Resource Agent -# Records (in the CIB) the current number of ping nodes a -# cluster node can connect to. -# -# Copyright (c) 2006 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. -# -####################################################################### - -import os -import sys -import getopt -import readline -import traceback -from popen2 import Popen3 - -crm_topic = "crm" -topic_stack = [ crm_topic ] -hist_file = os.environ.get('HOME')+"/.crm_history" -global_opts = {} - -def exit_(code=0): - if global_opts["interactive"]: - log_info("Exiting... ") - try: - readline.write_history_file(hist_file) - log_debug("Wrote history to: "+hist_file) - except: - log_debug("Couldnt write history to: "+hist_file) - sys.exit(code) - -def log_debug(log): - if global_opts.has_key("debug") and global_opts["debug"]: - print log - -def log_dev(log): - if global_opts.has_key("devlog") and global_opts["devlog"]: - print log - -def log_info(log): - print log - -def log_err(log): - print "ERROR: "+log - -def set_topic(name): - global crm_topic - if crm_topic != name: - log_dev("topic: %s->%s" % (crm_topic, name)) - crm_topic = name - -def os_system(cmd, print_raw=False): - log_debug("Performing command: "+cmd) - p = Popen3(cmd, None) - p.tochild.close() - result = p.fromchild.readlines() - p.fromchild.close() - p.wait() - if print_raw: - for line in result: - print line.rstrip() - return result - -# -# Creates an argv-style array (that preserves quoting) for use in shell-mode -# -def create_argv(text): - args = [] - word = [] - index = 0 - total = len(text) - - in_word = False - in_verbatum = False - - while index < total: - finish_word = False - append_word = False - #log_debug("processing: "+text[index]) - if text[index] == '\\': - index = index +1 - append_word = True - - elif text[index].isspace(): - if in_verbatum or in_word: - append_word = True - else: - finish_word = True - - elif text[index] == '"': - if in_verbatum: - append_word = True - else: - finish_word = True - if in_word: - in_word = False - else: - in_word = True - - elif text[index] == '\'': - finish_word = True - if in_verbatum: - in_verbatum = False - else: - in_verbatum = True - else: - append_word = True - - if finish_word: - if word: - args.append(''.join(word)) - word = [] - elif append_word: - word.append(text[index]) - #log_debug("Added %s to word: %s" % (text[index], str(word))) - - index = index +1 - - if in_verbatum or in_word: - text="" - if word: - text=" after: '%s'"%''.join(word) - raise QuotingError("Un-matched quoting%s"%text, args) - - elif word: - args.append(''.join(word)) - - return args - -def init_readline(func): - readline.set_completer(func) - readline.parse_and_bind("tab: complete") - readline.set_history_length(100) - - try: - readline.read_history_file(hist_file) - except: - pass - -def fancyopts(args, options, state): - long = [] - short = '' - map = {} - dt = {} - - for s, l, d, c in options: - pl = l.replace('-', '_') - map['-'+s] = map['--'+l] = pl - state[pl] = d - dt[pl] = type(d) - if not d is None and not callable(d): - if s: s += ':' - if l: l += '=' - if s: short = short + s - if l: long.append(l) - - opts, args = getopt.getopt(args, short, long) - - for opt, arg in opts: - if dt[map[opt]] is type(fancyopts): state[map[opt]](state,map[opt],arg) - elif dt[map[opt]] is type(1): state[map[opt]] = int(arg) - elif dt[map[opt]] is type(''): state[map[opt]] = arg - elif dt[map[opt]] is type([]): state[map[opt]].append(arg) - elif dt[map[opt]] is type(None): state[map[opt]] = 1 - - return args diff --git a/tools/regression.acls.exp b/tools/regression.acls.exp index ae6735a..ac7ae0c 100644 --- a/tools/regression.acls.exp +++ b/tools/regression.acls.exp @@ -253,10 +253,10 @@ Error performing operation: Permission denied =#=#=#= End test: unknownguy: Set stonith-enabled - Permission denied (13) =#=#=#= * Passed: crm_attribute - unknownguy: Set stonith-enabled =#=#=#= Begin test: unknownguy: Create a resource =#=#=#= -__xml_acl_check: Ordinary user unknownguy cannot access the CIB without any defined ACLs -__xml_acl_check: Ordinary user unknownguy cannot access the CIB without any defined ACLs -__xml_acl_check: Ordinary user unknownguy cannot access the CIB without any defined ACLs -__xml_acl_check: Ordinary user unknownguy cannot access the CIB without any defined ACLs +__xml_acl_check: Ordinary user unknownguy cannot access the CIB without any defined ACLs +__xml_acl_check: Ordinary user unknownguy cannot access the CIB without any defined ACLs +__xml_acl_check: Ordinary user unknownguy cannot access the CIB without any defined ACLs +__xml_acl_check: Ordinary user unknownguy cannot access the CIB without any defined ACLs Call failed: Permission denied =#=#=#= End test: unknownguy: Create a resource - Permission denied (13) =#=#=#= * Passed: cibadmin - unknownguy: Create a resource @@ -273,8 +273,8 @@ Error performing operation: Permission denied =#=#=#= End test: l33t-haxor: Set stonith-enabled - Permission denied (13) =#=#=#= * Passed: crm_attribute - l33t-haxor: Set stonith-enabled =#=#=#= Begin test: l33t-haxor: Create a resource =#=#=#= -__xml_acl_check: 400 access denied to /cib/configuration/resources/primitive[@id='dummy']: parent -__xml_acl_post_process: Cannot add new node primitive at /cib/configuration/resources/primitive[@id='dummy'] +__xml_acl_check: 400 access denied to /cib/configuration/resources/primitive[@id='dummy']: parent +__xml_acl_post_process: Cannot add new node primitive at /cib/configuration/resources/primitive[@id='dummy'] Call failed: Permission denied =#=#=#= End test: l33t-haxor: Create a resource - Permission denied (13) =#=#=#= * Passed: cibadmin - l33t-haxor: Create a resource @@ -323,13 +323,13 @@ Call failed: Permission denied =#=#=#= End test: niceguy: Query configuration - OK (0) =#=#=#= * Passed: cibadmin - niceguy: Query configuration =#=#=#= Begin test: niceguy: Set enable-acl =#=#=#= -__xml_acl_check: 400 access denied to /cib/configuration/crm_config/cluster_property_set[@id='cib-bootstrap-options']/nvpair[@id='cib-bootstrap-options-enable-acl'][@value]: default +__xml_acl_check: 400 access denied to /cib/configuration/crm_config/cluster_property_set[@id='cib-bootstrap-options']/nvpair[@id='cib-bootstrap-options-enable-acl'][@value]: default Error performing operation: Permission denied Error setting enable-acl=false (section=crm_config, set=): Permission denied =#=#=#= End test: niceguy: Set enable-acl - Permission denied (13) =#=#=#= * Passed: crm_attribute - niceguy: Set enable-acl =#=#=#= Begin test: niceguy: Set stonith-enabled =#=#=#= -__xml_acl_post_process: Creation of nvpair=cib-bootstrap-options-stonith-enabled is allowed +__xml_acl_post_process: Creation of nvpair=cib-bootstrap-options-stonith-enabled is allowed =#=#=#= Current cib after: niceguy: Set stonith-enabled =#=#=#= @@ -376,8 +376,8 @@ __xml_acl_post_process: Creation of nvpair=cib-bootstrap-options-stonith-enable =#=#=#= End test: niceguy: Set stonith-enabled - OK (0) =#=#=#= * Passed: crm_attribute - niceguy: Set stonith-enabled =#=#=#= Begin test: niceguy: Create a resource =#=#=#= -__xml_acl_check: 400 access denied to /cib/configuration/resources/primitive[@id='dummy']: default -__xml_acl_post_process: Cannot add new node primitive at /cib/configuration/resources/primitive[@id='dummy'] +__xml_acl_check: 400 access denied to /cib/configuration/resources/primitive[@id='dummy']: default +__xml_acl_post_process: Cannot add new node primitive at /cib/configuration/resources/primitive[@id='dummy'] Call failed: Permission denied =#=#=#= End test: niceguy: Create a resource - Permission denied (13) =#=#=#= * Passed: cibadmin - niceguy: Create a resource @@ -533,10 +533,11 @@ Error performing operation: Permission denied =#=#=#= End test: l33t-haxor: Remove a resource meta attribute - Permission denied (13) =#=#=#= * Passed: crm_resource - l33t-haxor: Remove a resource meta attribute =#=#=#= Begin test: niceguy: Create a resource meta attribute =#=#=#= -error: unpack_resources: Resource start-up disabled since no STONITH resources have been defined -error: unpack_resources: Either configure some or disable STONITH with the stonith-enabled option -error: unpack_resources: NOTE: Clusters with shared data need STONITH to ensure data integrity -__xml_acl_post_process: Creation of nvpair=dummy-meta_attributes-target-role is allowed +error: unpack_resources: Resource start-up disabled since no STONITH resources have been defined +error: unpack_resources: Either configure some or disable STONITH with the stonith-enabled option +error: unpack_resources: NOTE: Clusters with shared data need STONITH to ensure data integrity +__xml_acl_post_process: Creation of nvpair=dummy-meta_attributes-target-role is allowed +Set 'dummy' option: id=dummy-meta_attributes-target-role set=dummy-meta_attributes name=target-role=Stopped =#=#=#= Current cib after: niceguy: Create a resource meta attribute =#=#=#= @@ -589,9 +590,9 @@ __xml_acl_post_process: Creation of nvpair=dummy-meta_attributes-target-role is =#=#=#= End test: niceguy: Create a resource meta attribute - OK (0) =#=#=#= * Passed: crm_resource - niceguy: Create a resource meta attribute =#=#=#= Begin test: niceguy: Query a resource meta attribute =#=#=#= -error: unpack_resources: Resource start-up disabled since no STONITH resources have been defined -error: unpack_resources: Either configure some or disable STONITH with the stonith-enabled option -error: unpack_resources: NOTE: Clusters with shared data need STONITH to ensure data integrity +error: unpack_resources: Resource start-up disabled since no STONITH resources have been defined +error: unpack_resources: Either configure some or disable STONITH with the stonith-enabled option +error: unpack_resources: NOTE: Clusters with shared data need STONITH to ensure data integrity Stopped =#=#=#= Current cib after: niceguy: Query a resource meta attribute =#=#=#= @@ -645,10 +646,10 @@ Stopped =#=#=#= End test: niceguy: Query a resource meta attribute - OK (0) =#=#=#= * Passed: crm_resource - niceguy: Query a resource meta attribute =#=#=#= Begin test: niceguy: Remove a resource meta attribute =#=#=#= -error: unpack_resources: Resource start-up disabled since no STONITH resources have been defined -error: unpack_resources: Either configure some or disable STONITH with the stonith-enabled option -error: unpack_resources: NOTE: Clusters with shared data need STONITH to ensure data integrity -Deleted dummy option: id=dummy-meta_attributes-target-role name=target-role +error: unpack_resources: Resource start-up disabled since no STONITH resources have been defined +error: unpack_resources: Either configure some or disable STONITH with the stonith-enabled option +error: unpack_resources: NOTE: Clusters with shared data need STONITH to ensure data integrity +Deleted 'dummy' option: id=dummy-meta_attributes-target-role name=target-role =#=#=#= Current cib after: niceguy: Remove a resource meta attribute =#=#=#= @@ -699,10 +700,11 @@ Deleted dummy option: id=dummy-meta_attributes-target-role name=target-role =#=#=#= End test: niceguy: Remove a resource meta attribute - OK (0) =#=#=#= * Passed: crm_resource - niceguy: Remove a resource meta attribute =#=#=#= Begin test: niceguy: Create a resource meta attribute =#=#=#= -error: unpack_resources: Resource start-up disabled since no STONITH resources have been defined -error: unpack_resources: Either configure some or disable STONITH with the stonith-enabled option -error: unpack_resources: NOTE: Clusters with shared data need STONITH to ensure data integrity -__xml_acl_post_process: Creation of nvpair=dummy-meta_attributes-target-role is allowed +error: unpack_resources: Resource start-up disabled since no STONITH resources have been defined +error: unpack_resources: Either configure some or disable STONITH with the stonith-enabled option +error: unpack_resources: NOTE: Clusters with shared data need STONITH to ensure data integrity +__xml_acl_post_process: Creation of nvpair=dummy-meta_attributes-target-role is allowed +Set 'dummy' option: id=dummy-meta_attributes-target-role set=dummy-meta_attributes name=target-role=Started =#=#=#= Current cib after: niceguy: Create a resource meta attribute =#=#=#= @@ -804,8 +806,8 @@ __xml_acl_post_process: Creation of nvpair=dummy-meta_attributes-target-role is =#=#=#= Begin test: niceguy: Replace - remove acls =#=#=#= -__xml_acl_check: 400 access denied to /cib[@epoch]: default -__xml_acl_check: 400 access denied to /cib/configuration/acls: default +__xml_acl_check: 400 access denied to /cib[@epoch]: default +__xml_acl_check: 400 access denied to /cib/configuration/acls: default Call failed: Permission denied =#=#=#= End test: niceguy: Replace - remove acls - Permission denied (13) =#=#=#= * Passed: cibadmin - niceguy: Replace - remove acls @@ -859,9 +861,9 @@ Call failed: Permission denied =#=#=#= Begin test: niceguy: Replace - create resource =#=#=#= -__xml_acl_check: 400 access denied to /cib[@epoch]: default -__xml_acl_check: 400 access denied to /cib/configuration/resources/primitive[@id='dummy2']: default -__xml_acl_post_process: Cannot add new node primitive at /cib/configuration/resources/primitive[@id='dummy2'] +__xml_acl_check: 400 access denied to /cib[@epoch]: default +__xml_acl_check: 400 access denied to /cib/configuration/resources/primitive[@id='dummy2']: default +__xml_acl_post_process: Cannot add new node primitive at /cib/configuration/resources/primitive[@id='dummy2'] Call failed: Permission denied =#=#=#= End test: niceguy: Replace - create resource - Permission denied (13) =#=#=#= * Passed: cibadmin - niceguy: Replace - create resource @@ -914,8 +916,8 @@ Call failed: Permission denied =#=#=#= Begin test: niceguy: Replace - modify attribute (deny) =#=#=#= -__xml_acl_check: 400 access denied to /cib[@epoch]: default -__xml_acl_check: 400 access denied to /cib/configuration/crm_config/cluster_property_set[@id='cib-bootstrap-options']/nvpair[@id='cib-bootstrap-options-enable-acl'][@value]: default +__xml_acl_check: 400 access denied to /cib[@epoch]: default +__xml_acl_check: 400 access denied to /cib/configuration/crm_config/cluster_property_set[@id='cib-bootstrap-options']/nvpair[@id='cib-bootstrap-options-enable-acl'][@value]: default Call failed: Permission denied =#=#=#= End test: niceguy: Replace - modify attribute (deny) - Permission denied (13) =#=#=#= * Passed: cibadmin - niceguy: Replace - modify attribute (deny) @@ -968,8 +970,8 @@ Call failed: Permission denied =#=#=#= Begin test: niceguy: Replace - delete attribute (deny) =#=#=#= -__xml_acl_check: 400 access denied to /cib[@epoch]: default -__xml_acl_check: 400 access denied to /cib/configuration/crm_config/cluster_property_set[@id='cib-bootstrap-options']/nvpair[@id='cib-bootstrap-options-enable-acl']: default +__xml_acl_check: 400 access denied to /cib[@epoch]: default +__xml_acl_check: 400 access denied to /cib/configuration/crm_config/cluster_property_set[@id='cib-bootstrap-options']/nvpair[@id='cib-bootstrap-options-enable-acl']: default Call failed: Permission denied =#=#=#= End test: niceguy: Replace - delete attribute (deny) - Permission denied (13) =#=#=#= * Passed: cibadmin - niceguy: Replace - delete attribute (deny) @@ -1022,8 +1024,8 @@ Call failed: Permission denied =#=#=#= Begin test: niceguy: Replace - create attribute (deny) =#=#=#= -__xml_acl_check: 400 access denied to /cib[@epoch]: default -__xml_acl_check: 400 access denied to /cib/configuration/resources/primitive[@id='dummy'][@description]: default +__xml_acl_check: 400 access denied to /cib[@epoch]: default +__xml_acl_check: 400 access denied to /cib/configuration/resources/primitive[@id='dummy'][@description]: default Call failed: Permission denied =#=#=#= End test: niceguy: Replace - create attribute (deny) - Permission denied (13) =#=#=#= * Passed: cibadmin - niceguy: Replace - create attribute (deny) @@ -1180,28 +1182,28 @@ Call failed: Permission denied !#!#!#!#! Upgrading to pacemaker-2.0 and retesting !#!#!#!#! =#=#=#= Begin test: root: Upgrade to pacemaker-2.0 =#=#=#= -__xml_acl_post_process: Creation of acl_permission=observer-read-1 is allowed -__xml_acl_post_process: Creation of acl_permission=observer-write-1 is allowed -__xml_acl_post_process: Creation of acl_permission=observer-write-2 is allowed -__xml_acl_post_process: Creation of acl_permission=admin-read-1 is allowed -__xml_acl_post_process: Creation of acl_permission=admin-write-1 is allowed -__xml_acl_post_process: Creation of acl_target=l33t-haxor is allowed -__xml_acl_post_process: Creation of role=auto-l33t-haxor is allowed -__xml_acl_post_process: Creation of acl_role=auto-l33t-haxor is allowed -__xml_acl_post_process: Creation of acl_permission=crook-nothing is allowed -__xml_acl_post_process: Creation of acl_target=niceguy is allowed -__xml_acl_post_process: Creation of role=observer is allowed -__xml_acl_post_process: Creation of acl_target=bob is allowed -__xml_acl_post_process: Creation of role=admin is allowed -__xml_acl_post_process: Creation of acl_target=badidea is allowed -__xml_acl_post_process: Creation of role=auto-badidea is allowed -__xml_acl_post_process: Creation of acl_role=auto-badidea is allowed -__xml_acl_post_process: Creation of acl_permission=badidea-resources is allowed -__xml_acl_post_process: Creation of acl_target=betteridea is allowed -__xml_acl_post_process: Creation of role=auto-betteridea is allowed -__xml_acl_post_process: Creation of acl_role=auto-betteridea is allowed -__xml_acl_post_process: Creation of acl_permission=betteridea-nothing is allowed -__xml_acl_post_process: Creation of acl_permission=betteridea-resources is allowed +__xml_acl_post_process: Creation of acl_permission=observer-read-1 is allowed +__xml_acl_post_process: Creation of acl_permission=observer-write-1 is allowed +__xml_acl_post_process: Creation of acl_permission=observer-write-2 is allowed +__xml_acl_post_process: Creation of acl_permission=admin-read-1 is allowed +__xml_acl_post_process: Creation of acl_permission=admin-write-1 is allowed +__xml_acl_post_process: Creation of acl_target=l33t-haxor is allowed +__xml_acl_post_process: Creation of role=auto-l33t-haxor is allowed +__xml_acl_post_process: Creation of acl_role=auto-l33t-haxor is allowed +__xml_acl_post_process: Creation of acl_permission=crook-nothing is allowed +__xml_acl_post_process: Creation of acl_target=niceguy is allowed +__xml_acl_post_process: Creation of role=observer is allowed +__xml_acl_post_process: Creation of acl_target=bob is allowed +__xml_acl_post_process: Creation of role=admin is allowed +__xml_acl_post_process: Creation of acl_target=badidea is allowed +__xml_acl_post_process: Creation of role=auto-badidea is allowed +__xml_acl_post_process: Creation of acl_role=auto-badidea is allowed +__xml_acl_post_process: Creation of acl_permission=badidea-resources is allowed +__xml_acl_post_process: Creation of acl_target=betteridea is allowed +__xml_acl_post_process: Creation of role=auto-betteridea is allowed +__xml_acl_post_process: Creation of acl_role=auto-betteridea is allowed +__xml_acl_post_process: Creation of acl_permission=betteridea-nothing is allowed +__xml_acl_post_process: Creation of acl_permission=betteridea-resources is allowed =#=#=#= Current cib after: root: Upgrade to pacemaker-2.0 =#=#=#= @@ -1271,10 +1273,10 @@ Error performing operation: Permission denied =#=#=#= End test: unknownguy: Set stonith-enabled - Permission denied (13) =#=#=#= * Passed: crm_attribute - unknownguy: Set stonith-enabled =#=#=#= Begin test: unknownguy: Create a resource =#=#=#= -__xml_acl_check: Ordinary user unknownguy cannot access the CIB without any defined ACLs -__xml_acl_check: Ordinary user unknownguy cannot access the CIB without any defined ACLs -__xml_acl_check: Ordinary user unknownguy cannot access the CIB without any defined ACLs -__xml_acl_check: Ordinary user unknownguy cannot access the CIB without any defined ACLs +__xml_acl_check: Ordinary user unknownguy cannot access the CIB without any defined ACLs +__xml_acl_check: Ordinary user unknownguy cannot access the CIB without any defined ACLs +__xml_acl_check: Ordinary user unknownguy cannot access the CIB without any defined ACLs +__xml_acl_check: Ordinary user unknownguy cannot access the CIB without any defined ACLs Call failed: Permission denied =#=#=#= End test: unknownguy: Create a resource - Permission denied (13) =#=#=#= * Passed: cibadmin - unknownguy: Create a resource @@ -1291,8 +1293,8 @@ Error performing operation: Permission denied =#=#=#= End test: l33t-haxor: Set stonith-enabled - Permission denied (13) =#=#=#= * Passed: crm_attribute - l33t-haxor: Set stonith-enabled =#=#=#= Begin test: l33t-haxor: Create a resource =#=#=#= -__xml_acl_check: 400 access denied to /cib/configuration/resources/primitive[@id='dummy']: parent -__xml_acl_post_process: Cannot add new node primitive at /cib/configuration/resources/primitive[@id='dummy'] +__xml_acl_check: 400 access denied to /cib/configuration/resources/primitive[@id='dummy']: parent +__xml_acl_post_process: Cannot add new node primitive at /cib/configuration/resources/primitive[@id='dummy'] Call failed: Permission denied =#=#=#= End test: l33t-haxor: Create a resource - Permission denied (13) =#=#=#= * Passed: cibadmin - l33t-haxor: Create a resource @@ -1351,7 +1353,7 @@ Call failed: Permission denied =#=#=#= End test: niceguy: Query configuration - OK (0) =#=#=#= * Passed: cibadmin - niceguy: Query configuration =#=#=#= Begin test: niceguy: Set enable-acl =#=#=#= -__xml_acl_check: 400 access denied to /cib/configuration/crm_config/cluster_property_set[@id='cib-bootstrap-options']/nvpair[@id='cib-bootstrap-options-enable-acl'][@value]: default +__xml_acl_check: 400 access denied to /cib/configuration/crm_config/cluster_property_set[@id='cib-bootstrap-options']/nvpair[@id='cib-bootstrap-options-enable-acl'][@value]: default Error performing operation: Permission denied Error setting enable-acl=false (section=crm_config, set=): Permission denied =#=#=#= End test: niceguy: Set enable-acl - Permission denied (13) =#=#=#= @@ -1412,8 +1414,8 @@ Error setting enable-acl=false (section=crm_config, set=): Permission deni =#=#=#= End test: niceguy: Set stonith-enabled - OK (0) =#=#=#= * Passed: crm_attribute - niceguy: Set stonith-enabled =#=#=#= Begin test: niceguy: Create a resource =#=#=#= -__xml_acl_check: 400 access denied to /cib/configuration/resources/primitive[@id='dummy']: default -__xml_acl_post_process: Cannot add new node primitive at /cib/configuration/resources/primitive[@id='dummy'] +__xml_acl_check: 400 access denied to /cib/configuration/resources/primitive[@id='dummy']: default +__xml_acl_post_process: Cannot add new node primitive at /cib/configuration/resources/primitive[@id='dummy'] Call failed: Permission denied =#=#=#= End test: niceguy: Create a resource - Permission denied (13) =#=#=#= * Passed: cibadmin - niceguy: Create a resource @@ -1596,10 +1598,11 @@ Error performing operation: Permission denied =#=#=#= End test: l33t-haxor: Remove a resource meta attribute - Permission denied (13) =#=#=#= * Passed: crm_resource - l33t-haxor: Remove a resource meta attribute =#=#=#= Begin test: niceguy: Create a resource meta attribute =#=#=#= -error: unpack_resources: Resource start-up disabled since no STONITH resources have been defined -error: unpack_resources: Either configure some or disable STONITH with the stonith-enabled option -error: unpack_resources: NOTE: Clusters with shared data need STONITH to ensure data integrity -__xml_acl_post_process: Creation of nvpair=dummy-meta_attributes-target-role is allowed +error: unpack_resources: Resource start-up disabled since no STONITH resources have been defined +error: unpack_resources: Either configure some or disable STONITH with the stonith-enabled option +error: unpack_resources: NOTE: Clusters with shared data need STONITH to ensure data integrity +__xml_acl_post_process: Creation of nvpair=dummy-meta_attributes-target-role is allowed +Set 'dummy' option: id=dummy-meta_attributes-target-role set=dummy-meta_attributes name=target-role=Stopped =#=#=#= Current cib after: niceguy: Create a resource meta attribute =#=#=#= @@ -1661,9 +1664,9 @@ __xml_acl_post_process: Creation of nvpair=dummy-meta_attributes-target-role is =#=#=#= End test: niceguy: Create a resource meta attribute - OK (0) =#=#=#= * Passed: crm_resource - niceguy: Create a resource meta attribute =#=#=#= Begin test: niceguy: Query a resource meta attribute =#=#=#= -error: unpack_resources: Resource start-up disabled since no STONITH resources have been defined -error: unpack_resources: Either configure some or disable STONITH with the stonith-enabled option -error: unpack_resources: NOTE: Clusters with shared data need STONITH to ensure data integrity +error: unpack_resources: Resource start-up disabled since no STONITH resources have been defined +error: unpack_resources: Either configure some or disable STONITH with the stonith-enabled option +error: unpack_resources: NOTE: Clusters with shared data need STONITH to ensure data integrity Stopped =#=#=#= Current cib after: niceguy: Query a resource meta attribute =#=#=#= @@ -1726,10 +1729,10 @@ Stopped =#=#=#= End test: niceguy: Query a resource meta attribute - OK (0) =#=#=#= * Passed: crm_resource - niceguy: Query a resource meta attribute =#=#=#= Begin test: niceguy: Remove a resource meta attribute =#=#=#= -error: unpack_resources: Resource start-up disabled since no STONITH resources have been defined -error: unpack_resources: Either configure some or disable STONITH with the stonith-enabled option -error: unpack_resources: NOTE: Clusters with shared data need STONITH to ensure data integrity -Deleted dummy option: id=dummy-meta_attributes-target-role name=target-role +error: unpack_resources: Resource start-up disabled since no STONITH resources have been defined +error: unpack_resources: Either configure some or disable STONITH with the stonith-enabled option +error: unpack_resources: NOTE: Clusters with shared data need STONITH to ensure data integrity +Deleted 'dummy' option: id=dummy-meta_attributes-target-role name=target-role =#=#=#= Current cib after: niceguy: Remove a resource meta attribute =#=#=#= @@ -1789,10 +1792,11 @@ Deleted dummy option: id=dummy-meta_attributes-target-role name=target-role =#=#=#= End test: niceguy: Remove a resource meta attribute - OK (0) =#=#=#= * Passed: crm_resource - niceguy: Remove a resource meta attribute =#=#=#= Begin test: niceguy: Create a resource meta attribute =#=#=#= -error: unpack_resources: Resource start-up disabled since no STONITH resources have been defined -error: unpack_resources: Either configure some or disable STONITH with the stonith-enabled option -error: unpack_resources: NOTE: Clusters with shared data need STONITH to ensure data integrity -__xml_acl_post_process: Creation of nvpair=dummy-meta_attributes-target-role is allowed +error: unpack_resources: Resource start-up disabled since no STONITH resources have been defined +error: unpack_resources: Either configure some or disable STONITH with the stonith-enabled option +error: unpack_resources: NOTE: Clusters with shared data need STONITH to ensure data integrity +__xml_acl_post_process: Creation of nvpair=dummy-meta_attributes-target-role is allowed +Set 'dummy' option: id=dummy-meta_attributes-target-role set=dummy-meta_attributes name=target-role=Started =#=#=#= Current cib after: niceguy: Create a resource meta attribute =#=#=#= @@ -1903,8 +1907,8 @@ __xml_acl_post_process: Creation of nvpair=dummy-meta_attributes-target-role is =#=#=#= Begin test: niceguy: Replace - remove acls =#=#=#= -__xml_acl_check: 400 access denied to /cib[@epoch]: default -__xml_acl_check: 400 access denied to /cib/configuration/acls: default +__xml_acl_check: 400 access denied to /cib[@epoch]: default +__xml_acl_check: 400 access denied to /cib/configuration/acls: default Call failed: Permission denied =#=#=#= End test: niceguy: Replace - remove acls - Permission denied (13) =#=#=#= * Passed: cibadmin - niceguy: Replace - remove acls @@ -1967,9 +1971,9 @@ Call failed: Permission denied =#=#=#= Begin test: niceguy: Replace - create resource =#=#=#= -__xml_acl_check: 400 access denied to /cib[@epoch]: default -__xml_acl_check: 400 access denied to /cib/configuration/resources/primitive[@id='dummy2']: default -__xml_acl_post_process: Cannot add new node primitive at /cib/configuration/resources/primitive[@id='dummy2'] +__xml_acl_check: 400 access denied to /cib[@epoch]: default +__xml_acl_check: 400 access denied to /cib/configuration/resources/primitive[@id='dummy2']: default +__xml_acl_post_process: Cannot add new node primitive at /cib/configuration/resources/primitive[@id='dummy2'] Call failed: Permission denied =#=#=#= End test: niceguy: Replace - create resource - Permission denied (13) =#=#=#= * Passed: cibadmin - niceguy: Replace - create resource @@ -2031,8 +2035,8 @@ Call failed: Permission denied =#=#=#= Begin test: niceguy: Replace - modify attribute (deny) =#=#=#= -__xml_acl_check: 400 access denied to /cib[@epoch]: default -__xml_acl_check: 400 access denied to /cib/configuration/crm_config/cluster_property_set[@id='cib-bootstrap-options']/nvpair[@id='cib-bootstrap-options-enable-acl'][@value]: default +__xml_acl_check: 400 access denied to /cib[@epoch]: default +__xml_acl_check: 400 access denied to /cib/configuration/crm_config/cluster_property_set[@id='cib-bootstrap-options']/nvpair[@id='cib-bootstrap-options-enable-acl'][@value]: default Call failed: Permission denied =#=#=#= End test: niceguy: Replace - modify attribute (deny) - Permission denied (13) =#=#=#= * Passed: cibadmin - niceguy: Replace - modify attribute (deny) @@ -2094,8 +2098,8 @@ Call failed: Permission denied =#=#=#= Begin test: niceguy: Replace - delete attribute (deny) =#=#=#= -__xml_acl_check: 400 access denied to /cib[@epoch]: default -__xml_acl_check: 400 access denied to /cib/configuration/crm_config/cluster_property_set[@id='cib-bootstrap-options']/nvpair[@id='cib-bootstrap-options-enable-acl']: default +__xml_acl_check: 400 access denied to /cib[@epoch]: default +__xml_acl_check: 400 access denied to /cib/configuration/crm_config/cluster_property_set[@id='cib-bootstrap-options']/nvpair[@id='cib-bootstrap-options-enable-acl']: default Call failed: Permission denied =#=#=#= End test: niceguy: Replace - delete attribute (deny) - Permission denied (13) =#=#=#= * Passed: cibadmin - niceguy: Replace - delete attribute (deny) @@ -2157,8 +2161,8 @@ Call failed: Permission denied =#=#=#= Begin test: niceguy: Replace - create attribute (deny) =#=#=#= -__xml_acl_check: 400 access denied to /cib[@epoch]: default -__xml_acl_check: 400 access denied to /cib/configuration/resources/primitive[@id='dummy'][@description]: default +__xml_acl_check: 400 access denied to /cib[@epoch]: default +__xml_acl_check: 400 access denied to /cib/configuration/resources/primitive[@id='dummy'][@description]: default Call failed: Permission denied =#=#=#= End test: niceguy: Replace - create attribute (deny) - Permission denied (13) =#=#=#= * Passed: cibadmin - niceguy: Replace - create attribute (deny) diff --git a/tools/regression.tools.exp b/tools/regression.tools.exp index 287caf9..b2f4df1 100644 --- a/tools/regression.tools.exp +++ b/tools/regression.tools.exp @@ -626,6 +626,7 @@ Deleted nodes attribute: id=nodes-node1-standby name=standby =#=#=#= End test: Create a resource - OK (0) =#=#=#= * Passed: cibadmin - Create a resource =#=#=#= Begin test: Create a resource meta attribute =#=#=#= +Set 'dummy' option: id=dummy-meta_attributes-is-managed set=dummy-meta_attributes name=is-managed=false =#=#=#= Current cib after: Create a resource meta attribute =#=#=#= @@ -695,7 +696,7 @@ false =#=#=#= End test: Query a resource meta attribute - OK (0) =#=#=#= * Passed: crm_resource - Query a resource meta attribute =#=#=#= Begin test: Remove a resource meta attribute =#=#=#= -Deleted dummy option: id=dummy-meta_attributes-is-managed name=is-managed +Deleted 'dummy' option: id=dummy-meta_attributes-is-managed name=is-managed =#=#=#= Current cib after: Remove a resource meta attribute =#=#=#= @@ -728,6 +729,7 @@ Deleted dummy option: id=dummy-meta_attributes-is-managed name=is-managed =#=#=#= End test: Remove a resource meta attribute - OK (0) =#=#=#= * Passed: crm_resource - Remove a resource meta attribute =#=#=#= Begin test: Create a resource attribute =#=#=#= +Set 'dummy' option: id=dummy-instance_attributes-delay set=dummy-instance_attributes name=delay=10s =#=#=#= Current cib after: Create a resource attribute =#=#=#= @@ -763,7 +765,7 @@ Deleted dummy option: id=dummy-meta_attributes-is-managed name=is-managed =#=#=#= End test: Create a resource attribute - OK (0) =#=#=#= * Passed: crm_resource - Create a resource attribute =#=#=#= Begin test: List the configured resources =#=#=#= - dummy (ocf::pacemaker:Dummy): Stopped + dummy (ocf::pacemaker:Dummy): Stopped =#=#=#= Current cib after: List the configured resources =#=#=#= @@ -973,8 +975,8 @@ Error performing operation: No such device or address Current cluster status: Online: [ node1 ] - dummy (ocf::pacemaker:Dummy): Stopped - Fence (stonith:fence_true): Stopped + dummy (ocf::pacemaker:Dummy): Stopped + Fence (stonith:fence_true): Stopped Transition Summary: * Start dummy (node1) @@ -990,8 +992,8 @@ Executing cluster transition: Revised cluster status: Online: [ node1 ] - dummy (ocf::pacemaker:Dummy): Started node1 - Fence (stonith:fence_true): Started node1 + dummy (ocf::pacemaker:Dummy): Started node1 + Fence (stonith:fence_true): Started node1 =#=#=#= Current cib after: Bring resources online =#=#=#= @@ -1710,8 +1712,8 @@ Error performing operation: No such device or address Current cluster status: Online: [ node1 ] - dummy (ocf::pacemaker:Dummy): Started node1 - Fence (stonith:fence_true): Started node1 + dummy (ocf::pacemaker:Dummy): Started node1 + Fence (stonith:fence_true): Started node1 Performing requested modifications + Bringing node node2 online @@ -1733,8 +1735,8 @@ Executing cluster transition: Revised cluster status: Online: [ node1 node2 node3 ] - dummy (ocf::pacemaker:Dummy): Started node1 - Fence (stonith:fence_true): Started node2 + dummy (ocf::pacemaker:Dummy): Started node1 + Fence (stonith:fence_true): Started node2 =#=#=#= Current cib after: Create two more nodes and bring them online =#=#=#= @@ -1996,8 +1998,8 @@ WARNING: Creating rsc_location constraint 'cli-ban-dummy-on-node2' with a score Current cluster status: Online: [ node1 node2 node3 ] - dummy (ocf::pacemaker:Dummy): Started node1 - Fence (stonith:fence_true): Started node2 + dummy (ocf::pacemaker:Dummy): Started node1 + Fence (stonith:fence_true): Started node2 Transition Summary: * Move dummy (Started node1 -> node3) @@ -2010,8 +2012,8 @@ Executing cluster transition: Revised cluster status: Online: [ node1 node2 node3 ] - dummy (ocf::pacemaker:Dummy): Started node3 - Fence (stonith:fence_true): Started node2 + dummy (ocf::pacemaker:Dummy): Started node3 + Fence (stonith:fence_true): Started node2 =#=#=#= Current cib after: Relocate resources due to ban =#=#=#= diff --git a/valgrind-pcmk.suppressions b/valgrind-pcmk.suppressions index 2e382df..0a47096 100644 --- a/valgrind-pcmk.suppressions +++ b/valgrind-pcmk.suppressions @@ -1,4 +1,4 @@ -# Valgrind suppressions for PE testing +# Valgrind suppressions for Pacemaker testing { Valgrind bug Memcheck:Addr8 @@ -57,6 +57,15 @@ } { + Cman - Who cares if unused bytes are uninitialized + Memcheck:Param + sendmsg(msg) + fun:__sendmsg_nocancel + obj:*/libcman.so.3.0 + obj:*/libcman.so.3.0 +} + +{ Cman - Jump or move depends on uninitialized values Memcheck:Cond obj:*/libcman.so.3.0