23 typedef struct clone_variant_data_s {
28 int promoted_node_max;
39 xmlNode *xml_obj_child;
42 #define get_clone_variant_data(data, rsc) do { \ 43 pcmk__assert(pcmk__is_clone(rsc)); \ 44 data = rsc->priv->variant_opaque; \ 61 return clone_data->clone_max;
78 return clone_data->clone_node_max;
95 return clone_data->promoted_max;
112 return clone_data->promoted_node_max;
116 sorted_hash_table_values(GHashTable *table)
118 GList *retval = NULL;
122 g_hash_table_iter_init(&iter, table);
123 while (g_hash_table_iter_next(&iter, &key, &value)) {
124 if (!g_list_find_custom(retval, value, (GCompareFunc) strcmp)) {
125 retval = g_list_prepend(retval, (
char *) value);
129 retval = g_list_sort(retval, (GCompareFunc) strcmp);
134 nodes_with_status(GHashTable *table,
const char *status)
136 GList *retval = NULL;
140 g_hash_table_iter_init(&iter, table);
141 while (g_hash_table_iter_next(&iter, &key, &value)) {
142 if (!strcmp((
char *) value, status)) {
143 retval = g_list_prepend(retval, key);
152 node_list_to_str(
const GList *list)
154 GString *retval = NULL;
156 for (
const GList *iter = list; iter != NULL; iter = iter->next) {
157 pcmk__add_word(&retval, 1024, (
const char *) iter->data);
167 GString *attrs = NULL;
191 pcmk__xe_id(clone_data->xml_obj_child),
192 (
const char *) attrs->str, desc ?
" (" :
"",
193 desc ? desc :
"", desc ?
")" :
"");
194 g_string_free(attrs, TRUE);
198 pcmk__xe_id(clone_data->xml_obj_child),
199 desc ?
" (" :
"", desc ? desc :
"",
208 if (pcmk__is_clone(rsc)) {
212 "because %s resources such as %s can be used only as " 213 "anonymous clones", rsc->
id, standard, rid);
215 clone_data->clone_node_max = 1;
216 clone_data->clone_max = QB_MIN(clone_data->clone_max,
224 gboolean as_orphan = FALSE;
225 char *inc_num = NULL;
226 char *inc_max = NULL;
228 xmlNode *child_copy = NULL;
233 CRM_CHECK(clone_data->xml_obj_child != NULL,
return FALSE);
235 if (clone_data->total_clones >= clone_data->clone_max) {
241 inc_num = pcmk__itoa(clone_data->total_clones);
242 inc_max = pcmk__itoa(clone_data->clone_max);
255 clone_data->total_clones += 1;
288 const char *deprecated_name,
int default_value)
290 int integer = default_value;
291 const char *value = g_hash_table_lookup(rsc->
priv->
meta, meta_name);
293 if ((value == NULL) && (deprecated_name != NULL)) {
294 value = g_hash_table_lookup(rsc->
priv->
meta, deprecated_name);
301 " meta-attribute (such as in %s) is deprecated " 302 "and will be removed in a future release. Use the " 309 " meta-attribute (such as in %s) is deprecated " 310 "and will be removed in a future release. Use the " 326 xmlNode *a_child = NULL;
327 xmlNode *xml_obj = rsc->
priv->
xml;
338 clone_data->promoted_max =
344 clone_data->promoted_node_max =
361 clone_data->flags = pcmk__set_flags_as(__func__, __LINE__,
LOG_TRACE,
365 "pcmk__clone_ordered");
369 && (clone_data->clone_node_max > 1)) {
372 "because anonymous clones support only one instance " 373 "per node", clone_data->clone_node_max, rsc->
id);
374 clone_data->clone_node_max = 1;
379 pcmk__rsc_trace(rsc,
"\tClone node max: %d", clone_data->clone_node_max);
391 clone_data->xml_obj_child = a_child;
396 if (clone_data->xml_obj_child == NULL) {
407 if (g_hash_table_lookup(rsc->
priv->
meta,
419 if (clone_data->clone_max <= 0) {
429 for (lpc = 0; lpc < clone_data->clone_max; lpc++) {
437 clone_data->clone_max, rsc->
id);
445 gIter != NULL; gIter = gIter->next) {
448 gboolean child_active = child_rsc->
priv->
fns->
active(child_rsc, all);
450 if (all == FALSE && child_active) {
452 }
else if (all && child_active == FALSE) {
467 const char *target_role = g_hash_table_lookup(rsc->
priv->
meta,
470 if ((target_role == NULL) && (rsc->
priv->
children != NULL)) {
474 target_role = g_hash_table_lookup(instance->
priv->
meta,
484 const char *target_role = configured_role_str(rsc);
486 if (target_role != NULL) {
490 " for resource %s", rsc->
id);
510 gIter != NULL; gIter = gIter->next) {
528 PCMK__OUTPUT_ARGS(
"clone",
"uint32_t",
"pcmk_resource_t *",
"GList *",
533 uint32_t show_opts = va_arg(args, uint32_t);
535 GList *only_node = va_arg(args, GList *);
536 GList *only_rsc = va_arg(args, GList *);
540 gboolean printed_header = FALSE;
541 gboolean print_everything = TRUE;
550 all = g_list_prepend(all, (gpointer)
"*");
553 gIter != NULL; gIter = gIter->next) {
566 if (!printed_header) {
567 const char *multi_state = pcmk__flag_text(rsc->
flags,
570 const char *maintenance = pcmk__flag_text(rsc->
flags,
572 const char *managed = pcmk__flag_text(rsc->
flags,
576 const char *ignored = pcmk__flag_text(rsc->
flags,
578 const char *target_role = configured_role_str(rsc);
581 printed_header = TRUE;
598 out->message(out, (
const char *) child_rsc->
priv->
xml->name,
599 show_opts, child_rsc, only_node, all);
602 if (printed_header) {
610 PCMK__OUTPUT_ARGS(
"clone",
"uint32_t",
"pcmk_resource_t *",
"GList *",
615 uint32_t show_opts = va_arg(args, uint32_t);
617 GList *only_node = va_arg(args, GList *);
618 GList *only_rsc = va_arg(args, GList *);
620 GHashTable *stopped = NULL;
622 GString *list_text = NULL;
624 GList *promoted_list = NULL;
625 GList *started_list = NULL;
628 const char *desc = NULL;
631 int active_instances = 0;
633 gboolean print_everything = TRUE;
646 for (gIter = rsc->
priv->
children; gIter != NULL; gIter = gIter->next) {
647 gboolean print_full = FALSE;
649 gboolean partially_active = child_rsc->
priv->
fns->
active(child_rsc,
681 }
else if (partially_active == FALSE) {
686 if (stopped == NULL) {
717 promoted_list = g_list_append(promoted_list, location);
720 started_list = g_list_append(started_list, location);
736 clone_header(out, &rc, rsc, clone_data, desc);
739 all = g_list_prepend(all, (gpointer)
"*");
740 out->message(out, (
const char *) child_rsc->
priv->
xml->name,
741 show_opts, child_rsc, only_node, all);
753 for (gIter = promoted_list; gIter; gIter = gIter->next) {
761 pcmk__add_word(&list_text, 1024,
host->priv->name);
764 g_list_free(promoted_list);
766 if ((list_text != NULL) && (list_text->len > 0)) {
767 clone_header(out, &rc, rsc, clone_data, desc);
770 (
const char *) list_text->str);
771 g_string_truncate(list_text, 0);
776 for (gIter = started_list; gIter; gIter = gIter->next) {
784 pcmk__add_word(&list_text, 1024,
host->priv->name);
787 g_list_free(started_list);
789 if ((list_text != NULL) && (list_text->len > 0)) {
790 clone_header(out, &rc, rsc, clone_data, desc);
796 out->list_item(out, NULL,
799 (
const char *) list_text->str);
802 (
const char *) list_text->str);
806 out->list_item(out, NULL,
"Started: [ %s ]",
807 (
const char *) list_text->str);
811 if (list_text != NULL) {
812 g_string_free(list_text, TRUE);
817 && (clone_data->clone_max > active_instances)) {
823 if (stopped != NULL) {
824 g_hash_table_destroy(stopped);
837 for (nIter = list; nIter != NULL; nIter = nIter->next) {
845 xmlNode *probe_op = NULL;
846 const char *state =
"Stopped";
849 state =
"Stopped (disabled)";
852 if (stopped == NULL) {
858 if (probe_op != NULL) {
864 g_hash_table_insert(stopped, strdup(node->
priv->
name),
875 if (stopped != NULL) {
876 GList *list = sorted_hash_table_values(stopped);
878 clone_header(out, &rc, rsc, clone_data, desc);
880 for (GList *status_iter = list; status_iter != NULL; status_iter = status_iter->next) {
881 const char *status = status_iter->data;
882 GList *nodes = nodes_with_status(stopped, status);
883 GString *nodes_str = node_list_to_str(nodes);
885 if (nodes_str != NULL) {
886 if (nodes_str->len > 0) {
887 out->list_item(out, NULL,
"%s: [ %s ]", status,
888 (
const char *) nodes_str->str);
890 g_string_free(nodes_str, TRUE);
897 g_hash_table_destroy(stopped);
903 }
else if (active_instances == 0) {
904 clone_header(out, &rc, rsc, clone_data, desc);
924 gIter != NULL; gIter = gIter->next) {
942 && (clone_data->stop_notify == NULL)
943 && (clone_data->start_notify == NULL)
944 && (clone_data->promote_notify == NULL));
956 gIter != NULL; gIter = gIter->next) {
962 if (a_role > clone_role) {
982 if (pcmk__is_clone(rsc)) {
994 gboolean check_parent)
996 gboolean passes = FALSE;
1008 iter != NULL; iter = iter->next) {
1029 return pcmk__xe_id(clone_data->xml_obj_child);
1068 clone_data->flags = pcmk__set_flags_as(__func__, __LINE__,
LOG_TRACE,
1070 clone_data->flags, flag,
"flag");
1091 return pcmk_all_flags_set(clone_data->flags,
flags);
1114 !any_promoting,
true);
1118 !any_promoting,
true);
1122 if (clone_data->promote_notify == NULL) {
1131 !any_demoting,
true);
1135 !any_demoting,
true);
1139 if (clone_data->demote_notify == NULL) {
1145 if (clone_data->promote_notify != NULL) {
1193 clone_data->demote_notify = NULL;
1196 clone_data->stop_notify = NULL;
1199 clone_data->start_notify = NULL;
1202 clone_data->promote_notify = NULL;
1224 if (clone_data->start_notify == NULL) {
1230 if (clone_data->stop_notify == NULL) {
1234 if ((clone_data->start_notify != NULL)
1235 && (clone_data->stop_notify != NULL)) {
1256 return clone_data->clone_node_max;
const pcmk_resource_t * pe__const_top_resource(const pcmk_resource_t *rsc, bool include_bundle)
bool pe__clone_is_ordered(const pcmk_resource_t *clone)
#define CRM_CHECK(expr, failure_action)
xmlNode * pcmk__xml_copy(xmlNode *parent, xmlNode *src)
xmlNode * pcmk__xe_first_child(const xmlNode *parent, const char *node_name, const char *attr_n, const char *attr_v)
const char * pcmk_role_text(enum rsc_role_e role)
Get readable description of a resource role.
unsigned int pe__clone_max_per_node(const pcmk_resource_t *rsc)
Control output from tools.
gboolean(* active)(pcmk_resource_t *rsc, gboolean all)
int pcmk__scan_min_int(const char *text, int *result, int minimum)
bool is_set_recursive(const pcmk_resource_t *rsc, long long flag, bool any)
#define PCMK_XE_PRIMITIVE
gint pe__cmp_node_name(gconstpointer a, gconstpointer b)
xmlNode * pe__failed_probe_for_rsc(const pcmk_resource_t *rsc, const char *name)
bool pe__is_universal_clone(const pcmk_resource_t *rsc, const pcmk_scheduler_t *scheduler)
#define pcmk__config_warn(fmt...)
void pe__create_clone_notifications(pcmk_resource_t *clone)
#define pcmk__rsc_trace(rsc, fmt, args...)
gboolean(* is_filtered)(const pcmk_resource_t *rsc, GList *only_rsc, gboolean check_parent)
void pe__force_anon(const char *standard, pcmk_resource_t *rsc, const char *rid, pcmk_scheduler_t *scheduler)
pcmk_resource_t * pe__create_clone_child(pcmk_resource_t *rsc, pcmk_scheduler_t *scheduler)
gboolean clone_active(pcmk_resource_t *rsc, gboolean all)
#define pcmk__insert_meta(obj, name, value)
#define pcmk__config_err(fmt...)
const char * pe__resource_description(const pcmk_resource_t *rsc, uint32_t show_opts)
#define PCMK_XA_FAILURE_IGNORED
int pe__clone_default(pcmk__output_t *out, va_list args)
pcmk_node_t *(* location)(const pcmk_resource_t *rsc, GList **list, uint32_t target)
void pcmk__add_separated_word(GString **list, size_t init_size, const char *word, const char *separator)
#define PCMK_META_CLONE_MAX
const char * rsc_printable_id(const pcmk_resource_t *rsc)
const pcmk__rsc_methods_t * fns
void pe__set_resource_flags_recursive(pcmk_resource_t *rsc, uint64_t flags)
void clone_free(pcmk_resource_t *rsc)
struct clone_variant_data_s clone_variant_data_t
gboolean clone_unpack(pcmk_resource_t *rsc, pcmk_scheduler_t *scheduler)
#define PCMK_XA_TARGET_ROLE
int pe__unpack_resource(xmlNode *xml_obj, pcmk_resource_t **rsc, pcmk_resource_t *parent, pcmk_scheduler_t *scheduler)
enum rsc_role_e pcmk_parse_role(const char *role)
Parse a resource role from a string role specification.
void pcmk__xml_free(xmlNode *xml)
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.
pcmk__node_private_t * priv
pcmk_action_t * pe__new_rsc_pseudo_action(pcmk_resource_t *rsc, const char *task, bool optional, bool runnable)
int pe__clone_promoted_max(const pcmk_resource_t *clone)
#define PCMK__META_PROMOTED_NODE_MAX_LEGACY
#define PCMK_META_GLOBALLY_UNIQUE
#define PCMK_ACTION_DEMOTE
void common_free(pcmk_resource_t *rsc)
const char * crm_exit_str(crm_exit_t exit_code)
void pe__free_action_notification_data(notify_data_t *n_data)
Actions are ordered (optionally, if no other flags are set)
pcmk_node_t * pcmk__find_node_in_list(const GList *nodes, const char *node_name)
#define PCMK_META_CLONE_NODE_MAX
void pe__create_promotable_pseudo_ops(pcmk_resource_t *clone, bool any_promoting, bool any_demoting)
int pe__name_and_nvpairs_xml(pcmk__output_t *out, bool is_list, const char *tag_name,...) G_GNUC_NULL_TERMINATED
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
#define PCMK_XA_DESCRIPTION
int pe__clone_xml(pcmk__output_t *out, va_list args)
void pe__create_action_notifications(pcmk_resource_t *rsc, notify_data_t *n_data)
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
#define PCMK_ACTION_START
pcmk__resource_private_t * priv
#define PCMK_META_RESOURCE_STICKINESS
Wrappers for and extensions to libxml2.
#define PCMK_META_TARGET_ROLE
#define PCMK__META_PROMOTED_MAX_LEGACY
enum rsc_role_e(* state)(const pcmk_resource_t *rsc, gboolean current)
#define get_clone_variant_data(data, rsc)
bool pcmk__str_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
#define pcmk__warn_once(wo_flag, fmt...)
void pcmk__output_xml_pop_parent(pcmk__output_t *out)
gboolean order_actions(pcmk_action_t *first, pcmk_action_t *then, uint32_t flags)
#define PCMK_XA_MAINTENANCE
GHashTable * allowed_nodes
enum rsc_role_e clone_resource_state(const pcmk_resource_t *rsc, gboolean current)
xmlNode * pcmk__xe_next(const xmlNode *node, const char *element_name)
void pe__free_clone_notification_data(pcmk_resource_t *clone)
#define pcmk__assert(expr)
#define PCMK__OUTPUT_LIST_FOOTER(out_obj, retcode)
notify_data_t * pe__action_notif_pseudo_ops(pcmk_resource_t *rsc, const char *task, pcmk_action_t *action, pcmk_action_t *complete)
void pe__create_clone_notif_pseudo_ops(pcmk_resource_t *clone, pcmk_action_t *start, pcmk_action_t *started, pcmk_action_t *stop, pcmk_action_t *stopped)
int pe__clone_node_max(const pcmk_resource_t *clone)
#define PCMK__OUTPUT_LIST_HEADER(out_obj, cond, retcode, title...)
Cluster status and scheduling.
int pe__clone_max(const pcmk_resource_t *clone)
GHashTable * pcmk__strkey_table(GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
int pe__set_clone_flag(pcmk_resource_t *clone, enum pcmk__clone_flags flag)
#define PCMK_ROLE_PROMOTED
#define PCMK_XA_MULTI_STATE
pcmk_scheduler_t * scheduler
#define PCMK_META_PROMOTED_NODE_MAX
const char * pe__clone_child_id(const pcmk_resource_t *rsc)
bool pcmk__rsc_filtered_by_node(pcmk_resource_t *rsc, GList *only_node)
This structure contains everything that makes up a single output formatter.
bool pe__resource_is_disabled(const pcmk_resource_t *rsc)
#define PCMK_ROLE_UNPROMOTED
#define PCMK_ACTION_PROMOTE
gboolean crm_is_true(const char *s)
#define PCMK_META_PROMOTED_MAX
int pcmk__numeric_strcasecmp(const char *s1, const char *s2)
bool pe__clone_flag_is_set(const pcmk_resource_t *clone, uint32_t flags)
gboolean pe__clone_is_filtered(const pcmk_resource_t *rsc, GList *only_rsc, gboolean check_parent)
#define PCMK_ACTION_PROMOTED
int pe__clone_promoted_node_max(const pcmk_resource_t *clone)
Resource role is unknown.
#define PCMK_META_ORDERED
void(* free)(pcmk_resource_t *rsc)
struct pcmk__node_details * details
#define PCMK_ACTION_DEMOTED
#define pcmk__assert_alloc(nmemb, size)
void pcmk__insert_dup(GHashTable *table, const char *name, const char *value)
GHashTable * probed_nodes
#define PCMK_SCORE_INFINITY
Integer score to use to represent "infinity".
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
gboolean pcmk__str_in_list(const gchar *s, const GList *lst, uint32_t flags)