This source file includes following definitions.
- attrd_create_attribute
- attrd_update_dampening
- attrd_add_value_xml
- attrd_clear_value_seen
- attrd_populate_attribute
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/msg_xml.h>
18 #include <crm/common/logging.h>
19 #include <crm/common/results.h>
20 #include <crm/common/strings_internal.h>
21 #include <crm/common/xml.h>
22
23 #include "pacemaker-attrd.h"
24
25 static attribute_t *
26 attrd_create_attribute(xmlNode *xml)
27 {
28 int is_private = 0;
29 int dampen = 0;
30 const char *name = crm_element_value(xml, PCMK__XA_ATTR_NAME);
31 const char *set_type = crm_element_value(xml, PCMK__XA_ATTR_SET_TYPE);
32 const char *dampen_s = crm_element_value(xml, PCMK__XA_ATTR_DAMPENING);
33 attribute_t *a = NULL;
34
35 if (set_type == NULL) {
36 set_type = XML_TAG_ATTR_SETS;
37 }
38
39
40
41
42 crm_element_value_int(xml, PCMK__XA_ATTR_IS_PRIVATE, &is_private);
43 if ((is_private != 0)
44 && !pcmk__str_any_of(set_type, XML_TAG_ATTR_SETS, XML_TAG_UTILIZATION,
45 NULL)) {
46 crm_warn("Ignoring attribute %s with invalid set type %s",
47 pcmk__s(name, "(unidentified)"), set_type);
48 return NULL;
49 }
50
51 a = calloc(1, sizeof(attribute_t));
52 CRM_ASSERT(a != NULL);
53
54 a->is_private = is_private;
55 pcmk__str_update(&a->id, name);
56 pcmk__str_update(&a->set_type, set_type);
57
58 a->set_id = crm_element_value_copy(xml, PCMK__XA_ATTR_SET);
59 a->uuid = crm_element_value_copy(xml, PCMK__XA_ATTR_UUID);
60 a->values = pcmk__strikey_table(NULL, attrd_free_attribute_value);
61
62 a->user = crm_element_value_copy(xml, PCMK__XA_ATTR_USER);
63 crm_trace("Performing all %s operations as user '%s'", a->id, a->user);
64
65 if (dampen_s != NULL) {
66 dampen = crm_get_msec(dampen_s);
67 }
68 crm_trace("Created attribute %s with %s write delay", a->id,
69 (a->timeout_ms == 0)? "no" : pcmk__readable_interval(a->timeout_ms));
70
71 if(dampen > 0) {
72 a->timeout_ms = dampen;
73 a->timer = attrd_add_timer(a->id, a->timeout_ms, a);
74 } else if (dampen < 0) {
75 crm_warn("Ignoring invalid delay %s for attribute %s", dampen_s, a->id);
76 }
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 int 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 = dampen;
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 = create_xml_node(parent, __func__);
140
141 crm_xml_add(xml, PCMK__XA_ATTR_NAME, a->id);
142 crm_xml_add(xml, PCMK__XA_ATTR_SET, a->set_id);
143 crm_xml_add(xml, PCMK__XA_ATTR_UUID, a->uuid);
144 crm_xml_add(xml, PCMK__XA_ATTR_USER, a->user);
145 pcmk__xe_add_node(xml, v->nodename, v->nodeid);
146 if (v->is_remote != 0) {
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, a->is_private);
152 crm_xml_add_int(xml, PCMK__XA_ATTR_FORCE, force_write);
153
154 return xml;
155 }
156
157 void
158 attrd_clear_value_seen(void)
159 {
160 GHashTableIter aIter;
161 GHashTableIter vIter;
162 attribute_t *a;
163 attribute_value_t *v = NULL;
164
165 g_hash_table_iter_init(&aIter, attributes);
166 while (g_hash_table_iter_next(&aIter, NULL, (gpointer *) & a)) {
167 g_hash_table_iter_init(&vIter, a->values);
168 while (g_hash_table_iter_next(&vIter, NULL, (gpointer *) & v)) {
169 v->seen = FALSE;
170 crm_trace("Clear seen flag %s[%s] = %s.", a->id, v->nodename, v->current);
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 }