This source file includes following definitions.
- ra_param_free
- metadata_free
- metadata_cache_new
- metadata_cache_free
- metadata_cache_reset
- valid_version_format
- metadata_cache_fini
- ra_version_from_xml
- ra_param_from_xml
- log_ra_ocf_version
- metadata_cache_update
- controld_get_rsc_metadata
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11
12 #include <stdio.h>
13 #include <glib.h>
14 #include <regex.h>
15
16 #include <crm/crm.h>
17 #include <crm/lrmd.h>
18
19 #include <pacemaker-controld.h>
20
21 #if ENABLE_VERSIONED_ATTRS
22 static regex_t *version_format_regex = NULL;
23 #endif
24
25 static void
26 ra_param_free(void *param)
27 {
28 if (param) {
29 struct ra_param_s *p = (struct ra_param_s *) param;
30
31 if (p->rap_name) {
32 free(p->rap_name);
33 }
34 free(param);
35 }
36 }
37
38 static void
39 metadata_free(void *metadata)
40 {
41 if (metadata) {
42 struct ra_metadata_s *md = (struct ra_metadata_s *) metadata;
43
44 if (md->ra_version) {
45 free(md->ra_version);
46 }
47 g_list_free_full(md->ra_params, ra_param_free);
48 free(metadata);
49 }
50 }
51
52 GHashTable *
53 metadata_cache_new()
54 {
55 return pcmk__strkey_table(free, metadata_free);
56 }
57
58 void
59 metadata_cache_free(GHashTable *mdc)
60 {
61 if (mdc) {
62 crm_trace("Destroying metadata cache with %d members", g_hash_table_size(mdc));
63 g_hash_table_destroy(mdc);
64 }
65 }
66
67 void
68 metadata_cache_reset(GHashTable *mdc)
69 {
70 if (mdc) {
71 crm_trace("Resetting metadata cache with %d members",
72 g_hash_table_size(mdc));
73 g_hash_table_remove_all(mdc);
74 }
75 }
76
77 #if ENABLE_VERSIONED_ATTRS
78 static gboolean
79 valid_version_format(const char *version)
80 {
81 if (version == NULL) {
82 return FALSE;
83 }
84
85 if (version_format_regex == NULL) {
86
87
88
89
90
91 const char *regex_string = "^[[:digit:]]+([.][[:digit:]]+)*$";
92
93 version_format_regex = calloc(1, sizeof(regex_t));
94 regcomp(version_format_regex, regex_string, REG_EXTENDED | REG_NOSUB);
95
96
97
98
99
100
101 CRM_CHECK(version_format_regex != NULL, return TRUE);
102 }
103
104 return regexec(version_format_regex, version, 0, NULL, 0) == 0;
105 }
106 #endif
107
108 void
109 metadata_cache_fini()
110 {
111 #if ENABLE_VERSIONED_ATTRS
112 if (version_format_regex) {
113 regfree(version_format_regex);
114 free(version_format_regex);
115 version_format_regex = NULL;
116 }
117 #endif
118 }
119
120 #if ENABLE_VERSIONED_ATTRS
121 static char *
122 ra_version_from_xml(xmlNode *metadata_xml, const lrmd_rsc_info_t *rsc)
123 {
124 const char *version = crm_element_value(metadata_xml, XML_ATTR_VERSION);
125
126 if (version == NULL) {
127 crm_debug("Metadata for %s:%s:%s does not specify a version",
128 rsc->standard, rsc->provider, rsc->type);
129 version = PCMK_DEFAULT_AGENT_VERSION;
130
131 } else if (!valid_version_format(version)) {
132 crm_notice("%s:%s:%s metadata version has unrecognized format",
133 rsc->standard, rsc->provider, rsc->type);
134 version = PCMK_DEFAULT_AGENT_VERSION;
135
136 } else {
137 crm_debug("Metadata for %s:%s:%s has version %s",
138 rsc->standard, rsc->provider, rsc->type, version);
139 }
140 return strdup(version);
141 }
142 #endif
143
144 static struct ra_param_s *
145 ra_param_from_xml(xmlNode *param_xml)
146 {
147 const char *param_name = crm_element_value(param_xml, "name");
148 struct ra_param_s *p;
149
150 p = calloc(1, sizeof(struct ra_param_s));
151 if (p == NULL) {
152 crm_crit("Could not allocate memory for resource metadata");
153 return NULL;
154 }
155
156 p->rap_name = strdup(param_name);
157 if (p->rap_name == NULL) {
158 crm_crit("Could not allocate memory for resource metadata");
159 free(p);
160 return NULL;
161 }
162
163 if (pcmk__xe_attr_is_true(param_xml, "reloadable")) {
164 controld_set_ra_param_flags(p, ra_param_reloadable);
165 }
166
167 if (pcmk__xe_attr_is_true(param_xml, "unique")) {
168 controld_set_ra_param_flags(p, ra_param_unique);
169 }
170
171 if (pcmk__xe_attr_is_true(param_xml, "private")) {
172 controld_set_ra_param_flags(p, ra_param_private);
173 }
174 return p;
175 }
176
177 static void
178 log_ra_ocf_version(const char *ra_key, const char *ra_ocf_version)
179 {
180 if (pcmk__str_empty(ra_ocf_version)) {
181 crm_warn("%s does not advertise OCF version supported", ra_key);
182
183 } else if (compare_version(ra_ocf_version, "2") >= 0) {
184 crm_warn("%s supports OCF version %s (this Pacemaker version supports "
185 PCMK_OCF_VERSION " and might not work properly with agent)",
186 ra_key, ra_ocf_version);
187
188 } else if (compare_version(ra_ocf_version, PCMK_OCF_VERSION) > 0) {
189 crm_info("%s supports OCF version %s (this Pacemaker version supports "
190 PCMK_OCF_VERSION " and might not use all agent features)",
191 ra_key, ra_ocf_version);
192
193 } else {
194 crm_debug("%s supports OCF version %s", ra_key, ra_ocf_version);
195 }
196 }
197
198 struct ra_metadata_s *
199 metadata_cache_update(GHashTable *mdc, lrmd_rsc_info_t *rsc,
200 const char *metadata_str)
201 {
202 char *key = NULL;
203 xmlNode *metadata = NULL;
204 xmlNode *match = NULL;
205 struct ra_metadata_s *md = NULL;
206 bool any_private_params = false;
207 bool ocf1_1 = false;
208
209 CRM_CHECK(mdc && rsc && metadata_str, return NULL);
210
211 key = crm_generate_ra_key(rsc->standard, rsc->provider, rsc->type);
212 if (!key) {
213 crm_crit("Could not allocate memory for resource metadata");
214 goto err;
215 }
216
217 metadata = string2xml(metadata_str);
218 if (!metadata) {
219 crm_err("Metadata for %s:%s:%s is not valid XML",
220 rsc->standard, rsc->provider, rsc->type);
221 goto err;
222 }
223
224 md = calloc(1, sizeof(struct ra_metadata_s));
225 if (md == NULL) {
226 crm_crit("Could not allocate memory for resource metadata");
227 goto err;
228 }
229
230 #if ENABLE_VERSIONED_ATTRS
231 md->ra_version = ra_version_from_xml(metadata, rsc);
232 #endif
233
234 if (strcmp(rsc->standard, PCMK_RESOURCE_CLASS_OCF) == 0) {
235 xmlChar *content = NULL;
236 xmlNode *version_element = first_named_child(metadata, "version");
237
238 if (version_element != NULL) {
239 content = xmlNodeGetContent(version_element);
240 }
241 log_ra_ocf_version(key, (const char *) content);
242 if (content != NULL) {
243 ocf1_1 = (compare_version((const char *) content, "1.1") >= 0);
244 xmlFree(content);
245 }
246 }
247
248
249 match = first_named_child(metadata, "actions");
250 for (match = first_named_child(match, "action"); match != NULL;
251 match = crm_next_same_xml(match)) {
252
253 const char *action_name = crm_element_value(match, "name");
254
255 if (pcmk__str_eq(action_name, CRMD_ACTION_RELOAD_AGENT,
256 pcmk__str_none)) {
257 if (ocf1_1) {
258 controld_set_ra_flags(md, key, ra_supports_reload_agent);
259 } else {
260 crm_notice("reload-agent action will not be used with %s "
261 "because it does not support OCF 1.1 or later", key);
262 }
263
264 } else if (!ocf1_1 && pcmk__str_eq(action_name, CRMD_ACTION_RELOAD,
265 pcmk__str_casei)) {
266 controld_set_ra_flags(md, key, ra_supports_legacy_reload);
267 }
268 }
269
270
271 match = first_named_child(metadata, "parameters");
272 for (match = first_named_child(match, "parameter"); match != NULL;
273 match = crm_next_same_xml(match)) {
274
275 const char *param_name = crm_element_value(match, "name");
276
277 if (param_name == NULL) {
278 crm_warn("Metadata for %s:%s:%s has parameter without a name",
279 rsc->standard, rsc->provider, rsc->type);
280 } else {
281 struct ra_param_s *p = ra_param_from_xml(match);
282
283 if (p == NULL) {
284 goto err;
285 }
286 if (pcmk_is_set(p->rap_flags, ra_param_private)) {
287 any_private_params = true;
288 }
289 md->ra_params = g_list_prepend(md->ra_params, p);
290 }
291 }
292
293
294
295
296
297
298 if (!any_private_params) {
299 for (GList *iter = md->ra_params; iter != NULL; iter = iter->next) {
300 struct ra_param_s *p = iter->data;
301
302 if (pcmk__str_any_of(p->rap_name, "password", "passwd", "user",
303 NULL)) {
304 controld_set_ra_param_flags(p, ra_param_private);
305 }
306 }
307 }
308
309 g_hash_table_replace(mdc, key, md);
310 free_xml(metadata);
311 return md;
312
313 err:
314 free(key);
315 free_xml(metadata);
316 metadata_free(md);
317 return NULL;
318 }
319
320
321
322
323
324
325
326
327
328
329
330
331 struct ra_metadata_s *
332 controld_get_rsc_metadata(lrm_state_t *lrm_state, lrmd_rsc_info_t *rsc,
333 uint32_t source)
334 {
335 struct ra_metadata_s *metadata = NULL;
336 char *metadata_str = NULL;
337 char *key = NULL;
338 int rc = pcmk_ok;
339
340 CRM_CHECK((lrm_state != NULL) && (rsc != NULL), return NULL);
341
342 if (pcmk_is_set(source, controld_metadata_from_cache)) {
343 key = crm_generate_ra_key(rsc->standard, rsc->provider, rsc->type);
344 if (key != NULL) {
345 metadata = g_hash_table_lookup(lrm_state->metadata_cache, key);
346 free(key);
347 }
348 if (metadata != NULL) {
349 return metadata;
350 }
351 }
352
353 if (!pcmk_is_set(source, controld_metadata_from_agent)) {
354 return NULL;
355 }
356
357
358
359
360
361
362
363
364
365
366
367
368
369 rc = lrm_state_get_metadata(lrm_state, rsc->standard, rsc->provider,
370 rsc->type, &metadata_str, 0);
371 if (rc != pcmk_ok) {
372 crm_warn("Failed to get metadata for %s (%s%s%s:%s): %s",
373 rsc->id, rsc->standard,
374 ((rsc->provider == NULL)? "" : ":"),
375 ((rsc->provider == NULL)? "" : rsc->provider),
376 rsc->type, pcmk_strerror(rc));
377 return NULL;
378 }
379
380 metadata = metadata_cache_update(lrm_state->metadata_cache, rsc,
381 metadata_str);
382 free(metadata_str);
383 if (metadata == NULL) {
384 crm_warn("Failed to update metadata for %s (%s%s%s:%s)",
385 rsc->id, rsc->standard, ((rsc->provider == NULL)? "" : ":"),
386 ((rsc->provider == NULL)? "" : rsc->provider), rsc->type);
387 }
388 return metadata;
389 }