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 30 typedef struct clone_variant_data_s {
35 int promoted_node_max;
46 xmlNode *xml_obj_child;
49 #define get_clone_variant_data(data, rsc) \ 50 CRM_ASSERT((rsc != NULL) && (rsc->variant == pe_clone)); \ 51 data = (clone_variant_data_t *) rsc->variant_opaque; 67 return clone_data->clone_max;
84 return clone_data->clone_node_max;
101 return clone_data->promoted_max;
118 return clone_data->promoted_node_max;
122 sorted_hash_table_values(GHashTable *table)
124 GList *retval = NULL;
128 g_hash_table_iter_init(&iter, table);
129 while (g_hash_table_iter_next(&iter, &key, &value)) {
130 if (!g_list_find_custom(retval, value, (GCompareFunc) strcmp)) {
131 retval = g_list_prepend(retval, (
char *) value);
135 retval = g_list_sort(retval, (GCompareFunc) strcmp);
140 nodes_with_status(GHashTable *table,
const char *status)
142 GList *retval = NULL;
146 g_hash_table_iter_init(&iter, table);
147 while (g_hash_table_iter_next(&iter, &key, &value)) {
148 if (!strcmp((
char *) value, status)) {
149 retval = g_list_prepend(retval, key);
158 node_list_to_str(
const GList *list)
160 GString *retval = NULL;
162 for (
const GList *iter = list; iter != NULL; iter = iter->next) {
163 pcmk__add_word(&retval, 1024, (
const char *) iter->data);
173 GString *attrs = NULL;
196 rsc->
id,
ID(clone_data->xml_obj_child),
197 (
const char *) attrs->str, desc ?
" (" :
"",
198 desc ? desc :
"", desc ?
")" :
"");
199 g_string_free(attrs, TRUE);
202 rsc->
id,
ID(clone_data->xml_obj_child),
203 desc ?
" (" :
"", desc ? desc :
"",
212 if (pe_rsc_is_clone(rsc)) {
216 "such as %s can be used only as anonymous clones",
217 rsc->
id, standard, rid);
219 clone_data->clone_node_max = 1;
220 clone_data->clone_max = QB_MIN(clone_data->clone_max,
228 char *child_id = NULL;
230 const char *child_base = NULL;
235 child_base =
ID(clone_data->xml_obj_child);
246 gboolean as_orphan = FALSE;
247 char *inc_num = NULL;
248 char *inc_max = NULL;
250 xmlNode *child_copy = NULL;
255 CRM_CHECK(clone_data->xml_obj_child != NULL,
return FALSE);
257 if (clone_data->total_clones >= clone_data->clone_max) {
263 inc_num = pcmk__itoa(clone_data->total_clones);
264 inc_max = pcmk__itoa(clone_data->clone_max);
266 child_copy =
copy_xml(clone_data->xml_obj_child);
277 clone_data->total_clones += 1;
278 pe_rsc_trace(child_rsc,
"Setting clone attributes for: %s", child_rsc->
id);
298 xmlNode *a_child = NULL;
299 xmlNode *xml_obj = rsc->
xml;
311 const char *promoted_max = NULL;
312 const char *promoted_node_max = NULL;
314 promoted_max = g_hash_table_lookup(rsc->
meta,
316 if (promoted_max == NULL) {
318 promoted_max = g_hash_table_lookup(rsc->
meta,
322 promoted_node_max = g_hash_table_lookup(rsc->
meta,
324 if (promoted_node_max == NULL) {
327 g_hash_table_lookup(rsc->
meta,
332 if (promoted_max == NULL) {
333 clone_data->promoted_max = 1;
339 if (promoted_node_max == NULL) {
340 clone_data->promoted_node_max = 1;
343 &(clone_data->promoted_node_max), 0);
351 if (max_clones_node == NULL) {
352 clone_data->clone_node_max = 1;
360 if (max_clones == NULL) {
361 clone_data->clone_max = QB_MAX(1, g_list_length(
data_set->
nodes));
367 clone_data->flags = pcmk__set_flags_as(__func__, __LINE__,
LOG_TRACE,
371 "pe__clone_ordered");
376 "because anonymous clones support only one instance " 377 "per node", rsc->
id);
378 clone_data->clone_node_max = 1;
382 pe_rsc_trace(rsc,
"\tClone max: %d", clone_data->clone_max);
383 pe_rsc_trace(rsc,
"\tClone node max: %d", clone_data->clone_node_max);
390 for (a_child = pcmk__xe_first_child(xml_obj); a_child != NULL;
391 a_child = pcmk__xe_next(a_child)) {
394 clone_data->xml_obj_child = a_child;
399 if (clone_data->xml_obj_child == NULL) {
420 if (clone_data->clone_max <= 0) {
430 for (lpc = 0; lpc < clone_data->clone_max; lpc++) {
437 pe_rsc_trace(rsc,
"Added %d children to resource %s...", clone_data->clone_max, rsc->
id);
446 for (; gIter != NULL; gIter = gIter->next) {
448 gboolean child_active = child_rsc->
fns->
active(child_rsc, all);
450 if (all == FALSE && child_active) {
452 }
else if (all && child_active == FALSE) {
469 short_print(
const char *list,
const char *prefix,
const char *
type,
470 const char *suffix,
long options,
void *print_data)
476 if (!pcmk__str_empty(list)) {
497 const char *target_role = g_hash_table_lookup(rsc->
meta,
510 const char *target_role = configured_role_str(rsc);
523 clone_print_xml(
pe_resource_t *rsc,
const char *pre_text,
long options,
527 const char *target_role = configured_role_str(rsc);
544 for (; gIter != NULL; gIter = gIter->next) {
547 child_rsc->
fns->
print(child_rsc, child_text, options, print_data);
568 for (gIter = rsc->
children; gIter != NULL; gIter = gIter->next) {
593 GString *list_text = NULL;
594 char *child_text = NULL;
595 GString *stopped_list = NULL;
597 GList *promoted_list = NULL;
598 GList *started_list = NULL;
602 int active_instances = 0;
604 if (pre_text == NULL) {
609 clone_print_xml(rsc, pre_text, options, print_data);
618 pre_text ? pre_text :
"", rsc->
id,
ID(clone_data->xml_obj_child),
630 for (; gIter != NULL; gIter = gIter->next) {
631 gboolean print_full = FALSE;
633 gboolean partially_active = child_rsc->
fns->
active(child_rsc, FALSE);
653 }
else if (partially_active == FALSE) {
658 pcmk__add_word(&stopped_list, 1024, child_rsc->
id);
668 }
else if (child_rsc->
fns->
active(child_rsc, TRUE)) {
682 promoted_list = g_list_append(promoted_list, location);
685 started_list = g_list_append(started_list, location);
702 child_rsc->
fns->
print(child_rsc, child_text, options, print_data);
711 for (gIter = promoted_list; gIter; gIter = gIter->next) {
714 pcmk__add_word(&list_text, 1024,
host->details->uname);
718 if (list_text != NULL) {
719 short_print((
const char *) list_text->str, child_text,
721 g_string_truncate(list_text, 0);
723 g_list_free(promoted_list);
727 for (gIter = started_list; gIter; gIter = gIter->next) {
730 pcmk__add_word(&list_text, 1024,
host->details->uname);
734 if (list_text != NULL) {
739 short_print((
const char *) list_text->str, child_text,
741 options, print_data);
743 short_print((
const char *) list_text->str, child_text,
748 short_print((
const char *) list_text->str, child_text,
"Started",
749 NULL, options, print_data);
753 g_list_free(started_list);
756 const char *state =
"Stopped";
760 state =
"Stopped (disabled)";
764 && (clone_data->clone_max > active_instances)) {
770 if (stopped_list != NULL) {
771 g_string_truncate(stopped_list, 0);
778 list = g_hash_table_get_values(rsc->
known_on);
782 for (nIter = list; nIter != NULL; nIter = nIter->next) {
786 pcmk__add_word(&stopped_list, 1024, node->
details->
uname);
792 if (stopped_list != NULL) {
793 short_print((
const char *) stopped_list->str, child_text, state,
794 NULL, options, print_data);
802 if (list_text != NULL) {
803 g_string_free(list_text, TRUE);
806 if (stopped_list != NULL) {
807 g_string_free(stopped_list, TRUE);
816 uint32_t show_opts = va_arg(args, uint32_t);
818 GList *only_node = va_arg(args, GList *);
819 GList *only_rsc = va_arg(args, GList *);
822 const char *desc = NULL;
826 gboolean printed_header = FALSE;
827 gboolean print_everything = TRUE;
838 all = g_list_prepend(all, (gpointer)
"*");
840 for (; gIter != NULL; gIter = gIter->next) {
847 if (child_rsc->
fns->
is_filtered(child_rsc, only_rsc, print_everything)) {
851 if (!printed_header) {
852 printed_header = TRUE;
865 "target_role", configured_role_str(rsc),
866 "description", desc);
870 out->message(out, crm_map_element_name(child_rsc->
xml), show_opts,
871 child_rsc, only_node, all);
874 if (printed_header) {
886 uint32_t show_opts = va_arg(args, uint32_t);
888 GList *only_node = va_arg(args, GList *);
889 GList *only_rsc = va_arg(args, GList *);
891 GHashTable *stopped = NULL;
893 GString *list_text = NULL;
895 GList *promoted_list = NULL;
896 GList *started_list = NULL;
899 const char *desc = NULL;
902 int active_instances = 0;
904 gboolean print_everything = TRUE;
917 for (; gIter != NULL; gIter = gIter->next) {
918 gboolean print_full = FALSE;
920 gboolean partially_active = child_rsc->
fns->
active(child_rsc, FALSE);
926 if (child_rsc->
fns->
is_filtered(child_rsc, only_rsc, print_everything)) {
948 }
else if (partially_active == FALSE) {
953 if (stopped == NULL) {
956 g_hash_table_insert(stopped, strdup(child_rsc->
id), strdup(
"Stopped"));
966 }
else if (child_rsc->
fns->
active(child_rsc, TRUE)) {
980 promoted_list = g_list_append(promoted_list, location);
983 started_list = g_list_append(started_list, location);
999 clone_header(out, &rc, rsc, clone_data, desc);
1002 all = g_list_prepend(all, (gpointer)
"*");
1003 out->message(out, crm_map_element_name(child_rsc->
xml), show_opts,
1004 child_rsc, only_node, all);
1016 for (gIter = promoted_list; gIter; gIter = gIter->next) {
1024 pcmk__add_word(&list_text, 1024,
host->details->uname);
1027 g_list_free(promoted_list);
1029 if ((list_text != NULL) && (list_text->len > 0)) {
1030 clone_header(out, &rc, rsc, clone_data, desc);
1033 (
const char *) list_text->str);
1034 g_string_truncate(list_text, 0);
1039 for (gIter = started_list; gIter; gIter = gIter->next) {
1047 pcmk__add_word(&list_text, 1024,
host->details->uname);
1050 g_list_free(started_list);
1052 if ((list_text != NULL) && (list_text->len > 0)) {
1053 clone_header(out, &rc, rsc, clone_data, desc);
1059 out->list_item(out, NULL,
1061 (
const char *) list_text->str);
1064 (
const char *) list_text->str);
1068 out->list_item(out, NULL,
"Started: [ %s ]",
1069 (
const char *) list_text->str);
1073 if (list_text != NULL) {
1074 g_string_free(list_text, TRUE);
1079 && (clone_data->clone_max > active_instances)) {
1085 if (stopped != NULL) {
1086 g_hash_table_destroy(stopped);
1094 list = g_hash_table_get_values(rsc->
known_on);
1098 for (nIter = list; nIter != NULL; nIter = nIter->next) {
1105 const char *state =
"Stopped";
1108 state =
"Stopped (disabled)";
1111 if (stopped == NULL) {
1114 if (probe_op != NULL) {
1118 g_hash_table_insert(stopped, strdup(node->
details->
uname),
1121 g_hash_table_insert(stopped, strdup(node->
details->
uname),
1129 if (stopped != NULL) {
1130 GList *list = sorted_hash_table_values(stopped);
1132 clone_header(out, &rc, rsc, clone_data, desc);
1134 for (GList *status_iter = list; status_iter != NULL; status_iter = status_iter->next) {
1135 const char *status = status_iter->data;
1136 GList *nodes = nodes_with_status(stopped, status);
1137 GString *nodes_str = node_list_to_str(nodes);
1139 if (nodes_str != NULL) {
1140 if (nodes_str->len > 0) {
1141 out->list_item(out, NULL,
"%s: [ %s ]", status,
1142 (
const char *) nodes_str->str);
1144 g_string_free(nodes_str, TRUE);
1151 g_hash_table_destroy(stopped);
1157 }
else if (active_instances == 0) {
1158 clone_header(out, &rc, rsc, clone_data, desc);
1177 for (GList *gIter = rsc->
children; gIter != NULL; gIter = gIter->next) {
1183 child_rsc->
xml = NULL;
1187 child_rsc->
fns->
free(child_rsc);
1193 CRM_ASSERT(clone_data->demote_notify == NULL);
1195 CRM_ASSERT(clone_data->start_notify == NULL);
1196 CRM_ASSERT(clone_data->promote_notify == NULL);
1208 for (; gIter != NULL; gIter = gIter->next) {
1212 if (a_role > clone_role) {
1213 clone_role = a_role;
1232 if (pe_rsc_is_clone(rsc)) {
1235 if (clone_data->clone_max == g_list_length(
data_set->
nodes)) {
1244 gboolean check_parent)
1246 gboolean passes = FALSE;
1256 for (
const GList *iter = rsc->
children;
1257 iter != NULL; iter = iter->next) {
1277 return ID(clone_data->xml_obj_child);
1316 clone_data->flags = pcmk__set_flags_as(__func__, __LINE__,
LOG_TRACE,
1318 clone_data->flags, flag,
"flag");
1346 !any_promoting,
true);
1350 if (clone_data->promote_notify == NULL) {
1362 !any_demoting,
true);
1366 if (clone_data->demote_notify == NULL) {
1372 if (clone_data->promote_notify != NULL) {
1374 clone_data->promote_notify->pre,
1377 clone_data->promote_notify->pre,
1380 clone_data->promote_notify->pre,
1383 clone_data->start_notify->pre,
1386 clone_data->stop_notify->pre,
1425 clone_data->demote_notify = NULL;
1428 clone_data->stop_notify = NULL;
1431 clone_data->start_notify = NULL;
1434 clone_data->promote_notify = NULL;
1456 if (clone_data->start_notify == NULL) {
1461 if (clone_data->stop_notify == NULL) {
1464 if ((clone_data->start_notify != NULL)
1465 && (clone_data->stop_notify != NULL)) {
#define CRM_CHECK(expr, failure_action)
#define PCMK_XA_PROMOTED_MAX_LEGACY
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...)
void pe__force_anon(const char *standard, pe_resource_t *rsc, const char *rid, pe_working_set_t *data_set)
int pe__clone_promoted_node_max(const pe_resource_t *clone)
resource_object_functions_t * fns
int pe__clone_node_max(const 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.
bool pe__resource_is_disabled(const pe_resource_t *rsc)
const pe_resource_t * pe__const_top_resource(const pe_resource_t *rsc, bool include_bundle)
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
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)
const char * pe__resource_description(const pe_resource_t *rsc, uint32_t show_opts)
struct clone_variant_data_s clone_variant_data_t
#define XML_RSC_ATTR_INCARNATION_MAX
int pe__clone_xml(pcmk__output_t *out, va_list args)
void pe__create_action_notifications(pe_resource_t *rsc, notify_data_t *n_data)
#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)
void pe__free_action_notification_data(notify_data_t *n_data)
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
void pe__create_clone_notifications(pe_resource_t *clone)
#define XML_CIB_TAG_RESOURCE
int pe__clone_promoted_max(const pe_resource_t *clone)
#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 pe__free_clone_notification_data(pe_resource_t *clone)
int pe__clone_max(const pe_resource_t *clone)
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 *)
notify_data_t * pe__action_notif_pseudo_ops(pe_resource_t *rsc, const char *task, pe_action_t *action, pe_action_t *complete)
void free_xml(xmlNode *child)
#define get_clone_variant_data(data, rsc)
enum rsc_role_e text2role(const char *role)
bool pcmk__str_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
gboolean(* is_filtered)(const pe_resource_t *, GList *, gboolean)
void pcmk__output_xml_pop_parent(pcmk__output_t *out)
bool pe__clone_is_ordered(const pe_resource_t *clone)
#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
const char * rsc_printable_id(const pe_resource_t *rsc)
#define PCMK__OUTPUT_LIST_HEADER(out_obj, cond, retcode, title...)
Cluster status and scheduling.
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)
gboolean pe__clone_is_filtered(const pe_resource_t *rsc, GList *only_rsc, gboolean check_parent)
#define status_print(fmt, args...)
bool pe__is_universal_clone(const pe_resource_t *rsc, const pe_working_set_t *data_set)
This structure contains everything that makes up a single output formatter.
pe_node_t * pe_find_node(const GList *node_list, const char *node_name)
Find a node by name in a list of nodes.
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_maintenance
#define pe_rsc_failure_ignored
gboolean clone_active(pe_resource_t *rsc, gboolean all)
void pe__create_clone_notif_pseudo_ops(pe_resource_t *clone, pe_action_t *start, pe_action_t *started, pe_action_t *stop, pe_action_t *stopped)
gboolean crm_is_true(const char *s)
#define XML_CIB_TAG_GROUP
#define pe_rsc_trace(rsc, fmt, args...)
pe_resource_t * find_clone_instance(const pe_resource_t *rsc, const char *sub_id)
xmlNode * pe__failed_probe_for_rsc(const pe_resource_t *rsc, const char *name)
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)
const char * pe__clone_child_id(const pe_resource_t *rsc)
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)