static int get_minnextcheck(int now) { DB_RESULT result; DB_ROW row; int res = FAIL; result = DBselect( "select count(*),min(nextcheck)" " from drules" " where proxy_hostid is null" " and status=%d" " and " ZBX_SQL_MOD(druleid,%d) "=%d" DB_NODE, DRULE_STATUS_MONITORED, CONFIG_DISCOVERER_FORKS, process_num - 1, DBnode_local("druleid")); row = DBfetch(result); if (NULL == row || DBis_null(row[0]) == SUCCEED || DBis_null(row[1]) == SUCCEED) zabbix_log(LOG_LEVEL_DEBUG, "get_minnextcheck(): no items to update"); else if (0 != atoi(row[0])) res = atoi(row[1]); DBfree_result(result); return res; }
/****************************************************************************** * * * Function: get_minnextcheck * * * * Purpose: calculate when we have to process earliest httptest * * * * Parameters: now - current timestamp (not used) * * * * Return value: timestamp of earliest check or -1 if not found * * * * Author: Alexei Vladishev * * * * Comments: * * * ******************************************************************************/ static int get_minnextcheck(int now) { DB_RESULT result; DB_ROW row; int res; result = DBselect( "select min(t.nextcheck)" " from httptest t,applications a,hosts h" " where t.applicationid=a.applicationid" " and a.hostid=h.hostid" " and " ZBX_SQL_MOD(t.httptestid,%d) "=%d" " and t.status=%d" " and h.proxy_hostid is null" " and h.status=%d" " and (h.maintenance_status=%d or h.maintenance_type=%d)" DB_NODE, CONFIG_HTTPPOLLER_FORKS, process_num - 1, HTTPTEST_STATUS_MONITORED, HOST_STATUS_MONITORED, HOST_MAINTENANCE_STATUS_OFF, MAINTENANCE_TYPE_NORMAL, DBnode_local("t.httptestid")); if (NULL == (row = DBfetch(result)) || SUCCEED == DBis_null(row[0])) { zabbix_log(LOG_LEVEL_DEBUG, "No httptests to process in get_minnextcheck."); res = FAIL; } else res = atoi(row[0]); DBfree_result(result); return res; }
/****************************************************************************** * * * Function: get_proxy_id * * * * Purpose: * * * * Parameters: * * * * Return value: SUCCEED - processed successfully * * FAIL - an error occurred * * * * Author: Aleksander Vladishev * * * * Comments: * * * ******************************************************************************/ int get_proxy_id(struct zbx_json_parse *jp, zbx_uint64_t *hostid) { DB_RESULT result; DB_ROW row; char host[HOST_HOST_LEN_MAX], host_esc[MAX_STRING_LEN]; int res = FAIL; if (SUCCEED == zbx_json_value_by_name(jp, ZBX_PROTO_TAG_HOST, host, sizeof(host))) { DBescape_string(host, host_esc, sizeof(host_esc)); result = DBselect("select hostid from hosts where host='%s'" " and status in (%d)" DB_NODE, host_esc, HOST_STATUS_PROXY, DBnode_local("hostid")); if (NULL != (row = DBfetch(result)) && FAIL == DBis_null(row[0])) { *hostid = zbx_atoui64(row[0]); res = SUCCEED; } else zabbix_log(LOG_LEVEL_WARNING, "Unknown proxy \"%s\"", host); DBfree_result(result); } else { zabbix_log(LOG_LEVEL_WARNING, "Incorrect data. %s", zbx_json_strerror()); zabbix_syslog("Incorrect data. %s", zbx_json_strerror()); } return res; }
static int housekeeping_events(int now) { int event_history; DB_RESULT result; DB_ROW row1; int res = SUCCEED; zabbix_log( LOG_LEVEL_DEBUG, "In housekeeping_events(%d)", now); result = DBselect("select event_history from config"); row1=DBfetch(result); if(!row1 || DBis_null(row1[0])==SUCCEED) { zabbix_log( LOG_LEVEL_ERR, "No records in table 'config'."); res = FAIL; } else { event_history=atoi(row1[0]); DBexecute ("delete from events where clock < %d", now-24*3600*event_history); } DBfree_result(result); return res; }
static int housekeeping_alerts(int now) { int alert_history; DB_RESULT result; DB_ROW row; int res = SUCCEED; int deleted; zabbix_log( LOG_LEVEL_DEBUG, "In housekeeping_alerts(%d)", now); result = DBselect("select alert_history from config"); row=DBfetch(result); if(!row || DBis_null(row[0])==SUCCEED) { zabbix_log( LOG_LEVEL_ERR, "No records in table 'config'."); res = FAIL; } else { alert_history=atoi(row[0]); deleted = DBexecute("delete from alerts where clock<%d", now-24*3600*alert_history); zabbix_log( LOG_LEVEL_DEBUG, "Deleted [%ld] records from table [alerts]", deleted); } DBfree_result(result); return res; }
/****************************************************************************** * * * Function: delete_history * * * * Purpose: remove outdated information from historical table * * * * Parameters: now - current timestamp * * * * Return value: number of rows deleted * * * * Author: Alexei Vladishev * * * * Comments: * * * ******************************************************************************/ static int delete_history(const char *table, zbx_uint64_t itemid, int keep_history, int now) { const char *__function_name = "delete_history"; DB_RESULT result; DB_ROW row; int min_clock, deleted; zabbix_log(LOG_LEVEL_DEBUG, "In %s() table:'%s' itemid:" ZBX_FS_UI64 " keep_history:%d now:%d", __function_name, table, itemid, keep_history, now); result = DBselect("select min(clock) from %s where itemid=" ZBX_FS_UI64, table, itemid); if (NULL == (row = DBfetch(result)) || SUCCEED == DBis_null(row[0])) { DBfree_result(result); return 0; } min_clock = atoi(row[0]); min_clock = MIN(now - keep_history * SEC_PER_DAY, min_clock + 4 * CONFIG_HOUSEKEEPING_FREQUENCY * SEC_PER_HOUR); DBfree_result(result); deleted = DBexecute("delete from %s where itemid=" ZBX_FS_UI64 " and clock<%d", table, itemid, min_clock); zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%d", __function_name, deleted); return deleted; }
/****************************************************************************** * * * Function: register_host * * * * Purpose: register host if one does not exist * * * * Parameters: host ip address * * * * Return value: dhostid or 0 if we didn't add host * * * * Author: Alexei Vladishev * * * * Comments: * * * ******************************************************************************/ static void register_host(DB_DHOST *host,DB_DCHECK *check, zbx_uint64_t druleid, char *ip) { DB_RESULT result; DB_ROW row; char hostname[MAX_STRING_LEN], hostname_esc[MAX_STRING_LEN]; assert(host); assert(check); assert(ip); zabbix_log(LOG_LEVEL_DEBUG, "In register_host(ip:%s)", ip); host->dhostid=0; result = DBselect("select dhostid,druleid,ip,status,lastup,lastdown from dhosts where ip='%s'", ip); row=DBfetch(result); if(!row || DBis_null(row[0])==SUCCEED) { /* Add host only if service is up */ if(check->status == DOBJECT_STATUS_UP) { alarm(CONFIG_TIMEOUT); zbx_gethost_by_ip(ip, hostname, sizeof(hostname)); alarm(0); if (hostname[0] != '\0') DBescape_string(hostname, hostname_esc, sizeof(hostname_esc)); else hostname_esc[0] = '\0'; zabbix_log(LOG_LEVEL_DEBUG, "New host discovered at %s (%s)", ip, hostname); host->dhostid = DBget_maxid("dhosts","dhostid"); DBexecute("insert into dhosts (dhostid, druleid, dns, ip) values (" ZBX_FS_UI64 "," ZBX_FS_UI64 ", '%s','%s')", host->dhostid, druleid, hostname_esc, ip); host->druleid = druleid; strscpy(host->ip,ip); host->status = 0; host->lastup = 0; host->lastdown = 0; } } else { zabbix_log(LOG_LEVEL_DEBUG, "Host is already in database"); ZBX_STR2UINT64(host->dhostid,row[0]); ZBX_STR2UINT64(host->druleid,row[1]); strscpy(host->ip, row[2]); host->status = atoi(row[3]); host->lastup = atoi(row[4]); host->lastdown = atoi(row[5]); } DBfree_result(result); zabbix_log(LOG_LEVEL_DEBUG, "End register_host()"); }
/****************************************************************************** * * * Function: get_host_permission * * * * Purpose: Return user permissions for access to the host * * * * Parameters: * * * * Return value: PERM_DENY - if host or user not found, * * or permission otherwise * * * * Author: * * * * Comments: * * * ******************************************************************************/ static int get_host_permission(zbx_uint64_t userid, zbx_uint64_t hostid) { const char *__function_name = "get_host_permission"; DB_RESULT result; DB_ROW row; int user_type = -1, perm = PERM_DENY; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); result = DBselect("select type from users where userid=" ZBX_FS_UI64, userid); if (NULL != (row = DBfetch(result)) && FAIL == DBis_null(row[0])) user_type = atoi(row[0]); DBfree_result(result); if (-1 == user_type) goto out; if (USER_TYPE_SUPER_ADMIN == user_type) { perm = PERM_MAX; goto out; } result = DBselect( "select min(r.permission)" " from rights r,hosts_groups hg,users_groups ug" " where r.groupid=ug.usrgrpid" " and r.id=hg.groupid" " and hg.hostid=" ZBX_FS_UI64 " and ug.userid=" ZBX_FS_UI64, hostid, userid); if (NULL != (row = DBfetch(result)) && FAIL == DBis_null(row[0])) perm = atoi(row[0]); DBfree_result(result); out: zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_permission_string(perm)); return perm; }
static int housekeeping_events(int now) { int event_history; DB_RESULT result; DB_RESULT result2; DB_ROW row1; DB_ROW row2; zbx_uint64_t eventid; int res = SUCCEED; zabbix_log( LOG_LEVEL_DEBUG, "In housekeeping_events(%d)", now); result = DBselect("select event_history from config"); row1=DBfetch(result); if(!row1 || DBis_null(row1[0])==SUCCEED) { zabbix_log( LOG_LEVEL_ERR, "No records in table 'config'."); res = FAIL; } else { event_history=atoi(row1[0]); result2 = DBselect("select eventid from events where clock<%d", now-24*3600*event_history); while((row2=DBfetch(result2))) { ZBX_STR2UINT64(eventid,row2[0]); DBexecute("delete from acknowledges where eventid=" ZBX_FS_UI64, eventid); DBexecute("delete from events where eventid=" ZBX_FS_UI64, eventid); } DBfree_result(result2); } DBfree_result(result); return res; }
/****************************************************************************** * * * Function: check_perm2system * * * * Purpose: Checking user permissions to access system. * * * * Parameters: userid - user ID * * * * Return value: SUCCEED - prermission is positive, FAIL - otherwise * * * * Author: * * * * Comments: * * * ******************************************************************************/ static int check_perm2system(zbx_uint64_t userid) { DB_RESULT result; DB_ROW row; int res = SUCCEED; result = DBselect( "select count(g.usrgrpid) from usrgrp g,users_groups ug where ug.userid=" ZBX_FS_UI64 " and g.usrgrpid = ug.usrgrpid and g.users_status=%d", userid, GROUP_STATUS_DISABLED); if (NULL != (row = DBfetch(result)) && SUCCEED != DBis_null(row[0]) && atoi(row[0]) > 0) res = FAIL; DBfree_result(result); return res; }
/****************************************************************************** * * * Function: housekeeping_process_rule * * * * Purpose: removes old records from a table according to the specified rule * * * * Parameters: now - [IN] the current time in seconds * * rule - [IN/OUT] the housekeeping rule specifying table to * * clean and the required data (fields, filters, time) * * * * Return value: the number of deleted records * * * * Author: Andris Zeila * * * ******************************************************************************/ static int housekeeping_process_rule(int now, zbx_hk_rule_t *rule) { const char *__function_name = "housekeeping_process_rule"; DB_RESULT result; DB_ROW row; int keep_from, deleted = 0; int rc; zabbix_log(LOG_LEVEL_DEBUG, "In %s() table:'%s' filter:'%s' min_clock:%d now:%d", __function_name, rule->table, rule->filter, rule->min_clock, now); /* initialize min_clock with the oldest record timestamp from database */ if (0 == rule->min_clock) { result = DBselect("select min(clock) from %s%s%s", rule->table, ('\0' != *rule->filter ? " where " : ""), rule->filter); if (NULL != (row = DBfetch(result)) && SUCCEED != DBis_null(row[0])) rule->min_clock = atoi(row[0]); else rule->min_clock = now; DBfree_result(result); } /* Delete the old records from database. Don't remove more than 4 x housekeeping */ /* periods worth of data to prevent database stalling. */ keep_from = now - *rule->phistory * SEC_PER_DAY; if (keep_from > rule->min_clock) { rule->min_clock = MIN(keep_from, rule->min_clock + HK_MAX_DELETE_PERIODS * CONFIG_HOUSEKEEPING_FREQUENCY * SEC_PER_HOUR); rc = DBexecute("delete from %s where %s%sclock<%d", rule->table, rule->filter, ('\0' != *rule->filter ? " and " : ""), rule->min_clock); if (ZBX_DB_OK <= rc) deleted = rc; } zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%d", __function_name, deleted); return deleted; }
/****************************************************************************** * * * Function: is_master_node * * * * Purpose: * * * * Parameters: * * * * Return value: SUCCEED - master_nodeid is a master node of current_nodeid * * FAIL - otherwise * * * * Author: Alexander Vladishev * * * * Comments: * * * ******************************************************************************/ int is_master_node(int current_nodeid, int master_nodeid) { DB_RESULT result; DB_ROW row; int res = FAIL; result = DBselect("select masterid from nodes where nodeid=%d", current_nodeid); if (NULL != (row = DBfetch(result))) { current_nodeid = (SUCCEED == DBis_null(row[0])) ? 0 : atoi(row[0]); if (current_nodeid == master_nodeid) res = SUCCEED; else if (0 != current_nodeid) res = is_master_node(current_nodeid, master_nodeid); } DBfree_result(result); return res; }
/****************************************************************************** * * * Function: delete_history * * * * Purpose: remove outdated information from historical table * * * * Parameters: now - current timestamp * * * * Return value: number of rows deleted * * * * Author: Alexei Vladishev * * * * Comments: * * * ******************************************************************************/ static int delete_history(char *table, zbx_uint64_t itemid, int keep_history, int now) { DB_RESULT result; DB_ROW row; int min_clock; zabbix_log( LOG_LEVEL_DEBUG, "In delete_history(%s," ZBX_FS_UI64 "," ZBX_FS_UI64 ",%d)", table, itemid, keep_history, now); result = DBselect("select min(clock) from %s where itemid=" ZBX_FS_UI64, table, itemid); row=DBfetch(result); if(!row || DBis_null(row[0]) == SUCCEED) { DBfree_result(result); return 0; } min_clock = atoi(row[0]); DBfree_result(result); /* zabbix_log( LOG_LEVEL_DEBUG, "Now %d keep_history %d Itemid " ZBX_FS_UI64 " min %d new min %d", now, keep_history, itemid, min_clock, MIN(now-24*3600*keep_history, min_clock+4*3600*CONFIG_HOUSEKEEPING_FREQUENCY));*/ return DBexecute("delete from %s where itemid=" ZBX_FS_UI64 " and clock<%d", table, itemid, MIN(now-24*3600*keep_history, min_clock+4*3600*CONFIG_HOUSEKEEPING_FREQUENCY) ); }
/****************************************************************************** * * * Function: add_host_event * * * * Purpose: generate host UP/DOWN event if required * * * * Parameters: * * * * Return value: * * * * Author: Alexei Vladishev * * * * Comments: * * * ******************************************************************************/ static void add_host_event(char *ip) { DB_RESULT result; DB_ROW row; DB_EVENT event; int now; int status; zbx_uint64_t dhostid; assert(ip); zabbix_log(LOG_LEVEL_DEBUG, "In add_host_event(ip:%s)", ip); result = DBselect("select status,dhostid from dhosts where ip='%s'", ip); row=DBfetch(result); if(row && DBis_null(row[0])!=SUCCEED) { now = time(NULL); status = atoi(row[0]); ZBX_STR2UINT64(dhostid, row[1]); memset(&event,0,sizeof(DB_EVENT)); event.eventid = 0; event.source = EVENT_SOURCE_DISCOVERY; event.object = EVENT_OBJECT_DHOST; event.objectid = dhostid; event.clock = now; event.value = status; event.acknowledged = 0; process_event(&event); } DBfree_result(result); zabbix_log(LOG_LEVEL_DEBUG, "End add_host_event()"); }
/****************************************************************************** * * * Function: send_history_last_id * * * * Purpose: send list of last historical tables IDs * * * * Parameters: sock - opened socket of node-node connection * * record * * * * Return value: SUCCEED - sent successfully * * FAIL - an error occurred * * * * Author: Alexander Vladishev * * * * Comments: * * * ******************************************************************************/ int send_history_last_id(zbx_sock_t *sock, const char *data) { DB_RESULT result; DB_ROW row; const char *r; const ZBX_TABLE *table; size_t buffer_offset; int sender_nodeid = (-1), nodeid = (-1), res; zabbix_log(LOG_LEVEL_DEBUG, "In send_history_last_id()"); buffer_alloc = 320; buffer = zbx_malloc(buffer, buffer_alloc); r = data; if (NULL == r) goto error; zbx_get_next_field(&r, &buffer, &buffer_alloc, ZBX_DM_DELIMITER); /* constant 'ZBX_GET_HISTORY_LAST_ID' */ if (NULL == r) goto error; zbx_get_next_field(&r, &buffer, &buffer_alloc, ZBX_DM_DELIMITER); /* sender_nodeid */ sender_nodeid = atoi(buffer); if (NULL == r) goto error; if (FAIL == is_direct_slave_node(sender_nodeid)) { zabbix_log(LOG_LEVEL_ERR, "NODE %d: Received data from node %d that is not a direct slave node [%s]", CONFIG_NODEID, sender_nodeid, data); goto fail; } zbx_get_next_field(&r, &buffer, &buffer_alloc, '\n'); /* nodeid */ nodeid = atoi(buffer); if (NULL == r) goto error; if (FAIL == is_slave_node(CONFIG_NODEID, nodeid)) { zabbix_log(LOG_LEVEL_ERR, "NODE %d: Received data for unknown slave node %d [%s]", CONFIG_NODEID, nodeid, data); goto fail; } zbx_get_next_field(&r, &buffer, &buffer_alloc, ZBX_DM_DELIMITER); /* table name */ if (NULL == (table = DBget_table(buffer))) goto error; if (0 == (table->flags & ZBX_HISTORY)) goto error; if (NULL == r) goto error; zbx_get_next_field(&r, &buffer, &buffer_alloc, ZBX_DM_DELIMITER); /* field name */ if (0 != strcmp(buffer, table->recid)) goto error; buffer_offset= 0; zbx_snprintf_alloc(&buffer, &buffer_alloc, &buffer_offset, "select max(%s)" " from %s" " where 1=1" DB_NODE, table->recid, table->table, DBnode(table->recid, nodeid)); buffer_offset= 0; result = DBselect("%s", buffer); if (NULL != (row = DBfetch(result))) zbx_strcpy_alloc(&buffer, &buffer_alloc, &buffer_offset, SUCCEED == DBis_null(row[0]) ? "0" : row[0]); DBfree_result(result); if (buffer_offset == 0) goto error; alarm(CONFIG_TIMEOUT); res = send_data_to_node(sender_nodeid, sock, buffer); alarm(0); zbx_free(buffer); 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, data); fail: buffer_offset= 0; zbx_strcpy_alloc(&buffer, &buffer_alloc, &buffer_offset, "FAIL"); alarm(CONFIG_TIMEOUT); res = send_data_to_node(sender_nodeid, sock, buffer); alarm(0); zbx_free(buffer); return FAIL; }
/****************************************************************************** * * * Function: check_trigger_condition * * * * Purpose: check if event matches single condition * * * * Parameters: event - trigger event to check * * (event->source == EVENT_SOURCE_TRIGGERS) * * condition - condition for matching * * * * Return value: SUCCEED - matches, FAIL - otherwise * * * * Author: Alexei Vladishev * * * * Comments: * * * ******************************************************************************/ static int check_trigger_condition(DB_EVENT *event, DB_CONDITION *condition) { const char *__function_name = "check_trigger_condition"; DB_RESULT result; DB_ROW row; zbx_uint64_t condition_value; int nodeid; char *tmp_str = NULL; int ret = FAIL; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); if (condition->conditiontype == CONDITION_TYPE_HOST_GROUP) { ZBX_STR2UINT64(condition_value, condition->value); result = DBselect( "select distinct hg.groupid" " from hosts_groups hg,hosts h,items i,functions f,triggers t" " where hg.hostid=h.hostid" " and h.hostid=i.hostid" " and i.itemid=f.itemid" " and f.triggerid=t.triggerid" " and t.triggerid=" ZBX_FS_UI64 " and hg.groupid=" ZBX_FS_UI64, event->objectid, condition_value); switch (condition->operator) { case CONDITION_OPERATOR_EQUAL: if (NULL != DBfetch(result)) ret = SUCCEED; break; case CONDITION_OPERATOR_NOT_EQUAL: if (NULL == DBfetch(result)) ret = SUCCEED; break; default: zabbix_log(LOG_LEVEL_ERR, "Unsupported operator [%d] for condition id [" ZBX_FS_UI64 "]", condition->operator, condition->conditionid); } DBfree_result(result); } else if (condition->conditiontype == CONDITION_TYPE_HOST_TEMPLATE) { zbx_uint64_t hostid, triggerid; ZBX_STR2UINT64(condition_value, condition->value); switch (condition->operator) { case CONDITION_OPERATOR_EQUAL: case CONDITION_OPERATOR_NOT_EQUAL: triggerid = event->objectid; do { result = DBselect( "select distinct i.hostid,t.templateid" " from items i,functions f,triggers t" " where i.itemid=f.itemid" " and f.triggerid=t.templateid" " and t.triggerid=" ZBX_FS_UI64, triggerid); if (NULL != (row = DBfetch(result))) { ZBX_STR2UINT64(hostid, row[0]); ZBX_STR2UINT64(triggerid, row[1]); if (hostid == condition_value) { ret = SUCCEED; break; } } else triggerid = 0; DBfree_result(result); } while (SUCCEED != ret && 0 != triggerid); if (CONDITION_OPERATOR_NOT_EQUAL == condition->operator) ret = (SUCCEED == ret) ? FAIL : SUCCEED; break; default: zabbix_log(LOG_LEVEL_ERR, "Unsupported operator [%d] for condition id [" ZBX_FS_UI64 "]", condition->operator, condition->conditionid); } } else if (condition->conditiontype == CONDITION_TYPE_HOST) { ZBX_STR2UINT64(condition_value, condition->value); switch (condition->operator) { case CONDITION_OPERATOR_EQUAL: case CONDITION_OPERATOR_NOT_EQUAL: result = DBselect( "select distinct i.hostid" " from items i,functions f,triggers t" " where i.itemid=f.itemid" " and f.triggerid=t.triggerid" " and t.triggerid=" ZBX_FS_UI64 " and i.hostid=" ZBX_FS_UI64, event->objectid, condition_value); if (NULL != DBfetch(result)) ret = SUCCEED; DBfree_result(result); if (CONDITION_OPERATOR_NOT_EQUAL == condition->operator) ret = (SUCCEED == ret) ? FAIL : SUCCEED; break; default: zabbix_log(LOG_LEVEL_ERR, "Unsupported operator [%d] for condition id [" ZBX_FS_UI64 "]", condition->operator, condition->conditionid); } } else if (condition->conditiontype == CONDITION_TYPE_TRIGGER) { zbx_uint64_t triggerid; ZBX_STR2UINT64(condition_value, condition->value); switch (condition->operator) { case CONDITION_OPERATOR_EQUAL: case CONDITION_OPERATOR_NOT_EQUAL: if (event->objectid == condition_value) ret = SUCCEED; /* Processing of templated triggers */ else { for (triggerid = event->objectid; 0 != triggerid && FAIL == ret;) { result = DBselect( "select templateid" " from triggers" " where triggerid=" ZBX_FS_UI64, triggerid); if (NULL == (row = DBfetch(result))) triggerid = 0; else { ZBX_STR2UINT64(triggerid, row[0]); if (triggerid == condition_value) ret = SUCCEED; } DBfree_result(result); } } if (CONDITION_OPERATOR_NOT_EQUAL == condition->operator) ret = (SUCCEED == ret) ? FAIL : SUCCEED; break; default: zabbix_log(LOG_LEVEL_ERR, "Unsupported operator [%d] for condition id [" ZBX_FS_UI64 "]", condition->operator, condition->conditionid); } } else if (condition->conditiontype == CONDITION_TYPE_TRIGGER_NAME) { tmp_str = zbx_strdup(tmp_str, event->trigger.description); substitute_simple_macros(event, NULL, NULL, NULL, NULL, &tmp_str, MACRO_TYPE_TRIGGER_DESCRIPTION, NULL, 0); switch (condition->operator) { case CONDITION_OPERATOR_LIKE: if (NULL != strstr(tmp_str, condition->value)) ret = SUCCEED; break; case CONDITION_OPERATOR_NOT_LIKE: if (NULL == strstr(tmp_str, condition->value)) ret = SUCCEED; break; default: zabbix_log(LOG_LEVEL_ERR, "Unsupported operator [%d] for condition id [" ZBX_FS_UI64 "]", condition->operator, condition->conditionid); } zbx_free(tmp_str); } else if (condition->conditiontype == CONDITION_TYPE_TRIGGER_SEVERITY) { condition_value = atoi(condition->value); switch (condition->operator) { case CONDITION_OPERATOR_EQUAL: if (event->trigger.priority == condition_value) ret = SUCCEED; break; case CONDITION_OPERATOR_NOT_EQUAL: if (event->trigger.priority != condition_value) ret = SUCCEED; break; case CONDITION_OPERATOR_MORE_EQUAL: if (event->trigger.priority >= condition_value) ret = SUCCEED; break; case CONDITION_OPERATOR_LESS_EQUAL: if (event->trigger.priority <= condition_value) ret = SUCCEED; break; default: zabbix_log(LOG_LEVEL_ERR, "Unsupported operator [%d] for condition id [" ZBX_FS_UI64 "]", condition->operator, condition->conditionid); } } else if (condition->conditiontype == CONDITION_TYPE_TRIGGER_VALUE) { condition_value = atoi(condition->value); switch (condition->operator) { case CONDITION_OPERATOR_EQUAL: if (event->value == condition_value) ret = SUCCEED; break; default: zabbix_log(LOG_LEVEL_ERR, "Unsupported operator [%d] for condition id [" ZBX_FS_UI64 "]", condition->operator, condition->conditionid); } } else if (condition->conditiontype == CONDITION_TYPE_TIME_PERIOD) { switch (condition->operator) { case CONDITION_OPERATOR_IN: if (SUCCEED == check_time_period(condition->value, (time_t)NULL)) ret = SUCCEED; break; case CONDITION_OPERATOR_NOT_IN: if (FAIL == check_time_period(condition->value, (time_t)NULL)) ret = SUCCEED; break; default: zabbix_log(LOG_LEVEL_ERR, "Unsupported operator [%d] for condition id [" ZBX_FS_UI64 "]", condition->operator, condition->conditionid); } } else if (condition->conditiontype == CONDITION_TYPE_MAINTENANCE) { switch (condition->operator) { case CONDITION_OPERATOR_IN: result = DBselect( "select count(*)" " from hosts h,items i,functions f,triggers t" " where h.hostid=i.hostid" " and h.maintenance_status=%d" " and i.itemid=f.itemid" " and f.triggerid=t.triggerid" " and t.triggerid=" ZBX_FS_UI64, HOST_MAINTENANCE_STATUS_ON, event->objectid); if (NULL != (row = DBfetch(result)) && FAIL == DBis_null(row[0]) && 0 != atoi(row[0])) ret = SUCCEED; DBfree_result(result); break; case CONDITION_OPERATOR_NOT_IN: result = DBselect( "select count(*)" " from hosts h,items i,functions f,triggers t" " where h.hostid=i.hostid" " and h.maintenance_status=%d" " and i.itemid=f.itemid" " and f.triggerid=t.triggerid" " and t.triggerid=" ZBX_FS_UI64, HOST_MAINTENANCE_STATUS_OFF, event->objectid); if (NULL != (row = DBfetch(result)) && FAIL == DBis_null(row[0]) && 0 != atoi(row[0])) ret = SUCCEED; DBfree_result(result); break; default: zabbix_log(LOG_LEVEL_ERR, "Unsupported operator [%d] for condition id [" ZBX_FS_UI64 "]", condition->operator, condition->conditionid); } } else if (condition->conditiontype == CONDITION_TYPE_NODE) { nodeid = get_nodeid_by_id(event->objectid); condition_value = atoi(condition->value); switch (condition->operator) { case CONDITION_OPERATOR_EQUAL: if (nodeid == condition_value) ret = SUCCEED; break; case CONDITION_OPERATOR_NOT_EQUAL: if (nodeid != condition_value) ret = SUCCEED; break; default: zabbix_log(LOG_LEVEL_ERR, "Unsupported operator [%d] for condition id [" ZBX_FS_UI64 "]", condition->operator, condition->conditionid); } } else if (condition->conditiontype == CONDITION_TYPE_EVENT_ACKNOWLEDGED) { result = DBselect( "select acknowledged" " from events" " where acknowledged=%d" " and eventid=" ZBX_FS_UI64, atoi(condition->value), event->eventid); switch (condition->operator) { case CONDITION_OPERATOR_EQUAL: if (NULL != (row = DBfetch(result))) ret = SUCCEED; break; default: zabbix_log(LOG_LEVEL_ERR, "Unsupported operator [%d] for condition id [" ZBX_FS_UI64 "]", condition->operator, condition->conditionid); } DBfree_result(result); } else if (condition->conditiontype == CONDITION_TYPE_APPLICATION) { result = DBselect( "select distinct a.name" " from applications a,items_applications i,functions f,triggers t" " where a.applicationid=i.applicationid" " and i.itemid=f.itemid" " and f.triggerid=t.triggerid" " and t.triggerid=" ZBX_FS_UI64, event->objectid); switch (condition->operator) { case CONDITION_OPERATOR_EQUAL: while (NULL != (row = DBfetch(result))) { if (0 == strcmp(row[0], condition->value)) { ret = SUCCEED; break; } } break; case CONDITION_OPERATOR_LIKE: while (NULL != (row = DBfetch(result))) { if (NULL != strstr(row[0], condition->value)) { ret = SUCCEED; break; } } break; case CONDITION_OPERATOR_NOT_LIKE: ret = SUCCEED; while (NULL != (row = DBfetch(result))) { if (NULL != strstr(row[0], condition->value)) { ret = FAIL; break; } } break; default: zabbix_log(LOG_LEVEL_ERR, "Unsupported operator [%d] for condition id [" ZBX_FS_UI64 "]", condition->operator, condition->conditionid); } DBfree_result(result); } else { zabbix_log(LOG_LEVEL_ERR, "Unsupported condition type [%d] for condition id [" ZBX_FS_UI64 "]", condition->conditiontype, condition->conditionid); } zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret)); return ret; }
static void execute_operations(DB_ESCALATION *escalation, DB_EVENT *event, DB_ACTION *action) { const char *__function_name = "execute_operations"; DB_RESULT result; DB_ROW row; DB_OPERATION operation; int esc_period = 0, operations = 0; ZBX_USER_MSG *user_msg = NULL, *p; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); if (0 == action->esc_period) { result = DBselect( "select o.operationid,o.operationtype,o.esc_period,o.evaltype," "m.operationid,m.default_msg,subject,message,mediatypeid" " from operations o" " left join opmessage m" " on m.operationid=o.operationid" " where o.actionid=" ZBX_FS_UI64 " and o.operationtype in (%d,%d)", action->actionid, OPERATION_TYPE_MESSAGE, OPERATION_TYPE_COMMAND); } else { escalation->esc_step++; result = DBselect( "select o.operationid,o.operationtype,o.esc_period,o.evaltype," "m.operationid,m.default_msg,subject,message,mediatypeid" " from operations o" " left join opmessage m" " on m.operationid=o.operationid" " where o.actionid=" ZBX_FS_UI64 " and o.operationtype in (%d,%d)" " and o.esc_step_from<=%d" " and (o.esc_step_to=0 or o.esc_step_to>=%d)", action->actionid, OPERATION_TYPE_MESSAGE, OPERATION_TYPE_COMMAND, escalation->esc_step, escalation->esc_step); } while (NULL != (row = DBfetch(result))) { memset(&operation, 0, sizeof(operation)); ZBX_STR2UINT64(operation.operationid, row[0]); operation.actionid = action->actionid; operation.operationtype = atoi(row[1]); operation.esc_period = atoi(row[2]); operation.evaltype = (unsigned char)atoi(row[3]); if (SUCCEED == check_operation_conditions(event, operation.operationid, operation.evaltype)) { unsigned char default_msg; char *subject, *message; zbx_uint64_t mediatypeid; zabbix_log(LOG_LEVEL_DEBUG, "Conditions match our event. Execute operation."); if (0 == esc_period || esc_period > operation.esc_period) esc_period = operation.esc_period; switch (operation.operationtype) { case OPERATION_TYPE_MESSAGE: if (SUCCEED == DBis_null(row[4])) break; default_msg = (unsigned char)atoi(row[5]); ZBX_DBROW2UINT64(mediatypeid, row[8]); if (0 == default_msg) { subject = row[6]; message = row[7]; } else { subject = action->shortdata; message = action->longdata; } add_object_msg(operation.operationid, mediatypeid, &user_msg, subject, message, event->source, event->objectid); break; case OPERATION_TYPE_COMMAND: execute_commands(event, action->actionid, operation.operationid, escalation->esc_step); break; } } else zabbix_log(LOG_LEVEL_DEBUG, "Conditions do not match our event. Do not execute operation."); 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->mediatypeid, p->subject, p->message); zbx_free(p->subject); zbx_free(p->message); zbx_free(p); } if (0 == action->esc_period) { escalation->status = (action->recovery_msg == 1) ? ESCALATION_STATUS_SLEEP : 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 = (action->recovery_msg == 1) ? ESCALATION_STATUS_SLEEP : ESCALATION_STATUS_COMPLETED; } zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name); }
/****************************************************************************** * * * Function: update_checksums * * * * Purpose: overwrite old checksums with new ones * * * * Parameters: * * * * Return value: SUCCESS - calculated successfully * * FAIL - an error occurred * * * * Author: Alexei Vladishev * * * * Comments: * * * ******************************************************************************/ int update_checksums(int nodeid, int synked_nodetype, int synked, const char *tablename, const zbx_uint64_t id, char *fields) { const char *__function_name = "update_checksums"; char *r[2], *d[2], sync[129], *s; char c[2], sql[2][256]; char cksum[32*64+32], *ck; char *exsql = NULL; int exsql_alloc = 65536, exsql_offset = 0, cksumtype; DB_RESULT result; DB_ROW row; int f; const ZBX_TABLE *table; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); exsql = zbx_malloc(exsql, exsql_alloc); DBbegin(); #ifdef HAVE_ORACLE zbx_snprintf_alloc(&exsql, &exsql_alloc, &exsql_offset, 8, "begin\n"); #endif c[0] = synked == SUCCEED ? '1' : ' '; /* for new and updated records */ c[1] = synked == SUCCEED ? '2' : ' '; /* for deleted records */ if (NULL != tablename) { zbx_snprintf(sql[0], sizeof(sql[0]), " and curr.tablename='%s' and curr.recordid=" ZBX_FS_UI64, tablename, id); zbx_snprintf(sql[1], sizeof(sql[1]), " and prev.tablename='%s' and prev.recordid=" ZBX_FS_UI64, tablename, id); } else { *sql[0] = '\0'; *sql[1] = '\0'; } /* Find updated records */ result = DBselect("select curr.tablename,curr.recordid,prev.cksum,curr.cksum,prev.sync " "from node_cksum curr, node_cksum prev " "where curr.nodeid=%d and prev.nodeid=curr.nodeid and " "curr.tablename=prev.tablename and curr.recordid=prev.recordid and " "curr.cksumtype=%d and prev.cksumtype=%d%s " "union all " /* Find new records */ "select curr.tablename,curr.recordid,prev.cksum,curr.cksum,NULL " "from node_cksum curr left join node_cksum prev " "on prev.nodeid=curr.nodeid and prev.tablename=curr.tablename and " "prev.recordid=curr.recordid and prev.cksumtype=%d " "where curr.nodeid=%d and curr.cksumtype=%d and prev.tablename is null%s " "union all " /* Find deleted records */ "select prev.tablename,prev.recordid,prev.cksum,curr.cksum,prev.sync " "from node_cksum prev left join node_cksum curr " "on curr.nodeid=prev.nodeid and curr.tablename=prev.tablename and " "curr.recordid=prev.recordid and curr.cksumtype=%d " "where prev.nodeid=%d and prev.cksumtype=%d and curr.tablename is null%s", nodeid, NODE_CKSUM_TYPE_NEW, NODE_CKSUM_TYPE_OLD, sql[0], NODE_CKSUM_TYPE_OLD, nodeid, NODE_CKSUM_TYPE_NEW, sql[0], NODE_CKSUM_TYPE_NEW, nodeid, NODE_CKSUM_TYPE_OLD, sql[1]); while (NULL != (row = DBfetch(result))) { /* Found table */ if (NULL == (table = DBget_table(row[0]))) { zabbix_log(LOG_LEVEL_WARNING, "Cannot find table [%s]", row[0]); continue; } if (FAIL == DBis_null(row[4])) zbx_strlcpy(sync, row[4], sizeof(sync)); else memset(sync, ' ', sizeof(sync)); s = sync; ck = cksum; *ck = '\0'; /* Special (simpler) processing for operation DELETE */ if (SUCCEED == DBis_null(row[3])) { if (synked == SUCCEED) { if (synked_nodetype == ZBX_NODE_SLAVE) s[0] = c[1]; else if (synked_nodetype == ZBX_NODE_MASTER) s[1] = c[1]; } if ((0 == CONFIG_MASTER_NODEID || s[1] == c[1]) && (CONFIG_NODEID == nodeid || s[0] == c[1])) { zbx_snprintf_alloc(&exsql, &exsql_alloc, &exsql_offset, 256, "delete from node_cksum" " where nodeid=%d" " and cksumtype=%d" " and tablename='%s'" " and recordid=%s;\n", nodeid, NODE_CKSUM_TYPE_OLD, row[0], row[1]); DBexecute_overflowed_sql(&exsql, &exsql_alloc, &exsql_offset); continue; } s += 2; } else { r[0] = DBis_null(row[2]) == SUCCEED ? NULL : row[2]; r[1] = row[3]; f = 0; do { while ((table->fields[f].flags & ZBX_SYNC) == 0) f++; d[0] = NULL; d[1] = NULL; if (NULL != r[0] && NULL != (d[0] = strchr(r[0], ','))) *d[0] = '\0'; if (NULL != r[1] && NULL != (d[1] = strchr(r[1], ','))) *d[1] = '\0'; if (NULL == tablename || SUCCEED == str_in_list(fields, table->fields[f].name, ',')) { ck += zbx_snprintf(ck, 64, "%s,", NULL != r[1] ? r[1] : r[0]); if (r[0] == NULL || r[1] == NULL || strcmp(r[0], r[1]) != 0) { if (synked_nodetype == ZBX_NODE_SLAVE) { s[0] = c[0]; s[1] = ' '; } else if (synked_nodetype == ZBX_NODE_MASTER) { s[0] = ' '; s[1] = c[0]; } } else { if (synked == SUCCEED) { if (synked_nodetype == ZBX_NODE_SLAVE) s[0] = c[0]; else if (synked_nodetype == ZBX_NODE_MASTER) s[1] = c[0]; } } } else ck += zbx_snprintf(ck, 64, "%s,", NULL != r[0] ? r[0] : ""); s += 2; f++; if (d[0] != NULL) { *d[0] = ','; r[0] = d[0] + 1; } else r[0] = NULL; if (d[1] != NULL) { *d[1] = ','; r[1] = d[1] + 1; } else r[1] = NULL; } while (d[0] != NULL || d[1] != NULL); *--ck = '\0'; } *s = '\0'; if (SUCCEED == DBis_null(row[2]) || SUCCEED == DBis_null(row[3]) || 0 != strcmp(row[4], sync) || 0 != strcmp(row[2], row[3])) { cksumtype = (DBis_null(row[2]) == SUCCEED) ? NODE_CKSUM_TYPE_NEW : NODE_CKSUM_TYPE_OLD; zbx_snprintf_alloc(&exsql, &exsql_alloc, &exsql_offset, 2560, "update node_cksum" " set cksumtype=%d," "cksum='%s'," "sync='%s'" " where nodeid=%d" " and cksumtype=%d" " and tablename='%s'" " and recordid=%s;\n", NODE_CKSUM_TYPE_OLD, cksum, sync, nodeid, cksumtype, row[0], row[1]); DBexecute_overflowed_sql(&exsql, &exsql_alloc, &exsql_offset); } } DBfree_result(result); #ifdef HAVE_ORACLE zbx_snprintf_alloc(&exsql, &exsql_alloc, &exsql_offset, 8, "end;\n"); #endif if (exsql_offset > 16) /* In ORACLE always present begin..end; */ DBexecute("%s", exsql); zbx_free(exsql); DBcommit(); zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name); return SUCCEED; }
/****************************************************************************** * * * Function: get_config_data * * * * Purpose: obtain configuration changes to required node * * * * Parameters: * * * * Return value: SUCCESS - processed successfully * * FAIL - an error occurred * * * * Author: Alexei Vladishev * * * * Comments: * * * ******************************************************************************/ char *get_config_data(int nodeid, int dest_nodetype) { const char *__function_name = "get_config_data"; DB_RESULT result; DB_RESULT result2; DB_ROW row; DB_ROW row2; const ZBX_TABLE *table; char *data = NULL, *hex = NULL, *sql = NULL, c[2], sync[129], *s, *r[2], *d[2]; int data_offset = 0, sql_offset = 0; int data_allocated = 1024, hex_allocated = 1024, sql_allocated = 8192; int f, j, rowlen; zabbix_log(LOG_LEVEL_DEBUG, "In %s() node:%d dest_nodetype:%s", __function_name, nodeid, (dest_nodetype == ZBX_NODE_MASTER) ? "MASTER" : "SLAVE"); data = zbx_malloc(data, data_allocated); hex = zbx_malloc(hex, hex_allocated); sql = zbx_malloc(sql, sql_allocated); c[0] = '1'; /* for new and updated records */ c[1] = '2'; /* for deleted records */ zbx_snprintf_alloc(&data, &data_allocated, &data_offset, 16, "Data%c%d%c%d", ZBX_DM_DELIMITER, CONFIG_NODEID, ZBX_DM_DELIMITER, nodeid); /* Find updated records */ result = DBselect("select curr.tablename,curr.recordid,prev.cksum,curr.cksum,prev.sync " "from node_cksum curr, node_cksum prev " "where curr.nodeid=%d and prev.nodeid=curr.nodeid and " "curr.tablename=prev.tablename and curr.recordid=prev.recordid and " "curr.cksumtype=%d and prev.cksumtype=%d " "union all " /* Find new records */ "select curr.tablename,curr.recordid,prev.cksum,curr.cksum,curr.sync " "from node_cksum curr left join node_cksum prev " "on prev.nodeid=curr.nodeid and prev.tablename=curr.tablename and " "prev.recordid=curr.recordid and prev.cksumtype=%d " "where curr.nodeid=%d and curr.cksumtype=%d and prev.tablename is null " "union all " /* Find deleted records */ "select prev.tablename,prev.recordid,prev.cksum,curr.cksum,prev.sync " "from node_cksum prev left join node_cksum curr " "on curr.nodeid=prev.nodeid and curr.tablename=prev.tablename and " "curr.recordid=prev.recordid and curr.cksumtype=%d " "where prev.nodeid=%d and prev.cksumtype=%d and curr.tablename is null", nodeid, NODE_CKSUM_TYPE_NEW, NODE_CKSUM_TYPE_OLD, NODE_CKSUM_TYPE_OLD, nodeid, NODE_CKSUM_TYPE_NEW, NODE_CKSUM_TYPE_NEW, nodeid, NODE_CKSUM_TYPE_OLD); while (NULL != (row = DBfetch(result))) { /* Found table */ if (NULL == (table = DBget_table(row[0]))) { zabbix_log(LOG_LEVEL_WARNING, "Cannot find table [%s]", row[0]); continue; } if (FAIL == DBis_null(row[4])) zbx_strlcpy(sync, row[4], sizeof(sync)); else memset(sync, ' ', sizeof(sync)); s = sync; /* Special (simpler) processing for operation DELETE */ if (SUCCEED == DBis_null(row[3])) { if ((dest_nodetype == ZBX_NODE_SLAVE && s[0] != c[1]) || (dest_nodetype == ZBX_NODE_MASTER && s[1] != c[1])) { zbx_snprintf_alloc(&data, &data_allocated, &data_offset, 128, "\n%s%c%s%c%d", row[0], ZBX_DM_DELIMITER, row[1], ZBX_DM_DELIMITER, NODE_CONFIGLOG_OP_DELETE); } continue; } r[0] = (SUCCEED == DBis_null(row[2]) ? NULL : row[2]); r[1] = row[3]; f = 0; sql_offset = 0; zbx_snprintf_alloc(&sql, &sql_allocated, &sql_offset, 128, "select "); do { while (0 == (table->fields[f].flags & ZBX_SYNC)) f++; d[0] = NULL; d[1] = NULL; if (NULL != r[0] && NULL != (d[0] = strchr(r[0], ','))) *d[0] = '\0'; if (NULL != r[1] && NULL != (d[1] = strchr(r[1], ','))) *d[1] = '\0'; if (NULL == r[0] || NULL == r[1] || (ZBX_NODE_SLAVE == dest_nodetype && s[0] != c[0]) || (ZBX_NODE_MASTER == dest_nodetype && s[1] != c[0]) || 0 != strcmp(r[0], r[1])) { zbx_snprintf_alloc(&sql, &sql_allocated, &sql_offset, 128, "%s,", table->fields[f].name); if (table->fields[f].type == ZBX_TYPE_BLOB) { zbx_snprintf_alloc(&sql, &sql_allocated, &sql_offset, 128, "length(%s),", table->fields[f].name); } } s += 2; f++; if (d[0] != NULL) { *d[0] = ','; r[0] = d[0] + 1; } else r[0] = NULL; if (d[1] != NULL) { *d[1] = ','; r[1] = d[1] + 1; } else r[1] = NULL; } while (NULL != d[0] || NULL != d[1]); if (sql[sql_offset-1] != ',') continue; sql_offset--; zbx_snprintf_alloc(&sql, &sql_allocated, &sql_offset, 128, " from %s where %s=%s", row[0], table->recid, row[1]); result2 = DBselect("%s", sql); if (NULL == (row2 = DBfetch(result2))) goto out; zbx_snprintf_alloc(&data, &data_allocated, &data_offset, 128, "\n%s%c%s%c%d", row[0], ZBX_DM_DELIMITER, row[1], ZBX_DM_DELIMITER, NODE_CONFIGLOG_OP_UPDATE); r[0] = DBis_null(row[2]) == SUCCEED ? NULL : row[2]; r[1] = row[3]; s = sync; f = 0; j = 0; do { while ((table->fields[f].flags & ZBX_SYNC) == 0) f++; d[0] = NULL; d[1] = NULL; if (NULL != r[0] && NULL != (d[0] = strchr(r[0], ','))) *d[0] = '\0'; if (NULL != r[1] && NULL != (d[1] = strchr(r[1], ','))) *d[1] = '\0'; if (r[0] == NULL || r[1] == NULL || (dest_nodetype == ZBX_NODE_SLAVE && *s != c[0]) || (dest_nodetype == ZBX_NODE_MASTER && *(s+1) != c[0]) || strcmp(r[0], r[1]) != 0) { zbx_snprintf_alloc(&data, &data_allocated, &data_offset, 128, "%c%s%c%d%c", ZBX_DM_DELIMITER, table->fields[f].name, ZBX_DM_DELIMITER, table->fields[f].type, ZBX_DM_DELIMITER); /* Fieldname, type, value */ if (SUCCEED == DBis_null(row2[j])) { zbx_snprintf_alloc(&data, &data_allocated, &data_offset, 5, "NULL"); } else 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) { zbx_snprintf_alloc(&data, &data_allocated, &data_offset, 128, "%s", row2[j]); } else { if (ZBX_TYPE_BLOB == table->fields[f].type) rowlen = atoi(row2[j + 1]); else rowlen = strlen(row2[j]); zbx_binary2hex((u_char *)row2[j], rowlen, &hex, &hex_allocated); zbx_snprintf_alloc(&data, &data_allocated, &data_offset, strlen(hex) + 128, "%s", hex); } if (ZBX_TYPE_BLOB == table->fields[f].type) j += 2; else j++; } s += 2; f++; if (NULL != d[0]) { *d[0] = ','; r[0] = d[0] + 1; } else r[0] = NULL; if (NULL != d[1]) { *d[1] = ','; r[1] = d[1] + 1; } else r[1] = NULL; } while (NULL != d[0] || NULL != d[1]); out: DBfree_result(result2); } DBfree_result(result); zbx_free(hex); zbx_free(sql); zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name); return data; }
/****************************************************************************** * * * 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()"); }
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 " and operationtype in (%d,%d)", action->actionid, OPERATION_TYPE_MESSAGE, OPERATION_TYPE_COMMAND); } 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 operationtype in (%d,%d)" " and esc_step_from<=%d and (esc_step_to=0 or esc_step_to>=%d)", action->actionid, OPERATION_TYPE_MESSAGE, OPERATION_TYPE_COMMAND, escalation->esc_step, escalation->esc_step); } while (NULL != (row = DBfetch(result))) { memset(&operation, 0, sizeof(operation)); ZBX_STR2UINT64(operation.operationid, row[0]); operation.actionid = action->actionid; operation.operationtype = atoi(row[1]); operation.object = atoi(row[2]); ZBX_STR2UINT64(operation.objectid, 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, NULL, &operation.shortdata); substitute_macros(event, action, NULL, &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_object_msg(event->source, escalation->triggerid, &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->mediatypeid, p->subject, p->message); zbx_free(p->subject); zbx_free(p->message); zbx_free(p); } if (0 == action->esc_period) { escalation->status = (action->recovery_msg == 1) ? ESCALATION_STATUS_SLEEP : 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 = (action->recovery_msg == 1) ? ESCALATION_STATUS_SLEEP : ESCALATION_STATUS_COMPLETED; } }
/****************************************************************************** * * * Function: ja_log * * * * Purpose: output a message to the log file * * it also performs error notification app * * * * Parameters: message_id (in) - message id * * inner_jobnet_id (in) - inner jobnet id * * jobnet_id (in) - jobnet id * * inner_job_id (in) - inner job id * * ... - additional information (variable parameters) * * * * Return value: SUCCEED - processed successfully * * FAIL - Processing error occurs * * * * Comments: * * * ******************************************************************************/ int ja_log(char *message_id, zbx_uint64_t inner_jobnet_id, char *jobnet_id, zbx_uint64_t inner_job_id, ...) { FILE *fp; struct tm *tm; time_t now; DIR *dir; struct dirent *dp; va_list ap; DB_RESULT result; DB_RESULT result2; DB_ROW row; DB_ROW row2; int log_type, log_level, send_flag, rc, hit, m, n, cnt, job_type, host_flag, get_host_flag; int state, zbxsnd; zbx_uint64_t w_inner_jobnet_id, inner_jobnet_main_id; char *now_date, *message = NULL, *name = NULL, *type = NULL, *send = NULL, *msg = NULL; char *after_value_esc, *user_name_esc, *host_name_esc, *jobnet_name_esc, *job_name_esc; char s_jobnet_id[JA_DATA_BUFFER_LEN] = "none"; char s_user_name[JA_DATA_BUFFER_LEN] = "none"; char s_job_id[JA_DATA_BUFFER_LEN] = "none"; char s_job_id_full[JA_DATA_BUFFER_LEN] = "none"; char line[AP_MESSAGE_BUF_SIZE]; char cmd[AP_MESSAGE_BUF_SIZE]; char host_name[JA_DATA_BUFFER_LEN] = ""; char jobnet_name[JA_JOBNET_NAME_LEN] = ""; char job_name[JA_JOB_NAME_LEN] = ""; char now_time[20]; const char *__function_name = "ja_log"; zabbix_log(LOG_LEVEL_DEBUG, "In %s() message_id: %s inner_jobnet_id: " ZBX_FS_UI64 " inner_job_id: " ZBX_FS_UI64, __function_name, message_id, inner_jobnet_id, inner_job_id); w_inner_jobnet_id = inner_jobnet_id; inner_jobnet_main_id = 0; /* message file open */ fp = fopen(CONFIG_JA_LOG_MESSAGE_FILE, "r"); if (fp == NULL) { zabbix_log(LOG_LEVEL_ERR, "failed to open the log message file: [%s] (%s)", CONFIG_JA_LOG_MESSAGE_FILE, strerror(errno)); return FAIL; } /* message get */ cnt = 0; hit = 0; while (fgets(line, sizeof(line), fp) != NULL) { cnt = cnt + 1; if (line[0] == '#' || line[0] == '\n' || line[0] == '\r' ) { continue; } if (strlen(line) > 0) { if (line[strlen(line)-1] == '\n') { line[strlen(line)-1] = '\0'; } } if (strlen(line) > 0) { if (line[strlen(line)-1] == '\r') { line[strlen(line)-1] = '\0'; } } n = 0; m = 0; name = line; type = NULL; send = NULL; msg = NULL; while (line[++n]) { if (line[n] == ',') { if (m == 0) { line[n] = '\0'; type = &line[n + 1]; m++; } else if (m == 1) { line[n] = '\0'; send = &line[n + 1]; m++; } else if (m == 2) { line[n] = '\0'; msg = &line[n + 1]; break; } } } lrtrim_spaces(name); if (strcmp(name, message_id) == 0) { hit = 1; break; } } fclose(fp); /* message hit check */ if (hit == 0) { zabbix_log(LOG_LEVEL_ERR, "could not find an appropriate message: [%s]", message_id); return FAIL; } /* message get check */ if (name == NULL || type == NULL || send == NULL || msg == NULL) { zabbix_log(LOG_LEVEL_ERR, "line data in the message file is invalid: line(%d) id[%s] file[%s]", cnt, message_id, CONFIG_JA_LOG_MESSAGE_FILE); return FAIL; } lrtrim_spaces(type); lrtrim_spaces(send); /* check the empty data */ if (strlen(type) <= 0 || strlen(send) <= 0 || strlen(msg) <= 0) { zabbix_log(LOG_LEVEL_ERR, "line data in the message file is invalid: line(%d) id[%s] file[%s]", cnt, message_id, CONFIG_JA_LOG_MESSAGE_FILE); return FAIL; } /* log type check */ log_level = LOG_LEVEL_INFORMATION; log_type = atoi(type); switch (log_type) { case JALOG_TYPE_INFO: log_level = LOG_LEVEL_INFORMATION; break; case JALOG_TYPE_CRIT: log_level = LOG_LEVEL_CRIT; break; case JALOG_TYPE_ERR: log_level = LOG_LEVEL_ERR; break; case JALOG_TYPE_WARN: log_level = LOG_LEVEL_WARNING; break; case JALOG_TYPE_DEBUG: log_level = LOG_LEVEL_DEBUG; break; default: zabbix_log(LOG_LEVEL_ERR, "detected an invalid log type: line(%d) type[%s] id[%s] file[%s]", cnt, type, message_id, CONFIG_JA_LOG_MESSAGE_FILE); return FAIL; } /* send flad check */ send_flag = atoi(send); if (send_flag == JASENDER_OFF || send_flag == JASENDER_ON) { /* OK */ } else { zabbix_log(LOG_LEVEL_ERR, "detected an invalid jasender flag: line(%d) flag[%s] id[%s] file[%s]", cnt, send, message_id, CONFIG_JA_LOG_MESSAGE_FILE); return FAIL; } /* message body edit */ va_start(ap, inner_job_id); message = zbx_dvsprintf(message, msg, ap); va_end(ap); if (strlen(message) > AP_MESSAGE_BUF_SIZE) { *(message + (AP_MESSAGE_BUF_SIZE - 1)) = '\0'; } /* get the current time */ time(&now); tm = localtime(&now); strftime(now_time, sizeof(now_time), "%Y%m%d%H%M%S", tm); now_date = zbx_dsprintf(NULL, "%04d/%02d/%02d %02d:%02d:%02d", (tm->tm_year + 1900), (tm->tm_mon + 1), tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); /* get the inner jobnet id */ if (w_inner_jobnet_id == 0 && inner_job_id != 0) { result = DBselect("select inner_jobnet_id from ja_run_job_table" " where inner_job_id = " ZBX_FS_UI64, inner_job_id); if (NULL != (row = DBfetch(result))) { ZBX_STR2UINT64(w_inner_jobnet_id, row[0]); } DBfree_result(result); } /* get the host name and job id */ if (inner_job_id != 0) { zbx_strlcpy(s_job_id_full, ja_get_jobid(inner_job_id), sizeof(s_job_id_full)); job_type = -1; result = DBselect("select job_type, job_id, job_name" " from ja_run_job_table" " where inner_job_id = " ZBX_FS_UI64, inner_job_id); if (NULL != (row = DBfetch(result))) { job_type = atoi(row[0]); zbx_strlcpy(s_job_id, row[1], sizeof(s_job_id)); if (SUCCEED != DBis_null(row[2])) { zbx_strlcpy(job_name, row[2], sizeof(job_name)); } } DBfree_result(result); get_host_flag = 0; switch (job_type) { case JA_JOB_TYPE_JOB: get_host_flag = 1; result = DBselect("select host_flag, host_name" " from ja_run_icon_job_table" " where inner_job_id = " ZBX_FS_UI64, inner_job_id); break; case JA_JOB_TYPE_FCOPY: get_host_flag = 1; result = DBselect("select from_host_flag, from_host_name" " from ja_run_icon_fcopy_table" " where inner_job_id = " ZBX_FS_UI64, inner_job_id); break; case JA_JOB_TYPE_FWAIT: get_host_flag = 1; result = DBselect("select host_flag, host_name" " from ja_run_icon_fwait_table" " where inner_job_id = " ZBX_FS_UI64, inner_job_id); break; case JA_JOB_TYPE_REBOOT: get_host_flag = 1; result = DBselect("select host_flag, host_name" " from ja_run_icon_reboot_table" " where inner_job_id = " ZBX_FS_UI64, inner_job_id); break; case JA_JOB_TYPE_LESS: get_host_flag = 1; result = DBselect("select host_flag, host_name" " from ja_run_icon_agentless_table" " where inner_job_id = " ZBX_FS_UI64, inner_job_id); break; } /* host name acquisition target icon */ if (get_host_flag != 0) { if (NULL != (row = DBfetch(result))) { if (SUCCEED != DBis_null(row[1])) { host_flag = atoi(row[0]); if (host_flag == USE_HOSTNAME) { zbx_strlcpy(host_name, row[1], sizeof(host_name)); } else { /* get the host name from the job controller variable */ result2 = DBselect("select before_value" " from ja_run_value_before_table" " where inner_job_id = " ZBX_FS_UI64 " and value_name = '%s'", inner_job_id, row[1]); if (NULL != (row2 = DBfetch(result2))) { zbx_strlcpy(host_name, row2[0], sizeof(host_name)); } DBfree_result(result2); } } } DBfree_result(result); } } /* get the user id */ if (w_inner_jobnet_id != 0 || jobnet_id != NULL) { if (w_inner_jobnet_id != 0) { result = DBselect("select inner_jobnet_id, inner_jobnet_main_id, jobnet_id, user_name, jobnet_name" " from ja_run_jobnet_table" " where inner_jobnet_id = " ZBX_FS_UI64, w_inner_jobnet_id); if (NULL != (row = DBfetch(result))) { ZBX_STR2UINT64(inner_jobnet_main_id, row[1]); if (strcmp(row[0], row[1]) != 0) { result2 = DBselect("select jobnet_id, user_name, jobnet_name" " from ja_run_jobnet_table" " where inner_jobnet_id = %s", row[1]); if (NULL != (row2 = DBfetch(result2))) { zbx_strlcpy(s_jobnet_id, row2[0], sizeof(s_jobnet_id)); zbx_strlcpy(s_user_name, row2[1], sizeof(s_user_name)); zbx_strlcpy(jobnet_name, row2[2], sizeof(jobnet_name)); } DBfree_result(result2); } else { zbx_strlcpy(s_jobnet_id, row[2], sizeof(s_jobnet_id)); zbx_strlcpy(s_user_name, row[3], sizeof(s_user_name)); zbx_strlcpy(jobnet_name, row[4], sizeof(jobnet_name)); } } } else { result = DBselect("select jobnet_id, user_name, jobnet_name" " from ja_jobnet_control_table" " where jobnet_id = '%s' and valid_flag = %d", jobnet_id, VALID_FLAG_ON); if (NULL != (row = DBfetch(result))) { zbx_strlcpy(s_jobnet_id, row[0], sizeof(s_jobnet_id)); zbx_strlcpy(s_user_name, row[1], sizeof(s_user_name)); zbx_strlcpy(jobnet_name, row[2], sizeof(jobnet_name)); } } DBfree_result(result); } /* log write */ zabbix_log(log_level, "[%s] %s", message_id, message); /* register the error message variable */ if (w_inner_jobnet_id == 0 || inner_job_id == 0 || log_level == LOG_LEVEL_INFORMATION || log_level == LOG_LEVEL_DEBUG) { /* skip the registration */ } else { after_value_esc = DBdyn_escape_string(message); /* to add a variable */ rc = DBexecute("insert into ja_run_value_after_table (" "inner_job_id, inner_jobnet_id, value_name, after_value) " "values (" ZBX_FS_UI64 ", " ZBX_FS_UI64 ", '%s', '[%s] %s')", inner_job_id, w_inner_jobnet_id, JOBARG_MESSAGE, message_id, after_value_esc); if (rc <= ZBX_DB_OK) { zabbix_log(LOG_LEVEL_ERR, "failed to insert the ja_run_value_after_table (ja_log): " " message id[%s] inner job id[" ZBX_FS_UI64 "] value name[%s]", message_id, inner_job_id, JOBARG_MESSAGE); zbx_free(after_value_esc); zbx_free(message); zbx_free(now_date); return FAIL; } zbx_free(after_value_esc); } /* no notification of message ? */ if (send_flag == JASENDER_OFF) { zbx_free(message); zbx_free(now_date); return SUCCEED; } /* get zabbix notification existence */ zbxsnd = ja_get_zbxsnd_on(); /* with no notice of Zabbix ? */ if (zbxsnd == ZBXSND_NOTICE_ON) { /* registration of the send message information */ after_value_esc = DBdyn_escape_string(message); user_name_esc = DBdyn_escape_string(s_user_name); host_name_esc = DBdyn_escape_string(host_name); jobnet_name_esc = DBdyn_escape_string(jobnet_name); job_name_esc = DBdyn_escape_string(job_name); rc = DBexecute("insert into ja_send_message_table (" "message_date, inner_jobnet_id, inner_jobnet_main_id, send_status, retry_count, retry_date, send_date, send_error_date, " "message_type, user_name, host_name, jobnet_id, jobnet_name, job_id, job_id_full, job_name, " "log_message_id, log_message) " "values (%s, " ZBX_FS_UI64 ", " ZBX_FS_UI64 ", %d, 0, 0, 0, 0, " "%d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', " "'%s', '%s')", now_time, w_inner_jobnet_id, inner_jobnet_main_id, JA_SNT_SEND_STATUS_BEGIN, log_type, user_name_esc, host_name_esc, s_jobnet_id, jobnet_name_esc, s_job_id, s_job_id_full, job_name_esc, message_id, after_value_esc); if (rc <= ZBX_DB_OK) { zabbix_log(LOG_LEVEL_ERR, "failed to insert the ja_send_message_table (ja_log): " " message date[%s] message id[%s]", now_time, message_id); zbx_free(after_value_esc); zbx_free(user_name_esc); zbx_free(host_name_esc); zbx_free(jobnet_name_esc); zbx_free(job_name_esc); zbx_free(message); zbx_free(now_date); return FAIL; } zbx_free(after_value_esc); zbx_free(user_name_esc); zbx_free(host_name_esc); zbx_free(jobnet_name_esc); zbx_free(job_name_esc); /* application execution error notification */ dir = opendir(CONFIG_ERROR_CMD_PATH); if (dir == NULL) { zabbix_log(LOG_LEVEL_ERR, "failed to open the error notification directory: [%s]", CONFIG_ERROR_CMD_PATH); zbx_free(message); zbx_free(now_date); return FAIL; } while ((dp = readdir(dir)) != NULL) { if (dp->d_name[0] == '.') { continue; } /* start command in the background */ zbx_snprintf(cmd, sizeof(cmd), "%s/%s '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' &", CONFIG_ERROR_CMD_PATH, dp->d_name, s_user_name, s_jobnet_id, now_date, message_id, type, message, host_name, s_job_id_full); rc = system(cmd); zabbix_log(LOG_LEVEL_DEBUG, "application execution [%s] (%d)", cmd, rc); if (rc != EXIT_SUCCESS) { if (WIFEXITED(rc)) { state = WEXITSTATUS(rc); } else { state = rc; } zabbix_log(LOG_LEVEL_ERR, "failed to run the error notification application: (%d) [%s]", state, cmd); zbx_free(message); zbx_free(now_date); closedir(dir); return FAIL; } } closedir(dir); zbx_free(message); zbx_free(now_date); } return SUCCEED; }
/****************************************************************************** * * * Function: DMcolect_table_data * * * * Purpose: obtain configuration changes to required node * * * * Return value: SUCCESS - processed successfully * * FAIL - an error occurred * * * * Author: Alexander Vladishev * * * * Comments: the changes are collected into data parameter * * * ******************************************************************************/ static void DMcollect_table_data(int nodeid, unsigned char dest_nodetype, const ZBX_TABLE *table, char **data, size_t *data_alloc, size_t *data_offset) { #define ZBX_REC_UPDATED '1' #define ZBX_REC_DELETED '2' const char *__function_name = "DMcolect_table_data"; DB_RESULT result; DB_RESULT result2; DB_ROW row; DB_ROW row2; const char *s; char *hex = NULL, *sql = NULL, sync[128], *curr_cksum, *d_curr_cksum, *prev_cksum, *d_prev_cksum; size_t sql_alloc = 8 * ZBX_KIBIBYTE, sql_offset = 0, hex_alloc = ZBX_KIBIBYTE, rowlen; int f, j; zabbix_log(LOG_LEVEL_DEBUG, "In %s() table:'%s'", __function_name, table->table); hex = zbx_malloc(hex, hex_alloc); sql = zbx_malloc(sql, sql_alloc); result = DBselect( /* new records */ "select curr.recordid,prev.cksum,curr.cksum,curr.sync" " from node_cksum curr" " left join node_cksum prev" " on prev.nodeid=curr.nodeid" " and prev.tablename=curr.tablename" " and prev.recordid=curr.recordid" " and prev.cksumtype=%d" " where curr.nodeid=%d" " and curr.tablename='%s'" " and curr.cksumtype=%d" " and prev.tablename is null" " union all " /* updated records */ "select curr.recordid,prev.cksum,curr.cksum,prev.sync" " from node_cksum curr,node_cksum prev" " where curr.nodeid=prev.nodeid" " and curr.tablename=prev.tablename" " and curr.recordid=prev.recordid" " and curr.nodeid=%d" " and curr.tablename='%s'" " and curr.cksumtype=%d" " and prev.cksumtype=%d" " union all " /* deleted records */ "select prev.recordid,prev.cksum,curr.cksum,prev.sync" " from node_cksum prev" " left join node_cksum curr" " on curr.nodeid=prev.nodeid" " and curr.tablename=prev.tablename" " and curr.recordid=prev.recordid" " and curr.cksumtype=%d" " where prev.nodeid=%d" " and prev.tablename='%s'" " and prev.cksumtype=%d" " and curr.tablename is null", NODE_CKSUM_TYPE_OLD, nodeid, table->table, NODE_CKSUM_TYPE_NEW, nodeid, table->table, NODE_CKSUM_TYPE_NEW, NODE_CKSUM_TYPE_OLD, NODE_CKSUM_TYPE_NEW, nodeid, table->table, NODE_CKSUM_TYPE_OLD); while (NULL != (row = DBfetch(result))) { memset(sync, ' ', sizeof(sync)); memcpy(sync, row[3], strlen(row[3])); s = sync; /* special (simpler) processing for operation DELETE */ if (SUCCEED == DBis_null(row[2])) { if (ZBX_REC_DELETED != s[dest_nodetype]) { zbx_snprintf_alloc(data, data_alloc, data_offset, "\n%s%c%s%c%d", table->table, ZBX_DM_DELIMITER, row[0], ZBX_DM_DELIMITER, NODE_CONFIGLOG_OP_DELETE); } continue; } prev_cksum = (SUCCEED == DBis_null(row[1]) ? NULL : row[1]); curr_cksum = row[2]; f = 0; sql_offset = 0; zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "select "); do { while (0 == (table->fields[f].flags & ZBX_SYNC)) f++; d_prev_cksum = NULL; if (NULL != prev_cksum && NULL != (d_prev_cksum = strchr(prev_cksum, ','))) *d_prev_cksum = '\0'; d_curr_cksum = NULL; if (NULL != curr_cksum && NULL != (d_curr_cksum = strchr(curr_cksum, ','))) *d_curr_cksum = '\0'; if (NULL == prev_cksum || NULL == curr_cksum || ZBX_REC_UPDATED != s[dest_nodetype] || 0 != strcmp(prev_cksum, curr_cksum)) { zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%s,", table->fields[f].name); if (table->fields[f].type == ZBX_TYPE_BLOB) { zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "length(%s),", table->fields[f].name); } } /* "host_inventory" table has more than 64 fields */ /* remaining fields are processed as one */ if (126 > s - sync) s += 2; f++; if (d_prev_cksum != NULL) { *d_prev_cksum = ','; prev_cksum = d_prev_cksum + 1; } else prev_cksum = NULL; if (d_curr_cksum != NULL) { *d_curr_cksum = ','; curr_cksum = d_curr_cksum + 1; } else curr_cksum = NULL; } while (NULL != d_prev_cksum || NULL != d_curr_cksum); if (sql[sql_offset - 1] != ',') continue; sql_offset--; zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, " from %s where %s=%s", table->table, table->recid, row[0]); result2 = DBselect("%s", sql); if (NULL == (row2 = DBfetch(result2))) goto out; zbx_snprintf_alloc(data, data_alloc, data_offset, "\n%s%c%s%c%d", table->table, ZBX_DM_DELIMITER, row[0], ZBX_DM_DELIMITER, NODE_CONFIGLOG_OP_UPDATE); prev_cksum = DBis_null(row[1]) == SUCCEED ? NULL : row[1]; curr_cksum = row[2]; s = sync; f = 0; j = 0; do { while (0 == (table->fields[f].flags & ZBX_SYNC)) f++; d_prev_cksum = NULL; if (NULL != prev_cksum && NULL != (d_prev_cksum = strchr(prev_cksum, ','))) *d_prev_cksum = '\0'; d_curr_cksum = NULL; if (NULL != curr_cksum && NULL != (d_curr_cksum = strchr(curr_cksum, ','))) *d_curr_cksum = '\0'; if (NULL == prev_cksum || NULL == curr_cksum || ZBX_REC_UPDATED != s[dest_nodetype] || 0 != strcmp(prev_cksum, curr_cksum)) { /* fieldname, type */ zbx_snprintf_alloc(data, data_alloc, data_offset, "%c%s%c%d%c", ZBX_DM_DELIMITER, table->fields[f].name, ZBX_DM_DELIMITER, table->fields[f].type, ZBX_DM_DELIMITER); /* value */ if (SUCCEED == DBis_null(row2[j])) { zbx_strcpy_alloc(data, data_alloc, data_offset, "NULL"); } else if (ZBX_TYPE_INT == table->fields[f].type || ZBX_TYPE_UINT == table->fields[f].type || ZBX_TYPE_ID == table->fields[f].type || ZBX_TYPE_FLOAT == table->fields[f].type) { zbx_strcpy_alloc(data, data_alloc, data_offset, row2[j]); } else { if (table->fields[f].type == ZBX_TYPE_BLOB) rowlen = (size_t)atoi(row2[j + 1]); else rowlen = strlen(row2[j]); zbx_binary2hex((u_char *)row2[j], rowlen, &hex, &hex_alloc); zbx_strcpy_alloc(data, data_alloc, data_offset, hex); } if (table->fields[f].type == ZBX_TYPE_BLOB) j += 2; else j++; } /* "host_inventory" table has more than 64 fields */ /* remaining fields are processed as one */ if (126 > s - sync) s += 2; f++; if (d_prev_cksum != NULL) { *d_prev_cksum = ','; prev_cksum = d_prev_cksum + 1; } else prev_cksum = NULL; if (d_curr_cksum != NULL) { *d_curr_cksum = ','; curr_cksum = d_curr_cksum + 1; } else curr_cksum = NULL; } while (NULL != d_prev_cksum || NULL != d_curr_cksum); out: DBfree_result(result2); } DBfree_result(result); zbx_free(hex); zbx_free(sql); zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name); }
/****************************************************************************** * * * Function: delete_history * * * * Purpose: remove outdated information from historical table * * * * Parameters: now - current timestamp * * * * Return value: number of rows records * * * * Author: Alexei Vladishev * * * * Comments: * * * ******************************************************************************/ static int delete_history(const char *table, const char *fieldname, int now) { const char *__function_name = "delete_history"; DB_RESULT result; DB_ROW row; int minclock, records = 0; zbx_uint64_t lastid, maxid; zabbix_log(LOG_LEVEL_DEBUG, "In %s() table:'%s' now:%d", __function_name, table, now); DBbegin(); result = DBselect( "select nextid" " from ids" " where table_name='%s'" " and field_name='%s'", table, fieldname); if (NULL == (row = DBfetch(result))) goto rollback; ZBX_STR2UINT64(lastid, row[0]); DBfree_result(result); result = DBselect("select min(clock) from %s", table); if (NULL == (row = DBfetch(result)) || SUCCEED == DBis_null(row[0])) goto rollback; minclock = atoi(row[0]); DBfree_result(result); result = DBselect("select max(id) from %s", table); if (NULL == (row = DBfetch(result)) || SUCCEED == DBis_null(row[0])) goto rollback; ZBX_STR2UINT64(maxid, row[0]); DBfree_result(result); records = DBexecute( "delete from %s" " where id<" ZBX_FS_UI64 " and (clock<%d" " or (id<=" ZBX_FS_UI64 " and clock<%d))", table, maxid, now - CONFIG_PROXY_OFFLINE_BUFFER * SEC_PER_HOUR, lastid, MIN(now - CONFIG_PROXY_LOCAL_BUFFER * SEC_PER_HOUR, minclock + HK_MAX_DELETE_PERIODS * hk_period)); DBcommit(); return records; rollback: DBfree_result(result); DBrollback(); return 0; }
/****************************************************************************** * * * Function: update_checksums * * * * Purpose: overwrite old checksums with new ones * * * * Parameters: * * * * Return value: SUCCESS - calculated successfully * * FAIL - an error occurred * * * * Author: Alexei Vladishev * * * * Comments: * * * ******************************************************************************/ int update_checksums(int nodeid, int synked_nodetype, int synked, const char *tablename, const zbx_uint64_t id, const char *fields) { const char *__function_name = "update_checksums"; char *r[2], *d[2], sync[129], *s; char c[2], sql[2][256]; char cksum[32 * 72 + 72], *ck; char *exsql = NULL; size_t exsql_alloc = 64 * ZBX_KIBIBYTE, exsql_offset = 0; int cksumtype; DB_RESULT result; DB_ROW row; int f; const ZBX_TABLE *table; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); exsql = zbx_malloc(exsql, exsql_alloc); DBbegin(); DBbegin_multiple_update(&exsql, &exsql_alloc, &exsql_offset); c[0] = SUCCEED == synked ? '1' : ' '; /* for new and updated records */ c[1] = SUCCEED == synked ? '2' : ' '; /* for deleted records */ if (NULL != tablename) { zbx_snprintf(sql[0], sizeof(sql[0]), " and curr.tablename='%s' and curr.recordid=" ZBX_FS_UI64, tablename, id); zbx_snprintf(sql[1], sizeof(sql[1]), " and prev.tablename='%s' and prev.recordid=" ZBX_FS_UI64, tablename, id); } else { *sql[0] = '\0'; *sql[1] = '\0'; } result = DBselect( /* new records */ "select curr.tablename,curr.recordid,prev.cksum,curr.cksum,NULL" " from node_cksum curr" " left join node_cksum prev" " on prev.nodeid=curr.nodeid" " and prev.tablename=curr.tablename" " and prev.recordid=curr.recordid" " and prev.cksumtype=%d" " where curr.nodeid=%d" " and curr.cksumtype=%d" " and prev.tablename is null%s" " union all " /* updated records */ "select curr.tablename,curr.recordid,prev.cksum,curr.cksum,prev.sync" " from node_cksum curr, node_cksum prev" " where curr.nodeid=%d" " and prev.nodeid=curr.nodeid" " and curr.tablename=prev.tablename" " and curr.recordid=prev.recordid" " and curr.cksumtype=%d" " and prev.cksumtype=%d%s" " union all " /* deleted records */ "select prev.tablename,prev.recordid,prev.cksum,curr.cksum,prev.sync" " from node_cksum prev" " left join node_cksum curr" " on curr.nodeid=prev.nodeid" " and curr.tablename=prev.tablename" " and curr.recordid=prev.recordid" " and curr.cksumtype=%d" " where prev.nodeid=%d" " and prev.cksumtype=%d" " and curr.tablename is null%s", NODE_CKSUM_TYPE_OLD, nodeid, NODE_CKSUM_TYPE_NEW, sql[0], nodeid, NODE_CKSUM_TYPE_NEW, NODE_CKSUM_TYPE_OLD, sql[0], NODE_CKSUM_TYPE_NEW, nodeid, NODE_CKSUM_TYPE_OLD, sql[1]); while (NULL != (row = DBfetch(result))) { if (NULL == (table = DBget_table(row[0]))) { zabbix_log(LOG_LEVEL_WARNING, "cannot find table [%s]", row[0]); continue; } memset(sync, ' ', sizeof(sync)); if (FAIL == DBis_null(row[4])) memcpy(sync, row[4], strlen(row[4])); s = sync; ck = cksum; *ck = '\0'; /* special (simpler) processing for operation DELETE */ if (SUCCEED == DBis_null(row[3])) { if (SUCCEED == synked) s[synked_nodetype] = c[1]; if ((0 == CONFIG_MASTER_NODEID || s[1] == c[1]) && (CONFIG_NODEID == nodeid || s[0] == c[1])) { zbx_snprintf_alloc(&exsql, &exsql_alloc, &exsql_offset, "delete from node_cksum" " where nodeid=%d" " and cksumtype=%d" " and tablename='%s'" " and recordid=%s;\n", nodeid, NODE_CKSUM_TYPE_OLD, row[0], row[1]); DBexecute_overflowed_sql(&exsql, &exsql_alloc, &exsql_offset); continue; } s += 2; } else { r[0] = SUCCEED == DBis_null(row[2]) ? NULL : row[2]; r[1] = row[3]; f = 0; do { while ((table->fields[f].flags & ZBX_SYNC) == 0) f++; /* "host_inventory" table has more than 64 fields */ /* remaining fields are processed as one */ if (128 == s - sync) s -= 2; d[0] = NULL; d[1] = NULL; if (NULL != r[0] && NULL != (d[0] = strchr(r[0], ','))) *d[0] = '\0'; if (NULL != r[1] && NULL != (d[1] = strchr(r[1], ','))) *d[1] = '\0'; if (NULL == tablename || SUCCEED == str_in_list(fields, table->fields[f].name, ',')) { ck += zbx_snprintf(ck, 64, "%s,", NULL != r[1] ? r[1] : r[0]); if (NULL == r[0] || NULL == r[1] || 0 != strcmp(r[0], r[1])) { s[0] = s[1] = ' '; s[synked_nodetype] = c[0]; } else { if (SUCCEED == synked) s[synked_nodetype] = c[0]; } } else ck += zbx_snprintf(ck, 64, "%s,", NULL != r[0] ? r[0] : ""); s += 2; f++; if (d[0] != NULL) { *d[0] = ','; r[0] = d[0] + 1; } else r[0] = NULL; if (d[1] != NULL) { *d[1] = ','; r[1] = d[1] + 1; } else r[1] = NULL; } while (d[0] != NULL || d[1] != NULL); *--ck = '\0'; } *s = '\0'; if (SUCCEED == DBis_null(row[2]) || SUCCEED == DBis_null(row[3]) || 0 != strcmp(row[4], sync) || 0 != strcmp(row[2], row[3])) { cksumtype = (DBis_null(row[2]) == SUCCEED) ? NODE_CKSUM_TYPE_NEW : NODE_CKSUM_TYPE_OLD; zbx_snprintf_alloc(&exsql, &exsql_alloc, &exsql_offset, "update node_cksum" " set cksumtype=%d," "cksum='%s'," "sync='%s'" " where nodeid=%d" " and cksumtype=%d" " and tablename='%s'" " and recordid=%s;\n", NODE_CKSUM_TYPE_OLD, cksum, sync, nodeid, cksumtype, row[0], row[1]); DBexecute_overflowed_sql(&exsql, &exsql_alloc, &exsql_offset); } } DBfree_result(result); DBend_multiple_update(&exsql, &exsql_alloc, &exsql_offset); if (exsql_offset > 16) /* In ORACLE always present begin..end; */ DBexecute("%s", exsql); zbx_free(exsql); DBcommit(); zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name); return SUCCEED; }
/****************************************************************************** * * * Function: register_service * * * * Purpose: register service if one does not exist * * * * Parameters: host ip address * * * * Return value: * * * * Author: Alexei Vladishev * * * * Comments: * * * ******************************************************************************/ static void register_service(DB_DSERVICE *service,DB_DRULE *rule,DB_DCHECK *check,zbx_uint64_t dhostid,char *ip,int port) { DB_RESULT result; DB_ROW row; char value_esc[MAX_STRING_LEN]; char key_esc[MAX_STRING_LEN]; assert(service); assert(rule); assert(check); assert(ip); zabbix_log(LOG_LEVEL_DEBUG, "In register_service(ip:%s,port:%d)", ip, port); DBescape_string(check->key_, key_esc, sizeof(key_esc)-1); result = DBselect("select dserviceid,dhostid,type,port,status,lastup,lastdown,value,key_ from dservices where dhostid=" ZBX_FS_UI64 " and type=%d and port=%d and key_='%s'", dhostid, check->type, port, key_esc); row=DBfetch(result); if(!row || DBis_null(row[0])==SUCCEED) { /* Add host only if service is up */ if(check->status == DOBJECT_STATUS_UP) { zabbix_log(LOG_LEVEL_DEBUG, "New service discovered on port %d", port); service->dserviceid = DBget_maxid("dservices","dserviceid"); service->dhostid = dhostid; service->type = check->type; service->port = port; service->status = DOBJECT_STATUS_UP; service->lastup = 0; service->lastdown = 0; strscpy(service->value, check->value); strscpy(service->key_, check->key_); DBescape_string(service->value, value_esc, sizeof(value_esc)-1); DBescape_string(service->key_, key_esc, sizeof(key_esc)-1); DBexecute("insert into dservices (dhostid,dserviceid,type,port,status,value,key_) values (" ZBX_FS_UI64 "," ZBX_FS_UI64 ",%d,%d,%d,'%s','%s')", service->dhostid, service->dserviceid, check->type, service->port, service->status, value_esc, key_esc); } } else { zabbix_log(LOG_LEVEL_DEBUG, "Service is already in database"); ZBX_STR2UINT64(service->dserviceid, row[0]); ZBX_STR2UINT64(service->dhostid, row[1]); service->type = atoi(row[2]); service->port = atoi(row[3]); service->status = atoi(row[4]); service->lastup = atoi(row[5]); service->lastdown = atoi(row[6]); strscpy(service->value,row[7]); strscpy(service->key_,row[8]); } DBfree_result(result); zabbix_log(LOG_LEVEL_DEBUG, "End register_service()"); }
/****************************************************************************** * * * Function: get_template_items * * * * Purpose: read template items from database * * * * Parameters: hostid - [IN] host id * * templateids - [IN] array of template IDs * * items - [OUT] the item data * * * * Comments: The itemid and key are set depending on whether the item exists * * for the specified host. * * If item exists itemid will be set to its itemid and key will be * * set to NULL. * * If item does not exist, itemid will be set to 0 and key will be * * set to item key. * * * ******************************************************************************/ static void get_template_items(zbx_uint64_t hostid, const zbx_vector_uint64_t *templateids, zbx_vector_ptr_t *items) { DB_RESULT result; DB_ROW row; char *sql = NULL; size_t sql_alloc = 0, sql_offset = 0, i; unsigned char interface_type; zbx_template_item_t *item; zbx_uint64_t interfaceids[4]; memset(&interfaceids, 0, sizeof(interfaceids)); DBget_interfaces_by_hostid(hostid, interfaceids); zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "select ti.itemid,ti.name,ti.key_,ti.type,ti.value_type,ti.data_type,ti.delay,ti.delay_flex," "ti.history,ti.trends,ti.status,ti.trapper_hosts,ti.units,ti.multiplier,ti.delta," "ti.formula,ti.logtimefmt,ti.valuemapid,ti.params,ti.ipmi_sensor,ti.snmp_community," "ti.snmp_oid,ti.snmpv3_securityname,ti.snmpv3_securitylevel,ti.snmpv3_authprotocol," "ti.snmpv3_authpassphrase,ti.snmpv3_privprotocol,ti.snmpv3_privpassphrase,ti.authtype," "ti.username,ti.password,ti.publickey,ti.privatekey,ti.flags,ti.description," "ti.inventory_link,ti.lifetime,ti.snmpv3_contextname,hi.itemid,ti.evaltype,ti.port" " from items ti" " left join items hi on hi.key_=ti.key_" " and hi.hostid=" ZBX_FS_UI64 " where", hostid); DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "ti.hostid", templateids->values, templateids->values_num); result = DBselect("%s", sql); while (NULL != (row = DBfetch(result))) { item = zbx_malloc(NULL, sizeof(zbx_template_item_t)); ZBX_STR2UINT64(item->templateid, row[0]); ZBX_STR2UCHAR(item->type, row[3]); ZBX_STR2UCHAR(item->value_type, row[4]); ZBX_STR2UCHAR(item->data_type, row[5]); item->delay = atoi(row[6]); item->history = atoi(row[8]); item->trends = atoi(row[9]); ZBX_STR2UCHAR(item->status, row[10]); ZBX_STR2UCHAR(item->multiplier, row[13]); ZBX_STR2UCHAR(item->delta, row[14]); ZBX_DBROW2UINT64(item->valuemapid, row[17]); ZBX_STR2UCHAR(item->snmpv3_securitylevel, row[23]); ZBX_STR2UCHAR(item->snmpv3_authprotocol, row[24]); ZBX_STR2UCHAR(item->snmpv3_privprotocol, row[26]); ZBX_STR2UCHAR(item->authtype, row[28]); ZBX_STR2UCHAR(item->flags, row[33]); ZBX_STR2UCHAR(item->inventory_link, row[35]); ZBX_STR2UCHAR(item->evaltype, row[39]); switch (interface_type = get_interface_type_by_item_type(item->type)) { case INTERFACE_TYPE_UNKNOWN: item->interfaceid = 0; break; case INTERFACE_TYPE_ANY: for (i = 0; INTERFACE_TYPE_COUNT > i; i++) { if (0 != interfaceids[INTERFACE_TYPE_PRIORITY[i] - 1]) break; } item->interfaceid = interfaceids[INTERFACE_TYPE_PRIORITY[i] - 1]; break; default: item->interfaceid = interfaceids[interface_type - 1]; } item->name = zbx_strdup(NULL, row[1]); item->delay_flex = zbx_strdup(NULL, row[7]); item->trapper_hosts = zbx_strdup(NULL, row[11]); item->units = zbx_strdup(NULL, row[12]); item->formula = zbx_strdup(NULL, row[15]); item->logtimefmt = zbx_strdup(NULL, row[16]); item->params = zbx_strdup(NULL, row[18]); item->ipmi_sensor = zbx_strdup(NULL, row[19]); item->snmp_community = zbx_strdup(NULL, row[20]); item->snmp_oid = zbx_strdup(NULL, row[21]); item->snmpv3_securityname = zbx_strdup(NULL, row[22]); item->snmpv3_authpassphrase = zbx_strdup(NULL, row[25]); item->snmpv3_privpassphrase = zbx_strdup(NULL, row[27]); item->username = zbx_strdup(NULL, row[29]); item->password = zbx_strdup(NULL, row[30]); item->publickey = zbx_strdup(NULL, row[31]); item->privatekey = zbx_strdup(NULL, row[32]); item->description = zbx_strdup(NULL, row[34]); item->lifetime = zbx_strdup(NULL, row[36]); item->snmpv3_contextname = zbx_strdup(NULL, row[37]); item->port = zbx_strdup(NULL, row[40]); if (SUCCEED != DBis_null(row[38])) { item->key = NULL; ZBX_STR2UINT64(item->itemid, row[38]); } else { item->key = zbx_strdup(NULL, row[2]); item->itemid = 0; } zbx_vector_ptr_append(items, item); } DBfree_result(result); zbx_free(sql); zbx_vector_ptr_sort(items, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC); }
int MAIN_ZABBIX_ENTRY() { DB_RESULT result; DB_ROW row; pid_t pid; zbx_sock_t listen_sock; int i, server_num = 0, server_count = 0; if (NULL == CONFIG_LOG_FILE || '\0' == *CONFIG_LOG_FILE) zabbix_open_log(LOG_TYPE_SYSLOG, CONFIG_LOG_LEVEL, NULL); else zabbix_open_log(LOG_TYPE_FILE, CONFIG_LOG_LEVEL, CONFIG_LOG_FILE); #ifdef HAVE_SNMP # define SNMP_FEATURE_STATUS "YES" #else # define SNMP_FEATURE_STATUS " NO" #endif #ifdef HAVE_OPENIPMI # define IPMI_FEATURE_STATUS "YES" #else # define IPMI_FEATURE_STATUS " NO" #endif #ifdef HAVE_LIBCURL # define LIBCURL_FEATURE_STATUS "YES" #else # define LIBCURL_FEATURE_STATUS " NO" #endif #if defined(HAVE_LIBXML2) && defined(HAVE_LIBCURL) # define VMWARE_FEATURE_STATUS "YES" #else # define VMWARE_FEATURE_STATUS " NO" #endif #ifdef HAVE_JABBER # define JABBER_FEATURE_STATUS "YES" #else # define JABBER_FEATURE_STATUS " NO" #endif #ifdef HAVE_UNIXODBC # define ODBC_FEATURE_STATUS "YES" #else # define ODBC_FEATURE_STATUS " NO" #endif #ifdef HAVE_SSH2 # define SSH2_FEATURE_STATUS "YES" #else # define SSH2_FEATURE_STATUS " NO" #endif #ifdef HAVE_IPV6 # define IPV6_FEATURE_STATUS "YES" #else # define IPV6_FEATURE_STATUS " NO" #endif zabbix_log(LOG_LEVEL_INFORMATION, "Starting Zabbix Server. Zabbix %s (revision %s).", ZABBIX_VERSION, ZABBIX_REVISION); zabbix_log(LOG_LEVEL_INFORMATION, "****** Enabled features ******"); zabbix_log(LOG_LEVEL_INFORMATION, "SNMP monitoring: " SNMP_FEATURE_STATUS); zabbix_log(LOG_LEVEL_INFORMATION, "IPMI monitoring: " IPMI_FEATURE_STATUS); zabbix_log(LOG_LEVEL_INFORMATION, "WEB monitoring: " LIBCURL_FEATURE_STATUS); zabbix_log(LOG_LEVEL_INFORMATION, "VMware monitoring: " VMWARE_FEATURE_STATUS); zabbix_log(LOG_LEVEL_INFORMATION, "Jabber notifications: " JABBER_FEATURE_STATUS); zabbix_log(LOG_LEVEL_INFORMATION, "Ez Texting notifications: " LIBCURL_FEATURE_STATUS); zabbix_log(LOG_LEVEL_INFORMATION, "ODBC: " ODBC_FEATURE_STATUS); zabbix_log(LOG_LEVEL_INFORMATION, "SSH2 support: " SSH2_FEATURE_STATUS); zabbix_log(LOG_LEVEL_INFORMATION, "IPv6 support: " IPV6_FEATURE_STATUS); zabbix_log(LOG_LEVEL_INFORMATION, "******************************"); if (0 != CONFIG_NODEID) { zabbix_log(LOG_LEVEL_INFORMATION, "NodeID: %3d", CONFIG_NODEID); zabbix_log(LOG_LEVEL_INFORMATION, "******************************"); } zabbix_log(LOG_LEVEL_INFORMATION, "using configuration file: %s", CONFIG_FILE); if (FAIL == load_modules(CONFIG_LOAD_MODULE_PATH, CONFIG_LOAD_MODULE, CONFIG_TIMEOUT, 1)) { zabbix_log(LOG_LEVEL_CRIT, "loading modules failed, exiting..."); exit(EXIT_FAILURE); } zbx_free_config(); init_database_cache(); init_configuration_cache(); init_selfmon_collector(); /* initialize vmware support */ if (0 != CONFIG_VMWARE_FORKS) zbx_vmware_init(); /* initialize history value cache */ zbx_vc_init(); zbx_create_itservices_lock(); #ifdef HAVE_SQLITE3 zbx_create_sqlite3_mutex(); #endif if (SUCCEED != DBcheck_version()) exit(EXIT_FAILURE); DBconnect(ZBX_DB_CONNECT_NORMAL); if (0 != CONFIG_NODEID) { result = DBselect("select masterid from nodes where nodeid=%d", CONFIG_NODEID); if (NULL != (row = DBfetch(result)) && SUCCEED != DBis_null(row[0])) CONFIG_MASTER_NODEID = atoi(row[0]); DBfree_result(result); } DCload_config(); /* make initial configuration sync before worker processes are forked */ DCsync_configuration(); DBclose(); if (ZBX_MUTEX_ERROR == zbx_mutex_create_force(&node_sync_access, ZBX_MUTEX_NODE_SYNC)) { zbx_error("Unable to create mutex for node syncs"); exit(FAIL); } threads_num = CONFIG_CONFSYNCER_FORKS + CONFIG_WATCHDOG_FORKS + CONFIG_POLLER_FORKS + CONFIG_UNREACHABLE_POLLER_FORKS + CONFIG_TRAPPER_FORKS + CONFIG_PINGER_FORKS + CONFIG_ALERTER_FORKS + CONFIG_HOUSEKEEPER_FORKS + CONFIG_TIMER_FORKS + CONFIG_NODEWATCHER_FORKS + CONFIG_HTTPPOLLER_FORKS + CONFIG_DISCOVERER_FORKS + CONFIG_HISTSYNCER_FORKS + CONFIG_ESCALATOR_FORKS + CONFIG_IPMIPOLLER_FORKS + CONFIG_JAVAPOLLER_FORKS + CONFIG_SNMPTRAPPER_FORKS + CONFIG_PROXYPOLLER_FORKS + CONFIG_SELFMON_FORKS + CONFIG_VMWARE_FORKS; threads = zbx_calloc(threads, threads_num, sizeof(pid_t)); if (0 < CONFIG_TRAPPER_FORKS) { if (FAIL == zbx_tcp_listen(&listen_sock, CONFIG_LISTEN_IP, (unsigned short)CONFIG_LISTEN_PORT)) { zabbix_log(LOG_LEVEL_CRIT, "listener failed: %s", zbx_tcp_strerror()); exit(1); } } for (i = 0; i < threads_num; i++) { if (0 == (pid = zbx_child_fork())) { server_num = i + 1; /* child processes are numbered starting from 1 */ break; } else threads[i] = pid; } if (0 == server_num) { zabbix_log(LOG_LEVEL_INFORMATION, "server #0 started [main process]"); while (-1 == wait(&i)) /* wait for any child to exit */ { if (EINTR != errno) { zabbix_log(LOG_LEVEL_ERR, "failed to wait on child processes: %s", zbx_strerror(errno)); break; } } /* all exiting child processes should be caught by signal handlers */ THIS_SHOULD_NEVER_HAPPEN; zbx_on_exit(); } else if (server_num <= (server_count += CONFIG_CONFSYNCER_FORKS)) { /* !!! configuration syncer must be server #1 - child_signal_handler() uses threads[0] !!! */ INIT_SERVER(ZBX_PROCESS_TYPE_CONFSYNCER, CONFIG_CONFSYNCER_FORKS); main_dbconfig_loop(); } else if (server_num <= (server_count += CONFIG_WATCHDOG_FORKS)) { INIT_SERVER(ZBX_PROCESS_TYPE_WATCHDOG, CONFIG_WATCHDOG_FORKS); main_watchdog_loop(); } else if (server_num <= (server_count += CONFIG_POLLER_FORKS)) { #ifdef HAVE_SNMP init_snmp("zabbix_server"); #endif INIT_SERVER(ZBX_PROCESS_TYPE_POLLER, CONFIG_POLLER_FORKS); main_poller_loop(ZBX_POLLER_TYPE_NORMAL); } else if (server_num <= (server_count += CONFIG_UNREACHABLE_POLLER_FORKS)) { #ifdef HAVE_SNMP init_snmp("zabbix_server"); #endif INIT_SERVER(ZBX_PROCESS_TYPE_UNREACHABLE, CONFIG_UNREACHABLE_POLLER_FORKS); main_poller_loop(ZBX_POLLER_TYPE_UNREACHABLE); } else if (server_num <= (server_count += CONFIG_TRAPPER_FORKS)) { INIT_SERVER(ZBX_PROCESS_TYPE_TRAPPER, CONFIG_TRAPPER_FORKS); main_trapper_loop(&listen_sock); } else if (server_num <= (server_count += CONFIG_PINGER_FORKS)) { INIT_SERVER(ZBX_PROCESS_TYPE_PINGER, CONFIG_PINGER_FORKS); main_pinger_loop(); } else if (server_num <= (server_count += CONFIG_ALERTER_FORKS)) { INIT_SERVER(ZBX_PROCESS_TYPE_ALERTER, CONFIG_ALERTER_FORKS); main_alerter_loop(); } else if (server_num <= (server_count += CONFIG_HOUSEKEEPER_FORKS)) { INIT_SERVER(ZBX_PROCESS_TYPE_HOUSEKEEPER, CONFIG_HOUSEKEEPER_FORKS); main_housekeeper_loop(); } else if (server_num <= (server_count += CONFIG_TIMER_FORKS)) { INIT_SERVER(ZBX_PROCESS_TYPE_TIMER, CONFIG_TIMER_FORKS); main_timer_loop(); } else if (server_num <= (server_count += CONFIG_NODEWATCHER_FORKS)) { INIT_SERVER(ZBX_PROCESS_TYPE_NODEWATCHER, CONFIG_NODEWATCHER_FORKS); main_nodewatcher_loop(); } else if (server_num <= (server_count += CONFIG_HTTPPOLLER_FORKS)) { INIT_SERVER(ZBX_PROCESS_TYPE_HTTPPOLLER, CONFIG_HTTPPOLLER_FORKS); main_httppoller_loop(); } else if (server_num <= (server_count += CONFIG_DISCOVERER_FORKS)) { #ifdef HAVE_SNMP init_snmp("zabbix_server"); #endif INIT_SERVER(ZBX_PROCESS_TYPE_DISCOVERER, CONFIG_DISCOVERER_FORKS); main_discoverer_loop(); } else if (server_num <= (server_count += CONFIG_HISTSYNCER_FORKS)) { INIT_SERVER(ZBX_PROCESS_TYPE_HISTSYNCER, CONFIG_HISTSYNCER_FORKS); main_dbsyncer_loop(); } else if (server_num <= (server_count += CONFIG_ESCALATOR_FORKS)) { INIT_SERVER(ZBX_PROCESS_TYPE_ESCALATOR, CONFIG_ESCALATOR_FORKS); main_escalator_loop(); } else if (server_num <= (server_count += CONFIG_IPMIPOLLER_FORKS)) { INIT_SERVER(ZBX_PROCESS_TYPE_IPMIPOLLER, CONFIG_IPMIPOLLER_FORKS); main_poller_loop(ZBX_POLLER_TYPE_IPMI); } else if (server_num <= (server_count += CONFIG_JAVAPOLLER_FORKS)) { INIT_SERVER(ZBX_PROCESS_TYPE_JAVAPOLLER, CONFIG_JAVAPOLLER_FORKS); main_poller_loop(ZBX_POLLER_TYPE_JAVA); } else if (server_num <= (server_count += CONFIG_SNMPTRAPPER_FORKS)) { INIT_SERVER(ZBX_PROCESS_TYPE_SNMPTRAPPER, CONFIG_SNMPTRAPPER_FORKS); main_snmptrapper_loop(); } else if (server_num <= (server_count += CONFIG_PROXYPOLLER_FORKS)) { INIT_SERVER(ZBX_PROCESS_TYPE_PROXYPOLLER, CONFIG_PROXYPOLLER_FORKS); main_proxypoller_loop(); } else if (server_num <= (server_count += CONFIG_SELFMON_FORKS)) { INIT_SERVER(ZBX_PROCESS_TYPE_SELFMON, CONFIG_SELFMON_FORKS); main_selfmon_loop(); } else if (server_num <= (server_count += CONFIG_VMWARE_FORKS)) { INIT_SERVER(ZBX_PROCESS_TYPE_VMWARE, CONFIG_VMWARE_FORKS); main_vmware_loop(); } return SUCCEED; }