]> git.proxmox.com Git - mirror_corosync-qdevice.git/blame - qdevices/qdevice-instance.c
qdevice: Use log instead of libqb log
[mirror_corosync-qdevice.git] / qdevices / qdevice-instance.c
CommitLineData
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
45int
46qdevice_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
60int
61qdevice_instance_destroy(struct qdevice_instance *instance)
62{
63
64 node_list_free(&instance->config_node_list);
65
66 return (0);
67}
68
69int
70qdevice_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
256int
257qdevice_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}