commit a33aadaf14f1e0cc2fb9d025801a2d86e3732275 Author: Gao,Yan Date: Mon Jan 13 20:03:28 2014 +0800 Feature: tools: Display pending state in crm_mon/crm_resource/crm_simulate if --pending/-j is supplied (cl#5178) diff --git a/include/crm/pengine/common.h b/include/crm/pengine/common.h index 2477e47..c1901ef 100644 --- a/include/crm/pengine/common.h +++ b/include/crm/pengine/common.h @@ -97,6 +97,7 @@ enum pe_print_options { pe_print_ops = 0x0100, pe_print_suppres_nl = 0x0200, pe_print_xml = 0x0400, + pe_print_pending = 0x0800, }; /* *INDENT-ON* */ diff --git a/include/crm/pengine/status.h b/include/crm/pengine/status.h index 3f3de17..3a380cc 100644 --- a/include/crm/pengine/status.h +++ b/include/crm/pengine/status.h @@ -275,6 +275,8 @@ struct resource_s { resource_t *container; GListPtr fillers; + + char *pending_task; }; struct pe_action_s { diff --git a/lib/pengine/complex.c b/lib/pengine/complex.c index 2ada463..a592fc8 100644 --- a/lib/pengine/complex.c +++ b/lib/pengine/complex.c @@ -743,5 +743,6 @@ common_free(resource_t * rsc) free(rsc->clone_name); free(rsc->allocated_to); free(rsc->variant_opaque); + free(rsc->pending_task); free(rsc); } diff --git a/lib/pengine/native.c b/lib/pengine/native.c index adfd5ba..be95ba1 100644 --- a/lib/pengine/native.c +++ b/lib/pengine/native.c @@ -291,12 +291,60 @@ native_print_attr(gpointer key, gpointer value, gpointer user_data) status_print("Option: %s = %s\n", (char *)key, (char *)value); } +static const char * +native_pending_state(resource_t * rsc) +{ + const char *pending_state = NULL; + + if (safe_str_eq(rsc->pending_task, CRMD_ACTION_START)) { + pending_state = "Starting"; + + } else if (safe_str_eq(rsc->pending_task, CRMD_ACTION_STOP)) { + pending_state = "Stopping"; + + } else if (safe_str_eq(rsc->pending_task, CRMD_ACTION_MIGRATE)) { + pending_state = "Migrating"; + + } else if (safe_str_eq(rsc->pending_task, CRMD_ACTION_MIGRATED)) { + /* Work might be done in here. */ + pending_state = "Migrating"; + + } else if (safe_str_eq(rsc->pending_task, CRMD_ACTION_PROMOTE)) { + pending_state = "Promoting"; + + } else if (safe_str_eq(rsc->pending_task, CRMD_ACTION_DEMOTE)) { + pending_state = "Demoting"; + } + + return pending_state; +} + +static const char * +native_pending_task(resource_t * rsc) +{ + const char *pending_task = NULL; + + if (safe_str_eq(rsc->pending_task, CRMD_ACTION_NOTIFY)) { + /* "Notifying" is not very useful to be shown. */ + pending_task = NULL; + + } else if (safe_str_eq(rsc->pending_task, CRMD_ACTION_STATUS)) { + pending_task = "Monitoring"; + + } else if (safe_str_eq(rsc->pending_task, "probe")) { + pending_task = "Checking"; + } + + return pending_task; +} + static void native_print_xml(resource_t * rsc, const char *pre_text, long options, void *print_data) { enum rsc_role_e role = rsc->role; const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS); const char *prov = crm_element_value(rsc->xml, XML_AGENT_ATTR_PROVIDER); + const char *rsc_state = NULL; if(role == RSC_ROLE_STARTED && uber_parent(rsc)->variant == pe_master) { role = RSC_ROLE_SLAVE; @@ -308,7 +356,14 @@ native_print_xml(resource_t * rsc, const char *pre_text, long options, void *pri 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(role)); + + if (options & pe_print_pending) { + rsc_state = native_pending_state(rsc); + } + if (rsc_state == NULL) { + rsc_state = role2text(role); + } + status_print("role=\"%s\" ", rsc_state); status_print("active=\"%s\" ", rsc->fns->active(rsc, TRUE) ? "true" : "false"); status_print("orphaned=\"%s\" ", is_set(rsc->flags, pe_rsc_orphan) ? "true" : "false"); status_print("managed=\"%s\" ", is_set(rsc->flags, pe_rsc_managed) ? "true" : "false"); @@ -317,6 +372,14 @@ native_print_xml(resource_t * rsc, const char *pre_text, long options, void *pri is_set(rsc->flags, pe_rsc_failure_ignored) ? "true" : "false"); status_print("nodes_running_on=\"%d\" ", g_list_length(rsc->running_on)); + if (options & pe_print_pending) { + const char *pending_task = native_pending_task(rsc); + + if (pending_task) { + status_print("pending=\"%s\" ", pending_task); + } + } + if (options & pe_print_dev) { status_print("provisional=\"%s\" ", is_set(rsc->flags, pe_rsc_provisional) ? "true" : "false"); @@ -423,12 +486,29 @@ native_print(resource_t * rsc, const char *pre_text, long options, void *print_d } else if(is_set(rsc->flags, pe_rsc_failed)) { offset += snprintf(buffer + offset, LINE_MAX - offset, "FAILED "); } else { - offset += snprintf(buffer + offset, LINE_MAX - offset, "%s ", role2text(rsc->role)); + const char *rsc_state = NULL; + + if (options & pe_print_pending) { + rsc_state = native_pending_state(rsc); + } + if (rsc_state == NULL) { + rsc_state = role2text(rsc->role); + } + offset += snprintf(buffer + offset, LINE_MAX - offset, "%s ", rsc_state); } if(node) { offset += snprintf(buffer + offset, LINE_MAX - offset, "%s ", node->details->uname); } + + if (options & pe_print_pending) { + const char *pending_task = native_pending_task(rsc); + + if (pending_task) { + offset += snprintf(buffer + offset, LINE_MAX - offset, "(%s) ", pending_task); + } + } + if(is_not_set(rsc->flags, pe_rsc_managed)) { offset += snprintf(buffer + offset, LINE_MAX - offset, "(unmanaged) "); } diff --git a/lib/pengine/unpack.c b/lib/pengine/unpack.c index aaa9a67..57960cc 100644 --- a/lib/pengine/unpack.c +++ b/lib/pengine/unpack.c @@ -2757,6 +2757,7 @@ unpack_rsc_op(resource_t * rsc, node_t * node, xmlNode * xml_op, int rc = 0; int status = PCMK_LRM_OP_PENDING-1; int target_rc = get_target_rc(xml_op); + int interval = 0; gboolean expired = FALSE; resource_t *parent = rsc; @@ -2774,6 +2775,7 @@ unpack_rsc_op(resource_t * rsc, node_t * node, xmlNode * xml_op, crm_element_value_int(xml_op, XML_LRM_ATTR_RC, &rc); crm_element_value_int(xml_op, XML_LRM_ATTR_CALLID, &task_id); crm_element_value_int(xml_op, XML_LRM_ATTR_OPSTATUS, &status); + crm_element_value_int(xml_op, XML_LRM_ATTR_INTERVAL, &interval); CRM_CHECK(task != NULL, return FALSE); CRM_CHECK(status <= PCMK_LRM_OP_NOT_INSTALLED, return FALSE); @@ -2807,7 +2809,6 @@ unpack_rsc_op(resource_t * rsc, node_t * node, xmlNode * xml_op, } if (expired && target_rc != rc) { - int interval = 0; const char *magic = crm_element_value(xml_op, XML_ATTR_TRANSITION_MAGIC); pe_rsc_debug(rsc, "Expired operation '%s' on %s returned '%s' (%d) instead of the expected value: '%s' (%d)", @@ -2815,7 +2816,6 @@ unpack_rsc_op(resource_t * rsc, node_t * node, xmlNode * xml_op, services_ocf_exitcode_str(rc), rc, services_ocf_exitcode_str(target_rc), target_rc); - crm_element_value_int(xml_op, XML_LRM_ATTR_INTERVAL, &interval); if(interval == 0) { crm_notice("Ignoring expired calculated failure %s (rc=%d, magic=%s) on %s", task_key, rc, magic, node->details->uname); @@ -2858,6 +2858,14 @@ unpack_rsc_op(resource_t * rsc, node_t * node, xmlNode * xml_op, stop_action(rsc, target, FALSE); } } + + if (safe_str_eq(task, CRMD_ACTION_STATUS) && interval == 0) { + /* Temporarily comment this out until cl#5184 is fixed */ + /*rsc->pending_task = strdup("probe");*/ + + } else { + rsc->pending_task = strdup(task); + } break; case PCMK_LRM_OP_DONE: diff --git a/tools/crm_mon.c b/tools/crm_mon.c index a9dd1b7..746094f 100644 --- a/tools/crm_mon.c +++ b/tools/crm_mon.c @@ -96,6 +96,7 @@ gboolean print_last_change = TRUE; gboolean print_tickets = FALSE; gboolean watch_fencing = FALSE; gboolean hide_headers = FALSE; +gboolean print_pending = FALSE; /* FIXME allow, detect, and correctly interpret glob pattern or regex? */ const char *print_neg_location_prefix; @@ -340,6 +341,7 @@ static struct crm_option long_options[] = { {"neg-locations", 2, 0, 'L', "Display negative location constraints [optionally filtered by id prefix]"}, {"show-node-attributes", 0, 0, 'A', "Display node attributes" }, {"hide-headers", 0, 0, 'D', "\tHide all headers" }, + {"pending", 0, 0, 'j', "\t\tDisplay pending state if 'record-pending' is enabled" }, {"-spacer-", 1, 0, '-', "\nAdditional Options:"}, {"interval", 1, 0, 'i', "\tUpdate frequency in seconds" }, @@ -449,6 +451,9 @@ detect_user_input(GIOChannel *channel, GIOCondition condition, gpointer unused) case 'D': hide_headers = ! hide_headers; break; + case 'j': + print_pending = ! print_pending; + break; case '?': config_mode = TRUE; break; @@ -472,6 +477,7 @@ detect_user_input(GIOChannel *channel, GIOCondition condition, gpointer unused) print_as("%c A: \t%s\n", print_nodes_attr ? '*': ' ', get_option_desc('A')); print_as("%c L: \t%s\n", print_neg_location_prefix ? '*': ' ', get_option_desc('L')); print_as("%c D: \t%s\n", hide_headers ? '*': ' ', get_option_desc('D')); + print_as("%c j: \t%s\n", print_pending ? '*': ' ', get_option_desc('j')); print_as("\n"); print_as("Toggle fields via field letter, type any other key to return"); } @@ -550,6 +556,9 @@ main(int argc, char **argv) case 'L': print_neg_location_prefix = optarg ?: ""; break; + case 'j': + print_pending = TRUE; + break; case 'D': hide_headers = TRUE; break; @@ -1159,6 +1168,10 @@ print_status(pe_working_set_t * data_set) print_opts = pe_print_printf; } + if (print_pending) { + print_opts |= pe_print_pending; + } + updates++; dc = data_set->dc_node; @@ -1463,9 +1476,14 @@ print_xml_status(pe_working_set_t * data_set) xmlNode *stack = NULL; xmlNode *quorum_node = NULL; const char *quorum_votes = "unknown"; + int print_opts = pe_print_xml; dc = data_set->dc_node; + if (print_pending) { + print_opts |= pe_print_pending; + } + fprintf(stream, "\n"); fprintf(stream, "\n", VERSION); @@ -1567,7 +1585,7 @@ print_xml_status(pe_working_set_t * data_set) 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); + rsc->fns->print(rsc, " ", print_opts | pe_print_rsconly, stream); } fprintf(stream, " \n"); } else { @@ -1589,11 +1607,11 @@ print_xml_status(pe_working_set_t * data_set) } else if (group_by_node == FALSE) { if (partially_active || inactive_resources) { - rsc->fns->print(rsc, " ", pe_print_xml, stream); + rsc->fns->print(rsc, " ", print_opts, stream); } } else if (is_active == FALSE && inactive_resources) { - rsc->fns->print(rsc, " ", pe_print_xml, stream); + rsc->fns->print(rsc, " ", print_opts, stream); } } fprintf(stream, " \n"); @@ -1614,6 +1632,11 @@ print_html_status(pe_working_set_t * data_set, const char *filename, gboolean we node_t *dc = NULL; static int updates = 0; char *filename_tmp = NULL; + int print_opts = pe_print_html; + + if (print_pending) { + print_opts |= pe_print_pending; + } if (web_cgi) { stream = stdout; @@ -1725,7 +1748,7 @@ print_html_status(pe_working_set_t * data_set, const char *filename, gboolean we resource_t *rsc = (resource_t *) lpc2->data; fprintf(stream, "
  • "); - rsc->fns->print(rsc, NULL, pe_print_html | pe_print_rsconly, stream); + rsc->fns->print(rsc, NULL, print_opts | pe_print_rsconly, stream); fprintf(stream, "
  • \n"); } fprintf(stream, "\n"); @@ -1752,11 +1775,11 @@ print_html_status(pe_working_set_t * data_set, const char *filename, gboolean we } else if (group_by_node == FALSE) { if (partially_active || inactive_resources) { - rsc->fns->print(rsc, NULL, pe_print_html, stream); + rsc->fns->print(rsc, NULL, print_opts, stream); } } else if (is_active == FALSE && inactive_resources) { - rsc->fns->print(rsc, NULL, pe_print_html, stream); + rsc->fns->print(rsc, NULL, print_opts, stream); } } } diff --git a/tools/crm_resource.c b/tools/crm_resource.c index bd576cc..b2cab67 100644 --- a/tools/crm_resource.c +++ b/tools/crm_resource.c @@ -64,6 +64,7 @@ char *xml_file = NULL; int cib_options = cib_sync_call; int crmd_replies_needed = 1; /* The welcome message */ GMainLoop *mainloop = NULL; +gboolean print_pending = FALSE; extern void cleanup_alloc_calculations(pe_working_set_t * data_set); @@ -284,6 +285,11 @@ do_find_resource_list(pe_working_set_t * data_set, gboolean raw) int found = 0; GListPtr lpc = NULL; + int opts = pe_print_printf | pe_print_rsconly; + + if (print_pending) { + opts |= pe_print_pending; + } for (lpc = data_set->resources; lpc != NULL; lpc = lpc->next) { resource_t *rsc = (resource_t *) lpc->data; @@ -292,7 +298,7 @@ do_find_resource_list(pe_working_set_t * data_set, gboolean raw) && rsc->fns->active(rsc, TRUE) == FALSE) { continue; } - rsc->fns->print(rsc, NULL, pe_print_printf | pe_print_rsconly, stdout); + rsc->fns->print(rsc, NULL, opts, stdout); found++; } @@ -323,11 +329,16 @@ dump_resource(const char *rsc, pe_working_set_t * data_set, gboolean expanded) { char *rsc_xml = NULL; resource_t *the_rsc = find_rsc_or_clone(rsc, data_set); + int opts = pe_print_printf; if (the_rsc == NULL) { return -ENXIO; } - the_rsc->fns->print(the_rsc, NULL, pe_print_printf, stdout); + + if (print_pending) { + opts |= pe_print_pending; + } + the_rsc->fns->print(the_rsc, NULL, opts, stdout); if (expanded) { rsc_xml = dump_xml_formatted(the_rsc->xml); @@ -1088,6 +1099,10 @@ list_resource_operations(const char *rsc_id, const char *host_uname, gboolean ac GListPtr ops = find_operations(rsc_id, host_uname, active, data_set); GListPtr lpc = NULL; + if (print_pending) { + opts |= pe_print_pending; + } + for (lpc = ops; lpc != NULL; lpc = lpc->next) { xmlNode *xml_op = (xmlNode *) lpc->data; @@ -1275,7 +1290,8 @@ static struct crm_option long_options[] = { {"list-raw", 0, 0, 'l', "\tList the IDs of all instantiated resources (no groups/clones/...)"}, {"list-cts", 0, 0, 'c', NULL, 1}, {"list-operations", 0, 0, 'O', "\tList active resource operations. Optionally filtered by resource (-r) and/or node (-N)"}, - {"list-all-operations", 0, 0, 'o', "List all resource operations. Optionally filtered by resource (-r) and/or node (-N)\n"}, + {"list-all-operations", 0, 0, 'o', "List all resource operations. Optionally filtered by resource (-r) and/or node (-N)"}, + {"pending", 0, 0, 'j', "\t\tDisplay pending state if 'record-pending' is enabled\n"}, {"list-standards", 0, 0, 0, "\tList supported standards"}, {"list-ocf-providers", 0, 0, 0, "List all available OCF providers"}, @@ -1598,6 +1614,9 @@ main(int argc, char **argv) case 'a': rsc_cmd = flag; break; + case 'j': + print_pending = TRUE; + break; case 'p': case 'g': case 'd': diff --git a/tools/crm_simulate.c b/tools/crm_simulate.c index 61065c4..0956141 100644 --- a/tools/crm_simulate.c +++ b/tools/crm_simulate.c @@ -39,6 +39,7 @@ cib_t *global_cib = NULL; GListPtr op_fail = NULL; gboolean quiet = FALSE; gboolean bringing_nodes_online = FALSE; +gboolean print_pending = FALSE; #define new_node_template "//"XML_CIB_TAG_NODE"[@uname='%s']" #define node_template "//"XML_CIB_TAG_STATE"[@uname='%s']" @@ -528,7 +529,7 @@ exec_stonith_action(crm_graph_t * graph, crm_action_t * action) } static void -print_cluster_status(pe_working_set_t * data_set) +print_cluster_status(pe_working_set_t * data_set, long options) { char *online_nodes = NULL; char *online_remote_nodes = NULL; @@ -649,7 +650,7 @@ print_cluster_status(pe_working_set_t * data_set) && rsc->role == RSC_ROLE_STOPPED) { continue; } - rsc->fns->print(rsc, NULL, pe_print_printf, stdout); + rsc->fns->print(rsc, NULL, pe_print_printf | options, stdout); } fprintf(stdout, "\n"); } @@ -701,7 +702,7 @@ run_simulation(pe_working_set_t * data_set) data_set->now = get_date(); cluster_status(data_set); - print_cluster_status(data_set); + print_cluster_status(data_set, 0); } if (graph_rc != transition_complete) { @@ -1201,6 +1202,7 @@ static struct crm_option long_options[] = { {"show-scores", 0, 0, 's', "Show allocation scores"}, {"show-utilization", 0, 0, 'U', "Show utilization information"}, {"profile", 1, 0, 'P', "Run all tests in the named directory to create profiling data"}, + {"pending", 0, 0, 'j', "\tDisplay pending state if 'record-pending' is enabled"}, {"-spacer-", 0, 0, '-', "\nSynthetic Cluster Events:"}, {"node-up", 1, 0, 'u', "\tBring a node online"}, @@ -1447,6 +1449,9 @@ main(int argc, char **argv) process = TRUE; show_utilization = TRUE; break; + case 'j': + print_pending = TRUE; + break; case 'S': process = TRUE; simulate = TRUE; @@ -1515,8 +1520,10 @@ main(int argc, char **argv) cluster_status(&data_set); if (quiet == FALSE) { + int options = print_pending ? pe_print_pending : 0; + quiet_log("\nCurrent cluster status:\n"); - print_cluster_status(&data_set); + print_cluster_status(&data_set, options); } if (modified) {