]>
Commit | Line | Data |
---|---|---|
9a1955a7 | 1 | /* |
c8d19612 | 2 | * Copyright (c) 2015-2019 Red Hat, Inc. |
9a1955a7 JF |
3 | * |
4 | * All rights reserved. | |
5 | * | |
6 | * Author: Jan Friesse (jfriesse@redhat.com) | |
7 | * | |
8 | * This software licensed under BSD license, the text of which follows: | |
9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions are met: | |
12 | * | |
13 | * - Redistributions of source code must retain the above copyright notice, | |
14 | * this list of conditions and the following disclaimer. | |
15 | * - Redistributions in binary form must reproduce the above copyright notice, | |
16 | * this list of conditions and the following disclaimer in the documentation | |
17 | * and/or other materials provided with the distribution. | |
18 | * - Neither the name of the Red Hat, Inc. nor the names of its | |
19 | * contributors may be used to endorse or promote products derived from this | |
20 | * software without specific prior written permission. | |
21 | * | |
22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |
23 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | |
26 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
27 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
28 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
29 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
30 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
31 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | |
32 | * THE POSSIBILITY OF SUCH DAMAGE. | |
33 | */ | |
34 | ||
c8d19612 JF |
35 | #include <string.h> |
36 | #include <stdio.h> | |
37 | ||
9a1955a7 JF |
38 | #include "qdevice-config.h" |
39 | #include "qdevice-instance.h" | |
40 | #include "qdevice-heuristics-exec-list.h" | |
41 | #include "qdevice-log.h" | |
42 | #include "qdevice-model.h" | |
43 | #include "utils.h" | |
44 | ||
45 | int | |
46 | qdevice_instance_init(struct qdevice_instance *instance, | |
47 | const struct qdevice_advanced_settings *advanced_settings) | |
48 | { | |
49 | ||
50 | memset(instance, 0, sizeof(*instance)); | |
51 | ||
52 | node_list_init(&instance->config_node_list); | |
53 | ||
54 | instance->vq_last_poll = ((time_t) -1); | |
55 | instance->advanced_settings = advanced_settings; | |
56 | ||
57 | return (0); | |
58 | } | |
59 | ||
60 | int | |
61 | qdevice_instance_destroy(struct qdevice_instance *instance) | |
62 | { | |
63 | ||
64 | node_list_free(&instance->config_node_list); | |
65 | ||
66 | return (0); | |
67 | } | |
68 | ||
69 | int | |
70 | qdevice_instance_configure_from_cmap_heuristics(struct qdevice_instance *instance) | |
71 | { | |
72 | char *str; | |
c5081836 | 73 | long long int lli; |
9a1955a7 JF |
74 | int i; |
75 | int res; | |
76 | cs_error_t cs_err; | |
77 | cmap_iter_handle_t iter_handle; | |
78 | char key_name[CMAP_KEYNAME_MAXLEN + 1]; | |
79 | size_t value_len; | |
80 | cmap_value_types_t type; | |
81 | struct qdevice_heuristics_exec_list tmp_exec_list; | |
82 | struct qdevice_heuristics_exec_list *exec_list; | |
83 | char *command; | |
84 | char exec_name[CMAP_KEYNAME_MAXLEN + 1]; | |
85 | char tmp_key[CMAP_KEYNAME_MAXLEN + 1]; | |
86 | size_t no_execs; | |
87 | int send_exec_list; | |
88 | ||
89 | instance->heuristics_instance.timeout = instance->heartbeat_interval / 2; | |
90 | if (cmap_get_string(instance->cmap_handle, | |
91 | "quorum.device.heuristics.timeout", &str) == CS_OK) { | |
c5081836 JF |
92 | if (utils_strtonum(str, instance->advanced_settings->heuristics_min_timeout, |
93 | instance->advanced_settings->heuristics_max_timeout, &lli) == -1) { | |
c8d19612 | 94 | log(LOG_ERR, "heuristics.timeout must be valid number in " |
9a1955a7 JF |
95 | "range <%"PRIu32",%"PRIu32">", |
96 | instance->advanced_settings->heuristics_min_timeout, | |
97 | instance->advanced_settings->heuristics_max_timeout); | |
98 | ||
99 | free(str); | |
100 | return (-1); | |
101 | } else { | |
c5081836 | 102 | instance->heuristics_instance.timeout = lli; |
9a1955a7 JF |
103 | } |
104 | ||
105 | free(str); | |
106 | } | |
107 | ||
108 | instance->heuristics_instance.sync_timeout = instance->sync_heartbeat_interval / 2; | |
109 | if (cmap_get_string(instance->cmap_handle, | |
110 | "quorum.device.heuristics.sync_timeout", &str) == CS_OK) { | |
c5081836 JF |
111 | if (utils_strtonum(str, instance->advanced_settings->heuristics_min_timeout, |
112 | instance->advanced_settings->heuristics_max_timeout, &lli) == -1) { | |
c8d19612 | 113 | log(LOG_ERR, "heuristics.sync_timeout must be valid number in " |
9a1955a7 JF |
114 | "range <%"PRIu32",%"PRIu32">", |
115 | instance->advanced_settings->heuristics_min_timeout, | |
116 | instance->advanced_settings->heuristics_max_timeout); | |
117 | ||
118 | free(str); | |
119 | return (-1); | |
120 | } else { | |
c5081836 | 121 | instance->heuristics_instance.sync_timeout = lli; |
9a1955a7 JF |
122 | } |
123 | ||
124 | free(str); | |
125 | } | |
126 | ||
127 | instance->heuristics_instance.interval = instance->heartbeat_interval * 3; | |
128 | if (cmap_get_string(instance->cmap_handle, | |
129 | "quorum.device.heuristics.interval", &str) == CS_OK) { | |
c5081836 JF |
130 | if (utils_strtonum(str, instance->advanced_settings->heuristics_min_interval, |
131 | instance->advanced_settings->heuristics_max_interval, &lli) == -1) { | |
c8d19612 | 132 | log(LOG_ERR, "heuristics.interval must be valid number in " |
9a1955a7 JF |
133 | "range <%"PRIu32",%"PRIu32">", |
134 | instance->advanced_settings->heuristics_min_interval, | |
135 | instance->advanced_settings->heuristics_max_interval); | |
136 | ||
137 | free(str); | |
138 | return (-1); | |
139 | } else { | |
c5081836 | 140 | instance->heuristics_instance.interval = lli; |
9a1955a7 JF |
141 | } |
142 | ||
143 | free(str); | |
144 | } | |
145 | ||
146 | instance->heuristics_instance.mode = QDEVICE_DEFAULT_HEURISTICS_MODE; | |
147 | ||
148 | if (cmap_get_string(instance->cmap_handle, "quorum.device.heuristics.mode", &str) == CS_OK) { | |
149 | if ((i = utils_parse_bool_str(str)) == -1) { | |
150 | if (strcasecmp(str, "sync") != 0) { | |
c8d19612 | 151 | log(LOG_ERR, "quorum.device.heuristics.mode value is not valid."); |
9a1955a7 JF |
152 | |
153 | free(str); | |
154 | return (-1); | |
155 | } else { | |
156 | instance->heuristics_instance.mode = QDEVICE_HEURISTICS_MODE_SYNC; | |
157 | } | |
158 | } else { | |
159 | if (i == 1) { | |
160 | instance->heuristics_instance.mode = QDEVICE_HEURISTICS_MODE_ENABLED; | |
161 | } else { | |
162 | instance->heuristics_instance.mode = QDEVICE_HEURISTICS_MODE_DISABLED; | |
163 | } | |
164 | } | |
165 | ||
166 | free(str); | |
167 | } | |
168 | ||
169 | send_exec_list = 0; | |
170 | exec_list = NULL; | |
171 | qdevice_heuristics_exec_list_init(&tmp_exec_list); | |
172 | ||
173 | if (instance->heuristics_instance.mode == QDEVICE_HEURISTICS_MODE_DISABLED) { | |
174 | exec_list = NULL; | |
175 | send_exec_list = 1; | |
176 | } else if (instance->heuristics_instance.mode == QDEVICE_HEURISTICS_MODE_ENABLED || | |
177 | instance->heuristics_instance.mode == QDEVICE_HEURISTICS_MODE_SYNC) { | |
178 | /* | |
179 | * Walk thru list of commands to exec | |
180 | */ | |
181 | cs_err = cmap_iter_init(instance->cmap_handle, "quorum.device.heuristics.exec_", &iter_handle); | |
182 | if (cs_err != CS_OK) { | |
c8d19612 | 183 | log(LOG_ERR, "Can't iterate quorum.device.heuristics.exec_ keys. " |
9a1955a7 JF |
184 | "Error %s", cs_strerror(cs_err)); |
185 | ||
186 | return (-1); | |
187 | } | |
188 | ||
189 | while ((cs_err = cmap_iter_next(instance->cmap_handle, iter_handle, key_name, | |
190 | &value_len, &type)) == CS_OK) { | |
191 | if (type != CMAP_VALUETYPE_STRING) { | |
c8d19612 | 192 | log(LOG_WARNING, "%s key is not of string type. Ignoring", key_name); |
9a1955a7 JF |
193 | continue ; |
194 | } | |
195 | ||
196 | res = sscanf(key_name, "quorum.device.heuristics.exec_%[^.]%s", exec_name, tmp_key); | |
197 | if (res != 1) { | |
c8d19612 | 198 | log(LOG_WARNING, "%s key is not correct heuristics exec name. Ignoring", key_name); |
9a1955a7 JF |
199 | continue ; |
200 | } | |
201 | ||
202 | cs_err = cmap_get_string(instance->cmap_handle, key_name, &command); | |
203 | if (cs_err != CS_OK) { | |
c8d19612 | 204 | log(LOG_WARNING, "Can't get value of %s key. Ignoring", key_name); |
9a1955a7 JF |
205 | continue ; |
206 | } | |
207 | ||
208 | if (qdevice_heuristics_exec_list_add(&tmp_exec_list, exec_name, command) == NULL) { | |
c8d19612 | 209 | log(LOG_WARNING, "Can't store value of %s key into list. Ignoring", key_name); |
9a1955a7 JF |
210 | } |
211 | ||
212 | free(command); | |
213 | } | |
214 | ||
215 | no_execs = qdevice_heuristics_exec_list_size(&tmp_exec_list); | |
216 | ||
217 | if (no_execs == 0) { | |
c8d19612 | 218 | log(LOG_INFO, "No valid heuristics execs defined. Disabling heuristics."); |
9a1955a7 JF |
219 | instance->heuristics_instance.mode = QDEVICE_HEURISTICS_MODE_DISABLED; |
220 | exec_list = NULL; | |
221 | send_exec_list = 1; | |
222 | } else if (no_execs > instance->advanced_settings->heuristics_max_execs) { | |
c8d19612 | 223 | log(LOG_ERR, "Too much (%zu) heuristics execs defined (max is %zu)." |
9a1955a7 JF |
224 | " Disabling heuristics.", no_execs, |
225 | instance->advanced_settings->heuristics_max_execs); | |
226 | instance->heuristics_instance.mode = QDEVICE_HEURISTICS_MODE_DISABLED; | |
227 | exec_list = NULL; | |
228 | send_exec_list = 1; | |
229 | } else if (qdevice_heuristics_exec_list_eq(&tmp_exec_list, | |
230 | &instance->heuristics_instance.exec_list) == 1) { | |
c8d19612 | 231 | log(LOG_DEBUG, "Heuristics list is unchanged"); |
9a1955a7 JF |
232 | send_exec_list = 0; |
233 | } else { | |
c8d19612 | 234 | log(LOG_DEBUG, "Heuristics list changed"); |
9a1955a7 JF |
235 | exec_list = &tmp_exec_list; |
236 | send_exec_list = 1; | |
237 | } | |
238 | ||
239 | } else { | |
c8d19612 | 240 | log(LOG_CRIT, "Undefined heuristics mode"); |
9a1955a7 JF |
241 | exit(1); |
242 | } | |
243 | ||
244 | if (send_exec_list) { | |
245 | if (qdevice_heuristics_change_exec_list(&instance->heuristics_instance, | |
246 | exec_list, instance->sync_in_progress) != 0) { | |
247 | return (-1); | |
248 | } | |
249 | } | |
250 | ||
251 | qdevice_heuristics_exec_list_free(&tmp_exec_list); | |
252 | ||
253 | return (0); | |
254 | } | |
255 | ||
256 | int | |
257 | qdevice_instance_configure_from_cmap(struct qdevice_instance *instance) | |
258 | { | |
259 | char *str; | |
260 | ||
261 | if (cmap_get_string(instance->cmap_handle, "quorum.device.model", &str) != CS_OK) { | |
c8d19612 | 262 | log(LOG_ERR, "Can't read quorum.device.model cmap key."); |
9a1955a7 JF |
263 | |
264 | return (-1); | |
265 | } | |
266 | ||
267 | if (qdevice_model_str_to_type(str, &instance->model_type) != 0) { | |
c8d19612 | 268 | log(LOG_ERR, "Configured device model %s is not supported.", str); |
9a1955a7 JF |
269 | free(str); |
270 | ||
271 | return (-1); | |
272 | } | |
273 | free(str); | |
274 | ||
275 | if (cmap_get_uint32(instance->cmap_handle, "runtime.votequorum.this_node_id", | |
276 | &instance->node_id) != CS_OK) { | |
c8d19612 | 277 | log(LOG_ERR, "Unable to retrieve this node nodeid."); |
9a1955a7 JF |
278 | |
279 | return (-1); | |
280 | } | |
281 | ||
282 | if (cmap_get_uint32(instance->cmap_handle, "quorum.device.timeout", &instance->heartbeat_interval) != CS_OK) { | |
283 | instance->heartbeat_interval = VOTEQUORUM_QDEVICE_DEFAULT_TIMEOUT; | |
284 | } | |
285 | ||
286 | if (cmap_get_uint32(instance->cmap_handle, "quorum.device.sync_timeout", | |
287 | &instance->sync_heartbeat_interval) != CS_OK) { | |
288 | instance->sync_heartbeat_interval = VOTEQUORUM_QDEVICE_DEFAULT_SYNC_TIMEOUT; | |
289 | } | |
290 | ||
291 | if (qdevice_instance_configure_from_cmap_heuristics(instance) != 0) { | |
292 | return (-1); | |
293 | } | |
294 | ||
295 | return (0); | |
296 | } |