This source file includes following definitions.
- ra_param_free
- metadata_free
- metadata_cache_new
- metadata_cache_free
- metadata_cache_reset
- ra_param_from_xml
- log_ra_ocf_version
- controld_cache_metadata
- 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 static void
22 ra_param_free(void *param)
23 {
24 if (param) {
25 struct ra_param_s *p = (struct ra_param_s *) param;
26
27 if (p->rap_name) {
28 free(p->rap_name);
29 }
30 free(param);
31 }
32 }
33
34 static void
35 metadata_free(void *metadata)
36 {
37 if (metadata) {
38 struct ra_metadata_s *md = (struct ra_metadata_s *) metadata;
39
40 g_list_free_full(md->ra_params, ra_param_free);
41 free(metadata);
42 }
43 }
44
45 GHashTable *
46 metadata_cache_new(void)
47 {
48 return pcmk__strkey_table(free, metadata_free);
49 }
50
51 void
52 metadata_cache_free(GHashTable *mdc)
53 {
54 if (mdc) {
55 crm_trace("Destroying metadata cache with %d members", g_hash_table_size(mdc));
56 g_hash_table_destroy(mdc);
57 }
58 }
59
60 void
61 metadata_cache_reset(GHashTable *mdc)
62 {
63 if (mdc) {
64 crm_trace("Resetting metadata cache with %d members",
65 g_hash_table_size(mdc));
66 g_hash_table_remove_all(mdc);
67 }
68 }
69
70 static struct ra_param_s *
71 ra_param_from_xml(xmlNode *param_xml)
72 {
73 const char *param_name = crm_element_value(param_xml, PCMK_XA_NAME);
74 struct ra_param_s *p;
75
76 p = pcmk__assert_alloc(1, sizeof(struct ra_param_s));
77
78 p->rap_name = pcmk__str_copy(param_name);
79
80 if (pcmk__xe_attr_is_true(param_xml, PCMK_XA_RELOADABLE)) {
81 controld_set_ra_param_flags(p, ra_param_reloadable);
82 }
83
84 if (pcmk__xe_attr_is_true(param_xml, PCMK_XA_UNIQUE)) {
85 controld_set_ra_param_flags(p, ra_param_unique);
86 }
87
88 if (pcmk__xe_attr_is_true(param_xml, "private")) {
89 controld_set_ra_param_flags(p, ra_param_private);
90 }
91 return p;
92 }
93
94 static void
95 log_ra_ocf_version(const char *ra_key, const char *ra_ocf_version)
96 {
97 if (pcmk__str_empty(ra_ocf_version)) {
98 crm_warn("%s does not advertise OCF version supported", ra_key);
99
100 } else if (compare_version(ra_ocf_version, "2") >= 0) {
101 crm_warn("%s supports OCF version %s (this Pacemaker version supports "
102 PCMK_OCF_VERSION " and might not work properly with agent)",
103 ra_key, ra_ocf_version);
104
105 } else if (compare_version(ra_ocf_version, PCMK_OCF_VERSION) > 0) {
106 crm_info("%s supports OCF version %s (this Pacemaker version supports "
107 PCMK_OCF_VERSION " and might not use all agent features)",
108 ra_key, ra_ocf_version);
109
110 } else {
111 crm_debug("%s supports OCF version %s", ra_key, ra_ocf_version);
112 }
113 }
114
115 struct ra_metadata_s *
116 controld_cache_metadata(GHashTable *mdc, const lrmd_rsc_info_t *rsc,
117 const char *metadata_str)
118 {
119 char *key = NULL;
120 const char *reason = NULL;
121 xmlNode *metadata = NULL;
122 xmlNode *match = NULL;
123 struct ra_metadata_s *md = NULL;
124 bool any_private_params = false;
125 bool ocf1_1 = false;
126
127 CRM_CHECK(mdc && rsc && metadata_str, return NULL);
128
129 key = crm_generate_ra_key(rsc->standard, rsc->provider, rsc->type);
130 if (!key) {
131 reason = "Invalid resource agent standard or type";
132 goto err;
133 }
134
135 metadata = pcmk__xml_parse(metadata_str);
136 if (!metadata) {
137 reason = "Metadata is not valid XML";
138 goto err;
139 }
140
141 md = pcmk__assert_alloc(1, sizeof(struct ra_metadata_s));
142
143 if (strcmp(rsc->standard, PCMK_RESOURCE_CLASS_OCF) == 0) {
144 xmlChar *content = NULL;
145 xmlNode *version_element = pcmk__xe_first_child(metadata,
146 PCMK_XE_VERSION, NULL,
147 NULL);
148
149 if (version_element != NULL) {
150 content = xmlNodeGetContent(version_element);
151 }
152 log_ra_ocf_version(key, (const char *) content);
153 if (content != NULL) {
154 ocf1_1 = (compare_version((const char *) content, "1.1") >= 0);
155 xmlFree(content);
156 }
157 }
158
159
160 match = pcmk__xe_first_child(metadata, PCMK_XE_ACTIONS, NULL, NULL);
161 for (match = pcmk__xe_first_child(match, PCMK_XE_ACTION, NULL, NULL);
162 match != NULL; match = pcmk__xe_next_same(match)) {
163
164 const char *action_name = crm_element_value(match, PCMK_XA_NAME);
165
166 if (pcmk__str_eq(action_name, PCMK_ACTION_RELOAD_AGENT,
167 pcmk__str_none)) {
168 if (ocf1_1) {
169 controld_set_ra_flags(md, key, ra_supports_reload_agent);
170 } else {
171 crm_notice("reload-agent action will not be used with %s "
172 "because it does not support OCF 1.1 or later", key);
173 }
174
175 } else if (!ocf1_1 && pcmk__str_eq(action_name, PCMK_ACTION_RELOAD,
176 pcmk__str_casei)) {
177 controld_set_ra_flags(md, key, ra_supports_legacy_reload);
178 }
179 }
180
181
182 match = pcmk__xe_first_child(metadata, PCMK_XE_PARAMETERS, NULL, NULL);
183 for (match = pcmk__xe_first_child(match, PCMK_XE_PARAMETER, NULL, NULL);
184 match != NULL; match = pcmk__xe_next_same(match)) {
185
186 const char *param_name = crm_element_value(match, PCMK_XA_NAME);
187
188 if (param_name == NULL) {
189 crm_warn("Metadata for %s:%s:%s has parameter without a "
190 PCMK_XA_NAME, rsc->standard, rsc->provider, rsc->type);
191 } else {
192 struct ra_param_s *p = ra_param_from_xml(match);
193
194 if (p == NULL) {
195 reason = "Could not allocate memory";
196 goto err;
197 }
198 if (pcmk_is_set(p->rap_flags, ra_param_private)) {
199 any_private_params = true;
200 }
201 md->ra_params = g_list_prepend(md->ra_params, p);
202 }
203 }
204
205
206
207
208
209
210 if (!any_private_params) {
211 for (GList *iter = md->ra_params; iter != NULL; iter = iter->next) {
212 struct ra_param_s *p = iter->data;
213
214 if (pcmk__str_any_of(p->rap_name, "password", "passwd", "user",
215 NULL)) {
216 controld_set_ra_param_flags(p, ra_param_private);
217 }
218 }
219 }
220
221 g_hash_table_replace(mdc, key, md);
222 free_xml(metadata);
223 return md;
224
225 err:
226 crm_warn("Unable to update metadata for %s (%s%s%s:%s): %s",
227 rsc->id, rsc->standard, ((rsc->provider == NULL)? "" : ":"),
228 pcmk__s(rsc->provider, ""), rsc->type, reason);
229 free(key);
230 free_xml(metadata);
231 metadata_free(md);
232 return NULL;
233 }
234
235
236
237
238
239
240
241
242
243
244
245
246 struct ra_metadata_s *
247 controld_get_rsc_metadata(lrm_state_t *lrm_state, const lrmd_rsc_info_t *rsc,
248 uint32_t source)
249 {
250 struct ra_metadata_s *metadata = NULL;
251 char *metadata_str = NULL;
252 char *key = NULL;
253 int rc = pcmk_ok;
254
255 CRM_CHECK((lrm_state != NULL) && (rsc != NULL), return NULL);
256
257 if (pcmk_is_set(source, controld_metadata_from_cache)) {
258 key = crm_generate_ra_key(rsc->standard, rsc->provider, rsc->type);
259 if (key != NULL) {
260 metadata = g_hash_table_lookup(lrm_state->metadata_cache, key);
261 free(key);
262 }
263 if (metadata != NULL) {
264 crm_debug("Retrieved metadata for %s (%s%s%s:%s) from cache",
265 rsc->id, rsc->standard,
266 ((rsc->provider == NULL)? "" : ":"),
267 ((rsc->provider == NULL)? "" : rsc->provider),
268 rsc->type);
269 return metadata;
270 }
271 }
272
273 if (!pcmk_is_set(source, controld_metadata_from_agent)) {
274 return NULL;
275 }
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291 crm_debug("Retrieving metadata for %s (%s%s%s:%s) synchronously",
292 rsc->id, rsc->standard,
293 ((rsc->provider == NULL)? "" : ":"),
294 ((rsc->provider == NULL)? "" : rsc->provider),
295 rsc->type);
296 rc = lrm_state_get_metadata(lrm_state, rsc->standard, rsc->provider,
297 rsc->type, &metadata_str, 0);
298 if (rc != pcmk_ok) {
299 crm_warn("Failed to get metadata for %s (%s%s%s:%s): %s",
300 rsc->id, rsc->standard,
301 ((rsc->provider == NULL)? "" : ":"),
302 ((rsc->provider == NULL)? "" : rsc->provider),
303 rsc->type, pcmk_strerror(rc));
304 return NULL;
305 }
306
307 metadata = controld_cache_metadata(lrm_state->metadata_cache, rsc,
308 metadata_str);
309 free(metadata_str);
310 return metadata;
311 }