22 #define VARIANT_CLONE 1 25 #ifdef PCMK__COMPAT_2_0 26 #define PROMOTED_INSTANCES RSC_ROLE_PROMOTED_LEGACY_S "s" 27 #define UNPROMOTED_INSTANCES RSC_ROLE_UNPROMOTED_LEGACY_S "s" 29 #define PROMOTED_INSTANCES RSC_ROLE_PROMOTED_S 30 #define UNPROMOTED_INSTANCES RSC_ROLE_UNPROMOTED_S 34 sorted_hash_table_values(GHashTable *table)
40 g_hash_table_iter_init(&iter, table);
41 while (g_hash_table_iter_next(&iter, &key, &value)) {
42 if (!g_list_find_custom(retval, value, (GCompareFunc) strcmp)) {
43 retval = g_list_prepend(retval, (
char *) value);
47 retval = g_list_sort(retval, (GCompareFunc) strcmp);
52 nodes_with_status(GHashTable *table,
const char *status)
58 g_hash_table_iter_init(&iter, table);
59 while (g_hash_table_iter_next(&iter, &key, &value)) {
60 if (!strcmp((
char *) value, status)) {
61 retval = g_list_prepend(retval, key);
70 node_list_to_str(GList *list)
75 for (GList *iter = list; iter != NULL; iter = iter->next) {
76 pcmk__add_word(&retval, &len, (
char *) iter->data);
106 rsc->
id,
ID(clone_data->xml_obj_child),
111 rsc->
id,
ID(clone_data->xml_obj_child))
119 if (pe_rsc_is_clone(rsc)) {
120 clone_variant_data_t *clone_data = NULL;
122 get_clone_variant_data(clone_data, rsc);
125 "such as %s can be used only as anonymous clones",
126 rsc->
id, standard, rid);
128 clone_data->clone_node_max = 1;
129 clone_data->clone_max = QB_MIN(clone_data->clone_max,
137 char *child_id = NULL;
139 const char *child_base = NULL;
140 clone_variant_data_t *clone_data = NULL;
142 get_clone_variant_data(clone_data, rsc);
144 child_base =
ID(clone_data->xml_obj_child);
155 gboolean as_orphan = FALSE;
156 char *inc_num = NULL;
157 char *inc_max = NULL;
159 xmlNode *child_copy = NULL;
160 clone_variant_data_t *clone_data = NULL;
162 get_clone_variant_data(clone_data, rsc);
164 CRM_CHECK(clone_data->xml_obj_child != NULL,
return FALSE);
166 if (clone_data->total_clones >= clone_data->clone_max) {
172 inc_num = pcmk__itoa(clone_data->total_clones);
173 inc_max = pcmk__itoa(clone_data->clone_max);
175 child_copy =
copy_xml(clone_data->xml_obj_child);
187 clone_data->total_clones += 1;
188 pe_rsc_trace(child_rsc,
"Setting clone attributes for: %s", child_rsc->
id);
208 xmlNode *a_child = NULL;
209 xmlNode *xml_obj = rsc->
xml;
210 clone_variant_data_t *clone_data = NULL;
218 clone_data = calloc(1,
sizeof(clone_variant_data_t));
222 const char *promoted_max = NULL;
223 const char *promoted_node_max = NULL;
225 promoted_max = g_hash_table_lookup(rsc->
meta,
227 if (promoted_max == NULL) {
229 promoted_max = g_hash_table_lookup(rsc->
meta,
233 promoted_node_max = g_hash_table_lookup(rsc->
meta,
235 if (promoted_node_max == NULL) {
237 promoted_node_max = g_hash_table_lookup(rsc->
meta,
242 if (promoted_max == NULL) {
243 clone_data->promoted_max = 1;
249 if (promoted_node_max == NULL) {
250 clone_data->promoted_node_max = 1;
253 &(clone_data->promoted_node_max), 0);
261 if (max_clones_node == NULL) {
262 clone_data->clone_node_max = 1;
270 if (max_clones == NULL) {
271 clone_data->clone_max = QB_MAX(1, g_list_length(
data_set->
nodes));
280 "because anonymous clones support only one instance " 281 "per node", rsc->
id);
282 clone_data->clone_node_max = 1;
286 pe_rsc_trace(rsc,
"\tClone max: %d", clone_data->clone_max);
287 pe_rsc_trace(rsc,
"\tClone node max: %d", clone_data->clone_node_max);
294 for (a_child = pcmk__xe_first_child(xml_obj); a_child != NULL;
295 a_child = pcmk__xe_next(a_child)) {
298 clone_data->xml_obj_child = a_child;
303 if (clone_data->xml_obj_child == NULL) {
324 if (clone_data->clone_max <= 0) {
334 for (lpc = 0; lpc < clone_data->clone_max; lpc++) {
341 pe_rsc_trace(rsc,
"Added %d children to resource %s...", clone_data->clone_max, rsc->
id);
350 for (; gIter != NULL; gIter = gIter->next) {
352 gboolean child_active = child_rsc->
fns->
active(child_rsc, all);
354 if (all == FALSE && child_active) {
356 }
else if (all && child_active == FALSE) {
369 short_print(
char *list,
const char *prefix,
const char *
type,
const char *suffix,
long options,
void *print_data)
396 const char *target_role = g_hash_table_lookup(rsc->
meta,
409 const char *target_role = configured_role_str(rsc);
418 clone_print_xml(
pe_resource_t * rsc,
const char *pre_text,
long options,
void *print_data)
421 const char *target_role = configured_role_str(rsc);
438 for (; gIter != NULL; gIter = gIter->next) {
441 child_rsc->
fns->
print(child_rsc, child_text, options, print_data);
461 for (gIter = rsc->
children; gIter != NULL; gIter = gIter->next) {
481 char *list_text = NULL;
482 char *child_text = NULL;
483 char *stopped_list = NULL;
484 size_t list_text_len = 0;
485 size_t stopped_list_len = 0;
487 GList *promoted_list = NULL;
488 GList *started_list = NULL;
491 clone_variant_data_t *clone_data = NULL;
492 int active_instances = 0;
494 if (pre_text == NULL) {
499 clone_print_xml(rsc, pre_text, options, print_data);
503 get_clone_variant_data(clone_data, rsc);
508 pre_text ? pre_text :
"", rsc->
id,
ID(clone_data->xml_obj_child),
520 for (; gIter != NULL; gIter = gIter->next) {
521 gboolean print_full = FALSE;
523 gboolean partially_active = child_rsc->
fns->
active(child_rsc, FALSE);
543 }
else if (partially_active == FALSE) {
547 pcmk__add_word(&stopped_list, &stopped_list_len, child_rsc->
id);
557 }
else if (child_rsc->
fns->
active(child_rsc, TRUE)) {
571 promoted_list = g_list_append(promoted_list, location);
574 started_list = g_list_append(started_list, location);
591 child_rsc->
fns->
print(child_rsc, child_text, options, print_data);
600 for (gIter = promoted_list; gIter; gIter = gIter->next) {
603 pcmk__add_word(&list_text, &list_text_len,
host->details->uname);
609 g_list_free(promoted_list);
616 for (gIter = started_list; gIter; gIter = gIter->next) {
619 pcmk__add_word(&list_text, &list_text_len,
host->details->uname);
627 short_print(list_text, child_text,
632 options, print_data);
636 short_print(list_text, child_text,
"Started", NULL, options, print_data);
639 g_list_free(started_list);
645 const char *state =
"Stopped";
649 state =
"Stopped (disabled)";
653 && (clone_data->clone_max > active_instances)) {
661 stopped_list_len = 0;
667 list = g_hash_table_get_values(rsc->
known_on);
671 for (nIter = list; nIter != NULL; nIter = nIter->next) {
675 pcmk__add_word(&stopped_list, &stopped_list_len,
682 short_print(stopped_list, child_text, state, NULL, options, print_data);
697 uint32_t show_opts = va_arg(args, uint32_t);
699 GList *only_node = va_arg(args, GList *);
700 GList *only_rsc = va_arg(args, GList *);
705 gboolean printed_header = FALSE;
706 gboolean print_everything = TRUE;
715 all = g_list_prepend(all, (gpointer)
"*");
717 for (; gIter != NULL; gIter = gIter->next) {
724 if (child_rsc->
fns->
is_filtered(child_rsc, only_rsc, print_everything)) {
728 if (!printed_header) {
729 printed_header = TRUE;
739 "target_role", configured_role_str(rsc));
743 out->message(out, crm_map_element_name(child_rsc->
xml), show_opts,
744 child_rsc, only_node, all);
747 if (printed_header) {
759 uint32_t show_opts = va_arg(args, uint32_t);
761 GList *only_node = va_arg(args, GList *);
762 GList *only_rsc = va_arg(args, GList *);
764 GHashTable *stopped = NULL;
766 char *list_text = NULL;
767 size_t list_text_len = 0;
769 GList *promoted_list = NULL;
770 GList *started_list = NULL;
773 clone_variant_data_t *clone_data = NULL;
774 int active_instances = 0;
776 gboolean print_everything = TRUE;
778 get_clone_variant_data(clone_data, rsc);
787 for (; gIter != NULL; gIter = gIter->next) {
788 gboolean print_full = FALSE;
790 gboolean partially_active = child_rsc->
fns->
active(child_rsc, FALSE);
796 if (child_rsc->
fns->
is_filtered(child_rsc, only_rsc, print_everything)) {
818 }
else if (partially_active == FALSE) {
823 if (stopped == NULL) {
826 g_hash_table_insert(stopped, strdup(child_rsc->
id), strdup(
"Stopped"));
836 }
else if (child_rsc->
fns->
active(child_rsc, TRUE)) {
850 promoted_list = g_list_append(promoted_list, location);
853 started_list = g_list_append(started_list, location);
869 clone_header(out, &rc, rsc, clone_data);
872 all = g_list_prepend(all, (gpointer)
"*");
873 out->message(out, crm_map_element_name(child_rsc->
xml), show_opts,
874 child_rsc, only_node, all);
886 for (gIter = promoted_list; gIter; gIter = gIter->next) {
894 pcmk__add_word(&list_text, &list_text_len,
host->details->uname);
897 g_list_free(promoted_list);
899 if (list_text != NULL) {
900 clone_header(out, &rc, rsc, clone_data);
910 for (gIter = started_list; gIter; gIter = gIter->next) {
918 pcmk__add_word(&list_text, &list_text_len,
host->details->uname);
921 g_list_free(started_list);
923 if (list_text != NULL) {
924 clone_header(out, &rc, rsc, clone_data);
930 out->list_item(out, NULL,
939 out->list_item(out, NULL,
"Started: [ %s ]", list_text);
948 && (clone_data->clone_max > active_instances)) {
954 if (stopped != NULL) {
955 g_hash_table_destroy(stopped);
963 list = g_hash_table_get_values(rsc->
known_on);
967 for (nIter = list; nIter != NULL; nIter = nIter->next) {
974 const char *state =
"Stopped";
977 state =
"Stopped (disabled)";
980 if (stopped == NULL) {
983 if (probe_op != NULL) {
987 g_hash_table_insert(stopped, strdup(node->
details->
uname),
990 g_hash_table_insert(stopped, strdup(node->
details->
uname),
998 if (stopped != NULL) {
999 GList *list = sorted_hash_table_values(stopped);
1001 clone_header(out, &rc, rsc, clone_data);
1003 for (GList *status_iter = list; status_iter != NULL; status_iter = status_iter->next) {
1004 const char *status = status_iter->data;
1005 GList *nodes = nodes_with_status(stopped, status);
1006 char *str = node_list_to_str(nodes);
1009 out->list_item(out, NULL,
"%s: [ %s ]", status, str);
1017 g_hash_table_destroy(stopped);
1023 }
else if (active_instances == 0) {
1024 clone_header(out, &rc, rsc, clone_data);
1037 clone_variant_data_t *clone_data = NULL;
1039 get_clone_variant_data(clone_data, rsc);
1043 for (GList *gIter = rsc->
children; gIter != NULL; gIter = gIter->next) {
1049 child_rsc->
xml = NULL;
1053 child_rsc->
fns->
free(child_rsc);
1059 CRM_ASSERT(clone_data->demote_notify == NULL);
1061 CRM_ASSERT(clone_data->start_notify == NULL);
1062 CRM_ASSERT(clone_data->promote_notify == NULL);
1074 for (; gIter != NULL; gIter = gIter->next) {
1078 if (a_role > clone_role) {
1079 clone_role = a_role;
1098 if (pe_rsc_is_clone(rsc)) {
1099 clone_variant_data_t *clone_data = NULL;
1101 get_clone_variant_data(clone_data, rsc);
1102 if (clone_data->clone_max == g_list_length(
data_set->
nodes)) {
1112 gboolean passes = FALSE;
1113 clone_variant_data_t *clone_data = NULL;
1118 get_clone_variant_data(clone_data, rsc);
1122 for (GList *gIter = rsc->
children; gIter != NULL; gIter = gIter->next) {
1139 clone_variant_data_t *clone_data = NULL;
1140 get_clone_variant_data(clone_data, rsc);
1141 return ID(clone_data->xml_obj_child);
#define CRM_CHECK(expr, failure_action)
pe_resource_t * find_clone_instance(pe_resource_t *rsc, const char *sub_id, pe_working_set_t *data_set)
pe_node_t * pe_find_node(GList *node_list, const char *uname)
void clone_print(pe_resource_t *rsc, const char *pre_text, long options, void *print_data)
void pcmk__add_separated_word(char **list, size_t *len, const char *word, const char *separator)
bool is_set_recursive(pe_resource_t *rsc, long long flag, bool any)
#define PROMOTED_INSTANCES
Control output from tools.
int pcmk__scan_min_int(const char *text, int *result, int minimum)
gboolean clone_unpack(pe_resource_t *rsc, pe_working_set_t *data_set)
#define UNPROMOTED_INSTANCES
#define XML_RSC_ATTR_INCARNATION
#define pcmk__config_err(fmt...)
bool pe__is_universal_clone(pe_resource_t *rsc, pe_working_set_t *data_set)
void pe__force_anon(const char *standard, pe_resource_t *rsc, const char *rid, pe_working_set_t *data_set)
resource_object_functions_t * fns
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.
pe_resource_t * pe_find_resource(GList *rsc_list, const char *id_rh)
#define PCMK_XE_PROMOTED_NODE_MAX_LEGACY
#define XML_RSC_ATTR_STICKINESS
const char * pe__clone_child_id(pe_resource_t *rsc)
enum crm_ais_msg_types type
enum rsc_role_e clone_resource_state(const pe_resource_t *rsc, gboolean current)
#define XML_RSC_ATTR_INCARNATION_MAX
#define PCMK_XE_PROMOTED_MAX_LEGACY
gboolean pe__clone_is_filtered(pe_resource_t *rsc, GList *only_rsc, gboolean check_parent)
int pe__clone_xml(pcmk__output_t *out, va_list args)
xmlNode * copy_xml(xmlNode *src_node)
void pe__set_resource_flags_recursive(pe_resource_t *rsc, uint64_t flags)
const char * role2text(enum rsc_role_e role)
pe_node_t *(* location)(const pe_resource_t *, GList **, int)
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
#define XML_CIB_TAG_RESOURCE
#define PCMK__OUTPUT_ARGS(ARGS...)
int pe__name_and_nvpairs_xml(pcmk__output_t *out, bool is_list, const char *tag_name, size_t pairs_count,...)
void clone_free(pe_resource_t *rsc)
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
struct pe_node_shared_s * details
void common_free(pe_resource_t *rsc)
#define pe_rsc_promotable
#define XML_RSC_ATTR_ORDERED
pe_working_set_t * data_set
gboolean pcmk__str_in_list(const gchar *s, GList *lst, uint32_t flags)
void(* print)(pe_resource_t *, const char *, long, void *)
#define XML_RSC_ATTR_INCARNATION_NODEMAX
pe_resource_t * pe__create_clone_child(pe_resource_t *rsc, pe_working_set_t *data_set)
#define XML_RSC_ATTR_TARGET_ROLE
void(* free)(pe_resource_t *)
void free_xml(xmlNode *child)
enum rsc_role_e text2role(const char *role)
bool pcmk__str_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
void pcmk__output_xml_pop_parent(pcmk__output_t *out)
#define XML_RSC_ATTR_UNIQUE
#define PCMK__OUTPUT_LIST_FOOTER(out_obj, retcode)
enum rsc_role_e(* state)(const pe_resource_t *, gboolean)
#define XML_RSC_ATTR_PROMOTED_MAX
xmlNode * pe__failed_probe_for_rsc(pe_resource_t *rsc, const char *name)
#define PCMK__OUTPUT_LIST_HEADER(out_obj, cond, retcode, title...)
Cluster status and scheduling.
gboolean(* is_filtered)(pe_resource_t *, GList *, gboolean)
bool pcmk__rsc_filtered_by_node(pe_resource_t *rsc, GList *only_node)
GHashTable * pcmk__strkey_table(GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
void add_hash_param(GHashTable *hash, const char *name, const char *value)
const char * rsc_printable_id(pe_resource_t *rsc)
#define status_print(fmt, args...)
This structure contains everything that makes up a single output formatter.
int pcmk__numeric_strcasecmp(const char *s1, const char *s2)
rsc_role_e
Possible roles that a resource can be in.
#define XML_RSC_ATTR_PROMOTED_NODEMAX
#define pe_rsc_failure_ignored
gboolean common_unpack(xmlNode *xml_obj, pe_resource_t **rsc, pe_resource_t *parent, pe_working_set_t *data_set)
gboolean clone_active(pe_resource_t *rsc, gboolean all)
gboolean crm_is_true(const char *s)
#define XML_CIB_TAG_GROUP
#define pe_rsc_trace(rsc, fmt, args...)
bool pe__resource_is_disabled(pe_resource_t *rsc)
gint sort_node_uname(gconstpointer a, gconstpointer b)
gboolean(* active)(pe_resource_t *, gboolean)
int pe__clone_default(pcmk__output_t *out, va_list args)
GHashTable * allowed_nodes