19 #define VARIANT_CLONE 1
22 #ifdef PCMK__COMPAT_2_0
23 #define PROMOTED_INSTANCES RSC_ROLE_PROMOTED_LEGACY_S "s"
24 #define UNPROMOTED_INSTANCES RSC_ROLE_UNPROMOTED_LEGACY_S "s"
26 #define PROMOTED_INSTANCES RSC_ROLE_PROMOTED_S
27 #define UNPROMOTED_INSTANCES RSC_ROLE_UNPROMOTED_S
34 if (pe_rsc_is_clone(rsc)) {
35 clone_variant_data_t *clone_data = NULL;
37 get_clone_variant_data(clone_data, rsc);
40 "such as %s can be used only as anonymous clones",
41 rsc->
id, standard, rid);
43 clone_data->clone_node_max = 1;
44 clone_data->clone_max = QB_MIN(clone_data->clone_max,
45 g_list_length(data_set->
nodes));
52 char *child_id = NULL;
54 const char *child_base = NULL;
55 clone_variant_data_t *clone_data = NULL;
57 get_clone_variant_data(clone_data, rsc);
59 child_base =
ID(clone_data->xml_obj_child);
70 gboolean as_orphan = FALSE;
74 xmlNode *child_copy = NULL;
75 clone_variant_data_t *clone_data = NULL;
77 get_clone_variant_data(clone_data, rsc);
79 CRM_CHECK(clone_data->xml_obj_child != NULL,
return FALSE);
81 if (clone_data->total_clones >= clone_data->clone_max) {
87 inc_num = pcmk__itoa(clone_data->total_clones);
88 inc_max = pcmk__itoa(clone_data->clone_max);
90 child_copy =
copy_xml(clone_data->xml_obj_child);
94 if (
common_unpack(child_copy, &child_rsc, rsc, data_set) == FALSE) {
102 clone_data->total_clones += 1;
103 pe_rsc_trace(child_rsc,
"Setting clone attributes for: %s", child_rsc->
id);
123 xmlNode *a_child = NULL;
124 xmlNode *xml_obj = rsc->
xml;
125 clone_variant_data_t *clone_data = NULL;
133 clone_data = calloc(1,
sizeof(clone_variant_data_t));
137 const char *promoted_max = NULL;
138 const char *promoted_node_max = NULL;
140 promoted_max = g_hash_table_lookup(rsc->
meta,
142 if (promoted_max == NULL) {
144 promoted_max = g_hash_table_lookup(rsc->
meta,
148 promoted_node_max = g_hash_table_lookup(rsc->
meta,
150 if (promoted_node_max == NULL) {
152 promoted_node_max = g_hash_table_lookup(rsc->
meta,
157 if (promoted_max == NULL) {
158 clone_data->promoted_max = 1;
164 if (promoted_node_max == NULL) {
165 clone_data->promoted_node_max = 1;
168 &(clone_data->promoted_node_max), 0);
176 if (max_clones_node == NULL) {
177 clone_data->clone_node_max = 1;
185 if (max_clones == NULL) {
186 clone_data->clone_max = QB_MAX(1, g_list_length(data_set->
nodes));
195 "because anonymous clones support only one instance "
196 "per node", rsc->
id);
197 clone_data->clone_node_max = 1;
201 pe_rsc_trace(rsc,
"\tClone max: %d", clone_data->clone_max);
202 pe_rsc_trace(rsc,
"\tClone node max: %d", clone_data->clone_node_max);
209 for (a_child = pcmk__xe_first_child(xml_obj); a_child != NULL;
210 a_child = pcmk__xe_next(a_child)) {
213 clone_data->xml_obj_child = a_child;
218 if (clone_data->xml_obj_child == NULL) {
239 if (clone_data->clone_max <= 0) {
249 for (lpc = 0; lpc < clone_data->clone_max; lpc++) {
256 pe_rsc_trace(rsc,
"Added %d children to resource %s...", clone_data->clone_max, rsc->
id);
265 for (; gIter != NULL; gIter = gIter->next) {
267 gboolean child_active = child_rsc->
fns->
active(child_rsc, all);
269 if (all == FALSE && child_active) {
271 }
else if (all && child_active == FALSE) {
284 short_print(
char *list,
const char *prefix,
const char *
type,
const char *suffix,
long options,
void *print_data)
294 status_print(
"%s%s: [ %s ]%s", prefix, type, list, suffix);
296 if (options & pe_print_html) {
311 const char *target_role = g_hash_table_lookup(rsc->
meta,
324 const char *target_role = configured_role_str(rsc);
333 clone_print_xml(
pe_resource_t * rsc,
const char *pre_text,
long options,
void *print_data)
336 const char *target_role = configured_role_str(rsc);
353 for (; gIter != NULL; gIter = gIter->next) {
356 child_rsc->
fns->
print(child_rsc, child_text, options, print_data);
376 for (gIter = rsc->
children; gIter != NULL; gIter = gIter->next) {
396 char *list_text = NULL;
397 char *child_text = NULL;
398 char *stopped_list = NULL;
399 size_t list_text_len = 0;
400 size_t stopped_list_len = 0;
402 GList *promoted_list = NULL;
403 GList *started_list = NULL;
406 clone_variant_data_t *clone_data = NULL;
407 int active_instances = 0;
409 if (pre_text == NULL) {
414 clone_print_xml(rsc, pre_text, options, print_data);
418 get_clone_variant_data(clone_data, rsc);
423 pre_text ? pre_text :
"", rsc->
id,
ID(clone_data->xml_obj_child),
428 if (options & pe_print_html) {
435 for (; gIter != NULL; gIter = gIter->next) {
436 gboolean print_full = FALSE;
438 gboolean partially_active = child_rsc->
fns->
active(child_rsc, FALSE);
458 }
else if (partially_active == FALSE) {
462 pcmk__add_word(&stopped_list, &stopped_list_len, child_rsc->
id);
472 }
else if (child_rsc->
fns->
active(child_rsc, TRUE)) {
486 promoted_list = g_list_append(promoted_list, location);
489 started_list = g_list_append(started_list, location);
503 if (options & pe_print_html) {
506 child_rsc->
fns->
print(child_rsc, child_text, options, print_data);
507 if (options & pe_print_html) {
515 for (gIter = promoted_list; gIter; gIter = gIter->next) {
518 pcmk__add_word(&list_text, &list_text_len, host->
details->
uname);
524 g_list_free(promoted_list);
531 for (gIter = started_list; gIter; gIter = gIter->next) {
534 pcmk__add_word(&list_text, &list_text_len, host->
details->
uname);
542 short_print(list_text, child_text,
547 options, print_data);
551 short_print(list_text, child_text,
"Started", NULL, options, print_data);
554 g_list_free(started_list);
560 const char *state =
"Stopped";
564 state =
"Stopped (disabled)";
568 && (clone_data->clone_max > active_instances)) {
576 stopped_list_len = 0;
582 list = g_hash_table_get_values(rsc->
known_on);
586 for (nIter = list; nIter != NULL; nIter = nIter->next) {
590 pcmk__add_word(&stopped_list, &stopped_list_len,
597 short_print(stopped_list, child_text, state, NULL, options, print_data);
601 if (options & pe_print_html) {
608 PCMK__OUTPUT_ARGS(
"clone",
"unsigned int",
"pe_resource_t *",
"GList *",
"GList *")
612 unsigned int options = va_arg(args,
unsigned int);
614 GList *only_node = va_arg(args, GList *);
615 GList *only_rsc = va_arg(args, GList *);
619 gboolean printed_header = FALSE;
620 gboolean print_everything = TRUE;
629 for (; gIter != NULL; gIter = gIter->next) {
636 if (child_rsc->
fns->
is_filtered(child_rsc, only_rsc, print_everything)) {
640 if (!printed_header) {
641 printed_header = TRUE;
651 "target_role", configured_role_str(rsc));
655 out->message(out, crm_map_element_name(child_rsc->
xml), options,
656 child_rsc, only_node, only_rsc);
659 if (printed_header) {
666 PCMK__OUTPUT_ARGS(
"clone",
"unsigned int",
"pe_resource_t *",
"GList *",
"GList *")
670 unsigned int options = va_arg(args,
unsigned int);
672 GList *only_node = va_arg(args, GList *);
673 GList *only_rsc = va_arg(args, GList *);
675 char *list_text = NULL;
676 char *stopped_list = NULL;
677 size_t list_text_len = 0;
678 size_t stopped_list_len = 0;
680 GList *promoted_list = NULL;
681 GList *started_list = NULL;
684 clone_variant_data_t *clone_data = NULL;
685 int active_instances = 0;
687 gboolean print_everything = TRUE;
689 get_clone_variant_data(clone_data, rsc);
698 out->begin_list(out, NULL, NULL,
"Clone Set: %s [%s]%s%s%s%s",
699 rsc->
id,
ID(clone_data->xml_obj_child),
706 for (; gIter != NULL; gIter = gIter->next) {
707 gboolean print_full = FALSE;
709 gboolean partially_active = child_rsc->
fns->
active(child_rsc, FALSE);
715 if (child_rsc->
fns->
is_filtered(child_rsc, only_rsc, print_everything)) {
737 }
else if (partially_active == FALSE) {
741 pcmk__add_word(&stopped_list, &stopped_list_len, child_rsc->
id);
751 }
else if (child_rsc->
fns->
active(child_rsc, TRUE)) {
765 promoted_list = g_list_append(promoted_list, location);
768 started_list = g_list_append(started_list, location);
785 all = g_list_prepend(all, strdup(
"*"));
786 out->message(out, crm_map_element_name(child_rsc->
xml), options,
787 child_rsc, only_node, all);
788 g_list_free_full(all, free);
800 for (gIter = promoted_list; gIter; gIter = gIter->next) {
807 pcmk__add_word(&list_text, &list_text_len, host->
details->
uname);
811 if (list_text != NULL) {
813 g_list_free(promoted_list);
821 for (gIter = started_list; gIter; gIter = gIter->next) {
828 pcmk__add_word(&list_text, &list_text_len, host->
details->
uname);
832 if (list_text != NULL) {
837 out->list_item(out, NULL,
846 out->list_item(out, NULL,
"Started: [ %s ]", list_text);
849 g_list_free(started_list);
856 const char *state =
"Stopped";
860 state =
"Stopped (disabled)";
864 && (clone_data->clone_max > active_instances)) {
872 stopped_list_len = 0;
878 list = g_hash_table_get_values(rsc->
known_on);
882 for (nIter = list; nIter != NULL; nIter = nIter->next) {
887 pcmk__add_word(&stopped_list, &stopped_list_len,
894 if (stopped_list != NULL) {
895 out->list_item(out, NULL,
"%s: [ %s ]", state, stopped_list);
897 stopped_list_len = 0;
906 PCMK__OUTPUT_ARGS(
"clone",
"unsigned int",
"pe_resource_t *",
"GList *",
"GList *")
910 unsigned int options = va_arg(args,
unsigned int);
912 GList *only_node = va_arg(args, GList *);
913 GList *only_rsc = va_arg(args, GList *);
915 char *list_text = NULL;
916 char *stopped_list = NULL;
917 size_t list_text_len = 0;
918 size_t stopped_list_len = 0;
920 GList *promoted_list = NULL;
921 GList *started_list = NULL;
924 clone_variant_data_t *clone_data = NULL;
925 int active_instances = 0;
927 gboolean print_everything = TRUE;
929 get_clone_variant_data(clone_data, rsc);
938 out->begin_list(out, NULL, NULL,
"Clone Set: %s [%s]%s%s%s%s",
939 rsc->
id,
ID(clone_data->xml_obj_child),
946 for (; gIter != NULL; gIter = gIter->next) {
947 gboolean print_full = FALSE;
949 gboolean partially_active = child_rsc->
fns->
active(child_rsc, FALSE);
955 if (child_rsc->
fns->
is_filtered(child_rsc, only_rsc, print_everything)) {
977 }
else if (partially_active == FALSE) {
981 pcmk__add_word(&stopped_list, &stopped_list_len, child_rsc->
id);
991 }
else if (child_rsc->
fns->
active(child_rsc, TRUE)) {
1005 promoted_list = g_list_append(promoted_list, location);
1008 started_list = g_list_append(started_list, location);
1025 all = g_list_prepend(all, strdup(
"*"));
1026 out->message(out, crm_map_element_name(child_rsc->
xml), options,
1027 child_rsc, only_node, all);
1028 g_list_free_full(all, free);
1040 for (gIter = promoted_list; gIter; gIter = gIter->next) {
1047 pcmk__add_word(&list_text, &list_text_len, host->
details->
uname);
1051 if (list_text != NULL) {
1053 g_list_free(promoted_list);
1061 for (gIter = started_list; gIter; gIter = gIter->next) {
1068 pcmk__add_word(&list_text, &list_text_len, host->
details->
uname);
1072 if (list_text != NULL) {
1078 "[ %s ]", list_text);
1083 out->list_item(out,
"Started",
"[ %s ]", list_text);
1086 g_list_free(started_list);
1092 const char *state =
"Stopped";
1096 state =
"Stopped (disabled)";
1100 && (clone_data->clone_max > active_instances)) {
1107 stopped_list = NULL;
1108 stopped_list_len = 0;
1114 list = g_hash_table_get_values(rsc->
known_on);
1118 for (nIter = list; nIter != NULL; nIter = nIter->next) {
1123 pcmk__add_word(&stopped_list, &stopped_list_len,
1130 if (stopped_list != NULL) {
1131 out->list_item(out, state,
"[ %s ]", stopped_list);
1144 clone_variant_data_t *clone_data = NULL;
1146 get_clone_variant_data(clone_data, rsc);
1150 for (GList *gIter = rsc->
children; gIter != NULL; gIter = gIter->next) {
1156 child_rsc->
xml = NULL;
1160 child_rsc->
fns->
free(child_rsc);
1166 CRM_ASSERT(clone_data->demote_notify == NULL);
1168 CRM_ASSERT(clone_data->start_notify == NULL);
1169 CRM_ASSERT(clone_data->promote_notify == NULL);
1181 for (; gIter != NULL; gIter = gIter->next) {
1185 if (a_role > clone_role) {
1186 clone_role = a_role;
1205 if (pe_rsc_is_clone(rsc)) {
1206 clone_variant_data_t *clone_data = NULL;
1208 get_clone_variant_data(clone_data, rsc);
1209 if (clone_data->clone_max == g_list_length(data_set->
nodes)) {
1219 gboolean passes = FALSE;
1220 clone_variant_data_t *clone_data = NULL;
1225 get_clone_variant_data(clone_data, rsc);
1229 for (GList *gIter = rsc->
children; gIter != NULL; gIter = gIter->next) {
#define CRM_CHECK(expr, failure_action)
pe_node_t * pe_find_node(GList *node_list, const char *uname)
bool is_set_recursive(pe_resource_t *rsc, long long flag, bool any)
#define PROMOTED_INSTANCES
enum rsc_role_e(* state)(const pe_resource_t *, gboolean)
int pcmk__scan_min_int(const char *text, int *result, int minimum)
#define UNPROMOTED_INSTANCES
gboolean pcmk__str_in_list(GList *lst, const gchar *s)
#define XML_RSC_ATTR_INCARNATION
#define pcmk__config_err(fmt...)
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
enum crm_ais_msg_types type
#define XML_RSC_ATTR_INCARNATION_MAX
#define PCMK_XE_PROMOTED_MAX_LEGACY
void clone_free(pe_resource_t *rsc)
int pe__clone_html(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)
enum rsc_role_e clone_resource_state(const pe_resource_t *rsc, gboolean current)
gboolean clone_active(pe_resource_t *rsc, gboolean all)
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__clone_xml(pcmk__output_t *out, va_list args)
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
pe_resource_t * find_clone_instance(pe_resource_t *rsc, const char *sub_id, pe_working_set_t *data_set)
void common_free(pe_resource_t *rsc)
#define pe_rsc_promotable
#define XML_RSC_ATTR_ORDERED
void clone_print(pe_resource_t *rsc, const char *pre_text, long options, void *print_data)
#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_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)
void(* print)(pe_resource_t *, const char *, long, void *)
#define XML_RSC_ATTR_UNIQUE
#define XML_RSC_ATTR_PROMOTED_MAX
gboolean(* is_filtered)(pe_resource_t *, GList *, gboolean)
Cluster status and scheduling.
bool pcmk__rsc_filtered_by_node(pe_resource_t *rsc, GList *only_node)
int pe__clone_text(pcmk__output_t *out, va_list args)
void add_hash_param(GHashTable *hash, const char *name, const char *value)
gboolean clone_unpack(pe_resource_t *rsc, pe_working_set_t *data_set)
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.
void(* free)(pe_resource_t *)
rsc_role_e
Possible roles that a resource can be in.
#define XML_RSC_ATTR_PROMOTED_NODEMAX
bool pe__is_universal_clone(pe_resource_t *rsc, pe_working_set_t *data_set)
#define pe_rsc_failure_ignored
pe_node_t *(* location)(const pe_resource_t *, GList **, int)
gboolean common_unpack(xmlNode *xml_obj, pe_resource_t **rsc, pe_resource_t *parent, pe_working_set_t *data_set)
gboolean crm_is_true(const char *s)
#define XML_CIB_TAG_GROUP
#define pe_rsc_trace(rsc, fmt, args...)
gboolean(* active)(pe_resource_t *, gboolean)
bool pe__resource_is_disabled(pe_resource_t *rsc)
gint sort_node_uname(gconstpointer a, gconstpointer b)
gboolean pe__clone_is_filtered(pe_resource_t *rsc, GList *only_rsc, gboolean check_parent)
GHashTable * allowed_nodes