diff options
| author | sasha <sasha@97f52cf1-0a1b-0410-bd0e-c28be96e8082> | 2008-05-27 08:24:17 +0000 |
|---|---|---|
| committer | sasha <sasha@97f52cf1-0a1b-0410-bd0e-c28be96e8082> | 2008-05-27 08:24:17 +0000 |
| commit | c0bfb062b8ac422278fbd5b299ecbef51203011b (patch) | |
| tree | 0d21b48a18b42a9fafeb19236cff97f50436bc3a /src/zabbix_server | |
| parent | 1528814bf6b442cc01211b9f0b3f2adaadf970f4 (diff) | |
| download | zabbix-c0bfb062b8ac422278fbd5b299ecbef51203011b.tar.gz zabbix-c0bfb062b8ac422278fbd5b299ecbef51203011b.tar.xz zabbix-c0bfb062b8ac422278fbd5b299ecbef51203011b.zip | |
- [DEV-173] added support of notification escalations on server side
git-svn-id: svn://svn.zabbix.com/trunk@5725 97f52cf1-0a1b-0410-bd0e-c28be96e8082
Diffstat (limited to 'src/zabbix_server')
| -rw-r--r-- | src/zabbix_server/Makefile.am | 4 | ||||
| -rw-r--r-- | src/zabbix_server/actions.c | 34 | ||||
| -rw-r--r-- | src/zabbix_server/actions.h | 1 | ||||
| -rw-r--r-- | src/zabbix_server/alerter/alerter.c | 118 | ||||
| -rw-r--r-- | src/zabbix_server/escalator/Makefile.am | 5 | ||||
| -rw-r--r-- | src/zabbix_server/escalator/escalator.c | 679 | ||||
| -rw-r--r-- | src/zabbix_server/escalator/escalator.h | 27 | ||||
| -rw-r--r-- | src/zabbix_server/events.c | 4 | ||||
| -rw-r--r-- | src/zabbix_server/events.h | 1 | ||||
| -rw-r--r-- | src/zabbix_server/operations.c | 59 | ||||
| -rw-r--r-- | src/zabbix_server/operations.h | 6 | ||||
| -rw-r--r-- | src/zabbix_server/server.c | 18 |
12 files changed, 850 insertions, 106 deletions
diff --git a/src/zabbix_server/Makefile.am b/src/zabbix_server/Makefile.am index 9e2874fb..e9313db1 100644 --- a/src/zabbix_server/Makefile.am +++ b/src/zabbix_server/Makefile.am @@ -12,7 +12,8 @@ SUBDIRS = \ timer \ trapper \ utils \ - watchdog + watchdog \ + escalator sbin_PROGRAMS = zabbix_server @@ -40,6 +41,7 @@ zabbix_server_LDADD = \ utils/libzbxutils.a \ httppoller/libzbxhttppoller.a \ watchdog/libzbxwatchdog.a \ + escalator/libzbxescalator.a \ $(top_srcdir)/src/libs/zbxsysinfo/libzbxserversysinfo.a \ $(top_srcdir)/src/libs/zbxsysinfo/$(ARCH)/libspecsysinfo.a \ $(top_srcdir)/src/libs/zbxsysinfo/common/libcommonsysinfo.a \ diff --git a/src/zabbix_server/actions.c b/src/zabbix_server/actions.c index 565f3d07..103402d1 100644 --- a/src/zabbix_server/actions.c +++ b/src/zabbix_server/actions.c @@ -65,7 +65,7 @@ * Comments: * * * ******************************************************************************/ -static int check_action_condition(DB_EVENT *event, DB_CONDITION *condition) +int check_action_condition(DB_EVENT *event, DB_CONDITION *condition) { DB_RESULT result; DB_ROW row; @@ -333,6 +333,25 @@ static int check_action_condition(DB_EVENT *event, DB_CONDITION *condition) condition->conditionid); } } + else if(event->source == EVENT_SOURCE_TRIGGERS && condition->conditiontype == CONDITION_TYPE_EVENT_ACKNOWLEDGED) + { + result = DBselect("select count(*) from acknowledges where eventid=" ZBX_FS_UI64, + event->eventid); + + value_int = (NULL != (row = DBfetch(result)) && SUCCEED != DBis_null(row[0]) && 0 != atoi(row[0])) ? 1 : 0; + + DBfree_result(result); + +zabbix_log(LOG_LEVEL_ERR, "----- operator:%d value:%s:%d=%d", condition->operator, condition->value, atoi(condition->value), value_int); + if(condition->operator == CONDITION_OPERATOR_EQUAL) { + if (value_int == atoi(condition->value)) + ret = SUCCEED; + } else { + zabbix_log(LOG_LEVEL_ERR, "Unsupported operator [%d] for condition id [" ZBX_FS_UI64 "]", + condition->operator, + condition->conditionid); + } + } else if(event->source == EVENT_SOURCE_DISCOVERY && event->object == EVENT_OBJECT_DSERVICE && condition->conditiontype == CONDITION_TYPE_DVALUE) @@ -730,12 +749,12 @@ void execute_operations(DB_EVENT *event, DB_ACTION *action) switch(operation.operationtype) { - case OPERATION_TYPE_MESSAGE: +/* case OPERATION_TYPE_MESSAGE: op_notify_user(event,action,&operation); break; case OPERATION_TYPE_COMMAND: op_run_commands(event,&operation); - break; + break;*/ case OPERATION_TYPE_HOST_ADD: op_host_add(event); break; @@ -807,12 +826,17 @@ void process_actions(DB_EVENT *event) { zabbix_log( LOG_LEVEL_DEBUG, "Conditions match our event. Execute operations."); - execute_operations(event, &action); - + if (event->source == EVENT_SOURCE_TRIGGERS && event->object == EVENT_OBJECT_TRIGGER) + DBstart_escalation(action.actionid, event->objectid, event->eventid); + else + execute_operations(event, &action); } else { zabbix_log( LOG_LEVEL_DEBUG, "Conditions do not match our event. Do not execute operations."); + + if (event->source == EVENT_SOURCE_TRIGGERS && event->object == EVENT_OBJECT_TRIGGER) + DBstop_escalation(action.actionid, event->objectid); } } DBfree_result(result); diff --git a/src/zabbix_server/actions.h b/src/zabbix_server/actions.h index eb2ab1f5..cdda16c1 100644 --- a/src/zabbix_server/actions.h +++ b/src/zabbix_server/actions.h @@ -24,6 +24,7 @@ #include "common.h" #include "db.h" +int check_action_condition(DB_EVENT *event, DB_CONDITION *condition); void process_actions(DB_EVENT *event); #endif diff --git a/src/zabbix_server/alerter/alerter.c b/src/zabbix_server/alerter/alerter.c index 196f3601..26f0920f 100644 --- a/src/zabbix_server/alerter/alerter.c +++ b/src/zabbix_server/alerter/alerter.c @@ -66,22 +66,22 @@ int execute_action(DB_ALERT *alert,DB_MEDIATYPE *mediatype, char *error, int max zabbix_log( LOG_LEVEL_DEBUG, "In execute_action(%s)", mediatype->smtp_server); - if(mediatype->type==ALERT_TYPE_EMAIL) + if(mediatype->type==MEDIA_TYPE_EMAIL) { res = send_email(mediatype->smtp_server,mediatype->smtp_helo,mediatype->smtp_email,alert->sendto,alert->subject, alert->message, error, max_error_len); } #if defined (HAVE_JABBER) - else if(mediatype->type==ALERT_TYPE_JABBER) + else if(mediatype->type==MEDIA_TYPE_JABBER) { res = send_jabber(mediatype->username, mediatype->passwd, alert->sendto, alert->message, error, max_error_len); } #endif /* HAVE_JABBER */ - else if(mediatype->type==ALERT_TYPE_SMS) + else if(mediatype->type==MEDIA_TYPE_SMS) { res = send_sms(mediatype->gsm_modem,alert->sendto,alert->message, error, max_error_len); } - else if(mediatype->type==ALERT_TYPE_EXEC) + else if(mediatype->type==MEDIA_TYPE_EXEC) { /* if(-1 == execl(CONFIG_ALERT_SCRIPTS_PATH,mediatype->exec_path,alert->sendto,alert->subject,alert->message))*/ zabbix_log( LOG_LEVEL_DEBUG, "Before execl([%s],[%s])", @@ -175,68 +175,67 @@ int execute_action(DB_ALERT *alert,DB_MEDIATYPE *mediatype, char *error, int max ******************************************************************************/ int main_alerter_loop() { - char error[MAX_STRING_LEN]; - char error_esc[MAX_STRING_LEN]; - - int res, now; - - struct sigaction phan; - - DB_RESULT result; - DB_ROW row; - DB_ALERT alert; - DB_MEDIATYPE mediatype; - - for(;;) - { - zbx_setproctitle("connecting to the database"); - - DBconnect(ZBX_DB_CONNECT_NORMAL); - - now = time(NULL); - - result = DBselect("select a.alertid,a.mediatypeid,a.sendto,a.subject,a.message,a.status,mt.mediatypeid,mt.type,mt.description,mt.smtp_server,mt.smtp_helo,mt.smtp_email,mt.exec_path,mt.gsm_modem,mt.username,mt.passwd,a.retries from alerts a,media_type mt where a.status=%d and a.mediatypeid=mt.mediatypeid" DB_NODE " order by a.clock", - ALERT_STATUS_NOT_SENT, - DBnode_local("mt.mediatypeid")); - - while((row=DBfetch(result))) - { + char error[MAX_STRING_LEN], *error_esc; + int res, now; + struct sigaction phan; + DB_RESULT result; + DB_ROW row; + DB_ALERT alert; + DB_MEDIATYPE mediatype; + + phan.sa_handler = child_signal_handler; + sigemptyset(&phan.sa_mask); + phan.sa_flags = 0; + sigaction(SIGALRM, &phan, NULL); + + zbx_setproctitle("connecting to the database"); + + DBconnect(ZBX_DB_CONNECT_NORMAL); + + for (;;) { + now = time(NULL); + + result = DBselect("select a.alertid,a.mediatypeid,a.sendto,a.subject,a.message,a.status,mt.mediatypeid" + ",mt.type,mt.description,mt.smtp_server,mt.smtp_helo,mt.smtp_email,mt.exec_path" + ",mt.gsm_modem,mt.username,mt.passwd,a.retries from alerts a,media_type mt" + " where a.status=%d and a.mediatypeid=mt.mediatypeid and a.alerttype=%d" DB_NODE + " order by a.clock", + ALERT_STATUS_NOT_SENT, + ALERT_TYPE_MESSAGE, + DBnode_local("mt.mediatypeid")); + + while (NULL != (row = DBfetch(result))) { res = FAIL; - ZBX_STR2UINT64(alert.alertid,row[0]); - alert.mediatypeid=atoi(row[1]); - alert.sendto=row[2]; - alert.subject=row[3]; - alert.message=row[4]; - alert.status=atoi(row[5]); - - ZBX_STR2UINT64(mediatype.mediatypeid,row[6]); - mediatype.type=atoi(row[7]); - mediatype.description=row[8]; - mediatype.smtp_server=row[9]; - mediatype.smtp_helo=row[10]; - mediatype.smtp_email=row[11]; - mediatype.exec_path=row[12]; + ZBX_STR2UINT64(alert.alertid, row[0]); + alert.mediatypeid = atoi(row[1]); + alert.sendto = row[2]; + alert.subject = row[3]; + alert.message = row[4]; + alert.status = atoi(row[5]); - mediatype.gsm_modem=row[13]; - mediatype.username=row[14]; - mediatype.passwd=row[15]; + ZBX_STR2UINT64(mediatype.mediatypeid, row[6]); + mediatype.type = atoi(row[7]); + mediatype.description = row[8]; + mediatype.smtp_server = row[9]; + mediatype.smtp_helo = row[10]; + mediatype.smtp_email = row[11]; + mediatype.exec_path = row[12]; - alert.retries=atoi(row[16]); + mediatype.gsm_modem = row[13]; + mediatype.username = row[14]; + mediatype.passwd = row[15]; - phan.sa_handler = child_signal_handler; - sigemptyset(&phan.sa_mask); - phan.sa_flags = 0; - sigaction(SIGALRM, &phan, NULL); + alert.retries = atoi(row[16]); /* Hardcoded value */ /* SMS uses its own timeouts */ alarm(40); *error = '\0'; - res = execute_action(&alert,&mediatype,error,sizeof(error)); + res = execute_action(&alert, &mediatype, error, sizeof(error)); alarm(0); - if(res==SUCCEED) + if (res == SUCCEED) { zabbix_log( LOG_LEVEL_DEBUG, "Alert ID [" ZBX_FS_UI64 "] was sent successfully", alert.alertid); @@ -250,7 +249,7 @@ int main_alerter_loop() alert.alertid); zabbix_syslog("Error sending alert ID [" ZBX_FS_UI64 "]", alert.alertid); - DBescape_string(error,error_esc,MAX_STRING_LEN); + error_esc = DBdyn_escape_string(error); alert.retries++; if(alert.retries < ALERT_MAX_RETRIES) @@ -268,16 +267,19 @@ int main_alerter_loop() error_esc, alert.alertid); } + + zbx_free(error_esc); } } DBfree_result(result); - DBclose(); - zbx_setproctitle("sender [sleeping for %d seconds]", - CONFIG_SENDER_FREQUENCY); + CONFIG_SENDER_FREQUENCY); sleep(CONFIG_SENDER_FREQUENCY); } + + /* Never reached */ + DBclose(); } diff --git a/src/zabbix_server/escalator/Makefile.am b/src/zabbix_server/escalator/Makefile.am new file mode 100644 index 00000000..27204d6b --- /dev/null +++ b/src/zabbix_server/escalator/Makefile.am @@ -0,0 +1,5 @@ +## Process this file with automake to produce Makefile.in + +noinst_LIBRARIES = libzbxescalator.a + +libzbxescalator_a_SOURCES = escalator.c escalator.h diff --git a/src/zabbix_server/escalator/escalator.c b/src/zabbix_server/escalator/escalator.c new file mode 100644 index 00000000..81b730d9 --- /dev/null +++ b/src/zabbix_server/escalator/escalator.c @@ -0,0 +1,679 @@ +/* +** ZABBIX +** Copyright (C) 2000-2005 SIA Zabbix +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +**/ + +#include "common.h" +#include "db.h" +#include "log.h" +#include "zlog.h" +#include "daemon.h" +#include "zbxserver.h" + +#include "escalator.h" +#include "../operations.h" +#include "../events.h" +#include "../actions.h" + +#define CONFIG_ESCALATOR_FREQUENCY 5 + +#define ZBX_USER_MSG struct zxb_user_msg_t +ZBX_USER_MSG +{ + zbx_uint64_t userid; + char *subject; + char *message; + void *next; +}; + +static void add_user_msg(DB_OPERATION *operation, ZBX_USER_MSG **user_msg, char *subject, char *message) +{ + DB_RESULT result; + DB_ROW row; + ZBX_USER_MSG *p; + zbx_uint64_t userid; + + switch (operation->object) { + case OPERATION_OBJECT_USER: + case OPERATION_OBJECT_GROUP: + /* user group disabled ? */ + result = DBselect("select ug.userid from users_groups ug,usrgrp g" + " WHERE ug.%s=" ZBX_FS_UI64 " AND g.usrgrpid=ug.usrgrpid AND g.users_status=%d", + operation->object == OPERATION_OBJECT_USER ? "userid" : "usrgrpid", + operation->objectid, + GROUP_STATUS_ACTIVE); + + while (NULL != (row = DBfetch(result))) { + userid = zbx_atoui64(row[0]); + + p = *user_msg; + while (NULL != p) { + if (p->userid == userid && 0 == strcmp(p->subject, subject) + && 0 == strcmp(p->message, message)) + break; + + p = p->next; + } + + if (NULL == p) { + p = zbx_malloc(p, sizeof(ZBX_USER_MSG)); + + p->userid = userid; + p->subject = strdup(subject); + p->message = strdup(message); + p->next = *user_msg; + + *user_msg = p; + + } + } + + DBfree_result(result); + break; + default: + zabbix_log(LOG_LEVEL_WARNING, "Unknown object type [%d] for operationid [" ZBX_FS_UI64 "]", + operation->object, + operation->operationid); + zabbix_syslog("Unknown object type [%d] for operationid [" ZBX_FS_UI64 "]", + operation->object, + operation->operationid); + break; + } +} + +static void add_command_alert(DB_ESCALATION *escalation, DB_EVENT *event, DB_ACTION *action, char *command) +{ + zbx_uint64_t alertid; + int now; + char *command_esc = NULL; + + zabbix_log(LOG_LEVEL_DEBUG, "In add_command_alert()"); +/* zabbix_log(LOG_LEVEL_DEBUG,"----- COMMAND\n\tcommand: %s", command);*/ + + alertid = DBget_maxid("alerts", "alertid"); + now = time(NULL); + command_esc = DBdyn_escape_string(command); + + DBexecute("insert into alerts (alertid,actionid,eventid,clock,message,status,alerttype,esc_step)" + " values (" ZBX_FS_UI64 "," ZBX_FS_UI64 "," ZBX_FS_UI64 ",%d,'%s',%d,%d,%d)", + alertid, + action->actionid, + event->eventid, + now, + command_esc, + ALERT_STATUS_NOT_SENT, + ALERT_TYPE_COMMAND, + escalation->esc_step); + + op_run_commands(command); + + zbx_free(command_esc); +} + +static void add_message_alert(DB_ESCALATION *escalation, DB_EVENT *event, DB_ACTION *action, zbx_uint64_t userid, char *subject, char *message) +{ + DB_RESULT result; + DB_ROW row; + zbx_uint64_t alertid, mediatypeid; + int now, severity, medias = 0; + char *sendto_esc = NULL; + char *subject_esc = NULL; + char *message_esc = NULL; + char *error_esc = NULL; + + zabbix_log(LOG_LEVEL_DEBUG, "In add_message_alert()"); +/* zabbix_log(LOG_LEVEL_DEBUG,"MESSAGE\n\tuserid : " ZBX_FS_UI64 "\n\tsubject: %s\n\tmessage: %s", userid, subject, message);*/ + + now = time(NULL); + subject_esc = DBdyn_escape_string(subject); + message_esc = DBdyn_escape_string(message); + + result = DBselect("select mediatypeid,sendto,severity,period from media" + " where active=%d and userid=" ZBX_FS_UI64, + MEDIA_STATUS_ACTIVE, + userid); + + while (NULL != (row = DBfetch(result))) { + medias = 1; + + mediatypeid = zbx_atoui64(row[0]); + severity = atoi(row[2]); + + zabbix_log( LOG_LEVEL_DEBUG, "Trigger severity [%d] Media severity [%d] Period [%s]", + event->trigger_priority, + severity, + row[3]); + + if (((1 << event->trigger_priority) & severity) == 0) { + zabbix_log( LOG_LEVEL_DEBUG, "Won't send message (severity)"); + continue; + } + + if (check_time_period(row[3], (time_t)NULL) == 0) { + zabbix_log( LOG_LEVEL_DEBUG, "Won't send message (period)"); + continue; + } + + alertid = DBget_maxid("alerts", "alertid"); + sendto_esc = DBdyn_escape_string(row[1]); + + DBexecute("insert into alerts (alertid,actionid,eventid,userid,clock" + ",mediatypeid,sendto,subject,message,status,alerttype,esc_step)" + " values (" ZBX_FS_UI64 "," ZBX_FS_UI64 "," ZBX_FS_UI64 "," ZBX_FS_UI64 ",%d" + "," ZBX_FS_UI64 ",'%s','%s','%s',%d,%d,%d)", + alertid, + action->actionid, + event->eventid, + userid, + now, + mediatypeid, + sendto_esc, + subject_esc, + message_esc, + ALERT_STATUS_NOT_SENT, + ALERT_TYPE_MESSAGE, + escalation->esc_step); + + zbx_free(sendto_esc); + } + + DBfree_result(result); + + if (0 == medias) { + alertid = DBget_maxid("alerts", "alertid"); + error_esc = DBdyn_escape_string("No media defined"); + + DBexecute("insert into alerts (alertid,actionid,eventid,userid,clock" + ",subject,message,status,alerttype,error,esc_step)" + " values (" ZBX_FS_UI64 "," ZBX_FS_UI64 "," ZBX_FS_UI64 "," ZBX_FS_UI64 ",%d" + ",'%s','%s',%d,%d,'%s',%d)", + alertid, + action->actionid, + event->eventid, + userid, + now, + subject_esc, + message_esc, + ALERT_STATUS_FAILED, + ALERT_TYPE_MESSAGE, + error_esc, + escalation->esc_step); + + zbx_free(error_esc); + } + + zbx_free(subject_esc); + zbx_free(message_esc); +} + +/****************************************************************************** + * * + * Function: check_operation_conditions * + * * + * Purpose: * + * * + * Parameters: event - event to check * + * actionid - action ID for matching * + * * + * Return value: SUCCEED - matches, FAIL - otherwise * + * * + * Author: Alexei Vladishev * + * * + * Comments: * + * * + ******************************************************************************/ +static int check_operation_conditions(DB_EVENT *event, DB_OPERATION *operation) +{ + DB_RESULT result; + DB_ROW row; + DB_CONDITION condition; + + /* SUCCEED required for ACTION_EVAL_TYPE_AND_OR */ + int ret = SUCCEED; + int old_type = -1; + int cond; + int num = 0; + int exit = 0; + + zabbix_log(LOG_LEVEL_DEBUG, "In check_opeartion_conditions (operationid:" ZBX_FS_UI64 ")", + operation->operationid); + + result = DBselect("select conditiontype,operator,value from opconditions where operationid=" ZBX_FS_UI64 " order by conditiontype", + operation->operationid); + + while (NULL != (row = DBfetch(result)) && (0 == exit)) { + num++; + + memset(&condition, 0, sizeof(condition)); + condition.conditiontype = atoi(row[0]); + condition.operator = atoi(row[1]); + condition.value = row[2]; + + switch (operation->evaltype) { + case ACTION_EVAL_TYPE_AND_OR: + if (old_type == condition.conditiontype) { /* OR conditions */ + if (SUCCEED == check_action_condition(event, &condition)) + ret = SUCCEED; + } else { /* AND conditions */ + /* Break if PREVIOUS AND condition is FALSE */ + if (ret == FAIL) + exit = 1; + else if (FAIL == check_action_condition(event, &condition)) + ret = FAIL; + } + + old_type = condition.conditiontype; + break; + case ACTION_EVAL_TYPE_AND: + cond = check_action_condition(event, &condition); + /* Break if any of AND conditions is FALSE */ + if(cond == FAIL) { + ret = FAIL; + exit = 1; + } else + ret = SUCCEED; + break; + case ACTION_EVAL_TYPE_OR: + cond = check_action_condition(event, &condition); + /* Break if any of OR conditions is TRUE */ + if (cond == SUCCEED) { + ret = SUCCEED; + exit = 1; + } else + ret = FAIL; + break; + default: + ret = FAIL; + exit = 1; + break; + + } + + } + DBfree_result(result); + + zabbix_log(LOG_LEVEL_DEBUG, "End check_opeartion_conditions():%s", + FAIL == ret ? "FALSE" : "TRUE"); + + return ret; +} + +static void execute_operations(DB_ESCALATION *escalation, DB_EVENT *event, DB_ACTION *action) +{ + DB_RESULT result; + DB_ROW row; + DB_OPERATION operation; + int esc_period = 0, operations = 0; + ZBX_USER_MSG *user_msg = NULL, *p; + char *shortdata, *longdata; + + if (0 == action->esc_period) + result = DBselect("select operationid,operationtype,object,objectid,default_msg,shortdata,longdata" + ",esc_period,evaltype from operations where actionid=" ZBX_FS_UI64, + action->actionid); + else { + escalation->esc_step++; + + result = DBselect("select operationid,operationtype,object,objectid,default_msg,shortdata,longdata" + ",esc_period,evaltype from operations where actionid=" ZBX_FS_UI64 + " and esc_step_from<=%d and (esc_step_to=0 or esc_step_to>=%d)", + action->actionid, + escalation->esc_step, + escalation->esc_step); + } + + while (NULL != (row = DBfetch(result))) { + memset(&operation, 0, sizeof(operation)); + operation.operationid = zbx_atoui64(row[0]); + operation.actionid = action->actionid; + operation.operationtype = atoi(row[1]); + operation.object = atoi(row[2]); + operation.objectid = zbx_atoui64(row[3]); + operation.default_msg = atoi(row[4]); + operation.shortdata = strdup(row[5]); + operation.longdata = strdup(row[6]); + operation.esc_period = atoi(row[7]); + operation.evaltype = atoi(row[8]); + + if (SUCCEED == check_operation_conditions(event, &operation)) { + zabbix_log(LOG_LEVEL_DEBUG, "Conditions match our event. Execute operation."); + + substitute_macros(event, action, &operation.shortdata); + substitute_macros(event, action, &operation.longdata); + + if (0 == esc_period || esc_period > operation.esc_period) + esc_period = operation.esc_period; + + switch (operation.operationtype) { + case OPERATION_TYPE_MESSAGE: + if (0 == operation.default_msg) { + shortdata = operation.shortdata; + longdata = operation.longdata; + } else { + shortdata = action->shortdata; + longdata = action->longdata; + } + + add_user_msg(&operation, &user_msg, shortdata, longdata); + break; + case OPERATION_TYPE_COMMAND: + add_command_alert(escalation, event, action, operation.longdata); + break; + default: + break; + } + } else + zabbix_log(LOG_LEVEL_DEBUG, "Conditions do not match our event. Do not execute operation."); + + zbx_free(operation.shortdata); + zbx_free(operation.longdata); + + operations = 1; + } + + DBfree_result(result); + + while (NULL != user_msg) { + p = user_msg; + user_msg = user_msg->next; + + add_message_alert(escalation, event, action, p->userid, p->subject, p->message); + + zbx_free(p->subject); + zbx_free(p->message); + zbx_free(p); + } + + if (0 == action->esc_period) + escalation->status = ESCALATION_STATUS_COMPLETED; + else { + if (0 == operations) { + result = DBselect("select operationid from operations where actionid=" ZBX_FS_UI64 " and esc_step_from>%d", + action->actionid, + escalation->esc_step); + + if (NULL != (row = DBfetch(result)) && SUCCEED != DBis_null(row[0])) + operations = 1; + + DBfree_result(result); + } + + if (1 == operations) { + esc_period = (0 != esc_period) ? esc_period : action->esc_period; + escalation->nextcheck = time(NULL) + esc_period; + } else + escalation->status = ESCALATION_STATUS_COMPLETED; + } +} + +static void process_recovery_msg(DB_ESCALATION *escalation, DB_EVENT *event, DB_ACTION *action) +{ + DB_RESULT result; + DB_ROW row; + zbx_uint64_t userid; + + if (1 == action->recovery_msg) { + result = DBselect("select distinct userid from alerts where actionid=" ZBX_FS_UI64 " and eventid=" ZBX_FS_UI64, + action->actionid, + event->eventid); + + while (NULL != (row = DBfetch(result))) { + userid = zbx_atoui64(row[0]); + + add_message_alert(escalation, event, action, userid, action->shortdata, action->longdata); + } + + DBfree_result(result); + } else { + zabbix_log(LOG_LEVEL_DEBUG, "Escalation stopped: recovery message not defined", + escalation->actionid); + DBremove_escalation(escalation->escalationid); + } + + escalation->status = ESCALATION_STATUS_COMPLETED; +} + +static void execute_escalation(DB_ESCALATION *escalation, DB_EVENT *event) +{ + DB_RESULT result; + DB_ROW row; + DB_ACTION action; + + switch (escalation->status) { + case ESCALATION_STATUS_ACTIVE: + result = DBselect("select actionid,eventsource,esc_period,shortdata,longdata" + " from actions where actionid=" ZBX_FS_UI64, + escalation->actionid); + break; + case ESCALATION_STATUS_RECOVERY: + result = DBselect("select actionid,eventsource,esc_period,r_shortdata,r_longdata,recovery_msg" + " from actions where actionid=" ZBX_FS_UI64, + escalation->actionid); + break; + default: + /* Never reached */ + return; + } + + if (NULL != (row = DBfetch(result))) { + memset(&action, 0, sizeof(action)); + action.actionid = zbx_atoui64(row[0]); + action.eventsource = atoi(row[1]); + action.esc_period = atoi(row[2]); + action.shortdata = strdup(row[3]); + action.longdata = strdup(row[4]); + action.recovery_msg = atoi(row[5]); + + substitute_macros(event, &action, &action.shortdata); + substitute_macros(event, &action, &action.longdata); + + switch (escalation->status) { + case ESCALATION_STATUS_ACTIVE: + execute_operations(escalation, event, &action); + break; + case ESCALATION_STATUS_RECOVERY: + process_recovery_msg(escalation, event, &action); + break; + default: + break; + } + + zbx_free(action.shortdata); + zbx_free(action.longdata); + } else { + zabbix_log(LOG_LEVEL_DEBUG, "Escalation canceled: action [" ZBX_FS_UI64 "] not found", + escalation->actionid); + DBremove_escalation(escalation->escalationid); + } + + DBfree_result(result); +} + +static void process_escalations(int now) +{ + DB_RESULT result; + DB_ROW row; + DB_ESCALATION escalation; + DB_EVENT event; + + zabbix_log(LOG_LEVEL_DEBUG, "In process_escalations()"); + + result = DBselect("select e.escalationid,e.actionid,e.esc_step,e.status,ev.eventid" + ",ev.source,ev.object,ev.objectid,ev.clock,ev.value,ev.acknowledged" + " from escalations e,events ev where e.eventid=ev.eventid" + " and e.status in (%d,%d) and e.nextcheck<=%d" DB_NODE, + ESCALATION_STATUS_ACTIVE, + ESCALATION_STATUS_RECOVERY, + now, + DBnode_local("escalationid")); + + while (NULL != (row = DBfetch(result))) { + memset(&escalation, 0, sizeof(escalation)); + escalation.escalationid = zbx_atoui64(row[0]); + escalation.actionid = zbx_atoui64(row[1]); + escalation.esc_step = atoi(row[2]); + escalation.status = atoi(row[3]); + escalation.nextcheck = 0; + + memset(&event, 0, sizeof(event)); + event.eventid = zbx_atoui64(row[4]); + event.source = atoi(row[5]); + event.object = atoi(row[6]); + event.objectid = zbx_atoui64(row[7]); + event.clock = atoi(row[8]); + event.value = atoi(row[9]); + event.acknowledged = atoi(row[10]); + + add_trigger_info(&event); + + DBbegin(); + + execute_escalation(&escalation, &event); + + if (escalation.status == ESCALATION_STATUS_COMPLETED) + DBremove_escalation(escalation.escalationid); + else + DBexecute("update escalations set esc_step=%d,nextcheck=%d where escalationid=" ZBX_FS_UI64, + escalation.esc_step, + escalation.nextcheck, + escalation.escalationid); + + DBcommit(); + } + + DBfree_result(result); +} + +/****************************************************************************** + * * + * Function: get_minnextcheck * + * * + * Purpose: calculate when we have to process earliest escalations * + * * + * Parameters: now - current timestamp * + * * + * Return value: timestamp of earliest check or -1 if not found * + * * + * Author: Aleksander Vladishev * + * * + * Comments: * + * * + ******************************************************************************/ +static int get_minnextcheck() +{ + DB_RESULT result; + DB_ROW row; + int res; + + zabbix_log(LOG_LEVEL_DEBUG, "In get_minnextcheck()"); + + result = DBselect("select count(*),min(nextcheck) from escalations where status in (%d,%d)" DB_NODE, + ESCALATION_STATUS_ACTIVE, + ESCALATION_STATUS_RECOVERY, + DBnode_local("escalationid")); + + if (NULL == (row = DBfetch(result)) || DBis_null(row[0]) == SUCCEED || DBis_null(row[1]) == SUCCEED) + { + zabbix_log(LOG_LEVEL_DEBUG, "No items to update for minnextcheck."); + res = FAIL; + } + else + { + if (atoi(row[0]) == 0) + { + res = FAIL; + } + else + { + res = atoi(row[1]); + } + } + DBfree_result(result); + + return res; +} + +/****************************************************************************** + * * + * Function: main_escalator_loop * + * * + * Purpose: periodically check table escalations and generate alerts * + * * + * Parameters: * + * * + * Return value: * + * * + * Author: Aleksander Vladishev * + * * + * Comments: never returns * + * * + ******************************************************************************/ +int main_escalator_loop() +{ + int now, nextcheck, sleeptime; + double sec; + struct sigaction phan; + + zabbix_log(LOG_LEVEL_DEBUG, "In main_escalator_loop()"); + + phan.sa_handler = child_signal_handler; + sigemptyset(&phan.sa_mask); + phan.sa_flags = 0; + sigaction(SIGALRM, &phan, NULL); + + zbx_setproctitle("escalator [connecting to the database]"); + + DBconnect(ZBX_DB_CONNECT_NORMAL); + + for (;;) { + now = time(NULL); + sec = zbx_time(); + + zbx_setproctitle("escalator [processing escalations]"); + + process_escalations(now); + + sec = zbx_time() - sec; + + nextcheck = get_minnextcheck(); + + if (FAIL == nextcheck) + sleeptime = CONFIG_ESCALATOR_FREQUENCY; + else { + sleeptime = nextcheck - time(NULL); + if (sleeptime < 0) + sleeptime = 0; + else if (sleeptime > CONFIG_ESCALATOR_FREQUENCY) + sleeptime = CONFIG_ESCALATOR_FREQUENCY; + } + + zabbix_log(LOG_LEVEL_DEBUG, "Escalator spent " ZBX_FS_DBL " seconds while processing escalation items." + " Nextcheck after %d sec.", + sec, + sleeptime); + + if (sleeptime > 0) { + zbx_setproctitle("escalator [sleeping for %d seconds]", + sleeptime); + + sleep(sleeptime); + } + } + + /* Never reached */ + DBclose(); +} diff --git a/src/zabbix_server/escalator/escalator.h b/src/zabbix_server/escalator/escalator.h new file mode 100644 index 00000000..aeb70d4c --- /dev/null +++ b/src/zabbix_server/escalator/escalator.h @@ -0,0 +1,27 @@ +/* +** ZABBIX +** Copyright (C) 2000-2005 SIA Zabbix +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +**/ + +#ifndef ZABBIX_ESCALATOR_H +#define ZABBIX_ESCALATOR_H + +#include "db.h" + +int main_escalator_loop(); + +#endif diff --git a/src/zabbix_server/events.c b/src/zabbix_server/events.c index c29bed27..2d0dfa5e 100644 --- a/src/zabbix_server/events.c +++ b/src/zabbix_server/events.c @@ -62,7 +62,7 @@ * Comments: use 'free_trigger_info' function to clear allocated memory * * * ******************************************************************************/ -static void add_trigger_info(DB_EVENT *event) +void add_trigger_info(DB_EVENT *event) { DB_RESULT result; DB_ROW row; @@ -189,10 +189,12 @@ int process_event(DB_EVENT *event) event->eventid, ALERT_STATUS_NOT_SENT); }*/ +/* zabbix_set_log_level(LOG_LEVEL_DEBUG);*/ if(event->skip_actions == 0) { process_actions(event); } +/* zabbix_set_log_level(LOG_LEVEL_CRIT);*/ if(TRIGGER_VALUE_TRUE == event->value) { diff --git a/src/zabbix_server/events.h b/src/zabbix_server/events.h index b56d9f77..80e15946 100644 --- a/src/zabbix_server/events.h +++ b/src/zabbix_server/events.h @@ -24,6 +24,7 @@ #include "common.h" #include "db.h" +void add_trigger_info(DB_EVENT *event); int process_event(DB_EVENT *event); #endif diff --git a/src/zabbix_server/operations.c b/src/zabbix_server/operations.c index 173a337b..f16c49b5 100644 --- a/src/zabbix_server/operations.c +++ b/src/zabbix_server/operations.c @@ -58,7 +58,7 @@ * Comments: Cannot use action->userid as it may also be groupid * * * ******************************************************************************/ -static void send_to_user_medias(DB_EVENT *event,DB_OPERATION *operation, zbx_uint64_t userid) +/*static void send_to_user_medias(DB_EVENT *event,DB_OPERATION *operation, zbx_uint64_t userid) { DB_MEDIA media; DB_RESULT result; @@ -101,7 +101,7 @@ static void send_to_user_medias(DB_EVENT *event,DB_OPERATION *operation, zbx_uin zabbix_log(LOG_LEVEL_DEBUG, "End send_to_user_medias()"); } - +*/ /****************************************************************************** * * * Function: check_user_active * @@ -117,7 +117,7 @@ static void send_to_user_medias(DB_EVENT *event,DB_OPERATION *operation, zbx_uin * Comments: * * * ******************************************************************************/ -int check_user_active(zbx_uint64_t userid){ +/*int check_user_active(zbx_uint64_t userid){ DB_RESULT result; DB_ROW row; int rtrn = SUCCEED; @@ -132,7 +132,7 @@ int check_user_active(zbx_uint64_t userid){ return rtrn; } - +*/ /****************************************************************************** * * * Function: op_notify_user * @@ -149,7 +149,7 @@ return rtrn; * Comments: action->recipient specifies user or group * * * ******************************************************************************/ -void op_notify_user(DB_EVENT *event, DB_ACTION *action, DB_OPERATION *operation) +/*void op_notify_user(DB_EVENT *event, DB_ACTION *action, DB_OPERATION *operation) { DB_RESULT result; DB_ROW row; @@ -186,7 +186,7 @@ void op_notify_user(DB_EVENT *event, DB_ACTION *action, DB_OPERATION *operation) } zabbix_log(LOG_LEVEL_DEBUG, "End send_to_user()"); } - +*/ /****************************************************************************** * * @@ -354,44 +354,33 @@ static int get_next_command(char** command_list, char** alias, int* is_group, ch * Comments: commands devided with newline * * * ******************************************************************************/ -void op_run_commands(DB_EVENT *event, DB_OPERATION *operation) +void op_run_commands(char *cmd_list) { - DB_RESULT result; + DB_RESULT result; DB_ROW row; + char *alias, *command; + int is_group; - char *cmd_list = NULL; - char *alias = NULL; - char *command = NULL; - int is_group = 0; + assert(cmd_list); - assert(event); - assert(operation); + zabbix_log(LOG_LEVEL_DEBUG, "In run_commands()"); - zabbix_log( LOG_LEVEL_DEBUG, "In run_commands(operationid:" ZBX_FS_UI64 ")", - operation->operationid); + while (1 != get_next_command(&cmd_list, &alias, &is_group, &command)) { + if (!alias || *alias == '\0' || !command || *command == '\0') + continue; - cmd_list = operation->longdata; - while(get_next_command(&cmd_list,&alias,&is_group,&command)!=1) - { - if(!alias || !command) continue; - if(alias == '\0' || command == '\0') continue; - if(is_group) - { - result = DBselect("select distinct h.host from hosts_groups hg,hosts h, groups g where hg.hostid=h.hostid and hg.groupid=g.groupid and g.name='%s'" DB_NODE, - alias, - DBnode_local("h.hostid")); - while((row=DBfetch(result))) - { + if (is_group) { + result = DBselect("select distinct h.host from hosts_groups hg,hosts h,groups g" + " where hg.hostid=h.hostid and hg.groupid=g.groupid and g.name='%s'" DB_NODE, + alias, + DBnode_local("h.hostid")); + + while (NULL != (row = DBfetch(result))) run_remote_command(row[0], command); - } - + DBfree_result(result); - } - else - { + } else run_remote_command(alias, command); - } -/* DBadd_alert(action->actionid,trigger->triggerid, userid, media.mediatypeid,media.sendto,action->subject,action->scripts); */ /* TODO !!! Add alert for remote commands !!! */ } zabbix_log( LOG_LEVEL_DEBUG, "End run_commands()"); } diff --git a/src/zabbix_server/operations.h b/src/zabbix_server/operations.h index c4c14b3d..24b23f41 100644 --- a/src/zabbix_server/operations.h +++ b/src/zabbix_server/operations.h @@ -30,8 +30,8 @@ void op_group_add(DB_EVENT *event, DB_ACTION *action, DB_OPERATION *operation); void op_group_del(DB_EVENT *event, DB_ACTION *action, DB_OPERATION *operation); void op_host_add(DB_EVENT *event); void op_host_del(DB_EVENT *event); -void op_run_commands(DB_EVENT *event, DB_OPERATION *operation); -int check_user_active(zbx_uint64_t userid); -void op_notify_user(DB_EVENT *event, DB_ACTION *action, DB_OPERATION *operation); +void op_run_commands(char *cmd_list); +/*int check_user_active(zbx_uint64_t userid); +void op_notify_user(DB_EVENT *event, DB_ACTION *action, DB_OPERATION *operation);*/ #endif diff --git a/src/zabbix_server/server.c b/src/zabbix_server/server.c index 9059f828..272bdf8d 100644 --- a/src/zabbix_server/server.c +++ b/src/zabbix_server/server.c @@ -47,6 +47,7 @@ #include "nodewatcher/nodewatcher.h" #include "watchdog/watchdog.h" #include "utils/nodechange.h" +#include "escalator/escalator.h" #define LISTENQ 1024 @@ -126,6 +127,7 @@ int CONFIG_HTTPPOLLER_FORKS = 5; int CONFIG_TIMER_FORKS = 1; int CONFIG_TRAPPERD_FORKS = 5; int CONFIG_UNREACHABLE_POLLER_FORKS = 1; +int CONFIG_ESCALATOR_FORKS = 1; int CONFIG_LISTEN_PORT = 10051; char *CONFIG_LISTEN_IP = NULL; @@ -1073,7 +1075,7 @@ int MAIN_ZABBIX_ENTRY(void) #endif threads = calloc(1+CONFIG_POLLER_FORKS+CONFIG_TRAPPERD_FORKS+CONFIG_PINGER_FORKS+CONFIG_ALERTER_FORKS +CONFIG_HOUSEKEEPER_FORKS+CONFIG_TIMER_FORKS+CONFIG_UNREACHABLE_POLLER_FORKS - +CONFIG_NODEWATCHER_FORKS+CONFIG_HTTPPOLLER_FORKS+CONFIG_DISCOVERER_FORKS, + +CONFIG_NODEWATCHER_FORKS+CONFIG_HTTPPOLLER_FORKS+CONFIG_DISCOVERER_FORKS+CONFIG_ESCALATOR_FORKS, sizeof(pid_t)); if(CONFIG_TRAPPERD_FORKS > 0) @@ -1086,7 +1088,7 @@ int MAIN_ZABBIX_ENTRY(void) } for( i=1; - i<=CONFIG_POLLER_FORKS+CONFIG_TRAPPERD_FORKS+CONFIG_PINGER_FORKS+CONFIG_ALERTER_FORKS+CONFIG_HOUSEKEEPER_FORKS+CONFIG_TIMER_FORKS+CONFIG_UNREACHABLE_POLLER_FORKS+CONFIG_NODEWATCHER_FORKS+CONFIG_HTTPPOLLER_FORKS+CONFIG_DISCOVERER_FORKS+CONFIG_DBSYNCER_FORKS; + i<=CONFIG_POLLER_FORKS+CONFIG_TRAPPERD_FORKS+CONFIG_PINGER_FORKS+CONFIG_ALERTER_FORKS+CONFIG_HOUSEKEEPER_FORKS+CONFIG_TIMER_FORKS+CONFIG_UNREACHABLE_POLLER_FORKS+CONFIG_NODEWATCHER_FORKS+CONFIG_HTTPPOLLER_FORKS+CONFIG_DISCOVERER_FORKS+CONFIG_DBSYNCER_FORKS+CONFIG_ESCALATOR_FORKS; i++) { if((pid = zbx_fork()) == 0) @@ -1223,6 +1225,16 @@ int MAIN_ZABBIX_ENTRY(void) main_dbsyncer_loop(); } + else if (server_num <= CONFIG_POLLER_FORKS + CONFIG_TRAPPERD_FORKS + CONFIG_PINGER_FORKS + CONFIG_ALERTER_FORKS + + CONFIG_HOUSEKEEPER_FORKS + CONFIG_TIMER_FORKS + CONFIG_UNREACHABLE_POLLER_FORKS + + CONFIG_NODEWATCHER_FORKS + CONFIG_HTTPPOLLER_FORKS + CONFIG_DISCOVERER_FORKS + CONFIG_DBSYNCER_FORKS + + CONFIG_ESCALATOR_FORKS) + { + zabbix_log(LOG_LEVEL_WARNING, "server #%d started [Escalator]", + server_num); + + main_escalator_loop(); + } return SUCCEED; } @@ -1235,7 +1247,7 @@ void zbx_on_exit() if(threads != NULL) { - for(i = 1; i <= CONFIG_POLLER_FORKS+CONFIG_TRAPPERD_FORKS+CONFIG_PINGER_FORKS+CONFIG_ALERTER_FORKS+CONFIG_HOUSEKEEPER_FORKS+CONFIG_TIMER_FORKS+CONFIG_UNREACHABLE_POLLER_FORKS+CONFIG_NODEWATCHER_FORKS+CONFIG_HTTPPOLLER_FORKS+CONFIG_DISCOVERER_FORKS+CONFIG_DBSYNCER_FORKS; i++) + for(i = 1; i <= CONFIG_POLLER_FORKS+CONFIG_TRAPPERD_FORKS+CONFIG_PINGER_FORKS+CONFIG_ALERTER_FORKS+CONFIG_HOUSEKEEPER_FORKS+CONFIG_TIMER_FORKS+CONFIG_UNREACHABLE_POLLER_FORKS+CONFIG_NODEWATCHER_FORKS+CONFIG_HTTPPOLLER_FORKS+CONFIG_DISCOVERER_FORKS+CONFIG_DBSYNCER_FORKS+CONFIG_ESCALATOR_FORKS; i++) { if(threads[i]) { kill(threads[i],SIGTERM); |
