diff options
Diffstat (limited to '')
-rw-r--r-- | tools/crm_resource_runtime.c | 540 |
1 files changed, 303 insertions, 237 deletions
diff --git a/tools/crm_resource_runtime.c b/tools/crm_resource_runtime.c index f25dbbc..da360fd 100644 --- a/tools/crm_resource_runtime.c +++ b/tools/crm_resource_runtime.c @@ -16,22 +16,22 @@ #include <crm/services_internal.h> static GList * -build_node_info_list(const pe_resource_t *rsc) +build_node_info_list(const pcmk_resource_t *rsc) { GList *retval = NULL; for (const GList *iter = rsc->children; iter != NULL; iter = iter->next) { - const pe_resource_t *child = (const pe_resource_t *) iter->data; + const pcmk_resource_t *child = (const pcmk_resource_t *) iter->data; for (const GList *iter2 = child->running_on; iter2 != NULL; iter2 = iter2->next) { - const pe_node_t *node = (const pe_node_t *) iter2->data; + const pcmk_node_t *node = (const pcmk_node_t *) iter2->data; node_info_t *ni = calloc(1, sizeof(node_info_t)); ni->node_name = node->details->uname; - ni->promoted = pcmk_is_set(rsc->flags, pe_rsc_promotable) && - child->fns->state(child, TRUE) == RSC_ROLE_PROMOTED; + ni->promoted = pcmk_is_set(rsc->flags, pcmk_rsc_promotable) && + child->fns->state(child, TRUE) == pcmk_role_promoted; retval = g_list_prepend(retval, ni); } @@ -41,18 +41,18 @@ build_node_info_list(const pe_resource_t *rsc) } GList * -cli_resource_search(pe_resource_t *rsc, const char *requested_name, - pe_working_set_t *data_set) +cli_resource_search(pcmk_resource_t *rsc, const char *requested_name, + pcmk_scheduler_t *scheduler) { GList *retval = NULL; - const pe_resource_t *parent = pe__const_top_resource(rsc, false); + const pcmk_resource_t *parent = pe__const_top_resource(rsc, false); if (pe_rsc_is_clone(rsc)) { retval = build_node_info_list(rsc); /* The anonymous clone children's common ID is supplied */ } else if (pe_rsc_is_clone(parent) - && !pcmk_is_set(rsc->flags, pe_rsc_unique) + && !pcmk_is_set(rsc->flags, pcmk_rsc_unique) && rsc->clone_name && pcmk__str_eq(requested_name, rsc->clone_name, pcmk__str_casei) && !pcmk__str_eq(requested_name, rsc->id, pcmk__str_casei)) { @@ -61,10 +61,10 @@ cli_resource_search(pe_resource_t *rsc, const char *requested_name, } else if (rsc->running_on != NULL) { for (GList *iter = rsc->running_on; iter != NULL; iter = iter->next) { - pe_node_t *node = (pe_node_t *) iter->data; + pcmk_node_t *node = (pcmk_node_t *) iter->data; node_info_t *ni = calloc(1, sizeof(node_info_t)); ni->node_name = node->details->uname; - ni->promoted = (rsc->fns->state(rsc, TRUE) == RSC_ROLE_PROMOTED); + ni->promoted = (rsc->fns->state(rsc, TRUE) == pcmk_role_promoted); retval = g_list_prepend(retval, ni); } @@ -133,7 +133,7 @@ find_resource_attr(pcmk__output_t *out, cib_t * the_cib, const char *attr, } crm_log_xml_debug(xml_search, "Match"); - if (xml_has_children(xml_search)) { + if (xml_search->children != NULL) { xmlNode *child = NULL; rc = ENOTUNIQ; @@ -159,8 +159,9 @@ find_resource_attr(pcmk__output_t *out, cib_t * the_cib, const char *attr, /* PRIVATE. Use the find_matching_attr_resources instead. */ static void -find_matching_attr_resources_recursive(pcmk__output_t *out, GList/* <pe_resource_t*> */ ** result, - pe_resource_t * rsc, const char * rsc_id, +find_matching_attr_resources_recursive(pcmk__output_t *out, + GList /* <pcmk_resource_t*> */ **result, + pcmk_resource_t *rsc, const char *rsc_id, const char * attr_set, const char * attr_set_type, const char * attr_id, const char * attr_name, cib_t * cib, const char * cmd, int depth) @@ -171,18 +172,19 @@ find_matching_attr_resources_recursive(pcmk__output_t *out, GList/* <pe_resource /* visit the children */ for(GList *gIter = rsc->children; gIter; gIter = gIter->next) { - find_matching_attr_resources_recursive(out, result, (pe_resource_t*)gIter->data, + find_matching_attr_resources_recursive(out, result, + (pcmk_resource_t *) gIter->data, rsc_id, attr_set, attr_set_type, attr_id, attr_name, cib, cmd, depth+1); /* do it only once for clones */ - if(pe_clone == rsc->variant) { + if (rsc->variant == pcmk_rsc_variant_clone) { break; } } rc = find_resource_attr(out, cib, XML_ATTR_ID, lookup_id, attr_set_type, attr_set, attr_id, attr_name, &local_attr_id); - /* Post-order traversal. + /* Post-order traversal. * The root is always on the list and it is the last item. */ if((0 == depth) || (pcmk_rc_ok == rc)) { /* push the head */ @@ -195,8 +197,8 @@ find_matching_attr_resources_recursive(pcmk__output_t *out, GList/* <pe_resource /* The result is a linearized pre-ordered tree of resources. */ -static GList/*<pe_resource_t*>*/ * -find_matching_attr_resources(pcmk__output_t *out, pe_resource_t * rsc, +static GList/*<pcmk_resource_t*>*/ * +find_matching_attr_resources(pcmk__output_t *out, pcmk_resource_t *rsc, const char * rsc_id, const char * attr_set, const char * attr_set_type, const char * attr_id, const char * attr_name, cib_t * cib, const char * cmd, @@ -212,7 +214,8 @@ find_matching_attr_resources(pcmk__output_t *out, pe_resource_t * rsc, if(force == TRUE) { return g_list_append(result, rsc); } - if(rsc->parent && pe_clone == rsc->parent->variant) { + if ((rsc->parent != NULL) + && (rsc->parent->variant == pcmk_rsc_variant_clone)) { int rc = pcmk_rc_ok; char *local_attr_id = NULL; rc = find_resource_attr(out, cib, XML_ATTR_ID, rsc_id, attr_set_type, @@ -225,10 +228,12 @@ find_matching_attr_resources(pcmk__output_t *out, pe_resource_t * rsc, cmd, attr_name, rsc->id, rsc_id); } return g_list_append(result, rsc); - } else if(rsc->parent == NULL && rsc->children && pe_clone == rsc->variant) { - pe_resource_t *child = rsc->children->data; - if(child->variant == pe_native) { + } else if ((rsc->parent == NULL) && (rsc->children != NULL) + && (rsc->variant == pcmk_rsc_variant_clone)) { + pcmk_resource_t *child = rsc->children->data; + + if (child->variant == pcmk_rsc_variant_primitive) { lookup_id = clone_strip(child->id); /* Could be a cloned group! */ rc = find_resource_attr(out, cib, XML_ATTR_ID, lookup_id, attr_set_type, attr_set, attr_id, attr_name, &local_attr_id); @@ -253,7 +258,7 @@ find_matching_attr_resources(pcmk__output_t *out, pe_resource_t * rsc, // \return Standard Pacemaker return code int -cli_resource_update_attribute(pe_resource_t *rsc, const char *requested_name, +cli_resource_update_attribute(pcmk_resource_t *rsc, const char *requested_name, const char *attr_set, const char *attr_set_type, const char *attr_id, const char *attr_name, const char *attr_value, gboolean recursive, @@ -264,7 +269,7 @@ cli_resource_update_attribute(pe_resource_t *rsc, const char *requested_name, char *found_attr_id = NULL; - GList/*<pe_resource_t*>*/ *resources = NULL; + GList/*<pcmk_resource_t*>*/ *resources = NULL; const char *top_id = pe__const_top_resource(rsc, false)->id; if ((attr_id == NULL) && !force) { @@ -333,7 +338,7 @@ cli_resource_update_attribute(pe_resource_t *rsc, const char *requested_name, xmlNode *xml_obj = NULL; found_attr_id = NULL; - rsc = (pe_resource_t *) iter->data; + rsc = (pcmk_resource_t *) iter->data; lookup_id = clone_strip(rsc->id); /* Could be a cloned group! */ rc = find_resource_attr(out, cib, XML_ATTR_ID, lookup_id, attr_set_type, @@ -358,7 +363,7 @@ cli_resource_update_attribute(pe_resource_t *rsc, const char *requested_name, rsc_attr_id = found_attr_id; } - xml_top = create_xml_node(NULL, crm_element_name(rsc->xml)); + xml_top = create_xml_node(NULL, (const char *) rsc->xml->name); crm_xml_add(xml_top, XML_ATTR_ID, lookup_id); xml_obj = create_xml_node(xml_top, attr_set_type); @@ -408,19 +413,19 @@ cli_resource_update_attribute(pe_resource_t *rsc, const char *requested_name, need_init = false; pcmk__unpack_constraints(rsc->cluster); pe__clear_resource_flags_on_all(rsc->cluster, - pe_rsc_detect_loop); + pcmk_rsc_detect_loop); } /* We want to set the attribute only on resources explicitly * colocated with this one, so we use rsc->rsc_cons_lhs directly * rather than the with_this_colocations() method. */ - pe__set_resource_flags(rsc, pe_rsc_detect_loop); + pe__set_resource_flags(rsc, pcmk_rsc_detect_loop); for (lpc = rsc->rsc_cons_lhs; lpc != NULL; lpc = lpc->next) { pcmk__colocation_t *cons = (pcmk__colocation_t *) lpc->data; crm_debug("Checking %s %d", cons->id, cons->score); - if (!pcmk_is_set(cons->dependent->flags, pe_rsc_detect_loop) + if (!pcmk_is_set(cons->dependent->flags, pcmk_rsc_detect_loop) && (cons->score > 0)) { crm_debug("Setting %s=%s for dependent resource %s", attr_name, attr_value, cons->dependent->id); @@ -440,14 +445,14 @@ cli_resource_update_attribute(pe_resource_t *rsc, const char *requested_name, // \return Standard Pacemaker return code int -cli_resource_delete_attribute(pe_resource_t *rsc, const char *requested_name, +cli_resource_delete_attribute(pcmk_resource_t *rsc, const char *requested_name, const char *attr_set, const char *attr_set_type, const char *attr_id, const char *attr_name, cib_t *cib, int cib_options, gboolean force) { pcmk__output_t *out = rsc->cluster->priv; int rc = pcmk_rc_ok; - GList/*<pe_resource_t*>*/ *resources = NULL; + GList/*<pcmk_resource_t*>*/ *resources = NULL; if ((attr_id == NULL) && !force) { find_resource_attr(out, cib, XML_ATTR_ID, @@ -482,7 +487,7 @@ cli_resource_delete_attribute(pe_resource_t *rsc, const char *requested_name, char *found_attr_id = NULL; const char *rsc_attr_id = attr_id; - rsc = (pe_resource_t *) iter->data; + rsc = (pcmk_resource_t *) iter->data; lookup_id = clone_strip(rsc->id); rc = find_resource_attr(out, cib, XML_ATTR_ID, lookup_id, attr_set_type, @@ -534,9 +539,10 @@ cli_resource_delete_attribute(pe_resource_t *rsc, const char *requested_name, // \return Standard Pacemaker return code static int send_lrm_rsc_op(pcmk_ipc_api_t *controld_api, bool do_fail_resource, - const char *host_uname, const char *rsc_id, pe_working_set_t *data_set) + const char *host_uname, const char *rsc_id, + pcmk_scheduler_t *scheduler) { - pcmk__output_t *out = data_set->priv; + pcmk__output_t *out = scheduler->priv; const char *router_node = host_uname; const char *rsc_api_id = NULL; const char *rsc_long_id = NULL; @@ -544,13 +550,13 @@ send_lrm_rsc_op(pcmk_ipc_api_t *controld_api, bool do_fail_resource, const char *rsc_provider = NULL; const char *rsc_type = NULL; bool cib_only = false; - pe_resource_t *rsc = pe_find_resource(data_set->resources, rsc_id); + pcmk_resource_t *rsc = pe_find_resource(scheduler->resources, rsc_id); if (rsc == NULL) { out->err(out, "Resource %s not found", rsc_id); return ENXIO; - } else if (rsc->variant != pe_native) { + } else if (rsc->variant != pcmk_rsc_variant_primitive) { out->err(out, "We can only process primitive resources, not %s", rsc_id); return EINVAL; } @@ -564,7 +570,7 @@ send_lrm_rsc_op(pcmk_ipc_api_t *controld_api, bool do_fail_resource, } { - pe_node_t *node = pe_find_node(data_set->nodes, host_uname); + pcmk_node_t *node = pe_find_node(scheduler->nodes, host_uname); if (node == NULL) { out->err(out, "Node %s not found", host_uname); @@ -617,17 +623,20 @@ send_lrm_rsc_op(pcmk_ipc_api_t *controld_api, bool do_fail_resource, * \note The caller is responsible for freeing the result. */ static inline char * -rsc_fail_name(const pe_resource_t *rsc) +rsc_fail_name(const pcmk_resource_t *rsc) { const char *name = (rsc->clone_name? rsc->clone_name : rsc->id); - return pcmk_is_set(rsc->flags, pe_rsc_unique)? strdup(name) : clone_strip(name); + if (pcmk_is_set(rsc->flags, pcmk_rsc_unique)) { + return strdup(name); + } + return clone_strip(name); } // \return Standard Pacemaker return code static int clear_rsc_history(pcmk_ipc_api_t *controld_api, const char *host_uname, - const char *rsc_id, pe_working_set_t *data_set) + const char *rsc_id, pcmk_scheduler_t *scheduler) { int rc = pcmk_rc_ok; @@ -636,7 +645,7 @@ clear_rsc_history(pcmk_ipc_api_t *controld_api, const char *host_uname, * single operation, we might wind up with a wrong idea of the current * resource state, and we might not re-probe the resource. */ - rc = send_lrm_rsc_op(controld_api, false, host_uname, rsc_id, data_set); + rc = send_lrm_rsc_op(controld_api, false, host_uname, rsc_id, scheduler); if (rc != pcmk_rc_ok) { return rc; } @@ -654,7 +663,7 @@ clear_rsc_history(pcmk_ipc_api_t *controld_api, const char *host_uname, static int clear_rsc_failures(pcmk__output_t *out, pcmk_ipc_api_t *controld_api, const char *node_name, const char *rsc_id, const char *operation, - const char *interval_spec, pe_working_set_t *data_set) + const char *interval_spec, pcmk_scheduler_t *scheduler) { int rc = pcmk_rc_ok; const char *failed_value = NULL; @@ -675,7 +684,7 @@ clear_rsc_failures(pcmk__output_t *out, pcmk_ipc_api_t *controld_api, crm_parse_interval_spec(interval_spec)); } - for (xmlNode *xml_op = pcmk__xml_first_child(data_set->failed); + for (xmlNode *xml_op = pcmk__xml_first_child(scheduler->failed); xml_op != NULL; xml_op = pcmk__xml_next(xml_op)) { @@ -687,10 +696,12 @@ clear_rsc_failures(pcmk__output_t *out, pcmk_ipc_api_t *controld_api, // No resource specified means all resources match if (rsc_id) { - pe_resource_t *fail_rsc = pe_find_resource_with_flags(data_set->resources, - failed_id, - pe_find_renamed|pe_find_anon); + pcmk_resource_t *fail_rsc = NULL; + fail_rsc = pe_find_resource_with_flags(scheduler->resources, + failed_id, + pcmk_rsc_match_history + |pcmk_rsc_match_anon_basename); if (!fail_rsc || !pcmk__str_eq(rsc_id, fail_rsc->id, pcmk__str_casei)) { continue; } @@ -722,7 +733,7 @@ clear_rsc_failures(pcmk__output_t *out, pcmk_ipc_api_t *controld_api, g_hash_table_iter_init(&iter, rscs); while (g_hash_table_iter_next(&iter, (gpointer *) &failed_id, NULL)) { crm_debug("Erasing failures of %s on %s", failed_id, node_name); - rc = clear_rsc_history(controld_api, node_name, failed_id, data_set); + rc = clear_rsc_history(controld_api, node_name, failed_id, scheduler); if (rc != pcmk_rc_ok) { return rc; } @@ -733,8 +744,8 @@ clear_rsc_failures(pcmk__output_t *out, pcmk_ipc_api_t *controld_api, // \return Standard Pacemaker return code static int -clear_rsc_fail_attrs(const pe_resource_t *rsc, const char *operation, - const char *interval_spec, const pe_node_t *node) +clear_rsc_fail_attrs(const pcmk_resource_t *rsc, const char *operation, + const char *interval_spec, const pcmk_node_t *node) { int rc = pcmk_rc_ok; int attr_options = pcmk__node_attr_none; @@ -754,13 +765,13 @@ clear_rsc_fail_attrs(const pe_resource_t *rsc, const char *operation, // \return Standard Pacemaker return code int cli_resource_delete(pcmk_ipc_api_t *controld_api, const char *host_uname, - const pe_resource_t *rsc, const char *operation, + const pcmk_resource_t *rsc, const char *operation, const char *interval_spec, bool just_failures, - pe_working_set_t *data_set, gboolean force) + pcmk_scheduler_t *scheduler, gboolean force) { - pcmk__output_t *out = data_set->priv; + pcmk__output_t *out = scheduler->priv; int rc = pcmk_rc_ok; - pe_node_t *node = NULL; + pcmk_node_t *node = NULL; if (rsc == NULL) { return ENXIO; @@ -768,10 +779,11 @@ cli_resource_delete(pcmk_ipc_api_t *controld_api, const char *host_uname, } else if (rsc->children) { for (const GList *lpc = rsc->children; lpc != NULL; lpc = lpc->next) { - const pe_resource_t *child = (const pe_resource_t *) lpc->data; + const pcmk_resource_t *child = (const pcmk_resource_t *) lpc->data; rc = cli_resource_delete(controld_api, host_uname, child, operation, - interval_spec, just_failures, data_set, force); + interval_spec, just_failures, scheduler, + force); if (rc != pcmk_rc_ok) { return rc; } @@ -783,11 +795,11 @@ cli_resource_delete(pcmk_ipc_api_t *controld_api, const char *host_uname, GList *nodes = g_hash_table_get_values(rsc->known_on); if(nodes == NULL && force) { - nodes = pcmk__copy_node_list(data_set->nodes, false); + nodes = pcmk__copy_node_list(scheduler->nodes, false); } else if(nodes == NULL && rsc->exclusive_discover) { GHashTableIter iter; - pe_node_t *node = NULL; + pcmk_node_t *node = NULL; g_hash_table_iter_init(&iter, rsc->allowed_nodes); while (g_hash_table_iter_next(&iter, NULL, (void**)&node)) { @@ -801,12 +813,12 @@ cli_resource_delete(pcmk_ipc_api_t *controld_api, const char *host_uname, } for (lpc = nodes; lpc != NULL; lpc = lpc->next) { - node = (pe_node_t *) lpc->data; + node = (pcmk_node_t *) lpc->data; if (node->details->online) { rc = cli_resource_delete(controld_api, node->details->uname, rsc, operation, interval_spec, just_failures, - data_set, force); + scheduler, force); } if (rc != pcmk_rc_ok) { g_list_free(nodes); @@ -818,7 +830,7 @@ cli_resource_delete(pcmk_ipc_api_t *controld_api, const char *host_uname, return pcmk_rc_ok; } - node = pe_find_node(data_set->nodes, host_uname); + node = pe_find_node(scheduler->nodes, host_uname); if (node == NULL) { out->err(out, "Unable to clean up %s because node %s not found", @@ -847,13 +859,13 @@ cli_resource_delete(pcmk_ipc_api_t *controld_api, const char *host_uname, if (just_failures) { rc = clear_rsc_failures(out, controld_api, host_uname, rsc->id, operation, - interval_spec, data_set); + interval_spec, scheduler); } else { - rc = clear_rsc_history(controld_api, host_uname, rsc->id, data_set); + rc = clear_rsc_history(controld_api, host_uname, rsc->id, scheduler); } if (rc != pcmk_rc_ok) { out->err(out, "Cleaned %s failures on %s, but unable to clean history: %s", - rsc->id, host_uname, pcmk_strerror(rc)); + rsc->id, host_uname, pcmk_rc_str(rc)); } else { out->info(out, "Cleaned up %s on %s", rsc->id, host_uname); } @@ -864,9 +876,9 @@ cli_resource_delete(pcmk_ipc_api_t *controld_api, const char *host_uname, int cli_cleanup_all(pcmk_ipc_api_t *controld_api, const char *node_name, const char *operation, const char *interval_spec, - pe_working_set_t *data_set) + pcmk_scheduler_t *scheduler) { - pcmk__output_t *out = data_set->priv; + pcmk__output_t *out = scheduler->priv; int rc = pcmk_rc_ok; int attr_options = pcmk__node_attr_none; const char *display_name = node_name? node_name : "all nodes"; @@ -878,7 +890,7 @@ cli_cleanup_all(pcmk_ipc_api_t *controld_api, const char *node_name, } if (node_name) { - pe_node_t *node = pe_find_node(data_set->nodes, node_name); + pcmk_node_t *node = pe_find_node(scheduler->nodes, node_name); if (node == NULL) { out->err(out, "Unknown node: %s", node_name); @@ -899,21 +911,21 @@ cli_cleanup_all(pcmk_ipc_api_t *controld_api, const char *node_name, if (node_name) { rc = clear_rsc_failures(out, controld_api, node_name, NULL, - operation, interval_spec, data_set); + operation, interval_spec, scheduler); if (rc != pcmk_rc_ok) { out->err(out, "Cleaned all resource failures on %s, but unable to clean history: %s", - node_name, pcmk_strerror(rc)); + node_name, pcmk_rc_str(rc)); return rc; } } else { - for (GList *iter = data_set->nodes; iter; iter = iter->next) { - pe_node_t *node = (pe_node_t *) iter->data; + for (GList *iter = scheduler->nodes; iter; iter = iter->next) { + pcmk_node_t *node = (pcmk_node_t *) iter->data; rc = clear_rsc_failures(out, controld_api, node->details->uname, NULL, - operation, interval_spec, data_set); + operation, interval_spec, scheduler); if (rc != pcmk_rc_ok) { out->err(out, "Cleaned all resource failures on all nodes, but unable to clean history: %s", - pcmk_strerror(rc)); + pcmk_rc_str(rc)); return rc; } } @@ -933,13 +945,13 @@ check_role(resource_checks_t *checks) return; } switch (text2role(role_s)) { - case RSC_ROLE_STOPPED: + case pcmk_role_stopped: checks->flags |= rsc_remain_stopped; break; - case RSC_ROLE_UNPROMOTED: + case pcmk_role_unpromoted: if (pcmk_is_set(pe__const_top_resource(checks->rsc, false)->flags, - pe_rsc_promotable)) { + pcmk_rsc_promotable)) { checks->flags |= rsc_unpromotable; } break; @@ -970,7 +982,7 @@ check_locked(resource_checks_t *checks) } static bool -node_is_unhealthy(pe_node_t *node) +node_is_unhealthy(pcmk_node_t *node) { switch (pe__health_strategy(node->details->data_set)) { case pcmk__health_strategy_none: @@ -1000,7 +1012,7 @@ node_is_unhealthy(pe_node_t *node) } static void -check_node_health(resource_checks_t *checks, pe_node_t *node) +check_node_health(resource_checks_t *checks, pcmk_node_t *node) { if (node == NULL) { GHashTableIter iter; @@ -1025,7 +1037,7 @@ check_node_health(resource_checks_t *checks, pe_node_t *node) } int -cli_resource_check(pcmk__output_t *out, pe_resource_t *rsc, pe_node_t *node) +cli_resource_check(pcmk__output_t *out, pcmk_resource_t *rsc, pcmk_node_t *node) { resource_checks_t checks = { .rsc = rsc }; @@ -1040,15 +1052,15 @@ cli_resource_check(pcmk__output_t *out, pe_resource_t *rsc, pe_node_t *node) // \return Standard Pacemaker return code int cli_resource_fail(pcmk_ipc_api_t *controld_api, const char *host_uname, - const char *rsc_id, pe_working_set_t *data_set) + const char *rsc_id, pcmk_scheduler_t *scheduler) { crm_notice("Failing %s on %s", rsc_id, host_uname); - return send_lrm_rsc_op(controld_api, true, host_uname, rsc_id, data_set); + return send_lrm_rsc_op(controld_api, true, host_uname, rsc_id, scheduler); } static GHashTable * -generate_resource_params(pe_resource_t *rsc, pe_node_t *node, - pe_working_set_t *data_set) +generate_resource_params(pcmk_resource_t *rsc, pcmk_node_t *node, + pcmk_scheduler_t *scheduler) { GHashTable *params = NULL; GHashTable *meta = NULL; @@ -1059,7 +1071,7 @@ generate_resource_params(pe_resource_t *rsc, pe_node_t *node, combined = pcmk__strkey_table(free, free); - params = pe_rsc_params(rsc, node, data_set); + params = pe_rsc_params(rsc, node, scheduler); if (params != NULL) { g_hash_table_iter_init(&iter, params); while (g_hash_table_iter_next(&iter, (gpointer *) & key, (gpointer *) & value)) { @@ -1068,7 +1080,7 @@ generate_resource_params(pe_resource_t *rsc, pe_node_t *node, } meta = pcmk__strkey_table(free, free); - get_meta_attributes(meta, rsc, node, data_set); + get_meta_attributes(meta, rsc, node, scheduler); if (meta != NULL) { g_hash_table_iter_init(&iter, meta); while (g_hash_table_iter_next(&iter, (gpointer *) & key, (gpointer *) & value)) { @@ -1082,7 +1094,7 @@ generate_resource_params(pe_resource_t *rsc, pe_node_t *node, return combined; } -bool resource_is_running_on(pe_resource_t *rsc, const char *host) +bool resource_is_running_on(pcmk_resource_t *rsc, const char *host) { bool found = true; GList *hIter = NULL; @@ -1094,7 +1106,7 @@ bool resource_is_running_on(pe_resource_t *rsc, const char *host) rsc->fns->location(rsc, &hosts, TRUE); for (hIter = hosts; host != NULL && hIter != NULL; hIter = hIter->next) { - pe_node_t *node = (pe_node_t *) hIter->data; + pcmk_node_t *node = (pcmk_node_t *) hIter->data; if (pcmk__strcase_any_of(host, node->details->uname, node->details->id, NULL)) { crm_trace("Resource %s is running on %s\n", rsc->id, host); @@ -1132,13 +1144,13 @@ get_active_resources(const char *host, GList *rsc_list) GList *active = NULL; for (rIter = rsc_list; rIter != NULL; rIter = rIter->next) { - pe_resource_t *rsc = (pe_resource_t *) rIter->data; + pcmk_resource_t *rsc = (pcmk_resource_t *) rIter->data; /* Expand groups to their members, because if we're restarting a member * other than the first, we can't otherwise tell which resources are * stopping and starting. */ - if (rsc->variant == pe_group) { + if (rsc->variant == pcmk_rsc_variant_group) { active = g_list_concat(active, get_active_resources(host, rsc->children)); } else if (resource_is_running_on(rsc, host)) { @@ -1148,7 +1160,7 @@ get_active_resources(const char *host, GList *rsc_list) return active; } -static void dump_list(GList *items, const char *tag) +static void dump_list(GList *items, const char *tag) { int lpc = 0; GList *item = NULL; @@ -1170,45 +1182,45 @@ static void display_list(pcmk__output_t *out, GList *items, const char *tag) /*! * \internal - * \brief Upgrade XML to latest schema version and use it as working set input + * \brief Upgrade XML to latest schema version and use it as scheduler input * - * This also updates the working set timestamp to the current time. + * This also updates the scheduler timestamp to the current time. * - * \param[in,out] data_set Working set instance to update - * \param[in,out] xml XML to use as input + * \param[in,out] scheduler Scheduler data to update + * \param[in,out] xml XML to use as input * * \return Standard Pacemaker return code * \note On success, caller is responsible for freeing memory allocated for - * data_set->now. + * scheduler->now. * \todo This follows the example of other callers of cli_config_update() * and returns ENOKEY ("Required key not available") if that fails, * but perhaps pcmk_rc_schema_validation would be better in that case. */ int -update_working_set_xml(pe_working_set_t *data_set, xmlNode **xml) +update_scheduler_input(pcmk_scheduler_t *scheduler, xmlNode **xml) { if (cli_config_update(xml, NULL, FALSE) == FALSE) { return ENOKEY; } - data_set->input = *xml; - data_set->now = crm_time_new(NULL); + scheduler->input = *xml; + scheduler->now = crm_time_new(NULL); return pcmk_rc_ok; } /*! * \internal - * \brief Update a working set's XML input based on a CIB query + * \brief Update scheduler XML input based on a CIB query * - * \param[in] data_set Data set instance to initialize + * \param[in] scheduler Scheduler data to initialize * \param[in] cib Connection to the CIB manager * * \return Standard Pacemaker return code * \note On success, caller is responsible for freeing memory allocated for - * data_set->input and data_set->now. + * scheduler->input and scheduler->now. */ static int -update_working_set_from_cib(pcmk__output_t *out, pe_working_set_t * data_set, - cib_t *cib) +update_scheduler_input_to_cib(pcmk__output_t *out, pcmk_scheduler_t *scheduler, + cib_t *cib) { xmlNode *cib_xml_copy = NULL; int rc = pcmk_rc_ok; @@ -1217,10 +1229,10 @@ update_working_set_from_cib(pcmk__output_t *out, pe_working_set_t * data_set, rc = pcmk_legacy2rc(rc); if (rc != pcmk_rc_ok) { - out->err(out, "Could not obtain the current CIB: %s (%d)", pcmk_strerror(rc), rc); + out->err(out, "Could not obtain the current CIB: %s (%d)", pcmk_rc_str(rc), rc); return rc; } - rc = update_working_set_xml(data_set, &cib_xml_copy); + rc = update_scheduler_input(scheduler, &cib_xml_copy); if (rc != pcmk_rc_ok) { out->err(out, "Could not upgrade the current CIB XML"); free_xml(cib_xml_copy); @@ -1232,18 +1244,19 @@ update_working_set_from_cib(pcmk__output_t *out, pe_working_set_t * data_set, // \return Standard Pacemaker return code static int -update_dataset(cib_t *cib, pe_working_set_t * data_set, bool simulate) +update_dataset(cib_t *cib, pcmk_scheduler_t *scheduler, bool simulate) { char *pid = NULL; char *shadow_file = NULL; cib_t *shadow_cib = NULL; int rc = pcmk_rc_ok; - pcmk__output_t *out = data_set->priv; + pcmk__output_t *out = scheduler->priv; - pe_reset_working_set(data_set); - pe__set_working_set_flags(data_set, pe_flag_no_counts|pe_flag_no_compat); - rc = update_working_set_from_cib(out, data_set, cib); + pe_reset_working_set(scheduler); + pe__set_working_set_flags(scheduler, + pcmk_sched_no_counts|pcmk_sched_no_compat); + rc = update_scheduler_input_to_cib(out, scheduler, cib); if (rc != pcmk_rc_ok) { return rc; } @@ -1261,7 +1274,7 @@ update_dataset(cib_t *cib, pe_working_set_t * data_set, bool simulate) goto done; } - rc = write_xml_file(data_set->input, shadow_file, FALSE); + rc = write_xml_file(scheduler->input, shadow_file, FALSE); if (rc < 0) { out->err(out, "Could not populate shadow cib: %s (%d)", pcmk_strerror(rc), rc); @@ -1272,26 +1285,27 @@ update_dataset(cib_t *cib, pe_working_set_t * data_set, bool simulate) rc = pcmk_legacy2rc(rc); if (rc != pcmk_rc_ok) { - out->err(out, "Could not connect to shadow cib: %s (%d)", pcmk_strerror(rc), rc); + out->err(out, "Could not connect to shadow cib: %s (%d)", pcmk_rc_str(rc), rc); goto done; } - pcmk__schedule_actions(data_set->input, - pe_flag_no_counts|pe_flag_no_compat, data_set); + pcmk__schedule_actions(scheduler->input, + pcmk_sched_no_counts|pcmk_sched_no_compat, + scheduler); prev_quiet = out->is_quiet(out); out->quiet = true; - pcmk__simulate_transition(data_set, shadow_cib, NULL); + pcmk__simulate_transition(scheduler, shadow_cib, NULL); out->quiet = prev_quiet; - rc = update_dataset(shadow_cib, data_set, false); + rc = update_dataset(shadow_cib, scheduler, false); } else { - cluster_status(data_set); + cluster_status(scheduler); } done: - /* Do not free data_set->input here, we need rsc->xml to be valid later on */ + // Do not free scheduler->input here, we need rsc->xml to be valid later on cib_delete(shadow_cib); free(pid); @@ -1303,64 +1317,96 @@ update_dataset(cib_t *cib, pe_working_set_t * data_set, bool simulate) return rc; } +/*! + * \internal + * \brief Find the maximum stop timeout of a resource and its children (if any) + * + * \param[in,out] rsc Resource to get timeout for + * + * \return Maximum stop timeout for \p rsc (in milliseconds) + */ static int -max_delay_for_resource(pe_working_set_t * data_set, pe_resource_t *rsc) +max_rsc_stop_timeout(pcmk_resource_t *rsc) { - int delay = 0; + long long result_ll; int max_delay = 0; + xmlNode *config = NULL; + GHashTable *meta = NULL; - if(rsc && rsc->children) { - GList *iter = NULL; + if (rsc == NULL) { + return 0; + } - for(iter = rsc->children; iter; iter = iter->next) { - pe_resource_t *child = (pe_resource_t *)iter->data; + // If resource is collective, use maximum of its children's stop timeouts + if (rsc->children != NULL) { + for (GList *iter = rsc->children; iter; iter = iter->next) { + pcmk_resource_t *child = iter->data; + int delay = max_rsc_stop_timeout(child); - delay = max_delay_for_resource(data_set, child); - if(delay > max_delay) { - double seconds = delay / 1000.0; - crm_trace("Calculated new delay of %.1fs due to %s", seconds, child->id); + if (delay > max_delay) { + pe_rsc_trace(rsc, + "Maximum stop timeout for %s is now %s due to %s", + rsc->id, pcmk__readable_interval(delay), child->id); max_delay = delay; } } + return max_delay; + } - } else if(rsc) { - char *key = crm_strdup_printf("%s_%s_0", rsc->id, RSC_STOP); - pe_action_t *stop = custom_action(rsc, key, RSC_STOP, NULL, TRUE, FALSE, data_set); - const char *value = g_hash_table_lookup(stop->meta, XML_ATTR_TIMEOUT); - long long result_ll; + // Get resource's stop action configuration from CIB + config = pcmk__find_action_config(rsc, PCMK_ACTION_STOP, 0, true); - if ((pcmk__scan_ll(value, &result_ll, -1LL) == pcmk_rc_ok) - && (result_ll >= 0) && (result_ll <= INT_MAX)) { - max_delay = (int) result_ll; - } else { - max_delay = -1; - } - pe_free_action(stop); + /* Get configured timeout for stop action (fully evaluated for rules, + * defaults, etc.). + * + * @TODO This currently ignores node (which might matter for rules) + */ + meta = pcmk__unpack_action_meta(rsc, NULL, PCMK_ACTION_STOP, 0, config); + if ((pcmk__scan_ll(g_hash_table_lookup(meta, XML_ATTR_TIMEOUT), + &result_ll, -1LL) == pcmk_rc_ok) + && (result_ll >= 0) && (result_ll <= INT_MAX)) { + max_delay = (int) result_ll; } + g_hash_table_destroy(meta); return max_delay; } +/*! + * \internal + * \brief Find a reasonable waiting time for stopping any one resource in a list + * + * \param[in,out] scheduler Scheduler data + * \param[in] resources List of names of resources that will be stopped + * + * \return Rough estimate of a reasonable time to wait (in seconds) to stop any + * one resource in \p resources + * \note This estimate is very rough, simply the maximum stop timeout of all + * given resources and their children, plus a small fudge factor. It does + * not account for children that must be stopped in sequence, action + * throttling, or any demotions needed. It checks the stop timeout, even + * if the resources in question are actually being started. + */ static int -max_delay_in(pe_working_set_t * data_set, GList *resources) +wait_time_estimate(pcmk_scheduler_t *scheduler, const GList *resources) { int max_delay = 0; - GList *item = NULL; - - for (item = resources; item != NULL; item = item->next) { - int delay = 0; - pe_resource_t *rsc = pe_find_resource(data_set->resources, (const char *)item->data); - delay = max_delay_for_resource(data_set, rsc); + // Find maximum stop timeout in milliseconds + for (const GList *item = resources; item != NULL; item = item->next) { + pcmk_resource_t *rsc = pe_find_resource(scheduler->resources, + (const char *) item->data); + int delay = max_rsc_stop_timeout(rsc); - if(delay > max_delay) { - double seconds = delay / 1000.0; - crm_trace("Calculated new delay of %.1fs due to %s", seconds, rsc->id); + if (delay > max_delay) { + pe_rsc_trace(rsc, + "Wait time is now %s due to %s", + pcmk__readable_interval(delay), rsc->id); max_delay = delay; } } - return 5 + (max_delay / 1000); + return (max_delay / 1000) + 5; } #define waiting_for_starts(d, r, h) ((d != NULL) || \ @@ -1390,8 +1436,8 @@ max_delay_in(pe_working_set_t * data_set, GList *resources) * \return Standard Pacemaker return code (exits on certain failures) */ int -cli_resource_restart(pcmk__output_t *out, pe_resource_t *rsc, - const pe_node_t *node, const char *move_lifetime, +cli_resource_restart(pcmk__output_t *out, pcmk_resource_t *rsc, + const pcmk_node_t *node, const char *move_lifetime, int timeout_ms, cib_t *cib, int cib_options, gboolean promoted_role_only, gboolean force) { @@ -1412,8 +1458,8 @@ cli_resource_restart(pcmk__output_t *out, pe_resource_t *rsc, GList *current_active = NULL; GList *restart_target_active = NULL; - pe_working_set_t *data_set = NULL; - pe_resource_t *parent = uber_parent(rsc); + pcmk_scheduler_t *scheduler = NULL; + pcmk_resource_t *parent = uber_parent(rsc); bool running = false; const char *id = rsc->clone_name ? rsc->clone_name : rsc->id; @@ -1435,7 +1481,9 @@ cli_resource_restart(pcmk__output_t *out, pe_resource_t *rsc, lookup_id = clone_strip(rsc->id); } - rsc = parent->fns->find_rsc(parent, lookup_id, node, pe_find_any|pe_find_current); + rsc = parent->fns->find_rsc(parent, lookup_id, node, + pcmk_rsc_match_basename + |pcmk_rsc_match_current_node); free(lookup_id); running = resource_is_running_on(rsc, host); } @@ -1449,6 +1497,11 @@ cli_resource_restart(pcmk__output_t *out, pe_resource_t *rsc, return ENXIO; } + if (!pcmk_is_set(rsc->flags, pcmk_rsc_managed)) { + out->err(out, "Unmanaged resources cannot be restarted."); + return EAGAIN; + } + rsc_id = strdup(rsc->id); if (pe_rsc_is_unique_clone(parent)) { @@ -1485,32 +1538,32 @@ cli_resource_restart(pcmk__output_t *out, pe_resource_t *rsc, - Allow a --no-deps option (aka. --force-restart) */ - data_set = pe_new_working_set(); - if (data_set == NULL) { - crm_perror(LOG_ERR, "Could not allocate working set"); - rc = ENOMEM; + scheduler = pe_new_working_set(); + if (scheduler == NULL) { + rc = errno; + out->err(out, "Could not allocate scheduler data: %s", pcmk_rc_str(rc)); goto done; } - data_set->priv = out; - rc = update_dataset(cib, data_set, false); + scheduler->priv = out; + rc = update_dataset(cib, scheduler, false); if(rc != pcmk_rc_ok) { - out->err(out, "Could not get new resource list: %s (%d)", pcmk_strerror(rc), rc); + out->err(out, "Could not get new resource list: %s (%d)", pcmk_rc_str(rc), rc); goto done; } - restart_target_active = get_active_resources(host, data_set->resources); - current_active = get_active_resources(host, data_set->resources); + restart_target_active = get_active_resources(host, scheduler->resources); + current_active = get_active_resources(host, scheduler->resources); dump_list(current_active, "Origin"); if (stop_via_ban) { /* Stop the clone or bundle instance by banning it from the host */ out->quiet = true; - rc = cli_resource_ban(out, lookup_id, host, move_lifetime, NULL, cib, - cib_options, promoted_role_only); - + rc = cli_resource_ban(out, lookup_id, host, move_lifetime, cib, + cib_options, promoted_role_only, + PCMK__ROLE_PROMOTED); } else { /* Stop the resource by setting target-role to Stopped. * Remember any existing target-role so we can restore it later @@ -1521,11 +1574,11 @@ cli_resource_restart(pcmk__output_t *out, pe_resource_t *rsc, NULL, XML_RSC_ATTR_TARGET_ROLE, &orig_target_role); rc = cli_resource_update_attribute(rsc, rsc_id, NULL, XML_TAG_META_SETS, NULL, XML_RSC_ATTR_TARGET_ROLE, - RSC_STOPPED, FALSE, cib, cib_options, - force); + PCMK_ACTION_STOPPED, FALSE, cib, + cib_options, force); } if(rc != pcmk_rc_ok) { - out->err(out, "Could not set target-role for %s: %s (%d)", rsc_id, pcmk_strerror(rc), rc); + out->err(out, "Could not set target-role for %s: %s (%d)", rsc_id, pcmk_rc_str(rc), rc); if (current_active != NULL) { g_list_free_full(current_active, free); current_active = NULL; @@ -1537,13 +1590,13 @@ cli_resource_restart(pcmk__output_t *out, pe_resource_t *rsc, goto done; } - rc = update_dataset(cib, data_set, true); + rc = update_dataset(cib, scheduler, true); if(rc != pcmk_rc_ok) { out->err(out, "Could not determine which resources would be stopped"); goto failure; } - target_active = get_active_resources(host, data_set->resources); + target_active = get_active_resources(host, scheduler->resources); dump_list(target_active, "Target"); list_delta = pcmk__subtract_lists(current_active, target_active, (GCompareFunc) strcmp); @@ -1554,7 +1607,8 @@ cli_resource_restart(pcmk__output_t *out, pe_resource_t *rsc, while (list_delta != NULL) { before = g_list_length(list_delta); if(timeout_ms == 0) { - step_timeout_s = max_delay_in(data_set, list_delta) / sleep_interval; + step_timeout_s = wait_time_estimate(scheduler, list_delta) + / sleep_interval; } /* We probably don't need the entire step timeout */ @@ -1564,7 +1618,7 @@ cli_resource_restart(pcmk__output_t *out, pe_resource_t *rsc, timeout -= sleep_interval; crm_trace("%ds remaining", timeout); } - rc = update_dataset(cib, data_set, FALSE); + rc = update_dataset(cib, scheduler, FALSE); if(rc != pcmk_rc_ok) { out->err(out, "Could not determine which resources were stopped"); goto failure; @@ -1572,12 +1626,12 @@ cli_resource_restart(pcmk__output_t *out, pe_resource_t *rsc, if (current_active != NULL) { g_list_free_full(current_active, free); - current_active = NULL; } - current_active = get_active_resources(host, data_set->resources); + current_active = get_active_resources(host, scheduler->resources); + g_list_free(list_delta); - list_delta = NULL; list_delta = pcmk__subtract_lists(current_active, target_active, (GCompareFunc) strcmp); + dump_list(current_active, "Current"); dump_list(list_delta, "Delta"); } @@ -1610,15 +1664,15 @@ cli_resource_restart(pcmk__output_t *out, pe_resource_t *rsc, } if(rc != pcmk_rc_ok) { - out->err(out, "Could not unset target-role for %s: %s (%d)", rsc_id, pcmk_strerror(rc), rc); + out->err(out, "Could not unset target-role for %s: %s (%d)", rsc_id, pcmk_rc_str(rc), rc); goto done; } if (target_active != NULL) { g_list_free_full(target_active, free); - target_active = NULL; } target_active = restart_target_active; + list_delta = pcmk__subtract_lists(target_active, current_active, (GCompareFunc) strcmp); out->info(out, "Waiting for %d resources to start again:", g_list_length(list_delta)); display_list(out, list_delta, " * "); @@ -1627,7 +1681,8 @@ cli_resource_restart(pcmk__output_t *out, pe_resource_t *rsc, while (waiting_for_starts(list_delta, rsc, host)) { before = g_list_length(list_delta); if(timeout_ms == 0) { - step_timeout_s = max_delay_in(data_set, list_delta) / sleep_interval; + step_timeout_s = wait_time_estimate(scheduler, list_delta) + / sleep_interval; } /* We probably don't need the entire step timeout */ @@ -1639,21 +1694,20 @@ cli_resource_restart(pcmk__output_t *out, pe_resource_t *rsc, crm_trace("%ds remaining", timeout); } - rc = update_dataset(cib, data_set, false); + rc = update_dataset(cib, scheduler, false); if(rc != pcmk_rc_ok) { out->err(out, "Could not determine which resources were started"); goto failure; } + /* It's OK if dependent resources moved to a different node, + * so we check active resources on all nodes. + */ if (current_active != NULL) { g_list_free_full(current_active, free); - current_active = NULL; } + current_active = get_active_resources(NULL, scheduler->resources); - /* It's OK if dependent resources moved to a different node, - * so we check active resources on all nodes. - */ - current_active = get_active_resources(NULL, data_set->resources); g_list_free(list_delta); list_delta = pcmk__subtract_lists(target_active, current_active, (GCompareFunc) strcmp); dump_list(current_active, "Current"); @@ -1702,16 +1756,17 @@ done: } free(rsc_id); free(lookup_id); - pe_free_working_set(data_set); + pe_free_working_set(scheduler); return rc; } static inline bool -action_is_pending(const pe_action_t *action) +action_is_pending(const pcmk_action_t *action) { - if (pcmk_any_flags_set(action->flags, pe_action_optional|pe_action_pseudo) - || !pcmk_is_set(action->flags, pe_action_runnable) - || pcmk__str_eq("notify", action->task, pcmk__str_casei)) { + if (pcmk_any_flags_set(action->flags, + pcmk_action_optional|pcmk_action_pseudo) + || !pcmk_is_set(action->flags, pcmk_action_runnable) + || pcmk__str_eq(PCMK_ACTION_NOTIFY, action->task, pcmk__str_casei)) { return false; } return true; @@ -1729,7 +1784,7 @@ static bool actions_are_pending(const GList *actions) { for (const GList *action = actions; action != NULL; action = action->next) { - const pe_action_t *a = (const pe_action_t *) action->data; + const pcmk_action_t *a = (const pcmk_action_t *) action->data; if (action_is_pending(a)) { crm_notice("Waiting for %s (flags=%#.8x)", a->uuid, a->flags); @@ -1746,7 +1801,7 @@ print_pending_actions(pcmk__output_t *out, GList *actions) out->info(out, "Pending actions:"); for (action = actions; action != NULL; action = action->next) { - pe_action_t *a = (pe_action_t *) action->data; + pcmk_action_t *a = (pcmk_action_t *) action->data; if (!action_is_pending(a)) { continue; @@ -1786,27 +1841,28 @@ print_pending_actions(pcmk__output_t *out, GList *actions) int wait_till_stable(pcmk__output_t *out, int timeout_ms, cib_t * cib) { - pe_working_set_t *data_set = NULL; + pcmk_scheduler_t *scheduler = NULL; + xmlXPathObjectPtr search; int rc = pcmk_rc_ok; + bool pending_unknown_state_resources; int timeout_s = timeout_ms? ((timeout_ms + 999) / 1000) : WAIT_DEFAULT_TIMEOUT_S; time_t expire_time = time(NULL) + timeout_s; time_t time_diff; bool printed_version_warning = out->is_quiet(out); // i.e. don't print if quiet - data_set = pe_new_working_set(); - if (data_set == NULL) { + scheduler = pe_new_working_set(); + if (scheduler == NULL) { return ENOMEM; } do { - /* Abort if timeout is reached */ time_diff = expire_time - time(NULL); if (time_diff > 0) { crm_info("Waiting up to %lld seconds for cluster actions to complete", (long long) time_diff); } else { - print_pending_actions(out, data_set->actions); - pe_free_working_set(data_set); + print_pending_actions(out, scheduler->actions); + pe_free_working_set(scheduler); return ETIME; } if (rc == pcmk_rc_ok) { /* this avoids sleep on first loop iteration */ @@ -1814,14 +1870,15 @@ wait_till_stable(pcmk__output_t *out, int timeout_ms, cib_t * cib) } /* Get latest transition graph */ - pe_reset_working_set(data_set); - rc = update_working_set_from_cib(out, data_set, cib); + pe_reset_working_set(scheduler); + rc = update_scheduler_input_to_cib(out, scheduler, cib); if (rc != pcmk_rc_ok) { - pe_free_working_set(data_set); + pe_free_working_set(scheduler); return rc; } - pcmk__schedule_actions(data_set->input, - pe_flag_no_counts|pe_flag_no_compat, data_set); + pcmk__schedule_actions(scheduler->input, + pcmk_sched_no_counts|pcmk_sched_no_compat, + scheduler); if (!printed_version_warning) { /* If the DC has a different version than the local node, the two @@ -1832,7 +1889,7 @@ wait_till_stable(pcmk__output_t *out, int timeout_ms, cib_t * cib) * wait as a new controller operation that would be forwarded to the * DC. However, that would have potential problems of its own. */ - const char *dc_version = g_hash_table_lookup(data_set->config_hash, + const char *dc_version = g_hash_table_lookup(scheduler->config_hash, "dc-version"); if (!pcmk__str_eq(dc_version, PACEMAKER_VERSION "-" BUILD_VERSION, pcmk__str_casei)) { @@ -1842,9 +1899,13 @@ wait_till_stable(pcmk__output_t *out, int timeout_ms, cib_t * cib) } } - } while (actions_are_pending(data_set->actions)); + search = xpath_search(scheduler->input, "/cib/status/node_state/lrm/lrm_resources/lrm_resource/" + XML_LRM_TAG_RSC_OP "[@" XML_LRM_ATTR_RC "='193']"); + pending_unknown_state_resources = (numXpathResults(search) > 0); + freeXpathObject(search); + } while (actions_are_pending(scheduler->actions) || pending_unknown_state_resources); - pe_free_working_set(data_set); + pe_free_working_set(scheduler); return rc; } @@ -1853,10 +1914,10 @@ get_action(const char *rsc_action) { const char *action = NULL; if (pcmk__str_eq(rsc_action, "validate", pcmk__str_casei)) { - action = "validate-all"; + action = PCMK_ACTION_VALIDATE_ALL; } else if (pcmk__str_eq(rsc_action, "force-check", pcmk__str_casei)) { - action = "monitor"; + action = PCMK_ACTION_MONITOR; } else if (pcmk__strcase_any_of(rsc_action, "force-start", "force-stop", "force-demote", "force-promote", NULL)) { @@ -1898,7 +1959,7 @@ set_agent_environment(GHashTable *params, int timeout_ms, int check_level, free(level); } - setenv("HA_debug", (verbosity > 0)? "1" : "0", 1); + pcmk__set_env_option(PCMK__ENV_DEBUG, ((verbosity > 0)? "1" : "0"), true); if (verbosity > 1) { setenv("OCF_TRACE_RA", "1", 1); } @@ -1948,7 +2009,7 @@ cli_resource_execute_from_params(pcmk__output_t *out, const char *rsc_name, // If no timeout was provided, use the same default as the cluster if (timeout_ms == 0) { - timeout_ms = crm_get_msec(CRM_DEFAULT_OP_TIMEOUT_S); + timeout_ms = PCMK_DEFAULT_ACTION_TIMEOUT_MS; } set_agent_environment(params, timeout_ms, check_level, resource_verbose); @@ -2000,12 +2061,12 @@ done: } crm_exit_t -cli_resource_execute(pe_resource_t *rsc, const char *requested_name, +cli_resource_execute(pcmk_resource_t *rsc, const char *requested_name, const char *rsc_action, GHashTable *override_hash, - int timeout_ms, cib_t * cib, pe_working_set_t *data_set, + int timeout_ms, cib_t *cib, pcmk_scheduler_t *scheduler, int resource_verbose, gboolean force, int check_level) { - pcmk__output_t *out = data_set->priv; + pcmk__output_t *out = scheduler->priv; crm_exit_t exit_code = CRM_EX_OK; const char *rid = NULL; const char *rtype = NULL; @@ -2016,7 +2077,7 @@ cli_resource_execute(pe_resource_t *rsc, const char *requested_name, if (pcmk__strcase_any_of(rsc_action, "force-start", "force-demote", "force-promote", NULL)) { if(pe_rsc_is_clone(rsc)) { - GList *nodes = cli_resource_search(rsc, requested_name, data_set); + GList *nodes = cli_resource_search(rsc, requested_name, scheduler); if(nodes != NULL && force == FALSE) { out->err(out, "It is not safe to %s %s here: the cluster claims it is already active", rsc_action, rsc->id); @@ -2034,10 +2095,10 @@ cli_resource_execute(pe_resource_t *rsc, const char *requested_name, rsc = rsc->children->data; } - if(rsc->variant == pe_group) { + if (rsc->variant == pcmk_rsc_variant_group) { out->err(out, "Sorry, the %s option doesn't support group resources", rsc_action); return CRM_EX_UNIMPLEMENT_FEATURE; - } else if (rsc->variant == pe_container || pe_rsc_is_bundled(rsc)) { + } else if (pe_rsc_is_bundled(rsc)) { out->err(out, "Sorry, the %s option doesn't support bundled resources", rsc_action); return CRM_EX_UNIMPLEMENT_FEATURE; } @@ -2047,10 +2108,11 @@ cli_resource_execute(pe_resource_t *rsc, const char *requested_name, rtype = crm_element_value(rsc->xml, XML_ATTR_TYPE); params = generate_resource_params(rsc, NULL /* @TODO use local node */, - data_set); + scheduler); if (timeout_ms == 0) { - timeout_ms = pe_get_configured_timeout(rsc, get_action(rsc_action), data_set); + timeout_ms = pe_get_configured_timeout(rsc, get_action(rsc_action), + scheduler); } rid = pe_rsc_is_anon_clone(rsc->parent)? requested_name : rsc->id; @@ -2063,26 +2125,28 @@ cli_resource_execute(pe_resource_t *rsc, const char *requested_name, // \return Standard Pacemaker return code int -cli_resource_move(const pe_resource_t *rsc, const char *rsc_id, +cli_resource_move(const pcmk_resource_t *rsc, const char *rsc_id, const char *host_name, const char *move_lifetime, cib_t *cib, - int cib_options, pe_working_set_t *data_set, + int cib_options, pcmk_scheduler_t *scheduler, gboolean promoted_role_only, gboolean force) { - pcmk__output_t *out = data_set->priv; + pcmk__output_t *out = scheduler->priv; int rc = pcmk_rc_ok; unsigned int count = 0; - pe_node_t *current = NULL; - pe_node_t *dest = pe_find_node(data_set->nodes, host_name); + pcmk_node_t *current = NULL; + pcmk_node_t *dest = pe_find_node(scheduler->nodes, host_name); bool cur_is_dest = false; if (dest == NULL) { return pcmk_rc_node_unknown; } - if (promoted_role_only && !pcmk_is_set(rsc->flags, pe_rsc_promotable)) { - const pe_resource_t *p = pe__const_top_resource(rsc, false); + if (promoted_role_only + && !pcmk_is_set(rsc->flags, pcmk_rsc_promotable)) { - if (pcmk_is_set(p->flags, pe_rsc_promotable)) { + const pcmk_resource_t *p = pe__const_top_resource(rsc, false); + + if (pcmk_is_set(p->flags, pcmk_rsc_promotable)) { out->info(out, "Using parent '%s' for move instead of '%s'.", rsc->id, rsc_id); rsc_id = p->id; rsc = p; @@ -2096,15 +2160,15 @@ cli_resource_move(const pe_resource_t *rsc, const char *rsc_id, current = pe__find_active_requires(rsc, &count); - if (pcmk_is_set(rsc->flags, pe_rsc_promotable)) { + if (pcmk_is_set(rsc->flags, pcmk_rsc_promotable)) { unsigned int promoted_count = 0; - pe_node_t *promoted_node = NULL; + pcmk_node_t *promoted_node = NULL; for (const GList *iter = rsc->children; iter; iter = iter->next) { - const pe_resource_t *child = (const pe_resource_t *) iter->data; + const pcmk_resource_t *child = (const pcmk_resource_t *) iter->data; enum rsc_role_e child_role = child->fns->state(child, TRUE); - if (child_role == RSC_ROLE_PROMOTED) { + if (child_role == pcmk_role_promoted) { rsc = child; promoted_node = pe__current_node(child); promoted_count++; @@ -2137,15 +2201,17 @@ cli_resource_move(const pe_resource_t *rsc, const char *rsc_id, } /* Clear any previous prefer constraints across all nodes. */ - cli_resource_clear(rsc_id, NULL, data_set->nodes, cib, cib_options, false, force); + cli_resource_clear(rsc_id, NULL, scheduler->nodes, cib, cib_options, false, + force); /* Clear any previous ban constraints on 'dest'. */ - cli_resource_clear(rsc_id, dest->details->uname, data_set->nodes, cib, + cli_resource_clear(rsc_id, dest->details->uname, scheduler->nodes, cib, cib_options, TRUE, force); /* Record an explicit preference for 'dest' */ rc = cli_resource_prefer(out, rsc_id, dest->details->uname, move_lifetime, - cib, cib_options, promoted_role_only); + cib, cib_options, promoted_role_only, + PCMK__ROLE_PROMOTED); crm_trace("%s%s now prefers %s%s", rsc->id, (promoted_role_only? " (promoted)" : ""), @@ -2158,8 +2224,8 @@ cli_resource_move(const pe_resource_t *rsc, const char *rsc_id, /* Ban the original location if possible */ if(current) { (void)cli_resource_ban(out, rsc_id, current->details->uname, move_lifetime, - NULL, cib, cib_options, promoted_role_only); - + cib, cib_options, promoted_role_only, + PCMK__ROLE_PROMOTED); } else if(count > 1) { out->info(out, "Resource '%s' is currently %s in %d locations. " "One may now move to %s", |