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 44 clone_variant_data_t *clone_data = NULL;
46 get_clone_variant_data(clone_data,
uber_parent(clone));
47 return clone_data->promoted_max;
61 clone_variant_data_t *clone_data = NULL;
63 get_clone_variant_data(clone_data,
uber_parent(clone));
64 return clone_data->promoted_node_max;
68 sorted_hash_table_values(GHashTable *table)
74 g_hash_table_iter_init(&iter, table);
75 while (g_hash_table_iter_next(&iter, &key, &value)) {
76 if (!g_list_find_custom(retval, value, (GCompareFunc) strcmp)) {
77 retval = g_list_prepend(retval, (
char *) value);
81 retval = g_list_sort(retval, (GCompareFunc) strcmp);
86 nodes_with_status(GHashTable *table,
const char *status)
92 g_hash_table_iter_init(&iter, table);
93 while (g_hash_table_iter_next(&iter, &key, &value)) {
94 if (!strcmp((
char *) value, status)) {
95 retval = g_list_prepend(retval, key);
104 node_list_to_str(
const GList *list)
106 GString *retval = NULL;
108 for (
const GList *iter = list; iter != NULL; iter = iter->next) {
109 pcmk__add_word(&retval, 1024, (
const char *) iter->data);
118 GString *attrs = NULL;
138 rsc->
id,
ID(clone_data->xml_obj_child),
139 (
const char *) attrs->str);
140 g_string_free(attrs, TRUE);
143 rsc->
id,
ID(clone_data->xml_obj_child))
151 if (pe_rsc_is_clone(rsc)) {
152 clone_variant_data_t *clone_data = NULL;
154 get_clone_variant_data(clone_data, rsc);
157 "such as %s can be used only as anonymous clones",
158 rsc->
id, standard, rid);
160 clone_data->clone_node_max = 1;
161 clone_data->clone_max = QB_MIN(clone_data->clone_max,
169 char *child_id = NULL;
171 const char *child_base = NULL;
172 clone_variant_data_t *clone_data = NULL;
174 get_clone_variant_data(clone_data, rsc);
176 child_base =
ID(clone_data->xml_obj_child);
187 gboolean as_orphan = FALSE;
188 char *inc_num = NULL;
189 char *inc_max = NULL;
191 xmlNode *child_copy = NULL;
192 clone_variant_data_t *clone_data = NULL;
194 get_clone_variant_data(clone_data, rsc);
196 CRM_CHECK(clone_data->xml_obj_child != NULL,
return FALSE);
198 if (clone_data->total_clones >= clone_data->clone_max) {
204 inc_num = pcmk__itoa(clone_data->total_clones);
205 inc_max = pcmk__itoa(clone_data->clone_max);
207 child_copy =
copy_xml(clone_data->xml_obj_child);
218 clone_data->total_clones += 1;
219 pe_rsc_trace(child_rsc,
"Setting clone attributes for: %s", child_rsc->
id);
239 xmlNode *a_child = NULL;
240 xmlNode *xml_obj = rsc->
xml;
241 clone_variant_data_t *clone_data = NULL;
248 clone_data = calloc(1,
sizeof(clone_variant_data_t));
252 const char *promoted_max = NULL;
253 const char *promoted_node_max = NULL;
255 promoted_max = g_hash_table_lookup(rsc->
meta,
257 if (promoted_max == NULL) {
259 promoted_max = g_hash_table_lookup(rsc->
meta,
263 promoted_node_max = g_hash_table_lookup(rsc->
meta,
265 if (promoted_node_max == NULL) {
268 g_hash_table_lookup(rsc->
meta,
273 if (promoted_max == NULL) {
274 clone_data->promoted_max = 1;
280 if (promoted_node_max == NULL) {
281 clone_data->promoted_node_max = 1;
284 &(clone_data->promoted_node_max), 0);
292 if (max_clones_node == NULL) {
293 clone_data->clone_node_max = 1;
301 if (max_clones == NULL) {
302 clone_data->clone_max = QB_MAX(1, g_list_length(
data_set->
nodes));
308 clone_data->flags = pcmk__set_flags_as(__func__, __LINE__,
LOG_TRACE,
312 "pe__clone_ordered");
317 "because anonymous clones support only one instance " 318 "per node", rsc->
id);
319 clone_data->clone_node_max = 1;
323 pe_rsc_trace(rsc,
"\tClone max: %d", clone_data->clone_max);
324 pe_rsc_trace(rsc,
"\tClone node max: %d", clone_data->clone_node_max);
331 for (a_child = pcmk__xe_first_child(xml_obj); a_child != NULL;
332 a_child = pcmk__xe_next(a_child)) {
335 clone_data->xml_obj_child = a_child;
340 if (clone_data->xml_obj_child == NULL) {
361 if (clone_data->clone_max <= 0) {
371 for (lpc = 0; lpc < clone_data->clone_max; lpc++) {
378 pe_rsc_trace(rsc,
"Added %d children to resource %s...", clone_data->clone_max, rsc->
id);
387 for (; gIter != NULL; gIter = gIter->next) {
389 gboolean child_active = child_rsc->
fns->
active(child_rsc, all);
391 if (all == FALSE && child_active) {
393 }
else if (all && child_active == FALSE) {
410 short_print(
const char *list,
const char *prefix,
const char *
type,
411 const char *suffix,
long options,
void *print_data)
417 if (!pcmk__str_empty(list)) {
438 const char *target_role = g_hash_table_lookup(rsc->
meta,
451 const char *target_role = configured_role_str(rsc);
464 clone_print_xml(
pe_resource_t *rsc,
const char *pre_text,
long options,
468 const char *target_role = configured_role_str(rsc);
485 for (; gIter != NULL; gIter = gIter->next) {
488 child_rsc->
fns->
print(child_rsc, child_text, options, print_data);
509 for (gIter = rsc->
children; gIter != NULL; gIter = gIter->next) {
534 GString *list_text = NULL;
535 char *child_text = NULL;
536 GString *stopped_list = NULL;
538 GList *promoted_list = NULL;
539 GList *started_list = NULL;
542 clone_variant_data_t *clone_data = NULL;
543 int active_instances = 0;
545 if (pre_text == NULL) {
550 clone_print_xml(rsc, pre_text, options, print_data);
554 get_clone_variant_data(clone_data, rsc);
559 pre_text ? pre_text :
"", rsc->
id,
ID(clone_data->xml_obj_child),
571 for (; gIter != NULL; gIter = gIter->next) {
572 gboolean print_full = FALSE;
574 gboolean partially_active = child_rsc->
fns->
active(child_rsc, FALSE);
594 }
else if (partially_active == FALSE) {
599 pcmk__add_word(&stopped_list, 1024, child_rsc->
id);
609 }
else if (child_rsc->
fns->
active(child_rsc, TRUE)) {
623 promoted_list = g_list_append(promoted_list, location);
626 started_list = g_list_append(started_list, location);
643 child_rsc->
fns->
print(child_rsc, child_text, options, print_data);
652 for (gIter = promoted_list; gIter; gIter = gIter->next) {
655 pcmk__add_word(&list_text, 1024,
host->details->uname);
659 if (list_text != NULL) {
660 short_print((
const char *) list_text->str, child_text,
662 g_string_truncate(list_text, 0);
664 g_list_free(promoted_list);
668 for (gIter = started_list; gIter; gIter = gIter->next) {
671 pcmk__add_word(&list_text, 1024,
host->details->uname);
675 if (list_text != NULL) {
680 short_print((
const char *) list_text->str, child_text,
682 options, print_data);
684 short_print((
const char *) list_text->str, child_text,
689 short_print((
const char *) list_text->str, child_text,
"Started",
690 NULL, options, print_data);
694 g_list_free(started_list);
697 const char *state =
"Stopped";
701 state =
"Stopped (disabled)";
705 && (clone_data->clone_max > active_instances)) {
711 if (stopped_list != NULL) {
712 g_string_truncate(stopped_list, 0);
719 list = g_hash_table_get_values(rsc->
known_on);
723 for (nIter = list; nIter != NULL; nIter = nIter->next) {
727 pcmk__add_word(&stopped_list, 1024, node->
details->
uname);
733 if (stopped_list != NULL) {
734 short_print((
const char *) stopped_list->str, child_text, state,
735 NULL, options, print_data);
743 if (list_text != NULL) {
744 g_string_free(list_text, TRUE);
747 if (stopped_list != NULL) {
748 g_string_free(stopped_list, TRUE);
757 uint32_t show_opts = va_arg(args, uint32_t);
759 GList *only_node = va_arg(args, GList *);
760 GList *only_rsc = va_arg(args, GList *);
765 gboolean printed_header = FALSE;
766 gboolean print_everything = TRUE;
775 all = g_list_prepend(all, (gpointer)
"*");
777 for (; gIter != NULL; gIter = gIter->next) {
784 if (child_rsc->
fns->
is_filtered(child_rsc, only_rsc, print_everything)) {
788 if (!printed_header) {
789 printed_header = TRUE;
799 "target_role", configured_role_str(rsc));
803 out->message(out, crm_map_element_name(child_rsc->
xml), show_opts,
804 child_rsc, only_node, all);
807 if (printed_header) {
819 uint32_t show_opts = va_arg(args, uint32_t);
821 GList *only_node = va_arg(args, GList *);
822 GList *only_rsc = va_arg(args, GList *);
824 GHashTable *stopped = NULL;
826 GString *list_text = NULL;
828 GList *promoted_list = NULL;
829 GList *started_list = NULL;
832 clone_variant_data_t *clone_data = NULL;
833 int active_instances = 0;
835 gboolean print_everything = TRUE;
837 get_clone_variant_data(clone_data, rsc);
846 for (; gIter != NULL; gIter = gIter->next) {
847 gboolean print_full = FALSE;
849 gboolean partially_active = child_rsc->
fns->
active(child_rsc, FALSE);
855 if (child_rsc->
fns->
is_filtered(child_rsc, only_rsc, print_everything)) {
877 }
else if (partially_active == FALSE) {
882 if (stopped == NULL) {
885 g_hash_table_insert(stopped, strdup(child_rsc->
id), strdup(
"Stopped"));
895 }
else if (child_rsc->
fns->
active(child_rsc, TRUE)) {
909 promoted_list = g_list_append(promoted_list, location);
912 started_list = g_list_append(started_list, location);
928 clone_header(out, &rc, rsc, clone_data);
931 all = g_list_prepend(all, (gpointer)
"*");
932 out->message(out, crm_map_element_name(child_rsc->
xml), show_opts,
933 child_rsc, only_node, all);
945 for (gIter = promoted_list; gIter; gIter = gIter->next) {
953 pcmk__add_word(&list_text, 1024,
host->details->uname);
956 g_list_free(promoted_list);
958 if ((list_text != NULL) && (list_text->len > 0)) {
959 clone_header(out, &rc, rsc, clone_data);
962 (
const char *) list_text->str);
963 g_string_truncate(list_text, 0);
968 for (gIter = started_list; gIter; gIter = gIter->next) {
976 pcmk__add_word(&list_text, 1024,
host->details->uname);
979 g_list_free(started_list);
981 if ((list_text != NULL) && (list_text->len > 0)) {
982 clone_header(out, &rc, rsc, clone_data);
988 out->list_item(out, NULL,
990 (
const char *) list_text->str);
993 (
const char *) list_text->str);
997 out->list_item(out, NULL,
"Started: [ %s ]",
998 (
const char *) list_text->str);
1002 if (list_text != NULL) {
1003 g_string_free(list_text, TRUE);
1008 && (clone_data->clone_max > active_instances)) {
1014 if (stopped != NULL) {
1015 g_hash_table_destroy(stopped);
1023 list = g_hash_table_get_values(rsc->
known_on);
1027 for (nIter = list; nIter != NULL; nIter = nIter->next) {
1034 const char *state =
"Stopped";
1037 state =
"Stopped (disabled)";
1040 if (stopped == NULL) {
1043 if (probe_op != NULL) {
1047 g_hash_table_insert(stopped, strdup(node->
details->
uname),
1050 g_hash_table_insert(stopped, strdup(node->
details->
uname),
1058 if (stopped != NULL) {
1059 GList *list = sorted_hash_table_values(stopped);
1061 clone_header(out, &rc, rsc, clone_data);
1063 for (GList *status_iter = list; status_iter != NULL; status_iter = status_iter->next) {
1064 const char *status = status_iter->data;
1065 GList *nodes = nodes_with_status(stopped, status);
1066 GString *nodes_str = node_list_to_str(nodes);
1068 if (nodes_str != NULL) {
1069 if (nodes_str->len > 0) {
1070 out->list_item(out, NULL,
"%s: [ %s ]", status,
1071 (
const char *) nodes_str->str);
1073 g_string_free(nodes_str, TRUE);
1080 g_hash_table_destroy(stopped);
1086 }
else if (active_instances == 0) {
1087 clone_header(out, &rc, rsc, clone_data);
1100 clone_variant_data_t *clone_data = NULL;
1102 get_clone_variant_data(clone_data, rsc);
1106 for (GList *gIter = rsc->
children; gIter != NULL; gIter = gIter->next) {
1112 child_rsc->
xml = NULL;
1116 child_rsc->
fns->
free(child_rsc);
1122 CRM_ASSERT(clone_data->demote_notify == NULL);
1124 CRM_ASSERT(clone_data->start_notify == NULL);
1125 CRM_ASSERT(clone_data->promote_notify == NULL);
1137 for (; gIter != NULL; gIter = gIter->next) {
1141 if (a_role > clone_role) {
1142 clone_role = a_role;
1161 if (pe_rsc_is_clone(rsc)) {
1162 clone_variant_data_t *clone_data = NULL;
1164 get_clone_variant_data(clone_data, rsc);
1165 if (clone_data->clone_max == g_list_length(
data_set->
nodes)) {
1175 gboolean passes = FALSE;
1176 clone_variant_data_t *clone_data = NULL;
1181 get_clone_variant_data(clone_data, rsc);
1185 for (GList *gIter = rsc->
children; gIter != NULL; gIter = gIter->next) {
1202 clone_variant_data_t *clone_data = NULL;
1203 get_clone_variant_data(clone_data, rsc);
1204 return ID(clone_data->xml_obj_child);
1218 clone_variant_data_t *clone_data = NULL;
1220 get_clone_variant_data(clone_data, clone);
1237 clone_variant_data_t *clone_data = NULL;
1239 get_clone_variant_data(clone_data, clone);
1243 clone_data->flags = pcmk__set_flags_as(__func__, __LINE__,
LOG_TRACE,
1245 clone_data->flags, flag,
"flag");
1263 clone_variant_data_t *clone_data = NULL;
1265 get_clone_variant_data(clone_data, clone);
1273 !any_promoting,
true);
1277 if (clone_data->promote_notify == NULL) {
1289 !any_demoting,
true);
1293 if (clone_data->demote_notify == NULL) {
1299 if (clone_data->promote_notify != NULL) {
1301 clone_data->promote_notify->pre,
1304 clone_data->promote_notify->pre,
1307 clone_data->promote_notify->pre,
1310 clone_data->start_notify->pre,
1313 clone_data->stop_notify->pre,
#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)
#define PCMK_XA_PROMOTED_MAX_LEGACY
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)
#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)
gint pe__cmp_node_name(gconstpointer a, gconstpointer b)
#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
bool pe__clone_is_ordered(pe_resource_t *clone)
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.
int pe__clone_promoted_node_max(pe_resource_t *clone)
void pcmk__add_separated_word(GString **list, size_t init_size, const char *word, const char *separator)
pe_resource_t * pe_find_resource(GList *rsc_list, const char *id_rh)
#define XML_RSC_ATTR_STICKINESS
const char * pe__clone_child_id(pe_resource_t *rsc)
pe_action_t * pe__new_rsc_pseudo_action(pe_resource_t *rsc, const char *task, bool optional, bool runnable)
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
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)
#define PCMK_XA_PROMOTED_NODE_MAX_LEGACY
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)
pe_resource_t * uber_parent(pe_resource_t *rsc)
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,...)
int pe__set_clone_flag(pe_resource_t *clone, enum pe__clone_flags flag)
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
bool is_set_recursive(const pe_resource_t *rsc, long long flag, bool any)
void common_free(pe_resource_t *rsc)
gboolean order_actions(pe_action_t *lh_action, pe_action_t *rh_action, enum pe_ordering order)
#define pe_rsc_promotable
#define XML_RSC_ATTR_ORDERED
pe_working_set_t * data_set
void(* print)(pe_resource_t *, const char *, long, void *)
void pe__create_promotable_pseudo_ops(pe_resource_t *clone, bool any_promoting, bool any_demoting)
#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 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...)
notify_data_t * pe__clone_notif_pseudo_ops(pe_resource_t *rsc, const char *task, pe_action_t *action, pe_action_t *complete)
bool pe__resource_is_disabled(pe_resource_t *rsc)
int pe__clone_promoted_max(pe_resource_t *clone)
int pe__unpack_resource(xmlNode *xml_obj, pe_resource_t **rsc, pe_resource_t *parent, pe_working_set_t *data_set)
gboolean(* active)(pe_resource_t *, gboolean)
int pe__clone_default(pcmk__output_t *out, va_list args)
GHashTable * allowed_nodes
gboolean pcmk__str_in_list(const gchar *s, const GList *lst, uint32_t flags)