This source file includes following definitions.
- fencing_connect
- pcmk__output_cluster_status
- pcmk_status
- pcmk__status
- pcmk__output_simple_status
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11
12 #include <stdbool.h>
13 #include <stddef.h>
14 #include <stdint.h>
15
16 #include <crm/cib/internal.h>
17 #include <crm/common/output.h>
18 #include <crm/common/results.h>
19 #include <crm/fencing/internal.h>
20 #include <crm/stonith-ng.h>
21 #include <pacemaker.h>
22 #include <pacemaker-internal.h>
23
24 static stonith_t *
25 fencing_connect(void)
26 {
27 stonith_t *st = stonith_api_new();
28 int rc = pcmk_rc_ok;
29
30 if (st == NULL) {
31 return NULL;
32 }
33
34 rc = st->cmds->connect(st, crm_system_name, NULL);
35 if (rc == pcmk_rc_ok) {
36 return st;
37 } else {
38 stonith_api_delete(st);
39 return NULL;
40 }
41 }
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70 int
71 pcmk__output_cluster_status(pcmk__output_t *out, stonith_t *stonith, cib_t *cib,
72 xmlNode *current_cib,
73 enum pcmk_pacemakerd_state pcmkd_state,
74 enum pcmk__fence_history fence_history,
75 uint32_t show, uint32_t show_opts,
76 const char *only_node, const char *only_rsc,
77 const char *neg_location_prefix, bool simple_output)
78 {
79 xmlNode *cib_copy = copy_xml(current_cib);
80 stonith_history_t *stonith_history = NULL;
81 int history_rc = 0;
82 pe_working_set_t *data_set = NULL;
83 GList *unames = NULL;
84 GList *resources = NULL;
85
86 int rc = pcmk_rc_ok;
87
88 if (cli_config_update(&cib_copy, NULL, FALSE) == FALSE) {
89 cib__clean_up_connection(&cib);
90 free_xml(cib_copy);
91 rc = pcmk_rc_schema_validation;
92 out->err(out, "Upgrade failed: %s", pcmk_rc_str(rc));
93 return rc;
94 }
95
96
97 if (fence_history != pcmk__fence_history_none) {
98 history_rc = pcmk__get_fencing_history(stonith, &stonith_history,
99 fence_history);
100 }
101
102 data_set = pe_new_working_set();
103 CRM_ASSERT(data_set != NULL);
104 pe__set_working_set_flags(data_set, pe_flag_no_compat);
105
106 data_set->input = cib_copy;
107 data_set->priv = out;
108 cluster_status(data_set);
109
110 if ((cib->variant == cib_native) && pcmk_is_set(show, pcmk_section_times)) {
111 if (pcmk__our_nodename == NULL) {
112
113 pcmk__query_node_name(out, 0, &pcmk__our_nodename, 0);
114 }
115 data_set->localhost = pcmk__our_nodename;
116 }
117
118
119
120
121 if (pcmk_is_set(show, pcmk_section_bans) || pcmk_is_set(show, pcmk_section_tickets)) {
122 pcmk__unpack_constraints(data_set);
123 }
124
125 unames = pe__build_node_name_list(data_set, only_node);
126 resources = pe__build_rsc_list(data_set, only_rsc);
127
128
129 if (data_set->dc_node == NULL) {
130 show |= pcmk_section_dc;
131 }
132
133 if (simple_output) {
134 rc = pcmk__output_simple_status(out, data_set);
135 } else {
136 out->message(out, "cluster-status",
137 data_set, pcmkd_state, pcmk_rc2exitc(history_rc),
138 stonith_history, fence_history, show, show_opts,
139 neg_location_prefix, unames, resources);
140 }
141
142 g_list_free_full(unames, free);
143 g_list_free_full(resources, free);
144
145 stonith_history_free(stonith_history);
146 stonith_history = NULL;
147 pe_free_working_set(data_set);
148 return rc;
149 }
150
151 int
152 pcmk_status(xmlNodePtr *xml)
153 {
154 cib_t *cib = NULL;
155 pcmk__output_t *out = NULL;
156 int rc = pcmk_rc_ok;
157
158 uint32_t show_opts = pcmk_show_pending | pcmk_show_inactive_rscs | pcmk_show_timing;
159
160 cib = cib_new();
161
162 if (cib == NULL) {
163 return pcmk_rc_cib_corrupt;
164 }
165
166 rc = pcmk__xml_output_new(&out, xml);
167 if (rc != pcmk_rc_ok) {
168 cib_delete(cib);
169 return rc;
170 }
171
172 pcmk__register_lib_messages(out);
173 pe__register_messages(out);
174 stonith__register_messages(out);
175
176 rc = pcmk__status(out, cib, pcmk__fence_history_full, pcmk_section_all,
177 show_opts, NULL, NULL, NULL, false, 0);
178 pcmk__xml_output_finish(out, xml);
179
180 cib_delete(cib);
181 return rc;
182 }
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219 int
220 pcmk__status(pcmk__output_t *out, cib_t *cib,
221 enum pcmk__fence_history fence_history, uint32_t show,
222 uint32_t show_opts, const char *only_node, const char *only_rsc,
223 const char *neg_location_prefix, bool simple_output,
224 unsigned int timeout_ms)
225 {
226 xmlNode *current_cib = NULL;
227 int rc = pcmk_rc_ok;
228 stonith_t *stonith = NULL;
229 enum pcmk_pacemakerd_state pcmkd_state = pcmk_pacemakerd_state_invalid;
230 time_t last_updated = 0;
231
232 if (cib == NULL) {
233 return ENOTCONN;
234 }
235
236 if (cib->variant == cib_native) {
237 rc = pcmk__pacemakerd_status(out, crm_system_name, timeout_ms, false,
238 &pcmkd_state);
239 if (rc != pcmk_rc_ok) {
240 return rc;
241 }
242
243 last_updated = time(NULL);
244
245 switch (pcmkd_state) {
246 case pcmk_pacemakerd_state_running:
247 case pcmk_pacemakerd_state_shutting_down:
248 case pcmk_pacemakerd_state_remote:
249
250
251
252 break;
253 default:
254
255 out->message(out, "pacemakerd-health",
256 NULL, pcmkd_state, NULL, last_updated);
257 return rc;
258 }
259
260 if (fence_history != pcmk__fence_history_none) {
261 stonith = fencing_connect();
262 }
263 }
264
265 rc = cib__signon_query(out, &cib, ¤t_cib);
266 if (rc != pcmk_rc_ok) {
267 if (pcmkd_state != pcmk_pacemakerd_state_invalid) {
268
269 out->message(out, "pacemakerd-health",
270 NULL, pcmkd_state, NULL, last_updated);
271 }
272 goto done;
273 }
274
275 rc = pcmk__output_cluster_status(out, stonith, cib, current_cib,
276 pcmkd_state, fence_history, show,
277 show_opts, only_node, only_rsc,
278 neg_location_prefix, simple_output);
279 if (rc != pcmk_rc_ok) {
280 out->err(out, "Error outputting status info from the fencer or CIB");
281 }
282
283 done:
284 stonith_api_delete(stonith);
285 free_xml(current_cib);
286 return pcmk_rc_ok;
287 }
288
289
290
291
292 int
293 pcmk__output_simple_status(pcmk__output_t *out,
294 const pe_working_set_t *data_set)
295 {
296 int nodes_online = 0;
297 int nodes_standby = 0;
298 int nodes_maintenance = 0;
299 GString *offline_nodes = NULL;
300 bool no_dc = false;
301 bool offline = false;
302 bool has_warnings = false;
303
304 if (data_set->dc_node == NULL) {
305 has_warnings = true;
306 no_dc = true;
307 }
308
309 for (GList *iter = data_set->nodes; iter != NULL; iter = iter->next) {
310 pe_node_t *node = (pe_node_t *) iter->data;
311
312 if (node->details->standby && node->details->online) {
313 nodes_standby++;
314 } else if (node->details->maintenance && node->details->online) {
315 nodes_maintenance++;
316 } else if (node->details->online) {
317 nodes_online++;
318 } else {
319 pcmk__add_word(&offline_nodes, 1024, "offline node:");
320 pcmk__add_word(&offline_nodes, 0, pe__node_name(node));
321 has_warnings = true;
322 offline = true;
323 }
324 }
325
326 if (has_warnings) {
327 out->info(out, "CLUSTER WARN: %s%s%s",
328 no_dc ? "No DC" : "",
329 no_dc && offline ? ", " : "",
330 (offline? (const char *) offline_nodes->str : ""));
331
332 if (offline_nodes != NULL) {
333 g_string_free(offline_nodes, TRUE);
334 }
335
336 } else {
337 char *nodes_standby_s = NULL;
338 char *nodes_maint_s = NULL;
339
340 if (nodes_standby > 0) {
341 nodes_standby_s = crm_strdup_printf(", %d standby node%s", nodes_standby,
342 pcmk__plural_s(nodes_standby));
343 }
344
345 if (nodes_maintenance > 0) {
346 nodes_maint_s = crm_strdup_printf(", %d maintenance node%s",
347 nodes_maintenance,
348 pcmk__plural_s(nodes_maintenance));
349 }
350
351 out->info(out, "CLUSTER OK: %d node%s online%s%s, "
352 "%d resource instance%s configured",
353 nodes_online, pcmk__plural_s(nodes_online),
354 nodes_standby_s != NULL ? nodes_standby_s : "",
355 nodes_maint_s != NULL ? nodes_maint_s : "",
356 data_set->ninstances, pcmk__plural_s(data_set->ninstances));
357
358 free(nodes_standby_s);
359 free(nodes_maint_s);
360 }
361
362 if (has_warnings) {
363 return pcmk_rc_error;
364 } else {
365 return pcmk_rc_ok;
366 }
367
368 }