diff --git a/include/crm/pengine/status.h b/include/crm/pengine/status.h index 57a2511b6f..bd0a9babf9 100644 --- a/include/crm/pengine/status.h +++ b/include/crm/pengine/status.h @@ -1,356 +1,357 @@ /* * Copyright (C) 2004 Andrew Beekhof * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef PENGINE_STATUS__H # define PENGINE_STATUS__H # include # include # include typedef struct node_s node_t; typedef struct pe_action_s action_t; typedef struct pe_action_s pe_action_t; typedef struct resource_s resource_t; typedef struct ticket_s ticket_t; typedef enum no_quorum_policy_e { no_quorum_freeze, no_quorum_stop, no_quorum_ignore, no_quorum_suicide } no_quorum_policy_t; enum node_type { node_ping, node_member, node_remote }; enum pe_restart { pe_restart_restart, pe_restart_ignore }; enum pe_find { pe_find_renamed = 0x001, pe_find_clone = 0x004, pe_find_current = 0x008, pe_find_inactive = 0x010, }; # define pe_flag_have_quorum 0x00000001ULL # define pe_flag_symmetric_cluster 0x00000002ULL # define pe_flag_is_managed_default 0x00000004ULL # define pe_flag_maintenance_mode 0x00000008ULL # define pe_flag_stonith_enabled 0x00000010ULL # define pe_flag_have_stonith_resource 0x00000020ULL # define pe_flag_stop_rsc_orphans 0x00000100ULL # define pe_flag_stop_action_orphans 0x00000200ULL # define pe_flag_stop_everything 0x00000400ULL # define pe_flag_start_failure_fatal 0x00001000ULL # define pe_flag_remove_after_stop 0x00002000ULL # define pe_flag_startup_probes 0x00010000ULL # define pe_flag_have_status 0x00020000ULL # define pe_flag_have_remote_nodes 0x00040000ULL # define pe_flag_quick_location 0x00100000ULL typedef struct pe_working_set_s { xmlNode *input; crm_time_t *now; /* options extracted from the input */ char *dc_uuid; node_t *dc_node; const char *stonith_action; const char *placement_strategy; unsigned long long flags; int stonith_timeout; int default_resource_stickiness; no_quorum_policy_t no_quorum_policy; GHashTable *config_hash; GHashTable *domains; GHashTable *tickets; GListPtr nodes; GListPtr resources; GListPtr placement_constraints; GListPtr ordering_constraints; GListPtr colocation_constraints; GListPtr ticket_constraints; GListPtr actions; xmlNode *failed; xmlNode *op_defaults; xmlNode *rsc_defaults; /* stats */ int num_synapse; int max_valid_nodes; int order_id; int action_id; /* final output */ xmlNode *graph; GHashTable *template_rsc_sets; const char *localhost; } pe_working_set_t; struct node_shared_s { const char *id; const char *uname; gboolean online; gboolean standby; gboolean standby_onfail; gboolean pending; gboolean unclean; gboolean shutdown; gboolean expected_up; gboolean is_dc; int num_resources; GListPtr running_rsc; /* resource_t* */ GListPtr allocated_rsc; /* resource_t* */ resource_t *remote_rsc; GHashTable *attrs; /* char* => char* */ enum node_type type; GHashTable *utilization; /*! cache of calculated rsc digests for this node. */ GHashTable *digest_cache; }; struct node_s { int weight; gboolean fixed; int count; struct node_shared_s *details; }; # include # define pe_rsc_orphan 0x00000001ULL # define pe_rsc_managed 0x00000002ULL # define pe_rsc_block 0x00000004ULL /* Further operations are prohibited due to failure policy */ # define pe_rsc_notify 0x00000010ULL # define pe_rsc_unique 0x00000020ULL # define pe_rsc_provisional 0x00000100ULL # define pe_rsc_allocating 0x00000200ULL # define pe_rsc_merging 0x00000400ULL # define pe_rsc_try_reload 0x00001000ULL # define pe_rsc_reload 0x00002000ULL # define pe_rsc_failed 0x00010000ULL # define pe_rsc_shutdown 0x00020000ULL # define pe_rsc_runnable 0x00040000ULL # define pe_rsc_start_pending 0x00080000ULL # define pe_rsc_starting 0x00100000ULL # define pe_rsc_stopping 0x00200000ULL # define pe_rsc_failure_ignored 0x01000000ULL # define pe_rsc_needs_quorum 0x10000000ULL # define pe_rsc_needs_fencing 0x20000000ULL # define pe_rsc_needs_unfencing 0x40000000ULL enum pe_graph_flags { pe_graph_none = 0x00000, pe_graph_updated_first = 0x00001, pe_graph_updated_then = 0x00002, pe_graph_disable = 0x00004, }; /* *INDENT-OFF* */ enum pe_action_flags { pe_action_pseudo = 0x00001, pe_action_runnable = 0x00002, pe_action_optional = 0x00004, pe_action_print_always = 0x00008, pe_action_have_node_attrs = 0x00010, pe_action_failure_is_fatal = 0x00020, pe_action_implied_by_stonith = 0x00040, pe_action_dumped = 0x00100, pe_action_processed = 0x00200, pe_action_clear = 0x00400, pe_action_dangle = 0x00800, pe_action_requires_any = 0x01000, /* This action requires one or mre of its dependancies to be runnable * We use this to clear the runnable flag before checking dependancies */ }; /* *INDENT-ON* */ struct resource_s { char *id; char *clone_name; xmlNode *xml; xmlNode *orig_xml; xmlNode *ops_xml; resource_t *parent; void *variant_opaque; enum pe_obj_types variant; resource_object_functions_t *fns; resource_alloc_functions_t *cmds; enum rsc_recovery_type recovery_type; enum pe_restart restart_type; int priority; int stickiness; int sort_index; int failure_timeout; int effective_priority; int migration_threshold; gboolean is_remote_node; unsigned long long flags; GListPtr rsc_cons_lhs; /* rsc_colocation_t* */ GListPtr rsc_cons; /* rsc_colocation_t* */ GListPtr rsc_location; /* rsc_to_node_t* */ GListPtr actions; /* action_t* */ GListPtr rsc_tickets; /* rsc_ticket* */ node_t *allocated_to; GListPtr running_on; /* node_t* */ GHashTable *known_on; /* node_t* */ GHashTable *allowed_nodes; /* node_t* */ enum rsc_role_e role; enum rsc_role_e next_role; GHashTable *meta; GHashTable *parameters; GHashTable *utilization; GListPtr children; /* resource_t* */ GListPtr dangling_migrations; /* node_t* */ node_t *partial_migration_target; node_t *partial_migration_source; resource_t *container; GListPtr fillers; }; struct pe_action_s { int id; int priority; resource_t *rsc; node_t *node; xmlNode *op_entry; char *task; char *uuid; enum pe_action_flags flags; enum rsc_start_requirement needs; enum action_fail_response on_fail; enum rsc_role_e fail_role; action_t *pre_notify; action_t *pre_notified; action_t *post_notify; action_t *post_notified; int seen_count; GHashTable *meta; GHashTable *extra; GListPtr actions_before; /* action_warpper_t* */ GListPtr actions_after; /* action_warpper_t* */ }; struct ticket_s { char *id; gboolean granted; time_t last_granted; gboolean standby; GHashTable *state; }; enum pe_link_state { pe_link_not_dumped, pe_link_dumped, pe_link_dup, }; /* *INDENT-OFF* */ enum pe_ordering { pe_order_none = 0x0, /* deleted */ pe_order_optional = 0x1, /* pure ordering, nothing implied */ pe_order_implies_first = 0x10, /* If 'first' is required, ensure 'then' is too */ pe_order_implies_then = 0x20, /* If 'then' is required, ensure 'first' is too */ pe_order_implies_first_master = 0x40, /* Imply 'first' is required when 'then' is required and then's rsc holds Master role. */ pe_order_runnable_left = 0x100, /* 'then' requires 'first' to be runnable */ pe_order_restart = 0x1000, /* 'then' is runnable if 'first' is optional or runnable */ pe_order_stonith_stop = 0x2000, /* only applies if the action is non-pseudo */ pe_order_serialize_only = 0x4000, /* serialize */ pe_order_implies_first_printed = 0x10000, /* Like ..implies_first but only ensures 'first' is printed, not manditory */ pe_order_implies_then_printed = 0x20000, /* Like ..implies_then but only ensures 'then' is printed, not manditory */ pe_order_asymmetrical = 0x100000, /* Indicates asymmetrical one way ordering constraint. */ pe_order_load = 0x200000, /* Only relevant if... */ pe_order_one_or_more = 0x400000, /* 'then' is only runnable if one or more of it's dependancies are too */ pe_order_trace = 0x4000000 /* test marker */ }; /* *INDENT-ON* */ typedef struct action_wrapper_s action_wrapper_t; struct action_wrapper_s { enum pe_ordering type; enum pe_link_state state; action_t *action; }; +const char *rsc_printable_id(resource_t *rsc); gboolean cluster_status(pe_working_set_t * data_set); void set_working_set_defaults(pe_working_set_t * data_set); void cleanup_calculations(pe_working_set_t * data_set); resource_t *pe_find_resource(GListPtr rsc_list, const char *id_rh); node_t *pe_find_node(GListPtr node_list, const char *uname); node_t *pe_find_node_id(GListPtr node_list, const char *id); node_t *pe_find_node_any(GListPtr node_list, const char *id, const char *uname); GListPtr find_operations(const char *rsc, const char *node, gboolean active_filter, pe_working_set_t * data_set); #endif diff --git a/lib/pengine/native.c b/lib/pengine/native.c index e974e504ef..9b2f5ffa6b 100644 --- a/lib/pengine/native.c +++ b/lib/pengine/native.c @@ -1,588 +1,588 @@ /* * Copyright (C) 2004 Andrew Beekhof * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #define VARIANT_NATIVE 1 #include "./variant.h" void native_add_running(resource_t * rsc, node_t * node, pe_working_set_t * data_set) { GListPtr gIter = rsc->running_on; CRM_CHECK(node != NULL, return); for (; gIter != NULL; gIter = gIter->next) { node_t *a_node = (node_t *) gIter->data; CRM_CHECK(a_node != NULL, return); if (safe_str_eq(a_node->details->id, node->details->id)) { return; } } pe_rsc_trace(rsc, "Adding %s to %s", rsc->id, node->details->uname); rsc->running_on = g_list_append(rsc->running_on, node); if (rsc->variant == pe_native) { node->details->running_rsc = g_list_append(node->details->running_rsc, rsc); } if (is_not_set(rsc->flags, pe_rsc_managed)) { pe_rsc_info(rsc, "resource %s isnt managed", rsc->id); resource_location(rsc, node, INFINITY, "not_managed_default", data_set); return; } if (rsc->variant == pe_native && g_list_length(rsc->running_on) > 1) { switch (rsc->recovery_type) { case recovery_stop_only: { GHashTableIter gIter; node_t *local_node = NULL; /* make sure it doesnt come up again */ g_hash_table_destroy(rsc->allowed_nodes); rsc->allowed_nodes = node_hash_from_list(data_set->nodes); g_hash_table_iter_init(&gIter, rsc->allowed_nodes); while (g_hash_table_iter_next(&gIter, NULL, (void **)&local_node)) { local_node->weight = -INFINITY; } } break; case recovery_stop_start: break; case recovery_block: clear_bit(rsc->flags, pe_rsc_managed); set_bit(rsc->flags, pe_rsc_block); break; } crm_debug("%s is active on %d nodes including %s: %s", rsc->id, g_list_length(rsc->running_on), node->details->uname, recovery2text(rsc->recovery_type)); } else { pe_rsc_trace(rsc, "Resource %s is active on: %s", rsc->id, node->details->uname); } if (rsc->parent != NULL) { native_add_running(rsc->parent, node, data_set); } } extern void force_non_unique_clone(resource_t * rsc, const char *rid, pe_working_set_t * data_set); gboolean native_unpack(resource_t * rsc, pe_working_set_t * data_set) { resource_t *parent = uber_parent(rsc); native_variant_data_t *native_data = NULL; const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS); pe_rsc_trace(rsc, "Processing resource %s...", rsc->id); native_data = calloc(1, sizeof(native_variant_data_t)); rsc->variant_opaque = native_data; if (is_set(rsc->flags, pe_rsc_unique) && rsc->parent) { if (safe_str_eq(class, "lsb")) { resource_t *top = uber_parent(rsc); force_non_unique_clone(top, rsc->id, data_set); } } if (safe_str_eq(class, "ocf") == FALSE) { const char *stateful = g_hash_table_lookup(parent->meta, "stateful"); if (safe_str_eq(stateful, XML_BOOLEAN_TRUE)) { pe_err ("Resource %s is of type %s and therefore cannot be used as a master/slave resource", rsc->id, class); return FALSE; } } return TRUE; } resource_t * native_find_rsc(resource_t * rsc, const char *id, node_t * on_node, int flags) { gboolean match = FALSE; resource_t *result = NULL; GListPtr gIter = rsc->children; CRM_ASSERT(id != NULL); if (flags & pe_find_clone) { const char *rid = ID(rsc->xml); if (rsc->parent == NULL) { match = FALSE; } else if (safe_str_eq(rsc->id, id)) { match = TRUE; } else if (safe_str_eq(rid, id)) { match = TRUE; } } else { if (strcmp(rsc->id, id) == 0) { match = TRUE; } else if (is_set(flags, pe_find_renamed) && rsc->clone_name && strcmp(rsc->clone_name, id) == 0) { match = TRUE; } } if (match && on_node) { pe_rsc_trace(rsc, "Now checking %s is on %s", rsc->id, on_node->details->uname); if (is_set(flags, pe_find_current) && rsc->running_on) { GListPtr gIter = rsc->running_on; for (; gIter != NULL; gIter = gIter->next) { node_t *loc = (node_t *) gIter->data; if (loc->details == on_node->details) { return rsc; } } } else if (is_set(flags, pe_find_inactive) && rsc->running_on == NULL) { return rsc; } else if (is_not_set(flags, pe_find_current) && rsc->allocated_to && rsc->allocated_to->details == on_node->details) { return rsc; } } else if (match) { return rsc; } for (; gIter != NULL; gIter = gIter->next) { resource_t *child = (resource_t *) gIter->data; result = rsc->fns->find_rsc(child, id, on_node, flags); if (result) { return result; } } return NULL; } char * native_parameter(resource_t * rsc, node_t * node, gboolean create, const char *name, pe_working_set_t * data_set) { char *value_copy = NULL; const char *value = NULL; GHashTable *hash = rsc->parameters; GHashTable *local_hash = NULL; CRM_CHECK(rsc != NULL, return NULL); CRM_CHECK(name != NULL && strlen(name) != 0, return NULL); pe_rsc_trace(rsc, "Looking up %s in %s", name, rsc->id); if (create || g_hash_table_size(rsc->parameters) == 0) { if (node != NULL) { pe_rsc_trace(rsc, "Creating hash with node %s", node->details->uname); } else { pe_rsc_trace(rsc, "Creating default hash"); } local_hash = g_hash_table_new_full(crm_str_hash, g_str_equal, g_hash_destroy_str, g_hash_destroy_str); get_rsc_attributes(local_hash, rsc, node, data_set); hash = local_hash; } value = g_hash_table_lookup(hash, name); if (value == NULL) { /* try meta attributes instead */ value = g_hash_table_lookup(rsc->meta, name); } if (value != NULL) { value_copy = strdup(value); } if (local_hash != NULL) { g_hash_table_destroy(local_hash); } return value_copy; } gboolean native_active(resource_t * rsc, gboolean all) { GListPtr gIter = rsc->running_on; for (; gIter != NULL; gIter = gIter->next) { node_t *a_node = (node_t *) gIter->data; if (a_node->details->unclean) { crm_debug("Resource %s: node %s is unclean", rsc->id, a_node->details->uname); return TRUE; } else if (a_node->details->online == FALSE) { crm_debug("Resource %s: node %s is offline", rsc->id, a_node->details->uname); } else { crm_debug("Resource %s active on %s", rsc->id, a_node->details->uname); return TRUE; } } return FALSE; } struct print_data_s { long options; void *print_data; }; static void native_print_attr(gpointer key, gpointer value, gpointer user_data) { long options = ((struct print_data_s *)user_data)->options; void *print_data = ((struct print_data_s *)user_data)->print_data; status_print("Option: %s = %s\n", (char *)key, (char *)value); } static void native_print_xml(resource_t * rsc, const char *pre_text, long options, void *print_data) { const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS); const char *prov = crm_element_value(rsc->xml, XML_AGENT_ATTR_PROVIDER); /* resource information. */ status_print("%sid); + status_print("id=\"%s\" ", rsc_printable_id(rsc)); status_print("resource_agent=\"%s%s%s:%s\" ", class, prov ? "::" : "", prov ? prov : "", crm_element_value(rsc->xml, XML_ATTR_TYPE)); status_print("role=\"%s\" ", role2text(rsc->role)); status_print("active=\"%s\" ", rsc->fns->active(rsc, TRUE) ? "true" : "false"); status_print("orphaned=\"%s\" ", is_set(rsc->flags, pe_rsc_orphan) ? "true" : "false"); status_print("managed=\"%s\" ", is_set(rsc->flags, pe_rsc_managed) ? "true" : "false"); status_print("failed=\"%s\" ", is_set(rsc->flags, pe_rsc_failed) ? "true" : "false"); status_print("failure_ignored=\"%s\" ", is_set(rsc->flags, pe_rsc_failure_ignored) ? "true" : "false"); status_print("nodes_running_on=\"%d\" ", g_list_length(rsc->running_on)); if (options & pe_print_dev) { status_print("provisional=\"%s\" ", is_set(rsc->flags, pe_rsc_provisional) ? "true" : "false"); status_print("runnable=\"%s\" ", is_set(rsc->flags, pe_rsc_runnable) ? "true" : "false"); status_print("priority=\"%f\" ", (double)rsc->priority); status_print("variant=\"%s\" ", crm_element_name(rsc->xml)); } /* print out the nodes this resource is running on */ if (options & pe_print_rsconly) { status_print("/>\n"); /* do nothing */ } else if (g_list_length(rsc->running_on) > 0) { GListPtr gIter = rsc->running_on; status_print(">\n"); for (; gIter != NULL; gIter = gIter->next) { node_t *node = (node_t *) gIter->data; status_print("%s \n", pre_text, node->details->uname, node->details->id, node->details->online ? "false" : "true"); } status_print("%s\n", pre_text); } else { status_print("/>\n"); } } void native_print(resource_t * rsc, const char *pre_text, long options, void *print_data) { node_t *node = NULL; const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS); const char *kind = crm_element_value(rsc->xml, XML_ATTR_TYPE); int offset = 0; char buffer[LINE_MAX]; CRM_ASSERT(rsc->variant == pe_native); CRM_ASSERT(kind != NULL); if (rsc->meta) { const char *is_internal = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_INTERNAL_RSC); if (crm_is_true(is_internal)) { crm_trace("skipping print of internal resource %s", rsc->id); return; } } if (pre_text == NULL && (options & pe_print_printf)) { pre_text = " "; } if (options & pe_print_xml) { native_print_xml(rsc, pre_text, options, print_data); return; } if (rsc->running_on != NULL) { node = rsc->running_on->data; } if ((options & pe_print_rsconly) || g_list_length(rsc->running_on) > 1) { node = NULL; } if (options & pe_print_html) { if (is_not_set(rsc->flags, pe_rsc_managed)) { status_print(""); } else if (is_set(rsc->flags, pe_rsc_failed)) { status_print(""); } else if (rsc->variant == pe_native && g_list_length(rsc->running_on) == 0) { status_print(""); } else if (g_list_length(rsc->running_on) > 1) { status_print(""); } else if (is_set(rsc->flags, pe_rsc_failure_ignored)) { status_print(""); } else { status_print(""); } } if(pre_text) { offset += snprintf(buffer + offset, LINE_MAX - offset, "%s", pre_text); } - offset += snprintf(buffer + offset, LINE_MAX - offset, "%s", rsc->id); + offset += snprintf(buffer + offset, LINE_MAX - offset, "%s", rsc_printable_id(rsc)); offset += snprintf(buffer + offset, LINE_MAX - offset, "\t(%s", class); if (safe_str_eq(class, "ocf")) { const char *prov = crm_element_value(rsc->xml, XML_AGENT_ATTR_PROVIDER); offset += snprintf(buffer + offset, LINE_MAX - offset, "::%s", prov); } offset += snprintf(buffer + offset, LINE_MAX - offset, ":%s):\t", kind); if(is_set(rsc->flags, pe_rsc_orphan)) { offset += snprintf(buffer + offset, LINE_MAX - offset, " ORPHANED "); } offset += snprintf(buffer + offset, LINE_MAX - offset, "%s ", role2text(rsc->role)); if(node) { offset += snprintf(buffer + offset, LINE_MAX - offset, "%s ", node->details->uname); } if(is_not_set(rsc->flags, pe_rsc_managed)) { offset += snprintf(buffer + offset, LINE_MAX - offset, "(unmanaged) "); } if(is_set(rsc->flags, pe_rsc_failed)) { offset += snprintf(buffer + offset, LINE_MAX - offset, "FAILED "); } if(is_set(rsc->flags, pe_rsc_failure_ignored)) { offset += snprintf(buffer + offset, LINE_MAX - offset, "(failure ignored)"); } if ((options & pe_print_rsconly) || g_list_length(rsc->running_on) > 1) { const char *desc = crm_element_value(rsc->xml, XML_ATTR_DESC); if(desc) { offset += snprintf(buffer + offset, LINE_MAX - offset, "%s", desc); } } status_print("%s", buffer); #if CURSES_ENABLED if ((options & pe_print_rsconly) || g_list_length(rsc->running_on) > 1) { /* Done */ } else if (options & pe_print_ncurses) { /* coverity[negative_returns] False positive */ move(-1, 0); } #endif if (options & pe_print_html) { status_print(" "); } if ((options & pe_print_rsconly)) { } else if (g_list_length(rsc->running_on) > 1) { GListPtr gIter = rsc->running_on; int counter = 0; if (options & pe_print_html) { status_print("
    \n"); } else if ((options & pe_print_printf) || (options & pe_print_ncurses)) { status_print("["); } for (; gIter != NULL; gIter = gIter->next) { node_t *node = (node_t *) gIter->data; counter++; if (options & pe_print_html) { status_print("
  • \n%s", node->details->uname); } else if ((options & pe_print_printf) || (options & pe_print_ncurses)) { status_print(" %s", node->details->uname); } else if ((options & pe_print_log)) { status_print("\t%d : %s", counter, node->details->uname); } else { status_print("%s", node->details->uname); } if (options & pe_print_html) { status_print("
  • \n"); } } if (options & pe_print_html) { status_print("
\n"); } else if ((options & pe_print_printf) || (options & pe_print_ncurses)) { status_print(" ]"); } } if (options & pe_print_html) { status_print("
\n"); } else if (options & pe_print_suppres_nl) { /* nothing */ } else if ((options & pe_print_printf) || (options & pe_print_ncurses)) { status_print("\n"); } if (options & pe_print_details) { struct print_data_s pdata; pdata.options = options; pdata.print_data = print_data; g_hash_table_foreach(rsc->parameters, native_print_attr, &pdata); } if (options & pe_print_dev) { GHashTableIter iter; node_t *node = NULL; status_print("%s\t(%s%svariant=%s, priority=%f)", pre_text, is_set(rsc->flags, pe_rsc_provisional) ? "provisional, " : "", is_set(rsc->flags, pe_rsc_runnable) ? "" : "non-startable, ", crm_element_name(rsc->xml), (double)rsc->priority); status_print("%s\tAllowed Nodes", pre_text); g_hash_table_iter_init(&iter, rsc->allowed_nodes); while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) { status_print("%s\t * %s %d", pre_text, node->details->uname, node->weight); } } if (options & pe_print_max_details) { GHashTableIter iter; node_t *node = NULL; status_print("%s\t=== Allowed Nodes\n", pre_text); g_hash_table_iter_init(&iter, rsc->allowed_nodes); while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) { print_node("\t", node, FALSE); } } } void native_free(resource_t * rsc) { pe_rsc_trace(rsc, "Freeing resource action list (not the data)"); common_free(rsc); } enum rsc_role_e native_resource_state(const resource_t * rsc, gboolean current) { enum rsc_role_e role = rsc->next_role; if (current) { role = rsc->role; } pe_rsc_trace(rsc, "%s state: %s", rsc->id, role2text(role)); return role; } node_t * native_location(resource_t * rsc, GListPtr * list, gboolean current) { node_t *one = NULL; GListPtr result = NULL; if (rsc->children) { GListPtr gIter = rsc->children; for (; gIter != NULL; gIter = gIter->next) { resource_t *child = (resource_t *) gIter->data; child->fns->location(child, &result, current); } } else if (current && rsc->running_on) { result = g_list_copy(rsc->running_on); } else if (current == FALSE && rsc->allocated_to) { result = g_list_append(NULL, rsc->allocated_to); } if (result && g_list_length(result) == 1) { one = g_list_nth_data(result, 0); } if (list) { GListPtr gIter = result; for (; gIter != NULL; gIter = gIter->next) { node_t *node = (node_t *) gIter->data; if (*list == NULL || pe_find_node_id(*list, node->details->id) == NULL) { *list = g_list_append(*list, node); } } } g_list_free(result); return one; } diff --git a/lib/pengine/utils.c b/lib/pengine/utils.c index 8ecc5008a4..6bf67adf1b 100644 --- a/lib/pengine/utils.c +++ b/lib/pengine/utils.c @@ -1,1744 +1,1752 @@ /* * Copyright (C) 2004 Andrew Beekhof * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include pe_working_set_t *pe_dataset = NULL; extern xmlNode *get_object_root(const char *object_type, xmlNode * the_root); void print_str_str(gpointer key, gpointer value, gpointer user_data); gboolean ghash_free_str_str(gpointer key, gpointer value, gpointer user_data); void unpack_operation(action_t * action, xmlNode * xml_obj, resource_t * container, pe_working_set_t * data_set); static xmlNode *find_rsc_op_entry_helper(resource_t * rsc, const char *key, gboolean include_disabled); node_t * node_copy(node_t * this_node) { node_t *new_node = NULL; CRM_CHECK(this_node != NULL, return NULL); new_node = calloc(1, sizeof(node_t)); CRM_ASSERT(new_node != NULL); crm_trace("Copying %p (%s) to %p", this_node, this_node->details->uname, new_node); new_node->weight = this_node->weight; new_node->fixed = this_node->fixed; new_node->details = this_node->details; return new_node; } /* any node in list1 or list2 and not in the other gets a score of -INFINITY */ void node_list_exclude(GHashTable * hash, GListPtr list, gboolean merge_scores) { GHashTable *result = hash; node_t *other_node = NULL; GListPtr gIter = list; GHashTableIter iter; node_t *node = NULL; g_hash_table_iter_init(&iter, hash); while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) { other_node = pe_find_node_id(list, node->details->id); if (other_node == NULL) { node->weight = -INFINITY; } else if (merge_scores) { node->weight = merge_weights(node->weight, other_node->weight); } } for (; gIter != NULL; gIter = gIter->next) { node_t *node = (node_t *) gIter->data; other_node = pe_hash_table_lookup(result, node->details->id); if (other_node == NULL) { node_t *new_node = node_copy(node); new_node->weight = -INFINITY; g_hash_table_insert(result, (gpointer) new_node->details->id, new_node); } } } GHashTable * node_hash_from_list(GListPtr list) { GListPtr gIter = list; GHashTable *result = g_hash_table_new_full(crm_str_hash, g_str_equal, NULL, g_hash_destroy_str); for (; gIter != NULL; gIter = gIter->next) { node_t *node = (node_t *) gIter->data; node_t *n = node_copy(node); g_hash_table_insert(result, (gpointer) n->details->id, n); } return result; } GListPtr node_list_dup(GListPtr list1, gboolean reset, gboolean filter) { GListPtr result = NULL; GListPtr gIter = list1; for (; gIter != NULL; gIter = gIter->next) { node_t *new_node = NULL; node_t *this_node = (node_t *) gIter->data; if (filter && this_node->weight < 0) { continue; } new_node = node_copy(this_node); if (reset) { new_node->weight = 0; } if (new_node != NULL) { result = g_list_prepend(result, new_node); } } return result; } gint sort_node_uname(gconstpointer a, gconstpointer b) { const node_t *node_a = a; const node_t *node_b = b; return strcmp(node_a->details->uname, node_b->details->uname); } void dump_node_scores_worker(int level, const char *file, const char *function, int line, resource_t * rsc, const char *comment, GHashTable * nodes) { GHashTable *hash = nodes; GHashTableIter iter; node_t *node = NULL; if (rsc) { hash = rsc->allowed_nodes; } if (rsc && is_set(rsc->flags, pe_rsc_orphan)) { /* Don't show the allocation scores for orphans */ return; } if (level == 0) { /* For now we want this in sorted order to keep the regression tests happy */ GListPtr gIter = NULL; GListPtr list = g_hash_table_get_values(hash); list = g_list_sort(list, sort_node_uname); gIter = list; for (; gIter != NULL; gIter = gIter->next) { node_t *node = (node_t *) gIter->data; char *score = score2char(node->weight); if (rsc) { printf("%s: %s allocation score on %s: %s\n", comment, rsc->id, node->details->uname, score); } else { printf("%s: %s = %s\n", comment, node->details->uname, score); } free(score); } g_list_free(list); } else if (hash) { g_hash_table_iter_init(&iter, hash); while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) { char *score = score2char(node->weight); if (rsc) { do_crm_log_alias(LOG_TRACE, file, function, line, "%s: %s allocation score on %s: %s", comment, rsc->id, node->details->uname, score); } else { do_crm_log_alias(LOG_TRACE, file, function, line + 1, "%s: %s = %s", comment, node->details->uname, score); } free(score); } } if (rsc && rsc->children) { GListPtr gIter = NULL; gIter = rsc->children; for (; gIter != NULL; gIter = gIter->next) { resource_t *child = (resource_t *) gIter->data; dump_node_scores_worker(level, file, function, line, child, comment, nodes); } } } static void append_dump_text(gpointer key, gpointer value, gpointer user_data) { char **dump_text = user_data; int len = 0; char *new_text = NULL; len = strlen(*dump_text) + strlen(" ") + strlen(key) + strlen("=") + strlen(value) + 1; new_text = calloc(1, len); sprintf(new_text, "%s %s=%s", *dump_text, (char *)key, (char *)value); free(*dump_text); *dump_text = new_text; } void dump_node_capacity(int level, const char *comment, node_t * node) { int len = 0; char *dump_text = NULL; len = strlen(comment) + strlen(": ") + strlen(node->details->uname) + strlen(" capacity:") + 1; dump_text = calloc(1, len); sprintf(dump_text, "%s: %s capacity:", comment, node->details->uname); g_hash_table_foreach(node->details->utilization, append_dump_text, &dump_text); if (level == 0) { fprintf(stdout, "%s\n", dump_text); } else { crm_trace("%s", dump_text); } free(dump_text); } void dump_rsc_utilization(int level, const char *comment, resource_t * rsc, node_t * node) { int len = 0; char *dump_text = NULL; len = strlen(comment) + strlen(": ") + strlen(rsc->id) + strlen(" utilization on ") + strlen(node->details->uname) + strlen(":") + 1; dump_text = calloc(1, len); sprintf(dump_text, "%s: %s utilization on %s:", comment, rsc->id, node->details->uname); g_hash_table_foreach(rsc->utilization, append_dump_text, &dump_text); if (level == 0) { fprintf(stdout, "%s\n", dump_text); } else { crm_trace("%s", dump_text); } free(dump_text); } gint sort_rsc_index(gconstpointer a, gconstpointer b) { const resource_t *resource1 = (const resource_t *)a; const resource_t *resource2 = (const resource_t *)b; if (a == NULL && b == NULL) { return 0; } if (a == NULL) { return 1; } if (b == NULL) { return -1; } if (resource1->sort_index > resource2->sort_index) { return -1; } if (resource1->sort_index < resource2->sort_index) { return 1; } return 0; } gint sort_rsc_priority(gconstpointer a, gconstpointer b) { const resource_t *resource1 = (const resource_t *)a; const resource_t *resource2 = (const resource_t *)b; if (a == NULL && b == NULL) { return 0; } if (a == NULL) { return 1; } if (b == NULL) { return -1; } if (resource1->priority > resource2->priority) { return -1; } if (resource1->priority < resource2->priority) { return 1; } return 0; } action_t * custom_action(resource_t * rsc, char *key, const char *task, node_t * on_node, gboolean optional, gboolean save_action, pe_working_set_t * data_set) { action_t *action = NULL; GListPtr possible_matches = NULL; CRM_CHECK(key != NULL, return NULL); CRM_CHECK(task != NULL, return NULL); if (save_action && rsc != NULL) { possible_matches = find_actions(rsc->actions, key, on_node); } if (possible_matches != NULL) { if (g_list_length(possible_matches) > 1) { pe_warn("Action %s for %s on %s exists %d times", task, rsc ? rsc->id : "", on_node ? on_node->details->uname : "", g_list_length(possible_matches)); } action = g_list_nth_data(possible_matches, 0); pe_rsc_trace(rsc, "Found existing action (%d) %s for %s on %s", action->id, task, rsc ? rsc->id : "", on_node ? on_node->details->uname : ""); g_list_free(possible_matches); } if (action == NULL) { if (save_action) { pe_rsc_trace(rsc, "Creating%s action %d: %s for %s on %s", optional ? "" : " manditory", data_set->action_id, key, rsc ? rsc->id : "", on_node ? on_node->details->uname : ""); } action = calloc(1, sizeof(action_t)); if (save_action) { action->id = data_set->action_id++; } else { action->id = 0; } action->rsc = rsc; CRM_ASSERT(task != NULL); action->task = strdup(task); if (on_node) { action->node = node_copy(on_node); } action->uuid = strdup(key); pe_set_action_bit(action, pe_action_failure_is_fatal); pe_set_action_bit(action, pe_action_runnable); if (optional) { pe_set_action_bit(action, pe_action_optional); } else { pe_clear_action_bit(action, pe_action_optional); } /* Implied by calloc()... action->actions_before = NULL; action->actions_after = NULL; action->pseudo = FALSE; action->dumped = FALSE; action->processed = FALSE; action->seen_count = 0; */ action->extra = g_hash_table_new_full(crm_str_hash, g_str_equal, free, free); action->meta = g_hash_table_new_full(crm_str_hash, g_str_equal, free, free); if (save_action) { data_set->actions = g_list_prepend(data_set->actions, action); } if (rsc != NULL) { action->op_entry = find_rsc_op_entry_helper(rsc, key, TRUE); unpack_operation(action, action->op_entry, rsc->container, data_set); if (save_action) { rsc->actions = g_list_prepend(rsc->actions, action); } } if (save_action) { pe_rsc_trace(rsc, "Action %d created", action->id); } } if (optional == FALSE) { pe_rsc_trace(rsc, "Action %d (%s) marked manditory", action->id, action->uuid); pe_clear_action_bit(action, pe_action_optional); } if (rsc != NULL) { enum action_tasks a_task = text2task(action->task); int warn_level = LOG_TRACE; if (save_action) { warn_level = LOG_WARNING; } if (is_set(action->flags, pe_action_have_node_attrs) == FALSE && action->node != NULL && action->op_entry != NULL) { pe_set_action_bit(action, pe_action_have_node_attrs); unpack_instance_attributes(data_set->input, action->op_entry, XML_TAG_ATTR_SETS, action->node->details->attrs, action->extra, NULL, FALSE, data_set->now); } if (is_set(action->flags, pe_action_pseudo)) { /* leave untouched */ } else if (action->node == NULL) { pe_clear_action_bit(action, pe_action_runnable); } else if (is_not_set(rsc->flags, pe_rsc_managed) && g_hash_table_lookup(action->meta, XML_LRM_ATTR_INTERVAL) == NULL) { crm_debug("Action %s (unmanaged)", action->uuid); pe_set_action_bit(action, pe_action_optional); /* action->runnable = FALSE; */ } else if (action->node->details->online == FALSE) { pe_clear_action_bit(action, pe_action_runnable); do_crm_log(warn_level, "Action %s on %s is unrunnable (offline)", action->uuid, action->node->details->uname); if (is_set(action->rsc->flags, pe_rsc_managed) && action->node->details->unclean == FALSE && save_action && a_task == stop_rsc) { do_crm_log(warn_level, "Marking node %s unclean", action->node->details->uname); action->node->details->unclean = TRUE; } } else if (action->node->details->pending) { pe_clear_action_bit(action, pe_action_runnable); do_crm_log(warn_level, "Action %s on %s is unrunnable (pending)", action->uuid, action->node->details->uname); } else if (action->needs == rsc_req_nothing) { pe_rsc_trace(rsc, "Action %s doesnt require anything", action->uuid); pe_set_action_bit(action, pe_action_runnable); #if 0 /* * No point checking this * - if we dont have quorum we cant stonith anyway */ } else if (action->needs == rsc_req_stonith) { crm_trace("Action %s requires only stonith", action->uuid); action->runnable = TRUE; #endif } else if (is_set(data_set->flags, pe_flag_have_quorum) == FALSE && data_set->no_quorum_policy == no_quorum_stop) { pe_clear_action_bit(action, pe_action_runnable); crm_debug("%s\t%s (cancelled : quorum)", action->node->details->uname, action->uuid); } else if (is_set(data_set->flags, pe_flag_have_quorum) == FALSE && data_set->no_quorum_policy == no_quorum_freeze) { pe_rsc_trace(rsc, "Check resource is already active"); if (rsc->fns->active(rsc, TRUE) == FALSE) { pe_clear_action_bit(action, pe_action_runnable); pe_rsc_debug(rsc, "%s\t%s (cancelled : quorum freeze)", action->node->details->uname, action->uuid); } } else { pe_rsc_trace(rsc, "Action %s is runnable", action->uuid); pe_set_action_bit(action, pe_action_runnable); } if (save_action) { switch (a_task) { case stop_rsc: set_bit(rsc->flags, pe_rsc_stopping); break; case start_rsc: clear_bit(rsc->flags, pe_rsc_starting); if (is_set(action->flags, pe_action_runnable)) { set_bit(rsc->flags, pe_rsc_starting); } break; default: break; } } } free(key); return action; } static const char * unpack_operation_on_fail(action_t * action) { const char *value = g_hash_table_lookup(action->meta, XML_OP_ATTR_ON_FAIL); if (safe_str_eq(action->task, CRMD_ACTION_STOP) && safe_str_eq(value, "standby")) { crm_config_err("on-fail=standby is not allowed for stop actions: %s", action->rsc->id); return NULL; } else if (safe_str_eq(action->task, CRMD_ACTION_DEMOTE) && !value) { /* demote on_fail defaults to master monitor value if present */ xmlNode *operation = NULL; const char *name = NULL; const char *role = NULL; const char *on_fail = NULL; const char *interval = NULL; const char *enabled = NULL; CRM_CHECK(action->rsc != NULL, return NULL); for (operation = __xml_first_child(action->rsc->ops_xml); operation && !value; operation = __xml_next(operation)) { if (!crm_str_eq((const char *)operation->name, "op", TRUE)) { continue; } name = crm_element_value(operation, "name"); role = crm_element_value(operation, "role"); on_fail = crm_element_value(operation, XML_OP_ATTR_ON_FAIL); enabled = crm_element_value(operation, "enabled"); interval = crm_element_value(operation, XML_LRM_ATTR_INTERVAL); if (!on_fail) { continue; } else if (enabled && !crm_is_true(enabled)) { continue; } else if (safe_str_neq(name, "monitor") || safe_str_neq(role, "Master")) { continue; } else if (crm_get_interval(interval) <= 0) { continue; } value = on_fail; } } return value; } static xmlNode * find_min_interval_mon(resource_t * rsc, gboolean include_disabled) { int number = 0; int min_interval = -1; const char *name = NULL; const char *value = NULL; const char *interval = NULL; xmlNode *op = NULL; xmlNode *operation = NULL; for (operation = __xml_first_child(rsc->ops_xml); operation != NULL; operation = __xml_next(operation)) { if (crm_str_eq((const char *)operation->name, "op", TRUE)) { name = crm_element_value(operation, "name"); interval = crm_element_value(operation, XML_LRM_ATTR_INTERVAL); value = crm_element_value(operation, "enabled"); if (!include_disabled && value && crm_is_true(value) == FALSE) { continue; } if (safe_str_neq(name, RSC_STATUS)) { continue; } number = crm_get_interval(interval); if (number < 0) { continue; } if (min_interval < 0 || number < min_interval) { min_interval = number; op = operation; } } } return op; } void unpack_operation(action_t * action, xmlNode * xml_obj, resource_t * container, pe_working_set_t * data_set) { int value_i = 0; unsigned long long interval = 0; unsigned long long start_delay = 0; char *value_ms = NULL; const char *value = NULL; const char *field = NULL; CRM_CHECK(action->rsc != NULL, return); unpack_instance_attributes(data_set->input, data_set->op_defaults, XML_TAG_META_SETS, NULL, action->meta, NULL, FALSE, data_set->now); if (xml_obj) { xmlAttrPtr xIter = NULL; for (xIter = xml_obj->properties; xIter; xIter = xIter->next) { const char *prop_name = (const char *)xIter->name; const char *prop_value = crm_element_value(xml_obj, prop_name); g_hash_table_replace(action->meta, strdup(prop_name), strdup(prop_value)); } } unpack_instance_attributes(data_set->input, xml_obj, XML_TAG_META_SETS, NULL, action->meta, NULL, FALSE, data_set->now); unpack_instance_attributes(data_set->input, xml_obj, XML_TAG_ATTR_SETS, NULL, action->meta, NULL, FALSE, data_set->now); g_hash_table_remove(action->meta, "id"); /* Begin compatability code */ value = g_hash_table_lookup(action->meta, "requires"); if (safe_str_neq(action->task, RSC_START) && safe_str_neq(action->task, RSC_PROMOTE)) { action->needs = rsc_req_nothing; value = "nothing (not start/promote)"; } else if (safe_str_eq(value, "nothing")) { action->needs = rsc_req_nothing; } else if (safe_str_eq(value, "quorum")) { action->needs = rsc_req_quorum; } else if (safe_str_eq(value, "unfencing")) { action->needs = rsc_req_stonith; set_bit(action->rsc->flags, pe_rsc_needs_unfencing); if (is_set(data_set->flags, pe_flag_stonith_enabled)) { crm_notice("%s requires (un)fencing but fencing is disabled", action->rsc->id); } } else if (is_set(data_set->flags, pe_flag_stonith_enabled) && safe_str_eq(value, "fencing")) { action->needs = rsc_req_stonith; if (is_set(data_set->flags, pe_flag_stonith_enabled)) { crm_notice("%s requires fencing but fencing is disabled", action->rsc->id); } /* End compatability code */ } else if (is_set(action->rsc->flags, pe_rsc_needs_fencing)) { action->needs = rsc_req_stonith; value = "fencing (resource)"; } else if (is_set(action->rsc->flags, pe_rsc_needs_quorum)) { action->needs = rsc_req_quorum; value = "quorum (resource)"; } else { action->needs = rsc_req_nothing; value = "nothing (resource)"; } pe_rsc_trace(action->rsc, "\tAction %s requires: %s", action->task, value); value = unpack_operation_on_fail(action); if (value == NULL) { } else if (safe_str_eq(value, "block")) { action->on_fail = action_fail_block; } else if (safe_str_eq(value, "fence")) { action->on_fail = action_fail_fence; value = "node fencing"; if (is_set(data_set->flags, pe_flag_stonith_enabled) == FALSE) { crm_config_err("Specifying on_fail=fence and" " stonith-enabled=false makes no sense"); action->on_fail = action_fail_stop; action->fail_role = RSC_ROLE_STOPPED; value = "stop resource"; } } else if (safe_str_eq(value, "standby")) { action->on_fail = action_fail_standby; value = "node standby"; } else if (safe_str_eq(value, "ignore") || safe_str_eq(value, "nothing")) { action->on_fail = action_fail_ignore; value = "ignore"; } else if (safe_str_eq(value, "migrate")) { action->on_fail = action_fail_migrate; value = "force migration"; } else if (safe_str_eq(value, "stop")) { action->on_fail = action_fail_stop; action->fail_role = RSC_ROLE_STOPPED; value = "stop resource"; } else if (safe_str_eq(value, "restart")) { action->on_fail = action_fail_recover; value = "restart (and possibly migrate)"; } else if (safe_str_eq(value, "restart-container")) { if (container) { action->on_fail = action_fail_restart_container; value = "restart container (and possibly migrate)"; } else { value = NULL; } } else { pe_err("Resource %s: Unknown failure type (%s)", action->rsc->id, value); value = NULL; } /* defaults */ if (value == NULL && container) { action->on_fail = action_fail_restart_container; value = "restart container (and possibly migrate) (default)"; } else if (value == NULL && safe_str_eq(action->task, CRMD_ACTION_STOP)) { if (is_set(data_set->flags, pe_flag_stonith_enabled)) { action->on_fail = action_fail_fence; value = "resource fence (default)"; } else { action->on_fail = action_fail_block; value = "resource block (default)"; } } else if (value == NULL) { action->on_fail = action_fail_recover; value = "restart (and possibly migrate) (default)"; } pe_rsc_trace(action->rsc, "\t%s failure handling: %s", action->task, value); value = NULL; if (xml_obj != NULL) { value = g_hash_table_lookup(action->meta, "role_after_failure"); } if (value != NULL && action->fail_role == RSC_ROLE_UNKNOWN) { action->fail_role = text2role(value); } /* defaults */ if (action->fail_role == RSC_ROLE_UNKNOWN) { if (safe_str_eq(action->task, CRMD_ACTION_PROMOTE)) { action->fail_role = RSC_ROLE_SLAVE; } else { action->fail_role = RSC_ROLE_STARTED; } } pe_rsc_trace(action->rsc, "\t%s failure results in: %s", action->task, role2text(action->fail_role)); field = XML_LRM_ATTR_INTERVAL; value = g_hash_table_lookup(action->meta, field); if (value != NULL) { interval = crm_get_interval(value); if (interval > 0) { value_ms = crm_itoa(interval); g_hash_table_replace(action->meta, strdup(field), value_ms); } else { g_hash_table_remove(action->meta, field); } } field = XML_OP_ATTR_START_DELAY; value = g_hash_table_lookup(action->meta, field); if (value != NULL) { value_i = crm_get_msec(value); if (value_i < 0) { value_i = 0; } start_delay = value_i; value_ms = crm_itoa(value_i); g_hash_table_replace(action->meta, strdup(field), value_ms); } else if (interval > 0 && g_hash_table_lookup(action->meta, XML_OP_ATTR_ORIGIN)) { crm_time_t *origin = NULL; value = g_hash_table_lookup(action->meta, XML_OP_ATTR_ORIGIN); origin = crm_time_new(value); if (origin == NULL) { crm_config_err("Operation %s contained an invalid " XML_OP_ATTR_ORIGIN ": %s", ID(xml_obj), value); } else { crm_time_t *delay = NULL; int rc = crm_time_compare(origin, data_set->now); unsigned long long delay_s = 0; while (rc < 0) { crm_time_add_seconds(origin, interval / 1000); rc = crm_time_compare(origin, data_set->now); } delay = crm_time_subtract(origin, data_set->now); delay_s = crm_time_get_seconds(delay); start_delay = delay_s * 1000; crm_info("Calculated a start delay of %llus for %s", delay_s, ID(xml_obj)); g_hash_table_replace(action->meta, strdup(XML_OP_ATTR_START_DELAY), crm_itoa(start_delay)); crm_time_free(origin); crm_time_free(delay); } } field = XML_ATTR_TIMEOUT; value = g_hash_table_lookup(action->meta, field); if (value == NULL && xml_obj == NULL && safe_str_eq(action->task, RSC_STATUS) && interval == 0) { xmlNode *min_interval_mon = find_min_interval_mon(action->rsc, FALSE); if (min_interval_mon) { value = crm_element_value(min_interval_mon, XML_ATTR_TIMEOUT); pe_rsc_trace(action->rsc, "\t%s uses the timeout value '%s' from the minimum interval monitor", action->uuid, value); } } if (value == NULL) { value = pe_pref(data_set->config_hash, "default-action-timeout"); } value_i = crm_get_msec(value); if (value_i < 0) { value_i = 0; } value_i += start_delay; value_ms = crm_itoa(value_i); g_hash_table_replace(action->meta, strdup(field), value_ms); } static xmlNode * find_rsc_op_entry_helper(resource_t * rsc, const char *key, gboolean include_disabled) { int number = 0; gboolean do_retry = TRUE; char *local_key = NULL; const char *name = NULL; const char *value = NULL; const char *interval = NULL; char *match_key = NULL; xmlNode *op = NULL; xmlNode *operation = NULL; retry: for (operation = __xml_first_child(rsc->ops_xml); operation != NULL; operation = __xml_next(operation)) { if (crm_str_eq((const char *)operation->name, "op", TRUE)) { name = crm_element_value(operation, "name"); interval = crm_element_value(operation, XML_LRM_ATTR_INTERVAL); value = crm_element_value(operation, "enabled"); if (!include_disabled && value && crm_is_true(value) == FALSE) { continue; } number = crm_get_interval(interval); if (number < 0) { continue; } match_key = generate_op_key(rsc->id, name, number); if (safe_str_eq(key, match_key)) { op = operation; } free(match_key); if (rsc->clone_name) { match_key = generate_op_key(rsc->clone_name, name, number); if (safe_str_eq(key, match_key)) { op = operation; } free(match_key); } if (op != NULL) { free(local_key); return op; } } } free(local_key); if (do_retry == FALSE) { return NULL; } do_retry = FALSE; if (strstr(key, CRMD_ACTION_MIGRATE) || strstr(key, CRMD_ACTION_MIGRATED)) { local_key = generate_op_key(rsc->id, "migrate", 0); key = local_key; goto retry; } else if (strstr(key, "_notify_")) { local_key = generate_op_key(rsc->id, "notify", 0); key = local_key; goto retry; } return NULL; } xmlNode * find_rsc_op_entry(resource_t * rsc, const char *key) { return find_rsc_op_entry_helper(rsc, key, FALSE); } void print_node(const char *pre_text, node_t * node, gboolean details) { if (node == NULL) { crm_trace("%s%s: ", pre_text == NULL ? "" : pre_text, pre_text == NULL ? "" : ": "); return; } crm_trace("%s%s%sNode %s: (weight=%d, fixed=%s)", pre_text == NULL ? "" : pre_text, pre_text == NULL ? "" : ": ", node->details == NULL ? "error " : node->details->online ? "" : "Unavailable/Unclean ", node->details->uname, node->weight, node->fixed ? "True" : "False"); if (details && node != NULL && node->details != NULL) { char *pe_mutable = strdup("\t\t"); GListPtr gIter = node->details->running_rsc; crm_trace("\t\t===Node Attributes"); g_hash_table_foreach(node->details->attrs, print_str_str, pe_mutable); free(pe_mutable); crm_trace("\t\t=== Resources"); for (; gIter != NULL; gIter = gIter->next) { resource_t *rsc = (resource_t *) gIter->data; print_resource(LOG_DEBUG_4, "\t\t", rsc, FALSE); } } } /* * Used by the HashTable for-loop */ void print_str_str(gpointer key, gpointer value, gpointer user_data) { crm_trace("%s%s %s ==> %s", user_data == NULL ? "" : (char *)user_data, user_data == NULL ? "" : ": ", (char *)key, (char *)value); } void print_resource(int log_level, const char *pre_text, resource_t * rsc, gboolean details) { long options = pe_print_log; if (rsc == NULL) { do_crm_log(log_level - 1, "%s%s: ", pre_text == NULL ? "" : pre_text, pre_text == NULL ? "" : ": "); return; } if (details) { options |= pe_print_details; } rsc->fns->print(rsc, pre_text, options, &log_level); } void pe_free_action(action_t * action) { if (action == NULL) { return; } g_list_free_full(action->actions_before, free); /* action_warpper_t* */ g_list_free_full(action->actions_after, free); /* action_warpper_t* */ if (action->extra) { g_hash_table_destroy(action->extra); } if (action->meta) { g_hash_table_destroy(action->meta); } free(action->task); free(action->uuid); free(action->node); free(action); } GListPtr find_recurring_actions(GListPtr input, node_t * not_on_node) { const char *value = NULL; GListPtr result = NULL; GListPtr gIter = input; CRM_CHECK(input != NULL, return NULL); for (; gIter != NULL; gIter = gIter->next) { action_t *action = (action_t *) gIter->data; value = g_hash_table_lookup(action->meta, XML_LRM_ATTR_INTERVAL); if (value == NULL) { /* skip */ } else if (safe_str_eq(value, "0")) { /* skip */ } else if (safe_str_eq(CRMD_ACTION_CANCEL, action->task)) { /* skip */ } else if (not_on_node == NULL) { crm_trace("(null) Found: %s", action->uuid); result = g_list_prepend(result, action); } else if (action->node == NULL) { /* skip */ } else if (action->node->details != not_on_node->details) { crm_trace("Found: %s", action->uuid); result = g_list_prepend(result, action); } } return result; } enum action_tasks get_complex_task(resource_t * rsc, const char *name, gboolean allow_non_atomic) { enum action_tasks task = text2task(name); if (rsc == NULL) { return task; } else if (allow_non_atomic == FALSE || rsc->variant == pe_native) { switch (task) { case stopped_rsc: case started_rsc: case action_demoted: case action_promoted: crm_trace("Folding %s back into its atomic counterpart for %s", name, rsc->id); return task - 1; break; default: break; } } return task; } action_t * find_first_action(GListPtr input, const char *uuid, const char *task, node_t * on_node) { GListPtr gIter = NULL; CRM_CHECK(uuid || task, return NULL); for (gIter = input; gIter != NULL; gIter = gIter->next) { action_t *action = (action_t *) gIter->data; if (uuid != NULL && safe_str_neq(uuid, action->uuid)) { continue; } else if (task != NULL && safe_str_neq(task, action->task)) { continue; } else if (on_node == NULL) { return action; } else if (action->node == NULL) { continue; } else if (on_node->details == action->node->details) { return action; } } return NULL; } GListPtr find_actions(GListPtr input, const char *key, node_t * on_node) { GListPtr gIter = input; GListPtr result = NULL; CRM_CHECK(key != NULL, return NULL); for (; gIter != NULL; gIter = gIter->next) { action_t *action = (action_t *) gIter->data; crm_trace("Matching %s against %s", key, action->uuid); if (safe_str_neq(key, action->uuid)) { continue; } else if (on_node == NULL) { result = g_list_prepend(result, action); } else if (action->node == NULL) { /* skip */ crm_trace("While looking for %s action on %s, " "found an unallocated one. Assigning" " it to the requested node...", key, on_node->details->uname); action->node = node_copy(on_node); result = g_list_prepend(result, action); } else if (on_node->details == action->node->details) { result = g_list_prepend(result, action); } } return result; } GListPtr find_actions_exact(GListPtr input, const char *key, node_t * on_node) { GListPtr gIter = input; GListPtr result = NULL; CRM_CHECK(key != NULL, return NULL); for (; gIter != NULL; gIter = gIter->next) { action_t *action = (action_t *) gIter->data; crm_trace("Matching %s against %s", key, action->uuid); if (safe_str_neq(key, action->uuid)) { crm_trace("Key mismatch: %s vs. %s", key, action->uuid); continue; } else if (on_node == NULL || action->node == NULL) { crm_trace("on_node=%p, action->node=%p", on_node, action->node); continue; } else if (safe_str_eq(on_node->details->id, action->node->details->id)) { result = g_list_prepend(result, action); } crm_trace("Node mismatch: %s vs. %s", on_node->details->id, action->node->details->id); } return result; } static void resource_node_score(resource_t * rsc, node_t * node, int score, const char *tag) { node_t *match = NULL; if (rsc->children) { GListPtr gIter = rsc->children; for (; gIter != NULL; gIter = gIter->next) { resource_t *child_rsc = (resource_t *) gIter->data; resource_node_score(child_rsc, node, score, tag); } } pe_rsc_trace(rsc, "Setting %s for %s on %s: %d", tag, rsc->id, node->details->uname, score); match = pe_hash_table_lookup(rsc->allowed_nodes, node->details->id); if (match == NULL) { match = node_copy(node); match->weight = merge_weights(score, node->weight); g_hash_table_insert(rsc->allowed_nodes, (gpointer) match->details->id, match); } match->weight = merge_weights(match->weight, score); } void resource_location(resource_t * rsc, node_t * node, int score, const char *tag, pe_working_set_t * data_set) { if (node != NULL) { resource_node_score(rsc, node, score, tag); } else if (data_set != NULL) { GListPtr gIter = data_set->nodes; for (; gIter != NULL; gIter = gIter->next) { node_t *node = (node_t *) gIter->data; resource_node_score(rsc, node, score, tag); } } else { GHashTableIter iter; node_t *node = NULL; g_hash_table_iter_init(&iter, rsc->allowed_nodes); while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) { resource_node_score(rsc, node, score, tag); } } if (node == NULL && score == -INFINITY) { if (rsc->allocated_to) { crm_info("Deallocating %s from %s", rsc->id, rsc->allocated_to->details->uname); free(rsc->allocated_to); rsc->allocated_to = NULL; } } } #define sort_return(an_int, why) do { \ free(a_uuid); \ free(b_uuid); \ crm_trace("%s (%d) %c %s (%d) : %s", \ a_xml_id, a_call_id, an_int>0?'>':an_int<0?'<':'=', \ b_xml_id, b_call_id, why); \ return an_int; \ } while(0) gint sort_op_by_callid(gconstpointer a, gconstpointer b) { int a_call_id = -1; int b_call_id = -1; char *a_uuid = NULL; char *b_uuid = NULL; const xmlNode *xml_a = a; const xmlNode *xml_b = b; const char *a_xml_id = crm_element_value_const(xml_a, XML_ATTR_ID); const char *b_xml_id = crm_element_value_const(xml_b, XML_ATTR_ID); if (safe_str_eq(a_xml_id, b_xml_id)) { /* We have duplicate lrm_rsc_op entries in the status * section which is unliklely to be a good thing * - we can handle it easily enough, but we need to get * to the bottom of why its happening. */ pe_err("Duplicate lrm_rsc_op entries named %s", a_xml_id); sort_return(0, "duplicate"); } crm_element_value_const_int(xml_a, XML_LRM_ATTR_CALLID, &a_call_id); crm_element_value_const_int(xml_b, XML_LRM_ATTR_CALLID, &b_call_id); if (a_call_id == -1 && b_call_id == -1) { /* both are pending ops so it doesnt matter since * stops are never pending */ sort_return(0, "pending"); } else if (a_call_id >= 0 && a_call_id < b_call_id) { sort_return(-1, "call id"); } else if (b_call_id >= 0 && a_call_id > b_call_id) { sort_return(1, "call id"); } else if (b_call_id >= 0 && a_call_id == b_call_id) { /* * The op and last_failed_op are the same * Order on last-rc-change */ int last_a = -1; int last_b = -1; crm_element_value_const_int(xml_a, XML_RSC_OP_LAST_CHANGE, &last_a); crm_element_value_const_int(xml_b, XML_RSC_OP_LAST_CHANGE, &last_b); crm_trace("rc-change: %d vs %d", last_a, last_b); if (last_a >= 0 && last_a < last_b) { sort_return(-1, "rc-change"); } else if (last_b >= 0 && last_a > last_b) { sort_return(1, "rc-change"); } sort_return(0, "rc-change"); } else { /* One of the inputs is a pending operation * Attempt to use XML_ATTR_TRANSITION_MAGIC to determine its age relative to the other */ int a_id = -1; int b_id = -1; int dummy = -1; const char *a_magic = crm_element_value_const(xml_a, XML_ATTR_TRANSITION_MAGIC); const char *b_magic = crm_element_value_const(xml_b, XML_ATTR_TRANSITION_MAGIC); CRM_CHECK(a_magic != NULL && b_magic != NULL, sort_return(0, "No magic")); CRM_CHECK(decode_transition_magic(a_magic, &a_uuid, &a_id, &dummy, &dummy, &dummy, &dummy), sort_return(0, "bad magic a")); CRM_CHECK(decode_transition_magic(b_magic, &b_uuid, &b_id, &dummy, &dummy, &dummy, &dummy), sort_return(0, "bad magic b")); /* try and determin the relative age of the operation... * some pending operations (ie. a start) may have been supuerceeded * by a subsequent stop * * [a|b]_id == -1 means its a shutdown operation and _always_ comes last */ if (safe_str_neq(a_uuid, b_uuid) || a_id == b_id) { /* * some of the logic in here may be redundant... * * if the UUID from the TE doesnt match then one better * be a pending operation. * pending operations dont survive between elections and joins * because we query the LRM directly */ if (b_call_id == -1) { sort_return(-1, "transition + call"); } else if (a_call_id == -1) { sort_return(1, "transition + call"); } } else if ((a_id >= 0 && a_id < b_id) || b_id == -1) { sort_return(-1, "transition"); } else if ((b_id >= 0 && a_id > b_id) || a_id == -1) { sort_return(1, "transition"); } } /* we should never end up here */ CRM_CHECK(FALSE, sort_return(0, "default")); } time_t get_effective_time(pe_working_set_t * data_set) { if(data_set) { if (data_set->now == NULL) { crm_trace("Recording a new 'now'"); data_set->now = crm_time_new(NULL); } return crm_time_get_seconds_since_epoch(data_set->now); } crm_trace("Defaulting to 'now'"); return time(NULL); } struct fail_search { resource_t *rsc; int count; long long last; char *key; }; static void get_failcount_by_prefix(gpointer key_p, gpointer value, gpointer user_data) { struct fail_search *search = user_data; const char *key = key_p; const char *match = strstr(key, search->key); if (match) { if (strstr(key, "last-failure-") == key && (key + 13) == match) { search->last = crm_int_helper(value, NULL); } else if (strstr(key, "fail-count-") == key && (key + 11) == match) { search->count += char2score(value); } } } int get_failcount(node_t * node, resource_t * rsc, time_t *last_failure, pe_working_set_t * data_set) { return get_failcount_full(node, rsc, last_failure, TRUE, data_set); } int get_failcount_full(node_t * node, resource_t * rsc, time_t *last_failure, bool effective, pe_working_set_t * data_set) { char *key = NULL; const char *value = NULL; struct fail_search search = { rsc, 0, 0, NULL }; /* Optimize the "normal" case */ key = crm_concat("fail-count", rsc->clone_name ? rsc->clone_name : rsc->id, '-'); value = g_hash_table_lookup(node->details->attrs, key); search.count = char2score(value); crm_trace("%s = %s", key, value); free(key); if (value) { key = crm_concat("last-failure", rsc->clone_name ? rsc->clone_name : rsc->id, '-'); value = g_hash_table_lookup(node->details->attrs, key); search.last = crm_int_helper(value, NULL); free(key); /* This block is still relevant once we omit anonymous instance numbers * because stopped clones wont have clone_name set */ } else if (is_not_set(rsc->flags, pe_rsc_unique)) { search.rsc = uber_parent(rsc); search.key = clone_strip(rsc->id); g_hash_table_foreach(node->details->attrs, get_failcount_by_prefix, &search); free(search.key); } if (search.count != 0 && search.last != 0 && last_failure) { *last_failure = search.last; } if(search.count && rsc->failure_timeout) { /* Never time-out if blocking failures are configured */ char *xml_name = clone_strip(rsc->id); char *xpath = g_strdup_printf("//primitive[@id='%s']//op[@on-fail='block']", xml_name); xmlXPathObject *xpathObj = xpath_search(rsc->xml, xpath); free(xml_name); free(xpath); if (numXpathResults(xpathObj) > 0) { xmlNode *pref = getXpathResult(xpathObj, 0); pe_warn("Setting %s.failure_timeout=%d in %s conflicts with on-fail=block: ignoring timeout", rsc->id, rsc->failure_timeout, ID(pref)); rsc->failure_timeout = 0; #if 0 /* A good idea? */ } else if (rsc->container == NULL && is_not_set(data_set->flags, pe_flag_stonith_enabled)) { /* In this case, stop.on-fail defaults to block in unpack_operation() */ rsc->failure_timeout = 0; #endif } freeXpathObject(xpathObj); } if (effective && search.count != 0 && search.last != 0 && rsc->failure_timeout) { if (search.last > 0) { time_t now = get_effective_time(data_set); if (now > (search.last + rsc->failure_timeout)) { crm_debug("Failcount for %s on %s has expired (limit was %ds)", search.rsc->id, node->details->uname, rsc->failure_timeout); search.count = 0; } } } if (search.count != 0) { char *score = score2char(search.count); crm_info("%s has failed %s times on %s", search.rsc->id, score, node->details->uname); free(score); } return search.count; } /* If it's a resource container, get its failcount plus all the failcounts of the resources within it */ int get_failcount_all(node_t * node, resource_t * rsc, time_t *last_failure, pe_working_set_t * data_set) { int failcount_all = 0; failcount_all = get_failcount(node, rsc, last_failure, data_set); if (rsc->fillers) { GListPtr gIter = NULL; for (gIter = rsc->fillers; gIter != NULL; gIter = gIter->next) { resource_t *filler = (resource_t *) gIter->data; time_t filler_last_failure = 0; failcount_all += get_failcount(node, filler, &filler_last_failure, data_set); if (last_failure && filler_last_failure > *last_failure) { *last_failure = filler_last_failure; } } if (failcount_all != 0) { char *score = score2char(failcount_all); crm_info("Container %s and the resources within it have failed %s times on %s", rsc->id, score, node->details->uname); free(score); } } return failcount_all; } gboolean get_target_role(resource_t * rsc, enum rsc_role_e * role) { enum rsc_role_e local_role = RSC_ROLE_UNKNOWN; const char *value = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_TARGET_ROLE); CRM_CHECK(role != NULL, return FALSE); if (value == NULL || safe_str_eq("started", value) || safe_str_eq("default", value)) { return FALSE; } local_role = text2role(value); if (local_role == RSC_ROLE_UNKNOWN) { crm_config_err("%s: Unknown value for %s: %s", rsc->id, XML_RSC_ATTR_TARGET_ROLE, value); return FALSE; } else if (local_role > RSC_ROLE_STARTED) { if (uber_parent(rsc)->variant == pe_master) { if (local_role > RSC_ROLE_SLAVE) { /* This is what we'd do anyway, just leave the default to avoid messing up the placement algorithm */ return FALSE; } } else { crm_config_err("%s is not part of a master/slave resource, a %s of '%s' makes no sense", rsc->id, XML_RSC_ATTR_TARGET_ROLE, value); return FALSE; } } *role = local_role; return TRUE; } gboolean order_actions(action_t * lh_action, action_t * rh_action, enum pe_ordering order) { GListPtr gIter = NULL; action_wrapper_t *wrapper = NULL; GListPtr list = NULL; if (order == pe_order_none) { return FALSE; } if (lh_action == NULL || rh_action == NULL) { return FALSE; } crm_trace("Ordering Action %s before %s", lh_action->uuid, rh_action->uuid); /* Filter dups, otherwise update_action_states() has too much work to do */ gIter = lh_action->actions_after; for (; gIter != NULL; gIter = gIter->next) { action_wrapper_t *after = (action_wrapper_t *) gIter->data; if (after->action == rh_action && (after->type & order)) { return FALSE; } } wrapper = calloc(1, sizeof(action_wrapper_t)); wrapper->action = rh_action; wrapper->type = order; list = lh_action->actions_after; list = g_list_prepend(list, wrapper); lh_action->actions_after = list; wrapper = NULL; /* order |= pe_order_implies_then; */ /* order ^= pe_order_implies_then; */ wrapper = calloc(1, sizeof(action_wrapper_t)); wrapper->action = lh_action; wrapper->type = order; list = rh_action->actions_before; list = g_list_prepend(list, wrapper); rh_action->actions_before = list; return TRUE; } action_t * get_pseudo_op(const char *name, pe_working_set_t * data_set) { action_t *op = NULL; const char *op_s = name; GListPtr possible_matches = NULL; possible_matches = find_actions(data_set->actions, name, NULL); if (possible_matches != NULL) { if (g_list_length(possible_matches) > 1) { pe_warn("Action %s exists %d times", name, g_list_length(possible_matches)); } op = g_list_nth_data(possible_matches, 0); g_list_free(possible_matches); } else { op = custom_action(NULL, strdup(op_s), op_s, NULL, TRUE, TRUE, data_set); set_bit(op->flags, pe_action_pseudo); set_bit(op->flags, pe_action_runnable); } return op; } void destroy_ticket(gpointer data) { ticket_t *ticket = data; if (ticket->state) { g_hash_table_destroy(ticket->state); } free(ticket->id); free(ticket); } ticket_t * ticket_new(const char *ticket_id, pe_working_set_t * data_set) { ticket_t *ticket = NULL; if (ticket_id == NULL || strlen(ticket_id) == 0) { return NULL; } if (data_set->tickets == NULL) { data_set->tickets = g_hash_table_new_full(crm_str_hash, g_str_equal, g_hash_destroy_str, destroy_ticket); } ticket = g_hash_table_lookup(data_set->tickets, ticket_id); if (ticket == NULL) { ticket = calloc(1, sizeof(ticket_t)); if (ticket == NULL) { crm_err("Cannot allocate ticket '%s'", ticket_id); return NULL; } crm_trace("Creaing ticket entry for %s", ticket_id); ticket->id = strdup(ticket_id); ticket->granted = FALSE; ticket->last_granted = -1; ticket->standby = FALSE; ticket->state = g_hash_table_new_full(crm_str_hash, g_str_equal, g_hash_destroy_str, g_hash_destroy_str); g_hash_table_insert(data_set->tickets, strdup(ticket->id), ticket); } return ticket; } op_digest_cache_t * rsc_action_digest_cmp(resource_t * rsc, xmlNode * xml_op, node_t * node, pe_working_set_t * data_set) { op_digest_cache_t *data = NULL; GHashTable *local_rsc_params = NULL; action_t *action = NULL; char *key = NULL; int interval = 0; const char *op_id = ID(xml_op); const char *interval_s = crm_element_value(xml_op, XML_LRM_ATTR_INTERVAL); const char *task = crm_element_value(xml_op, XML_LRM_ATTR_TASK); const char *digest_all; const char *digest_restart; const char *restart_list; const char *op_version; data = g_hash_table_lookup(node->details->digest_cache, op_id); if (data) { return data; } data = calloc(1, sizeof(op_digest_cache_t)); digest_all = crm_element_value(xml_op, XML_LRM_ATTR_OP_DIGEST); digest_restart = crm_element_value(xml_op, XML_LRM_ATTR_RESTART_DIGEST); restart_list = crm_element_value(xml_op, XML_LRM_ATTR_OP_RESTART); op_version = crm_element_value(xml_op, XML_ATTR_CRM_VERSION); /* key is freed in custom_action */ interval = crm_parse_int(interval_s, "0"); key = generate_op_key(rsc->id, task, interval); action = custom_action(rsc, key, task, node, TRUE, FALSE, data_set); key = NULL; local_rsc_params = g_hash_table_new_full(crm_str_hash, g_str_equal, g_hash_destroy_str, g_hash_destroy_str); get_rsc_attributes(local_rsc_params, rsc, node, data_set); data->params_all = create_xml_node(NULL, XML_TAG_PARAMS); g_hash_table_foreach(local_rsc_params, hash2field, data->params_all); g_hash_table_foreach(action->extra, hash2field, data->params_all); g_hash_table_foreach(rsc->parameters, hash2field, data->params_all); g_hash_table_foreach(action->meta, hash2metafield, data->params_all); filter_action_parameters(data->params_all, op_version); data->digest_all_calc = calculate_operation_digest(data->params_all, op_version); if (digest_restart) { data->params_restart = copy_xml(data->params_all); if (restart_list) { filter_reload_parameters(data->params_restart, restart_list); } data->digest_restart_calc = calculate_operation_digest(data->params_restart, op_version); } if (digest_restart && strcmp(data->digest_restart_calc, digest_restart) != 0) { data->rc = RSC_DIGEST_RESTART; } else if (digest_all == NULL) { /* it is unknown what the previous op digest was */ data->rc = RSC_DIGEST_UNKNOWN; } else if (strcmp(digest_all, data->digest_all_calc) != 0) { data->rc = RSC_DIGEST_ALL; } g_hash_table_insert(node->details->digest_cache, strdup(op_id), data); g_hash_table_destroy(local_rsc_params); pe_free_action(action); return data; } + +const char *rsc_printable_id(resource_t *rsc) +{ + if (is_not_set(rsc->flags, pe_rsc_unique)) { + return ID(rsc->xml); + } + return rsc->id; +} diff --git a/pengine/test10/bug-5059.summary b/pengine/test10/bug-5059.summary index e8c282a136..b93e4e63f1 100644 --- a/pengine/test10/bug-5059.summary +++ b/pengine/test10/bug-5059.summary @@ -1,79 +1,79 @@ Current cluster status: Node gluster03.h: standby Online: [ gluster01.h gluster02.h ] OFFLINE: [ gluster04.h ] Master/Slave Set: ms_stateful [g_stateful] Resource Group: g_stateful:0 - p_stateful1:0 (ocf::pacemaker:Stateful): Started gluster01.h - p_stateful2:0 (ocf::pacemaker:Stateful): Stopped + p_stateful1 (ocf::pacemaker:Stateful): Started gluster01.h + p_stateful2 (ocf::pacemaker:Stateful): Stopped Resource Group: g_stateful:1 - p_stateful1:1 (ocf::pacemaker:Stateful): Started gluster02.h - p_stateful2:1 (ocf::pacemaker:Stateful): Stopped + p_stateful1 (ocf::pacemaker:Stateful): Started gluster02.h + p_stateful2 (ocf::pacemaker:Stateful): Stopped Stopped: [ gluster03.h gluster04.h ] Clone Set: c_dummy [p_dummy1] Started: [ gluster01.h gluster02.h ] Stopped: [ gluster03.h gluster04.h ] Transition Summary: * Promote p_stateful1:0 (Slave -> Master gluster01.h) * Start p_stateful2:0 (gluster01.h) * Promote p_stateful2:0 (Stopped -> Master gluster01.h) * Start p_stateful2:1 (gluster02.h) Executing cluster transition: * Pseudo action: ms_stateful_pre_notify_start_0 * Resource action: iptest delete on gluster02.h * Resource action: ipsrc2 delete on gluster02.h * Resource action: p_stateful1:0 notify on gluster01.h * Resource action: p_stateful1:1 notify on gluster02.h * Pseudo action: ms_stateful_confirmed-pre_notify_start_0 * Pseudo action: ms_stateful_start_0 * Pseudo action: g_stateful:0_start_0 * Resource action: p_stateful2:0 start on gluster01.h * Pseudo action: g_stateful:1_start_0 * Resource action: p_stateful2:1 start on gluster02.h * Pseudo action: g_stateful:0_running_0 * Pseudo action: g_stateful:1_running_0 * Pseudo action: ms_stateful_running_0 * Pseudo action: ms_stateful_post_notify_running_0 * Resource action: p_stateful1:0 notify on gluster01.h * Resource action: p_stateful2:0 notify on gluster01.h * Resource action: p_stateful1:1 notify on gluster02.h * Resource action: p_stateful2:1 notify on gluster02.h * Pseudo action: ms_stateful_confirmed-post_notify_running_0 * Pseudo action: ms_stateful_pre_notify_promote_0 * Resource action: p_stateful1:0 notify on gluster01.h * Resource action: p_stateful2:0 notify on gluster01.h * Resource action: p_stateful1:1 notify on gluster02.h * Resource action: p_stateful2:1 notify on gluster02.h * Pseudo action: ms_stateful_confirmed-pre_notify_promote_0 * Pseudo action: ms_stateful_promote_0 * Pseudo action: g_stateful:0_promote_0 * Resource action: p_stateful1:0 promote on gluster01.h * Resource action: p_stateful2:0 promote on gluster01.h * Pseudo action: g_stateful:0_promoted_0 * Pseudo action: ms_stateful_promoted_0 * Pseudo action: ms_stateful_post_notify_promoted_0 * Resource action: p_stateful1:0 notify on gluster01.h * Resource action: p_stateful2:0 notify on gluster01.h * Resource action: p_stateful1:1 notify on gluster02.h * Resource action: p_stateful2:1 notify on gluster02.h * Pseudo action: ms_stateful_confirmed-post_notify_promoted_0 * Resource action: p_stateful1:1 monitor=10000 on gluster02.h * Resource action: p_stateful2:1 monitor=10000 on gluster02.h Revised cluster status: Node gluster03.h: standby Online: [ gluster01.h gluster02.h ] OFFLINE: [ gluster04.h ] Master/Slave Set: ms_stateful [g_stateful] Masters: [ gluster01.h ] Slaves: [ gluster02.h ] Stopped: [ gluster03.h gluster04.h ] Clone Set: c_dummy [p_dummy1] Started: [ gluster01.h gluster02.h ] Stopped: [ gluster03.h gluster04.h ] diff --git a/pengine/test10/bug-5140-require-all-false.summary b/pengine/test10/bug-5140-require-all-false.summary index 7cb1a8f452..b9d38bbeca 100644 --- a/pengine/test10/bug-5140-require-all-false.summary +++ b/pengine/test10/bug-5140-require-all-false.summary @@ -1,80 +1,80 @@ Current cluster status: Node hex-1: standby Node hex-2: standby Node hex-3: OFFLINE (standby) fencing (stonith:external/sbd): Stopped Clone Set: baseclone [basegrp] Resource Group: basegrp:0 - dlm:0 (ocf::pacemaker:controld): Started hex-2 - clvmd:0 (ocf::lvm2:clvmd): Started hex-2 - o2cb:0 (ocf::ocfs2:o2cb): Started hex-2 - vg1:0 (ocf::heartbeat:LVM): Stopped - fs-ocfs-1:0 (ocf::heartbeat:Filesystem): Stopped + dlm (ocf::pacemaker:controld): Started hex-2 + clvmd (ocf::lvm2:clvmd): Started hex-2 + o2cb (ocf::ocfs2:o2cb): Started hex-2 + vg1 (ocf::heartbeat:LVM): Stopped + fs-ocfs-1 (ocf::heartbeat:Filesystem): Stopped Stopped: [ hex-1 hex-3 ] fs-xfs-1 (ocf::heartbeat:Filesystem): Stopped Clone Set: fs2 [fs-ocfs-2] Stopped: [ hex-1 hex-2 hex-3 ] Master/Slave Set: ms-r0 [drbd-r0] Stopped: [ hex-1 hex-2 hex-3 ] Master/Slave Set: ms-r1 [drbd-r1] Stopped: [ hex-1 hex-2 hex-3 ] Resource Group: md0-group md0 (ocf::heartbeat:Raid1): Stopped vg-md0 (ocf::heartbeat:LVM): Stopped fs-md0 (ocf::heartbeat:Filesystem): Stopped dummy1 (ocf::heartbeat:Delay): Stopped dummy3 (ocf::heartbeat:Delay): Stopped dummy4 (ocf::heartbeat:Delay): Stopped dummy5 (ocf::heartbeat:Delay): Stopped dummy6 (ocf::heartbeat:Delay): Stopped Resource Group: r0-group fs-r0 (ocf::heartbeat:Filesystem): Stopped dummy2 (ocf::heartbeat:Delay): Stopped cluster-md0 (ocf::heartbeat:Raid1): Stopped Transition Summary: * Stop dlm:0 (hex-2) * Stop clvmd:0 (hex-2) * Stop o2cb:0 (hex-2) Executing cluster transition: * Pseudo action: baseclone_stop_0 * Pseudo action: basegrp:0_stop_0 * Resource action: o2cb stop on hex-2 * Resource action: clvmd stop on hex-2 * Resource action: dlm stop on hex-2 * Pseudo action: all_stopped * Pseudo action: basegrp:0_stopped_0 * Pseudo action: baseclone_stopped_0 Revised cluster status: Node hex-1: standby Node hex-2: standby Node hex-3: OFFLINE (standby) fencing (stonith:external/sbd): Stopped Clone Set: baseclone [basegrp] Stopped: [ hex-1 hex-2 hex-3 ] fs-xfs-1 (ocf::heartbeat:Filesystem): Stopped Clone Set: fs2 [fs-ocfs-2] Stopped: [ hex-1 hex-2 hex-3 ] Master/Slave Set: ms-r0 [drbd-r0] Stopped: [ hex-1 hex-2 hex-3 ] Master/Slave Set: ms-r1 [drbd-r1] Stopped: [ hex-1 hex-2 hex-3 ] Resource Group: md0-group md0 (ocf::heartbeat:Raid1): Stopped vg-md0 (ocf::heartbeat:LVM): Stopped fs-md0 (ocf::heartbeat:Filesystem): Stopped dummy1 (ocf::heartbeat:Delay): Stopped dummy3 (ocf::heartbeat:Delay): Stopped dummy4 (ocf::heartbeat:Delay): Stopped dummy5 (ocf::heartbeat:Delay): Stopped dummy6 (ocf::heartbeat:Delay): Stopped Resource Group: r0-group fs-r0 (ocf::heartbeat:Filesystem): Stopped dummy2 (ocf::heartbeat:Delay): Stopped cluster-md0 (ocf::heartbeat:Raid1): Stopped diff --git a/pengine/test10/bug-lf-2422.summary b/pengine/test10/bug-lf-2422.summary index 566460a4d0..760fc2baf4 100644 --- a/pengine/test10/bug-lf-2422.summary +++ b/pengine/test10/bug-lf-2422.summary @@ -1,80 +1,80 @@ Current cluster status: Online: [ qa-suse-1 qa-suse-2 qa-suse-3 qa-suse-4 ] sbd_stonith (stonith:external/sbd): Started qa-suse-2 Clone Set: c-o2stage [o2stage] Started: [ qa-suse-1 qa-suse-2 qa-suse-3 qa-suse-4 ] Clone Set: c-ocfs [ocfs] Started: [ qa-suse-1 qa-suse-2 qa-suse-3 qa-suse-4 ] Transition Summary: * Stop o2cb:0 (qa-suse-1) * Stop cmirror:0 (qa-suse-1) * Stop o2cb:1 (qa-suse-4) * Stop cmirror:1 (qa-suse-4) * Stop o2cb:2 (qa-suse-3) * Stop cmirror:2 (qa-suse-3) * Stop o2cb:3 (qa-suse-2) * Stop cmirror:3 (qa-suse-2) * Stop ocfs:0 (qa-suse-1) * Stop ocfs:1 (qa-suse-4) * Stop ocfs:2 (qa-suse-3) * Stop ocfs:3 (qa-suse-2) Executing cluster transition: * Resource action: sbd_stonith monitor=15000 on qa-suse-2 * Pseudo action: c-ocfs_stop_0 * Resource action: ocfs:3 stop on qa-suse-2 * Resource action: ocfs:2 stop on qa-suse-3 * Resource action: ocfs:0 stop on qa-suse-4 * Resource action: ocfs:1 stop on qa-suse-1 * Pseudo action: c-ocfs_stopped_0 * Pseudo action: c-o2stage_stop_0 * Pseudo action: o2stage:0_stop_0 * Resource action: cmirror:1 stop on qa-suse-1 * Pseudo action: o2stage:1_stop_0 * Resource action: cmirror:0 stop on qa-suse-4 * Pseudo action: o2stage:2_stop_0 * Resource action: cmirror:2 stop on qa-suse-3 * Pseudo action: o2stage:3_stop_0 * Resource action: cmirror:3 stop on qa-suse-2 * Resource action: o2cb:1 stop on qa-suse-1 * Resource action: o2cb:0 stop on qa-suse-4 * Resource action: o2cb:2 stop on qa-suse-3 * Resource action: o2cb:3 stop on qa-suse-2 * Pseudo action: all_stopped * Pseudo action: o2stage:0_stopped_0 * Pseudo action: o2stage:1_stopped_0 * Pseudo action: o2stage:2_stopped_0 * Pseudo action: o2stage:3_stopped_0 * Pseudo action: c-o2stage_stopped_0 Revised cluster status: Online: [ qa-suse-1 qa-suse-2 qa-suse-3 qa-suse-4 ] sbd_stonith (stonith:external/sbd): Started qa-suse-2 Clone Set: c-o2stage [o2stage] Resource Group: o2stage:0 - dlm:0 (ocf::pacemaker:controld): Started qa-suse-1 - clvm:0 (ocf::lvm2:clvmd): Started qa-suse-1 - o2cb:0 (ocf::ocfs2:o2cb): Stopped - cmirror:0 (ocf::lvm2:cmirrord): Stopped + dlm (ocf::pacemaker:controld): Started qa-suse-1 + clvm (ocf::lvm2:clvmd): Started qa-suse-1 + o2cb (ocf::ocfs2:o2cb): Stopped + cmirror (ocf::lvm2:cmirrord): Stopped Resource Group: o2stage:1 - dlm:1 (ocf::pacemaker:controld): Started qa-suse-4 - clvm:1 (ocf::lvm2:clvmd): Started qa-suse-4 - o2cb:1 (ocf::ocfs2:o2cb): Stopped - cmirror:1 (ocf::lvm2:cmirrord): Stopped + dlm (ocf::pacemaker:controld): Started qa-suse-4 + clvm (ocf::lvm2:clvmd): Started qa-suse-4 + o2cb (ocf::ocfs2:o2cb): Stopped + cmirror (ocf::lvm2:cmirrord): Stopped Resource Group: o2stage:2 - dlm:2 (ocf::pacemaker:controld): Started qa-suse-3 - clvm:2 (ocf::lvm2:clvmd): Started qa-suse-3 - o2cb:2 (ocf::ocfs2:o2cb): Stopped - cmirror:2 (ocf::lvm2:cmirrord): Stopped + dlm (ocf::pacemaker:controld): Started qa-suse-3 + clvm (ocf::lvm2:clvmd): Started qa-suse-3 + o2cb (ocf::ocfs2:o2cb): Stopped + cmirror (ocf::lvm2:cmirrord): Stopped Resource Group: o2stage:3 - dlm:3 (ocf::pacemaker:controld): Started qa-suse-2 - clvm:3 (ocf::lvm2:clvmd): Started qa-suse-2 - o2cb:3 (ocf::ocfs2:o2cb): Stopped - cmirror:3 (ocf::lvm2:cmirrord): Stopped + dlm (ocf::pacemaker:controld): Started qa-suse-2 + clvm (ocf::lvm2:clvmd): Started qa-suse-2 + o2cb (ocf::ocfs2:o2cb): Stopped + cmirror (ocf::lvm2:cmirrord): Stopped Clone Set: c-ocfs [ocfs] Stopped: [ qa-suse-1 qa-suse-2 qa-suse-3 qa-suse-4 ] diff --git a/pengine/test10/bug-lf-2508.summary b/pengine/test10/bug-lf-2508.summary index 9754d558fa..4435cedcca 100644 --- a/pengine/test10/bug-lf-2508.summary +++ b/pengine/test10/bug-lf-2508.summary @@ -1,102 +1,102 @@ Current cluster status: Node srv02 (71085d5e-1c63-49e0-8c8c-400d610b4182): UNCLEAN (offline) Online: [ srv01 srv03 srv04 ] Resource Group: Group01 Dummy01 (ocf::heartbeat:Dummy): Stopped Resource Group: Group02 Dummy02 (ocf::heartbeat:Dummy): Started srv02 Resource Group: Group03 Dummy03 (ocf::heartbeat:Dummy): Started srv03 Clone Set: clnStonith1 [grpStonith1] Started: [ srv02 srv03 srv04 ] Stopped: [ srv01 ] Clone Set: clnStonith2 [grpStonith2] Started: [ srv01 srv03 srv04 ] Stopped: [ srv02 ] Clone Set: clnStonith3 [grpStonith3] Resource Group: grpStonith3:1 - prmStonith3-1:1 (stonith:external/stonith-helper): Started srv01 - prmStonith3-3:1 (stonith:external/ssh): Stopped + prmStonith3-1 (stonith:external/stonith-helper): Started srv01 + prmStonith3-3 (stonith:external/ssh): Stopped Started: [ srv02 srv04 ] Stopped: [ srv03 ] Clone Set: clnStonith4 [grpStonith4] Started: [ srv01 srv02 srv03 ] Stopped: [ srv04 ] Transition Summary: * Start Dummy01 (srv01) * Move Dummy02 (Started srv02 -> srv04) * Stop prmStonith1-1:1 (srv02) * Stop prmStonith1-3:1 (srv02) * Stop prmStonith3-1:0 (srv02) * Stop prmStonith3-3:0 (srv02) * Start prmStonith3-3:1 (srv01) * Stop prmStonith4-1:1 (srv02) * Stop prmStonith4-3:1 (srv02) Executing cluster transition: * Pseudo action: Group01_start_0 * Resource action: prmStonith3-1:1 monitor=3600000 on srv01 * Fencing srv02 * Pseudo action: stonith_complete * Resource action: Dummy01 start on srv01 * Pseudo action: Group02_stop_0 * Pseudo action: Dummy02_stop_0 * Pseudo action: clnStonith1_stop_0 * Pseudo action: clnStonith3_stop_0 * Pseudo action: clnStonith4_stop_0 * Pseudo action: Group01_running_0 * Resource action: Dummy01 monitor=10000 on srv01 * Pseudo action: Group02_stopped_0 * Pseudo action: Group02_start_0 * Resource action: Dummy02 start on srv04 * Pseudo action: grpStonith1:1_stop_0 * Pseudo action: prmStonith1-3:1_stop_0 * Pseudo action: grpStonith3:0_stop_0 * Pseudo action: prmStonith3-3:1_stop_0 * Pseudo action: grpStonith4:1_stop_0 * Pseudo action: prmStonith4-3:1_stop_0 * Pseudo action: Group02_running_0 * Resource action: Dummy02 monitor=10000 on srv04 * Pseudo action: prmStonith1-1:1_stop_0 * Pseudo action: prmStonith3-1:1_stop_0 * Pseudo action: prmStonith4-1:1_stop_0 * Pseudo action: all_stopped * Pseudo action: grpStonith1:1_stopped_0 * Pseudo action: clnStonith1_stopped_0 * Pseudo action: grpStonith3:0_stopped_0 * Pseudo action: clnStonith3_stopped_0 * Pseudo action: clnStonith3_start_0 * Pseudo action: grpStonith4:1_stopped_0 * Pseudo action: clnStonith4_stopped_0 * Pseudo action: grpStonith3:1_start_0 * Resource action: prmStonith3-3:1 start on srv01 * Pseudo action: grpStonith3:1_running_0 * Resource action: prmStonith3-3:1 monitor=3600000 on srv01 * Pseudo action: clnStonith3_running_0 Revised cluster status: Online: [ srv01 srv03 srv04 ] OFFLINE: [ srv02 ] Resource Group: Group01 Dummy01 (ocf::heartbeat:Dummy): Started srv01 Resource Group: Group02 Dummy02 (ocf::heartbeat:Dummy): Started srv04 Resource Group: Group03 Dummy03 (ocf::heartbeat:Dummy): Started srv03 Clone Set: clnStonith1 [grpStonith1] Started: [ srv03 srv04 ] Stopped: [ srv01 srv02 ] Clone Set: clnStonith2 [grpStonith2] Started: [ srv01 srv03 srv04 ] Stopped: [ srv02 ] Clone Set: clnStonith3 [grpStonith3] Started: [ srv01 srv04 ] Stopped: [ srv02 srv03 ] Clone Set: clnStonith4 [grpStonith4] Started: [ srv01 srv03 ] Stopped: [ srv02 srv04 ] diff --git a/pengine/test10/bug-lf-2619.summary b/pengine/test10/bug-lf-2619.summary index 00cb069614..ad94dd4aa7 100644 --- a/pengine/test10/bug-lf-2619.summary +++ b/pengine/test10/bug-lf-2619.summary @@ -1,99 +1,99 @@ Current cluster status: Online: [ act1 act2 act3 sby1 sby2 ] Resource Group: grpPostgreSQLDB1 prmExPostgreSQLDB1 (ocf::pacemaker:Dummy): Started act1 prmFsPostgreSQLDB1-1 (ocf::pacemaker:Dummy): Started act1 prmFsPostgreSQLDB1-2 (ocf::pacemaker:Dummy): Started act1 prmFsPostgreSQLDB1-3 (ocf::pacemaker:Dummy): Started act1 prmIpPostgreSQLDB1 (ocf::pacemaker:Dummy): Started act1 prmApPostgreSQLDB1 (ocf::pacemaker:Dummy): Started act1 Resource Group: grpPostgreSQLDB2 prmExPostgreSQLDB2 (ocf::pacemaker:Dummy): Started act2 prmFsPostgreSQLDB2-1 (ocf::pacemaker:Dummy): Started act2 prmFsPostgreSQLDB2-2 (ocf::pacemaker:Dummy): Started act2 prmFsPostgreSQLDB2-3 (ocf::pacemaker:Dummy): Started act2 prmIpPostgreSQLDB2 (ocf::pacemaker:Dummy): Started act2 prmApPostgreSQLDB2 (ocf::pacemaker:Dummy): Started act2 Resource Group: grpPostgreSQLDB3 prmExPostgreSQLDB3 (ocf::pacemaker:Dummy): Started act3 prmFsPostgreSQLDB3-1 (ocf::pacemaker:Dummy): Started act3 prmFsPostgreSQLDB3-2 (ocf::pacemaker:Dummy): Started act3 prmFsPostgreSQLDB3-3 (ocf::pacemaker:Dummy): Started act3 prmIpPostgreSQLDB3 (ocf::pacemaker:Dummy): Started act3 prmApPostgreSQLDB3 (ocf::pacemaker:Dummy): Started act3 Clone Set: clnPingd [prmPingd] - prmPingd:0 (ocf::pacemaker:ping): Started act1 FAILED + prmPingd (ocf::pacemaker:ping): Started act1 FAILED Started: [ act2 act3 sby1 sby2 ] Transition Summary: * Move prmExPostgreSQLDB1 (Started act1 -> sby1) * Move prmFsPostgreSQLDB1-1 (Started act1 -> sby1) * Move prmFsPostgreSQLDB1-2 (Started act1 -> sby1) * Move prmFsPostgreSQLDB1-3 (Started act1 -> sby1) * Move prmIpPostgreSQLDB1 (Started act1 -> sby1) * Move prmApPostgreSQLDB1 (Started act1 -> sby1) * Stop prmPingd:0 (act1) Executing cluster transition: * Pseudo action: grpPostgreSQLDB1_stop_0 * Resource action: prmApPostgreSQLDB1 stop on act1 * Pseudo action: load_stopped_sby2 * Pseudo action: load_stopped_sby1 * Pseudo action: load_stopped_act3 * Pseudo action: load_stopped_act2 * Resource action: prmIpPostgreSQLDB1 stop on act1 * Resource action: prmFsPostgreSQLDB1-3 stop on act1 * Resource action: prmFsPostgreSQLDB1-2 stop on act1 * Resource action: prmFsPostgreSQLDB1-1 stop on act1 * Resource action: prmExPostgreSQLDB1 stop on act1 * Pseudo action: load_stopped_act1 * Pseudo action: grpPostgreSQLDB1_stopped_0 * Pseudo action: grpPostgreSQLDB1_start_0 * Resource action: prmExPostgreSQLDB1 start on sby1 * Resource action: prmFsPostgreSQLDB1-1 start on sby1 * Resource action: prmFsPostgreSQLDB1-2 start on sby1 * Resource action: prmFsPostgreSQLDB1-3 start on sby1 * Resource action: prmIpPostgreSQLDB1 start on sby1 * Resource action: prmApPostgreSQLDB1 start on sby1 * Pseudo action: clnPingd_stop_0 * Pseudo action: grpPostgreSQLDB1_running_0 * Resource action: prmExPostgreSQLDB1 monitor=5000 on sby1 * Resource action: prmFsPostgreSQLDB1-1 monitor=5000 on sby1 * Resource action: prmFsPostgreSQLDB1-2 monitor=5000 on sby1 * Resource action: prmFsPostgreSQLDB1-3 monitor=5000 on sby1 * Resource action: prmIpPostgreSQLDB1 monitor=5000 on sby1 * Resource action: prmApPostgreSQLDB1 monitor=5000 on sby1 * Resource action: prmPingd:0 stop on act1 * Pseudo action: clnPingd_stopped_0 * Pseudo action: all_stopped Revised cluster status: Online: [ act1 act2 act3 sby1 sby2 ] Resource Group: grpPostgreSQLDB1 prmExPostgreSQLDB1 (ocf::pacemaker:Dummy): Started sby1 prmFsPostgreSQLDB1-1 (ocf::pacemaker:Dummy): Started sby1 prmFsPostgreSQLDB1-2 (ocf::pacemaker:Dummy): Started sby1 prmFsPostgreSQLDB1-3 (ocf::pacemaker:Dummy): Started sby1 prmIpPostgreSQLDB1 (ocf::pacemaker:Dummy): Started sby1 prmApPostgreSQLDB1 (ocf::pacemaker:Dummy): Started sby1 Resource Group: grpPostgreSQLDB2 prmExPostgreSQLDB2 (ocf::pacemaker:Dummy): Started act2 prmFsPostgreSQLDB2-1 (ocf::pacemaker:Dummy): Started act2 prmFsPostgreSQLDB2-2 (ocf::pacemaker:Dummy): Started act2 prmFsPostgreSQLDB2-3 (ocf::pacemaker:Dummy): Started act2 prmIpPostgreSQLDB2 (ocf::pacemaker:Dummy): Started act2 prmApPostgreSQLDB2 (ocf::pacemaker:Dummy): Started act2 Resource Group: grpPostgreSQLDB3 prmExPostgreSQLDB3 (ocf::pacemaker:Dummy): Started act3 prmFsPostgreSQLDB3-1 (ocf::pacemaker:Dummy): Started act3 prmFsPostgreSQLDB3-2 (ocf::pacemaker:Dummy): Started act3 prmFsPostgreSQLDB3-3 (ocf::pacemaker:Dummy): Started act3 prmIpPostgreSQLDB3 (ocf::pacemaker:Dummy): Started act3 prmApPostgreSQLDB3 (ocf::pacemaker:Dummy): Started act3 Clone Set: clnPingd [prmPingd] Started: [ act2 act3 sby1 sby2 ] Stopped: [ act1 ] diff --git a/pengine/test10/bug-suse-707150.summary b/pengine/test10/bug-suse-707150.summary index f9414a4d7d..6d1fcdf8b6 100644 --- a/pengine/test10/bug-suse-707150.summary +++ b/pengine/test10/bug-suse-707150.summary @@ -1,72 +1,72 @@ Current cluster status: Online: [ hex-0 hex-9 ] OFFLINE: [ hex-7 hex-8 ] vm-00 (ocf::heartbeat:Xen): Stopped Clone Set: base-clone [base-group] Resource Group: base-group:0 - dlm:0 (ocf::pacemaker:controld): Started hex-0 - o2cb:0 (ocf::ocfs2:o2cb): Stopped - clvm:0 (ocf::lvm2:clvmd): Stopped - cmirrord:0 (ocf::lvm2:cmirrord): Stopped - vg1:0 (ocf::heartbeat:LVM): Stopped - ocfs2-1:0 (ocf::heartbeat:Filesystem): Stopped + dlm (ocf::pacemaker:controld): Started hex-0 + o2cb (ocf::ocfs2:o2cb): Stopped + clvm (ocf::lvm2:clvmd): Stopped + cmirrord (ocf::lvm2:cmirrord): Stopped + vg1 (ocf::heartbeat:LVM): Stopped + ocfs2-1 (ocf::heartbeat:Filesystem): Stopped Stopped: [ hex-7 hex-8 hex-9 ] vm-01 (ocf::heartbeat:Xen): Stopped fencing-sbd (stonith:external/sbd): Started hex-9 dummy1 (ocf::heartbeat:Dummy): Started hex-0 Transition Summary: * Start o2cb:0 (hex-0) * Start clvm:0 (hex-0) * Start cmirrord:0 (hex-0) * Start dlm:1 (hex-9) * Start o2cb:1 (hex-9) * Start clvm:1 (hex-9) * Start cmirrord:1 (hex-9) * Start vm-01 (hex-9 - blocked) Executing cluster transition: * Resource action: vg1:1 monitor on hex-9 * Pseudo action: base-clone_start_0 * Pseudo action: probe_complete * Pseudo action: load_stopped_hex-9 * Pseudo action: load_stopped_hex-8 * Pseudo action: load_stopped_hex-7 * Pseudo action: load_stopped_hex-0 * Pseudo action: base-group:0_start_0 * Resource action: o2cb:0 start on hex-0 * Resource action: clvm:0 start on hex-0 * Resource action: cmirrord:0 start on hex-0 * Pseudo action: base-group:1_start_0 * Resource action: dlm:1 start on hex-9 * Resource action: o2cb:1 start on hex-9 * Resource action: clvm:1 start on hex-9 * Resource action: cmirrord:1 start on hex-9 Revised cluster status: Online: [ hex-0 hex-9 ] OFFLINE: [ hex-7 hex-8 ] vm-00 (ocf::heartbeat:Xen): Stopped Clone Set: base-clone [base-group] Resource Group: base-group:0 - dlm:0 (ocf::pacemaker:controld): Started hex-0 - o2cb:0 (ocf::ocfs2:o2cb): Started hex-0 - clvm:0 (ocf::lvm2:clvmd): Started hex-0 - cmirrord:0 (ocf::lvm2:cmirrord): Started hex-0 - vg1:0 (ocf::heartbeat:LVM): Stopped - ocfs2-1:0 (ocf::heartbeat:Filesystem): Stopped + dlm (ocf::pacemaker:controld): Started hex-0 + o2cb (ocf::ocfs2:o2cb): Started hex-0 + clvm (ocf::lvm2:clvmd): Started hex-0 + cmirrord (ocf::lvm2:cmirrord): Started hex-0 + vg1 (ocf::heartbeat:LVM): Stopped + ocfs2-1 (ocf::heartbeat:Filesystem): Stopped Resource Group: base-group:1 - dlm:1 (ocf::pacemaker:controld): Started hex-9 - o2cb:1 (ocf::ocfs2:o2cb): Started hex-9 - clvm:1 (ocf::lvm2:clvmd): Started hex-9 - cmirrord:1 (ocf::lvm2:cmirrord): Started hex-9 - vg1:1 (ocf::heartbeat:LVM): Stopped - ocfs2-1:1 (ocf::heartbeat:Filesystem): Stopped + dlm (ocf::pacemaker:controld): Started hex-9 + o2cb (ocf::ocfs2:o2cb): Started hex-9 + clvm (ocf::lvm2:clvmd): Started hex-9 + cmirrord (ocf::lvm2:cmirrord): Started hex-9 + vg1 (ocf::heartbeat:LVM): Stopped + ocfs2-1 (ocf::heartbeat:Filesystem): Stopped Stopped: [ hex-7 hex-8 ] vm-01 (ocf::heartbeat:Xen): Stopped fencing-sbd (stonith:external/sbd): Started hex-9 dummy1 (ocf::heartbeat:Dummy): Started hex-0 diff --git a/pengine/test10/clone-anon-dup.summary b/pengine/test10/clone-anon-dup.summary index a93cca07aa..bffbf15623 100644 --- a/pengine/test10/clone-anon-dup.summary +++ b/pengine/test10/clone-anon-dup.summary @@ -1,37 +1,37 @@ Current cluster status: Online: [ wc01 wc02 wc03 ] stonith-1 (stonith:dummy): Stopped Clone Set: clone_webservice [group_webservice] Resource Group: group_webservice:2 - fs_www:2 (ocf::heartbeat:Filesystem): ORPHANED Stopped - apache2:2 (ocf::heartbeat:apache): ORPHANED Started wc02 + fs_www (ocf::heartbeat:Filesystem): ORPHANED Stopped + apache2 (ocf::heartbeat:apache): ORPHANED Started wc02 Started: [ wc01 wc02 ] Stopped: [ wc03 ] Transition Summary: * Start stonith-1 (wc01) * Stop apache2:2 (wc02) Executing cluster transition: * Resource action: stonith-1 monitor on wc03 * Resource action: stonith-1 monitor on wc02 * Resource action: stonith-1 monitor on wc01 * Pseudo action: clone_webservice_stop_0 * Pseudo action: probe_complete * Resource action: stonith-1 start on wc01 * Pseudo action: group_webservice:2_stop_0 * Resource action: apache2:0 stop on wc02 * Pseudo action: all_stopped * Pseudo action: group_webservice:2_stopped_0 * Pseudo action: clone_webservice_stopped_0 Revised cluster status: Online: [ wc01 wc02 wc03 ] stonith-1 (stonith:dummy): Started wc01 Clone Set: clone_webservice [group_webservice] Started: [ wc01 wc02 ] Stopped: [ wc03 ] diff --git a/pengine/test10/clone-anon-failcount.summary b/pengine/test10/clone-anon-failcount.summary index 44b8d36208..7e899b351a 100644 --- a/pengine/test10/clone-anon-failcount.summary +++ b/pengine/test10/clone-anon-failcount.summary @@ -1,118 +1,118 @@ Current cluster status: Online: [ srv01 srv02 srv03 srv04 ] Resource Group: UMgroup01 UmVIPcheck (ocf::pacemaker:Dummy): Started srv01 UmIPaddr (ocf::pacemaker:Dummy): Started srv01 UmDummy01 (ocf::pacemaker:Dummy): Started srv01 UmDummy02 (ocf::pacemaker:Dummy): Started srv01 Resource Group: OVDBgroup02-1 prmExPostgreSQLDB1 (ocf::pacemaker:Dummy): Started srv01 Resource Group: OVDBgroup02-2 prmExPostgreSQLDB2 (ocf::pacemaker:Dummy): Started srv02 Resource Group: OVDBgroup02-3 prmExPostgreSQLDB3 (ocf::pacemaker:Dummy): Started srv03 Resource Group: grpStonith1 prmStonithN1 (stonith:external/ssh): Started srv04 Resource Group: grpStonith2 prmStonithN2 (stonith:external/ssh): Started srv01 Resource Group: grpStonith3 prmStonithN3 (stonith:external/ssh): Started srv02 Resource Group: grpStonith4 prmStonithN4 (stonith:external/ssh): Started srv03 Clone Set: clnUMgroup01 [clnUmResource] Resource Group: clnUmResource:0 - clnUMdummy01:0 (ocf::pacemaker:Dummy): Started srv04 FAILED - clnUMdummy02:0 (ocf::pacemaker:Dummy): Started srv04 + clnUMdummy01 (ocf::pacemaker:Dummy): Started srv04 FAILED + clnUMdummy02 (ocf::pacemaker:Dummy): Started srv04 Started: [ srv01 ] Stopped: [ srv02 srv03 ] Clone Set: clnPingd [clnPrmPingd] Started: [ srv01 srv02 srv03 srv04 ] Clone Set: clnDiskd1 [clnPrmDiskd1] Started: [ srv01 srv02 srv03 srv04 ] Clone Set: clnG3dummy1 [clnG3dummy01] Started: [ srv01 srv02 srv03 srv04 ] Clone Set: clnG3dummy2 [clnG3dummy02] Started: [ srv01 srv02 srv03 srv04 ] Transition Summary: * Move UmVIPcheck (Started srv01 -> srv04) * Move UmIPaddr (Started srv01 -> srv04) * Move UmDummy01 (Started srv01 -> srv04) * Move UmDummy02 (Started srv01 -> srv04) * Recover clnUMdummy01:0 (Started srv04) * Restart clnUMdummy02:0 (Started srv04) * Stop clnUMdummy01:1 (srv01) * Stop clnUMdummy02:1 (srv01) Executing cluster transition: * Pseudo action: UMgroup01_stop_0 * Resource action: UmDummy02 stop on srv01 * Resource action: UmDummy01 stop on srv01 * Resource action: UmIPaddr stop on srv01 * Resource action: UmVIPcheck stop on srv01 * Pseudo action: UMgroup01_stopped_0 * Pseudo action: clnUMgroup01_stop_0 * Pseudo action: clnUmResource:0_stop_0 * Resource action: clnUMdummy02:1 stop on srv04 * Pseudo action: clnUmResource:1_stop_0 * Resource action: clnUMdummy02:0 stop on srv01 * Resource action: clnUMdummy01:1 stop on srv04 * Resource action: clnUMdummy01:0 stop on srv01 * Pseudo action: all_stopped * Pseudo action: clnUmResource:0_stopped_0 * Pseudo action: clnUmResource:1_stopped_0 * Pseudo action: clnUMgroup01_stopped_0 * Pseudo action: clnUMgroup01_start_0 * Pseudo action: clnUmResource:0_start_0 * Resource action: clnUMdummy01:1 start on srv04 * Resource action: clnUMdummy01:1 monitor=10000 on srv04 * Resource action: clnUMdummy02:1 start on srv04 * Resource action: clnUMdummy02:1 monitor=10000 on srv04 * Pseudo action: clnUmResource:0_running_0 * Pseudo action: clnUMgroup01_running_0 * Pseudo action: UMgroup01_start_0 * Resource action: UmVIPcheck start on srv04 * Resource action: UmIPaddr start on srv04 * Resource action: UmDummy01 start on srv04 * Resource action: UmDummy02 start on srv04 * Pseudo action: UMgroup01_running_0 * Resource action: UmIPaddr monitor=10000 on srv04 * Resource action: UmDummy01 monitor=10000 on srv04 * Resource action: UmDummy02 monitor=10000 on srv04 Revised cluster status: Online: [ srv01 srv02 srv03 srv04 ] Resource Group: UMgroup01 UmVIPcheck (ocf::pacemaker:Dummy): Started srv04 UmIPaddr (ocf::pacemaker:Dummy): Started srv04 UmDummy01 (ocf::pacemaker:Dummy): Started srv04 UmDummy02 (ocf::pacemaker:Dummy): Started srv04 Resource Group: OVDBgroup02-1 prmExPostgreSQLDB1 (ocf::pacemaker:Dummy): Started srv01 Resource Group: OVDBgroup02-2 prmExPostgreSQLDB2 (ocf::pacemaker:Dummy): Started srv02 Resource Group: OVDBgroup02-3 prmExPostgreSQLDB3 (ocf::pacemaker:Dummy): Started srv03 Resource Group: grpStonith1 prmStonithN1 (stonith:external/ssh): Started srv04 Resource Group: grpStonith2 prmStonithN2 (stonith:external/ssh): Started srv01 Resource Group: grpStonith3 prmStonithN3 (stonith:external/ssh): Started srv02 Resource Group: grpStonith4 prmStonithN4 (stonith:external/ssh): Started srv03 Clone Set: clnUMgroup01 [clnUmResource] Started: [ srv04 ] Stopped: [ srv01 srv02 srv03 ] Clone Set: clnPingd [clnPrmPingd] Started: [ srv01 srv02 srv03 srv04 ] Clone Set: clnDiskd1 [clnPrmDiskd1] Started: [ srv01 srv02 srv03 srv04 ] Clone Set: clnG3dummy1 [clnG3dummy01] Started: [ srv01 srv02 srv03 srv04 ] Clone Set: clnG3dummy2 [clnG3dummy02] Started: [ srv01 srv02 srv03 srv04 ] diff --git a/pengine/test10/clone-max-zero.summary b/pengine/test10/clone-max-zero.summary index fef6e8c980..54829c8ab0 100644 --- a/pengine/test10/clone-max-zero.summary +++ b/pengine/test10/clone-max-zero.summary @@ -1,51 +1,51 @@ Current cluster status: Online: [ c001n11 c001n12 ] fencing (stonith:external/ssh): Started c001n11 Clone Set: dlm-clone [dlm] - dlm:0 (ocf::pacemaker:controld): ORPHANED Started c001n12 - dlm:1 (ocf::pacemaker:controld): ORPHANED Started c001n11 + dlm (ocf::pacemaker:controld): ORPHANED Started c001n12 + dlm (ocf::pacemaker:controld): ORPHANED Started c001n11 Clone Set: o2cb-clone [o2cb] Started: [ c001n11 c001n12 ] Clone Set: clone-drbd0 [drbd0] Started: [ c001n11 c001n12 ] Clone Set: c-ocfs2-1 [ocfs2-1] Started: [ c001n11 c001n12 ] Transition Summary: * Stop dlm:0 (c001n12) * Stop dlm:1 (c001n11) * Stop o2cb:0 (c001n12) * Stop o2cb:1 (c001n11) * Stop ocfs2-1:0 (c001n12) * Stop ocfs2-1:1 (c001n11) Executing cluster transition: * Pseudo action: c-ocfs2-1_stop_0 * Resource action: ocfs2-1:1 stop on c001n12 * Resource action: ocfs2-1:0 stop on c001n11 * Pseudo action: c-ocfs2-1_stopped_0 * Pseudo action: o2cb-clone_stop_0 * Resource action: o2cb:1 stop on c001n12 * Resource action: o2cb:0 stop on c001n11 * Pseudo action: o2cb-clone_stopped_0 * Pseudo action: dlm-clone_stop_0 * Resource action: dlm:1 stop on c001n12 * Resource action: dlm:0 stop on c001n11 * Pseudo action: dlm-clone_stopped_0 * Pseudo action: all_stopped Revised cluster status: Online: [ c001n11 c001n12 ] fencing (stonith:external/ssh): Started c001n11 Clone Set: dlm-clone [dlm] Stopped: [ c001n11 c001n12 ] Clone Set: o2cb-clone [o2cb] Stopped: [ c001n11 c001n12 ] Clone Set: clone-drbd0 [drbd0] Started: [ c001n11 c001n12 ] Clone Set: c-ocfs2-1 [ocfs2-1] Stopped: [ c001n11 c001n12 ] diff --git a/pengine/test10/cloned-group.summary b/pengine/test10/cloned-group.summary index a37331feea..7d64be4b2e 100644 --- a/pengine/test10/cloned-group.summary +++ b/pengine/test10/cloned-group.summary @@ -1,47 +1,47 @@ Current cluster status: Online: [ webcluster01 ] OFFLINE: [ webcluster02 ] Clone Set: apache2_clone [grrr] Resource Group: grrr:2 - apache2:2 (ocf::heartbeat:apache): ORPHANED Started webcluster01 - mysql-proxy:2 (lsb:mysql-proxy): ORPHANED Started webcluster01 + apache2 (ocf::heartbeat:apache): ORPHANED Started webcluster01 + mysql-proxy (lsb:mysql-proxy): ORPHANED Started webcluster01 Started: [ webcluster01 ] Stopped: [ webcluster02 ] Transition Summary: * Restart apache2:0 (Started webcluster01) * Restart mysql-proxy:0 (Started webcluster01) * Stop apache2:2 (webcluster01) * Stop mysql-proxy:2 (webcluster01) Executing cluster transition: * Pseudo action: apache2_clone_stop_0 * Pseudo action: grrr:0_stop_0 * Resource action: mysql-proxy:1 stop on webcluster01 * Pseudo action: grrr:2_stop_0 * Resource action: mysql-proxy:0 stop on webcluster01 * Resource action: apache2:1 stop on webcluster01 * Resource action: apache2:0 stop on webcluster01 * Pseudo action: all_stopped * Pseudo action: grrr:0_stopped_0 * Pseudo action: grrr:2_stopped_0 * Pseudo action: apache2_clone_stopped_0 * Pseudo action: apache2_clone_start_0 * Pseudo action: grrr:0_start_0 * Resource action: apache2:1 start on webcluster01 * Resource action: apache2:1 monitor=10000 on webcluster01 * Resource action: mysql-proxy:1 start on webcluster01 * Resource action: mysql-proxy:1 monitor=10000 on webcluster01 * Pseudo action: grrr:0_running_0 * Pseudo action: apache2_clone_running_0 Revised cluster status: Online: [ webcluster01 ] OFFLINE: [ webcluster02 ] Clone Set: apache2_clone [grrr] Started: [ webcluster01 ] Stopped: [ webcluster02 ] diff --git a/pengine/test10/inc9.summary b/pengine/test10/inc9.summary index 3e11d48419..5a7f123d0b 100644 --- a/pengine/test10/inc9.summary +++ b/pengine/test10/inc9.summary @@ -1,29 +1,29 @@ Current cluster status: Online: [ node1 node2 ] Clone Set: rsc1 [child_rsc1] - child_rsc1:5 (heartbeat:apache): ORPHANED Started node1 - child_rsc1:6 (heartbeat:apache): ORPHANED Started node1 - child_rsc1:7 (heartbeat:apache): ORPHANED Started node2 + child_rsc1 (heartbeat:apache): ORPHANED Started node1 + child_rsc1 (heartbeat:apache): ORPHANED Started node1 + child_rsc1 (heartbeat:apache): ORPHANED Started node2 Started: [ node1 node2 ] Transition Summary: * Stop child_rsc1:5 (node1) * Stop child_rsc1:6 (node1) * Stop child_rsc1:7 (node2) Executing cluster transition: * Pseudo action: rsc1_stop_0 * Resource action: child_rsc1:1 stop on node1 * Resource action: child_rsc1:2 stop on node1 * Resource action: child_rsc1:1 stop on node2 * Pseudo action: rsc1_stopped_0 * Pseudo action: all_stopped Revised cluster status: Online: [ node1 node2 ] Clone Set: rsc1 [child_rsc1] Started: [ node1 node2 ] diff --git a/pengine/test10/interleave-restart.summary b/pengine/test10/interleave-restart.summary index 2aca03629f..32ff5922b4 100644 --- a/pengine/test10/interleave-restart.summary +++ b/pengine/test10/interleave-restart.summary @@ -1,96 +1,96 @@ Current cluster status: Online: [ node1 node2 ] Clone Set: stonithcloneset [stonithclone] Started: [ node1 node2 ] Clone Set: evmscloneset [evmsclone] - evmsclone:1 (ocf::heartbeat:EvmsSCC): Started node1 FAILED + evmsclone (ocf::heartbeat:EvmsSCC): Started node1 FAILED Started: [ node2 ] Clone Set: imagestorecloneset [imagestoreclone] Started: [ node1 node2 ] Clone Set: configstorecloneset [configstoreclone] Started: [ node1 node2 ] Transition Summary: * Recover evmsclone:1 (Started node1) * Restart imagestoreclone:1 (Started node1) * Restart configstoreclone:1 (Started node1) Executing cluster transition: * Pseudo action: evmscloneset_pre_notify_stop_0 * Pseudo action: imagestorecloneset_pre_notify_stop_0 * Pseudo action: configstorecloneset_pre_notify_stop_0 * Resource action: evmsclone:1 notify on node2 * Resource action: evmsclone:0 notify on node1 * Pseudo action: evmscloneset_confirmed-pre_notify_stop_0 * Resource action: imagestoreclone:1 notify on node2 * Resource action: imagestoreclone:0 notify on node1 * Pseudo action: imagestorecloneset_confirmed-pre_notify_stop_0 * Pseudo action: imagestorecloneset_stop_0 * Resource action: configstoreclone:1 notify on node2 * Resource action: configstoreclone:0 notify on node1 * Pseudo action: configstorecloneset_confirmed-pre_notify_stop_0 * Pseudo action: configstorecloneset_stop_0 * Resource action: imagestoreclone:0 stop on node1 * Pseudo action: imagestorecloneset_stopped_0 * Resource action: configstoreclone:0 stop on node1 * Pseudo action: configstorecloneset_stopped_0 * Pseudo action: imagestorecloneset_post_notify_stopped_0 * Pseudo action: configstorecloneset_post_notify_stopped_0 * Resource action: imagestoreclone:1 notify on node2 * Pseudo action: imagestorecloneset_confirmed-post_notify_stopped_0 * Pseudo action: imagestorecloneset_pre_notify_start_0 * Resource action: configstoreclone:1 notify on node2 * Pseudo action: configstorecloneset_confirmed-post_notify_stopped_0 * Pseudo action: configstorecloneset_pre_notify_start_0 * Pseudo action: evmscloneset_stop_0 * Resource action: imagestoreclone:1 notify on node2 * Pseudo action: imagestorecloneset_confirmed-pre_notify_start_0 * Resource action: configstoreclone:1 notify on node2 * Pseudo action: configstorecloneset_confirmed-pre_notify_start_0 * Resource action: evmsclone:0 stop on node1 * Pseudo action: evmscloneset_stopped_0 * Pseudo action: evmscloneset_post_notify_stopped_0 * Resource action: evmsclone:1 notify on node2 * Pseudo action: evmscloneset_confirmed-post_notify_stopped_0 * Pseudo action: evmscloneset_pre_notify_start_0 * Pseudo action: all_stopped * Resource action: evmsclone:1 notify on node2 * Pseudo action: evmscloneset_confirmed-pre_notify_start_0 * Pseudo action: evmscloneset_start_0 * Resource action: evmsclone:0 start on node1 * Pseudo action: evmscloneset_running_0 * Pseudo action: evmscloneset_post_notify_running_0 * Resource action: evmsclone:1 notify on node2 * Resource action: evmsclone:0 notify on node1 * Pseudo action: evmscloneset_confirmed-post_notify_running_0 * Pseudo action: imagestorecloneset_start_0 * Pseudo action: configstorecloneset_start_0 * Resource action: imagestoreclone:0 start on node1 * Pseudo action: imagestorecloneset_running_0 * Resource action: configstoreclone:0 start on node1 * Pseudo action: configstorecloneset_running_0 * Pseudo action: imagestorecloneset_post_notify_running_0 * Pseudo action: configstorecloneset_post_notify_running_0 * Resource action: imagestoreclone:1 notify on node2 * Resource action: imagestoreclone:0 notify on node1 * Pseudo action: imagestorecloneset_confirmed-post_notify_running_0 * Resource action: configstoreclone:1 notify on node2 * Resource action: configstoreclone:0 notify on node1 * Pseudo action: configstorecloneset_confirmed-post_notify_running_0 * Resource action: imagestoreclone:0 monitor=20000 on node1 * Resource action: configstoreclone:0 monitor=20000 on node1 Revised cluster status: Online: [ node1 node2 ] Clone Set: stonithcloneset [stonithclone] Started: [ node1 node2 ] Clone Set: evmscloneset [evmsclone] Started: [ node1 node2 ] Clone Set: imagestorecloneset [imagestoreclone] Started: [ node1 node2 ] Clone Set: configstorecloneset [configstoreclone] Started: [ node1 node2 ] diff --git a/pengine/test10/master-demote-2.summary b/pengine/test10/master-demote-2.summary index 22ed0946d4..53259a7aaa 100644 --- a/pengine/test10/master-demote-2.summary +++ b/pengine/test10/master-demote-2.summary @@ -1,74 +1,74 @@ Current cluster status: Online: [ pcmk-1 pcmk-2 pcmk-3 pcmk-4 ] Fencing (stonith:fence_xvm): Started pcmk-1 Resource Group: group-1 r192.168.122.105 (ocf::heartbeat:IPaddr): Stopped r192.168.122.106 (ocf::heartbeat:IPaddr): Stopped r192.168.122.107 (ocf::heartbeat:IPaddr): Stopped rsc_pcmk-1 (ocf::heartbeat:IPaddr): Started pcmk-1 rsc_pcmk-2 (ocf::heartbeat:IPaddr): Started pcmk-2 rsc_pcmk-3 (ocf::heartbeat:IPaddr): Started pcmk-3 rsc_pcmk-4 (ocf::heartbeat:IPaddr): Started pcmk-4 lsb-dummy (lsb:/usr/share/pacemaker/tests/cts/LSBDummy): Stopped migrator (ocf::pacemaker:Dummy): Started pcmk-4 Clone Set: Connectivity [ping-1] Started: [ pcmk-1 pcmk-2 pcmk-3 pcmk-4 ] Master/Slave Set: master-1 [stateful-1] - stateful-1:0 (ocf::pacemaker:Stateful): Slave pcmk-1 FAILED + stateful-1 (ocf::pacemaker:Stateful): Slave pcmk-1 FAILED Slaves: [ pcmk-2 pcmk-3 pcmk-4 ] Transition Summary: * Start r192.168.122.105 (pcmk-2) * Start r192.168.122.106 (pcmk-2) * Start r192.168.122.107 (pcmk-2) * Start lsb-dummy (pcmk-2) * Recover stateful-1:0 (Slave pcmk-1) * Promote stateful-1:1 (Slave -> Master pcmk-2) Executing cluster transition: * Resource action: stateful-1:0 cancel=15000 on pcmk-2 * Pseudo action: master-1_stop_0 * Resource action: stateful-1:1 stop on pcmk-1 * Pseudo action: master-1_stopped_0 * Pseudo action: master-1_start_0 * Pseudo action: all_stopped * Resource action: stateful-1:1 start on pcmk-1 * Pseudo action: master-1_running_0 * Resource action: stateful-1:1 monitor=15000 on pcmk-1 * Pseudo action: master-1_promote_0 * Resource action: stateful-1:0 promote on pcmk-2 * Pseudo action: master-1_promoted_0 * Pseudo action: group-1_start_0 * Resource action: r192.168.122.105 start on pcmk-2 * Resource action: r192.168.122.106 start on pcmk-2 * Resource action: r192.168.122.107 start on pcmk-2 * Resource action: stateful-1:0 monitor=16000 on pcmk-2 * Pseudo action: group-1_running_0 * Resource action: r192.168.122.105 monitor=5000 on pcmk-2 * Resource action: r192.168.122.106 monitor=5000 on pcmk-2 * Resource action: r192.168.122.107 monitor=5000 on pcmk-2 * Resource action: lsb-dummy start on pcmk-2 * Resource action: lsb-dummy monitor=5000 on pcmk-2 Revised cluster status: Online: [ pcmk-1 pcmk-2 pcmk-3 pcmk-4 ] Fencing (stonith:fence_xvm): Started pcmk-1 Resource Group: group-1 r192.168.122.105 (ocf::heartbeat:IPaddr): Started pcmk-2 r192.168.122.106 (ocf::heartbeat:IPaddr): Started pcmk-2 r192.168.122.107 (ocf::heartbeat:IPaddr): Started pcmk-2 rsc_pcmk-1 (ocf::heartbeat:IPaddr): Started pcmk-1 rsc_pcmk-2 (ocf::heartbeat:IPaddr): Started pcmk-2 rsc_pcmk-3 (ocf::heartbeat:IPaddr): Started pcmk-3 rsc_pcmk-4 (ocf::heartbeat:IPaddr): Started pcmk-4 lsb-dummy (lsb:/usr/share/pacemaker/tests/cts/LSBDummy): Started pcmk-2 migrator (ocf::pacemaker:Dummy): Started pcmk-4 Clone Set: Connectivity [ping-1] Started: [ pcmk-1 pcmk-2 pcmk-3 pcmk-4 ] Master/Slave Set: master-1 [stateful-1] Masters: [ pcmk-2 ] Slaves: [ pcmk-1 pcmk-3 pcmk-4 ] diff --git a/pengine/test10/master-reattach.summary b/pengine/test10/master-reattach.summary index 6e2345f91f..1c0a7e0a3b 100644 --- a/pengine/test10/master-reattach.summary +++ b/pengine/test10/master-reattach.summary @@ -1,34 +1,34 @@ Current cluster status: Online: [ dktest1 dktest2 ] Master/Slave Set: ms-drbd1 [drbd1] (unmanaged) - drbd1:0 (ocf::heartbeat:drbd): Master dktest1 (unmanaged) - drbd1:1 (ocf::heartbeat:drbd): Slave dktest2 (unmanaged) + drbd1 (ocf::heartbeat:drbd): Master dktest1 (unmanaged) + drbd1 (ocf::heartbeat:drbd): Slave dktest2 (unmanaged) Stopped: [ dktest1 dktest2 ] Resource Group: apache apache-vip (ocf::heartbeat:IPaddr2): Started dktest1 (unmanaged) mount (ocf::heartbeat:Filesystem): Started dktest1 (unmanaged) webserver (ocf::heartbeat:apache): Started dktest1 (unmanaged) Transition Summary: Executing cluster transition: * Resource action: drbd1:0 monitor=10000 on dktest1 * Resource action: drbd1:0 monitor=11000 on dktest2 * Resource action: apache-vip monitor=60000 on dktest1 * Resource action: mount monitor=10000 on dktest1 * Resource action: webserver monitor=30000 on dktest1 Revised cluster status: Online: [ dktest1 dktest2 ] Master/Slave Set: ms-drbd1 [drbd1] (unmanaged) - drbd1:0 (ocf::heartbeat:drbd): Master dktest1 (unmanaged) - drbd1:1 (ocf::heartbeat:drbd): Slave dktest2 (unmanaged) + drbd1 (ocf::heartbeat:drbd): Master dktest1 (unmanaged) + drbd1 (ocf::heartbeat:drbd): Slave dktest2 (unmanaged) Stopped: [ dktest1 dktest2 ] Resource Group: apache apache-vip (ocf::heartbeat:IPaddr2): Started dktest1 (unmanaged) mount (ocf::heartbeat:Filesystem): Started dktest1 (unmanaged) webserver (ocf::heartbeat:apache): Started dktest1 (unmanaged) diff --git a/pengine/test10/master-unmanaged-monitor.summary b/pengine/test10/master-unmanaged-monitor.summary index 46c90118fa..4ee74d2d2f 100644 --- a/pengine/test10/master-unmanaged-monitor.summary +++ b/pengine/test10/master-unmanaged-monitor.summary @@ -1,70 +1,70 @@ Current cluster status: Online: [ pcmk-1 pcmk-2 pcmk-3 pcmk-4 ] Clone Set: Fencing [FencingChild] (unmanaged) Stopped: [ pcmk-1 pcmk-2 pcmk-3 pcmk-4 ] Resource Group: group-1 r192.168.122.112 (ocf::heartbeat:IPaddr): Started pcmk-3 (unmanaged) r192.168.122.113 (ocf::heartbeat:IPaddr): Started pcmk-3 (unmanaged) r192.168.122.114 (ocf::heartbeat:IPaddr): Started pcmk-3 (unmanaged) rsc_pcmk-1 (ocf::heartbeat:IPaddr): Started pcmk-1 (unmanaged) rsc_pcmk-2 (ocf::heartbeat:IPaddr): Started pcmk-2 (unmanaged) rsc_pcmk-3 (ocf::heartbeat:IPaddr): Started pcmk-3 (unmanaged) rsc_pcmk-4 (ocf::heartbeat:IPaddr): Started pcmk-4 (unmanaged) lsb-dummy (lsb:/usr/share/pacemaker/tests/cts/LSBDummy): Started pcmk-3 (unmanaged) migrator (ocf::pacemaker:Dummy): Started pcmk-4 (unmanaged) Clone Set: Connectivity [ping-1] (unmanaged) - ping-1:0 (ocf::pacemaker:ping): Started pcmk-2 (unmanaged) - ping-1:1 (ocf::pacemaker:ping): Started pcmk-3 (unmanaged) - ping-1:2 (ocf::pacemaker:ping): Started pcmk-4 (unmanaged) - ping-1:3 (ocf::pacemaker:ping): Started pcmk-1 (unmanaged) + ping-1 (ocf::pacemaker:ping): Started pcmk-2 (unmanaged) + ping-1 (ocf::pacemaker:ping): Started pcmk-3 (unmanaged) + ping-1 (ocf::pacemaker:ping): Started pcmk-4 (unmanaged) + ping-1 (ocf::pacemaker:ping): Started pcmk-1 (unmanaged) Stopped: [ pcmk-1 pcmk-2 pcmk-3 pcmk-4 ] Master/Slave Set: master-1 [stateful-1] (unmanaged) - stateful-1:0 (ocf::pacemaker:Stateful): Slave pcmk-2 (unmanaged) - stateful-1:1 (ocf::pacemaker:Stateful): Master pcmk-3 (unmanaged) - stateful-1:2 (ocf::pacemaker:Stateful): Slave pcmk-4 (unmanaged) + stateful-1 (ocf::pacemaker:Stateful): Slave pcmk-2 (unmanaged) + stateful-1 (ocf::pacemaker:Stateful): Master pcmk-3 (unmanaged) + stateful-1 (ocf::pacemaker:Stateful): Slave pcmk-4 (unmanaged) Stopped: [ pcmk-1 pcmk-2 pcmk-3 pcmk-4 ] Transition Summary: Executing cluster transition: * Resource action: lsb-dummy monitor=5000 on pcmk-3 * Resource action: migrator monitor=10000 on pcmk-4 * Resource action: ping-1:0 monitor=60000 on pcmk-2 * Resource action: ping-1:0 monitor=60000 on pcmk-3 * Resource action: ping-1:0 monitor=60000 on pcmk-4 * Resource action: ping-1:0 monitor=60000 on pcmk-1 * Resource action: stateful-1:0 monitor=15000 on pcmk-2 * Resource action: stateful-1:0 monitor on pcmk-1 * Resource action: stateful-1:0 monitor=16000 on pcmk-3 * Resource action: stateful-1:0 monitor=15000 on pcmk-4 * Pseudo action: probe_complete Revised cluster status: Online: [ pcmk-1 pcmk-2 pcmk-3 pcmk-4 ] Clone Set: Fencing [FencingChild] (unmanaged) Stopped: [ pcmk-1 pcmk-2 pcmk-3 pcmk-4 ] Resource Group: group-1 r192.168.122.112 (ocf::heartbeat:IPaddr): Started pcmk-3 (unmanaged) r192.168.122.113 (ocf::heartbeat:IPaddr): Started pcmk-3 (unmanaged) r192.168.122.114 (ocf::heartbeat:IPaddr): Started pcmk-3 (unmanaged) rsc_pcmk-1 (ocf::heartbeat:IPaddr): Started pcmk-1 (unmanaged) rsc_pcmk-2 (ocf::heartbeat:IPaddr): Started pcmk-2 (unmanaged) rsc_pcmk-3 (ocf::heartbeat:IPaddr): Started pcmk-3 (unmanaged) rsc_pcmk-4 (ocf::heartbeat:IPaddr): Started pcmk-4 (unmanaged) lsb-dummy (lsb:/usr/share/pacemaker/tests/cts/LSBDummy): Started pcmk-3 (unmanaged) migrator (ocf::pacemaker:Dummy): Started pcmk-4 (unmanaged) Clone Set: Connectivity [ping-1] (unmanaged) - ping-1:0 (ocf::pacemaker:ping): Started pcmk-2 (unmanaged) - ping-1:1 (ocf::pacemaker:ping): Started pcmk-3 (unmanaged) - ping-1:2 (ocf::pacemaker:ping): Started pcmk-4 (unmanaged) - ping-1:3 (ocf::pacemaker:ping): Started pcmk-1 (unmanaged) + ping-1 (ocf::pacemaker:ping): Started pcmk-2 (unmanaged) + ping-1 (ocf::pacemaker:ping): Started pcmk-3 (unmanaged) + ping-1 (ocf::pacemaker:ping): Started pcmk-4 (unmanaged) + ping-1 (ocf::pacemaker:ping): Started pcmk-1 (unmanaged) Stopped: [ pcmk-1 pcmk-2 pcmk-3 pcmk-4 ] Master/Slave Set: master-1 [stateful-1] (unmanaged) - stateful-1:0 (ocf::pacemaker:Stateful): Slave pcmk-2 (unmanaged) - stateful-1:1 (ocf::pacemaker:Stateful): Master pcmk-3 (unmanaged) - stateful-1:2 (ocf::pacemaker:Stateful): Slave pcmk-4 (unmanaged) + stateful-1 (ocf::pacemaker:Stateful): Slave pcmk-2 (unmanaged) + stateful-1 (ocf::pacemaker:Stateful): Master pcmk-3 (unmanaged) + stateful-1 (ocf::pacemaker:Stateful): Slave pcmk-4 (unmanaged) Stopped: [ pcmk-1 pcmk-2 pcmk-3 pcmk-4 ] diff --git a/pengine/test10/novell-252693-3.summary b/pengine/test10/novell-252693-3.summary index a147a79355..9d42229a54 100644 --- a/pengine/test10/novell-252693-3.summary +++ b/pengine/test10/novell-252693-3.summary @@ -1,107 +1,107 @@ Current cluster status: Online: [ node1 node2 ] Clone Set: stonithcloneset [stonithclone] Started: [ node2 ] Stopped: [ node1 ] Clone Set: evmsdcloneset [evmsdclone] Started: [ node2 ] Stopped: [ node1 ] Clone Set: evmscloneset [evmsclone] Started: [ node2 ] Stopped: [ node1 ] Clone Set: imagestorecloneset [imagestoreclone] - imagestoreclone:0 (ocf::heartbeat:Filesystem): Started node2 FAILED + imagestoreclone (ocf::heartbeat:Filesystem): Started node2 FAILED Stopped: [ node1 ] Clone Set: configstorecloneset [configstoreclone] Started: [ node2 ] Stopped: [ node1 ] sles10 (ocf::heartbeat:Xen): Started node2 Transition Summary: * Start stonithclone:1 (node1) * Start evmsdclone:1 (node1) * Start evmsclone:1 (node1) * Recover imagestoreclone:0 (Started node2 -> node1) * Start imagestoreclone:1 (node2) * Start configstoreclone:1 (node1) * Move sles10 (Started node2 -> node1) Executing cluster transition: * Resource action: stonithclone:1 monitor on node1 * Pseudo action: stonithcloneset_start_0 * Resource action: evmsdclone:1 monitor on node1 * Pseudo action: evmsdcloneset_start_0 * Resource action: evmsclone:1 monitor on node1 * Pseudo action: evmscloneset_pre_notify_start_0 * Resource action: imagestoreclone:0 monitor on node1 * Pseudo action: imagestorecloneset_pre_notify_stop_0 * Resource action: configstoreclone:1 monitor on node1 * Pseudo action: configstorecloneset_pre_notify_start_0 * Resource action: sles10 monitor on node1 * Pseudo action: probe_complete * Resource action: stonithclone:1 start on node1 * Pseudo action: stonithcloneset_running_0 * Resource action: evmsdclone:1 start on node1 * Pseudo action: evmsdcloneset_running_0 * Resource action: evmsclone:0 notify on node2 * Pseudo action: evmscloneset_confirmed-pre_notify_start_0 * Pseudo action: evmscloneset_start_0 * Resource action: imagestoreclone:0 notify on node2 * Pseudo action: imagestorecloneset_confirmed-pre_notify_stop_0 * Resource action: configstoreclone:0 notify on node2 * Pseudo action: configstorecloneset_confirmed-pre_notify_start_0 * Resource action: sles10 stop on node2 * Resource action: stonithclone:1 monitor=5000 on node1 * Resource action: evmsdclone:1 monitor=5000 on node1 * Resource action: evmsclone:1 start on node1 * Pseudo action: evmscloneset_running_0 * Pseudo action: imagestorecloneset_stop_0 * Pseudo action: evmscloneset_post_notify_running_0 * Resource action: imagestoreclone:0 stop on node2 * Pseudo action: imagestorecloneset_stopped_0 * Resource action: evmsclone:0 notify on node2 * Resource action: evmsclone:1 notify on node1 * Pseudo action: evmscloneset_confirmed-post_notify_running_0 * Pseudo action: imagestorecloneset_post_notify_stopped_0 * Pseudo action: configstorecloneset_start_0 * Pseudo action: imagestorecloneset_confirmed-post_notify_stopped_0 * Pseudo action: imagestorecloneset_pre_notify_start_0 * Resource action: configstoreclone:1 start on node1 * Pseudo action: configstorecloneset_running_0 * Pseudo action: all_stopped * Pseudo action: imagestorecloneset_confirmed-pre_notify_start_0 * Pseudo action: imagestorecloneset_start_0 * Pseudo action: configstorecloneset_post_notify_running_0 * Resource action: imagestoreclone:0 start on node1 * Resource action: imagestoreclone:1 start on node2 * Pseudo action: imagestorecloneset_running_0 * Resource action: configstoreclone:0 notify on node2 * Resource action: configstoreclone:1 notify on node1 * Pseudo action: configstorecloneset_confirmed-post_notify_running_0 * Pseudo action: imagestorecloneset_post_notify_running_0 * Resource action: configstoreclone:1 monitor=20000 on node1 * Resource action: imagestoreclone:0 notify on node1 * Resource action: imagestoreclone:1 notify on node2 * Pseudo action: imagestorecloneset_confirmed-post_notify_running_0 * Resource action: sles10 start on node1 * Resource action: imagestoreclone:0 monitor=20000 on node1 * Resource action: imagestoreclone:1 monitor=20000 on node2 * Resource action: sles10 monitor=10000 on node1 Revised cluster status: Online: [ node1 node2 ] Clone Set: stonithcloneset [stonithclone] Started: [ node1 node2 ] Clone Set: evmsdcloneset [evmsdclone] Started: [ node1 node2 ] Clone Set: evmscloneset [evmsclone] Started: [ node1 node2 ] Clone Set: imagestorecloneset [imagestoreclone] Started: [ node1 node2 ] Clone Set: configstorecloneset [configstoreclone] Started: [ node1 node2 ] sles10 (ocf::heartbeat:Xen): Started node1 diff --git a/pengine/test10/unmanaged-master.summary b/pengine/test10/unmanaged-master.summary index 60f419b754..86efd8aff7 100644 --- a/pengine/test10/unmanaged-master.summary +++ b/pengine/test10/unmanaged-master.summary @@ -1,61 +1,61 @@ Current cluster status: Online: [ pcmk-1 pcmk-2 ] OFFLINE: [ pcmk-3 pcmk-4 ] Clone Set: Fencing [FencingChild] (unmanaged) - FencingChild:2 (stonith:fence_xvm): Started pcmk-2 (unmanaged) - FencingChild:3 (stonith:fence_xvm): Started pcmk-1 (unmanaged) + FencingChild (stonith:fence_xvm): Started pcmk-2 (unmanaged) + FencingChild (stonith:fence_xvm): Started pcmk-1 (unmanaged) Stopped: [ pcmk-1 pcmk-2 pcmk-3 pcmk-4 ] Resource Group: group-1 r192.168.122.126 (ocf::heartbeat:IPaddr): Started pcmk-2 (unmanaged) r192.168.122.127 (ocf::heartbeat:IPaddr): Started pcmk-2 (unmanaged) r192.168.122.128 (ocf::heartbeat:IPaddr): Started pcmk-2 (unmanaged) rsc_pcmk-1 (ocf::heartbeat:IPaddr): Started pcmk-1 (unmanaged) rsc_pcmk-2 (ocf::heartbeat:IPaddr): Started pcmk-2 (unmanaged) rsc_pcmk-3 (ocf::heartbeat:IPaddr): Started pcmk-3 (unmanaged) rsc_pcmk-4 (ocf::heartbeat:IPaddr): Started pcmk-4 (unmanaged) lsb-dummy (lsb:/usr/share/pacemaker/tests/cts/LSBDummy): Started pcmk-2 (unmanaged) migrator (ocf::pacemaker:Dummy): Started pcmk-4 (unmanaged) Clone Set: Connectivity [ping-1] (unmanaged) - ping-1:2 (ocf::pacemaker:ping): Started pcmk-2 (unmanaged) - ping-1:3 (ocf::pacemaker:ping): Started pcmk-1 (unmanaged) + ping-1 (ocf::pacemaker:ping): Started pcmk-2 (unmanaged) + ping-1 (ocf::pacemaker:ping): Started pcmk-1 (unmanaged) Stopped: [ pcmk-1 pcmk-2 pcmk-3 pcmk-4 ] Master/Slave Set: master-1 [stateful-1] (unmanaged) - stateful-1:2 (ocf::pacemaker:Stateful): Master pcmk-2 (unmanaged) - stateful-1:3 (ocf::pacemaker:Stateful): Started pcmk-1 (unmanaged) + stateful-1 (ocf::pacemaker:Stateful): Master pcmk-2 (unmanaged) + stateful-1 (ocf::pacemaker:Stateful): Started pcmk-1 (unmanaged) Stopped: [ pcmk-1 pcmk-2 pcmk-3 pcmk-4 ] Transition Summary: Executing cluster transition: * Cluster action: do_shutdown on pcmk-2 * Cluster action: do_shutdown on pcmk-1 Revised cluster status: Online: [ pcmk-1 pcmk-2 ] OFFLINE: [ pcmk-3 pcmk-4 ] Clone Set: Fencing [FencingChild] (unmanaged) - FencingChild:2 (stonith:fence_xvm): Started pcmk-2 (unmanaged) - FencingChild:3 (stonith:fence_xvm): Started pcmk-1 (unmanaged) + FencingChild (stonith:fence_xvm): Started pcmk-2 (unmanaged) + FencingChild (stonith:fence_xvm): Started pcmk-1 (unmanaged) Stopped: [ pcmk-1 pcmk-2 pcmk-3 pcmk-4 ] Resource Group: group-1 r192.168.122.126 (ocf::heartbeat:IPaddr): Started pcmk-2 (unmanaged) r192.168.122.127 (ocf::heartbeat:IPaddr): Started pcmk-2 (unmanaged) r192.168.122.128 (ocf::heartbeat:IPaddr): Started pcmk-2 (unmanaged) rsc_pcmk-1 (ocf::heartbeat:IPaddr): Started pcmk-1 (unmanaged) rsc_pcmk-2 (ocf::heartbeat:IPaddr): Started pcmk-2 (unmanaged) rsc_pcmk-3 (ocf::heartbeat:IPaddr): Started pcmk-3 (unmanaged) rsc_pcmk-4 (ocf::heartbeat:IPaddr): Started pcmk-4 (unmanaged) lsb-dummy (lsb:/usr/share/pacemaker/tests/cts/LSBDummy): Started pcmk-2 (unmanaged) migrator (ocf::pacemaker:Dummy): Started pcmk-4 (unmanaged) Clone Set: Connectivity [ping-1] (unmanaged) - ping-1:2 (ocf::pacemaker:ping): Started pcmk-2 (unmanaged) - ping-1:3 (ocf::pacemaker:ping): Started pcmk-1 (unmanaged) + ping-1 (ocf::pacemaker:ping): Started pcmk-2 (unmanaged) + ping-1 (ocf::pacemaker:ping): Started pcmk-1 (unmanaged) Stopped: [ pcmk-1 pcmk-2 pcmk-3 pcmk-4 ] Master/Slave Set: master-1 [stateful-1] (unmanaged) - stateful-1:2 (ocf::pacemaker:Stateful): Master pcmk-2 (unmanaged) - stateful-1:3 (ocf::pacemaker:Stateful): Started pcmk-1 (unmanaged) + stateful-1 (ocf::pacemaker:Stateful): Master pcmk-2 (unmanaged) + stateful-1 (ocf::pacemaker:Stateful): Started pcmk-1 (unmanaged) Stopped: [ pcmk-1 pcmk-2 pcmk-3 pcmk-4 ] diff --git a/tools/crm_mon.c b/tools/crm_mon.c index b3e8c0b310..d2b9a072ac 100644 --- a/tools/crm_mon.c +++ b/tools/crm_mon.c @@ -1,2306 +1,2306 @@ /* * Copyright (C) 2004 Andrew Beekhof * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include <../lib/pengine/unpack.h> #include <../pengine/pengine.h> #include /* GMainLoop *mainloop = NULL; */ void wait_for_refresh(int offset, const char *prefix, int msec); void clean_up(int rc); void crm_diff_update(const char *event, xmlNode * msg); gboolean mon_refresh_display(gpointer user_data); int cib_connect(gboolean full); void mon_st_callback(stonith_t * st, stonith_event_t * e); char *xml_file = NULL; char *as_html_file = NULL; int as_xml = 0; char *pid_file = NULL; char *snmp_target = NULL; char *snmp_community = NULL; gboolean as_console = TRUE;; gboolean simple_status = FALSE; gboolean group_by_node = FALSE; gboolean inactive_resources = FALSE; gboolean web_cgi = FALSE; int reconnect_msec = 5000; gboolean daemonize = FALSE; GMainLoop *mainloop = NULL; guint timer_id = 0; GList *attr_list = NULL; const char *crm_mail_host = NULL; const char *crm_mail_prefix = NULL; const char *crm_mail_from = NULL; const char *crm_mail_to = NULL; const char *external_agent = NULL; const char *external_recipient = NULL; cib_t *cib = NULL; stonith_t *st = NULL; xmlNode *current_cib = NULL; gboolean one_shot = FALSE; gboolean has_warnings = FALSE; gboolean print_failcount = FALSE; gboolean print_operations = FALSE; gboolean print_timing = FALSE; gboolean print_nodes_attr = FALSE; gboolean print_last_updated = TRUE; gboolean print_last_change = TRUE; gboolean print_tickets = FALSE; gboolean watch_fencing = FALSE; #define FILTER_STR {"shutdown", "terminate", "standby", "fail-count", \ "last-failure", "probe_complete", "#id", "#uname", \ "#is_dc", NULL} gboolean log_diffs = FALSE; gboolean log_updates = FALSE; long last_refresh = 0; crm_trigger_t *refresh_trigger = NULL; /* * 1.3.6.1.4.1.32723 has been assigned to the project by IANA * http://www.iana.org/assignments/enterprise-numbers */ #define PACEMAKER_PREFIX "1.3.6.1.4.1.32723" #define PACEMAKER_TRAP_PREFIX PACEMAKER_PREFIX ".1" #define snmp_crm_trap_oid PACEMAKER_TRAP_PREFIX #define snmp_crm_oid_node PACEMAKER_TRAP_PREFIX ".1" #define snmp_crm_oid_rsc PACEMAKER_TRAP_PREFIX ".2" #define snmp_crm_oid_task PACEMAKER_TRAP_PREFIX ".3" #define snmp_crm_oid_desc PACEMAKER_TRAP_PREFIX ".4" #define snmp_crm_oid_status PACEMAKER_TRAP_PREFIX ".5" #define snmp_crm_oid_rc PACEMAKER_TRAP_PREFIX ".6" #define snmp_crm_oid_trc PACEMAKER_TRAP_PREFIX ".7" #if CURSES_ENABLED # define print_dot() if(as_console) { \ printw("."); \ clrtoeol(); \ refresh(); \ } else { \ fprintf(stdout, "."); \ } #else # define print_dot() fprintf(stdout, "."); #endif #if CURSES_ENABLED # define print_as(fmt, args...) if(as_console) { \ printw(fmt, ##args); \ clrtoeol(); \ refresh(); \ } else { \ fprintf(stdout, fmt, ##args); \ } #else # define print_as(fmt, args...) fprintf(stdout, fmt, ##args); #endif static void blank_screen(void) { #if CURSES_ENABLED int lpc = 0; for (lpc = 0; lpc < LINES; lpc++) { move(lpc, 0); clrtoeol(); } move(0, 0); refresh(); #endif } static gboolean mon_timer_popped(gpointer data) { int rc = pcmk_ok; if (timer_id > 0) { g_source_remove(timer_id); } rc = cib_connect(TRUE); if (rc != pcmk_ok) { print_dot(); timer_id = g_timeout_add(reconnect_msec, mon_timer_popped, NULL); } return FALSE; } static void mon_cib_connection_destroy(gpointer user_data) { print_as("Connection to the CIB terminated\n"); if (cib) { print_as("Reconnecting..."); cib->cmds->signoff(cib); timer_id = g_timeout_add(reconnect_msec, mon_timer_popped, NULL); } return; } /* * Mainloop signal handler. */ static void mon_shutdown(int nsig) { clean_up(EX_OK); } #if ON_DARWIN # define sighandler_t sig_t #endif #if CURSES_ENABLED # ifndef HAVE_SIGHANDLER_T typedef void (*sighandler_t) (int); # endif static sighandler_t ncurses_winch_handler; static void mon_winresize(int nsig) { static int not_done; int lines = 0, cols = 0; if (!not_done++) { if (ncurses_winch_handler) /* the original ncurses WINCH signal handler does the * magic of retrieving the new window size; * otherwise, we'd have to use ioctl or tgetent */ (*ncurses_winch_handler) (SIGWINCH); getmaxyx(stdscr, lines, cols); resizeterm(lines, cols); mainloop_set_trigger(refresh_trigger); } not_done--; } #endif int cib_connect(gboolean full) { int rc = pcmk_ok; static gboolean need_pass = TRUE; CRM_CHECK(cib != NULL, return -EINVAL); if (getenv("CIB_passwd") != NULL) { need_pass = FALSE; } if (watch_fencing && st == NULL) { st = stonith_api_new(); } if (watch_fencing && st->state == stonith_disconnected) { crm_trace("Connecting to stonith"); rc = st->cmds->connect(st, crm_system_name, NULL); if (rc == pcmk_ok) { crm_trace("Setting up stonith callbacks"); st->cmds->register_notification(st, T_STONITH_NOTIFY_FENCE, mon_st_callback); } } if (cib->state != cib_connected_query && cib->state != cib_connected_command) { crm_trace("Connecting to the CIB"); if (as_console && need_pass && cib->variant == cib_remote) { need_pass = FALSE; print_as("Password:"); } rc = cib->cmds->signon(cib, crm_system_name, cib_query); if (rc != pcmk_ok) { return rc; } current_cib = get_cib_copy(cib); mon_refresh_display(NULL); if (full) { if (rc == pcmk_ok) { rc = cib->cmds->set_connection_dnotify(cib, mon_cib_connection_destroy); if (rc == -EPROTONOSUPPORT) { print_as ("Notification setup not supported, won't be able to reconnect after failure"); if (as_console) { sleep(2); } rc = pcmk_ok; } } if (rc == pcmk_ok) { cib->cmds->del_notify_callback(cib, T_CIB_DIFF_NOTIFY, crm_diff_update); rc = cib->cmds->add_notify_callback(cib, T_CIB_DIFF_NOTIFY, crm_diff_update); } if (rc != pcmk_ok) { print_as("Notification setup failed, could not monitor CIB actions"); if (as_console) { sleep(2); } clean_up(-rc); } } } return rc; } /* *INDENT-OFF* */ static struct crm_option long_options[] = { /* Top-level Options */ {"help", 0, 0, '?', "\tThis text"}, {"version", 0, 0, '$', "\tVersion information" }, {"verbose", 0, 0, 'V', "\tIncrease debug output"}, {"quiet", 0, 0, 'Q', "\tDisplay only essential output" }, {"-spacer-", 1, 0, '-', "\nModes:"}, {"as-html", 1, 0, 'h', "Write cluster status to the named html file"}, {"as-xml", 0, 0, 'X', "\tWrite cluster status as xml to stdout. This will enable one-shot mode."}, {"web-cgi", 0, 0, 'w', "\tWeb mode with output suitable for cgi"}, {"simple-status", 0, 0, 's', "Display the cluster status once as a simple one line output (suitable for nagios)"}, {"snmp-traps", 1, 0, 'S', "Send SNMP traps to this station", !ENABLE_SNMP}, {"snmp-community", 1, 0, 'C', "Specify community for SNMP traps(default is NULL)", !ENABLE_SNMP}, {"mail-to", 1, 0, 'T', "Send Mail alerts to this user. See also --mail-from, --mail-host, --mail-prefix", !ENABLE_ESMTP}, {"-spacer-", 1, 0, '-', "\nDisplay Options:"}, {"group-by-node", 0, 0, 'n', "\tGroup resources by node" }, {"inactive", 0, 0, 'r', "\tDisplay inactive resources" }, {"failcounts", 0, 0, 'f', "\tDisplay resource fail counts"}, {"operations", 0, 0, 'o', "\tDisplay resource operation history" }, {"timing-details", 0, 0, 't', "\tDisplay resource operation history with timing details" }, {"tickets", 0, 0, 'c', "\t\tDisplay cluster tickets"}, {"watch-fencing", 0, 0, 'W', "\t\tListen for fencing events. For use with --external-agent, --mail-to and/or --snmp-traps where supported"}, {"show-node-attributes", 0, 0, 'A', "Display node attributes" }, {"-spacer-", 1, 0, '-', "\nAdditional Options:"}, {"interval", 1, 0, 'i', "\tUpdate frequency in seconds" }, {"one-shot", 0, 0, '1', "\tDisplay the cluster status once on the console and exit"}, {"disable-ncurses",0, 0, 'N', "\tDisable the use of ncurses", !CURSES_ENABLED}, {"daemonize", 0, 0, 'd', "\tRun in the background as a daemon"}, {"pid-file", 1, 0, 'p', "\t(Advanced) Daemon pid file location"}, {"mail-from", 1, 0, 'F', "\tMail alerts should come from the named user", !ENABLE_ESMTP}, {"mail-host", 1, 0, 'H', "\tMail alerts should be sent via the named host", !ENABLE_ESMTP}, {"mail-prefix", 1, 0, 'P', "Subjects for mail alerts should start with this string", !ENABLE_ESMTP}, {"external-agent", 1, 0, 'E', "A program to run when resource operations take place."}, {"external-recipient",1, 0, 'e', "A recipient for your program (assuming you want the program to send something to someone)."}, {"xml-file", 1, 0, 'x', NULL, 1}, {"-spacer-", 1, 0, '-', "\nExamples:", pcmk_option_paragraph}, {"-spacer-", 1, 0, '-', "Display the cluster status on the console with updates as they occur:", pcmk_option_paragraph}, {"-spacer-", 1, 0, '-', " crm_mon", pcmk_option_example}, {"-spacer-", 1, 0, '-', "Display the cluster status on the console just once then exit:", pcmk_option_paragraph}, {"-spacer-", 1, 0, '-', " crm_mon -1", pcmk_option_example}, {"-spacer-", 1, 0, '-', "Display your cluster status, group resources by node, and include inactive resources in the list:", pcmk_option_paragraph}, {"-spacer-", 1, 0, '-', " crm_mon --group-by-node --inactive", pcmk_option_example}, {"-spacer-", 1, 0, '-', "Start crm_mon as a background daemon and have it write the cluster status to an HTML file:", pcmk_option_paragraph}, {"-spacer-", 1, 0, '-', " crm_mon --daemonize --as-html /path/to/docroot/filename.html", pcmk_option_example}, {"-spacer-", 1, 0, '-', "Start crm_mon and export the current cluster status as xml to stdout, then exit.:", pcmk_option_paragraph}, {"-spacer-", 1, 0, '-', " crm_mon --as-xml", pcmk_option_example}, {"-spacer-", 1, 0, '-', "Start crm_mon as a background daemon and have it send email alerts:", pcmk_option_paragraph|!ENABLE_ESMTP}, {"-spacer-", 1, 0, '-', " crm_mon --daemonize --mail-to user@example.com --mail-host mail.example.com", pcmk_option_example|!ENABLE_ESMTP}, {"-spacer-", 1, 0, '-', "Start crm_mon as a background daemon and have it send SNMP alerts:", pcmk_option_paragraph|!ENABLE_SNMP}, {"-spacer-", 1, 0, '-', " crm_mon --daemonize --snmp-traps snmptrapd.example.com", pcmk_option_example|!ENABLE_SNMP}, {NULL, 0, 0, 0} }; /* *INDENT-ON* */ int main(int argc, char **argv) { int flag; int argerr = 0; int exit_code = 0; int option_index = 0; pid_file = strdup("/tmp/ClusterMon.pid"); crm_log_cli_init("crm_mon"); crm_set_options(NULL, "mode [options]", long_options, "Provides a summary of cluster's current state." "\n\nOutputs varying levels of detail in a number of different formats.\n"); #ifndef ON_DARWIN /* prevent zombies */ signal(SIGCLD, SIG_IGN); #endif if (strcmp(crm_system_name, "crm_mon.cgi") == 0) { web_cgi = TRUE; one_shot = TRUE; } while (1) { flag = crm_get_option(argc, argv, &option_index); if (flag == -1) break; switch (flag) { case 'V': crm_bump_log_level(argc, argv); break; case 'Q': print_last_updated = FALSE; print_last_change = FALSE; break; case 'i': reconnect_msec = crm_get_msec(optarg); break; case 'n': group_by_node = TRUE; break; case 'r': inactive_resources = TRUE; break; case 'W': watch_fencing = TRUE; break; case 'd': daemonize = TRUE; break; case 't': print_timing = TRUE; print_operations = TRUE; break; case 'o': print_operations = TRUE; break; case 'f': print_failcount = TRUE; break; case 'A': print_nodes_attr = TRUE; break; case 'c': print_tickets = TRUE; break; case 'p': free(pid_file); pid_file = strdup(optarg); break; case 'x': xml_file = strdup(optarg); one_shot = TRUE; break; case 'h': as_html_file = strdup(optarg); break; case 'X': as_xml = TRUE; one_shot = TRUE; break; case 'w': web_cgi = TRUE; one_shot = TRUE; break; case 's': simple_status = TRUE; one_shot = TRUE; break; case 'S': snmp_target = optarg; break; case 'T': crm_mail_to = optarg; break; case 'F': crm_mail_from = optarg; break; case 'H': crm_mail_host = optarg; break; case 'P': crm_mail_prefix = optarg; break; case 'E': external_agent = optarg; break; case 'e': external_recipient = optarg; break; case '1': one_shot = TRUE; break; case 'N': as_console = FALSE; break; case 'C': snmp_community = optarg; break; case '$': case '?': crm_help(flag, EX_OK); break; default: printf("Argument code 0%o (%c) is not (?yet?) supported\n", flag, flag); ++argerr; break; } } if (optind < argc) { printf("non-option ARGV-elements: "); while (optind < argc) printf("%s ", argv[optind++]); printf("\n"); } if (argerr) { crm_help('?', EX_USAGE); } if (one_shot) { as_console = FALSE; } else if (daemonize) { as_console = FALSE; crm_enable_stderr(FALSE); if (!as_html_file && !snmp_target && !crm_mail_to && !external_agent && !as_xml) { printf ("Looks like you forgot to specify one or more of: --as-html, --as-xml, --mail-to, --snmp-target, --external-agent\n"); crm_help('?', EX_USAGE); } crm_make_daemon(crm_system_name, TRUE, pid_file); } else if (as_console) { #if CURSES_ENABLED initscr(); cbreak(); noecho(); crm_enable_stderr(FALSE); #else one_shot = TRUE; as_console = FALSE; printf("Defaulting to one-shot mode\n"); printf("You need to have curses available at compile time to enable console mode\n"); #endif } crm_info("Starting %s", crm_system_name); if (xml_file != NULL) { current_cib = filename2xml(xml_file); mon_refresh_display(NULL); return exit_code; } if (current_cib == NULL) { cib = cib_new(); if (!one_shot) { print_as("Attempting connection to the cluster..."); } do { exit_code = cib_connect(!one_shot); if (one_shot) { break; } else if (exit_code != pcmk_ok) { print_dot(); sleep(reconnect_msec / 1000); } } while (exit_code == -ENOTCONN); if (exit_code != pcmk_ok) { print_as("\nConnection to cluster failed: %s\n", pcmk_strerror(exit_code)); if (as_console) { sleep(2); } clean_up(-exit_code); } } if (one_shot) { return exit_code; } mainloop = g_main_new(FALSE); mainloop_add_signal(SIGTERM, mon_shutdown); mainloop_add_signal(SIGINT, mon_shutdown); #if CURSES_ENABLED if (as_console) { ncurses_winch_handler = signal(SIGWINCH, mon_winresize); if (ncurses_winch_handler == SIG_DFL || ncurses_winch_handler == SIG_IGN || ncurses_winch_handler == SIG_ERR) ncurses_winch_handler = NULL; } #endif refresh_trigger = mainloop_add_trigger(G_PRIORITY_LOW, mon_refresh_display, NULL); g_main_run(mainloop); g_main_destroy(mainloop); crm_info("Exiting %s", crm_system_name); clean_up(0); return 0; /* never reached */ } void wait_for_refresh(int offset, const char *prefix, int msec) { int lpc = msec / 1000; struct timespec sleept = { 1, 0 }; if (as_console == FALSE) { timer_id = g_timeout_add(msec, mon_timer_popped, NULL); return; } crm_notice("%sRefresh in %ds...", prefix ? prefix : "", lpc); while (lpc > 0) { #if CURSES_ENABLED move(offset, 0); /* printw("%sRefresh in \033[01;32m%ds\033[00m...", prefix?prefix:"", lpc); */ printw("%sRefresh in %ds...\n", prefix ? prefix : "", lpc); clrtoeol(); refresh(); #endif lpc--; if (lpc == 0) { timer_id = g_timeout_add(1000, mon_timer_popped, NULL); } else { if (nanosleep(&sleept, NULL) != 0) { return; } } } } #define mon_warn(fmt...) do { \ if (!has_warnings) { \ print_as("Warning:"); \ } else { \ print_as(","); \ } \ print_as(fmt); \ has_warnings = TRUE; \ } while(0) static int count_resources(pe_working_set_t * data_set, resource_t * rsc) { int count = 0; GListPtr gIter = NULL; if (rsc == NULL) { gIter = data_set->resources; } else if (rsc->children) { gIter = rsc->children; } else { return is_not_set(rsc->flags, pe_rsc_orphan); } for (; gIter != NULL; gIter = gIter->next) { count += count_resources(data_set, gIter->data); } return count; } static int print_simple_status(pe_working_set_t * data_set) { node_t *dc = NULL; GListPtr gIter = NULL; int nodes_online = 0; int nodes_standby = 0; dc = data_set->dc_node; if (dc == NULL) { mon_warn("No DC "); } for (gIter = data_set->nodes; gIter != NULL; gIter = gIter->next) { node_t *node = (node_t *) gIter->data; if (node->details->standby && node->details->online) { nodes_standby++; } else if (node->details->online) { nodes_online++; } else { mon_warn("offline node: %s", node->details->uname); } } if (!has_warnings) { print_as("Ok: %d nodes online", nodes_online); if (nodes_standby > 0) { print_as(", %d standby nodes", nodes_standby); } print_as(", %d resources configured", count_resources(data_set, NULL)); } print_as("\n"); return 0; } static void print_date(time_t time) { int lpc = 0; char date_str[26]; asctime_r(localtime(&time), date_str); for (; lpc < 26; lpc++) { if (date_str[lpc] == '\n') { date_str[lpc] = 0; } } print_as("'%s'", date_str); } #include static void print_rsc_summary(pe_working_set_t * data_set, node_t * node, resource_t * rsc, gboolean all) { gboolean printed = FALSE; time_t last_failure = 0; int failcount = get_failcount_full(node, rsc, &last_failure, FALSE, data_set); if (all || failcount || last_failure > 0) { printed = TRUE; - print_as(" %s: migration-threshold=%d", rsc->id, rsc->migration_threshold); + print_as(" %s: migration-threshold=%d", rsc_printable_id(rsc), rsc->migration_threshold); } if (failcount > 0) { printed = TRUE; print_as(" fail-count=%d", failcount); } if (last_failure > 0) { printed = TRUE; print_as(" last-failure="); print_date(last_failure); } if (printed) { print_as("\n"); } } static void print_rsc_history(pe_working_set_t * data_set, node_t * node, xmlNode * rsc_entry) { GListPtr gIter = NULL; GListPtr op_list = NULL; gboolean print_name = TRUE; GListPtr sorted_op_list = NULL; const char *rsc_id = crm_element_value(rsc_entry, XML_ATTR_ID); resource_t *rsc = pe_find_resource(data_set->resources, rsc_id); xmlNode *rsc_op = NULL; for (rsc_op = __xml_first_child(rsc_entry); rsc_op != NULL; rsc_op = __xml_next(rsc_op)) { if (crm_str_eq((const char *)rsc_op->name, XML_LRM_TAG_RSC_OP, TRUE)) { op_list = g_list_append(op_list, rsc_op); } } sorted_op_list = g_list_sort(op_list, sort_op_by_callid); for (gIter = sorted_op_list; gIter != NULL; gIter = gIter->next) { xmlNode *xml_op = (xmlNode *) gIter->data; const char *value = NULL; const char *call = crm_element_value(xml_op, XML_LRM_ATTR_CALLID); const char *task = crm_element_value(xml_op, XML_LRM_ATTR_TASK); const char *op_rc = crm_element_value(xml_op, XML_LRM_ATTR_RC); const char *interval = crm_element_value(xml_op, XML_LRM_ATTR_INTERVAL); int rc = crm_parse_int(op_rc, "0"); if (safe_str_eq(task, CRMD_ACTION_STATUS) && safe_str_eq(interval, "0")) { task = "probe"; } if (rc == 7 && safe_str_eq(task, "probe")) { continue; } else if (safe_str_eq(task, CRMD_ACTION_NOTIFY)) { continue; } if (print_name) { print_name = FALSE; if (rsc == NULL) { print_as("Orphan resource: %s", rsc_id); } else { print_rsc_summary(data_set, node, rsc, TRUE); } } print_as(" + (%s) %s:", call, task); if (safe_str_neq(interval, "0")) { print_as(" interval=%sms", interval); } if (print_timing) { int int_value; const char *attr = XML_RSC_OP_LAST_CHANGE; value = crm_element_value(xml_op, attr); if (value) { int_value = crm_parse_int(value, NULL); if (int_value > 0) { print_as(" %s=", attr); print_date(int_value); } } attr = XML_RSC_OP_LAST_RUN; value = crm_element_value(xml_op, attr); if (value) { int_value = crm_parse_int(value, NULL); if (int_value > 0) { print_as(" %s=", attr); print_date(int_value); } } attr = XML_RSC_OP_T_EXEC; value = crm_element_value(xml_op, attr); if (value) { int_value = crm_parse_int(value, NULL); print_as(" %s=%dms", attr, int_value); } attr = XML_RSC_OP_T_QUEUE; value = crm_element_value(xml_op, attr); if (value) { int_value = crm_parse_int(value, NULL); print_as(" %s=%dms", attr, int_value); } } print_as(" rc=%s (%s)\n", op_rc, lrmd_event_rc2str(rc)); } /* no need to free the contents */ g_list_free(sorted_op_list); } static void print_attr_msg(node_t * node, GListPtr rsc_list, const char *attrname, const char *attrvalue) { GListPtr gIter = NULL; for (gIter = rsc_list; gIter != NULL; gIter = gIter->next) { resource_t *rsc = (resource_t *) gIter->data; const char *type = g_hash_table_lookup(rsc->meta, "type"); if (rsc->children != NULL) { print_attr_msg(node, rsc->children, attrname, attrvalue); } if (safe_str_eq(type, "ping") || safe_str_eq(type, "pingd")) { const char *name = "pingd"; const char *multiplier = NULL; char **host_list = NULL; int host_list_num = 0; int expected_score = 0; if (g_hash_table_lookup(rsc->meta, "name") != NULL) { name = g_hash_table_lookup(rsc->meta, "name"); } /* To identify the resource with the attribute name. */ if (safe_str_eq(name, attrname)) { int value = crm_parse_int(attrvalue, "0"); multiplier = g_hash_table_lookup(rsc->meta, "multiplier"); host_list = g_strsplit(g_hash_table_lookup(rsc->meta, "host_list"), " ", 0); host_list_num = g_strv_length(host_list); g_strfreev(host_list); /* pingd multiplier is the same as the default value. */ expected_score = host_list_num * crm_parse_int(multiplier, "1"); /* pingd is abnormal score. */ if (value <= 0) { print_as("\t: Connectivity is lost"); } else if (value < expected_score) { print_as("\t: Connectivity is degraded (Expected=%d)", expected_score); } } } } } static int compare_attribute(gconstpointer a, gconstpointer b) { int rc; rc = strcmp((const char *)a, (const char *)b); return rc; } static void create_attr_list(gpointer name, gpointer value, gpointer data) { int i; const char *filt_str[] = FILTER_STR; CRM_CHECK(name != NULL, return); /* filtering automatic attributes */ for (i = 0; filt_str[i] != NULL; i++) { if (g_str_has_prefix(name, filt_str[i])) { return; } } attr_list = g_list_insert_sorted(attr_list, name, compare_attribute); } static void print_node_attribute(gpointer name, gpointer node_data) { const char *value = NULL; node_t *node = (node_t *) node_data; value = g_hash_table_lookup(node->details->attrs, name); print_as(" + %-32s\t: %-10s", (char *)name, value); print_attr_msg(node, node->details->running_rsc, name, value); print_as("\n"); } static void print_node_summary(pe_working_set_t * data_set, gboolean operations) { xmlNode *lrm_rsc = NULL; xmlNode *rsc_entry = NULL; xmlNode *node_state = NULL; xmlNode *cib_status = get_object_root(XML_CIB_TAG_STATUS, data_set->input); if (operations) { print_as("\nOperations:\n"); } else { print_as("\nMigration summary:\n"); } for (node_state = __xml_first_child(cib_status); node_state != NULL; node_state = __xml_next(node_state)) { if (crm_str_eq((const char *)node_state->name, XML_CIB_TAG_STATE, TRUE)) { node_t *node = pe_find_node_id(data_set->nodes, ID(node_state)); if (node == NULL || node->details->online == FALSE) { continue; } print_as("* Node %s: ", crm_element_value(node_state, XML_ATTR_UNAME)); print_as("\n"); lrm_rsc = find_xml_node(node_state, XML_CIB_TAG_LRM, FALSE); lrm_rsc = find_xml_node(lrm_rsc, XML_LRM_TAG_RESOURCES, FALSE); for (rsc_entry = __xml_first_child(lrm_rsc); rsc_entry != NULL; rsc_entry = __xml_next(rsc_entry)) { if (crm_str_eq((const char *)rsc_entry->name, XML_LRM_TAG_RESOURCE, TRUE)) { if (operations) { print_rsc_history(data_set, node, rsc_entry); } else { const char *rsc_id = crm_element_value(rsc_entry, XML_ATTR_ID); resource_t *rsc = pe_find_resource(data_set->resources, rsc_id); if (rsc) { print_rsc_summary(data_set, node, rsc, FALSE); } else { print_as(" %s: orphan\n", rsc_id); } } } } } } } static void print_ticket(gpointer name, gpointer value, gpointer data) { ticket_t *ticket = (ticket_t *) value; print_as(" %s\t%s%10s", ticket->id, ticket->granted ? "granted" : "revoked", ticket->standby ? " [standby]" : ""); if (ticket->last_granted > -1) { print_as(" last-granted="); print_date(ticket->last_granted); } print_as("\n"); return; } static void print_cluster_tickets(pe_working_set_t * data_set) { xmlNode *cib_constraints = get_object_root(XML_CIB_TAG_CONSTRAINTS, data_set->input); /* For recording the tickets that are referenced in rsc_ticket constraints * but have never been granted yet. */ unpack_constraints(cib_constraints, data_set); print_as("\nTickets:\n"); g_hash_table_foreach(data_set->tickets, print_ticket, NULL); return; } static int print_status(pe_working_set_t * data_set) { static int updates = 0; GListPtr gIter = NULL; node_t *dc = NULL; char *since_epoch = NULL; char *online_nodes = NULL; char *offline_nodes = NULL; xmlNode *dc_version = NULL; xmlNode *quorum_node = NULL; xmlNode *stack = NULL; time_t a_time = time(NULL); int print_opts = pe_print_ncurses; const char *quorum_votes = "unknown"; if (as_console) { blank_screen(); } else { print_opts = pe_print_printf; } updates++; dc = data_set->dc_node; if (a_time == (time_t) - 1) { crm_perror(LOG_ERR, "set_node_tstamp(): Invalid time returned"); return 1; } since_epoch = ctime(&a_time); if (since_epoch != NULL && print_last_updated) { print_as("Last updated: %s", since_epoch); } if (print_last_change) { const char *last_written = crm_element_value(data_set->input, XML_CIB_ATTR_WRITTEN); const char *user = crm_element_value(data_set->input, XML_ATTR_UPDATE_USER); const char *client = crm_element_value(data_set->input, XML_ATTR_UPDATE_CLIENT); const char *origin = crm_element_value(data_set->input, XML_ATTR_UPDATE_ORIG); print_as("Last change: %s", last_written ? last_written : ""); if (user) { print_as(" by %s", user); } if (client) { print_as(" via %s", client); } if (origin) { print_as(" on %s", origin); } print_as("\n"); } stack = get_xpath_object("//nvpair[@name='cluster-infrastructure']", data_set->input, LOG_DEBUG); if (stack) { print_as("Stack: %s\n", crm_element_value(stack, XML_NVPAIR_ATTR_VALUE)); } dc_version = get_xpath_object("//nvpair[@name='dc-version']", data_set->input, LOG_DEBUG); if (dc == NULL) { print_as("Current DC: NONE\n"); } else { const char *quorum = crm_element_value(data_set->input, XML_ATTR_HAVE_QUORUM); if (safe_str_neq(dc->details->uname, dc->details->id)) { print_as("Current DC: %s (%s)", dc->details->uname, dc->details->id); } else { print_as("Current DC: %s", dc->details->uname); } print_as(" - partition %s quorum\n", crm_is_true(quorum) ? "with" : "WITHOUT"); if (dc_version) { print_as("Version: %s\n", crm_element_value(dc_version, XML_NVPAIR_ATTR_VALUE)); } } quorum_node = get_xpath_object("//nvpair[@name='" XML_ATTR_EXPECTED_VOTES "']", data_set->input, LOG_DEBUG); if (quorum_node) { quorum_votes = crm_element_value(quorum_node, XML_NVPAIR_ATTR_VALUE); } print_as("%d Nodes configured, %s expected votes\n", g_list_length(data_set->nodes), quorum_votes); print_as("%d Resources configured.\n", count_resources(data_set, NULL)); print_as("\n\n"); for (gIter = data_set->nodes; gIter != NULL; gIter = gIter->next) { node_t *node = (node_t *) gIter->data; const char *node_mode = NULL; char *node_name = NULL; if(node->details->remote_rsc) { node_name = g_strdup_printf("%s:%s", node->details->uname, node->details->remote_rsc->container->id); } else { node_name = g_strdup_printf("%s", node->details->uname); } if (node->details->unclean) { if (node->details->online && node->details->unclean) { node_mode = "UNCLEAN (online)"; } else if (node->details->pending) { node_mode = "UNCLEAN (pending)"; } else { node_mode = "UNCLEAN (offline)"; } } else if (node->details->pending) { node_mode = "pending"; } else if (node->details->standby_onfail && node->details->online) { node_mode = "standby (on-fail)"; } else if (node->details->standby) { if (node->details->online) { node_mode = "standby"; } else { node_mode = "OFFLINE (standby)"; } } else if (node->details->online) { node_mode = "online"; if (group_by_node == FALSE) { online_nodes = add_list_element(online_nodes, node_name); continue; } } else { node_mode = "OFFLINE"; if (group_by_node == FALSE) { offline_nodes = add_list_element(offline_nodes, node_name); continue; } } if(node->details->remote_rsc) { online_nodes = add_list_element(online_nodes, node->details->remote_rsc->id); } if (safe_str_eq(node->details->uname, node->details->id)) { print_as("Node %s: %s\n", node_name, node_mode); } else { print_as("Node %s (%s): %s\n", node_name, node->details->id, node_mode); } if (group_by_node) { GListPtr gIter2 = NULL; for (gIter2 = node->details->running_rsc; gIter2 != NULL; gIter2 = gIter2->next) { resource_t *rsc = (resource_t *) gIter2->data; rsc->fns->print(rsc, "\t", print_opts | pe_print_rsconly, stdout); } } free(node_name); } if (online_nodes) { print_as("Online: [%s ]\n", online_nodes); free(online_nodes); } if (offline_nodes) { print_as("OFFLINE: [%s ]\n", offline_nodes); free(offline_nodes); } if (group_by_node == FALSE && inactive_resources) { print_as("\nFull list of resources:\n"); } else if (inactive_resources) { print_as("\nInactive resources:\n"); } if (group_by_node == FALSE || inactive_resources) { print_as("\n"); for (gIter = data_set->resources; gIter != NULL; gIter = gIter->next) { resource_t *rsc = (resource_t *) gIter->data; gboolean is_active = rsc->fns->active(rsc, TRUE); gboolean partially_active = rsc->fns->active(rsc, FALSE); if (is_set(rsc->flags, pe_rsc_orphan) && is_active == FALSE) { continue; } else if (group_by_node == FALSE) { if (partially_active || inactive_resources) { rsc->fns->print(rsc, NULL, print_opts, stdout); } } else if (is_active == FALSE && inactive_resources) { rsc->fns->print(rsc, NULL, print_opts, stdout); } } } if (print_nodes_attr) { print_as("\nNode Attributes:\n"); for (gIter = data_set->nodes; gIter != NULL; gIter = gIter->next) { node_t *node = (node_t *) gIter->data; if (node == NULL || node->details->online == FALSE) { continue; } attr_list = NULL; print_as("* Node %s:\n", node->details->uname); g_hash_table_foreach(node->details->attrs, create_attr_list, NULL); g_list_foreach(attr_list, print_node_attribute, node); } } if (print_operations || print_failcount) { print_node_summary(data_set, print_operations); } if (xml_has_children(data_set->failed)) { xmlNode *xml_op = NULL; print_as("\nFailed actions:\n"); for (xml_op = __xml_first_child(data_set->failed); xml_op != NULL; xml_op = __xml_next(xml_op)) { int val = 0; const char *id = ID(xml_op); const char *op_key = crm_element_value(xml_op, XML_LRM_ATTR_TASK_KEY); const char *last = crm_element_value(xml_op, XML_RSC_OP_LAST_CHANGE); const char *node = crm_element_value(xml_op, XML_ATTR_UNAME); const char *call = crm_element_value(xml_op, XML_LRM_ATTR_CALLID); const char *rc = crm_element_value(xml_op, XML_LRM_ATTR_RC); const char *status = crm_element_value(xml_op, XML_LRM_ATTR_OPSTATUS); val = crm_parse_int(status, "0"); print_as(" %s (node=%s, call=%s, rc=%s, status=%s", op_key ? op_key : id, node, call, rc, services_lrm_status_str(val)); if (last) { time_t run_at = crm_parse_int(last, "0"); print_as(", last-rc-change=%s, queued=%sms, exec=%sms\n", ctime(&run_at), crm_element_value(xml_op, XML_RSC_OP_T_EXEC), crm_element_value(xml_op, XML_RSC_OP_T_QUEUE)); } val = crm_parse_int(rc, "0"); print_as("): %s\n", lrmd_event_rc2str(val)); } } if (print_tickets) { print_cluster_tickets(data_set); } #if CURSES_ENABLED if (as_console) { refresh(); } #endif return 0; } static int print_xml_status(pe_working_set_t * data_set) { FILE *stream = stdout; GListPtr gIter = NULL; node_t *dc = NULL; xmlNode *stack = NULL; xmlNode *quorum_node = NULL; const char *quorum_votes = "unknown"; dc = data_set->dc_node; fprintf(stream, "\n"); fprintf(stream, "\n", VERSION); /*** SUMMARY ***/ fprintf(stream, " \n"); if (print_last_updated) { time_t now = time(NULL); char *now_str = ctime(&now); now_str[24] = EOS; /* replace the newline */ fprintf(stream, " \n", now_str); } if (print_last_change) { const char *last_written = crm_element_value(data_set->input, XML_CIB_ATTR_WRITTEN); const char *user = crm_element_value(data_set->input, XML_ATTR_UPDATE_USER); const char *client = crm_element_value(data_set->input, XML_ATTR_UPDATE_CLIENT); const char *origin = crm_element_value(data_set->input, XML_ATTR_UPDATE_ORIG); fprintf(stream, " \n", last_written ? last_written : "", user ? user : "", client ? client : "", origin ? origin : ""); } stack = get_xpath_object("//nvpair[@name='cluster-infrastructure']", data_set->input, LOG_DEBUG); if (stack) { fprintf(stream, " \n", crm_element_value(stack, XML_NVPAIR_ATTR_VALUE)); } if (!dc) { fprintf(stream, " \n"); } else { const char *quorum = crm_element_value(data_set->input, XML_ATTR_HAVE_QUORUM); const char *uname = dc->details->uname; const char *id = dc->details->id; xmlNode *dc_version = get_xpath_object("//nvpair[@name='dc-version']", data_set->input, LOG_DEBUG); fprintf(stream, " \n", dc_version ? crm_element_value(dc_version, XML_NVPAIR_ATTR_VALUE) : "", uname, id, quorum ? (crm_is_true(quorum) ? "true" : "false") : "false"); } quorum_node = get_xpath_object("//nvpair[@name='" XML_ATTR_EXPECTED_VOTES "']", data_set->input, LOG_DEBUG); if (quorum_node) { quorum_votes = crm_element_value(quorum_node, XML_NVPAIR_ATTR_VALUE); } fprintf(stream, " \n", g_list_length(data_set->nodes), quorum_votes); fprintf(stream, " \n", count_resources(data_set, NULL)); fprintf(stream, " \n"); /*** NODES ***/ fprintf(stream, " \n"); for (gIter = data_set->nodes; gIter != NULL; gIter = gIter->next) { node_t *node = (node_t *) gIter->data; const char *node_type = "unknown"; switch (node->details->type) { case node_member: node_type = "member"; break; case node_remote: node_type = "remote"; break; case node_ping: node_type = "ping"; break; } fprintf(stream, " details->uname); fprintf(stream, "id=\"%s\" ", node->details->id); fprintf(stream, "online=\"%s\" ", node->details->online ? "true" : "false"); fprintf(stream, "standby=\"%s\" ", node->details->standby ? "true" : "false"); fprintf(stream, "standby_onfail=\"%s\" ", node->details->standby_onfail ? "true" : "false"); fprintf(stream, "pending=\"%s\" ", node->details->pending ? "true" : "false"); fprintf(stream, "unclean=\"%s\" ", node->details->unclean ? "true" : "false"); fprintf(stream, "shutdown=\"%s\" ", node->details->shutdown ? "true" : "false"); fprintf(stream, "expected_up=\"%s\" ", node->details->expected_up ? "true" : "false"); fprintf(stream, "is_dc=\"%s\" ", node->details->is_dc ? "true" : "false"); fprintf(stream, "resources_running=\"%d\" ", g_list_length(node->details->running_rsc)); fprintf(stream, "type=\"%s\" ", node_type); if (group_by_node) { GListPtr lpc2 = NULL; fprintf(stream, ">\n"); for (lpc2 = node->details->running_rsc; lpc2 != NULL; lpc2 = lpc2->next) { resource_t *rsc = (resource_t *) lpc2->data; rsc->fns->print(rsc, " ", pe_print_xml | pe_print_rsconly, stream); } fprintf(stream, " \n"); } else { fprintf(stream, "/>\n"); } } fprintf(stream, " \n"); /*** RESOURCES ***/ if (group_by_node == FALSE || inactive_resources) { fprintf(stream, " \n"); for (gIter = data_set->resources; gIter != NULL; gIter = gIter->next) { resource_t *rsc = (resource_t *) gIter->data; gboolean is_active = rsc->fns->active(rsc, TRUE); gboolean partially_active = rsc->fns->active(rsc, FALSE); if (is_set(rsc->flags, pe_rsc_orphan) && is_active == FALSE) { continue; } else if (group_by_node == FALSE) { if (partially_active || inactive_resources) { rsc->fns->print(rsc, " ", pe_print_xml, stream); } } else if (is_active == FALSE && inactive_resources) { rsc->fns->print(rsc, " ", pe_print_xml, stream); } } fprintf(stream, " \n"); } fprintf(stream, "\n"); fflush(stream); fclose(stream); return 0; } static int print_html_status(pe_working_set_t * data_set, const char *filename, gboolean web_cgi) { FILE *stream; GListPtr gIter = NULL; node_t *dc = NULL; static int updates = 0; char *filename_tmp = NULL; if (web_cgi) { stream = stdout; fprintf(stream, "Content-type: text/html\n\n"); } else { filename_tmp = crm_concat(filename, "tmp", '.'); stream = fopen(filename_tmp, "w"); if (stream == NULL) { crm_perror(LOG_ERR, "Cannot open %s for writing", filename_tmp); free(filename_tmp); return -1; } } updates++; dc = data_set->dc_node; fprintf(stream, ""); fprintf(stream, ""); fprintf(stream, "Cluster status"); /* content="%d;url=http://webdesign.about.com" */ fprintf(stream, "", reconnect_msec / 1000); fprintf(stream, ""); /*** SUMMARY ***/ fprintf(stream, "

