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:
authorVladimirs Maksimovs <vladimirs.maksimovs@zabbix.com>2022-01-05 15:23:12 +0300
committerVladimirs Maksimovs <vladimirs.maksimovs@zabbix.com>2022-01-05 15:23:12 +0300
commita893912ab552fc44521662e22974b8586e984385 (patch)
tree4941370c95a81fdd799cc543bf56740cb210e894
parent583678511bd86c1e53df42b34d6525bb2cdeb971 (diff)
parent6ce43839b8c77e8789cb3ddf3416b48228dcba8a (diff)
.......... [ZBXNEXT-6470,ZBXNEXT-6890] updated to latest from master; no conflicts
-rw-r--r--ChangeLog.d/bugfix/ZBX-201431
-rw-r--r--ChangeLog.d/bugfix/ZBX-202361
-rw-r--r--ChangeLog.d/bugfix/ZBX-202921
-rw-r--r--ChangeLog.d/feature/ZBXNEXT-71091
-rw-r--r--configure.ac1
-rw-r--r--database/mysql/Makefile.am3
-rw-r--r--database/oracle/Makefile.am3
-rw-r--r--database/postgresql/Makefile.am3
-rw-r--r--include/common.h8
-rw-r--r--include/daemon.h3
-rw-r--r--include/dbcache.h8
-rw-r--r--include/log.h4
-rw-r--r--include/proxy.h2
-rw-r--r--include/zbxdiag.h2
-rw-r--r--include/zbxha.h27
-rw-r--r--include/zbxjson.h6
-rw-r--r--include/zbxrtc.h41
-rw-r--r--src/libs/Makefile.am9
-rw-r--r--src/libs/zbxcomms/comms.c1
-rw-r--r--src/libs/zbxdbcache/dbconfig.c47
-rw-r--r--src/libs/zbxdbhigh/proxy.c16
-rw-r--r--src/libs/zbxdiag/diag.c118
-rw-r--r--src/libs/zbxha/ha.c139
-rw-r--r--src/libs/zbxlog/log.c50
-rw-r--r--src/libs/zbxnix/control.c138
-rw-r--r--src/libs/zbxnix/control.h2
-rw-r--r--src/libs/zbxnix/daemon.c90
-rw-r--r--src/libs/zbxrtc/Makefile.am33
-rw-r--r--src/libs/zbxrtc/rtc.c120
-rw-r--r--src/libs/zbxrtc/rtc.h (renamed from src/zabbix_server/rtc.h)8
-rw-r--r--src/libs/zbxrtc/rtc_client.c251
-rw-r--r--src/libs/zbxrtc/rtc_proxy.c54
-rw-r--r--src/libs/zbxrtc/rtc_server.c473
-rw-r--r--src/libs/zbxrtc/rtc_service.c342
-rw-r--r--src/libs/zbxsysinfo/common/dns.c36
-rw-r--r--src/zabbix_agent/zabbix_agentd.c2
-rw-r--r--src/zabbix_proxy/Makefile.am3
-rw-r--r--src/zabbix_proxy/proxy.c85
-rw-r--r--src/zabbix_proxy/proxyconfig/proxyconfig.c70
-rw-r--r--src/zabbix_server/Makefile.am7
-rw-r--r--src/zabbix_server/dbconfig/dbconfig.c18
-rw-r--r--src/zabbix_server/ha/ha.h20
-rw-r--r--src/zabbix_server/ha/ha_manager.c511
-rw-r--r--src/zabbix_server/lld/lld.c8
-rw-r--r--src/zabbix_server/lld/lld.h3
-rw-r--r--src/zabbix_server/lld/lld_item.c2
-rw-r--r--src/zabbix_server/poller/checks_internal_server.c2
-rw-r--r--src/zabbix_server/rtc.c303
-rw-r--r--src/zabbix_server/server.c164
-rw-r--r--src/zabbix_server/trapper/proxyconfig.c34
-rw-r--r--src/zabbix_server/trapper/trapper.c8
-rw-r--r--ui/tests/include/web/CPage.php28
-rw-r--r--ui/tests/selenium/dashboard/testDashboardProblemsBySeverityWidget.php2
-rw-r--r--ui/tests/selenium/reports/testFormScheduledReport.php2
-rw-r--r--ui/tests/selenium/reports/testPageReportsNotifications.php2
-rw-r--r--ui/tests/selenium/roles/testUserRolesPermissions.php2
-rw-r--r--ui/tests/selenium/testFormAdministrationAuthenticationHttp.php2
-rw-r--r--ui/tests/selenium/testFormAdministrationAuthenticationSaml.php4
-rw-r--r--ui/tests/selenium/testFormEventCorrelation.php6
-rw-r--r--ui/tests/selenium/testFormSetup.php8
-rw-r--r--ui/tests/selenium/testFormTrigger.php2
-rw-r--r--ui/tests/selenium/testFormTriggerPrototype.php2
-rw-r--r--ui/tests/selenium/testPageAdministrationGeneralModules.php4
-rw-r--r--ui/tests/selenium/testPageTriggerDescription.php2
-rw-r--r--ui/tests/selenium/testPageTriggerUrl.php4
-rw-r--r--ui/tests/selenium/testSID.php4
-rw-r--r--ui/tests/selenium/testTemplateInheritance.php8
-rw-r--r--ui/tests/selenium/users/testFormUser.php8
-rw-r--r--ui/tests/selenium/users/testFormUserMedia.php4
69 files changed, 2342 insertions, 1034 deletions
diff --git a/ChangeLog.d/bugfix/ZBX-20143 b/ChangeLog.d/bugfix/ZBX-20143
new file mode 100644
index 00000000000..81c37f8226f
--- /dev/null
+++ b/ChangeLog.d/bugfix/ZBX-20143
@@ -0,0 +1 @@
+...G...... [ZBX-20143] fixed tcp timeout not working in net.dns.record (dgoloscapov)
diff --git a/ChangeLog.d/bugfix/ZBX-20236 b/ChangeLog.d/bugfix/ZBX-20236
new file mode 100644
index 00000000000..69a60141c67
--- /dev/null
+++ b/ChangeLog.d/bugfix/ZBX-20236
@@ -0,0 +1 @@
+...G...PS. [ZBX-20236] improved memory consumption in Zabbix proxy trappers by moving configuration sync between database and cache to configuration syncer; improved trappers and listeners memory consumption by freeing received data after it was processed instead of after new data is received (vso)
diff --git a/ChangeLog.d/bugfix/ZBX-20292 b/ChangeLog.d/bugfix/ZBX-20292
new file mode 100644
index 00000000000..47d61cfe09e
--- /dev/null
+++ b/ChangeLog.d/bugfix/ZBX-20292
@@ -0,0 +1 @@
+........S. [ZBX-20292] fixed LLD overrides for item for particular corner-case (ssimonenko)
diff --git a/ChangeLog.d/feature/ZBXNEXT-7109 b/ChangeLog.d/feature/ZBXNEXT-7109
new file mode 100644
index 00000000000..ab5210bf129
--- /dev/null
+++ b/ChangeLog.d/feature/ZBXNEXT-7109
@@ -0,0 +1 @@
+.......PS. [ZBXNEXT-7109] changed runtime control options to connecto to zabbix server/proxy using socket rather than sending signals (wiper)
diff --git a/configure.ac b/configure.ac
index cd3f5475c93..fddcf42116b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2112,6 +2112,7 @@ AC_OUTPUT([
src/libs/zbxservice/Makefile
src/libs/zbxxml/Makefile
src/libs/zbxha/Makefile
+ src/libs/zbxrtc/Makefile
src/zabbix_agent/Makefile
src/zabbix_agent/logfiles/Makefile
src/zabbix_get/Makefile
diff --git a/database/mysql/Makefile.am b/database/mysql/Makefile.am
index 6f7a78934ce..417096c245d 100644
--- a/database/mysql/Makefile.am
+++ b/database/mysql/Makefile.am
@@ -12,4 +12,5 @@ EXTRA_DIST = \
data.sql \
images.sql \
schema.sql \
- double.sql
+ double.sql \
+ history_pk_prepare.sql
diff --git a/database/oracle/Makefile.am b/database/oracle/Makefile.am
index 992167c47ec..11bc82ceab1 100644
--- a/database/oracle/Makefile.am
+++ b/database/oracle/Makefile.am
@@ -12,4 +12,5 @@ EXTRA_DIST = \
data.sql \
images.sql \
schema.sql \
- double.sql
+ double.sql \
+ history_pk_prepare.sql
diff --git a/database/postgresql/Makefile.am b/database/postgresql/Makefile.am
index 1b3eabb8c23..7fd2b92d657 100644
--- a/database/postgresql/Makefile.am
+++ b/database/postgresql/Makefile.am
@@ -17,4 +17,5 @@ EXTRA_DIST = \
images.sql \
schema.sql \
double.sql \
- $(DB_EXTENSION).sql
+ $(DB_EXTENSION).sql \
+ history_pk_prepare.sql
diff --git a/include/common.h b/include/common.h
index 82b2c93f254..f947effcc57 100644
--- a/include/common.h
+++ b/include/common.h
@@ -982,6 +982,8 @@ typedef enum
}
zbx_task_t;
+/* runtime control commands */
+#define ZBX_RTC_UNKNOWN 0
#define ZBX_RTC_LOG_LEVEL_INCREASE 1
#define ZBX_RTC_LOG_LEVEL_DECREASE 2
#define ZBX_RTC_HOUSEKEEPER_EXECUTE 3
@@ -996,6 +998,11 @@ zbx_task_t;
#define ZBX_RTC_HA_SET_FAILOVER_DELAY 16
#define ZBX_RTC_USER_PARAMETERS_RELOAD 17
+/* runtime control notifications, must be less than 10000 */
+#define ZBX_RTC_CONFIG_SYNC_NOTIFY 9999
+
+#define ZBX_IPC_RTC_MAX 9999
+
typedef enum
{
HTTPTEST_AUTH_NONE = 0,
@@ -1014,6 +1021,7 @@ typedef struct
zbx_task_t task;
unsigned int flags;
int data;
+ char *opts;
}
ZBX_TASK_EX;
diff --git a/include/daemon.h b/include/daemon.h
index a0b7477e086..68a9ca3db1f 100644
--- a/include/daemon.h
+++ b/include/daemon.h
@@ -45,4 +45,7 @@ void zbx_set_sigusr_handler(void (*handler)(int flags));
#define START_MAIN_ZABBIX_ENTRY(allow_root, user, flags) daemon_start(allow_root, user, flags)
+void zbx_signal_process_by_type(int proc_type, int proc_num, int flags, char **out);
+void zbx_signal_process_by_pid(int pid, int flags, char **out);
+
#endif /* ZABBIX_DAEMON_H */
diff --git a/include/dbcache.h b/include/dbcache.h
index 075d82e52a9..3a21af9e393 100644
--- a/include/dbcache.h
+++ b/include/dbcache.h
@@ -52,6 +52,10 @@
#define ZBX_SNMPTRAP_LOGGING_ENABLED 1
+#define ZBX_IPC_SERVICE_CONFIG "config"
+#define ZBX_IPC_CONFIG_RELOAD_REQUEST 1
+#define ZBX_IPC_CONFIG_RELOAD_RESPONSE 2
+
extern int CONFIG_TIMEOUT;
extern zbx_uint64_t CONFIG_CONF_CACHE_SIZE;
@@ -666,7 +670,8 @@ zbx_uint64_t DCget_nextid(const char *table_name, int num);
#define ZBX_ITEM_GET_PROCESS (ZBX_ITEM_GET_MAINTENANCE|ZBX_ITEM_GET_MISC|ZBX_ITEM_GET_LOGTIMEFMT)
-void DCsync_configuration(unsigned char mode, const struct zbx_json_parse *jp_kvs_paths);
+void DCsync_configuration(unsigned char mode);
+void DCsync_kvs_paths(const struct zbx_json_parse *jp_kvs_paths);
int init_configuration_cache(char **error);
void free_configuration_cache(void);
@@ -740,7 +745,6 @@ int DCget_host_inventory_value_by_hostid(zbx_uint64_t hostid, char **replace_to,
void *DCconfig_get_stats(int request);
int DCconfig_get_last_sync_time(void);
-void DCconfig_wait_sync(void);
int DCconfig_get_proxypoller_hosts(DC_PROXY *proxies, int max_hosts);
int DCconfig_get_proxypoller_nextcheck(void);
diff --git a/include/log.h b/include/log.h
index 4f2acba3a31..a7e3b08d358 100644
--- a/include/log.h
+++ b/include/log.h
@@ -85,4 +85,8 @@ void zbx_handle_log(void);
int zbx_get_log_type(const char *logtype);
int zbx_validate_log_parameters(ZBX_TASK_EX *task);
+void zbx_strlog_alloc(int level, char **out, size_t *out_alloc, size_t *out_offset, const char *format,
+ ...) __zbx_attr_format_printf(5, 6);
+
+
#endif
diff --git a/include/proxy.h b/include/proxy.h
index 246e47c6f0c..c1029fde9ad 100644
--- a/include/proxy.h
+++ b/include/proxy.h
@@ -44,7 +44,7 @@ int check_access_passive_proxy(zbx_socket_t *sock, int send_response, const char
void update_proxy_lastaccess(const zbx_uint64_t hostid, time_t last_access);
int get_proxyconfig_data(zbx_uint64_t proxy_hostid, struct zbx_json *j, char **error);
-void process_proxyconfig(struct zbx_json_parse *jp_data);
+int process_proxyconfig(struct zbx_json_parse *jp_data, struct zbx_json_parse *jp_kvs_paths);
int get_interface_availability_data(struct zbx_json *json, int *ts);
diff --git a/include/zbxdiag.h b/include/zbxdiag.h
index e185b8f05bb..7b64a5acd5e 100644
--- a/include/zbxdiag.h
+++ b/include/zbxdiag.h
@@ -45,6 +45,6 @@ zbx_diaginfo_section_t;
#define ZBX_DIAG_LOCKS "locks"
int zbx_diag_get_info(const struct zbx_json_parse *jp, char **info);
-void zbx_diag_log_info(unsigned int flags);
+void zbx_diag_log_info(unsigned int flags, char **result);
#endif
diff --git a/include/zbxha.h b/include/zbxha.h
index a8f6bc4fdf6..c59c257f8a1 100644
--- a/include/zbxha.h
+++ b/include/zbxha.h
@@ -22,19 +22,36 @@
#define ZBX_IPC_SERVICE_HA "haservice"
-#define ZBX_IPC_SERVICE_HA_REGISTER 0
#define ZBX_IPC_SERVICE_HA_PAUSE 1
#define ZBX_IPC_SERVICE_HA_STOP 2
-#define ZBX_IPC_SERVICE_HA_UPDATE 3
+#define ZBX_IPC_SERVICE_HA_STATUS 3
#define ZBX_IPC_SERVICE_HA_GET_NODES 4
#define ZBX_IPC_SERVICE_HA_REMOVE_NODE 5
#define ZBX_IPC_SERVICE_HA_SET_FAILOVER_DELAY 6
-#define ZBX_IPC_SERVICE_HA_LOGLEVEL_INCREASE 7
-#define ZBX_IPC_SERVICE_HA_LOGLEVEL_DECREASE 8
-#define ZBX_IPC_SERVICE_HA_HEARTBEAT 9
+#define ZBX_IPC_SERVICE_HA_GET_FAILOVER_DELAY 7
+#define ZBX_IPC_SERVICE_HA_LOGLEVEL_INCREASE 8
+#define ZBX_IPC_SERVICE_HA_LOGLEVEL_DECREASE 9
+
+#define ZBX_IPC_SERVICE_HA_RTC_FIRST (ZBX_IPC_RTC_MAX + 1)
+
+#define ZBX_IPC_SERVICE_HA_REGISTER ZBX_IPC_SERVICE_HA_RTC_FIRST
+#define ZBX_IPC_SERVICE_HA_HEARTBEAT (ZBX_IPC_SERVICE_HA_RTC_FIRST + 1)
+#define ZBX_IPC_SERVICE_HA_STATUS_UPDATE (ZBX_IPC_SERVICE_HA_RTC_FIRST + 2)
#define ZBX_HA_SERVICE_TIMEOUT 10
+#define ZBX_NODE_STATUS_ERROR -2
+#define ZBX_NODE_STATUS_UNKNOWN -1
+#define ZBX_NODE_STATUS_STANDBY 0
+#define ZBX_NODE_STATUS_STOPPED 1
+#define ZBX_NODE_STATUS_UNAVAILABLE 2
+#define ZBX_NODE_STATUS_ACTIVE 3
+
int zbx_ha_get_nodes(char **nodes, char **error);
+int zbx_ha_remove_node(const char *node, char **result, char **error);
+int zbx_ha_set_failover_delay(int delay, char **error);
+int zbx_ha_get_failover_delay(int *delay, char **error);
+int zbx_ha_change_loglevel(int direction, char **error);
+const char *zbx_ha_status_str(int ha_status);
#endif
diff --git a/include/zbxjson.h b/include/zbxjson.h
index 7f3790afa71..e0d27e63580 100644
--- a/include/zbxjson.h
+++ b/include/zbxjson.h
@@ -180,6 +180,12 @@
#define ZBX_PROTO_TAG_LASTACCESS "lastaccess"
#define ZBX_PROTO_TAG_LASTACCESS_AGE "lastaccess_age"
#define ZBX_PROTO_TAG_DB_TIMESTAMP "db_timestamp"
+#define ZBX_PROTO_TAG_NODE "node"
+#define ZBX_PROTO_TAG_FAILOVER_DELAY "failover_delay"
+#define ZBX_PROTO_TAG_SECTION "section"
+#define ZBX_PROTO_TAG_PID "pid"
+#define ZBX_PROTO_TAG_PROCESS_NAME "process_name"
+#define ZBX_PROTO_TAG_PROCESS_NUM "process_num"
#define ZBX_PROTO_VALUE_FAILED "failed"
#define ZBX_PROTO_VALUE_SUCCESS "success"
diff --git a/include/zbxrtc.h b/include/zbxrtc.h
new file mode 100644
index 00000000000..fb21a40341c
--- /dev/null
+++ b/include/zbxrtc.h
@@ -0,0 +1,41 @@
+/*
+** Zabbix
+** Copyright (C) 2001-2021 Zabbix SIA
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+**/
+
+#ifndef ZABBIX_ZBXRTC_H
+#define ZABBIX_ZBXRTC_H
+
+#include "zbxipcservice.h"
+
+typedef struct
+{
+ zbx_ipc_service_t service;
+}
+zbx_rtc_t;
+
+/* provider API */
+int zbx_rtc_init(zbx_rtc_t *rtc ,char **error);
+void zbx_rtc_dispatch(zbx_ipc_client_t *client, zbx_ipc_message_t *message);
+void zbx_rtc_wait_config_sync(zbx_rtc_t *rtc);
+
+/* client API */
+int zbx_rtc_process(const char *option, char **error);
+int zbx_rtc_open(zbx_ipc_async_socket_t *asocket, int timeout, char **error);
+int zbx_rtc_notify_config_sync(char **error);
+
+#endif
diff --git a/src/libs/Makefile.am b/src/libs/Makefile.am
index 0f7fd73fbc5..f985f86701e 100644
--- a/src/libs/Makefile.am
+++ b/src/libs/Makefile.am
@@ -39,7 +39,8 @@ DIST_SUBDIRS = \
zbxaudit \
zbxeval \
zbxxml \
- zbxha
+ zbxha \
+ zbxrtc
if SERVER
SERVER_SUBDIRS = \
@@ -66,7 +67,8 @@ SERVER_SUBDIRS = \
zbxservice \
zbxaudit \
zbxeval \
- zbxha
+ zbxha \
+ zbxrtc
else
if PROXY
PROXY_SUBDIRS = \
@@ -90,7 +92,8 @@ PROXY_SUBDIRS = \
zbxtrends \
zbxavailability \
zbxaudit \
- zbxeval
+ zbxeval \
+ zbxrtc
endif
endif
diff --git a/src/libs/zbxcomms/comms.c b/src/libs/zbxcomms/comms.c
index e9d28061d6a..2a56b617c12 100644
--- a/src/libs/zbxcomms/comms.c
+++ b/src/libs/zbxcomms/comms.c
@@ -1551,6 +1551,7 @@ void zbx_tcp_unaccept(zbx_socket_t *s)
shutdown(s->socket, 2);
+ zbx_socket_free(s);
zbx_socket_close(s->socket);
s->socket = s->socket_orig; /* restore main socket */
diff --git a/src/libs/zbxdbcache/dbconfig.c b/src/libs/zbxdbcache/dbconfig.c
index 82c8b0d2c0d..cbd0a907f06 100644
--- a/src/libs/zbxdbcache/dbconfig.c
+++ b/src/libs/zbxdbcache/dbconfig.c
@@ -2136,13 +2136,13 @@ static void DCsync_hmacros(zbx_dbsync_t *sync)
zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
}
-static int DCsync_kvs_paths(const struct zbx_json_parse *jp_kvs_paths)
+void DCsync_kvs_paths(const struct zbx_json_parse *jp_kvs_paths)
{
zbx_dc_kvs_path_t *dc_kvs_path;
zbx_dc_kv_t *dc_kv;
zbx_hashset_t kvs;
zbx_hashset_iter_t iter;
- int i, j, ret;
+ int i, j;
zbx_vector_ptr_pair_t diff;
zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
@@ -2157,14 +2157,8 @@ static int DCsync_kvs_paths(const struct zbx_json_parse *jp_kvs_paths)
dc_kvs_path = (zbx_dc_kvs_path_t *)config->kvs_paths.values[i];
- if (0 == (program_type & ZBX_PROGRAM_TYPE_SERVER))
+ if (NULL != jp_kvs_paths)
{
- if (NULL == jp_kvs_paths)
- {
- ret = FAIL;
- goto fail;
- }
-
if (FAIL == zbx_vault_json_kvs_get(dc_kvs_path->path, jp_kvs_paths, &kvs, &error))
{
zabbix_log(LOG_LEVEL_WARNING, "cannot get secrets for path \"%s\": %s",
@@ -2228,13 +2222,10 @@ static int DCsync_kvs_paths(const struct zbx_json_parse *jp_kvs_paths)
zbx_vector_ptr_pair_clear(&diff);
zbx_hashset_clear(&kvs);
}
- ret = SUCCEED;
-fail:
+
zbx_vector_ptr_pair_destroy(&diff);
zbx_hashset_destroy(&kvs);
zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
-
- return ret;
}
/******************************************************************************
@@ -5941,7 +5932,7 @@ static void dc_load_trigger_queue(zbx_hashset_t *trend_functions)
* Author: Alexander Vladishev, Aleksandrs Saveljevs *
* *
******************************************************************************/
-void DCsync_configuration(unsigned char mode, const struct zbx_json_parse *jp_kvs_paths)
+void DCsync_configuration(unsigned char mode)
{
int i, flags;
double sec, csec, hsec, hisec, htsec, gmsec, hmsec, ifsec, isec, tsec, dsec, fsec, expr_sec, csec2,
@@ -5970,12 +5961,6 @@ void DCsync_configuration(unsigned char mode, const struct zbx_json_parse *jp_kv
config->sync_start_ts = time(NULL);
- if (ZBX_SYNC_SECRETS == mode)
- {
- DCsync_kvs_paths(NULL);
- goto skip;
- }
-
zbx_dbsync_init_env(config);
if (ZBX_DBSYNC_INIT == mode)
@@ -6084,14 +6069,16 @@ void DCsync_configuration(unsigned char mode, const struct zbx_json_parse *jp_kv
sec = zbx_time();
DCsync_host_tags(&host_tag_sync);
host_tag_sec2 = zbx_time() - sec;
- FINISH_SYNC;
- if (FAIL == DCsync_kvs_paths(jp_kvs_paths))
+ /* postpone configuration sync until macro secrets are received from Zabbix server */
+ if (0 == (program_type & ZBX_PROGRAM_TYPE_SERVER) && 0 != config->kvs_paths.values_num &&
+ ZBX_DBSYNC_INIT == mode)
{
- START_SYNC;
goto out;
}
+ FINISH_SYNC;
+
/* sync host data to support host lookups when resolving macros during configuration sync */
sec = zbx_time();
@@ -6682,7 +6669,7 @@ out:
zbx_hashset_destroy(&trend_queue);
zbx_dbsync_free_env();
-skip:
+
if (SUCCEED == ZBX_CHECK_LOG_LEVEL(LOG_LEVEL_TRACE))
DCdump_configuration();
@@ -9986,7 +9973,7 @@ static void DCagent_set_availability(zbx_agent_availability_t *av, unsigned cha
if (dst != src) \
dst = src; \
else \
- flags &= (~(mask)); \
+ flags &= (unsigned char)(~(mask)); \
}
#define AGENT_AVAILABILITY_ASSIGN_STR(flags, mask, dst, src) \
@@ -9995,7 +9982,7 @@ static void DCagent_set_availability(zbx_agent_availability_t *av, unsigned cha
if (0 != strcmp(dst, src)) \
DCstrpool_replace(1, &dst, src); \
else \
- flags &= (~(mask)); \
+ flags &= (unsigned char)(~(mask)); \
}
AGENT_AVAILABILITY_ASSIGN(av->flags, ZBX_FLAGS_AGENT_STATUS_AVAILABLE, *available, av->available);
@@ -10750,14 +10737,6 @@ int DCconfig_get_last_sync_time(void)
return config->sync_ts;
}
-void DCconfig_wait_sync(void)
-{
- struct timespec ts = {0, 1e8};
-
- while (0 == config->sync_ts)
- nanosleep(&ts, NULL);
-}
-
/******************************************************************************
* *
* Function: DCconfig_get_proxypoller_hosts *
diff --git a/src/libs/zbxdbhigh/proxy.c b/src/libs/zbxdbhigh/proxy.c
index c2b156b78ca..59588f5ab11 100644
--- a/src/libs/zbxdbhigh/proxy.c
+++ b/src/libs/zbxdbhigh/proxy.c
@@ -1986,7 +1986,7 @@ out:
* Purpose: update configuration *
* *
******************************************************************************/
-void process_proxyconfig(struct zbx_json_parse *jp_data)
+int process_proxyconfig(struct zbx_json_parse *jp_data, struct zbx_json_parse *jp_kvs_paths)
{
typedef struct
{
@@ -1997,7 +1997,7 @@ void process_proxyconfig(struct zbx_json_parse *jp_data)
char buf[ZBX_TABLENAME_LEN_MAX];
const char *p = NULL;
- struct zbx_json_parse jp_obj, jp_kvs_paths, *jp_kvs_paths_ptr = NULL;
+ struct zbx_json_parse jp_obj;
char *error = NULL;
int i, ret = SUCCEED;
@@ -2023,8 +2023,7 @@ void process_proxyconfig(struct zbx_json_parse *jp_data)
if (0 == strcmp(buf, "macro.secrets"))
{
- jp_kvs_paths = jp_obj;
- jp_kvs_paths_ptr = &jp_kvs_paths;
+ *jp_kvs_paths = jp_obj;
continue;
}
@@ -2086,20 +2085,17 @@ void process_proxyconfig(struct zbx_json_parse *jp_data)
}
zbx_vector_ptr_destroy(&tables_proxy);
- if (SUCCEED != DBend(ret))
+ if (SUCCEED != (ret = DBend(ret)))
{
zabbix_log(LOG_LEVEL_ERR, "failed to update local proxy configuration copy: %s",
(NULL == error ? "database error" : error));
}
- else
- {
- DCsync_configuration(ZBX_DBSYNC_UPDATE, jp_kvs_paths_ptr);
- DCupdate_interfaces_availability();
- }
zbx_free(error);
zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
+
+ return ret;
}
/******************************************************************************
diff --git a/src/libs/zbxdiag/diag.c b/src/libs/zbxdiag/diag.c
index 18e983d16e5..a3e4997e0eb 100644
--- a/src/libs/zbxdiag/diag.c
+++ b/src/libs/zbxdiag/diag.c
@@ -697,7 +697,8 @@ static void diag_get_simple_values(const struct zbx_json_parse *jp, char **msg)
* path - [OUT] the json path to the memory data *
* *
******************************************************************************/
-static void diag_log_memory_info(struct zbx_json_parse *jp, const char *field, const char *path)
+static void diag_log_memory_info(struct zbx_json_parse *jp, const char *field, const char *path, char **out,
+ size_t *out_alloc, size_t *out_offset)
{
struct zbx_json_parse jp_memory, jp_size, jp_chunks;
char *msg = NULL;
@@ -705,11 +706,11 @@ static void diag_log_memory_info(struct zbx_json_parse *jp, const char *field, c
if (FAIL == zbx_json_open_path(jp, path, &jp_memory))
return;
- zabbix_log(LOG_LEVEL_INFORMATION, "%s:", field);
+ zbx_strlog_alloc(LOG_LEVEL_INFORMATION, out, out_alloc, out_offset, "%s:", field);
if (SUCCEED == zbx_json_brackets_by_name(&jp_memory, "size", &jp_size))
{
diag_get_simple_values(&jp_size, &msg);
- zabbix_log(LOG_LEVEL_INFORMATION, " size: %s", msg);
+ zbx_strlog_alloc(LOG_LEVEL_INFORMATION, out, out_alloc, out_offset, " size: %s", msg);
zbx_free(msg);
}
@@ -718,21 +719,22 @@ static void diag_log_memory_info(struct zbx_json_parse *jp, const char *field, c
struct zbx_json_parse jp_buckets, jp_bucket;
diag_get_simple_values(&jp_chunks, &msg);
- zabbix_log(LOG_LEVEL_INFORMATION, " chunks: %s", msg);
+ zbx_strlog_alloc(LOG_LEVEL_INFORMATION, out, out_alloc, out_offset, " chunks: %s", msg);
zbx_free(msg);
if (SUCCEED == zbx_json_brackets_by_name(&jp_chunks, "buckets", &jp_buckets))
{
const char *pnext;
- zabbix_log(LOG_LEVEL_INFORMATION, " buckets:");
+ zbx_strlog_alloc(LOG_LEVEL_INFORMATION, out, out_alloc, out_offset, " buckets:");
for (pnext = NULL; NULL != (pnext = zbx_json_next(&jp_buckets, pnext));)
{
if (SUCCEED == zbx_json_brackets_open(pnext, &jp_bucket))
{
diag_get_simple_values(&jp_bucket, &msg);
- zabbix_log(LOG_LEVEL_INFORMATION, " %s", msg);
+ zbx_strlog_alloc(LOG_LEVEL_INFORMATION, out, out_alloc, out_offset, " %s",
+ msg);
zbx_free(msg);
}
}
@@ -746,12 +748,16 @@ static void diag_log_memory_info(struct zbx_json_parse *jp, const char *field, c
* *
* Purpose: log top view *
* *
- * Parameters: jp - [IN] the section json *
- * field - [OUT] the top field name *
- * path - [OUT] the json path to the top view *
+ * Parameters: jp - [IN] the section json *
+ * field - [OUT] the top field name *
+ * path - [OUT] the json path to the top view *
+ * out - [OUT] the output buffer (optional) *
+ * out_alloc - [OUT] the output buffer size *
+ * out_offset - [OUT] the output buffer offset *
* *
******************************************************************************/
-static void diag_log_top_view(struct zbx_json_parse *jp, const char *field, const char *path)
+static void diag_log_top_view(struct zbx_json_parse *jp, const char *field, const char *path,
+ char **out, size_t *out_alloc, size_t *out_offset)
{
struct zbx_json_parse jp_top, jp_row;
const char *pnext;
@@ -764,14 +770,14 @@ static void diag_log_top_view(struct zbx_json_parse *jp, const char *field, cons
else if (FAIL == zbx_json_open_path(jp, path, &jp_top))
return;
- zabbix_log(LOG_LEVEL_INFORMATION, "%s:", field);
+ zbx_strlog_alloc(LOG_LEVEL_INFORMATION, out, out_alloc, out_offset, "%s:", field);
for (pnext = NULL; NULL != (pnext = zbx_json_next(&jp_top, pnext));)
{
if (SUCCEED == zbx_json_brackets_open(pnext, &jp_row))
{
diag_get_simple_values(&jp_row, &msg);
- zabbix_log(LOG_LEVEL_INFORMATION, " %s", msg);
+ zbx_strlog_alloc(LOG_LEVEL_INFORMATION, out, out_alloc, out_offset, " %s", msg);
zbx_free(msg);
}
}
@@ -784,22 +790,22 @@ static void diag_log_top_view(struct zbx_json_parse *jp, const char *field, cons
* Purpose: log history cache diagnostic information *
* *
******************************************************************************/
-static void diag_log_history_cache(struct zbx_json_parse *jp)
+static void diag_log_history_cache(struct zbx_json_parse *jp, char **out, size_t *out_alloc, size_t *out_offset)
{
char *msg = NULL;
- zabbix_log(LOG_LEVEL_INFORMATION, "== history cache diagnostic information ==");
+ zbx_strlog_alloc(LOG_LEVEL_INFORMATION, out, out_alloc, out_offset, "== history cache diagnostic information ==");
diag_get_simple_values(jp, &msg);
- zabbix_log(LOG_LEVEL_INFORMATION, "%s", msg);
+ zbx_strlog_alloc(LOG_LEVEL_INFORMATION, out, out_alloc, out_offset, "%s", msg);
zbx_free(msg);
- diag_log_memory_info(jp, "memory.data", "$.memory.data");
- diag_log_memory_info(jp, "memory.index", "$.memory.index");
+ diag_log_memory_info(jp, "memory.data", "$.memory.data", out, out_alloc, out_offset);
+ diag_log_memory_info(jp, "memory.index", "$.memory.index", out, out_alloc, out_offset);
- diag_log_top_view(jp, "top.values", "$.top.values");
+ diag_log_top_view(jp, "top.values", "$.top.values", out, out_alloc, out_offset);
- zabbix_log(LOG_LEVEL_INFORMATION, "==");
+ zbx_strlog_alloc(LOG_LEVEL_INFORMATION, out, out_alloc, out_offset, "==");
}
/******************************************************************************
@@ -809,22 +815,22 @@ static void diag_log_history_cache(struct zbx_json_parse *jp)
* Purpose: log value cache diagnostic information *
* *
******************************************************************************/
-static void diag_log_value_cache(struct zbx_json_parse *jp)
+static void diag_log_value_cache(struct zbx_json_parse *jp, char **out, size_t *out_alloc, size_t *out_offset)
{
char *msg = NULL;
- zabbix_log(LOG_LEVEL_INFORMATION, "== value cache diagnostic information ==");
+ zbx_strlog_alloc(LOG_LEVEL_INFORMATION, out, out_alloc, out_offset, "== value cache diagnostic information ==");
diag_get_simple_values(jp, &msg);
- zabbix_log(LOG_LEVEL_INFORMATION, "%s", msg);
+ zbx_strlog_alloc(LOG_LEVEL_INFORMATION, out, out_alloc, out_offset, "%s", msg);
zbx_free(msg);
- diag_log_memory_info(jp, "memory", "$.memory");
+ diag_log_memory_info(jp, "memory", "$.memory", out, out_alloc, out_offset);
- diag_log_top_view(jp, "top.values", "$.top.values");
- diag_log_top_view(jp, "top.request.values", "$.top['request.values']");
+ diag_log_top_view(jp, "top.values", "$.top.values", out, out_alloc, out_offset);
+ diag_log_top_view(jp, "top.request.values", "$.top['request.values']", out, out_alloc, out_offset);
- zabbix_log(LOG_LEVEL_INFORMATION, "==");
+ zbx_strlog_alloc(LOG_LEVEL_INFORMATION, out, out_alloc, out_offset, "==");
}
/******************************************************************************
@@ -834,20 +840,20 @@ static void diag_log_value_cache(struct zbx_json_parse *jp)
* Purpose: log preprocessing diagnostic information *
* *
******************************************************************************/
-static void diag_log_preprocessing(struct zbx_json_parse *jp)
+static void diag_log_preprocessing(struct zbx_json_parse *jp, char **out, size_t *out_alloc, size_t *out_offset)
{
char *msg = NULL;
- zabbix_log(LOG_LEVEL_INFORMATION, "== preprocessing diagnostic information ==");
+ zbx_strlog_alloc(LOG_LEVEL_INFORMATION, out, out_alloc, out_offset, "== preprocessing diagnostic information ==");
diag_get_simple_values(jp, &msg);
- zabbix_log(LOG_LEVEL_INFORMATION, "%s", msg);
+ zbx_strlog_alloc(LOG_LEVEL_INFORMATION, out, out_alloc, out_offset, "%s", msg);
zbx_free(msg);
- diag_log_top_view(jp, "top.values", "$.top.values");
- diag_log_top_view(jp, "top.oldest.preproc.values", "$.top['oldest.preproc.values']");
+ diag_log_top_view(jp, "top.values", "$.top.values", out, out_alloc, out_offset);
+ diag_log_top_view(jp, "top.oldest.preproc.values", "$.top['oldest.preproc.values']", out, out_alloc, out_offset);
- zabbix_log(LOG_LEVEL_INFORMATION, "==");
+ zbx_strlog_alloc(LOG_LEVEL_INFORMATION, out, out_alloc, out_offset, "==");
}
/******************************************************************************
@@ -858,19 +864,19 @@ static void diag_log_preprocessing(struct zbx_json_parse *jp)
* *
******************************************************************************/
-static void diag_log_lld(struct zbx_json_parse *jp)
+static void diag_log_lld(struct zbx_json_parse *jp, char **out, size_t *out_alloc, size_t *out_offset)
{
char *msg = NULL;
- zabbix_log(LOG_LEVEL_INFORMATION, "== LLD diagnostic information ==");
+ zbx_strlog_alloc(LOG_LEVEL_INFORMATION, out, out_alloc, out_offset, "== LLD diagnostic information ==");
diag_get_simple_values(jp, &msg);
- zabbix_log(LOG_LEVEL_INFORMATION, "%s", msg);
+ zbx_strlog_alloc(LOG_LEVEL_INFORMATION, out, out_alloc, out_offset, "%s", msg);
zbx_free(msg);
- diag_log_top_view(jp, "top.values", "$.top.values");
+ diag_log_top_view(jp, "top.values", "$.top.values", out, out_alloc, out_offset);
- zabbix_log(LOG_LEVEL_INFORMATION, "==");
+ zbx_strlog_alloc(LOG_LEVEL_INFORMATION, out, out_alloc, out_offset, "==");
}
/******************************************************************************
@@ -880,20 +886,20 @@ static void diag_log_lld(struct zbx_json_parse *jp)
* Purpose: log alerting diagnostic information *
* *
******************************************************************************/
-static void diag_log_alerting(struct zbx_json_parse *jp)
+static void diag_log_alerting(struct zbx_json_parse *jp, char **out, size_t *out_alloc, size_t *out_offset)
{
char *msg = NULL;
- zabbix_log(LOG_LEVEL_INFORMATION, "== alerting diagnostic information ==");
+ zbx_strlog_alloc(LOG_LEVEL_INFORMATION, out, out_alloc, out_offset, "== alerting diagnostic information ==");
diag_get_simple_values(jp, &msg);
- zabbix_log(LOG_LEVEL_INFORMATION, "%s", msg);
+ zbx_strlog_alloc(LOG_LEVEL_INFORMATION, out, out_alloc, out_offset, "%s", msg);
zbx_free(msg);
- diag_log_top_view(jp, "media.alerts", "$.top['media.alerts']");
- diag_log_top_view(jp, "source.alerts", "$.top['source.alerts']");
+ diag_log_top_view(jp, "media.alerts", "$.top['media.alerts']", out, out_alloc, out_offset);
+ diag_log_top_view(jp, "source.alerts", "$.top['source.alerts']", out, out_alloc, out_offset);
- zabbix_log(LOG_LEVEL_INFORMATION, "==");
+ zbx_strlog_alloc(LOG_LEVEL_INFORMATION, out, out_alloc, out_offset, "==");
}
/******************************************************************************
@@ -905,11 +911,12 @@ static void diag_log_alerting(struct zbx_json_parse *jp)
* Parameters: flags - [IN] flags describing section to log *
* *
******************************************************************************/
-void zbx_diag_log_info(unsigned int flags)
+void zbx_diag_log_info(unsigned int flags, char **result)
{
struct zbx_json j;
struct zbx_json_parse jp;
char *info = NULL;
+ size_t result_alloc = 0, result_offset = 0;
zbx_json_init(&j, 1024);
@@ -942,25 +949,30 @@ void zbx_diag_log_info(unsigned int flags)
}
if (0 == strcmp(section, ZBX_DIAG_HISTORYCACHE))
- diag_log_history_cache(&jp_section);
+ diag_log_history_cache(&jp_section, result, &result_alloc, &result_offset);
else if (0 == strcmp(section, ZBX_DIAG_VALUECACHE))
- diag_log_value_cache(&jp_section);
+ diag_log_value_cache(&jp_section, result, &result_alloc, &result_offset);
else if (0 == strcmp(section, ZBX_DIAG_PREPROCESSING))
- diag_log_preprocessing(&jp_section);
+ diag_log_preprocessing(&jp_section, result, &result_alloc, &result_offset);
else if (0 == strcmp(section, ZBX_DIAG_LLD))
- diag_log_lld(&jp_section);
+ diag_log_lld(&jp_section, result, &result_alloc, &result_offset);
else if (0 == strcmp(section, ZBX_DIAG_ALERTING))
- diag_log_alerting(&jp_section);
+ diag_log_alerting(&jp_section, result, &result_alloc, &result_offset);
else if (0 == strcmp(section, ZBX_DIAG_LOCKS))
{
- zabbix_log(LOG_LEVEL_INFORMATION, "== locks diagnostic information ==");
- diag_log_top_view(&jp_section, ZBX_DIAG_LOCKS, NULL);
- zabbix_log(LOG_LEVEL_INFORMATION, "==");
+ zbx_strlog_alloc(LOG_LEVEL_INFORMATION, result, &result_alloc, &result_offset,
+ "== locks diagnostic information ==");
+ diag_log_top_view(&jp_section, ZBX_DIAG_LOCKS, NULL, result, &result_alloc,
+ &result_offset);
+ zbx_strlog_alloc(LOG_LEVEL_INFORMATION, result, &result_alloc, &result_offset, "==");
}
}
}
else
- zabbix_log(LOG_LEVEL_INFORMATION, "cannot obtain diagnostic information: %s", info);
+ {
+ zbx_strlog_alloc(LOG_LEVEL_INFORMATION, result, &result_alloc, &result_offset,
+ "cannot obtain diagnostic information: %s", info);
+ }
out:
zbx_free(info);
zbx_json_free(&j);
diff --git a/src/libs/zbxha/ha.c b/src/libs/zbxha/ha.c
index e118273146b..759b39fe3ce 100644
--- a/src/libs/zbxha/ha.c
+++ b/src/libs/zbxha/ha.c
@@ -21,6 +21,7 @@
#include "zbxipcservice.h"
#include "zbxserialize.h"
#include "zbxha.h"
+#include "log.h"
/******************************************************************************
* *
@@ -36,6 +37,8 @@ int zbx_ha_get_nodes(char **nodes, char **error)
int ret;
char *str;
+ zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
+
if (SUCCEED != zbx_ipc_async_exchange(ZBX_IPC_SERVICE_HA, ZBX_IPC_SERVICE_HA_GET_NODES,
ZBX_HA_SERVICE_TIMEOUT, NULL, 0, &data, error))
{
@@ -52,5 +55,141 @@ int zbx_ha_get_nodes(char **nodes, char **error)
else
*error = str;
+ zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
+
return ret;
}
+
+/******************************************************************************
+ * *
+ * Function: zbx_ha_remove_node *
+ * *
+ * Purpose: remove HA node *
+ * *
+ * Comments: A new socket is opened to avoid interfering with notification *
+ * channel *
+ * *
+ ******************************************************************************/
+int zbx_ha_remove_node(const char *node, char **result, char **error)
+{
+ unsigned char *data, *ptr;
+ zbx_uint32_t error_len, result_len;
+
+ if (SUCCEED != zbx_ipc_async_exchange(ZBX_IPC_SERVICE_HA, ZBX_IPC_SERVICE_HA_REMOVE_NODE,
+ ZBX_HA_SERVICE_TIMEOUT, (const unsigned char *)node, (zbx_uint32_t)strlen(node) + 1, &data, error))
+ {
+ return FAIL;
+ }
+
+ ptr = data;
+ ptr += zbx_deserialize_str(ptr, result, result_len);
+ (void)zbx_deserialize_str(ptr, error, error_len);
+ zbx_free(data);
+
+ return (0 == error_len ? SUCCEED : FAIL);
+}
+
+/******************************************************************************
+ * *
+ * Function: zbx_ha_set_failover_delay *
+ * *
+ * Purpose: set HA failover delay *
+ * *
+ * Comments: A new socket is opened to avoid interfering with notification *
+ * channel *
+ * *
+ ******************************************************************************/
+int zbx_ha_set_failover_delay(int delay, char **error)
+{
+ unsigned char *data;
+ zbx_uint32_t error_len;
+
+ if (SUCCEED != zbx_ipc_async_exchange(ZBX_IPC_SERVICE_HA, ZBX_IPC_SERVICE_HA_SET_FAILOVER_DELAY,
+ ZBX_HA_SERVICE_TIMEOUT, (unsigned char *)&delay, sizeof(delay), &data, error))
+ {
+ return FAIL;
+ }
+
+ (void)zbx_deserialize_str(data, error, error_len);
+ zbx_free(data);
+
+ return (0 == error_len ? SUCCEED : FAIL);
+}
+
+/******************************************************************************
+ * *
+ * Function: zbx_ha_get_failover_delay *
+ * *
+ * Purpose: get HA failover delay *
+ * *
+ * Comments: A new socket is opened to avoid interfering with notification *
+ * channel *
+ * *
+ ******************************************************************************/
+int zbx_ha_get_failover_delay(int *delay, char **error)
+{
+ unsigned char *data;
+
+ if (SUCCEED != zbx_ipc_async_exchange(ZBX_IPC_SERVICE_HA, ZBX_IPC_SERVICE_HA_GET_FAILOVER_DELAY,
+ ZBX_HA_SERVICE_TIMEOUT, NULL, 0, &data, error))
+ {
+ return FAIL;
+ }
+
+ memcpy(delay, data, sizeof(*delay));
+ zbx_free(data);
+
+ return SUCCEED;
+}
+
+/******************************************************************************
+ * *
+ * Function: zbx_ha_change_loglevel *
+ * *
+ * Purpose: change HA manager log level *
+ * *
+ ******************************************************************************/
+int zbx_ha_change_loglevel(int direction, char **error)
+{
+ int ret = FAIL;
+ zbx_uint32_t cmd;
+ unsigned char *result = NULL;
+
+ zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
+
+ cmd = 0 < direction ? ZBX_IPC_SERVICE_HA_LOGLEVEL_INCREASE : ZBX_IPC_SERVICE_HA_LOGLEVEL_DECREASE;
+
+ ret = zbx_ipc_async_exchange(ZBX_IPC_SERVICE_HA, cmd, ZBX_HA_SERVICE_TIMEOUT, NULL, 0, &result, error);
+ zbx_free(result);
+
+ zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
+
+ return ret;
+}
+
+/******************************************************************************
+ * *
+ * Function: zbx_ha_status_str *
+ * *
+ * Purpose: get HA status in text format *
+ * *
+ ******************************************************************************/
+const char *zbx_ha_status_str(int ha_status)
+{
+ switch (ha_status)
+ {
+ case ZBX_NODE_STATUS_STANDBY:
+ return "standby";
+ case ZBX_NODE_STATUS_STOPPED:
+ return "stopped";
+ case ZBX_NODE_STATUS_UNAVAILABLE:
+ return "unavailable";
+ case ZBX_NODE_STATUS_ACTIVE:
+ return "active";
+ case ZBX_NODE_STATUS_ERROR:
+ return "error";
+ default:
+ return "unknown";
+ }
+}
+
diff --git a/src/libs/zbxlog/log.c b/src/libs/zbxlog/log.c
index d6649f9093f..74508a22d2a 100644
--- a/src/libs/zbxlog/log.c
+++ b/src/libs/zbxlog/log.c
@@ -678,3 +678,53 @@ char *strerror_from_module(unsigned long error, const wchar_t *module)
return utf8_string;
}
#endif /* _WINDOWS */
+
+/******************************************************************************
+ * *
+ * Function: zbx_strlog_alloc *
+ * *
+ * Purpose: log the message optionally appending to a string buffer *
+ * *
+ * Parameters: lebel - [IN] the log level *
+ * out - [OUT] the output buffer (optional) *
+ * out_alloc - [OUT] the output buffer size *
+ * out_offset - [OUT] the output buffer offset *
+ * format - [IN] the format string *
+ * *
+ * Return value: SUCCEED - the socket was successfully opened *
+ * FAIL - otherwise *
+ * *
+ ******************************************************************************/
+void zbx_strlog_alloc(int level, char **out, size_t *out_alloc, size_t *out_offset, const char *format, ...)
+{
+ va_list args;
+ size_t len;
+ char *buf;
+
+ if (SUCCEED != ZBX_CHECK_LOG_LEVEL(level) && NULL == out)
+ return;
+
+ va_start(args, format);
+ len = (size_t)vsnprintf(NULL, 0, format, args) + 2;
+ va_end(args);
+
+ buf = (char *)zbx_malloc(NULL, len);
+
+ va_start(args, format);
+ len = (size_t)vsnprintf(buf, len, format, args);
+ va_end(args);
+
+ if (SUCCEED == ZBX_CHECK_LOG_LEVEL(level))
+ zabbix_log(level, "%s", buf);
+
+ if (NULL != out)
+ {
+ buf[0] = (char)toupper((unsigned char)buf[0]);
+ buf[len++] = '\n';
+ buf[len] = '\0';
+
+ zbx_strcpy_alloc(out, out_alloc, out_offset, buf);
+ }
+
+ zbx_free(buf);
+}
diff --git a/src/libs/zbxnix/control.c b/src/libs/zbxnix/control.c
index ffd25a7c024..248103c1216 100644
--- a/src/libs/zbxnix/control.c
+++ b/src/libs/zbxnix/control.c
@@ -115,7 +115,6 @@ static int parse_log_level_options(const char *opt, size_t len, unsigned int *sc
* message *
* *
* Parameters: opt - [IN] the command line argument *
- * program_type - [IN] the program type *
* message - [OUT] the message containing options for log *
* level change or cache reload *
* *
@@ -123,7 +122,7 @@ static int parse_log_level_options(const char *opt, size_t len, unsigned int *sc
* FAIL - an error occurred *
* *
******************************************************************************/
-int parse_rtc_options(const char *opt, unsigned char program_type, int *message)
+int parse_rtc_options(const char *opt, int *message)
{
unsigned int scope, data, command;
@@ -141,145 +140,12 @@ int parse_rtc_options(const char *opt, unsigned char program_type, int *message)
if (SUCCEED != parse_log_level_options(opt, ZBX_CONST_STRLEN(ZBX_LOG_LEVEL_DECREASE), &scope, &data))
return FAIL;
}
- else if (0 != (program_type & (ZBX_PROGRAM_TYPE_SERVER | ZBX_PROGRAM_TYPE_PROXY)) &&
- 0 == strcmp(opt, ZBX_CONFIG_CACHE_RELOAD))
- {
- command = ZBX_RTC_CONFIG_CACHE_RELOAD;
- scope = 0;
- data = 0;
- }
- else if (0 != (program_type & (ZBX_PROGRAM_TYPE_SERVER | ZBX_PROGRAM_TYPE_PROXY)) &&
- 0 == strcmp(opt, ZBX_HOUSEKEEPER_EXECUTE))
- {
- command = ZBX_RTC_HOUSEKEEPER_EXECUTE;
- scope = 0;
- data = 0;
- }
- else if (0 != (program_type & (ZBX_PROGRAM_TYPE_SERVER | ZBX_PROGRAM_TYPE_PROXY)) &&
- 0 == strcmp(opt, ZBX_SNMP_CACHE_RELOAD))
- {
-#ifdef HAVE_NETSNMP
- command = ZBX_RTC_SNMP_CACHE_RELOAD;
- /* Scope is ignored for SNMP. R/U pollers, trapper, discoverer and taskmanager always get targeted. */
- scope = 0;
- data = 0;
-#else
- zbx_error("invalid runtime control option: no SNMP support enabled");
- return FAIL;
-#endif
- }
- else if (0 != (program_type & (ZBX_PROGRAM_TYPE_SERVER | ZBX_PROGRAM_TYPE_PROXY)) &&
- 0 == strncmp(opt, ZBX_DIAGINFO, ZBX_CONST_STRLEN(ZBX_DIAGINFO)))
- {
- command = ZBX_RTC_DIAGINFO;
- data = 0;
- scope = ZBX_DIAGINFO_ALL;
-
- if ('=' == opt[ZBX_CONST_STRLEN(ZBX_DIAGINFO)])
- {
- const char *section = opt + ZBX_CONST_STRLEN(ZBX_DIAGINFO) + 1;
-
- if (0 == strcmp(section, ZBX_DIAG_HISTORYCACHE))
- {
- scope = ZBX_DIAGINFO_HISTORYCACHE;
- }
- else if (0 == strcmp(section, ZBX_DIAG_PREPROCESSING))
- {
- scope = ZBX_DIAGINFO_PREPROCESSING;
- }
- else if (0 == strcmp(section, ZBX_DIAG_LOCKS))
- {
- scope = ZBX_DIAGINFO_LOCKS;
- }
- else if (0 != (program_type & (ZBX_PROGRAM_TYPE_SERVER)))
- {
- if (0 == strcmp(section, ZBX_DIAG_VALUECACHE))
- scope = ZBX_DIAGINFO_VALUECACHE;
- else if (0 == strcmp(section, ZBX_DIAG_LLD))
- scope = ZBX_DIAGINFO_LLD;
- else if (0 == strcmp(section, ZBX_DIAG_ALERTING))
- scope = ZBX_DIAGINFO_ALERTING;
- }
-
- if (0 == scope)
- {
- zbx_error("invalid diaginfo section: %s", section);
- return FAIL;
- }
- }
- else if ('\0' != opt[ZBX_CONST_STRLEN(ZBX_DIAGINFO)])
- {
- zbx_error("invalid runtime control option: %s", opt);
- return FAIL;
- }
- }
- else if (0 != (program_type & ZBX_PROGRAM_TYPE_SERVER) && 0 == strcmp(opt, ZBX_SECRETS_RELOAD))
- {
- command = ZBX_RTC_SECRETS_RELOAD;
- scope = 0;
- data = 0;
- }
- else if (0 != (program_type & ZBX_PROGRAM_TYPE_SERVER) && 0 == strcmp(opt, ZBX_SERVICE_CACHE_RELOAD))
- {
- command = ZBX_RTC_SERVICE_CACHE_RELOAD;
- scope = 0;
- data = 0;
- }
- else if (0 != (program_type & (ZBX_PROGRAM_TYPE_SERVER)) && 0 == strcmp(opt, ZBX_TRIGGER_HOUSEKEEPER_EXECUTE))
- {
- command = ZBX_RTC_TRIGGER_HOUSEKEEPER_EXECUTE;
- scope = 0;
- data = 0;
- }
- else if (0 != (program_type & (ZBX_PROGRAM_TYPE_AGENTD)) && 0 == strcmp(opt, ZBX_USER_PARAMETERS_RELOAD))
+ else if (0 == strcmp(opt, ZBX_USER_PARAMETERS_RELOAD))
{
command = ZBX_RTC_USER_PARAMETERS_RELOAD;
scope = 0;
data = 0;
}
- else if (0 != (program_type & (ZBX_PROGRAM_TYPE_SERVER)) && 0 == strcmp(opt, ZBX_HA_STATUS))
- {
- command = ZBX_RTC_HA_STATUS;
- scope = 0;
- data = 0;
- }
- else if (0 != (program_type & (ZBX_PROGRAM_TYPE_SERVER)) &&
- 0 == strncmp(opt, ZBX_HA_REMOVE_NODE, ZBX_CONST_STRLEN(ZBX_HA_REMOVE_NODE)))
- {
- command = ZBX_RTC_HA_REMOVE_NODE;
- scope = 0;
- if ('=' != opt[ZBX_CONST_STRLEN(ZBX_HA_REMOVE_NODE)] ||
- SUCCEED != is_uint32(opt + ZBX_CONST_STRLEN(ZBX_HA_REMOVE_NODE) + 1, &data))
- {
- zbx_error("invalid HA node number: %s\n", opt);
- return FAIL;
- }
- }
- else if (0 != (program_type & (ZBX_PROGRAM_TYPE_SERVER)) &&
- 0 == strncmp(opt, ZBX_HA_SET_FAILOVER_DELAY, ZBX_CONST_STRLEN(ZBX_HA_SET_FAILOVER_DELAY)))
- {
- int delay;
-
- if ('=' == opt[ZBX_CONST_STRLEN(ZBX_HA_SET_FAILOVER_DELAY)] &&
- SUCCEED == is_time_suffix(opt + ZBX_CONST_STRLEN(ZBX_HA_SET_FAILOVER_DELAY) + 1, &delay,
- ZBX_LENGTH_UNLIMITED))
- {
- if (delay < 10 || delay > 15 * SEC_PER_MIN)
- {
- zbx_error("failover delay must be in range from 10s to 15m");
- return FAIL;
- }
-
- command = ZBX_RTC_HA_SET_FAILOVER_DELAY;
- scope = 0;
- data = (unsigned int)delay;
- }
- else
- {
- zbx_error("invalid HA failover delay value: %s\n", opt);
- return FAIL;
- }
- }
else
{
zbx_error("invalid runtime control option: %s", opt);
diff --git a/src/libs/zbxnix/control.h b/src/libs/zbxnix/control.h
index 79e641a9fdd..8e851c9de3c 100644
--- a/src/libs/zbxnix/control.h
+++ b/src/libs/zbxnix/control.h
@@ -26,6 +26,6 @@
#define ZBX_RTC_LOG_SCOPE_PROC 0
#define ZBX_RTC_LOG_SCOPE_PID 1
-int parse_rtc_options(const char *opt, unsigned char program_type, int *message);
+int parse_rtc_options(const char *opt, int *message);
#endif
diff --git a/src/libs/zbxnix/daemon.c b/src/libs/zbxnix/daemon.c
index 0b89460b190..44f781aa646 100644
--- a/src/libs/zbxnix/daemon.c
+++ b/src/libs/zbxnix/daemon.c
@@ -87,11 +87,12 @@ static void common_sigusr_handler(int flags)
}
}
-static void zbx_signal_process_by_type(int proc_type, int proc_num, int flags)
+void zbx_signal_process_by_type(int proc_type, int proc_num, int flags, char **out)
{
- int process_num, found = 0, i;
+ int process_num, found = 0, i, failed_num = 0;
union sigval s;
unsigned char process_type;
+ size_t out_alloc = 0, out_offset = 0;
s.sival_ptr = NULL;
s.ZBX_SIVAL_INT = flags;
@@ -121,53 +122,70 @@ static void zbx_signal_process_by_type(int proc_type, int proc_num, int flags)
" pid:%d", get_process_type_string(process_type), threads[i]);
}
else
+ {
zabbix_log(LOG_LEVEL_ERR, "cannot redirect signal: %s", zbx_strerror(errno));
+ failed_num++;
+ }
}
if (0 == found)
{
if (0 == proc_num)
{
- zabbix_log(LOG_LEVEL_ERR, "cannot redirect signal:"
+ zbx_strlog_alloc(LOG_LEVEL_ERR, out, &out_alloc, &out_offset, "cannot redirect signal:"
" \"%s\" process does not exist",
get_process_type_string(proc_type));
}
else
{
- zabbix_log(LOG_LEVEL_ERR, "cannot redirect signal:"
+ zbx_strlog_alloc(LOG_LEVEL_ERR, out, &out_alloc, &out_offset, "cannot redirect signal:"
" \"%s #%d\" process does not exist",
get_process_type_string(proc_type), proc_num);
}
}
+ else
+ {
+ if (0 != failed_num)
+ *out = zbx_strdup(*out, "failed to redirect remote control signal(s)");
+ }
}
-static void zbx_signal_process_by_pid(int pid, int flags)
+void zbx_signal_process_by_pid(int pid, int flags, char **out)
{
union sigval s;
- int i, found = 0;
+ int i, found = 0, failed_num = 0;
+ size_t out_alloc = 0, out_offset = 0;
+ s.sival_ptr = NULL;
s.ZBX_SIVAL_INT = flags;
for (i = 0; i < threads_num; i++)
{
- if (0 != pid && threads[i] != ZBX_RTC_GET_DATA(flags))
+ if ((0 != pid && threads[i] != pid) || 0 == threads[i])
continue;
found = 1;
if (-1 != sigqueue(threads[i], SIGUSR1, s))
{
- zabbix_log(LOG_LEVEL_DEBUG, "the signal was redirected to process pid:%d",
- threads[i]);
+ zabbix_log(LOG_LEVEL_DEBUG, "the signal was redirected to process pid:%d", threads[i]);
}
else
+ {
zabbix_log(LOG_LEVEL_ERR, "cannot redirect signal: %s", zbx_strerror(errno));
+ failed_num++;
+ }
}
- if (0 != ZBX_RTC_GET_DATA(flags) && 0 == found)
+ if (0 != pid && 0 == found)
+ {
+ zbx_strlog_alloc(LOG_LEVEL_DEBUG, out, &out_alloc, &out_offset,
+ "cannot redirect signal: process pid:%d is not a Zabbix child process", pid);
+ }
+ else
{
- zabbix_log(LOG_LEVEL_ERR, "cannot redirect signal: process pid:%d is not a Zabbix child"
- " process", ZBX_RTC_GET_DATA(flags));
+ if (0 != failed_num)
+ *out = zbx_strdup(*out, "failed to redirect remote control signal(s)");
}
}
@@ -215,42 +233,28 @@ static void user1_signal_handler(int sig, siginfo_t *siginfo, void *context)
return;
}
- switch (ZBX_RTC_GET_MSG(flags))
+ if (0 == (program_type & ZBX_PROGRAM_TYPE_AGENTD))
{
- case ZBX_RTC_CONFIG_CACHE_RELOAD:
- if (0 != (program_type & ZBX_PROGRAM_TYPE_PROXY_PASSIVE))
- {
- zabbix_log(LOG_LEVEL_WARNING, "forced reloading of the configuration cache"
- " cannot be performed for a passive proxy");
- return;
- }
+ zabbix_log(LOG_LEVEL_ERR, "cannot redirect signal: runtime control signals are supported only by agent");
+ return;
+ }
- if (0 != (program_type & ZBX_PROGRAM_TYPE_SERVER))
- {
- zbx_signal_process_by_type(ZBX_PROCESS_TYPE_SERVICEMAN, 1,
- ZBX_RTC_MAKE_MESSAGE(ZBX_RTC_SERVICE_CACHE_RELOAD, 0, 0));
- }
- ZBX_FALLTHROUGH;
- case ZBX_RTC_SECRETS_RELOAD:
- zbx_signal_process_by_type(ZBX_PROCESS_TYPE_CONFSYNCER, 1, flags);
- break;
- case ZBX_RTC_HOUSEKEEPER_EXECUTE:
- zbx_signal_process_by_type(ZBX_PROCESS_TYPE_HOUSEKEEPER, 1, flags);
- break;
+ switch (ZBX_RTC_GET_MSG(flags))
+ {
case ZBX_RTC_LOG_LEVEL_INCREASE:
case ZBX_RTC_LOG_LEVEL_DECREASE:
scope = ZBX_RTC_GET_SCOPE(flags);
if ((ZBX_RTC_LOG_SCOPE_FLAG | ZBX_RTC_LOG_SCOPE_PID) == scope)
{
- zbx_signal_process_by_pid(ZBX_RTC_GET_DATA(flags), flags);
+ zbx_signal_process_by_pid(ZBX_RTC_GET_DATA(flags), flags, NULL);
}
else
{
if (scope < ZBX_PROCESS_TYPE_EXT_FIRST)
{
zbx_signal_process_by_type(ZBX_RTC_GET_SCOPE(flags), ZBX_RTC_GET_DATA(flags),
- flags);
+ flags, NULL);
}
}
@@ -259,22 +263,9 @@ static void user1_signal_handler(int sig, siginfo_t *siginfo, void *context)
zbx_sigusr_handler(flags);
break;
- case ZBX_RTC_SNMP_CACHE_RELOAD:
- zbx_signal_process_by_type(ZBX_PROCESS_TYPE_UNREACHABLE, ZBX_RTC_GET_DATA(flags), flags);
- zbx_signal_process_by_type(ZBX_PROCESS_TYPE_POLLER, ZBX_RTC_GET_DATA(flags), flags);
- zbx_signal_process_by_type(ZBX_PROCESS_TYPE_TRAPPER, ZBX_RTC_GET_DATA(flags), flags);
- zbx_signal_process_by_type(ZBX_PROCESS_TYPE_DISCOVERER, ZBX_RTC_GET_DATA(flags), flags);
- zbx_signal_process_by_type(ZBX_PROCESS_TYPE_TASKMANAGER, ZBX_RTC_GET_DATA(flags), flags);
- break;
- case ZBX_RTC_TRIGGER_HOUSEKEEPER_EXECUTE:
- zbx_signal_process_by_type(ZBX_PROCESS_TYPE_PROBLEMHOUSEKEEPER, 1, flags);
- break;
- case ZBX_RTC_SERVICE_CACHE_RELOAD:
- zbx_signal_process_by_type(ZBX_PROCESS_TYPE_SERVICEMAN, ZBX_RTC_GET_DATA(flags), flags);
- break;
case ZBX_RTC_USER_PARAMETERS_RELOAD:
- zbx_signal_process_by_type(ZBX_PROCESS_TYPE_ACTIVE_CHECKS, ZBX_RTC_GET_DATA(flags), flags);
- zbx_signal_process_by_type(ZBX_PROCESS_TYPE_LISTENER, ZBX_RTC_GET_DATA(flags), flags);
+ zbx_signal_process_by_type(ZBX_PROCESS_TYPE_ACTIVE_CHECKS, ZBX_RTC_GET_DATA(flags), flags, NULL);
+ zbx_signal_process_by_type(ZBX_PROCESS_TYPE_LISTENER, ZBX_RTC_GET_DATA(flags), flags, NULL);
break;
default:
if (NULL != zbx_sigusr_handler)
@@ -453,6 +444,7 @@ int zbx_sigusr_send(int flags)
{
union sigval s;
+ s.sival_ptr = NULL;
s.ZBX_SIVAL_INT = flags;
if (-1 != sigqueue(pid, SIGUSR1, s))
diff --git a/src/libs/zbxrtc/Makefile.am b/src/libs/zbxrtc/Makefile.am
new file mode 100644
index 00000000000..a739d3868f6
--- /dev/null
+++ b/src/libs/zbxrtc/Makefile.am
@@ -0,0 +1,33 @@
+## Process this file with automake to produce Makefile.in
+
+noinst_LIBRARIES = \
+ libzbxrtc.a \
+ libzbxrtc_service.a \
+ libzbxrtc_server.a \
+ libzbxrtc_proxy.a
+
+# common rtc functionality
+
+libzbxrtc_a_SOURCES = \
+ rtc.c \
+ rtc.h
+
+# common rtc service functionality
+
+libzbxrtc_service_a_SOURCES = \
+ rtc_service.c \
+ rtc_client.c \
+ rtc.h
+
+# server specific functionality
+
+libzbxrtc_server_a_SOURCES = \
+ rtc_server.c \
+ rtc.h
+
+# proxy specific functionality
+
+libzbxrtc_proxy_a_SOURCES = \
+ rtc_proxy.c \
+ rtc.h
+
diff --git a/src/libs/zbxrtc/rtc.c b/src/libs/zbxrtc/rtc.c
new file mode 100644
index 00000000000..f333fd8d192
--- /dev/null
+++ b/src/libs/zbxrtc/rtc.c
@@ -0,0 +1,120 @@
+/*
+** Zabbix
+** Copyright (C) 2001-2021 Zabbix SIA
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+**/
+
+#include "zbxipcservice.h"
+#include "zbxjson.h"
+#include "daemon.h"
+#include "zbxrtc.h"
+#include "rtc.h"
+#include "log.h"
+#include "zbxdiag.h"
+
+/******************************************************************************
+ * *
+ * Function: zbx_rtc_parse_loglevel_option *
+ * *
+ * Purpose: parse loglevel runtime control option *
+ * *
+ * Parameters: opt - [IN] the runtime control option *
+ * len - [IN] the runtime control option length without *
+ * parameter *
+ * pid - [OUT] the target pid (if specified) *
+ * proc_type - [OUT] the target process type (if specified) *
+ * proc_num - [OUT] the target process num (if specified) *
+ * error - [OUT] the error message *
+ * *
+ * Return value: SUCCEED - the runtime control option was processed *
+ * FAIL - otherwise *
+ * *
+ ******************************************************************************/
+int zbx_rtc_parse_loglevel_option(const char *opt, size_t len, pid_t *pid, int *proc_type, int *proc_num,
+ char **error)
+{
+ const char *rtc_options;
+
+ rtc_options = opt + len;
+
+ if ('\0' == *rtc_options)
+ return SUCCEED;
+
+ if ('=' != *rtc_options)
+ {
+ *error = zbx_dsprintf(NULL, "invalid runtime control option \"%s\"", opt);
+ return FAIL;
+ }
+ else if (0 != isdigit(*(++rtc_options)))
+ {
+ /* convert PID */
+ if (FAIL == is_uint32(rtc_options, pid) || 0 == *pid)
+ {
+ *error = zbx_dsprintf(NULL, "invalid log level control target -"
+ " invalid or unsupported process identifier");
+ return FAIL;
+ }
+ }
+ else
+ {
+ char proc_name[MAX_STRING_LEN], *proc_num_ptr;
+
+ if ('\0' == *rtc_options)
+ {
+ *error = zbx_dsprintf(NULL, "invalid log level control target -"
+ " unspecified process identifier or type");
+ return FAIL;
+ }
+
+ zbx_strlcpy(proc_name, rtc_options, sizeof(proc_name));
+
+ if (NULL != (proc_num_ptr = strchr(proc_name, ',')))
+ *proc_num_ptr++ = '\0';
+
+ if ('\0' == *proc_name)
+ {
+ *error = zbx_dsprintf(NULL, "invalid log level control target - unspecified process type");
+ return FAIL;
+ }
+
+ if (ZBX_PROCESS_TYPE_UNKNOWN == (*proc_type = get_process_type_by_name(proc_name)))
+ {
+ *error = zbx_dsprintf(NULL, "invalid log level control target - unknown process type \"%s\"",
+ proc_name);
+ return FAIL;
+ }
+
+ if (NULL != proc_num_ptr)
+ {
+ if ('\0' == *proc_num_ptr)
+ {
+ *error = zbx_dsprintf(NULL, "invalid log level control target -"
+ " unspecified process number");
+ return FAIL;
+ }
+
+ /* convert Zabbix process number (e.g. "2" in "poller,2") */
+ if (FAIL == is_uint32(proc_num_ptr, proc_num) || 0 == *proc_num)
+ {
+ *error = zbx_dsprintf(NULL, "invalid log level control target -"
+ " invalid or unsupported process number \"%s\"", proc_num_ptr);
+ return FAIL;
+ }
+ }
+ }
+
+ return SUCCEED;
+}
diff --git a/src/zabbix_server/rtc.h b/src/libs/zbxrtc/rtc.h
index 6926f627c74..57d67b55e4e 100644
--- a/src/zabbix_server/rtc.h
+++ b/src/libs/zbxrtc/rtc.h
@@ -20,6 +20,12 @@
#ifndef ZABBIX_RTC_H
#define ZABBIX_RTC_H
-void zbx_rtc_process_command(unsigned int command);
+#define ZBX_IPC_SERVICE_RTC "rtc"
+
+int zbx_rtc_parse_loglevel_option(const char *opt, size_t len, pid_t *pid, int *proc_type, int *proc_num,
+ char **error);
+
+int rtc_parse_options_ex(const char *opt, zbx_uint32_t *code, char **data, char **error);
+int rtc_process_request_ex(int code, const unsigned char *data, char **result);
#endif
diff --git a/src/libs/zbxrtc/rtc_client.c b/src/libs/zbxrtc/rtc_client.c
new file mode 100644
index 00000000000..f5c6a698539
--- /dev/null
+++ b/src/libs/zbxrtc/rtc_client.c
@@ -0,0 +1,251 @@
+/*
+** Zabbix
+** Copyright (C) 2001-2021 Zabbix SIA
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+**/
+
+#include "zbxipcservice.h"
+#include "zbxjson.h"
+#include "zbxrtc.h"
+#include "rtc.h"
+
+extern int CONFIG_TIMEOUT;
+
+/******************************************************************************
+ * *
+ * Function: rtc_parse_log_level_parameter *
+ * *
+ * Purpose: parse loglevel runtime control option *
+ * *
+ * Parameters: opt - [IN] the runtime control option *
+ * len - [IN] the runtime control option length without *
+ * parameter *
+ * data - [OUT] the runtime control option result *
+ * error - [OUT] error message *
+ * *
+ * Return value: SUCCEED - the runtime control option was processed *
+ * FAIL - otherwise *
+ * *
+ ******************************************************************************/
+static int rtc_parse_log_level_parameter(const char *opt, size_t len, char **data, char **error)
+{
+ struct zbx_json j;
+ const char *proc_name;
+ int pid = 0, proc_num = 0, proc_type = ZBX_PROCESS_TYPE_UNKNOWN;
+
+ if (SUCCEED != zbx_rtc_parse_loglevel_option(opt, len, &pid, &proc_type, &proc_num, error))
+ return FAIL;
+
+ if (0 != pid)
+ {
+ zbx_json_init(&j, 1024);
+ zbx_json_addint64(&j, ZBX_PROTO_TAG_PID, pid);
+ goto finish;
+ }
+
+ if (ZBX_PROCESS_TYPE_UNKNOWN == proc_type)
+ return SUCCEED;
+
+ proc_name = get_process_type_string((unsigned char)proc_type);
+
+ zbx_json_init(&j, 1024);
+ zbx_json_addstring(&j, ZBX_PROTO_TAG_PROCESS_NAME, proc_name, ZBX_JSON_TYPE_STRING);
+
+ if (0 != proc_num)
+ zbx_json_addint64(&j, ZBX_PROTO_TAG_PROCESS_NUM, proc_num);
+
+finish:
+ *data = zbx_strdup(NULL, j.buffer);
+ zbx_json_clean(&j);
+
+ return SUCCEED;
+}
+
+/******************************************************************************
+ * *
+ * Function: rtc_parse_options *
+ * *
+ * Purpose: parse runtime control options and create a runtime control *
+ * message *
+ * *
+ * Parameters: opt - [IN] the command line argument *
+ * program_type - [IN] the program type *
+ * message - [OUT] the message containing options for log *
+ * level change or cache reload *
+ * *
+ * Return value: SUCCEED - the message was created successfully *
+ * FAIL - an error occurred *
+ * *
+ ******************************************************************************/
+static int rtc_parse_options(const char *opt, zbx_uint32_t *code, char **data, char **error)
+{
+ if (0 == strncmp(opt, ZBX_LOG_LEVEL_INCREASE, ZBX_CONST_STRLEN(ZBX_LOG_LEVEL_INCREASE)))
+ {
+ *code = ZBX_RTC_LOG_LEVEL_INCREASE;
+
+ return rtc_parse_log_level_parameter(opt, ZBX_CONST_STRLEN(ZBX_LOG_LEVEL_INCREASE), data, error);
+ }
+
+ if (0 == strncmp(opt, ZBX_LOG_LEVEL_DECREASE, ZBX_CONST_STRLEN(ZBX_LOG_LEVEL_DECREASE)))
+ {
+ *code = ZBX_RTC_LOG_LEVEL_DECREASE;
+
+ return rtc_parse_log_level_parameter(opt, ZBX_CONST_STRLEN(ZBX_LOG_LEVEL_DECREASE), data, error);
+ }
+
+ if (0 == strcmp(opt, ZBX_CONFIG_CACHE_RELOAD))
+ {
+ *code = ZBX_RTC_CONFIG_CACHE_RELOAD;
+ return SUCCEED;
+ }
+
+ if (0 == strcmp(opt, ZBX_HOUSEKEEPER_EXECUTE))
+ {
+ *code = ZBX_RTC_HOUSEKEEPER_EXECUTE;
+ return SUCCEED;
+ }
+
+ if (0 == strcmp(opt, ZBX_SNMP_CACHE_RELOAD))
+ {
+#ifdef HAVE_NETSNMP
+ *code = ZBX_RTC_SNMP_CACHE_RELOAD;
+ return SUCCEED;
+#else
+ *error = zbx_strdup(NULL, "invalid runtime control option - no SNMP support enabled");
+ return FAIL;
+#endif
+ }
+
+ if (0 == strncmp(opt, ZBX_DIAGINFO, ZBX_CONST_STRLEN(ZBX_DIAGINFO)))
+ {
+ const char *param = opt + ZBX_CONST_STRLEN(ZBX_DIAGINFO);
+
+ if ('=' == *param)
+ param++;
+ else if ('\0' == *param)
+ param = "all";
+ else
+ param = NULL;
+
+ if (NULL != param)
+ {
+ struct zbx_json j;
+
+ *code = ZBX_RTC_DIAGINFO;
+
+ zbx_json_init(&j, 1024);
+ zbx_json_addstring(&j, ZBX_PROTO_TAG_SECTION, param, ZBX_JSON_TYPE_STRING);
+ *data = zbx_strdup(NULL, j.buffer);
+ zbx_json_clean(&j);
+
+ return SUCCEED;
+ }
+ }
+
+ return SUCCEED;
+}
+
+/******************************************************************************
+ * *
+ * Function: zbx_rtc_process *
+ * *
+ * Purpose: process runtime control option and print result *
+ * *
+ * Parameters: opt - [IN] the runtime control option *
+ * error - [OUT] error message *
+ * *
+ * Return value: SUCCEED - the runtime control option was processed *
+ * FAIL - otherwise *
+ * *
+ ******************************************************************************/
+int zbx_rtc_process(const char *option, char **error)
+{
+ zbx_uint32_t code = ZBX_RTC_UNKNOWN, size = 0;
+ char *data = NULL;
+ unsigned char *result = NULL;
+ int ret;
+
+ if (SUCCEED != rtc_parse_options(option, &code, &data, error))
+ return FAIL;
+
+ if (ZBX_RTC_UNKNOWN == code)
+ {
+ if (SUCCEED != rtc_parse_options_ex(option, &code, &data, error))
+ return FAIL;
+
+ if (ZBX_RTC_UNKNOWN == code)
+ {
+ *error = zbx_dsprintf(NULL, "unknown option \"%s\"", option);
+ return FAIL;
+ }
+ }
+
+ if (NULL != data)
+ size = (zbx_uint32_t)strlen(data) + 1;
+
+ if (SUCCEED == (ret = zbx_ipc_async_exchange(ZBX_IPC_SERVICE_RTC, code, CONFIG_TIMEOUT, (unsigned char *)data,
+ size, &result, error)))
+ {
+ if (NULL != result)
+ {
+ printf("%s", result);
+ zbx_free(result);
+ }
+ else
+ printf("No response\n");
+
+ }
+
+ zbx_free(data);
+
+ return ret;
+}
+
+int zbx_rtc_open(zbx_ipc_async_socket_t *asocket, int timeout, char **error)
+{
+ if (FAIL == zbx_ipc_async_socket_open(asocket, ZBX_IPC_SERVICE_RTC, timeout, error))
+ return FAIL;
+
+ return SUCCEED;
+}
+
+/******************************************************************************
+ * *
+ * Function: zbx_rtc_notify_config_sync *
+ * *
+ * Purpose: notify RTC service about finishing initial configuration sync *
+ * *
+ * Parameters: error - [OUT] error message *
+ * *
+ * Return value: SUCCEED - the notification was sent successfully *
+ * FAIL - otherwise *
+ * *
+ ******************************************************************************/
+int zbx_rtc_notify_config_sync(char **error)
+{
+ zbx_ipc_socket_t sock;
+ int ret;
+
+ if (FAIL == zbx_ipc_socket_open(&sock, ZBX_IPC_SERVICE_RTC, CONFIG_TIMEOUT, error))
+ return FAIL;
+
+ if (FAIL == (ret = zbx_ipc_socket_write(&sock, ZBX_RTC_CONFIG_SYNC_NOTIFY, NULL, 0)))
+ *error = zbx_strdup(NULL, "failed to send message");
+
+ zbx_ipc_socket_close(&sock);
+
+ return ret;
+}
diff --git a/src/libs/zbxrtc/rtc_proxy.c b/src/libs/zbxrtc/rtc_proxy.c
new file mode 100644
index 00000000000..6a9b3096476
--- /dev/null
+++ b/src/libs/zbxrtc/rtc_proxy.c
@@ -0,0 +1,54 @@
+/*
+** Zabbix
+** Copyright (C) 2001-2021 Zabbix SIA
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+**/
+
+#include "zbxipcservice.h"
+#include "zbxrtc.h"
+#include "rtc.h"
+#include "proxy.h"
+
+extern int CONFIG_PROXYMODE;
+
+int rtc_parse_options_ex(const char *opt, zbx_uint32_t *code, char **data, char **error)
+{
+ ZBX_UNUSED(opt);
+ ZBX_UNUSED(code);
+ ZBX_UNUSED(data);
+ ZBX_UNUSED(error);
+
+ return SUCCEED;
+}
+
+int rtc_process_request_ex(int code, const unsigned char *data, char **result)
+{
+ ZBX_UNUSED(data);
+
+ switch (code)
+ {
+ case ZBX_RTC_CONFIG_CACHE_RELOAD:
+ if (ZBX_PROXYMODE_PASSIVE == CONFIG_PROXYMODE)
+ {
+ *result = zbx_strdup(NULL, "Cannot perform configuration cache reloading on passive"
+ " proxy\n");
+ return SUCCEED;
+ }
+ return FAIL;
+ }
+
+ return FAIL;
+}
diff --git a/src/libs/zbxrtc/rtc_server.c b/src/libs/zbxrtc/rtc_server.c
new file mode 100644
index 00000000000..76a638b4901
--- /dev/null
+++ b/src/libs/zbxrtc/rtc_server.c
@@ -0,0 +1,473 @@
+/*
+** Zabbix
+** Copyright (C) 2001-2021 Zabbix SIA
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+**/
+
+#include "zbxipcservice.h"
+#include "daemon.h"
+#include "log.h"
+#include "zbxdiag.h"
+#include "zbxjson.h"
+#include "zbxha.h"
+#include "zbxrtc.h"
+#include "rtc.h"
+
+int rtc_parse_options_ex(const char *opt, zbx_uint32_t *code, char **data, char **error)
+{
+ const char *param;
+
+ if (0 == strcmp(opt, ZBX_SECRETS_RELOAD))
+ {
+ *code = ZBX_RTC_SECRETS_RELOAD;
+ return SUCCEED;
+ }
+
+ if (0 == strcmp(opt, ZBX_SERVICE_CACHE_RELOAD))
+ {
+ *code = ZBX_RTC_SERVICE_CACHE_RELOAD;
+ return SUCCEED;
+ }
+
+ if (0 == strcmp(opt, ZBX_TRIGGER_HOUSEKEEPER_EXECUTE))
+ {
+ *code = ZBX_RTC_TRIGGER_HOUSEKEEPER_EXECUTE;
+ return SUCCEED;
+ }
+
+ if (0 == strcmp(opt, ZBX_HA_STATUS))
+ {
+ *code = ZBX_RTC_HA_STATUS;
+ return SUCCEED;
+ }
+
+ if (0 == strncmp(opt, ZBX_HA_REMOVE_NODE, ZBX_CONST_STRLEN(ZBX_HA_REMOVE_NODE)))
+ {
+ param = opt + ZBX_CONST_STRLEN(ZBX_HA_REMOVE_NODE);
+
+ if ('=' == *param)
+ {
+ struct zbx_json j;
+
+ *code = ZBX_RTC_HA_REMOVE_NODE;
+
+ zbx_json_init(&j, 1024);
+ zbx_json_addstring(&j, ZBX_PROTO_TAG_NODE, param + 1, ZBX_JSON_TYPE_STRING);
+ *data = zbx_strdup(NULL, j.buffer);
+ zbx_json_clean(&j);
+
+ return SUCCEED;
+ }
+
+ if ('\0' == *param)
+ {
+ *error = zbx_strdup(NULL, "missing node cuid or name parameter");
+ return FAIL;
+ }
+
+ /* not ha_remove_node runtime control option */
+ }
+
+ if (0 == strncmp(opt, ZBX_HA_SET_FAILOVER_DELAY, ZBX_CONST_STRLEN(ZBX_HA_SET_FAILOVER_DELAY)))
+ {
+ int delay;
+
+ param = opt + ZBX_CONST_STRLEN(ZBX_HA_SET_FAILOVER_DELAY);
+
+ if ('=' == *param)
+ {
+ if (SUCCEED == is_time_suffix(param + 1, &delay, ZBX_LENGTH_UNLIMITED))
+ {
+ struct zbx_json j;
+
+ if (delay < 10 || delay > 15 * SEC_PER_MIN)
+ {
+ *error = zbx_strdup(NULL, "failover delay must be in range from 10s to 15m");
+ return FAIL;
+ }
+
+ *code = ZBX_RTC_HA_SET_FAILOVER_DELAY;
+
+ zbx_json_init(&j, 1024);
+ zbx_json_addint64(&j, ZBX_PROTO_TAG_FAILOVER_DELAY, delay);
+ *data = zbx_strdup(NULL, j.buffer);
+ zbx_json_clean(&j);
+
+ return SUCCEED;
+ }
+ else
+ {
+ *error = zbx_dsprintf(NULL, "invalid HA failover delay parameter: %s\n", param + 1);
+ return FAIL;
+ }
+ }
+
+ if ('\0' == *param)
+ {
+ *error = zbx_strdup(NULL, "missing failover delay parameter");
+ return FAIL;
+ }
+ }
+
+ return SUCCEED;
+}
+
+/******************************************************************************
+ * *
+ * Function: rtc_process_loglevel *
+ * *
+ * Purpose: process loglevel runtime control option *
+ * *
+ * Parameters: direction - [IN] the loglevel change direction: *
+ * (1) - increase, (-1) - decrease *
+ * data - [IN] the runtime control parameter (optional) *
+ * result - [OUT] the runtime control result *
+ * *
+ * Return value: SUCCEED - the loglevel command was processed *
+ * FAIL - the loglevel command must be processed by the *
+ * default loglevel command handler *
+ * *
+ ******************************************************************************/
+static int rtc_process_loglevel(int direction, const char *data, char **result)
+{
+ struct zbx_json_parse jp;
+ char buf[MAX_STRING_LEN];
+ int process_num = 0;
+
+ if (NULL == data)
+ {
+ (void)zbx_ha_change_loglevel(direction, result);
+ return FAIL;
+ }
+
+ if (FAIL == zbx_json_open(data, &jp))
+ {
+ *result = zbx_dsprintf(NULL, "Invalid parameters \"%s\"\n", data);
+ return SUCCEED;
+ }
+
+ if (SUCCEED == zbx_json_value_by_name(&jp, ZBX_PROTO_TAG_PROCESS_NUM, buf, sizeof(buf), NULL))
+ process_num = atoi(buf);
+
+ if (SUCCEED != zbx_json_value_by_name(&jp, ZBX_PROTO_TAG_PROCESS_NAME, buf, sizeof(buf), NULL))
+ {
+ return FAIL;
+ }
+
+ if (0 == strcmp(buf, "ha manager"))
+ {
+ if (0 != process_num && 1 != process_num)
+ {
+ *result = zbx_dsprintf(NULL, "Invalid option parameter \"%d\"\n", process_num);
+ }
+ else
+ {
+ (void)zbx_ha_change_loglevel(direction, result);
+ *result = zbx_strdup(NULL, "Changed HA manager log level\n");
+
+ }
+ return SUCCEED;
+ }
+
+ return FAIL;
+}
+
+
+/******************************************************************************
+ * *
+ * Function: rtc_process_diaginfo *
+ * *
+ * Purpose: process diaginfo runtime control option *
+ * *
+ * Parameters: data - [IN] the runtime control parameter (optional) *
+ * result - [OUT] the runtime control result *
+ * *
+ ******************************************************************************/
+static void rtc_process_diaginfo(const char *data, char **result)
+{
+ struct zbx_json_parse jp;
+ char buf[MAX_STRING_LEN];
+ unsigned int scope;
+
+ if (FAIL == zbx_json_open(data, &jp) ||
+ SUCCEED != zbx_json_value_by_name(&jp, ZBX_PROTO_TAG_SECTION, buf, sizeof(buf), NULL))
+ {
+ *result = zbx_dsprintf(NULL, "Invalid parameter \"%s\"\n", data);
+ return;
+ }
+
+ if (0 == strcmp(buf, "all"))
+ {
+ scope = (1 << ZBX_DIAGINFO_HISTORYCACHE) | (1 << ZBX_DIAGINFO_PREPROCESSING) |
+ (1 << ZBX_DIAGINFO_LOCKS) | (1 << ZBX_DIAGINFO_VALUECACHE) |
+ (1 << ZBX_DIAGINFO_LLD) | (1 << ZBX_DIAGINFO_ALERTING);
+ }
+ else if (0 == strcmp(buf, ZBX_DIAG_HISTORYCACHE))
+ scope = 1 << ZBX_DIAGINFO_HISTORYCACHE;
+ else if (0 == strcmp(buf, ZBX_DIAG_PREPROCESSING))
+ scope = 1 << ZBX_DIAGINFO_PREPROCESSING;
+ else if (0 == strcmp(buf, ZBX_DIAG_LOCKS))
+ scope = 1 << ZBX_DIAGINFO_LOCKS;
+ else if (0 == strcmp(buf, ZBX_DIAG_VALUECACHE))
+ scope = 1 << ZBX_DIAGINFO_VALUECACHE;
+ else if (0 == strcmp(buf, ZBX_DIAG_LLD))
+ scope = 1 << ZBX_DIAGINFO_LLD;
+ else if (0 == strcmp(buf, ZBX_DIAG_ALERTING))
+ scope = 1 << ZBX_DIAGINFO_ALERTING;
+ else
+ return;
+
+ zbx_diag_log_info(scope, result);
+}
+
+/******************************************************************************
+ * *
+ * Function: rtc_ha_status *
+ * *
+ * Purpose: process ha_status runtime command *
+ * *
+ ******************************************************************************/
+static void rtc_ha_status(char **out)
+{
+ char *nodes = NULL, *error = NULL;
+ struct zbx_json_parse jp, jp_node;
+ size_t out_alloc = 0, out_offset = 0;
+ int failover_delay;
+
+ if (SUCCEED != zbx_ha_get_failover_delay(&failover_delay, &error))
+ {
+ zbx_strlog_alloc(LOG_LEVEL_ERR, out, &out_alloc, &out_offset, "cannot get failover delay: %s",
+ error);
+ zbx_free(error);
+ return;
+ }
+
+ if (SUCCEED != zbx_ha_get_nodes(&nodes, &error))
+ {
+ zbx_strlog_alloc(LOG_LEVEL_ERR, out, &out_alloc, &out_offset, "cannot get HA node information: %s",
+ error);
+ zbx_free(error);
+ return;
+ }
+
+#define ZBX_HA_REPORT_FMT "%-25s %-25s %-30s %-11s %s"
+
+ if (SUCCEED == zbx_json_open(nodes, &jp))
+ {
+ const char *pnext;
+ char name[256], address[261], id[26], buffer[256];
+ int status, lastaccess_age, index = 1;
+
+ zbx_strlog_alloc(LOG_LEVEL_INFORMATION, out, &out_alloc, &out_offset, "failover delay: %d seconds",
+ failover_delay);
+
+ zbx_strlog_alloc(LOG_LEVEL_INFORMATION, out, &out_alloc, &out_offset, "cluster status:");
+ zbx_strlog_alloc(LOG_LEVEL_INFORMATION, out, &out_alloc, &out_offset, " %2s " ZBX_HA_REPORT_FMT, "#",
+ "ID", "Name", "Address", "Status", "Last Access");
+
+ for (pnext = NULL; NULL != (pnext = zbx_json_next(&jp, pnext));)
+ {
+ if (FAIL == zbx_json_brackets_open(pnext, &jp_node))
+ {
+ THIS_SHOULD_NEVER_HAPPEN;
+ continue;
+ }
+
+ if (SUCCEED != zbx_json_value_by_name(&jp_node, ZBX_PROTO_TAG_ID, id, sizeof(id), NULL))
+ {
+ THIS_SHOULD_NEVER_HAPPEN;
+ continue;
+ }
+
+ if (SUCCEED != zbx_json_value_by_name(&jp_node, ZBX_PROTO_TAG_NAME, name, sizeof(name),
+ NULL))
+ {
+ THIS_SHOULD_NEVER_HAPPEN;
+ continue;
+ }
+
+ if (SUCCEED != zbx_json_value_by_name(&jp_node, ZBX_PROTO_TAG_STATUS, buffer,
+ sizeof(buffer), NULL))
+ {
+ THIS_SHOULD_NEVER_HAPPEN;
+ continue;
+ }
+ status = atoi(buffer);
+
+ if (SUCCEED != zbx_json_value_by_name(&jp_node, ZBX_PROTO_TAG_LASTACCESS_AGE, buffer,
+ sizeof(buffer), NULL))
+ {
+ THIS_SHOULD_NEVER_HAPPEN;
+ continue;
+ }
+ lastaccess_age = atoi(buffer);
+
+ if (SUCCEED != zbx_json_value_by_name(&jp_node, ZBX_PROTO_TAG_ADDRESS, address,
+ sizeof(address), NULL))
+ {
+ THIS_SHOULD_NEVER_HAPPEN;
+ continue;
+ }
+
+ zbx_strlog_alloc(LOG_LEVEL_INFORMATION, out, &out_alloc, &out_offset, " %2d. "
+ ZBX_HA_REPORT_FMT, index++, id, '\0' != *name ? name : "<standalone server>",
+ address, zbx_ha_status_str(status), zbx_age2str(lastaccess_age));
+ }
+ }
+ else
+ {
+ zbx_strlog_alloc(LOG_LEVEL_ERR, out, &out_alloc, &out_offset, "invalid response: %s",
+ nodes);
+ }
+ zbx_free(nodes);
+
+#undef ZBX_HA_REPORT_FMT
+}
+
+/******************************************************************************
+ * *
+ * Function: rtc_ha_remove_node *
+ * *
+ * Purpose: process ha_remove_node runtime command *
+ * *
+ ******************************************************************************/
+static void rtc_ha_remove_node(const char *data, char **out)
+{
+ char *error = NULL;
+ struct zbx_json_parse jp;
+ char buf[MAX_STRING_LEN];
+ size_t out_alloc = 0, out_offset = 0;
+
+ if (FAIL == zbx_json_open(data, &jp))
+ {
+ *out = zbx_dsprintf(NULL, "Invalid parameter format \"%s\"\n", data);
+ return;
+ }
+
+ if (SUCCEED != zbx_json_value_by_name(&jp, ZBX_PROTO_TAG_NODE, buf, sizeof(buf), NULL))
+ {
+ *out = zbx_dsprintf(NULL, "Missing node parameter \"%s\"\n", data);
+ return;
+ }
+
+ if (SUCCEED != zbx_ha_remove_node(buf, out, &error))
+ {
+ zbx_strlog_alloc(LOG_LEVEL_ERR, out, &out_alloc, &out_offset, "cannot remove HA node: %s", error);
+ zbx_free(error);
+ return;
+ }
+}
+
+/******************************************************************************
+ * *
+ * Function: rtc_ha_failover_delay *
+ * *
+ * Purpose: process ha_failover_delay runtime command *
+ * *
+ ******************************************************************************/
+static void rtc_ha_failover_delay(const char *data, char **out)
+{
+ char *error = NULL;
+ struct zbx_json_parse jp;
+ char buf[MAX_STRING_LEN];
+ int failover_delay;
+ size_t out_alloc = 0, out_offset = 0;
+
+ if (FAIL == zbx_json_open(data, &jp))
+ {
+ *out = zbx_dsprintf(NULL, "Invalid parameter format \"%s\"\n", data);
+ return;
+ }
+
+ if (SUCCEED != zbx_json_value_by_name(&jp, ZBX_PROTO_TAG_FAILOVER_DELAY, buf, sizeof(buf), NULL))
+ {
+ *out = zbx_dsprintf(NULL, "Missing failover_delay parameter \"%s\"\n", data);
+ return;
+ }
+
+ if (10 > (failover_delay = atoi(buf)) || 15 * SEC_PER_MIN < failover_delay)
+ {
+ *out = zbx_dsprintf(NULL, "Invalid failover delay value \"%s\"\n", buf);
+ return;
+ }
+
+ if (SUCCEED != zbx_ha_set_failover_delay(failover_delay, &error))
+ {
+ zbx_strlog_alloc(LOG_LEVEL_ERR, out, &out_alloc, &out_offset, "cannot set HA failover delay: %s", error);
+ zbx_free(error);
+ return;
+ }
+
+ *out = zbx_dsprintf(NULL, "HA failover delay set to %d seconds\n", failover_delay);
+
+}
+/******************************************************************************
+ * *
+ * Function: rtc_process_request_ex *
+ * *
+ * Purpose: process runtime control option *
+ * *
+ * Parameters: code - [IN] the request code *
+ * data - [IN] the runtime control parameter (optional) *
+ * result - [OUT] the runtime control result *
+ * *
+ * Return value: SUCCEED - the rtc command was processed *
+ * FAIL - the rtc command must be processed by the default *
+ * rtc command handler *
+ * *
+ ******************************************************************************/
+int rtc_process_request_ex(int code, const unsigned char *data, char **result)
+{
+ ZBX_UNUSED(data);
+
+ switch (code)
+ {
+ case ZBX_RTC_LOG_LEVEL_INCREASE:
+ return rtc_process_loglevel(1, (const char *)data, result);
+ case ZBX_RTC_LOG_LEVEL_DECREASE:
+ return rtc_process_loglevel(-1, (const char *)data, result);
+ case ZBX_RTC_CONFIG_CACHE_RELOAD:
+ zbx_signal_process_by_type(ZBX_PROCESS_TYPE_SERVICEMAN, 1,
+ ZBX_RTC_MAKE_MESSAGE(ZBX_RTC_SERVICE_CACHE_RELOAD, 0, 0), result);
+ return FAIL;
+ case ZBX_RTC_SERVICE_CACHE_RELOAD:
+ zbx_signal_process_by_type(ZBX_PROCESS_TYPE_SERVICEMAN, 1,
+ ZBX_RTC_MAKE_MESSAGE(ZBX_RTC_SERVICE_CACHE_RELOAD, 0, 0), result);
+ return SUCCEED;
+ case ZBX_RTC_SECRETS_RELOAD:
+ zbx_signal_process_by_type(ZBX_PROCESS_TYPE_CONFSYNCER, 1, ZBX_RTC_MAKE_MESSAGE(code, 0, 0),
+ result);
+ return SUCCEED;
+ case ZBX_RTC_TRIGGER_HOUSEKEEPER_EXECUTE:
+ zbx_signal_process_by_type(ZBX_PROCESS_TYPE_PROBLEMHOUSEKEEPER, 1,
+ ZBX_RTC_MAKE_MESSAGE(code, 0, 0), result);
+ return SUCCEED;
+ case ZBX_RTC_DIAGINFO:
+ rtc_process_diaginfo((const char *)data, result);
+ return FAIL;
+ case ZBX_RTC_HA_STATUS:
+ rtc_ha_status(result);
+ return SUCCEED;
+ case ZBX_RTC_HA_SET_FAILOVER_DELAY:
+ rtc_ha_failover_delay((const char *)data, result);
+ return SUCCEED;
+ case ZBX_RTC_HA_REMOVE_NODE:
+ rtc_ha_remove_node((const char *)data, result);
+ return SUCCEED;
+ }
+
+ return FAIL;
+}
diff --git a/src/libs/zbxrtc/rtc_service.c b/src/libs/zbxrtc/rtc_service.c
new file mode 100644
index 00000000000..e7c61febecb
--- /dev/null
+++ b/src/libs/zbxrtc/rtc_service.c
@@ -0,0 +1,342 @@
+/*
+** Zabbix
+** Copyright (C) 2001-2021 Zabbix SIA
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+**/
+
+#include "zbxipcservice.h"
+#include "zbxjson.h"
+#include "daemon.h"
+#include "zbxrtc.h"
+#include "rtc.h"
+#include "log.h"
+#include "zbxdiag.h"
+
+/******************************************************************************
+ * *
+ * Function: rtc_change_service_loglevel *
+ * *
+ * Purpose: change log level of service process *
+ * *
+ ******************************************************************************/
+static void rtc_change_service_loglevel(int code)
+{
+ if (ZBX_RTC_LOG_LEVEL_INCREASE == code)
+ {
+ if (SUCCEED != zabbix_increase_log_level())
+ {
+ zabbix_log(LOG_LEVEL_INFORMATION, "cannot increase log level:"
+ " maximum level has been already set");
+ }
+ else
+ {
+ zabbix_log(LOG_LEVEL_INFORMATION, "log level has been increased to %s",
+ zabbix_get_log_level_string());
+ }
+ }
+ else
+ {
+ if (SUCCEED != zabbix_decrease_log_level())
+ {
+ zabbix_log(LOG_LEVEL_INFORMATION, "cannot decrease log level:"
+ " minimum level has been already set");
+ }
+ else
+ {
+ zabbix_log(LOG_LEVEL_INFORMATION, "log level has been decreased to %s",
+ zabbix_get_log_level_string());
+ }
+ }
+}
+
+/******************************************************************************
+ * *
+ * Function: rtc_process_loglevel *
+ * *
+ * Purpose: process loglevel runtime control option *
+ * *
+ * Parameters: code - [IN] the runtime control request code *
+ * data - [IN] the runtime control parameter (optional) *
+ * result - [OUT] the runtime control result *
+ * *
+ ******************************************************************************/
+static void rtc_process_loglevel(int code, const char *data, char **result)
+{
+ struct zbx_json_parse jp;
+ char buf[MAX_STRING_LEN];
+ int process_num = 0, process_type;
+
+ if (NULL == data)
+ {
+ rtc_change_service_loglevel(code);
+ zbx_signal_process_by_pid(0, ZBX_RTC_MAKE_MESSAGE(code, 0, 0), result);
+ return;
+ }
+
+ if (FAIL == zbx_json_open(data, &jp))
+ {
+ *result = zbx_dsprintf(NULL, "Invalid parameters \"%s\"\n", data);
+ return;
+ }
+
+ if (SUCCEED == zbx_json_value_by_name(&jp, ZBX_PROTO_TAG_PID, buf, sizeof(buf), NULL))
+ {
+ zbx_uint64_t pid;
+
+ if (SUCCEED != is_uint64(buf, &pid) || 0 == pid)
+ {
+ *result = zbx_dsprintf(NULL, "Invalid pid value \"%s\"\n", buf);
+ return;
+ }
+
+ if ((pid_t)pid == getpid())
+ {
+ rtc_change_service_loglevel(code);
+ /* temporary message, the signal forwarding command output will be changed later */
+ *result = zbx_strdup(NULL, "Changed log level for the main process\n");
+ }
+ else
+ zbx_signal_process_by_pid((int)pid, ZBX_RTC_MAKE_MESSAGE(code, 0, 0), result);
+
+ return;
+ }
+
+ if (SUCCEED == zbx_json_value_by_name(&jp, ZBX_PROTO_TAG_PROCESS_NUM, buf, sizeof(buf), NULL))
+ process_num = atoi(buf);
+
+ if (SUCCEED != zbx_json_value_by_name(&jp, ZBX_PROTO_TAG_PROCESS_NAME, buf, sizeof(buf), NULL))
+ {
+ *result = zbx_dsprintf(NULL, "Invalid parameters \"%s\"\n", data);
+ return;
+ }
+
+ if (ZBX_PROCESS_TYPE_UNKNOWN == (process_type = get_process_type_by_name(buf)))
+ {
+ *result = zbx_dsprintf(NULL, "Invalid parameters \"%s\"\n", data);
+ return;
+ }
+
+ zbx_signal_process_by_type(process_type, process_num, ZBX_RTC_MAKE_MESSAGE(code, 0, 0), result);
+}
+
+/******************************************************************************
+ * *
+ * Function: rtc_process_diaginfo *
+ * *
+ * Purpose: process diaginfo runtime control option *
+ * *
+ * Parameters: data - [IN] the runtime control parameter (optional) *
+ * result - [OUT] the runtime control result *
+ * *
+ ******************************************************************************/
+static void rtc_process_diaginfo(const char *data, char **result)
+{
+ struct zbx_json_parse jp;
+ char buf[MAX_STRING_LEN];
+ unsigned int scope;
+
+ if (FAIL == zbx_json_open(data, &jp) ||
+ SUCCEED != zbx_json_value_by_name(&jp, ZBX_PROTO_TAG_SECTION, buf, sizeof(buf), NULL))
+ {
+ *result = zbx_dsprintf(NULL, "Invalid parameters \"%s\"\n", data);
+ return;
+ }
+
+ if (0 == strcmp(buf, "all"))
+ {
+ scope = (1 << ZBX_DIAGINFO_HISTORYCACHE) | (1 << ZBX_DIAGINFO_PREPROCESSING) | (1 << ZBX_DIAGINFO_LOCKS);
+ }
+ else if (0 == strcmp(buf, ZBX_DIAG_HISTORYCACHE))
+ {
+ scope = 1 << ZBX_DIAGINFO_HISTORYCACHE;
+ }
+ else if (0 == strcmp(buf, ZBX_DIAG_PREPROCESSING))
+ {
+ scope = 1 << ZBX_DIAGINFO_PREPROCESSING;
+ }
+ else if (0 == strcmp(buf, ZBX_DIAG_LOCKS))
+ {
+ scope = 1 << ZBX_DIAGINFO_LOCKS;
+ }
+ else
+ {
+ if (NULL == *result)
+ *result = zbx_dsprintf(NULL, "Unknown diaginfo section \"%s\"\n", buf);
+ return;
+ }
+
+ zbx_diag_log_info(scope, result);
+}
+
+/******************************************************************************
+ * *
+ * Function: rtc_process_request *
+ * *
+ * Purpose: process runtime control option *
+ * *
+ * Parameters: code - [IN] the request code *
+ * data - [IN] the runtime control parameter (optional) *
+ * result - [OUT] the runtime control result *
+ * *
+ ******************************************************************************/
+static void rtc_process_request(int code, const unsigned char *data, char **result)
+{
+#ifdef HAVE_NETSNMP
+ int cmd;
+ char *tmp = NULL;
+#endif
+
+ switch (code)
+ {
+ case ZBX_RTC_LOG_LEVEL_INCREASE:
+ case ZBX_RTC_LOG_LEVEL_DECREASE:
+ rtc_process_loglevel(code, (const char *)data, result);
+ return;
+ case ZBX_RTC_HOUSEKEEPER_EXECUTE:
+ zbx_signal_process_by_type(ZBX_PROCESS_TYPE_HOUSEKEEPER, 1, ZBX_RTC_MAKE_MESSAGE(code, 0, 0),
+ result);
+ return;
+ case ZBX_RTC_CONFIG_CACHE_RELOAD:
+ zbx_signal_process_by_type(ZBX_PROCESS_TYPE_CONFSYNCER, 1, ZBX_RTC_MAKE_MESSAGE(code, 0, 0),
+ result);
+ return;
+ case ZBX_RTC_SNMP_CACHE_RELOAD:
+#ifdef HAVE_NETSNMP
+ cmd = ZBX_RTC_MAKE_MESSAGE(code, 0, 0);
+
+ zbx_signal_process_by_type(ZBX_PROCESS_TYPE_UNREACHABLE, 0, cmd, result);
+ zbx_signal_process_by_type(ZBX_PROCESS_TYPE_POLLER, 0, cmd, &tmp);
+ *result = zbx_strdcat(*result, tmp);
+ zbx_free(tmp);
+ zbx_signal_process_by_type(ZBX_PROCESS_TYPE_TRAPPER, 0, cmd, &tmp);
+ *result = zbx_strdcat(*result, tmp);
+ zbx_free(tmp);
+ zbx_signal_process_by_type(ZBX_PROCESS_TYPE_DISCOVERER, 0, cmd, &tmp);
+ *result = zbx_strdcat(*result, tmp);
+ zbx_free(tmp);
+ zbx_signal_process_by_type(ZBX_PROCESS_TYPE_TASKMANAGER, 0, cmd, &tmp);
+ *result = zbx_strdcat(*result, tmp);
+ zbx_free(tmp);
+#else
+ *result = zbx_strdup(NULL, "Invalid runtime control option: no SNMP support enabled\n");
+#endif
+ return;
+ case ZBX_RTC_DIAGINFO:
+ rtc_process_diaginfo((const char *)data, result);
+ return;
+ default:
+ *result = zbx_strdup(*result, "Unknown runtime control option\n");
+ }
+}
+
+/******************************************************************************
+ * *
+ * Function: zbx_rtc_init *
+ * *
+ * Purpose: initialize runtime control service *
+ * *
+ ******************************************************************************/
+int zbx_rtc_init(zbx_rtc_t *rtc ,char **error)
+{
+ return zbx_ipc_service_start(&rtc->service, ZBX_IPC_SERVICE_RTC, error);
+}
+
+/******************************************************************************
+ * *
+ * Function: zbx_rtc_dispatch *
+ * *
+ * Purpose: accept and process runtime control request *
+ * *
+ ******************************************************************************/
+void zbx_rtc_dispatch(zbx_ipc_client_t *client, zbx_ipc_message_t *message)
+{
+ char *result = NULL, *result_ex = NULL;
+ zbx_uint32_t size = 0;
+
+ zabbix_log(LOG_LEVEL_DEBUG, "In %s() code:%u", __func__, message->code);
+
+ if (FAIL == rtc_process_request_ex((int)message->code, message->data, &result_ex))
+ rtc_process_request((int)message->code, message->data, &result);
+
+ if (NULL != result_ex)
+ result = zbx_strdcat(result, result_ex);
+
+ if (NULL == result)
+ {
+ /* generate default success message if no specific success or error messages were returned */
+ result = zbx_strdup(NULL, "Runtime control command was forwarded successfully\n");
+ }
+
+ size = (zbx_uint32_t)strlen(result) + 1;
+ zbx_ipc_client_send(client, message->code, (unsigned char *)result, size);
+ zbx_free(result);
+
+ zbx_free(result_ex);
+ zbx_free(result);
+
+ zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
+}
+
+/******************************************************************************
+ * *
+ * Function: zbx_rtc_wait_config_sync *
+ * *
+ * Purpose: wait for configuration sync notification while optionally *
+ * dispatching runtime control commands *
+ * *
+ ******************************************************************************/
+void zbx_rtc_wait_config_sync(zbx_rtc_t *rtc)
+{
+ zbx_timespec_t rtc_timeout = {1, 0};
+ int sync = 0;
+
+ while (ZBX_IS_RUNNING() && 0 == sync)
+ {
+ zbx_ipc_client_t *client;
+ zbx_ipc_message_t *message;
+
+ (void)zbx_ipc_service_recv(&rtc->service, &rtc_timeout, &client, &message);
+
+ if (NULL != message)
+ {
+ switch (message->code)
+ {
+ case ZBX_RTC_CONFIG_SYNC_NOTIFY:
+ sync = 1;
+ break;
+ case ZBX_RTC_LOG_LEVEL_DECREASE:
+ case ZBX_RTC_LOG_LEVEL_INCREASE:
+ zbx_rtc_dispatch(client, message);
+ break;
+ default:
+ if (ZBX_IPC_RTC_MAX >= message->code)
+ {
+ const char *rtc_error = "Cannot perform specified runtime control"
+ " command during initial configuration cache sync\n";
+ zbx_ipc_client_send(client, message->code,
+ (const unsigned char *)rtc_error,
+ (zbx_uint32_t)strlen(rtc_error) + 1);
+ }
+ }
+ zbx_ipc_message_free(message);
+
+ }
+
+ if (NULL != client)
+ zbx_ipc_client_release(client);
+ }
+}
+
diff --git a/src/libs/zbxsysinfo/common/dns.c b/src/libs/zbxsysinfo/common/dns.c
index 8b1281cd0d7..7e566cfb179 100644
--- a/src/libs/zbxsysinfo/common/dns.c
+++ b/src/libs/zbxsysinfo/common/dns.c
@@ -612,11 +612,11 @@ static int dns_query(AGENT_REQUEST *request, AGENT_RESULT *result, int short_ans
if (1 == short_answer)
{
- SET_UI64_RESULT(result, NOERROR != hp->rcode || 0 == ntohs(hp->ancount) || -1 == res ? 0 : 1);
+ SET_UI64_RESULT(result, -1 == res || NOERROR != hp->rcode || 0 == ntohs(hp->ancount) ? 0 : 1);
return SYSINFO_RET_OK;
}
- if (NOERROR != hp->rcode || 0 == ntohs(hp->ancount) || -1 == res)
+ if (-1 == res || NOERROR != hp->rcode || 0 == ntohs(hp->ancount))
{
SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot perform DNS query."));
return SYSINFO_RET_FAIL;
@@ -902,12 +902,40 @@ clean_dns:
#endif /* defined(HAVE_RES_QUERY) || defined(_WINDOWS) || defined(__MINGW32__)*/
}
-int NET_DNS(AGENT_REQUEST *request, AGENT_RESULT *result)
+static int dns_query_short(AGENT_REQUEST *request, AGENT_RESULT *result)
{
return dns_query(request, result, 1);
}
-int NET_DNS_RECORD(AGENT_REQUEST *request, AGENT_RESULT *result)
+static int dns_query_long(AGENT_REQUEST *request, AGENT_RESULT *result)
{
return dns_query(request, result, 0);
}
+
+static int dns_query_is_tcp(AGENT_REQUEST *request)
+{
+ char *param;
+
+ if (NULL != (param = get_rparam(request, 5)) && 0 == strcmp(param, "tcp"))
+ return SUCCEED;
+
+ return FAIL;
+}
+
+int NET_DNS(AGENT_REQUEST *request, AGENT_RESULT *result)
+{
+#if !defined(_WINDOWS) && !defined(__MINGW32__)
+ if (SUCCEED == dns_query_is_tcp(request))
+ return zbx_execute_threaded_metric(dns_query_short, request, result);
+#endif
+ return dns_query_short(request, result);
+}
+
+int NET_DNS_RECORD(AGENT_REQUEST *request, AGENT_RESULT *result)
+{
+#if !defined(_WINDOWS) && !defined(__MINGW32__)
+ if (SUCCEED == dns_query_is_tcp(request))
+ return zbx_execute_threaded_metric(dns_query_long, request, result);
+#endif
+ return dns_query_long(request, result);
+}
diff --git a/src/zabbix_agent/zabbix_agentd.c b/src/zabbix_agent/zabbix_agentd.c
index 6583c540213..4163f66e049 100644
--- a/src/zabbix_agent/zabbix_agentd.c
+++ b/src/zabbix_agent/zabbix_agentd.c
@@ -365,7 +365,7 @@ static int parse_commandline(int argc, char **argv, ZBX_TASK_EX *t)
break;
#ifndef _WINDOWS
case 'R':
- if (SUCCEED != parse_rtc_options(zbx_optarg, program_type, &t->data))
+ if (SUCCEED != parse_rtc_options(zbx_optarg, &t->data))
exit(EXIT_FAILURE);
t->task = ZBX_TASK_RUNTIME_CONTROL;
diff --git a/src/zabbix_proxy/Makefile.am b/src/zabbix_proxy/Makefile.am
index e4320f7c2d4..5a6c77d98b9 100644
--- a/src/zabbix_proxy/Makefile.am
+++ b/src/zabbix_proxy/Makefile.am
@@ -77,6 +77,9 @@ zabbix_proxy_LDADD = \
$(top_builddir)/src/libs/zbxdb/libzbxdb.a \
$(top_builddir)/src/libs/zbxmodules/libzbxmodules.a \
$(top_builddir)/src/libs/zbxtasks/libzbxtasks.a \
+ $(top_builddir)/src/libs/zbxrtc/libzbxrtc_service.a \
+ $(top_builddir)/src/libs/zbxrtc/libzbxrtc_proxy.a \
+ $(top_builddir)/src/libs/zbxrtc/libzbxrtc.a \
$(top_builddir)/src/libs/zbxdiag/libzbxdiag_proxy.a \
$(top_builddir)/src/libs/zbxcompress/libzbxcompress.a \
$(top_builddir)/src/libs/zbxtrends/libzbxtrends_baseline.a \
diff --git a/src/zabbix_proxy/proxy.c b/src/zabbix_proxy/proxy.c
index 970d8840ecf..e0bfbf2f8ae 100644
--- a/src/zabbix_proxy/proxy.c
+++ b/src/zabbix_proxy/proxy.c
@@ -62,6 +62,7 @@
#include "zbxvault.h"
#include "zbxdiag.h"
#include "sighandler.h"
+#include "zbxrtc.h"
#ifdef HAVE_OPENIPMI
#include "../zabbix_server/ipmi/ipmi_manager.h"
@@ -155,7 +156,7 @@ ZBX_THREAD_LOCAL unsigned char process_type = ZBX_PROCESS_TYPE_UNKNOWN;
ZBX_THREAD_LOCAL int process_num = 0;
ZBX_THREAD_LOCAL int server_num = 0;
-static int CONFIG_PROXYMODE = ZBX_PROXYMODE_ACTIVE;
+int CONFIG_PROXYMODE = ZBX_PROXYMODE_ACTIVE;
int CONFIG_DATASENDER_FORKS = 1;
int CONFIG_DISCOVERER_FORKS = 1;
int CONFIG_HOUSEKEEPER_FORKS = 1;
@@ -316,8 +317,6 @@ int CONFIG_DOUBLE_PRECISION = ZBX_DB_DBL_PRECISION_ENABLED;
zbx_vector_ptr_t zbx_addrs;
-volatile sig_atomic_t zbx_diaginfo_scope = ZBX_DIAGINFO_UNDEFINED;
-
int get_process_info_by_thread(int local_server_num, unsigned char *local_process_type, int *local_process_num);
int get_process_info_by_thread(int local_server_num, unsigned char *local_process_type, int *local_process_num)
@@ -529,7 +528,7 @@ static void zbx_set_defaults(void)
if (ZBX_PROXYMODE_PASSIVE == CONFIG_PROXYMODE)
{
- CONFIG_CONFSYNCER_FORKS = CONFIG_DATASENDER_FORKS = 0;
+ CONFIG_DATASENDER_FORKS = 0;
program_type = ZBX_PROGRAM_TYPE_PROXY_PASSIVE;
}
@@ -979,9 +978,7 @@ int main(int argc, char **argv)
break;
case 'R':
opt_r++;
- if (SUCCEED != parse_rtc_options(zbx_optarg, program_type, &t.data))
- exit(EXIT_FAILURE);
-
+ t.opts = zbx_strdup(t.opts, zbx_optarg);
t.task = ZBX_TASK_RUNTIME_CONTROL;
break;
case 'h':
@@ -1034,23 +1031,27 @@ int main(int argc, char **argv)
zbx_load_config(&t);
if (ZBX_TASK_RUNTIME_CONTROL == t.task)
- exit(SUCCEED == zbx_sigusr_send(t.data) ? EXIT_SUCCESS : EXIT_FAILURE);
+ {
+ int ret;
+ char *error = NULL;
- return daemon_start(CONFIG_ALLOW_ROOT, CONFIG_USER, t.flags);
-}
+ if (FAIL == zbx_ipc_service_init_env(CONFIG_SOCKET_PATH, &error))
+ {
+ zbx_error("cannot initialize IPC services: %s", error);
+ zbx_free(error);
+ exit(EXIT_FAILURE);
+ }
-static void zbx_main_sigusr_handler(int flags)
-{
- if (ZBX_RTC_DIAGINFO == ZBX_RTC_GET_MSG(flags))
- {
- int scope = ZBX_RTC_GET_SCOPE(flags);
+ if (SUCCEED != (ret = zbx_rtc_process(t.opts, &error)))
+ {
+ zbx_error("Cannot perform runtime control command: %s", error);
+ zbx_free(error);
+ }
- if (ZBX_DIAGINFO_ALL == scope)
- zbx_diaginfo_scope = (1 << ZBX_DIAGINFO_HISTORYCACHE) | (1 << ZBX_DIAGINFO_PREPROCESSING) |
- (1 << ZBX_DIAGINFO_LOCKS);
- else
- zbx_diaginfo_scope = 1 << scope;
+ exit(SUCCEED == ret ? EXIT_SUCCESS : EXIT_FAILURE);
}
+
+ return daemon_start(CONFIG_ALLOW_ROOT, CONFIG_USER, t.flags);
}
static void zbx_check_db(void)
@@ -1094,7 +1095,9 @@ int MAIN_ZABBIX_ENTRY(int flags)
{
zbx_socket_t listen_sock;
char *error = NULL;
- int i, db_type;
+ int i, db_type, ret;
+ zbx_rtc_t rtc;
+ zbx_timespec_t rtc_timeout = {1, 0};
if (0 != (flags & ZBX_TASK_FLAG_FOREGROUND))
{
@@ -1197,6 +1200,13 @@ int MAIN_ZABBIX_ENTRY(int flags)
zbx_free_config();
+ if (SUCCEED != zbx_rtc_init(&rtc, &error))
+ {
+ zabbix_log(LOG_LEVEL_CRIT, "cannot initialize runtime control service: %s", error);
+ zbx_free(error);
+ exit(EXIT_FAILURE);
+ }
+
if (SUCCEED != init_database_cache(&error))
{
zabbix_log(LOG_LEVEL_CRIT, "cannot initialize database cache: %s", error);
@@ -1319,13 +1329,11 @@ int MAIN_ZABBIX_ENTRY(int flags)
{
case ZBX_PROCESS_TYPE_CONFSYNCER:
zbx_thread_start(proxyconfig_thread, &thread_args, &threads[i]);
- DCconfig_wait_sync();
+ zbx_rtc_wait_config_sync(&rtc);
break;
case ZBX_PROCESS_TYPE_TRAPPER:
thread_args.args = &listen_sock;
zbx_thread_start(trapper_thread, &thread_args, &threads[i]);
- if (0 == CONFIG_CONFSYNCER_FORKS)
- DCconfig_wait_sync();
break;
case ZBX_PROCESS_TYPE_HEARTBEAT:
zbx_thread_start(heart_thread, &thread_args, &threads[i]);
@@ -1402,23 +1410,36 @@ int MAIN_ZABBIX_ENTRY(int flags)
}
}
- zbx_set_sigusr_handler(zbx_main_sigusr_handler);
zbx_unset_exit_on_terminate();
- while (ZBX_IS_RUNNING() && -1 == wait(&i)) /* wait for any child to exit */
+ while (ZBX_IS_RUNNING())
{
- if (EINTR != errno)
+ zbx_ipc_client_t *client;
+ zbx_ipc_message_t *message;
+
+ (void)zbx_ipc_service_recv(&rtc.service, &rtc_timeout, &client, &message);
+
+ if (NULL != message)
{
- zabbix_log(LOG_LEVEL_ERR, "failed to wait on child processes: %s", zbx_strerror(errno));
+ zbx_rtc_dispatch(client, message);
+ zbx_ipc_message_free(message);
+ }
+
+ if (NULL != client)
+ zbx_ipc_client_release(client);
+
+ if (0 < (ret = waitpid((pid_t)-1, &i, WNOHANG)))
+ {
+ zabbix_log(LOG_LEVEL_CRIT, "PROCESS EXIT: %d", ret);
sig_exiting = ZBX_EXIT_FAILURE;
break;
}
- /* check if the wait was interrupted because of diaginfo remote command */
- if (ZBX_DIAGINFO_UNDEFINED != zbx_diaginfo_scope)
+ if (-1 == ret && EINTR != errno)
{
- zbx_diag_log_info((unsigned int)zbx_diaginfo_scope);
- zbx_diaginfo_scope = ZBX_DIAGINFO_UNDEFINED;
+ zabbix_log(LOG_LEVEL_ERR, "failed to wait on child processes: %s", zbx_strerror(errno));
+ sig_exiting = ZBX_EXIT_FAILURE;
+ break;
}
}
diff --git a/src/zabbix_proxy/proxyconfig/proxyconfig.c b/src/zabbix_proxy/proxyconfig/proxyconfig.c
index 5a2c9061f50..5e209809681 100644
--- a/src/zabbix_proxy/proxyconfig/proxyconfig.c
+++ b/src/zabbix_proxy/proxyconfig/proxyconfig.c
@@ -27,6 +27,8 @@
#include "proxyconfig.h"
#include "zbxcrypto.h"
#include "zbxcompress.h"
+#include "zbxrtc.h"
+#include "zbxipcservice.h"
#define CONFIG_PROXYCONFIG_RETRY 120 /* seconds */
@@ -61,7 +63,7 @@ static void zbx_proxyconfig_sigusr_handler(int flags)
static void process_configuration_sync(size_t *data_size)
{
zbx_socket_t sock;
- struct zbx_json_parse jp;
+ struct zbx_json_parse jp, jp_kvs_paths = {0};
char value[16], *error = NULL, *buffer = NULL;
size_t buffer_size, reserved;
struct zbx_json j;
@@ -134,7 +136,15 @@ static void process_configuration_sync(size_t *data_size)
zabbix_log(LOG_LEVEL_WARNING, "received configuration data from server at \"%s\", datalen " ZBX_FS_SIZE_T,
sock.peer, (zbx_fs_size_t)*data_size);
- process_proxyconfig(&jp);
+ if (SUCCEED == process_proxyconfig(&jp, &jp_kvs_paths))
+ {
+ DCsync_configuration(ZBX_DBSYNC_UPDATE);
+
+ if (NULL != jp_kvs_paths.start)
+ DCsync_kvs_paths(&jp_kvs_paths);
+
+ DCupdate_interfaces_availability();
+ }
error:
disconnect_server(&sock);
out:
@@ -162,8 +172,11 @@ out:
******************************************************************************/
ZBX_THREAD_ENTRY(proxyconfig_thread, args)
{
- size_t data_size;
- double sec;
+ size_t data_size;
+ double sec;
+ zbx_ipc_service_t config_service;
+ char *error = NULL;
+ zbx_timespec_t timeout = {1, 0};
process_type = ((zbx_thread_args_t *)args)->process_type;
server_num = ((zbx_thread_args_t *)args)->server_num;
@@ -176,15 +189,62 @@ ZBX_THREAD_ENTRY(proxyconfig_thread, args)
#if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
zbx_tls_init_child();
#endif
+
+ if (FAIL == zbx_ipc_service_start(&config_service, ZBX_IPC_SERVICE_CONFIG, &error))
+ {
+ zabbix_log(LOG_LEVEL_CRIT, "cannot start configuration syncer service: %s", error);
+ zbx_free(error);
+ exit(EXIT_FAILURE);
+ }
+
zbx_setproctitle("%s [connecting to the database]", get_process_type_string(process_type));
DBconnect(ZBX_DB_CONNECT_NORMAL);
zbx_setproctitle("%s [syncing configuration]", get_process_type_string(process_type));
- DCsync_configuration(ZBX_DBSYNC_INIT, NULL);
+ DCsync_configuration(ZBX_DBSYNC_INIT);
+
+ if (SUCCEED != zbx_rtc_notify_config_sync(&error))
+ {
+ zabbix_log(LOG_LEVEL_CRIT, "cannot send configuration syncer notification: %s", error);
+ zbx_free(error);
+ exit(EXIT_FAILURE);
+ }
while (ZBX_IS_RUNNING())
{
+ if (ZBX_PROGRAM_TYPE_PROXY_PASSIVE == program_type)
+ {
+ zbx_ipc_client_t *client;
+ zbx_ipc_message_t *message;
+
+ update_selfmon_counter(ZBX_PROCESS_STATE_IDLE);
+ zbx_ipc_service_recv(&config_service, &timeout, &client, &message);
+ update_selfmon_counter(ZBX_PROCESS_STATE_BUSY);
+
+ sec = zbx_time();
+ zbx_update_env(sec);
+
+ if (NULL != message)
+ {
+ zbx_setproctitle("%s [loading configuration]", get_process_type_string(process_type));
+
+ DCsync_configuration(ZBX_DBSYNC_UPDATE);
+ DCupdate_interfaces_availability();
+
+ zbx_setproctitle("%s [synced config in " ZBX_FS_DBL " sec]",
+ get_process_type_string(process_type), zbx_time() - sec);
+ zbx_ipc_client_send(client, ZBX_IPC_CONFIG_RELOAD_RESPONSE, NULL, 0);
+ }
+
+ zbx_ipc_message_free(message);
+
+ if (NULL != client)
+ zbx_ipc_client_release(client);
+
+ continue;
+ }
+
sec = zbx_time();
zbx_update_env(sec);
diff --git a/src/zabbix_server/Makefile.am b/src/zabbix_server/Makefile.am
index f44884903d0..96e778f8b44 100644
--- a/src/zabbix_server/Makefile.am
+++ b/src/zabbix_server/Makefile.am
@@ -39,9 +39,7 @@ libzbxserver_a_SOURCES = \
operations.c \
operations.h \
postinit.c \
- postinit.h \
- rtc.c \
- rtc.h
+ postinit.h
libzbxserver_a_CFLAGS = \
-DZABBIX_DAEMON \
@@ -120,6 +118,9 @@ zabbix_server_LDADD = \
$(top_builddir)/src/libs/zbxtrends/libzbxtrends.a \
$(top_builddir)/src/libs/zbxserver/libzbxserver_server.a \
$(top_builddir)/src/libs/zbxha/libzbxha.a \
+ $(top_builddir)/src/libs/zbxrtc/libzbxrtc_service.a \
+ $(top_builddir)/src/libs/zbxrtc/libzbxrtc_server.a \
+ $(top_builddir)/src/libs/zbxrtc/libzbxrtc.a \
$(top_builddir)/src/libs/zbxvault/libzbxvault.a \
$(top_builddir)/src/libs/zbxavailability/libzbxavailability.a \
$(top_builddir)/src/libs/zbxaudit/libzbxaudit.a \
diff --git a/src/zabbix_server/dbconfig/dbconfig.c b/src/zabbix_server/dbconfig/dbconfig.c
index 818a255dadb..e8c0f13761e 100644
--- a/src/zabbix_server/dbconfig/dbconfig.c
+++ b/src/zabbix_server/dbconfig/dbconfig.c
@@ -25,6 +25,7 @@
#include "log.h"
#include "dbconfig.h"
#include "dbcache.h"
+#include "zbxrtc.h"
extern int CONFIG_CONFSYNCER_FREQUENCY;
extern ZBX_THREAD_LOCAL unsigned char process_type;
@@ -80,6 +81,7 @@ ZBX_THREAD_ENTRY(dbconfig_thread, args)
{
double sec = 0.0;
int nextcheck = 0;
+ char *error = NULL;
process_type = ((zbx_thread_args_t *)args)->process_type;
server_num = ((zbx_thread_args_t *)args)->server_num;
@@ -98,9 +100,18 @@ ZBX_THREAD_ENTRY(dbconfig_thread, args)
sec = zbx_time();
zbx_setproctitle("%s [syncing configuration]", get_process_type_string(process_type));
- DCsync_configuration(ZBX_DBSYNC_INIT, NULL);
+ DCsync_configuration(ZBX_DBSYNC_INIT);
+ DCsync_kvs_paths(NULL);
zbx_setproctitle("%s [synced configuration in " ZBX_FS_DBL " sec, idle %d sec]",
get_process_type_string(process_type), (sec = zbx_time() - sec), CONFIG_CONFSYNCER_FREQUENCY);
+
+ if (SUCCEED != zbx_rtc_notify_config_sync(&error))
+ {
+ zabbix_log(LOG_LEVEL_CRIT, "cannot send configuration syncer notification: %s", error);
+ zbx_free(error);
+ exit(EXIT_FAILURE);
+ }
+
zbx_sleep_loop(CONFIG_CONFSYNCER_FREQUENCY);
while (ZBX_IS_RUNNING())
@@ -113,12 +124,13 @@ ZBX_THREAD_ENTRY(dbconfig_thread, args)
if (1 == secrets_reload)
{
- DCsync_configuration(ZBX_SYNC_SECRETS, NULL);
+ DCsync_kvs_paths(NULL);
secrets_reload = 0;
}
else
{
- DCsync_configuration(ZBX_DBSYNC_UPDATE, NULL);
+ DCsync_configuration(ZBX_DBSYNC_UPDATE);
+ DCsync_kvs_paths(NULL);
DCupdate_interfaces_availability();
nextcheck = time(NULL) + CONFIG_CONFSYNCER_FREQUENCY;
}
diff --git a/src/zabbix_server/ha/ha.h b/src/zabbix_server/ha/ha.h
index 277aa5c0981..c94ecf4c17f 100644
--- a/src/zabbix_server/ha/ha.h
+++ b/src/zabbix_server/ha/ha.h
@@ -21,14 +21,7 @@
#define ZABBIX_HA_H
#include "common.h"
-
-#define ZBX_NODE_STATUS_UNINITIALIZED -3
-#define ZBX_NODE_STATUS_ERROR -2
-#define ZBX_NODE_STATUS_UNKNOWN -1
-#define ZBX_NODE_STATUS_STANDBY 0
-#define ZBX_NODE_STATUS_STOPPED 1
-#define ZBX_NODE_STATUS_UNAVAILABLE 2
-#define ZBX_NODE_STATUS_ACTIVE 3
+#include "zbxrtc.h"
typedef struct
{
@@ -40,18 +33,13 @@ zbx_cuid_t;
#define zbx_cuid_compare(a, b) (0 == memcmp((a).str, (b).str, CUID_LEN) ? SUCCEED : FAIL)
#define zbx_cuid_clear(a) memset((a).str, 0, CUID_LEN)
-int zbx_ha_start(char **error, int ha_status);
+int zbx_ha_start(zbx_rtc_t *rtc, int ha_status, char **error);
int zbx_ha_pause(char **error);
int zbx_ha_stop(char **error);
void zbx_ha_kill(void);
-int zbx_ha_get_status(char **error);
-int zbx_ha_recv_status(int timeout, int *ha_status, char **error);
-int zbx_ha_get_nodes(char **nodes, char **error);
-int zbx_ha_remove_node(int node_num, char **error);
-int zbx_ha_set_failover_delay(int delay, char **error);
-int zbx_ha_change_loglevel(int direction, char **error);
+int zbx_ha_get_status(int *ha_status, char **error);
+int zbx_ha_dispatch_message(zbx_ipc_message_t *message, int *ha_status, char **error);
-const char *zbx_ha_status_str(int ha_status);
int zbx_ha_check_pid(pid_t pid);
#endif
diff --git a/src/zabbix_server/ha/ha_manager.c b/src/zabbix_server/ha/ha_manager.c
index ee6ef148d59..4b675f98f89 100644
--- a/src/zabbix_server/ha/ha_manager.c
+++ b/src/zabbix_server/ha/ha_manager.c
@@ -23,6 +23,7 @@
#include "zbxserialize.h"
#include "threads.h"
#include "zbxjson.h"
+#include "mutexs.h"
#include "../../libs/zbxalgo/vectorimpl.h"
#include "../../libs/zbxaudit/audit.h"
#include "../../libs/zbxaudit/audit_ha.h"
@@ -37,7 +38,6 @@
#define ZBX_HA_NODE_LOCK 1
static pid_t ha_pid = ZBX_THREAD_ERROR;
-static zbx_ipc_async_socket_t ha_socket;
extern char *CONFIG_HA_NODE_NAME;
extern char *CONFIG_NODE_ADDRESS;
@@ -105,26 +105,67 @@ static int ha_db_execute(zbx_ha_info_t *info, const char *sql, ...) __zbx_attr_f
/******************************************************************************
* *
- * Function: ha_send_manager_message *
+ * Function: ha_manager_send_message *
* *
- * Purpose: send message to HA manager *
+ * Purpose: connect, send message and receive response in a given timeout *
+ * *
+ * Parameters: service_name - [IN] the IPC service name *
+ * code - [IN] the message code *
+ * timeout - [IN] time allowed to be spent on receive, note *
+ * that this does not include open, send and *
+ * flush that have their own timeouts *
+ * data - [IN] the data *
+ * size - [IN] the data size *
+ * out - [OUT] the received message or NULL on error *
+ * The message must be freed by zbx_free() *
+ * error - [OUT] the error message *
+ * *
+ * Return value: SUCCEED - successfully sent message and received response *
+ * or timeout occurred while waiting for response *
+ * FAIL - error occurred *
* *
******************************************************************************/
-static int ha_send_manager_message(zbx_uint32_t code, char **error)
+static int ha_manager_send_message(zbx_uint32_t code, int timeout, const unsigned char *data, zbx_uint32_t size,
+ unsigned char **out, char **error)
{
- if (FAIL == zbx_ipc_async_socket_send(&ha_socket, code, NULL, 0))
- {
- *error = zbx_strdup(NULL, "cannot queue message to HA manager service");
+ zbx_ipc_message_t *message;
+ zbx_ipc_async_socket_t asocket;
+ int ret = FAIL;
+
+ if (FAIL == zbx_ipc_async_socket_open(&asocket, ZBX_IPC_SERVICE_HA, timeout, error))
return FAIL;
+
+ if (FAIL == zbx_ipc_async_socket_send(&asocket, code, data, size))
+ {
+ *error = zbx_strdup(NULL, "Cannot send request");
+ goto out;
}
- if (FAIL == zbx_ipc_async_socket_flush(&ha_socket, ZBX_HA_SERVICE_TIMEOUT))
+ if (FAIL == zbx_ipc_async_socket_flush(&asocket, timeout))
{
- *error = zbx_strdup(NULL, "cannot send message to HA manager service");
- return FAIL;
+ *error = zbx_strdup(NULL, "Cannot flush request");
+ goto out;
}
- return SUCCEED;
+ if (FAIL == zbx_ipc_async_socket_recv(&asocket, timeout, &message))
+ {
+ *error = zbx_strdup(NULL, "Cannot receive response");
+ goto out;
+ }
+
+ if (NULL != message)
+ {
+ *out = message->data;
+ message->data = NULL;
+ zbx_ipc_message_free(message);
+ }
+ else
+ *out = NULL;
+ ret = SUCCEED;
+out:
+ zbx_ipc_async_socket_close(&asocket);
+
+ return ret;
}
/******************************************************************************
@@ -134,7 +175,7 @@ static int ha_send_manager_message(zbx_uint32_t code, char **error)
* Purpose: update parent process with ha_status and failover delay *
* *
******************************************************************************/
-static void ha_update_parent(zbx_ipc_client_t *client, zbx_ha_info_t *info)
+static void ha_update_parent(zbx_ipc_async_socket_t *rtc_socket, zbx_ha_info_t *info)
{
zbx_uint32_t len = 0, error_len;
unsigned char *ptr, *data;
@@ -153,7 +194,9 @@ static void ha_update_parent(zbx_ipc_client_t *client, zbx_ha_info_t *info)
ptr += zbx_serialize_value(ptr, info->failover_delay);
(void)zbx_serialize_str(ptr, error, error_len);
- ret = zbx_ipc_client_send(client, ZBX_IPC_SERVICE_HA_UPDATE, data, len);
+ if (SUCCEED == (ret = zbx_ipc_async_socket_send(rtc_socket, ZBX_IPC_SERVICE_HA_STATUS_UPDATE, data, len)))
+ ret = zbx_ipc_async_socket_flush(rtc_socket, ZBX_HA_SERVICE_TIMEOUT);
+
zbx_free(data);
if (SUCCEED != ret)
@@ -172,9 +215,10 @@ static void ha_update_parent(zbx_ipc_client_t *client, zbx_ha_info_t *info)
* Purpose: send heartbeat message to main process *
* *
******************************************************************************/
-static void ha_send_heartbeat(zbx_ipc_client_t *client)
+static void ha_send_heartbeat(zbx_ipc_async_socket_t *rtc_socket)
{
- if (SUCCEED != zbx_ipc_client_send(client, ZBX_IPC_SERVICE_HA_HEARTBEAT, NULL, 0))
+ if (SUCCEED != zbx_ipc_async_socket_send(rtc_socket, ZBX_IPC_SERVICE_HA_HEARTBEAT, NULL, 0) ||
+ SUCCEED != zbx_ipc_async_socket_flush(rtc_socket, ZBX_HA_SERVICE_TIMEOUT))
{
zabbix_log(LOG_LEVEL_CRIT, "cannot send HA heartbeat to main process");
exit(EXIT_FAILURE);
@@ -942,7 +986,7 @@ static int ha_check_active_node(zbx_ha_info_t *info, zbx_vector_ha_node_t *nodes
else
info->offline_ticks_active++;
- if (info->failover_delay / ZBX_HA_POLL_PERIOD + 1 < info->offline_ticks_active)
+ if (info->failover_delay / ZBX_HA_POLL_PERIOD < info->offline_ticks_active)
{
*unavailable_index = i;
*ha_status = ZBX_NODE_STATUS_ACTIVE;
@@ -1159,15 +1203,15 @@ out:
/******************************************************************************
* *
- * Function: ha_remove_node_by_index *
+ * Function: ha_remove_node_impl *
* *
- * Purpose: remove node by its index in node list *
+ * Purpose: remove node by its cuid or name *
* *
******************************************************************************/
-static int ha_remove_node_by_index(zbx_ha_info_t *info, int index, char **error)
+static int ha_remove_node_impl(zbx_ha_info_t *info, const char *node, char **result, char **error)
{
zbx_vector_ha_node_t nodes;
- int ret = FAIL;
+ int i, ret = FAIL;
if (ZBX_DB_OK > ha_db_begin(info))
{
@@ -1183,22 +1227,35 @@ static int ha_remove_node_by_index(zbx_ha_info_t *info, int index, char **error)
goto out;
}
- index--;
+ for (i = 0; i < nodes.values_num; i++)
+ {
+ if (0 == strcmp(node, nodes.values[i]->ha_nodeid.str))
+ break;
+ }
+
+ if (i == nodes.values_num)
+ {
+ for (i = 0; i < nodes.values_num; i++)
+ {
+ if (0 == strcmp(node, nodes.values[i]->name))
+ break;
+ }
+ }
- if (0 > index || index >= nodes.values_num)
+ if (i == nodes.values_num)
{
- *error = zbx_strdup(NULL, "node index out of range");
+ *error = zbx_dsprintf(NULL, "unknown node \"%s\"", node);
goto out;
}
- if (ZBX_NODE_STATUS_ACTIVE == nodes.values[index]->status ||
- ZBX_NODE_STATUS_STANDBY == nodes.values[index]->status)
+ if (ZBX_NODE_STATUS_ACTIVE == nodes.values[i]->status || ZBX_NODE_STATUS_STANDBY == nodes.values[i]->status)
{
- *error = zbx_dsprintf(NULL, "node is %s", zbx_ha_status_str(nodes.values[index]->status));
+ *error = zbx_dsprintf(NULL, "node \"%s\" is %s", nodes.values[i]->name,
+ zbx_ha_status_str(nodes.values[i]->status));
goto out;
}
- if (SUCCEED != ha_db_execute(info, "delete from ha_node where ha_nodeid='%s'", nodes.values[index]->ha_nodeid.str))
+ if (SUCCEED != ha_db_execute(info, "delete from ha_node where ha_nodeid='%s'", nodes.values[i]->ha_nodeid.str))
{
*error = zbx_strdup(NULL, "database connection problem");
goto out;
@@ -1206,8 +1263,8 @@ static int ha_remove_node_by_index(zbx_ha_info_t *info, int index, char **error)
else
{
zbx_audit_init(info->auditlog);
- zbx_audit_ha_create_entry(AUDIT_ACTION_DELETE, nodes.values[index]->ha_nodeid.str,
- nodes.values[index]->name);
+ zbx_audit_ha_create_entry(AUDIT_ACTION_DELETE, nodes.values[i]->ha_nodeid.str,
+ nodes.values[i]->name);
ha_flush_audit(info);
}
@@ -1217,8 +1274,11 @@ out:
{
if (ZBX_DB_OK <= ha_db_commit(info))
{
- zabbix_log(LOG_LEVEL_WARNING, "removed node \"%s\" with ID \"%s\"", nodes.values[index]->name,
- nodes.values[index]->ha_nodeid.str);
+ size_t result_alloc = 0, result_offset = 0;
+
+ zbx_strlog_alloc(LOG_LEVEL_WARNING, result, &result_alloc, &result_offset,
+ "removed node \"%s\" with ID \"%s\"", nodes.values[i]->name,
+ nodes.values[i]->ha_nodeid.str);
}
}
else
@@ -1239,22 +1299,23 @@ out:
******************************************************************************/
static void ha_remove_node(zbx_ha_info_t *info, zbx_ipc_client_t *client, const zbx_ipc_message_t *message)
{
- int index;
- char *error = NULL;
- zbx_uint32_t len = 0, error_len;
- unsigned char *data;
+ char *error = NULL, *result = NULL;
+ zbx_uint32_t len = 0, error_len, result_len;
+ unsigned char *data, *ptr;
zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
- memcpy(&index, message->data, sizeof(index));
-
- ha_remove_node_by_index(info, index, &error);
+ ha_remove_node_impl(info, (const char *)message->data, &result, &error);
+ zbx_serialize_prepare_str(len, result);
zbx_serialize_prepare_str(len, error);
- data = zbx_malloc(NULL, len);
- zbx_serialize_str(data, error, error_len);
+ ptr = data = zbx_malloc(NULL, len);
+ ptr += zbx_serialize_str(ptr, result, result_len);
+ zbx_serialize_str(ptr, error, error_len);
+
zbx_free(error);
+ zbx_free(result);
zbx_ipc_client_send(client, ZBX_IPC_SERVICE_HA_REMOVE_NODE, data, len);
zbx_free(data);
@@ -1262,6 +1323,40 @@ static void ha_remove_node(zbx_ha_info_t *info, zbx_ipc_client_t *client, const
zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
}
+
+/******************************************************************************
+ * *
+ * Function: ha_send_status *
+ * *
+ * Purpose: reply to ha_status request *
+ * *
+ ******************************************************************************/
+static void ha_send_status(zbx_ha_info_t *info, zbx_ipc_client_t *client)
+{
+ zbx_uint32_t len = 0, error_len;
+ unsigned char *ptr, *data;
+ const char *error = info->error;
+ int ret;
+
+ zabbix_log(LOG_LEVEL_DEBUG, "In %s() ha_status:%s info:%s", __func__, zbx_ha_status_str(info->ha_status),
+ ZBX_NULL2EMPTY_STR(info->error));
+
+ zbx_serialize_prepare_value(len, info->ha_status);
+ zbx_serialize_prepare_value(len, info->failover_delay);
+ zbx_serialize_prepare_str(len, error);
+
+ ptr = data = (unsigned char *)zbx_malloc(NULL, len);
+ ptr += zbx_serialize_value(ptr, info->ha_status);
+ ptr += zbx_serialize_value(ptr, info->failover_delay);
+ (void)zbx_serialize_str(ptr, error, error_len);
+
+ ret = zbx_ipc_client_send(client, ZBX_IPC_SERVICE_HA_STATUS, data, len);
+ zbx_free(data);
+
+ zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_sysinfo_ret_string(ret));
+}
+
+
/******************************************************************************
* *
* Function: ha_set_failover_delay *
@@ -1321,6 +1416,23 @@ out:
/******************************************************************************
* *
+ * Function: ha_get_failover_delay *
+ * *
+ * Purpose: get failover delay *
+ * *
+ ******************************************************************************/
+static void ha_get_failover_delay(zbx_ha_info_t *info, zbx_ipc_client_t *client)
+{
+
+ zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
+
+ zbx_ipc_client_send(client, ZBX_IPC_SERVICE_HA_GET_FAILOVER_DELAY, (const unsigned char *)&info->failover_delay,
+ (zbx_uint32_t)sizeof(info->failover_delay));
+
+ zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
+}
+/******************************************************************************
+ * *
* Function: ha_send_node_list *
* *
* Purpose: reply to get nodes request *
@@ -1392,16 +1504,51 @@ out:
* *
* Function: zbx_ha_get_status *
* *
- * Purpose: requests HA manager to send status update *
+ * Purpose: get HA manager status *
* *
******************************************************************************/
-int zbx_ha_get_status(char **error)
+int zbx_ha_get_status(int *ha_status, char **error)
{
- int ret;
+ static time_t last_update;
+ static int ha_failover_delay = ZBX_HA_DEFAULT_FAILOVER_DELAY;
+ int ret;
+ unsigned char *result = NULL;
zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
- ret = ha_send_manager_message(ZBX_IPC_SERVICE_HA_UPDATE, error);
+ if (SUCCEED == (ret = ha_manager_send_message(ZBX_IPC_SERVICE_HA_STATUS, ZBX_HA_SERVICE_TIMEOUT, NULL, 0,
+ &result, error)))
+ {
+ if (NULL != result)
+ {
+ unsigned char *ptr = result;
+ zbx_uint32_t len;
+
+ ptr += zbx_deserialize_value(ptr, ha_status);
+ ptr += zbx_deserialize_value(ptr, &ha_failover_delay);
+ (void)zbx_deserialize_str(ptr, error, len);
+
+ zbx_free(result);
+ last_update = time(NULL);
+
+ if (ZBX_NODE_STATUS_ERROR == *ha_status)
+ ret = FAIL;
+ }
+ else
+ {
+ time_t now;
+
+ now = time(NULL);
+
+ /* in the case of timeout switch status to standby if enough time has */
+ /* passed since last successful update */
+ if (ZBX_HA_IS_CLUSTER() && *ha_status == ZBX_NODE_STATUS_ACTIVE && 0 != last_update)
+ {
+ if (last_update + ha_failover_delay - ZBX_HA_POLL_PERIOD <= now || now < last_update)
+ *ha_status = ZBX_NODE_STATUS_STANDBY;
+ }
+ }
+ }
zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
@@ -1410,7 +1557,7 @@ int zbx_ha_get_status(char **error)
/******************************************************************************
* *
- * Function: zbx_ha_recv_status *
+ * Function: zbx_ha_dispatch_message *
* *
* Purpose: handle HA manager notifications *
* *
@@ -1420,37 +1567,24 @@ int zbx_ha_get_status(char **error)
* process to switch to standby mode and initiate teardown process *
* *
******************************************************************************/
-int zbx_ha_recv_status(int timeout, int *ha_status, char **error)
+int zbx_ha_dispatch_message(zbx_ipc_message_t *message, int *ha_status, char **error)
{
- zbx_ipc_message_t *message = NULL;
- int ret = SUCCEED, ha_status_old;
- time_t now;
- static time_t last_hb;
- static int ha_failover_delay = ZBX_HA_DEFAULT_FAILOVER_DELAY;
+ static time_t last_hb;
+ static int ha_failover_delay = ZBX_HA_DEFAULT_FAILOVER_DELAY;
+ int ret = SUCCEED, ha_status_old;
+ time_t now;
+ unsigned char *ptr;
+ zbx_uint32_t len;
zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
- while (1)
- {
- unsigned char *ptr;
- zbx_uint32_t len;
-
- if (SUCCEED != zbx_ipc_async_socket_recv(&ha_socket, timeout, &message))
- {
- *ha_status = ZBX_NODE_STATUS_ERROR;
- *error = zbx_strdup(NULL, "cannot receive message from HA manager service");
- ret = FAIL;
- goto out;
- }
-
- now = time(NULL);
-
- if (NULL == message)
- break;
+ now = time(NULL);
+ if (NULL != message)
+ {
switch (message->code)
{
- case ZBX_IPC_SERVICE_HA_UPDATE:
+ case ZBX_IPC_SERVICE_HA_STATUS_UPDATE:
ha_status_old = *ha_status;
ptr = message->data;
@@ -1474,11 +1608,6 @@ int zbx_ha_recv_status(int timeout, int *ha_status, char **error)
last_hb = now;
break;
}
-
- zbx_ipc_message_free(message);
-
- /* reset timeout for getting pending messages */
- timeout = 0;
}
if (ZBX_HA_IS_CLUSTER() && *ha_status == ZBX_NODE_STATUS_ACTIVE && 0 != last_hb)
@@ -1487,77 +1616,25 @@ int zbx_ha_recv_status(int timeout, int *ha_status, char **error)
*ha_status = ZBX_NODE_STATUS_STANDBY;
}
out:
- zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
-
return ret;
}
/******************************************************************************
* *
- * Function: zbx_ha_remove_node *
- * *
- * Purpose: remove HA node *
- * *
- * Comments: A new socket is opened to avoid interfering with notification *
- * channel *
- * *
- ******************************************************************************/
-int zbx_ha_remove_node(int node_num, char **error)
-{
- unsigned char *data;
- zbx_uint32_t error_len;
-
- if (SUCCEED != zbx_ipc_async_exchange(ZBX_IPC_SERVICE_HA, ZBX_IPC_SERVICE_HA_REMOVE_NODE,
- ZBX_HA_SERVICE_TIMEOUT, (unsigned char *)&node_num, sizeof(node_num), &data, error))
- {
- return FAIL;
- }
-
- (void)zbx_deserialize_str(data, error, error_len);
- zbx_free(data);
-
- return (0 == error_len ? SUCCEED : FAIL);
-}
-
-/******************************************************************************
- * *
- * Function: zbx_ha_set_failover_delay *
- * *
- * Purpose: set HA failover delay *
- * *
- * Comments: A new socket is opened to avoid interfering with notification *
- * channel *
- * *
- ******************************************************************************/
-int zbx_ha_set_failover_delay(int delay, char **error)
-{
- unsigned char *data;
- zbx_uint32_t error_len;
-
- if (SUCCEED != zbx_ipc_async_exchange(ZBX_IPC_SERVICE_HA, ZBX_IPC_SERVICE_HA_SET_FAILOVER_DELAY,
- ZBX_HA_SERVICE_TIMEOUT, (unsigned char *)&delay, sizeof(delay), &data, error))
- {
- return FAIL;
- }
-
- (void)zbx_deserialize_str(data, error, error_len);
- zbx_free(data);
-
- return (0 == error_len ? SUCCEED : FAIL);
-}
-
-/******************************************************************************
- * *
* Function: zbx_ha_start *
* *
* Purpose: start HA manager *
* *
******************************************************************************/
-int zbx_ha_start(char **error, int ha_status)
+int zbx_ha_start(zbx_rtc_t *rtc, int ha_status, char **error)
{
- char *errmsg = NULL;
int ret = FAIL;
+ zbx_uint32_t code = 0;
zbx_thread_args_t args;
+ zbx_ipc_client_t *client;
+ zbx_ipc_message_t *message;
+ zbx_timespec_t rtc_timeout = {1, 0};
+ time_t now, start;
zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
@@ -1570,29 +1647,42 @@ int zbx_ha_start(char **error, int ha_status)
goto out;
}
- if (SUCCEED != zbx_ipc_async_socket_open(&ha_socket, ZBX_IPC_SERVICE_HA, ZBX_HA_SERVICE_TIMEOUT, &errmsg))
- {
- *error = zbx_dsprintf(NULL, "cannot connect to HA manager process: %s", errmsg);
- zbx_free(errmsg);
- goto out;
- }
+ start = now = time(NULL);
- if (FAIL == zbx_ipc_async_socket_send(&ha_socket, ZBX_IPC_SERVICE_HA_REGISTER, NULL, 0))
+ while (start + ZBX_HA_SERVICE_TIMEOUT > now)
{
- *error = zbx_dsprintf(NULL, "cannot queue message to HA manager service");
- goto out;
+ (void)zbx_ipc_service_recv(&rtc->service, &rtc_timeout, &client, &message);
+
+ if (NULL != client)
+ zbx_ipc_client_release(client);
+
+ if (NULL != message)
+ {
+ code = message->code;
+ zbx_ipc_message_free(message);
+
+ if (ZBX_IPC_SERVICE_HA_REGISTER == code)
+ break;
+ }
+
+ now = time(NULL);
}
- if (FAIL == zbx_ipc_async_socket_flush(&ha_socket, ZBX_HA_SERVICE_TIMEOUT))
+ if (ZBX_IPC_SERVICE_HA_REGISTER != code)
{
- *error = zbx_dsprintf(NULL, "cannot send message to HA manager service");
+ *error = zbx_strdup(NULL, "timeout while waiting for HA manager registration");
goto out;
}
ret = SUCCEED;
out:
if (SUCCEED != ret && ZBX_THREAD_ERROR != ha_pid)
+ {
+#ifdef HAVE_PTHREAD_PROCESS_SHARED
+ zbx_locks_disable();
+#endif
zbx_ha_kill();
+ }
zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
@@ -1610,11 +1700,14 @@ out:
******************************************************************************/
int zbx_ha_pause(char **error)
{
- int ret;
+ int ret;
+ unsigned char *result = NULL;
zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
- ret = ha_send_manager_message(ZBX_IPC_SERVICE_HA_PAUSE, error);
+ ret = zbx_ipc_async_exchange(ZBX_IPC_SERVICE_HA, ZBX_IPC_SERVICE_HA_PAUSE, ZBX_HA_SERVICE_TIMEOUT, NULL, 0,
+ &result, error);
+ zbx_free(result);
zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
@@ -1632,7 +1725,8 @@ int zbx_ha_pause(char **error)
******************************************************************************/
int zbx_ha_stop(char **error)
{
- int ret = FAIL;
+ int ret = FAIL;
+ unsigned char *result = NULL;
zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
@@ -1642,8 +1736,11 @@ int zbx_ha_stop(char **error)
goto out;
}
- if (SUCCEED == ha_send_manager_message(ZBX_IPC_SERVICE_HA_STOP, error))
+ if (SUCCEED == zbx_ipc_async_exchange(ZBX_IPC_SERVICE_HA, ZBX_IPC_SERVICE_HA_STOP, ZBX_HA_SERVICE_TIMEOUT,
+ NULL, 0, &result, error))
{
+ zbx_free(result);
+
if (ZBX_THREAD_ERROR == zbx_thread_wait(ha_pid))
{
*error = zbx_dsprintf(NULL, "failed to wait for HA manager to exit: %s", zbx_strerror(errno));
@@ -1662,35 +1759,6 @@ out:
/******************************************************************************
* *
- * Function: zbx_ha_change_loglevel *
- * *
- * Purpose: change HA manager log level *
- * *
- ******************************************************************************/
-int zbx_ha_change_loglevel(int direction, char **error)
-{
- int ret = FAIL;
- zbx_uint32_t cmd;
-
- zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
-
- if (ZBX_THREAD_ERROR == ha_pid)
- {
- *error = zbx_strdup(NULL, "HA manager has not been started");
- goto out;
- }
-
- cmd = 0 < direction ? ZBX_IPC_SERVICE_HA_LOGLEVEL_INCREASE : ZBX_IPC_SERVICE_HA_LOGLEVEL_DECREASE;
-
- ret = ha_send_manager_message(cmd, error);
-out:
- zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
-
- return ret;
-}
-
-/******************************************************************************
- * *
* Function: zbx_ha_kill *
* *
* Purpose: kill HA manager *
@@ -1701,35 +1769,6 @@ void zbx_ha_kill(void)
kill(ha_pid, SIGKILL);
zbx_thread_wait(ha_pid);
ha_pid = ZBX_THREAD_ERROR;
-
- if (SUCCEED == zbx_ipc_async_socket_connected(&ha_socket))
- zbx_ipc_async_socket_close(&ha_socket);
-}
-
-/******************************************************************************
- * *
- * Function: zbx_ha_status_str *
- * *
- * Purpose: get HA status in text format *
- * *
- ******************************************************************************/
-const char *zbx_ha_status_str(int ha_status)
-{
- switch (ha_status)
- {
- case ZBX_NODE_STATUS_STANDBY:
- return "standby";
- case ZBX_NODE_STATUS_STOPPED:
- return "stopped";
- case ZBX_NODE_STATUS_UNAVAILABLE:
- return "unavailable";
- case ZBX_NODE_STATUS_ACTIVE:
- return "active";
- case ZBX_NODE_STATUS_ERROR:
- return "error";
- default:
- return "unknown";
- }
}
/******************************************************************************
@@ -1751,7 +1790,8 @@ ZBX_THREAD_ENTRY(ha_manager_thread, args)
{
zbx_ipc_service_t service;
char *error = NULL;
- zbx_ipc_client_t *client, *main_proc = NULL;
+ zbx_ipc_client_t *client;
+ zbx_ipc_async_socket_t rtc_socket;
zbx_ipc_message_t *message;
int pause = FAIL, stop = FAIL, ticks_num = 0, nextcheck;
double now, tick;
@@ -1769,6 +1809,20 @@ ZBX_THREAD_ENTRY(ha_manager_thread, args)
exit(EXIT_FAILURE);
}
+ if (FAIL == zbx_rtc_open(&rtc_socket, ZBX_HA_SERVICE_TIMEOUT, &error))
+ {
+ zabbix_log(LOG_LEVEL_CRIT, "cannot start HA manager service: %s", error);
+ zbx_free(error);
+ exit(EXIT_FAILURE);
+ }
+
+ if (FAIL == zbx_ipc_async_socket_send(&rtc_socket, ZBX_IPC_SERVICE_HA_REGISTER, NULL, 0) ||
+ FAIL == zbx_ipc_async_socket_flush(&rtc_socket, ZBX_HA_SERVICE_TIMEOUT))
+ {
+ zabbix_log(LOG_LEVEL_CRIT, "cannot register HA manager to runtime control service");
+ exit(EXIT_FAILURE);
+ }
+
zbx_cuid_clear(info.ha_nodeid);
info.name = ZBX_NULL2EMPTY_STR(CONFIG_HA_NODE_NAME);
info.ha_status = (int)(uintptr_t)((zbx_thread_args_t *)args)->args;
@@ -1789,6 +1843,8 @@ ZBX_THREAD_ENTRY(ha_manager_thread, args)
goto pause;
}
+ ha_update_parent(&rtc_socket, &info);
+
nextcheck = ZBX_HA_POLL_PERIOD;
/* double the initial database check delay in standby mode to avoid the same node becoming active */
@@ -1813,11 +1869,8 @@ ZBX_THREAD_ENTRY(ha_manager_thread, args)
else
ha_check_nodes(&info);
- if (NULL != main_proc)
- {
- if (old_status != info.ha_status && ZBX_NODE_STATUS_UNKNOWN != info.ha_status)
- ha_update_parent(main_proc, &info);
- }
+ if (old_status != info.ha_status && ZBX_NODE_STATUS_UNKNOWN != info.ha_status)
+ ha_update_parent(&rtc_socket, &info);
if (ZBX_NODE_STATUS_ERROR == info.ha_status)
break;
@@ -1831,8 +1884,8 @@ ZBX_THREAD_ENTRY(ha_manager_thread, args)
nextcheck += delay;
}
- if (NULL != main_proc && ZBX_DB_OK <= info.db_status)
- ha_send_heartbeat(main_proc);
+ if (ZBX_DB_OK <= info.db_status)
+ ha_send_heartbeat(&rtc_socket);
while (tick <= now)
tick++;
@@ -1847,16 +1900,15 @@ ZBX_THREAD_ENTRY(ha_manager_thread, args)
{
switch (message->code)
{
- case ZBX_IPC_SERVICE_HA_REGISTER:
- main_proc = client;
- break;
- case ZBX_IPC_SERVICE_HA_UPDATE:
- ha_update_parent(main_proc, &info);
+ case ZBX_IPC_SERVICE_HA_STATUS:
+ ha_send_status(&info, client);
break;
case ZBX_IPC_SERVICE_HA_STOP:
- stop = SUCCEED;
- ZBX_FALLTHROUGH;
+ zbx_ipc_client_send(client, ZBX_IPC_SERVICE_HA_STOP, NULL, 0);
+ pause = stop = SUCCEED;
+ break;
case ZBX_IPC_SERVICE_HA_PAUSE:
+ zbx_ipc_client_send(client, ZBX_IPC_SERVICE_HA_PAUSE, NULL, 0);
pause = SUCCEED;
break;
case ZBX_IPC_SERVICE_HA_GET_NODES:
@@ -1867,7 +1919,10 @@ ZBX_THREAD_ENTRY(ha_manager_thread, args)
break;
case ZBX_IPC_SERVICE_HA_SET_FAILOVER_DELAY:
ha_set_failover_delay(&info, client, message);
- ha_update_parent(main_proc, &info);
+ ha_update_parent(&rtc_socket, &info);
+ break;
+ case ZBX_IPC_SERVICE_HA_GET_FAILOVER_DELAY:
+ ha_get_failover_delay(&info, client);
break;
case ZBX_IPC_SERVICE_HA_LOGLEVEL_INCREASE:
if (SUCCEED != zabbix_increase_log_level())
@@ -1880,6 +1935,7 @@ ZBX_THREAD_ENTRY(ha_manager_thread, args)
zabbix_log(LOG_LEVEL_INFORMATION, "log level has been increased to %s",
zabbix_get_log_level_string());
}
+ zbx_ipc_client_send(client, ZBX_IPC_SERVICE_HA_LOGLEVEL_INCREASE, NULL, 0);
break;
case ZBX_IPC_SERVICE_HA_LOGLEVEL_DECREASE:
if (SUCCEED != zabbix_decrease_log_level())
@@ -1892,6 +1948,7 @@ ZBX_THREAD_ENTRY(ha_manager_thread, args)
zabbix_log(LOG_LEVEL_INFORMATION, "log level has been decreased to %s",
zabbix_get_log_level_string());
}
+ zbx_ipc_client_send(client, ZBX_IPC_SERVICE_HA_LOGLEVEL_DECREASE, NULL, 0);
break;
}
@@ -1918,15 +1975,16 @@ pause:
{
switch (message->code)
{
- case ZBX_IPC_SERVICE_HA_REGISTER:
- main_proc = client;
- break;
- case ZBX_IPC_SERVICE_HA_UPDATE:
- ha_update_parent(main_proc, &info);
+ case ZBX_IPC_SERVICE_HA_STATUS:
+ ha_send_status(&info, client);
break;
case ZBX_IPC_SERVICE_HA_STOP:
+ zbx_ipc_client_send(client, ZBX_IPC_SERVICE_HA_STOP, NULL, 0);
stop = SUCCEED;
break;
+ case ZBX_IPC_SERVICE_HA_PAUSE:
+ zbx_ipc_client_send(client, ZBX_IPC_SERVICE_HA_PAUSE, NULL, 0);
+ break;
}
zbx_ipc_message_free(message);
@@ -1942,6 +2000,7 @@ pause:
DBclose();
+ zbx_ipc_async_socket_close(&rtc_socket);
zbx_ipc_service_close(&service);
zabbix_log(LOG_LEVEL_INFORMATION, "HA manager has been stopped");
diff --git a/src/zabbix_server/lld/lld.c b/src/zabbix_server/lld/lld.c
index c55ff475975..b5995300683 100644
--- a/src/zabbix_server/lld/lld.c
+++ b/src/zabbix_server/lld/lld.c
@@ -978,7 +978,8 @@ void lld_override_graph(const zbx_vector_ptr_t *overrides, const char *name, uns
zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
}
-int lld_validate_item_override_no_discover(const zbx_vector_ptr_t *overrides, const char *name)
+int lld_validate_item_override_no_discover(const zbx_vector_ptr_t *overrides, const char *name,
+ unsigned char override_default)
{
int i, j;
@@ -995,16 +996,15 @@ int lld_validate_item_override_no_discover(const zbx_vector_ptr_t *overrides, co
override_operation = (const zbx_lld_override_operation_t *)override->override_operations.values[j];
if (ZBX_LLD_OVERRIDE_OP_OBJECT_ITEM == override_operation->operationtype &&
- ZBX_PROTOTYPE_NO_DISCOVER == override_operation->discover &&
SUCCEED == regexp_strmatch_condition(name, override_operation->value,
override_operation->operator))
{
- return FAIL;
+ return ZBX_PROTOTYPE_NO_DISCOVER == override_operation->discover ? FAIL : SUCCEED;
}
}
}
- return SUCCEED;
+ return ZBX_PROTOTYPE_NO_DISCOVER == override_default ? FAIL : SUCCEED;
}
static int lld_rows_get(const char *value, lld_filter_t *filter, zbx_vector_ptr_t *lld_rows,
diff --git a/src/zabbix_server/lld/lld.h b/src/zabbix_server/lld/lld.h
index f0205fadbb5..b19b546aa2c 100644
--- a/src/zabbix_server/lld/lld.h
+++ b/src/zabbix_server/lld/lld.h
@@ -238,7 +238,8 @@ void lld_override_host(const zbx_vector_ptr_t *overrides, const char *name, zbx_
unsigned char *discover);
void lld_override_graph(const zbx_vector_ptr_t *overrides, const char *name, unsigned char *discover);
-int lld_validate_item_override_no_discover(const zbx_vector_ptr_t *overrides, const char *name);
+int lld_validate_item_override_no_discover(const zbx_vector_ptr_t *overrides, const char *name,
+ unsigned char override_default);
int lld_update_items(zbx_uint64_t hostid, zbx_uint64_t lld_ruleid, zbx_vector_ptr_t *lld_rows,
const zbx_vector_ptr_t *lld_macro_paths, char **error, int lifetime, int lastcheck);
diff --git a/src/zabbix_server/lld/lld_item.c b/src/zabbix_server/lld/lld_item.c
index edbd46a5b5d..61449dc40fd 100644
--- a/src/zabbix_server/lld/lld_item.c
+++ b/src/zabbix_server/lld/lld_item.c
@@ -2548,7 +2548,7 @@ static void lld_items_make(const zbx_vector_ptr_t *item_prototypes, zbx_vector_p
if (0 == strcmp(item->key, buffer) &&
SUCCEED == lld_validate_item_override_no_discover(&lld_row->overrides,
- item->name))
+ item->name, item_prototype->discover))
{
item_index_local.parent_itemid = item->parent_itemid;
item_index_local.lld_row = lld_row;
diff --git a/src/zabbix_server/poller/checks_internal_server.c b/src/zabbix_server/poller/checks_internal_server.c
index e7c376f4eaa..5c9efac7699 100644
--- a/src/zabbix_server/poller/checks_internal_server.c
+++ b/src/zabbix_server/poller/checks_internal_server.c
@@ -22,7 +22,7 @@
#include "preproc.h"
#include "zbxlld.h"
#include "checks_internal.h"
-#include "../ha/ha.h"
+#include "zbxha.h"
/******************************************************************************
* *
diff --git a/src/zabbix_server/rtc.c b/src/zabbix_server/rtc.c
deleted file mode 100644
index 6dc378abd32..00000000000
--- a/src/zabbix_server/rtc.c
+++ /dev/null
@@ -1,303 +0,0 @@
-/*
-** Zabbix
-** Copyright (C) 2001-2021 Zabbix SIA
-**
-** This program is free software; you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation; either version 2 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program; if not, write to the Free Software
-** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-**/
-
-#include "common.h"
-#include "log.h"
-#include "zbxdiag.h"
-#include "ha/ha.h"
-#include "../libs/zbxnix/control.h"
-#include "rtc.h"
-
-/******************************************************************************
- * *
- * Function: rtc_diaginfo *
- * *
- * Purpose: process diaginfo runtime command *
- * *
- ******************************************************************************/
-static void rtc_diaginfo(int scope)
-{
- unsigned int flags;
-
- if (ZBX_DIAGINFO_ALL == scope)
- {
- flags = (1 << ZBX_DIAGINFO_HISTORYCACHE) | (1 << ZBX_DIAGINFO_VALUECACHE) |
- (1 << ZBX_DIAGINFO_PREPROCESSING) | (1 << ZBX_DIAGINFO_LLD) |
- (1 << ZBX_DIAGINFO_ALERTING) | (1 << ZBX_DIAGINFO_LOCKS);
- }
- else
- flags = 1u << scope;
-
- zbx_diag_log_info(flags);
-}
-
-/******************************************************************************
- * *
- * Function: rtc_ha_status *
- * *
- * Purpose: process ha_status runtime command *
- * *
- ******************************************************************************/
-static void rtc_ha_status(void)
-{
- char *nodes = NULL, *error = NULL;
- struct zbx_json_parse jp, jp_node;
-
- if (SUCCEED != zbx_ha_get_nodes(&nodes, &error))
- {
- zabbix_log(LOG_LEVEL_ERR, "cannot get HA node information: %s", error);
- zbx_free(error);
- return;
- }
-
-#define ZBX_HA_REPORT_FMT "%-25s %-25s %-30s %-11s %s"
-
- if (SUCCEED == zbx_json_open(nodes, &jp))
- {
- const char *pnext;
- char name[256], address[261], id[26], buffer[256];
- int status, lastaccess_age, index = 1;
-
- zabbix_log(LOG_LEVEL_INFORMATION, "cluster status:");
- zabbix_log(LOG_LEVEL_INFORMATION, " %2s " ZBX_HA_REPORT_FMT, "#", "ID", "Name",
- "Address", "Status", "Last Access");
-
- for (pnext = NULL; NULL != (pnext = zbx_json_next(&jp, pnext));)
- {
- if (FAIL == zbx_json_brackets_open(pnext, &jp_node))
- {
- THIS_SHOULD_NEVER_HAPPEN;
- continue;
- }
-
- if (SUCCEED != zbx_json_value_by_name(&jp_node, ZBX_PROTO_TAG_ID, id, sizeof(id), NULL))
- {
- THIS_SHOULD_NEVER_HAPPEN;
- continue;
- }
-
- if (SUCCEED != zbx_json_value_by_name(&jp_node, ZBX_PROTO_TAG_NAME, name, sizeof(name),
- NULL))
- {
- THIS_SHOULD_NEVER_HAPPEN;
- continue;
- }
-
- if (SUCCEED != zbx_json_value_by_name(&jp_node, ZBX_PROTO_TAG_STATUS, buffer,
- sizeof(buffer), NULL))
- {
- THIS_SHOULD_NEVER_HAPPEN;
- continue;
- }
- status = atoi(buffer);
-
- if (SUCCEED != zbx_json_value_by_name(&jp_node, ZBX_PROTO_TAG_LASTACCESS_AGE, buffer,
- sizeof(buffer), NULL))
- {
- THIS_SHOULD_NEVER_HAPPEN;
- continue;
- }
- lastaccess_age = atoi(buffer);
-
- if (SUCCEED != zbx_json_value_by_name(&jp_node, ZBX_PROTO_TAG_ADDRESS, address,
- sizeof(address), NULL))
- {
- THIS_SHOULD_NEVER_HAPPEN;
- continue;
- }
-
- zabbix_log(LOG_LEVEL_INFORMATION, " %2d. " ZBX_HA_REPORT_FMT, index++, id,
- '\0' != *name ? name : "<standalone server>",
- address, zbx_ha_status_str(status), zbx_age2str(lastaccess_age));
- }
- }
- zbx_free(nodes);
-
-#undef ZBX_HA_REPORT_FMT
-}
-
-/******************************************************************************
- * *
- * Function: rtc_remove_node *
- * *
- * Purpose: process ha_remove_node runtime command *
- * *
- ******************************************************************************/
-static void rtc_remove_node(int index)
-{
- char *error = NULL;
-
- if (SUCCEED != zbx_ha_remove_node(index, &error))
- {
- zabbix_log(LOG_LEVEL_ERR, "cannot remove HA node: %s", error);
- zbx_free(error);
- }
-}
-
-/******************************************************************************
- * *
- * Function: rtc_ha_failover_delay *
- * *
- * Purpose: process ha_failover_delay runtime command *
- * *
- ******************************************************************************/
-static void rtc_ha_failover_delay(int delay)
-{
- char *error = NULL;
-
- if (SUCCEED != zbx_ha_set_failover_delay(delay, &error))
- {
- zabbix_log(LOG_LEVEL_ERR, "cannot set HA failover delay: %s", error);
- zbx_free(error);
- }
-}
-
-/******************************************************************************
- * *
- * Function: rtc_change_loglevel_main *
- * *
- * Purpose: change log level of main process *
- * *
- ******************************************************************************/
-static void rtc_change_loglevel_main(int command)
-{
- if (ZBX_RTC_LOG_LEVEL_INCREASE == command)
- {
- if (SUCCEED != zabbix_increase_log_level())
- {
- zabbix_log(LOG_LEVEL_INFORMATION, "cannot increase log level:"
- " maximum level has been already set");
- }
- else
- {
- zabbix_log(LOG_LEVEL_INFORMATION, "log level has been increased to %s",
- zabbix_get_log_level_string());
- }
- }
- else
- {
- if (SUCCEED != zabbix_decrease_log_level())
- {
- zabbix_log(LOG_LEVEL_INFORMATION, "cannot decrease log level:"
- " minimum level has been already set");
- }
- else
- {
- zabbix_log(LOG_LEVEL_INFORMATION, "log level has been decreased to %s",
- zabbix_get_log_level_string());
- }
- }
-}
-
-/******************************************************************************
- * *
- * Function: rtc_change_loglevel_ha *
- * *
- * Purpose: change log level of HA manager *
- * *
- ******************************************************************************/
-static void rtc_change_loglevel_ha(int command)
-{
- int direction;
- char *error = NULL;
-
- direction = ZBX_RTC_LOG_LEVEL_INCREASE == command ? 1 : -1;
-
- if (SUCCEED != zbx_ha_change_loglevel(direction, &error))
- {
- zabbix_log(LOG_LEVEL_WARNING, "cannot change HA manager log level: %s", error);
- zbx_free(error);
- }
-}
-
-/******************************************************************************
- * *
- * Function: rtc_change_loglevel *
- * *
- * Purpose: process log level changes affecting main/ha manager processes *
- * *
- ******************************************************************************/
-static void rtc_change_loglevel(int command, int scope, int data)
-{
- if ((ZBX_RTC_LOG_SCOPE_FLAG | ZBX_RTC_LOG_SCOPE_PID) == scope)
- {
- if (0 == data || getpid() == (pid_t)data)
- rtc_change_loglevel_main(command);
-
- if (0 == data || SUCCEED == zbx_ha_check_pid((pid_t)data))
- rtc_change_loglevel_ha(command);
- return;
- }
-
- if (ZBX_PROCESS_TYPE_MAIN == scope)
- {
- if (1 < data)
- {
- zabbix_log(LOG_LEVEL_ERR, "cannot redirect signal: \"%s #%d\" process does not exist",
- get_process_type_string((unsigned char)scope), data);
- }
- else
- rtc_change_loglevel_main(command);
- }
- else if (ZBX_PROCESS_TYPE_HA_MANAGER == scope)
- {
- if (1 < data)
- {
- zabbix_log(LOG_LEVEL_ERR, "cannot redirect signal: \"%s #%d\" process does not exist",
- get_process_type_string((unsigned char)scope), data);
- }
- else
- rtc_change_loglevel_ha(command);
- }
-}
-
-/******************************************************************************
- * *
- * Function: zbx_rtc_process_command *
- * *
- * Purpose: process runtime command *
- * *
- ******************************************************************************/
-void zbx_rtc_process_command(unsigned int command)
-{
- zabbix_log(LOG_LEVEL_DEBUG, "In %s() command:%d", __func__, ZBX_RTC_GET_MSG(command));
-
- switch (ZBX_RTC_GET_MSG(command))
- {
- case ZBX_RTC_DIAGINFO:
- rtc_diaginfo(ZBX_RTC_GET_SCOPE(command));
- break;
- case ZBX_RTC_HA_STATUS:
- rtc_ha_status();
- break;
- case ZBX_RTC_HA_REMOVE_NODE:
- rtc_remove_node(ZBX_RTC_GET_DATA(command));
- break;
- case ZBX_RTC_HA_SET_FAILOVER_DELAY:
- rtc_ha_failover_delay(ZBX_RTC_GET_DATA(command));
- break;
- case ZBX_RTC_LOG_LEVEL_INCREASE:
- case ZBX_RTC_LOG_LEVEL_DECREASE:
- rtc_change_loglevel(ZBX_RTC_GET_MSG(command), ZBX_RTC_GET_SCOPE(command),
- ZBX_RTC_GET_DATA(command));
- break;
- }
-
- zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
-}
diff --git a/src/zabbix_server/server.c b/src/zabbix_server/server.c
index 417b9205cac..149cee9e7ae 100644
--- a/src/zabbix_server/server.c
+++ b/src/zabbix_server/server.c
@@ -80,7 +80,8 @@
#include "zbxtrends.h"
#include "ha/ha.h"
#include "sighandler.h"
-#include "rtc.h"
+#include "zbxrtc.h"
+#include "zbxha.h"
#ifdef HAVE_OPENIPMI
#include "ipmi/ipmi_manager.h"
@@ -178,7 +179,7 @@ int threads_num = 0;
pid_t *threads = NULL;
static int *threads_flags;
-static int ha_status = ZBX_NODE_STATUS_UNINITIALIZED;
+static int ha_status = ZBX_NODE_STATUS_UNKNOWN;
static int ha_status_old;
zbx_cuid_t ha_sessionid;
@@ -354,8 +355,6 @@ char *CONFIG_WEBSERVICE_URL = NULL;
int CONFIG_SERVICEMAN_SYNC_FREQUENCY = 60;
-static volatile sig_atomic_t zbx_rtc_command;
-
int get_process_info_by_thread(int local_server_num, unsigned char *local_process_type, int *local_process_num);
int get_process_info_by_thread(int local_server_num, unsigned char *local_process_type, int *local_process_num)
@@ -1035,9 +1034,7 @@ int main(int argc, char **argv)
break;
case 'R':
opt_r++;
- if (SUCCEED != parse_rtc_options(zbx_optarg, program_type, &t.data))
- exit(EXIT_FAILURE);
-
+ t.opts = zbx_strdup(t.opts, zbx_optarg);
t.task = ZBX_TASK_RUNTIME_CONTROL;
break;
case 'h':
@@ -1090,14 +1087,27 @@ int main(int argc, char **argv)
zbx_load_config(&t);
if (ZBX_TASK_RUNTIME_CONTROL == t.task)
- exit(SUCCEED == zbx_sigusr_send(t.data) ? EXIT_SUCCESS : EXIT_FAILURE);
+ {
+ int ret;
+ char *error = NULL;
- return daemon_start(CONFIG_ALLOW_ROOT, CONFIG_USER, t.flags);
-}
+ if (FAIL == zbx_ipc_service_init_env(CONFIG_SOCKET_PATH, &error))
+ {
+ zbx_error("cannot initialize IPC services: %s", error);
+ zbx_free(error);
+ exit(EXIT_FAILURE);
+ }
-static void zbx_main_sigusr_handler(int flags)
-{
- zbx_rtc_command = flags;
+ if (SUCCEED != (ret = zbx_rtc_process(t.opts, &error)))
+ {
+ zbx_error("Cannot perform runtime control command: %s", error);
+ zbx_free(error);
+ }
+
+ exit(SUCCEED == ret ? EXIT_SUCCESS : EXIT_FAILURE);
+ }
+
+ return daemon_start(CONFIG_ALLOW_ROOT, CONFIG_USER, t.flags);
}
static void zbx_check_db(void)
@@ -1186,33 +1196,12 @@ static void zbx_check_db(void)
/******************************************************************************
* *
- * Function: server_update_ha_status *
- * *
- * Purpose: check for queued status message and update HA status *
- * *
- ******************************************************************************/
-static int server_update_ha_status(void)
-{
- char *error = NULL;
-
- if (SUCCEED != zbx_ha_recv_status(0, &ha_status, &error))
- {
- zabbix_log(LOG_LEVEL_CRIT, "cannot check HA manager status: %s", error);
- zbx_free(error);
- return FAIL;
- }
-
- return SUCCEED;
-}
-
-/******************************************************************************
- * *
* Function: server_startup *
* *
* Purpose: initialize shared resources and start processes *
* *
******************************************************************************/
-static int server_startup(zbx_socket_t *listen_sock)
+static int server_startup(zbx_socket_t *listen_sock, zbx_rtc_t *rtc)
{
int i, ret = SUCCEED;
char *error = NULL;
@@ -1307,11 +1296,12 @@ static int server_startup(zbx_socket_t *listen_sock)
break;
case ZBX_PROCESS_TYPE_CONFSYNCER:
zbx_thread_start(dbconfig_thread, &thread_args, &threads[i]);
- DCconfig_wait_sync();
+ zbx_rtc_wait_config_sync(rtc);
- if (SUCCEED != server_update_ha_status())
+ if (SUCCEED != (ret = zbx_ha_get_status(&ha_status, &error)))
{
- ret = FAIL;
+ zabbix_log(LOG_LEVEL_CRIT, "cannot obtain HA status: %s", error);
+ zbx_free(error);
goto out;
}
@@ -1445,8 +1435,11 @@ static int server_startup(zbx_socket_t *listen_sock)
}
/* startup/postinit tasks can take a long time, update status */
- if (SUCCEED != server_update_ha_status())
- ret = FAIL;
+ if (SUCCEED != (ret = zbx_ha_get_status(&ha_status, &error)))
+ {
+ zabbix_log(LOG_LEVEL_CRIT, "cannot obtain HA status: %s", error);
+ zbx_free(error);
+ }
out:
zbx_unset_exit_on_terminate();
@@ -1474,7 +1467,7 @@ static int server_restart_logger(char **error)
* Purpose: terminate processes and destroy shared resources *
* *
******************************************************************************/
-static void server_teardown(zbx_socket_t *listen_sock)
+static void server_teardown(zbx_rtc_t *rtc, zbx_socket_t *listen_sock)
{
int i;
char *error = NULL;
@@ -1535,7 +1528,7 @@ static void server_teardown(zbx_socket_t *listen_sock)
zbx_locks_enable();
#endif
- if (SUCCEED != zbx_ha_start(&error, ZBX_NODE_STATUS_STANDBY))
+ if (SUCCEED != zbx_ha_start(rtc, ZBX_NODE_STATUS_STANDBY, &error))
{
zabbix_log(LOG_LEVEL_CRIT, "cannot start HA manager: %s", error);
zbx_free(error);
@@ -1549,6 +1542,8 @@ int MAIN_ZABBIX_ENTRY(int flags)
int i, db_type, ret;
zbx_socket_t listen_sock;
time_t standby_warning_time;
+ zbx_rtc_t rtc;
+ zbx_timespec_t rtc_timeout = {1, 0};
if (0 != (flags & ZBX_TASK_FLAG_FOREGROUND))
{
@@ -1660,6 +1655,13 @@ int MAIN_ZABBIX_ENTRY(int flags)
zbx_free_config();
+ if (SUCCEED != zbx_rtc_init(&rtc, &error))
+ {
+ zabbix_log(LOG_LEVEL_CRIT, "cannot initialize runtime control service: %s", error);
+ zbx_free(error);
+ exit(EXIT_FAILURE);
+ }
+
if (SUCCEED != zbx_vault_init_token_from_env(&error))
{
zabbix_log(LOG_LEVEL_CRIT, "cannot initialize vault token: %s", error);
@@ -1724,7 +1726,7 @@ int MAIN_ZABBIX_ENTRY(int flags)
zbx_unset_exit_on_terminate();
- if (SUCCEED != zbx_ha_start(&error, ZBX_NODE_STATUS_UNKNOWN))
+ if (SUCCEED != zbx_ha_start(&rtc, ZBX_NODE_STATUS_UNKNOWN, &error))
{
zabbix_log(LOG_LEVEL_CRIT, "cannot start HA manager: %s", error);
zbx_free(error);
@@ -1740,21 +1742,7 @@ int MAIN_ZABBIX_ENTRY(int flags)
if (SUCCEED == zbx_is_export_enabled(ZBX_FLAG_EXPTYPE_TRENDS))
zbx_trends_export_init("main-process", 0);
- zbx_set_sigusr_handler(zbx_main_sigusr_handler);
-
- if (SUCCEED == zbx_ha_get_status(&error))
- {
- while (ZBX_IS_RUNNING() && ZBX_NODE_STATUS_UNINITIALIZED == ha_status)
- {
- if (SUCCEED != zbx_ha_recv_status(ZBX_IPC_WAIT_FOREVER, &ha_status, &error))
- {
- zabbix_log(LOG_LEVEL_CRIT, "cannot start server: %s", error);
- zbx_free(error);
- sig_exiting = ZBX_EXIT_FAILURE;
- }
- }
- }
- else
+ if (SUCCEED != zbx_ha_get_status(&ha_status, &error))
{
zabbix_log(LOG_LEVEL_CRIT, "cannot start server: %s", error);
zbx_free(error);
@@ -1763,7 +1751,7 @@ int MAIN_ZABBIX_ENTRY(int flags)
if (ZBX_NODE_STATUS_ACTIVE == ha_status)
{
- if (SUCCEED != server_startup(&listen_sock))
+ if (SUCCEED != server_startup(&listen_sock, &rtc))
{
sig_exiting = ZBX_EXIT_FAILURE;
ha_status = ZBX_NODE_STATUS_ERROR;
@@ -1772,7 +1760,7 @@ int MAIN_ZABBIX_ENTRY(int flags)
{
/* check if the HA status has not been changed during startup process */
if (ZBX_NODE_STATUS_ACTIVE != ha_status)
- server_teardown(&listen_sock);
+ server_teardown(&rtc, &listen_sock);
}
}
@@ -1798,28 +1786,52 @@ int MAIN_ZABBIX_ENTRY(int flags)
while (ZBX_IS_RUNNING())
{
- time_t now;
+ time_t now;
+ zbx_ipc_client_t *client;
+ zbx_ipc_message_t *message;
- if (SUCCEED != zbx_ha_recv_status(1, &ha_status, &error))
+ (void)zbx_ipc_service_recv(&rtc.service, &rtc_timeout, &client, &message);
+
+ if (NULL == message || ZBX_IPC_SERVICE_HA_RTC_FIRST <= message->code)
{
- zabbix_log(LOG_LEVEL_CRIT, "cannot receive HA manager status: %s", error);
- zbx_free(error);
- sig_exiting = ZBX_EXIT_FAILURE;
- break;
+ if (SUCCEED != zbx_ha_dispatch_message(message, &ha_status, &error))
+ {
+ zabbix_log(LOG_LEVEL_CRIT, "HA manager error: %s", error);
+ sig_exiting = ZBX_EXIT_FAILURE;
+ }
+ }
+ else
+ {
+ if (ZBX_NODE_STATUS_ACTIVE == ha_status || ZBX_RTC_LOG_LEVEL_DECREASE == message->code ||
+ ZBX_RTC_LOG_LEVEL_INCREASE == message->code)
+ {
+ zbx_rtc_dispatch(client, message);
+ }
+ else
+ {
+ const char *result = "Runtime commands can be executed only in active mode\n";
+ zbx_ipc_client_send(client, message->code, (const unsigned char *)result,
+ (zbx_uint32_t)strlen(result) + 1);
+ }
}
+ zbx_ipc_message_free(message);
+
+ if (NULL != client)
+ zbx_ipc_client_release(client);
+
now = time(NULL);
if (ZBX_NODE_STATUS_UNKNOWN != ha_status && ha_status != ha_status_old)
{
ha_status_old = ha_status;
- zabbix_log(LOG_LEVEL_INFORMATION, "\"%s\" node switched to \"%s\" mode", CONFIG_HA_NODE_NAME,
- zbx_ha_status_str(ha_status));
+ zabbix_log(LOG_LEVEL_INFORMATION, "\"%s\" node switched to \"%s\" mode",
+ ZBX_NULL2EMPTY_STR(CONFIG_HA_NODE_NAME), zbx_ha_status_str(ha_status));
switch (ha_status)
{
case ZBX_NODE_STATUS_ACTIVE:
- if (SUCCEED != server_startup(&listen_sock))
+ if (SUCCEED != server_startup(&listen_sock, &rtc))
{
sig_exiting = ZBX_EXIT_FAILURE;
ha_status = ZBX_NODE_STATUS_ERROR;
@@ -1827,11 +1839,11 @@ int MAIN_ZABBIX_ENTRY(int flags)
}
if (ZBX_NODE_STATUS_ACTIVE != ha_status)
- server_teardown(&listen_sock);
+ server_teardown(&rtc, &listen_sock);
break;
case ZBX_NODE_STATUS_STANDBY:
- server_teardown(&listen_sock);
+ server_teardown(&rtc, &listen_sock);
standby_warning_time = now;
break;
default:
@@ -1864,16 +1876,6 @@ int MAIN_ZABBIX_ENTRY(int flags)
zabbix_log(LOG_LEVEL_ERR, "failed to wait on child processes: %s", zbx_strerror(errno));
break;
}
-
- if (0 != zbx_rtc_command)
- {
- if (ZBX_NODE_STATUS_ACTIVE == ha_status)
- zbx_rtc_process_command((unsigned int)zbx_rtc_command);
- else
- zabbix_log(LOG_LEVEL_INFORMATION, "runtime commands can be executed only in active mode");
-
- zbx_rtc_command = 0;
- }
}
if (SUCCEED != zbx_ha_pause(&error))
diff --git a/src/zabbix_server/trapper/proxyconfig.c b/src/zabbix_server/trapper/proxyconfig.c
index 7dc93c26236..b833f8e3476 100644
--- a/src/zabbix_server/trapper/proxyconfig.c
+++ b/src/zabbix_server/trapper/proxyconfig.c
@@ -24,6 +24,7 @@
#include "../../libs/zbxcrypto/tls_tcp_active.h"
#include "zbxcompress.h"
+#include "zbxipcservice.h"
#include "proxyconfig.h"
@@ -61,7 +62,7 @@ void send_proxyconfig(zbx_socket_t *sock, struct zbx_json_parse *jp)
goto out;
}
- zbx_update_proxy_data(&proxy, zbx_get_proxy_protocol_version(jp), time(NULL),
+ zbx_update_proxy_data(&proxy, zbx_get_proxy_protocol_version(jp), (int)time(NULL),
(0 != (sock->protocol & ZBX_TCP_COMPRESS) ? 1 : 0), ZBX_FLAGS_PROXY_DIFF_UPDATE_CONFIG);
if (0 != proxy.auto_compress)
@@ -94,16 +95,18 @@ void send_proxyconfig(zbx_socket_t *sock, struct zbx_json_parse *jp)
zabbix_log(LOG_LEVEL_WARNING, "sending configuration data to proxy \"%s\" at \"%s\", datalen "
ZBX_FS_SIZE_T ", bytes " ZBX_FS_SIZE_T " with compression ratio %.1f", proxy.host,
sock->peer, (zbx_fs_size_t)reserved, (zbx_fs_size_t)buffer_size,
- (double)reserved / buffer_size);
+ (double)reserved / (double)buffer_size);
- ret = zbx_tcp_send_ext(sock, buffer, buffer_size, reserved, flags, CONFIG_TRAPPER_TIMEOUT);
+ ret = zbx_tcp_send_ext(sock, buffer, buffer_size, reserved, (unsigned char)flags,
+ CONFIG_TRAPPER_TIMEOUT);
}
else
{
zabbix_log(LOG_LEVEL_WARNING, "sending configuration data to proxy \"%s\" at \"%s\", datalen "
ZBX_FS_SIZE_T, proxy.host, sock->peer, (zbx_fs_size_t)j.buffer_size);
- ret = zbx_tcp_send_ext(sock, j.buffer, strlen(j.buffer), 0, flags, CONFIG_TRAPPER_TIMEOUT);
+ ret = zbx_tcp_send_ext(sock, j.buffer, strlen(j.buffer), 0, (unsigned char)flags,
+ CONFIG_TRAPPER_TIMEOUT);
}
if (SUCCEED != ret)
@@ -131,7 +134,7 @@ out:
******************************************************************************/
void recv_proxyconfig(zbx_socket_t *sock, struct zbx_json_parse *jp)
{
- struct zbx_json_parse jp_data;
+ struct zbx_json_parse jp_data, jp_kvs_paths = {0};
int ret;
zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
@@ -147,7 +150,26 @@ void recv_proxyconfig(zbx_socket_t *sock, struct zbx_json_parse *jp)
if (SUCCEED != check_access_passive_proxy(sock, ZBX_SEND_RESPONSE, "configuration update"))
goto out;
- process_proxyconfig(&jp_data);
+ if (SUCCEED == process_proxyconfig(&jp_data, &jp_kvs_paths))
+ {
+ unsigned char *result;
+ char *error = NULL;
+
+ if (SUCCEED == zbx_ipc_async_exchange(ZBX_IPC_SERVICE_CONFIG, ZBX_IPC_CONFIG_RELOAD_REQUEST,
+ ZBX_IPC_WAIT_FOREVER, NULL, 0, &result, &error))
+ {
+ zbx_free(result);
+
+ if (NULL != jp_kvs_paths.start)
+ DCsync_kvs_paths(&jp_kvs_paths);
+ }
+ else
+ {
+ THIS_SHOULD_NEVER_HAPPEN;
+ zabbix_log(LOG_LEVEL_WARNING, "cannot send message to configuration syncer: %s", error);
+ zbx_free(error);
+ }
+ }
zbx_send_proxy_response(sock, ret, NULL, CONFIG_TIMEOUT);
out:
zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
diff --git a/src/zabbix_server/trapper/trapper.c b/src/zabbix_server/trapper/trapper.c
index 327f08ceb07..0c7d2332c05 100644
--- a/src/zabbix_server/trapper/trapper.c
+++ b/src/zabbix_server/trapper/trapper.c
@@ -35,6 +35,7 @@
#include "../../libs/zbxserver/zabbix_stats.h"
#include "zbxipcservice.h"
#include "../poller/checks_snmp.h"
+#include "zbxrtc.h"
#include "trapper_auth.h"
#include "trapper_preproc.h"
@@ -1226,13 +1227,6 @@ ZBX_THREAD_ENTRY(trapper_thread, args)
DBconnect(ZBX_DB_CONNECT_NORMAL);
- /* configuration sync is performed by trappers on passive Zabbix proxy */
- if (1 == process_num && 0 == CONFIG_CONFSYNCER_FORKS)
- {
- zbx_setproctitle("%s [syncing configuration]", get_process_type_string(process_type));
- DCsync_configuration(ZBX_DBSYNC_INIT, NULL);
- }
-
zbx_set_sigusr_handler(zbx_trapper_sigusr_handler);
while (ZBX_IS_RUNNING())
diff --git a/ui/tests/include/web/CPage.php b/ui/tests/include/web/CPage.php
index 1a28f289023..fe8c4d3a4a9 100644
--- a/ui/tests/include/web/CPage.php
+++ b/ui/tests/include/web/CPage.php
@@ -126,11 +126,13 @@ class CPage {
$this->resetViewport();
if (self::$cookie !== null) {
- $cookie = $this->driver->manage()->getCookieNamed('zbx_session');
-
- if ($cookie === null
- || $cookie->getValue() !== self::$cookie['value']) {
- self::$cookie = null;
+ foreach ($this->driver->manage()->getCookies() as $cookie) {
+ if ($cookie->getName() === 'zbx_session') {
+ if ($cookie->getValue() !== self::$cookie['value']) {
+ self::$cookie = null;
+ }
+ break;
+ }
}
}
@@ -236,9 +238,19 @@ class CPage {
// Before logout open page without any scripts, otherwise session might be restored and logout won't work.
$this->open('setup.php');
- $session = (self::$cookie === null)
- ? CTestArrayHelper::get($this->driver->manage()->getCookieNamed('zbx_session'), 'value')
- : self::$cookie['value'];
+ $session = null;
+
+ if (self::$cookie === null) {
+ foreach ($this->driver->manage()->getCookies() as $cookie) {
+ if ($cookie->getName() === 'zbx_session') {
+ $session = $cookie->getValue();
+ break;
+ }
+ }
+ }
+ else {
+ $session = self::$cookie['value'];
+ }
if ($session !== null) {
DBExecute('DELETE FROM sessions WHERE sessionid='.zbx_dbstr($session));
diff --git a/ui/tests/selenium/dashboard/testDashboardProblemsBySeverityWidget.php b/ui/tests/selenium/dashboard/testDashboardProblemsBySeverityWidget.php
index f632f65f7c8..3873810907d 100644
--- a/ui/tests/selenium/dashboard/testDashboardProblemsBySeverityWidget.php
+++ b/ui/tests/selenium/dashboard/testDashboardProblemsBySeverityWidget.php
@@ -1671,7 +1671,7 @@ class testDashboardProblemsBySeverityWidget extends CWebTest {
}
foreach ($expected_popup['Tags'] as $tag) {
$tag_array = $row->getColumn('Tags')->getText();
- $this->assertContains($tag, $tag_array);
+ $this->assertStringContainsString($tag, $tag_array);
}
if (CTestArrayHelper::get($data['fields'], 'Show operational data', 'None') === 'Separately') {
$this->assertEquals('*UNKNOWN*', $row->getColumn('Operational data')->getText());
diff --git a/ui/tests/selenium/reports/testFormScheduledReport.php b/ui/tests/selenium/reports/testFormScheduledReport.php
index 56353dec6d9..fb516499c2a 100644
--- a/ui/tests/selenium/reports/testFormScheduledReport.php
+++ b/ui/tests/selenium/reports/testFormScheduledReport.php
@@ -914,7 +914,7 @@ class testFormScheduledReport extends CWebTest {
'Description' => '',
'Enabled' => false
],
- 'Start time' => '0:0',
+ 'Start time' => '00:00',
'Subscriptions' => [
[
'action' => USER_ACTION_REMOVE,
diff --git a/ui/tests/selenium/reports/testPageReportsNotifications.php b/ui/tests/selenium/reports/testPageReportsNotifications.php
index ac82198c59c..e1a8e5940bd 100644
--- a/ui/tests/selenium/reports/testPageReportsNotifications.php
+++ b/ui/tests/selenium/reports/testPageReportsNotifications.php
@@ -37,7 +37,7 @@ class testPageReportsNotifications extends CLegacyWebTest {
$dropdowns = [
'media_type' => array_merge(['all'], $all_media),
'period' => ['Daily', 'Weekly', 'Monthly', 'Yearly'],
- 'year' => ['2012', '2013', '2014', '2015', '2016', '2017', '2018', '2019', '2020', '2021']
+ 'year' => ['2012', '2013', '2014', '2015', '2016', '2017', '2018', '2019', '2020', '2021', '2022']
];
$default_selected = [
'media_type' => 'all',
diff --git a/ui/tests/selenium/roles/testUserRolesPermissions.php b/ui/tests/selenium/roles/testUserRolesPermissions.php
index d5ef7ce6e16..4c401c72d23 100644
--- a/ui/tests/selenium/roles/testUserRolesPermissions.php
+++ b/ui/tests/selenium/roles/testUserRolesPermissions.php
@@ -1423,7 +1423,7 @@ class testUserRolesPermissions extends CWebTest {
$this->query('button:Go to "'.$page.'"')->one()->waitUntilClickable()->click();
if ($page === 'Dashboard') {
- $this->assertContains('zabbix.php?action=dashboard', $this->page->getCurrentUrl());
+ $this->assertStringContainsString('zabbix.php?action=dashboard', $this->page->getCurrentUrl());
}
}
}
diff --git a/ui/tests/selenium/testFormAdministrationAuthenticationHttp.php b/ui/tests/selenium/testFormAdministrationAuthenticationHttp.php
index 68fc7186279..18a53778d14 100644
--- a/ui/tests/selenium/testFormAdministrationAuthenticationHttp.php
+++ b/ui/tests/selenium/testFormAdministrationAuthenticationHttp.php
@@ -526,7 +526,7 @@ class testFormAdministrationAuthenticationHttp extends CLegacyWebTest {
$message = CMessageElement::find()->one();
$this->assertEquals('msg-bad msg-global', $message->getAttribute('class'));
$message_title= $message->getText();
- $this->assertContains($check['error'], $message_title);
+ $this->assertStringContainsString($check['error'], $message_title);
}
continue;
diff --git a/ui/tests/selenium/testFormAdministrationAuthenticationSaml.php b/ui/tests/selenium/testFormAdministrationAuthenticationSaml.php
index 03b17de78d5..63dbac8b157 100644
--- a/ui/tests/selenium/testFormAdministrationAuthenticationSaml.php
+++ b/ui/tests/selenium/testFormAdministrationAuthenticationSaml.php
@@ -220,7 +220,7 @@ class testFormAdministrationAuthenticationSaml extends CWebTest {
$this->page->logout();
$this->page->open('index.php')->waitUntilReady();
$link = $this->query('link:Sign in with Single Sign-On (SAML)')->one()->waitUntilClickable();
- $this->assertContains('index_sso.php', $link->getAttribute('href'));
+ $this->assertStringContainsString('index_sso.php', $link->getAttribute('href'));
// Login and disable SAML authentication.
$this->page->login()->open('zabbix.php?action=authentication.edit');
$form = $this->query('name:form_auth')->asForm()->one();
@@ -379,7 +379,7 @@ class testFormAdministrationAuthenticationSaml extends CWebTest {
// Make sure that it is possible to log out.
$this->query('link:Sign out')->one()->click();
$this->page->waitUntilReady();
- $this->assertContains('index.php', $this->page->getCurrentUrl());
+ $this->assertStringContainsString('index.php', $this->page->getCurrentUrl());
}
/**
diff --git a/ui/tests/selenium/testFormEventCorrelation.php b/ui/tests/selenium/testFormEventCorrelation.php
index 6595f7647c6..965efa0ed70 100644
--- a/ui/tests/selenium/testFormEventCorrelation.php
+++ b/ui/tests/selenium/testFormEventCorrelation.php
@@ -153,9 +153,9 @@ class testFormEventCorrelation extends CLegacyWebTest {
$this->zbxTestClick('add');
$this->zbxTestWaitUntilMessageTextPresent('msg-bad', $data['error_header']);
$error = $this->zbxTestGetText('//ul[@class=\'list-dashed msg-details-border\']');
- $this->assertContains($data['error_message'], $error);
+ $this->assertStringContainsString($data['error_message'], $error);
- if (array_key_exists('name', $data) && $data['name'] === 'Event correlation for update') {
+ if (array_key_exists('name', $data) && $data['name'] === 'Event correlation for update') {
$sql = 'SELECT NULL FROM correlation WHERE name='.zbx_dbstr($data['name']);
$this->assertEquals(1, CDBHelper::getCount($sql));
}
@@ -656,7 +656,7 @@ class testFormEventCorrelation extends CLegacyWebTest {
$this->zbxTestWaitUntilMessageTextPresent('msg-bad', 'Cannot add correlation');
$error = $this->zbxTestGetText('//ul[@class=\'list-dashed msg-details-border\']');
- $this->assertContains($data['error_message'], $error);
+ $this->assertStringContainsString($data['error_message'], $error);
$sql = 'SELECT NULL FROM correlation WHERE name='.zbx_dbstr($data['name']);
$this->assertEquals(0, CDBHelper::getCount($sql));
diff --git a/ui/tests/selenium/testFormSetup.php b/ui/tests/selenium/testFormSetup.php
index 6cc52b22bb8..01f057bc53c 100644
--- a/ui/tests/selenium/testFormSetup.php
+++ b/ui/tests/selenium/testFormSetup.php
@@ -316,7 +316,7 @@ class testFormSetup extends CWebTest {
$xpath = 'xpath://span[text()='.CXPathHelper::escapeQuotes($field_name).']/../../div[@class="table-forms-td-right"]';
// Assert contains is used as Password length can differ.
if ($field_name === 'Database password') {
- $this->assertContains($value, $this->query($xpath)->one()->getText());
+ $this->assertStringContainsString($value, $this->query($xpath)->one()->getText());
}
else {
$this->assertEquals($value, $this->query($xpath)->one()->getText());
@@ -344,7 +344,7 @@ class testFormSetup extends CWebTest {
// Check that Dashboard view is opened after completing the form.
$this->query('button:Finish')->one()->click();
$this->page->waitUntilReady();
- $this->assertContains('index.php', $this->page->getCurrentURL());
+ $this->assertStringContainsString('index.php', $this->page->getCurrentURL());
}
public function getDbConnectionDetails() {
@@ -804,7 +804,7 @@ class testFormSetup extends CWebTest {
// Cancel setup form update.
$this->query('button:Cancel')->one()->click();
- $this->assertContains('zabbix.php?action=dashboard.view', $this->page->getCurrentURL());
+ $this->assertStringContainsString('zabbix.php?action=dashboard.view', $this->page->getCurrentURL());
}
/**
@@ -817,7 +817,7 @@ class testFormSetup extends CWebTest {
$this->assertTrue($this->query('xpath://h1[text()='.CXPathHelper::escapeQuotes($title).']')->one()->isValid());
$this->checkSections($title);
if ($text) {
- $this->assertContains($text, $this->query('xpath:.//p')->one()->getText());
+ $this->assertStringContainsString($text, $this->query('xpath:.//p')->one()->getText());
}
}
diff --git a/ui/tests/selenium/testFormTrigger.php b/ui/tests/selenium/testFormTrigger.php
index 4c5faadb831..fa768d13fbc 100644
--- a/ui/tests/selenium/testFormTrigger.php
+++ b/ui/tests/selenium/testFormTrigger.php
@@ -913,7 +913,7 @@ class testFormTrigger extends CLegacyWebTest {
$this->assertEquals($count, $this->query('xpath://span[@class="icon-info status-red"]')->all()->count());
$text = $this->query('xpath://tr[1]//div[@class="hint-box"]')->one()->getText();
foreach ($constructor['errors'] as $error) {
- $this->assertContains($error, $text);
+ $this->assertStringContainsString($error, $text);
}
}
else {
diff --git a/ui/tests/selenium/testFormTriggerPrototype.php b/ui/tests/selenium/testFormTriggerPrototype.php
index 060ffe8384a..69297a7ffb2 100644
--- a/ui/tests/selenium/testFormTriggerPrototype.php
+++ b/ui/tests/selenium/testFormTriggerPrototype.php
@@ -869,7 +869,7 @@ class testFormTriggerPrototype extends CLegacyWebTest {
$this->assertEquals($count, $this->query('xpath://span[@class="icon-info status-red"]')->all()->count());
$text = $this->query('xpath://tr[1]//div[@class="hint-box"]')->one()->getText();
foreach ($constructor['errors'] as $error) {
- $this->assertContains($error, $text);
+ $this->assertStringContainsString($error, $text);
}
}
else {
diff --git a/ui/tests/selenium/testPageAdministrationGeneralModules.php b/ui/tests/selenium/testPageAdministrationGeneralModules.php
index 9e0dbb77db8..1f505ba53d9 100644
--- a/ui/tests/selenium/testPageAdministrationGeneralModules.php
+++ b/ui/tests/selenium/testPageAdministrationGeneralModules.php
@@ -552,7 +552,7 @@ class testPageAdministrationGeneralModules extends CWebTest {
sleep(1);
$this->query($xpath.$entry['name'].'"]')->one()->waitUntilClickable()->click();
$this->page->waitUntilReady();
- $this->assertContains('zabbix.php?action='.$entry['action'], $this->page->getCurrentURL());
+ $this->assertStringContainsString('zabbix.php?action='.$entry['action'], $this->page->getCurrentURL());
$this->assertEquals($entry['message'], $this->query('tag:h1')->waitUntilVisible()->one()->getText());
}
// Get back to modules list to enable or disable the next module.
@@ -582,7 +582,7 @@ class testPageAdministrationGeneralModules extends CWebTest {
if (CTestArrayHelper::get($entry, 'check_disabled', true)) {
$this->page->open('zabbix.php?action='.$entry['action'])->waitUntilReady();
$message = CMessageElement::find()->one();
- $this->assertContains('Class not found for action '.$entry['action'], $message->getText());
+ $this->assertStringContainsString('Class not found for action '.$entry['action'], $message->getText());
$this->page->open('zabbix.php?action=module.list');
}
}
diff --git a/ui/tests/selenium/testPageTriggerDescription.php b/ui/tests/selenium/testPageTriggerDescription.php
index c3e8468cc9e..89ac21672e0 100644
--- a/ui/tests/selenium/testPageTriggerDescription.php
+++ b/ui/tests/selenium/testPageTriggerDescription.php
@@ -113,7 +113,7 @@ class testPageTriggerDescription extends CWebTest {
$this->page->waitUntilReady();
// Check the URL of the opened page to make sure that correct event is opened.
- $this->assertContains($data['event_url'], $this->page->getCurrentURL());
+ $this->assertStringContainsString($data['event_url'], $this->page->getCurrentURL());
// Find the row that contains trigger description and select the column that holds the value of description field.
$description = $this->query('xpath://td[text()="Description"]/..')->one()->asTableRow()->getColumn(1);
diff --git a/ui/tests/selenium/testPageTriggerUrl.php b/ui/tests/selenium/testPageTriggerUrl.php
index fda65e7a0b6..9863366b610 100644
--- a/ui/tests/selenium/testPageTriggerUrl.php
+++ b/ui/tests/selenium/testPageTriggerUrl.php
@@ -134,7 +134,7 @@ class testPageTriggerUrl extends CWebTest {
// Check Url of each link.
foreach ($data['links'] as $link => $url) {
$this->assertTrue($popup->hasItems($link));
- $this->assertContains($url, $popup->getItem($link)->getAttribute('href'));
+ $this->assertStringContainsString($url, $popup->getItem($link)->getAttribute('href'));
}
if ($trigger_overview) {
$this->assertTrue($popup->hasItems('Acknowledge'));
@@ -156,6 +156,6 @@ class testPageTriggerUrl extends CWebTest {
// Check opened page.
$this->assertEquals('Event details', $this->query('tag:h1')->waitUntilVisible()->one()->getText());
- $this->assertContains($data['links']['Trigger URL'], $this->page->getCurrentUrl());
+ $this->assertStringContainsString($data['links']['Trigger URL'], $this->page->getCurrentUrl());
}
}
diff --git a/ui/tests/selenium/testSID.php b/ui/tests/selenium/testSID.php
index 77b7ce6dae6..e4dca61c2fe 100644
--- a/ui/tests/selenium/testSID.php
+++ b/ui/tests/selenium/testSID.php
@@ -668,7 +668,7 @@ class testSID extends CWebTest {
$this->assertMessage(TEST_BAD, 'Access denied', 'You are logged in as "Admin". You have no permissions to access this page.');
$this->query('button:Go to "Dashboard"')->one()->waitUntilClickable()->click();
- $this->assertContains('zabbix.php?action=dashboard', $this->page->getCurrentUrl());
+ $this->assertStringContainsString('zabbix.php?action=dashboard', $this->page->getCurrentUrl());
}
}
@@ -1205,7 +1205,7 @@ class testSID extends CWebTest {
if (CTestArrayHelper::get($data, 'incorrect_request')) {
$this->query('button:Go to "Dashboard"')->one()->waitUntilClickable()->click();
$this->page->waitUntilReady();
- $this->assertContains('zabbix.php?action=dashboard', $this->page->getCurrentUrl());
+ $this->assertStringContainsString('zabbix.php?action=dashboard', $this->page->getCurrentUrl());
}
$this->assertEquals($hash_before, CDBHelper::getHash($data['db']));
diff --git a/ui/tests/selenium/testTemplateInheritance.php b/ui/tests/selenium/testTemplateInheritance.php
index b9ff4b64336..358a6a5605c 100644
--- a/ui/tests/selenium/testTemplateInheritance.php
+++ b/ui/tests/selenium/testTemplateInheritance.php
@@ -276,9 +276,9 @@ class testTemplateInheritance extends CLegacyWebTest {
$this->assertFalse($this->zbxTestCheckboxSelected('show_work_period'));
$this->assertFalse($this->zbxTestCheckboxSelected('show_triggers'));
$this->assertTrue($this->zbxTestCheckboxSelected('visible_percent_left'));
- $this->zbxTestAssertElementValue('percent_left', '4.00');
+ $this->zbxTestAssertElementValue('percent_left', '4');
$this->assertTrue($this->zbxTestCheckboxSelected('visible_percent_right'));
- $this->zbxTestAssertElementValue('percent_right', '5.00');
+ $this->zbxTestAssertElementValue('percent_right', '5');
$this->zbxTestDropdownAssertSelected('ymin_type', 'Calculated');
$this->zbxTestDropdownAssertSelected('ymax_type', 'Calculated');
$this->zbxTestTextPresent('Parent graphs');
@@ -513,9 +513,9 @@ class testTemplateInheritance extends CLegacyWebTest {
$this->assertFalse($this->zbxTestCheckboxSelected('show_work_period'));
$this->assertFalse($this->zbxTestCheckboxSelected('show_triggers'));
$this->assertTrue($this->zbxTestCheckboxSelected('visible_percent_left'));
- $this->zbxTestAssertElementValue('percent_left', '4.00');
+ $this->zbxTestAssertElementValue('percent_left', '4');
$this->assertTrue($this->zbxTestCheckboxSelected('visible_percent_right'));
- $this->zbxTestAssertElementValue('percent_right', '5.00');
+ $this->zbxTestAssertElementValue('percent_right', '5');
$this->zbxTestDropdownAssertSelected('ymin_type', 'Calculated');
$this->zbxTestDropdownAssertSelected('ymax_type', 'Calculated');
$this->zbxTestTextPresent($this->hostName.': itemDiscovery');
diff --git a/ui/tests/selenium/users/testFormUser.php b/ui/tests/selenium/users/testFormUser.php
index d1388601a44..daacc77a2a1 100644
--- a/ui/tests/selenium/users/testFormUser.php
+++ b/ui/tests/selenium/users/testFormUser.php
@@ -593,7 +593,7 @@ class testFormUser extends CWebTest {
$password = CTestArrayHelper::get($data['fields'], 'Password', $data['fields']['Password'] = 'zabbix');
$this->page->userLogin($data['fields']['Username'], $password);
// Verification of URL after login.
- $this->assertContains($data['fields']['URL (after login)'], $this->page->getCurrentURL());
+ $this->assertStringContainsString($data['fields']['URL (after login)'], $this->page->getCurrentURL());
// Verification of the number of rows per page parameter.
$rows = $this->query('name:frm_maps')->asTable()->waitUntilVisible()->one()->getRows();
$this->assertEquals($data['fields']['Rows per page'], $rows->count());
@@ -1009,12 +1009,12 @@ class testFormUser extends CWebTest {
$this->page->logout();
// Attempt to sign in with old password.
- $this->page->userLogin($data['username'],$data['old_password']);
+ $this->page->userLogin($data['username'], $data['old_password']);
$message = $this->query('class:red')->one()->getText();
$this->assertEquals($message, $data['error_message']);
// Sign in with new password.
- $this->page->userLogin($data['username'],$data['new_password']);
+ $this->page->userLogin($data['username'], $data['new_password']);
$attempt_message = CMessageElement::find()->one();
$this->assertTrue($attempt_message->hasLine($data['attempt_message']));
$this->page->logout();
@@ -1140,7 +1140,7 @@ class testFormUser extends CWebTest {
$form_create->fill($data);
$this->query('button:Cancel')->one()->click();
$cancel_url = $this->page->getCurrentURL();
- $this->assertContains('zabbix.php?action=user.list', $cancel_url);
+ $this->assertStringContainsString('zabbix.php?action=user.list', $cancel_url);
$this->assertEquals($user_hash, CDBHelper::getHash($sql_users));
// Check Cancellation when updating users.
diff --git a/ui/tests/selenium/users/testFormUserMedia.php b/ui/tests/selenium/users/testFormUserMedia.php
index d99f4f8a4c4..33c1fa19c13 100644
--- a/ui/tests/selenium/users/testFormUserMedia.php
+++ b/ui/tests/selenium/users/testFormUserMedia.php
@@ -550,7 +550,7 @@ class testFormUserMedia extends CWebTest {
// Check that the removed email is not present in 'Send to' field.
$user_form = $this->query('name:user_form')->asForm()->waitUntilVisible()->one();
$row = $user_form->getField('Media')->asTable()->getRow(0);
- $this->assertNotContains($email, $row->getColumn('Send to')->getText());
+ $this->assertStringNotContainsString($email, $row->getColumn('Send to')->getText());
}
private function setMediaValues($data) {
@@ -635,7 +635,7 @@ class testFormUserMedia extends CWebTest {
// Check that when no severities are passed - they all are turned on by default
for ($i = 1; $i < 7; $i++) {
$severity = $row->query('xpath:./td[4]/div/div['.$i.']')->one()->getText();
- $this->assertContains('(on)', $severity);
+ $this->assertStringContainsString('(on)', $severity);
}
}
}