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 "db.h"
22 #include "log.h"
23 #include "zbxserver.h"
24
25 #include "actions.h"
26 #include "operations.h"
27
28 /******************************************************************************
29 * *
30 * Function: check_trigger_condition *
31 * *
32 * Purpose: check if event matches single condition *
33 * *
34 * Parameters: event - trigger event to check *
35 * (event->source == EVENT_SOURCE_TRIGGERS) *
36 * condition - condition for matching *
37 * *
38 * Return value: SUCCEED - matches, FAIL - otherwise *
39 * *
40 * Author: Alexei Vladishev *
41 * *
42 ******************************************************************************/
check_trigger_condition(const DB_EVENT * event,DB_CONDITION * condition)43 static int check_trigger_condition(const DB_EVENT *event, DB_CONDITION *condition)
44 {
45 const char *__function_name = "check_trigger_condition";
46 DB_RESULT result;
47 DB_ROW row;
48 zbx_uint64_t condition_value;
49 char *tmp_str = NULL;
50 int ret = FAIL;
51
52 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
53
54 if (CONDITION_TYPE_HOST_GROUP == condition->conditiontype)
55 {
56 ZBX_STR2UINT64(condition_value, condition->value);
57
58 result = DBselect(
59 "select distinct hg.groupid"
60 " from hosts_groups hg,hosts h,items i,functions f,triggers t"
61 " where hg.hostid=h.hostid"
62 " and h.hostid=i.hostid"
63 " and i.itemid=f.itemid"
64 " and f.triggerid=t.triggerid"
65 " and t.triggerid=" ZBX_FS_UI64
66 " and hg.groupid=" ZBX_FS_UI64,
67 event->objectid,
68 condition_value);
69
70 switch (condition->operator)
71 {
72 case CONDITION_OPERATOR_EQUAL:
73 if (NULL != DBfetch(result))
74 ret = SUCCEED;
75 break;
76 case CONDITION_OPERATOR_NOT_EQUAL:
77 if (NULL == DBfetch(result))
78 ret = SUCCEED;
79 break;
80 default:
81 ret = NOTSUPPORTED;
82 }
83 DBfree_result(result);
84 }
85 else if (CONDITION_TYPE_HOST_TEMPLATE == condition->conditiontype)
86 {
87 zbx_uint64_t hostid, triggerid;
88
89 ZBX_STR2UINT64(condition_value, condition->value);
90
91 switch (condition->operator)
92 {
93 case CONDITION_OPERATOR_EQUAL:
94 case CONDITION_OPERATOR_NOT_EQUAL:
95 triggerid = event->objectid;
96
97 /* use parent trigger ID for generated triggers */
98 result = DBselect(
99 "select parent_triggerid"
100 " from trigger_discovery"
101 " where triggerid=" ZBX_FS_UI64,
102 triggerid);
103
104 if (NULL != (row = DBfetch(result)))
105 {
106 ZBX_STR2UINT64(triggerid, row[0]);
107
108 zabbix_log(LOG_LEVEL_DEBUG, "%s() check host template condition,"
109 " selecting parent triggerid:" ZBX_FS_UI64,
110 __function_name, triggerid);
111 }
112 DBfree_result(result);
113
114 do
115 {
116 result = DBselect(
117 "select distinct i.hostid,t.templateid"
118 " from items i,functions f,triggers t"
119 " where i.itemid=f.itemid"
120 " and f.triggerid=t.templateid"
121 " and t.triggerid=" ZBX_FS_UI64,
122 triggerid);
123
124 triggerid = 0;
125
126 while (NULL != (row = DBfetch(result)))
127 {
128 ZBX_STR2UINT64(hostid, row[0]);
129 ZBX_STR2UINT64(triggerid, row[1]);
130
131 if (hostid == condition_value)
132 {
133 ret = SUCCEED;
134 break;
135 }
136 }
137 DBfree_result(result);
138 }
139 while (SUCCEED != ret && 0 != triggerid);
140
141 if (CONDITION_OPERATOR_NOT_EQUAL == condition->operator)
142 ret = (SUCCEED == ret) ? FAIL : SUCCEED;
143 break;
144 default:
145 ret = NOTSUPPORTED;
146 }
147 }
148 else if (CONDITION_TYPE_HOST == condition->conditiontype)
149 {
150 ZBX_STR2UINT64(condition_value, condition->value);
151
152 switch (condition->operator)
153 {
154 case CONDITION_OPERATOR_EQUAL:
155 case CONDITION_OPERATOR_NOT_EQUAL:
156 result = DBselect(
157 "select distinct i.hostid"
158 " from items i,functions f,triggers t"
159 " where i.itemid=f.itemid"
160 " and f.triggerid=t.triggerid"
161 " and t.triggerid=" ZBX_FS_UI64
162 " and i.hostid=" ZBX_FS_UI64,
163 event->objectid,
164 condition_value);
165
166 if (NULL != DBfetch(result))
167 ret = SUCCEED;
168 DBfree_result(result);
169
170 if (CONDITION_OPERATOR_NOT_EQUAL == condition->operator)
171 ret = (SUCCEED == ret) ? FAIL : SUCCEED;
172 break;
173 default:
174 ret = NOTSUPPORTED;
175 }
176 }
177 else if (CONDITION_TYPE_TRIGGER == condition->conditiontype)
178 {
179 zbx_uint64_t triggerid;
180
181 ZBX_STR2UINT64(condition_value, condition->value);
182
183 switch (condition->operator)
184 {
185 case CONDITION_OPERATOR_EQUAL:
186 case CONDITION_OPERATOR_NOT_EQUAL:
187 if (event->objectid == condition_value)
188 {
189 ret = SUCCEED;
190 }
191 else
192 {
193 /* processing of templated triggers */
194
195 for (triggerid = event->objectid; 0 != triggerid && FAIL == ret;)
196 {
197 result = DBselect(
198 "select templateid"
199 " from triggers"
200 " where triggerid=" ZBX_FS_UI64,
201 triggerid);
202
203 if (NULL == (row = DBfetch(result)))
204 triggerid = 0;
205 else
206 {
207 ZBX_DBROW2UINT64(triggerid, row[0]);
208 if (triggerid == condition_value)
209 ret = SUCCEED;
210 }
211 DBfree_result(result);
212 }
213 }
214
215 if (CONDITION_OPERATOR_NOT_EQUAL == condition->operator)
216 ret = (SUCCEED == ret) ? FAIL : SUCCEED;
217 break;
218 default:
219 ret = NOTSUPPORTED;
220 }
221 }
222 else if (CONDITION_TYPE_TRIGGER_NAME == condition->conditiontype)
223 {
224 tmp_str = zbx_strdup(tmp_str, event->trigger.description);
225
226 substitute_simple_macros(NULL, event, NULL, NULL, NULL, NULL, NULL, NULL,
227 &tmp_str, MACRO_TYPE_TRIGGER_DESCRIPTION, NULL, 0);
228
229 switch (condition->operator)
230 {
231 case CONDITION_OPERATOR_LIKE:
232 if (NULL != strstr(tmp_str, condition->value))
233 ret = SUCCEED;
234 break;
235 case CONDITION_OPERATOR_NOT_LIKE:
236 if (NULL == strstr(tmp_str, condition->value))
237 ret = SUCCEED;
238 break;
239 default:
240 ret = NOTSUPPORTED;
241 }
242 zbx_free(tmp_str);
243 }
244 else if (CONDITION_TYPE_TRIGGER_SEVERITY == condition->conditiontype)
245 {
246 condition_value = atoi(condition->value);
247
248 switch (condition->operator)
249 {
250 case CONDITION_OPERATOR_EQUAL:
251 if (event->trigger.priority == condition_value)
252 ret = SUCCEED;
253 break;
254 case CONDITION_OPERATOR_NOT_EQUAL:
255 if (event->trigger.priority != condition_value)
256 ret = SUCCEED;
257 break;
258 case CONDITION_OPERATOR_MORE_EQUAL:
259 if (event->trigger.priority >= condition_value)
260 ret = SUCCEED;
261 break;
262 case CONDITION_OPERATOR_LESS_EQUAL:
263 if (event->trigger.priority <= condition_value)
264 ret = SUCCEED;
265 break;
266 default:
267 ret = NOTSUPPORTED;
268 }
269 }
270 else if (CONDITION_TYPE_TRIGGER_VALUE == condition->conditiontype)
271 {
272 int condition_value_i = atoi(condition->value);
273
274 switch (condition->operator)
275 {
276 case CONDITION_OPERATOR_EQUAL:
277 if (event->value == condition_value_i)
278 ret = SUCCEED;
279 break;
280 default:
281 ret = NOTSUPPORTED;
282 }
283 }
284 else if (CONDITION_TYPE_TIME_PERIOD == condition->conditiontype)
285 {
286 switch (condition->operator)
287 {
288 case CONDITION_OPERATOR_IN:
289 if (SUCCEED == check_time_period(condition->value, (time_t)event->clock))
290 ret = SUCCEED;
291 break;
292 case CONDITION_OPERATOR_NOT_IN:
293 if (FAIL == check_time_period(condition->value, (time_t)event->clock))
294 ret = SUCCEED;
295 break;
296 default:
297 ret = NOTSUPPORTED;
298 }
299 }
300 else if (CONDITION_TYPE_MAINTENANCE == condition->conditiontype)
301 {
302 switch (condition->operator)
303 {
304 case CONDITION_OPERATOR_IN:
305 result = DBselect(
306 "select count(*)"
307 " from hosts h,items i,functions f,triggers t"
308 " where h.hostid=i.hostid"
309 " and h.maintenance_status=%d"
310 " and i.itemid=f.itemid"
311 " and f.triggerid=t.triggerid"
312 " and t.triggerid=" ZBX_FS_UI64,
313 HOST_MAINTENANCE_STATUS_ON,
314 event->objectid);
315
316 if (NULL != (row = DBfetch(result)) && FAIL == DBis_null(row[0]) && 0 != atoi(row[0]))
317 ret = SUCCEED;
318 DBfree_result(result);
319 break;
320 case CONDITION_OPERATOR_NOT_IN:
321 result = DBselect(
322 "select count(*)"
323 " from hosts h,items i,functions f,triggers t"
324 " where h.hostid=i.hostid"
325 " and h.maintenance_status=%d"
326 " and i.itemid=f.itemid"
327 " and f.triggerid=t.triggerid"
328 " and t.triggerid=" ZBX_FS_UI64,
329 HOST_MAINTENANCE_STATUS_OFF,
330 event->objectid);
331
332 if (NULL != (row = DBfetch(result)) && FAIL == DBis_null(row[0]) && 0 != atoi(row[0]))
333 ret = SUCCEED;
334 DBfree_result(result);
335 break;
336 default:
337 ret = NOTSUPPORTED;
338 }
339 }
340 else if (CONDITION_TYPE_EVENT_ACKNOWLEDGED == condition->conditiontype)
341 {
342 result = DBselect(
343 "select acknowledged"
344 " from events"
345 " where acknowledged=%d"
346 " and eventid=" ZBX_FS_UI64,
347 atoi(condition->value),
348 event->eventid);
349
350 switch (condition->operator)
351 {
352 case CONDITION_OPERATOR_EQUAL:
353 if (NULL != (row = DBfetch(result)))
354 ret = SUCCEED;
355 break;
356 default:
357 ret = NOTSUPPORTED;
358 }
359 DBfree_result(result);
360 }
361 else if (CONDITION_TYPE_APPLICATION == condition->conditiontype)
362 {
363 result = DBselect(
364 "select distinct a.name"
365 " from applications a,items_applications i,functions f,triggers t"
366 " where a.applicationid=i.applicationid"
367 " and i.itemid=f.itemid"
368 " and f.triggerid=t.triggerid"
369 " and t.triggerid=" ZBX_FS_UI64,
370 event->objectid);
371
372 switch (condition->operator)
373 {
374 case CONDITION_OPERATOR_EQUAL:
375 while (NULL != (row = DBfetch(result)))
376 {
377 if (0 == strcmp(row[0], condition->value))
378 {
379 ret = SUCCEED;
380 break;
381 }
382 }
383 break;
384 case CONDITION_OPERATOR_LIKE:
385 while (NULL != (row = DBfetch(result)))
386 {
387 if (NULL != strstr(row[0], condition->value))
388 {
389 ret = SUCCEED;
390 break;
391 }
392 }
393 break;
394 case CONDITION_OPERATOR_NOT_LIKE:
395 ret = SUCCEED;
396 while (NULL != (row = DBfetch(result)))
397 {
398 if (NULL != strstr(row[0], condition->value))
399 {
400 ret = FAIL;
401 break;
402 }
403 }
404 break;
405 default:
406 ret = NOTSUPPORTED;
407 }
408 DBfree_result(result);
409 }
410 else
411 {
412 zabbix_log(LOG_LEVEL_ERR, "unsupported condition type [%d] for condition id [" ZBX_FS_UI64 "]",
413 (int)condition->conditiontype, condition->conditionid);
414 }
415
416 if (NOTSUPPORTED == ret)
417 {
418 zabbix_log(LOG_LEVEL_ERR, "unsupported operator [%d] for condition id [" ZBX_FS_UI64 "]",
419 (int)condition->operator, condition->conditionid);
420 ret = FAIL;
421 }
422
423 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
424
425 return ret;
426 }
427
428 /******************************************************************************
429 * *
430 * Function: check_discovery_condition *
431 * *
432 * Purpose: check if event matches single condition *
433 * *
434 * Parameters: event - discovery event to check *
435 * (event->source == EVENT_SOURCE_DISCOVERY) *
436 * condition - condition for matching *
437 * *
438 * Return value: SUCCEED - matches, FAIL - otherwise *
439 * *
440 * Author: Alexei Vladishev *
441 * *
442 ******************************************************************************/
check_discovery_condition(const DB_EVENT * event,DB_CONDITION * condition)443 static int check_discovery_condition(const DB_EVENT *event, DB_CONDITION *condition)
444 {
445 const char *__function_name = "check_discovery_condition";
446 DB_RESULT result;
447 DB_ROW row;
448 zbx_uint64_t condition_value;
449 int tmp_int, ret = FAIL;
450
451 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
452
453 if (CONDITION_TYPE_DRULE == condition->conditiontype)
454 {
455 ZBX_STR2UINT64(condition_value, condition->value);
456
457 if (EVENT_OBJECT_DHOST == event->object)
458 {
459 result = DBselect(
460 "select druleid"
461 " from dhosts"
462 " where druleid=" ZBX_FS_UI64
463 " and dhostid=" ZBX_FS_UI64,
464 condition_value,
465 event->objectid);
466 }
467 else /* EVENT_OBJECT_DSERVICE */
468 {
469 result = DBselect(
470 "select h.druleid"
471 " from dhosts h,dservices s"
472 " where h.dhostid=s.dhostid"
473 " and h.druleid=" ZBX_FS_UI64
474 " and s.dserviceid=" ZBX_FS_UI64,
475 condition_value,
476 event->objectid);
477 }
478
479 switch (condition->operator)
480 {
481 case CONDITION_OPERATOR_EQUAL:
482 if (NULL != DBfetch(result))
483 ret = SUCCEED;
484 break;
485 case CONDITION_OPERATOR_NOT_EQUAL:
486 if (NULL == DBfetch(result))
487 ret = SUCCEED;
488 break;
489 default:
490 ret = NOTSUPPORTED;
491 }
492 DBfree_result(result);
493 }
494 else if (CONDITION_TYPE_DCHECK == condition->conditiontype)
495 {
496 if (EVENT_OBJECT_DSERVICE == event->object)
497 {
498 ZBX_STR2UINT64(condition_value, condition->value);
499
500 result = DBselect(
501 "select dcheckid"
502 " from dservices"
503 " where dcheckid=" ZBX_FS_UI64
504 " and dserviceid=" ZBX_FS_UI64,
505 condition_value,
506 event->objectid);
507
508 switch (condition->operator)
509 {
510 case CONDITION_OPERATOR_EQUAL:
511 if (NULL != DBfetch(result))
512 ret = SUCCEED;
513 break;
514 case CONDITION_OPERATOR_NOT_EQUAL:
515 if (NULL == DBfetch(result))
516 ret = SUCCEED;
517 break;
518 default:
519 ret = NOTSUPPORTED;
520 }
521 DBfree_result(result);
522 }
523 }
524 else if (CONDITION_TYPE_DOBJECT == condition->conditiontype)
525 {
526 int condition_value_i = atoi(condition->value);
527
528 switch (condition->operator)
529 {
530 case CONDITION_OPERATOR_EQUAL:
531 if (event->object == condition_value_i)
532 ret = SUCCEED;
533 break;
534 default:
535 ret = NOTSUPPORTED;
536 }
537 }
538 else if (CONDITION_TYPE_PROXY == condition->conditiontype)
539 {
540 ZBX_STR2UINT64(condition_value, condition->value);
541
542 if (EVENT_OBJECT_DHOST == event->object)
543 {
544 result = DBselect(
545 "select r.proxy_hostid"
546 " from drules r,dhosts h"
547 " where r.druleid=h.druleid"
548 " and r.proxy_hostid=" ZBX_FS_UI64
549 " and h.dhostid=" ZBX_FS_UI64,
550 condition_value,
551 event->objectid);
552 }
553 else /* EVENT_OBJECT_DSERVICE */
554 {
555 result = DBselect(
556 "select r.proxy_hostid"
557 " from drules r,dhosts h,dservices s"
558 " where r.druleid=h.druleid"
559 " and h.dhostid=s.dhostid"
560 " and r.proxy_hostid=" ZBX_FS_UI64
561 " and s.dserviceid=" ZBX_FS_UI64,
562 condition_value,
563 event->objectid);
564 }
565
566 switch (condition->operator)
567 {
568 case CONDITION_OPERATOR_EQUAL:
569 if (NULL != DBfetch(result))
570 ret = SUCCEED;
571 break;
572 case CONDITION_OPERATOR_NOT_EQUAL:
573 if (NULL == DBfetch(result))
574 ret = SUCCEED;
575 break;
576 default:
577 ret = NOTSUPPORTED;
578 }
579 DBfree_result(result);
580 }
581 else if (CONDITION_TYPE_DVALUE == condition->conditiontype)
582 {
583 if (EVENT_OBJECT_DSERVICE == event->object)
584 {
585 result = DBselect(
586 "select value"
587 " from dservices"
588 " where dserviceid=" ZBX_FS_UI64,
589 event->objectid);
590
591 if (NULL != (row = DBfetch(result)))
592 {
593 switch (condition->operator)
594 {
595 case CONDITION_OPERATOR_EQUAL:
596 if (0 == strcmp(condition->value, row[0]))
597 ret = SUCCEED;
598 break;
599 case CONDITION_OPERATOR_NOT_EQUAL:
600 if (0 != strcmp(condition->value, row[0]))
601 ret = SUCCEED;
602 break;
603 case CONDITION_OPERATOR_MORE_EQUAL:
604 if (0 <= strcmp(row[0], condition->value))
605 ret = SUCCEED;
606 break;
607 case CONDITION_OPERATOR_LESS_EQUAL:
608 if (0 >= strcmp(row[0], condition->value))
609 ret = SUCCEED;
610 break;
611 case CONDITION_OPERATOR_LIKE:
612 if (NULL != strstr(row[0], condition->value))
613 ret = SUCCEED;
614 break;
615 case CONDITION_OPERATOR_NOT_LIKE:
616 if (NULL == strstr(row[0], condition->value))
617 ret = SUCCEED;
618 break;
619 default:
620 ret = NOTSUPPORTED;
621 }
622 }
623 DBfree_result(result);
624 }
625 }
626 else if (CONDITION_TYPE_DHOST_IP == condition->conditiontype)
627 {
628 if (EVENT_OBJECT_DHOST == event->object)
629 {
630 result = DBselect(
631 "select distinct ip"
632 " from dservices"
633 " where dhostid=" ZBX_FS_UI64,
634 event->objectid);
635 }
636 else
637 {
638 result = DBselect(
639 "select ip"
640 " from dservices"
641 " where dserviceid=" ZBX_FS_UI64,
642 event->objectid);
643 }
644
645 while (NULL != (row = DBfetch(result)) && FAIL == ret)
646 {
647 switch (condition->operator)
648 {
649 case CONDITION_OPERATOR_EQUAL:
650 if (SUCCEED == ip_in_list(condition->value, row[0]))
651 ret = SUCCEED;
652 break;
653 case CONDITION_OPERATOR_NOT_EQUAL:
654 if (SUCCEED != ip_in_list(condition->value, row[0]))
655 ret = SUCCEED;
656 break;
657 default:
658 ret = NOTSUPPORTED;
659 }
660 }
661 DBfree_result(result);
662 }
663 else if (CONDITION_TYPE_DSERVICE_TYPE == condition->conditiontype)
664 {
665 if (EVENT_OBJECT_DSERVICE == event->object)
666 {
667 int condition_value_i = atoi(condition->value);
668
669 result = DBselect(
670 "select type"
671 " from dservices"
672 " where dserviceid=" ZBX_FS_UI64,
673 event->objectid);
674
675 if (NULL != (row = DBfetch(result)))
676 {
677 tmp_int = atoi(row[0]);
678
679 switch (condition->operator)
680 {
681 case CONDITION_OPERATOR_EQUAL:
682 if (condition_value_i == tmp_int)
683 ret = SUCCEED;
684 break;
685 case CONDITION_OPERATOR_NOT_EQUAL:
686 if (condition_value_i != tmp_int)
687 ret = SUCCEED;
688 break;
689 default:
690 ret = NOTSUPPORTED;
691 }
692 }
693 DBfree_result(result);
694 }
695 }
696 else if (CONDITION_TYPE_DSTATUS == condition->conditiontype)
697 {
698 int condition_value_i = atoi(condition->value);
699
700 switch (condition->operator)
701 {
702 case CONDITION_OPERATOR_EQUAL:
703 if (condition_value_i == event->value)
704 ret = SUCCEED;
705 break;
706 case CONDITION_OPERATOR_NOT_EQUAL:
707 if (condition_value_i != event->value)
708 ret = SUCCEED;
709 break;
710 default:
711 ret = NOTSUPPORTED;
712 }
713 }
714 else if (CONDITION_TYPE_DUPTIME == condition->conditiontype)
715 {
716 int condition_value_i = atoi(condition->value);
717
718 if (EVENT_OBJECT_DHOST == event->object)
719 {
720 result = DBselect(
721 "select status,lastup,lastdown"
722 " from dhosts"
723 " where dhostid=" ZBX_FS_UI64,
724 event->objectid);
725 }
726 else
727 {
728 result = DBselect(
729 "select status,lastup,lastdown"
730 " from dservices"
731 " where dserviceid=" ZBX_FS_UI64,
732 event->objectid);
733 }
734
735 if (NULL != (row = DBfetch(result)))
736 {
737 int now;
738
739 now = time(NULL);
740 tmp_int = DOBJECT_STATUS_UP == atoi(row[0]) ? atoi(row[1]) : atoi(row[2]);
741
742 switch (condition->operator)
743 {
744 case CONDITION_OPERATOR_LESS_EQUAL:
745 if (0 != tmp_int && (now - tmp_int) <= condition_value_i)
746 ret = SUCCEED;
747 break;
748 case CONDITION_OPERATOR_MORE_EQUAL:
749 if (0 != tmp_int && (now - tmp_int) >= condition_value_i)
750 ret = SUCCEED;
751 break;
752 default:
753 ret = NOTSUPPORTED;
754 }
755 }
756 DBfree_result(result);
757 }
758 else if (CONDITION_TYPE_DSERVICE_PORT == condition->conditiontype)
759 {
760 if (EVENT_OBJECT_DSERVICE == event->object)
761 {
762 result = DBselect(
763 "select port"
764 " from dservices"
765 " where dserviceid=" ZBX_FS_UI64,
766 event->objectid);
767
768 if (NULL != (row = DBfetch(result)))
769 {
770 switch (condition->operator)
771 {
772 case CONDITION_OPERATOR_EQUAL:
773 if (SUCCEED == int_in_list(condition->value, atoi(row[0])))
774 ret = SUCCEED;
775 break;
776 case CONDITION_OPERATOR_NOT_EQUAL:
777 if (SUCCEED != int_in_list(condition->value, atoi(row[0])))
778 ret = SUCCEED;
779 break;
780 default:
781 ret = NOTSUPPORTED;
782 }
783 }
784 DBfree_result(result);
785 }
786 }
787 else
788 {
789 zabbix_log(LOG_LEVEL_ERR, "unsupported condition type [%d] for condition id [" ZBX_FS_UI64 "]",
790 (int)condition->conditiontype, condition->conditionid);
791 }
792
793 if (NOTSUPPORTED == ret)
794 {
795 zabbix_log(LOG_LEVEL_ERR, "unsupported operator [%d] for condition id [" ZBX_FS_UI64 "]",
796 (int)condition->operator, condition->conditionid);
797 ret = FAIL;
798 }
799
800 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
801
802 return ret;
803 }
804
805 /******************************************************************************
806 * *
807 * Function: check_auto_registration_condition *
808 * *
809 * Purpose: check if event matches single condition *
810 * *
811 * Parameters: event - auto registration event to check *
812 * (event->source == EVENT_SOURCE_AUTO_REGISTRATION) *
813 * condition - condition for matching *
814 * *
815 * Return value: SUCCEED - matches, FAIL - otherwise *
816 * *
817 * Author: Alexei Vladishev *
818 * *
819 ******************************************************************************/
check_auto_registration_condition(const DB_EVENT * event,DB_CONDITION * condition)820 static int check_auto_registration_condition(const DB_EVENT *event, DB_CONDITION *condition)
821 {
822 const char *__function_name = "check_auto_registration_condition";
823 DB_RESULT result;
824 DB_ROW row;
825 zbx_uint64_t condition_value, id;
826 int ret = FAIL;
827 const char *condition_field;
828
829 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
830
831 switch (condition->conditiontype)
832 {
833 case CONDITION_TYPE_HOST_NAME:
834 case CONDITION_TYPE_HOST_METADATA:
835 if (CONDITION_TYPE_HOST_NAME == condition->conditiontype)
836 condition_field = "host";
837 else
838 condition_field = "host_metadata";
839
840 result = DBselect(
841 "select %s"
842 " from autoreg_host"
843 " where autoreg_hostid=" ZBX_FS_UI64,
844 condition_field, event->objectid);
845
846 if (NULL != (row = DBfetch(result)))
847 {
848 switch (condition->operator)
849 {
850 case CONDITION_OPERATOR_LIKE:
851 if (NULL != strstr(row[0], condition->value))
852 ret = SUCCEED;
853 break;
854 case CONDITION_OPERATOR_NOT_LIKE:
855 if (NULL == strstr(row[0], condition->value))
856 ret = SUCCEED;
857 break;
858 default:
859 ret = NOTSUPPORTED;
860 }
861 }
862 DBfree_result(result);
863
864 break;
865 case CONDITION_TYPE_PROXY:
866 ZBX_STR2UINT64(condition_value, condition->value);
867
868 result = DBselect(
869 "select proxy_hostid"
870 " from autoreg_host"
871 " where autoreg_hostid=" ZBX_FS_UI64,
872 event->objectid);
873
874 if (NULL != (row = DBfetch(result)))
875 {
876 ZBX_DBROW2UINT64(id, row[0]);
877
878 switch (condition->operator)
879 {
880 case CONDITION_OPERATOR_EQUAL:
881 if (id == condition_value)
882 ret = SUCCEED;
883 break;
884 case CONDITION_OPERATOR_NOT_EQUAL:
885 if (id != condition_value)
886 ret = SUCCEED;
887 break;
888 default:
889 ret = NOTSUPPORTED;
890 }
891 }
892 DBfree_result(result);
893
894 break;
895 default:
896 zabbix_log(LOG_LEVEL_ERR, "unsupported condition type [%d] for condition id [" ZBX_FS_UI64 "]",
897 (int)condition->conditiontype, condition->conditionid);
898 }
899
900 if (NOTSUPPORTED == ret)
901 {
902 zabbix_log(LOG_LEVEL_ERR, "unsupported operator [%d] for condition id [" ZBX_FS_UI64 "]",
903 (int)condition->operator, condition->conditionid);
904 ret = FAIL;
905 }
906
907 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
908
909 return ret;
910 }
911
912 /******************************************************************************
913 * *
914 * Function: check_internal_condition *
915 * *
916 * Purpose: check if internal event matches single condition *
917 * *
918 * Parameters: event - [IN] trigger event to check *
919 * condition - [IN] condition for matching *
920 * *
921 * Return value: SUCCEED - matches, FAIL - otherwise *
922 * *
923 ******************************************************************************/
check_internal_condition(const DB_EVENT * event,DB_CONDITION * condition)924 static int check_internal_condition(const DB_EVENT *event, DB_CONDITION *condition)
925 {
926 const char *__function_name = "check_internal_condition";
927 DB_RESULT result;
928 DB_ROW row;
929 zbx_uint64_t condition_value;
930 int ret = FAIL;
931 char sql[256];
932
933 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
934
935 if (EVENT_OBJECT_TRIGGER != event->object && EVENT_OBJECT_ITEM != event->object &&
936 EVENT_OBJECT_LLDRULE != event->object)
937 {
938 zabbix_log(LOG_LEVEL_ERR, "unsupported event object [%d] for condition id [" ZBX_FS_UI64 "]",
939 event->object, condition->conditionid);
940 goto out;
941 }
942
943 if (CONDITION_TYPE_EVENT_TYPE == condition->conditiontype)
944 {
945 condition_value = atoi(condition->value);
946
947 switch (condition_value)
948 {
949 case EVENT_TYPE_ITEM_NORMAL:
950 if (EVENT_OBJECT_ITEM == event->object && ITEM_STATE_NORMAL == event->value)
951 ret = SUCCEED;
952 break;
953 case EVENT_TYPE_ITEM_NOTSUPPORTED:
954 if (EVENT_OBJECT_ITEM == event->object && ITEM_STATE_NOTSUPPORTED == event->value)
955 ret = SUCCEED;
956 break;
957 case EVENT_TYPE_TRIGGER_NORMAL:
958 if (EVENT_OBJECT_TRIGGER == event->object && TRIGGER_STATE_NORMAL == event->value)
959 ret = SUCCEED;
960 break;
961 case EVENT_TYPE_TRIGGER_UNKNOWN:
962 if (EVENT_OBJECT_TRIGGER == event->object && TRIGGER_STATE_UNKNOWN == event->value)
963 ret = SUCCEED;
964 break;
965 case EVENT_TYPE_LLDRULE_NORMAL:
966 if (EVENT_OBJECT_LLDRULE == event->object && ITEM_STATE_NORMAL == event->value)
967 ret = SUCCEED;
968 break;
969 case EVENT_TYPE_LLDRULE_NOTSUPPORTED:
970 if (EVENT_OBJECT_LLDRULE == event->object && ITEM_STATE_NOTSUPPORTED == event->value)
971 ret = SUCCEED;
972 break;
973 default:
974 ret = NOTSUPPORTED;
975 }
976 }
977 else if (CONDITION_TYPE_HOST_GROUP == condition->conditiontype)
978 {
979 ZBX_STR2UINT64(condition_value, condition->value);
980
981 switch (event->object)
982 {
983 case EVENT_OBJECT_TRIGGER:
984 zbx_snprintf(sql, sizeof(sql),
985 "select null"
986 " from hosts_groups hg,hosts h,items i,functions f,triggers t"
987 " where hg.hostid=h.hostid"
988 " and h.hostid=i.hostid"
989 " and i.itemid=f.itemid"
990 " and f.triggerid=t.triggerid"
991 " and t.triggerid=" ZBX_FS_UI64
992 " and hg.groupid=" ZBX_FS_UI64,
993 event->objectid, condition_value);
994 break;
995 default:
996 zbx_snprintf(sql, sizeof(sql),
997 "select null"
998 " from hosts_groups hg,hosts h,items i"
999 " where hg.hostid=h.hostid"
1000 " and h.hostid=i.hostid"
1001 " and i.itemid=" ZBX_FS_UI64
1002 " and hg.groupid=" ZBX_FS_UI64,
1003 event->objectid, condition_value);
1004 }
1005
1006 result = DBselectN(sql, 1);
1007
1008 switch (condition->operator)
1009 {
1010 case CONDITION_OPERATOR_EQUAL:
1011 if (NULL != DBfetch(result))
1012 ret = SUCCEED;
1013 break;
1014 case CONDITION_OPERATOR_NOT_EQUAL:
1015 if (NULL == DBfetch(result))
1016 ret = SUCCEED;
1017 break;
1018 default:
1019 ret = NOTSUPPORTED;
1020 }
1021 DBfree_result(result);
1022 }
1023 else if (CONDITION_TYPE_HOST_TEMPLATE == condition->conditiontype)
1024 {
1025 zbx_uint64_t hostid, objectid;
1026
1027 ZBX_STR2UINT64(condition_value, condition->value);
1028
1029 switch (condition->operator)
1030 {
1031 case CONDITION_OPERATOR_EQUAL:
1032 case CONDITION_OPERATOR_NOT_EQUAL:
1033 objectid = event->objectid;
1034
1035 /* use parent object ID for generated objects */
1036 switch (event->object)
1037 {
1038 case EVENT_OBJECT_TRIGGER:
1039 result = DBselect(
1040 "select parent_triggerid"
1041 " from trigger_discovery"
1042 " where triggerid=" ZBX_FS_UI64,
1043 objectid);
1044 break;
1045 default:
1046 result = DBselect(
1047 "select id.parent_itemid"
1048 " from item_discovery id,items i"
1049 " where id.itemid=i.itemid"
1050 " and i.itemid=" ZBX_FS_UI64
1051 " and i.flags=%d",
1052 objectid, ZBX_FLAG_DISCOVERY_CREATED);
1053 }
1054
1055 if (NULL != (row = DBfetch(result)))
1056 {
1057 ZBX_STR2UINT64(objectid, row[0]);
1058
1059 zabbix_log(LOG_LEVEL_DEBUG, "%s() check host template condition,"
1060 " selecting parent objectid:" ZBX_FS_UI64,
1061 __function_name, objectid);
1062 }
1063 DBfree_result(result);
1064
1065 do
1066 {
1067 switch (event->object)
1068 {
1069 case EVENT_OBJECT_TRIGGER:
1070 result = DBselect(
1071 "select distinct i.hostid,t.templateid"
1072 " from items i,functions f,triggers t"
1073 " where i.itemid=f.itemid"
1074 " and f.triggerid=t.templateid"
1075 " and t.triggerid=" ZBX_FS_UI64,
1076 objectid);
1077 break;
1078 default:
1079 result = DBselect(
1080 "select t.hostid,t.itemid"
1081 " from items t,items h"
1082 " where t.itemid=h.templateid"
1083 " and h.itemid=" ZBX_FS_UI64,
1084 objectid);
1085 }
1086
1087 objectid = 0;
1088
1089 while (NULL != (row = DBfetch(result)))
1090 {
1091 ZBX_STR2UINT64(hostid, row[0]);
1092 ZBX_STR2UINT64(objectid, row[1]);
1093
1094 if (hostid == condition_value)
1095 {
1096 ret = SUCCEED;
1097 break;
1098 }
1099 }
1100 DBfree_result(result);
1101 }
1102 while (SUCCEED != ret && 0 != objectid);
1103
1104 if (CONDITION_OPERATOR_NOT_EQUAL == condition->operator)
1105 ret = (SUCCEED == ret) ? FAIL : SUCCEED;
1106 break;
1107 default:
1108 ret = NOTSUPPORTED;
1109 }
1110 }
1111 else if (CONDITION_TYPE_HOST == condition->conditiontype)
1112 {
1113 ZBX_STR2UINT64(condition_value, condition->value);
1114
1115 switch (event->object)
1116 {
1117 case EVENT_OBJECT_TRIGGER:
1118 zbx_snprintf(sql, sizeof(sql),
1119 "select null"
1120 " from items i,functions f,triggers t"
1121 " where i.itemid=f.itemid"
1122 " and f.triggerid=t.triggerid"
1123 " and t.triggerid=" ZBX_FS_UI64
1124 " and i.hostid=" ZBX_FS_UI64,
1125 event->objectid, condition_value);
1126 break;
1127 default:
1128 zbx_snprintf(sql, sizeof(sql),
1129 "select null"
1130 " from items"
1131 " where itemid=" ZBX_FS_UI64
1132 " and hostid=" ZBX_FS_UI64,
1133 event->objectid, condition_value);
1134 }
1135
1136 result = DBselectN(sql, 1);
1137
1138 switch (condition->operator)
1139 {
1140 case CONDITION_OPERATOR_EQUAL:
1141 if (NULL != DBfetch(result))
1142 ret = SUCCEED;
1143 break;
1144 case CONDITION_OPERATOR_NOT_EQUAL:
1145 if (NULL == DBfetch(result))
1146 ret = SUCCEED;
1147 break;
1148 default:
1149 ret = NOTSUPPORTED;
1150 }
1151 DBfree_result(result);
1152 }
1153 else if (CONDITION_TYPE_APPLICATION == condition->conditiontype)
1154 {
1155 switch (event->object)
1156 {
1157 case EVENT_OBJECT_TRIGGER:
1158 result = DBselect(
1159 "select distinct a.name"
1160 " from applications a,items_applications i,functions f,triggers t"
1161 " where a.applicationid=i.applicationid"
1162 " and i.itemid=f.itemid"
1163 " and f.triggerid=t.triggerid"
1164 " and t.triggerid=" ZBX_FS_UI64,
1165 event->objectid);
1166 break;
1167 default:
1168 result = DBselect(
1169 "select distinct a.name"
1170 " from applications a,items_applications i"
1171 " where a.applicationid=i.applicationid"
1172 " and i.itemid=" ZBX_FS_UI64,
1173 event->objectid);
1174 }
1175
1176 switch (condition->operator)
1177 {
1178 case CONDITION_OPERATOR_EQUAL:
1179 while (NULL != (row = DBfetch(result)))
1180 {
1181 if (0 == strcmp(row[0], condition->value))
1182 {
1183 ret = SUCCEED;
1184 break;
1185 }
1186 }
1187 break;
1188 case CONDITION_OPERATOR_LIKE:
1189 while (NULL != (row = DBfetch(result)))
1190 {
1191 if (NULL != strstr(row[0], condition->value))
1192 {
1193 ret = SUCCEED;
1194 break;
1195 }
1196 }
1197 break;
1198 case CONDITION_OPERATOR_NOT_LIKE:
1199 ret = SUCCEED;
1200 while (NULL != (row = DBfetch(result)))
1201 {
1202 if (NULL != strstr(row[0], condition->value))
1203 {
1204 ret = FAIL;
1205 break;
1206 }
1207 }
1208 break;
1209 default:
1210 ret = NOTSUPPORTED;
1211 }
1212 DBfree_result(result);
1213 }
1214 else
1215 {
1216 zabbix_log(LOG_LEVEL_ERR, "unsupported condition type [%d] for condition id [" ZBX_FS_UI64 "]",
1217 (int)condition->conditiontype, condition->conditionid);
1218 }
1219
1220 if (NOTSUPPORTED == ret)
1221 {
1222 zabbix_log(LOG_LEVEL_ERR, "unsupported operator [%d] for condition id [" ZBX_FS_UI64 "]",
1223 (int)condition->operator, condition->conditionid);
1224 ret = FAIL;
1225 }
1226 out:
1227 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
1228
1229 return ret;
1230 }
1231
1232 /******************************************************************************
1233 * *
1234 * Function: check_action_condition *
1235 * *
1236 * Purpose: check if event matches single condition *
1237 * *
1238 * Parameters: event - event to check *
1239 * condition - condition for matching *
1240 * *
1241 * Return value: SUCCEED - matches, FAIL - otherwise *
1242 * *
1243 * Author: Alexei Vladishev *
1244 * *
1245 ******************************************************************************/
check_action_condition(const DB_EVENT * event,DB_CONDITION * condition)1246 int check_action_condition(const DB_EVENT *event, DB_CONDITION *condition)
1247 {
1248 const char *__function_name = "check_action_condition";
1249 int ret = FAIL;
1250
1251 zabbix_log(LOG_LEVEL_DEBUG, "In %s() actionid:" ZBX_FS_UI64 " conditionid:" ZBX_FS_UI64 " cond.value:'%s'",
1252 __function_name, condition->actionid, condition->conditionid, condition->value);
1253
1254 switch (event->source)
1255 {
1256 case EVENT_SOURCE_TRIGGERS:
1257 ret = check_trigger_condition(event, condition);
1258 break;
1259 case EVENT_SOURCE_DISCOVERY:
1260 ret = check_discovery_condition(event, condition);
1261 break;
1262 case EVENT_SOURCE_AUTO_REGISTRATION:
1263 ret = check_auto_registration_condition(event, condition);
1264 break;
1265 case EVENT_SOURCE_INTERNAL:
1266 ret = check_internal_condition(event, condition);
1267 break;
1268 default:
1269 zabbix_log(LOG_LEVEL_ERR, "unsupported event source [%d] for condition id [" ZBX_FS_UI64 "]",
1270 event->source, condition->conditionid);
1271 }
1272
1273 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
1274
1275 return ret;
1276 }
1277
1278 /******************************************************************************
1279 * *
1280 * Function: check_action_conditions *
1281 * *
1282 * Purpose: check if actions have to be processed for the event *
1283 * (check all conditions of the action) *
1284 * *
1285 * Parameters: event - event to check *
1286 * actionid - action ID for matching *
1287 * *
1288 * Return value: SUCCEED - matches, FAIL - otherwise *
1289 * *
1290 * Author: Alexei Vladishev *
1291 * *
1292 ******************************************************************************/
check_action_conditions(const DB_EVENT * event,zbx_action_eval_t * action)1293 static int check_action_conditions(const DB_EVENT *event, zbx_action_eval_t *action)
1294 {
1295 const char *__function_name = "check_action_conditions";
1296
1297 DB_CONDITION *condition;
1298 int condition_result, ret = SUCCEED, id_len, i;
1299 unsigned char old_type = 0xff;
1300 char *expression = NULL, tmp[ZBX_MAX_UINT64_LEN + 2], *ptr, error[256];
1301 double eval_result;
1302
1303 zabbix_log(LOG_LEVEL_DEBUG, "In %s() actionid:" ZBX_FS_UI64, __function_name, action->actionid);
1304
1305 if (action->evaltype == CONDITION_EVAL_TYPE_EXPRESSION)
1306 expression = zbx_strdup(expression, action->formula);
1307
1308 for (i = 0; i < action->conditions.values_num; i++)
1309 {
1310 condition = (DB_CONDITION *)action->conditions.values[i];
1311
1312 if (CONDITION_EVAL_TYPE_AND_OR == action->evaltype && old_type == condition->conditiontype &&
1313 SUCCEED == ret)
1314 {
1315 continue; /* short-circuit true OR condition block to the next AND condition */
1316 }
1317
1318 condition_result = check_action_condition(event, condition);
1319
1320 switch (action->evaltype)
1321 {
1322 case CONDITION_EVAL_TYPE_AND_OR:
1323 if (old_type == condition->conditiontype) /* assume conditions are sorted by type */
1324 {
1325 if (SUCCEED == condition_result)
1326 ret = SUCCEED;
1327 }
1328 else
1329 {
1330 if (FAIL == ret)
1331 goto clean;
1332
1333 ret = condition_result;
1334 old_type = condition->conditiontype;
1335 }
1336
1337 break;
1338 case CONDITION_EVAL_TYPE_AND:
1339 if (FAIL == condition_result) /* break if any AND condition is FALSE */
1340 {
1341 ret = FAIL;
1342 goto clean;
1343 }
1344
1345 break;
1346 case CONDITION_EVAL_TYPE_OR:
1347 if (SUCCEED == condition_result) /* break if any OR condition is TRUE */
1348 {
1349 ret = SUCCEED;
1350 goto clean;
1351 }
1352 ret = FAIL;
1353
1354 break;
1355 case CONDITION_EVAL_TYPE_EXPRESSION:
1356 zbx_snprintf(tmp, sizeof(tmp), "{" ZBX_FS_UI64 "}", condition->conditionid);
1357 id_len = strlen(tmp);
1358
1359 for (ptr = expression; NULL != (ptr = strstr(ptr, tmp)); ptr += id_len)
1360 {
1361 *ptr = (SUCCEED == condition_result ? '1' : '0');
1362 memset(ptr + 1, ' ', id_len - 1);
1363 }
1364
1365 break;
1366 default:
1367 ret = FAIL;
1368 goto clean;
1369 }
1370 }
1371
1372 if (action->evaltype == CONDITION_EVAL_TYPE_EXPRESSION)
1373 {
1374 if (SUCCEED == evaluate(&eval_result, expression, error, sizeof(error)))
1375 ret = (SUCCEED != zbx_double_compare(eval_result, 0) ? SUCCEED : FAIL);
1376
1377 zbx_free(expression);
1378 }
1379 clean:
1380
1381 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
1382
1383 return ret;
1384 }
1385
1386 /******************************************************************************
1387 * *
1388 * Function: execute_operations *
1389 * *
1390 * Purpose: execute all operations linked to the action *
1391 * *
1392 * Parameters: action - action to execute operations for *
1393 * *
1394 * Author: Alexei Vladishev *
1395 * *
1396 ******************************************************************************/
execute_operations(const DB_EVENT * event,zbx_uint64_t actionid)1397 static void execute_operations(const DB_EVENT *event, zbx_uint64_t actionid)
1398 {
1399 const char *__function_name = "execute_operations";
1400
1401 DB_RESULT result;
1402 DB_ROW row;
1403 zbx_uint64_t groupid, templateid;
1404 zbx_vector_uint64_t lnk_templateids, del_templateids,
1405 new_groupids, del_groupids;
1406
1407 zabbix_log(LOG_LEVEL_DEBUG, "In %s() actionid:" ZBX_FS_UI64, __function_name, actionid);
1408
1409 zbx_vector_uint64_create(&lnk_templateids);
1410 zbx_vector_uint64_create(&del_templateids);
1411 zbx_vector_uint64_create(&new_groupids);
1412 zbx_vector_uint64_create(&del_groupids);
1413
1414 result = DBselect(
1415 "select o.operationtype,g.groupid,t.templateid,oi.inventory_mode"
1416 " from operations o"
1417 " left join opgroup g on g.operationid=o.operationid"
1418 " left join optemplate t on t.operationid=o.operationid"
1419 " left join opinventory oi on oi.operationid=o.operationid"
1420 " where o.actionid=" ZBX_FS_UI64,
1421 actionid);
1422
1423 while (NULL != (row = DBfetch(result)))
1424 {
1425 int inventory_mode;
1426 unsigned char operationtype;
1427
1428 operationtype = (unsigned char)atoi(row[0]);
1429 ZBX_DBROW2UINT64(groupid, row[1]);
1430 ZBX_DBROW2UINT64(templateid, row[2]);
1431 inventory_mode = (SUCCEED == DBis_null(row[3]) ? 0 : atoi(row[3]));
1432
1433 switch (operationtype)
1434 {
1435 case OPERATION_TYPE_HOST_ADD:
1436 op_host_add(event);
1437 break;
1438 case OPERATION_TYPE_HOST_REMOVE:
1439 op_host_del(event);
1440 break;
1441 case OPERATION_TYPE_HOST_ENABLE:
1442 op_host_enable(event);
1443 break;
1444 case OPERATION_TYPE_HOST_DISABLE:
1445 op_host_disable(event);
1446 break;
1447 case OPERATION_TYPE_GROUP_ADD:
1448 if (0 != groupid)
1449 zbx_vector_uint64_append(&new_groupids, groupid);
1450 break;
1451 case OPERATION_TYPE_GROUP_REMOVE:
1452 if (0 != groupid)
1453 zbx_vector_uint64_append(&del_groupids, groupid);
1454 break;
1455 case OPERATION_TYPE_TEMPLATE_ADD:
1456 if (0 != templateid)
1457 zbx_vector_uint64_append(&lnk_templateids, templateid);
1458 break;
1459 case OPERATION_TYPE_TEMPLATE_REMOVE:
1460 if (0 != templateid)
1461 zbx_vector_uint64_append(&del_templateids, templateid);
1462 break;
1463 case OPERATION_TYPE_HOST_INVENTORY:
1464 op_host_inventory_mode(event, inventory_mode);
1465 break;
1466 default:
1467 ;
1468 }
1469 }
1470 DBfree_result(result);
1471
1472 if (0 != lnk_templateids.values_num)
1473 {
1474 zbx_vector_uint64_sort(&lnk_templateids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1475 zbx_vector_uint64_uniq(&lnk_templateids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1476 op_template_add(event, &lnk_templateids);
1477 }
1478
1479 if (0 != del_templateids.values_num)
1480 {
1481 zbx_vector_uint64_sort(&del_templateids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1482 zbx_vector_uint64_uniq(&del_templateids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1483 op_template_del(event, &del_templateids);
1484 }
1485
1486 if (0 != new_groupids.values_num)
1487 {
1488 zbx_vector_uint64_sort(&new_groupids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1489 zbx_vector_uint64_uniq(&new_groupids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1490 op_groups_add(event, &new_groupids);
1491 }
1492
1493 if (0 != del_groupids.values_num)
1494 {
1495 zbx_vector_uint64_sort(&del_groupids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1496 zbx_vector_uint64_uniq(&del_groupids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1497 op_groups_del(event, &del_groupids);
1498 }
1499
1500 zbx_vector_uint64_destroy(&del_groupids);
1501 zbx_vector_uint64_destroy(&new_groupids);
1502 zbx_vector_uint64_destroy(&del_templateids);
1503 zbx_vector_uint64_destroy(&lnk_templateids);
1504
1505 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
1506 }
1507
escalation_add_values(zbx_db_insert_t * db_insert,int escalations_num,zbx_uint64_t actionid,const DB_EVENT * event,unsigned char recovery)1508 static void escalation_add_values(zbx_db_insert_t *db_insert, int escalations_num, zbx_uint64_t actionid,
1509 const DB_EVENT *event, unsigned char recovery)
1510 {
1511 zbx_uint64_t escalationid, triggerid = 0, itemid = 0, eventid = 0, r_eventid = 0;
1512
1513 if (0 == escalations_num)
1514 {
1515 zbx_db_insert_prepare(db_insert, "escalations", "escalationid", "actionid", "status", "triggerid",
1516 "itemid", "eventid", "r_eventid", NULL);
1517 }
1518
1519 escalationid = DBget_maxid("escalations");
1520
1521 switch (event->object)
1522 {
1523 case EVENT_OBJECT_TRIGGER:
1524 triggerid = event->objectid;
1525 break;
1526 case EVENT_OBJECT_ITEM:
1527 case EVENT_OBJECT_LLDRULE:
1528 itemid = event->objectid;
1529 break;
1530 }
1531
1532 if (0 == recovery)
1533 eventid = event->eventid;
1534 else
1535 r_eventid = event->eventid;
1536
1537 zbx_db_insert_add_values(db_insert, escalationid, actionid, (int)ESCALATION_STATUS_ACTIVE, triggerid, itemid,
1538 eventid, r_eventid);
1539 }
1540
1541 /******************************************************************************
1542 * *
1543 * Function: process_actions *
1544 * *
1545 * Purpose: process all actions of each event in a list *
1546 * *
1547 * Parameters: events - [IN] events to apply actions for *
1548 * events_num - [IN] number of events *
1549 * *
1550 ******************************************************************************/
process_actions(const DB_EVENT * events,size_t events_num)1551 void process_actions(const DB_EVENT *events, size_t events_num)
1552 {
1553 const char *__function_name = "process_actions";
1554
1555 DB_RESULT result;
1556 DB_ROW row;
1557 zbx_uint64_t actionid;
1558 size_t i;
1559 zbx_vector_uint64_t rec_actionids; /* actionids of possible recovery events */
1560 zbx_vector_uint64_pair_t rec_mapping; /* which action is possibly recovered by which event */
1561 const DB_EVENT *event;
1562 zbx_db_insert_t db_insert;
1563 int escalations_num = 0, j;
1564 zbx_vector_ptr_t actions;
1565
1566 zabbix_log(LOG_LEVEL_DEBUG, "In %s() events_num:" ZBX_FS_SIZE_T, __function_name, (zbx_fs_size_t)events_num);
1567
1568 zbx_vector_uint64_create(&rec_actionids);
1569 zbx_vector_uint64_pair_create(&rec_mapping);
1570
1571 zbx_vector_ptr_create(&actions);
1572 zbx_dc_get_actions_eval(&actions);
1573
1574 for (i = 0; i < events_num; i++)
1575 {
1576 event = &events[i];
1577
1578 for (j = 0; j < actions.values_num; j++)
1579 {
1580 zbx_action_eval_t *action = (zbx_action_eval_t *)actions.values[j];
1581
1582 if (action->eventsource != event->source)
1583 continue;
1584
1585 if (SUCCEED == check_action_conditions(event, action))
1586 {
1587 escalation_add_values(&db_insert, escalations_num++, action->actionid, event, 0);
1588
1589 if (EVENT_SOURCE_DISCOVERY == event->source ||
1590 EVENT_SOURCE_AUTO_REGISTRATION == event->source)
1591 {
1592 execute_operations(event, action->actionid);
1593 }
1594 }
1595 else if (EVENT_SOURCE_TRIGGERS == event->source || EVENT_SOURCE_INTERNAL == event->source)
1596 {
1597 /* Action conditions evaluated to false, but it could be a recovery */
1598 /* event for this action. Remember this and check escalations later. */
1599
1600 zbx_uint64_pair_t pair;
1601
1602 pair.first = action->actionid;
1603 pair.second = (zbx_uint64_t)i;
1604
1605 zbx_vector_uint64_pair_append(&rec_mapping, pair);
1606
1607 zbx_vector_uint64_append(&rec_actionids, action->actionid);
1608 }
1609 }
1610 }
1611
1612 zbx_vector_ptr_clear_ext(&actions, (zbx_clean_func_t)zbx_action_eval_free);
1613 zbx_vector_ptr_destroy(&actions);
1614
1615 if (0 != rec_actionids.values_num)
1616 {
1617 char *sql = NULL;
1618 size_t sql_alloc = 0, sql_offset = 0;
1619 zbx_uint64_t triggerid, itemid;
1620
1621 zbx_vector_uint64_sort(&rec_actionids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1622 zbx_vector_uint64_uniq(&rec_actionids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1623
1624 /* list of ongoing escalations matching actionids collected before */
1625 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
1626 "select actionid,triggerid,itemid"
1627 " from escalations"
1628 " where eventid is not null"
1629 " and");
1630 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "actionid",
1631 rec_actionids.values, rec_actionids.values_num);
1632 result = DBselect("%s", sql);
1633 zbx_free(sql);
1634
1635 while (NULL != (row = DBfetch(result)))
1636 {
1637 ZBX_STR2UINT64(actionid, row[0]);
1638 ZBX_DBROW2UINT64(triggerid, row[1]);
1639 ZBX_DBROW2UINT64(itemid, row[2]);
1640
1641 for (j = 0; j < rec_mapping.values_num; j++)
1642 {
1643 if (actionid != rec_mapping.values[j].first)
1644 continue;
1645
1646 event = &events[(int)rec_mapping.values[j].second];
1647
1648 /* only add recovery if it matches event */
1649 switch (event->source)
1650 {
1651 case EVENT_SOURCE_TRIGGERS:
1652 if (triggerid != event->objectid)
1653 continue;
1654 break;
1655 case EVENT_SOURCE_INTERNAL:
1656 switch (event->object)
1657 {
1658 case EVENT_OBJECT_TRIGGER:
1659 if (triggerid != event->objectid)
1660 continue;
1661 break;
1662 case EVENT_OBJECT_ITEM:
1663 case EVENT_OBJECT_LLDRULE:
1664 if (itemid != event->objectid)
1665 continue;
1666 break;
1667 default:
1668 THIS_SHOULD_NEVER_HAPPEN;
1669 }
1670
1671 break;
1672 default:
1673 continue;
1674 }
1675
1676 escalation_add_values(&db_insert, escalations_num++, actionid, event, 1);
1677
1678 break;
1679 }
1680 }
1681 DBfree_result(result);
1682 }
1683
1684 zbx_vector_uint64_pair_destroy(&rec_mapping);
1685 zbx_vector_uint64_destroy(&rec_actionids);
1686
1687 if (0 != escalations_num)
1688 {
1689 zbx_db_insert_execute(&db_insert);
1690 zbx_db_insert_clean(&db_insert);
1691 }
1692
1693 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
1694 }
1695