Cluster summary

"); { char *now_str = NULL; time_t now = time(NULL); now_str = ctime(&now); now_str[24] = EOS; /* replace the newline */ fprintf(stream, "Last updated: %s
\n", now_str); } if (dc == NULL) { fprintf(stream, "Current DC: NONE
"); } else { fprintf(stream, "Current DC: %s (%s)
", dc->details->uname, dc->details->id); } fprintf(stream, "%d Nodes configured.
", g_list_length(data_set->nodes)); fprintf(stream, "%d Resources configured.
", count_resources(data_set, NULL)); /*** CONFIG ***/ fprintf(stream, "

Config Options

\n"); fprintf(stream, "\n"); fprintf(stream, "\n", is_set(data_set->flags, pe_flag_stonith_enabled) ? "enabled" : "disabled"); fprintf(stream, "\n", is_set(data_set->flags, pe_flag_symmetric_cluster) ? "" : "a-"); fprintf(stream, "\n
STONITH of failed nodes:%s
Cluster is:%ssymmetric
No Quorum Policy:"); switch (data_set->no_quorum_policy) { case no_quorum_freeze: fprintf(stream, "Freeze resources"); break; case no_quorum_stop: fprintf(stream, "Stop ALL resources"); break; case no_quorum_ignore: fprintf(stream, "Ignore"); break; case no_quorum_suicide: fprintf(stream, "Suicide"); break; } fprintf(stream, "\n
\n"); /*** NODE LIST ***/ fprintf(stream, "

