This source file includes following definitions.
- pcmk__corosync_uuid
- node_name_is_valid
- pcmk__corosync_name
- pcmk__corosync_disconnect
- quorum_dispatch_cb
- quorum_notification_cb
- pcmk__corosync_quorum_connect
- pcmk__corosync_connect
- pcmk__corosync_is_active
- pcmk__corosync_is_peer_active
- pcmk__corosync_add_nodes
- pcmk__corosync_cluster_name
- pcmk__corosync_has_nodelist
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11
12 #include <arpa/inet.h>
13 #include <inttypes.h>
14 #include <netdb.h>
15 #include <netinet/in.h>
16 #include <stdbool.h>
17 #include <sys/socket.h>
18 #include <sys/utsname.h>
19
20 #include <bzlib.h>
21 #include <corosync/cfg.h>
22 #include <corosync/cmap.h>
23 #include <corosync/corodefs.h>
24 #include <corosync/corotypes.h>
25 #include <corosync/hdb.h>
26 #include <corosync/quorum.h>
27 #include <qb/qbipcc.h>
28 #include <qb/qbutil.h>
29
30 #include <crm/cluster/internal.h>
31 #include <crm/common/ipc.h>
32 #include <crm/common/ipc_internal.h>
33 #include <crm/common/mainloop.h>
34 #include <crm/common/xml.h>
35
36 #include "crmcluster_private.h"
37
38 static quorum_handle_t pcmk_quorum_handle = 0;
39
40 static gboolean (*quorum_app_callback)(unsigned long long seq,
41 gboolean quorate) = NULL;
42
43
44
45
46
47
48
49
50
51
52 char *
53 pcmk__corosync_uuid(const pcmk__node_status_t *node)
54 {
55 pcmk__assert(pcmk_get_cluster_layer() == pcmk_cluster_layer_corosync);
56
57 if (node != NULL) {
58 if (node->cluster_layer_id > 0) {
59 return crm_strdup_printf("%" PRIu32, node->cluster_layer_id);
60 } else {
61 crm_info("Node %s is not yet known by Corosync", node->name);
62 }
63 }
64 return NULL;
65 }
66
67 static bool
68 node_name_is_valid(const char *key, const char *name)
69 {
70 int octet;
71
72 if (name == NULL) {
73 crm_trace("%s is empty", key);
74 return false;
75
76 } else if (sscanf(name, "%d.%d.%d.%d", &octet, &octet, &octet, &octet) == 4) {
77 crm_trace("%s contains an IPv4 address (%s), ignoring", key, name);
78 return false;
79
80 } else if (strstr(name, ":") != NULL) {
81 crm_trace("%s contains an IPv6 address (%s), ignoring", key, name);
82 return false;
83 }
84 crm_trace("'%s: %s' is valid", key, name);
85 return true;
86 }
87
88
89
90
91
92
93
94
95
96
97
98
99
100 char *
101 pcmk__corosync_name(uint64_t cmap_handle, uint32_t nodeid)
102 {
103
104
105 int lpc = 0;
106 cs_error_t rc = CS_OK;
107 int retries = 0;
108 char *name = NULL;
109 cmap_handle_t local_handle = 0;
110 int fd = -1;
111 uid_t found_uid = 0;
112 gid_t found_gid = 0;
113 pid_t found_pid = 0;
114 int rv;
115
116 if (nodeid == 0) {
117 nodeid = pcmk__cpg_local_nodeid(0);
118 }
119
120 if (cmap_handle == 0 && local_handle == 0) {
121 retries = 0;
122 crm_trace("Initializing CMAP connection");
123 do {
124 rc = pcmk__init_cmap(&local_handle);
125 if (rc != CS_OK) {
126 retries++;
127 crm_debug("API connection setup failed: %s. Retrying in %ds", cs_strerror(rc),
128 retries);
129 sleep(retries);
130 }
131
132 } while (retries < 5 && rc != CS_OK);
133
134 if (rc != CS_OK) {
135 crm_warn("Could not connect to Cluster Configuration Database API, error %s",
136 cs_strerror(rc));
137 local_handle = 0;
138 }
139 }
140
141 if (cmap_handle == 0) {
142 cmap_handle = local_handle;
143
144 rc = cmap_fd_get(cmap_handle, &fd);
145 if (rc != CS_OK) {
146 crm_err("Could not obtain the CMAP API connection: %s (%d)",
147 cs_strerror(rc), rc);
148 goto bail;
149 }
150
151
152 if (!(rv = crm_ipc_is_authentic_process(fd, (uid_t) 0,(gid_t) 0, &found_pid,
153 &found_uid, &found_gid))) {
154 crm_err("CMAP provider is not authentic:"
155 " process %lld (uid: %lld, gid: %lld)",
156 (long long) PCMK__SPECIAL_PID_AS_0(found_pid),
157 (long long) found_uid, (long long) found_gid);
158 goto bail;
159 } else if (rv < 0) {
160 crm_err("Could not verify authenticity of CMAP provider: %s (%d)",
161 strerror(-rv), -rv);
162 goto bail;
163 }
164 }
165
166 while (name == NULL && cmap_handle != 0) {
167 uint32_t id = 0;
168 char *key = NULL;
169
170 key = crm_strdup_printf("nodelist.node.%d.nodeid", lpc);
171 rc = cmap_get_uint32(cmap_handle, key, &id);
172 crm_trace("Checking %u vs %u from %s", nodeid, id, key);
173 free(key);
174
175 if (rc != CS_OK) {
176 break;
177 }
178
179 if (nodeid == id) {
180 crm_trace("Searching for node name for %u in nodelist.node.%d %s",
181 nodeid, lpc, pcmk__s(name, "<null>"));
182 if (name == NULL) {
183 key = crm_strdup_printf("nodelist.node.%d.name", lpc);
184 cmap_get_string(cmap_handle, key, &name);
185 crm_trace("%s = %s", key, pcmk__s(name, "<null>"));
186 free(key);
187 }
188 if (name == NULL) {
189 key = crm_strdup_printf("nodelist.node.%d.ring0_addr", lpc);
190 cmap_get_string(cmap_handle, key, &name);
191 crm_trace("%s = %s", key, pcmk__s(name, "<null>"));
192
193 if (!node_name_is_valid(key, name)) {
194 free(name);
195 name = NULL;
196 }
197 free(key);
198 }
199 break;
200 }
201
202 lpc++;
203 }
204
205 bail:
206 if(local_handle) {
207 cmap_finalize(local_handle);
208 }
209
210 if (name == NULL) {
211 crm_info("Unable to get node name for nodeid %u", nodeid);
212 }
213 return name;
214 }
215
216
217
218
219
220
221
222 void
223 pcmk__corosync_disconnect(pcmk_cluster_t *cluster)
224 {
225 pcmk__cpg_disconnect(cluster);
226
227 if (pcmk_quorum_handle != 0) {
228 quorum_finalize(pcmk_quorum_handle);
229 pcmk_quorum_handle = 0;
230 }
231 crm_notice("Disconnected from Corosync");
232 }
233
234
235
236
237
238
239
240
241
242 static int
243 quorum_dispatch_cb(gpointer user_data)
244 {
245 int rc = quorum_dispatch(pcmk_quorum_handle, CS_DISPATCH_ALL);
246
247 if (rc < 0) {
248 crm_err("Connection to the Quorum API failed: %d", rc);
249 quorum_finalize(pcmk_quorum_handle);
250 pcmk_quorum_handle = 0;
251 return -1;
252 }
253 return 0;
254 }
255
256
257
258
259
260
261
262
263
264
265
266 static void
267 quorum_notification_cb(quorum_handle_t handle, uint32_t quorate,
268 uint64_t ring_id, uint32_t view_list_entries,
269 uint32_t *view_list)
270 {
271 int i;
272 GHashTableIter iter;
273 pcmk__node_status_t *node = NULL;
274 static gboolean init_phase = TRUE;
275
276 bool is_quorate = (quorate != 0);
277 bool was_quorate = pcmk__cluster_has_quorum();
278
279 if (is_quorate && !was_quorate) {
280 crm_notice("Quorum acquired " QB_XS " membership=%" PRIu64
281 " members=%" PRIu32,
282 ring_id, view_list_entries);
283 pcmk__cluster_set_quorum(true);
284
285 } else if (!is_quorate && was_quorate) {
286 crm_warn("Quorum lost " QB_XS " membership=%" PRIu64 " members=" PRIu32,
287 ring_id, view_list_entries);
288 pcmk__cluster_set_quorum(false);
289
290 } else {
291 crm_info("Quorum %s " QB_XS " membership=%" PRIu64 " members=%" PRIu32,
292 (is_quorate? "retained" : "still lost"), ring_id,
293 view_list_entries);
294 }
295
296 if (view_list_entries == 0 && init_phase) {
297 crm_info("Corosync membership is still forming, ignoring");
298 return;
299 }
300
301 init_phase = FALSE;
302
303
304
305 g_hash_table_iter_init(&iter, pcmk__peer_cache);
306 while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &node)) {
307 node->membership_id = 0;
308 }
309
310
311 for (i = 0; i < view_list_entries; i++) {
312 uint32_t id = view_list[i];
313
314 crm_debug("Member[%d] %u ", i, id);
315
316
317 node = pcmk__get_node(id, NULL, NULL, pcmk__node_search_cluster_member);
318 if (node->name == NULL) {
319 char *name = pcmk__corosync_name(0, id);
320
321 crm_info("Obtaining name for new node %u", id);
322 node = pcmk__get_node(id, name, NULL,
323 pcmk__node_search_cluster_member);
324 free(name);
325 }
326
327
328 pcmk__update_peer_state(__func__, node, PCMK_VALUE_MEMBER, ring_id);
329 }
330
331
332 pcmk__reap_unseen_nodes(ring_id);
333
334 if (quorum_app_callback) {
335 quorum_app_callback(ring_id, is_quorate);
336 }
337 }
338
339
340
341
342
343
344
345
346 void
347 pcmk__corosync_quorum_connect(gboolean (*dispatch)(unsigned long long,
348 gboolean),
349 void (*destroy)(gpointer))
350 {
351 cs_error_t rc;
352 int fd = 0;
353 int quorate = 0;
354 uint32_t quorum_type = 0;
355 struct mainloop_fd_callbacks quorum_fd_callbacks;
356 uid_t found_uid = 0;
357 gid_t found_gid = 0;
358 pid_t found_pid = 0;
359 int rv;
360
361 quorum_fd_callbacks.dispatch = quorum_dispatch_cb;
362 quorum_fd_callbacks.destroy = destroy;
363
364 crm_debug("Configuring Pacemaker to obtain quorum from Corosync");
365
366 {
367 #if 0
368
369 quorum_model_v0_data_t quorum_model_data = {
370 .model = QUORUM_MODEL_V0,
371 .quorum_notify_fn = quorum_notification_cb,
372 };
373
374 rc = quorum_model_initialize(&pcmk_quorum_handle, QUORUM_MODEL_V0,
375 (quorum_model_data_t *) &quorum_model_data,
376 &quorum_type, NULL);
377 #else
378 quorum_callbacks_t quorum_callbacks = {
379 .quorum_notify_fn = quorum_notification_cb,
380 };
381
382 rc = quorum_initialize(&pcmk_quorum_handle, &quorum_callbacks,
383 &quorum_type);
384 #endif
385 }
386
387 if (rc != CS_OK) {
388 crm_err("Could not connect to the Quorum API: %s (%d)",
389 cs_strerror(rc), rc);
390 goto bail;
391
392 } else if (quorum_type != QUORUM_SET) {
393 crm_err("Corosync quorum is not configured");
394 goto bail;
395 }
396
397 rc = quorum_fd_get(pcmk_quorum_handle, &fd);
398 if (rc != CS_OK) {
399 crm_err("Could not obtain the Quorum API connection: %s (%d)",
400 strerror(rc), rc);
401 goto bail;
402 }
403
404
405 if (!(rv = crm_ipc_is_authentic_process(fd, (uid_t) 0,(gid_t) 0, &found_pid,
406 &found_uid, &found_gid))) {
407 crm_err("Quorum provider is not authentic:"
408 " process %lld (uid: %lld, gid: %lld)",
409 (long long) PCMK__SPECIAL_PID_AS_0(found_pid),
410 (long long) found_uid, (long long) found_gid);
411 rc = CS_ERR_ACCESS;
412 goto bail;
413 } else if (rv < 0) {
414 crm_err("Could not verify authenticity of Quorum provider: %s (%d)",
415 strerror(-rv), -rv);
416 rc = CS_ERR_ACCESS;
417 goto bail;
418 }
419
420 rc = quorum_getquorate(pcmk_quorum_handle, &quorate);
421 if (rc != CS_OK) {
422 crm_err("Could not obtain the current Quorum API state: %d", rc);
423 goto bail;
424 }
425
426 if (quorate) {
427 crm_notice("Quorum acquired");
428 } else {
429 crm_warn("No quorum");
430 }
431 quorum_app_callback = dispatch;
432 pcmk__cluster_set_quorum(quorate != 0);
433
434 rc = quorum_trackstart(pcmk_quorum_handle, CS_TRACK_CHANGES | CS_TRACK_CURRENT);
435 if (rc != CS_OK) {
436 crm_err("Could not setup Quorum API notifications: %d", rc);
437 goto bail;
438 }
439
440 mainloop_add_fd("quorum", G_PRIORITY_HIGH, fd, dispatch, &quorum_fd_callbacks);
441
442 pcmk__corosync_add_nodes(NULL);
443
444 bail:
445 if (rc != CS_OK) {
446 quorum_finalize(pcmk_quorum_handle);
447 }
448 }
449
450
451
452
453
454
455
456
457
458 int
459 pcmk__corosync_connect(pcmk_cluster_t *cluster)
460 {
461 const enum pcmk_cluster_layer cluster_layer = pcmk_get_cluster_layer();
462 const char *cluster_layer_s = pcmk_cluster_layer_text(cluster_layer);
463 int rc = pcmk_rc_ok;
464
465 pcmk__cluster_init_node_caches();
466
467 if (cluster_layer != pcmk_cluster_layer_corosync) {
468 crm_err("Invalid cluster layer: %s " QB_XS " cluster_layer=%d",
469 cluster_layer_s, cluster_layer);
470 return EINVAL;
471 }
472
473 rc = pcmk__cpg_connect(cluster);
474 if (rc != pcmk_rc_ok) {
475
476 return rc;
477 }
478 crm_info("Connection to %s established", cluster_layer_s);
479
480 cluster->priv->node_id = pcmk__cpg_local_nodeid(0);
481 if (cluster->priv->node_id == 0) {
482 crm_err("Could not determine local node ID");
483 return ENXIO;
484 }
485
486 cluster->priv->node_name = pcmk__cluster_node_name(0);
487 if (cluster->priv->node_name == NULL) {
488 crm_err("Could not determine local node name");
489 return ENXIO;
490 }
491
492
493 pcmk__get_node(cluster->priv->node_id, cluster->priv->node_name, NULL,
494 pcmk__node_search_cluster_member);
495
496 return pcmk_rc_ok;
497 }
498
499
500
501
502
503
504
505 bool
506 pcmk__corosync_is_active(void)
507 {
508 cmap_handle_t handle;
509 int rc = pcmk__init_cmap(&handle);
510
511 if (rc == CS_OK) {
512 cmap_finalize(handle);
513 return true;
514 }
515
516 crm_info("Failed to initialize the cmap API: %s (%d)",
517 pcmk__cs_err_str(rc), rc);
518 return false;
519 }
520
521
522
523
524
525
526
527
528
529 bool
530 pcmk__corosync_is_peer_active(const pcmk__node_status_t *node)
531 {
532 if (node == NULL) {
533 crm_trace("Corosync peer inactive: NULL");
534 return false;
535 }
536 if (!pcmk__str_eq(node->state, PCMK_VALUE_MEMBER, pcmk__str_none)) {
537 crm_trace("Corosync peer %s inactive: state=%s",
538 node->name, node->state);
539 return false;
540 }
541 if (!pcmk_is_set(node->processes, crm_proc_cpg)) {
542 crm_trace("Corosync peer %s inactive " QB_XS " processes=%.16" PRIx32,
543 node->name, node->processes);
544 return false;
545 }
546 return true;
547 }
548
549
550
551
552
553
554
555
556
557 bool
558 pcmk__corosync_add_nodes(xmlNode *xml_parent)
559 {
560 int lpc = 0;
561 cs_error_t rc = CS_OK;
562 int retries = 0;
563 bool any = false;
564 cmap_handle_t cmap_handle;
565 int fd = -1;
566 uid_t found_uid = 0;
567 gid_t found_gid = 0;
568 pid_t found_pid = 0;
569 int rv;
570
571 do {
572 rc = pcmk__init_cmap(&cmap_handle);
573 if (rc != CS_OK) {
574 retries++;
575 crm_debug("API connection setup failed: %s. Retrying in %ds", cs_strerror(rc),
576 retries);
577 sleep(retries);
578 }
579
580 } while (retries < 5 && rc != CS_OK);
581
582 if (rc != CS_OK) {
583 crm_warn("Could not connect to Cluster Configuration Database API, error %d", rc);
584 return false;
585 }
586
587 rc = cmap_fd_get(cmap_handle, &fd);
588 if (rc != CS_OK) {
589 crm_err("Could not obtain the CMAP API connection: %s (%d)",
590 cs_strerror(rc), rc);
591 goto bail;
592 }
593
594
595 if (!(rv = crm_ipc_is_authentic_process(fd, (uid_t) 0,(gid_t) 0, &found_pid,
596 &found_uid, &found_gid))) {
597 crm_err("CMAP provider is not authentic:"
598 " process %lld (uid: %lld, gid: %lld)",
599 (long long) PCMK__SPECIAL_PID_AS_0(found_pid),
600 (long long) found_uid, (long long) found_gid);
601 goto bail;
602 } else if (rv < 0) {
603 crm_err("Could not verify authenticity of CMAP provider: %s (%d)",
604 strerror(-rv), -rv);
605 goto bail;
606 }
607
608 pcmk__cluster_init_node_caches();
609 crm_trace("Initializing Corosync node list");
610 for (lpc = 0; TRUE; lpc++) {
611 uint32_t nodeid = 0;
612 char *name = NULL;
613 char *key = NULL;
614
615 key = crm_strdup_printf("nodelist.node.%d.nodeid", lpc);
616 rc = cmap_get_uint32(cmap_handle, key, &nodeid);
617 free(key);
618
619 if (rc != CS_OK) {
620 break;
621 }
622
623 name = pcmk__corosync_name(cmap_handle, nodeid);
624 if (name != NULL) {
625 GHashTableIter iter;
626 pcmk__node_status_t *node = NULL;
627
628 g_hash_table_iter_init(&iter, pcmk__peer_cache);
629 while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &node)) {
630 if ((node != NULL)
631 && (node->cluster_layer_id > 0)
632 && (node->cluster_layer_id != nodeid)
633 && pcmk__str_eq(node->name, name, pcmk__str_casei)) {
634
635 crm_crit("Nodes %" PRIu32 " and %" PRIu32 " share the "
636 "same name '%s': shutting down",
637 node->cluster_layer_id, nodeid, name);
638 crm_exit(CRM_EX_FATAL);
639 }
640 }
641 }
642
643 if (nodeid > 0 || name != NULL) {
644 crm_trace("Initializing node[%d] %u = %s", lpc, nodeid, name);
645 pcmk__get_node(nodeid, name, NULL, pcmk__node_search_cluster_member);
646 }
647
648 if (nodeid > 0 && name != NULL) {
649 any = true;
650
651 if (xml_parent) {
652 xmlNode *node = pcmk__xe_create(xml_parent, PCMK_XE_NODE);
653
654 crm_xml_add_ll(node, PCMK_XA_ID, (long long) nodeid);
655 crm_xml_add(node, PCMK_XA_UNAME, name);
656 }
657 }
658
659 free(name);
660 }
661 bail:
662 cmap_finalize(cmap_handle);
663 return any;
664 }
665
666
667
668
669
670
671
672 char *
673 pcmk__corosync_cluster_name(void)
674 {
675 cmap_handle_t handle;
676 char *cluster_name = NULL;
677 cs_error_t rc = CS_OK;
678 int fd = -1;
679 uid_t found_uid = 0;
680 gid_t found_gid = 0;
681 pid_t found_pid = 0;
682 int rv;
683
684 rc = pcmk__init_cmap(&handle);
685 if (rc != CS_OK) {
686 crm_info("Failed to initialize the cmap API: %s (%d)",
687 cs_strerror(rc), rc);
688 return NULL;
689 }
690
691 rc = cmap_fd_get(handle, &fd);
692 if (rc != CS_OK) {
693 crm_err("Could not obtain the CMAP API connection: %s (%d)",
694 cs_strerror(rc), rc);
695 goto bail;
696 }
697
698
699 if (!(rv = crm_ipc_is_authentic_process(fd, (uid_t) 0,(gid_t) 0, &found_pid,
700 &found_uid, &found_gid))) {
701 crm_err("CMAP provider is not authentic:"
702 " process %lld (uid: %lld, gid: %lld)",
703 (long long) PCMK__SPECIAL_PID_AS_0(found_pid),
704 (long long) found_uid, (long long) found_gid);
705 goto bail;
706 } else if (rv < 0) {
707 crm_err("Could not verify authenticity of CMAP provider: %s (%d)",
708 strerror(-rv), -rv);
709 goto bail;
710 }
711
712 rc = cmap_get_string(handle, "totem.cluster_name", &cluster_name);
713 if (rc != CS_OK) {
714 crm_info("Cannot get totem.cluster_name: %s (%d)", cs_strerror(rc), rc);
715
716 } else {
717 crm_debug("cmap totem.cluster_name = '%s'", cluster_name);
718 }
719
720 bail:
721 cmap_finalize(handle);
722 return cluster_name;
723 }
724
725
726
727
728
729
730
731 bool
732 pcmk__corosync_has_nodelist(void)
733 {
734 cs_error_t cs_rc = CS_OK;
735 int retries = 0;
736 cmap_handle_t cmap_handle;
737 cmap_iter_handle_t iter_handle;
738 char key_name[CMAP_KEYNAME_MAXLEN + 1];
739 int fd = -1;
740 uid_t found_uid = 0;
741 gid_t found_gid = 0;
742 pid_t found_pid = 0;
743 int rc = pcmk_ok;
744
745 static bool got_result = false;
746 static bool result = false;
747
748 if (got_result) {
749 return result;
750 }
751
752
753 do {
754 cs_rc = pcmk__init_cmap(&cmap_handle);
755 if (cs_rc != CS_OK) {
756 retries++;
757 crm_debug("CMAP connection failed: %s (rc=%d, retrying in %ds)",
758 cs_strerror(cs_rc), cs_rc, retries);
759 sleep(retries);
760 }
761 } while ((retries < 5) && (cs_rc != CS_OK));
762 if (cs_rc != CS_OK) {
763 crm_warn("Assuming Corosync does not have node list: "
764 "CMAP connection failed (%s) " QB_XS " rc=%d",
765 cs_strerror(cs_rc), cs_rc);
766 return false;
767 }
768
769
770 cs_rc = cmap_fd_get(cmap_handle, &fd);
771 if (cs_rc != CS_OK) {
772 crm_warn("Assuming Corosync does not have node list: "
773 "CMAP unusable (%s) " QB_XS " rc=%d",
774 cs_strerror(cs_rc), cs_rc);
775 goto bail;
776 }
777
778
779 rc = crm_ipc_is_authentic_process(fd, (uid_t) 0, (gid_t) 0,
780 &found_pid, &found_uid, &found_gid);
781 if (rc == 0) {
782 crm_warn("Assuming Corosync does not have node list: "
783 "CMAP provider is inauthentic "
784 QB_XS " pid=%lld uid=%lld gid=%lld",
785 (long long) PCMK__SPECIAL_PID_AS_0(found_pid),
786 (long long) found_uid, (long long) found_gid);
787 goto bail;
788 } else if (rc < 0) {
789 crm_warn("Assuming Corosync does not have node list: "
790 "Could not verify CMAP authenticity (%s) " QB_XS " rc=%d",
791 pcmk_strerror(rc), rc);
792 goto bail;
793 }
794
795
796 cs_rc = cmap_iter_init(cmap_handle, "nodelist", &iter_handle);
797 if (cs_rc != CS_OK) {
798 crm_warn("Assuming Corosync does not have node list: "
799 "CMAP not readable (%s) " QB_XS " rc=%d",
800 cs_strerror(cs_rc), cs_rc);
801 goto bail;
802 }
803
804 cs_rc = cmap_iter_next(cmap_handle, iter_handle, key_name, NULL, NULL);
805 if (cs_rc == CS_OK) {
806 result = true;
807 }
808
809 cmap_iter_finalize(cmap_handle, iter_handle);
810 got_result = true;
811 crm_debug("Corosync %s node list", (result? "has" : "does not have"));
812
813 bail:
814 cmap_finalize(cmap_handle);
815 return result;
816 }