22 #define VARIANT_CLONE 1    25 #ifdef PCMK__COMPAT_2_0    26 #define PROMOTED_INSTANCES   RSC_ROLE_PROMOTED_LEGACY_S "s"    27 #define UNPROMOTED_INSTANCES RSC_ROLE_UNPROMOTED_LEGACY_S "s"    29 #define PROMOTED_INSTANCES   RSC_ROLE_PROMOTED_S    30 #define UNPROMOTED_INSTANCES RSC_ROLE_UNPROMOTED_S    44     clone_variant_data_t *clone_data = NULL;
    46     get_clone_variant_data(clone_data, 
uber_parent(clone));
    47     return clone_data->promoted_max;
    61     clone_variant_data_t *clone_data = NULL;
    63     get_clone_variant_data(clone_data, 
uber_parent(clone));
    64     return clone_data->promoted_node_max;
    68 sorted_hash_table_values(GHashTable *table)
    74     g_hash_table_iter_init(&iter, table);
    75     while (g_hash_table_iter_next(&iter, &key, &value)) {
    76         if (!g_list_find_custom(retval, value, (GCompareFunc) strcmp)) {
    77             retval = g_list_prepend(retval, (
char *) value);
    81     retval = g_list_sort(retval, (GCompareFunc) strcmp);
    86 nodes_with_status(GHashTable *table, 
const char *status)
    92     g_hash_table_iter_init(&iter, table);
    93     while (g_hash_table_iter_next(&iter, &key, &value)) {
    94         if (!strcmp((
char *) value, status)) {
    95             retval = g_list_prepend(retval, key);
   104 node_list_to_str(
const GList *list)
   106     GString *retval = NULL;
   108     for (
const GList *iter = list; iter != NULL; iter = iter->next) {
   109         pcmk__add_word(&retval, 1024, (
const char *) iter->data);
   118     GString *attrs = NULL;
   138                                  rsc->
id, 
ID(clone_data->xml_obj_child),
   139                                  (
const char *) attrs->str);
   140         g_string_free(attrs, TRUE);
   143                                  rsc->
id, 
ID(clone_data->xml_obj_child))
   151     if (pe_rsc_is_clone(rsc)) {
   152         clone_variant_data_t *clone_data = NULL;
   154         get_clone_variant_data(clone_data, rsc);
   157                 "such as %s can be used only as anonymous clones",
   158                 rsc->
id, standard, rid);
   160         clone_data->clone_node_max = 1;
   161         clone_data->clone_max = QB_MIN(clone_data->clone_max,
   169     char *child_id = NULL;
   171     const char *child_base = NULL;
   172     clone_variant_data_t *clone_data = NULL;
   174     get_clone_variant_data(clone_data, rsc);
   176     child_base = 
ID(clone_data->xml_obj_child);
   187     gboolean as_orphan = FALSE;
   188     char *inc_num = NULL;
   189     char *inc_max = NULL;
   191     xmlNode *child_copy = NULL;
   192     clone_variant_data_t *clone_data = NULL;
   194     get_clone_variant_data(clone_data, rsc);
   196     CRM_CHECK(clone_data->xml_obj_child != NULL, 
return FALSE);
   198     if (clone_data->total_clones >= clone_data->clone_max) {
   204     inc_num = pcmk__itoa(clone_data->total_clones);
   205     inc_max = pcmk__itoa(clone_data->clone_max);
   207     child_copy = 
copy_xml(clone_data->xml_obj_child);
   218     clone_data->total_clones += 1;
   219     pe_rsc_trace(child_rsc, 
"Setting clone attributes for: %s", child_rsc->
id);
   239     xmlNode *a_child = NULL;
   240     xmlNode *xml_obj = rsc->
xml;
   241     clone_variant_data_t *clone_data = NULL;
   248     clone_data = calloc(1, 
sizeof(clone_variant_data_t));
   252         const char *promoted_max = NULL;
   253         const char *promoted_node_max = NULL;
   255         promoted_max = g_hash_table_lookup(rsc->
meta,
   257         if (promoted_max == NULL) {
   259             promoted_max = g_hash_table_lookup(rsc->
meta,
   263         promoted_node_max = g_hash_table_lookup(rsc->
meta,
   265         if (promoted_node_max == NULL) {
   268                 g_hash_table_lookup(rsc->
meta,
   273         if (promoted_max == NULL) {
   274             clone_data->promoted_max = 1;
   280         if (promoted_node_max == NULL) {
   281             clone_data->promoted_node_max = 1;
   284                                &(clone_data->promoted_node_max), 0);
   292     if (max_clones_node == NULL) {
   293         clone_data->clone_node_max = 1;
   301     if (max_clones == NULL) {
   302         clone_data->clone_max = QB_MAX(1, g_list_length(
data_set->
nodes));
   308         clone_data->flags = pcmk__set_flags_as(__func__, __LINE__, 
LOG_TRACE,
   312                                                "pe__clone_ordered");
   317                          "because anonymous clones support only one instance "   318                          "per node", rsc->
id);
   319         clone_data->clone_node_max = 1;
   323     pe_rsc_trace(rsc, 
"\tClone max: %d", clone_data->clone_max);
   324     pe_rsc_trace(rsc, 
"\tClone node max: %d", clone_data->clone_node_max);
   331     for (a_child = pcmk__xe_first_child(xml_obj); a_child != NULL;
   332          a_child = pcmk__xe_next(a_child)) {
   335             clone_data->xml_obj_child = a_child;
   340     if (clone_data->xml_obj_child == NULL) {
   361     if (clone_data->clone_max <= 0) {
   371         for (lpc = 0; lpc < clone_data->clone_max; lpc++) {
   378     pe_rsc_trace(rsc, 
"Added %d children to resource %s...", clone_data->clone_max, rsc->
id);
   387     for (; gIter != NULL; gIter = gIter->next) {
   389         gboolean child_active = child_rsc->
fns->
active(child_rsc, all);
   391         if (all == FALSE && child_active) {
   393         } 
else if (all && child_active == FALSE) {
   410 short_print(
const char *list, 
const char *prefix, 
const char *
type,
   411             const char *suffix, 
long options, 
void *print_data)
   417     if (!pcmk__str_empty(list)) {
   438     const char *target_role = g_hash_table_lookup(rsc->
meta,
   451     const char *target_role = configured_role_str(rsc);
   464 clone_print_xml(
pe_resource_t *rsc, 
const char *pre_text, 
long options,
   468     const char *target_role = configured_role_str(rsc);
   485     for (; gIter != NULL; gIter = gIter->next) {
   488         child_rsc->
fns->
print(child_rsc, child_text, options, print_data);
   509     for (gIter = rsc->
children; gIter != NULL; gIter = gIter->next) {
   534     GString *list_text = NULL;
   535     char *child_text = NULL;
   536     GString *stopped_list = NULL;
   538     GList *promoted_list = NULL;
   539     GList *started_list = NULL;
   542     clone_variant_data_t *clone_data = NULL;
   543     int active_instances = 0;
   545     if (pre_text == NULL) {
   550         clone_print_xml(rsc, pre_text, options, print_data);
   554     get_clone_variant_data(clone_data, rsc);
   559                  pre_text ? pre_text : 
"", rsc->
id, 
ID(clone_data->xml_obj_child),
   571     for (; gIter != NULL; gIter = gIter->next) {
   572         gboolean print_full = FALSE;
   574         gboolean partially_active = child_rsc->
fns->
active(child_rsc, FALSE);
   594         } 
else if (partially_active == FALSE) {
   599                 pcmk__add_word(&stopped_list, 1024, child_rsc->
id);
   609         } 
else if (child_rsc->
fns->
active(child_rsc, TRUE)) {
   623                     promoted_list = g_list_append(promoted_list, location);
   626                     started_list = g_list_append(started_list, location);
   643             child_rsc->
fns->
print(child_rsc, child_text, options, print_data);
   652     for (gIter = promoted_list; gIter; gIter = gIter->next) {
   655         pcmk__add_word(&list_text, 1024, 
host->details->uname);
   659     if (list_text != NULL) {
   660         short_print((
const char *) list_text->str, child_text,
   662         g_string_truncate(list_text, 0);
   664     g_list_free(promoted_list);
   668     for (gIter = started_list; gIter; gIter = gIter->next) {
   671         pcmk__add_word(&list_text, 1024, 
host->details->uname);
   675     if (list_text != NULL) {
   680                 short_print((
const char *) list_text->str, child_text,
   682                             options, print_data);
   684                 short_print((
const char *) list_text->str, child_text,
   689             short_print((
const char *) list_text->str, child_text, 
"Started",
   690                         NULL, options, print_data);
   694     g_list_free(started_list);
   697         const char *state = 
"Stopped";
   701             state = 
"Stopped (disabled)";
   705             && (clone_data->clone_max > active_instances)) {
   711             if (stopped_list != NULL) {
   712                 g_string_truncate(stopped_list, 0);
   719                 list = g_hash_table_get_values(rsc->
known_on);
   723             for (nIter = list; nIter != NULL; nIter = nIter->next) {
   727                     pcmk__add_word(&stopped_list, 1024, node->
details->
uname);
   733         if (stopped_list != NULL) {
   734             short_print((
const char *) stopped_list->str, child_text, state,
   735                         NULL, options, print_data);
   743     if (list_text != NULL) {
   744         g_string_free(list_text, TRUE);
   747     if (stopped_list != NULL) {
   748         g_string_free(stopped_list, TRUE);
   757     uint32_t show_opts = va_arg(args, uint32_t);
   759     GList *only_node = va_arg(args, GList *);
   760     GList *only_rsc = va_arg(args, GList *);
   765     gboolean printed_header = FALSE;
   766     gboolean print_everything = TRUE;
   775     all = g_list_prepend(all, (gpointer) 
"*");
   777     for (; gIter != NULL; gIter = gIter->next) {
   784         if (child_rsc->
fns->
is_filtered(child_rsc, only_rsc, print_everything)) {
   788         if (!printed_header) {
   789             printed_header = TRUE;
   799                     "target_role", configured_role_str(rsc));
   803         out->message(out, crm_map_element_name(child_rsc->
xml), show_opts,
   804                      child_rsc, only_node, all);
   807     if (printed_header) {
   819     uint32_t show_opts = va_arg(args, uint32_t);
   821     GList *only_node = va_arg(args, GList *);
   822     GList *only_rsc = va_arg(args, GList *);
   824     GHashTable *stopped = NULL;
   826     GString *list_text = NULL;
   828     GList *promoted_list = NULL;
   829     GList *started_list = NULL;
   832     clone_variant_data_t *clone_data = NULL;
   833     int active_instances = 0;
   835     gboolean print_everything = TRUE;
   837     get_clone_variant_data(clone_data, rsc);
   846     for (; gIter != NULL; gIter = gIter->next) {
   847         gboolean print_full = FALSE;
   849         gboolean partially_active = child_rsc->
fns->
active(child_rsc, FALSE);
   855         if (child_rsc->
fns->
is_filtered(child_rsc, only_rsc, print_everything)) {
   877         } 
else if (partially_active == FALSE) {
   882                 if (stopped == NULL) {
   885                 g_hash_table_insert(stopped, strdup(child_rsc->
id), strdup(
"Stopped"));
   895         } 
else if (child_rsc->
fns->
active(child_rsc, TRUE)) {
   909                     promoted_list = g_list_append(promoted_list, location);
   912                     started_list = g_list_append(started_list, location);
   928             clone_header(out, &rc, rsc, clone_data);
   931             all = g_list_prepend(all, (gpointer) 
"*");
   932             out->message(out, crm_map_element_name(child_rsc->
xml), show_opts,
   933                          child_rsc, only_node, all);
   945     for (gIter = promoted_list; gIter; gIter = gIter->next) {
   953         pcmk__add_word(&list_text, 1024, 
host->details->uname);
   956     g_list_free(promoted_list);
   958     if ((list_text != NULL) && (list_text->len > 0)) {
   959         clone_header(out, &rc, rsc, clone_data);
   962                        (
const char *) list_text->str);
   963         g_string_truncate(list_text, 0);
   968     for (gIter = started_list; gIter; gIter = gIter->next) {
   976         pcmk__add_word(&list_text, 1024, 
host->details->uname);
   979     g_list_free(started_list);
   981     if ((list_text != NULL) && (list_text->len > 0)) {
   982         clone_header(out, &rc, rsc, clone_data);
   988                 out->list_item(out, NULL,
   990                                (
const char *) list_text->str);
   993                                (
const char *) list_text->str);
   997             out->list_item(out, NULL, 
"Started: [ %s ]",
   998                            (
const char *) list_text->str);
  1002     if (list_text != NULL) {
  1003         g_string_free(list_text, TRUE);
  1008             && (clone_data->clone_max > active_instances)) {
  1014             if (stopped != NULL) {
  1015                 g_hash_table_destroy(stopped);
  1023                 list = g_hash_table_get_values(rsc->
known_on);
  1027             for (nIter = list; nIter != NULL; nIter = nIter->next) {
  1034                     const char *state = 
"Stopped";
  1037                         state = 
"Stopped (disabled)";
  1040                     if (stopped == NULL) {
  1043                     if (probe_op != NULL) {
  1047                         g_hash_table_insert(stopped, strdup(node->
details->
uname),
  1050                         g_hash_table_insert(stopped, strdup(node->
details->
uname),
  1058         if (stopped != NULL) {
  1059             GList *list = sorted_hash_table_values(stopped);
  1061             clone_header(out, &rc, rsc, clone_data);
  1063             for (GList *status_iter = list; status_iter != NULL; status_iter = status_iter->next) {
  1064                 const char *status = status_iter->data;
  1065                 GList *nodes = nodes_with_status(stopped, status);
  1066                 GString *nodes_str = node_list_to_str(nodes);
  1068                 if (nodes_str != NULL) {
  1069                     if (nodes_str->len > 0) {
  1070                         out->list_item(out, NULL, 
"%s: [ %s ]", status,
  1071                                        (
const char *) nodes_str->str);
  1073                     g_string_free(nodes_str, TRUE);
  1080             g_hash_table_destroy(stopped);
  1086         } 
else if (active_instances == 0) {
  1087             clone_header(out, &rc, rsc, clone_data);
  1100     clone_variant_data_t *clone_data = NULL;
  1102     get_clone_variant_data(clone_data, rsc);
  1106     for (GList *gIter = rsc->
children; gIter != NULL; gIter = gIter->next) {
  1112         child_rsc->
xml = NULL;
  1116         child_rsc->
fns->
free(child_rsc);
  1122         CRM_ASSERT(clone_data->demote_notify == NULL);
  1124         CRM_ASSERT(clone_data->start_notify == NULL);
  1125         CRM_ASSERT(clone_data->promote_notify == NULL);
  1137     for (; gIter != NULL; gIter = gIter->next) {
  1141         if (a_role > clone_role) {
  1142             clone_role = a_role;
  1161     if (pe_rsc_is_clone(rsc)) {
  1162         clone_variant_data_t *clone_data = NULL;
  1164         get_clone_variant_data(clone_data, rsc);
  1165         if (clone_data->clone_max == g_list_length(
data_set->
nodes)) {
  1175     gboolean passes = FALSE;
  1176     clone_variant_data_t *clone_data = NULL;
  1181         get_clone_variant_data(clone_data, rsc);
  1185             for (GList *gIter = rsc->
children; gIter != NULL; gIter = gIter->next) {
  1202     clone_variant_data_t *clone_data = NULL;
  1203     get_clone_variant_data(clone_data, rsc);
  1204     return ID(clone_data->xml_obj_child);
  1218     clone_variant_data_t *clone_data = NULL;
  1220     get_clone_variant_data(clone_data, clone);
  1237     clone_variant_data_t *clone_data = NULL;
  1239     get_clone_variant_data(clone_data, clone);
  1243     clone_data->flags = pcmk__set_flags_as(__func__, __LINE__, 
LOG_TRACE,
  1245                                            clone_data->flags, flag, 
"flag");
  1263     clone_variant_data_t *clone_data = NULL;
  1265     get_clone_variant_data(clone_data, clone);
  1273                                                 !any_promoting, 
true);
  1277     if (clone_data->promote_notify == NULL) {
  1289                                                 !any_demoting, 
true);
  1293     if (clone_data->demote_notify == NULL) {
  1299         if (clone_data->promote_notify != NULL) {
  1301                           clone_data->promote_notify->pre,
  1304                           clone_data->promote_notify->pre,
  1307                           clone_data->promote_notify->pre,
  1310                           clone_data->start_notify->pre,
  1313                           clone_data->stop_notify->pre,
 
#define CRM_CHECK(expr, failure_action)
 
pe_resource_t * find_clone_instance(pe_resource_t *rsc, const char *sub_id, pe_working_set_t *data_set)
 
#define PCMK_XA_PROMOTED_MAX_LEGACY
 
pe_node_t * pe_find_node(GList *node_list, const char *uname)
 
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...)
 
bool pe__is_universal_clone(pe_resource_t *rsc, pe_working_set_t *data_set)
 
void pe__force_anon(const char *standard, pe_resource_t *rsc, const char *rid, pe_working_set_t *data_set)
 
resource_object_functions_t * fns
 
bool pe__clone_is_ordered(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. 
 
int pe__clone_promoted_node_max(pe_resource_t *clone)
 
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
 
const char * pe__clone_child_id(pe_resource_t *rsc)
 
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)
 
#define XML_RSC_ATTR_INCARNATION_MAX
 
gboolean pe__clone_is_filtered(pe_resource_t *rsc, GList *only_rsc, gboolean check_parent)
 
int pe__clone_xml(pcmk__output_t *out, va_list args)
 
#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)
 
pe_resource_t * uber_parent(pe_resource_t *rsc)
 
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute. 
 
#define XML_CIB_TAG_RESOURCE
 
#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,...)
 
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 *)
 
void free_xml(xmlNode *child)
 
enum rsc_role_e text2role(const char *role)
 
bool pcmk__str_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
 
void pcmk__output_xml_pop_parent(pcmk__output_t *out)
 
#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
 
xmlNode * pe__failed_probe_for_rsc(pe_resource_t *rsc, const char *name)
 
#define PCMK__OUTPUT_LIST_HEADER(out_obj, cond, retcode, title...)
 
Cluster status and scheduling. 
 
gboolean(* is_filtered)(pe_resource_t *, GList *, gboolean)
 
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)
 
const char * rsc_printable_id(pe_resource_t *rsc)
 
#define status_print(fmt, args...)
 
This structure contains everything that makes up a single output formatter. 
 
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_failure_ignored
 
gboolean clone_active(pe_resource_t *rsc, gboolean all)
 
gboolean crm_is_true(const char *s)
 
#define XML_CIB_TAG_GROUP
 
#define pe_rsc_trace(rsc, fmt, args...)
 
notify_data_t * pe__clone_notif_pseudo_ops(pe_resource_t *rsc, const char *task, pe_action_t *action, pe_action_t *complete)
 
bool pe__resource_is_disabled(pe_resource_t *rsc)
 
int pe__clone_promoted_max(pe_resource_t *clone)
 
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)
 
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)