1 /*
2 * Copyright 2022-2024 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 <libxml/tree.h> // xmlNode
13 #include <crm/common/nvpair.h>
14
15 /*!
16 * \internal
17 * \brief Check whether a node is online
18 *
19 * \param[in] node Node to check
20 *
21 * \return true if \p node is online, otherwise false
22 */
23 bool
24 pcmk_node_is_online(const pcmk_node_t *node)
/* ![[previous]](../icons/n_left.png)
![[next]](../icons/right.png)
![[first]](../icons/n_first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
25 {
26 return (node != NULL) && node->details->online;
27 }
28
29 /*!
30 * \internal
31 * \brief Check whether a node is pending
32 *
33 * Check whether a node is pending. A node is pending if it is a member of the
34 * cluster but not the controller group, which means it is in the process of
35 * either joining or leaving the cluster.
36 *
37 * \param[in] node Node to check
38 *
39 * \return true if \p node is pending, otherwise false
40 */
41 bool
42 pcmk_node_is_pending(const pcmk_node_t *node)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
43 {
44 return (node != NULL) && node->details->pending;
45 }
46
47 /*!
48 * \internal
49 * \brief Check whether a node is clean
50 *
51 * Check whether a node is clean. A node is clean if it is a cluster node or
52 * remote node that has been seen by the cluster at least once, or the
53 * startup-fencing cluster option is false; and the node, and its host if a
54 * guest or bundle node, are not scheduled to be fenced.
55 *
56 * \param[in] node Node to check
57 *
58 * \return true if \p node is clean, otherwise false
59 */
60 bool
61 pcmk_node_is_clean(const pcmk_node_t *node)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
62 {
63 return (node != NULL) && !(node->details->unclean);
64 }
65
66 /*!
67 * \internal
68 * \brief Check whether a node is shutting down
69 *
70 * \param[in] node Node to check
71 *
72 * \return true if \p node is shutting down, otherwise false
73 */
74 bool
75 pcmk_node_is_shutting_down(const pcmk_node_t *node)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
76 {
77 return (node != NULL) && node->details->shutdown;
78 }
79
80 /*!
81 * \internal
82 * \brief Check whether a node is in maintenance mode
83 *
84 * \param[in] node Node to check
85 *
86 * \return true if \p node is in maintenance mode, otherwise false
87 */
88 bool
89 pcmk_node_is_in_maintenance(const pcmk_node_t *node)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
90 {
91 return (node != NULL) && node->details->maintenance;
92 }
93
94 /*!
95 * \internal
96 * \brief Call a function for each resource active on a node
97 *
98 * Call a caller-supplied function with a caller-supplied argument for each
99 * resource that is active on a given node. If the function returns false, this
100 * function will return immediately without processing any remaining resources.
101 *
102 * \param[in] node Node to check
103 *
104 * \return Result of last call of \p fn (or false if none)
105 */
106 bool
107 pcmk_foreach_active_resource(pcmk_node_t *node,
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
108 bool (*fn)(pcmk_resource_t *, void *),
109 void *user_data)
110 {
111 bool result = false;
112
113 if ((node != NULL) && (fn != NULL)) {
114 for (GList *item = node->details->running_rsc; item != NULL;
115 item = item->next) {
116
117 result = fn((pcmk_resource_t *) item->data, user_data);
118 if (!result) {
119 break;
120 }
121 }
122 }
123 return result;
124 }
125
126 void
127 pcmk__xe_add_node(xmlNode *xml, const char *node, int nodeid)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
128 {
129 CRM_ASSERT(xml != NULL);
130
131 if (node != NULL) {
132 crm_xml_add(xml, PCMK__XA_ATTR_HOST, node);
133 }
134
135 if (nodeid > 0) {
136 crm_xml_add_int(xml, PCMK__XA_ATTR_HOST_ID, nodeid);
137 }
138 }
139
140 /*!
141 * \internal
142 * \brief Find a node by name in a list of nodes
143 *
144 * \param[in] nodes List of nodes (as pcmk_node_t*)
145 * \param[in] node_name Name of node to find
146 *
147 * \return Node from \p nodes that matches \p node_name if any, otherwise NULL
148 */
149 pcmk_node_t *
150 pcmk__find_node_in_list(const GList *nodes, const char *node_name)
/* ![[previous]](../icons/left.png)
![[next]](../icons/n_right.png)
![[first]](../icons/first.png)
![[last]](../icons/n_last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
151 {
152 if (node_name != NULL) {
153 for (const GList *iter = nodes; iter != NULL; iter = iter->next) {
154 pcmk_node_t *node = (pcmk_node_t *) iter->data;
155
156 if (pcmk__str_eq(node->details->uname, node_name,
157 pcmk__str_casei)) {
158 return node;
159 }
160 }
161 }
162 return NULL;
163 }