pacemaker  2.0.3-4b1f869f0f
Scalable High-Availability cluster resource manager
group.c
Go to the documentation of this file.
1 /*
2  * Copyright 2004-2019 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 
13 #include <crm/pengine/rules.h>
14 #include <crm/pengine/status.h>
15 #include <crm/pengine/internal.h>
16 #include <crm/msg_xml.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  group_data->ordered = TRUE;
40  group_data->colocated = TRUE;
41 
42  if (group_ordered != NULL) {
43  crm_str_to_boolean(group_ordered, &(group_data->ordered));
44  }
45  if (group_colocated != NULL) {
46  crm_str_to_boolean(group_colocated, &(group_data->colocated));
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  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 #if 0
78  /* Bug #1287 */
79  crm_config_err("Group %s did not have any children", rsc->id);
80  return FALSE;
81 #else
82  crm_config_warn("Group %s did not have any children", rsc->id);
83  return TRUE;
84 #endif
85  }
86 
87  pe_rsc_trace(rsc, "Added %d children to resource %s...", group_data->num_children, rsc->id);
88 
89  return TRUE;
90 }
91 
92 gboolean
93 group_active(resource_t * rsc, gboolean all)
94 {
95  gboolean c_all = TRUE;
96  gboolean c_any = FALSE;
97  GListPtr gIter = rsc->children;
98 
99  for (; gIter != NULL; gIter = gIter->next) {
100  resource_t *child_rsc = (resource_t *) gIter->data;
101 
102  if (child_rsc->fns->active(child_rsc, all)) {
103  c_any = TRUE;
104  } else {
105  c_all = FALSE;
106  }
107  }
108 
109  if (c_any == FALSE) {
110  return FALSE;
111  } else if (all && c_all == FALSE) {
112  return FALSE;
113  }
114  return TRUE;
115 }
116 
117 static void
118 group_print_xml(resource_t * rsc, const char *pre_text, long options, void *print_data)
119 {
120  GListPtr gIter = rsc->children;
121  char *child_text = crm_concat(pre_text, " ", ' ');
122 
123  status_print("%s<group id=\"%s\" ", pre_text, rsc->id);
124  status_print("number_resources=\"%d\" ", g_list_length(rsc->children));
125  status_print(">\n");
126 
127  for (; gIter != NULL; gIter = gIter->next) {
128  resource_t *child_rsc = (resource_t *) gIter->data;
129 
130  child_rsc->fns->print(child_rsc, child_text, options, print_data);
131  }
132 
133  status_print("%s</group>\n", pre_text);
134  free(child_text);
135 }
136 
137 void
138 group_print(resource_t * rsc, const char *pre_text, long options, void *print_data)
139 {
140  char *child_text = NULL;
141  GListPtr gIter = rsc->children;
142 
143  if (pre_text == NULL) {
144  pre_text = " ";
145  }
146 
147  if (options & pe_print_xml) {
148  group_print_xml(rsc, pre_text, options, print_data);
149  return;
150  }
151 
152  child_text = crm_concat(pre_text, " ", ' ');
153 
154  status_print("%sResource Group: %s", pre_text ? pre_text : "", rsc->id);
155 
156  if (options & pe_print_html) {
157  status_print("\n<ul>\n");
158 
159  } else if ((options & pe_print_log) == 0) {
160  status_print("\n");
161  }
162 
163  if (options & pe_print_brief) {
164  print_rscs_brief(rsc->children, child_text, options, print_data, TRUE);
165 
166  } else {
167  for (; gIter != NULL; gIter = gIter->next) {
168  resource_t *child_rsc = (resource_t *) gIter->data;
169 
170  if (options & pe_print_html) {
171  status_print("<li>\n");
172  }
173  child_rsc->fns->print(child_rsc, child_text, options, print_data);
174  if (options & pe_print_html) {
175  status_print("</li>\n");
176  }
177  }
178  }
179 
180  if (options & pe_print_html) {
181  status_print("</ul>\n");
182  }
183  free(child_text);
184 }
185 
186 int
187 pe__group_xml(pcmk__output_t *out, va_list args)
188 {
189  unsigned int options = va_arg(args, unsigned int);
190  resource_t *rsc = va_arg(args, resource_t *);
191 
192  GListPtr gIter = rsc->children;
193  char *count = crm_itoa(g_list_length(gIter));
194 
195  int rc = pe__name_and_nvpairs_xml(out, true, "group", 2
196  , "id", rsc->id
197  , "number_resources", count);
198  free(count);
199  CRM_ASSERT(rc == 0);
200 
201  for (; gIter != NULL; gIter = gIter->next) {
202  resource_t *child_rsc = (resource_t *) gIter->data;
203 
204  out->message(out, crm_map_element_name(child_rsc->xml), options, child_rsc);
205  }
206 
208  return rc;
209 }
210 
211 int
212 pe__group_html(pcmk__output_t *out, va_list args)
213 {
214  unsigned int options = va_arg(args, unsigned int);
215  resource_t *rsc = va_arg(args, resource_t *);
216 
217  out->begin_list(out, NULL, NULL, "Resource Group: %s", rsc->id);
218 
219  if (options & pe_print_brief) {
220  pe__rscs_brief_output(out, rsc->children, options, TRUE);
221 
222  } else {
223  for (GListPtr gIter = rsc->children; gIter; gIter = gIter->next) {
224  resource_t *child_rsc = (resource_t *) gIter->data;
225  out->message(out, crm_map_element_name(child_rsc->xml), options, child_rsc);
226  }
227  }
228 
229  out->end_list(out);
230 
231  return 0;
232 }
233 
234 int
235 pe__group_text(pcmk__output_t *out, va_list args)
236 {
237  unsigned int options = va_arg(args, unsigned int);
238  resource_t *rsc = va_arg(args, resource_t *);
239 
240  out->begin_list(out, NULL, NULL, "Resource Group: %s", rsc->id);
241 
242  if (options & pe_print_brief) {
243  pe__rscs_brief_output(out, rsc->children, options, TRUE);
244 
245  } else {
246  for (GListPtr gIter = rsc->children; gIter; gIter = gIter->next) {
247  resource_t *child_rsc = (resource_t *) gIter->data;
248 
249  out->message(out, crm_map_element_name(child_rsc->xml), options, child_rsc);
250  }
251  }
252  out->end_list(out);
253 
254  return 0;
255 }
256 
257 void
259 {
260  CRM_CHECK(rsc != NULL, return);
261 
262  pe_rsc_trace(rsc, "Freeing %s", rsc->id);
263 
264  for (GListPtr gIter = rsc->children; gIter != NULL; gIter = gIter->next) {
265  resource_t *child_rsc = (resource_t *) gIter->data;
266 
267  CRM_ASSERT(child_rsc);
268  pe_rsc_trace(child_rsc, "Freeing child %s", child_rsc->id);
269  child_rsc->fns->free(child_rsc);
270  }
271 
272  pe_rsc_trace(rsc, "Freeing child list");
273  g_list_free(rsc->children);
274 
275  common_free(rsc);
276 }
277 
278 enum rsc_role_e
279 group_resource_state(const resource_t * rsc, gboolean current)
280 {
281  enum rsc_role_e group_role = RSC_ROLE_UNKNOWN;
282  GListPtr gIter = rsc->children;
283 
284  for (; gIter != NULL; gIter = gIter->next) {
285  resource_t *child_rsc = (resource_t *) gIter->data;
286  enum rsc_role_e role = child_rsc->fns->state(child_rsc, current);
287 
288  if (role > group_role) {
289  group_role = role;
290  }
291  }
292 
293  pe_rsc_trace(rsc, "%s role: %s", rsc->id, role2text(group_role));
294  return group_role;
295 }
GListPtr
GList * GListPtr
Definition: crm.h:215
group_unpack
gboolean group_unpack(resource_t *rsc, pe_working_set_t *data_set)
Definition: group.c:22
crm_str_eq
gboolean crm_str_eq(const char *a, const char *b, gboolean use_case)
Definition: strings.c:224
curses_internal.h
pe_print_log
@ pe_print_log
Definition: common.h:115
pe_print_xml
@ pe_print_xml
Definition: common.h:125
pe__rscs_brief_output
void pe__rscs_brief_output(pcmk__output_t *out, GListPtr rsc_list, long options, gboolean print_all)
Definition: native.c:1412
msg_xml.h
pe_resource_s::variant_opaque
void * variant_opaque
Definition: pe_types.h:304
group_print
void group_print(resource_t *rsc, const char *pre_text, long options, void *print_data)
Definition: group.c:138
common_free
void common_free(resource_t *rsc)
Definition: complex.c:779
crm_str_to_boolean
int crm_str_to_boolean(const char *s, int *ret)
Definition: strings.c:187
pe_resource_s::children
GListPtr children
Definition: pe_types.h:350
pe_resource_s::id
char * id
Definition: pe_types.h:294
rsc_role_e
rsc_role_e
Definition: common.h:98
CRM_CHECK
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:157
pe_print_brief
@ pe_print_brief
Definition: common.h:126
print_rscs_brief
void print_rscs_brief(GListPtr rsc_list, const char *pre_text, long options, void *print_data, gboolean print_all)
Definition: native.c:1332
internal.h
pe__group_text
int pe__group_text(pcmk__output_t *out, va_list args)
Definition: group.c:235
group_active
gboolean group_active(resource_t *rsc, gboolean all)
Definition: group.c:93
pe_resource_s::meta
GHashTable * meta
Definition: pe_types.h:346
group_free
void group_free(resource_t *rsc)
Definition: group.c:258
common_unpack
gboolean common_unpack(xmlNode *xml_obj, resource_t **rsc, resource_t *parent, pe_working_set_t *data_set)
Definition: complex.c:368
pcmk__output_s::message
int(* message)(pcmk__output_t *out, const char *message_id,...)
Definition: output.h:308
resource_object_functions_s::free
void(* free)(pe_resource_t *)
Definition: pe_types.h:54
XML_ATTR_ID
#define XML_ATTR_ID
Definition: msg_xml.h:96
XML_CIB_TAG_RESOURCE
#define XML_CIB_TAG_RESOURCE
Definition: msg_xml.h:174
pe_err
#define pe_err(fmt...)
Definition: internal.h:21
pe_resource_s::xml
xmlNode * xml
Definition: pe_types.h:296
pe_print_html
@ pe_print_html
Definition: common.h:116
resource_object_functions_s::print
void(* print)(pe_resource_t *, const char *, long, void *)
Definition: pe_types.h:50
pcmk__output_s::end_list
void(* end_list)(pcmk__output_t *out)
Definition: output.h:429
role2text
const char * role2text(enum rsc_role_e role)
Definition: common.c:338
RSC_ROLE_UNKNOWN
@ RSC_ROLE_UNKNOWN
Definition: common.h:99
resource_object_functions_s::state
enum rsc_role_e(* state)(const pe_resource_t *, gboolean)
Definition: pe_types.h:52
pe__group_html
int pe__group_html(pcmk__output_t *out, va_list args)
Definition: group.c:212
group_resource_state
enum rsc_role_e group_resource_state(const resource_t *rsc, gboolean current)
Definition: group.c:279
crm_xml_add
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:313
XML_RSC_ATTR_ORDERED
#define XML_RSC_ATTR_ORDERED
Definition: msg_xml.h:184
pe_working_set_s
Definition: pe_types.h:118
crm_element_value
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: nvpair.c:519
pcmk__output_s::begin_list
void(* begin_list)(pcmk__output_t *out, const char *singular_noun, const char *plural_noun, const char *format,...) G_GNUC_PRINTF(4
Definition: output.h:389
resource_object_functions_s::active
gboolean(* active)(pe_resource_t *, gboolean)
Definition: pe_types.h:51
rules.h
variant.h
pcmk__output_s
This structure contains everything that makes up a single output formatter.
Definition: output.h:150
crm_config_warn
#define crm_config_warn(fmt...)
Definition: crm_internal.h:180
pe_rsc_trace
#define pe_rsc_trace(rsc, fmt, args...)
Definition: internal.h:19
CRM_ASSERT
#define CRM_ASSERT(expr)
Definition: results.h:42
status_print
#define status_print(fmt, args...)
Definition: curses_internal.h:51
pe_resource_s
Definition: pe_types.h:293
pe__group_xml
int pe__group_xml(pcmk__output_t *out, va_list args)
Definition: group.c:187
pcmk__output_xml_pop_parent
void pcmk__output_xml_pop_parent(pcmk__output_t *out)
Definition: output_xml.c:384
XML_RSC_ATTR_INCARNATION
#define XML_RSC_ATTR_INCARNATION
Definition: msg_xml.h:186
crm_internal.h
status.h
Cluster status and scheduling.
pe__name_and_nvpairs_xml
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:15
pe_resource_s::fns
resource_object_functions_t * fns
Definition: pe_types.h:305
crm_config_err
#define crm_config_err(fmt...)
Definition: crm_internal.h:179