static void add_command_alert(DC_HOST *host, zbx_uint64_t eventid, zbx_uint64_t actionid, int esc_step, const char *command, zbx_alert_status_t status, const char *error) { const char *__function_name = "add_command_alert"; zbx_uint64_t alertid; int now; char *tmp = NULL, *command_esc, *error_esc; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); alertid = DBget_maxid("alerts"); now = (int)time(NULL); tmp = zbx_dsprintf(tmp, "%s:%s", host->host, NULL == command ? "" : command); command_esc = DBdyn_escape_string_len(tmp, ALERT_MESSAGE_LEN); error_esc = DBdyn_escape_string_len(error, ALERT_ERROR_LEN); zbx_free(tmp); DBexecute("insert into alerts" " (alertid,actionid,eventid,clock,message,status,error,alerttype,esc_step)" " values " "(" ZBX_FS_UI64 "," ZBX_FS_UI64 "," ZBX_FS_UI64 ",%d,'%s',%d,'%s',%d,%d)", alertid, actionid, eventid, now, command_esc, (int)status, error_esc, ALERT_TYPE_COMMAND, esc_step); zbx_free(error_esc); zbx_free(command_esc); zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name); }
/****************************************************************************** * * * Function: proxy_update_host * * * * Purpose: process new service status * * * * Parameters: service - service info * * * * Author: Alexander Vladishev * * * ******************************************************************************/ static void proxy_update_host(DB_DRULE *drule, const char *ip, const char *dns, int status, int now) { char *ip_esc, *dns_esc; ip_esc = DBdyn_escape_string_len(ip, INTERFACE_IP_LEN); dns_esc = DBdyn_escape_string_len(dns, INTERFACE_DNS_LEN); DBexecute("insert into proxy_dhistory (clock,druleid,type,ip,dns,status)" " values (%d," ZBX_FS_UI64 ",-1,'%s','%s',%d)", now, drule->druleid, ip_esc, dns_esc, status); zbx_free(dns_esc); zbx_free(ip_esc); }
static int DBpatch_2010176(void) { DB_RESULT result; DB_ROW row; char *name, *name_esc; int ret = SUCCEED; result = DBselect("select scriptid,name from scripts"); while (SUCCEED == ret && NULL != (row = DBfetch(result))) { name = zbx_dyn_escape_string(row[1], "/\\"); if (0 != strcmp(name, row[1])) { name_esc = DBdyn_escape_string_len(name, 255); if (ZBX_DB_OK > DBexecute("update scripts set name='%s' where scriptid=%s", name_esc, row[0])) ret = FAIL; zbx_free(name_esc); } zbx_free(name); } DBfree_result(result); return ret; }
/****************************************************************************** * * * Function: convert_triggers_expression * * * * Purpose: convert trigger expressions to new node ID * * * * Parameters: old_id - old id, new_id - new node id * * * * Author: Alexander Vladishev * * * * Comments: * * * ******************************************************************************/ static void convert_triggers_expression(int old_id, int new_id) { zbx_uint64_t prefix; const ZBX_TABLE *r_table; DB_RESULT result; DB_ROW row; char new_expression[MAX_STRING_LEN], *new_expression_esc; r_table = DBget_table("functions"); assert(NULL != r_table); prefix = (zbx_uint64_t)__UINT64_C(100000000000000) * (zbx_uint64_t)new_id; if (0 != (r_table->flags & ZBX_SYNC)) prefix += (zbx_uint64_t)__UINT64_C(100000000000) * (zbx_uint64_t)new_id; result = DBselect("select expression,triggerid from triggers"); while (NULL != (row = DBfetch(result))) { memset(new_expression, 0, sizeof(new_expression)); convert_expression(old_id, new_id, prefix, row[0], new_expression); new_expression_esc = DBdyn_escape_string_len(new_expression, TRIGGER_EXPRESSION_LEN); DBexecute("update triggers set expression='%s' where triggerid=%s", new_expression_esc, row[1]); zbx_free(new_expression_esc); } DBfree_result(result); }
/****************************************************************************** * * * Function: DBlld_get_item * * * * Purpose: finds item in the selected host by an item prototype key and * * discovered data * * * ******************************************************************************/ int DBlld_get_item(zbx_uint64_t hostid, const char *tmpl_key, struct zbx_json_parse *jp_row, zbx_uint64_t *itemid) { const char *__function_name = "DBlld_get_item"; DB_RESULT result; DB_ROW row; char *key = NULL, *key_esc; int res = SUCCEED; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); if (NULL != jp_row) { key = zbx_strdup(key, tmpl_key); substitute_key_macros(&key, NULL, NULL, jp_row, MACRO_TYPE_ITEM_KEY, NULL, 0); key_esc = DBdyn_escape_string_len(key, ITEM_KEY_LEN); } else key_esc = DBdyn_escape_string_len(tmpl_key, ITEM_KEY_LEN); result = DBselect( "select itemid" " from items" " where hostid=" ZBX_FS_UI64 " and key_='%s'", hostid, key_esc); zbx_free(key_esc); zbx_free(key); if (NULL == (row = DBfetch(result))) { zabbix_log(LOG_LEVEL_DEBUG, "%s() cannot find item [%s] on the host", __function_name, key); res = FAIL; } else ZBX_STR2UINT64(*itemid, row[0]); DBfree_result(result); zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(res)); return res; }
/****************************************************************************** * * * Function: proxy_update_service * * * * Purpose: process new service status * * * * Parameters: service - service info * * * * Author: Alexander Vladishev * * * ******************************************************************************/ static void proxy_update_service(DB_DRULE *drule, DB_DCHECK *dcheck, const char *ip, const char *dns, int port, int status, const char *value, int now) { char *ip_esc, *dns_esc, *key_esc, *value_esc; ip_esc = DBdyn_escape_string_len(ip, INTERFACE_IP_LEN); dns_esc = DBdyn_escape_string_len(dns, INTERFACE_DNS_LEN); key_esc = DBdyn_escape_string_len(dcheck->key_, PROXY_DHISTORY_KEY_LEN); value_esc = DBdyn_escape_string_len(value, PROXY_DHISTORY_VALUE_LEN); DBexecute("insert into proxy_dhistory (clock,druleid,dcheckid,type,ip,dns,port,key_,value,status)" " values (%d," ZBX_FS_UI64 "," ZBX_FS_UI64 ",%d,'%s','%s',%d,'%s','%s',%d)", now, drule->druleid, dcheck->dcheckid, dcheck->type, ip_esc, dns_esc, port, key_esc, value_esc, status); zbx_free(value_esc); zbx_free(key_esc); zbx_free(dns_esc); zbx_free(ip_esc); }
/****************************************************************************** * * * Function: discovery_update_dservice_value * * * * Purpose: update discovered service details * * Author: Alexei Vladishev * * * ******************************************************************************/ static void discovery_update_dservice_value(DB_DSERVICE *service) { char *value_esc; value_esc = DBdyn_escape_string_len(service->value, DSERVICE_VALUE_LEN); DBexecute("update dservices set value='%s' where dserviceid=" ZBX_FS_UI64, value_esc, service->dserviceid); zbx_free(value_esc); }
/****************************************************************************** * * * Function: proxy_update_host * * * * Purpose: process new service status * * * * Parameters: service - service info * * * * Return value: * * * * Author: Alexander Vladishev * * * * Comments: * * * ******************************************************************************/ static void proxy_update_host(DB_DRULE *drule, char *ip, int status, int now) { char *ip_esc; ip_esc = DBdyn_escape_string_len(ip, PROXY_DHISTORY_IP_LEN); DBexecute("insert into proxy_dhistory (clock,druleid,type,ip,status)" " values (%d," ZBX_FS_UI64 ",-1,'%s',%d)", now, drule->druleid, ip_esc, status); zbx_free(ip_esc); }
/****************************************************************************** * * * Function: discovery_separate_host * * * * Purpose: separate multiple-IP hosts * * * * Parameters: host ip address * * * * Author: Alexander Vladishev * * * ******************************************************************************/ static void discovery_separate_host(DB_DRULE *drule, DB_DHOST *dhost, const char *ip) { const char *__function_name = "discovery_separate_host"; DB_RESULT result; DB_ROW row; char *ip_esc, *sql = NULL; zbx_uint64_t dhostid; zabbix_log(LOG_LEVEL_DEBUG, "In %s() ip:'%s'", __function_name, ip); ip_esc = DBdyn_escape_string_len(ip, INTERFACE_IP_LEN); sql = zbx_dsprintf(sql, "select dserviceid" " from dservices" " where dhostid=" ZBX_FS_UI64 " and ip" ZBX_SQL_STRCMP, dhost->dhostid, ZBX_SQL_STRVAL_NE(ip_esc)); result = DBselectN(sql, 1); if (NULL != (row = DBfetch(result))) { dhostid = DBget_maxid("dhosts"); DBexecute("insert into dhosts (dhostid,druleid)" " values (" ZBX_FS_UI64 "," ZBX_FS_UI64 ")", dhostid, drule->druleid); DBexecute("update dservices" " set dhostid=" ZBX_FS_UI64 " where dhostid=" ZBX_FS_UI64 " and ip" ZBX_SQL_STRCMP, dhostid, dhost->dhostid, ZBX_SQL_STRVAL_EQ(ip_esc)); dhost->dhostid = dhostid; dhost->status = DOBJECT_STATUS_DOWN; dhost->lastup = 0; dhost->lastdown = 0; } DBfree_result(result); zbx_free(sql); zbx_free(ip_esc); zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name); }
static DB_RESULT discovery_get_dhost_by_ip(zbx_uint64_t druleid, const char *ip) { DB_RESULT result; char *ip_esc; ip_esc = DBdyn_escape_string_len(ip, INTERFACE_IP_LEN); result = DBselect( "select dh.dhostid,dh.status,dh.lastup,dh.lastdown" " from dhosts dh,dservices ds" " where ds.dhostid=dh.dhostid" " and dh.druleid=" ZBX_FS_UI64 " and ds.ip" ZBX_SQL_STRCMP " order by dh.dhostid", druleid, ZBX_SQL_STRVAL_EQ(ip_esc)); zbx_free(ip_esc); return result; }
static DB_RESULT discovery_get_dhost_by_value(zbx_uint64_t dcheckid, const char *value) { DB_RESULT result; char *value_esc; value_esc = DBdyn_escape_string_len(value, DSERVICE_VALUE_LEN); result = DBselect( "select dh.dhostid,dh.status,dh.lastup,dh.lastdown" " from dhosts dh,dservices ds" " where ds.dhostid=dh.dhostid" " and ds.dcheckid=" ZBX_FS_UI64 " and ds.value" ZBX_SQL_STRCMP " order by dh.dhostid", dcheckid, ZBX_SQL_STRVAL_EQ(value_esc)); zbx_free(value_esc); return result; }
static void add_message_alert(DB_ESCALATION *escalation, DB_EVENT *event, DB_ACTION *action, zbx_uint64_t userid, zbx_uint64_t mediatypeid, const char *subject, const char *message) { const char *__function_name = "add_message_alert"; DB_RESULT result; DB_ROW row; zbx_uint64_t alertid; int now, severity, medias = 0; char *subject_dyn, *message_dyn, *sendto_esc, *subject_esc, *message_esc, *error_esc; char error[MAX_STRING_LEN]; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); subject_dyn = zbx_strdup(NULL, subject); message_dyn = zbx_strdup(NULL, message); substitute_simple_macros(event, &userid, NULL, NULL, NULL, NULL, &subject_dyn, MACRO_TYPE_MESSAGE, NULL, 0); substitute_simple_macros(event, &userid, NULL, NULL, NULL, NULL, &message_dyn, MACRO_TYPE_MESSAGE, NULL, 0); now = time(NULL); subject_esc = DBdyn_escape_string_len(subject_dyn, ALERT_SUBJECT_LEN); message_esc = DBdyn_escape_string_len(message_dyn, ALERT_MESSAGE_LEN); zbx_free(subject_dyn); zbx_free(message_dyn); if (0 == mediatypeid) { result = DBselect( "select m.mediatypeid,m.sendto,m.severity,m.period,mt.status" " from media m,media_type mt" " where m.mediatypeid=mt.mediatypeid" " and m.active=%d" " and m.userid=" ZBX_FS_UI64, MEDIA_STATUS_ACTIVE, userid); } else { result = DBselect( "select m.mediatypeid,m.sendto,m.severity,m.period,mt.status" " from media m,media_type mt" " where m.mediatypeid=mt.mediatypeid" " and m.active=%d" " and m.userid=" ZBX_FS_UI64 " and m.mediatypeid=" ZBX_FS_UI64, MEDIA_STATUS_ACTIVE, userid, mediatypeid); } while (NULL != (row = DBfetch(result))) { medias = 1; ZBX_STR2UINT64(mediatypeid, row[0]); severity = atoi(row[2]); zabbix_log(LOG_LEVEL_DEBUG, "Trigger severity [%d] Media severity [%d] Period [%s]", (int)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 (FAIL == check_time_period(row[3], (time_t)NULL)) { zabbix_log(LOG_LEVEL_DEBUG, "Won't send message (period)"); continue; } alertid = DBget_maxid("alerts"); sendto_esc = DBdyn_escape_string_len(row[1], ALERT_SENDTO_LEN); if (MEDIA_TYPE_STATUS_ACTIVE == atoi(row[4])) { 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); } else { error_esc = DBdyn_escape_string("Media type disabled"); DBexecute("insert into alerts (alertid,actionid,eventid,userid,clock" ",mediatypeid,sendto,subject,message,status,alerttype,esc_step,error)" " values (" ZBX_FS_UI64 "," ZBX_FS_UI64 "," ZBX_FS_UI64 "," ZBX_FS_UI64 ",%d" "," ZBX_FS_UI64 ",'%s','%s','%s',%d,%d,%d,'%s')", alertid, action->actionid, event->eventid, userid, now, mediatypeid, sendto_esc, subject_esc, message_esc, ALERT_STATUS_FAILED, ALERT_TYPE_MESSAGE, escalation->esc_step, error_esc); zbx_free(error_esc); } zbx_free(sendto_esc); } DBfree_result(result); if (0 == medias) { zbx_snprintf(error, sizeof(error), "No media defined for user \"%s\"", zbx_user_string(userid)); alertid = DBget_maxid("alerts"); error_esc = DBdyn_escape_string(error); DBexecute("insert into alerts (alertid,actionid,eventid,userid,retries,clock" ",subject,message,status,alerttype,error,esc_step)" " values (" ZBX_FS_UI64 "," ZBX_FS_UI64 "," ZBX_FS_UI64 "," ZBX_FS_UI64 ",%d,%d" ",'%s','%s',%d,%d,'%s',%d)", alertid, action->actionid, event->eventid, userid, ALERT_MAX_RETRIES, 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); zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name); }
/****************************************************************************** * * * Function: DCflush_nextchecks * * * * Purpose: add item nextcheck to the array * * * * Parameters: * * * * Return value: * * * * Author: Alexander Vladishev, Dmitry Borovikov * * * * Comments: * * * ******************************************************************************/ void DCflush_nextchecks() { const char *__function_name = "DCflush_nextchecks"; int i, sql_offset = 0, sql_allocated = 4096; char *sql = NULL; DB_RESULT result; DB_ROW row; zbx_uint64_t triggerid; zbx_uint64_t itemid; zbx_uint64_t events_maxid = 0; char *error_msg_esc = NULL; char *sql_select = NULL; int sql_select_offset = 0, sql_select_allocated = 512; /* a crutch for the function `DBadd_condition_alloc' */ zbx_uint64_t *ids = NULL; int ids_allocated = 0, ids_num = 0; zbx_uint64_t *triggerids = NULL; int triggerids_allocated = 0, triggerids_num = 0; struct event_objectid_clock *events = NULL; int events_num = 0, events_allocated = 32; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); if (nextcheck_num == 0) return; sql = zbx_malloc(sql, sql_allocated); DBbegin(); #ifdef HAVE_ORACLE zbx_snprintf_alloc(&sql, &sql_allocated, &sql_offset, 8, "begin\n"); #endif /* dealing with items */ for (i = 0; i < nextcheck_num; i++) { if (NULL == nextchecks[i].error_msg) continue; uint64_array_add(&ids, &ids_allocated, &ids_num, nextchecks[i].itemid, 64); error_msg_esc = DBdyn_escape_string_len(nextchecks[i].error_msg, ITEM_ERROR_LEN); zbx_snprintf_alloc(&sql, &sql_allocated, &sql_offset, 128 + strlen(error_msg_esc), "update items set status=%d,lastclock=%d,error='%s' where itemid=" ZBX_FS_UI64 ";\n", ITEM_STATUS_NOTSUPPORTED, (int)nextchecks[i].now, error_msg_esc, nextchecks[i].itemid); zbx_free(error_msg_esc); DBexecute_overflowed_sql(&sql, &sql_allocated, &sql_offset); } /* dealing with notsupported items */ if (ids_num > 0) { sql_select = zbx_malloc(sql_select, sql_select_allocated); events = zbx_malloc(events, events_allocated * sizeof(struct event_objectid_clock)); /* preparing triggers */ zbx_snprintf_alloc(&sql_select, &sql_select_allocated, &sql_select_offset, 256, "select t.triggerid,i.itemid" " from triggers t,functions f,items i" " where t.triggerid=f.triggerid" " and f.itemid=i.itemid" " and t.status in (%d)" " and t.value not in (%d)" " and", TRIGGER_STATUS_ENABLED, TRIGGER_VALUE_UNKNOWN); DBadd_condition_alloc(&sql_select, &sql_select_allocated, &sql_select_offset, "i.itemid", ids, ids_num); result = DBselect("%s", sql_select); zbx_free(sql_select); /* processing triggers */ while (NULL != (row = DBfetch(result))) { ZBX_STR2UINT64(triggerid, row[0]); ZBX_STR2UINT64(itemid, row[1]); /* do not generate multiple unknown events for a trigger */ if (SUCCEED == uint64_array_exists(triggerids, triggerids_num, triggerid)) continue; uint64_array_add(&triggerids, &triggerids_allocated, &triggerids_num, triggerid, 64); /* index `i' will surely contain necessary itemid */ i = get_nearestindex(nextchecks, sizeof(ZBX_DC_NEXTCHECK), nextcheck_num, itemid); if (i == nextcheck_num || nextchecks[i].itemid != itemid) { THIS_SHOULD_NEVER_HAPPEN; continue; } error_msg_esc = DBdyn_escape_string_len(nextchecks[i].error_msg, TRIGGER_ERROR_LEN); zbx_snprintf_alloc(&sql, &sql_allocated, &sql_offset, 128 + strlen(error_msg_esc), "update triggers set value=%d,lastchange=%d,error='%s' where triggerid=" ZBX_FS_UI64";\n", TRIGGER_VALUE_UNKNOWN, nextchecks[i].now, error_msg_esc, triggerid); zbx_free(error_msg_esc); if (events_num == events_allocated) { events_allocated += 32; events = zbx_realloc(events, events_allocated * sizeof(struct event_objectid_clock)); } events[events_num].objectid = triggerid; events[events_num].clock = nextchecks[i].now; events_num++; DBexecute_overflowed_sql(&sql, &sql_allocated, &sql_offset); } DBfree_result(result); /* dealing with events */ for (i = 0; i < events_num; i++) { events_maxid = DBget_maxid("events"); zbx_snprintf_alloc(&sql, &sql_allocated, &sql_offset, 256, "insert into events (eventid,source,object,objectid,clock,value) " "values (" ZBX_FS_UI64 ",%d,%d," ZBX_FS_UI64 ",%d,%d);\n", events_maxid, EVENT_SOURCE_TRIGGERS, EVENT_OBJECT_TRIGGER, events[i].objectid, events[i].clock, TRIGGER_VALUE_UNKNOWN); DBexecute_overflowed_sql(&sql, &sql_allocated, &sql_offset); } zbx_free(events); } #ifdef HAVE_ORACLE zbx_snprintf_alloc(&sql, &sql_allocated, &sql_offset, 8, "end;\n"); #endif if (sql_offset > 16) /* In ORACLE always present begin..end; */ DBexecute("%s", sql); zbx_free(sql); zbx_free(ids); zbx_free(triggerids); DCrelease_nextchecks(); DBcommit(); zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name); }
/****************************************************************************** * * * Function: add host if not added already * * * * Purpose: add discovered host * * * * Parameters: dhostid - discovered host id * * * * Return value: hostid - new/existing hostid * * * * Author: Alexei Vladishev * * * ******************************************************************************/ static zbx_uint64_t add_discovered_host(DB_EVENT *event) { const char *__function_name = "add_discovered_host"; DB_RESULT result; DB_RESULT result2; DB_ROW row; DB_ROW row2; zbx_uint64_t hostid = 0, proxy_hostid, host_proxy_hostid; char host[MAX_STRING_LEN], *host_esc, *ip_esc, *host_unique, *host_unique_esc; int port; zbx_uint64_t groupid; zabbix_log(LOG_LEVEL_DEBUG, "In %s(eventid:" ZBX_FS_UI64 ")", __function_name, event->eventid); result = DBselect( "select discovery_groupid" " from config" " where 1=1" DB_NODE, DBnode_local("configid")); if (NULL != (row = DBfetch(result))) { ZBX_STR2UINT64(groupid, row[0]); } else { zabbix_log(LOG_LEVEL_WARNING, "cannot add discovered host: group for discovered hosts is not defined"); return 0; } DBfree_result(result); switch (event->object) { case EVENT_OBJECT_DHOST: result = DBselect( "select dr.proxy_hostid,ds.ip" " from drules dr,dchecks dc,dservices ds" " where dc.druleid=dr.druleid" " and ds.dcheckid=dc.dcheckid" " and ds.dhostid=" ZBX_FS_UI64 " order by ds.dserviceid", event->objectid); break; case EVENT_OBJECT_DSERVICE: result = DBselect( "select dr.proxy_hostid,ds.ip" " from drules dr,dchecks dc,dservices ds,dservices ds1" " where dc.druleid=dr.druleid" " and ds.dcheckid=dc.dcheckid" " and ds1.dhostid=ds.dhostid" " and ds1.dserviceid=" ZBX_FS_UI64 " order by ds.dserviceid", event->objectid); break; case EVENT_OBJECT_ZABBIX_ACTIVE: result = DBselect("select proxy_hostid,host from autoreg_host" " where autoreg_hostid=" ZBX_FS_UI64, event->objectid); break; default: return 0; } if (NULL != (row = DBfetch(result))) { ZBX_STR2UINT64(proxy_hostid, row[0]); if (EVENT_OBJECT_ZABBIX_ACTIVE == event->object) { char sql[512]; host_esc = DBdyn_escape_string_len(row[1], HOST_HOST_LEN); zbx_snprintf(sql, sizeof(sql), "select hostid,proxy_hostid" " from hosts" " where host='%s'" DB_NODE " order by hostid", host_esc, DBnode_local("hostid")); result2 = DBselectN(sql, 1); if (NULL == (row2 = DBfetch(result2))) { hostid = DBget_maxid("hosts"); DBexecute("insert into hosts (hostid,proxy_hostid,host,useip,dns)" " values (" ZBX_FS_UI64 "," ZBX_FS_UI64 ",'%s',0,'%s')", hostid, proxy_hostid, host_esc, host_esc); } else { ZBX_STR2UINT64(hostid, row2[0]); ZBX_STR2UINT64(host_proxy_hostid, row2[1]); if (host_proxy_hostid != proxy_hostid) { DBexecute("update hosts" " set proxy_hostid=" ZBX_FS_UI64 " where hostid=" ZBX_FS_UI64, proxy_hostid, hostid); } } DBfree_result(result2); zbx_free(host_esc); } else /* EVENT_OBJECT_DHOST, EVENT_OBJECT_DSERVICE */ { alarm(CONFIG_TIMEOUT); zbx_gethost_by_ip(row[1], host, sizeof(host)); alarm(0); host_esc = DBdyn_escape_string_len(host, HOST_HOST_LEN); ip_esc = DBdyn_escape_string_len(row[1], HOST_IP_LEN); port = get_discovered_agent_port(event); result2 = DBselect( "select hostid,dns,port,proxy_hostid" " from hosts" " where ip='%s'" DB_NODE, ip_esc, DBnode_local("hostid")); if (NULL == (row2 = DBfetch(result2))) { hostid = DBget_maxid("hosts"); /* for host uniqueness purposes */ if ('\0' != *host) { /* by host name */ make_hostname(host); /* replace not-allowed characters */ host_unique = DBget_unique_hostname_by_sample(host); } else { /* by ip */ make_hostname(row[1]); /* replace not-allowed characters */ host_unique = DBget_unique_hostname_by_sample(row[1]); } host_unique_esc = DBdyn_escape_string(host_unique); DBexecute("insert into hosts (hostid,proxy_hostid,host,useip,ip,dns,port)" " values (" ZBX_FS_UI64 "," ZBX_FS_UI64 ",'%s',1,'%s','%s',%d)", hostid, proxy_hostid, host_unique_esc, ip_esc, host_esc, port); zbx_free(host_unique); zbx_free(host_unique_esc); } else { ZBX_STR2UINT64(hostid, row2[0]); ZBX_STR2UINT64(host_proxy_hostid, row2[3]); if (0 != strcmp(host, row2[1]) || host_proxy_hostid != proxy_hostid) { DBexecute("update hosts" " set dns='%s',proxy_hostid=" ZBX_FS_UI64 " where hostid=" ZBX_FS_UI64, host_esc, proxy_hostid, hostid); } } DBfree_result(result2); zbx_free(host_esc); zbx_free(ip_esc); } } DBfree_result(result); if (0 != hostid) add_discovered_host_group(hostid, groupid); zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name); return hostid; }
static void add_message_alert(DB_ESCALATION *escalation, DB_EVENT *event, DB_ACTION *action, zbx_uint64_t userid, zbx_uint64_t mediatypeid, char *subject, char *message) { DB_RESULT result; DB_ROW row; zbx_uint64_t alertid; int now, severity, medias = 0; char *sendto_esc, *subject_esc, *message_esc, *error_esc; char error[MAX_STRING_LEN]; 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_len(subject, ALERT_SUBJECT_LEN); message_esc = DBdyn_escape_string(message); if (0 == mediatypeid) { result = DBselect("select mediatypeid,sendto,severity,period from media" " where active=%d and userid=" ZBX_FS_UI64, MEDIA_STATUS_ACTIVE, userid); } else { result = DBselect("select mediatypeid,sendto,severity,period from media" " where active=%d and userid=" ZBX_FS_UI64 " and mediatypeid=" ZBX_FS_UI64, MEDIA_STATUS_ACTIVE, userid, mediatypeid); } while (NULL != (row = DBfetch(result))) { medias = 1; ZBX_STR2UINT64(mediatypeid, 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_len(row[1], ALERT_SENDTO_LEN); 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) { zbx_snprintf(error, sizeof(error), "No media defined for user \"%s\"", zbx_user_string(userid)); alertid = DBget_maxid("alerts", "alertid"); error_esc = DBdyn_escape_string(error); DBexecute("insert into alerts (alertid,actionid,eventid,userid,retries,clock" ",subject,message,status,alerttype,error,esc_step)" " values (" ZBX_FS_UI64 "," ZBX_FS_UI64 "," ZBX_FS_UI64 "," ZBX_FS_UI64 ",%d,%d" ",'%s','%s',%d,%d,'%s',%d)", alertid, action->actionid, event->eventid, userid, ALERT_MAX_RETRIES, 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: update_items * * * * Purpose: process record update * * * * Parameters: * * * * Return value: SUCCEED - processed successfully * * FAIL - an error occurred * * * * Author: * * * * Comments: * * * ******************************************************************************/ static int process_items(char **sql, size_t *sql_alloc, size_t *sql_offset, int sender_nodeid, int nodeid, const ZBX_TABLE *table, const char *record, int lastrecord) { const char *r; int f, res = FAIL; zbx_uint64_t itemid = 0; char *value_esc; int clock, value_type = -1; double value_double; zbx_uint64_t value_uint64; zabbix_log(LOG_LEVEL_DEBUG, "In process_items()"); if (*sql_offset == 0) DBbegin_multiple_update(sql, sql_alloc, sql_offset); zbx_strcpy_alloc(sql, sql_alloc, sql_offset, "update items set prevvalue=lastvalue"); for (r = record, f = 0; table->fields[f].name != 0; f++) { if (0 != (table->flags & ZBX_HISTORY_SYNC) && 0 == (table->fields[f].flags & ZBX_HISTORY_SYNC)) continue; if (NULL == r) goto error; zbx_get_next_field(&r, &buffer, &buffer_alloc, ZBX_DM_DELIMITER); if (0 == strcmp(table->fields[f].name, "itemid")) ZBX_STR2UINT64(itemid, buffer); if (table->fields[f].type == ZBX_TYPE_INT || table->fields[f].type == ZBX_TYPE_UINT || table->fields[f].type == ZBX_TYPE_ID || table->fields[f].type == ZBX_TYPE_FLOAT) { if (0 == strcmp(table->fields[f].name, "clock")) { zbx_snprintf_alloc(sql, sql_alloc, sql_offset, ",lastclock=%s", buffer); clock = atoi(buffer); } else if (0 == strcmp(table->fields[f].name, "value")) { zbx_snprintf_alloc(sql, sql_alloc, sql_offset, ",lastvalue=%s", buffer); value_type = table->fields[f].type; if (value_type == ZBX_TYPE_FLOAT) value_double = atof(buffer); else if (value_type == ZBX_TYPE_UINT) ZBX_STR2UINT64(value_uint64, buffer); } } else /* ZBX_TYPE_TEXT, ZBX_TYPE_CHAR */ { if (0 == strcmp(table->fields[f].name, "value")) { zbx_hex2binary(buffer); value_esc = DBdyn_escape_string_len(buffer, ITEM_LASTVALUE_LEN); zbx_snprintf_alloc(sql, sql_alloc, sql_offset, ",lastvalue='%s'", value_esc); zbx_free(value_esc); } } } if (value_type == ZBX_TYPE_FLOAT) DBadd_trend(itemid, value_double, clock); else if (value_type == ZBX_TYPE_UINT) DBadd_trend_uint(itemid, value_uint64, clock); zbx_snprintf_alloc(sql, sql_alloc, sql_offset, " where itemid=" ZBX_FS_UI64 ";\n", itemid); if (lastrecord || *sql_offset > ZBX_MAX_SQL_SIZE) { DBend_multiple_update(sql, sql_alloc, sql_offset); if (DBexecute("%s", *sql) >= ZBX_DB_OK) res = SUCCEED; *sql_offset = 0; } else res = SUCCEED; return res; error: zabbix_log(LOG_LEVEL_ERR, "NODE %d: Received invalid record from node %d for node %d [%s]", CONFIG_NODEID, sender_nodeid, nodeid, record); return FAIL; }
/****************************************************************************** * * * Function: lld_process_discovery_rule * * * * Purpose: add or update items, triggers and graphs for discovery item * * * * Parameters: lld_ruleid - [IN] discovery item identificator from database * * value - [IN] received value from agent * * * ******************************************************************************/ void lld_process_discovery_rule(zbx_uint64_t lld_ruleid, char *value, zbx_timespec_t *ts) { const char *__function_name = "lld_process_discovery_rule"; DB_RESULT result; DB_ROW row; zbx_uint64_t hostid = 0; char *discovery_key = NULL, *filter = NULL, *error = NULL, *db_error = NULL, *error_esc; unsigned char state = 0; unsigned short lifetime; zbx_vector_ptr_t lld_rows; char *sql = NULL; size_t sql_alloc = 128, sql_offset = 0; const char *sql_start = "update items set ", *sql_continue = ","; zabbix_log(LOG_LEVEL_DEBUG, "In %s() itemid:" ZBX_FS_UI64, __function_name, lld_ruleid); zbx_vector_ptr_create(&lld_rows); sql = zbx_malloc(sql, sql_alloc); result = DBselect( "select hostid,key_,state,filter,error,lifetime" " from items" " where itemid=" ZBX_FS_UI64, lld_ruleid); if (NULL != (row = DBfetch(result))) { char *lifetime_str; ZBX_STR2UINT64(hostid, row[0]); discovery_key = zbx_strdup(discovery_key, row[1]); state = (unsigned char)atoi(row[2]); filter = zbx_strdup(filter, row[3]); db_error = zbx_strdup(db_error, row[4]); lifetime_str = zbx_strdup(NULL, row[5]); substitute_simple_macros(NULL, NULL, NULL, NULL, &hostid, NULL, NULL, &lifetime_str, MACRO_TYPE_COMMON, NULL, 0); if (SUCCEED != is_ushort(lifetime_str, &lifetime)) { zabbix_log(LOG_LEVEL_WARNING, "cannot process lost resources for the discovery rule \"%s:%s\":" " \"%s\" is not a valid value", zbx_host_string(hostid), discovery_key, lifetime_str); lifetime = 3650; /* max value for the field */ } zbx_free(lifetime_str); } else zabbix_log(LOG_LEVEL_WARNING, "invalid discovery rule ID [" ZBX_FS_UI64 "]", lld_ruleid); DBfree_result(result); if (0 == hostid) goto clean; if (SUCCEED != lld_rows_get(value, filter, &lld_rows, &error)) goto error; error = zbx_strdup(error, ""); lld_update_items(hostid, lld_ruleid, &lld_rows, &error, lifetime, ts->sec); lld_update_triggers(hostid, lld_ruleid, &lld_rows, &error); lld_update_graphs(hostid, lld_ruleid, &lld_rows, &error); lld_update_hosts(lld_ruleid, &lld_rows, &error, lifetime, ts->sec); if (ITEM_STATE_NOTSUPPORTED == state) { zabbix_log(LOG_LEVEL_WARNING, "discovery rule [" ZBX_FS_UI64 "][%s] became supported", lld_ruleid, zbx_host_key_string(lld_ruleid)); add_event(0, EVENT_SOURCE_INTERNAL, EVENT_OBJECT_LLDRULE, lld_ruleid, ts, ITEM_STATE_NORMAL, NULL, NULL, 0, 0); process_events(); zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%sstate=%d", sql_start, ITEM_STATE_NORMAL); sql_start = sql_continue; } error: if (NULL != error && 0 != strcmp(error, db_error)) { error_esc = DBdyn_escape_string_len(error, ITEM_ERROR_LEN); zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%serror='%s'", sql_start, error_esc); sql_start = sql_continue; zbx_free(error_esc); } if (sql_start == sql_continue) { zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, " where itemid=" ZBX_FS_UI64, lld_ruleid); DBbegin(); DBexecute("%s", sql); DBcommit(); } clean: zbx_free(error); zbx_free(db_error); zbx_free(filter); zbx_free(discovery_key); zbx_free(sql); zbx_vector_ptr_clean(&lld_rows, (zbx_mem_free_func_t)lld_row_free); zbx_vector_ptr_destroy(&lld_rows); zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name); }
/****************************************************************************** * * * Function: process_httptest * * * * Purpose: process single scenario of http test * * * * Parameters: * * * * Return value: * * * * Author: Alexei Vladishev * * * * Comments: * * * ******************************************************************************/ static void process_httptest(DB_HTTPTEST *httptest) { const char *__function_name = "process_httptest"; DB_RESULT result; DB_ROW row; DB_HTTPSTEP httpstep; char *err_str = NULL, *err_str_esc = NULL; int now, lastfailedstep; ZBX_HTTPSTAT stat; double speed_download = 0; int speed_download_num = 0; #ifdef HAVE_LIBCURL int err, opt; char auth[HTTPTEST_HTTP_USER_LEN_MAX + HTTPTEST_HTTP_PASSWORD_LEN_MAX]; CURL *easyhandle = NULL; #endif zabbix_log(LOG_LEVEL_DEBUG, "In %s() httptestid:" ZBX_FS_UI64 " name:'%s'", __function_name, httptest->httptestid, httptest->name); lastfailedstep = 0; httptest->time = 0; now = time(NULL); DBexecute("update httptest" " set lastcheck=%d" " where httptestid=" ZBX_FS_UI64, now, httptest->httptestid); result = DBselect( "select httpstepid,no,name,url,timeout," "posts,required,status_codes" " from httpstep" " where httptestid=" ZBX_FS_UI64 " order by no", httptest->httptestid); #ifdef HAVE_LIBCURL if (NULL == (easyhandle = curl_easy_init())) { zabbix_log(LOG_LEVEL_ERR, "Web scenario [%s] error: could not init cURL library", httptest->name); err_str = zbx_strdup(err_str, "could not init cURL library"); goto clean; } if (CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_COOKIEFILE, "")) || CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_USERAGENT, httptest->agent)) || CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_FOLLOWLOCATION, 1)) || CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_WRITEFUNCTION, WRITEFUNCTION2)) || CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_HEADERFUNCTION, HEADERFUNCTION2)) || CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_SSL_VERIFYPEER, 0)) || CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_SSL_VERIFYHOST, 0)) || /* The pointed data are not copied by the library. As a consequence, the data */ /* must be preserved by the calling application until the transfer finishes. */ CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_POSTFIELDS, httpstep.posts))) { zabbix_log(LOG_LEVEL_ERR, "Web scenario [%s] error: could not set cURL option [%d]: %s", httptest->name, opt, curl_easy_strerror(err)); err_str = zbx_strdup(err_str, curl_easy_strerror(err)); goto clean; } while (NULL == err_str && NULL != (row = DBfetch(result))) { /* NOTE: do not use break or return for this block! * process_step_data calling required! */ ZBX_STR2UINT64(httpstep.httpstepid, row[0]); httpstep.httptestid = httptest->httptestid; httpstep.no = atoi(row[1]); httpstep.name = row[2]; strscpy(httpstep.url, row[3]); httpstep.timeout = atoi(row[4]); strscpy(httpstep.posts, row[5]); strscpy(httpstep.required, row[6]); strscpy(httpstep.status_codes, row[7]); DBexecute("update httptest" " set curstep=%d," "curstate=%d" " where httptestid=" ZBX_FS_UI64, httpstep.no, HTTPTEST_STATE_BUSY, httptest->httptestid); memset(&stat, 0, sizeof(stat)); /* Substitute macros */ http_substitute_macros(httptest, httpstep.url, sizeof(httpstep.url)); http_substitute_macros(httptest, httpstep.posts, sizeof(httpstep.posts)); zabbix_log(LOG_LEVEL_DEBUG, "WEBMonitor: use step [%s]", httpstep.name); if ('\0' != *httpstep.posts) { zabbix_log(LOG_LEVEL_DEBUG, "WEBMonitor: use post [%s]", httpstep.posts); curl_easy_setopt(easyhandle, CURLOPT_POST, 1); } else curl_easy_setopt(easyhandle, CURLOPT_POST, 0); if (HTTPTEST_AUTH_NONE != httptest->authentication) { long curlauth = 0; zabbix_log(LOG_LEVEL_DEBUG, "WEBMonitor: Setting HTTPAUTH [%d]", httptest->authentication); zabbix_log(LOG_LEVEL_DEBUG, "WEBMonitor: Setting USERPWD for authentication"); switch (httptest->authentication) { case HTTPTEST_AUTH_BASIC: curlauth = CURLAUTH_BASIC; break; case HTTPTEST_AUTH_NTLM: curlauth = CURLAUTH_NTLM; break; default: THIS_SHOULD_NEVER_HAPPEN; break; } zbx_snprintf(auth, sizeof(auth), "%s:%s", httptest->http_user, httptest->http_password); if (CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_HTTPAUTH, curlauth)) || CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_USERPWD, auth))) { zabbix_log(LOG_LEVEL_ERR, "Web scenario step [%s:%s] error: could not set cURL option [%d]: %s", httptest->name, httpstep.name, opt, curl_easy_strerror(err)); err_str = zbx_strdup(err_str, curl_easy_strerror(err)); } } if (NULL == err_str) { zabbix_log(LOG_LEVEL_DEBUG, "WEBMonitor: go to URL [%s]", httpstep.url); if (CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_URL, httpstep.url)) || CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_TIMEOUT, httpstep.timeout)) || CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_CONNECTTIMEOUT, httpstep.timeout))) { zabbix_log(LOG_LEVEL_ERR, "Web scenario step [%s:%s] error: could not set cURL option [%d]: %s", httptest->name, httpstep.name, opt, curl_easy_strerror(err)); err_str = zbx_strdup(err_str, curl_easy_strerror(err)); } } if (NULL == err_str) { memset(&page, 0, sizeof(page)); if (CURLE_OK != (err = curl_easy_perform(easyhandle))) { zabbix_log(LOG_LEVEL_ERR, "Web scenario step [%s:%s] error: error doing curl_easy_perform: %s", httptest->name, httpstep.name, curl_easy_strerror(err)); err_str = zbx_strdup(err_str, curl_easy_strerror(err)); } else { if ('\0' != httpstep.required[0] && NULL == zbx_regexp_match(page.data, httpstep.required, NULL)) { zabbix_log(LOG_LEVEL_DEBUG, "Page did not match [%s]", httpstep.required); err_str = zbx_strdup(err_str, "Page did not match"); } if (CURLE_OK != (err = curl_easy_getinfo(easyhandle, CURLINFO_RESPONSE_CODE, &stat.rspcode))) { zabbix_log(LOG_LEVEL_ERR, "Web scenario step [%s:%s] error: error getting CURLINFO_RESPONSE_CODE: %s", httptest->name, httpstep.name, curl_easy_strerror(err)); err_str = (NULL == err_str ? zbx_strdup(err_str, curl_easy_strerror(err)) : err_str); } else if ('\0' != httpstep.status_codes[0] && FAIL == int_in_list(httpstep.status_codes, stat.rspcode)) { zabbix_log(LOG_LEVEL_DEBUG, "Status code did not match [%s]", httpstep.status_codes); err_str = (NULL == err_str ? zbx_strdup(err_str, "Status code did not match") : err_str); } if (CURLE_OK != (err = curl_easy_getinfo(easyhandle, CURLINFO_TOTAL_TIME, &stat.total_time))) { zabbix_log(LOG_LEVEL_ERR, "Web scenario step [%s:%s] error: error getting CURLINFO_TOTAL_TIME: %s", httptest->name, httpstep.name, curl_easy_strerror(err)); err_str = (NULL == err_str ? zbx_strdup(err_str, curl_easy_strerror(err)) : err_str); } if (CURLE_OK != (err = curl_easy_getinfo(easyhandle, CURLINFO_SPEED_DOWNLOAD, &stat.speed_download))) { zabbix_log(LOG_LEVEL_ERR, "Web scenario step [%s:%s] error: error getting CURLINFO_SPEED_DOWNLOAD: %s", httptest->name, httpstep.name, curl_easy_strerror(err)); err_str = (NULL == err_str ? zbx_strdup(err_str, curl_easy_strerror(err)) : err_str); } else { speed_download += stat.speed_download; speed_download_num++; } } zbx_free(page.data); } if (NULL != err_str) lastfailedstep = httpstep.no; httptest->time += stat.total_time; process_step_data(httpstep.httpstepid, &stat); } clean: curl_easy_cleanup(easyhandle); #else err_str = zbx_strdup(err_str, "cURL library is required for Web monitoring support"); #endif /* HAVE_LIBCURL */ if (0 == lastfailedstep && NULL != err_str) { /* we are here either because cURL initialization failed before */ /* the first step or we have been compiled without cURL library */ lastfailedstep = 1; if (NULL != (row = DBfetch(result))) { ZBX_STR2UINT64(httpstep.httpstepid, row[0]); memset(&stat, 0, sizeof(stat)); process_step_data(httpstep.httpstepid, &stat); } else THIS_SHOULD_NEVER_HAPPEN; } DBfree_result(result); err_str_esc = DBdyn_escape_string_len(err_str, HTTPTEST_ERROR_LEN); DBexecute("update httptest" " set curstep=0," "curstate=%d," "lastcheck=%d," "nextcheck=%d+delay," "lastfailedstep=%d," "time=" ZBX_FS_DBL "," "error='%s'" " where httptestid=" ZBX_FS_UI64, HTTPTEST_STATE_IDLE, now, now, lastfailedstep, httptest->time, err_str_esc, httptest->httptestid); zbx_free(err_str_esc); zbx_free(err_str); stat.test_total_time = httptest->time; stat.test_last_step = lastfailedstep; stat.speed_download = speed_download_num ? speed_download / speed_download_num : 0; process_test_data(httptest->httptestid, &stat); zabbix_log(LOG_LEVEL_DEBUG, "End of %s() total_time:" ZBX_FS_DBL, __function_name, httptest->time); }
/****************************************************************************** * * * Function: DCflush_nextchecks * * * * Purpose: add item nextcheck to the array * * * * Parameters: * * * * Return value: * * * * Author: Aleksander Vladishev * * * * Comments: * * * ******************************************************************************/ void DCflush_nextchecks() { int i, sql_offset = 0, sql_allocated = 1024; char *sql = NULL; time_t last_clock = -1; zbx_uint64_t last_itemid = 0; char *error_esc; zabbix_log(LOG_LEVEL_DEBUG, "In DCflush_nextchecks()"); if (nextcheck_num == 0) return; sql = zbx_malloc(sql, sql_allocated); #ifdef HAVE_ORACLE zbx_snprintf_alloc(&sql, &sql_allocated, &sql_offset, 8, "begin\n"); #endif for (i = 0; i < nextcheck_num; i++) { if (NULL != nextchecks[i].error_msg) continue; if (last_clock != nextchecks[i].clock) { if (last_clock != -1) { sql_offset--; zbx_snprintf_alloc(&sql, &sql_allocated, &sql_offset, 4, ");\n"); } if (last_itemid > nextchecks[i].itemid) { #ifdef HAVE_ORACLE zbx_snprintf_alloc(&sql, &sql_allocated, &sql_offset, 8, "end;\n"); #endif DBbegin(); DBexecute("%s", sql); DBcommit(); sql_offset = 0; #ifdef HAVE_ORACLE zbx_snprintf_alloc(&sql, &sql_allocated, &sql_offset, 8, "begin\n"); #endif } zbx_snprintf_alloc(&sql, &sql_allocated, &sql_offset, 64, "update items set nextcheck=%d where itemid in (", (int)nextchecks[i].clock); last_clock = nextchecks[i].clock; } zbx_snprintf_alloc(&sql, &sql_allocated, &sql_offset, 32, ZBX_FS_UI64 ",", nextchecks[i].itemid); last_itemid = nextchecks[i].itemid; } if (sql_offset > 8) { sql_offset--; zbx_snprintf_alloc(&sql, &sql_allocated, &sql_offset, 4, ");\n"); } for (i = 0; i < nextcheck_num; i++) { if (NULL == nextchecks[i].error_msg) /* not supported items */ continue; if (last_itemid > nextchecks[i].itemid) { #ifdef HAVE_ORACLE zbx_snprintf_alloc(&sql, &sql_allocated, &sql_offset, 8, "end;\n"); #endif DBbegin(); DBexecute("%s", sql); DBcommit(); sql_offset = 0; #ifdef HAVE_ORACLE zbx_snprintf_alloc(&sql, &sql_allocated, &sql_offset, 8, "begin\n"); #endif } error_esc = DBdyn_escape_string_len(nextchecks[i].error_msg, ITEM_ERROR_LEN); zbx_free(nextchecks[i].error_msg); zbx_snprintf_alloc(&sql, &sql_allocated, &sql_offset, 128 + strlen(error_esc), "update items set status=%d,lastclock=%d,nextcheck=%d,error='%s'" " where itemid=" ZBX_FS_UI64 ";\n", ITEM_STATUS_NOTSUPPORTED, (int)nextchecks[i].clock, (int)(nextchecks[i].clock + CONFIG_REFRESH_UNSUPPORTED), error_esc, nextchecks[i].itemid); last_itemid = nextchecks[i].itemid; zbx_free(error_esc); } #ifdef HAVE_ORACLE zbx_snprintf_alloc(&sql, &sql_allocated, &sql_offset, 8, "end;\n"); #endif if (sql_offset > 16) { DBbegin(); DBexecute("%s", sql); DBcommit(); } zbx_free(sql); }
/****************************************************************************** * * * Function: main_alerter_loop * * * * Purpose: periodically check table alerts and send notifications if needed * * * * Parameters: * * * * Return value: * * * * Author: Alexei Vladishev * * * * Comments: never returns * * * ******************************************************************************/ int main_alerter_loop() { 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;*/ phan.sa_sigaction = child_signal_handler; sigemptyset(&phan.sa_mask); phan.sa_flags = SA_SIGINFO; 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]; mediatype.gsm_modem = row[13]; mediatype.username = row[14]; mediatype.passwd = row[15]; alert.retries = atoi(row[16]); *error = '\0'; res = execute_action(&alert, &mediatype, error, sizeof(error)); if (res == SUCCEED) { zabbix_log( LOG_LEVEL_DEBUG, "Alert ID [" ZBX_FS_UI64 "] was sent successfully", alert.alertid); DBexecute("update alerts set status=%d,error='' where alertid=" ZBX_FS_UI64, ALERT_STATUS_SENT, alert.alertid); } else { zabbix_log( LOG_LEVEL_DEBUG, "Error sending alert ID [" ZBX_FS_UI64 "]", alert.alertid); zabbix_syslog("Error sending alert ID [" ZBX_FS_UI64 "]", alert.alertid); error_esc = DBdyn_escape_string_len(error, ALERT_ERROR_LEN); alert.retries++; if(alert.retries < ALERT_MAX_RETRIES) { DBexecute("update alerts set retries=%d,error='%s' where alertid=" ZBX_FS_UI64, alert.retries, error_esc, alert.alertid); } else { DBexecute("update alerts set status=%d,retries=%d,error='%s' where alertid=" ZBX_FS_UI64, ALERT_STATUS_FAILED, alert.retries, error_esc, alert.alertid); } zbx_free(error_esc); } } DBfree_result(result); zbx_setproctitle("sender [sleeping for %d seconds]", CONFIG_SENDER_FREQUENCY); sleep(CONFIG_SENDER_FREQUENCY); } /* Never reached */ DBclose(); }
/****************************************************************************** * * * Function: update_item * * * * Purpose: update item info after new value is received * * * * Parameters: item - item data * * value - new value of the item * * now - current timestamp * * * * Author: Alexei Vladishev, Eugene Grigorjev * * * * Comments: * * * ******************************************************************************/ static void update_item(DB_ITEM *item, AGENT_RESULT *value, time_t now) { char *value_esc; zbx_uint64_t value_uint64; double value_double; zabbix_log(LOG_LEVEL_DEBUG, "In update_item()"); item->nextcheck = calculate_item_nextcheck(item->itemid, item->type, item->delay, item->delay_flex, now); switch (item->value_type) { case ITEM_VALUE_TYPE_FLOAT: if (NULL == GET_DBL_RESULT(value)) break; switch (item->delta) { /* Should we store delta or original value? */ case ITEM_STORE_AS_IS: value_double = DBmultiply_value_float(item, value->dbl); DBexecute("update items set nextcheck=%d,prevvalue=lastvalue,prevorgvalue=NULL," "lastvalue='" ZBX_FS_DBL "',lastclock=%d where itemid=" ZBX_FS_UI64, item->nextcheck, value_double, (int)now, item->itemid); SET_DBL_RESULT(value, value_double); break; case ITEM_STORE_SPEED_PER_SECOND: /* Delta as speed of change */ if (0 == item->prevorgvalue_null && item->prevorgvalue_dbl <= value->dbl) { /* In order to continue normal processing, we assume difference 1 second Otherwise function update_functions and update_triggers won't work correctly*/ if (now != item->lastclock) value_double = (value->dbl - item->prevorgvalue_dbl) / (now - item->lastclock); else value_double = value->dbl - item->prevorgvalue_dbl; value_double = DBmultiply_value_float(item, value_double); DBexecute("update items set nextcheck=%d,prevvalue=lastvalue,prevorgvalue='" ZBX_FS_DBL "'," "lastvalue='" ZBX_FS_DBL "',lastclock=%d where itemid=" ZBX_FS_UI64, item->nextcheck, value->dbl, value_double, (int)now, item->itemid); SET_DBL_RESULT(value, value_double); } else { DBexecute("update items set nextcheck=%d,prevorgvalue='" ZBX_FS_DBL "',lastclock=%d where itemid=" ZBX_FS_UI64, item->nextcheck, value->dbl, (int)now, item->itemid); } break; case ITEM_STORE_SIMPLE_CHANGE: /* Real delta: simple difference between values */ if (0 == item->prevorgvalue_null && item->prevorgvalue_dbl <= value->dbl) { value_double = DBmultiply_value_float(item, value->dbl - item->prevorgvalue_dbl); DBexecute("update items set nextcheck=%d,prevvalue=lastvalue,prevorgvalue='" ZBX_FS_DBL "'," "lastvalue='" ZBX_FS_DBL "',lastclock=%d where itemid=" ZBX_FS_UI64, item->nextcheck, value->dbl, value_double, (int)now, item->itemid); SET_DBL_RESULT(value, value_double); } else { DBexecute("update items set nextcheck=%d,prevorgvalue='" ZBX_FS_DBL "',lastclock=%d where itemid=" ZBX_FS_UI64, item->nextcheck, value->dbl, (int)now, item->itemid); } break; } break; case ITEM_VALUE_TYPE_UINT64: if (NULL == GET_UI64_RESULT(value)) break; switch (item->delta) { /* Should we store delta or original value? */ case ITEM_STORE_AS_IS: value_uint64 = DBmultiply_value_uint64(item, value->ui64); DBexecute("update items set nextcheck=%d,prevvalue=lastvalue,prevorgvalue=NULL," "lastvalue='" ZBX_FS_UI64 "',lastclock=%d where itemid=" ZBX_FS_UI64, item->nextcheck, value_uint64, (int)now, item->itemid); SET_UI64_RESULT(value, value_uint64); break; case ITEM_STORE_SPEED_PER_SECOND: /* Delta as speed of change */ if (0 == item->prevorgvalue_null && item->prevorgvalue_uint64 <= value->ui64) { if (now != item->lastclock) value_uint64 = (zbx_uint64_t)(value->ui64 - item->prevorgvalue_uint64) / (now - item->lastclock); else value_uint64 = value->ui64 - item->prevorgvalue_uint64; value_uint64 = DBmultiply_value_uint64(item, value_uint64); DBexecute("update items set nextcheck=%d,prevvalue=lastvalue,prevorgvalue='" ZBX_FS_UI64 "'," "lastvalue='" ZBX_FS_UI64 "',lastclock=%d where itemid=" ZBX_FS_UI64, item->nextcheck, value->ui64, value_uint64, (int)now, item->itemid); SET_UI64_RESULT(value, value_uint64); } else { DBexecute("update items set nextcheck=%d,prevorgvalue='" ZBX_FS_UI64 "',lastclock=%d where itemid=" ZBX_FS_UI64, item->nextcheck, value->ui64, (int)now, item->itemid); } break; case ITEM_STORE_SIMPLE_CHANGE: /* Real delta: simple difference between values */ if (0 == item->prevorgvalue_null && item->prevorgvalue_uint64 <= value->ui64) { value_uint64 = DBmultiply_value_uint64(item, value->ui64 - item->prevorgvalue_uint64); DBexecute("update items set nextcheck=%d,prevvalue=lastvalue,prevorgvalue='" ZBX_FS_UI64 "'," "lastvalue='" ZBX_FS_UI64 "',lastclock=%d where itemid=" ZBX_FS_UI64, item->nextcheck, value->ui64, value_uint64, (int)now, item->itemid); SET_UI64_RESULT(value, value_uint64); } else { DBexecute("update items set nextcheck=%d,prevorgvalue='" ZBX_FS_UI64 "',lastclock=%d where itemid=" ZBX_FS_UI64, item->nextcheck, value->ui64, (int)now, item->itemid); } break; } break; case ITEM_VALUE_TYPE_STR: case ITEM_VALUE_TYPE_TEXT: if (NULL == GET_STR_RESULT(value)) break; value_esc = DBdyn_escape_string_len(value->str, ITEM_LASTVALUE_LEN); DBexecute("update items set nextcheck=%d,prevvalue=lastvalue,lastvalue='%s',lastclock=%d" " where itemid=" ZBX_FS_UI64, item->nextcheck, value_esc, (int)now, item->itemid); zbx_free(value_esc); break; case ITEM_VALUE_TYPE_LOG: if (NULL == GET_STR_RESULT(value)) break; value_esc = DBdyn_escape_string_len(value->str, ITEM_LASTVALUE_LEN); DBexecute("update items set nextcheck=%d,prevvalue=lastvalue,lastvalue='%s',lastclock=%d,lastlogsize=%d" " where itemid=" ZBX_FS_UI64, item->nextcheck, value_esc, (int)now, item->lastlogsize, item->itemid); zbx_free(value_esc); break; } item->prevvalue_str = item->lastvalue_str; item->prevvalue_dbl = item->lastvalue_dbl; item->prevvalue_uint64 = item->lastvalue_uint64; item->prevvalue_null = item->lastvalue_null; item->lastvalue_uint64 = value->ui64; item->lastvalue_dbl = value->dbl; item->lastvalue_str = value->str; item->lastvalue_null = 0; /* Required for nodata() */ item->lastclock = now; /* Update item status if required */ if (item->status == ITEM_STATUS_NOTSUPPORTED) { zabbix_log( LOG_LEVEL_WARNING, "Parameter [%s] became supported by agent on host [%s]", item->key, item->host_name); zabbix_syslog("Parameter [%s] became supported by agent on host [%s]", item->key, item->host_name); item->status = ITEM_STATUS_ACTIVE; DBexecute("update items set status=%d,error='' where itemid=" ZBX_FS_UI64, item->status, item->itemid); } zabbix_log(LOG_LEVEL_DEBUG, "End of update_item()"); }
static int dm_rename_slave_data(const char *table_name, const char *key_name, const char *field_name, int field_length) { DB_RESULT result; DB_ROW row; int local_nodeid = 0, nodeid, globalmacro; zbx_uint64_t id, min, max; char *name = NULL, *name_esc; size_t name_alloc = 0, name_offset; /* 1 - ZBX_NODE_LOCAL */ if (NULL == (result = DBselect("select nodeid from nodes where nodetype=1"))) return FAIL; if (NULL != (row = DBfetch(result))) local_nodeid = atoi(row[0]); DBfree_result(result); if (0 == local_nodeid) return SUCCEED; globalmacro = (0 == strcmp(table_name, "globalmacro")); min = local_nodeid * __UINT64_C(100000000000000); max = min + __UINT64_C(100000000000000) - 1; if (NULL == (result = DBselect( "select %s,%s" " from %s" " where not %s between " ZBX_FS_UI64 " and " ZBX_FS_UI64 " order by %s", key_name, field_name, table_name, key_name, min, max, key_name))) { return FAIL; } while (NULL != (row = DBfetch(result))) { ZBX_STR2UINT64(id, row[0]); nodeid = (int)(id / __UINT64_C(100000000000000)); name_offset = 0; if (0 == globalmacro) zbx_snprintf_alloc(&name, &name_alloc, &name_offset, "N%d_%s", nodeid, row[1]); else zbx_snprintf_alloc(&name, &name_alloc, &name_offset, "{$N%d_%s", nodeid, row[1] + 2); name_esc = DBdyn_escape_string_len(name, field_length); if (ZBX_DB_OK > DBexecute("update %s set %s='%s' where %s=" ZBX_FS_UI64, table_name, field_name, name_esc, key_name, id)) { zbx_free(name_esc); break; } zbx_free(name_esc); } DBfree_result(result); zbx_free(name); return SUCCEED; }
static void deactivate_host(DC_ITEM *item, int now, const char *error) { char sql[MAX_STRING_LEN], *error_esc, error_msg[MAX_STRING_LEN]; int offset = 0, *errors_from, *disable_until; unsigned char *available; const char *fld_errors_from, *fld_available, *fld_disable_until, *fld_error, *type; switch (item->type) { case ITEM_TYPE_ZABBIX: errors_from = &item->host.errors_from; available = &item->host.available; disable_until = &item->host.disable_until; fld_errors_from = "errors_from"; fld_available = "available"; fld_disable_until = "disable_until"; fld_error = "error"; type = "Zabbix"; break; case ITEM_TYPE_SNMPv1: case ITEM_TYPE_SNMPv2c: case ITEM_TYPE_SNMPv3: errors_from = &item->host.snmp_errors_from; available = &item->host.snmp_available; disable_until = &item->host.snmp_disable_until; fld_errors_from = "snmp_errors_from"; fld_available = "snmp_available"; fld_disable_until = "snmp_disable_until"; fld_error = "snmp_error"; type = "SNMP"; break; case ITEM_TYPE_IPMI: errors_from = &item->host.ipmi_errors_from; available = &item->host.ipmi_available; disable_until = &item->host.ipmi_disable_until; fld_errors_from = "ipmi_errors_from"; fld_available = "ipmi_available"; fld_disable_until = "ipmi_disable_until"; fld_error = "ipmi_error"; type = "IPMI"; break; default: return; } if (SUCCEED != DCconfig_deactivate_host(item, now)) return; DBbegin(); *error_msg = '\0'; offset += zbx_snprintf(sql + offset, sizeof(sql) - offset, "update hosts set "); /* First error */ if (0 == *errors_from) { zbx_snprintf(error_msg, sizeof(error_msg), "%s Host [%s]: first network error, wait for %d seconds", type, item->host.host, CONFIG_UNREACHABLE_DELAY); *errors_from = now; *disable_until = now + CONFIG_UNREACHABLE_DELAY; offset += zbx_snprintf(sql + offset, sizeof(sql) - offset, "%s=%d,", fld_errors_from, *errors_from); } else { if (now - *errors_from <= CONFIG_UNREACHABLE_PERIOD) { /* Still unavailable, but won't change status to UNAVAILABLE yet */ zbx_snprintf(error_msg, sizeof(error_msg), "%s Host [%s]: another network error, wait for %d seconds", type, item->host.host, CONFIG_UNREACHABLE_DELAY); *disable_until = now + CONFIG_UNREACHABLE_DELAY; } else { *disable_until = now + CONFIG_UNAVAILABLE_DELAY; if (HOST_AVAILABLE_FALSE != *available) { zbx_snprintf(error_msg, sizeof(error_msg), "Disabling %s host [%s]", type, item->host.host); *available = HOST_AVAILABLE_FALSE; offset += zbx_snprintf(sql + offset, sizeof(sql) - offset, "%s=%d,", fld_available, *available); if (available == &item->host.available) update_key_status(item->host.hostid, HOST_AVAILABLE_FALSE, now); /* 2 */ update_triggers_status_to_unknown(item->host.hostid, item->type, now, "Agent is unavailable."); } error_esc = DBdyn_escape_string_len(error, HOST_ERROR_LEN); offset += zbx_snprintf(sql + offset, sizeof(sql) - offset, "%s='%s',", fld_error, error_esc); zbx_free(error_esc); } } offset += zbx_snprintf(sql + offset, sizeof(sql) - offset, "%s=%d where hostid=" ZBX_FS_UI64, fld_disable_until, *disable_until, item->host.hostid); DBexecute("%s", sql); DBcommit(); if ('\0' != *error_msg) { zabbix_log(LOG_LEVEL_WARNING, "%s", error_msg); zabbix_syslog("%s", error_msg); } }
/****************************************************************************** * * * Function: add_discovered_host * * * * Purpose: add discovered host if it was not added already * * * * Parameters: dhostid - discovered host id * * * * Return value: hostid - new/existing hostid * * * * Author: Alexei Vladishev * * * ******************************************************************************/ static zbx_uint64_t add_discovered_host(const DB_EVENT *event) { const char *__function_name = "add_discovered_host"; DB_RESULT result; DB_RESULT result2; DB_ROW row; DB_ROW row2; zbx_uint64_t dhostid, hostid = 0, proxy_hostid; char *host = NULL, *host_esc, *host_unique; unsigned short port; zbx_uint64_t groupid; zbx_vector_uint64_t groupids; unsigned char svc_type, interface_type; zabbix_log(LOG_LEVEL_DEBUG, "In %s() eventid:" ZBX_FS_UI64, __function_name, event->eventid); zbx_vector_uint64_create(&groupids); if (0 == *(zbx_uint64_t *)DCconfig_get_config_data(&groupid, CONFIG_DISCOVERY_GROUPID)) { zabbix_log(LOG_LEVEL_WARNING, "cannot add discovered host: group for discovered hosts is not defined"); goto clean; } zbx_vector_uint64_append(&groupids, groupid); if (EVENT_OBJECT_DHOST == event->object || EVENT_OBJECT_DSERVICE == event->object) { if (EVENT_OBJECT_DHOST == event->object) { result = DBselect( "select ds.dhostid,dr.proxy_hostid,ds.ip,ds.dns,ds.port,ds.type" " from drules dr,dchecks dc,dservices ds" " where dc.druleid=dr.druleid" " and ds.dcheckid=dc.dcheckid" " and ds.dhostid=" ZBX_FS_UI64 " order by ds.dserviceid", event->objectid); } else { result = DBselect( "select ds.dhostid,dr.proxy_hostid,ds.ip,ds.dns,ds.port,ds.type" " from drules dr,dchecks dc,dservices ds,dservices ds1" " where dc.druleid=dr.druleid" " and ds.dcheckid=dc.dcheckid" " and ds1.dhostid=ds.dhostid" " and ds1.dserviceid=" ZBX_FS_UI64 " order by ds.dserviceid", event->objectid); } while (NULL != (row = DBfetch(result))) { ZBX_STR2UINT64(dhostid, row[0]); ZBX_DBROW2UINT64(proxy_hostid, row[1]); svc_type = (unsigned char)atoi(row[5]); switch (svc_type) { case SVC_AGENT: port = (unsigned short)atoi(row[4]); interface_type = INTERFACE_TYPE_AGENT; break; case SVC_SNMPv1: case SVC_SNMPv2c: case SVC_SNMPv3: port = (unsigned short)atoi(row[4]); interface_type = INTERFACE_TYPE_SNMP; break; default: port = ZBX_DEFAULT_AGENT_PORT; interface_type = INTERFACE_TYPE_AGENT; } if (0 == hostid) { result2 = DBselect( "select distinct h.hostid" " from hosts h,interface i,dservices ds" " where h.hostid=i.hostid" " and i.ip=ds.ip" " and h.proxy_hostid%s" " and ds.dhostid=" ZBX_FS_UI64 ZBX_SQL_NODE " order by h.hostid", DBsql_id_cmp(proxy_hostid), dhostid, DBand_node_local("h.hostid")); if (NULL != (row2 = DBfetch(result2))) ZBX_STR2UINT64(hostid, row2[0]); DBfree_result(result2); } if (0 == hostid) { hostid = DBget_maxid("hosts"); /* for host uniqueness purposes */ host = zbx_strdup(host, '\0' != *row[3] ? row[3] : row[2]); make_hostname(host); /* replace not-allowed symbols */ host_unique = DBget_unique_hostname_by_sample(host); host_esc = DBdyn_escape_string(host_unique); zbx_free(host); DBexecute("insert into hosts" " (hostid,proxy_hostid,host,name)" " values" " (" ZBX_FS_UI64 ",%s,'%s','%s')", hostid, DBsql_id_ins(proxy_hostid), host_esc, host_esc); DBadd_interface(hostid, interface_type, 1, row[2], row[3], port); zbx_free(host_unique); zbx_free(host_esc); add_discovered_host_groups(hostid, &groupids); } else { DBadd_interface(hostid, interface_type, 1, row[2], row[3], port); } } DBfree_result(result); } else if (EVENT_OBJECT_ZABBIX_ACTIVE == event->object) { result = DBselect( "select proxy_hostid,host,listen_ip,listen_dns,listen_port" " from autoreg_host" " where autoreg_hostid=" ZBX_FS_UI64, event->objectid); if (NULL != (row = DBfetch(result))) { char *sql = NULL; zbx_uint64_t host_proxy_hostid; ZBX_DBROW2UINT64(proxy_hostid, row[0]); host_esc = DBdyn_escape_string_len(row[1], HOST_HOST_LEN); port = (unsigned short)atoi(row[4]); result2 = DBselect( "select null" " from hosts" " where host='%s'" " and status=%d", host_esc, HOST_STATUS_TEMPLATE); if (NULL != (row2 = DBfetch(result2))) { zabbix_log(LOG_LEVEL_WARNING, "cannot add discovered host \"%s\":" " template with the same name already exists", row[1]); DBfree_result(result2); goto out; } DBfree_result(result2); sql = zbx_dsprintf(sql, "select hostid,proxy_hostid" " from hosts" " where host='%s'" " and flags<>%d" " and status in (%d,%d)" ZBX_SQL_NODE " order by hostid", host_esc, ZBX_FLAG_DISCOVERY_PROTOTYPE, HOST_STATUS_MONITORED, HOST_STATUS_NOT_MONITORED, DBand_node_local("hostid")); result2 = DBselectN(sql, 1); zbx_free(sql); if (NULL == (row2 = DBfetch(result2))) { hostid = DBget_maxid("hosts"); DBexecute("insert into hosts" " (hostid,proxy_hostid,host,name)" " values" " (" ZBX_FS_UI64 ",%s,'%s','%s')", hostid, DBsql_id_ins(proxy_hostid), host_esc, host_esc); DBadd_interface(hostid, INTERFACE_TYPE_AGENT, 1, row[2], row[3], port); add_discovered_host_groups(hostid, &groupids); } else { ZBX_STR2UINT64(hostid, row2[0]); ZBX_DBROW2UINT64(host_proxy_hostid, row2[1]); if (host_proxy_hostid != proxy_hostid) { DBexecute("update hosts" " set proxy_hostid=%s" " where hostid=" ZBX_FS_UI64, DBsql_id_ins(proxy_hostid), hostid); } DBadd_interface(hostid, INTERFACE_TYPE_AGENT, 1, row[2], row[3], port); } DBfree_result(result2); out: zbx_free(host_esc); } DBfree_result(result); } clean: zbx_vector_uint64_destroy(&groupids); zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name); return hostid; }
/****************************************************************************** * * * Function: main_alerter_loop * * * * Purpose: periodically check table alerts and send notifications if needed * * * * Author: Alexei Vladishev * * * ******************************************************************************/ void main_alerter_loop() { char error[MAX_STRING_LEN], *error_esc; int res; DB_RESULT result; DB_ROW row; DB_ALERT alert; DB_MEDIATYPE mediatype; zbx_setproctitle("%s [connecting to the database]", get_process_type_string(process_type)); DBconnect(ZBX_DB_CONNECT_NORMAL); for (;;) { zbx_setproctitle("%s [sending alerts]", get_process_type_string(process_type)); 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))) { 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]; mediatype.gsm_modem = row[13]; mediatype.username = row[14]; mediatype.passwd = row[15]; alert.retries = atoi(row[16]); *error = '\0'; res = execute_action(&alert, &mediatype, error, sizeof(error)); if (SUCCEED == res) { zabbix_log(LOG_LEVEL_DEBUG, "Alert ID [" ZBX_FS_UI64 "] was sent successfully", alert.alertid); DBexecute("update alerts set status=%d,error='' where alertid=" ZBX_FS_UI64, ALERT_STATUS_SENT, alert.alertid); } else { zabbix_log(LOG_LEVEL_DEBUG, "Error sending alert ID [" ZBX_FS_UI64 "]", alert.alertid); zabbix_syslog("Error sending alert ID [" ZBX_FS_UI64 "]", alert.alertid); error_esc = DBdyn_escape_string_len(error, ALERT_ERROR_LEN); alert.retries++; if (ALERT_MAX_RETRIES > alert.retries) { DBexecute("update alerts set retries=%d,error='%s' where alertid=" ZBX_FS_UI64, alert.retries, error_esc, alert.alertid); } else { DBexecute("update alerts set status=%d,retries=%d,error='%s' where alertid=" ZBX_FS_UI64, ALERT_STATUS_FAILED, alert.retries, error_esc, alert.alertid); } zbx_free(error_esc); } } DBfree_result(result); zbx_sleep_loop(CONFIG_SENDER_FREQUENCY); } }
/****************************************************************************** * * * Function: update_functions * * * * Purpose: re-calculate and updates values of functions related to the item * * * * Parameters: item - item to update functions for * * * * Return value: * * * * Author: Alexei Vladishev * * * * Comments: * * * ******************************************************************************/ void update_functions(DB_ITEM *item, time_t now) { DB_FUNCTION function; DB_RESULT result; DB_ROW row; char value[MAX_STRING_LEN]; char *value_esc, *function_esc, *parameter_esc; char *lastvalue; int ret=SUCCEED; zabbix_log( LOG_LEVEL_DEBUG, "In update_functions(" ZBX_FS_UI64 ")", item->itemid); /* Oracle does'n support this */ /* zbx_snprintf(sql,sizeof(sql),"select function,parameter,itemid,lastvalue from functions where itemid=%d group by function,parameter,itemid order by function,parameter,itemid",item->itemid);*/ result = DBselect("select distinct function,parameter,itemid,lastvalue from functions where itemid=" ZBX_FS_UI64, item->itemid); while((row=DBfetch(result))) { function.function=row[0]; function.parameter=row[1]; ZBX_STR2UINT64(function.itemid,row[2]); /* function.itemid=atoi(row[2]); */ /* It is not required to check lastvalue for NULL here */ lastvalue=row[3]; zabbix_log( LOG_LEVEL_DEBUG, "ItemId:" ZBX_FS_UI64 " Evaluating %s(%s)", function.itemid, function.function, function.parameter); ret = evaluate_function(value, item, function.function, function.parameter, now); if( FAIL == ret) { zabbix_log( LOG_LEVEL_DEBUG, "Evaluation failed for function:%s", function.function); continue; } if (ret == SUCCEED) { /* Update only if lastvalue differs from new one */ if (DBis_null(lastvalue) == SUCCEED || 0 != strcmp(lastvalue, value)) { value_esc = DBdyn_escape_string_len(value, FUNCTION_LASTVALUE_LEN); function_esc = DBdyn_escape_string(function.function); parameter_esc = DBdyn_escape_string(function.parameter); DBexecute("update functions set lastvalue='%s' where itemid=" ZBX_FS_UI64 " and function='%s' and parameter='%s'", value_esc, function.itemid, function_esc, parameter_esc); zbx_free(parameter_esc); zbx_free(function_esc); zbx_free(value_esc); } else zabbix_log( LOG_LEVEL_DEBUG, "Do not update functions, same value"); } } DBfree_result(result); zabbix_log( LOG_LEVEL_DEBUG, "End update_functions()"); }
/****************************************************************************** * * * Function: discovery_register_service * * * * Purpose: register service if one does not exist * * * * Parameters: host ip address * * * * Author: Alexei Vladishev * * * ******************************************************************************/ static void discovery_register_service(DB_DRULE *drule, DB_DCHECK *dcheck, DB_DHOST *dhost, DB_DSERVICE *dservice, const char *ip, const char *dns, int port, int status, int now) { const char *__function_name = "discovery_register_service"; DB_RESULT result; DB_ROW row; char *key_esc, *ip_esc, *dns_esc; zbx_uint64_t dhostid; zabbix_log(LOG_LEVEL_DEBUG, "In %s() ip:'%s' port:%d key:'%s'", __function_name, ip, port, dcheck->key_); key_esc = DBdyn_escape_string_len(dcheck->key_, DSERVICE_KEY_LEN); ip_esc = DBdyn_escape_string_len(ip, INTERFACE_IP_LEN); result = DBselect( "select dserviceid,dhostid,status,lastup,lastdown,value,dns" " from dservices" " where dcheckid=" ZBX_FS_UI64 " and type=%d" " and key_" ZBX_SQL_STRCMP " and ip" ZBX_SQL_STRCMP " and port=%d", dcheck->dcheckid, dcheck->type, ZBX_SQL_STRVAL_EQ(key_esc), ZBX_SQL_STRVAL_EQ(ip_esc), port); if (NULL == (row = DBfetch(result))) { if (DOBJECT_STATUS_UP == status) /* add host only if service is up */ { zabbix_log(LOG_LEVEL_DEBUG, "new service discovered on port %d", port); dservice->dserviceid = DBget_maxid("dservices"); dservice->status = DOBJECT_STATUS_DOWN; dns_esc = DBdyn_escape_string_len(dns, INTERFACE_DNS_LEN); DBexecute("insert into dservices (dserviceid,dhostid,dcheckid,type,key_,ip,dns,port,status)" " values (" ZBX_FS_UI64 "," ZBX_FS_UI64 "," ZBX_FS_UI64 ",%d,'%s','%s','%s',%d,%d)", dservice->dserviceid, dhost->dhostid, dcheck->dcheckid, dcheck->type, key_esc, ip_esc, dns_esc, port, dservice->status); zbx_free(dns_esc); } } else { zabbix_log(LOG_LEVEL_DEBUG, "service is already in database"); ZBX_STR2UINT64(dservice->dserviceid, row[0]); ZBX_STR2UINT64(dhostid, row[1]); dservice->status = atoi(row[2]); dservice->lastup = atoi(row[3]); dservice->lastdown = atoi(row[4]); strscpy(dservice->value, row[5]); if (dhostid != dhost->dhostid) { DBexecute("update dservices" " set dhostid=" ZBX_FS_UI64 " where dhostid=" ZBX_FS_UI64, dhost->dhostid, dhostid); DBexecute("delete from dhosts" " where dhostid=" ZBX_FS_UI64, dhostid); } if (0 != strcmp(row[6], dns)) { dns_esc = DBdyn_escape_string_len(dns, INTERFACE_DNS_LEN); DBexecute("update dservices" " set dns='%s'" " where dserviceid=" ZBX_FS_UI64, dns_esc, dservice->dserviceid); zbx_free(dns_esc); } } DBfree_result(result); zbx_free(ip_esc); zbx_free(key_esc); zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name); }
/****************************************************************************** * * * Function: main_alerter_loop * * * * Purpose: periodically check table alerts and send notifications if needed * * * * Author: Alexei Vladishev * * * ******************************************************************************/ ZBX_THREAD_ENTRY(alerter_thread, args) { char error[MAX_STRING_LEN], *error_esc; int res, alerts_success, alerts_fail; double sec; DB_RESULT result; DB_ROW row; DB_ALERT alert; DB_MEDIATYPE mediatype; process_type = ((zbx_thread_args_t *)args)->process_type; server_num = ((zbx_thread_args_t *)args)->server_num; process_num = ((zbx_thread_args_t *)args)->process_num; zabbix_log(LOG_LEVEL_INFORMATION, "%s #%d started [%s #%d]", get_daemon_type_string(daemon_type), server_num, get_process_type_string(process_type), process_num); zbx_setproctitle("%s [connecting to the database]", get_process_type_string(process_type)); DBconnect(ZBX_DB_CONNECT_NORMAL); for (;;) { zbx_setproctitle("%s [sending alerts]", get_process_type_string(process_type)); sec = zbx_time(); alerts_success = alerts_fail = 0; 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,mt.smtp_port,mt.smtp_security," "mt.smtp_verify_peer,mt.smtp_verify_host,mt.smtp_authentication,a.retries" " from alerts a,media_type mt" " where a.mediatypeid=mt.mediatypeid" " and a.status=%d" " and a.alerttype=%d" " order by a.alertid", ALERT_STATUS_NOT_SENT, ALERT_TYPE_MESSAGE); while (NULL != (row = DBfetch(result))) { ZBX_STR2UINT64(alert.alertid, row[0]); ZBX_STR2UINT64(alert.mediatypeid, 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]; mediatype.gsm_modem = row[13]; mediatype.username = row[14]; mediatype.passwd = row[15]; mediatype.smtp_port = (unsigned short)atoi(row[16]); ZBX_STR2UCHAR(mediatype.smtp_security, row[17]); ZBX_STR2UCHAR(mediatype.smtp_verify_peer, row[18]); ZBX_STR2UCHAR(mediatype.smtp_verify_host, row[19]); ZBX_STR2UCHAR(mediatype.smtp_authentication, row[20]); alert.retries = atoi(row[21]); *error = '\0'; res = execute_action(&alert, &mediatype, error, sizeof(error)); if (SUCCEED == res) { zabbix_log(LOG_LEVEL_DEBUG, "alert ID [" ZBX_FS_UI64 "] was sent successfully", alert.alertid); DBexecute("update alerts set status=%d,error='' where alertid=" ZBX_FS_UI64, ALERT_STATUS_SENT, alert.alertid); alerts_success++; } else { zabbix_log(LOG_LEVEL_DEBUG, "error sending alert ID [" ZBX_FS_UI64 "]", alert.alertid); error_esc = DBdyn_escape_string_len(error, ALERT_ERROR_LEN); alert.retries++; if (ALERT_MAX_RETRIES > alert.retries) { DBexecute("update alerts set retries=%d,error='%s' where alertid=" ZBX_FS_UI64, alert.retries, error_esc, alert.alertid); } else { DBexecute("update alerts set status=%d,retries=%d,error='%s' where alertid=" ZBX_FS_UI64, ALERT_STATUS_FAILED, alert.retries, error_esc, alert.alertid); } zbx_free(error_esc); alerts_fail++; } } DBfree_result(result); sec = zbx_time() - sec; zbx_setproctitle("%s [sent alerts: %d success, %d fail in " ZBX_FS_DBL " sec, idle %d sec]", get_process_type_string(process_type), alerts_success, alerts_fail, sec, CONFIG_SENDER_FREQUENCY); zbx_sleep_loop(CONFIG_SENDER_FREQUENCY); } }