1 /*
2 ** Zabbix
3 ** Copyright (C) 2001-2021 Zabbix SIA
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License as published by
7 ** the Free Software Foundation; either version 2 of the License, or
8 ** (at your option) any later version.
9 **
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ** GNU General Public License for more details.
14 **
15 ** You should have received a copy of the GNU General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 **/
19
20 #include "lld.h"
21 #include "db.h"
22 #include "log.h"
23 #include "zbxalgo.h"
24 #include "zbxserver.h"
25
26 typedef struct
27 {
28 zbx_uint64_t hostmacroid;
29 char *macro;
30 char *value;
31 }
32 zbx_lld_hostmacro_t;
33
lld_hostmacro_free(zbx_lld_hostmacro_t * hostmacro)34 static void lld_hostmacro_free(zbx_lld_hostmacro_t *hostmacro)
35 {
36 zbx_free(hostmacro->macro);
37 zbx_free(hostmacro->value);
38 zbx_free(hostmacro);
39 }
40
41 typedef struct
42 {
43 zbx_uint64_t interfaceid;
44 zbx_uint64_t parent_interfaceid;
45 char *ip;
46 char *dns;
47 char *port;
48 unsigned char main;
49 unsigned char main_orig;
50 unsigned char type;
51 unsigned char type_orig;
52 unsigned char useip;
53 unsigned char bulk;
54 #define ZBX_FLAG_LLD_INTERFACE_UPDATE_TYPE __UINT64_C(0x00000001) /* interface.type field should be updated */
55 #define ZBX_FLAG_LLD_INTERFACE_UPDATE_MAIN __UINT64_C(0x00000002) /* interface.main field should be updated */
56 #define ZBX_FLAG_LLD_INTERFACE_UPDATE_USEIP __UINT64_C(0x00000004) /* interface.useip field should be updated */
57 #define ZBX_FLAG_LLD_INTERFACE_UPDATE_IP __UINT64_C(0x00000008) /* interface.ip field should be updated */
58 #define ZBX_FLAG_LLD_INTERFACE_UPDATE_DNS __UINT64_C(0x00000010) /* interface.dns field should be updated */
59 #define ZBX_FLAG_LLD_INTERFACE_UPDATE_PORT __UINT64_C(0x00000020) /* interface.port field should be updated */
60 #define ZBX_FLAG_LLD_INTERFACE_UPDATE_BULK __UINT64_C(0x00000040) /* interface.bulk field should be updated */
61 #define ZBX_FLAG_LLD_INTERFACE_UPDATE \
62 (ZBX_FLAG_LLD_INTERFACE_UPDATE_TYPE | ZBX_FLAG_LLD_INTERFACE_UPDATE_MAIN | \
63 ZBX_FLAG_LLD_INTERFACE_UPDATE_USEIP | ZBX_FLAG_LLD_INTERFACE_UPDATE_IP | \
64 ZBX_FLAG_LLD_INTERFACE_UPDATE_DNS | ZBX_FLAG_LLD_INTERFACE_UPDATE_PORT | \
65 ZBX_FLAG_LLD_INTERFACE_UPDATE_BULK)
66 #define ZBX_FLAG_LLD_INTERFACE_REMOVE __UINT64_C(0x00000080) /* interfaces which should be deleted */
67 zbx_uint64_t flags;
68 }
69 zbx_lld_interface_t;
70
lld_interface_free(zbx_lld_interface_t * interface)71 static void lld_interface_free(zbx_lld_interface_t *interface)
72 {
73 zbx_free(interface->port);
74 zbx_free(interface->dns);
75 zbx_free(interface->ip);
76 zbx_free(interface);
77 }
78
79 typedef struct
80 {
81 zbx_uint64_t hostid;
82 zbx_vector_uint64_t new_groupids; /* host groups which should be added */
83 zbx_vector_uint64_t lnk_templateids; /* templates which should be linked */
84 zbx_vector_uint64_t del_templateids; /* templates which should be unlinked */
85 zbx_vector_ptr_t new_hostmacros; /* host macros which should be added */
86 zbx_vector_ptr_t interfaces;
87 char *host_proto;
88 char *host;
89 char *host_orig;
90 char *name;
91 char *name_orig;
92 int lastcheck;
93 int ts_delete;
94
95 #define ZBX_FLAG_LLD_HOST_DISCOVERED __UINT64_C(0x00000001) /* hosts which should be updated or added */
96 #define ZBX_FLAG_LLD_HOST_UPDATE_HOST __UINT64_C(0x00000002) /* hosts.host and host_discovery.host fields should be updated */
97 #define ZBX_FLAG_LLD_HOST_UPDATE_NAME __UINT64_C(0x00000004) /* hosts.name field should be updated */
98 #define ZBX_FLAG_LLD_HOST_UPDATE_PROXY __UINT64_C(0x00000008) /* hosts.proxy_hostid field should be updated */
99 #define ZBX_FLAG_LLD_HOST_UPDATE_IPMI_AUTH __UINT64_C(0x00000010) /* hosts.ipmi_authtype field should be updated */
100 #define ZBX_FLAG_LLD_HOST_UPDATE_IPMI_PRIV __UINT64_C(0x00000020) /* hosts.ipmi_privilege field should be updated */
101 #define ZBX_FLAG_LLD_HOST_UPDATE_IPMI_USER __UINT64_C(0x00000040) /* hosts.ipmi_username field should be updated */
102 #define ZBX_FLAG_LLD_HOST_UPDATE_IPMI_PASS __UINT64_C(0x00000080) /* hosts.ipmi_password field should be updated */
103 #define ZBX_FLAG_LLD_HOST_UPDATE_TLS_CONNECT __UINT64_C(0x00000100) /* hosts.tls_connect field should be updated */
104 #define ZBX_FLAG_LLD_HOST_UPDATE_TLS_ACCEPT __UINT64_C(0x00000200) /* hosts.tls_accept field should be updated */
105 #define ZBX_FLAG_LLD_HOST_UPDATE_TLS_ISSUER __UINT64_C(0x00000400) /* hosts.tls_issuer field should be updated */
106 #define ZBX_FLAG_LLD_HOST_UPDATE_TLS_SUBJECT __UINT64_C(0x00000800) /* hosts.tls_subject field should be updated */
107 #define ZBX_FLAG_LLD_HOST_UPDATE_TLS_PSK_IDENTITY __UINT64_C(0x00001000) /* hosts.tls_psk_identity field should be updated */
108 #define ZBX_FLAG_LLD_HOST_UPDATE_TLS_PSK __UINT64_C(0x00002000) /* hosts.tls_psk field should be updated */
109
110 #define ZBX_FLAG_LLD_HOST_UPDATE \
111 (ZBX_FLAG_LLD_HOST_UPDATE_HOST | ZBX_FLAG_LLD_HOST_UPDATE_NAME | \
112 ZBX_FLAG_LLD_HOST_UPDATE_PROXY | ZBX_FLAG_LLD_HOST_UPDATE_IPMI_AUTH | \
113 ZBX_FLAG_LLD_HOST_UPDATE_IPMI_PRIV | ZBX_FLAG_LLD_HOST_UPDATE_IPMI_USER | \
114 ZBX_FLAG_LLD_HOST_UPDATE_IPMI_PASS | ZBX_FLAG_LLD_HOST_UPDATE_TLS_CONNECT | \
115 ZBX_FLAG_LLD_HOST_UPDATE_TLS_ACCEPT | ZBX_FLAG_LLD_HOST_UPDATE_TLS_ISSUER | \
116 ZBX_FLAG_LLD_HOST_UPDATE_TLS_SUBJECT | ZBX_FLAG_LLD_HOST_UPDATE_TLS_PSK_IDENTITY | \
117 ZBX_FLAG_LLD_HOST_UPDATE_TLS_PSK)
118
119 zbx_uint64_t flags;
120 char inventory_mode;
121 }
122 zbx_lld_host_t;
123
lld_host_free(zbx_lld_host_t * host)124 static void lld_host_free(zbx_lld_host_t *host)
125 {
126 zbx_vector_uint64_destroy(&host->new_groupids);
127 zbx_vector_uint64_destroy(&host->lnk_templateids);
128 zbx_vector_uint64_destroy(&host->del_templateids);
129 zbx_vector_ptr_clear_ext(&host->new_hostmacros, (zbx_clean_func_t)lld_hostmacro_free);
130 zbx_vector_ptr_destroy(&host->new_hostmacros);
131 zbx_vector_ptr_clear_ext(&host->interfaces, (zbx_clean_func_t)lld_interface_free);
132 zbx_vector_ptr_destroy(&host->interfaces);
133 zbx_free(host->host_proto);
134 zbx_free(host->host);
135 zbx_free(host->host_orig);
136 zbx_free(host->name);
137 zbx_free(host->name_orig);
138 zbx_free(host);
139 }
140
141 typedef struct
142 {
143 zbx_uint64_t group_prototypeid;
144 char *name;
145 }
146 zbx_lld_group_prototype_t;
147
lld_group_prototype_free(zbx_lld_group_prototype_t * group_prototype)148 static void lld_group_prototype_free(zbx_lld_group_prototype_t *group_prototype)
149 {
150 zbx_free(group_prototype->name);
151 zbx_free(group_prototype);
152 }
153
154 typedef struct
155 {
156 zbx_uint64_t groupid;
157 zbx_uint64_t group_prototypeid;
158 zbx_vector_ptr_t hosts;
159 char *name_proto;
160 char *name;
161 char *name_orig;
162 int lastcheck;
163 int ts_delete;
164 #define ZBX_FLAG_LLD_GROUP_DISCOVERED __UINT64_C(0x00000001) /* groups which should be updated or added */
165 #define ZBX_FLAG_LLD_GROUP_UPDATE_NAME __UINT64_C(0x00000002) /* groups.name field should be updated */
166 #define ZBX_FLAG_LLD_GROUP_UPDATE ZBX_FLAG_LLD_GROUP_UPDATE_NAME
167 zbx_uint64_t flags;
168 }
169 zbx_lld_group_t;
170
lld_group_free(zbx_lld_group_t * group)171 static void lld_group_free(zbx_lld_group_t *group)
172 {
173 /* zbx_vector_ptr_clear_ext(&group->hosts, (zbx_clean_func_t)lld_host_free); is not missing here */
174 zbx_vector_ptr_destroy(&group->hosts);
175 zbx_free(group->name_proto);
176 zbx_free(group->name);
177 zbx_free(group->name_orig);
178 zbx_free(group);
179 }
180
181 /******************************************************************************
182 * *
183 * Function: lld_hosts_get *
184 * *
185 * Purpose: retrieves existing hosts for the specified host prototype *
186 * *
187 * Parameters: parent_hostid - [IN] host prototype identifier *
188 * hosts - [OUT] list of hosts *
189 * *
190 ******************************************************************************/
lld_hosts_get(zbx_uint64_t parent_hostid,zbx_vector_ptr_t * hosts,zbx_uint64_t proxy_hostid,char ipmi_authtype,unsigned char ipmi_privilege,const char * ipmi_username,const char * ipmi_password,char inventory_mode,unsigned char tls_connect,unsigned char tls_accept,const char * tls_issuer,const char * tls_subject,const char * tls_psk_identity,const char * tls_psk)191 static void lld_hosts_get(zbx_uint64_t parent_hostid, zbx_vector_ptr_t *hosts, zbx_uint64_t proxy_hostid,
192 char ipmi_authtype, unsigned char ipmi_privilege, const char *ipmi_username, const char *ipmi_password,
193 char inventory_mode, unsigned char tls_connect, unsigned char tls_accept, const char *tls_issuer,
194 const char *tls_subject, const char *tls_psk_identity, const char *tls_psk)
195 {
196 const char *__function_name = "lld_hosts_get";
197
198 DB_RESULT result;
199 DB_ROW row;
200 zbx_lld_host_t *host;
201 zbx_uint64_t db_proxy_hostid;
202
203 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
204
205 result = DBselect(
206 "select hd.hostid,hd.host,hd.lastcheck,hd.ts_delete,h.host,h.name,h.proxy_hostid,"
207 "h.ipmi_authtype,h.ipmi_privilege,h.ipmi_username,h.ipmi_password,hi.inventory_mode,"
208 "h.tls_connect,h.tls_accept,h.tls_issuer,h.tls_subject,h.tls_psk_identity,h.tls_psk"
209 " from host_discovery hd"
210 " join hosts h"
211 " on hd.hostid=h.hostid"
212 " left join host_inventory hi"
213 " on hd.hostid=hi.hostid"
214 " where hd.parent_hostid=" ZBX_FS_UI64,
215 parent_hostid);
216
217 while (NULL != (row = DBfetch(result)))
218 {
219 host = zbx_malloc(NULL, sizeof(zbx_lld_host_t));
220
221 ZBX_STR2UINT64(host->hostid, row[0]);
222 host->host_proto = zbx_strdup(NULL, row[1]);
223 host->lastcheck = atoi(row[2]);
224 host->ts_delete = atoi(row[3]);
225 host->host = zbx_strdup(NULL, row[4]);
226 host->host_orig = NULL;
227 host->name = zbx_strdup(NULL, row[5]);
228 host->name_orig = NULL;
229 host->flags = 0x00;
230
231 ZBX_DBROW2UINT64(db_proxy_hostid, row[6]);
232 if (db_proxy_hostid != proxy_hostid)
233 host->flags |= ZBX_FLAG_LLD_HOST_UPDATE_PROXY;
234
235 if ((char)atoi(row[7]) != ipmi_authtype)
236 host->flags |= ZBX_FLAG_LLD_HOST_UPDATE_IPMI_AUTH;
237
238 if ((unsigned char)atoi(row[8]) != ipmi_privilege)
239 host->flags |= ZBX_FLAG_LLD_HOST_UPDATE_IPMI_PRIV;
240
241 if (0 != strcmp(row[9], ipmi_username))
242 host->flags |= ZBX_FLAG_LLD_HOST_UPDATE_IPMI_USER;
243
244 if (0 != strcmp(row[10], ipmi_password))
245 host->flags |= ZBX_FLAG_LLD_HOST_UPDATE_IPMI_PASS;
246
247 if (atoi(row[12]) != tls_connect)
248 host->flags |= ZBX_FLAG_LLD_HOST_UPDATE_TLS_CONNECT;
249
250 if (atoi(row[13]) != tls_accept)
251 host->flags |= ZBX_FLAG_LLD_HOST_UPDATE_TLS_ACCEPT;
252
253 if (0 != strcmp(tls_issuer, row[14]))
254 host->flags |= ZBX_FLAG_LLD_HOST_UPDATE_TLS_ISSUER;
255
256 if (0 != strcmp(tls_subject, row[15]))
257 host->flags |= ZBX_FLAG_LLD_HOST_UPDATE_TLS_SUBJECT;
258
259 if (0 != strcmp(tls_psk_identity, row[16]))
260 host->flags |= ZBX_FLAG_LLD_HOST_UPDATE_TLS_PSK_IDENTITY;
261
262 if (0 != strcmp(tls_psk, row[17]))
263 host->flags |= ZBX_FLAG_LLD_HOST_UPDATE_TLS_PSK;
264
265 if (SUCCEED == DBis_null(row[11]))
266 host->inventory_mode = HOST_INVENTORY_DISABLED;
267 else
268 host->inventory_mode = (char)atoi(row[11]);
269
270 zbx_vector_uint64_create(&host->new_groupids);
271 zbx_vector_uint64_create(&host->lnk_templateids);
272 zbx_vector_uint64_create(&host->del_templateids);
273 zbx_vector_ptr_create(&host->new_hostmacros);
274 zbx_vector_ptr_create(&host->interfaces);
275
276 zbx_vector_ptr_append(hosts, host);
277 }
278 DBfree_result(result);
279
280 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
281 }
282
283 /******************************************************************************
284 * *
285 * Function: lld_hosts_validate *
286 * *
287 * Parameters: hosts - [IN] list of hosts; should be sorted by hostid *
288 * *
289 ******************************************************************************/
lld_hosts_validate(zbx_vector_ptr_t * hosts,char ** error)290 void lld_hosts_validate(zbx_vector_ptr_t *hosts, char **error)
291 {
292 const char *__function_name = "lld_hosts_validate";
293
294 DB_RESULT result;
295 DB_ROW row;
296 int i, j;
297 zbx_lld_host_t *host, *host_b;
298 zbx_vector_uint64_t hostids;
299 zbx_vector_str_t tnames, vnames;
300
301 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
302
303 zbx_vector_uint64_create(&hostids);
304 zbx_vector_str_create(&tnames); /* list of technical host names */
305 zbx_vector_str_create(&vnames); /* list of visible host names */
306
307 /* checking a host name validity */
308 for (i = 0; i < hosts->values_num; i++)
309 {
310 char *ch_error;
311
312 host = (zbx_lld_host_t *)hosts->values[i];
313
314 if (0 == (host->flags & ZBX_FLAG_LLD_HOST_DISCOVERED))
315 continue;
316
317 /* only new hosts or hosts with changed host name will be validated */
318 if (0 != host->hostid && 0 == (host->flags & ZBX_FLAG_LLD_HOST_UPDATE_HOST))
319 continue;
320
321 /* host name is valid? */
322 if (SUCCEED == zbx_check_hostname(host->host, &ch_error))
323 continue;
324
325 *error = zbx_strdcatf(*error, "Cannot %s host \"%s\": %s.\n",
326 (0 != host->hostid ? "update" : "create"), host->host, ch_error);
327
328 zbx_free(ch_error);
329
330 if (0 != host->hostid)
331 {
332 lld_field_str_rollback(&host->host, &host->host_orig, &host->flags,
333 ZBX_FLAG_LLD_HOST_UPDATE_HOST);
334 }
335 else
336 host->flags &= ~ZBX_FLAG_LLD_HOST_DISCOVERED;
337 }
338
339 /* checking a visible host name validity */
340 for (i = 0; i < hosts->values_num; i++)
341 {
342 host = (zbx_lld_host_t *)hosts->values[i];
343
344 if (0 == (host->flags & ZBX_FLAG_LLD_HOST_DISCOVERED))
345 continue;
346
347 /* only new hosts or hosts with changed visible name will be validated */
348 if (0 != host->hostid && 0 == (host->flags & ZBX_FLAG_LLD_HOST_UPDATE_NAME))
349 continue;
350
351 /* visible host name is valid utf8 sequence and has a valid length */
352 if (SUCCEED == zbx_is_utf8(host->name) && '\0' != *host->name &&
353 HOST_NAME_LEN >= zbx_strlen_utf8(host->name))
354 {
355 continue;
356 }
357
358 zbx_replace_invalid_utf8(host->name);
359 *error = zbx_strdcatf(*error, "Cannot %s host: invalid visible host name \"%s\".\n",
360 (0 != host->hostid ? "update" : "create"), host->name);
361
362 if (0 != host->hostid)
363 {
364 lld_field_str_rollback(&host->name, &host->name_orig, &host->flags,
365 ZBX_FLAG_LLD_HOST_UPDATE_NAME);
366 }
367 else
368 host->flags &= ~ZBX_FLAG_LLD_HOST_DISCOVERED;
369 }
370
371 /* checking duplicated host names */
372 for (i = 0; i < hosts->values_num; i++)
373 {
374 host = (zbx_lld_host_t *)hosts->values[i];
375
376 if (0 == (host->flags & ZBX_FLAG_LLD_HOST_DISCOVERED))
377 continue;
378
379 /* only new hosts or hosts with changed host name will be validated */
380 if (0 != host->hostid && 0 == (host->flags & ZBX_FLAG_LLD_HOST_UPDATE_HOST))
381 continue;
382
383 for (j = 0; j < hosts->values_num; j++)
384 {
385 host_b = (zbx_lld_host_t *)hosts->values[j];
386
387 if (0 == (host_b->flags & ZBX_FLAG_LLD_HOST_DISCOVERED) || i == j)
388 continue;
389
390 if (0 != strcmp(host->host, host_b->host))
391 continue;
392
393 *error = zbx_strdcatf(*error, "Cannot %s host:"
394 " host with the same name \"%s\" already exists.\n",
395 (0 != host->hostid ? "update" : "create"), host->host);
396
397 if (0 != host->hostid)
398 {
399 lld_field_str_rollback(&host->host, &host->host_orig, &host->flags,
400 ZBX_FLAG_LLD_HOST_UPDATE_HOST);
401 }
402 else
403 host->flags &= ~ZBX_FLAG_LLD_HOST_DISCOVERED;
404 }
405 }
406
407 /* checking duplicated visible host names */
408 for (i = 0; i < hosts->values_num; i++)
409 {
410 host = (zbx_lld_host_t *)hosts->values[i];
411
412 if (0 == (host->flags & ZBX_FLAG_LLD_HOST_DISCOVERED))
413 continue;
414
415 /* only new hosts or hosts with changed visible name will be validated */
416 if (0 != host->hostid && 0 == (host->flags & ZBX_FLAG_LLD_HOST_UPDATE_NAME))
417 continue;
418
419 for (j = 0; j < hosts->values_num; j++)
420 {
421 host_b = (zbx_lld_host_t *)hosts->values[j];
422
423 if (0 == (host_b->flags & ZBX_FLAG_LLD_HOST_DISCOVERED) || i == j)
424 continue;
425
426 if (0 != strcmp(host->name, host_b->name))
427 continue;
428
429 *error = zbx_strdcatf(*error, "Cannot %s host:"
430 " host with the same visible name \"%s\" already exists.\n",
431 (0 != host->hostid ? "update" : "create"), host->name);
432
433 if (0 != host->hostid)
434 {
435 lld_field_str_rollback(&host->name, &host->name_orig, &host->flags,
436 ZBX_FLAG_LLD_HOST_UPDATE_NAME);
437 }
438 else
439 host->flags &= ~ZBX_FLAG_LLD_HOST_DISCOVERED;
440 }
441 }
442
443 /* checking duplicated host names and visible host names in DB */
444
445 for (i = 0; i < hosts->values_num; i++)
446 {
447 host = (zbx_lld_host_t *)hosts->values[i];
448
449 if (0 == (host->flags & ZBX_FLAG_LLD_HOST_DISCOVERED))
450 continue;
451
452 if (0 != host->hostid)
453 zbx_vector_uint64_append(&hostids, host->hostid);
454
455 if (0 == host->hostid || 0 != (host->flags & ZBX_FLAG_LLD_HOST_UPDATE_HOST))
456 zbx_vector_str_append(&tnames, host->host);
457
458 if (0 == host->hostid || 0 != (host->flags & ZBX_FLAG_LLD_HOST_UPDATE_NAME))
459 zbx_vector_str_append(&vnames, host->name);
460 }
461
462 if (0 != tnames.values_num || 0 != vnames.values_num)
463 {
464 char *sql = NULL;
465 size_t sql_alloc = 0, sql_offset = 0;
466
467 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
468 "select host,name"
469 " from hosts"
470 " where status in (%d,%d,%d)"
471 " and flags<>%d"
472 " and",
473 HOST_STATUS_MONITORED, HOST_STATUS_NOT_MONITORED, HOST_STATUS_TEMPLATE,
474 ZBX_FLAG_DISCOVERY_PROTOTYPE);
475
476 if (0 != tnames.values_num && 0 != vnames.values_num)
477 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " (");
478
479 if (0 != tnames.values_num)
480 {
481 DBadd_str_condition_alloc(&sql, &sql_alloc, &sql_offset, "host",
482 (const char **)tnames.values, tnames.values_num);
483 }
484
485 if (0 != tnames.values_num && 0 != vnames.values_num)
486 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " or");
487
488 if (0 != vnames.values_num)
489 {
490 DBadd_str_condition_alloc(&sql, &sql_alloc, &sql_offset, "name",
491 (const char **)vnames.values, vnames.values_num);
492 }
493
494 if (0 != tnames.values_num && 0 != vnames.values_num)
495 zbx_chrcpy_alloc(&sql, &sql_alloc, &sql_offset, ')');
496
497 if (0 != hostids.values_num)
498 {
499 zbx_vector_uint64_sort(&hostids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
500 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " and not");
501 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hostid",
502 hostids.values, hostids.values_num);
503 }
504
505 result = DBselect("%s", sql);
506
507 while (NULL != (row = DBfetch(result)))
508 {
509 for (i = 0; i < hosts->values_num; i++)
510 {
511 host = (zbx_lld_host_t *)hosts->values[i];
512
513 if (0 == (host->flags & ZBX_FLAG_LLD_HOST_DISCOVERED))
514 continue;
515
516 if (0 == strcmp(host->host, row[0]))
517 {
518 *error = zbx_strdcatf(*error, "Cannot %s host:"
519 " host with the same name \"%s\" already exists.\n",
520 (0 != host->hostid ? "update" : "create"), host->host);
521
522 if (0 != host->hostid)
523 {
524 lld_field_str_rollback(&host->host, &host->host_orig, &host->flags,
525 ZBX_FLAG_LLD_HOST_UPDATE_HOST);
526 }
527 else
528 host->flags &= ~ZBX_FLAG_LLD_HOST_DISCOVERED;
529 }
530
531 if (0 == strcmp(host->name, row[1]))
532 {
533 *error = zbx_strdcatf(*error, "Cannot %s host:"
534 " host with the same visible name \"%s\" already exists.\n",
535 (0 != host->hostid ? "update" : "create"), host->name);
536
537 if (0 != host->hostid)
538 {
539 lld_field_str_rollback(&host->name, &host->name_orig, &host->flags,
540 ZBX_FLAG_LLD_HOST_UPDATE_NAME);
541 }
542 else
543 host->flags &= ~ZBX_FLAG_LLD_HOST_DISCOVERED;
544 }
545 }
546 }
547 DBfree_result(result);
548
549 zbx_free(sql);
550 }
551
552 zbx_vector_str_destroy(&vnames);
553 zbx_vector_str_destroy(&tnames);
554 zbx_vector_uint64_destroy(&hostids);
555
556 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
557 }
558
lld_host_make(zbx_vector_ptr_t * hosts,const char * host_proto,const char * name_proto,const struct zbx_json_parse * jp_row)559 static zbx_lld_host_t *lld_host_make(zbx_vector_ptr_t *hosts, const char *host_proto, const char *name_proto,
560 const struct zbx_json_parse *jp_row)
561 {
562 const char *__function_name = "lld_host_make";
563
564 char *buffer = NULL;
565 int i;
566 zbx_lld_host_t *host = NULL;
567
568 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
569
570 for (i = 0; i < hosts->values_num; i++)
571 {
572 host = (zbx_lld_host_t *)hosts->values[i];
573
574 if (0 != (host->flags & ZBX_FLAG_LLD_HOST_DISCOVERED))
575 continue;
576
577 buffer = zbx_strdup(buffer, host->host_proto);
578 substitute_discovery_macros(&buffer, jp_row, ZBX_MACRO_ANY, NULL, 0);
579 zbx_lrtrim(buffer, ZBX_WHITESPACE);
580
581 if (0 == strcmp(host->host, buffer))
582 break;
583 }
584
585 if (i == hosts->values_num) /* no host found */
586 {
587 host = zbx_malloc(NULL, sizeof(zbx_lld_host_t));
588
589 host->hostid = 0;
590 host->host_proto = NULL;
591 host->lastcheck = 0;
592 host->ts_delete = 0;
593 host->host = zbx_strdup(NULL, host_proto);
594 host->host_orig = NULL;
595 substitute_discovery_macros(&host->host, jp_row, ZBX_MACRO_ANY, NULL, 0);
596 zbx_lrtrim(host->host, ZBX_WHITESPACE);
597 host->name = zbx_strdup(NULL, name_proto);
598 substitute_discovery_macros(&host->name, jp_row, ZBX_MACRO_ANY, NULL, 0);
599 zbx_lrtrim(host->name, ZBX_WHITESPACE);
600 host->name_orig = NULL;
601 zbx_vector_uint64_create(&host->new_groupids);
602 zbx_vector_uint64_create(&host->lnk_templateids);
603 zbx_vector_uint64_create(&host->del_templateids);
604 zbx_vector_ptr_create(&host->new_hostmacros);
605 zbx_vector_ptr_create(&host->interfaces);
606 host->flags = ZBX_FLAG_LLD_HOST_DISCOVERED;
607
608 zbx_vector_ptr_append(hosts, host);
609 }
610 else
611 {
612 /* host technical name */
613 if (0 != strcmp(host->host_proto, host_proto)) /* the new host prototype differs */
614 {
615 host->host_orig = host->host;
616 host->host = zbx_strdup(NULL, host_proto);
617 substitute_discovery_macros(&host->host, jp_row, ZBX_MACRO_ANY, NULL, 0);
618 zbx_lrtrim(host->host, ZBX_WHITESPACE);
619 host->flags |= ZBX_FLAG_LLD_HOST_UPDATE_HOST;
620 }
621
622 /* host visible name */
623 buffer = zbx_strdup(buffer, name_proto);
624 substitute_discovery_macros(&buffer, jp_row, ZBX_MACRO_ANY, NULL, 0);
625 zbx_lrtrim(buffer, ZBX_WHITESPACE);
626 if (0 != strcmp(host->name, buffer))
627 {
628 host->name_orig = host->name;
629 host->name = buffer;
630 buffer = NULL;
631 host->flags |= ZBX_FLAG_LLD_HOST_UPDATE_NAME;
632 }
633
634 host->flags |= ZBX_FLAG_LLD_HOST_DISCOVERED;
635 }
636
637 zbx_free(buffer);
638
639 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%p", __function_name, host);
640
641 return host;
642 }
643
644 /******************************************************************************
645 * *
646 * Function: lld_simple_groups_get *
647 * *
648 * Purpose: retrieve list of host groups which should be present on the each *
649 * discovered host *
650 * *
651 * Parameters: parent_hostid - [IN] host prototype identifier *
652 * groupids - [OUT] sorted list of host groups *
653 * *
654 ******************************************************************************/
lld_simple_groups_get(zbx_uint64_t parent_hostid,zbx_vector_uint64_t * groupids)655 static void lld_simple_groups_get(zbx_uint64_t parent_hostid, zbx_vector_uint64_t *groupids)
656 {
657 DB_RESULT result;
658 DB_ROW row;
659 zbx_uint64_t groupid;
660
661 result = DBselect(
662 "select groupid"
663 " from group_prototype"
664 " where groupid is not null"
665 " and hostid=" ZBX_FS_UI64,
666 parent_hostid);
667
668 while (NULL != (row = DBfetch(result)))
669 {
670 ZBX_STR2UINT64(groupid, row[0]);
671 zbx_vector_uint64_append(groupids, groupid);
672 }
673 DBfree_result(result);
674
675 zbx_vector_uint64_sort(groupids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
676 }
677
678 /******************************************************************************
679 * *
680 * Function: lld_hostgroups_make *
681 * *
682 * Parameters: groupids - [IN] sorted list of host group ids which *
683 * should be present on the each *
684 * discovered host (Groups) *
685 * hosts - [IN/OUT] list of hosts *
686 * should be sorted by hostid *
687 * groups - [IN] list of host groups (Group prototypes)*
688 * del_hostgroupids - [OUT] sorted list of host groups which *
689 * should be deleted *
690 * *
691 ******************************************************************************/
lld_hostgroups_make(const zbx_vector_uint64_t * groupids,zbx_vector_ptr_t * hosts,const zbx_vector_ptr_t * groups,zbx_vector_uint64_t * del_hostgroupids)692 static void lld_hostgroups_make(const zbx_vector_uint64_t *groupids, zbx_vector_ptr_t *hosts,
693 const zbx_vector_ptr_t *groups, zbx_vector_uint64_t *del_hostgroupids)
694 {
695 const char *__function_name = "lld_hostgroups_make";
696
697 DB_RESULT result;
698 DB_ROW row;
699 int i, j;
700 zbx_vector_uint64_t hostids;
701 zbx_uint64_t hostgroupid, hostid, groupid;
702 zbx_lld_host_t *host;
703 const zbx_lld_group_t *group;
704
705 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
706
707 zbx_vector_uint64_create(&hostids);
708
709 for (i = 0; i < hosts->values_num; i++)
710 {
711 host = (zbx_lld_host_t *)hosts->values[i];
712
713 if (0 == (host->flags & ZBX_FLAG_LLD_HOST_DISCOVERED))
714 continue;
715
716 zbx_vector_uint64_reserve(&host->new_groupids, groupids->values_num);
717 for (j = 0; j < groupids->values_num; j++)
718 zbx_vector_uint64_append(&host->new_groupids, groupids->values[j]);
719
720 if (0 != host->hostid)
721 zbx_vector_uint64_append(&hostids, host->hostid);
722 }
723
724 for (i = 0; i < groups->values_num; i++)
725 {
726 group = (zbx_lld_group_t *)groups->values[i];
727
728 if (0 == (group->flags & ZBX_FLAG_LLD_GROUP_DISCOVERED) || 0 == group->groupid)
729 continue;
730
731 for (j = 0; j < group->hosts.values_num; j++)
732 {
733 host = (zbx_lld_host_t *)group->hosts.values[j];
734
735 zbx_vector_uint64_append(&host->new_groupids, group->groupid);
736 }
737 }
738
739 for (i = 0; i < hosts->values_num; i++)
740 {
741 host = (zbx_lld_host_t *)hosts->values[i];
742 zbx_vector_uint64_sort(&host->new_groupids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
743 }
744
745 if (0 != hostids.values_num)
746 {
747 char *sql = NULL;
748 size_t sql_alloc = 0, sql_offset = 0;
749
750 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
751 "select hostid,groupid,hostgroupid"
752 " from hosts_groups"
753 " where");
754 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hostid", hostids.values, hostids.values_num);
755
756 result = DBselect("%s", sql);
757
758 zbx_free(sql);
759
760 while (NULL != (row = DBfetch(result)))
761 {
762 ZBX_STR2UINT64(hostid, row[0]);
763 ZBX_STR2UINT64(groupid, row[1]);
764
765 if (FAIL == (i = zbx_vector_ptr_bsearch(hosts, &hostid, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
766 {
767 THIS_SHOULD_NEVER_HAPPEN;
768 continue;
769 }
770
771 host = (zbx_lld_host_t *)hosts->values[i];
772
773 if (FAIL == (i = zbx_vector_uint64_bsearch(&host->new_groupids, groupid,
774 ZBX_DEFAULT_UINT64_COMPARE_FUNC)))
775 {
776 /* host groups which should be unlinked */
777 ZBX_STR2UINT64(hostgroupid, row[2]);
778 zbx_vector_uint64_append(del_hostgroupids, hostgroupid);
779 }
780 else
781 {
782 /* host groups which are already added */
783 zbx_vector_uint64_remove(&host->new_groupids, i);
784 }
785 }
786 DBfree_result(result);
787
788 zbx_vector_uint64_sort(del_hostgroupids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
789 }
790
791 zbx_vector_uint64_destroy(&hostids);
792
793 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
794 }
795
796 /******************************************************************************
797 * *
798 * Function: lld_group_prototypes_get *
799 * *
800 * Purpose: retrieve list of group prototypes *
801 * *
802 * Parameters: parent_hostid - [IN] host prototype identifier *
803 * group_prototypes - [OUT] sorted list of group prototypes *
804 * *
805 ******************************************************************************/
lld_group_prototypes_get(zbx_uint64_t parent_hostid,zbx_vector_ptr_t * group_prototypes)806 static void lld_group_prototypes_get(zbx_uint64_t parent_hostid, zbx_vector_ptr_t *group_prototypes)
807 {
808 const char *__function_name = "lld_group_prototypes_get";
809
810 DB_RESULT result;
811 DB_ROW row;
812 zbx_lld_group_prototype_t *group_prototype;
813
814 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
815
816 result = DBselect(
817 "select group_prototypeid,name"
818 " from group_prototype"
819 " where groupid is null"
820 " and hostid=" ZBX_FS_UI64,
821 parent_hostid);
822
823 while (NULL != (row = DBfetch(result)))
824 {
825 group_prototype = zbx_malloc(NULL, sizeof(zbx_lld_group_prototype_t));
826
827 ZBX_STR2UINT64(group_prototype->group_prototypeid, row[0]);
828 group_prototype->name = zbx_strdup(NULL, row[1]);
829
830 zbx_vector_ptr_append(group_prototypes, group_prototype);
831 }
832 DBfree_result(result);
833
834 zbx_vector_ptr_sort(group_prototypes, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
835
836 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
837 }
838
839 /******************************************************************************
840 * *
841 * Function: lld_groups_get *
842 * *
843 * Purpose: retrieves existing groups for the specified host prototype *
844 * *
845 * Parameters: parent_hostid - [IN] host prototype identifier *
846 * groups - [OUT] list of groups *
847 * *
848 ******************************************************************************/
lld_groups_get(zbx_uint64_t parent_hostid,zbx_vector_ptr_t * groups)849 static void lld_groups_get(zbx_uint64_t parent_hostid, zbx_vector_ptr_t *groups)
850 {
851 const char *__function_name = "lld_groups_get";
852
853 DB_RESULT result;
854 DB_ROW row;
855 zbx_lld_group_t *group;
856
857 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
858
859 result = DBselect(
860 "select gd.groupid,gp.group_prototypeid,gd.name,gd.lastcheck,gd.ts_delete,g.name"
861 " from group_prototype gp,group_discovery gd"
862 " join groups g"
863 " on gd.groupid=g.groupid"
864 " where gp.group_prototypeid=gd.parent_group_prototypeid"
865 " and gp.hostid=" ZBX_FS_UI64,
866 parent_hostid);
867
868 while (NULL != (row = DBfetch(result)))
869 {
870 group = zbx_malloc(NULL, sizeof(zbx_lld_group_t));
871
872 ZBX_STR2UINT64(group->groupid, row[0]);
873 ZBX_STR2UINT64(group->group_prototypeid, row[1]);
874 zbx_vector_ptr_create(&group->hosts);
875 group->name_proto = zbx_strdup(NULL, row[2]);
876 group->lastcheck = atoi(row[3]);
877 group->ts_delete = atoi(row[4]);
878 group->name = zbx_strdup(NULL, row[5]);
879 group->name_orig = NULL;
880 group->flags = 0x00;
881
882 zbx_vector_ptr_append(groups, group);
883 }
884 DBfree_result(result);
885
886 zbx_vector_ptr_sort(groups, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
887
888 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
889 }
890
891 /******************************************************************************
892 * *
893 * Function: lld_group_make *
894 * *
895 ******************************************************************************/
lld_group_make(zbx_vector_ptr_t * groups,zbx_uint64_t group_prototypeid,const char * name_proto,const struct zbx_json_parse * jp_row)896 static zbx_lld_group_t *lld_group_make(zbx_vector_ptr_t *groups, zbx_uint64_t group_prototypeid,
897 const char *name_proto, const struct zbx_json_parse *jp_row)
898 {
899 const char *__function_name = "lld_group_make";
900
901 char *buffer = NULL;
902 int i;
903 zbx_lld_group_t *group = NULL;
904
905 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
906
907 for (i = 0; i < groups->values_num; i++)
908 {
909 group = (zbx_lld_group_t *)groups->values[i];
910
911 if (group->group_prototypeid != group_prototypeid)
912 continue;
913
914 if (0 != (group->flags & ZBX_FLAG_LLD_GROUP_DISCOVERED))
915 continue;
916
917 buffer = zbx_strdup(buffer, group->name_proto);
918 substitute_discovery_macros(&buffer, jp_row, ZBX_MACRO_ANY, NULL, 0);
919 zbx_lrtrim(buffer, ZBX_WHITESPACE);
920
921 if (0 == strcmp(group->name, buffer))
922 break;
923 }
924
925 if (i == groups->values_num) /* no group found */
926 {
927 /* trying to find an already existing group */
928
929 buffer = zbx_strdup(buffer, name_proto);
930 substitute_discovery_macros(&buffer, jp_row, ZBX_MACRO_ANY, NULL, 0);
931 zbx_lrtrim(buffer, ZBX_WHITESPACE);
932
933 for (i = 0; i < groups->values_num; i++)
934 {
935 group = (zbx_lld_group_t *)groups->values[i];
936
937 if (group->group_prototypeid != group_prototypeid)
938 continue;
939
940 if (0 == (group->flags & ZBX_FLAG_LLD_GROUP_DISCOVERED))
941 continue;
942
943 if (0 == strcmp(group->name, buffer))
944 goto out;
945 }
946
947 /* otherwise create a new group */
948
949 group = zbx_malloc(NULL, sizeof(zbx_lld_group_t));
950
951 group->groupid = 0;
952 group->group_prototypeid = group_prototypeid;
953 zbx_vector_ptr_create(&group->hosts);
954 group->name_proto = NULL;
955 group->name = zbx_strdup(NULL, name_proto);
956 substitute_discovery_macros(&group->name, jp_row, ZBX_MACRO_ANY, NULL, 0);
957 zbx_lrtrim(group->name, ZBX_WHITESPACE);
958 group->name_orig = NULL;
959 group->lastcheck = 0;
960 group->ts_delete = 0;
961 group->flags = 0x00;
962 group->flags = ZBX_FLAG_LLD_GROUP_DISCOVERED;
963
964 zbx_vector_ptr_append(groups, group);
965 }
966 else
967 {
968 /* update an already existing group */
969
970 /* group name */
971 buffer = zbx_strdup(buffer, name_proto);
972 substitute_discovery_macros(&buffer, jp_row, ZBX_MACRO_ANY, NULL, 0);
973 zbx_lrtrim(buffer, ZBX_WHITESPACE);
974 if (0 != strcmp(group->name, buffer))
975 {
976 group->name_orig = group->name;
977 group->name = buffer;
978 buffer = NULL;
979 group->flags |= ZBX_FLAG_LLD_GROUP_UPDATE_NAME;
980 }
981
982 group->flags |= ZBX_FLAG_LLD_GROUP_DISCOVERED;
983 }
984 out:
985 zbx_free(buffer);
986
987 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%p", __function_name, group);
988
989 return group;
990 }
991
992 /******************************************************************************
993 * *
994 * Function: lld_groups_make *
995 * *
996 ******************************************************************************/
lld_groups_make(zbx_lld_host_t * host,zbx_vector_ptr_t * groups,const zbx_vector_ptr_t * group_prototypes,const struct zbx_json_parse * jp_row)997 static void lld_groups_make(zbx_lld_host_t *host, zbx_vector_ptr_t *groups, const zbx_vector_ptr_t *group_prototypes,
998 const struct zbx_json_parse *jp_row)
999 {
1000 const char *__function_name = "lld_groups_make";
1001
1002 int i;
1003
1004 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
1005
1006 for (i = 0; i < group_prototypes->values_num; i++)
1007 {
1008 const zbx_lld_group_prototype_t *group_prototype;
1009 zbx_lld_group_t *group;
1010
1011 group_prototype = (zbx_lld_group_prototype_t *)group_prototypes->values[i];
1012
1013 group = lld_group_make(groups, group_prototype->group_prototypeid, group_prototype->name, jp_row);
1014
1015 zbx_vector_ptr_append(&group->hosts, host);
1016 }
1017
1018 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
1019 }
1020
1021 /******************************************************************************
1022 * *
1023 * Function: lld_groups_validate *
1024 * *
1025 * Parameters: groups - [IN] list of groups; should be sorted by groupid *
1026 * *
1027 ******************************************************************************/
lld_groups_validate(zbx_vector_ptr_t * groups,char ** error)1028 void lld_groups_validate(zbx_vector_ptr_t *groups, char **error)
1029 {
1030 const char *__function_name = "lld_groups_validate";
1031
1032 DB_RESULT result;
1033 DB_ROW row;
1034 int i, j;
1035 zbx_lld_group_t *group, *group_b;
1036 zbx_vector_uint64_t groupids;
1037 zbx_vector_str_t names;
1038
1039 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
1040
1041 zbx_vector_uint64_create(&groupids);
1042 zbx_vector_str_create(&names); /* list of group names */
1043
1044 /* checking a group name validity */
1045 for (i = 0; i < groups->values_num; i++)
1046 {
1047 group = (zbx_lld_group_t *)groups->values[i];
1048
1049 if (0 == (group->flags & ZBX_FLAG_LLD_GROUP_DISCOVERED))
1050 continue;
1051
1052 /* only new groups or groups with changed group name will be validated */
1053 if (0 != group->groupid && 0 == (group->flags & ZBX_FLAG_LLD_GROUP_UPDATE_NAME))
1054 continue;
1055
1056 /* group name is valid utf8 sequence and has a valid length */
1057 if (SUCCEED == zbx_is_utf8(group->name) && '\0' != *group->name &&
1058 GROUP_NAME_LEN >= zbx_strlen_utf8(group->name))
1059 {
1060 continue;
1061 }
1062
1063 zbx_replace_invalid_utf8(group->name);
1064 *error = zbx_strdcatf(*error, "Cannot %s group: invalid group name \"%s\".\n",
1065 (0 != group->groupid ? "update" : "create"), group->name);
1066
1067 if (0 != group->groupid)
1068 {
1069 lld_field_str_rollback(&group->name, &group->name_orig, &group->flags,
1070 ZBX_FLAG_LLD_GROUP_UPDATE_NAME);
1071 }
1072 else
1073 group->flags &= ~ZBX_FLAG_LLD_GROUP_DISCOVERED;
1074 }
1075
1076 /* checking duplicated group names */
1077 for (i = 0; i < groups->values_num; i++)
1078 {
1079 group = (zbx_lld_group_t *)groups->values[i];
1080
1081 if (0 == (group->flags & ZBX_FLAG_LLD_GROUP_DISCOVERED))
1082 continue;
1083
1084 /* only new groups or groups with changed group name will be validated */
1085 if (0 != group->groupid && 0 == (group->flags & ZBX_FLAG_LLD_GROUP_UPDATE_NAME))
1086 continue;
1087
1088 for (j = 0; j < groups->values_num; j++)
1089 {
1090 group_b = (zbx_lld_group_t *)groups->values[j];
1091
1092 if (0 == (group_b->flags & ZBX_FLAG_LLD_GROUP_DISCOVERED) || i == j)
1093 continue;
1094
1095 if (0 != strcmp(group->name, group_b->name))
1096 continue;
1097
1098 *error = zbx_strdcatf(*error, "Cannot %s group:"
1099 " group with the same name \"%s\" already exists.\n",
1100 (0 != group->groupid ? "update" : "create"), group->name);
1101
1102 if (0 != group->groupid)
1103 {
1104 lld_field_str_rollback(&group->name, &group->name_orig, &group->flags,
1105 ZBX_FLAG_LLD_GROUP_UPDATE_NAME);
1106 }
1107 else
1108 group->flags &= ~ZBX_FLAG_LLD_GROUP_DISCOVERED;
1109 }
1110 }
1111
1112 /* checking duplicated group names and group names in DB */
1113
1114 for (i = 0; i < groups->values_num; i++)
1115 {
1116 group = (zbx_lld_group_t *)groups->values[i];
1117
1118 if (0 == (group->flags & ZBX_FLAG_LLD_GROUP_DISCOVERED))
1119 continue;
1120
1121 if (0 != group->groupid)
1122 zbx_vector_uint64_append(&groupids, group->groupid);
1123
1124 if (0 == group->groupid || 0 != (group->flags & ZBX_FLAG_LLD_GROUP_UPDATE_NAME))
1125 zbx_vector_str_append(&names, group->name);
1126 }
1127
1128 if (0 != names.values_num)
1129 {
1130 char *sql = NULL;
1131 size_t sql_alloc = 0, sql_offset = 0;
1132
1133 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "select name from groups where");
1134 DBadd_str_condition_alloc(&sql, &sql_alloc, &sql_offset, "name",
1135 (const char **)names.values, names.values_num);
1136
1137 if (0 != groupids.values_num)
1138 {
1139 zbx_vector_uint64_sort(&groupids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1140 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " and not");
1141 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "groupid",
1142 groupids.values, groupids.values_num);
1143 }
1144
1145 result = DBselect("%s", sql);
1146
1147 while (NULL != (row = DBfetch(result)))
1148 {
1149 for (i = 0; i < groups->values_num; i++)
1150 {
1151 group = (zbx_lld_group_t *)groups->values[i];
1152
1153 if (0 == (group->flags & ZBX_FLAG_LLD_GROUP_DISCOVERED))
1154 continue;
1155
1156 if (0 == strcmp(group->name, row[0]))
1157 {
1158 *error = zbx_strdcatf(*error, "Cannot %s group:"
1159 " group with the same name \"%s\" already exists.\n",
1160 (0 != group->groupid ? "update" : "create"), group->name);
1161
1162 if (0 != group->groupid)
1163 {
1164 lld_field_str_rollback(&group->name, &group->name_orig, &group->flags,
1165 ZBX_FLAG_LLD_GROUP_UPDATE_NAME);
1166 }
1167 else
1168 group->flags &= ~ZBX_FLAG_LLD_GROUP_DISCOVERED;
1169 }
1170 }
1171 }
1172 DBfree_result(result);
1173
1174 zbx_free(sql);
1175 }
1176
1177 zbx_vector_str_destroy(&names);
1178 zbx_vector_uint64_destroy(&groupids);
1179
1180 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
1181 }
1182
1183 /******************************************************************************
1184 * *
1185 * Function: lld_groups_save *
1186 * *
1187 * Parameters: groups - [IN/OUT] list of groups; should be sorted *
1188 * by groupid *
1189 * group_prototypes - [IN] list of group prototypes; should be *
1190 * sorted by group_prototypeid *
1191 * *
1192 ******************************************************************************/
lld_groups_save(zbx_vector_ptr_t * groups,const zbx_vector_ptr_t * group_prototypes)1193 static void lld_groups_save(zbx_vector_ptr_t *groups, const zbx_vector_ptr_t *group_prototypes)
1194 {
1195 const char *__function_name = "lld_groups_save";
1196
1197 int i, j, new_groups = 0, upd_groups = 0;
1198 zbx_lld_group_t *group;
1199 const zbx_lld_group_prototype_t *group_prototype;
1200 zbx_lld_host_t *host;
1201 zbx_uint64_t groupid = 0;
1202 char *sql = NULL, *name_esc, *name_proto_esc;
1203 size_t sql_alloc = 0, sql_offset = 0;
1204 zbx_db_insert_t db_insert, db_insert_gdiscovery;
1205
1206 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
1207
1208 for (i = 0; i < groups->values_num; i++)
1209 {
1210 group = (zbx_lld_group_t *)groups->values[i];
1211
1212 if (0 == (group->flags & ZBX_FLAG_LLD_GROUP_DISCOVERED))
1213 continue;
1214
1215 if (0 == group->groupid)
1216 new_groups++;
1217 else if (0 != (group->flags & ZBX_FLAG_LLD_GROUP_UPDATE))
1218 upd_groups++;
1219 }
1220
1221 if (0 == new_groups && 0 == upd_groups)
1222 goto out;
1223
1224 DBbegin();
1225
1226 if (0 != new_groups)
1227 {
1228 groupid = DBget_maxid_num("groups", new_groups);
1229
1230 zbx_db_insert_prepare(&db_insert, "groups", "groupid", "name", "flags", NULL);
1231
1232 zbx_db_insert_prepare(&db_insert_gdiscovery, "group_discovery", "groupid", "parent_group_prototypeid",
1233 "name", NULL);
1234 }
1235
1236 if (0 != upd_groups)
1237 {
1238 DBbegin_multiple_update(&sql, &sql_alloc, &sql_offset);
1239 }
1240
1241 for (i = 0; i < groups->values_num; i++)
1242 {
1243 group = (zbx_lld_group_t *)groups->values[i];
1244
1245 if (0 == (group->flags & ZBX_FLAG_LLD_GROUP_DISCOVERED))
1246 continue;
1247
1248 if (0 == group->groupid)
1249 {
1250 group->groupid = groupid++;
1251
1252 zbx_db_insert_add_values(&db_insert, group->groupid, group->name,
1253 (int)ZBX_FLAG_DISCOVERY_CREATED);
1254
1255 if (FAIL != (j = zbx_vector_ptr_bsearch(group_prototypes, &group->group_prototypeid,
1256 ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
1257 {
1258 group_prototype = (zbx_lld_group_prototype_t *)group_prototypes->values[j];
1259
1260 zbx_db_insert_add_values(&db_insert_gdiscovery, group->groupid,
1261 group->group_prototypeid, group_prototype->name);
1262 }
1263 else
1264 THIS_SHOULD_NEVER_HAPPEN;
1265
1266 for (j = 0; j < group->hosts.values_num; j++)
1267 {
1268 host = (zbx_lld_host_t *)group->hosts.values[j];
1269
1270 /* hosts will be linked to a new host groups */
1271 zbx_vector_uint64_append(&host->new_groupids, group->groupid);
1272 }
1273 }
1274 else
1275 {
1276 if (0 != (group->flags & ZBX_FLAG_LLD_GROUP_UPDATE))
1277 {
1278 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "update groups set ");
1279 if (0 != (group->flags & ZBX_FLAG_LLD_GROUP_UPDATE_NAME))
1280 {
1281 name_esc = DBdyn_escape_string(group->name);
1282
1283 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "name='%s'", name_esc);
1284
1285 zbx_free(name_esc);
1286 }
1287 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
1288 " where groupid=" ZBX_FS_UI64 ";\n", group->groupid);
1289 }
1290
1291 if (0 != (group->flags & ZBX_FLAG_LLD_GROUP_UPDATE_NAME))
1292 {
1293 if (FAIL != (j = zbx_vector_ptr_bsearch(group_prototypes, &group->group_prototypeid,
1294 ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
1295 {
1296 group_prototype = (zbx_lld_group_prototype_t *)group_prototypes->values[j];
1297
1298 name_proto_esc = DBdyn_escape_string(group_prototype->name);
1299
1300 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
1301 "update group_discovery"
1302 " set name='%s'"
1303 " where groupid=" ZBX_FS_UI64 ";\n",
1304 name_proto_esc, group->groupid);
1305
1306 zbx_free(name_proto_esc);
1307 }
1308 else
1309 THIS_SHOULD_NEVER_HAPPEN;
1310 }
1311 }
1312 }
1313
1314 if (0 != upd_groups)
1315 {
1316 DBend_multiple_update(&sql, &sql_alloc, &sql_offset);
1317 DBexecute("%s", sql);
1318 zbx_free(sql);
1319 }
1320
1321 if (0 != new_groups)
1322 {
1323 zbx_db_insert_execute(&db_insert);
1324 zbx_db_insert_clean(&db_insert);
1325
1326 zbx_db_insert_execute(&db_insert_gdiscovery);
1327 zbx_db_insert_clean(&db_insert_gdiscovery);
1328 }
1329
1330 DBcommit();
1331 out:
1332 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
1333 }
1334
1335 /******************************************************************************
1336 * *
1337 * Function: lld_hostmacros_get *
1338 * *
1339 * Purpose: retrieve list of host macros which should be present on the each *
1340 * discovered host *
1341 * *
1342 * Parameters: hostmacros - [OUT] list of host macros *
1343 * *
1344 ******************************************************************************/
lld_hostmacros_get(zbx_uint64_t lld_ruleid,zbx_vector_ptr_t * hostmacros)1345 static void lld_hostmacros_get(zbx_uint64_t lld_ruleid, zbx_vector_ptr_t *hostmacros)
1346 {
1347 const char *__function_name = "lld_hostmacros_get";
1348
1349 DB_RESULT result;
1350 DB_ROW row;
1351 zbx_lld_hostmacro_t *hostmacro;
1352
1353 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
1354
1355 result = DBselect(
1356 "select hm.macro,hm.value"
1357 " from hostmacro hm,items i"
1358 " where hm.hostid=i.hostid"
1359 " and i.itemid=" ZBX_FS_UI64,
1360 lld_ruleid);
1361
1362 while (NULL != (row = DBfetch(result)))
1363 {
1364 hostmacro = zbx_malloc(NULL, sizeof(zbx_lld_hostmacro_t));
1365
1366 hostmacro->macro = zbx_strdup(NULL, row[0]);
1367 hostmacro->value = zbx_strdup(NULL, row[1]);
1368
1369 zbx_vector_ptr_append(hostmacros, hostmacro);
1370 }
1371 DBfree_result(result);
1372
1373 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
1374 }
1375
1376 /******************************************************************************
1377 * *
1378 * Function: lld_hostmacros_make *
1379 * *
1380 * Parameters: hostmacros - [IN] list of host macros which *
1381 * should be present on the each *
1382 * discovered host *
1383 * hosts - [IN/OUT] list of hosts *
1384 * should be sorted by hostid *
1385 * del_hostmacroids - [OUT] list of host macros which should be *
1386 * deleted *
1387 * *
1388 ******************************************************************************/
lld_hostmacros_make(const zbx_vector_ptr_t * hostmacros,zbx_vector_ptr_t * hosts,zbx_vector_uint64_t * del_hostmacroids)1389 static void lld_hostmacros_make(const zbx_vector_ptr_t *hostmacros, zbx_vector_ptr_t *hosts,
1390 zbx_vector_uint64_t *del_hostmacroids)
1391 {
1392 const char *__function_name = "lld_hostmacros_make";
1393
1394 DB_RESULT result;
1395 DB_ROW row;
1396 int i, j;
1397 zbx_vector_uint64_t hostids;
1398 zbx_uint64_t hostmacroid, hostid;
1399 zbx_lld_host_t *host;
1400 zbx_lld_hostmacro_t *hostmacro = NULL;
1401
1402 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
1403
1404 zbx_vector_uint64_create(&hostids);
1405
1406 for (i = 0; i < hosts->values_num; i++)
1407 {
1408 host = (zbx_lld_host_t *)hosts->values[i];
1409
1410 if (0 == (host->flags & ZBX_FLAG_LLD_HOST_DISCOVERED))
1411 continue;
1412
1413 zbx_vector_ptr_reserve(&host->new_hostmacros, hostmacros->values_num);
1414 for (j = 0; j < hostmacros->values_num; j++)
1415 {
1416 hostmacro = zbx_malloc(NULL, sizeof(zbx_lld_hostmacro_t));
1417
1418 hostmacro->hostmacroid = 0;
1419 hostmacro->macro = zbx_strdup(NULL, ((zbx_lld_hostmacro_t *)hostmacros->values[j])->macro);
1420 hostmacro->value = zbx_strdup(NULL, ((zbx_lld_hostmacro_t *)hostmacros->values[j])->value);
1421
1422 zbx_vector_ptr_append(&host->new_hostmacros, hostmacro);
1423 }
1424
1425 if (0 != host->hostid)
1426 zbx_vector_uint64_append(&hostids, host->hostid);
1427 }
1428
1429 if (0 != hostids.values_num)
1430 {
1431 char *sql = NULL;
1432 size_t sql_alloc = 0, sql_offset = 0;
1433
1434 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
1435 "select hostmacroid,hostid,macro,value"
1436 " from hostmacro"
1437 " where");
1438 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hostid", hostids.values, hostids.values_num);
1439
1440 result = DBselect("%s", sql);
1441
1442 zbx_free(sql);
1443
1444 while (NULL != (row = DBfetch(result)))
1445 {
1446 ZBX_STR2UINT64(hostid, row[1]);
1447
1448 if (FAIL == (i = zbx_vector_ptr_bsearch(hosts, &hostid, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
1449 {
1450 THIS_SHOULD_NEVER_HAPPEN;
1451 continue;
1452 }
1453
1454 host = (zbx_lld_host_t *)hosts->values[i];
1455
1456 for (i = 0; i < host->new_hostmacros.values_num; i++)
1457 {
1458 hostmacro = (zbx_lld_hostmacro_t *)host->new_hostmacros.values[i];
1459
1460 if (0 == strcmp(hostmacro->macro, row[2]))
1461 break;
1462 }
1463
1464 if (i == host->new_hostmacros.values_num)
1465 {
1466 /* host macros which should be deleted */
1467 ZBX_STR2UINT64(hostmacroid, row[0]);
1468 zbx_vector_uint64_append(del_hostmacroids, hostmacroid);
1469 }
1470 else
1471 {
1472 /* host macros which are already added */
1473 if (0 == strcmp(hostmacro->value, row[3])) /* value doesn't changed */
1474 {
1475 lld_hostmacro_free(hostmacro);
1476 zbx_vector_ptr_remove(&host->new_hostmacros, i);
1477 }
1478 else
1479 ZBX_STR2UINT64(hostmacro->hostmacroid, row[0]);
1480 }
1481 }
1482 DBfree_result(result);
1483
1484 zbx_vector_uint64_sort(del_hostmacroids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1485 }
1486
1487 zbx_vector_uint64_destroy(&hostids);
1488
1489 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
1490 }
1491
1492 /******************************************************************************
1493 * *
1494 * Function: lld_templates_make *
1495 * *
1496 * Purpose: gets templates from a host prototype *
1497 * *
1498 * Parameters: parent_hostid - [IN] host prototype identifier *
1499 * hosts - [IN/OUT] list of hosts *
1500 * should be sorted by hostid *
1501 * *
1502 ******************************************************************************/
lld_templates_make(zbx_uint64_t parent_hostid,zbx_vector_ptr_t * hosts)1503 static void lld_templates_make(zbx_uint64_t parent_hostid, zbx_vector_ptr_t *hosts)
1504 {
1505 const char *__function_name = "lld_templates_make";
1506
1507 DB_RESULT result;
1508 DB_ROW row;
1509 zbx_vector_uint64_t templateids, hostids;
1510 zbx_uint64_t templateid, hostid;
1511 zbx_lld_host_t *host;
1512 int i, j;
1513
1514 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
1515
1516 zbx_vector_uint64_create(&templateids);
1517 zbx_vector_uint64_create(&hostids);
1518
1519 /* select templates which should be linked */
1520
1521 result = DBselect("select templateid from hosts_templates where hostid=" ZBX_FS_UI64, parent_hostid);
1522
1523 while (NULL != (row = DBfetch(result)))
1524 {
1525 ZBX_STR2UINT64(templateid, row[0]);
1526 zbx_vector_uint64_append(&templateids, templateid);
1527 }
1528 DBfree_result(result);
1529
1530 zbx_vector_uint64_sort(&templateids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1531
1532 /* select list of already created hosts */
1533
1534 for (i = 0; i < hosts->values_num; i++)
1535 {
1536 host = (zbx_lld_host_t *)hosts->values[i];
1537
1538 if (0 == (host->flags & ZBX_FLAG_LLD_HOST_DISCOVERED))
1539 continue;
1540
1541 zbx_vector_uint64_reserve(&host->lnk_templateids, templateids.values_num);
1542 for (j = 0; j < templateids.values_num; j++)
1543 zbx_vector_uint64_append(&host->lnk_templateids, templateids.values[j]);
1544
1545 if (0 != host->hostid)
1546 zbx_vector_uint64_append(&hostids, host->hostid);
1547 }
1548
1549 if (0 != hostids.values_num)
1550 {
1551 char *sql = NULL;
1552 size_t sql_alloc = 0, sql_offset = 0;
1553
1554 /* select already linked temlates */
1555
1556 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
1557 "select hostid,templateid"
1558 " from hosts_templates"
1559 " where");
1560 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hostid", hostids.values, hostids.values_num);
1561
1562 result = DBselect("%s", sql);
1563
1564 zbx_free(sql);
1565
1566 while (NULL != (row = DBfetch(result)))
1567 {
1568 ZBX_STR2UINT64(hostid, row[0]);
1569 ZBX_STR2UINT64(templateid, row[1]);
1570
1571 if (FAIL == (i = zbx_vector_ptr_bsearch(hosts, &hostid, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
1572 {
1573 THIS_SHOULD_NEVER_HAPPEN;
1574 continue;
1575 }
1576
1577 host = (zbx_lld_host_t *)hosts->values[i];
1578
1579 if (FAIL == (i = zbx_vector_uint64_bsearch(&host->lnk_templateids, templateid,
1580 ZBX_DEFAULT_UINT64_COMPARE_FUNC)))
1581 {
1582 /* templates which should be unlinked */
1583 zbx_vector_uint64_append(&host->del_templateids, templateid);
1584 }
1585 else
1586 {
1587 /* templates which are already linked */
1588 zbx_vector_uint64_remove(&host->lnk_templateids, i);
1589 }
1590 }
1591 DBfree_result(result);
1592
1593 for (i = 0; i < hosts->values_num; i++)
1594 {
1595 host = (zbx_lld_host_t *)hosts->values[i];
1596
1597 if (0 == (host->flags & ZBX_FLAG_LLD_HOST_DISCOVERED))
1598 continue;
1599
1600 zbx_vector_uint64_sort(&host->del_templateids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1601 }
1602 }
1603
1604 zbx_vector_uint64_destroy(&hostids);
1605 zbx_vector_uint64_destroy(&templateids);
1606
1607 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
1608 }
1609
1610 /******************************************************************************
1611 * *
1612 * Function: lld_hosts_save *
1613 * *
1614 * Parameters: hosts - [IN] list of hosts; *
1615 * should be sorted by hostid *
1616 * status - [IN] initial host status *
1617 * del_hostgroupids - [IN] host groups which should be deleted *
1618 * del_hostmacroids - [IN] host macros which should be deleted *
1619 * *
1620 ******************************************************************************/
lld_hosts_save(zbx_uint64_t parent_hostid,zbx_vector_ptr_t * hosts,const char * host_proto,zbx_uint64_t proxy_hostid,char ipmi_authtype,unsigned char ipmi_privilege,const char * ipmi_username,const char * ipmi_password,unsigned char status,char inventory_mode,unsigned char tls_connect,unsigned char tls_accept,const char * tls_issuer,const char * tls_subject,const char * tls_psk_identity,const char * tls_psk,const zbx_vector_uint64_t * del_hostgroupids,const zbx_vector_uint64_t * del_hostmacroids)1621 static void lld_hosts_save(zbx_uint64_t parent_hostid, zbx_vector_ptr_t *hosts, const char *host_proto,
1622 zbx_uint64_t proxy_hostid, char ipmi_authtype, unsigned char ipmi_privilege, const char *ipmi_username,
1623 const char *ipmi_password, unsigned char status, char inventory_mode, unsigned char tls_connect,
1624 unsigned char tls_accept, const char *tls_issuer, const char *tls_subject, const char *tls_psk_identity,
1625 const char *tls_psk, const zbx_vector_uint64_t *del_hostgroupids,
1626 const zbx_vector_uint64_t *del_hostmacroids)
1627 {
1628 const char *__function_name = "lld_hosts_save";
1629
1630 int i, j, new_hosts = 0, new_host_inventories = 0, upd_hosts = 0, new_hostgroups = 0,
1631 new_hostmacros = 0, upd_hostmacros = 0, new_interfaces = 0, upd_interfaces = 0;
1632 zbx_lld_host_t *host;
1633 zbx_lld_hostmacro_t *hostmacro;
1634 zbx_lld_interface_t *interface;
1635 zbx_vector_uint64_t upd_host_inventory_hostids, del_host_inventory_hostids, del_interfaceids;
1636 zbx_uint64_t hostid = 0, hostgroupid = 0, hostmacroid = 0, interfaceid = 0;
1637 char *sql1 = NULL, *sql2 = NULL, *value_esc;
1638 size_t sql1_alloc = 0, sql1_offset = 0,
1639 sql2_alloc = 0, sql2_offset = 0;
1640 zbx_db_insert_t db_insert, db_insert_hdiscovery, db_insert_hinventory, db_insert_hgroups,
1641 db_insert_hmacro, db_insert_interface, db_insert_idiscovery;
1642
1643 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
1644
1645 zbx_vector_uint64_create(&upd_host_inventory_hostids);
1646 zbx_vector_uint64_create(&del_host_inventory_hostids);
1647 zbx_vector_uint64_create(&del_interfaceids);
1648
1649 for (i = 0; i < hosts->values_num; i++)
1650 {
1651 host = (zbx_lld_host_t *)hosts->values[i];
1652
1653 if (0 == (host->flags & ZBX_FLAG_LLD_HOST_DISCOVERED))
1654 continue;
1655
1656 if (0 == host->hostid)
1657 {
1658 new_hosts++;
1659 if (HOST_INVENTORY_DISABLED != inventory_mode)
1660 new_host_inventories++;
1661 }
1662 else
1663 {
1664 if (0 != (host->flags & ZBX_FLAG_LLD_HOST_UPDATE))
1665 upd_hosts++;
1666
1667 if (host->inventory_mode != inventory_mode)
1668 {
1669 if (HOST_INVENTORY_DISABLED == inventory_mode)
1670 zbx_vector_uint64_append(&del_host_inventory_hostids, host->hostid);
1671 else if (HOST_INVENTORY_DISABLED == host->inventory_mode)
1672 new_host_inventories++;
1673 else
1674 zbx_vector_uint64_append(&upd_host_inventory_hostids, host->hostid);
1675 }
1676 }
1677
1678 new_hostgroups += host->new_groupids.values_num;
1679
1680 for (j = 0; j < host->interfaces.values_num; j++)
1681 {
1682 interface = (zbx_lld_interface_t *)host->interfaces.values[j];
1683
1684 if (0 == interface->interfaceid)
1685 new_interfaces++;
1686 else if (0 != (interface->flags & ZBX_FLAG_LLD_INTERFACE_UPDATE))
1687 upd_interfaces++;
1688 else if (0 != (interface->flags & ZBX_FLAG_LLD_INTERFACE_REMOVE))
1689 zbx_vector_uint64_append(&del_interfaceids, interface->interfaceid);
1690 }
1691
1692 for (j = 0; j < host->new_hostmacros.values_num; j++)
1693 {
1694 hostmacro = (zbx_lld_hostmacro_t *)host->new_hostmacros.values[j];
1695
1696 if (0 == hostmacro->hostmacroid)
1697 new_hostmacros++;
1698 else
1699 upd_hostmacros++;
1700 }
1701 }
1702
1703 if (0 == new_hosts && 0 == new_host_inventories && 0 == upd_hosts && 0 == upd_interfaces &&
1704 0 == upd_hostmacros && 0 == new_hostgroups && 0 == new_hostmacros && 0 == new_interfaces &&
1705 0 == del_hostgroupids->values_num && 0 == del_hostmacroids->values_num &&
1706 0 == upd_host_inventory_hostids.values_num && 0 == del_host_inventory_hostids.values_num &&
1707 0 == del_interfaceids.values_num)
1708 {
1709 goto out;
1710 }
1711
1712 DBbegin();
1713
1714 if (0 != new_hosts)
1715 {
1716 hostid = DBget_maxid_num("hosts", new_hosts);
1717
1718 zbx_db_insert_prepare(&db_insert, "hosts", "hostid", "host", "name", "proxy_hostid", "ipmi_authtype",
1719 "ipmi_privilege", "ipmi_username", "ipmi_password", "status", "flags", "tls_connect",
1720 "tls_accept", "tls_issuer", "tls_subject", "tls_psk_identity", "tls_psk", NULL);
1721
1722 zbx_db_insert_prepare(&db_insert_hdiscovery, "host_discovery", "hostid", "parent_hostid", "host", NULL);
1723 }
1724
1725 if (0 != new_host_inventories)
1726 {
1727 zbx_db_insert_prepare(&db_insert_hinventory, "host_inventory", "hostid", "inventory_mode", NULL);
1728 }
1729
1730 if (0 != upd_hosts || 0 != upd_interfaces || 0 != upd_hostmacros)
1731 {
1732 DBbegin_multiple_update(&sql1, &sql1_alloc, &sql1_offset);
1733 }
1734
1735 if (0 != new_hostgroups)
1736 {
1737 hostgroupid = DBget_maxid_num("hosts_groups", new_hostgroups);
1738
1739 zbx_db_insert_prepare(&db_insert_hgroups, "hosts_groups", "hostgroupid", "hostid", "groupid", NULL);
1740 }
1741
1742 if (0 != new_hostmacros)
1743 {
1744 hostmacroid = DBget_maxid_num("hostmacro", new_hostmacros);
1745
1746 zbx_db_insert_prepare(&db_insert_hmacro, "hostmacro", "hostmacroid", "hostid", "macro", "value", NULL);
1747 }
1748
1749 if (0 != new_interfaces)
1750 {
1751 interfaceid = DBget_maxid_num("interface", new_interfaces);
1752
1753 zbx_db_insert_prepare(&db_insert_interface, "interface", "interfaceid", "hostid", "type", "main",
1754 "useip", "ip", "dns", "port", "bulk", NULL);
1755
1756 zbx_db_insert_prepare(&db_insert_idiscovery, "interface_discovery", "interfaceid",
1757 "parent_interfaceid", NULL);
1758 }
1759
1760 for (i = 0; i < hosts->values_num; i++)
1761 {
1762 host = (zbx_lld_host_t *)hosts->values[i];
1763
1764 if (0 == (host->flags & ZBX_FLAG_LLD_HOST_DISCOVERED))
1765 continue;
1766
1767 if (0 == host->hostid)
1768 {
1769 host->hostid = hostid++;
1770
1771 zbx_db_insert_add_values(&db_insert, host->hostid, host->host, host->name, proxy_hostid,
1772 (int)ipmi_authtype, (int)ipmi_privilege, ipmi_username, ipmi_password,
1773 (int)status, (int)ZBX_FLAG_DISCOVERY_CREATED, (int)tls_connect,
1774 (int)tls_accept, tls_issuer, tls_subject, tls_psk_identity, tls_psk);
1775
1776 zbx_db_insert_add_values(&db_insert_hdiscovery, host->hostid, parent_hostid, host_proto);
1777
1778 if (HOST_INVENTORY_DISABLED != inventory_mode)
1779 zbx_db_insert_add_values(&db_insert_hinventory, host->hostid, (int)inventory_mode);
1780 }
1781 else
1782 {
1783 if (0 != (host->flags & ZBX_FLAG_LLD_HOST_UPDATE))
1784 {
1785 const char *d = "";
1786
1787 zbx_strcpy_alloc(&sql1, &sql1_alloc, &sql1_offset, "update hosts set ");
1788 if (0 != (host->flags & ZBX_FLAG_LLD_HOST_UPDATE_HOST))
1789 {
1790 value_esc = DBdyn_escape_string(host->host);
1791
1792 zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset, "host='%s'", value_esc);
1793 d = ",";
1794
1795 zbx_free(value_esc);
1796 }
1797 if (0 != (host->flags & ZBX_FLAG_LLD_HOST_UPDATE_NAME))
1798 {
1799 value_esc = DBdyn_escape_string(host->name);
1800
1801 zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset,
1802 "%sname='%s'", d, value_esc);
1803 d = ",";
1804
1805 zbx_free(value_esc);
1806 }
1807 if (0 != (host->flags & ZBX_FLAG_LLD_HOST_UPDATE_PROXY))
1808 {
1809 zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset,
1810 "%sproxy_hostid=%s", d, DBsql_id_ins(proxy_hostid));
1811 d = ",";
1812 }
1813 if (0 != (host->flags & ZBX_FLAG_LLD_HOST_UPDATE_IPMI_AUTH))
1814 {
1815 zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset,
1816 "%sipmi_authtype=%d", d, (int)ipmi_authtype);
1817 d = ",";
1818 }
1819 if (0 != (host->flags & ZBX_FLAG_LLD_HOST_UPDATE_IPMI_PRIV))
1820 {
1821 zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset,
1822 "%sipmi_privilege=%d", d, (int)ipmi_privilege);
1823 d = ",";
1824 }
1825 if (0 != (host->flags & ZBX_FLAG_LLD_HOST_UPDATE_IPMI_USER))
1826 {
1827 value_esc = DBdyn_escape_string(ipmi_username);
1828
1829 zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset,
1830 "%sipmi_username='%s'", d, value_esc);
1831 d = ",";
1832
1833 zbx_free(value_esc);
1834 }
1835 if (0 != (host->flags & ZBX_FLAG_LLD_HOST_UPDATE_IPMI_PASS))
1836 {
1837 value_esc = DBdyn_escape_string(ipmi_password);
1838
1839 zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset,
1840 "%sipmi_password='%s'", d, value_esc);
1841 d = ",";
1842
1843 zbx_free(value_esc);
1844 }
1845 if (0 != (host->flags & ZBX_FLAG_LLD_HOST_UPDATE_TLS_CONNECT))
1846 {
1847 zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset,
1848 "%stls_connect=%d", d, tls_connect);
1849 d = ",";
1850 }
1851 if (0 != (host->flags & ZBX_FLAG_LLD_HOST_UPDATE_TLS_ACCEPT))
1852 {
1853 zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset,
1854 "%stls_accept=%d", d, tls_accept);
1855 d = ",";
1856 }
1857 if (0 != (host->flags & ZBX_FLAG_LLD_HOST_UPDATE_TLS_ISSUER))
1858 {
1859 value_esc = DBdyn_escape_string(tls_issuer);
1860
1861 zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset,
1862 "%stls_issuer='%s'", d, value_esc);
1863 d = ",";
1864
1865 zbx_free(value_esc);
1866 }
1867 if (0 != (host->flags & ZBX_FLAG_LLD_HOST_UPDATE_TLS_SUBJECT))
1868 {
1869 value_esc = DBdyn_escape_string(tls_subject);
1870
1871 zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset,
1872 "%stls_subject='%s'", d, value_esc);
1873 d = ",";
1874
1875 zbx_free(value_esc);
1876 }
1877 if (0 != (host->flags & ZBX_FLAG_LLD_HOST_UPDATE_TLS_PSK_IDENTITY))
1878 {
1879 value_esc = DBdyn_escape_string(tls_psk_identity);
1880
1881 zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset,
1882 "%stls_psk_identity='%s'", d, value_esc);
1883 d = ",";
1884
1885 zbx_free(value_esc);
1886 }
1887 if (0 != (host->flags & ZBX_FLAG_LLD_HOST_UPDATE_TLS_PSK))
1888 {
1889 value_esc = DBdyn_escape_string(tls_psk);
1890
1891 zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset,
1892 "%stls_psk='%s'", d, value_esc);
1893
1894 zbx_free(value_esc);
1895 }
1896 zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset, " where hostid=" ZBX_FS_UI64 ";\n",
1897 host->hostid);
1898 }
1899
1900 if (host->inventory_mode != inventory_mode && HOST_INVENTORY_DISABLED == host->inventory_mode)
1901 zbx_db_insert_add_values(&db_insert_hinventory, host->hostid, (int)inventory_mode);
1902
1903 if (0 != (host->flags & ZBX_FLAG_LLD_HOST_UPDATE_HOST))
1904 {
1905 value_esc = DBdyn_escape_string(host_proto);
1906
1907 zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset,
1908 "update host_discovery"
1909 " set host='%s'"
1910 " where hostid=" ZBX_FS_UI64 ";\n",
1911 value_esc, host->hostid);
1912
1913 zbx_free(value_esc);
1914 }
1915 }
1916
1917 for (j = 0; j < host->interfaces.values_num; j++)
1918 {
1919 interface = (zbx_lld_interface_t *)host->interfaces.values[j];
1920
1921 if (0 == interface->interfaceid)
1922 {
1923 interface->interfaceid = interfaceid++;
1924
1925 zbx_db_insert_add_values(&db_insert_interface, interface->interfaceid, host->hostid,
1926 (int)interface->type, (int)interface->main, (int)interface->useip,
1927 interface->ip, interface->dns, interface->port, (int)interface->bulk);
1928
1929 zbx_db_insert_add_values(&db_insert_idiscovery, interface->interfaceid,
1930 interface->parent_interfaceid);
1931 }
1932 else if (0 != (interface->flags & ZBX_FLAG_LLD_INTERFACE_UPDATE))
1933 {
1934 const char *d = "";
1935
1936 zbx_strcpy_alloc(&sql1, &sql1_alloc, &sql1_offset, "update interface set ");
1937 if (0 != (interface->flags & ZBX_FLAG_LLD_INTERFACE_UPDATE_TYPE))
1938 {
1939 zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset, "type=%d",
1940 (int)interface->type);
1941 d = ",";
1942 }
1943 if (0 != (interface->flags & ZBX_FLAG_LLD_INTERFACE_UPDATE_MAIN))
1944 {
1945 zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset, "%smain=%d",
1946 d, (int)interface->main);
1947 d = ",";
1948 }
1949 if (0 != (interface->flags & ZBX_FLAG_LLD_INTERFACE_UPDATE_USEIP))
1950 {
1951 zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset, "%suseip=%d",
1952 d, (int)interface->useip);
1953 d = ",";
1954 }
1955 if (0 != (interface->flags & ZBX_FLAG_LLD_INTERFACE_UPDATE_IP))
1956 {
1957 value_esc = DBdyn_escape_string(interface->ip);
1958 zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset, "%sip='%s'", d, value_esc);
1959 zbx_free(value_esc);
1960 d = ",";
1961 }
1962 if (0 != (interface->flags & ZBX_FLAG_LLD_INTERFACE_UPDATE_DNS))
1963 {
1964 value_esc = DBdyn_escape_string(interface->dns);
1965 zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset, "%sdns='%s'", d, value_esc);
1966 zbx_free(value_esc);
1967 d = ",";
1968 }
1969 if (0 != (interface->flags & ZBX_FLAG_LLD_INTERFACE_UPDATE_PORT))
1970 {
1971 value_esc = DBdyn_escape_string(interface->port);
1972 zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset, "%sport='%s'",
1973 d, value_esc);
1974 zbx_free(value_esc);
1975 d = ",";
1976 }
1977 if (0 != (interface->flags & ZBX_FLAG_LLD_INTERFACE_UPDATE_BULK))
1978 {
1979 zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset, "%sbulk=%d",
1980 d, (int)interface->bulk);
1981 }
1982 zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset,
1983 " where interfaceid=" ZBX_FS_UI64 ";\n", interface->interfaceid);
1984 }
1985 }
1986
1987 for (j = 0; j < host->new_groupids.values_num; j++)
1988 {
1989 zbx_db_insert_add_values(&db_insert_hgroups, hostgroupid++, host->hostid,
1990 host->new_groupids.values[j]);
1991 }
1992
1993 for (j = 0; j < host->new_hostmacros.values_num; j++)
1994 {
1995 hostmacro = (zbx_lld_hostmacro_t *)host->new_hostmacros.values[j];
1996
1997 value_esc = DBdyn_escape_string(hostmacro->value);
1998
1999 if (0 == hostmacro->hostmacroid)
2000 {
2001 zbx_db_insert_add_values(&db_insert_hmacro, hostmacroid++, host->hostid,
2002 hostmacro->macro, hostmacro->value);
2003 }
2004 else
2005 {
2006 zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset,
2007 "update hostmacro"
2008 " set value='%s'"
2009 " where hostmacroid=" ZBX_FS_UI64 ";\n",
2010 value_esc, hostmacro->hostmacroid);
2011 }
2012
2013 zbx_free(value_esc);
2014 }
2015 }
2016
2017 if (0 != new_hosts)
2018 {
2019 zbx_db_insert_execute(&db_insert);
2020 zbx_db_insert_clean(&db_insert);
2021
2022 zbx_db_insert_execute(&db_insert_hdiscovery);
2023 zbx_db_insert_clean(&db_insert_hdiscovery);
2024 }
2025
2026 if (0 != new_host_inventories)
2027 {
2028 zbx_db_insert_execute(&db_insert_hinventory);
2029 zbx_db_insert_clean(&db_insert_hinventory);
2030 }
2031
2032 if (0 != new_hostgroups)
2033 {
2034 zbx_db_insert_execute(&db_insert_hgroups);
2035 zbx_db_insert_clean(&db_insert_hgroups);
2036 }
2037
2038 if (0 != new_hostmacros)
2039 {
2040 zbx_db_insert_execute(&db_insert_hmacro);
2041 zbx_db_insert_clean(&db_insert_hmacro);
2042 }
2043
2044 if (0 != new_interfaces)
2045 {
2046 zbx_db_insert_execute(&db_insert_interface);
2047 zbx_db_insert_clean(&db_insert_interface);
2048
2049 zbx_db_insert_execute(&db_insert_idiscovery);
2050 zbx_db_insert_clean(&db_insert_idiscovery);
2051 }
2052
2053 if (0 != upd_hosts || 0 != upd_interfaces || 0 != upd_hostmacros)
2054 {
2055 DBend_multiple_update(&sql1, &sql1_alloc, &sql1_offset);
2056 DBexecute("%s", sql1);
2057 zbx_free(sql1);
2058 }
2059
2060 if (0 != del_hostgroupids->values_num || 0 != del_hostmacroids->values_num ||
2061 0 != upd_host_inventory_hostids.values_num || 0 != del_host_inventory_hostids.values_num ||
2062 0 != del_interfaceids.values_num)
2063 {
2064 DBbegin_multiple_update(&sql2, &sql2_alloc, &sql2_offset);
2065
2066 if (0 != del_hostgroupids->values_num)
2067 {
2068 zbx_strcpy_alloc(&sql2, &sql2_alloc, &sql2_offset, "delete from hosts_groups where");
2069 DBadd_condition_alloc(&sql2, &sql2_alloc, &sql2_offset, "hostgroupid",
2070 del_hostgroupids->values, del_hostgroupids->values_num);
2071 zbx_strcpy_alloc(&sql2, &sql2_alloc, &sql2_offset, ";\n");
2072 }
2073
2074 if (0 != del_hostmacroids->values_num)
2075 {
2076 zbx_strcpy_alloc(&sql2, &sql2_alloc, &sql2_offset, "delete from hostmacro where");
2077 DBadd_condition_alloc(&sql2, &sql2_alloc, &sql2_offset, "hostmacroid",
2078 del_hostmacroids->values, del_hostmacroids->values_num);
2079 zbx_strcpy_alloc(&sql2, &sql2_alloc, &sql2_offset, ";\n");
2080 }
2081
2082 if (0 != upd_host_inventory_hostids.values_num)
2083 {
2084 zbx_snprintf_alloc(&sql2, &sql2_alloc, &sql2_offset,
2085 "update host_inventory set inventory_mode=%d where", (int)inventory_mode);
2086 DBadd_condition_alloc(&sql2, &sql2_alloc, &sql2_offset, "hostid",
2087 upd_host_inventory_hostids.values, upd_host_inventory_hostids.values_num);
2088 zbx_strcpy_alloc(&sql2, &sql2_alloc, &sql2_offset, ";\n");
2089 }
2090
2091 if (0 != del_host_inventory_hostids.values_num)
2092 {
2093 zbx_strcpy_alloc(&sql2, &sql2_alloc, &sql2_offset, "delete from host_inventory where");
2094 DBadd_condition_alloc(&sql2, &sql2_alloc, &sql2_offset, "hostid",
2095 del_host_inventory_hostids.values, del_host_inventory_hostids.values_num);
2096 zbx_strcpy_alloc(&sql2, &sql2_alloc, &sql2_offset, ";\n");
2097 }
2098
2099 if (0 != del_interfaceids.values_num)
2100 {
2101 zbx_strcpy_alloc(&sql2, &sql2_alloc, &sql2_offset, "delete from interface where");
2102 DBadd_condition_alloc(&sql2, &sql2_alloc, &sql2_offset, "interfaceid",
2103 del_interfaceids.values, del_interfaceids.values_num);
2104 zbx_strcpy_alloc(&sql2, &sql2_alloc, &sql2_offset, ";\n");
2105 }
2106
2107 DBend_multiple_update(&sql2, &sql2_alloc, &sql2_offset);
2108 DBexecute("%s", sql2);
2109 zbx_free(sql2);
2110 }
2111
2112 DBcommit();
2113 out:
2114 zbx_vector_uint64_destroy(&del_interfaceids);
2115 zbx_vector_uint64_destroy(&del_host_inventory_hostids);
2116 zbx_vector_uint64_destroy(&upd_host_inventory_hostids);
2117
2118 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
2119 }
2120
2121 /******************************************************************************
2122 * *
2123 * Function: lld_templates_link *
2124 * *
2125 ******************************************************************************/
lld_templates_link(const zbx_vector_ptr_t * hosts,char ** error)2126 static void lld_templates_link(const zbx_vector_ptr_t *hosts, char **error)
2127 {
2128 const char *__function_name = "lld_templates_link";
2129
2130 int i;
2131 zbx_lld_host_t *host;
2132 char *err;
2133
2134 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
2135
2136 for (i = 0; i < hosts->values_num; i++)
2137 {
2138 host = (zbx_lld_host_t *)hosts->values[i];
2139
2140 if (0 == (host->flags & ZBX_FLAG_LLD_HOST_DISCOVERED))
2141 continue;
2142
2143 if (0 != host->del_templateids.values_num)
2144 {
2145 if (SUCCEED != DBdelete_template_elements(host->hostid, &host->del_templateids, &err))
2146 {
2147 *error = zbx_strdcatf(*error, "Cannot unlink template: %s.\n", err);
2148 zbx_free(err);
2149 }
2150 }
2151
2152 if (0 != host->lnk_templateids.values_num)
2153 {
2154 if (SUCCEED != DBcopy_template_elements(host->hostid, &host->lnk_templateids, &err))
2155 {
2156 *error = zbx_strdcatf(*error, "Cannot link template(s) %s.\n", err);
2157 zbx_free(err);
2158 }
2159 }
2160 }
2161
2162 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
2163 }
2164
2165 /******************************************************************************
2166 * *
2167 * Function: lld_hosts_remove *
2168 * *
2169 * Purpose: updates host_discovery.lastcheck and host_discovery.ts_delete *
2170 * fields; removes lost resources *
2171 * *
2172 ******************************************************************************/
lld_hosts_remove(const zbx_vector_ptr_t * hosts,unsigned short lifetime,int lastcheck)2173 static void lld_hosts_remove(const zbx_vector_ptr_t *hosts, unsigned short lifetime, int lastcheck)
2174 {
2175 char *sql = NULL;
2176 size_t sql_alloc = 0, sql_offset = 0;
2177 const zbx_lld_host_t *host;
2178 zbx_vector_uint64_t del_hostids, lc_hostids, ts_hostids;
2179 int i, lifetime_sec;
2180
2181 if (0 == hosts->values_num)
2182 return;
2183
2184 lifetime_sec = lifetime * SEC_PER_DAY;
2185
2186 zbx_vector_uint64_create(&del_hostids);
2187 zbx_vector_uint64_create(&lc_hostids);
2188 zbx_vector_uint64_create(&ts_hostids);
2189
2190 DBbegin_multiple_update(&sql, &sql_alloc, &sql_offset);
2191
2192 for (i = 0; i < hosts->values_num; i++)
2193 {
2194 host = (zbx_lld_host_t *)hosts->values[i];
2195
2196 if (0 == host->hostid)
2197 continue;
2198
2199 if (0 == (host->flags & ZBX_FLAG_LLD_HOST_DISCOVERED))
2200 {
2201 if (host->lastcheck < lastcheck - lifetime_sec)
2202 {
2203 zbx_vector_uint64_append(&del_hostids, host->hostid);
2204 }
2205 else if (host->ts_delete != host->lastcheck + lifetime_sec)
2206 {
2207 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
2208 "update host_discovery"
2209 " set ts_delete=%d"
2210 " where hostid=" ZBX_FS_UI64 ";\n",
2211 host->lastcheck + lifetime_sec, host->hostid);
2212 }
2213 }
2214 else
2215 {
2216 zbx_vector_uint64_append(&lc_hostids, host->hostid);
2217 if (0 != host->ts_delete)
2218 zbx_vector_uint64_append(&ts_hostids, host->hostid);
2219 }
2220 }
2221
2222 if (0 != lc_hostids.values_num)
2223 {
2224 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "update host_discovery set lastcheck=%d where",
2225 lastcheck);
2226 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hostid",
2227 lc_hostids.values, lc_hostids.values_num);
2228 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ";\n");
2229 }
2230
2231 if (0 != ts_hostids.values_num)
2232 {
2233 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "update host_discovery set ts_delete=0 where");
2234 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hostid",
2235 ts_hostids.values, ts_hostids.values_num);
2236 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ";\n");
2237 }
2238
2239 if (16 < sql_offset) /* in ORACLE always present begin..end; */
2240 {
2241 DBend_multiple_update(&sql, &sql_alloc, &sql_offset);
2242
2243 DBbegin();
2244
2245 DBexecute("%s", sql);
2246
2247 DBcommit();
2248 }
2249
2250 zbx_free(sql);
2251
2252 if (0 != del_hostids.values_num)
2253 {
2254 zbx_vector_uint64_sort(&del_hostids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
2255
2256 DBbegin();
2257
2258 DBdelete_hosts(&del_hostids);
2259
2260 DBcommit();
2261 }
2262
2263 zbx_vector_uint64_destroy(&ts_hostids);
2264 zbx_vector_uint64_destroy(&lc_hostids);
2265 zbx_vector_uint64_destroy(&del_hostids);
2266 }
2267
2268 /******************************************************************************
2269 * *
2270 * Function: lld_groups_remove *
2271 * *
2272 * Purpose: updates group_discovery.lastcheck and group_discovery.ts_delete *
2273 * fields; removes lost resources *
2274 * *
2275 ******************************************************************************/
lld_groups_remove(const zbx_vector_ptr_t * groups,unsigned short lifetime,int lastcheck)2276 static void lld_groups_remove(const zbx_vector_ptr_t *groups, unsigned short lifetime, int lastcheck)
2277 {
2278 char *sql = NULL;
2279 size_t sql_alloc = 0, sql_offset = 0;
2280 const zbx_lld_group_t *group;
2281 zbx_vector_uint64_t del_groupids, lc_groupids, ts_groupids;
2282 int i, lifetime_sec;
2283
2284 if (0 == groups->values_num)
2285 return;
2286
2287 lifetime_sec = lifetime * SEC_PER_DAY;
2288
2289 zbx_vector_uint64_create(&del_groupids);
2290 zbx_vector_uint64_create(&lc_groupids);
2291 zbx_vector_uint64_create(&ts_groupids);
2292
2293 DBbegin_multiple_update(&sql, &sql_alloc, &sql_offset);
2294
2295 for (i = 0; i < groups->values_num; i++)
2296 {
2297 group = (zbx_lld_group_t *)groups->values[i];
2298
2299 if (0 == group->groupid)
2300 continue;
2301
2302 if (0 == (group->flags & ZBX_FLAG_LLD_GROUP_DISCOVERED))
2303 {
2304 if (group->lastcheck < lastcheck - lifetime_sec)
2305 {
2306 zbx_vector_uint64_append(&del_groupids, group->groupid);
2307 }
2308 else if (group->ts_delete != group->lastcheck + lifetime_sec)
2309 {
2310 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
2311 "update group_discovery"
2312 " set ts_delete=%d"
2313 " where groupid=" ZBX_FS_UI64 ";\n",
2314 group->lastcheck + lifetime_sec, group->groupid);
2315 }
2316 }
2317 else
2318 {
2319 zbx_vector_uint64_append(&lc_groupids, group->groupid);
2320 if (0 != group->ts_delete)
2321 zbx_vector_uint64_append(&ts_groupids, group->groupid);
2322 }
2323 }
2324
2325 if (0 != lc_groupids.values_num)
2326 {
2327 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "update group_discovery set lastcheck=%d where",
2328 lastcheck);
2329 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "groupid",
2330 lc_groupids.values, lc_groupids.values_num);
2331 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ";\n");
2332 }
2333
2334 if (0 != ts_groupids.values_num)
2335 {
2336 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "update group_discovery set ts_delete=0 where");
2337 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "groupid",
2338 ts_groupids.values, ts_groupids.values_num);
2339 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ";\n");
2340 }
2341
2342 if (16 < sql_offset) /* in ORACLE always present begin..end; */
2343 {
2344 DBend_multiple_update(&sql, &sql_alloc, &sql_offset);
2345
2346 DBbegin();
2347
2348 DBexecute("%s", sql);
2349
2350 DBcommit();
2351 }
2352
2353 zbx_free(sql);
2354
2355 if (0 != del_groupids.values_num)
2356 {
2357 zbx_vector_uint64_sort(&del_groupids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
2358
2359 DBbegin();
2360
2361 DBdelete_groups(&del_groupids);
2362
2363 DBcommit();
2364 }
2365
2366 zbx_vector_uint64_destroy(&ts_groupids);
2367 zbx_vector_uint64_destroy(&lc_groupids);
2368 zbx_vector_uint64_destroy(&del_groupids);
2369 }
2370
2371 /******************************************************************************
2372 * *
2373 * Function: lld_interfaces_get *
2374 * *
2375 * Purpose: retrieves list of interfaces from the lld rule's host *
2376 * *
2377 ******************************************************************************/
lld_interfaces_get(zbx_uint64_t lld_ruleid,zbx_vector_ptr_t * interfaces)2378 static void lld_interfaces_get(zbx_uint64_t lld_ruleid, zbx_vector_ptr_t *interfaces)
2379 {
2380 DB_RESULT result;
2381 DB_ROW row;
2382 zbx_lld_interface_t *interface;
2383
2384 result = DBselect(
2385 "select hi.interfaceid,hi.type,hi.main,hi.useip,hi.ip,hi.dns,hi.port,hi.bulk"
2386 " from interface hi,items i"
2387 " where hi.hostid=i.hostid"
2388 " and i.itemid=" ZBX_FS_UI64,
2389 lld_ruleid);
2390
2391 while (NULL != (row = DBfetch(result)))
2392 {
2393 interface = zbx_malloc(NULL, sizeof(zbx_lld_interface_t));
2394
2395 ZBX_STR2UINT64(interface->interfaceid, row[0]);
2396 interface->type = (unsigned char)atoi(row[1]);
2397 interface->main = (unsigned char)atoi(row[2]);
2398 interface->useip = (unsigned char)atoi(row[3]);
2399 interface->ip = zbx_strdup(NULL, row[4]);
2400 interface->dns = zbx_strdup(NULL, row[5]);
2401 interface->port = zbx_strdup(NULL, row[6]);
2402 interface->bulk = (unsigned char)atoi(row[7]);
2403
2404 zbx_vector_ptr_append(interfaces, interface);
2405 }
2406 DBfree_result(result);
2407
2408 zbx_vector_ptr_sort(interfaces, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
2409 }
2410
2411 /******************************************************************************
2412 * *
2413 * Function: lld_interface_make *
2414 * *
2415 ******************************************************************************/
lld_interface_make(zbx_vector_ptr_t * interfaces,zbx_uint64_t parent_interfaceid,zbx_uint64_t interfaceid,unsigned char type,unsigned char main,unsigned char useip,const char * ip,const char * dns,const char * port,unsigned char bulk)2416 static void lld_interface_make(zbx_vector_ptr_t *interfaces, zbx_uint64_t parent_interfaceid,
2417 zbx_uint64_t interfaceid, unsigned char type, unsigned char main, unsigned char useip, const char *ip,
2418 const char *dns, const char *port, unsigned char bulk)
2419 {
2420 zbx_lld_interface_t *interface = NULL;
2421 int i;
2422
2423 for (i = 0; i < interfaces->values_num; i++)
2424 {
2425 interface = (zbx_lld_interface_t *)interfaces->values[i];
2426
2427 if (0 != interface->interfaceid)
2428 continue;
2429
2430 if (interface->parent_interfaceid == parent_interfaceid)
2431 break;
2432 }
2433
2434 if (i == interfaces->values_num)
2435 {
2436 /* interface which should be deleted */
2437 interface = zbx_malloc(NULL, sizeof(zbx_lld_interface_t));
2438
2439 interface->interfaceid = interfaceid;
2440 interface->parent_interfaceid = 0;
2441 interface->type = type;
2442 interface->main = main;
2443 interface->useip = 0;
2444 interface->ip = NULL;
2445 interface->dns = NULL;
2446 interface->port = NULL;
2447 interface->bulk = SNMP_BULK_ENABLED;
2448 interface->flags = ZBX_FLAG_LLD_INTERFACE_REMOVE;
2449
2450 zbx_vector_ptr_append(interfaces, interface);
2451 }
2452 else
2453 {
2454 /* interface which are already added */
2455 if (interface->type != type)
2456 {
2457 interface->type_orig = type;
2458 interface->flags |= ZBX_FLAG_LLD_INTERFACE_UPDATE_TYPE;
2459 }
2460 if (interface->main != main)
2461 {
2462 interface->main_orig = main;
2463 interface->flags |= ZBX_FLAG_LLD_INTERFACE_UPDATE_MAIN;
2464 }
2465 if (interface->useip != useip)
2466 interface->flags |= ZBX_FLAG_LLD_INTERFACE_UPDATE_USEIP;
2467 if (0 != strcmp(interface->ip, ip))
2468 interface->flags |= ZBX_FLAG_LLD_INTERFACE_UPDATE_IP;
2469 if (0 != strcmp(interface->dns, dns))
2470 interface->flags |= ZBX_FLAG_LLD_INTERFACE_UPDATE_DNS;
2471 if (0 != strcmp(interface->port, port))
2472 interface->flags |= ZBX_FLAG_LLD_INTERFACE_UPDATE_PORT;
2473 if (interface->bulk != bulk)
2474 interface->flags |= ZBX_FLAG_LLD_INTERFACE_UPDATE_BULK;
2475 }
2476
2477 interface->interfaceid = interfaceid;
2478 }
2479
2480 /******************************************************************************
2481 * *
2482 * Function: lld_interfaces_make *
2483 * *
2484 * Parameters: interfaces - [IN] sorted list of interfaces which *
2485 * should be present on the each *
2486 * discovered host *
2487 * hosts - [IN/OUT] sorted list of hosts *
2488 * *
2489 ******************************************************************************/
lld_interfaces_make(const zbx_vector_ptr_t * interfaces,zbx_vector_ptr_t * hosts)2490 static void lld_interfaces_make(const zbx_vector_ptr_t *interfaces, zbx_vector_ptr_t *hosts)
2491 {
2492 const char *__function_name = "lld_interfaces_make";
2493
2494 DB_RESULT result;
2495 DB_ROW row;
2496 int i, j;
2497 zbx_vector_uint64_t hostids;
2498 zbx_uint64_t parent_interfaceid, hostid, interfaceid;
2499 zbx_lld_host_t *host;
2500 zbx_lld_interface_t *new_interface, *interface;
2501
2502 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
2503
2504 zbx_vector_uint64_create(&hostids);
2505
2506 for (i = 0; i < hosts->values_num; i++)
2507 {
2508 host = (zbx_lld_host_t *)hosts->values[i];
2509
2510 if (0 == (host->flags & ZBX_FLAG_LLD_HOST_DISCOVERED))
2511 continue;
2512
2513 zbx_vector_ptr_reserve(&host->interfaces, interfaces->values_num);
2514 for (j = 0; j < interfaces->values_num; j++)
2515 {
2516 interface = (zbx_lld_interface_t *)interfaces->values[j];
2517
2518 new_interface = zbx_malloc(NULL, sizeof(zbx_lld_interface_t));
2519
2520 new_interface->interfaceid = 0;
2521 new_interface->parent_interfaceid = interface->interfaceid;
2522 new_interface->type = interface->type;
2523 new_interface->main = interface->main;
2524 new_interface->useip = interface->useip;
2525 new_interface->ip = zbx_strdup(NULL, interface->ip);
2526 new_interface->dns = zbx_strdup(NULL, interface->dns);
2527 new_interface->port = zbx_strdup(NULL, interface->port);
2528 new_interface->bulk = interface->bulk;
2529 new_interface->flags = 0x00;
2530
2531 zbx_vector_ptr_append(&host->interfaces, new_interface);
2532 }
2533
2534 if (0 != host->hostid)
2535 zbx_vector_uint64_append(&hostids, host->hostid);
2536 }
2537
2538 if (0 != hostids.values_num)
2539 {
2540 char *sql = NULL;
2541 size_t sql_alloc = 0, sql_offset = 0;
2542
2543 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
2544 "select hi.hostid,id.parent_interfaceid,hi.interfaceid,hi.type,hi.main,hi.useip,hi.ip,"
2545 "hi.dns,hi.port,hi.bulk"
2546 " from interface hi"
2547 " left join interface_discovery id"
2548 " on hi.interfaceid=id.interfaceid"
2549 " where");
2550 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hi.hostid", hostids.values, hostids.values_num);
2551
2552 result = DBselect("%s", sql);
2553
2554 zbx_free(sql);
2555
2556 while (NULL != (row = DBfetch(result)))
2557 {
2558 ZBX_STR2UINT64(hostid, row[0]);
2559 ZBX_DBROW2UINT64(parent_interfaceid, row[1]);
2560 ZBX_DBROW2UINT64(interfaceid, row[2]);
2561
2562 if (FAIL == (i = zbx_vector_ptr_bsearch(hosts, &hostid, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
2563 {
2564 THIS_SHOULD_NEVER_HAPPEN;
2565 continue;
2566 }
2567
2568 host = (zbx_lld_host_t *)hosts->values[i];
2569
2570 lld_interface_make(&host->interfaces, parent_interfaceid, interfaceid,
2571 (unsigned char)atoi(row[3]), (unsigned char)atoi(row[4]),
2572 (unsigned char)atoi(row[5]), row[6], row[7], row[8],
2573 (unsigned char)atoi(row[9]));
2574 }
2575 DBfree_result(result);
2576 }
2577
2578 zbx_vector_uint64_destroy(&hostids);
2579
2580 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
2581 }
2582
2583 /******************************************************************************
2584 * *
2585 * Function: another_main_interface_exists *
2586 * *
2587 * Return value: SUCCEED if interface with same type exists in the list of *
2588 * interfaces; FAIL - otherwise *
2589 * *
2590 * Comments: interfaces with ZBX_FLAG_LLD_INTERFACE_REMOVE flag are ignored *
2591 * auxiliary function for lld_interfaces_validate() *
2592 * *
2593 ******************************************************************************/
another_main_interface_exists(const zbx_vector_ptr_t * interfaces,const zbx_lld_interface_t * interface)2594 static int another_main_interface_exists(const zbx_vector_ptr_t *interfaces, const zbx_lld_interface_t *interface)
2595 {
2596 const zbx_lld_interface_t *interface_b;
2597 int i;
2598
2599 for (i = 0; i < interfaces->values_num; i++)
2600 {
2601 interface_b = (zbx_lld_interface_t *)interfaces->values[i];
2602
2603 if (interface_b == interface)
2604 continue;
2605
2606 if (0 != (interface_b->flags & ZBX_FLAG_LLD_INTERFACE_REMOVE))
2607 continue;
2608
2609 if (interface_b->type != interface->type)
2610 continue;
2611
2612 if (1 == interface_b->main)
2613 return SUCCEED;
2614 }
2615
2616 return FAIL;
2617 }
2618
2619 /******************************************************************************
2620 * *
2621 * Function: lld_interfaces_validate *
2622 * *
2623 * Parameters: hosts - [IN/OUT] list of hosts *
2624 * *
2625 ******************************************************************************/
lld_interfaces_validate(zbx_vector_ptr_t * hosts,char ** error)2626 static void lld_interfaces_validate(zbx_vector_ptr_t *hosts, char **error)
2627 {
2628 const char *__function_name = "lld_interfaces_validate";
2629
2630 DB_RESULT result;
2631 DB_ROW row;
2632 int i, j;
2633 zbx_vector_uint64_t interfaceids;
2634 zbx_uint64_t interfaceid;
2635 zbx_lld_host_t *host;
2636 zbx_lld_interface_t *interface;
2637 unsigned char type;
2638 char *sql = NULL;
2639 size_t sql_alloc = 0, sql_offset = 0;
2640
2641 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
2642
2643 /* validate changed types */
2644
2645 zbx_vector_uint64_create(&interfaceids);
2646
2647 for (i = 0; i < hosts->values_num; i++)
2648 {
2649 host = (zbx_lld_host_t *)hosts->values[i];
2650
2651 for (j = 0; j < host->interfaces.values_num; j++)
2652 {
2653 interface = (zbx_lld_interface_t *)host->interfaces.values[j];
2654
2655 if (0 == (interface->flags & ZBX_FLAG_LLD_INTERFACE_UPDATE_TYPE))
2656 continue;
2657
2658 zbx_vector_uint64_append(&interfaceids, interface->interfaceid);
2659 }
2660 }
2661
2662 if (0 != interfaceids.values_num)
2663 {
2664 zbx_vector_uint64_sort(&interfaceids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
2665
2666 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "select interfaceid,type from items where");
2667 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "interfaceid",
2668 interfaceids.values, interfaceids.values_num);
2669 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " group by interfaceid,type");
2670
2671 result = DBselect("%s", sql);
2672
2673 while (NULL != (row = DBfetch(result)))
2674 {
2675 type = get_interface_type_by_item_type((unsigned char)atoi(row[1]));
2676
2677 if (type != INTERFACE_TYPE_ANY && type != INTERFACE_TYPE_UNKNOWN)
2678 {
2679 ZBX_STR2UINT64(interfaceid, row[0]);
2680
2681 for (i = 0; i < hosts->values_num; i++)
2682 {
2683 host = (zbx_lld_host_t *)hosts->values[i];
2684
2685 for (j = 0; j < host->interfaces.values_num; j++)
2686 {
2687 interface = (zbx_lld_interface_t *)host->interfaces.values[j];
2688
2689 if (0 == (interface->flags & ZBX_FLAG_LLD_INTERFACE_UPDATE_TYPE))
2690 continue;
2691
2692 if (interface->interfaceid != interfaceid)
2693 continue;
2694
2695 *error = zbx_strdcatf(*error,
2696 "Cannot update \"%s\" interface on host \"%s\":"
2697 " the interface is used by items.\n",
2698 zbx_interface_type_string(interface->type_orig),
2699 host->host);
2700
2701 /* return an original interface type and drop the correspond flag */
2702 interface->type = interface->type_orig;
2703 interface->flags &= ~ZBX_FLAG_LLD_INTERFACE_UPDATE_TYPE;
2704 }
2705 }
2706 }
2707 }
2708 DBfree_result(result);
2709 }
2710
2711 /* validate interfaces which should be deleted */
2712
2713 zbx_vector_uint64_clear(&interfaceids);
2714
2715 for (i = 0; i < hosts->values_num; i++)
2716 {
2717 host = (zbx_lld_host_t *)hosts->values[i];
2718
2719 for (j = 0; j < host->interfaces.values_num; j++)
2720 {
2721 interface = (zbx_lld_interface_t *)host->interfaces.values[j];
2722
2723 if (0 == (interface->flags & ZBX_FLAG_LLD_INTERFACE_REMOVE))
2724 continue;
2725
2726 zbx_vector_uint64_append(&interfaceids, interface->interfaceid);
2727 }
2728 }
2729
2730 if (0 != interfaceids.values_num)
2731 {
2732 zbx_vector_uint64_sort(&interfaceids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
2733
2734 sql_offset = 0;
2735 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "select interfaceid from items where");
2736 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "interfaceid",
2737 interfaceids.values, interfaceids.values_num);
2738 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " group by interfaceid");
2739
2740 result = DBselect("%s", sql);
2741
2742 while (NULL != (row = DBfetch(result)))
2743 {
2744 ZBX_STR2UINT64(interfaceid, row[0]);
2745
2746 for (i = 0; i < hosts->values_num; i++)
2747 {
2748 host = (zbx_lld_host_t *)hosts->values[i];
2749
2750 for (j = 0; j < host->interfaces.values_num; j++)
2751 {
2752 interface = (zbx_lld_interface_t *)host->interfaces.values[j];
2753
2754 if (0 == (interface->flags & ZBX_FLAG_LLD_INTERFACE_REMOVE))
2755 continue;
2756
2757 if (interface->interfaceid != interfaceid)
2758 continue;
2759
2760 *error = zbx_strdcatf(*error, "Cannot delete \"%s\" interface on host \"%s\":"
2761 " the interface is used by items.\n",
2762 zbx_interface_type_string(interface->type), host->host);
2763
2764 /* drop the correspond flag */
2765 interface->flags &= ~ZBX_FLAG_LLD_INTERFACE_REMOVE;
2766
2767 if (SUCCEED == another_main_interface_exists(&host->interfaces, interface))
2768 {
2769 if (1 == interface->main)
2770 {
2771 /* drop main flag */
2772 interface->main_orig = interface->main;
2773 interface->main = 0;
2774 interface->flags |= ZBX_FLAG_LLD_INTERFACE_UPDATE_MAIN;
2775 }
2776 }
2777 else if (1 != interface->main)
2778 {
2779 /* set main flag */
2780 interface->main_orig = interface->main;
2781 interface->main = 1;
2782 interface->flags |= ZBX_FLAG_LLD_INTERFACE_UPDATE_MAIN;
2783 }
2784 }
2785 }
2786 }
2787 DBfree_result(result);
2788 }
2789
2790 zbx_vector_uint64_destroy(&interfaceids);
2791
2792 zbx_free(sql);
2793
2794 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
2795 }
2796
2797 /******************************************************************************
2798 * *
2799 * Function: lld_update_hosts *
2800 * *
2801 * Purpose: add or update low-level discovered hosts *
2802 * *
2803 ******************************************************************************/
lld_update_hosts(zbx_uint64_t lld_ruleid,const zbx_vector_ptr_t * lld_rows,char ** error,unsigned short lifetime,int lastcheck)2804 void lld_update_hosts(zbx_uint64_t lld_ruleid, const zbx_vector_ptr_t *lld_rows, char **error,
2805 unsigned short lifetime, int lastcheck)
2806 {
2807 const char *__function_name = "lld_update_hosts";
2808
2809 DB_RESULT result;
2810 DB_ROW row;
2811 zbx_vector_ptr_t hosts, group_prototypes, groups, interfaces, hostmacros;
2812 zbx_vector_uint64_t groupids; /* list of host groups which should be added */
2813 zbx_vector_uint64_t del_hostgroupids; /* list of host groups which should be deleted */
2814 zbx_vector_uint64_t del_hostmacroids; /* list of host macros which should be deleted */
2815 zbx_uint64_t proxy_hostid;
2816 char *ipmi_username = NULL, *ipmi_password, *tls_issuer, *tls_subject, *tls_psk_identity,
2817 *tls_psk;
2818 char ipmi_authtype, inventory_mode;
2819 unsigned char ipmi_privilege, tls_connect, tls_accept;
2820
2821 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
2822
2823 result = DBselect(
2824 "select h.proxy_hostid,h.ipmi_authtype,h.ipmi_privilege,h.ipmi_username,h.ipmi_password,"
2825 "h.tls_connect,h.tls_accept,h.tls_issuer,h.tls_subject,h.tls_psk_identity,h.tls_psk"
2826 " from hosts h,items i"
2827 " where h.hostid=i.hostid"
2828 " and i.itemid=" ZBX_FS_UI64,
2829 lld_ruleid);
2830
2831 if (NULL != (row = DBfetch(result)))
2832 {
2833 ZBX_DBROW2UINT64(proxy_hostid, row[0]);
2834 ipmi_authtype = (char)atoi(row[1]);
2835 ZBX_STR2UCHAR(ipmi_privilege, row[2]);
2836 ipmi_username = zbx_strdup(NULL, row[3]);
2837 ipmi_password = zbx_strdup(NULL, row[4]);
2838
2839 ZBX_STR2UCHAR(tls_connect, row[5]);
2840 ZBX_STR2UCHAR(tls_accept, row[6]);
2841 tls_issuer = zbx_strdup(NULL, row[7]);
2842 tls_subject = zbx_strdup(NULL, row[8]);
2843 tls_psk_identity = zbx_strdup(NULL, row[9]);
2844 tls_psk = zbx_strdup(NULL, row[10]);
2845 }
2846 DBfree_result(result);
2847
2848 if (NULL == row)
2849 {
2850 *error = zbx_strdcatf(*error, "Cannot process host prototypes: a parent host not found.\n");
2851 return;
2852 }
2853
2854 zbx_vector_ptr_create(&hosts);
2855 zbx_vector_uint64_create(&groupids);
2856 zbx_vector_ptr_create(&group_prototypes);
2857 zbx_vector_ptr_create(&groups);
2858 zbx_vector_uint64_create(&del_hostgroupids);
2859 zbx_vector_uint64_create(&del_hostmacroids);
2860 zbx_vector_ptr_create(&interfaces);
2861 zbx_vector_ptr_create(&hostmacros);
2862
2863 lld_interfaces_get(lld_ruleid, &interfaces);
2864 lld_hostmacros_get(lld_ruleid, &hostmacros);
2865
2866 result = DBselect(
2867 "select h.hostid,h.host,h.name,h.status,hi.inventory_mode"
2868 " from hosts h,host_discovery hd"
2869 " left join host_inventory hi"
2870 " on hd.hostid=hi.hostid"
2871 " where h.hostid=hd.hostid"
2872 " and hd.parent_itemid=" ZBX_FS_UI64,
2873 lld_ruleid);
2874
2875 while (NULL != (row = DBfetch(result)))
2876 {
2877 zbx_uint64_t parent_hostid;
2878 const char *host_proto, *name_proto;
2879 zbx_lld_host_t *host;
2880 unsigned char status;
2881 int i;
2882
2883 ZBX_STR2UINT64(parent_hostid, row[0]);
2884 host_proto = row[1];
2885 name_proto = row[2];
2886 status = (unsigned char)atoi(row[3]);
2887 if (SUCCEED == DBis_null(row[4]))
2888 inventory_mode = HOST_INVENTORY_DISABLED;
2889 else
2890 inventory_mode = (char)atoi(row[4]);
2891
2892 lld_hosts_get(parent_hostid, &hosts, proxy_hostid, ipmi_authtype, ipmi_privilege, ipmi_username,
2893 ipmi_password, inventory_mode, tls_connect, tls_accept, tls_issuer, tls_subject,
2894 tls_psk_identity, tls_psk);
2895
2896 lld_simple_groups_get(parent_hostid, &groupids);
2897
2898 lld_group_prototypes_get(parent_hostid, &group_prototypes);
2899 lld_groups_get(parent_hostid, &groups);
2900
2901 for (i = 0; i < lld_rows->values_num; i++)
2902 {
2903 const zbx_lld_row_t *lld_row = (zbx_lld_row_t *)lld_rows->values[i];
2904
2905 host = lld_host_make(&hosts, host_proto, name_proto, &lld_row->jp_row);
2906 lld_groups_make(host, &groups, &group_prototypes, &lld_row->jp_row);
2907 }
2908
2909 zbx_vector_ptr_sort(&hosts, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
2910
2911 lld_groups_validate(&groups, error);
2912 lld_hosts_validate(&hosts, error);
2913
2914 lld_interfaces_make(&interfaces, &hosts);
2915 lld_interfaces_validate(&hosts, error);
2916
2917 lld_hostgroups_make(&groupids, &hosts, &groups, &del_hostgroupids);
2918 lld_templates_make(parent_hostid, &hosts);
2919 lld_hostmacros_make(&hostmacros, &hosts, &del_hostmacroids);
2920
2921 lld_groups_save(&groups, &group_prototypes);
2922 lld_hosts_save(parent_hostid, &hosts, host_proto, proxy_hostid, ipmi_authtype, ipmi_privilege,
2923 ipmi_username, ipmi_password, status, inventory_mode, tls_connect, tls_accept,
2924 tls_issuer, tls_subject, tls_psk_identity, tls_psk, &del_hostgroupids,
2925 &del_hostmacroids);
2926
2927 /* linking of the templates */
2928 lld_templates_link(&hosts, error);
2929
2930 lld_hosts_remove(&hosts, lifetime, lastcheck);
2931 lld_groups_remove(&groups, lifetime, lastcheck);
2932
2933 zbx_vector_ptr_clear_ext(&groups, (zbx_clean_func_t)lld_group_free);
2934 zbx_vector_ptr_clear_ext(&group_prototypes, (zbx_clean_func_t)lld_group_prototype_free);
2935 zbx_vector_ptr_clear_ext(&hosts, (zbx_clean_func_t)lld_host_free);
2936
2937 zbx_vector_uint64_clear(&groupids);
2938 zbx_vector_uint64_clear(&del_hostgroupids);
2939 zbx_vector_uint64_clear(&del_hostmacroids);
2940 }
2941 DBfree_result(result);
2942
2943 zbx_vector_ptr_clear_ext(&hostmacros, (zbx_clean_func_t)lld_hostmacro_free);
2944 zbx_vector_ptr_clear_ext(&interfaces, (zbx_clean_func_t)lld_interface_free);
2945
2946 zbx_vector_ptr_destroy(&hostmacros);
2947 zbx_vector_ptr_destroy(&interfaces);
2948 zbx_vector_uint64_destroy(&del_hostmacroids);
2949 zbx_vector_uint64_destroy(&del_hostgroupids);
2950 zbx_vector_ptr_destroy(&groups);
2951 zbx_vector_ptr_destroy(&group_prototypes);
2952 zbx_vector_uint64_destroy(&groupids);
2953 zbx_vector_ptr_destroy(&hosts);
2954
2955 zbx_free(tls_psk);
2956 zbx_free(tls_psk_identity);
2957 zbx_free(tls_subject);
2958 zbx_free(tls_issuer);
2959 zbx_free(ipmi_password);
2960 zbx_free(ipmi_username);
2961
2962 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
2963 }
2964