Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/zabbix/zabbix.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog.d/bugfix/ZBX-190631
-rw-r--r--ChangeLog.d/bugfix/ZBX-190991
-rw-r--r--ChangeLog.d/feature/ZBXNEXT-49101
-rw-r--r--create/src/schema.tmpl3
-rw-r--r--include/db.h4
-rw-r--r--include/zbxdb.h49
-rw-r--r--include/zbxhistory.h3
-rw-r--r--include/zbxjson.h3
-rw-r--r--m4/ax_lib_oracle_oci.m429
-rw-r--r--src/go/cmd/zabbix_agent2/service_windows.go37
-rw-r--r--src/go/plugins/windows/services/services_windows.go2
-rw-r--r--src/libs/zbxdb/db.c301
-rw-r--r--src/libs/zbxdbhigh/db.c76
-rw-r--r--src/libs/zbxdbupgrade/dbupgrade_5030.c20
-rw-r--r--src/libs/zbxhistory/history.c13
-rw-r--r--src/libs/zbxhistory/history.h4
-rw-r--r--src/libs/zbxhistory/history_elastic.c127
-rw-r--r--src/libs/zbxjson/json.c6
-rw-r--r--src/libs/zbxtrends/cache.c4
-rw-r--r--src/zabbix_server/events.c1
-rw-r--r--src/zabbix_server/server.c21
-rw-r--r--tests/libs/zbxdbcache/Makefile.am2
-rw-r--r--tests/libs/zbxhistory/Makefile.am3
-rwxr-xr-xtests/libs/zbxserver/Makefile.am2
-rw-r--r--tests/mocks/valuecache/valuecache_mock.c11
-rw-r--r--ui/include/defines.inc.php2
-rw-r--r--ui/include/schema.inc.php6
-rw-r--r--ui/tests/bootstrap.php.template3
-rw-r--r--ui/tests/include/CTest.php13
-rw-r--r--ui/tests/include/helpers/CDataHelper.php83
30 files changed, 775 insertions, 56 deletions
diff --git a/ChangeLog.d/bugfix/ZBX-19063 b/ChangeLog.d/bugfix/ZBX-19063
new file mode 100644
index 00000000000..b7710bf7c65
--- /dev/null
+++ b/ChangeLog.d/bugfix/ZBX-19063
@@ -0,0 +1 @@
+...G...... [ZBX-19063] fixed logging for unsupported windows service command in Zabbix agent 2 (esneiders)
diff --git a/ChangeLog.d/bugfix/ZBX-19099 b/ChangeLog.d/bugfix/ZBX-19099
new file mode 100644
index 00000000000..d6fb2138d13
--- /dev/null
+++ b/ChangeLog.d/bugfix/ZBX-19099
@@ -0,0 +1 @@
+...G...... [ZBX-19099] fixed Zabbix agent 2 windows services plugin second parameter (esneiders)
diff --git a/ChangeLog.d/feature/ZBXNEXT-4910 b/ChangeLog.d/feature/ZBXNEXT-4910
new file mode 100644
index 00000000000..dc28d12ee38
--- /dev/null
+++ b/ChangeLog.d/feature/ZBXNEXT-4910
@@ -0,0 +1 @@
+........S. [ZBXNEXT-4910] added severity in problem real-time export protocol (akozlovs)
diff --git a/create/src/schema.tmpl b/create/src/schema.tmpl
index 889c35916f3..31d76a54827 100644
--- a/create/src/schema.tmpl
+++ b/create/src/schema.tmpl
@@ -577,6 +577,7 @@ FIELD |item_test_timeout |t_varchar(32) |'60s' |NOT NULL |ZBX_NODATA
FIELD |session_key |t_varchar(32)|'' |NOT NULL |ZBX_NODATA
FIELD |url |t_varchar(255) |'' |NOT NULL |ZBX_NODATA
FIELD |report_test_timeout|t_varchar(32)|'60s'|NOT NULL |ZBX_NODATA
+FIELD |dbversion_status |t_varchar(1024)|'' |NOT NULL |ZBX_NODATA
INDEX |1 |alert_usrgrpid
INDEX |2 |discovery_groupid
@@ -1846,4 +1847,4 @@ INDEX |1 |reportid
TABLE|dbversion||
FIELD |mandatory |t_integer |'0' |NOT NULL |
FIELD |optional |t_integer |'0' |NOT NULL |
-ROW |5030169 |5030169
+ROW |5030170 |5030170
diff --git a/include/db.h b/include/db.h
index 89645695535..5a49bec9a06 100644
--- a/include/db.h
+++ b/include/db.h
@@ -526,7 +526,9 @@ const ZBX_FIELD *DBget_field(const ZBX_TABLE *table, const char *fieldname);
#define DBget_maxid(table) DBget_maxid_num(table, 1)
zbx_uint64_t DBget_maxid_num(const char *tablename, int num);
-void DBcheck_capabilities(void);
+zbx_uint32_t DBextract_version(struct zbx_json *json);
+void DBflush_version_requirements(const char *version);
+int DBcheck_capabilities(zbx_uint32_t db_version);
#ifdef HAVE_POSTGRESQL
char *zbx_db_get_schema_esc(void);
diff --git a/include/zbxdb.h b/include/zbxdb.h
index 1631ee022d7..50a8a87797c 100644
--- a/include/zbxdb.h
+++ b/include/zbxdb.h
@@ -21,6 +21,7 @@
#define ZABBIX_ZBXDB_H
#include "common.h"
+#include "zbxjson.h"
#define ZBX_DB_OK 0
#define ZBX_DB_FAIL -1
@@ -97,7 +98,6 @@ int zbx_db_txn_end_error(void);
const char *zbx_db_last_strerr(void);
#ifdef HAVE_POSTGRESQL
-int zbx_dbms_get_version(void);
int zbx_tsdb_get_version(void);
#define ZBX_DB_TSDB_V1 (20000 > zbx_tsdb_get_version())
#endif
@@ -145,6 +145,51 @@ char *zbx_db_dyn_escape_string(const char *src, size_t max_bytes, size_t max_ch
#define ZBX_SQL_LIKE_ESCAPE_CHAR '!'
char *zbx_db_dyn_escape_like_pattern(const char *src);
-int zbx_db_strlen_n(const char *text, size_t maxlen);
+int zbx_db_strlen_n(const char *text_loc, size_t maxlen);
+
+#define ZBX_MYSQL_MIN_VERSION 50728
+#define ZBX_MYSQL_MIN_VERSION_FRIENDLY "5.07.28"
+#define ZBX_MYSQL_MAX_VERSION 80099
+#define ZBX_MYSQL_MAX_VERSION_FRIENDLY "8.00.x"
+
+#define ZBX_MARIA_MIN_VERSION 100037
+#define ZBX_MARIA_MIN_VERSION_FRIENDLY "10.00.37"
+#define ZBX_MARIA_MAX_VERSION 100599
+#define ZBX_MARIA_MAX_VERSION_FRIENDLY "10.05.x"
+
+#define ZBX_POSTGRESQL_MIN_VERSION 100900
+#define ZBX_POSTGRESQL_MIN_VERSION_FRIENDLY "10.9"
+#define ZBX_POSTGRESQL_MAX_VERSION 139999
+#define ZBX_POSTGRESQL_MAX_VERSION_FRIENDLY "13.x"
+
+#define ZBX_ORACLE_MIN_VERSION 1201000200
+#define ZBX_ORACLE_MIN_VERSION_FRIENDLY "Database 12c Release 12.01.00.02.x"
+#define ZBX_ORACLE_MAX_VERSION 1901000000
+#define ZBX_ORACLE_MAX_VERSION_FRIENDLY "Database 19c Release 19.1.0"
+
+#define ZBX_ELASTIC_MIN_VERSION 70000
+#define ZBX_ELASTIC_MIN_VERSION_FRIENDLY "7.x"
+
+#define ZBX_DBVERSION_UNDEFINED 0
+
+typedef enum
+{ /* db version status flags shared with FRONTEND */
+ DB_VERSION_SUPPORTED,
+ DB_VERSION_LOWER_THAN_MINIMUM,
+ DB_VERSION_HIGHER_THAN_MAXIMUM,
+ DB_VERSION_FAILED_TO_RETRIEVE
+} zbx_db_version_status_t;
+
+zbx_uint32_t zbx_dbms_version_get(void);
+zbx_uint32_t zbx_dbms_version_extract(struct zbx_json *json);
+
+#ifdef HAVE_MYSQL
+int zbx_dbms_mariadb_used(void);
+#endif
+
+int zbx_db_version_check(const char *database, zbx_uint32_t current_version, zbx_uint32_t min_version,
+ zbx_uint32_t max_version);
+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);
#endif
diff --git a/include/zbxhistory.h b/include/zbxhistory.h
index 788864aa1e5..e02bee7568a 100644
--- a/include/zbxhistory.h
+++ b/include/zbxhistory.h
@@ -21,6 +21,7 @@
#define ZABBIX_ZBXHISTORY_H
#include "zbxvariant.h"
+#include "zbxjson.h"
/* the item history value */
typedef struct
@@ -58,6 +59,6 @@ int zbx_history_get_values(zbx_uint64_t itemid, int value_type, int start, int c
zbx_vector_history_record_t *values);
int zbx_history_requires_trends(int value_type);
-
+void zbx_history_check_version(struct zbx_json *json);
#endif
diff --git a/include/zbxjson.h b/include/zbxjson.h
index 1a3971e02be..ba766305d69 100644
--- a/include/zbxjson.h
+++ b/include/zbxjson.h
@@ -80,6 +80,7 @@
#define ZBX_PROTO_TAG_JMX_ENDPOINT "jmx_endpoint"
#define ZBX_PROTO_TAG_EVENTID "eventid"
#define ZBX_PROTO_TAG_NAME "name"
+#define ZBX_PROTO_TAG_SEVERITY "severity"
#define ZBX_PROTO_TAG_HOSTS "hosts"
#define ZBX_PROTO_TAG_GROUPS "groups"
#define ZBX_PROTO_TAG_TAGS "tags"
@@ -289,8 +290,6 @@ void zbx_json_escape(char **string);
int zbx_json_open_path(const struct zbx_json_parse *jp, const char *path, struct zbx_json_parse *out);
zbx_json_type_t zbx_json_valuetype(const char *p);
-void zbx_json_log(const struct zbx_json_parse *jp, int loglevel);
-
/* jsonpath support */
typedef struct zbx_jsonpath_segment zbx_jsonpath_segment_t;
diff --git a/m4/ax_lib_oracle_oci.m4 b/m4/ax_lib_oracle_oci.m4
index cb8ccdb4785..ec1efd0a5e9 100644
--- a/m4/ax_lib_oracle_oci.m4
+++ b/m4/ax_lib_oracle_oci.m4
@@ -291,7 +291,7 @@ Please, locate Oracle directories using --with-oracle or \
AC_LINK_IFELSE([
AC_LANG_PROGRAM([[@%:@include <oci.h>]],
[[
-OCIEnv* envh = 0;
+OCIEnv *envh = 0;
OCIEnvNlsCreate(&envh, OCI_DEFAULT, 0, 0, 0, 0, 0, 0, 0, 0);
if (envh) OCIHandleFree(envh, OCI_HTYPE_ENV);
]]
@@ -309,6 +309,33 @@ if (envh) OCIHandleFree(envh, OCI_HTYPE_ENV);
)
fi
+ dnl
+ dnl Check OCIServerRelease2() API
+ dnl
+ if test "$oci_header_found" = "yes"; then
+
+ AC_MSG_CHECKING([for Oracle OCIServerRelease2() API in $oracle_lib_dir])
+
+ AC_LINK_IFELSE([
+ AC_LANG_PROGRAM([[@%:@include <oci.h>]],
+ [[
+OCIEnv *envh = 0;
+OCIError *errh = 0;
+OraText buf[256];
+ub4 version;
+sword ret = OCIServerRelease2(envh, errh, buf, (ub4)sizeof(buf), OCI_HTYPE_SVCCTX, &version, OCI_DEFAULT);
+ ]]
+ )],
+ [
+ AC_DEFINE(HAVE_OCI_SERVER_RELEASE2, 1, [Define to 1 if OCIServerRelease2 API are supported.])
+ AC_MSG_RESULT(yes)
+ ],
+ [
+ AC_MSG_RESULT([no])
+ ]
+ )
+ fi
+
CPPFLAGS="$saved_CPPFLAGS"
LDFLAGS="$saved_LDFLAGS"
LIBS="$saved_LIBS"
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())
diff --git a/tests/libs/zbxdbcache/Makefile.am b/tests/libs/zbxdbcache/Makefile.am
index 42ec3ded75b..df2e13eb9d5 100644
--- a/tests/libs/zbxdbcache/Makefile.am
+++ b/tests/libs/zbxdbcache/Makefile.am
@@ -82,6 +82,8 @@ COMMON_WRAP_FUNCS = \
-Wl,--wrap=zbx_history_add_values \
-Wl,--wrap=zbx_history_sql_init \
-Wl,--wrap=zbx_history_elastic_init \
+ -Wl,--wrap=zbx_elastic_version_extract \
+ -Wl,--wrap=zbx_elastic_version_get \
-Wl,--wrap=time
zbx_vc_get_values_SOURCES = \
diff --git a/tests/libs/zbxhistory/Makefile.am b/tests/libs/zbxhistory/Makefile.am
index 6f8f5eacfee..c28a45c55e9 100644
--- a/tests/libs/zbxhistory/Makefile.am
+++ b/tests/libs/zbxhistory/Makefile.am
@@ -22,6 +22,9 @@ HISTORY_LIBS = \
$(top_srcdir)/src/libs/zbxcommon/libzbxcommon.a \
$(top_srcdir)/src/libs/zbxdbhigh/libzbxdbhigh.a \
$(top_srcdir)/src/libs/zbxdb/libzbxdb.a \
+ $(top_srcdir)/src/libs/zbxjson/libzbxjson.a \
+ $(top_srcdir)/src/libs/zbxregexp/libzbxregexp.a \
+ $(top_srcdir)/src/libs/zbxcommon/libzbxcommon.a \
$(top_srcdir)/tests/libzbxmockdata.a
zbx_history_get_values_SOURCES = \
diff --git a/tests/libs/zbxserver/Makefile.am b/tests/libs/zbxserver/Makefile.am
index b4c9a175ce1..17ac0c03494 100755
--- a/tests/libs/zbxserver/Makefile.am
+++ b/tests/libs/zbxserver/Makefile.am
@@ -139,6 +139,8 @@ VALUECACHE_WRAP_FUNCS = \
-Wl,--wrap=zbx_history_add_values \
-Wl,--wrap=zbx_history_sql_init \
-Wl,--wrap=zbx_history_elastic_init \
+ -Wl,--wrap=zbx_elastic_version_extract \
+ -Wl,--wrap=zbx_elastic_version_get \
-Wl,--wrap=time \
-Wl,--wrap=substitute_simple_macros \
-Wl,--wrap=DCget_data_expected_from \
diff --git a/tests/mocks/valuecache/valuecache_mock.c b/tests/mocks/valuecache/valuecache_mock.c
index f8564929d4f..323bc8fc773 100644
--- a/tests/mocks/valuecache/valuecache_mock.c
+++ b/tests/mocks/valuecache/valuecache_mock.c
@@ -54,6 +54,8 @@ int __wrap_zbx_history_get_values(zbx_uint64_t itemid, int value_type, int start
int __wrap_zbx_history_add_values(const zbx_vector_ptr_t *history);
int __wrap_zbx_history_sql_init(zbx_history_iface_t *hist, unsigned char value_type, char **error);
int __wrap_zbx_history_elastic_init(zbx_history_iface_t *hist, unsigned char value_type, char **error);
+void __wrap_zbx_elastic_version_extract(void);
+int __wrap_zbx_elastic_version_get(void);
time_t __wrap_time(time_t *ptr);
void __wrap_zbx_timespec(zbx_timespec_t *ts);
@@ -685,6 +687,15 @@ int __wrap_zbx_history_elastic_init(zbx_history_iface_t *hist, unsigned char val
return SUCCEED;
}
+void __wrap_zbx_elastic_version_extract(void)
+{
+}
+
+int __wrap_zbx_elastic_version_get(void)
+{
+ return ZBX_DBVERSION_UNDEFINED;
+}
+
/*
* cache allocator size limit handling
*/
diff --git a/ui/include/defines.inc.php b/ui/include/defines.inc.php
index f6f8ac3bd0b..faa34521a68 100644
--- a/ui/include/defines.inc.php
+++ b/ui/include/defines.inc.php
@@ -21,7 +21,7 @@
define('ZABBIX_VERSION', '5.4.0rc1');
define('ZABBIX_API_VERSION', '5.4.0');
define('ZABBIX_EXPORT_VERSION', '5.4');
-define('ZABBIX_DB_VERSION', 5030169);
+define('ZABBIX_DB_VERSION', 5030170);
define('ZABBIX_COPYRIGHT_FROM', '2001');
define('ZABBIX_COPYRIGHT_TO', '2021');
diff --git a/ui/include/schema.inc.php b/ui/include/schema.inc.php
index 69b7237bb63..041f9b75932 100644
--- a/ui/include/schema.inc.php
+++ b/ui/include/schema.inc.php
@@ -2712,6 +2712,12 @@ return [
'type' => DB::FIELD_TYPE_CHAR,
'length' => 32,
'default' => '60s'
+ ],
+ 'dbversion_status' => [
+ 'null' => false,
+ 'type' => DB::FIELD_TYPE_CHAR,
+ 'length' => 1024,
+ 'default' => ''
]
]
],
diff --git a/ui/tests/bootstrap.php.template b/ui/tests/bootstrap.php.template
index 5ee1a8d5d5d..468b34b683b 100644
--- a/ui/tests/bootstrap.php.template
+++ b/ui/tests/bootstrap.php.template
@@ -26,6 +26,9 @@ define('PHPUNIT_CONFIG_DIR', '{CONFIG_DIR}');
define('PHPUNIT_COMPONENT_DIR', '{COMPONENT_DIR}');
define('PHPUNIT_PORT_PREFIX', '{PORT_PREFIX}');
+define('PHPUNIT_DATA_DIR', '{DATA_DIR}');
+define('PHPUNIT_DATA_SOURCES_DIR', '{DATA_SOURCES_DIR}');
+
// SAML settings.
define('PHPUNIT_SAML_TESTS_ENABLED', false);
define('PHPUNIT_IDP_ENTITY_ID', '{PHPUNIT_IDP_ENTITY_ID}');
diff --git a/ui/tests/include/CTest.php b/ui/tests/include/CTest.php
index 021798b0ee9..78b77aaafd2 100644
--- a/ui/tests/include/CTest.php
+++ b/ui/tests/include/CTest.php
@@ -25,6 +25,7 @@ require_once dirname(__FILE__).'/../../include/hosts.inc.php';
require_once dirname(__FILE__).'/helpers/CDBHelper.php';
require_once dirname(__FILE__).'/helpers/CAPIHelper.php';
+require_once dirname(__FILE__).'/helpers/CDataHelper.php';
require_once dirname(__FILE__).'/helpers/CExceptionHelper.php';
require_once dirname(__FILE__).'/helpers/CTestArrayHelper.php';
require_once dirname(__FILE__).'/helpers/CDateTimeHelper.php';
@@ -200,6 +201,12 @@ class CTest extends PHPUnit_Framework_TestCase {
// Test suite level annotations.
$class_annotations = $this->getAnnotationsByType($this->annotations, 'class');
+ // Data sources are processed before the backups.
+ $data_source = $this->getAnnotationTokensByName($class_annotations, 'dataSource');
+ if ($data_source) {
+ CDataHelper::load($data_source);
+ }
+
// Backup performed before test suite execution.
$suite_backup = $this->getAnnotationTokensByName($class_annotations, 'backup');
@@ -274,6 +281,12 @@ class CTest extends PHPUnit_Framework_TestCase {
$method_annotations = $this->getAnnotationsByType($this->annotations, 'method');
if ($method_annotations !== null) {
+ // Data sources are processed before the backups.
+ $data_source = $this->getAnnotationTokensByName($method_annotations, 'dataSource');
+ if ($data_source) {
+ CDataHelper::load($data_source);
+ }
+
// Backup performed before every test case execution.
$case_backup = $this->getAnnotationTokensByName($method_annotations, 'backup');
diff --git a/ui/tests/include/helpers/CDataHelper.php b/ui/tests/include/helpers/CDataHelper.php
index 764ab0c9c81..6814d576012 100644
--- a/ui/tests/include/helpers/CDataHelper.php
+++ b/ui/tests/include/helpers/CDataHelper.php
@@ -26,6 +26,7 @@ require_once dirname(__FILE__).'/../../../include/hosts.inc.php';
class CDataHelper extends CAPIHelper {
+ protected static $data = null;
protected static $request = [];
protected static $response = [];
@@ -216,4 +217,86 @@ class CDataHelper extends CAPIHelper {
return $result;
}
+
+ /**
+ * Load the data source data from the file cache.
+ */
+ protected static function preload() {
+ if (static::$data === null) {
+ static::$data = [];
+
+ if (!defined('PHPUNIT_DATA_DIR')) {
+ return;
+ }
+
+ foreach (new DirectoryIterator(PHPUNIT_DATA_DIR) as $file) {
+ if ($file->isDot() || $file->isDir() || strtolower($file->getExtension()) !== 'json') {
+ continue;
+ }
+
+ $name = $file->getBasename('.'.$file->getExtension());
+ static::$data[$name] = json_decode(file_get_contents($file->getPathname()), true);
+ }
+ }
+ }
+
+ /**
+ * Get data from the data sources.
+ *
+ * @param mixed $path data path to look for
+ * @param mixed $default default value to be returned if data doesn't exist
+ *
+ * @return mixed
+ */
+ public static function get($path, $default = null) {
+ return CTestArrayHelper::get(static::$data, $path, $default);
+ }
+
+ /**
+ * Load specific data source data.
+ *
+ * @param mixed $source name of the data source(s)
+ *
+ * @return boolean
+ *
+ * @throws \Exception
+ */
+ public static function load($source) {
+ if (is_array($source)) {
+ $result = true;
+ foreach ($source as $name) {
+ $result &= static::load($name);
+ }
+
+ return $result;
+ }
+
+ static::preload();
+
+ if (array_key_exists($source, static::$data)) {
+ return true;
+ }
+
+ try {
+ $path = PHPUNIT_DATA_SOURCES_DIR.$source.'.php';
+ if (!file_exists($path)) {
+ throw new \Exception('File "'.$path.'" doesn\'t exist.');
+ }
+
+ require_once $path;
+ static::$data[$source] = forward_static_call([$source, 'load']);
+
+ if (defined('PHPUNIT_DATA_DIR')) {
+ $data = json_encode(static::get($source));
+ file_put_contents(PHPUNIT_DATA_DIR.$source.'.json', $data);
+ }
+ }
+ catch (\Exception $e) {
+ echo 'Failed to load data from data source "'.$source.'".'."\n\n".$e->getMessage()."\n".$e->getTraceAsString();
+
+ return false;
+ }
+
+ return true;
+ }
}