Node List

\n"); fprintf(stream, "
    \n"); for (gIter = data_set->nodes; gIter != NULL; gIter = gIter->next) { node_t *node = (node_t *) gIter->data; fprintf(stream, "
  • "); if (node->details->standby_onfail && node->details->online) { fprintf(stream, "Node: %s (%s): %s", node->details->uname, node->details->id, "standby (on-fail)\n"); } else if (node->details->standby && node->details->online) { fprintf(stream, "Node: %s (%s): %s", node->details->uname, node->details->id, "standby\n"); } else if (node->details->standby) { fprintf(stream, "Node: %s (%s): %s", node->details->uname, node->details->id, "OFFLINE (standby)\n"); } else if (node->details->online) { fprintf(stream, "Node: %s (%s): %s", node->details->uname, node->details->id, "online\n"); } else { fprintf(stream, "Node: %s (%s): %s", node->details->uname, node->details->id, "OFFLINE\n"); } if (group_by_node) { GListPtr lpc2 = NULL; fprintf(stream, "
      \n"); for (lpc2 = node->details->running_rsc; lpc2 != NULL; lpc2 = lpc2->next) { resource_t *rsc = (resource_t *) lpc2->data; fprintf(stream, "
    • "); rsc->fns->print(rsc, NULL, pe_print_html | pe_print_rsconly, stream); fprintf(stream, "
    • \n"); } fprintf(stream, "
    \n"); } fprintf(stream, "
  • \n"); } fprintf(stream, "
