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)