23 #ifdef PCMK__COMPAT_2_0 24 #define PROMOTED_INSTANCES PCMK__ROLE_PROMOTED_LEGACY "s" 25 #define UNPROMOTED_INSTANCES PCMK__ROLE_UNPROMOTED_LEGACY "s" 27 #define PROMOTED_INSTANCES PCMK_ROLE_PROMOTED 28 #define UNPROMOTED_INSTANCES PCMK_ROLE_UNPROMOTED 31 typedef struct clone_variant_data_s {
36 int promoted_node_max;
47 xmlNode *xml_obj_child;
50 #define get_clone_variant_data(data, rsc) \ 51 pcmk__assert(pcmk__is_clone(rsc) && (rsc->variant_opaque != NULL)); \ 52 data = (clone_variant_data_t *) rsc->variant_opaque; 68 return clone_data->clone_max;
85 return clone_data->clone_node_max;
102 return clone_data->promoted_max;
119 return clone_data->promoted_node_max;
123 sorted_hash_table_values(GHashTable *table)
125 GList *retval = NULL;
129 g_hash_table_iter_init(&iter, table);
130 while (g_hash_table_iter_next(&iter, &key, &value)) {
131 if (!g_list_find_custom(retval, value, (GCompareFunc) strcmp)) {
132 retval = g_list_prepend(retval, (
char *) value);
136 retval = g_list_sort(retval, (GCompareFunc) strcmp);
141 nodes_with_status(GHashTable *table,
const char *status)
143 GList *retval = NULL;
147 g_hash_table_iter_init(&iter, table);
148 while (g_hash_table_iter_next(&iter, &key, &value)) {
149 if (!strcmp((
char *) value, status)) {
150 retval = g_list_prepend(retval, key);
159 node_list_to_str(
const GList *list)
161 GString *retval = NULL;
163 for (
const GList *iter = list; iter != NULL; iter = iter->next) {
164 pcmk__add_word(&retval, 1024, (
const char *) iter->data);
174 GString *attrs = NULL;
198 pcmk__xe_id(clone_data->xml_obj_child),
199 (
const char *) attrs->str, desc ?
" (" :
"",
200 desc ? desc :
"", desc ?
")" :
"");
201 g_string_free(attrs, TRUE);
205 pcmk__xe_id(clone_data->xml_obj_child),
206 desc ?
" (" :
"", desc ? desc :
"",
215 if (pcmk__is_clone(rsc)) {
219 "because %s resources such as %s can be used only as " 220 "anonymous clones", rsc->
id, standard, rid);
222 clone_data->clone_node_max = 1;
223 clone_data->clone_max = QB_MIN(clone_data->clone_max,
231 char *child_id = NULL;
233 const char *child_base = NULL;
238 child_base = pcmk__xe_id(clone_data->xml_obj_child);
249 gboolean as_orphan = FALSE;
250 char *inc_num = NULL;
251 char *inc_max = NULL;
253 xmlNode *child_copy = NULL;
258 CRM_CHECK(clone_data->xml_obj_child != NULL,
return FALSE);
260 if (clone_data->total_clones >= clone_data->clone_max) {
266 inc_num = pcmk__itoa(clone_data->total_clones);
267 inc_max = pcmk__itoa(clone_data->clone_max);
280 clone_data->total_clones += 1;
313 const char *deprecated_name,
int default_value)
315 int integer = default_value;
316 const char *value = g_hash_table_lookup(rsc->
meta, meta_name);
318 if ((value == NULL) && (deprecated_name != NULL)) {
319 value = g_hash_table_lookup(rsc->
meta, deprecated_name);
326 " meta-attribute (such as in %s) is deprecated " 327 "and will be removed in a future release. Use the " 334 " meta-attribute (such as in %s) is deprecated " 335 "and will be removed in a future release. Use the " 351 xmlNode *a_child = NULL;
352 xmlNode *xml_obj = rsc->
xml;
363 clone_data->promoted_max =
369 clone_data->promoted_node_max =
385 clone_data->flags = pcmk__set_flags_as(__func__, __LINE__,
LOG_TRACE,
389 "pcmk__clone_ordered");
393 && (clone_data->clone_node_max > 1)) {
396 "because anonymous clones support only one instance " 397 "per node", clone_data->clone_node_max, rsc->
id);
398 clone_data->clone_node_max = 1;
403 pcmk__rsc_trace(rsc,
"\tClone node max: %d", clone_data->clone_node_max);
411 a_child != NULL; a_child = pcmk__xe_next(a_child)) {
415 clone_data->xml_obj_child = a_child;
420 if (clone_data->xml_obj_child == NULL) {
442 if (clone_data->clone_max <= 0) {
452 for (lpc = 0; lpc < clone_data->clone_max; lpc++) {
460 clone_data->clone_max, rsc->
id);
469 for (; gIter != NULL; gIter = gIter->next) {
471 gboolean child_active = child_rsc->
fns->
active(child_rsc, all);
473 if (all == FALSE && child_active) {
475 }
else if (all && child_active == FALSE) {
492 short_print(
const char *list,
const char *prefix,
const char *
type,
493 const char *suffix,
long options,
void *print_data)
499 if (!pcmk__str_empty(list)) {
520 const char *target_role = g_hash_table_lookup(rsc->
meta,
526 target_role = g_hash_table_lookup(instance->
meta,
536 const char *target_role = configured_role_str(rsc);
538 if (target_role != NULL) {
542 " for resource %s", rsc->
id);
553 clone_print_xml(
pcmk_resource_t *rsc,
const char *pre_text,
long options,
557 const char *target_role = configured_role_str(rsc);
577 for (; gIter != NULL; gIter = gIter->next) {
580 child_rsc->
fns->
print(child_rsc, child_text, options, print_data);
601 for (gIter = rsc->
children; gIter != NULL; gIter = gIter->next) {
626 GString *list_text = NULL;
627 char *child_text = NULL;
628 GString *stopped_list = NULL;
630 GList *promoted_list = NULL;
631 GList *started_list = NULL;
635 int active_instances = 0;
637 if (pre_text == NULL) {
642 clone_print_xml(rsc, pre_text, options, print_data);
651 pcmk__s(pre_text,
""), rsc->
id,
652 pcmk__xe_id(clone_data->xml_obj_child),
664 for (; gIter != NULL; gIter = gIter->next) {
665 gboolean print_full = FALSE;
667 gboolean partially_active = child_rsc->
fns->
active(child_rsc, FALSE);
688 }
else if (partially_active == FALSE) {
693 pcmk__add_word(&stopped_list, 1024, child_rsc->
id);
703 }
else if (child_rsc->
fns->
active(child_rsc, TRUE)) {
708 location = child_rsc->
fns->
location(child_rsc, NULL, TRUE);
718 promoted_list = g_list_append(promoted_list, location);
721 started_list = g_list_append(started_list, location);
738 child_rsc->
fns->
print(child_rsc, child_text, options, print_data);
747 for (gIter = promoted_list; gIter; gIter = gIter->next) {
750 pcmk__add_word(&list_text, 1024,
host->details->uname);
754 if (list_text != NULL) {
755 short_print((
const char *) list_text->str, child_text,
757 g_string_truncate(list_text, 0);
759 g_list_free(promoted_list);
763 for (gIter = started_list; gIter; gIter = gIter->next) {
766 pcmk__add_word(&list_text, 1024,
host->details->uname);
770 if (list_text != NULL) {
775 short_print((
const char *) list_text->str, child_text,
777 NULL, options, print_data);
779 short_print((
const char *) list_text->str, child_text,
784 short_print((
const char *) list_text->str, child_text,
"Started",
785 NULL, options, print_data);
789 g_list_free(started_list);
792 const char *state =
"Stopped";
796 state =
"Stopped (disabled)";
800 && (clone_data->clone_max > active_instances)) {
806 if (stopped_list != NULL) {
807 g_string_truncate(stopped_list, 0);
815 list = g_hash_table_get_values(rsc->
known_on);
819 for (nIter = list; nIter != NULL; nIter = nIter->next) {
824 pcmk__add_word(&stopped_list, 1024, node->
details->
uname);
830 if (stopped_list != NULL) {
831 short_print((
const char *) stopped_list->str, child_text, state,
832 NULL, options, print_data);
840 if (list_text != NULL) {
841 g_string_free(list_text, TRUE);
844 if (stopped_list != NULL) {
845 g_string_free(stopped_list, TRUE);
855 uint32_t show_opts = va_arg(args, uint32_t);
857 GList *only_node = va_arg(args, GList *);
858 GList *only_rsc = va_arg(args, GList *);
863 gboolean printed_header = FALSE;
864 gboolean print_everything = TRUE;
873 all = g_list_prepend(all, (gpointer)
"*");
875 for (; gIter != NULL; gIter = gIter->next) {
882 if (child_rsc->
fns->
is_filtered(child_rsc, only_rsc, print_everything)) {
886 if (!printed_header) {
887 const char *multi_state = pcmk__flag_text(rsc->
flags,
890 const char *maintenance = pcmk__flag_text(rsc->
flags,
895 const char *ignored = pcmk__flag_text(rsc->
flags,
897 const char *target_role = configured_role_str(rsc);
900 printed_header = TRUE;
917 out->message(out, (
const char *) child_rsc->
xml->name, show_opts,
918 child_rsc, only_node, all);
921 if (printed_header) {
934 uint32_t show_opts = va_arg(args, uint32_t);
936 GList *only_node = va_arg(args, GList *);
937 GList *only_rsc = va_arg(args, GList *);
939 GHashTable *stopped = NULL;
941 GString *list_text = NULL;
943 GList *promoted_list = NULL;
944 GList *started_list = NULL;
947 const char *desc = NULL;
950 int active_instances = 0;
952 gboolean print_everything = TRUE;
965 for (; gIter != NULL; gIter = gIter->next) {
966 gboolean print_full = FALSE;
968 gboolean partially_active = child_rsc->
fns->
active(child_rsc, FALSE);
974 if (child_rsc->
fns->
is_filtered(child_rsc, only_rsc, print_everything)) {
997 }
else if (partially_active == FALSE) {
1002 if (stopped == NULL) {
1015 }
else if (child_rsc->
fns->
active(child_rsc, TRUE)) {
1020 location = child_rsc->
fns->
location(child_rsc, NULL, TRUE);
1030 promoted_list = g_list_append(promoted_list, location);
1033 started_list = g_list_append(started_list, location);
1049 clone_header(out, &rc, rsc, clone_data, desc);
1052 all = g_list_prepend(all, (gpointer)
"*");
1053 out->message(out, (
const char *) child_rsc->
xml->name, show_opts,
1054 child_rsc, only_node, all);
1066 for (gIter = promoted_list; gIter; gIter = gIter->next) {
1074 pcmk__add_word(&list_text, 1024,
host->details->uname);
1077 g_list_free(promoted_list);
1079 if ((list_text != NULL) && (list_text->len > 0)) {
1080 clone_header(out, &rc, rsc, clone_data, desc);
1083 (
const char *) list_text->str);
1084 g_string_truncate(list_text, 0);
1089 for (gIter = started_list; gIter; gIter = gIter->next) {
1097 pcmk__add_word(&list_text, 1024,
host->details->uname);
1100 g_list_free(started_list);
1102 if ((list_text != NULL) && (list_text->len > 0)) {
1103 clone_header(out, &rc, rsc, clone_data, desc);
1109 out->list_item(out, NULL,
1112 (
const char *) list_text->str);
1115 (
const char *) list_text->str);
1119 out->list_item(out, NULL,
"Started: [ %s ]",
1120 (
const char *) list_text->str);
1124 if (list_text != NULL) {
1125 g_string_free(list_text, TRUE);
1130 && (clone_data->clone_max > active_instances)) {
1136 if (stopped != NULL) {
1137 g_hash_table_destroy(stopped);
1146 list = g_hash_table_get_values(rsc->
known_on);
1150 for (nIter = list; nIter != NULL; nIter = nIter->next) {
1158 const char *state =
"Stopped";
1161 state =
"Stopped (disabled)";
1164 if (stopped == NULL) {
1167 if (probe_op != NULL) {
1173 g_hash_table_insert(stopped, strdup(node->
details->
uname),
1183 if (stopped != NULL) {
1184 GList *list = sorted_hash_table_values(stopped);
1186 clone_header(out, &rc, rsc, clone_data, desc);
1188 for (GList *status_iter = list; status_iter != NULL; status_iter = status_iter->next) {
1189 const char *status = status_iter->data;
1190 GList *nodes = nodes_with_status(stopped, status);
1191 GString *nodes_str = node_list_to_str(nodes);
1193 if (nodes_str != NULL) {
1194 if (nodes_str->len > 0) {
1195 out->list_item(out, NULL,
"%s: [ %s ]", status,
1196 (
const char *) nodes_str->str);
1198 g_string_free(nodes_str, TRUE);
1205 g_hash_table_destroy(stopped);
1211 }
else if (active_instances == 0) {
1212 clone_header(out, &rc, rsc, clone_data, desc);
1231 for (GList *gIter = rsc->
children; gIter != NULL; gIter = gIter->next) {
1237 child_rsc->
xml = NULL;
1241 child_rsc->
fns->
free(child_rsc);
1248 && (clone_data->stop_notify == NULL)
1249 && (clone_data->start_notify == NULL)
1250 && (clone_data->promote_notify == NULL));
1262 for (; gIter != NULL; gIter = gIter->next) {
1266 if (a_role > clone_role) {
1267 clone_role = a_role;
1286 if (pcmk__is_clone(rsc)) {
1298 gboolean check_parent)
1300 gboolean passes = FALSE;
1311 for (
const GList *iter = rsc->
children;
1312 iter != NULL; iter = iter->next) {
1332 return pcmk__xe_id(clone_data->xml_obj_child);
1371 clone_data->flags = pcmk__set_flags_as(__func__, __LINE__,
LOG_TRACE,
1373 clone_data->flags, flag,
"flag");
1394 return pcmk_all_flags_set(clone_data->flags,
flags);
1417 !any_promoting,
true);
1421 !any_promoting,
true);
1425 if (clone_data->promote_notify == NULL) {
1434 !any_demoting,
true);
1438 !any_demoting,
true);
1442 if (clone_data->demote_notify == NULL) {
1448 if (clone_data->promote_notify != NULL) {
1496 clone_data->demote_notify = NULL;
1499 clone_data->stop_notify = NULL;
1502 clone_data->start_notify = NULL;
1505 clone_data->promote_notify = NULL;
1527 if (clone_data->start_notify == NULL) {
1533 if (clone_data->stop_notify == NULL) {
1537 if ((clone_data->start_notify != NULL)
1538 && (clone_data->stop_notify != NULL)) {
1559 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)
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)
#define PROMOTED_INSTANCES
pcmk_node_t *(* location)(const pcmk_resource_t *rsc, GList **list, int current)
Control output from tools.
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...)
#define UNPROMOTED_INSTANCES
pcmk_resource_t * pe_find_resource(GList *rsc_list, const char *id)
void pe__force_anon(const char *standard, pcmk_resource_t *rsc, const char *rid, pcmk_scheduler_t *scheduler)
enum rsc_role_e(* state)(const pcmk_resource_t *rsc, gboolean current)
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
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.
int pe__clone_default(pcmk__output_t *out, va_list args)
void pcmk__add_separated_word(GString **list, size_t init_size, const char *word, const char *separator)
#define PCMK_META_CLONE_MAX
enum crm_ais_msg_types type
const char * rsc_printable_id(const pcmk_resource_t *rsc)
void pe__set_resource_flags_recursive(pcmk_resource_t *rsc, uint64_t flags)
void(* print)(pcmk_resource_t *rsc, const char *pre_text, long options, void *print_data)
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 clone_print(pcmk_resource_t *rsc, const char *pre_text, long options, void *print_data)
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)
void(* free)(pcmk_resource_t *rsc)
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
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
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
xmlNode * pcmk__xe_first_child(const xmlNode *parent, const char *node_name, const char *attr_n, const char *attr_v)
#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)
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
#define PCMK_ACTION_START
#define PCMK_META_RESOURCE_STICKINESS
Wrappers for and extensions to libxml2.
#define PCMK_META_TARGET_ROLE
#define PCMK__META_PROMOTED_MAX_LEGACY
PCMK__OUTPUT_ARGS("clone", "uint32_t", "pcmk_resource_t *", "GList *", "GList *")
void free_xml(xmlNode *child)
#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)
pcmk_resource_t * find_clone_instance(const pcmk_resource_t *rsc, const char *sub_id)
#define PCMK_XA_MAINTENANCE
enum rsc_role_e clone_resource_state(const pcmk_resource_t *rsc, gboolean current)
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)
gboolean(* active)(pcmk_resource_t *rsc, gboolean all)
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_XA_MULTI_STATE
pcmk_scheduler_t * scheduler
#define PCMK_META_PROMOTED_NODE_MAX
const char * pe__clone_child_id(const pcmk_resource_t *rsc)
#define status_print(fmt, args...)
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_ACTION_PROMOTE
#define PCMK_META_PROMOTED_MAX
int pcmk__numeric_strcasecmp(const char *s1, const char *s2)
gboolean(* is_filtered)(const pcmk_resource_t *rsc, GList *only_rsc, gboolean check_parent)
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
gboolean crm_is_true(const char *s)
int pe__clone_promoted_node_max(const pcmk_resource_t *clone)
Resource role is unknown.
#define PCMK_META_ORDERED
#define PCMK_ACTION_DEMOTED
#define pcmk__assert_alloc(nmemb, size)
void pcmk__insert_dup(GHashTable *table, const char *name, const char *value)
#define PCMK_SCORE_INFINITY
Integer score to use to represent "infinity".
GHashTable * allowed_nodes
gboolean pcmk__str_in_list(const gchar *s, const GList *lst, uint32_t flags)