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 pcmk__xe_add_node(xml, v->nodename, v->nodeid);
146 if (pcmk_is_set(v->flags, attrd_value_remote)) {
147 crm_xml_add_int(xml, PCMK__XA_ATTR_IS_REMOTE, 1);
148 }
149 crm_xml_add(xml, PCMK__XA_ATTR_VALUE, v->current);
150 crm_xml_add_int(xml, PCMK__XA_ATTR_DAMPENING, a->timeout_ms / 1000);
151 crm_xml_add_int(xml, PCMK__XA_ATTR_IS_PRIVATE,
152 pcmk_is_set(a->flags, attrd_attr_is_private));
153 crm_xml_add_int(xml, PCMK__XA_ATTRD_IS_FORCE_WRITE, force_write);
154
155 return xml;
156 }
157
158 void
159 attrd_clear_value_seen(void)
160 {
161 GHashTableIter aIter;
162 GHashTableIter vIter;
163 attribute_t *a;
164 attribute_value_t *v = NULL;
165
166 g_hash_table_iter_init(&aIter, attributes);
167 while (g_hash_table_iter_next(&aIter, NULL, (gpointer *) & a)) {
168 g_hash_table_iter_init(&vIter, a->values);
169 while (g_hash_table_iter_next(&vIter, NULL, (gpointer *) & v)) {
170 attrd_clear_value_flags(v, attrd_value_from_peer);
171 }
172 }
173 }
174
175 attribute_t *
176 attrd_populate_attribute(xmlNode *xml, const char *attr)
177 {
178 attribute_t *a = NULL;
179 bool update_both = false;
180
181 const char *op = crm_element_value(xml, PCMK_XA_TASK);
182
183
184 update_both = pcmk__str_eq(op, PCMK__ATTRD_CMD_UPDATE_BOTH,
185 pcmk__str_null_matches);
186
187
188 a = g_hash_table_lookup(attributes, attr);
189 if (a == NULL) {
190 if (update_both || pcmk__str_eq(op, PCMK__ATTRD_CMD_UPDATE, pcmk__str_none)) {
191 a = attrd_create_attribute(xml);
192 if (a == NULL) {
193 return NULL;
194 }
195
196 } else {
197 crm_warn("Could not update %s: attribute not found", attr);
198 return NULL;
199 }
200 }
201
202
203 if (update_both || pcmk__str_eq(op, PCMK__ATTRD_CMD_UPDATE_DELAY, pcmk__str_none)) {
204 int rc = attrd_update_dampening(a, xml, attr);
205
206 if (rc != pcmk_rc_ok || !update_both) {
207 return NULL;
208 }
209 }
210
211 return a;
212 }
213
214
215
216
217
218
219
220
221
222
223 char *
224 attrd_set_id(const attribute_t *attr, const char *node_state_id)
225 {
226 char *set_id = NULL;
227
228 pcmk__assert((attr != NULL) && (node_state_id != NULL));
229
230 if (attr->set_id == NULL) {
231
232
233
234
235
236
237 set_id = crm_strdup_printf("%s-%s", PCMK_XE_STATUS, node_state_id);
238 } else {
239
240
241
242
243
244
245
246 set_id = pcmk__str_copy(attr->set_id);
247 }
248 crm_xml_sanitize_id(set_id);
249 return set_id;
250 }
251
252
253
254
255
256
257
258
259
260
261 char *
262 attrd_nvpair_id(const attribute_t *attr, const char *node_state_id)
263 {
264 char *nvpair_id = NULL;
265
266 if (attr->set_id != NULL) {
267 nvpair_id = crm_strdup_printf("%s-%s", attr->set_id, attr->id);
268
269 } else {
270 nvpair_id = crm_strdup_printf(PCMK_XE_STATUS "-%s-%s",
271 node_state_id, attr->id);
272 }
273 crm_xml_sanitize_id(nvpair_id);
274 return nvpair_id;
275 }