diff options
author | Alexander Vladishev <aleksander.vladishev@zabbix.com> | 2021-05-07 18:39:56 +0300 |
---|---|---|
committer | Alexander Vladishev <aleksander.vladishev@zabbix.com> | 2021-05-07 18:39:56 +0300 |
commit | d3d1b6340db4bd59900ef61db90f5cc927dcd59b (patch) | |
tree | 2710aea0bb61e17af0b994b86a1656a04dc77ba0 /src | |
parent | 27d4e37650a3cd785ffc481dcb5c831c7b58f9e1 (diff) | |
parent | 6ef36762644b5d57dc2c96b4aa8392bc7af561f5 (diff) |
.......... [ZBXNEXT-6451,ZBXNEXT-6455] updated to the latest master; fixed conflicts in:
- create/src/schema.tmpl
- include/db.h
- include/zbxhistory.h
- src/libs/zbxdbupgrade/dbupgrade_5030.c
- src/libs/zbxhistory/history.c
- ui/include/defines.inc.php
Diffstat (limited to 'src')
-rw-r--r-- | src/go/cmd/zabbix_agent2/service_windows.go | 37 | ||||
-rw-r--r-- | src/go/plugins/windows/services/services_windows.go | 2 | ||||
-rw-r--r-- | src/libs/zbxdb/db.c | 301 | ||||
-rw-r--r-- | src/libs/zbxdbhigh/db.c | 76 | ||||
-rw-r--r-- | src/libs/zbxdbupgrade/dbupgrade_5030.c | 20 | ||||
-rw-r--r-- | src/libs/zbxhistory/history.c | 13 | ||||
-rw-r--r-- | src/libs/zbxhistory/history.h | 4 | ||||
-rw-r--r-- | src/libs/zbxhistory/history_elastic.c | 127 | ||||
-rw-r--r-- | src/libs/zbxjson/json.c | 6 | ||||
-rw-r--r-- | src/libs/zbxtrends/cache.c | 4 | ||||
-rw-r--r-- | src/zabbix_server/events.c | 1 | ||||
-rw-r--r-- | src/zabbix_server/server.c | 21 |
12 files changed, 565 insertions, 47 deletions
diff --git a/src/go/cmd/zabbix_agent2/service_windows.go b/src/go/cmd/zabbix_agent2/service_windows.go index 441de2b96c7..e7f21ce59a3 100644 --- a/src/go/cmd/zabbix_agent2/service_windows.go +++ b/src/go/cmd/zabbix_agent2/service_windows.go @@ -463,7 +463,7 @@ loop: closeChan <- true break loop default: - log.Warningf("unsupported windows service command received") + log.Debugf("unsupported windows service command '%s' received", getCmdName(c.Cmd)) } case <-stopChan: changes <- svc.Status{State: svc.StopPending} @@ -478,3 +478,38 @@ loop: return } + +func getCmdName(cmd svc.Cmd) string { + switch cmd { + case svc.Stop: + return "Stop" + case svc.Pause: + return "Pause" + case svc.Continue: + return "Continue" + case svc.Interrogate: + return "Interrogate" + case svc.Shutdown: + return "Shutdown" + case svc.ParamChange: + return "ParamChange" + case svc.NetBindAdd: + return "NetBindAdd" + case svc.NetBindRemove: + return "NetBindRemove" + case svc.NetBindEnable: + return "NetBindEnable" + case svc.NetBindDisable: + return "NetBindDisable" + case svc.DeviceEvent: + return "DeviceEvent" + case svc.HardwareProfileChange: + return "HardwareProfileChange" + case svc.PowerEvent: + return "PowerEvent" + case svc.SessionChange: + return "SessionChange" + default: + return "unknown" + } +} diff --git a/src/go/plugins/windows/services/services_windows.go b/src/go/plugins/windows/services/services_windows.go index 0e14aa9fb20..e179ff08180 100644 --- a/src/go/plugins/windows/services/services_windows.go +++ b/src/go/plugins/windows/services/services_windows.go @@ -420,7 +420,7 @@ func (p *Plugin) exportServices(params []string) (result interface{}, err error) } stateFilter := stateFlagAll - if len(params) > 1 && params[1] != "" { + if len(params) > 1 && params[1] != "all" && params[1] != "" { switch params[1] { case "stopped": stateFilter = stateFlagStopped diff --git a/src/libs/zbxdb/db.c b/src/libs/zbxdb/db.c index 8a385625755..672f5226b67 100644 --- a/src/libs/zbxdb/db.c +++ b/src/libs/zbxdb/db.c @@ -45,7 +45,7 @@ struct zbx_db_result MYSQL_RES *result; #elif defined(HAVE_ORACLE) OCIStmt *stmthp; /* the statement handle for select operations */ - int ncolumn; + int ncolumn; DB_ROW values; ub4 *values_alloc; OCILobLocator **clobs; @@ -76,6 +76,8 @@ static int db_auto_increment; #if defined(HAVE_MYSQL) static MYSQL *conn = NULL; +static zbx_uint32_t ZBX_MYSQL_SVERSION = ZBX_DBVERSION_UNDEFINED; +static int ZBX_MARIADB_SFORK = OFF; #elif defined(HAVE_ORACLE) #include "zbxalgo.h" @@ -90,6 +92,8 @@ typedef struct } zbx_oracle_db_handle_t; +static zbx_uint32_t ZBX_ORACLE_SVERSION = ZBX_DBVERSION_UNDEFINED; + static zbx_oracle_db_handle_t oracle; static ub4 OCI_DBserver_status(void); @@ -97,7 +101,8 @@ static ub4 OCI_DBserver_status(void); #elif defined(HAVE_POSTGRESQL) static PGconn *conn = NULL; static unsigned int ZBX_PG_BYTEAOID = 0; -static int ZBX_PG_SVERSION = 0, ZBX_TSDB_VERSION = -1; +static int ZBX_TSDB_VERSION = -1; +static zbx_uint32_t ZBX_PG_SVERSION = ZBX_DBVERSION_UNDEFINED; char ZBX_PG_ESCAPE_BACKSLASH = 1; #elif defined(HAVE_SQLITE3) static sqlite3 *conn = NULL; @@ -786,9 +791,6 @@ int zbx_db_connect(char *host, char *user, char *password, char *dbname, char *d ZBX_PG_BYTEAOID = atoi(row[0]); DBfree_result(result); - ZBX_PG_SVERSION = PQserverVersion(conn); - zabbix_log(LOG_LEVEL_DEBUG, "PostgreSQL Server version: %d", ZBX_PG_SVERSION); - /* disable "nonstandard use of \' in a string literal" warning */ if (0 < (ret = zbx_db_execute("set escape_string_warning to off"))) ret = ZBX_DB_OK; @@ -2438,31 +2440,304 @@ char *zbx_db_dyn_escape_like_pattern(const char *src) * Return value: the string length in bytes * * * ******************************************************************************/ -int zbx_db_strlen_n(const char *text, size_t maxlen) +int zbx_db_strlen_n(const char *text_loc, size_t maxlen) { - return zbx_strlen_utf8_nchars(text, maxlen); + return zbx_strlen_utf8_nchars(text_loc, maxlen); } -#if defined(HAVE_POSTGRESQL) /****************************************************************************** * * - * Function: zbx_dbms_get_version * + * Function: zbx_db_version_check * + * * + * Purpose: determine if a vendor database(MySQL, MariaDB, PostgreSQL, * + * Oracle, ElasticDB) version satisfies Zabbix requirements * + * * + * Parameters: database - [IN] database name * + * current_version - [IN] detected numeric version * + * min_version - [IN] minimum required numeric version * + * max_version - [IN] maximum required numeric version * + * * + * Return value: resulting status flag * + * * + ******************************************************************************/ +int zbx_db_version_check(const char *database, zbx_uint32_t current_version, zbx_uint32_t min_version, + zbx_uint32_t max_version) +{ + int flag; + + if (ZBX_DBVERSION_UNDEFINED == current_version) + { + flag = DB_VERSION_FAILED_TO_RETRIEVE; + zabbix_log(LOG_LEVEL_WARNING, "Failed to retrieve %s version", database); + } + else if (min_version > current_version && ZBX_DBVERSION_UNDEFINED != min_version) + { + flag = DB_VERSION_LOWER_THAN_MINIMUM; + zabbix_log(LOG_LEVEL_WARNING, "Unsupported DB! %s version is %lu which is smaller than minimum of %lu", + database, (unsigned long)current_version, (unsigned long)min_version); + } + else if (max_version < current_version && ZBX_DBVERSION_UNDEFINED != max_version) + { + flag = DB_VERSION_HIGHER_THAN_MAXIMUM; + zabbix_log(LOG_LEVEL_WARNING, "Unsupported DB! %s version is %lu which is higher than maximum of %lu", + database, (unsigned long)current_version, (unsigned long)max_version); + } + else + flag = DB_VERSION_SUPPORTED; + + return flag; +} + +/****************************************************************************** + * * + * Function: zbx_db_version_json_create * + * * + * Purpose: prepare json for front-end with the DB current, minimum and * + * maximum versions and a flag that indicates if the version * + * satisfies the requirements * * * - * Purpose: returns DBMS version as integer: MMmmuu * + * Parameters: json - [IN/OUT] json data * + * database - [IN] name of DB (MySQL/ElasticDB) * + * friendly_current_version - [IN] string current version * + * friendly_min_version - [IN] string min version * + * friendly_max_version - [IN] string max version * + * flag - [IN] status if DB satisfies the * + * requirements * + * * + ******************************************************************************/ +void zbx_db_version_json_create(struct zbx_json *json, const char *database, const char *friendly_current_version, + const char *friendly_min_version, const char *friendly_max_version, int flag) +{ + zbx_json_addobject(json, NULL); + zbx_json_addstring(json, "database", database, ZBX_JSON_TYPE_STRING); + + if (DB_VERSION_FAILED_TO_RETRIEVE != flag) + zbx_json_addstring(json, "current_version", friendly_current_version, ZBX_JSON_TYPE_STRING); + + zbx_json_addstring(json, "min_version", friendly_min_version, ZBX_JSON_TYPE_STRING); + zbx_json_addstring(json, "max_version", friendly_max_version, ZBX_JSON_TYPE_STRING); + zbx_json_addint64(json, "flag", flag); + zbx_json_close(json); +} + +/****************************************************************************** + * * + * Function: zbx_dbms_version_get * + * * + * Purpose: For PostgreSQL, MySQL and MariaDB: * + * returns DBMS version as integer: MMmmuu * * M = major version part * * m = minor version part * * u = patch version part * * * - * Example: 1.2.34 version will be returned as 10234 * + * Example: if the original DB version was 1.2.34 then 10234 gets returned * + * * + * Purpose: For OracleDB: * + * returns DBMS version as integer: MRruRRivUU * + * MR = major release version part * + * ru = release update version part * + * RR = release update version revision part * + * iv = increment version part * + * UU = unused, reserved for future use * + * * + * Example: if the OracleDB version was 18.1.0.0.7 then 1801000007 gets * + * returned * * * - * Return value: DBMS version or 0 if unknown * + * Return value: DBMS version or DBVERSION_UNDEFINED if unknown * * * ******************************************************************************/ -int zbx_dbms_get_version(void) +zbx_uint32_t zbx_dbms_version_get(void) { +#if defined(HAVE_MYSQL) + return ZBX_MYSQL_SVERSION; +#elif defined(HAVE_POSTGRESQL) return ZBX_PG_SVERSION; +#elif defined(HAVE_ORACLE) + return ZBX_ORACLE_SVERSION; +#else + return ZBX_DBVERSION_UNDEFINED; +#endif } +#ifdef HAVE_MYSQL +/****************************************************************************** + * * + * Function: zbx_dbms_mariadb_used * + * * + * Purpose: returns flag if the mariadb was detected * + * * + * Return value: ON - mariadb detected * + * OFF - otherwise (it is unforked mysql) * + ******************************************************************************/ +int zbx_dbms_mariadb_used(void) +{ + return ZBX_MARIADB_SFORK; +} +#endif + +/*************************************************************************************************************** + * * + * Function: zbx_dbms_version_extract * + * * + * Purpose: retrieves the DB version and makes sure it is stored in the numeric format, also fills the json * + * to report to front-end * + * * + * For PostgreSQL: * + * numeric version is available from the API * + * * + * For MySQL and MariaDB: * + * numeric version is available from the API, but also the additional processing is required * + * to determine if it is a MySQL or MariaDB and save this result as well * + * * + * For Oracle: * + * numeric version needs to be manually parsed from the string result * + * Oracle DB format is like 18.1.2.3.0 where * + * 18 - major release version * + * 1 - release update version * + * 2 - release update version revision * + * 3 - increment version * + * 0 - unused, reserved for future use * + * * + * Oracle Examples: * + * For "Oracle Database 18c Express Edition Release 1.0.0.0.0 - Production" => 100000000 * + * For "Oracle Database 18c Express Edition Release 18.2.0.0.7 - Production" => 1802000007 * + * For "Oracle Database 18c Express Edition Release 0.0.34.123.7 - Production" => DBVERSION_UNDEFINED * + * For "Oracle Database 18c Express Edition Release 1.0.3.x.7 - Production" => DBVERISON_UNDEFINED * + * For "<anything else>" => DBVERSION_UNDEFINED * + * * + **************************************************************************************************************/ +zbx_uint32_t zbx_dbms_version_extract(struct zbx_json *json) +{ +#define RIGHT2(x) ((int)((zbx_uint32_t)(x) - ((zbx_uint32_t)((x)/100))*100)) +#if defined(HAVE_MYSQL) + int flag; + const char *info; + char *version_friendly; + + zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); + ZBX_MYSQL_SVERSION = (zbx_uint32_t)mysql_get_server_version(conn); + + if (NULL != (info = mysql_get_server_info(conn)) && NULL != strstr(info, "MariaDB")) + { + zabbix_log(LOG_LEVEL_DEBUG, "MariaDB fork detected"); + ZBX_MARIADB_SFORK = ON; + } + + version_friendly = zbx_dsprintf(NULL, "%d.%.2d.%.2d", RIGHT2(ZBX_MYSQL_SVERSION/10000), + RIGHT2(ZBX_MYSQL_SVERSION/100), RIGHT2(ZBX_MYSQL_SVERSION)); + + if (ON == ZBX_MARIADB_SFORK) + { + flag = zbx_db_version_check("MariaDB", ZBX_MYSQL_SVERSION, ZBX_MARIA_MIN_VERSION, ZBX_DBVERSION_UNDEFINED); + zbx_db_version_json_create(json, "MariaDB", version_friendly, + ZBX_MARIA_MIN_VERSION_FRIENDLY, ZBX_MARIA_MAX_VERSION_FRIENDLY, flag); + } + else + { + flag = zbx_db_version_check("MySQL", ZBX_MYSQL_SVERSION, ZBX_MYSQL_MIN_VERSION, ZBX_MYSQL_MAX_VERSION); + zbx_db_version_json_create(json, "MySQL", version_friendly, + ZBX_MYSQL_MIN_VERSION_FRIENDLY, ZBX_MYSQL_MAX_VERSION_FRIENDLY, flag); + } + + zbx_free(version_friendly); +#elif defined(HAVE_POSTGRESQL) + int flag; + char *version_friendly; + + zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); + ZBX_PG_SVERSION = PQserverVersion(conn); + version_friendly = zbx_dsprintf(NULL, "%d.%d.%d", RIGHT2(ZBX_PG_SVERSION/10000), + RIGHT2(ZBX_PG_SVERSION/100), RIGHT2(ZBX_PG_SVERSION)); + flag = zbx_db_version_check("PostgreSQL", ZBX_PG_SVERSION, ZBX_POSTGRESQL_MIN_VERSION, + ZBX_POSTGRESQL_MAX_VERSION); + zbx_db_version_json_create(json, "PostgreSQL", version_friendly, + ZBX_POSTGRESQL_MIN_VERSION_FRIENDLY, ZBX_POSTGRESQL_MAX_VERSION_FRIENDLY, flag); + zbx_free(version_friendly); +#elif defined(HAVE_ORACLE) +# ifdef HAVE_OCI_SERVER_RELEASE2 + char *version_str = "Version "; + ub4 oci_ver = 0; +# endif + char *start, *release_str = "Release "; + char version_friendly[MAX_STRING_LEN / 8]; + int flag, major_release_version, release_update_version, release_update_version_revision, + increment_version, reserved_for_future_use, overall_status = SUCCEED; + + zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); +# ifdef HAVE_OCI_SERVER_RELEASE2 + if (OCI_SUCCESS != OCIServerRelease2(oracle.svchp, oracle.errhp, (OraText *) version_friendly, + (ub4)sizeof(version_friendly), OCI_HTYPE_SVCCTX, &oci_ver, OCI_DEFAULT)) +# else + if (OCI_SUCCESS != OCIServerVersion(oracle.svchp, oracle.errhp, (OraText *) version_friendly, + (ub4)sizeof(version_friendly), OCI_HTYPE_SVCCTX)) +# endif + { + overall_status = FAIL; + goto out; + } + + zabbix_log(LOG_LEVEL_DEBUG, "OracleDB version retrieved unparsed: %s", version_friendly); + + if ( +# ifdef HAVE_OCI_SERVER_RELEASE2 + NULL != (start = strstr(version_friendly, version_str)) || +# endif + NULL != (start = strstr(version_friendly, release_str))) + { + size_t next_start_index; + + next_start_index = start - version_friendly + strlen(release_str); /* same length for version_str */ + + if (5 != sscanf(version_friendly + next_start_index, "%d.%d.%d.%d.%d", &major_release_version, + &release_update_version, &release_update_version_revision, &increment_version, + &reserved_for_future_use) || major_release_version >= 100 || + major_release_version <= 0 || release_update_version >= 100 || + release_update_version < 0 || release_update_version_revision >= 100 || + release_update_version_revision < 0 || increment_version >= 100 || + increment_version < 0) + { + zabbix_log(LOG_LEVEL_WARNING, "Unexpected Oracle DB version format: %s", version_friendly); + overall_status = FAIL; + } + } + else + { + zabbix_log(LOG_LEVEL_WARNING, "Cannot find Release keyword in Oracle DB version."); + overall_status = FAIL; + } +out: + if (FAIL == overall_status) + { + zabbix_log(LOG_LEVEL_WARNING, "Failed to detect OracleDB version"); + ZBX_ORACLE_SVERSION = ZBX_DBVERSION_UNDEFINED; + } + else + { + ZBX_ORACLE_SVERSION = major_release_version * 100000000 + release_update_version * 1000000 + + release_update_version_revision * 10000 + increment_version * 100 + + reserved_for_future_use; +# ifndef HAVE_OCI_SERVER_RELEASE2 + if (18 <= major_release_version) + { + zabbix_log(LOG_LEVEL_WARNING, "Unable to determine the accurate Oracle DB version " + "(possibly there is a DB driver - DB version mismatch, " + "only the major Oracle DB version can be established): %s", version_friendly); + } +# endif + } + + flag = zbx_db_version_check("Oracle", ZBX_ORACLE_SVERSION, ZBX_ORACLE_MIN_VERSION, ZBX_ORACLE_MAX_VERSION); + zbx_db_version_json_create(json, "Oracle", version_friendly, ZBX_ORACLE_MIN_VERSION_FRIENDLY, + ZBX_ORACLE_MAX_VERSION_FRIENDLY, flag); +#else + zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); +#endif + zabbix_log(LOG_LEVEL_DEBUG, "End of %s() version:%lu", __func__, (unsigned long)zbx_dbms_version_get()); + + return zbx_dbms_version_get(); +} + +#if defined(HAVE_POSTGRESQL) /****************************************************************************** * * * Function: zbx_tsdb_get_version * diff --git a/src/libs/zbxdbhigh/db.c b/src/libs/zbxdbhigh/db.c index 9b2b1fe7c17..7b4bdc7ab36 100644 --- a/src/libs/zbxdbhigh/db.c +++ b/src/libs/zbxdbhigh/db.c @@ -851,18 +851,65 @@ zbx_uint64_t DBget_maxid_num(const char *tablename, int num) /****************************************************************************** * * + * Function: DBextract_version * + * * + * Purpose: connects to DB and tries to detect DB version * + * * + ******************************************************************************/ +zbx_uint32_t DBextract_version(struct zbx_json *json) +{ + zbx_uint32_t ret; + + DBconnect(ZBX_DB_CONNECT_NORMAL); + ret = zbx_dbms_version_extract(json); + DBclose(); + + return ret; +} + +/****************************************************************************** + * * + * Function: DBflush_version_requirements * + * * + * Purpose: writes a json entry in DB with the result for the front-end * + * * + * Parameters: version - [IN] entry of DB versions * + * * + ******************************************************************************/ +void DBflush_version_requirements(const char *version) +{ + zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); + + DBconnect(ZBX_DB_CONNECT_NORMAL); + + if (ZBX_DB_OK > DBexecute("update config set dbversion_status='%s'", version)) + zabbix_log(LOG_LEVEL_CRIT, "Failed to set dbversion_status"); + + DBclose(); + + zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__); +} + +/****************************************************************************** + * * * Function: DBcheck_capabilities * * * * Purpose: checks DBMS for optional features and exit if is not suitable * * * + * Parameters: db_version - [IN] version of DB * + * * + * Return value: SUCCEED - if optional features were checked successfully * + * FAIL - otherwise * + * * ******************************************************************************/ -void DBcheck_capabilities(void) +int DBcheck_capabilities(zbx_uint32_t db_version) { + int ret = SUCCEED; #ifdef HAVE_POSTGRESQL #define MIN_POSTGRESQL_VERSION_WITH_TIMESCALEDB 100002 #define MIN_TIMESCALEDB_VERSION 10500 - int postgresql_version, timescaledb_version; + int timescaledb_version; DB_RESULT result; DB_ROW row; @@ -880,22 +927,20 @@ void DBcheck_capabilities(void) if (0 != zbx_strcmp_null(row[0], ZBX_CONFIG_DB_EXTENSION_TIMESCALE)) goto clean; + ret = FAIL; /* In case of major upgrade, db_extension may be missing */ + /* Timescale compression feature is available in PostgreSQL 10.2 and TimescaleDB 1.5.0 */ - if (MIN_POSTGRESQL_VERSION_WITH_TIMESCALEDB > (postgresql_version = zbx_dbms_get_version())) + if (MIN_POSTGRESQL_VERSION_WITH_TIMESCALEDB > db_version) { - zabbix_log(LOG_LEVEL_CRIT, "PostgreSQL version %d is not supported with TimescaleDB, minimum is %d", - postgresql_version, MIN_POSTGRESQL_VERSION_WITH_TIMESCALEDB); - DBfree_result(result); - DBclose(); - exit(EXIT_FAILURE); + zabbix_log(LOG_LEVEL_CRIT, "PostgreSQL version %lu is not supported with TimescaleDB, minimum is %d", + (unsigned long)db_version, MIN_POSTGRESQL_VERSION_WITH_TIMESCALEDB); + goto clean; } if (0 == (timescaledb_version = zbx_tsdb_get_version())) { zabbix_log(LOG_LEVEL_CRIT, "Cannot determine TimescaleDB version"); - DBfree_result(result); - DBclose(); - exit(EXIT_FAILURE); + goto clean; } zabbix_log(LOG_LEVEL_INFORMATION, "TimescaleDB version: %d", timescaledb_version); @@ -904,15 +949,18 @@ void DBcheck_capabilities(void) { zabbix_log(LOG_LEVEL_CRIT, "TimescaleDB version %d is not supported, minimum is %d", timescaledb_version, MIN_TIMESCALEDB_VERSION); - DBfree_result(result); - DBclose(); - exit(EXIT_FAILURE); + goto clean; } + + ret = SUCCEED; clean: DBfree_result(result); out: DBclose(); +#else + ZBX_UNUSED(db_version); #endif + return ret; } #define MAX_EXPRESSIONS 950 diff --git a/src/libs/zbxdbupgrade/dbupgrade_5030.c b/src/libs/zbxdbupgrade/dbupgrade_5030.c index 58642d87a83..cbc421eb2fa 100644 --- a/src/libs/zbxdbupgrade/dbupgrade_5030.c +++ b/src/libs/zbxdbupgrade/dbupgrade_5030.c @@ -4654,6 +4654,13 @@ static int DBpatch_5030163(void) return DBadd_field("config", &field); } +static int DBpatch_5030164(void) +{ + const ZBX_FIELD field = {"dbversion_status", "", NULL, NULL, 1024, ZBX_TYPE_CHAR, ZBX_NOTNULL, 0}; + + return DBadd_field("config", &field); +} + /* trigger function conversion to new syntax */ #define ZBX_DBPATCH_FUNCTION_UPDATE_NAME 0x01 @@ -5632,7 +5639,7 @@ static int dbpatch_convert_trigger(zbx_dbpatch_trigger_t *trigger, zbx_vector_pt return SUCCEED; } -static int DBpatch_5030164(void) +static int DBpatch_5030165(void) { int i, ret = SUCCEED; DB_ROW row; @@ -5776,7 +5783,7 @@ static int DBpatch_5030164(void) return ret; } -static int DBpatch_5030165(void) +static int DBpatch_5030166(void) { if (0 == (program_type & ZBX_PROGRAM_TYPE_SERVER)) return SUCCEED; @@ -5966,7 +5973,7 @@ static int dbpatch_convert_expression_macro(const char *expression, const zbx_st return SUCCEED; } -static int DBpatch_5030166(void) +static int DBpatch_5030167(void) { DB_ROW row; DB_RESULT result; @@ -6160,7 +6167,7 @@ static char *dbpatch_formula_to_expression(zbx_uint64_t itemid, const char *form return exp; } -static int DBpatch_5030167(void) +static int DBpatch_5030168(void) { DB_ROW row; DB_RESULT result; @@ -6370,7 +6377,7 @@ static int dbpatch_aggregate2formula(const char *itemid, const AGENT_REQUEST *re return SUCCEED; } -static int DBpatch_5030168(void) +static int DBpatch_5030169(void) { DB_ROW row; DB_RESULT result; @@ -6429,7 +6436,7 @@ static int DBpatch_5030168(void) return ret; } -static int DBpatch_5030169(void) +static int DBpatch_5030170(void) { #ifdef HAVE_MYSQL return DBcreate_index("items", "items_8", "key_(1024)", 0); @@ -6614,5 +6621,6 @@ DBPATCH_ADD(5030166, 0, 1) DBPATCH_ADD(5030167, 0, 1) DBPATCH_ADD(5030168, 0, 1) DBPATCH_ADD(5030169, 0, 1) +DBPATCH_ADD(5030170, 0, 1) DBPATCH_END() diff --git a/src/libs/zbxhistory/history.c b/src/libs/zbxhistory/history.c index 54bc95ba1a9..3afcdabd790 100644 --- a/src/libs/zbxhistory/history.c +++ b/src/libs/zbxhistory/history.c @@ -456,3 +456,16 @@ void zbx_history_value2variant(const history_value_t *value, unsigned char value } } +/****************************************************************************** + * * + * Function: zbx_history_check_version * + * * + * Purpose: relays the version retrieval logic to the history implementation * + * functions * + * * + ******************************************************************************/ +void zbx_history_check_version(struct zbx_json *json) +{ + if (NULL != CONFIG_HISTORY_STORAGE_URL) + zbx_elastic_version_extract(json); +} diff --git a/src/libs/zbxhistory/history.h b/src/libs/zbxhistory/history.h index e086fa455db..710b9575d70 100644 --- a/src/libs/zbxhistory/history.h +++ b/src/libs/zbxhistory/history.h @@ -20,6 +20,8 @@ #ifndef ZABBIX_HISTORY_H #define ZABBIX_HISTORY_H +#include "zbxjson.h" + #define ZBX_HISTORY_IFACE_SQL 0 #define ZBX_HISTORY_IFACE_ELASTIC 1 @@ -48,5 +50,7 @@ int zbx_history_sql_init(zbx_history_iface_t *hist, unsigned char value_type, ch /* elastic hist */ int zbx_history_elastic_init(zbx_history_iface_t *hist, unsigned char value_type, char **error); +void zbx_elastic_version_extract(struct zbx_json *json); +zbx_uint32_t zbx_elastic_version_get(void); #endif diff --git a/src/libs/zbxhistory/history_elastic.c b/src/libs/zbxhistory/history_elastic.c index 313de56b563..c55e0a97a69 100644 --- a/src/libs/zbxhistory/history_elastic.c +++ b/src/libs/zbxhistory/history_elastic.c @@ -19,7 +19,6 @@ #include "common.h" #include "log.h" -#include "zbxjson.h" #include "zbxalgo.h" #include "dbcache.h" #include "zbxhistory.h" @@ -34,12 +33,13 @@ #define ZBX_IDX_JSON_ALLOCATE 256 #define ZBX_JSON_ALLOCATE 2048 - const char *value_type_str[] = {"dbl", "str", "log", "uint", "text"}; extern char *CONFIG_HISTORY_STORAGE_URL; extern int CONFIG_HISTORY_STORAGE_PIPELINES; +static zbx_uint32_t ZBX_ELASTIC_SVERSION = ZBX_DBVERSION_UNDEFINED; + typedef struct { char *base_url; @@ -479,7 +479,7 @@ try_again: { int fds; CURLMcode code; - char *error; + char *error; zbx_curlpage_t *curl_page; if (CURLM_OK != (code = curl_multi_perform(writer.handle, &running))) @@ -1015,15 +1015,134 @@ int zbx_history_elastic_init(zbx_history_iface_t *hist, unsigned char value_type return SUCCEED; } -#else +/************************************************************************************ + * * + * Function: zbx_elastic_version_extract * + * * + * Purpose: queries elastic search version and extracts the numeric version from * + * the response string * + * * + ************************************************************************************/ +void zbx_elastic_version_extract(struct zbx_json *json) +{ +#define RIGHT2(x) ((int)((zbx_uint32_t)(x) - ((zbx_uint32_t)((x)/100))*100)) + zbx_httppage_t page; + struct zbx_json_parse jp, jp_values, jp_sub; + struct curl_slist *curl_headers; + CURLcode err; + CURLoption opt; + CURL *handle; + size_t version_len = 0; + char *version_friendly = NULL, errbuf[CURL_ERROR_SIZE]; + int flag, major_num, minor_num, increment_num, ret = FAIL; + zbx_uint32_t version; + + zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); + + memset(&page, 0, sizeof(zbx_httppage_t)); + + if (0 != curl_global_init(CURL_GLOBAL_ALL)) + { + zabbix_log(LOG_LEVEL_WARNING, "cannot initialize cURL library"); + goto out; + } + + if (NULL == (handle = curl_easy_init())) + { + zabbix_log(LOG_LEVEL_WARNING, "cannot initialize cURL session"); + goto out; + } + + curl_headers = curl_slist_append(NULL, "Content-Type: application/json"); + + if (CURLE_OK != (err = curl_easy_setopt(handle, opt = CURLOPT_URL, CONFIG_HISTORY_STORAGE_URL)) || + CURLE_OK != (err = curl_easy_setopt(handle, opt = CURLOPT_WRITEFUNCTION, curl_write_cb)) || + CURLE_OK != (err = curl_easy_setopt(handle, opt = CURLOPT_WRITEDATA, &page)) || + CURLE_OK != (err = curl_easy_setopt(handle, opt = CURLOPT_HTTPHEADER, curl_headers)) || + CURLE_OK != (err = curl_easy_setopt(handle, opt = CURLOPT_FAILONERROR, 1L)) || + CURLE_OK != (err = curl_easy_setopt(handle, opt = CURLOPT_ERRORBUFFER, errbuf))) + { + zabbix_log(LOG_LEVEL_WARNING, "cannot set cURL option %d: [%s]", (int)opt, curl_easy_strerror(err)); + goto clean; + } + + *errbuf = '\0'; + + if (CURLE_OK != (err = curl_easy_perform(handle))) + { + elastic_log_error(handle, err, errbuf); + goto clean; + + } + if (SUCCEED != zbx_json_open(page.data, &jp) || + SUCCEED != zbx_json_brackets_open(jp.start, &jp_values) || + SUCCEED != zbx_json_brackets_by_name(&jp_values, "version", &jp_sub) || + SUCCEED != zbx_json_value_by_name_dyn(&jp_sub, "number", &version_friendly, &version_len, NULL)) + { + goto clean; + } + + ret = SUCCEED; +clean: + curl_slist_free_all(curl_headers); + curl_easy_cleanup(handle); +out: + if (FAIL == ret) + { + zabbix_log(LOG_LEVEL_CRIT, "Failed to extract ElasticDB version"); + version = ZBX_DBVERSION_UNDEFINED; + } + else + { + zabbix_log(LOG_LEVEL_DEBUG, "ElasticDB version retrieved unparsed: %s", version_friendly); + + if (3 != sscanf(version_friendly, "%d.%d.%d", &major_num, &minor_num, &increment_num) || + major_num >= 100 || major_num <= 0 || minor_num >= 100 || minor_num < 0 || + increment_num >= 100 || increment_num < 0) + { + zabbix_log(LOG_LEVEL_WARNING, "Failed to detect ElasticDB version from the " + "following query result: %s", version_friendly); + version = ZBX_DBVERSION_UNDEFINED; + } + else + { + version = major_num * 10000 + minor_num * 100 + increment_num; + } + } + + flag = zbx_db_version_check("ElasticDB", version, ZBX_ELASTIC_MIN_VERSION, ZBX_DBVERSION_UNDEFINED); + zbx_db_version_json_create(json, "ElasticDB", version_friendly, ZBX_ELASTIC_MIN_VERSION_FRIENDLY, "", flag); + ZBX_ELASTIC_SVERSION = version; + zbx_free(version_friendly); + zbx_free(page.data); + + zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s version:%lu", __func__, zbx_result_string(ret), + (unsigned long)version); +} + +zbx_uint32_t zbx_elastic_version_get(void) +{ + return ZBX_ELASTIC_SVERSION; +} +#else int zbx_history_elastic_init(zbx_history_iface_t *hist, unsigned char value_type, char **error) { ZBX_UNUSED(hist); ZBX_UNUSED(value_type); *error = zbx_strdup(*error, "cURL library support >= 7.28.0 is required for Elasticsearch history backend"); + return FAIL; } +void zbx_elastic_version_extract(struct zbx_json *json) +{ + ZBX_UNUSED(json); +} + +zbx_uint32_t zbx_elastic_version_get(void) +{ + return ZBX_DBVERSION_UNDEFINED; +} #endif diff --git a/src/libs/zbxjson/json.c b/src/libs/zbxjson/json.c index 7f73a05c0aa..5b0e4a6860e 100644 --- a/src/libs/zbxjson/json.c +++ b/src/libs/zbxjson/json.c @@ -875,11 +875,11 @@ static const char *zbx_json_copy_string(const char *p, char *out, size_t size) while ('\0' != *p) { + unsigned int nbytes, i; + unsigned char uc[4]; /* decoded Unicode character takes 1-4 bytes in UTF-8 */ + switch (*p) { - unsigned int nbytes, i; - unsigned char uc[4]; /* decoded Unicode character takes 1-4 bytes in UTF-8 */ - case '\\': ++p; if (0 == (nbytes = zbx_json_decode_character(&p, uc))) diff --git a/src/libs/zbxtrends/cache.c b/src/libs/zbxtrends/cache.c index 797eb56dfc8..f44f37fad79 100644 --- a/src/libs/zbxtrends/cache.c +++ b/src/libs/zbxtrends/cache.c @@ -90,7 +90,7 @@ static void tfc_free_slot(zbx_tfc_slot_t *slot) cache->free_head = index; } -static zbx_tfc_slot_t *tfc_alloc_slot() +static zbx_tfc_slot_t *tfc_alloc_slot(void) { zbx_uint32_t index; @@ -289,7 +289,7 @@ static void tfc_free_data(zbx_tfc_data_t *data) * Purpose: ensure there is a free slot available * * * ******************************************************************************/ -static void tfc_reserve_slot() +static void tfc_reserve_slot(void) { if (UINT32_MAX == cache->free_head && cache->slots_num == cache->free_slot) { diff --git a/src/zabbix_server/events.c b/src/zabbix_server/events.c index 469c7e33939..67e599fa174 100644 --- a/src/zabbix_server/events.c +++ b/src/zabbix_server/events.c @@ -1829,6 +1829,7 @@ void zbx_export_events(void) zbx_json_addint64(&json, ZBX_PROTO_TAG_VALUE, event->value); zbx_json_adduint64(&json, ZBX_PROTO_TAG_EVENTID, event->eventid); zbx_json_addstring(&json, ZBX_PROTO_TAG_NAME, event->name, ZBX_JSON_TYPE_STRING); + zbx_json_addint64(&json, ZBX_PROTO_TAG_SEVERITY, event->severity); db_trigger_get_hosts(&hosts, &event->trigger); diff --git a/src/zabbix_server/server.c b/src/zabbix_server/server.c index f6b8b348f06..acf3b21a482 100644 --- a/src/zabbix_server/server.c +++ b/src/zabbix_server/server.c @@ -1058,6 +1058,23 @@ static void zbx_main_sigusr_handler(int flags) } +static void zbx_check_db(void) +{ + struct zbx_json db_ver; + + zbx_json_initarray(&db_ver, ZBX_JSON_STAT_BUF_LEN); + + if (SUCCEED != DBcheck_capabilities(DBextract_version(&db_ver)) || SUCCEED != DBcheck_version()) + { + zbx_json_free(&db_ver); + exit(EXIT_FAILURE); + } + + zbx_history_check_version(&db_ver); + DBflush_version_requirements(db_ver.buffer); + zbx_json_free(&db_ver); +} + int MAIN_ZABBIX_ENTRY(int flags) { zbx_socket_t listen_sock; @@ -1252,10 +1269,8 @@ int MAIN_ZABBIX_ENTRY(int flags) exit(EXIT_FAILURE); } - DBcheck_capabilities(); + zbx_check_db(); - if (SUCCEED != DBcheck_version()) - exit(EXIT_FAILURE); DBcheck_character_set(); if (SUCCEED == DBcheck_double_type()) |