20 #define VARIANT_CLONE 1 23 #ifdef PCMK__COMPAT_2_0 24 #define PROMOTED_INSTANCES RSC_ROLE_PROMOTED_LEGACY_S "s" 25 #define UNPROMOTED_INSTANCES RSC_ROLE_UNPROMOTED_LEGACY_S "s" 27 #define PROMOTED_INSTANCES RSC_ROLE_PROMOTED_S 28 #define UNPROMOTED_INSTANCES RSC_ROLE_UNPROMOTED_S 55 rsc->
id,
ID(clone_data->xml_obj_child),
60 rsc->
id,
ID(clone_data->xml_obj_child))
68 if (pe_rsc_is_clone(rsc)) {
69 clone_variant_data_t *clone_data = NULL;
71 get_clone_variant_data(clone_data, rsc);
74 "such as %s can be used only as anonymous clones",
75 rsc->
id, standard, rid);
77 clone_data->clone_node_max = 1;
78 clone_data->clone_max = QB_MIN(clone_data->clone_max,
79 g_list_length(data_set->
nodes));
86 char *child_id = NULL;
88 const char *child_base = NULL;
89 clone_variant_data_t *clone_data = NULL;
91 get_clone_variant_data(clone_data, rsc);
93 child_base =
ID(clone_data->xml_obj_child);
104 gboolean as_orphan = FALSE;
105 char *inc_num = NULL;
106 char *inc_max = NULL;
108 xmlNode *child_copy = NULL;
109 clone_variant_data_t *clone_data = NULL;
111 get_clone_variant_data(clone_data, rsc);
113 CRM_CHECK(clone_data->xml_obj_child != NULL,
return FALSE);
115 if (clone_data->total_clones >= clone_data->clone_max) {
121 inc_num = pcmk__itoa(clone_data->total_clones);
122 inc_max = pcmk__itoa(clone_data->clone_max);
124 child_copy =
copy_xml(clone_data->xml_obj_child);
128 if (
common_unpack(child_copy, &child_rsc, rsc, data_set) == FALSE) {
136 clone_data->total_clones += 1;
137 pe_rsc_trace(child_rsc,
"Setting clone attributes for: %s", child_rsc->
id);
157 xmlNode *a_child = NULL;
158 xmlNode *xml_obj = rsc->
xml;
159 clone_variant_data_t *clone_data = NULL;
167 clone_data = calloc(1,
sizeof(clone_variant_data_t));
171 const char *promoted_max = NULL;
172 const char *promoted_node_max = NULL;
174 promoted_max = g_hash_table_lookup(rsc->
meta,
176 if (promoted_max == NULL) {
178 promoted_max = g_hash_table_lookup(rsc->
meta,
182 promoted_node_max = g_hash_table_lookup(rsc->
meta,
184 if (promoted_node_max == NULL) {
186 promoted_node_max = g_hash_table_lookup(rsc->
meta,
191 if (promoted_max == NULL) {
192 clone_data->promoted_max = 1;
198 if (promoted_node_max == NULL) {
199 clone_data->promoted_node_max = 1;
202 &(clone_data->promoted_node_max), 0);
210 if (max_clones_node == NULL) {
211 clone_data->clone_node_max = 1;
219 if (max_clones == NULL) {
220 clone_data->clone_max = QB_MAX(1, g_list_length(data_set->
nodes));
229 "because anonymous clones support only one instance " 230 "per node", rsc->
id);
231 clone_data->clone_node_max = 1;
235 pe_rsc_trace(rsc,
"\tClone max: %d", clone_data->clone_max);
236 pe_rsc_trace(rsc,
"\tClone node max: %d", clone_data->clone_node_max);
243 for (a_child = pcmk__xe_first_child(xml_obj); a_child != NULL;
244 a_child = pcmk__xe_next(a_child)) {
247 clone_data->xml_obj_child = a_child;
252 if (clone_data->xml_obj_child == NULL) {
273 if (clone_data->clone_max <= 0) {
283 for (lpc = 0; lpc < clone_data->clone_max; lpc++) {
290 pe_rsc_trace(rsc,
"Added %d children to resource %s...", clone_data->clone_max, rsc->
id);
299 for (; gIter != NULL; gIter = gIter->next) {
301 gboolean child_active = child_rsc->
fns->
active(child_rsc, all);
303 if (all == FALSE && child_active) {
305 }
else if (all && child_active == FALSE) {
318 short_print(
char *list,
const char *prefix,
const char *
type,
const char *suffix,
long options,
void *print_data)
345 const char *target_role = g_hash_table_lookup(rsc->
meta,
358 const char *target_role = configured_role_str(rsc);
367 clone_print_xml(
pe_resource_t * rsc,
const char *pre_text,
long options,
void *print_data)
370 const char *target_role = configured_role_str(rsc);
387 for (; gIter != NULL; gIter = gIter->next) {
390 child_rsc->
fns->
print(child_rsc, child_text, options, print_data);
410 for (gIter = rsc->
children; gIter != NULL; gIter = gIter->next) {
430 char *list_text = NULL;
431 char *child_text = NULL;
432 char *stopped_list = NULL;
433 size_t list_text_len = 0;
434 size_t stopped_list_len = 0;
436 GList *promoted_list = NULL;
437 GList *started_list = NULL;
440 clone_variant_data_t *clone_data = NULL;
441 int active_instances = 0;
443 if (pre_text == NULL) {
448 clone_print_xml(rsc, pre_text, options, print_data);
452 get_clone_variant_data(clone_data, rsc);
457 pre_text ? pre_text :
"", rsc->
id,
ID(clone_data->xml_obj_child),
469 for (; gIter != NULL; gIter = gIter->next) {
470 gboolean print_full = FALSE;
472 gboolean partially_active = child_rsc->
fns->
active(child_rsc, FALSE);
492 }
else if (partially_active == FALSE) {
496 pcmk__add_word(&stopped_list, &stopped_list_len, child_rsc->
id);
506 }
else if (child_rsc->
fns->
active(child_rsc, TRUE)) {
520 promoted_list = g_list_append(promoted_list, location);
523 started_list = g_list_append(started_list, location);
540 child_rsc->
fns->
print(child_rsc, child_text, options, print_data);
549 for (gIter = promoted_list; gIter; gIter = gIter->next) {
552 pcmk__add_word(&list_text, &list_text_len,
host->details->uname);
558 g_list_free(promoted_list);
565 for (gIter = started_list; gIter; gIter = gIter->next) {
568 pcmk__add_word(&list_text, &list_text_len,
host->details->uname);
576 short_print(list_text, child_text,
581 options, print_data);
585 short_print(list_text, child_text,
"Started", NULL, options, print_data);
588 g_list_free(started_list);
594 const char *state =
"Stopped";
598 state =
"Stopped (disabled)";
602 && (clone_data->clone_max > active_instances)) {
610 stopped_list_len = 0;
616 list = g_hash_table_get_values(rsc->
known_on);
620 for (nIter = list; nIter != NULL; nIter = nIter->next) {
624 pcmk__add_word(&stopped_list, &stopped_list_len,
631 short_print(stopped_list, child_text, state, NULL, options, print_data);
642 PCMK__OUTPUT_ARGS(
"clone",
"unsigned int",
"pe_resource_t *",
"GList *",
"GList *")
646 unsigned int show_opts = va_arg(args,
unsigned int);
648 GList *only_node = va_arg(args, GList *);
649 GList *only_rsc = va_arg(args, GList *);
654 gboolean printed_header = FALSE;
655 gboolean print_everything = TRUE;
664 all = g_list_prepend(all, (gpointer)
"*");
666 for (; gIter != NULL; gIter = gIter->next) {
673 if (child_rsc->
fns->
is_filtered(child_rsc, only_rsc, print_everything)) {
677 if (!printed_header) {
678 printed_header = TRUE;
688 "target_role", configured_role_str(rsc));
692 out->message(out, crm_map_element_name(child_rsc->
xml), show_opts,
693 child_rsc, only_node, all);
696 if (printed_header) {
704 PCMK__OUTPUT_ARGS(
"clone",
"unsigned int",
"pe_resource_t *",
"GList *",
"GList *")
708 unsigned int show_opts = va_arg(args,
unsigned int);
710 GList *only_node = va_arg(args, GList *);
711 GList *only_rsc = va_arg(args, GList *);
713 char *list_text = NULL;
714 char *stopped_list = NULL;
715 size_t list_text_len = 0;
716 size_t stopped_list_len = 0;
718 GList *promoted_list = NULL;
719 GList *started_list = NULL;
722 clone_variant_data_t *clone_data = NULL;
723 int active_instances = 0;
725 gboolean print_everything = TRUE;
727 get_clone_variant_data(clone_data, rsc);
736 for (; gIter != NULL; gIter = gIter->next) {
737 gboolean print_full = FALSE;
739 gboolean partially_active = child_rsc->
fns->
active(child_rsc, FALSE);
745 if (child_rsc->
fns->
is_filtered(child_rsc, only_rsc, print_everything)) {
767 }
else if (partially_active == FALSE) {
771 pcmk__add_word(&stopped_list, &stopped_list_len, child_rsc->
id);
781 }
else if (child_rsc->
fns->
active(child_rsc, TRUE)) {
795 promoted_list = g_list_append(promoted_list, location);
798 started_list = g_list_append(started_list, location);
814 clone_header(out, &
rc, rsc, clone_data);
817 all = g_list_prepend(all, (gpointer)
"*");
818 out->message(out, crm_map_element_name(child_rsc->
xml), show_opts,
819 child_rsc, only_node, all);
832 for (gIter = promoted_list; gIter; gIter = gIter->next) {
840 pcmk__add_word(&list_text, &list_text_len,
host->details->uname);
843 g_list_free(promoted_list);
845 if (list_text != NULL) {
846 clone_header(out, &
rc, rsc, clone_data);
856 for (gIter = started_list; gIter; gIter = gIter->next) {
864 pcmk__add_word(&list_text, &list_text_len,
host->details->uname);
867 g_list_free(started_list);
869 if (list_text != NULL) {
870 clone_header(out, &
rc, rsc, clone_data);
876 out->list_item(out, NULL,
885 out->list_item(out, NULL,
"Started: [ %s ]", list_text);
893 const char *state =
"Stopped";
897 state =
"Stopped (disabled)";
901 && (clone_data->clone_max > active_instances)) {
909 stopped_list_len = 0;
915 list = g_hash_table_get_values(rsc->
known_on);
919 for (nIter = list; nIter != NULL; nIter = nIter->next) {
925 pcmk__add_word(&stopped_list, &stopped_list_len,
932 if (stopped_list != NULL) {
933 clone_header(out, &
rc, rsc, clone_data);
935 out->list_item(out, NULL,
"%s: [ %s ]", state, stopped_list);
937 stopped_list_len = 0;
943 }
else if (active_instances == 0) {
944 clone_header(out, &
rc, rsc, clone_data);
957 clone_variant_data_t *clone_data = NULL;
959 get_clone_variant_data(clone_data, rsc);
963 for (GList *gIter = rsc->
children; gIter != NULL; gIter = gIter->next) {
969 child_rsc->
xml = NULL;
973 child_rsc->
fns->
free(child_rsc);
979 CRM_ASSERT(clone_data->demote_notify == NULL);
982 CRM_ASSERT(clone_data->promote_notify == NULL);
994 for (; gIter != NULL; gIter = gIter->next) {
998 if (a_role > clone_role) {
1018 if (pe_rsc_is_clone(rsc)) {
1019 clone_variant_data_t *clone_data = NULL;
1021 get_clone_variant_data(clone_data, rsc);
1022 if (clone_data->clone_max == g_list_length(data_set->
nodes)) {
1032 gboolean passes = FALSE;
1033 clone_variant_data_t *clone_data = NULL;
1038 get_clone_variant_data(clone_data, rsc);
1042 for (GList *gIter = rsc->
children; gIter != NULL; gIter = gIter->next) {
#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
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
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
#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)
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.
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