This source file includes following definitions.
- attrd_create_attribute
- attrd_update_dampening
- attrd_add_value_xml
- attrd_clear_value_seen
- attrd_populate_attribute
- attrd_set_id
- attrd_nvpair_id
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11
12 #include <errno.h>
13 #include <stdbool.h>
14 #include <stdlib.h>
15 #include <glib.h>
16
17 #include <crm/common/logging.h>
18 #include <crm/common/results.h>
19 #include <crm/common/strings_internal.h>
20 #include <crm/common/xml.h>
21
22 #include "pacemaker-attrd.h"
23
24 static attribute_t *
25 attrd_create_attribute(xmlNode *xml)
26 {
27 int is_private = 0;
28 long long dampen = 0;
29 const char *name = crm_element_value(xml, PCMK__XA_ATTR_NAME);
30 const char *set_type = crm_element_value(xml, PCMK__XA_ATTR_SET_TYPE);
31 const char *dampen_s = crm_element_value(xml, PCMK__XA_ATTR_DAMPENING);
32 attribute_t *a = NULL;
33
34 if (set_type == NULL) {
35 set_type = PCMK_XE_INSTANCE_ATTRIBUTES;
36 }
37
38
39
40
41 crm_element_value_int(xml, PCMK__XA_ATTR_IS_PRIVATE, &is_private);
42 if (!is_private && !pcmk__str_any_of(set_type,
43 PCMK_XE_INSTANCE_ATTRIBUTES,
44 PCMK_XE_UTILIZATION, NULL)) {
45 crm_warn("Ignoring attribute %s with invalid set type %s",
46 pcmk__s(name, "(unidentified)"), set_type);
47 return NULL;
48 }
49
50 a = pcmk__assert_alloc(1, sizeof(attribute_t));
51
52 a->id = pcmk__str_copy(name);
53 a->set_type = pcmk__str_copy(set_type);
54 a->set_id = crm_element_value_copy(xml, PCMK__XA_ATTR_SET);
55 a->user = crm_element_value_copy(xml, PCMK__XA_ATTR_USER);
56 a->values = pcmk__strikey_table(NULL, attrd_free_attribute_value);
57
58 if (is_private) {
59 attrd_set_attr_flags(a, attrd_attr_is_private);
60 }
61
62 if (dampen_s != NULL) {
63 dampen = crm_get_msec(dampen_s);
64 }
65
66 if (dampen > 0) {
67 a->timeout_ms = (int) QB_MIN(dampen, INT_MAX);
68 a->timer = attrd_add_timer(a->id, a->timeout_ms, a);
69 } else if (dampen < 0) {
70 crm_warn("Ignoring invalid delay %s for attribute %s", dampen_s, a->id);
71 }
72
73 crm_trace("Created attribute %s with %s write delay and %s CIB user",
74 a->id,
75 ((dampen > 0)? pcmk__readable_interval(a->timeout_ms) : "no"),
76 pcmk__s(a->user, "default"));
77
78 g_hash_table_replace(attributes, a->id, a);
79 return a;
80 }
81
82 static int
83 attrd_update_dampening(attribute_t *a, xmlNode *xml, const char *attr)
84 {
85 const char *dvalue = crm_element_value(xml, PCMK__XA_ATTR_DAMPENING);
86 long long dampen = 0;
87
88 if (dvalue == NULL) {
89 crm_warn("Could not update %s: peer did not specify value for delay",
90 attr);
91 return EINVAL;
92 }
93
94 dampen = crm_get_msec(dvalue);
95 if (dampen < 0) {
96 crm_warn("Could not update %s: invalid delay value %dms (%s)",
97 attr, dampen, dvalue);
98 return EINVAL;
99 }
100
101 if (a->timeout_ms != dampen) {
102 mainloop_timer_del(a->timer);
103 a->timeout_ms = (int) QB_MIN(dampen, INT_MAX);
104 if (dampen > 0) {
105 a->timer = attrd_add_timer(attr, a->timeout_ms, a);
106 crm_info("Update attribute %s delay to %dms (%s)",
107 attr, dampen, dvalue);
108 } else {
109 a->timer = NULL;
110 crm_info("Update attribute %s to remove delay", attr);
111 }
112
113
114
115
116 attrd_write_or_elect_attribute(a);
117 }
118
119 return pcmk_rc_ok;
120 }
121
122 GHashTable *attributes = NULL;
123
124
125
126
127
128
129
130
131
132
133
134
135 xmlNode *
136 attrd_add_value_xml(xmlNode *parent, const attribute_t *a,
137 const attribute_value_t *v, bool force_write)
138 {
139 xmlNode *xml = pcmk__xe_create(parent, __func__);
140
141 crm_xml_add(xml, PCMK__XA_ATTR_NAME, a->id);
142 crm_xml_add(xml, PCMK__XA_ATTR_SET_TYPE, a->set_type);
143 crm_xml_add(xml, PCMK__XA_ATTR_SET, a->set_id);
144 crm_xml_add(xml, PCMK__XA_ATTR_USER, a->user);
145 crm_xml_add(xml, PCMK__XA_ATTR_HOST, v->nodename);
146
147
148
149
150
151
152
153 crm_xml_add(xml, PCMK__XA_ATTR_HOST_ID, attrd_get_node_xml_id(v->nodename));
154
155 crm_xml_add(xml, PCMK__XA_ATTR_VALUE, v->current);
156 crm_xml_add_int(xml, PCMK__XA_ATTR_DAMPENING,
157 pcmk__timeout_ms2s(a->timeout_ms));
158 crm_xml_add_int(xml, PCMK__XA_ATTR_IS_PRIVATE,
159 pcmk_is_set(a->flags, attrd_attr_is_private));
160 crm_xml_add_int(xml, PCMK__XA_ATTR_IS_REMOTE,
161 pcmk_is_set(v->flags, attrd_value_remote));
162 crm_xml_add_int(xml, PCMK__XA_ATTRD_IS_FORCE_WRITE, force_write);
163
164 return xml;
165 }
166
167 void
168 attrd_clear_value_seen(void)
169 {
170 GHashTableIter aIter;
171 GHashTableIter vIter;
172 attribute_t *a;
173 attribute_value_t *v = NULL;
174
175 g_hash_table_iter_init(&aIter, attributes);
176 while (g_hash_table_iter_next(&aIter, NULL, (gpointer *) & a)) {
177 g_hash_table_iter_init(&vIter, a->values);
178 while (g_hash_table_iter_next(&vIter, NULL, (gpointer *) & v)) {
179 attrd_clear_value_flags(v, attrd_value_from_peer);
180 }
181 }
182 }
183
184 attribute_t *
185 attrd_populate_attribute(xmlNode *xml, const char *attr)
186 {
187 attribute_t *a = NULL;
188 bool update_both = false;
189
190 const char *op = crm_element_value(xml, PCMK_XA_TASK);
191
192
193 update_both = pcmk__str_eq(op, PCMK__ATTRD_CMD_UPDATE_BOTH,
194 pcmk__str_null_matches);
195
196
197 a = g_hash_table_lookup(attributes, attr);
198 if (a == NULL) {
199 if (update_both || pcmk__str_eq(op, PCMK__ATTRD_CMD_UPDATE, pcmk__str_none)) {
200 a = attrd_create_attribute(xml);
201 if (a == NULL) {
202 return NULL;
203 }
204
205 } else {
206 crm_warn("Could not update %s: attribute not found", attr);
207 return NULL;
208 }
209 }
210
211
212 if (update_both || pcmk__str_eq(op, PCMK__ATTRD_CMD_UPDATE_DELAY, pcmk__str_none)) {
213 int rc = attrd_update_dampening(a, xml, attr);
214
215 if (rc != pcmk_rc_ok || !update_both) {
216 return NULL;
217 }
218 }
219
220 return a;
221 }
222
223
224
225
226
227
228
229
230
231
232 char *
233 attrd_set_id(const attribute_t *attr, const char *node_state_id)
234 {
235 char *set_id = NULL;
236
237 pcmk__assert((attr != NULL) && (node_state_id != NULL));
238
239 if (pcmk__str_empty(attr->set_id)) {
240
241
242
243
244
245
246 set_id = crm_strdup_printf("%s-%s", PCMK_XE_STATUS, node_state_id);
247 } else {
248
249
250
251
252
253
254
255 set_id = pcmk__str_copy(attr->set_id);
256 }
257 pcmk__xml_sanitize_id(set_id);
258 return set_id;
259 }
260
261
262
263
264
265
266
267
268
269
270 char *
271 attrd_nvpair_id(const attribute_t *attr, const char *node_state_id)
272 {
273 char *nvpair_id = NULL;
274
275 if (attr->set_id != NULL) {
276 nvpair_id = crm_strdup_printf("%s-%s", attr->set_id, attr->id);
277
278 } else {
279 nvpair_id = crm_strdup_printf(PCMK_XE_STATUS "-%s-%s",
280 node_state_id, attr->id);
281 }
282 pcmk__xml_sanitize_id(nvpair_id);
283 return nvpair_id;
284 }