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 "common.h"
21 #include "comms.h"
22 #include "db.h"
23 #include "log.h"
24 #include "dbcache.h"
25 
26 #include "operations.h"
27 
28 /******************************************************************************
29  *                                                                            *
30  * Function: select_discovered_host                                           *
31  *                                                                            *
32  * Purpose: select hostid of discovered host                                  *
33  *                                                                            *
34  * Parameters: dhostid - discovered host id                                   *
35  *                                                                            *
36  * Return value: hostid - existing hostid, 0 - if not found                   *
37  *                                                                            *
38  * Author: Alexei Vladishev                                                   *
39  *                                                                            *
40  ******************************************************************************/
select_discovered_host(const DB_EVENT * event)41 static zbx_uint64_t	select_discovered_host(const DB_EVENT *event)
42 {
43 	const char	*__function_name = "select_discovered_host";
44 	DB_RESULT	result;
45 	DB_ROW		row;
46 	zbx_uint64_t	hostid = 0;
47 	char		*sql = NULL;
48 
49 	zabbix_log(LOG_LEVEL_DEBUG, "In %s() eventid:" ZBX_FS_UI64,
50 			__function_name, event->eventid);
51 
52 	switch (event->object)
53 	{
54 		case EVENT_OBJECT_DHOST:
55 			sql = zbx_dsprintf(sql,
56 				"select h.hostid,h.status"
57 				" from hosts h,interface i,dservices ds,dchecks dc,drules dr"
58 				" where h.hostid=i.hostid"
59 					" and i.ip=ds.ip"
60 					" and ds.dcheckid=dc.dcheckid"
61 					" and dc.druleid=dr.druleid"
62 					" and h.status in (%d,%d)"
63 					" and " ZBX_SQL_NULLCMP("dr.proxy_hostid", "h.proxy_hostid")
64 					" and i.useip=1"
65 					" and ds.dhostid=" ZBX_FS_UI64
66 				" order by i.hostid",
67 				HOST_STATUS_MONITORED, HOST_STATUS_NOT_MONITORED,
68 				event->objectid);
69 			break;
70 		case EVENT_OBJECT_DSERVICE:
71 			sql = zbx_dsprintf(sql,
72 				"select h.hostid,h.status"
73 				" from hosts h,interface i,dservices ds,dchecks dc,drules dr"
74 				" where h.hostid=i.hostid"
75 					" and i.ip=ds.ip"
76 					" and ds.dcheckid=dc.dcheckid"
77 					" and dc.druleid=dr.druleid"
78 					" and h.status in (%d,%d)"
79 					" and " ZBX_SQL_NULLCMP("dr.proxy_hostid", "h.proxy_hostid")
80 					" and i.useip=1"
81 					" and ds.dserviceid=" ZBX_FS_UI64
82 				" order by i.hostid",
83 				HOST_STATUS_MONITORED, HOST_STATUS_NOT_MONITORED,
84 				event->objectid);
85 			break;
86 		default:
87 			goto exit;
88 	}
89 
90 	result = DBselectN(sql, 1);
91 
92 	zbx_free(sql);
93 
94 	if (NULL != (row = DBfetch(result)))
95 		ZBX_STR2UINT64(hostid, row[0]);
96 	DBfree_result(result);
97 exit:
98 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():" ZBX_FS_UI64, __function_name, hostid);
99 
100 	return hostid;
101 }
102 
103 /******************************************************************************
104  *                                                                            *
105  * Function: add_discovered_host_groups                                       *
106  *                                                                            *
107  * Purpose: add group to host if not added already                            *
108  *                                                                            *
109  * Author: Alexander Vladishev                                                *
110  *                                                                            *
111  ******************************************************************************/
add_discovered_host_groups(zbx_uint64_t hostid,zbx_vector_uint64_t * groupids)112 static void	add_discovered_host_groups(zbx_uint64_t hostid, zbx_vector_uint64_t *groupids)
113 {
114 	const char	*__function_name = "add_discovered_host_groups";
115 
116 	DB_RESULT	result;
117 	DB_ROW		row;
118 	zbx_uint64_t	groupid;
119 	char		*sql = NULL;
120 	size_t		sql_alloc = 256, sql_offset = 0;
121 	int		i;
122 
123 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
124 
125 	sql = zbx_malloc(sql, sql_alloc);
126 
127 	zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
128 			"select groupid"
129 			" from hosts_groups"
130 			" where hostid=" ZBX_FS_UI64
131 				" and",
132 			hostid);
133 	DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "groupid", groupids->values, groupids->values_num);
134 
135 	result = DBselect("%s", sql);
136 
137 	zbx_free(sql);
138 
139 	while (NULL != (row = DBfetch(result)))
140 	{
141 		ZBX_STR2UINT64(groupid, row[0]);
142 
143 		if (FAIL == (i = zbx_vector_uint64_search(groupids, groupid, ZBX_DEFAULT_UINT64_COMPARE_FUNC)))
144 		{
145 			THIS_SHOULD_NEVER_HAPPEN;
146 			continue;
147 		}
148 
149 		zbx_vector_uint64_remove_noorder(groupids, i);
150 	}
151 	DBfree_result(result);
152 
153 	if (0 != groupids->values_num)
154 	{
155 		zbx_uint64_t	hostgroupid;
156 		zbx_db_insert_t	db_insert;
157 
158 		hostgroupid = DBget_maxid_num("hosts_groups", groupids->values_num);
159 
160 		zbx_db_insert_prepare(&db_insert, "hosts_groups", "hostgroupid", "hostid", "groupid", NULL);
161 
162 		zbx_vector_uint64_sort(groupids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
163 
164 		for (i = 0; i < groupids->values_num; i++)
165 		{
166 			zbx_db_insert_add_values(&db_insert, hostgroupid++, hostid, groupids->values[i]);
167 		}
168 
169 		zbx_db_insert_execute(&db_insert);
170 		zbx_db_insert_clean(&db_insert);
171 	}
172 
173 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
174 }
175 
176 /******************************************************************************
177  *                                                                            *
178  * Function: add_discovered_host                                              *
179  *                                                                            *
180  * Purpose: add discovered host if it was not added already                   *
181  *                                                                            *
182  * Parameters: dhostid - discovered host id                                   *
183  *                                                                            *
184  * Return value: hostid - new/existing hostid                                 *
185  *                                                                            *
186  * Author: Alexei Vladishev                                                   *
187  *                                                                            *
188  ******************************************************************************/
add_discovered_host(const DB_EVENT * event)189 static zbx_uint64_t	add_discovered_host(const DB_EVENT *event)
190 {
191 	const char		*__function_name = "add_discovered_host";
192 
193 	DB_RESULT		result;
194 	DB_RESULT		result2;
195 	DB_ROW			row;
196 	DB_ROW			row2;
197 	zbx_uint64_t		dhostid, hostid = 0, proxy_hostid;
198 	char			*host = NULL, *host_esc, *host_unique;
199 	unsigned short		port;
200 	zbx_vector_uint64_t	groupids;
201 	unsigned char		svc_type, interface_type;
202 	zbx_config_t		cfg;
203 	zbx_db_insert_t		db_insert;
204 
205 	zabbix_log(LOG_LEVEL_DEBUG, "In %s() eventid:" ZBX_FS_UI64, __function_name, event->eventid);
206 
207 	zbx_vector_uint64_create(&groupids);
208 
209 	zbx_config_get(&cfg, ZBX_CONFIG_FLAGS_DISCOVERY_GROUPID | ZBX_CONFIG_FLAGS_DEFAULT_INVENTORY_MODE);
210 
211 	if (0 == cfg.discovery_groupid)
212 	{
213 		zabbix_log(LOG_LEVEL_WARNING, "cannot add discovered host: group for discovered hosts is not defined");
214 		goto clean;
215 	}
216 
217 	zbx_vector_uint64_append(&groupids, cfg.discovery_groupid);
218 
219 	if (EVENT_OBJECT_DHOST == event->object || EVENT_OBJECT_DSERVICE == event->object)
220 	{
221 		if (EVENT_OBJECT_DHOST == event->object)
222 		{
223 			result = DBselect(
224 					"select ds.dhostid,dr.proxy_hostid,ds.ip,ds.dns,ds.port,ds.type"
225 					" from drules dr,dchecks dc,dservices ds"
226 					" where dc.druleid=dr.druleid"
227 						" and ds.dcheckid=dc.dcheckid"
228 						" and ds.dhostid=" ZBX_FS_UI64
229 					" order by ds.dserviceid",
230 					event->objectid);
231 		}
232 		else
233 		{
234 			result = DBselect(
235 					"select ds.dhostid,dr.proxy_hostid,ds.ip,ds.dns,ds.port,ds.type"
236 					" from drules dr,dchecks dc,dservices ds,dservices ds1"
237 					" where dc.druleid=dr.druleid"
238 						" and ds.dcheckid=dc.dcheckid"
239 						" and ds1.dhostid=ds.dhostid"
240 						" and ds1.dserviceid=" ZBX_FS_UI64
241 					" order by ds.dserviceid",
242 					event->objectid);
243 		}
244 
245 		while (NULL != (row = DBfetch(result)))
246 		{
247 			ZBX_STR2UINT64(dhostid, row[0]);
248 			ZBX_DBROW2UINT64(proxy_hostid, row[1]);
249 			svc_type = (unsigned char)atoi(row[5]);
250 
251 			switch (svc_type)
252 			{
253 				case SVC_AGENT:
254 					port = (unsigned short)atoi(row[4]);
255 					interface_type = INTERFACE_TYPE_AGENT;
256 					break;
257 				case SVC_SNMPv1:
258 				case SVC_SNMPv2c:
259 				case SVC_SNMPv3:
260 					port = (unsigned short)atoi(row[4]);
261 					interface_type = INTERFACE_TYPE_SNMP;
262 					break;
263 				default:
264 					port = ZBX_DEFAULT_AGENT_PORT;
265 					interface_type = INTERFACE_TYPE_AGENT;
266 			}
267 
268 			if (0 == hostid)
269 			{
270 				result2 = DBselect(
271 						"select distinct h.hostid"
272 						" from hosts h,interface i,dservices ds"
273 						" where h.hostid=i.hostid"
274 							" and i.ip=ds.ip"
275 							" and h.status in (%d,%d)"
276 							" and h.proxy_hostid%s"
277 							" and ds.dhostid=" ZBX_FS_UI64
278 						" order by h.hostid",
279 						HOST_STATUS_MONITORED, HOST_STATUS_NOT_MONITORED,
280 						DBsql_id_cmp(proxy_hostid), dhostid);
281 
282 				if (NULL != (row2 = DBfetch(result2)))
283 					ZBX_STR2UINT64(hostid, row2[0]);
284 
285 				DBfree_result(result2);
286 			}
287 
288 			if (0 == hostid)
289 			{
290 				hostid = DBget_maxid("hosts");
291 
292 				/* for host uniqueness purposes */
293 				host = zbx_strdup(host, '\0' != *row[3] ? row[3] : row[2]);
294 
295 				make_hostname(host);	/* replace not-allowed symbols */
296 				host_unique = DBget_unique_hostname_by_sample(host);
297 				zbx_free(host);
298 
299 				zbx_db_insert_prepare(&db_insert, "hosts", "hostid", "proxy_hostid", "host", "name",
300 						NULL);
301 				zbx_db_insert_add_values(&db_insert, hostid, proxy_hostid, host_unique, host_unique);
302 				zbx_db_insert_execute(&db_insert);
303 				zbx_db_insert_clean(&db_insert);
304 
305 				if (HOST_INVENTORY_DISABLED != cfg.default_inventory_mode)
306 					DBadd_host_inventory(hostid, cfg.default_inventory_mode);
307 
308 				DBadd_interface(hostid, interface_type, 1, row[2], row[3], port);
309 
310 				zbx_free(host_unique);
311 
312 				add_discovered_host_groups(hostid, &groupids);
313 			}
314 			else
315 			{
316 				DBadd_interface(hostid, interface_type, 1, row[2], row[3], port);
317 			}
318 		}
319 		DBfree_result(result);
320 	}
321 	else if (EVENT_OBJECT_ZABBIX_ACTIVE == event->object)
322 	{
323 		result = DBselect(
324 				"select proxy_hostid,host,listen_ip,listen_dns,listen_port"
325 				" from autoreg_host"
326 				" where autoreg_hostid=" ZBX_FS_UI64,
327 				event->objectid);
328 
329 		if (NULL != (row = DBfetch(result)))
330 		{
331 			char		*sql = NULL;
332 			zbx_uint64_t	host_proxy_hostid;
333 
334 			ZBX_DBROW2UINT64(proxy_hostid, row[0]);
335 			host_esc = DBdyn_escape_field("hosts", "host", row[1]);
336 			port = (unsigned short)atoi(row[4]);
337 
338 			result2 = DBselect(
339 					"select null"
340 					" from hosts"
341 					" where host='%s'"
342 						" and status=%d",
343 					host_esc, HOST_STATUS_TEMPLATE);
344 
345 			if (NULL != (row2 = DBfetch(result2)))
346 			{
347 				zabbix_log(LOG_LEVEL_WARNING, "cannot add discovered host \"%s\":"
348 						" template with the same name already exists", row[1]);
349 				DBfree_result(result2);
350 				goto out;
351 			}
352 			DBfree_result(result2);
353 
354 			sql = zbx_dsprintf(sql,
355 					"select hostid,proxy_hostid"
356 					" from hosts"
357 					" where host='%s'"
358 						" and flags<>%d"
359 						" and status in (%d,%d)"
360 					" order by hostid",
361 					host_esc, ZBX_FLAG_DISCOVERY_PROTOTYPE,
362 					HOST_STATUS_MONITORED, HOST_STATUS_NOT_MONITORED);
363 
364 			result2 = DBselectN(sql, 1);
365 
366 			zbx_free(sql);
367 
368 			if (NULL == (row2 = DBfetch(result2)))
369 			{
370 				hostid = DBget_maxid("hosts");
371 
372 				zbx_db_insert_prepare(&db_insert, "hosts", "hostid", "proxy_hostid", "host", "name",
373 						NULL);
374 				zbx_db_insert_add_values(&db_insert, hostid, proxy_hostid, row[1], row[1]);
375 				zbx_db_insert_execute(&db_insert);
376 				zbx_db_insert_clean(&db_insert);
377 
378 				if (HOST_INVENTORY_DISABLED != cfg.default_inventory_mode)
379 					DBadd_host_inventory(hostid, cfg.default_inventory_mode);
380 
381 				DBadd_interface(hostid, INTERFACE_TYPE_AGENT, 1, row[2], row[3], port);
382 
383 				add_discovered_host_groups(hostid, &groupids);
384 			}
385 			else
386 			{
387 				ZBX_STR2UINT64(hostid, row2[0]);
388 				ZBX_DBROW2UINT64(host_proxy_hostid, row2[1]);
389 
390 				if (host_proxy_hostid != proxy_hostid)
391 				{
392 					DBexecute("update hosts"
393 							" set proxy_hostid=%s"
394 							" where hostid=" ZBX_FS_UI64,
395 							DBsql_id_ins(proxy_hostid), hostid);
396 				}
397 
398 				DBadd_interface(hostid, INTERFACE_TYPE_AGENT, 1, row[2], row[3], port);
399 			}
400 			DBfree_result(result2);
401 out:
402 			zbx_free(host_esc);
403 		}
404 		DBfree_result(result);
405 	}
406 clean:
407 	zbx_config_clean(&cfg);
408 
409 	zbx_vector_uint64_destroy(&groupids);
410 
411 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
412 
413 	return hostid;
414 }
415 
416 /******************************************************************************
417  *                                                                            *
418  * Function: op_host_add                                                      *
419  *                                                                            *
420  * Purpose: add discovered host                                               *
421  *                                                                            *
422  * Parameters: trigger - trigger data                                         *
423  *             action  - action data                                          *
424  *                                                                            *
425  * Author: Alexei Vladishev                                                   *
426  *                                                                            *
427  ******************************************************************************/
op_host_add(const DB_EVENT * event)428 void	op_host_add(const DB_EVENT *event)
429 {
430 	const char	*__function_name = "op_host_add";
431 
432 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
433 
434 	if (event->source != EVENT_SOURCE_DISCOVERY && event->source != EVENT_SOURCE_AUTO_REGISTRATION)
435 		return;
436 
437 	if (event->object != EVENT_OBJECT_DHOST && event->object != EVENT_OBJECT_DSERVICE && event->object != EVENT_OBJECT_ZABBIX_ACTIVE)
438 		return;
439 
440 	add_discovered_host(event);
441 
442 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
443 }
444 
445 /******************************************************************************
446  *                                                                            *
447  * Function: op_host_del                                                      *
448  *                                                                            *
449  * Purpose: delete host                                                       *
450  *                                                                            *
451  * Author: Eugene Grigorjev                                                   *
452  *                                                                            *
453  ******************************************************************************/
op_host_del(const DB_EVENT * event)454 void	op_host_del(const DB_EVENT *event)
455 {
456 	const char		*__function_name = "op_host_del";
457 
458 	zbx_vector_uint64_t	hostids;
459 	zbx_uint64_t		hostid;
460 
461 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
462 
463 	if (event->source != EVENT_SOURCE_DISCOVERY)
464 		return;
465 
466 	if (event->object != EVENT_OBJECT_DHOST && event->object != EVENT_OBJECT_DSERVICE)
467 		return;
468 
469 	if (0 == (hostid = select_discovered_host(event)))
470 		return;
471 
472 	zbx_vector_uint64_create(&hostids);
473 
474 	zbx_vector_uint64_append(&hostids, hostid);
475 
476 	DBdelete_hosts_with_prototypes(&hostids);
477 
478 	zbx_vector_uint64_destroy(&hostids);
479 
480 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
481 }
482 
483 /******************************************************************************
484  *                                                                            *
485  * Function: op_host_enable                                                   *
486  *                                                                            *
487  * Purpose: enable discovered                                                 *
488  *                                                                            *
489  * Author: Alexander Vladishev                                                *
490  *                                                                            *
491  ******************************************************************************/
op_host_enable(const DB_EVENT * event)492 void	op_host_enable(const DB_EVENT *event)
493 {
494 	const char	*__function_name = "op_host_enable";
495 	zbx_uint64_t	hostid;
496 
497 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
498 
499 	if (event->source != EVENT_SOURCE_DISCOVERY)
500 		return;
501 
502 	if (event->object != EVENT_OBJECT_DHOST && event->object != EVENT_OBJECT_DSERVICE)
503 		return;
504 
505 	if (0 == (hostid = add_discovered_host(event)))
506 		return;
507 
508 	DBexecute(
509 			"update hosts"
510 			" set status=%d"
511 			" where hostid=" ZBX_FS_UI64,
512 			HOST_STATUS_MONITORED,
513 			hostid);
514 
515 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
516 }
517 
518 /******************************************************************************
519  *                                                                            *
520  * Function: op_host_disable                                                  *
521  *                                                                            *
522  * Purpose: disable host                                                      *
523  *                                                                            *
524  * Author: Alexander Vladishev                                                *
525  *                                                                            *
526  ******************************************************************************/
op_host_disable(const DB_EVENT * event)527 void	op_host_disable(const DB_EVENT *event)
528 {
529 	const char	*__function_name = "op_host_disable";
530 	zbx_uint64_t	hostid;
531 
532 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
533 
534 	if (event->source != EVENT_SOURCE_DISCOVERY && event->source != EVENT_SOURCE_AUTO_REGISTRATION)
535 		return;
536 
537 	if (event->object != EVENT_OBJECT_DHOST && event->object != EVENT_OBJECT_DSERVICE && event->object != EVENT_OBJECT_ZABBIX_ACTIVE)
538 		return;
539 
540 	if (0 == (hostid = add_discovered_host(event)))
541 		return;
542 
543 	DBexecute(
544 			"update hosts"
545 			" set status=%d"
546 			" where hostid=" ZBX_FS_UI64,
547 			HOST_STATUS_NOT_MONITORED,
548 			hostid);
549 
550 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
551 }
552 
553 /******************************************************************************
554  *                                                                            *
555  * Function: op_host_inventory_mode                                           *
556  *                                                                            *
557  * Purpose: sets host inventory mode                                          *
558  *                                                                            *
559  * Parameters: event          - [IN] the source event                         *
560  *             inventory_mode - [IN] the new inventory mode, see              *
561  *                              HOST_INVENTORY_ defines                       *
562  *                                                                            *
563  * Comments: This function does not allow disabling host inventory - only     *
564  *           setting manual or automatic host inventory mode is supported.    *
565  *                                                                            *
566  ******************************************************************************/
op_host_inventory_mode(const DB_EVENT * event,int inventory_mode)567 void	op_host_inventory_mode(const DB_EVENT *event, int inventory_mode)
568 {
569 	const char	*__function_name = "op_host_inventory_mode";
570 	zbx_uint64_t	hostid;
571 
572 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
573 
574 	if (event->source != EVENT_SOURCE_DISCOVERY && event->source != EVENT_SOURCE_AUTO_REGISTRATION)
575 		return;
576 
577 	if (event->object != EVENT_OBJECT_DHOST && event->object != EVENT_OBJECT_DSERVICE &&
578 			event->object != EVENT_OBJECT_ZABBIX_ACTIVE)
579 	{
580 		return;
581 	}
582 
583 	if (0 == (hostid = add_discovered_host(event)))
584 		return;
585 
586 	DBset_host_inventory(hostid, inventory_mode);
587 
588 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
589 }
590 
591 /******************************************************************************
592  *                                                                            *
593  * Function: op_groups_add                                                    *
594  *                                                                            *
595  * Purpose: add groups to discovered host                                     *
596  *                                                                            *
597  * Parameters: event    - [IN] event data                                     *
598  *             groupids - [IN] IDs of groups to add                           *
599  *                                                                            *
600  * Author: Alexei Vladishev                                                   *
601  *                                                                            *
602  ******************************************************************************/
op_groups_add(const DB_EVENT * event,zbx_vector_uint64_t * groupids)603 void	op_groups_add(const DB_EVENT *event, zbx_vector_uint64_t *groupids)
604 {
605 	const char	*__function_name = "op_groups_add";
606 	zbx_uint64_t	hostid;
607 
608 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
609 
610 	if (event->source != EVENT_SOURCE_DISCOVERY && event->source != EVENT_SOURCE_AUTO_REGISTRATION)
611 		return;
612 
613 	if (event->object != EVENT_OBJECT_DHOST && event->object != EVENT_OBJECT_DSERVICE && event->object != EVENT_OBJECT_ZABBIX_ACTIVE)
614 		return;
615 
616 	if (0 == (hostid = add_discovered_host(event)))
617 		return;
618 
619 	add_discovered_host_groups(hostid, groupids);
620 
621 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
622 }
623 
624 /******************************************************************************
625  *                                                                            *
626  * Function: op_groups_del                                                    *
627  *                                                                            *
628  * Purpose: delete groups from discovered host                                *
629  *                                                                            *
630  * Parameters: event    - [IN] event data                                     *
631  *             groupids - [IN] IDs of groups to delete                        *
632  *                                                                            *
633  * Author: Alexei Vladishev                                                   *
634  *                                                                            *
635  ******************************************************************************/
op_groups_del(const DB_EVENT * event,zbx_vector_uint64_t * groupids)636 void	op_groups_del(const DB_EVENT *event, zbx_vector_uint64_t *groupids)
637 {
638 	const char	*__function_name = "op_groups_del";
639 
640 	DB_RESULT	result;
641 	zbx_uint64_t	hostid;
642 	char		*sql = NULL;
643 	size_t		sql_alloc = 256, sql_offset = 0;
644 
645 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
646 
647 	if (event->source != EVENT_SOURCE_DISCOVERY)
648 		return;
649 
650 	if (event->object != EVENT_OBJECT_DHOST && event->object != EVENT_OBJECT_DSERVICE)
651 		return;
652 
653 	if (0 == (hostid = select_discovered_host(event)))
654 		return;
655 
656 	sql = zbx_malloc(sql, sql_alloc);
657 
658 	/* make sure host belongs to at least one hostgroup */
659 	zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
660 			"select groupid"
661 			" from hosts_groups"
662 			" where hostid=" ZBX_FS_UI64
663 				" and not",
664 			hostid);
665 	DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "groupid", groupids->values, groupids->values_num);
666 
667 	result = DBselectN(sql, 1);
668 
669 	if (NULL == DBfetch(result))
670 	{
671 		zabbix_log(LOG_LEVEL_WARNING, "cannot remove host \"%s\" from all host groups:"
672 				" it must belong to at least one", zbx_host_string(hostid));
673 	}
674 	else
675 	{
676 		sql_offset = 0;
677 		zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
678 				"delete from hosts_groups"
679 				" where hostid=" ZBX_FS_UI64
680 					" and",
681 				hostid);
682 		DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "groupid", groupids->values, groupids->values_num);
683 
684 		DBexecute("%s", sql);
685 	}
686 	DBfree_result(result);
687 
688 	zbx_free(sql);
689 
690 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
691 }
692 
693 /******************************************************************************
694  *                                                                            *
695  * Function: op_template_add                                                  *
696  *                                                                            *
697  * Purpose: link host with template                                           *
698  *                                                                            *
699  * Parameters: event           - [IN] event data                              *
700  *             lnk_templateids - [IN] array of template IDs                   *
701  *                                                                            *
702  * Author: Eugene Grigorjev                                                   *
703  *                                                                            *
704  ******************************************************************************/
op_template_add(const DB_EVENT * event,zbx_vector_uint64_t * lnk_templateids)705 void	op_template_add(const DB_EVENT *event, zbx_vector_uint64_t *lnk_templateids)
706 {
707 	const char	*__function_name = "op_template_add";
708 	zbx_uint64_t	hostid;
709 	char		*error;
710 
711 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
712 
713 	if (event->source != EVENT_SOURCE_DISCOVERY && event->source != EVENT_SOURCE_AUTO_REGISTRATION)
714 		return;
715 
716 	if (event->object != EVENT_OBJECT_DHOST && event->object != EVENT_OBJECT_DSERVICE && event->object != EVENT_OBJECT_ZABBIX_ACTIVE)
717 		return;
718 
719 	if (0 == (hostid = add_discovered_host(event)))
720 		return;
721 
722 	if (SUCCEED != DBcopy_template_elements(hostid, lnk_templateids, &error))
723 	{
724 		zabbix_log(LOG_LEVEL_WARNING, "cannot link template(s) %s", error);
725 		zbx_free(error);
726 	}
727 
728 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
729 }
730 
731 /******************************************************************************
732  *                                                                            *
733  * Function: op_template_del                                                  *
734  *                                                                            *
735  * Purpose: unlink and clear host from template                               *
736  *                                                                            *
737  * Parameters: event           - [IN] event data                              *
738  *             lnk_templateids - [IN] array of template IDs                   *
739  *                                                                            *
740  * Author: Eugene Grigorjev                                                   *
741  *                                                                            *
742  ******************************************************************************/
op_template_del(const DB_EVENT * event,zbx_vector_uint64_t * del_templateids)743 void	op_template_del(const DB_EVENT *event, zbx_vector_uint64_t *del_templateids)
744 {
745 	const char	*__function_name = "op_template_del";
746 	zbx_uint64_t	hostid;
747 	char		*error;
748 
749 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
750 
751 	if (event->source != EVENT_SOURCE_DISCOVERY)
752 		return;
753 
754 	if (event->object != EVENT_OBJECT_DHOST && event->object != EVENT_OBJECT_DSERVICE)
755 		return;
756 
757 	if (0 == (hostid = select_discovered_host(event)))
758 		return;
759 
760 	if (SUCCEED != DBdelete_template_elements(hostid, del_templateids, &error))
761 	{
762 		zabbix_log(LOG_LEVEL_WARNING, "cannot unlink template: %s", error);
763 		zbx_free(error);
764 	}
765 
766 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
767 }
768