pacemaker  2.0.4-2deceaa
Scalable High-Availability cluster resource manager
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
group.c
Go to the documentation of this file.
1 /*
2  * Copyright 2004-2020 the Pacemaker project contributors
3  *
4  * The version control history for this file may have further details.
5  *
6  * This source code is licensed under the GNU Lesser General Public License
7  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
8  */
9 
10 #include <crm_internal.h>
11 
12 #include <crm/pengine/rules.h>
13 #include <crm/pengine/status.h>
14 #include <crm/pengine/internal.h>
15 #include <crm/msg_xml.h>
16 #include <pe_status_private.h>
17 
18 #define VARIANT_GROUP 1
19 #include "./variant.h"
20 
21 gboolean
23 {
24  xmlNode *xml_obj = rsc->xml;
25  xmlNode *xml_native_rsc = NULL;
26  group_variant_data_t *group_data = NULL;
27  const char *group_ordered = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_ORDERED);
28  const char *group_colocated = g_hash_table_lookup(rsc->meta, "collocated");
29  const char *clone_id = NULL;
30 
31  pe_rsc_trace(rsc, "Processing resource %s...", rsc->id);
32 
33  group_data = calloc(1, sizeof(group_variant_data_t));
34  group_data->num_children = 0;
35  group_data->first_child = NULL;
36  group_data->last_child = NULL;
37  rsc->variant_opaque = group_data;
38 
39  // We don't actually need the null checks but it speeds up the common case
40  if ((group_ordered == NULL)
41  || (crm_str_to_boolean(group_ordered, &(group_data->ordered)) < 0)) {
42  group_data->ordered = TRUE;
43  }
44  if ((group_colocated == NULL)
45  || (crm_str_to_boolean(group_colocated, &(group_data->colocated)) < 0)) {
46  group_data->colocated = TRUE;
47  }
48 
50 
51  for (xml_native_rsc = __xml_first_child_element(xml_obj); xml_native_rsc != NULL;
52  xml_native_rsc = __xml_next_element(xml_native_rsc)) {
53  if (crm_str_eq((const char *)xml_native_rsc->name, XML_CIB_TAG_RESOURCE, TRUE)) {
54  pe_resource_t *new_rsc = NULL;
55 
56  crm_xml_add(xml_native_rsc, XML_RSC_ATTR_INCARNATION, clone_id);
57  if (common_unpack(xml_native_rsc, &new_rsc, rsc, data_set) == FALSE) {
58  pe_err("Failed unpacking resource %s", crm_element_value(xml_obj, XML_ATTR_ID));
59  if (new_rsc != NULL && new_rsc->fns != NULL) {
60  new_rsc->fns->free(new_rsc);
61  }
62  continue;
63  }
64 
65  group_data->num_children++;
66  rsc->children = g_list_append(rsc->children, new_rsc);
67 
68  if (group_data->first_child == NULL) {
69  group_data->first_child = new_rsc;
70  }
71  group_data->last_child = new_rsc;
72  pe_rsc_trace(rsc, "Added %s member %s", rsc->id, new_rsc->id);
73  }
74  }
75 
76  if (group_data->num_children == 0) {
77  pcmk__config_warn("Group %s does not have any children", rsc->id);
78  return TRUE; // Allow empty groups, children can be added later
79  }
80 
81  pe_rsc_trace(rsc, "Added %d children to resource %s...", group_data->num_children, rsc->id);
82 
83  return TRUE;
84 }
85 
86 gboolean
87 group_active(pe_resource_t * rsc, gboolean all)
88 {
89  gboolean c_all = TRUE;
90  gboolean c_any = FALSE;
91  GListPtr gIter = rsc->children;
92 
93  for (; gIter != NULL; gIter = gIter->next) {
94  pe_resource_t *child_rsc = (pe_resource_t *) gIter->data;
95 
96  if (child_rsc->fns->active(child_rsc, all)) {
97  c_any = TRUE;
98  } else {
99  c_all = FALSE;
100  }
101  }
102 
103  if (c_any == FALSE) {
104  return FALSE;
105  } else if (all && c_all == FALSE) {
106  return FALSE;
107  }
108  return TRUE;
109 }
110 
111 static void
112 group_print_xml(pe_resource_t * rsc, const char *pre_text, long options, void *print_data)
113 {
114  GListPtr gIter = rsc->children;
115  char *child_text = crm_strdup_printf("%s ", pre_text);
116 
117  status_print("%s<group id=\"%s\" ", pre_text, rsc->id);
118  status_print("number_resources=\"%d\" ", g_list_length(rsc->children));
119  status_print(">\n");
120 
121  for (; gIter != NULL; gIter = gIter->next) {
122  pe_resource_t *child_rsc = (pe_resource_t *) gIter->data;
123 
124  child_rsc->fns->print(child_rsc, child_text, options, print_data);
125  }
126 
127  status_print("%s</group>\n", pre_text);
128  free(child_text);
129 }
130 
131 void
132 group_print(pe_resource_t * rsc, const char *pre_text, long options, void *print_data)
133 {
134  char *child_text = NULL;
135  GListPtr gIter = rsc->children;
136 
137  if (pre_text == NULL) {
138  pre_text = " ";
139  }
140 
141  if (options & pe_print_xml) {
142  group_print_xml(rsc, pre_text, options, print_data);
143  return;
144  }
145 
146  child_text = crm_strdup_printf("%s ", pre_text);
147 
148  status_print("%sResource Group: %s", pre_text ? pre_text : "", rsc->id);
149 
150  if (options & pe_print_html) {
151  status_print("\n<ul>\n");
152 
153  } else if ((options & pe_print_log) == 0) {
154  status_print("\n");
155  }
156 
157  if (options & pe_print_brief) {
158  print_rscs_brief(rsc->children, child_text, options, print_data, TRUE);
159 
160  } else {
161  for (; gIter != NULL; gIter = gIter->next) {
162  pe_resource_t *child_rsc = (pe_resource_t *) gIter->data;
163 
164  if (options & pe_print_html) {
165  status_print("<li>\n");
166  }
167  child_rsc->fns->print(child_rsc, child_text, options, print_data);
168  if (options & pe_print_html) {
169  status_print("</li>\n");
170  }
171  }
172  }
173 
174  if (options & pe_print_html) {
175  status_print("</ul>\n");
176  }
177  free(child_text);
178 }
179 
180 PCMK__OUTPUT_ARGS("group", "unsigned int", "struct pe_resource_t *", "GListPtr")
181 int
182 pe__group_xml(pcmk__output_t *out, va_list args)
183 {
184  unsigned int options = va_arg(args, unsigned int);
185  pe_resource_t *rsc = va_arg(args, pe_resource_t *);
186  GListPtr only_show G_GNUC_UNUSED = va_arg(args, GListPtr);
187 
188  GListPtr gIter = rsc->children;
189  char *count = crm_itoa(g_list_length(gIter));
190 
191  int rc = pcmk_rc_no_output;
192  gboolean printed_header = FALSE;
193 
194  for (; gIter != NULL; gIter = gIter->next) {
195  pe_resource_t *child_rsc = (pe_resource_t *) gIter->data;
196 
197  if (!printed_header) {
198  printed_header = TRUE;
199 
200  rc = pe__name_and_nvpairs_xml(out, true, "group", 2
201  , "id", rsc->id
202  , "number_resources", count);
203  free(count);
204  CRM_ASSERT(rc == pcmk_rc_ok);
205  }
206 
207  out->message(out, crm_map_element_name(child_rsc->xml), options, child_rsc, only_show);
208  }
209 
210  if (printed_header) {
212  }
213 
214  return rc;
215 }
216 
217 PCMK__OUTPUT_ARGS("group", "unsigned int", "struct pe_resource_t *", "GListPtr")
218 int
219 pe__group_html(pcmk__output_t *out, va_list args)
220 {
221  unsigned int options = va_arg(args, unsigned int);
222  pe_resource_t *rsc = va_arg(args, pe_resource_t *);
223  GListPtr only_show G_GNUC_UNUSED = va_arg(args, GListPtr);
224 
225  out->begin_list(out, NULL, NULL, "Resource Group: %s", rsc->id);
226 
227  if (options & pe_print_brief) {
228  pe__rscs_brief_output(out, rsc->children, options, TRUE);
229 
230  } else {
231  for (GListPtr gIter = rsc->children; gIter; gIter = gIter->next) {
232  pe_resource_t *child_rsc = (pe_resource_t *) gIter->data;
233  out->message(out, crm_map_element_name(child_rsc->xml), options, child_rsc, only_show);
234  }
235  }
236 
237  out->end_list(out);
238 
239  return pcmk_rc_ok;
240 }
241 
242 PCMK__OUTPUT_ARGS("group", "unsigned int", "struct pe_resource_t *", "GListPtr")
243 int
244 pe__group_text(pcmk__output_t *out, va_list args)
245 {
246  unsigned int options = va_arg(args, unsigned int);
247  pe_resource_t *rsc = va_arg(args, pe_resource_t *);
248  GListPtr only_show G_GNUC_UNUSED = va_arg(args, GListPtr);
249 
250  out->begin_list(out, NULL, NULL, "Resource Group: %s", rsc->id);
251 
252  if (options & pe_print_brief) {
253  pe__rscs_brief_output(out, rsc->children, options, TRUE);
254 
255  } else {
256  for (GListPtr gIter = rsc->children; gIter; gIter = gIter->next) {
257  pe_resource_t *child_rsc = (pe_resource_t *) gIter->data;
258 
259  out->message(out, crm_map_element_name(child_rsc->xml), options, child_rsc, only_show);
260  }
261  }
262  out->end_list(out);
263 
264  return pcmk_rc_ok;
265 }
266 
267 void
269 {
270  CRM_CHECK(rsc != NULL, return);
271 
272  pe_rsc_trace(rsc, "Freeing %s", rsc->id);
273 
274  for (GListPtr gIter = rsc->children; gIter != NULL; gIter = gIter->next) {
275  pe_resource_t *child_rsc = (pe_resource_t *) gIter->data;
276 
277  CRM_ASSERT(child_rsc);
278  pe_rsc_trace(child_rsc, "Freeing child %s", child_rsc->id);
279  child_rsc->fns->free(child_rsc);
280  }
281 
282  pe_rsc_trace(rsc, "Freeing child list");
283  g_list_free(rsc->children);
284 
285  common_free(rsc);
286 }
287 
288 enum rsc_role_e
289 group_resource_state(const pe_resource_t * rsc, gboolean current)
290 {
291  enum rsc_role_e group_role = RSC_ROLE_UNKNOWN;
292  GListPtr gIter = rsc->children;
293 
294  for (; gIter != NULL; gIter = gIter->next) {
295  pe_resource_t *child_rsc = (pe_resource_t *) gIter->data;
296  enum rsc_role_e role = child_rsc->fns->state(child_rsc, current);
297 
298  if (role > group_role) {
299  group_role = role;
300  }
301  }
302 
303  pe_rsc_trace(rsc, "%s role: %s", rsc->id, role2text(group_role));
304  return group_role;
305 }
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:233
void group_free(pe_resource_t *rsc)
Definition: group.c:268
void group_print(pe_resource_t *rsc, const char *pre_text, long options, void *print_data)
Definition: group.c:132
enum rsc_role_e(* state)(const pe_resource_t *, gboolean)
Definition: pe_types.h:52
void pcmk__output_xml_pop_parent(pcmk__output_t *out)
Definition: output_xml.c:397
xmlNode * xml
Definition: pe_types.h:307
#define XML_RSC_ATTR_INCARNATION
Definition: msg_xml.h:186
gboolean group_active(pe_resource_t *rsc, gboolean all)
Definition: group.c:87
GHashTable * meta
Definition: pe_types.h:357
resource_object_functions_t * fns
Definition: pe_types.h:316
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.
Definition: nvpair.c:316
void print_rscs_brief(GListPtr rsc_list, const char *pre_text, long options, void *print_data, gboolean print_all)
Definition: native.c:1305
int pe__group_text(pcmk__output_t *out, va_list args)
Definition: group.c:244
enum rsc_role_e group_resource_state(const pe_resource_t *rsc, gboolean current)
Definition: group.c:289
const char * role2text(enum rsc_role_e role)
Definition: common.c:463
int rc
Definition: pcmk_fence.c:34
#define XML_ATTR_ID
Definition: msg_xml.h:96
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: nvpair.c:522
#define XML_CIB_TAG_RESOURCE
Definition: msg_xml.h:174
int pe__name_and_nvpairs_xml(pcmk__output_t *out, bool is_list, const char *tag_name, size_t pairs_count,...)
Definition: pe_output.c:413
int pe__group_html(pcmk__output_t *out, va_list args)
Definition: group.c:219
void common_free(pe_resource_t *rsc)
Definition: complex.c:776
#define XML_RSC_ATTR_ORDERED
Definition: msg_xml.h:184
PCMK__OUTPUT_ARGS("cluster-summary","struct pe_working_set_t *","gboolean","gboolean","gboolean","gboolean","gboolean","gboolean")
Definition: pe_output.c:214
gboolean crm_str_eq(const char *a, const char *b, gboolean use_case)
Definition: strings.c:326
void(* print)(pe_resource_t *, const char *, long, void *)
Definition: pe_types.h:50
int crm_str_to_boolean(const char *s, int *ret)
Definition: strings.c:289
Cluster status and scheduling.
GListPtr children
Definition: pe_types.h:361
void * variant_opaque
Definition: pe_types.h:315
#define CRM_ASSERT(expr)
Definition: results.h:42
#define status_print(fmt, args...)
int pe__group_xml(pcmk__output_t *out, va_list args)
Definition: group.c:182
This structure contains everything that makes up a single output formatter.
Definition: output.h:153
void(* free)(pe_resource_t *)
Definition: pe_types.h:54
rsc_role_e
Definition: common.h:76
gboolean common_unpack(xmlNode *xml_obj, pe_resource_t **rsc, pe_resource_t *parent, pe_working_set_t *data_set)
Definition: complex.c:366
#define pe_rsc_trace(rsc, fmt, args...)
Definition: internal.h:19
gboolean(* active)(pe_resource_t *, gboolean)
Definition: pe_types.h:51
#define pe_err(fmt...)
Definition: internal.h:21
int pe__rscs_brief_output(pcmk__output_t *out, GListPtr rsc_list, long options, gboolean print_all)
Definition: native.c:1385
char * crm_strdup_printf(char const *format,...) __attribute__((__format__(__printf__
GList * GListPtr
Definition: crm.h:214
#define pcmk__config_warn(fmt...)
Definition: internal.h:100
char * id
Definition: pe_types.h:305
gboolean group_unpack(pe_resource_t *rsc, pe_working_set_t *data_set)
Definition: group.c:22