\n"); if (group_by_node && inactive_resources) { fprintf(stream, "

Inactive Resources

\n"); } else if (group_by_node == FALSE) { fprintf(stream, "

Resource List

\n"); } if (group_by_node == FALSE || inactive_resources) { for (gIter = data_set->resources; gIter != NULL; gIter = gIter->next) { resource_t *rsc = (resource_t *) gIter->data; gboolean is_active = rsc->fns->active(rsc, TRUE); gboolean partially_active = rsc->fns->active(rsc, FALSE); if (is_set(rsc->flags, pe_rsc_orphan) && is_active == FALSE) { continue; } else if (group_by_node == FALSE) { if (partially_active || inactive_resources) { rsc->fns->print(rsc, NULL, pe_print_html, stream); } } else if (is_active == FALSE && inactive_resources) { rsc->fns->print(rsc, NULL, pe_print_html, stream); } } } fprintf(stream, ""); fflush(stream); fclose(stream); if (!web_cgi) { if (rename(filename_tmp, filename) != 0) { crm_perror(LOG_ERR, "Unable to rename %s->%s", filename_tmp, filename); } free(filename_tmp); } return 0; } #if ENABLE_SNMP # include # include # include # include # include # include # define add_snmp_field(list, oid_string, value) do { \ oid name[MAX_OID_LEN]; \ size_t name_length = MAX_OID_LEN; \ if (snmp_parse_oid(oid_string, name, &name_length)) { \ int s_rc = snmp_add_var(list, name, name_length, 's', (value)); \ if(s_rc != 0) { \ crm_err("Could not add %s=%s rc=%d", oid_string, value, s_rc); \ } else { \ crm_trace("Added %s=%s", oid_string, value); \ } \ } else { \ crm_err("Could not parse OID: %s", oid_string); \ } \ } while(0) \ # define add_snmp_field_int(list, oid_string, value) do { \ oid name[MAX_OID_LEN]; \ size_t name_length = MAX_OID_LEN; \ if (snmp_parse_oid(oid_string, name, &name_length)) { \ if(NULL == snmp_pdu_add_variable( \ list, name, name_length, ASN_INTEGER, \ (u_char *) & value, sizeof(value))) { \ crm_err("Could not add %s=%d", oid_string, value); \ } else { \ crm_trace("Added %s=%d", oid_string, value); \ } \ } else { \ crm_err("Could not parse OID: %s", oid_string); \ } \ } while(0) \ static int snmp_input(int operation, netsnmp_session * session, int reqid, netsnmp_pdu * pdu, void *magic) { return 1; } static netsnmp_session * crm_snmp_init(const char *target, char *community) { static netsnmp_session *session = NULL; # ifdef NETSNMPV53 char target53[128]; snprintf(target53, sizeof(target53), "%s:162", target); # endif if (session) { return session; } if (target == NULL) { return NULL; } if (get_crm_log_level() > LOG_INFO) { char *debug_tokens = strdup("run:shell,snmptrap,tdomain"); debug_register_tokens(debug_tokens); snmp_set_do_debugging(1); } session = calloc(1, sizeof(netsnmp_session)); snmp_sess_init(session); session->version = SNMP_VERSION_2c; session->callback = snmp_input; session->callback_magic = NULL; if (community) { session->community_len = strlen(community); session->community = (unsigned char *)community; } session = snmp_add(session, # ifdef NETSNMPV53 netsnmp_tdomain_transport(target53, 0, "udp"), # else netsnmp_transport_open_client("snmptrap", target), # endif NULL, NULL); if (session == NULL) { snmp_sess_perror("Could not create snmp transport", session); } return session; } #endif static int send_snmp_trap(const char *node, const char *rsc, const char *task, int target_rc, int rc, int status, const char *desc) { int ret = 1; #if ENABLE_SNMP static oid snmptrap_oid[] = { 1, 3, 6, 1, 6, 3, 1, 1, 4, 1, 0 }; static oid sysuptime_oid[] = { 1, 3, 6, 1, 2, 1, 1, 3, 0 }; netsnmp_pdu *trap_pdu; netsnmp_session *session = crm_snmp_init(snmp_target, snmp_community); trap_pdu = snmp_pdu_create(SNMP_MSG_TRAP2); if (!trap_pdu) { crm_err("Failed to create SNMP notification"); return SNMPERR_GENERR; } if (1) { /* send uptime */ char csysuptime[20]; time_t now = time(NULL); sprintf(csysuptime, "%ld", now); snmp_add_var(trap_pdu, sysuptime_oid, sizeof(sysuptime_oid) / sizeof(oid), 't', csysuptime); } /* Indicate what the trap is by setting snmpTrapOid.0 */ ret = snmp_add_var(trap_pdu, snmptrap_oid, sizeof(snmptrap_oid) / sizeof(oid), 'o', snmp_crm_trap_oid); if (ret != 0) { crm_err("Failed set snmpTrapOid.0=%s", snmp_crm_trap_oid); return ret; } /* Add extries to the trap */ if (rsc) { add_snmp_field(trap_pdu, snmp_crm_oid_rsc, rsc); } add_snmp_field(trap_pdu, snmp_crm_oid_node, node); add_snmp_field(trap_pdu, snmp_crm_oid_task, task); add_snmp_field(trap_pdu, snmp_crm_oid_desc, desc); add_snmp_field_int(trap_pdu, snmp_crm_oid_rc, rc); add_snmp_field_int(trap_pdu, snmp_crm_oid_trc, target_rc); add_snmp_field_int(trap_pdu, snmp_crm_oid_status, status); /* Send and cleanup */ ret = snmp_send(session, trap_pdu); if (ret == 0) { /* error */ snmp_sess_perror("Could not send SNMP trap", session); snmp_free_pdu(trap_pdu); ret = SNMPERR_GENERR; } else { ret = SNMPERR_SUCCESS; } #else crm_err("Sending SNMP traps is not supported by this installation"); #endif return ret; } #if ENABLE_ESMTP # include # include static void print_recipient_status(smtp_recipient_t recipient, const char *mailbox, void *arg) { const smtp_status_t *status; status = smtp_recipient_status(recipient); printf("%s: %d %s", mailbox, status->code, status->text); } static void event_cb(smtp_session_t session, int event_no, void *arg, ...) { int *ok; va_list alist; va_start(alist, arg); switch (event_no) { case SMTP_EV_CONNECT: case SMTP_EV_MAILSTATUS: case SMTP_EV_RCPTSTATUS: case SMTP_EV_MESSAGEDATA: case SMTP_EV_MESSAGESENT: case SMTP_EV_DISCONNECT: break; case SMTP_EV_WEAK_CIPHER:{ int bits = va_arg(alist, long); ok = va_arg(alist, int *); crm_debug("SMTP_EV_WEAK_CIPHER, bits=%d - accepted.", bits); *ok = 1; break; } case SMTP_EV_STARTTLS_OK: crm_debug("SMTP_EV_STARTTLS_OK - TLS started here."); break; case SMTP_EV_INVALID_PEER_CERTIFICATE:{ long vfy_result = va_arg(alist, long); ok = va_arg(alist, int *); /* There is a table in handle_invalid_peer_certificate() of mail-file.c */ crm_err("SMTP_EV_INVALID_PEER_CERTIFICATE: %ld", vfy_result); *ok = 1; break; } case SMTP_EV_NO_PEER_CERTIFICATE: ok = va_arg(alist, int *); crm_debug("SMTP_EV_NO_PEER_CERTIFICATE - accepted."); *ok = 1; break; case SMTP_EV_WRONG_PEER_CERTIFICATE: ok = va_arg(alist, int *); crm_debug("SMTP_EV_WRONG_PEER_CERTIFICATE - accepted."); *ok = 1; break; case SMTP_EV_NO_CLIENT_CERTIFICATE: ok = va_arg(alist, int *); crm_debug("SMTP_EV_NO_CLIENT_CERTIFICATE - accepted."); *ok = 1; break; default: crm_debug("Got event: %d - ignored.\n", event_no); } va_end(alist); } #endif #define BODY_MAX 2048 #if ENABLE_ESMTP static void crm_smtp_debug(const char *buf, int buflen, int writing, void *arg) { char type = 0; int lpc = 0, last = 0, level = *(int *)arg; if (writing == SMTP_CB_HEADERS) { type = 'H'; } else if (writing) { type = 'C'; } else { type = 'S'; } for (; lpc < buflen; lpc++) { switch (buf[lpc]) { case 0: case '\n': if (last > 0) { do_crm_log(level, " %.*s", lpc - last, buf + last); } else { do_crm_log(level, "%c: %.*s", type, lpc - last, buf + last); } last = lpc + 1; break; } } } #endif static int send_custom_trap(const char *node, const char *rsc, const char *task, int target_rc, int rc, int status, const char *desc) { pid_t pid; /*setenv needs chars, these are ints */ char *rc_s = crm_itoa(rc); char *status_s = crm_itoa(status); char *target_rc_s = crm_itoa(target_rc); crm_debug("Sending external notification to '%s' via '%s'", external_recipient, external_agent); setenv("CRM_notify_recipient", external_recipient, 1); setenv("CRM_notify_node", node, 1); setenv("CRM_notify_rsc", rsc, 1); setenv("CRM_notify_task", task, 1); setenv("CRM_notify_desc", desc, 1); setenv("CRM_notify_rc", rc_s, 1); setenv("CRM_notify_target_rc", target_rc_s, 1); setenv("CRM_notify_status", status_s, 1); pid = fork(); if (pid == -1) { crm_perror(LOG_ERR, "notification fork() failed."); } if (pid == 0) { /* crm_debug("notification: I am the child. Executing the nofitication program."); */ execl(external_agent, external_agent, NULL); } crm_trace("Finished running custom notification program '%s'.", external_agent); free(target_rc_s); free(status_s); free(rc_s); return 0; } static int send_smtp_trap(const char *node, const char *rsc, const char *task, int target_rc, int rc, int status, const char *desc) { #if ENABLE_ESMTP smtp_session_t session; smtp_message_t message; auth_context_t authctx; struct sigaction sa; int len = 20; int noauth = 1; int smtp_debug = LOG_DEBUG; char crm_mail_body[BODY_MAX]; char *crm_mail_subject = NULL; memset(&sa, 0, sizeof(struct sigaction)); if (node == NULL) { node = "-"; } if (rsc == NULL) { rsc = "-"; } if (desc == NULL) { desc = "-"; } if (crm_mail_to == NULL) { return 1; } if (crm_mail_host == NULL) { crm_mail_host = "localhost:25"; } if (crm_mail_prefix == NULL) { crm_mail_prefix = "Cluster notification"; } crm_debug("Sending '%s' mail to %s via %s", crm_mail_prefix, crm_mail_to, crm_mail_host); len += strlen(crm_mail_prefix); len += strlen(task); len += strlen(rsc); len += strlen(node); len += strlen(desc); len++; crm_mail_subject = calloc(1, len); snprintf(crm_mail_subject, len, "%s - %s event for %s on %s: %s\r\n", crm_mail_prefix, task, rsc, node, desc); len = 0; len += snprintf(crm_mail_body + len, BODY_MAX - len, "\r\n%s\r\n", crm_mail_prefix); len += snprintf(crm_mail_body + len, BODY_MAX - len, "====\r\n\r\n"); if (rc == target_rc) { len += snprintf(crm_mail_body + len, BODY_MAX - len, "Completed operation %s for resource %s on %s\r\n", task, rsc, node); } else { len += snprintf(crm_mail_body + len, BODY_MAX - len, "Operation %s for resource %s on %s failed: %s\r\n", task, rsc, node, desc); } len += snprintf(crm_mail_body + len, BODY_MAX - len, "\r\nDetails:\r\n"); len += snprintf(crm_mail_body + len, BODY_MAX - len, "\toperation status: (%d) %s\r\n", status, services_lrm_status_str(status)); if (status == PCMK_LRM_OP_DONE) { len += snprintf(crm_mail_body + len, BODY_MAX - len, "\tscript returned: (%d) %s\r\n", rc, lrmd_event_rc2str(rc)); len += snprintf(crm_mail_body + len, BODY_MAX - len, "\texpected return value: (%d) %s\r\n", target_rc, lrmd_event_rc2str(target_rc)); } auth_client_init(); session = smtp_create_session(); message = smtp_add_message(session); smtp_starttls_enable(session, Starttls_ENABLED); sa.sa_handler = SIG_IGN; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sigaction(SIGPIPE, &sa, NULL); smtp_set_server(session, crm_mail_host); authctx = auth_create_context(); auth_set_mechanism_flags(authctx, AUTH_PLUGIN_PLAIN, 0); smtp_set_eventcb(session, event_cb, NULL); /* Now tell libESMTP it can use the SMTP AUTH extension. */ if (!noauth) { crm_debug("Adding authentication context"); smtp_auth_set_context(session, authctx); } if (crm_mail_from == NULL) { struct utsname us; char auto_from[BODY_MAX]; CRM_ASSERT(uname(&us) == 0); snprintf(auto_from, BODY_MAX, "crm_mon@%s", us.nodename); smtp_set_reverse_path(message, auto_from); } else { /* NULL is ok */ smtp_set_reverse_path(message, crm_mail_from); } smtp_set_header(message, "To", NULL /*phrase */ , NULL /*addr */ ); /* "Phrase" */ smtp_add_recipient(message, crm_mail_to); /* Set the Subject: header and override any subject line in the message headers. */ smtp_set_header(message, "Subject", crm_mail_subject); smtp_set_header_option(message, "Subject", Hdr_OVERRIDE, 1); smtp_set_message_str(message, crm_mail_body); smtp_set_monitorcb(session, crm_smtp_debug, &smtp_debug, 1); if (smtp_start_session(session)) { char buf[128]; int rc = smtp_errno(); crm_err("SMTP server problem: %s (%d)", smtp_strerror(rc, buf, sizeof buf), rc); } else { char buf[128]; int rc = smtp_errno(); const smtp_status_t *smtp_status = smtp_message_transfer_status(message); if (rc != 0) { crm_err("SMTP server problem: %s (%d)", smtp_strerror(rc, buf, sizeof buf), rc); } crm_info("Send status: %d %s", smtp_status->code, crm_str(smtp_status->text)); smtp_enumerate_recipients(message, print_recipient_status, NULL); } smtp_destroy_session(session); auth_destroy_context(authctx); auth_client_exit(); #endif return 0; } static void handle_rsc_op(xmlNode * rsc_op) { int rc = -1; int status = -1; int action = -1; int interval = 0; int target_rc = -1; int transition_num = -1; gboolean notify = TRUE; char *rsc = NULL; char *task = NULL; const char *desc = NULL; const char *node = NULL; const char *magic = NULL; const char *id = crm_element_value(rsc_op, XML_LRM_ATTR_TASK_KEY); char *update_te_uuid = NULL; xmlNode *n = rsc_op; if (id == NULL) { /* Compatability with <= 1.1.5 */ id = ID(rsc_op); } magic = crm_element_value(rsc_op, XML_ATTR_TRANSITION_MAGIC); if (magic == NULL) { /* non-change */ return; } if (FALSE == decode_transition_magic(magic, &update_te_uuid, &transition_num, &action, &status, &rc, &target_rc)) { crm_err("Invalid event %s detected for %s", magic, id); return; } if (parse_op_key(id, &rsc, &task, &interval) == FALSE) { crm_err("Invalid event detected for %s", id); goto bail; } while (n != NULL && safe_str_neq(XML_CIB_TAG_STATE, TYPE(n))) { n = n->parent; } node = crm_element_value(n, XML_ATTR_UNAME); if (node == NULL) { node = ID(n); } if (node == NULL) { crm_err("No node detected for event %s (%s)", magic, id); goto bail; } /* look up where we expected it to be? */ desc = pcmk_strerror(pcmk_ok); if (status == PCMK_LRM_OP_DONE && target_rc == rc) { crm_notice("%s of %s on %s completed: %s", task, rsc, node, desc); if (rc == PCMK_EXECRA_NOT_RUNNING) { notify = FALSE; } } else if (status == PCMK_LRM_OP_DONE) { desc = lrmd_event_rc2str(rc); crm_warn("%s of %s on %s failed: %s", task, rsc, node, desc); } else { desc = services_lrm_status_str(status); crm_warn("%s of %s on %s failed: %s", task, rsc, node, desc); } if (notify && snmp_target) { send_snmp_trap(node, rsc, task, target_rc, rc, status, desc); } if (notify && crm_mail_to) { send_smtp_trap(node, rsc, task, target_rc, rc, status, desc); } if (notify && external_agent) { send_custom_trap(node, rsc, task, target_rc, rc, status, desc); } bail: free(update_te_uuid); free(rsc); free(task); } void crm_diff_update(const char *event, xmlNode * msg) { int rc = -1; long now = time(NULL); static bool stale = FALSE; print_dot(); if (current_cib != NULL) { xmlNode *cib_last = current_cib; current_cib = NULL; rc = cib_apply_patch_event(msg, cib_last, ¤t_cib, LOG_DEBUG); free_xml(cib_last); switch (rc) { case -pcmk_err_diff_resync: case -pcmk_err_diff_failed: crm_notice("[%s] Patch aborted: %s (%d)", event, pcmk_strerror(rc), rc); case pcmk_ok: break; default: crm_notice("[%s] ABORTED: %s (%d)", event, pcmk_strerror(rc), rc); } } if (current_cib == NULL) { current_cib = get_cib_copy(cib); } if (crm_mail_to || snmp_target || external_agent) { /* Process operation updates */ xmlXPathObject *xpathObj = xpath_search(msg, "//" F_CIB_UPDATE_RESULT "//" XML_TAG_DIFF_ADDED "//" XML_LRM_TAG_RSC_OP); int lpc = 0, max = numXpathResults(xpathObj); for (lpc = 0; lpc < max; lpc++) { xmlNode *rsc_op = getXpathResult(xpathObj, lpc); handle_rsc_op(rsc_op); } freeXpathObject(xpathObj); } if (current_cib == NULL) { if(!stale) { print_as("--- Stale data ---"); } stale = TRUE; return; } stale = FALSE; if ((now - last_refresh) > (reconnect_msec / 1000)) { /* Force a refresh */ mon_refresh_display(NULL); } else { mainloop_set_trigger(refresh_trigger); } } gboolean mon_refresh_display(gpointer user_data) { xmlNode *cib_copy = copy_xml(current_cib); pe_working_set_t data_set; last_refresh = time(NULL); if (cli_config_update(&cib_copy, NULL, FALSE) == FALSE) { if (cib) { cib->cmds->signoff(cib); } print_as("Upgrade failed: %s", pcmk_strerror(-pcmk_err_dtd_validation)); if (as_console) { sleep(2); } clean_up(EX_USAGE); return FALSE; } set_working_set_defaults(&data_set); data_set.input = cib_copy; cluster_status(&data_set); if (as_html_file || web_cgi) { if (print_html_status(&data_set, as_html_file, web_cgi) != 0) { fprintf(stderr, "Critical: Unable to output html file\n"); clean_up(EX_USAGE); } } else if (as_xml) { if (print_xml_status(&data_set) != 0) { fprintf(stderr, "Critical: Unable to output xml file\n"); clean_up(EX_USAGE); } } else if (daemonize) { /* do nothing */ } else if (simple_status) { print_simple_status(&data_set); if (has_warnings) { clean_up(EX_USAGE); } } else { print_status(&data_set); } cleanup_calculations(&data_set); return TRUE; } void mon_st_callback(stonith_t * st, stonith_event_t * e) { char *desc = g_strdup_printf("Operation %s requested by %s for peer %s: %s (ref=%s)", e->operation, e->origin, e->target, pcmk_strerror(e->result), e->id); if (snmp_target) { send_snmp_trap(e->target, NULL, e->operation, pcmk_ok, e->result, 0, desc); } if (crm_mail_to) { send_smtp_trap(e->target, NULL, e->operation, pcmk_ok, e->result, 0, desc); } if (external_agent) { send_custom_trap(e->target, NULL, e->operation, pcmk_ok, e->result, 0, desc); } g_free(desc); } /* * De-init ncurses, signoff from the CIB and deallocate memory. */ void clean_up(int rc) { #if ENABLE_SNMP netsnmp_session *session = crm_snmp_init(NULL, NULL); if (session) { snmp_close(session); snmp_shutdown("snmpapp"); } #endif #if CURSES_ENABLED if (as_console) { as_console = FALSE; echo(); nocbreak(); endwin(); } #endif if (cib != NULL) { cib->cmds->signoff(cib); cib_delete(cib); cib = NULL; } free(as_html_file); free(xml_file); free(pid_file); if (rc >= 0) { crm_exit(rc); } return; }