23typedef 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;
116sorted_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);
134nodes_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);
152node_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 "
327 xmlNode *a_child = NULL;
328 xmlNode *xml_obj = rsc->
priv->
xml;
339 clone_data->promoted_max =
345 clone_data->promoted_node_max =
360 QB_MAX(1, num_nodes));
364 clone_data->flags = pcmk__set_flags_as(__func__, __LINE__,
LOG_TRACE,
368 "pcmk__clone_ordered");
372 && (clone_data->clone_node_max > 1)) {
375 "because anonymous clones support only one instance "
376 "per node", clone_data->clone_node_max, rsc->
id);
377 clone_data->clone_node_max = 1;
382 pcmk__rsc_trace(rsc,
"\tClone node max: %d", clone_data->clone_node_max);
394 clone_data->xml_obj_child = a_child;
399 if (clone_data->xml_obj_child == NULL) {
410 if (g_hash_table_lookup(rsc->
priv->
meta,
422 if (clone_data->clone_max <= 0) {
432 for (lpc = 0; lpc < clone_data->clone_max; lpc++) {
440 clone_data->clone_max, rsc->
id);
448 gIter != NULL; gIter = gIter->next) {
451 bool child_active = child_rsc->
priv->
fns->
active(child_rsc, all);
453 if (all == FALSE && child_active) {
455 }
else if (all && child_active == FALSE) {
470 const char *target_role = g_hash_table_lookup(rsc->
priv->
meta,
473 if ((target_role == NULL) && (rsc->
priv->
children != NULL)) {
477 target_role = g_hash_table_lookup(instance->
priv->
meta,
487 const char *target_role = configured_role_str(rsc);
489 if (target_role != NULL) {
493 " for resource %s", rsc->
id);
513 gIter != NULL; gIter = gIter->next) {
531PCMK__OUTPUT_ARGS(
"clone",
"uint32_t",
"pcmk_resource_t *",
"GList *",
536 uint32_t show_opts = va_arg(args, uint32_t);
538 GList *only_node = va_arg(args, GList *);
539 GList *only_rsc = va_arg(args, GList *);
543 gboolean printed_header = FALSE;
544 bool print_everything =
true;
553 all = g_list_prepend(all, (gpointer)
"*");
556 gIter != NULL; gIter = gIter->next) {
564 if (child_rsc->priv->fns->is_filtered(child_rsc, only_rsc,
569 if (!printed_header) {
570 const char *multi_state = pcmk__flag_text(rsc->
flags,
573 const char *maintenance = pcmk__flag_text(rsc->
flags,
575 const char *managed = pcmk__flag_text(rsc->
flags,
579 const char *ignored = pcmk__flag_text(rsc->
flags,
581 const char *target_role = configured_role_str(rsc);
584 printed_header = TRUE;
601 out->message(out, (
const char *) child_rsc->priv->xml->name,
602 show_opts, child_rsc, only_node, all);
605 if (printed_header) {
613PCMK__OUTPUT_ARGS(
"clone",
"uint32_t",
"pcmk_resource_t *",
"GList *",
618 uint32_t show_opts = va_arg(args, uint32_t);
620 GList *only_node = va_arg(args, GList *);
621 GList *only_rsc = va_arg(args, GList *);
623 GHashTable *stopped = NULL;
625 GString *list_text = NULL;
627 GList *promoted_list = NULL;
628 GList *started_list = NULL;
631 const char *desc = NULL;
634 int active_instances = 0;
636 gboolean print_everything = TRUE;
649 for (gIter = rsc->
priv->
children; gIter != NULL; gIter = gIter->next) {
650 gboolean print_full = FALSE;
652 bool partially_active = child_rsc->priv->fns->active(child_rsc,
false);
658 if (child_rsc->priv->fns->is_filtered(child_rsc, only_rsc,
677 && (child_rsc->priv->pending_action != NULL)
678 && (strcmp(child_rsc->priv->pending_action,
683 }
else if (partially_active == FALSE) {
688 if (stopped == NULL) {
701 }
else if (child_rsc->priv->fns->active(child_rsc,
true)) {
706 location = child_rsc->
priv->fns->location(child_rsc, NULL,
713 a_role = child_rsc->priv->fns->state(child_rsc, TRUE);
719 promoted_list = g_list_append(promoted_list, location);
722 started_list = g_list_append(started_list, location);
738 clone_header(out, &rc, rsc, clone_data, desc);
741 all = g_list_prepend(all, (gpointer)
"*");
742 out->message(out, (
const char *) child_rsc->priv->xml->name,
743 show_opts, child_rsc, only_node, all);
755 for (gIter = promoted_list; gIter; gIter = gIter->next) {
763 pcmk__add_word(&list_text, 1024,
host->priv->name);
766 g_list_free(promoted_list);
768 if ((list_text != NULL) && (list_text->len > 0)) {
769 clone_header(out, &rc, rsc, clone_data, desc);
772 (
const char *) list_text->str);
773 g_string_truncate(list_text, 0);
778 for (gIter = started_list; gIter; gIter = gIter->next) {
786 pcmk__add_word(&list_text, 1024,
host->priv->name);
789 g_list_free(started_list);
791 if ((list_text != NULL) && (list_text->len > 0)) {
792 clone_header(out, &rc, rsc, clone_data, desc);
798 out->list_item(out, NULL,
801 (
const char *) list_text->str);
804 (
const char *) list_text->str);
808 out->list_item(out, NULL,
"Started: [ %s ]",
809 (
const char *) list_text->str);
813 if (list_text != NULL) {
814 g_string_free(list_text, TRUE);
819 && (clone_data->clone_max > active_instances)) {
825 if (stopped != NULL) {
826 g_hash_table_destroy(stopped);
839 for (nIter = list; nIter != NULL; nIter = nIter->next) {
843 node->priv->name) == NULL)
847 xmlNode *probe_op = NULL;
848 const char *state =
"Stopped";
851 state =
"Stopped (disabled)";
854 if (stopped == NULL) {
860 if (probe_op != NULL) {
866 g_hash_table_insert(stopped, strdup(node->priv->name),
877 if (stopped != NULL) {
878 GList *list = sorted_hash_table_values(stopped);
880 clone_header(out, &rc, rsc, clone_data, desc);
882 for (GList *status_iter = list; status_iter != NULL; status_iter = status_iter->next) {
883 const char *status = status_iter->data;
884 GList *nodes = nodes_with_status(stopped, status);
885 GString *nodes_str = node_list_to_str(nodes);
887 if (nodes_str != NULL) {
888 if (nodes_str->len > 0) {
889 out->list_item(out, NULL,
"%s: [ %s ]", status,
890 (
const char *) nodes_str->str);
892 g_string_free(nodes_str, TRUE);
899 g_hash_table_destroy(stopped);
905 }
else if (active_instances == 0) {
906 clone_header(out, &rc, rsc, clone_data, desc);
926 gIter != NULL; gIter = gIter->next) {
944 && (clone_data->stop_notify == NULL)
945 && (clone_data->start_notify == NULL)
946 && (clone_data->promote_notify == NULL));
958 gIter != NULL; gIter = gIter->next) {
964 if (a_role > clone_role) {
984 if (pcmk__is_clone(rsc)) {
1010 iter != NULL; iter = iter->next) {
1031 return pcmk__xe_id(clone_data->xml_obj_child);
1070 clone_data->flags = pcmk__set_flags_as(__func__, __LINE__,
LOG_TRACE,
1072 clone_data->flags, flag,
"flag");
1093 return pcmk_all_flags_set(clone_data->flags,
flags);
1116 !any_promoting,
true);
1120 !any_promoting,
true);
1124 if (clone_data->promote_notify == NULL) {
1133 !any_demoting,
true);
1137 !any_demoting,
true);
1141 if (clone_data->demote_notify == NULL) {
1147 if (clone_data->promote_notify != NULL) {
1195 clone_data->demote_notify = NULL;
1198 clone_data->stop_notify = NULL;
1201 clone_data->start_notify = NULL;
1204 clone_data->promote_notify = NULL;
1226 if (clone_data->start_notify == NULL) {
1232 if (clone_data->stop_notify == NULL) {
1236 if ((clone_data->start_notify != NULL)
1237 && (clone_data->stop_notify != NULL)) {
1258 return clone_data->clone_node_max;
@ pcmk__ar_ordered
Actions are ordered (optionally, if no other flags are set)
#define PCMK_ACTION_PROMOTED
#define PCMK_ACTION_PROMOTE
#define PCMK_ACTION_START
#define PCMK_ACTION_DEMOTED
#define PCMK_ACTION_DEMOTE
bool clone_active(const pcmk_resource_t *rsc, bool all)
bool is_set_recursive(const pcmk_resource_t *rsc, long long flag, bool any)
void pe__create_promotable_pseudo_ops(pcmk_resource_t *clone, bool any_promoting, bool any_demoting)
void pe__create_clone_notifications(pcmk_resource_t *clone)
int pe__clone_promoted_node_max(const pcmk_resource_t *clone)
int pe__clone_max(const pcmk_resource_t *clone)
#define get_clone_variant_data(data, rsc)
pcmk_resource_t * pe__create_clone_child(pcmk_resource_t *rsc, pcmk_scheduler_t *scheduler)
bool pe__is_universal_clone(const pcmk_resource_t *rsc, const pcmk_scheduler_t *scheduler)
void clone_free(pcmk_resource_t *rsc)
bool clone_unpack(pcmk_resource_t *rsc)
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)
struct clone_variant_data_s clone_variant_data_t
void pe__force_anon(const char *standard, pcmk_resource_t *rsc, const char *rid, pcmk_scheduler_t *scheduler)
bool pe__clone_flag_is_set(const pcmk_resource_t *clone, uint32_t flags)
bool pe__clone_is_ordered(const pcmk_resource_t *clone)
unsigned int pe__clone_max_per_node(const pcmk_resource_t *rsc)
int pe__set_clone_flag(pcmk_resource_t *clone, enum pcmk__clone_flags flag)
int pe__clone_node_max(const pcmk_resource_t *clone)
int pe__clone_promoted_max(const pcmk_resource_t *clone)
const char * pe__clone_child_id(const pcmk_resource_t *rsc)
void pe__free_clone_notification_data(pcmk_resource_t *clone)
bool pe__clone_is_filtered(const pcmk_resource_t *rsc, const GList *only_rsc, bool check_parent)
enum rsc_role_e clone_resource_state(const pcmk_resource_t *rsc, bool current)
#define pcmk__assert_alloc(nmemb, size)
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
int pe__unpack_resource(xmlNode *xml_obj, pcmk_resource_t **rsc, pcmk_resource_t *parent, pcmk_scheduler_t *scheduler)
#define CRM_CHECK(expr, failure_action)
#define pcmk__config_warn(fmt...)
#define pcmk__config_err(fmt...)
@ pcmk__wo_clone_master_max
@ pcmk__wo_clone_master_node_max
#define pcmk__warn_once(wo_flag, fmt...)
pcmk_scheduler_t * scheduler
pcmk_node_t * pcmk__find_node_in_list(const GList *nodes, const char *node_name)
#define pcmk__insert_meta(obj, name, value)
#define PCMK_META_RESOURCE_STICKINESS
#define PCMK_META_CLONE_NODE_MAX
#define PCMK_META_PROMOTED_MAX
#define PCMK_META_CLONE_MAX
#define PCMK_META_ORDERED
#define PCMK_META_TARGET_ROLE
#define PCMK_META_GLOBALLY_UNIQUE
#define PCMK_META_PROMOTED_NODE_MAX
#define PCMK__META_PROMOTED_MAX_LEGACY
#define PCMK__META_PROMOTED_NODE_MAX_LEGACY
Control output from tools.
@ pcmk_show_inactive_rscs
void pcmk__output_xml_pop_parent(pcmk__output_t *out)
#define PCMK__OUTPUT_LIST_HEADER(out_obj, cond, retcode, title...)
#define PCMK__OUTPUT_LIST_FOOTER(out_obj, retcode)
void pe__free_action_notification_data(notify_data_t *n_data)
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_action_notifications(pcmk_resource_t *rsc, notify_data_t *n_data)
int pe__clone_xml(pcmk__output_t *out, va_list args)
const char * pe__resource_description(const pcmk_resource_t *rsc, uint32_t show_opts)
const pcmk_resource_t * pe__const_top_resource(const pcmk_resource_t *rsc, bool include_bundle)
int pe__name_and_nvpairs_xml(pcmk__output_t *out, bool is_list, const char *tag_name,...) G_GNUC_NULL_TERMINATED
void pe__set_resource_flags_recursive(pcmk_resource_t *rsc, uint64_t flags)
pcmk_action_t * pe__new_rsc_pseudo_action(pcmk_resource_t *rsc, const char *task, bool optional, bool runnable)
gboolean order_actions(pcmk_action_t *first, pcmk_action_t *then, uint32_t flags)
int pe__clone_default(pcmk__output_t *out, va_list args)
gint pe__cmp_node_name(gconstpointer a, gconstpointer b)
xmlNode * pe__failed_probe_for_rsc(const pcmk_resource_t *rsc, const char *name)
void common_free(pcmk_resource_t *rsc)
bool pe__resource_is_disabled(const pcmk_resource_t *rsc)
bool pcmk__rsc_filtered_by_node(pcmk_resource_t *rsc, GList *only_node)
@ pcmk__rsc_ignore_failure
void pcmk__free_resource(gpointer user_data)
const char * crm_exit_str(crm_exit_t exit_code)
#define pcmk__assert(expr)
#define PCMK_ROLE_PROMOTED
const char * pcmk_role_text(enum rsc_role_e role)
Get readable description of a resource role.
enum rsc_role_e pcmk_parse_role(const char *role)
Parse a resource role from a string role specification.
@ pcmk_role_unknown
Resource role is unknown.
@ pcmk_role_unpromoted
Unpromoted.
@ pcmk_role_stopped
Stopped.
#define PCMK_ROLE_UNPROMOTED
#define pcmk__rsc_trace(rsc, fmt, args...)
#define PCMK_SCORE_INFINITY
Integer score to use to represent "infinity".
Cluster status and scheduling.
const char * rsc_printable_id(const pcmk_resource_t *rsc)
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
gboolean crm_is_true(const char *s)
void pcmk__insert_dup(GHashTable *table, const char *name, const char *value)
int pcmk__numeric_strcasecmp(const char *s1, const char *s2)
int pcmk__scan_min_int(const char *text, int *result, int minimum)
gboolean pcmk__str_in_list(const gchar *s, const GList *lst, uint32_t flags)
GHashTable * pcmk__strkey_table(GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
bool pcmk__str_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
void pcmk__add_separated_word(GString **list, size_t init_size, const char *word, const char *separator)
pcmk_action_t * post_done
This structure contains everything that makes up a single output formatter.
GHashTable * probed_nodes
pcmk_scheduler_t * scheduler
const pcmk__rsc_methods_t * fns
GHashTable * allowed_nodes
pcmk__resource_private_t * priv
enum rsc_role_e(* state)(const pcmk_resource_t *rsc, bool current)
bool(* is_filtered)(const pcmk_resource_t *rsc, const GList *only_rsc, bool check_parent)
bool(* active)(const pcmk_resource_t *rsc, bool all)
pcmk__node_private_t * priv
struct pcmk__node_details * details
Wrappers for and extensions to libxml2.
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.
xmlNode * pcmk__xe_first_child(const xmlNode *parent, const char *node_name, const char *attr_n, const char *attr_v)
xmlNode * pcmk__xe_next(const xmlNode *node, const char *element_name)
xmlNode * pcmk__xml_copy(xmlNode *parent, xmlNode *src)
void pcmk__xml_free(xmlNode *xml)
#define PCMK_XA_MULTI_STATE
#define PCMK_XA_DESCRIPTION
#define PCMK_XA_FAILURE_IGNORED
#define PCMK_XA_TARGET_ROLE
#define PCMK_XA_MAINTENANCE
#define PCMK_XE_PRIMITIVE