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
- metadata_cache_update
- metadata_cache_get
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 g_hash_table_new_full(crm_str_hash, g_str_equal, free,
56 metadata_free);
57 }
58
59 void
60 metadata_cache_free(GHashTable *mdc)
61 {
62 if (mdc) {
63 crm_trace("Destroying metadata cache with %d members", g_hash_table_size(mdc));
64 g_hash_table_destroy(mdc);
65 }
66 }
67
68 void
69 metadata_cache_reset(GHashTable *mdc)
70 {
71 if (mdc) {
72 crm_trace("Resetting metadata cache with %d members",
73 g_hash_table_size(mdc));
74 g_hash_table_remove_all(mdc);
75 }
76 }
77
78 #if ENABLE_VERSIONED_ATTRS
79 static gboolean
80 valid_version_format(const char *version)
81 {
82 if (version == NULL) {
83 return FALSE;
84 }
85
86 if (version_format_regex == NULL) {
87
88
89
90
91
92 const char *regex_string = "^[[:digit:]]+([.][[:digit:]]+)*$";
93
94 version_format_regex = calloc(1, sizeof(regex_t));
95 regcomp(version_format_regex, regex_string, REG_EXTENDED | REG_NOSUB);
96
97
98
99
100
101
102 CRM_CHECK(version_format_regex != NULL, return TRUE);
103 }
104
105 return regexec(version_format_regex, version, 0, NULL, 0) == 0;
106 }
107 #endif
108
109 void
110 metadata_cache_fini()
111 {
112 #if ENABLE_VERSIONED_ATTRS
113 if (version_format_regex) {
114 regfree(version_format_regex);
115 free(version_format_regex);
116 version_format_regex = NULL;
117 }
118 #endif
119 }
120
121 #if ENABLE_VERSIONED_ATTRS
122 static char *
123 ra_version_from_xml(xmlNode *metadata_xml, const lrmd_rsc_info_t *rsc)
124 {
125 const char *version = crm_element_value(metadata_xml, XML_ATTR_VERSION);
126
127 if (version == NULL) {
128 crm_debug("Metadata for %s:%s:%s does not specify a version",
129 rsc->standard, rsc->provider, rsc->type);
130 version = PCMK_DEFAULT_AGENT_VERSION;
131
132 } else if (!valid_version_format(version)) {
133 crm_notice("%s:%s:%s metadata version has unrecognized format",
134 rsc->standard, rsc->provider, rsc->type);
135 version = PCMK_DEFAULT_AGENT_VERSION;
136
137 } else {
138 crm_debug("Metadata for %s:%s:%s has version %s",
139 rsc->standard, rsc->provider, rsc->type, version);
140 }
141 return strdup(version);
142 }
143 #endif
144
145 static struct ra_param_s *
146 ra_param_from_xml(xmlNode *param_xml)
147 {
148 const char *param_name = crm_element_value(param_xml, "name");
149 const char *value;
150 struct ra_param_s *p;
151
152 p = calloc(1, sizeof(struct ra_param_s));
153 if (p == NULL) {
154 crm_crit("Could not allocate memory for resource metadata");
155 return NULL;
156 }
157
158 p->rap_name = strdup(param_name);
159 if (p->rap_name == NULL) {
160 crm_crit("Could not allocate memory for resource metadata");
161 free(p);
162 return NULL;
163 }
164
165 value = crm_element_value(param_xml, "unique");
166 if (crm_is_true(value)) {
167 controld_set_ra_param_flags(p, ra_param_unique);
168 }
169
170 value = crm_element_value(param_xml, "private");
171 if (crm_is_true(value)) {
172 controld_set_ra_param_flags(p, ra_param_private);
173 }
174 return p;
175 }
176
177 struct ra_metadata_s *
178 metadata_cache_update(GHashTable *mdc, lrmd_rsc_info_t *rsc,
179 const char *metadata_str)
180 {
181 char *key = NULL;
182 xmlNode *metadata = NULL;
183 xmlNode *match = NULL;
184 struct ra_metadata_s *md = NULL;
185
186 CRM_CHECK(mdc && rsc && metadata_str, return NULL);
187
188 key = crm_generate_ra_key(rsc->standard, rsc->provider, rsc->type);
189 if (!key) {
190 crm_crit("Could not allocate memory for resource metadata");
191 goto err;
192 }
193
194 metadata = string2xml(metadata_str);
195 if (!metadata) {
196 crm_err("Metadata for %s:%s:%s is not valid XML",
197 rsc->standard, rsc->provider, rsc->type);
198 goto err;
199 }
200
201 md = calloc(1, sizeof(struct ra_metadata_s));
202 if (md == NULL) {
203 crm_crit("Could not allocate memory for resource metadata");
204 goto err;
205 }
206
207 #if ENABLE_VERSIONED_ATTRS
208 md->ra_version = ra_version_from_xml(metadata, rsc);
209 #endif
210
211
212 match = first_named_child(metadata, "actions");
213 for (match = first_named_child(match, "action"); match != NULL;
214 match = crm_next_same_xml(match)) {
215
216 const char *action_name = crm_element_value(match, "name");
217
218 if (pcmk__str_eq(action_name, "reload", pcmk__str_casei)) {
219 controld_set_ra_flags(md, key, ra_supports_reload);
220 break;
221 }
222 }
223
224
225 match = first_named_child(metadata, "parameters");
226 for (match = first_named_child(match, "parameter"); match != NULL;
227 match = crm_next_same_xml(match)) {
228
229 const char *param_name = crm_element_value(match, "name");
230
231 if (param_name == NULL) {
232 crm_warn("Metadata for %s:%s:%s has parameter without a name",
233 rsc->standard, rsc->provider, rsc->type);
234 } else {
235 struct ra_param_s *p = ra_param_from_xml(match);
236
237 if (p == NULL) {
238 goto err;
239 }
240 if (pcmk_is_set(p->rap_flags, ra_param_private)) {
241 controld_set_ra_flags(md, key, ra_uses_private);
242 }
243 md->ra_params = g_list_prepend(md->ra_params, p);
244 }
245 }
246
247 g_hash_table_replace(mdc, key, md);
248 free_xml(metadata);
249 return md;
250
251 err:
252 free(key);
253 free_xml(metadata);
254 metadata_free(md);
255 return NULL;
256 }
257
258 struct ra_metadata_s *
259 metadata_cache_get(GHashTable *mdc, lrmd_rsc_info_t *rsc)
260 {
261 char *key = NULL;
262 struct ra_metadata_s *metadata = NULL;
263
264 CRM_CHECK(mdc && rsc, return NULL);
265 key = crm_generate_ra_key(rsc->standard, rsc->provider, rsc->type);
266 if (key) {
267 metadata = g_hash_table_lookup(mdc, key);
268 free(key);
269 }
270 return metadata;
271 }