mirror of
https://github.com/netdata/netdata.git
synced 2025-04-16 10:31:07 +00:00
Removes ACLK Legacy (#11841)
* remove legacy from makefiles * remove ACLK Legacy from installer * remove ACLK Legacy from configure.ac * remove legacy from cmake * aclk api cleanup * remove legacy files from packaging * changes for CI from Austin
This commit is contained in:
parent
2546c02f89
commit
5736b4bcb1
41 changed files with 59 additions and 5697 deletions
.github/workflows
CMakeLists.txtMakefile.amaclk
aclk.caclk.haclk_api.c
configure.aclegacy
contrib/debian
daemon
netdata-installer.shnetdata.spec.inpackaging
bundle-lws.shbundle-mosquitto.shlibwebsockets.checksumslibwebsockets.versionmosquitto.checksumsmosquitto.version
web/api
4
.github/workflows/build.yml
vendored
4
.github/workflows/build.yml
vendored
|
@ -223,10 +223,6 @@ jobs:
|
|||
run: |
|
||||
docker run --security-opt seccomp=unconfined -w /netdata sha256:${{ steps.load.outputs.image }} \
|
||||
/bin/sh -c './netdata-installer.sh --dont-wait --dont-start-it --require-cloud'
|
||||
- name: netdata-installer on ${{ matrix.distro }}, require cloud, require ACLK-NG
|
||||
run: |
|
||||
docker run --security-opt seccomp=unconfined -w /netdata -e NETDATA_CONFIGURE_OPTIONS='--with-aclk-ng' \
|
||||
sha256:${{ steps.load.outputs.image }} /bin/sh -c './netdata-installer.sh --dont-wait --dont-start-it --require-cloud'
|
||||
- name: netdata-installer on ${{ matrix.distro }}, require cloud, no JSON-C
|
||||
if: matrix.rmjsonc != ''
|
||||
run: |
|
||||
|
|
|
@ -773,26 +773,7 @@ set(ACLK_COMMON_FILES
|
|||
aclk/aclk_collector_list.h
|
||||
)
|
||||
|
||||
set(ACLK_LEGACY_FILES
|
||||
aclk/legacy/agent_cloud_link.c
|
||||
aclk/legacy/agent_cloud_link.h
|
||||
aclk/legacy/aclk_query.c
|
||||
aclk/legacy/aclk_query.h
|
||||
aclk/legacy/aclk_lws_wss_client.c
|
||||
aclk/legacy/aclk_lws_wss_client.h
|
||||
aclk/legacy/aclk_lws_https_client.c
|
||||
aclk/legacy/aclk_lws_https_client.h
|
||||
aclk/legacy/mqtt.c
|
||||
aclk/legacy/mqtt.h
|
||||
aclk/legacy/aclk_stats.c
|
||||
aclk/legacy/aclk_stats.h
|
||||
aclk/legacy/aclk_rx_msgs.c
|
||||
aclk/legacy/aclk_rx_msgs.h
|
||||
aclk/legacy/aclk_common.c
|
||||
aclk/legacy/aclk_common.h
|
||||
)
|
||||
|
||||
set(ACLK_NG_FILES
|
||||
set(ACLK_FILES
|
||||
aclk/aclk.c
|
||||
aclk/aclk.h
|
||||
aclk/aclk_util.c
|
||||
|
@ -854,11 +835,6 @@ set(SPAWN_PLUGIN_FILES
|
|||
spawn/spawn.h
|
||||
)
|
||||
|
||||
set(ACLK_LEGACY_STATIC_LIBS
|
||||
${CMAKE_SOURCE_DIR}/externaldeps/mosquitto/libmosquitto.a
|
||||
${CMAKE_SOURCE_DIR}/externaldeps/libwebsockets/libwebsockets.a
|
||||
)
|
||||
|
||||
set(EXPORTING_ENGINE_FILES
|
||||
exporting/exporting_engine.c
|
||||
exporting/exporting_engine.h
|
||||
|
@ -1070,31 +1046,6 @@ ENDIF()
|
|||
|
||||
set(NETDATA_COMMON_LIBRARIES ${NETDATA_COMMON_LIBRARIES} m ${CMAKE_THREAD_LIBS_INIT})
|
||||
|
||||
set(ACLK_LEGACY_CAN_BUILD 1)
|
||||
if(NOT EXISTS "${CMAKE_SOURCE_DIR}/externaldeps/mosquitto/libmosquitto.a")
|
||||
message(WARNING "Static build of mosquitto not found. Disabling ACLK")
|
||||
set(ACLK_LEGACY_CAN_BUILD 0)
|
||||
ENDIF()
|
||||
|
||||
if(NOT EXISTS "${CMAKE_SOURCE_DIR}/externaldeps/libwebsockets/libwebsockets.a")
|
||||
message(WARNING "Static build of libwebsockets not found. Disabling ACLK")
|
||||
set(ACLK_LEGACY_CAN_BUILD 0)
|
||||
ENDIF()
|
||||
|
||||
IF(ACLK_LEGACY_CAN_BUILD)
|
||||
message(STATUS "agent-cloud-link Legacy: enabled")
|
||||
list(APPEND NETDATA_FILES ${ACLK_LEGACY_FILES})
|
||||
list(APPEND NETDATA_COMMON_LIBRARIES ${ACLK_LEGACY_STATIC_LIBS})
|
||||
include_directories(BEFORE ${CMAKE_SOURCE_DIR}/externaldeps/libwebsockets/include)
|
||||
IF(LINUX AND CAP_FOUND)
|
||||
list(APPEND NETDATA_COMMON_LIBRARIES ${CAP_LIBRARIES})
|
||||
list(APPEND NETDATA_COMMON_INCLUDE_DIRS ${CAP_INCLUDE_DIRS})
|
||||
list(APPEND NETDATA_COMMON_CFLAGS ${CAP_CFLAGS_OTHER})
|
||||
ENDIF()
|
||||
ELSE()
|
||||
message(STATUS "agent-cloud-link Legacy: disabled")
|
||||
ENDIF()
|
||||
|
||||
find_package(Protobuf REQUIRED)
|
||||
|
||||
function(PROTOBUF_ACLK_GENERATE_CPP SRCS HDRS)
|
||||
|
@ -1133,7 +1084,7 @@ function(PROTOBUF_ACLK_GENERATE_CPP SRCS HDRS)
|
|||
set(${HDRS} ${${HDRS}} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
set(ACLK_NG_PROTO_DEFS
|
||||
set(ACLK_PROTO_DEFS
|
||||
aclk/aclk-schemas/proto/aclk/v1/lib.proto
|
||||
aclk/aclk-schemas/proto/agent/v1/disconnect.proto
|
||||
aclk/aclk-schemas/proto/agent/v1/connection.proto
|
||||
|
@ -1147,13 +1098,13 @@ set(ACLK_NG_PROTO_DEFS
|
|||
aclk/aclk-schemas/proto/nodeinstance/create/v1/creation.proto
|
||||
aclk/aclk-schemas/proto/nodeinstance/info/v1/info.proto
|
||||
)
|
||||
PROTOBUF_ACLK_GENERATE_CPP(ACLK_NG_PROTO_BUILT_SRCS ACLK_NG_PROTO_BUILT_HDRS ${ACLK_NG_PROTO_DEFS})
|
||||
PROTOBUF_ACLK_GENERATE_CPP(ACLK_PROTO_BUILT_SRCS ACLK_PROTO_BUILT_HDRS ${ACLK_PROTO_DEFS})
|
||||
|
||||
list(APPEND NETDATA_COMMON_LIBRARIES ${PROTOBUF_LIBRARIES})
|
||||
list(APPEND NETDATA_COMMON_INCLUDE_DIRS ${PROTOBUF_INCLUDE_DIRS})
|
||||
list(APPEND NETDATA_COMMON_CFLAGS ${PROTOBUF_CFLAGS_OTHER})
|
||||
list(APPEND NETDATA_FILES ${ACLK_ALWAYS_BUILD})
|
||||
list(APPEND NETDATA_FILES ${ACLK_NG_FILES} ${ACLK_NG_PROTO_BUILT_SRCS} ${ACLK_NG_PROTO_BUILT_HDRS})
|
||||
list(APPEND NETDATA_FILES ${ACLK_FILES} ${ACLK_PROTO_BUILT_SRCS} ${ACLK_PROTO_BUILT_HDRS})
|
||||
list(APPEND NETDATA_FILES ${ACLK_COMMON_FILES})
|
||||
include_directories(BEFORE ${CMAKE_SOURCE_DIR}/aclk/aclk-schemas)
|
||||
include_directories(BEFORE ${CMAKE_SOURCE_DIR}/mqtt_websockets/MQTT-C/include)
|
||||
|
|
66
Makefile.am
66
Makefile.am
|
@ -64,8 +64,6 @@ dist_noinst_DATA = \
|
|||
packaging/bundle-ebpf.sh \
|
||||
packaging/bundle-judy.sh \
|
||||
packaging/bundle-libbpf.sh \
|
||||
packaging/bundle-lws.sh \
|
||||
packaging/bundle-mosquitto.sh \
|
||||
packaging/check-kernel-config.sh \
|
||||
packaging/ebpf.checksums \
|
||||
packaging/ebpf.version \
|
||||
|
@ -80,10 +78,6 @@ dist_noinst_DATA = \
|
|||
packaging/judy.version \
|
||||
packaging/libbpf.checksums \
|
||||
packaging/libbpf.version \
|
||||
packaging/libwebsockets.checksums \
|
||||
packaging/libwebsockets.version \
|
||||
packaging/mosquitto.checksums \
|
||||
packaging/mosquitto.version \
|
||||
packaging/protobuf.checksums \
|
||||
packaging/protobuf.version \
|
||||
packaging/version \
|
||||
|
@ -121,12 +115,6 @@ SUBDIRS += \
|
|||
ml \
|
||||
$(NULL)
|
||||
|
||||
if ENABLE_ACLK
|
||||
SUBDIRS += \
|
||||
aclk/legacy \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
AM_CFLAGS = \
|
||||
$(OPTIONAL_MATH_CFLAGS) \
|
||||
$(OPTIONAL_NFACCT_CFLAGS) \
|
||||
|
@ -618,8 +606,8 @@ PARSER_FILES = \
|
|||
parser/parser.h \
|
||||
$(NULL)
|
||||
|
||||
if ACLK_NG
|
||||
ACLK_NG_FILES = \
|
||||
if ENABLE_ACLK
|
||||
ACLK_FILES = \
|
||||
aclk/aclk.c \
|
||||
aclk/aclk.h \
|
||||
aclk/aclk_util.c \
|
||||
|
@ -652,7 +640,7 @@ ACLK_NG_FILES = \
|
|||
$(NULL)
|
||||
|
||||
if ENABLE_NEW_CLOUD_PROTOCOL
|
||||
ACLK_NG_FILES += \
|
||||
ACLK_FILES += \
|
||||
aclk/aclk_charts_api.c \
|
||||
aclk/aclk_charts_api.h \
|
||||
aclk/aclk_alarm_api.c \
|
||||
|
@ -678,7 +666,7 @@ ACLK_NG_FILES += \
|
|||
aclk/schema-wrappers/schema_wrapper_utils.h \
|
||||
$(NULL)
|
||||
|
||||
ACLK_NG_PROTO_DEFINITIONS = \
|
||||
ACLK_PROTO_DEFINITIONS = \
|
||||
aclk/aclk-schemas/proto/aclk/v1/lib.proto \
|
||||
aclk/aclk-schemas/proto/agent/v1/disconnect.proto \
|
||||
aclk/aclk-schemas/proto/agent/v1/connection.proto \
|
||||
|
@ -693,9 +681,9 @@ ACLK_NG_PROTO_DEFINITIONS = \
|
|||
aclk/aclk-schemas/proto/nodeinstance/info/v1/info.proto \
|
||||
$(NULL)
|
||||
|
||||
dist_noinst_DATA += $(ACLK_NG_PROTO_DEFINITIONS)
|
||||
dist_noinst_DATA += $(ACLK_PROTO_DEFINITIONS)
|
||||
|
||||
ACLK_NG_PROTO_BUILT_FILES = aclk/aclk-schemas/proto/agent/v1/connection.pb.cc \
|
||||
ACLK_PROTO_BUILT_FILES = aclk/aclk-schemas/proto/agent/v1/connection.pb.cc \
|
||||
aclk/aclk-schemas/proto/agent/v1/connection.pb.h \
|
||||
aclk/aclk-schemas/proto/nodeinstance/connection/v1/connection.pb.cc \
|
||||
aclk/aclk-schemas/proto/nodeinstance/connection/v1/connection.pb.h \
|
||||
|
@ -721,9 +709,9 @@ ACLK_NG_PROTO_BUILT_FILES = aclk/aclk-schemas/proto/agent/v1/connection.pb.cc \
|
|||
aclk/aclk-schemas/proto/nodeinstance/info/v1/info.pb.h \
|
||||
$(NULL)
|
||||
|
||||
BUILT_SOURCES += $(ACLK_NG_PROTO_BUILT_FILES)
|
||||
nodist_netdata_SOURCES += $(ACLK_NG_PROTO_BUILT_FILES)
|
||||
CLEANFILES += $(ACLK_NG_PROTO_BUILT_FILES)
|
||||
BUILT_SOURCES += $(ACLK_PROTO_BUILT_FILES)
|
||||
nodist_netdata_SOURCES += $(ACLK_PROTO_BUILT_FILES)
|
||||
CLEANFILES += $(ACLK_PROTO_BUILT_FILES)
|
||||
|
||||
aclk/aclk-schemas/proto/agent/v1/connection.pb.cc \
|
||||
aclk/aclk-schemas/proto/agent/v1/connection.pb.h: aclk/aclk-schemas/proto/agent/v1/connection.proto
|
||||
|
@ -775,7 +763,7 @@ aclk/aclk-schemas/proto/nodeinstance/info/v1/info.pb.h: aclk/aclk-schemas/proto/
|
|||
|
||||
endif #ENABLE_NEW_CLOUD_PROTOCOL
|
||||
|
||||
endif #ACLK_NG
|
||||
endif #ENABLE_ACLK
|
||||
|
||||
if ENABLE_ACLK
|
||||
ACLK_COMMON_FILES = \
|
||||
|
@ -792,27 +780,6 @@ ACLK_ALWAYS_BUILD_FILES = \
|
|||
aclk/aclk_proxy.h \
|
||||
$(NULL)
|
||||
|
||||
if ACLK_LEGACY
|
||||
ACLK_LEGACY_FILES = \
|
||||
aclk/legacy/agent_cloud_link.c \
|
||||
aclk/legacy/agent_cloud_link.h \
|
||||
aclk/legacy/aclk_query.c \
|
||||
aclk/legacy/aclk_query.h \
|
||||
aclk/legacy/mqtt.c \
|
||||
aclk/legacy/mqtt.h \
|
||||
aclk/legacy/aclk_rx_msgs.c \
|
||||
aclk/legacy/aclk_rx_msgs.h \
|
||||
aclk/legacy/aclk_lws_wss_client.c \
|
||||
aclk/legacy/aclk_lws_wss_client.h \
|
||||
aclk/legacy/aclk_lws_https_client.c \
|
||||
aclk/legacy/aclk_lws_https_client.h \
|
||||
aclk/legacy/aclk_common.c \
|
||||
aclk/legacy/aclk_common.h \
|
||||
aclk/legacy/aclk_stats.c \
|
||||
aclk/legacy/aclk_stats.h \
|
||||
$(NULL)
|
||||
endif #ACLK_LEGACY
|
||||
|
||||
SPAWN_PLUGIN_FILES = \
|
||||
spawn/spawn.c \
|
||||
spawn/spawn_server.c \
|
||||
|
@ -929,8 +896,7 @@ NETDATA_FILES = \
|
|||
$(PARSER_FILES) \
|
||||
$(ACLK_ALWAYS_BUILD_FILES) \
|
||||
$(ACLK_COMMON_FILES) \
|
||||
$(ACLK_LEGACY_FILES) \
|
||||
$(ACLK_NG_FILES) \
|
||||
$(ACLK_FILES) \
|
||||
$(SPAWN_PLUGIN_FILES) \
|
||||
$(NULL)
|
||||
|
||||
|
@ -994,7 +960,7 @@ netdata_LDADD = \
|
|||
$(NETDATA_COMMON_LIBS) \
|
||||
$(NULL)
|
||||
|
||||
if ACLK_NG
|
||||
if ENABLE_ACLK
|
||||
netdata_LDADD += $(OPTIONAL_PROTOBUF_LIBS) \
|
||||
$(OPTIONAL_ATOMIC_LIBS) \
|
||||
$(NULL)
|
||||
|
@ -1005,14 +971,6 @@ if ENABLE_ML_TESTS
|
|||
$(NULL)
|
||||
endif
|
||||
|
||||
if ACLK_LEGACY
|
||||
netdata_LDADD += \
|
||||
$(abs_top_srcdir)/externaldeps/mosquitto/libmosquitto.a \
|
||||
$(OPTIONAL_LWS_LIBS) \
|
||||
$(OPTIONAL_LIBCAP_LIBS) \
|
||||
$(NULL)
|
||||
endif #ACLK_LEGACY
|
||||
|
||||
if ENABLE_CXX_LINKER
|
||||
netdata_LINK = $(CXXLD) $(CXXFLAGS) $(LDFLAGS) -o $@
|
||||
else
|
||||
|
|
12
aclk/aclk.c
12
aclk/aclk.c
|
@ -859,7 +859,7 @@ exit:
|
|||
// fix this in both old and new ACLK
|
||||
extern void health_alarm_entry2json_nolock(BUFFER *wb, ALARM_ENTRY *ae, RRDHOST *host);
|
||||
|
||||
void ng_aclk_alarm_reload(void)
|
||||
void aclk_alarm_reload(void)
|
||||
{
|
||||
ACLK_SHARED_STATE_LOCK;
|
||||
if (unlikely(aclk_shared_state.agent_state == ACLK_HOST_INITIALIZING)) {
|
||||
|
@ -871,7 +871,7 @@ void ng_aclk_alarm_reload(void)
|
|||
aclk_queue_query(aclk_query_new(METADATA_ALARMS));
|
||||
}
|
||||
|
||||
int ng_aclk_update_alarm(RRDHOST *host, ALARM_ENTRY *ae)
|
||||
int aclk_update_alarm(RRDHOST *host, ALARM_ENTRY *ae)
|
||||
{
|
||||
BUFFER *local_buffer;
|
||||
json_object *msg;
|
||||
|
@ -902,7 +902,7 @@ int ng_aclk_update_alarm(RRDHOST *host, ALARM_ENTRY *ae)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int ng_aclk_update_chart(RRDHOST *host, char *chart_name, int create)
|
||||
int aclk_update_chart(RRDHOST *host, char *chart_name, int create)
|
||||
{
|
||||
struct aclk_query *query;
|
||||
|
||||
|
@ -926,7 +926,7 @@ int ng_aclk_update_chart(RRDHOST *host, char *chart_name, int create)
|
|||
* Add a new collector to the list
|
||||
* If it exists, update the chart count
|
||||
*/
|
||||
void ng_aclk_add_collector(RRDHOST *host, const char *plugin_name, const char *module_name)
|
||||
void aclk_add_collector(RRDHOST *host, const char *plugin_name, const char *module_name)
|
||||
{
|
||||
struct aclk_query *query;
|
||||
struct _collector *tmp_collector;
|
||||
|
@ -969,7 +969,7 @@ void ng_aclk_add_collector(RRDHOST *host, const char *plugin_name, const char *m
|
|||
* This function will release the memory used and schedule
|
||||
* a cloud update
|
||||
*/
|
||||
void ng_aclk_del_collector(RRDHOST *host, const char *plugin_name, const char *module_name)
|
||||
void aclk_del_collector(RRDHOST *host, const char *plugin_name, const char *module_name)
|
||||
{
|
||||
struct aclk_query *query;
|
||||
struct _collector *tmp_collector;
|
||||
|
@ -1010,7 +1010,7 @@ void ng_aclk_del_collector(RRDHOST *host, const char *plugin_name, const char *m
|
|||
aclk_queue_query(query);
|
||||
}
|
||||
|
||||
void ng_aclk_host_state_update(RRDHOST *host, int cmd)
|
||||
void aclk_host_state_update(RRDHOST *host, int cmd)
|
||||
{
|
||||
uuid_t node_id;
|
||||
int ret;
|
||||
|
|
12
aclk/aclk.h
12
aclk/aclk.h
|
@ -32,18 +32,18 @@ extern struct aclk_shared_state {
|
|||
int mqtt_shutdown_msg_rcvd;
|
||||
} aclk_shared_state;
|
||||
|
||||
void ng_aclk_alarm_reload(void);
|
||||
int ng_aclk_update_alarm(RRDHOST *host, ALARM_ENTRY *ae);
|
||||
void aclk_alarm_reload(void);
|
||||
int aclk_update_alarm(RRDHOST *host, ALARM_ENTRY *ae);
|
||||
|
||||
/* Informs ACLK about created/deleted chart
|
||||
* @param create 0 - if chart was deleted, other if chart created
|
||||
*/
|
||||
int ng_aclk_update_chart(RRDHOST *host, char *chart_name, int create);
|
||||
int aclk_update_chart(RRDHOST *host, char *chart_name, int create);
|
||||
|
||||
void ng_aclk_add_collector(RRDHOST *host, const char *plugin_name, const char *module_name);
|
||||
void ng_aclk_del_collector(RRDHOST *host, const char *plugin_name, const char *module_name);
|
||||
void aclk_add_collector(RRDHOST *host, const char *plugin_name, const char *module_name);
|
||||
void aclk_del_collector(RRDHOST *host, const char *plugin_name, const char *module_name);
|
||||
|
||||
void ng_aclk_host_state_update(RRDHOST *host, int cmd);
|
||||
void aclk_host_state_update(RRDHOST *host, int cmd);
|
||||
|
||||
void aclk_send_node_instances(void);
|
||||
|
||||
|
|
159
aclk/aclk_api.c
159
aclk/aclk_api.c
|
@ -2,12 +2,9 @@
|
|||
#include "libnetdata/libnetdata.h"
|
||||
#include "database/rrd.h"
|
||||
|
||||
#ifdef ACLK_NG
|
||||
#ifdef ENABLE_ACLK
|
||||
#include "aclk.h"
|
||||
#endif
|
||||
#ifdef ACLK_LEGACY
|
||||
#include "legacy/agent_cloud_link.h"
|
||||
#endif
|
||||
|
||||
int aclk_connected = 0;
|
||||
int aclk_kill_link = 0;
|
||||
|
@ -20,12 +17,6 @@ int aclk_disable_single_updates = 0;
|
|||
|
||||
int aclk_stats_enabled;
|
||||
|
||||
#ifdef ACLK_NG
|
||||
int aclk_ng = 1;
|
||||
#else
|
||||
int aclk_ng = 0;
|
||||
#endif
|
||||
|
||||
#define ACLK_IMPL_KEY_NAME "aclk implementation"
|
||||
|
||||
#ifdef ENABLE_ACLK
|
||||
|
@ -33,41 +24,13 @@ void *aclk_starter(void *ptr) {
|
|||
char *aclk_impl_req = config_get(CONFIG_SECTION_CLOUD, ACLK_IMPL_KEY_NAME, "ng");
|
||||
|
||||
if (!strcasecmp(aclk_impl_req, "ng")) {
|
||||
aclk_ng = 1;
|
||||
} else if (!strcasecmp(aclk_impl_req, "legacy")) {
|
||||
aclk_ng = 0;
|
||||
} else {
|
||||
error("Unknown value \"%s\" of key \"" ACLK_IMPL_KEY_NAME "\" in section \"" CONFIG_SECTION_CLOUD "\". Trying default ACLK %s.", aclk_impl_req, aclk_ng ? "NG" : "Legacy");
|
||||
}
|
||||
|
||||
#ifndef ACLK_NG
|
||||
if (aclk_ng) {
|
||||
error("Configuration requests ACLK-NG but it is not available in this agent. Switching to Legacy.");
|
||||
aclk_ng = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef ACLK_LEGACY
|
||||
if (!aclk_ng) {
|
||||
error("Configuration requests ACLK Legacy but it is not available in this agent. Switching to NG.");
|
||||
aclk_ng = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ACLK_NG
|
||||
if (aclk_ng) {
|
||||
info("Starting ACLK-NG");
|
||||
return aclk_main(ptr);
|
||||
} else if (!strcasecmp(aclk_impl_req, "legacy")) {
|
||||
error("Legacy ACLK is not supported anymore key \"" ACLK_IMPL_KEY_NAME "\" in section \"" CONFIG_SECTION_CLOUD "\" ignored. Using ACLK-NG.");
|
||||
} else {
|
||||
error("Unknown value \"%s\" of key \"" ACLK_IMPL_KEY_NAME "\" in section \"" CONFIG_SECTION_CLOUD "\". Using ACLK-NG. This config key will be deprecated.", aclk_impl_req);
|
||||
}
|
||||
#endif
|
||||
#ifdef ACLK_LEGACY
|
||||
if (!aclk_ng) {
|
||||
info("Starting ACLK Legacy");
|
||||
return legacy_aclk_main(ptr);
|
||||
}
|
||||
#endif
|
||||
error_report("No ACLK could be started");
|
||||
return NULL;
|
||||
return aclk_main(ptr);
|
||||
}
|
||||
|
||||
void aclk_single_update_disable()
|
||||
|
@ -79,99 +42,15 @@ void aclk_single_update_enable()
|
|||
{
|
||||
aclk_disable_single_updates = 0;
|
||||
}
|
||||
|
||||
void aclk_alarm_reload(void)
|
||||
{
|
||||
#ifdef ACLK_NG
|
||||
if (aclk_ng)
|
||||
ng_aclk_alarm_reload();
|
||||
#endif
|
||||
#ifdef ACLK_LEGACY
|
||||
if (!aclk_ng)
|
||||
legacy_aclk_alarm_reload();
|
||||
#endif
|
||||
}
|
||||
|
||||
int aclk_update_chart(RRDHOST *host, char *chart_name, int create)
|
||||
{
|
||||
#ifdef ACLK_NG
|
||||
if (aclk_ng)
|
||||
return ng_aclk_update_chart(host, chart_name, create);
|
||||
#endif
|
||||
#ifdef ACLK_LEGACY
|
||||
if (!aclk_ng)
|
||||
return legacy_aclk_update_chart(host, chart_name, create);
|
||||
#endif
|
||||
error_report("No usable aclk_update_chart implementation");
|
||||
return 1;
|
||||
}
|
||||
|
||||
int aclk_update_alarm(RRDHOST *host, ALARM_ENTRY *ae)
|
||||
{
|
||||
#ifdef ACLK_NG
|
||||
if (aclk_ng)
|
||||
return ng_aclk_update_alarm(host, ae);
|
||||
#endif
|
||||
#ifdef ACLK_LEGACY
|
||||
if (!aclk_ng)
|
||||
return legacy_aclk_update_alarm(host, ae);
|
||||
#endif
|
||||
error_report("No usable aclk_update_alarm implementation");
|
||||
return 1;
|
||||
}
|
||||
|
||||
void aclk_add_collector(RRDHOST *host, const char *plugin_name, const char *module_name)
|
||||
{
|
||||
#ifdef ACLK_NG
|
||||
if (aclk_ng)
|
||||
return ng_aclk_add_collector(host, plugin_name, module_name);
|
||||
#endif
|
||||
#ifdef ACLK_LEGACY
|
||||
if (!aclk_ng)
|
||||
return legacy_aclk_add_collector(host, plugin_name, module_name);
|
||||
#endif
|
||||
error_report("No usable aclk_add_collector implementation");
|
||||
}
|
||||
|
||||
void aclk_del_collector(RRDHOST *host, const char *plugin_name, const char *module_name)
|
||||
{
|
||||
#ifdef ACLK_NG
|
||||
if (aclk_ng)
|
||||
return ng_aclk_del_collector(host, plugin_name, module_name);
|
||||
#endif
|
||||
#ifdef ACLK_LEGACY
|
||||
if (!aclk_ng)
|
||||
return legacy_aclk_del_collector(host, plugin_name, module_name);
|
||||
#endif
|
||||
error_report("No usable aclk_del_collector implementation");
|
||||
}
|
||||
|
||||
void aclk_host_state_update(RRDHOST *host, int connect)
|
||||
{
|
||||
#ifdef ACLK_NG
|
||||
if (aclk_ng)
|
||||
return ng_aclk_host_state_update(host, connect);
|
||||
#endif
|
||||
#ifdef ACLK_LEGACY
|
||||
if (!aclk_ng)
|
||||
return legacy_aclk_host_state_update(host, connect);
|
||||
#endif
|
||||
error_report("Couldn't use any version of aclk_host_state_update");
|
||||
}
|
||||
|
||||
#endif /* ENABLE_ACLK */
|
||||
|
||||
struct label *add_aclk_host_labels(struct label *label) {
|
||||
#ifdef ACLK_NG
|
||||
#ifdef ENABLE_ACLK
|
||||
label = add_label_to_list(label, "_aclk_ng_available", "true", LABEL_SOURCE_AUTO);
|
||||
#else
|
||||
label = add_label_to_list(label, "_aclk_ng_available", "false", LABEL_SOURCE_AUTO);
|
||||
#endif
|
||||
#ifdef ACLK_LEGACY
|
||||
label = add_label_to_list(label, "_aclk_legacy_available", "true", LABEL_SOURCE_AUTO);
|
||||
#else
|
||||
label = add_label_to_list(label, "_aclk_legacy_available", "false", LABEL_SOURCE_AUTO);
|
||||
#endif
|
||||
#ifdef ENABLE_ACLK
|
||||
ACLK_PROXY_TYPE aclk_proxy;
|
||||
char *proxy_str;
|
||||
|
@ -189,7 +68,7 @@ struct label *add_aclk_host_labels(struct label *label) {
|
|||
break;
|
||||
}
|
||||
|
||||
label = add_label_to_list(label, "_aclk_impl", aclk_ng ? "Next Generation" : "Legacy", LABEL_SOURCE_AUTO);
|
||||
label = add_label_to_list(label, "_aclk_impl", "Next Generation", LABEL_SOURCE_AUTO);
|
||||
label = add_label_to_list(label, "_aclk_proxy", proxy_str, LABEL_SOURCE_AUTO);
|
||||
#endif
|
||||
return label;
|
||||
|
@ -199,30 +78,14 @@ char *aclk_state(void) {
|
|||
#ifndef ENABLE_ACLK
|
||||
return strdupz("ACLK Available: No");
|
||||
#else
|
||||
#ifdef ACLK_NG
|
||||
if (aclk_ng)
|
||||
return ng_aclk_state();
|
||||
return ng_aclk_state();
|
||||
#endif
|
||||
#ifdef ACLK_LEGACY
|
||||
if (!aclk_ng)
|
||||
return legacy_aclk_state();
|
||||
#endif
|
||||
#endif /* ENABLE_ACLK */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *aclk_state_json(void) {
|
||||
#ifndef ENABLE_ACLK
|
||||
return strdupz("{\"aclk-available\": false}");
|
||||
return strdupz("{\"aclk-available\":false}");
|
||||
#else
|
||||
#ifdef ACLK_NG
|
||||
if (aclk_ng)
|
||||
return ng_aclk_state_json();
|
||||
return ng_aclk_state_json();
|
||||
#endif
|
||||
#ifdef ACLK_LEGACY
|
||||
if (!aclk_ng)
|
||||
return legacy_aclk_state_json();
|
||||
#endif
|
||||
#endif /* ENABLE_ACLK */
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
AUTOMAKE_OPTIONS = subdir-objects
|
||||
MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
|
||||
|
||||
CLEANFILES = \
|
||||
tests/install-fake-charts.d.sh \
|
||||
$(NULL)
|
||||
|
||||
include $(top_srcdir)/build/subst.inc
|
||||
SUFFIXES = .in
|
||||
|
||||
#sbin_SCRIPTS = \
|
||||
# tests/install-fake-charts.d.sh \
|
||||
# $(NULL)
|
||||
|
||||
dist_noinst_SCRIPTS = tests/install-fake-charts.d.sh
|
||||
dist_noinst_DATA = tests/install-fake-charts.d.sh.in
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
#include "aclk_common.h"
|
||||
|
||||
#include "daemon/common.h"
|
||||
|
||||
#ifdef ENABLE_ACLK
|
||||
#include <libwebsockets.h>
|
||||
#endif
|
||||
|
||||
netdata_mutex_t legacy_aclk_shared_state_mutex = NETDATA_MUTEX_INITIALIZER;
|
||||
|
||||
struct legacy_aclk_shared_state legacy_aclk_shared_state = {
|
||||
.version_neg = 0,
|
||||
.version_neg_wait_till = 0
|
||||
};
|
||||
|
||||
int aclk_decode_base_url(char *url, char **aclk_hostname, int *aclk_port)
|
||||
{
|
||||
int pos = 0;
|
||||
if (!strncmp("https://", url, 8)) {
|
||||
pos = 8;
|
||||
} else if (!strncmp("http://", url, 7)) {
|
||||
error("Cannot connect ACLK over %s -> unencrypted link is not supported", url);
|
||||
return 1;
|
||||
}
|
||||
int host_end = pos;
|
||||
while (url[host_end] != 0 && url[host_end] != '/' && url[host_end] != ':')
|
||||
host_end++;
|
||||
if (url[host_end] == 0) {
|
||||
*aclk_hostname = strdupz(url + pos);
|
||||
*aclk_port = 443;
|
||||
info("Setting ACLK target host=%s port=%d from %s", *aclk_hostname, *aclk_port, url);
|
||||
return 0;
|
||||
}
|
||||
if (url[host_end] == ':') {
|
||||
*aclk_hostname = callocz(host_end - pos + 1, 1);
|
||||
strncpy(*aclk_hostname, url + pos, host_end - pos);
|
||||
int port_end = host_end + 1;
|
||||
while (url[port_end] >= '0' && url[port_end] <= '9')
|
||||
port_end++;
|
||||
if (port_end - host_end > 6) {
|
||||
error("Port specified in %s is invalid", url);
|
||||
return 0;
|
||||
}
|
||||
*aclk_port = atoi(&url[host_end+1]);
|
||||
}
|
||||
if (url[host_end] == '/') {
|
||||
*aclk_port = 443;
|
||||
*aclk_hostname = callocz(1, host_end - pos + 1);
|
||||
strncpy(*aclk_hostname, url+pos, host_end - pos);
|
||||
}
|
||||
info("Setting ACLK target host=%s port=%d from %s", *aclk_hostname, *aclk_port, url);
|
||||
return 0;
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
#ifndef ACLK_COMMON_H
|
||||
#define ACLK_COMMON_H
|
||||
|
||||
#include "../aclk_rrdhost_state.h"
|
||||
#include "daemon/common.h"
|
||||
|
||||
extern netdata_mutex_t legacy_aclk_shared_state_mutex;
|
||||
#define legacy_aclk_shared_state_LOCK netdata_mutex_lock(&legacy_aclk_shared_state_mutex)
|
||||
#define legacy_aclk_shared_state_UNLOCK netdata_mutex_unlock(&legacy_aclk_shared_state_mutex)
|
||||
|
||||
// minimum and maximum supported version of ACLK
|
||||
// in this version of agent
|
||||
#define ACLK_VERSION_MIN 2
|
||||
#define ACLK_VERSION_MAX 3
|
||||
|
||||
// Version negotiation messages have they own versioning
|
||||
// this is also used for LWT message as we set that up
|
||||
// before version negotiation
|
||||
#define ACLK_VERSION_NEG_VERSION 1
|
||||
|
||||
// Maximum time to wait for version negotiation before aborting
|
||||
// and defaulting to oldest supported version
|
||||
#define VERSION_NEG_TIMEOUT 3
|
||||
|
||||
#if ACLK_VERSION_MIN > ACLK_VERSION_MAX
|
||||
#error "ACLK_VERSION_MAX must be >= than ACLK_VERSION_MIN"
|
||||
#endif
|
||||
|
||||
// Define ACLK Feature Version Boundaries Here
|
||||
#define ACLK_V_COMPRESSION 2
|
||||
#define ACLK_V_CHILDRENSTATE 3
|
||||
|
||||
#define ACLK_IS_HOST_INITIALIZING(host) (host->aclk_state.state == ACLK_HOST_INITIALIZING)
|
||||
#define ACLK_IS_HOST_POPCORNING(host) (ACLK_IS_HOST_INITIALIZING(host) && host->aclk_state.t_last_popcorn_update)
|
||||
|
||||
extern struct legacy_aclk_shared_state {
|
||||
// optimization to avoid looping through hosts
|
||||
// every time Query Thread wakes up
|
||||
RRDHOST *next_popcorn_host;
|
||||
|
||||
// read only while ACLK connected
|
||||
// protect by lock otherwise
|
||||
int version_neg;
|
||||
usec_t version_neg_wait_till;
|
||||
} legacy_aclk_shared_state;
|
||||
|
||||
const char *aclk_proxy_type_to_s(ACLK_PROXY_TYPE *type);
|
||||
|
||||
int aclk_decode_base_url(char *url, char **aclk_hostname, int *aclk_port);
|
||||
|
||||
#endif //ACLK_COMMON_H
|
|
@ -1,244 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#define ACLK_LWS_HTTPS_CLIENT_INTERNAL
|
||||
#include "aclk_lws_https_client.h"
|
||||
#include "aclk_common.h"
|
||||
#include "aclk_lws_wss_client.h"
|
||||
|
||||
#define SMALL_BUFFER 16
|
||||
|
||||
struct simple_hcc_data {
|
||||
char *data;
|
||||
size_t data_size;
|
||||
size_t written;
|
||||
char lws_work_buffer[1024 + LWS_PRE];
|
||||
char *payload;
|
||||
int response_code;
|
||||
int done;
|
||||
};
|
||||
|
||||
static int simple_https_client_callback(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len)
|
||||
{
|
||||
UNUSED(user);
|
||||
int n;
|
||||
char *ptr;
|
||||
char buffer[SMALL_BUFFER];
|
||||
struct simple_hcc_data *perconn_data = lws_get_opaque_user_data(wsi);
|
||||
|
||||
switch (reason) {
|
||||
case LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ:
|
||||
debug(D_ACLK, "LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ");
|
||||
if (perconn_data->data_size - 1 - perconn_data->written < len)
|
||||
return 1;
|
||||
memcpy(&perconn_data->data[perconn_data->written], in, len);
|
||||
perconn_data->written += len;
|
||||
return 0;
|
||||
case LWS_CALLBACK_RECEIVE_CLIENT_HTTP:
|
||||
debug(D_ACLK, "LWS_CALLBACK_RECEIVE_CLIENT_HTTP");
|
||||
if(!perconn_data) {
|
||||
error("Missing Per Connect Data");
|
||||
return -1;
|
||||
}
|
||||
n = sizeof(perconn_data->lws_work_buffer) - LWS_PRE;
|
||||
ptr = perconn_data->lws_work_buffer + LWS_PRE;
|
||||
if (lws_http_client_read(wsi, &ptr, &n) < 0)
|
||||
return -1;
|
||||
perconn_data->data[perconn_data->written] = '\0';
|
||||
return 0;
|
||||
case LWS_CALLBACK_WSI_DESTROY:
|
||||
debug(D_ACLK, "LWS_CALLBACK_WSI_DESTROY");
|
||||
if(perconn_data)
|
||||
perconn_data->done = 1;
|
||||
return 0;
|
||||
case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP:
|
||||
debug(D_ACLK, "LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP");
|
||||
if(perconn_data)
|
||||
perconn_data->response_code = lws_http_client_http_response(wsi);
|
||||
return 0;
|
||||
case LWS_CALLBACK_CLOSED_CLIENT_HTTP:
|
||||
debug(D_ACLK, "LWS_CALLBACK_CLOSED_CLIENT_HTTP");
|
||||
return 0;
|
||||
case LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS:
|
||||
debug(D_ACLK, "LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS");
|
||||
return 0;
|
||||
case LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER:
|
||||
debug(D_ACLK, "LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER");
|
||||
if(perconn_data && perconn_data->payload) {
|
||||
unsigned char **p = (unsigned char **)in, *end = (*p) + len;
|
||||
snprintfz(buffer, SMALL_BUFFER, "%zu", strlen(perconn_data->payload));
|
||||
if (lws_add_http_header_by_token(wsi,
|
||||
WSI_TOKEN_HTTP_CONTENT_LENGTH,
|
||||
(unsigned char *)buffer, strlen(buffer), p, end))
|
||||
return -1;
|
||||
if (lws_add_http_header_by_token(wsi,
|
||||
WSI_TOKEN_HTTP_CONTENT_TYPE,
|
||||
(unsigned char *)ACLK_CONTENT_TYPE_JSON,
|
||||
strlen(ACLK_CONTENT_TYPE_JSON), p, end))
|
||||
return -1;
|
||||
lws_client_http_body_pending(wsi, 1);
|
||||
lws_callback_on_writable(wsi);
|
||||
}
|
||||
return 0;
|
||||
case LWS_CALLBACK_CLIENT_HTTP_WRITEABLE:
|
||||
debug(D_ACLK, "LWS_CALLBACK_CLIENT_HTTP_WRITEABLE");
|
||||
if(perconn_data && perconn_data->payload) {
|
||||
n = strlen(perconn_data->payload);
|
||||
if(perconn_data->data_size < (size_t)LWS_PRE + n + 1) {
|
||||
error("Buffer given is not big enough");
|
||||
return 1;
|
||||
}
|
||||
|
||||
memcpy(&perconn_data->data[LWS_PRE], perconn_data->payload, n);
|
||||
if(n != lws_write(wsi, (unsigned char*)&perconn_data->data[LWS_PRE], n, LWS_WRITE_HTTP)) {
|
||||
error("lws_write error");
|
||||
perconn_data->data[0] = 0;
|
||||
return 1;
|
||||
}
|
||||
lws_client_http_body_pending(wsi, 0);
|
||||
// clean for subsequent reply read
|
||||
perconn_data->data[0] = 0;
|
||||
}
|
||||
return 0;
|
||||
case LWS_CALLBACK_CLIENT_HTTP_BIND_PROTOCOL:
|
||||
debug(D_ACLK, "LWS_CALLBACK_CLIENT_HTTP_BIND_PROTOCOL");
|
||||
return 0;
|
||||
case LWS_CALLBACK_WSI_CREATE:
|
||||
debug(D_ACLK, "LWS_CALLBACK_WSI_CREATE");
|
||||
return 0;
|
||||
case LWS_CALLBACK_PROTOCOL_INIT:
|
||||
debug(D_ACLK, "LWS_CALLBACK_PROTOCOL_INIT");
|
||||
return 0;
|
||||
case LWS_CALLBACK_CLIENT_HTTP_DROP_PROTOCOL:
|
||||
debug(D_ACLK, "LWS_CALLBACK_CLIENT_HTTP_DROP_PROTOCOL");
|
||||
return 0;
|
||||
case LWS_CALLBACK_SERVER_NEW_CLIENT_INSTANTIATED:
|
||||
debug(D_ACLK, "LWS_CALLBACK_SERVER_NEW_CLIENT_INSTANTIATED");
|
||||
return 0;
|
||||
case LWS_CALLBACK_GET_THREAD_ID:
|
||||
debug(D_ACLK, "LWS_CALLBACK_GET_THREAD_ID");
|
||||
return 0;
|
||||
case LWS_CALLBACK_EVENT_WAIT_CANCELLED:
|
||||
debug(D_ACLK, "LWS_CALLBACK_EVENT_WAIT_CANCELLED");
|
||||
return 0;
|
||||
case LWS_CALLBACK_OPENSSL_PERFORM_SERVER_CERT_VERIFICATION:
|
||||
debug(D_ACLK, "LWS_CALLBACK_OPENSSL_PERFORM_SERVER_CERT_VERIFICATION");
|
||||
return 0;
|
||||
case LWS_CALLBACK_CLIENT_FILTER_PRE_ESTABLISH:
|
||||
debug(D_ACLK, "LWS_CALLBACK_CLIENT_FILTER_PRE_ESTABLISH");
|
||||
return 0;
|
||||
default:
|
||||
debug(D_ACLK, "Unknown callback %d", (int)reason);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct lws_protocols protocols[] = {
|
||||
{
|
||||
"http",
|
||||
simple_https_client_callback,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
},
|
||||
{ NULL, NULL, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
static void simple_hcc_log_divert(int level, const char *line)
|
||||
{
|
||||
UNUSED(level);
|
||||
error("Libwebsockets: %s", line);
|
||||
}
|
||||
|
||||
int aclk_send_https_request(char *method, char *host, int port, char *url, char *b, size_t b_size, char *payload)
|
||||
{
|
||||
info("%s %s", __func__, method);
|
||||
|
||||
struct lws_context_creation_info info;
|
||||
struct lws_client_connect_info i;
|
||||
struct lws_context *context;
|
||||
|
||||
struct simple_hcc_data *data = callocz(1, sizeof(struct simple_hcc_data));
|
||||
data->data = b;
|
||||
data->data[0] = 0;
|
||||
data->data_size = b_size;
|
||||
data->payload = payload;
|
||||
|
||||
int n = 0;
|
||||
time_t timestamp;
|
||||
|
||||
struct lws_vhost *vhost;
|
||||
|
||||
memset(&info, 0, sizeof info);
|
||||
|
||||
info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
|
||||
info.port = CONTEXT_PORT_NO_LISTEN;
|
||||
info.protocols = protocols;
|
||||
|
||||
|
||||
context = lws_create_context(&info);
|
||||
if (!context) {
|
||||
error("Error creating LWS context");
|
||||
freez(data);
|
||||
return 1;
|
||||
}
|
||||
|
||||
lws_set_log_level(LLL_ERR | LLL_WARN, simple_hcc_log_divert);
|
||||
|
||||
lws_service(context, 0);
|
||||
|
||||
memset(&i, 0, sizeof i); /* otherwise uninitialized garbage */
|
||||
i.context = context;
|
||||
|
||||
#ifdef ACLK_SSL_ALLOW_SELF_SIGNED
|
||||
i.ssl_connection = LCCSCF_USE_SSL | LCCSCF_ALLOW_SELFSIGNED | LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK | LCCSCF_ALLOW_INSECURE;
|
||||
info("Disabling SSL certificate checks");
|
||||
#else
|
||||
i.ssl_connection = LCCSCF_USE_SSL;
|
||||
#endif
|
||||
#if defined(HAVE_X509_VERIFY_PARAM_set1_host) && HAVE_X509_VERIFY_PARAM_set1_host == 0
|
||||
#warning DISABLING SSL HOSTNAME VALIDATION BECAUSE IT IS NOT AVAILABLE ON THIS SYSTEM.
|
||||
i.ssl_connection |= LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK;
|
||||
#endif
|
||||
|
||||
i.port = port;
|
||||
i.address = host;
|
||||
i.path = url;
|
||||
|
||||
i.host = i.address;
|
||||
i.origin = i.address;
|
||||
i.method = method;
|
||||
i.opaque_user_data = data;
|
||||
i.alpn = "http/1.1";
|
||||
|
||||
i.protocol = protocols[0].name;
|
||||
|
||||
vhost = lws_get_vhost_by_name(context, "default");
|
||||
if(!vhost)
|
||||
fatal("Could not find the default LWS vhost.");
|
||||
|
||||
//set up proxy
|
||||
aclk_wss_set_proxy(vhost);
|
||||
|
||||
lws_client_connect_via_info(&i);
|
||||
|
||||
// libwebsockets handle connection timeouts already
|
||||
// this adds additional safety in case of bug in LWS
|
||||
timestamp = now_monotonic_sec();
|
||||
while( n >= 0 && !data->done && !netdata_exit) {
|
||||
n = lws_service(context, 0);
|
||||
if( now_monotonic_sec() - timestamp > SEND_HTTPS_REQUEST_TIMEOUT ) {
|
||||
data->data[0] = 0;
|
||||
data->done = 1;
|
||||
error("Servicing LWS took too long.");
|
||||
}
|
||||
}
|
||||
|
||||
lws_context_destroy(context);
|
||||
|
||||
n = data->response_code;
|
||||
|
||||
freez(data);
|
||||
return (n < 200 || n >= 300);
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#ifndef NETDATA_LWS_HTTPS_CLIENT_H
|
||||
#define NETDATA_LWS_HTTPS_CLIENT_H
|
||||
|
||||
#include "daemon/common.h"
|
||||
#include "libnetdata/libnetdata.h"
|
||||
|
||||
#define DATAMAXLEN 1024*16
|
||||
|
||||
#ifdef ACLK_LWS_HTTPS_CLIENT_INTERNAL
|
||||
#define ACLK_CONTENT_TYPE_JSON "application/json"
|
||||
#define SEND_HTTPS_REQUEST_TIMEOUT 30
|
||||
#endif
|
||||
|
||||
int aclk_send_https_request(char *method, char *host, int port, char *url, char *b, size_t b_size, char *payload);
|
||||
|
||||
#endif /* NETDATA_LWS_HTTPS_CLIENT_H */
|
|
@ -1,622 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include "aclk_lws_wss_client.h"
|
||||
|
||||
#include "libnetdata/libnetdata.h"
|
||||
#include "daemon/common.h"
|
||||
#include "aclk_common.h"
|
||||
#include "aclk_stats.h"
|
||||
#include "../aclk_proxy.h"
|
||||
|
||||
extern int aclk_shutting_down;
|
||||
|
||||
static int aclk_lws_wss_callback(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len);
|
||||
|
||||
struct aclk_lws_wss_perconnect_data {
|
||||
int todo;
|
||||
};
|
||||
|
||||
static struct aclk_lws_wss_engine_instance *engine_instance = NULL;
|
||||
|
||||
void lws_wss_check_queues(size_t *write_len, size_t *write_len_bytes, size_t *read_len)
|
||||
{
|
||||
if (write_len != NULL && write_len_bytes != NULL)
|
||||
{
|
||||
*write_len = 0;
|
||||
*write_len_bytes = 0;
|
||||
if (engine_instance != NULL)
|
||||
{
|
||||
aclk_lws_mutex_lock(&engine_instance->write_buf_mutex);
|
||||
|
||||
struct lws_wss_packet_buffer *write_b;
|
||||
size_t w,wb;
|
||||
for(w=0, wb=0, write_b = engine_instance->write_buffer_head; write_b != NULL; write_b = write_b->next)
|
||||
{
|
||||
w++;
|
||||
wb += write_b->data_size - write_b->written;
|
||||
}
|
||||
*write_len = w;
|
||||
*write_len_bytes = wb;
|
||||
aclk_lws_mutex_unlock(&engine_instance->write_buf_mutex);
|
||||
}
|
||||
}
|
||||
else if (write_len != NULL)
|
||||
{
|
||||
*write_len = 0;
|
||||
if (engine_instance != NULL)
|
||||
{
|
||||
aclk_lws_mutex_lock(&engine_instance->write_buf_mutex);
|
||||
|
||||
struct lws_wss_packet_buffer *write_b;
|
||||
size_t w;
|
||||
for(w=0, write_b = engine_instance->write_buffer_head; write_b != NULL; write_b = write_b->next)
|
||||
w++;
|
||||
*write_len = w;
|
||||
aclk_lws_mutex_unlock(&engine_instance->write_buf_mutex);
|
||||
}
|
||||
}
|
||||
if (read_len != NULL)
|
||||
{
|
||||
*read_len = 0;
|
||||
if (engine_instance != NULL)
|
||||
{
|
||||
aclk_lws_mutex_lock(&engine_instance->read_buf_mutex);
|
||||
*read_len = lws_ring_get_count_waiting_elements(engine_instance->read_ringbuffer, NULL);
|
||||
aclk_lws_mutex_unlock(&engine_instance->read_buf_mutex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline struct lws_wss_packet_buffer *lws_wss_packet_buffer_new(void *data, size_t size)
|
||||
{
|
||||
struct lws_wss_packet_buffer *new = callocz(1, sizeof(struct lws_wss_packet_buffer));
|
||||
if (data) {
|
||||
new->data = mallocz(LWS_PRE + size);
|
||||
memcpy(new->data + LWS_PRE, data, size);
|
||||
new->data_size = size;
|
||||
new->written = 0;
|
||||
}
|
||||
return new;
|
||||
}
|
||||
|
||||
static inline void lws_wss_packet_buffer_append(struct lws_wss_packet_buffer **list, struct lws_wss_packet_buffer *item)
|
||||
{
|
||||
struct lws_wss_packet_buffer *tail = *list;
|
||||
if (!*list) {
|
||||
*list = item;
|
||||
return;
|
||||
}
|
||||
while (tail->next) {
|
||||
tail = tail->next;
|
||||
}
|
||||
tail->next = item;
|
||||
}
|
||||
|
||||
static inline struct lws_wss_packet_buffer *lws_wss_packet_buffer_pop(struct lws_wss_packet_buffer **list)
|
||||
{
|
||||
struct lws_wss_packet_buffer *ret = *list;
|
||||
if (ret != NULL)
|
||||
*list = ret->next;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void lws_wss_packet_buffer_free(struct lws_wss_packet_buffer *item)
|
||||
{
|
||||
freez(item->data);
|
||||
freez(item);
|
||||
}
|
||||
|
||||
static inline void _aclk_lws_wss_read_buffer_clear(struct lws_ring *ringbuffer)
|
||||
{
|
||||
size_t elems = lws_ring_get_count_waiting_elements(ringbuffer, NULL);
|
||||
if (elems > 0)
|
||||
lws_ring_consume(ringbuffer, NULL, NULL, elems);
|
||||
}
|
||||
|
||||
static inline void _aclk_lws_wss_write_buffer_clear(struct lws_wss_packet_buffer **list)
|
||||
{
|
||||
struct lws_wss_packet_buffer *i;
|
||||
while ((i = lws_wss_packet_buffer_pop(list)) != NULL) {
|
||||
lws_wss_packet_buffer_free(i);
|
||||
}
|
||||
*list = NULL;
|
||||
}
|
||||
|
||||
static inline void aclk_lws_wss_clear_io_buffers()
|
||||
{
|
||||
aclk_lws_mutex_lock(&engine_instance->read_buf_mutex);
|
||||
_aclk_lws_wss_read_buffer_clear(engine_instance->read_ringbuffer);
|
||||
aclk_lws_mutex_unlock(&engine_instance->read_buf_mutex);
|
||||
aclk_lws_mutex_lock(&engine_instance->write_buf_mutex);
|
||||
_aclk_lws_wss_write_buffer_clear(&engine_instance->write_buffer_head);
|
||||
aclk_lws_mutex_unlock(&engine_instance->write_buf_mutex);
|
||||
}
|
||||
|
||||
static const struct lws_protocols protocols[] = { { "aclk-wss", aclk_lws_wss_callback,
|
||||
sizeof(struct aclk_lws_wss_perconnect_data), 32768*4, 0, 0, 32768*4 },
|
||||
{ NULL, NULL, 0, 0, 0, 0, 0 } };
|
||||
|
||||
static void aclk_lws_wss_log_divert(int level, const char *line)
|
||||
{
|
||||
switch (level) {
|
||||
case LLL_ERR:
|
||||
error("Libwebsockets Error: %s", line);
|
||||
break;
|
||||
case LLL_WARN:
|
||||
debug(D_ACLK, "Libwebsockets Warn: %s", line);
|
||||
break;
|
||||
default:
|
||||
error("Libwebsockets try to log with unknown log level (%d), msg: %s", level, line);
|
||||
}
|
||||
}
|
||||
|
||||
static int aclk_lws_wss_client_init( char *target_hostname, int target_port)
|
||||
{
|
||||
static int lws_logging_initialized = 0;
|
||||
|
||||
if (unlikely(!lws_logging_initialized)) {
|
||||
lws_set_log_level(LLL_ERR | LLL_WARN, aclk_lws_wss_log_divert);
|
||||
lws_logging_initialized = 1;
|
||||
}
|
||||
|
||||
if (!target_hostname)
|
||||
return 1;
|
||||
|
||||
engine_instance = callocz(1, sizeof(struct aclk_lws_wss_engine_instance));
|
||||
|
||||
engine_instance->host = target_hostname;
|
||||
engine_instance->port = target_port;
|
||||
|
||||
|
||||
aclk_lws_mutex_init(&engine_instance->write_buf_mutex);
|
||||
aclk_lws_mutex_init(&engine_instance->read_buf_mutex);
|
||||
|
||||
engine_instance->read_ringbuffer = lws_ring_create(1, ACLK_LWS_WSS_RECV_BUFF_SIZE_BYTES, NULL);
|
||||
if (!engine_instance->read_ringbuffer)
|
||||
goto failure_cleanup;
|
||||
|
||||
return 0;
|
||||
|
||||
failure_cleanup:
|
||||
freez(engine_instance);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void aclk_lws_wss_destroy_context()
|
||||
{
|
||||
if (!engine_instance)
|
||||
return;
|
||||
if (!engine_instance->lws_context)
|
||||
return;
|
||||
lws_context_destroy(engine_instance->lws_context);
|
||||
engine_instance->lws_context = NULL;
|
||||
}
|
||||
|
||||
|
||||
void aclk_lws_wss_client_destroy()
|
||||
{
|
||||
if (engine_instance == NULL)
|
||||
return;
|
||||
|
||||
aclk_lws_wss_destroy_context();
|
||||
engine_instance->lws_wsi = NULL;
|
||||
|
||||
aclk_lws_wss_clear_io_buffers();
|
||||
|
||||
#ifdef ACLK_LWS_MOSQUITTO_IO_CALLS_MULTITHREADED
|
||||
pthread_mutex_destroy(&engine_instance->write_buf_mutex);
|
||||
pthread_mutex_destroy(&engine_instance->read_buf_mutex);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef LWS_WITH_SOCKS5
|
||||
static int aclk_wss_set_socks(struct lws_vhost *vhost, const char *socks)
|
||||
{
|
||||
char *proxy = strstr(socks, ACLK_PROXY_PROTO_ADDR_SEPARATOR);
|
||||
|
||||
if (!proxy)
|
||||
return -1;
|
||||
|
||||
proxy += strlen(ACLK_PROXY_PROTO_ADDR_SEPARATOR);
|
||||
|
||||
if (!*proxy)
|
||||
return -1;
|
||||
|
||||
return lws_set_socks(vhost, proxy);
|
||||
}
|
||||
#endif
|
||||
|
||||
void aclk_wss_set_proxy(struct lws_vhost *vhost)
|
||||
{
|
||||
const char *proxy;
|
||||
ACLK_PROXY_TYPE proxy_type;
|
||||
char *log;
|
||||
|
||||
proxy = aclk_get_proxy(&proxy_type);
|
||||
|
||||
#ifdef LWS_WITH_SOCKS5
|
||||
lws_set_socks(vhost, ":");
|
||||
#endif
|
||||
lws_set_proxy(vhost, ":");
|
||||
|
||||
if (proxy_type == PROXY_TYPE_UNKNOWN) {
|
||||
error("Unknown proxy type");
|
||||
return;
|
||||
}
|
||||
|
||||
if (proxy_type == PROXY_TYPE_SOCKS5 || proxy_type == PROXY_TYPE_HTTP) {
|
||||
log = strdupz(proxy);
|
||||
safe_log_proxy_censor(log);
|
||||
info("Connecting using %s proxy:\"%s\"", aclk_proxy_type_to_s(&proxy_type), log);
|
||||
freez(log);
|
||||
}
|
||||
if (proxy_type == PROXY_TYPE_SOCKS5) {
|
||||
#ifdef LWS_WITH_SOCKS5
|
||||
if (aclk_wss_set_socks(vhost, proxy))
|
||||
error("LWS failed to accept socks proxy.");
|
||||
return;
|
||||
#else
|
||||
fatal("We have no SOCKS5 support but we made it here. Programming error!");
|
||||
#endif
|
||||
}
|
||||
if (proxy_type == PROXY_TYPE_HTTP) {
|
||||
if (lws_set_proxy(vhost, proxy))
|
||||
error("LWS failed to accept http proxy.");
|
||||
return;
|
||||
}
|
||||
if (proxy_type != PROXY_DISABLED)
|
||||
error("Unknown proxy type");
|
||||
}
|
||||
|
||||
// Return code indicates if connection attempt has started async.
|
||||
int aclk_lws_wss_connect(char *host, int port)
|
||||
{
|
||||
struct lws_client_connect_info i;
|
||||
struct lws_vhost *vhost;
|
||||
int n;
|
||||
|
||||
if (!engine_instance) {
|
||||
if (aclk_lws_wss_client_init(host, port))
|
||||
return 1; // Propagate failure
|
||||
}
|
||||
|
||||
if (!engine_instance->lws_context)
|
||||
{
|
||||
// First time through (on this connection), create the context
|
||||
struct lws_context_creation_info info;
|
||||
memset(&info, 0, sizeof(struct lws_context_creation_info));
|
||||
info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
|
||||
info.port = CONTEXT_PORT_NO_LISTEN;
|
||||
info.protocols = protocols;
|
||||
engine_instance->lws_context = lws_create_context(&info);
|
||||
if (!engine_instance->lws_context)
|
||||
{
|
||||
error("Failed to create lws_context, ACLK will not function");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
// PROTOCOL_INIT callback will call again.
|
||||
}
|
||||
|
||||
for (n = 0; n < ACLK_LWS_CALLBACK_HISTORY; n++)
|
||||
engine_instance->lws_callback_history[n] = 0;
|
||||
|
||||
if (engine_instance->lws_wsi) {
|
||||
error("Already Connected. Only one connection supported at a time.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(&i, 0, sizeof(i));
|
||||
i.context = engine_instance->lws_context;
|
||||
i.port = engine_instance->port;
|
||||
i.address = engine_instance->host;
|
||||
i.path = "/mqtt";
|
||||
i.host = engine_instance->host;
|
||||
i.protocol = "mqtt";
|
||||
|
||||
// from LWS docu:
|
||||
// If option LWS_SERVER_OPTION_EXPLICIT_VHOSTS is given, no vhost is
|
||||
// created; you're expected to create your own vhosts afterwards using
|
||||
// lws_create_vhost(). Otherwise a vhost named "default" is also created
|
||||
// using the information in the vhost-related members, for compatibility.
|
||||
vhost = lws_get_vhost_by_name(engine_instance->lws_context, "default");
|
||||
if(!vhost)
|
||||
fatal("Could not find the default LWS vhost.");
|
||||
|
||||
aclk_wss_set_proxy(vhost);
|
||||
|
||||
#ifdef ACLK_SSL_ALLOW_SELF_SIGNED
|
||||
i.ssl_connection = LCCSCF_USE_SSL | LCCSCF_ALLOW_SELFSIGNED | LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK | LCCSCF_ALLOW_INSECURE;
|
||||
info("Disabling SSL certificate checks");
|
||||
#else
|
||||
i.ssl_connection = LCCSCF_USE_SSL;
|
||||
#endif
|
||||
#if defined(HAVE_X509_VERIFY_PARAM_set1_host) && HAVE_X509_VERIFY_PARAM_set1_host == 0
|
||||
#warning DISABLING SSL HOSTNAME VALIDATION BECAUSE IT IS NOT AVAILABLE ON THIS SYSTEM.
|
||||
i.ssl_connection |= LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK;
|
||||
#endif
|
||||
lws_client_connect_via_info(&i);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int received_data_to_ringbuff(struct lws_ring *buffer, void *data, size_t len)
|
||||
{
|
||||
if (lws_ring_insert(buffer, data, len) != len) {
|
||||
error("ACLK_LWS_WSS_CLIENT: receive buffer full. Closing connection to prevent flooding.");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef ACLK_TRP_DEBUG_VERBOSE
|
||||
static const char *aclk_lws_callback_name(enum lws_callback_reasons reason)
|
||||
{
|
||||
switch (reason) {
|
||||
case LWS_CALLBACK_CLIENT_WRITEABLE:
|
||||
return "LWS_CALLBACK_CLIENT_WRITEABLE";
|
||||
case LWS_CALLBACK_CLIENT_RECEIVE:
|
||||
return "LWS_CALLBACK_CLIENT_RECEIVE";
|
||||
case LWS_CALLBACK_PROTOCOL_INIT:
|
||||
return "LWS_CALLBACK_PROTOCOL_INIT";
|
||||
case LWS_CALLBACK_SERVER_NEW_CLIENT_INSTANTIATED:
|
||||
return "LWS_CALLBACK_SERVER_NEW_CLIENT_INSTANTIATED";
|
||||
case LWS_CALLBACK_USER:
|
||||
return "LWS_CALLBACK_USER";
|
||||
case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
|
||||
return "LWS_CALLBACK_CLIENT_CONNECTION_ERROR";
|
||||
case LWS_CALLBACK_CLIENT_CLOSED:
|
||||
return "LWS_CALLBACK_CLIENT_CLOSED";
|
||||
case LWS_CALLBACK_WS_PEER_INITIATED_CLOSE:
|
||||
return "LWS_CALLBACK_WS_PEER_INITIATED_CLOSE";
|
||||
case LWS_CALLBACK_WSI_DESTROY:
|
||||
return "LWS_CALLBACK_WSI_DESTROY";
|
||||
case LWS_CALLBACK_CLIENT_ESTABLISHED:
|
||||
return "LWS_CALLBACK_CLIENT_ESTABLISHED";
|
||||
case LWS_CALLBACK_OPENSSL_PERFORM_SERVER_CERT_VERIFICATION:
|
||||
return "LWS_CALLBACK_OPENSSL_PERFORM_SERVER_CERT_VERIFICATION";
|
||||
case LWS_CALLBACK_EVENT_WAIT_CANCELLED:
|
||||
return "LWS_CALLBACK_EVENT_WAIT_CANCELLED";
|
||||
default:
|
||||
// Not using an internal buffer here for thread-safety with unknown calling context.
|
||||
error("Unknown LWS callback %u", reason);
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void aclk_lws_wss_fail_report()
|
||||
{
|
||||
int i;
|
||||
int anything_to_send = 0;
|
||||
BUFFER *buf;
|
||||
|
||||
if (netdata_anonymous_statistics_enabled <= 0)
|
||||
return;
|
||||
|
||||
// guess - most of the callback will be 1-99 + ',' + \0
|
||||
buf = buffer_create((ACLK_LWS_CALLBACK_HISTORY * 2) + 10);
|
||||
|
||||
for (i = 0; i < ACLK_LWS_CALLBACK_HISTORY; i++)
|
||||
if (engine_instance->lws_callback_history[i]) {
|
||||
buffer_sprintf(buf, "%s%d", (i ? "," : ""), engine_instance->lws_callback_history[i]);
|
||||
anything_to_send = 1;
|
||||
}
|
||||
|
||||
if (anything_to_send)
|
||||
send_statistics("ACLK_CONN_FAIL", "FAIL", buffer_tostring(buf));
|
||||
|
||||
buffer_free(buf);
|
||||
}
|
||||
|
||||
static int aclk_lws_wss_callback(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len)
|
||||
{
|
||||
UNUSED(user);
|
||||
struct lws_wss_packet_buffer *data;
|
||||
int retval = 0;
|
||||
static int lws_shutting_down = 0;
|
||||
int i;
|
||||
|
||||
for (i = ACLK_LWS_CALLBACK_HISTORY - 1; i > 0; i--)
|
||||
engine_instance->lws_callback_history[i] = engine_instance->lws_callback_history[i - 1];
|
||||
engine_instance->lws_callback_history[0] = (int)reason;
|
||||
|
||||
if (unlikely(aclk_shutting_down && !lws_shutting_down)) {
|
||||
lws_shutting_down = 1;
|
||||
retval = -1;
|
||||
engine_instance->upstream_reconnect_request = 0;
|
||||
}
|
||||
|
||||
// Callback servicing is forced when we are closed from above.
|
||||
if (engine_instance->upstream_reconnect_request) {
|
||||
error("Closing lws connection due to libmosquitto error.");
|
||||
char *upstream_connection_error = "MQTT protocol error. Closing underlying wss connection.";
|
||||
lws_close_reason(
|
||||
wsi, LWS_CLOSE_STATUS_PROTOCOL_ERR, (unsigned char *)upstream_connection_error,
|
||||
strlen(upstream_connection_error));
|
||||
retval = -1;
|
||||
engine_instance->upstream_reconnect_request = 0;
|
||||
}
|
||||
|
||||
// Don't log to info - volume is proportional to message flow on ACLK.
|
||||
switch (reason) {
|
||||
case LWS_CALLBACK_CLIENT_WRITEABLE:
|
||||
aclk_lws_mutex_lock(&engine_instance->write_buf_mutex);
|
||||
data = engine_instance->write_buffer_head;
|
||||
if (likely(data)) {
|
||||
size_t bytes_left = data->data_size - data->written;
|
||||
if ( bytes_left > FRAGMENT_SIZE)
|
||||
bytes_left = FRAGMENT_SIZE;
|
||||
int n = lws_write(wsi, data->data + LWS_PRE + data->written, bytes_left, LWS_WRITE_BINARY);
|
||||
if (n>=0) {
|
||||
data->written += n;
|
||||
if (aclk_stats_enabled) {
|
||||
LEGACY_ACLK_STATS_LOCK;
|
||||
legacy_aclk_metrics_per_sample.write_q_consumed += n;
|
||||
LEGACY_ACLK_STATS_UNLOCK;
|
||||
}
|
||||
}
|
||||
//error("lws_write(req=%u,written=%u) %zu of %zu",bytes_left, rc, data->written,data->data_size,rc);
|
||||
if (data->written == data->data_size)
|
||||
{
|
||||
lws_wss_packet_buffer_pop(&engine_instance->write_buffer_head);
|
||||
lws_wss_packet_buffer_free(data);
|
||||
}
|
||||
if (engine_instance->write_buffer_head)
|
||||
lws_callback_on_writable(engine_instance->lws_wsi);
|
||||
}
|
||||
aclk_lws_mutex_unlock(&engine_instance->write_buf_mutex);
|
||||
return retval;
|
||||
|
||||
case LWS_CALLBACK_CLIENT_RECEIVE:
|
||||
aclk_lws_mutex_lock(&engine_instance->read_buf_mutex);
|
||||
if (!received_data_to_ringbuff(engine_instance->read_ringbuffer, in, len))
|
||||
retval = 1;
|
||||
aclk_lws_mutex_unlock(&engine_instance->read_buf_mutex);
|
||||
if (aclk_stats_enabled) {
|
||||
LEGACY_ACLK_STATS_LOCK;
|
||||
legacy_aclk_metrics_per_sample.read_q_added += len;
|
||||
LEGACY_ACLK_STATS_UNLOCK;
|
||||
}
|
||||
|
||||
// to future myself -> do not call this while read lock is active as it will eventually
|
||||
// want to acquire same lock later in aclk_lws_wss_client_read() function
|
||||
aclk_lws_connection_data_received();
|
||||
return retval;
|
||||
|
||||
case LWS_CALLBACK_WSI_CREATE:
|
||||
case LWS_CALLBACK_CLIENT_FILTER_PRE_ESTABLISH:
|
||||
case LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER:
|
||||
case LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS:
|
||||
case LWS_CALLBACK_GET_THREAD_ID: // ?
|
||||
case LWS_CALLBACK_EVENT_WAIT_CANCELLED:
|
||||
case LWS_CALLBACK_OPENSSL_PERFORM_SERVER_CERT_VERIFICATION:
|
||||
// Expected and safe to ignore.
|
||||
#ifdef ACLK_TRP_DEBUG_VERBOSE
|
||||
debug(D_ACLK, "Ignoring expected callback from LWS: %s", aclk_lws_callback_name(reason));
|
||||
#endif
|
||||
return retval;
|
||||
|
||||
default:
|
||||
// Pass to next switch, this case removes compiler warnings.
|
||||
break;
|
||||
}
|
||||
// Log to info - volume is proportional to connection attempts.
|
||||
#ifdef ACLK_TRP_DEBUG_VERBOSE
|
||||
info("Processing callback %s", aclk_lws_callback_name(reason));
|
||||
#endif
|
||||
switch (reason) {
|
||||
case LWS_CALLBACK_PROTOCOL_INIT:
|
||||
aclk_lws_wss_connect(engine_instance->host, engine_instance->port); // Makes the outgoing connection
|
||||
break;
|
||||
case LWS_CALLBACK_SERVER_NEW_CLIENT_INSTANTIATED:
|
||||
if (engine_instance->lws_wsi != NULL && engine_instance->lws_wsi != wsi)
|
||||
error("Multiple connections on same WSI? %p vs %p", engine_instance->lws_wsi, wsi);
|
||||
engine_instance->lws_wsi = wsi;
|
||||
break;
|
||||
case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
|
||||
error(
|
||||
"Could not connect MQTT over WSS server \"%s:%d\". LwsReason:\"%s\"", engine_instance->host,
|
||||
engine_instance->port, (in ? (char *)in : "not given"));
|
||||
// Fall-through
|
||||
case LWS_CALLBACK_CLIENT_CLOSED:
|
||||
case LWS_CALLBACK_WS_PEER_INITIATED_CLOSE:
|
||||
engine_instance->lws_wsi = NULL; // inside libwebsockets lws_close_free_wsi is called after callback
|
||||
aclk_lws_connection_closed();
|
||||
return -1; // the callback response is ignored, hope the above remains true
|
||||
case LWS_CALLBACK_WSI_DESTROY:
|
||||
aclk_lws_wss_clear_io_buffers();
|
||||
if (!engine_instance->websocket_connection_up)
|
||||
aclk_lws_wss_fail_report();
|
||||
engine_instance->lws_wsi = NULL;
|
||||
engine_instance->websocket_connection_up = 0;
|
||||
aclk_lws_connection_closed();
|
||||
break;
|
||||
case LWS_CALLBACK_CLIENT_ESTABLISHED:
|
||||
engine_instance->websocket_connection_up = 1;
|
||||
aclk_lws_connection_established(engine_instance->host, engine_instance->port);
|
||||
break;
|
||||
|
||||
default:
|
||||
#ifdef ACLK_TRP_DEBUG_VERBOSE
|
||||
error("Unexpected callback from libwebsockets %s", aclk_lws_callback_name(reason));
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
return retval; //0-OK, other connection should be closed!
|
||||
}
|
||||
|
||||
int aclk_lws_wss_client_write(void *buf, size_t count)
|
||||
{
|
||||
if (engine_instance && engine_instance->lws_wsi && engine_instance->websocket_connection_up) {
|
||||
aclk_lws_mutex_lock(&engine_instance->write_buf_mutex);
|
||||
lws_wss_packet_buffer_append(&engine_instance->write_buffer_head, lws_wss_packet_buffer_new(buf, count));
|
||||
aclk_lws_mutex_unlock(&engine_instance->write_buf_mutex);
|
||||
|
||||
if (aclk_stats_enabled) {
|
||||
LEGACY_ACLK_STATS_LOCK;
|
||||
legacy_aclk_metrics_per_sample.write_q_added += count;
|
||||
LEGACY_ACLK_STATS_UNLOCK;
|
||||
}
|
||||
|
||||
lws_callback_on_writable(engine_instance->lws_wsi);
|
||||
return count;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int aclk_lws_wss_client_read(void *buf, size_t count)
|
||||
{
|
||||
size_t data_to_be_read = count;
|
||||
|
||||
aclk_lws_mutex_lock(&engine_instance->read_buf_mutex);
|
||||
size_t readable_byte_count = lws_ring_get_count_waiting_elements(engine_instance->read_ringbuffer, NULL);
|
||||
if (unlikely(readable_byte_count == 0)) {
|
||||
errno = EAGAIN;
|
||||
data_to_be_read = -1;
|
||||
goto abort;
|
||||
}
|
||||
|
||||
if (readable_byte_count < data_to_be_read)
|
||||
data_to_be_read = readable_byte_count;
|
||||
|
||||
data_to_be_read = lws_ring_consume(engine_instance->read_ringbuffer, NULL, buf, data_to_be_read);
|
||||
if (data_to_be_read == readable_byte_count)
|
||||
engine_instance->data_to_read = 0;
|
||||
|
||||
if (aclk_stats_enabled) {
|
||||
LEGACY_ACLK_STATS_LOCK;
|
||||
legacy_aclk_metrics_per_sample.read_q_consumed += data_to_be_read;
|
||||
LEGACY_ACLK_STATS_UNLOCK;
|
||||
}
|
||||
|
||||
abort:
|
||||
aclk_lws_mutex_unlock(&engine_instance->read_buf_mutex);
|
||||
return data_to_be_read;
|
||||
}
|
||||
|
||||
void aclk_lws_wss_service_loop()
|
||||
{
|
||||
if (engine_instance)
|
||||
{
|
||||
/*if (engine_instance->lws_wsi) {
|
||||
lws_cancel_service(engine_instance->lws_context);
|
||||
lws_callback_on_writable(engine_instance->lws_wsi);
|
||||
}*/
|
||||
lws_service(engine_instance->lws_context, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// in case the MQTT connection disconnect while lws transport is still operational
|
||||
// we should drop connection and reconnect
|
||||
// this function should be called when that happens to notify lws of that situation
|
||||
void aclk_lws_wss_mqtt_layer_disconnect_notif()
|
||||
{
|
||||
if (!engine_instance)
|
||||
return;
|
||||
if (engine_instance->lws_wsi && engine_instance->websocket_connection_up) {
|
||||
engine_instance->upstream_reconnect_request = 1;
|
||||
lws_callback_on_writable(
|
||||
engine_instance->lws_wsi); //here we just do it to ensure we get callback called from lws, we don't need any actual data to be written.
|
||||
}
|
||||
}
|
|
@ -1,92 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#ifndef ACLK_LWS_WSS_CLIENT_H
|
||||
#define ACLK_LWS_WSS_CLIENT_H
|
||||
|
||||
#include <libwebsockets.h>
|
||||
|
||||
#include "libnetdata/libnetdata.h"
|
||||
|
||||
// This is as define because ideally the ACLK at high level
|
||||
// can do mosquitto writes and reads only from one thread
|
||||
// which is cleaner implementation IMHO
|
||||
// in such case this mutexes are not necessary and life
|
||||
// is simpler
|
||||
#define ACLK_LWS_MOSQUITTO_IO_CALLS_MULTITHREADED 1
|
||||
|
||||
#define ACLK_LWS_WSS_RECV_BUFF_SIZE_BYTES (128 * 1024)
|
||||
|
||||
#define ACLK_LWS_CALLBACK_HISTORY 10
|
||||
|
||||
#ifdef ACLK_LWS_MOSQUITTO_IO_CALLS_MULTITHREADED
|
||||
#define aclk_lws_mutex_init(x) netdata_mutex_init(x)
|
||||
#define aclk_lws_mutex_lock(x) netdata_mutex_lock(x)
|
||||
#define aclk_lws_mutex_unlock(x) netdata_mutex_unlock(x)
|
||||
#else
|
||||
#define aclk_lws_mutex_init(x)
|
||||
#define aclk_lws_mutex_lock(x)
|
||||
#define aclk_lws_mutex_unlock(x)
|
||||
#endif
|
||||
|
||||
struct aclk_lws_wss_engine_callbacks {
|
||||
void (*connection_established_callback)();
|
||||
void (*data_rcvd_callback)();
|
||||
void (*data_writable_callback)();
|
||||
void (*connection_closed)();
|
||||
};
|
||||
|
||||
struct lws_wss_packet_buffer {
|
||||
unsigned char *data;
|
||||
size_t data_size, written;
|
||||
struct lws_wss_packet_buffer *next;
|
||||
};
|
||||
|
||||
struct aclk_lws_wss_engine_instance {
|
||||
//target host/port for connection
|
||||
char *host;
|
||||
int port;
|
||||
|
||||
//internal data
|
||||
struct lws_context *lws_context;
|
||||
struct lws *lws_wsi;
|
||||
|
||||
#ifdef ACLK_LWS_MOSQUITTO_IO_CALLS_MULTITHREADED
|
||||
netdata_mutex_t write_buf_mutex;
|
||||
netdata_mutex_t read_buf_mutex;
|
||||
#endif
|
||||
|
||||
struct lws_wss_packet_buffer *write_buffer_head;
|
||||
struct lws_ring *read_ringbuffer;
|
||||
|
||||
//flags to be read by engine user
|
||||
int websocket_connection_up;
|
||||
|
||||
// currently this is by default disabled
|
||||
|
||||
int data_to_read;
|
||||
int upstream_reconnect_request;
|
||||
|
||||
int lws_callback_history[ACLK_LWS_CALLBACK_HISTORY];
|
||||
};
|
||||
|
||||
void aclk_lws_wss_client_destroy();
|
||||
void aclk_lws_wss_destroy_context();
|
||||
|
||||
int aclk_lws_wss_connect(char *host, int port);
|
||||
|
||||
int aclk_lws_wss_client_write(void *buf, size_t count);
|
||||
int aclk_lws_wss_client_read(void *buf, size_t count);
|
||||
void aclk_lws_wss_service_loop();
|
||||
|
||||
void aclk_lws_wss_mqtt_layer_disconnect_notif();
|
||||
|
||||
// Notifications inside the layer above
|
||||
void aclk_lws_connection_established();
|
||||
void aclk_lws_connection_data_received();
|
||||
void aclk_lws_connection_closed();
|
||||
void lws_wss_check_queues(size_t *write_len, size_t *write_len_bytes, size_t *read_len);
|
||||
|
||||
void aclk_wss_set_proxy(struct lws_vhost *vhost);
|
||||
|
||||
#define FRAGMENT_SIZE 4096
|
||||
#endif
|
|
@ -1,843 +0,0 @@
|
|||
#include "aclk_common.h"
|
||||
#include "aclk_query.h"
|
||||
#include "aclk_stats.h"
|
||||
#include "aclk_rx_msgs.h"
|
||||
#include "agent_cloud_link.h"
|
||||
|
||||
#define WEB_HDR_ACCEPT_ENC "Accept-Encoding:"
|
||||
|
||||
#define ACLK_QUERY_THREAD_NAME "ACLK_Query"
|
||||
|
||||
pthread_cond_t legacy_query_cond_wait = PTHREAD_COND_INITIALIZER;
|
||||
pthread_mutex_t legacy_query_lock_wait = PTHREAD_MUTEX_INITIALIZER;
|
||||
#define LEGACY_QUERY_THREAD_LOCK pthread_mutex_lock(&legacy_query_lock_wait)
|
||||
#define LEGACY_QUERY_THREAD_UNLOCK pthread_mutex_unlock(&legacy_query_lock_wait)
|
||||
|
||||
#ifndef __GNUC__
|
||||
#pragma region ACLK_QUEUE
|
||||
#endif
|
||||
|
||||
static netdata_mutex_t queue_mutex = NETDATA_MUTEX_INITIALIZER;
|
||||
#define ACLK_QUEUE_LOCK netdata_mutex_lock(&queue_mutex)
|
||||
#define ACLK_QUEUE_UNLOCK netdata_mutex_unlock(&queue_mutex)
|
||||
|
||||
struct aclk_query {
|
||||
usec_t created;
|
||||
struct timeval tv_in;
|
||||
usec_t created_boot_time;
|
||||
time_t run_after; // Delay run until after this time
|
||||
ACLK_CMD cmd; // What command is this
|
||||
char *topic; // Topic to respond to
|
||||
char *data; // Internal data (NULL if request from the cloud)
|
||||
char *msg_id; // msg_id generated by the cloud (NULL if internal)
|
||||
char *query; // The actual query
|
||||
u_char deleted; // Mark deleted for garbage collect
|
||||
int idx; // index of query thread
|
||||
struct aclk_query *next;
|
||||
};
|
||||
|
||||
struct aclk_query_queue {
|
||||
struct aclk_query *aclk_query_head;
|
||||
struct aclk_query *aclk_query_tail;
|
||||
unsigned int count;
|
||||
} aclk_queue = { .aclk_query_head = NULL, .aclk_query_tail = NULL, .count = 0 };
|
||||
|
||||
|
||||
unsigned int aclk_query_size()
|
||||
{
|
||||
int r;
|
||||
ACLK_QUEUE_LOCK;
|
||||
r = aclk_queue.count;
|
||||
ACLK_QUEUE_UNLOCK;
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free a query structure when done
|
||||
*/
|
||||
static void aclk_query_free(struct aclk_query *this_query)
|
||||
{
|
||||
if (unlikely(!this_query))
|
||||
return;
|
||||
|
||||
freez(this_query->topic);
|
||||
if (likely(this_query->query))
|
||||
freez(this_query->query);
|
||||
if(this_query->data && this_query->cmd == ACLK_CMD_CLOUD_QUERY_2) {
|
||||
struct aclk_cloud_req_v2 *del = (struct aclk_cloud_req_v2 *)this_query->data;
|
||||
freez(del->query_endpoint);
|
||||
freez(del->data);
|
||||
freez(del);
|
||||
}
|
||||
if (likely(this_query->msg_id))
|
||||
freez(this_query->msg_id);
|
||||
freez(this_query);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the next query to process - NULL if nothing there
|
||||
* The caller needs to free memory by calling aclk_query_free()
|
||||
*
|
||||
* topic
|
||||
* query
|
||||
* The structure itself
|
||||
*
|
||||
*/
|
||||
static struct aclk_query *aclk_queue_pop()
|
||||
{
|
||||
struct aclk_query *this_query;
|
||||
|
||||
ACLK_QUEUE_LOCK;
|
||||
|
||||
if (likely(!aclk_queue.aclk_query_head)) {
|
||||
ACLK_QUEUE_UNLOCK;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
this_query = aclk_queue.aclk_query_head;
|
||||
|
||||
// Get rid of the deleted entries
|
||||
while (this_query && this_query->deleted) {
|
||||
aclk_queue.count--;
|
||||
|
||||
aclk_queue.aclk_query_head = aclk_queue.aclk_query_head->next;
|
||||
|
||||
if (likely(!aclk_queue.aclk_query_head)) {
|
||||
aclk_queue.aclk_query_tail = NULL;
|
||||
}
|
||||
|
||||
aclk_query_free(this_query);
|
||||
|
||||
this_query = aclk_queue.aclk_query_head;
|
||||
}
|
||||
|
||||
if (likely(!this_query)) {
|
||||
ACLK_QUEUE_UNLOCK;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!this_query->deleted && this_query->run_after > now_realtime_sec()) {
|
||||
info("Query %s will run in %ld seconds", this_query->query, this_query->run_after - now_realtime_sec());
|
||||
ACLK_QUEUE_UNLOCK;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
aclk_queue.count--;
|
||||
aclk_queue.aclk_query_head = aclk_queue.aclk_query_head->next;
|
||||
|
||||
if (likely(!aclk_queue.aclk_query_head)) {
|
||||
aclk_queue.aclk_query_tail = NULL;
|
||||
}
|
||||
|
||||
ACLK_QUEUE_UNLOCK;
|
||||
return this_query;
|
||||
}
|
||||
|
||||
// Returns the entry after which we need to create a new entry to run at the specified time
|
||||
// If NULL is returned we need to add to HEAD
|
||||
// Need to have a QUERY lock before calling this
|
||||
|
||||
static struct aclk_query *aclk_query_find_position(time_t time_to_run)
|
||||
{
|
||||
struct aclk_query *tmp_query, *last_query;
|
||||
|
||||
// Quick check if we will add to the end
|
||||
if (likely(aclk_queue.aclk_query_tail)) {
|
||||
if (aclk_queue.aclk_query_tail->run_after <= time_to_run)
|
||||
return aclk_queue.aclk_query_tail;
|
||||
}
|
||||
|
||||
last_query = NULL;
|
||||
tmp_query = aclk_queue.aclk_query_head;
|
||||
|
||||
while (tmp_query) {
|
||||
if (tmp_query->run_after > time_to_run)
|
||||
return last_query;
|
||||
last_query = tmp_query;
|
||||
tmp_query = tmp_query->next;
|
||||
}
|
||||
return last_query;
|
||||
}
|
||||
|
||||
// Need to have a QUERY lock before calling this
|
||||
static struct aclk_query *
|
||||
aclk_query_find(char *topic, void *data, char *msg_id, char *query, ACLK_CMD cmd, struct aclk_query **last_query)
|
||||
{
|
||||
struct aclk_query *tmp_query, *prev_query;
|
||||
UNUSED(cmd);
|
||||
|
||||
tmp_query = aclk_queue.aclk_query_head;
|
||||
prev_query = NULL;
|
||||
while (tmp_query) {
|
||||
if (likely(!tmp_query->deleted)) {
|
||||
if (strcmp(tmp_query->topic, topic) == 0 && (!query || strcmp(tmp_query->query, query) == 0)) {
|
||||
if ((!data || data == tmp_query->data) &&
|
||||
(!msg_id || (msg_id && strcmp(msg_id, tmp_query->msg_id) == 0))) {
|
||||
if (likely(last_query))
|
||||
*last_query = prev_query;
|
||||
return tmp_query;
|
||||
}
|
||||
}
|
||||
}
|
||||
prev_query = tmp_query;
|
||||
tmp_query = tmp_query->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a query to execute, the result will be send to the specified topic
|
||||
*/
|
||||
|
||||
int legacy_aclk_queue_query(char *topic, void *data, char *msg_id, char *query, int run_after, int internal, ACLK_CMD aclk_cmd)
|
||||
{
|
||||
struct aclk_query *new_query, *tmp_query;
|
||||
|
||||
// Ignore all commands while we wait for the agent to initialize
|
||||
if (unlikely(!aclk_connected))
|
||||
return 1;
|
||||
|
||||
run_after = now_realtime_sec() + run_after;
|
||||
|
||||
ACLK_QUEUE_LOCK;
|
||||
struct aclk_query *last_query = NULL;
|
||||
|
||||
tmp_query = aclk_query_find(topic, data, msg_id, query, aclk_cmd, &last_query);
|
||||
if (unlikely(tmp_query)) {
|
||||
if (tmp_query->run_after == run_after) {
|
||||
ACLK_QUEUE_UNLOCK;
|
||||
LEGACY_QUERY_THREAD_WAKEUP;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (last_query)
|
||||
last_query->next = tmp_query->next;
|
||||
else
|
||||
aclk_queue.aclk_query_head = tmp_query->next;
|
||||
|
||||
debug(D_ACLK, "Removing double entry");
|
||||
aclk_query_free(tmp_query);
|
||||
aclk_queue.count--;
|
||||
}
|
||||
|
||||
if (aclk_stats_enabled) {
|
||||
LEGACY_ACLK_STATS_LOCK;
|
||||
legacy_aclk_metrics_per_sample.queries_queued++;
|
||||
LEGACY_ACLK_STATS_UNLOCK;
|
||||
}
|
||||
|
||||
new_query = callocz(1, sizeof(struct aclk_query));
|
||||
new_query->cmd = aclk_cmd;
|
||||
if (internal) {
|
||||
new_query->topic = strdupz(topic);
|
||||
if (likely(query))
|
||||
new_query->query = strdupz(query);
|
||||
} else {
|
||||
new_query->topic = topic;
|
||||
new_query->query = query;
|
||||
new_query->msg_id = msg_id;
|
||||
}
|
||||
|
||||
new_query->data = data;
|
||||
new_query->next = NULL;
|
||||
now_realtime_timeval(&new_query->tv_in);
|
||||
new_query->created = (new_query->tv_in.tv_sec * USEC_PER_SEC) + new_query->tv_in.tv_usec;
|
||||
new_query->created_boot_time = now_boottime_usec();
|
||||
new_query->run_after = run_after;
|
||||
|
||||
debug(D_ACLK, "Added query (%s) (%s)", topic, query ? query : "");
|
||||
|
||||
tmp_query = aclk_query_find_position(run_after);
|
||||
|
||||
if (tmp_query) {
|
||||
new_query->next = tmp_query->next;
|
||||
tmp_query->next = new_query;
|
||||
if (tmp_query == aclk_queue.aclk_query_tail)
|
||||
aclk_queue.aclk_query_tail = new_query;
|
||||
aclk_queue.count++;
|
||||
ACLK_QUEUE_UNLOCK;
|
||||
LEGACY_QUERY_THREAD_WAKEUP;
|
||||
return 0;
|
||||
}
|
||||
|
||||
new_query->next = aclk_queue.aclk_query_head;
|
||||
aclk_queue.aclk_query_head = new_query;
|
||||
aclk_queue.count++;
|
||||
|
||||
ACLK_QUEUE_UNLOCK;
|
||||
LEGACY_QUERY_THREAD_WAKEUP;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef __GNUC__
|
||||
#pragma endregion
|
||||
#endif
|
||||
|
||||
#ifndef __GNUC__
|
||||
#pragma region Helper Functions
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Take a buffer, encode it and rewrite it
|
||||
*
|
||||
*/
|
||||
|
||||
static char *aclk_encode_response(char *src, size_t content_size, int keep_newlines)
|
||||
{
|
||||
char *tmp_buffer = mallocz(content_size * 2);
|
||||
char *dst = tmp_buffer;
|
||||
while (content_size > 0) {
|
||||
switch (*src) {
|
||||
case '\n':
|
||||
if (keep_newlines)
|
||||
{
|
||||
*dst++ = '\\';
|
||||
*dst++ = 'n';
|
||||
}
|
||||
break;
|
||||
case '\t':
|
||||
break;
|
||||
case 0x01 ... 0x08:
|
||||
case 0x0b ... 0x1F:
|
||||
*dst++ = '\\';
|
||||
*dst++ = 'u';
|
||||
*dst++ = '0';
|
||||
*dst++ = '0';
|
||||
*dst++ = (*src < 0x0F) ? '0' : '1';
|
||||
*dst++ = to_hex(*src);
|
||||
break;
|
||||
case '\"':
|
||||
*dst++ = '\\';
|
||||
*dst++ = *src;
|
||||
break;
|
||||
default:
|
||||
*dst++ = *src;
|
||||
}
|
||||
src++;
|
||||
content_size--;
|
||||
}
|
||||
*dst = '\0';
|
||||
|
||||
return tmp_buffer;
|
||||
}
|
||||
|
||||
#ifndef __GNUC__
|
||||
#pragma endregion
|
||||
#endif
|
||||
|
||||
#ifndef __GNUC__
|
||||
#pragma region ACLK_QUERY
|
||||
#endif
|
||||
|
||||
|
||||
static usec_t aclk_web_api_request_v1(RRDHOST *host, struct web_client *w, char *url, usec_t q_created)
|
||||
{
|
||||
usec_t t = now_boottime_usec();
|
||||
legacy_aclk_metric_mat_update(&legacy_aclk_metrics_per_sample.cloud_q_recvd_to_processed, t - q_created);
|
||||
|
||||
w->response.code = web_client_api_request_v1(host, w, url);
|
||||
t = now_boottime_usec() - t;
|
||||
|
||||
legacy_aclk_metric_mat_update(&legacy_aclk_metrics_per_sample.cloud_q_db_query_time, t);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
static int aclk_execute_query(struct aclk_query *this_query)
|
||||
{
|
||||
if (strncmp(this_query->query, "/api/v1/", 8) == 0) {
|
||||
struct web_client *w = (struct web_client *)callocz(1, sizeof(struct web_client));
|
||||
w->response.data = buffer_create(NETDATA_WEB_RESPONSE_INITIAL_SIZE);
|
||||
w->response.header = buffer_create(NETDATA_WEB_RESPONSE_HEADER_SIZE);
|
||||
w->response.header_output = buffer_create(NETDATA_WEB_RESPONSE_HEADER_SIZE);
|
||||
strcpy(w->origin, "*"); // Simulate web_client_create_on_fd()
|
||||
w->cookie1[0] = 0; // Simulate web_client_create_on_fd()
|
||||
w->cookie2[0] = 0; // Simulate web_client_create_on_fd()
|
||||
w->acl = 0x1f;
|
||||
|
||||
char *mysep = strchr(this_query->query, '?');
|
||||
if (mysep) {
|
||||
strncpyz(w->decoded_query_string, mysep, NETDATA_WEB_REQUEST_URL_SIZE);
|
||||
*mysep = '\0';
|
||||
} else
|
||||
strncpyz(w->decoded_query_string, this_query->query, NETDATA_WEB_REQUEST_URL_SIZE);
|
||||
|
||||
mysep = strrchr(this_query->query, '/');
|
||||
|
||||
// TODO: handle bad response perhaps in a different way. For now it does to the payload
|
||||
w->tv_in = this_query->tv_in;
|
||||
now_realtime_timeval(&w->tv_ready);
|
||||
aclk_web_api_request_v1(localhost, w, mysep ? mysep + 1 : "noop", this_query->created_boot_time);
|
||||
size_t size = w->response.data->len;
|
||||
size_t sent = size;
|
||||
w->response.data->date = w->tv_ready.tv_sec;
|
||||
web_client_build_http_header(w); // TODO: this function should offset from date, not tv_ready
|
||||
BUFFER *local_buffer = buffer_create(NETDATA_WEB_RESPONSE_INITIAL_SIZE);
|
||||
buffer_flush(local_buffer);
|
||||
local_buffer->contenttype = CT_APPLICATION_JSON;
|
||||
|
||||
aclk_create_header(local_buffer, "http", this_query->msg_id, 0, 0, legacy_aclk_shared_state.version_neg);
|
||||
buffer_strcat(local_buffer, ",\n\t\"payload\": ");
|
||||
char *encoded_response = aclk_encode_response(w->response.data->buffer, w->response.data->len, 0);
|
||||
char *encoded_header = aclk_encode_response(w->response.header_output->buffer, w->response.header_output->len, 1);
|
||||
|
||||
buffer_sprintf(
|
||||
local_buffer, "{\n\"code\": %d,\n\"body\": \"%s\",\n\"headers\": \"%s\"\n}",
|
||||
w->response.code, encoded_response, encoded_header);
|
||||
|
||||
buffer_sprintf(local_buffer, "\n}");
|
||||
|
||||
debug(D_ACLK, "Response:%s", encoded_header);
|
||||
|
||||
aclk_send_message(this_query->topic, local_buffer->buffer, this_query->msg_id);
|
||||
|
||||
struct timeval tv;
|
||||
now_realtime_timeval(&tv);
|
||||
|
||||
log_access("%llu: %d '[ACLK]:%d' '%s' (sent/all = %zu/%zu bytes %0.0f%%, prep/sent/total = %0.2f/%0.2f/%0.2f ms) %d '%s'",
|
||||
w->id
|
||||
, gettid()
|
||||
, this_query->idx
|
||||
, "DATA"
|
||||
, sent
|
||||
, size
|
||||
, size > sent ? -((size > 0) ? (((size - sent) / (double) size) * 100.0) : 0.0) : ((size > 0) ? (((sent - size ) / (double) size) * 100.0) : 0.0)
|
||||
, dt_usec(&w->tv_ready, &w->tv_in) / 1000.0
|
||||
, dt_usec(&tv, &w->tv_ready) / 1000.0
|
||||
, dt_usec(&tv, &w->tv_in) / 1000.0
|
||||
, w->response.code
|
||||
, strip_control_characters(this_query->query)
|
||||
);
|
||||
|
||||
buffer_free(w->response.data);
|
||||
buffer_free(w->response.header);
|
||||
buffer_free(w->response.header_output);
|
||||
freez(w);
|
||||
buffer_free(local_buffer);
|
||||
freez(encoded_response);
|
||||
freez(encoded_header);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int aclk_execute_query_v2(struct aclk_query *this_query)
|
||||
{
|
||||
int retval = 0;
|
||||
usec_t t;
|
||||
BUFFER *local_buffer = NULL;
|
||||
struct aclk_cloud_req_v2 *cloud_req = (struct aclk_cloud_req_v2 *)this_query->data;
|
||||
|
||||
#ifdef NETDATA_WITH_ZLIB
|
||||
int z_ret;
|
||||
BUFFER *z_buffer = buffer_create(NETDATA_WEB_RESPONSE_INITIAL_SIZE);
|
||||
char *start, *end;
|
||||
#endif
|
||||
|
||||
struct web_client *w = (struct web_client *)callocz(1, sizeof(struct web_client));
|
||||
w->response.data = buffer_create(NETDATA_WEB_RESPONSE_INITIAL_SIZE);
|
||||
w->response.header = buffer_create(NETDATA_WEB_RESPONSE_HEADER_SIZE);
|
||||
w->response.header_output = buffer_create(NETDATA_WEB_RESPONSE_HEADER_SIZE);
|
||||
strcpy(w->origin, "*"); // Simulate web_client_create_on_fd()
|
||||
w->cookie1[0] = 0; // Simulate web_client_create_on_fd()
|
||||
w->cookie2[0] = 0; // Simulate web_client_create_on_fd()
|
||||
w->acl = 0x1f;
|
||||
|
||||
char *mysep = strchr(this_query->query, '?');
|
||||
if (mysep) {
|
||||
url_decode_r(w->decoded_query_string, mysep, NETDATA_WEB_REQUEST_URL_SIZE + 1);
|
||||
*mysep = '\0';
|
||||
} else
|
||||
url_decode_r(w->decoded_query_string, this_query->query, NETDATA_WEB_REQUEST_URL_SIZE + 1);
|
||||
|
||||
mysep = strrchr(this_query->query, '/');
|
||||
|
||||
// execute the query
|
||||
w->tv_in = this_query->tv_in;
|
||||
now_realtime_timeval(&w->tv_ready);
|
||||
t = aclk_web_api_request_v1(cloud_req->host, w, mysep ? mysep + 1 : "noop", this_query->created_boot_time);
|
||||
size_t size = (w->mode == WEB_CLIENT_MODE_FILECOPY)?w->response.rlen:w->response.data->len;
|
||||
size_t sent = size;
|
||||
|
||||
#ifdef NETDATA_WITH_ZLIB
|
||||
// check if gzip encoding can and should be used
|
||||
if ((start = strstr(cloud_req->data, WEB_HDR_ACCEPT_ENC))) {
|
||||
start += strlen(WEB_HDR_ACCEPT_ENC);
|
||||
end = strstr(start, "\x0D\x0A");
|
||||
start = strstr(start, "gzip");
|
||||
|
||||
if (start && start < end) {
|
||||
w->response.zstream.zalloc = Z_NULL;
|
||||
w->response.zstream.zfree = Z_NULL;
|
||||
w->response.zstream.opaque = Z_NULL;
|
||||
if(deflateInit2(&w->response.zstream, web_gzip_level, Z_DEFLATED, 15 + 16, 8, web_gzip_strategy) == Z_OK) {
|
||||
w->response.zinitialized = 1;
|
||||
w->response.zoutput = 1;
|
||||
} else
|
||||
error("Failed to initialize zlib. Proceeding without compression.");
|
||||
}
|
||||
}
|
||||
|
||||
if (w->response.data->len && w->response.zinitialized) {
|
||||
w->response.zstream.next_in = (Bytef *)w->response.data->buffer;
|
||||
w->response.zstream.avail_in = w->response.data->len;
|
||||
do {
|
||||
w->response.zstream.avail_out = NETDATA_WEB_RESPONSE_ZLIB_CHUNK_SIZE;
|
||||
w->response.zstream.next_out = w->response.zbuffer;
|
||||
z_ret = deflate(&w->response.zstream, Z_FINISH);
|
||||
if(z_ret < 0) {
|
||||
if(w->response.zstream.msg)
|
||||
error("Error compressing body. ZLIB error: \"%s\"", w->response.zstream.msg);
|
||||
else
|
||||
error("Unknown error during zlib compression.");
|
||||
retval = 1;
|
||||
goto cleanup;
|
||||
}
|
||||
int bytes_to_cpy = NETDATA_WEB_RESPONSE_ZLIB_CHUNK_SIZE - w->response.zstream.avail_out;
|
||||
buffer_need_bytes(z_buffer, bytes_to_cpy);
|
||||
memcpy(&z_buffer->buffer[z_buffer->len], w->response.zbuffer, bytes_to_cpy);
|
||||
z_buffer->len += bytes_to_cpy;
|
||||
} while(z_ret != Z_STREAM_END);
|
||||
// so that web_client_build_http_header
|
||||
// puts correct content length into header
|
||||
buffer_free(w->response.data);
|
||||
w->response.data = z_buffer;
|
||||
z_buffer = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
w->response.data->date = w->tv_ready.tv_sec;
|
||||
web_client_build_http_header(w);
|
||||
local_buffer = buffer_create(NETDATA_WEB_RESPONSE_INITIAL_SIZE);
|
||||
local_buffer->contenttype = CT_APPLICATION_JSON;
|
||||
|
||||
aclk_create_header(local_buffer, "http", this_query->msg_id, 0, 0, legacy_aclk_shared_state.version_neg);
|
||||
buffer_sprintf(local_buffer, ",\"t-exec\": %llu,\"t-rx\": %llu,\"http-code\": %d", t, this_query->created, w->response.code);
|
||||
buffer_strcat(local_buffer, "}\x0D\x0A\x0D\x0A");
|
||||
buffer_strcat(local_buffer, w->response.header_output->buffer);
|
||||
|
||||
if (w->response.data->len) {
|
||||
#ifdef NETDATA_WITH_ZLIB
|
||||
if (w->response.zinitialized) {
|
||||
buffer_need_bytes(local_buffer, w->response.data->len);
|
||||
memcpy(&local_buffer->buffer[local_buffer->len], w->response.data->buffer, w->response.data->len);
|
||||
local_buffer->len += w->response.data->len;
|
||||
sent = sent - size + w->response.data->len;
|
||||
} else {
|
||||
#endif
|
||||
buffer_strcat(local_buffer, w->response.data->buffer);
|
||||
#ifdef NETDATA_WITH_ZLIB
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
aclk_send_message_bin(this_query->topic, local_buffer->buffer, local_buffer->len, this_query->msg_id);
|
||||
|
||||
struct timeval tv;
|
||||
now_realtime_timeval(&tv);
|
||||
|
||||
log_access("%llu: %d '[ACLK]:%d' '%s' (sent/all = %zu/%zu bytes %0.0f%%, prep/sent/total = %0.2f/%0.2f/%0.2f ms) %d '%s'",
|
||||
w->id
|
||||
, gettid()
|
||||
, this_query->idx
|
||||
, "DATA"
|
||||
, sent
|
||||
, size
|
||||
, size > sent ? -((size > 0) ? (((size - sent) / (double) size) * 100.0) : 0.0) : ((size > 0) ? (((sent - size ) / (double) size) * 100.0) : 0.0)
|
||||
, dt_usec(&w->tv_ready, &w->tv_in) / 1000.0
|
||||
, dt_usec(&tv, &w->tv_ready) / 1000.0
|
||||
, dt_usec(&tv, &w->tv_in) / 1000.0
|
||||
, w->response.code
|
||||
, strip_control_characters(this_query->query)
|
||||
);
|
||||
cleanup:
|
||||
#ifdef NETDATA_WITH_ZLIB
|
||||
if(w->response.zinitialized)
|
||||
deflateEnd(&w->response.zstream);
|
||||
buffer_free(z_buffer);
|
||||
#endif
|
||||
buffer_free(w->response.data);
|
||||
buffer_free(w->response.header);
|
||||
buffer_free(w->response.header_output);
|
||||
freez(w);
|
||||
buffer_free(local_buffer);
|
||||
return retval;
|
||||
}
|
||||
|
||||
#define ACLK_HOST_PTR_COMPULSORY(x) \
|
||||
if (unlikely(!host)) { \
|
||||
errno = 0; \
|
||||
error(x " needs host pointer"); \
|
||||
break; \
|
||||
}
|
||||
|
||||
/*
|
||||
* This function will fetch the next pending command and process it
|
||||
*
|
||||
*/
|
||||
static int aclk_process_query(struct aclk_query_thread *t_info)
|
||||
{
|
||||
struct aclk_query *this_query;
|
||||
static long int query_count = 0;
|
||||
ACLK_METADATA_STATE meta_state;
|
||||
RRDHOST *host;
|
||||
|
||||
if (!aclk_connected)
|
||||
return 0;
|
||||
|
||||
this_query = aclk_queue_pop();
|
||||
if (likely(!this_query)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (unlikely(this_query->deleted)) {
|
||||
debug(D_ACLK, "Garbage collect query %s:%s", this_query->topic, this_query->query);
|
||||
aclk_query_free(this_query);
|
||||
return 1;
|
||||
}
|
||||
query_count++;
|
||||
|
||||
host = (RRDHOST*)this_query->data;
|
||||
this_query->idx = t_info->idx;
|
||||
|
||||
debug(
|
||||
D_ACLK, "Query #%ld (%s) size=%zu in queue %llu ms", query_count, this_query->topic,
|
||||
this_query->query ? strlen(this_query->query) : 0, (now_realtime_usec() - this_query->created)/USEC_PER_MS);
|
||||
|
||||
switch (this_query->cmd) {
|
||||
case ACLK_CMD_ONCONNECT:
|
||||
ACLK_HOST_PTR_COMPULSORY("ACLK_CMD_ONCONNECT");
|
||||
#if ACLK_VERSION_MIN < ACLK_V_CHILDRENSTATE
|
||||
if (host != localhost && legacy_aclk_shared_state.version_neg < ACLK_V_CHILDRENSTATE) {
|
||||
error("We are not allowed to send connect message in ACLK version before %d", ACLK_V_CHILDRENSTATE);
|
||||
break;
|
||||
}
|
||||
#else
|
||||
#warning "This check became unnecessary. Remove"
|
||||
#endif
|
||||
|
||||
debug(D_ACLK, "EXECUTING on connect metadata command for host \"%s\" GUID \"%s\"",
|
||||
host->hostname,
|
||||
host->machine_guid);
|
||||
|
||||
rrdhost_aclk_state_lock(host);
|
||||
meta_state = host->aclk_state.metadata;
|
||||
host->aclk_state.metadata = ACLK_METADATA_SENT;
|
||||
rrdhost_aclk_state_unlock(host);
|
||||
aclk_send_metadata(meta_state, host);
|
||||
break;
|
||||
|
||||
case ACLK_CMD_CHART:
|
||||
ACLK_HOST_PTR_COMPULSORY("ACLK_CMD_CHART");
|
||||
|
||||
debug(D_ACLK, "EXECUTING a chart update command");
|
||||
aclk_send_single_chart(host, this_query->query);
|
||||
break;
|
||||
|
||||
case ACLK_CMD_CHARTDEL:
|
||||
ACLK_HOST_PTR_COMPULSORY("ACLK_CMD_CHARTDEL");
|
||||
|
||||
debug(D_ACLK, "EXECUTING a chart delete command");
|
||||
//TODO: This send the info metadata for now
|
||||
legacy_aclk_send_info_metadata(ACLK_METADATA_SENT, host);
|
||||
break;
|
||||
|
||||
case ACLK_CMD_ALARM:
|
||||
debug(D_ACLK, "EXECUTING an alarm update command");
|
||||
aclk_send_message(this_query->topic, this_query->query, this_query->msg_id);
|
||||
break;
|
||||
|
||||
case ACLK_CMD_CLOUD:
|
||||
debug(D_ACLK, "EXECUTING a cloud command");
|
||||
aclk_execute_query(this_query);
|
||||
break;
|
||||
case ACLK_CMD_CLOUD_QUERY_2:
|
||||
debug(D_ACLK, "EXECUTING Cloud Query v2");
|
||||
aclk_execute_query_v2(this_query);
|
||||
break;
|
||||
|
||||
case ACLK_CMD_CHILD_CONNECT:
|
||||
case ACLK_CMD_CHILD_DISCONNECT:
|
||||
ACLK_HOST_PTR_COMPULSORY("ACLK_CMD_CHILD_CONNECT/ACLK_CMD_CHILD_DISCONNECT");
|
||||
|
||||
debug(
|
||||
D_ACLK, "Execution Child %s command",
|
||||
this_query->cmd == ACLK_CMD_CHILD_CONNECT ? "connect" : "disconnect");
|
||||
aclk_send_info_child_connection(host, this_query->cmd);
|
||||
break;
|
||||
|
||||
default:
|
||||
errno = 0;
|
||||
error("Unknown ACLK Query Command");
|
||||
break;
|
||||
}
|
||||
debug(D_ACLK, "Query #%ld (%s) done", query_count, this_query->topic);
|
||||
|
||||
if (aclk_stats_enabled) {
|
||||
LEGACY_ACLK_STATS_LOCK;
|
||||
legacy_aclk_metrics_per_sample.queries_dispatched++;
|
||||
legacy_aclk_queries_per_thread[t_info->idx]++;
|
||||
LEGACY_ACLK_STATS_UNLOCK;
|
||||
|
||||
if (likely(getrusage_called_this_tick[t_info->idx] < MAX_GETRUSAGE_CALLS_PER_TICK)) {
|
||||
getrusage(RUSAGE_THREAD, &rusage_per_thread[t_info->idx]);
|
||||
getrusage_called_this_tick[t_info->idx]++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
aclk_query_free(this_query);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void legacy_aclk_query_threads_cleanup(struct aclk_query_threads *query_threads)
|
||||
{
|
||||
if (query_threads && query_threads->thread_list) {
|
||||
for (int i = 0; i < query_threads->count; i++) {
|
||||
netdata_thread_join(query_threads->thread_list[i].thread, NULL);
|
||||
}
|
||||
freez(query_threads->thread_list);
|
||||
}
|
||||
|
||||
struct aclk_query *this_query;
|
||||
|
||||
do {
|
||||
this_query = aclk_queue_pop();
|
||||
aclk_query_free(this_query);
|
||||
} while (this_query);
|
||||
}
|
||||
|
||||
#define TASK_LEN_MAX 22
|
||||
void legacy_aclk_query_threads_start(struct aclk_query_threads *query_threads)
|
||||
{
|
||||
info("Starting %d query threads.", query_threads->count);
|
||||
|
||||
char thread_name[TASK_LEN_MAX];
|
||||
query_threads->thread_list = callocz(query_threads->count, sizeof(struct aclk_query_thread));
|
||||
for (int i = 0; i < query_threads->count; i++) {
|
||||
query_threads->thread_list[i].idx = i; //thread needs to know its index for statistics
|
||||
|
||||
if(unlikely(snprintfz(thread_name, TASK_LEN_MAX, "%s_%d", ACLK_QUERY_THREAD_NAME, i) < 0))
|
||||
error("snprintf encoding error");
|
||||
netdata_thread_create(
|
||||
&query_threads->thread_list[i].thread, thread_name, NETDATA_THREAD_OPTION_JOINABLE, legacy_aclk_query_main_thread,
|
||||
&query_threads->thread_list[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks and updates popcorning state of rrdhost
|
||||
* returns actual/updated popcorning state
|
||||
*/
|
||||
|
||||
ACLK_AGENT_STATE aclk_host_popcorn_check(RRDHOST *host)
|
||||
{
|
||||
rrdhost_aclk_state_lock(host);
|
||||
ACLK_AGENT_STATE ret = host->aclk_state.state;
|
||||
if (host->aclk_state.state != ACLK_HOST_INITIALIZING){
|
||||
rrdhost_aclk_state_unlock(host);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!host->aclk_state.t_last_popcorn_update){
|
||||
rrdhost_aclk_state_unlock(host);
|
||||
return ret;
|
||||
}
|
||||
|
||||
time_t t_diff = now_monotonic_sec() - host->aclk_state.t_last_popcorn_update;
|
||||
|
||||
if (t_diff >= ACLK_STABLE_TIMEOUT) {
|
||||
host->aclk_state.state = ACLK_HOST_STABLE;
|
||||
host->aclk_state.t_last_popcorn_update = 0;
|
||||
rrdhost_aclk_state_unlock(host);
|
||||
info("Host \"%s\" stable, ACLK popcorning finished. Last interrupt was %ld seconds ago", host->hostname, t_diff);
|
||||
return ACLK_HOST_STABLE;
|
||||
}
|
||||
|
||||
rrdhost_aclk_state_unlock(host);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Main query processing thread
|
||||
*
|
||||
* On startup wait for the agent collectors to initialize
|
||||
* Expect at least a time of ACLK_STABLE_TIMEOUT seconds
|
||||
* of no new collectors coming in in order to mark the agent
|
||||
* as stable (set agent_state = AGENT_STABLE)
|
||||
*/
|
||||
void *legacy_aclk_query_main_thread(void *ptr)
|
||||
{
|
||||
struct aclk_query_thread *info = ptr;
|
||||
|
||||
while (!netdata_exit) {
|
||||
if(aclk_host_popcorn_check(localhost) == ACLK_HOST_STABLE) {
|
||||
#ifdef ACLK_DEBUG
|
||||
_dump_collector_list();
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
sleep_usec(USEC_PER_SEC * 1);
|
||||
}
|
||||
|
||||
while (!netdata_exit) {
|
||||
if(aclk_disable_runtime) {
|
||||
sleep(1);
|
||||
continue;
|
||||
}
|
||||
legacy_aclk_shared_state_LOCK;
|
||||
if (unlikely(!legacy_aclk_shared_state.version_neg)) {
|
||||
if (!legacy_aclk_shared_state.version_neg_wait_till || legacy_aclk_shared_state.version_neg_wait_till > now_monotonic_usec()) {
|
||||
legacy_aclk_shared_state_UNLOCK;
|
||||
info("Waiting for ACLK Version Negotiation message from Cloud");
|
||||
sleep(1);
|
||||
continue;
|
||||
}
|
||||
info("ACLK version negotiation failed (This is expected). No reply to \"hello\" with \"version\" from cloud in time of %ds."
|
||||
" Reverting to default ACLK version of %d.", VERSION_NEG_TIMEOUT, ACLK_VERSION_MIN);
|
||||
legacy_aclk_shared_state.version_neg = ACLK_VERSION_MIN;
|
||||
aclk_set_rx_handlers(legacy_aclk_shared_state.version_neg);
|
||||
}
|
||||
legacy_aclk_shared_state_UNLOCK;
|
||||
|
||||
rrdhost_aclk_state_lock(localhost);
|
||||
if (unlikely(localhost->aclk_state.metadata == ACLK_METADATA_REQUIRED)) {
|
||||
if (unlikely(legacy_aclk_queue_query("on_connect", localhost, NULL, NULL, 0, 1, ACLK_CMD_ONCONNECT))) {
|
||||
rrdhost_aclk_state_unlock(localhost);
|
||||
errno = 0;
|
||||
error("ACLK failed to queue on_connect command");
|
||||
sleep(1);
|
||||
continue;
|
||||
}
|
||||
localhost->aclk_state.metadata = ACLK_METADATA_CMD_QUEUED;
|
||||
}
|
||||
rrdhost_aclk_state_unlock(localhost);
|
||||
|
||||
legacy_aclk_shared_state_LOCK;
|
||||
if (legacy_aclk_shared_state.next_popcorn_host && aclk_host_popcorn_check(legacy_aclk_shared_state.next_popcorn_host) == ACLK_HOST_STABLE) {
|
||||
legacy_aclk_queue_query("on_connect", legacy_aclk_shared_state.next_popcorn_host, NULL, NULL, 0, 1, ACLK_CMD_ONCONNECT);
|
||||
legacy_aclk_shared_state.next_popcorn_host = NULL;
|
||||
aclk_update_next_child_to_popcorn();
|
||||
}
|
||||
legacy_aclk_shared_state_UNLOCK;
|
||||
|
||||
while (aclk_process_query(info)) {
|
||||
// Process all commands
|
||||
};
|
||||
|
||||
LEGACY_QUERY_THREAD_LOCK;
|
||||
|
||||
// TODO: Need to check if there are queries awaiting already
|
||||
if (unlikely(pthread_cond_wait(&legacy_query_cond_wait, &legacy_query_lock_wait)))
|
||||
sleep_usec(USEC_PER_SEC * 1);
|
||||
|
||||
LEGACY_QUERY_THREAD_UNLOCK;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifndef __GNUC__
|
||||
#pragma endregion
|
||||
#endif
|
|
@ -1,41 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#ifndef NETDATA_ACLK_QUERY_H
|
||||
#define NETDATA_ACLK_QUERY_H
|
||||
|
||||
#include "libnetdata/libnetdata.h"
|
||||
#include "web/server/web_client.h"
|
||||
|
||||
#define ACLK_STABLE_TIMEOUT 3 // Minimum delay to mark AGENT as stable
|
||||
|
||||
#define MAX_GETRUSAGE_CALLS_PER_TICK 5 // Maximum number of times getrusage can be called per tick, per thread.
|
||||
|
||||
extern pthread_cond_t legacy_query_cond_wait;
|
||||
extern pthread_mutex_t legacy_query_lock_wait;
|
||||
extern uint8_t *getrusage_called_this_tick;
|
||||
#define LEGACY_QUERY_THREAD_WAKEUP pthread_cond_signal(&legacy_query_cond_wait)
|
||||
#define LEGACY_QUERY_THREAD_WAKEUP_ALL pthread_cond_broadcast(&legacy_query_cond_wait)
|
||||
struct aclk_query_thread {
|
||||
netdata_thread_t thread;
|
||||
int idx;
|
||||
};
|
||||
|
||||
struct aclk_query_threads {
|
||||
struct aclk_query_thread *thread_list;
|
||||
int count;
|
||||
};
|
||||
|
||||
struct aclk_cloud_req_v2 {
|
||||
char *data;
|
||||
RRDHOST *host;
|
||||
char *query_endpoint;
|
||||
};
|
||||
|
||||
void *legacy_aclk_query_main_thread(void *ptr);
|
||||
int legacy_aclk_queue_query(char *token, void *data, char *msg_type, char *query, int run_after, int internal, ACLK_CMD cmd);
|
||||
|
||||
void legacy_aclk_query_threads_start(struct aclk_query_threads *query_threads);
|
||||
void legacy_aclk_query_threads_cleanup(struct aclk_query_threads *query_threads);
|
||||
unsigned int aclk_query_size();
|
||||
|
||||
#endif //NETDATA_AGENT_CLOUD_LINK_H
|
|
@ -1,388 +0,0 @@
|
|||
|
||||
#include "aclk_rx_msgs.h"
|
||||
|
||||
#include "aclk_common.h"
|
||||
#include "aclk_stats.h"
|
||||
#include "aclk_query.h"
|
||||
#include "agent_cloud_link.h"
|
||||
|
||||
#ifndef UUID_STR_LEN
|
||||
#define UUID_STR_LEN 37
|
||||
#endif
|
||||
|
||||
static inline int aclk_extract_v2_data(char *payload, char **data)
|
||||
{
|
||||
char* ptr = strstr(payload, ACLK_V2_PAYLOAD_SEPARATOR);
|
||||
if(!ptr)
|
||||
return 1;
|
||||
ptr += strlen(ACLK_V2_PAYLOAD_SEPARATOR);
|
||||
*data = strdupz(ptr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define ACLK_GET_REQ "GET "
|
||||
#define ACLK_CHILD_REQ "/host/"
|
||||
#define ACLK_CLOUD_REQ_V2_PREFIX "/api/v1/"
|
||||
#define STRNCMP_CONSTANT_PREFIX(str, const_pref) strncmp(str, const_pref, strlen(const_pref))
|
||||
static inline int aclk_v2_payload_get_query(struct aclk_cloud_req_v2 *cloud_req, struct aclk_request *req)
|
||||
{
|
||||
const char *start, *end, *ptr, *query_type;
|
||||
char uuid_str[UUID_STR_LEN];
|
||||
uuid_t uuid;
|
||||
|
||||
errno = 0;
|
||||
|
||||
if(STRNCMP_CONSTANT_PREFIX(cloud_req->data, ACLK_GET_REQ)) {
|
||||
error("Only accepting GET HTTP requests from CLOUD");
|
||||
return 1;
|
||||
}
|
||||
start = ptr = cloud_req->data + strlen(ACLK_GET_REQ);
|
||||
|
||||
if(!STRNCMP_CONSTANT_PREFIX(ptr, ACLK_CHILD_REQ)) {
|
||||
ptr += strlen(ACLK_CHILD_REQ);
|
||||
if(strlen(ptr) < UUID_STR_LEN) {
|
||||
error("the child id in URL too short \"%s\"", start);
|
||||
return 1;
|
||||
}
|
||||
|
||||
strncpyz(uuid_str, ptr, UUID_STR_LEN - 1);
|
||||
|
||||
for(int i = 0; i < UUID_STR_LEN && uuid_str[i]; i++)
|
||||
uuid_str[i] = tolower(uuid_str[i]);
|
||||
|
||||
if(ptr[0] && uuid_parse(uuid_str, uuid)) {
|
||||
error("Got Child query (/host/XXX/...) host id \"%s\" doesn't look like valid GUID", uuid_str);
|
||||
return 1;
|
||||
}
|
||||
ptr += UUID_STR_LEN - 1;
|
||||
|
||||
cloud_req->host = rrdhost_find_by_guid(uuid_str, 0);
|
||||
if(!cloud_req->host) {
|
||||
error("Cannot find host with GUID \"%s\"", uuid_str);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(STRNCMP_CONSTANT_PREFIX(ptr, ACLK_CLOUD_REQ_V2_PREFIX)) {
|
||||
error("Only accepting requests that start with \"%s\" from CLOUD.", ACLK_CLOUD_REQ_V2_PREFIX);
|
||||
return 1;
|
||||
}
|
||||
ptr += strlen(ACLK_CLOUD_REQ_V2_PREFIX);
|
||||
query_type = ptr;
|
||||
|
||||
if(!(end = strstr(ptr, " HTTP/1.1\x0D\x0A"))) {
|
||||
errno = 0;
|
||||
error("Doesn't look like HTTP GET request.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(!(ptr = strchr(ptr, '?')) || ptr > end)
|
||||
ptr = end;
|
||||
cloud_req->query_endpoint = mallocz((ptr - query_type) + 1);
|
||||
strncpyz(cloud_req->query_endpoint, query_type, ptr - query_type);
|
||||
|
||||
req->payload = mallocz((end - start) + 1);
|
||||
strncpyz(req->payload, start, end - start);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define HTTP_CHECK_AGENT_INITIALIZED() rrdhost_aclk_state_lock(localhost);\
|
||||
if (unlikely(localhost->aclk_state.state == ACLK_HOST_INITIALIZING)) {\
|
||||
debug(D_ACLK, "Ignoring \"http\" cloud request; agent not in stable state");\
|
||||
rrdhost_aclk_state_unlock(localhost);\
|
||||
return 1;\
|
||||
}\
|
||||
rrdhost_aclk_state_unlock(localhost);
|
||||
|
||||
/*
|
||||
* Parse the incoming payload and queue a command if valid
|
||||
*/
|
||||
static int aclk_handle_cloud_request_v1(struct aclk_request *cloud_to_agent, char *raw_payload)
|
||||
{
|
||||
UNUSED(raw_payload);
|
||||
HTTP_CHECK_AGENT_INITIALIZED();
|
||||
|
||||
errno = 0;
|
||||
if (unlikely(cloud_to_agent->version != 1)) {
|
||||
error(
|
||||
"Received \"http\" message from Cloud with version %d, but ACLK version %d is used",
|
||||
cloud_to_agent->version,
|
||||
legacy_aclk_shared_state.version_neg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (unlikely(!cloud_to_agent->payload)) {
|
||||
error("payload missing");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (unlikely(!cloud_to_agent->callback_topic)) {
|
||||
error("callback_topic missing");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (unlikely(!cloud_to_agent->msg_id)) {
|
||||
error("msg_id missing");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (unlikely(legacy_aclk_queue_query(cloud_to_agent->callback_topic, NULL, cloud_to_agent->msg_id, cloud_to_agent->payload, 0, 0, ACLK_CMD_CLOUD)))
|
||||
debug(D_ACLK, "ACLK failed to queue incoming \"http\" message");
|
||||
|
||||
if (aclk_stats_enabled) {
|
||||
LEGACY_ACLK_STATS_LOCK;
|
||||
legacy_aclk_metrics_per_sample.cloud_req_v1++;
|
||||
legacy_aclk_metrics_per_sample.cloud_req_ok++;
|
||||
LEGACY_ACLK_STATS_UNLOCK;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int aclk_handle_cloud_request_v2(struct aclk_request *cloud_to_agent, char *raw_payload)
|
||||
{
|
||||
HTTP_CHECK_AGENT_INITIALIZED();
|
||||
|
||||
struct aclk_cloud_req_v2 *cloud_req;
|
||||
char *data;
|
||||
int stat_idx;
|
||||
|
||||
errno = 0;
|
||||
if (cloud_to_agent->version < ACLK_V_COMPRESSION) {
|
||||
error(
|
||||
"This handler cannot reply to request with version older than %d, received %d.",
|
||||
ACLK_V_COMPRESSION,
|
||||
cloud_to_agent->version);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (unlikely(aclk_extract_v2_data(raw_payload, &data))) {
|
||||
error("Error extracting payload expected after the JSON dictionary.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
cloud_req = mallocz(sizeof(struct aclk_cloud_req_v2));
|
||||
cloud_req->data = data;
|
||||
cloud_req->host = localhost;
|
||||
|
||||
if (unlikely(aclk_v2_payload_get_query(cloud_req, cloud_to_agent))) {
|
||||
error("Could not extract payload from query");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (unlikely(!cloud_to_agent->callback_topic)) {
|
||||
error("Missing callback_topic");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (unlikely(!cloud_to_agent->msg_id)) {
|
||||
error("Missing msg_id");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// we do this here due to cloud_req being taken over by query thread
|
||||
// which if crazy quick can free it after legacy_aclk_queue_query
|
||||
stat_idx = aclk_cloud_req_type_to_idx(cloud_req->query_endpoint);
|
||||
|
||||
// legacy_aclk_queue_query takes ownership of data pointer
|
||||
if (unlikely(legacy_aclk_queue_query(
|
||||
cloud_to_agent->callback_topic, cloud_req, cloud_to_agent->msg_id, cloud_to_agent->payload, 0, 0,
|
||||
ACLK_CMD_CLOUD_QUERY_2))) {
|
||||
error("ACLK failed to queue incoming \"http\" v2 message");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (aclk_stats_enabled) {
|
||||
LEGACY_ACLK_STATS_LOCK;
|
||||
legacy_aclk_metrics_per_sample.cloud_req_v2++;
|
||||
legacy_aclk_metrics_per_sample.cloud_req_ok++;
|
||||
legacy_aclk_metrics_per_sample.cloud_req_by_type[stat_idx]++;
|
||||
LEGACY_ACLK_STATS_UNLOCK;
|
||||
}
|
||||
|
||||
return 0;
|
||||
cleanup:
|
||||
freez(cloud_req->query_endpoint);
|
||||
freez(cloud_req->data);
|
||||
freez(cloud_req);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// This handles `version` message from cloud used to negotiate
|
||||
// protocol version we will use
|
||||
static int aclk_handle_version_response(struct aclk_request *cloud_to_agent, char *raw_payload)
|
||||
{
|
||||
UNUSED(raw_payload);
|
||||
int version = -1;
|
||||
errno = 0;
|
||||
|
||||
if (unlikely(cloud_to_agent->version != ACLK_VERSION_NEG_VERSION)) {
|
||||
error(
|
||||
"Unsupported version of \"version\" message from cloud. Expected %d, Got %d",
|
||||
ACLK_VERSION_NEG_VERSION,
|
||||
cloud_to_agent->version);
|
||||
return 1;
|
||||
}
|
||||
if (unlikely(!cloud_to_agent->min_version)) {
|
||||
error("Min version missing or 0");
|
||||
return 1;
|
||||
}
|
||||
if (unlikely(!cloud_to_agent->max_version)) {
|
||||
error("Max version missing or 0");
|
||||
return 1;
|
||||
}
|
||||
if (unlikely(cloud_to_agent->max_version < cloud_to_agent->min_version)) {
|
||||
error(
|
||||
"Max version (%d) must be >= than min version (%d)", cloud_to_agent->max_version,
|
||||
cloud_to_agent->min_version);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (unlikely(cloud_to_agent->min_version > ACLK_VERSION_MAX)) {
|
||||
error(
|
||||
"Agent too old for this cloud. Minimum version required by cloud %d."
|
||||
" Maximum version supported by this agent %d.",
|
||||
cloud_to_agent->min_version, ACLK_VERSION_MAX);
|
||||
aclk_kill_link = 1;
|
||||
aclk_disable_runtime = 1;
|
||||
return 1;
|
||||
}
|
||||
if (unlikely(cloud_to_agent->max_version < ACLK_VERSION_MIN)) {
|
||||
error(
|
||||
"Cloud version is too old for this agent. Maximum version supported by cloud %d."
|
||||
" Minimum (oldest) version supported by this agent %d.",
|
||||
cloud_to_agent->max_version, ACLK_VERSION_MIN);
|
||||
aclk_kill_link = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
version = MIN(cloud_to_agent->max_version, ACLK_VERSION_MAX);
|
||||
|
||||
legacy_aclk_shared_state_LOCK;
|
||||
if (unlikely(now_monotonic_usec() > legacy_aclk_shared_state.version_neg_wait_till)) {
|
||||
errno = 0;
|
||||
error("The \"version\" message came too late ignoring.");
|
||||
goto err_cleanup;
|
||||
}
|
||||
if (unlikely(legacy_aclk_shared_state.version_neg)) {
|
||||
errno = 0;
|
||||
error("Version has already been set to %d", legacy_aclk_shared_state.version_neg);
|
||||
goto err_cleanup;
|
||||
}
|
||||
legacy_aclk_shared_state.version_neg = version;
|
||||
legacy_aclk_shared_state_UNLOCK;
|
||||
|
||||
info("Choosing version %d of ACLK", version);
|
||||
|
||||
aclk_set_rx_handlers(version);
|
||||
|
||||
return 0;
|
||||
|
||||
err_cleanup:
|
||||
legacy_aclk_shared_state_UNLOCK;
|
||||
return 1;
|
||||
}
|
||||
|
||||
typedef struct aclk_incoming_msg_type{
|
||||
char *name;
|
||||
int(*fnc)(struct aclk_request *, char *);
|
||||
}aclk_incoming_msg_type;
|
||||
|
||||
aclk_incoming_msg_type legacy_aclk_incoming_msg_types_v1[] = {
|
||||
{ .name = "http", .fnc = aclk_handle_cloud_request_v1 },
|
||||
{ .name = "version", .fnc = aclk_handle_version_response },
|
||||
{ .name = NULL, .fnc = NULL }
|
||||
};
|
||||
|
||||
aclk_incoming_msg_type legacy_aclk_incoming_msg_types_compression[] = {
|
||||
{ .name = "http", .fnc = aclk_handle_cloud_request_v2 },
|
||||
{ .name = "version", .fnc = aclk_handle_version_response },
|
||||
{ .name = NULL, .fnc = NULL }
|
||||
};
|
||||
|
||||
struct aclk_incoming_msg_type *legacy_aclk_incoming_msg_types = legacy_aclk_incoming_msg_types_v1;
|
||||
|
||||
void aclk_set_rx_handlers(int version)
|
||||
{
|
||||
if(version >= ACLK_V_COMPRESSION) {
|
||||
legacy_aclk_incoming_msg_types = legacy_aclk_incoming_msg_types_compression;
|
||||
return;
|
||||
}
|
||||
|
||||
legacy_aclk_incoming_msg_types = legacy_aclk_incoming_msg_types_v1;
|
||||
}
|
||||
|
||||
int legacy_aclk_handle_cloud_message(char *payload)
|
||||
{
|
||||
struct aclk_request cloud_to_agent;
|
||||
memset(&cloud_to_agent, 0, sizeof(struct aclk_request));
|
||||
|
||||
if (unlikely(!payload)) {
|
||||
errno = 0;
|
||||
error("ACLK incoming message is empty");
|
||||
goto err_cleanup_nojson;
|
||||
}
|
||||
|
||||
debug(D_ACLK, "ACLK incoming message (%s)", payload);
|
||||
|
||||
int rc = json_parse(payload, &cloud_to_agent, legacy_cloud_to_agent_parse);
|
||||
|
||||
if (unlikely(rc != JSON_OK)) {
|
||||
errno = 0;
|
||||
error("Malformed json request (%s)", payload);
|
||||
goto err_cleanup;
|
||||
}
|
||||
|
||||
if (!cloud_to_agent.type_id) {
|
||||
errno = 0;
|
||||
error("Cloud message is missing compulsory key \"type\"");
|
||||
goto err_cleanup;
|
||||
}
|
||||
|
||||
if (!legacy_aclk_shared_state.version_neg && strcmp(cloud_to_agent.type_id, "version")) {
|
||||
error("Only \"version\" message is allowed before popcorning and version negotiation is finished. Ignoring");
|
||||
goto err_cleanup;
|
||||
}
|
||||
|
||||
for (int i = 0; legacy_aclk_incoming_msg_types[i].name; i++) {
|
||||
if (strcmp(cloud_to_agent.type_id, legacy_aclk_incoming_msg_types[i].name) == 0) {
|
||||
if (likely(!legacy_aclk_incoming_msg_types[i].fnc(&cloud_to_agent, payload))) {
|
||||
// in case of success handler is supposed to clean up after itself
|
||||
// or as in the case of aclk_handle_cloud_request take
|
||||
// ownership of the pointers (done to avoid copying)
|
||||
// see what `legacy_aclk_queue_query` parameter `internal` does
|
||||
|
||||
// NEVER CONTINUE THIS LOOP AFTER CALLING FUNCTION!!!
|
||||
// msg handlers (namely aclk_handle_version_response)
|
||||
// can freely change what legacy_aclk_incoming_msg_types points to
|
||||
// so either exit or restart this for loop
|
||||
freez(cloud_to_agent.type_id);
|
||||
return 0;
|
||||
}
|
||||
goto err_cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
error("Unknown message type from Cloud \"%s\"", cloud_to_agent.type_id);
|
||||
|
||||
err_cleanup:
|
||||
if (cloud_to_agent.payload)
|
||||
freez(cloud_to_agent.payload);
|
||||
if (cloud_to_agent.type_id)
|
||||
freez(cloud_to_agent.type_id);
|
||||
if (cloud_to_agent.msg_id)
|
||||
freez(cloud_to_agent.msg_id);
|
||||
if (cloud_to_agent.callback_topic)
|
||||
freez(cloud_to_agent.callback_topic);
|
||||
|
||||
err_cleanup_nojson:
|
||||
if (aclk_stats_enabled) {
|
||||
LEGACY_ACLK_STATS_LOCK;
|
||||
legacy_aclk_metrics_per_sample.cloud_req_err++;
|
||||
LEGACY_ACLK_STATS_UNLOCK;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#ifndef NETDATA_ACLK_RX_MSGS_H
|
||||
#define NETDATA_ACLK_RX_MSGS_H
|
||||
|
||||
#include "daemon/common.h"
|
||||
#include "libnetdata/libnetdata.h"
|
||||
|
||||
int legacy_aclk_handle_cloud_message(char *payload);
|
||||
void aclk_set_rx_handlers(int version);
|
||||
|
||||
|
||||
#endif /* NETDATA_ACLK_RX_MSGS_H */
|
|
@ -1,411 +0,0 @@
|
|||
#include "aclk_stats.h"
|
||||
|
||||
netdata_mutex_t legacy_aclk_stats_mutex = NETDATA_MUTEX_INITIALIZER;
|
||||
|
||||
int legacy_query_thread_count;
|
||||
|
||||
// data ACLK stats need per query thread
|
||||
struct legacy_aclk_qt_data {
|
||||
RRDDIM *dim;
|
||||
} *legacy_aclk_qt_data = NULL;
|
||||
|
||||
// ACLK per query thread cpu stats
|
||||
struct legacy_aclk_cpu_data {
|
||||
RRDDIM *user;
|
||||
RRDDIM *system;
|
||||
RRDSET *st;
|
||||
} *legacy_aclk_cpu_data = NULL;
|
||||
|
||||
uint32_t *legacy_aclk_queries_per_thread = NULL;
|
||||
uint32_t *legacy_aclk_queries_per_thread_sample = NULL;
|
||||
struct rusage *rusage_per_thread;
|
||||
uint8_t *getrusage_called_this_tick = NULL;
|
||||
|
||||
static struct legacy_aclk_metrics legacy_aclk_metrics = {
|
||||
.online = 0,
|
||||
};
|
||||
|
||||
struct legacy_aclk_metrics_per_sample legacy_aclk_metrics_per_sample;
|
||||
|
||||
struct aclk_mat_metrics aclk_mat_metrics = {
|
||||
#ifdef NETDATA_INTERNAL_CHECKS
|
||||
.latency = { .name = "aclk_latency_mqtt",
|
||||
.prio = 200002,
|
||||
.st = NULL,
|
||||
.rd_avg = NULL,
|
||||
.rd_max = NULL,
|
||||
.rd_total = NULL,
|
||||
.unit = "ms",
|
||||
.title = "ACLK Message Publish Latency" },
|
||||
#endif
|
||||
|
||||
.cloud_q_db_query_time = { .name = "aclk_db_query_time",
|
||||
.prio = 200006,
|
||||
.st = NULL,
|
||||
.rd_avg = NULL,
|
||||
.rd_max = NULL,
|
||||
.rd_total = NULL,
|
||||
.unit = "us",
|
||||
.title = "Time it took to process cloud requested DB queries" },
|
||||
|
||||
.cloud_q_recvd_to_processed = { .name = "aclk_cloud_q_recvd_to_processed",
|
||||
.prio = 200007,
|
||||
.st = NULL,
|
||||
.rd_avg = NULL,
|
||||
.rd_max = NULL,
|
||||
.rd_total = NULL,
|
||||
.unit = "us",
|
||||
.title = "Time from receiving the Cloud Query until it was picked up "
|
||||
"by query thread (just before passing to the database)." }
|
||||
};
|
||||
|
||||
void legacy_aclk_metric_mat_update(struct aclk_metric_mat_data *metric, usec_t measurement)
|
||||
{
|
||||
if (aclk_stats_enabled) {
|
||||
LEGACY_ACLK_STATS_LOCK;
|
||||
if (metric->max < measurement)
|
||||
metric->max = measurement;
|
||||
|
||||
metric->total += measurement;
|
||||
metric->count++;
|
||||
LEGACY_ACLK_STATS_UNLOCK;
|
||||
}
|
||||
}
|
||||
|
||||
static void aclk_stats_collect(struct legacy_aclk_metrics_per_sample *per_sample, struct legacy_aclk_metrics *permanent)
|
||||
{
|
||||
static RRDSET *st_aclkstats = NULL;
|
||||
static RRDDIM *rd_online_status = NULL;
|
||||
|
||||
if (unlikely(!st_aclkstats)) {
|
||||
st_aclkstats = rrdset_create_localhost(
|
||||
"netdata", "aclk_status", NULL, "aclk", NULL, "ACLK/Cloud connection status",
|
||||
"connected", "netdata", "stats", 200000, localhost->rrd_update_every, RRDSET_TYPE_LINE);
|
||||
|
||||
rd_online_status = rrddim_add(st_aclkstats, "online", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
|
||||
} else
|
||||
rrdset_next(st_aclkstats);
|
||||
|
||||
rrddim_set_by_pointer(st_aclkstats, rd_online_status, per_sample->offline_during_sample ? 0 : permanent->online);
|
||||
|
||||
rrdset_done(st_aclkstats);
|
||||
}
|
||||
|
||||
static void aclk_stats_query_queue(struct legacy_aclk_metrics_per_sample *per_sample)
|
||||
{
|
||||
static RRDSET *st_query_thread = NULL;
|
||||
static RRDDIM *rd_queued = NULL;
|
||||
static RRDDIM *rd_dispatched = NULL;
|
||||
|
||||
if (unlikely(!st_query_thread)) {
|
||||
st_query_thread = rrdset_create_localhost(
|
||||
"netdata", "aclk_query_per_second", NULL, "aclk", NULL, "ACLK Queries per second", "queries/s",
|
||||
"netdata", "stats", 200001, localhost->rrd_update_every, RRDSET_TYPE_AREA);
|
||||
|
||||
rd_queued = rrddim_add(st_query_thread, "added", NULL, 1, localhost->rrd_update_every, RRD_ALGORITHM_ABSOLUTE);
|
||||
rd_dispatched = rrddim_add(st_query_thread, "dispatched", NULL, -1, localhost->rrd_update_every, RRD_ALGORITHM_ABSOLUTE);
|
||||
} else
|
||||
rrdset_next(st_query_thread);
|
||||
|
||||
rrddim_set_by_pointer(st_query_thread, rd_queued, per_sample->queries_queued);
|
||||
rrddim_set_by_pointer(st_query_thread, rd_dispatched, per_sample->queries_dispatched);
|
||||
|
||||
rrdset_done(st_query_thread);
|
||||
}
|
||||
|
||||
static void aclk_stats_write_q(struct legacy_aclk_metrics_per_sample *per_sample)
|
||||
{
|
||||
static RRDSET *st = NULL;
|
||||
static RRDDIM *rd_wq_add = NULL;
|
||||
static RRDDIM *rd_wq_consumed = NULL;
|
||||
|
||||
if (unlikely(!st)) {
|
||||
st = rrdset_create_localhost(
|
||||
"netdata", "aclk_write_q", NULL, "aclk", NULL, "Write Queue Mosq->Libwebsockets", "KiB/s",
|
||||
"netdata", "stats", 200003, localhost->rrd_update_every, RRDSET_TYPE_AREA);
|
||||
|
||||
rd_wq_add = rrddim_add(st, "added", NULL, 1, 1024 * localhost->rrd_update_every, RRD_ALGORITHM_ABSOLUTE);
|
||||
rd_wq_consumed = rrddim_add(st, "consumed", NULL, 1, -1024 * localhost->rrd_update_every, RRD_ALGORITHM_ABSOLUTE);
|
||||
} else
|
||||
rrdset_next(st);
|
||||
|
||||
rrddim_set_by_pointer(st, rd_wq_add, per_sample->write_q_added);
|
||||
rrddim_set_by_pointer(st, rd_wq_consumed, per_sample->write_q_consumed);
|
||||
|
||||
rrdset_done(st);
|
||||
}
|
||||
|
||||
static void aclk_stats_read_q(struct legacy_aclk_metrics_per_sample *per_sample)
|
||||
{
|
||||
static RRDSET *st = NULL;
|
||||
static RRDDIM *rd_rq_add = NULL;
|
||||
static RRDDIM *rd_rq_consumed = NULL;
|
||||
|
||||
if (unlikely(!st)) {
|
||||
st = rrdset_create_localhost(
|
||||
"netdata", "aclk_read_q", NULL, "aclk", NULL, "Read Queue Libwebsockets->Mosq", "KiB/s",
|
||||
"netdata", "stats", 200004, localhost->rrd_update_every, RRDSET_TYPE_AREA);
|
||||
|
||||
rd_rq_add = rrddim_add(st, "added", NULL, 1, 1024 * localhost->rrd_update_every, RRD_ALGORITHM_ABSOLUTE);
|
||||
rd_rq_consumed = rrddim_add(st, "consumed", NULL, 1, -1024 * localhost->rrd_update_every, RRD_ALGORITHM_ABSOLUTE);
|
||||
} else
|
||||
rrdset_next(st);
|
||||
|
||||
rrddim_set_by_pointer(st, rd_rq_add, per_sample->read_q_added);
|
||||
rrddim_set_by_pointer(st, rd_rq_consumed, per_sample->read_q_consumed);
|
||||
|
||||
rrdset_done(st);
|
||||
}
|
||||
|
||||
static void aclk_stats_cloud_req(struct legacy_aclk_metrics_per_sample *per_sample)
|
||||
{
|
||||
static RRDSET *st = NULL;
|
||||
static RRDDIM *rd_rq_ok = NULL;
|
||||
static RRDDIM *rd_rq_err = NULL;
|
||||
|
||||
if (unlikely(!st)) {
|
||||
st = rrdset_create_localhost(
|
||||
"netdata", "aclk_cloud_req", NULL, "aclk", NULL, "Requests received from cloud", "req/s",
|
||||
"netdata", "stats", 200005, localhost->rrd_update_every, RRDSET_TYPE_STACKED);
|
||||
|
||||
rd_rq_ok = rrddim_add(st, "accepted", NULL, 1, localhost->rrd_update_every, RRD_ALGORITHM_ABSOLUTE);
|
||||
rd_rq_err = rrddim_add(st, "rejected", NULL, 1, localhost->rrd_update_every, RRD_ALGORITHM_ABSOLUTE);
|
||||
} else
|
||||
rrdset_next(st);
|
||||
|
||||
rrddim_set_by_pointer(st, rd_rq_ok, per_sample->cloud_req_ok);
|
||||
rrddim_set_by_pointer(st, rd_rq_err, per_sample->cloud_req_err);
|
||||
|
||||
rrdset_done(st);
|
||||
}
|
||||
|
||||
static void aclk_stats_cloud_req_version(struct legacy_aclk_metrics_per_sample *per_sample)
|
||||
{
|
||||
static RRDSET *st = NULL;
|
||||
static RRDDIM *rd_rq_v1 = NULL;
|
||||
static RRDDIM *rd_rq_v2 = NULL;
|
||||
|
||||
if (unlikely(!st)) {
|
||||
st = rrdset_create_localhost(
|
||||
"netdata", "aclk_cloud_req_version", NULL, "aclk", NULL, "Requests received from cloud by their version", "req/s",
|
||||
"netdata", "stats", 200006, localhost->rrd_update_every, RRDSET_TYPE_STACKED);
|
||||
|
||||
rd_rq_v1 = rrddim_add(st, "v1", NULL, 1, localhost->rrd_update_every, RRD_ALGORITHM_ABSOLUTE);
|
||||
rd_rq_v2 = rrddim_add(st, "v2+", NULL, 1, localhost->rrd_update_every, RRD_ALGORITHM_ABSOLUTE);
|
||||
} else
|
||||
rrdset_next(st);
|
||||
|
||||
rrddim_set_by_pointer(st, rd_rq_v1, per_sample->cloud_req_v1);
|
||||
rrddim_set_by_pointer(st, rd_rq_v2, per_sample->cloud_req_v2);
|
||||
|
||||
rrdset_done(st);
|
||||
}
|
||||
|
||||
static char *cloud_req_type_names[ACLK_STATS_CLOUD_REQ_TYPE_CNT] = {
|
||||
"other",
|
||||
"info",
|
||||
"data",
|
||||
"alarms",
|
||||
"alarm_log",
|
||||
"chart",
|
||||
"charts"
|
||||
// if you change update:
|
||||
// #define ACLK_STATS_CLOUD_REQ_TYPE_CNT 7
|
||||
};
|
||||
|
||||
int aclk_cloud_req_type_to_idx(const char *name)
|
||||
{
|
||||
for (int i = 1; i < ACLK_STATS_CLOUD_REQ_TYPE_CNT; i++)
|
||||
if (!strcmp(cloud_req_type_names[i], name))
|
||||
return i;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void aclk_stats_cloud_req_cmd(struct legacy_aclk_metrics_per_sample *per_sample)
|
||||
{
|
||||
static RRDSET *st;
|
||||
static int initialized = 0;
|
||||
static RRDDIM *rd_rq_types[ACLK_STATS_CLOUD_REQ_TYPE_CNT];
|
||||
|
||||
if (unlikely(!initialized)) {
|
||||
initialized = 1;
|
||||
st = rrdset_create_localhost(
|
||||
"netdata", "aclk_cloud_req_cmd", NULL, "aclk", NULL, "Requests received from cloud by their type (api endpoint queried)", "req/s",
|
||||
"netdata", "stats", 200007, localhost->rrd_update_every, RRDSET_TYPE_STACKED);
|
||||
|
||||
for (int i = 0; i < ACLK_STATS_CLOUD_REQ_TYPE_CNT; i++)
|
||||
rd_rq_types[i] = rrddim_add(st, cloud_req_type_names[i], NULL, 1, localhost->rrd_update_every, RRD_ALGORITHM_ABSOLUTE);
|
||||
} else
|
||||
rrdset_next(st);
|
||||
|
||||
for (int i = 0; i < ACLK_STATS_CLOUD_REQ_TYPE_CNT; i++)
|
||||
rrddim_set_by_pointer(st, rd_rq_types[i], per_sample->cloud_req_by_type[i]);
|
||||
|
||||
rrdset_done(st);
|
||||
}
|
||||
|
||||
#define MAX_DIM_NAME 22
|
||||
static void aclk_stats_query_threads(uint32_t *queries_per_thread)
|
||||
{
|
||||
static RRDSET *st = NULL;
|
||||
|
||||
char dim_name[MAX_DIM_NAME];
|
||||
|
||||
if (unlikely(!st)) {
|
||||
st = rrdset_create_localhost(
|
||||
"netdata", "aclk_query_threads", NULL, "aclk", NULL, "Queries Processed Per Thread", "req/s",
|
||||
"netdata", "stats", 200008, localhost->rrd_update_every, RRDSET_TYPE_STACKED);
|
||||
|
||||
for (int i = 0; i < legacy_query_thread_count; i++) {
|
||||
if (snprintfz(dim_name, MAX_DIM_NAME, "Query %d", i) < 0)
|
||||
error("snprintf encoding error");
|
||||
legacy_aclk_qt_data[i].dim = rrddim_add(st, dim_name, NULL, 1, localhost->rrd_update_every, RRD_ALGORITHM_ABSOLUTE);
|
||||
}
|
||||
} else
|
||||
rrdset_next(st);
|
||||
|
||||
for (int i = 0; i < legacy_query_thread_count; i++) {
|
||||
rrddim_set_by_pointer(st, legacy_aclk_qt_data[i].dim, queries_per_thread[i]);
|
||||
}
|
||||
|
||||
rrdset_done(st);
|
||||
}
|
||||
|
||||
static void aclk_stats_mat_metric_process(struct aclk_metric_mat *metric, struct aclk_metric_mat_data *data)
|
||||
{
|
||||
if(unlikely(!metric->st)) {
|
||||
metric->st = rrdset_create_localhost(
|
||||
"netdata", metric->name, NULL, "aclk", NULL, metric->title, metric->unit, "netdata", "stats", metric->prio,
|
||||
localhost->rrd_update_every, RRDSET_TYPE_LINE);
|
||||
|
||||
metric->rd_avg = rrddim_add(metric->st, "avg", NULL, 1, localhost->rrd_update_every, RRD_ALGORITHM_ABSOLUTE);
|
||||
metric->rd_max = rrddim_add(metric->st, "max", NULL, 1, localhost->rrd_update_every, RRD_ALGORITHM_ABSOLUTE);
|
||||
metric->rd_total = rrddim_add(metric->st, "total", NULL, 1, localhost->rrd_update_every, RRD_ALGORITHM_ABSOLUTE);
|
||||
} else
|
||||
rrdset_next(metric->st);
|
||||
|
||||
if(data->count)
|
||||
rrddim_set_by_pointer(metric->st, metric->rd_avg, roundf((float)data->total / data->count));
|
||||
else
|
||||
rrddim_set_by_pointer(metric->st, metric->rd_avg, 0);
|
||||
rrddim_set_by_pointer(metric->st, metric->rd_max, data->max);
|
||||
rrddim_set_by_pointer(metric->st, metric->rd_total, data->total);
|
||||
|
||||
rrdset_done(metric->st);
|
||||
}
|
||||
|
||||
static void aclk_stats_cpu_threads(void)
|
||||
{
|
||||
char id[100 + 1];
|
||||
char title[100 + 1];
|
||||
|
||||
for (int i = 0; i < legacy_query_thread_count; i++) {
|
||||
if (unlikely(!legacy_aclk_cpu_data[i].st)) {
|
||||
|
||||
snprintfz(id, 100, "aclk_thread%d_cpu", i);
|
||||
snprintfz(title, 100, "Cpu Usage For Thread No %d", i);
|
||||
|
||||
legacy_aclk_cpu_data[i].st = rrdset_create_localhost(
|
||||
"netdata", id, NULL, "aclk", NULL, title, "milliseconds/s",
|
||||
"netdata", "stats", 200020 + i, localhost->rrd_update_every, RRDSET_TYPE_STACKED);
|
||||
|
||||
legacy_aclk_cpu_data[i].user = rrddim_add(legacy_aclk_cpu_data[i].st, "user", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL);
|
||||
legacy_aclk_cpu_data[i].system = rrddim_add(legacy_aclk_cpu_data[i].st, "system", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL);
|
||||
|
||||
} else
|
||||
rrdset_next(legacy_aclk_cpu_data[i].st);
|
||||
}
|
||||
|
||||
for (int i = 0; i < legacy_query_thread_count; i++) {
|
||||
rrddim_set_by_pointer(legacy_aclk_cpu_data[i].st, legacy_aclk_cpu_data[i].user, rusage_per_thread[i].ru_utime.tv_sec * 1000000ULL + rusage_per_thread[i].ru_utime.tv_usec);
|
||||
rrddim_set_by_pointer(legacy_aclk_cpu_data[i].st, legacy_aclk_cpu_data[i].system, rusage_per_thread[i].ru_stime.tv_sec * 1000000ULL + rusage_per_thread[i].ru_stime.tv_usec);
|
||||
rrdset_done(legacy_aclk_cpu_data[i].st);
|
||||
}
|
||||
}
|
||||
|
||||
void legacy_aclk_stats_thread_cleanup()
|
||||
{
|
||||
freez(legacy_aclk_qt_data);
|
||||
freez(legacy_aclk_queries_per_thread);
|
||||
freez(legacy_aclk_queries_per_thread_sample);
|
||||
freez(legacy_aclk_cpu_data);
|
||||
freez(rusage_per_thread);
|
||||
}
|
||||
|
||||
void *legacy_aclk_stats_main_thread(void *ptr)
|
||||
{
|
||||
struct aclk_stats_thread *args = ptr;
|
||||
|
||||
legacy_query_thread_count = args->query_thread_count;
|
||||
legacy_aclk_qt_data = callocz(legacy_query_thread_count, sizeof(struct legacy_aclk_qt_data));
|
||||
legacy_aclk_cpu_data = callocz(legacy_query_thread_count, sizeof(struct legacy_aclk_cpu_data));
|
||||
legacy_aclk_queries_per_thread = callocz(legacy_query_thread_count, sizeof(uint32_t));
|
||||
legacy_aclk_queries_per_thread_sample = callocz(legacy_query_thread_count, sizeof(uint32_t));
|
||||
rusage_per_thread = callocz(legacy_query_thread_count, sizeof(struct rusage));
|
||||
getrusage_called_this_tick = callocz(legacy_query_thread_count, sizeof(uint8_t));
|
||||
|
||||
heartbeat_t hb;
|
||||
heartbeat_init(&hb);
|
||||
usec_t step_ut = localhost->rrd_update_every * USEC_PER_SEC;
|
||||
|
||||
memset(&legacy_aclk_metrics_per_sample, 0, sizeof(struct legacy_aclk_metrics_per_sample));
|
||||
|
||||
struct legacy_aclk_metrics_per_sample per_sample;
|
||||
struct legacy_aclk_metrics permanent;
|
||||
|
||||
while (!netdata_exit) {
|
||||
netdata_thread_testcancel();
|
||||
// ------------------------------------------------------------------------
|
||||
// Wait for the next iteration point.
|
||||
|
||||
heartbeat_next(&hb, step_ut);
|
||||
if (netdata_exit) break;
|
||||
|
||||
LEGACY_ACLK_STATS_LOCK;
|
||||
// to not hold lock longer than necessary, especially not to hold it
|
||||
// during database rrd* operations
|
||||
memcpy(&per_sample, &legacy_aclk_metrics_per_sample, sizeof(struct legacy_aclk_metrics_per_sample));
|
||||
memcpy(&permanent, &legacy_aclk_metrics, sizeof(struct legacy_aclk_metrics));
|
||||
memset(&legacy_aclk_metrics_per_sample, 0, sizeof(struct legacy_aclk_metrics_per_sample));
|
||||
|
||||
memcpy(legacy_aclk_queries_per_thread_sample, legacy_aclk_queries_per_thread, sizeof(uint32_t) * legacy_query_thread_count);
|
||||
memset(legacy_aclk_queries_per_thread, 0, sizeof(uint32_t) * legacy_query_thread_count);
|
||||
memset(getrusage_called_this_tick, 0, sizeof(uint8_t) * legacy_query_thread_count);
|
||||
LEGACY_ACLK_STATS_UNLOCK;
|
||||
|
||||
aclk_stats_collect(&per_sample, &permanent);
|
||||
aclk_stats_query_queue(&per_sample);
|
||||
|
||||
aclk_stats_write_q(&per_sample);
|
||||
aclk_stats_read_q(&per_sample);
|
||||
|
||||
aclk_stats_cloud_req(&per_sample);
|
||||
aclk_stats_cloud_req_version(&per_sample);
|
||||
|
||||
aclk_stats_cloud_req_cmd(&per_sample);
|
||||
|
||||
aclk_stats_query_threads(legacy_aclk_queries_per_thread_sample);
|
||||
|
||||
aclk_stats_cpu_threads();
|
||||
|
||||
#ifdef NETDATA_INTERNAL_CHECKS
|
||||
aclk_stats_mat_metric_process(&aclk_mat_metrics.latency, &per_sample.latency);
|
||||
#endif
|
||||
aclk_stats_mat_metric_process(&aclk_mat_metrics.cloud_q_db_query_time, &per_sample.cloud_q_db_query_time);
|
||||
aclk_stats_mat_metric_process(&aclk_mat_metrics.cloud_q_recvd_to_processed, &per_sample.cloud_q_recvd_to_processed);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void legacy_aclk_stats_upd_online(int online) {
|
||||
if(!aclk_stats_enabled)
|
||||
return;
|
||||
|
||||
LEGACY_ACLK_STATS_LOCK;
|
||||
legacy_aclk_metrics.online = online;
|
||||
|
||||
if(!online)
|
||||
legacy_aclk_metrics_per_sample.offline_during_sample = 1;
|
||||
LEGACY_ACLK_STATS_UNLOCK;
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#ifndef NETDATA_ACLK_STATS_H
|
||||
#define NETDATA_ACLK_STATS_H
|
||||
|
||||
#include "daemon/common.h"
|
||||
#include "libnetdata/libnetdata.h"
|
||||
#include "aclk_common.h"
|
||||
|
||||
#define ACLK_STATS_THREAD_NAME "ACLK_Stats"
|
||||
|
||||
extern netdata_mutex_t legacy_aclk_stats_mutex;
|
||||
|
||||
#define LEGACY_ACLK_STATS_LOCK netdata_mutex_lock(&legacy_aclk_stats_mutex)
|
||||
#define LEGACY_ACLK_STATS_UNLOCK netdata_mutex_unlock(&legacy_aclk_stats_mutex)
|
||||
|
||||
struct aclk_stats_thread {
|
||||
netdata_thread_t *thread;
|
||||
int query_thread_count;
|
||||
};
|
||||
|
||||
// preserve between samples
|
||||
struct legacy_aclk_metrics {
|
||||
volatile uint8_t online;
|
||||
};
|
||||
|
||||
//mat = max average total
|
||||
struct aclk_metric_mat_data {
|
||||
volatile uint32_t total;
|
||||
volatile uint32_t count;
|
||||
volatile uint32_t max;
|
||||
};
|
||||
|
||||
//mat = max average total
|
||||
struct aclk_metric_mat {
|
||||
char *name;
|
||||
char *title;
|
||||
RRDSET *st;
|
||||
RRDDIM *rd_avg;
|
||||
RRDDIM *rd_max;
|
||||
RRDDIM *rd_total;
|
||||
long prio;
|
||||
char *unit;
|
||||
};
|
||||
|
||||
extern struct aclk_mat_metrics {
|
||||
#ifdef NETDATA_INTERNAL_CHECKS
|
||||
struct aclk_metric_mat latency;
|
||||
#endif
|
||||
struct aclk_metric_mat cloud_q_db_query_time;
|
||||
struct aclk_metric_mat cloud_q_recvd_to_processed;
|
||||
} aclk_mat_metrics;
|
||||
|
||||
void legacy_aclk_metric_mat_update(struct aclk_metric_mat_data *metric, usec_t measurement);
|
||||
|
||||
#define ACLK_STATS_CLOUD_REQ_TYPE_CNT 7
|
||||
// if you change update cloud_req_type_names
|
||||
|
||||
int aclk_cloud_req_type_to_idx(const char *name);
|
||||
|
||||
// reset to 0 on every sample
|
||||
extern struct legacy_aclk_metrics_per_sample {
|
||||
/* in the unlikely event of ACLK disconnecting
|
||||
and reconnecting under 1 sampling rate
|
||||
we want to make sure we record the disconnection
|
||||
despite it being then seemingly longer in graph */
|
||||
volatile uint8_t offline_during_sample;
|
||||
|
||||
volatile uint32_t queries_queued;
|
||||
volatile uint32_t queries_dispatched;
|
||||
|
||||
volatile uint32_t write_q_added;
|
||||
volatile uint32_t write_q_consumed;
|
||||
|
||||
volatile uint32_t read_q_added;
|
||||
volatile uint32_t read_q_consumed;
|
||||
|
||||
volatile uint32_t cloud_req_ok;
|
||||
volatile uint32_t cloud_req_err;
|
||||
|
||||
volatile uint16_t cloud_req_v1;
|
||||
volatile uint16_t cloud_req_v2;
|
||||
|
||||
volatile uint16_t cloud_req_by_type[ACLK_STATS_CLOUD_REQ_TYPE_CNT];
|
||||
|
||||
#ifdef NETDATA_INTERNAL_CHECKS
|
||||
struct aclk_metric_mat_data latency;
|
||||
#endif
|
||||
struct aclk_metric_mat_data cloud_q_db_query_time;
|
||||
struct aclk_metric_mat_data cloud_q_recvd_to_processed;
|
||||
} legacy_aclk_metrics_per_sample;
|
||||
|
||||
extern uint32_t *legacy_aclk_queries_per_thread;
|
||||
extern struct rusage *rusage_per_thread;
|
||||
|
||||
void *legacy_aclk_stats_main_thread(void *ptr);
|
||||
void legacy_aclk_stats_thread_cleanup();
|
||||
void legacy_aclk_stats_upd_online(int online);
|
||||
|
||||
#endif /* NETDATA_ACLK_STATS_H */
|
File diff suppressed because it is too large
Load diff
|
@ -1,85 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#ifndef NETDATA_AGENT_CLOUD_LINK_H
|
||||
#define NETDATA_AGENT_CLOUD_LINK_H
|
||||
|
||||
#include "daemon/common.h"
|
||||
#include "mqtt.h"
|
||||
#include "aclk_common.h"
|
||||
|
||||
#define ACLK_CHART_TOPIC "outbound/meta"
|
||||
#define ACLK_ALARMS_TOPIC "outbound/alarms"
|
||||
#define ACLK_METADATA_TOPIC "outbound/meta"
|
||||
#define ACLK_COMMAND_TOPIC "inbound/cmd"
|
||||
#define ACLK_TOPIC_STRUCTURE "/agent/%s"
|
||||
|
||||
#define ACLK_MAX_BACKOFF_DELAY 1024 // maximum backoff delay in seconds
|
||||
|
||||
#define ACLK_INITIALIZATION_WAIT 60 // Wait for link to initialize in seconds (per msg)
|
||||
#define ACLK_INITIALIZATION_SLEEP_WAIT 1 // Wait time @ spin lock for MQTT initialization in seconds
|
||||
#define ACLK_PING_INTERVAL 60
|
||||
#define ACLK_LOOP_TIMEOUT 5 // seconds to wait for operations in the library loop
|
||||
|
||||
#define ACLK_MAX_TOPIC 255
|
||||
|
||||
#define ACLK_RECONNECT_DELAY 1 // reconnect delay -- with backoff strategy for now
|
||||
#define ACLK_DEFAULT_PORT 9002
|
||||
#define ACLK_DEFAULT_HOST "localhost"
|
||||
|
||||
#define ACLK_V2_PAYLOAD_SEPARATOR "\x0D\x0A\x0D\x0A"
|
||||
|
||||
struct aclk_request {
|
||||
char *type_id;
|
||||
char *msg_id;
|
||||
char *callback_topic;
|
||||
char *payload;
|
||||
int version;
|
||||
int min_version;
|
||||
int max_version;
|
||||
};
|
||||
|
||||
typedef enum aclk_init_action { ACLK_INIT, ACLK_REINIT } ACLK_INIT_ACTION;
|
||||
|
||||
void *legacy_aclk_main(void *ptr);
|
||||
|
||||
extern int aclk_send_message(char *sub_topic, char *message, char *msg_id);
|
||||
extern int aclk_send_message_bin(char *sub_topic, const void *message, size_t len, char *msg_id);
|
||||
|
||||
extern char *is_agent_claimed(void);
|
||||
extern void aclk_lws_wss_mqtt_layer_disconnect_notif();
|
||||
char *create_uuid();
|
||||
|
||||
// callbacks for agent cloud link
|
||||
int aclk_subscribe(char *topic, int qos);
|
||||
int legacy_cloud_to_agent_parse(JSON_ENTRY *e);
|
||||
void aclk_disconnect();
|
||||
void aclk_connect();
|
||||
|
||||
#ifdef ENABLE_ACLK
|
||||
int aclk_send_metadata(ACLK_METADATA_STATE state, RRDHOST *host);
|
||||
int legacy_aclk_send_info_metadata(ACLK_METADATA_STATE metadata_submitted, RRDHOST *host);
|
||||
void legacy_aclk_send_alarm_metadata(ACLK_METADATA_STATE metadata_submitted);
|
||||
|
||||
int aclk_wait_for_initialization();
|
||||
char *create_publish_base_topic();
|
||||
|
||||
int aclk_send_single_chart(RRDHOST *host, char *chart);
|
||||
int legacy_aclk_update_chart(RRDHOST *host, char *chart_name, int create);
|
||||
int legacy_aclk_update_alarm(RRDHOST *host, ALARM_ENTRY *ae);
|
||||
void aclk_create_header(BUFFER *dest, char *type, char *msg_id, time_t ts_secs, usec_t ts_us, int version);
|
||||
int legacy_aclk_handle_cloud_message(char *payload);
|
||||
void legacy_aclk_add_collector(RRDHOST *host, const char *plugin_name, const char *module_name);
|
||||
void legacy_aclk_del_collector(RRDHOST *host, const char *plugin_name, const char *module_name);
|
||||
void legacy_aclk_alarm_reload(void);
|
||||
unsigned long int aclk_reconnect_delay(int mode);
|
||||
extern void health_alarm_entry2json_nolock(BUFFER *wb, ALARM_ENTRY *ae, RRDHOST *host);
|
||||
|
||||
void legacy_aclk_host_state_update(RRDHOST *host, int connect);
|
||||
int aclk_send_info_child_connection(RRDHOST *host, ACLK_CMD cmd);
|
||||
void aclk_update_next_child_to_popcorn(void);
|
||||
|
||||
char *legacy_aclk_state(void);
|
||||
char *legacy_aclk_state_json(void);
|
||||
#endif
|
||||
|
||||
#endif //NETDATA_AGENT_CLOUD_LINK_H
|
|
@ -1,370 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include <libnetdata/json/json.h>
|
||||
#include "daemon/common.h"
|
||||
#include "mqtt.h"
|
||||
#include "aclk_lws_wss_client.h"
|
||||
#include "aclk_stats.h"
|
||||
#include "aclk_rx_msgs.h"
|
||||
|
||||
#include "agent_cloud_link.h"
|
||||
|
||||
#define ACLK_QOS 1
|
||||
|
||||
extern usec_t aclk_session_us;
|
||||
extern time_t aclk_session_sec;
|
||||
|
||||
inline const char *_link_strerror(int rc)
|
||||
{
|
||||
return mosquitto_strerror(rc);
|
||||
}
|
||||
|
||||
#ifdef NETDATA_INTERNAL_CHECKS
|
||||
static struct timeval sendTimes[1024];
|
||||
#endif
|
||||
|
||||
static struct mosquitto *mosq = NULL;
|
||||
|
||||
|
||||
void mqtt_message_callback(struct mosquitto *mosq, void *obj, const struct mosquitto_message *msg)
|
||||
{
|
||||
UNUSED(mosq);
|
||||
UNUSED(obj);
|
||||
|
||||
legacy_aclk_handle_cloud_message(msg->payload);
|
||||
}
|
||||
|
||||
void publish_callback(struct mosquitto *mosq, void *obj, int rc)
|
||||
{
|
||||
UNUSED(mosq);
|
||||
UNUSED(obj);
|
||||
UNUSED(rc);
|
||||
#ifdef NETDATA_INTERNAL_CHECKS
|
||||
struct timeval now, *orig;
|
||||
now_realtime_timeval(&now);
|
||||
orig = &sendTimes[ rc & 0x3ff ];
|
||||
int64_t diff = (now.tv_sec - orig->tv_sec) * USEC_PER_SEC + (now.tv_usec - orig->tv_usec);
|
||||
diff /= 1000;
|
||||
|
||||
info("Publish_callback: mid=%d latency=%" PRId64 "ms", rc, diff);
|
||||
|
||||
legacy_aclk_metric_mat_update(&legacy_aclk_metrics_per_sample.latency, diff);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
void connect_callback(struct mosquitto *mosq, void *obj, int rc)
|
||||
{
|
||||
UNUSED(mosq);
|
||||
UNUSED(obj);
|
||||
UNUSED(rc);
|
||||
|
||||
info("Connection to cloud established");
|
||||
aclk_connect();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void disconnect_callback(struct mosquitto *mosq, void *obj, int rc)
|
||||
{
|
||||
UNUSED(mosq);
|
||||
UNUSED(obj);
|
||||
UNUSED(rc);
|
||||
|
||||
if (netdata_exit)
|
||||
info("Connection to cloud terminated due to agent shutdown");
|
||||
else {
|
||||
errno = 0;
|
||||
error("Connection to cloud failed");
|
||||
}
|
||||
aclk_disconnect();
|
||||
|
||||
aclk_lws_wss_mqtt_layer_disconnect_notif();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void _show_mqtt_info()
|
||||
{
|
||||
int libmosq_major, libmosq_minor, libmosq_revision, libmosq_version;
|
||||
libmosq_version = mosquitto_lib_version(&libmosq_major, &libmosq_minor, &libmosq_revision);
|
||||
|
||||
info(
|
||||
"Detected libmosquitto library version %d, %d.%d.%d", libmosq_version, libmosq_major, libmosq_minor,
|
||||
libmosq_revision);
|
||||
}
|
||||
|
||||
size_t _mqtt_external_write_hook(void *buf, size_t count)
|
||||
{
|
||||
return aclk_lws_wss_client_write(buf, count);
|
||||
}
|
||||
|
||||
size_t _mqtt_external_read_hook(void *buf, size_t count)
|
||||
{
|
||||
return aclk_lws_wss_client_read(buf, count);
|
||||
}
|
||||
|
||||
int _mqtt_lib_init()
|
||||
{
|
||||
int rc;
|
||||
//int libmosq_major, libmosq_minor, libmosq_revision, libmosq_version;
|
||||
/* Commenting out now as it is unused - do not delete, this is needed for the on-prem version.
|
||||
char *ca_crt;
|
||||
char *server_crt;
|
||||
char *server_key;
|
||||
|
||||
// show library info so can have it in the logfile
|
||||
//libmosq_version = mosquitto_lib_version(&libmosq_major, &libmosq_minor, &libmosq_revision);
|
||||
ca_crt = config_get(CONFIG_SECTION_CLOUD, "link cert", "*");
|
||||
server_crt = config_get(CONFIG_SECTION_CLOUD, "link server cert", "*");
|
||||
server_key = config_get(CONFIG_SECTION_CLOUD, "link server key", "*");
|
||||
|
||||
if (ca_crt[0] == '*') {
|
||||
freez(ca_crt);
|
||||
ca_crt = NULL;
|
||||
}
|
||||
|
||||
if (server_crt[0] == '*') {
|
||||
freez(server_crt);
|
||||
server_crt = NULL;
|
||||
}
|
||||
|
||||
if (server_key[0] == '*') {
|
||||
freez(server_key);
|
||||
server_key = NULL;
|
||||
}
|
||||
*/
|
||||
|
||||
// info(
|
||||
// "Detected libmosquitto library version %d, %d.%d.%d", libmosq_version, libmosq_major, libmosq_minor,
|
||||
// libmosq_revision);
|
||||
|
||||
rc = mosquitto_lib_init();
|
||||
if (unlikely(rc != MOSQ_ERR_SUCCESS)) {
|
||||
error("Failed to initialize MQTT (libmosquitto library)");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _mqtt_create_connection(char *username, char *password)
|
||||
{
|
||||
if (mosq != NULL)
|
||||
mosquitto_destroy(mosq);
|
||||
mosq = mosquitto_new(username, true, NULL);
|
||||
if (unlikely(!mosq)) {
|
||||
mosquitto_lib_cleanup();
|
||||
error("MQTT new structure -- %s", mosquitto_strerror(errno));
|
||||
return MOSQ_ERR_UNKNOWN;
|
||||
}
|
||||
|
||||
// Record the session start time to allow a nominal LWT timestamp
|
||||
usec_t now = now_realtime_usec();
|
||||
aclk_session_sec = now / USEC_PER_SEC;
|
||||
aclk_session_us = now % USEC_PER_SEC;
|
||||
|
||||
_link_set_lwt("outbound/meta", 2);
|
||||
|
||||
mosquitto_connect_callback_set(mosq, connect_callback);
|
||||
mosquitto_disconnect_callback_set(mosq, disconnect_callback);
|
||||
mosquitto_publish_callback_set(mosq, publish_callback);
|
||||
|
||||
info("Using challenge-response: %s / %s", username, password);
|
||||
mosquitto_username_pw_set(mosq, username, password);
|
||||
|
||||
int rc = mosquitto_threaded_set(mosq, 1);
|
||||
if (unlikely(rc != MOSQ_ERR_SUCCESS))
|
||||
error("Failed to tune the thread model for libmosquitto (%s)", mosquitto_strerror(rc));
|
||||
|
||||
#if defined(LIBMOSQUITTO_VERSION_NUMBER) >= 1006000
|
||||
rc = mosquitto_int_option(mosq, MQTT_PROTOCOL_V311, 0);
|
||||
if (unlikely(rc != MOSQ_ERR_SUCCESS))
|
||||
error("MQTT protocol specification rc = %d (%s)", rc, mosquitto_strerror(rc));
|
||||
|
||||
rc = mosquitto_int_option(mosq, MOSQ_OPT_SEND_MAXIMUM, 1);
|
||||
info("MQTT in flight messages set to 1 -- %s", mosquitto_strerror(rc));
|
||||
#endif
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int _link_mqtt_connect(char *aclk_hostname, int aclk_port)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = mosquitto_connect_async(mosq, aclk_hostname, aclk_port, ACLK_PING_INTERVAL);
|
||||
|
||||
if (unlikely(rc != MOSQ_ERR_SUCCESS))
|
||||
error(
|
||||
"Failed to establish link to [%s:%d] MQTT status = %d (%s)", aclk_hostname, aclk_port, rc,
|
||||
mosquitto_strerror(rc));
|
||||
else
|
||||
info("Establishing MQTT link to [%s:%d]", aclk_hostname, aclk_port);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static inline void _link_mosquitto_write()
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (unlikely(!mosq)) {
|
||||
return;
|
||||
}
|
||||
|
||||
rc = mosquitto_loop_misc(mosq);
|
||||
if (unlikely(rc != MOSQ_ERR_SUCCESS))
|
||||
debug(D_ACLK, "ACLK: failure during mosquitto_loop_misc %s", mosquitto_strerror(rc));
|
||||
|
||||
if (likely(mosquitto_want_write(mosq))) {
|
||||
rc = mosquitto_loop_write(mosq, 1);
|
||||
if (rc != MOSQ_ERR_SUCCESS)
|
||||
debug(D_ACLK, "ACLK: failure during mosquitto_loop_write %s", mosquitto_strerror(rc));
|
||||
}
|
||||
}
|
||||
|
||||
void aclk_lws_connection_established(char *hostname, int port)
|
||||
{
|
||||
_link_mqtt_connect(hostname, port); // Parameters only used for logging, lower layer connected.
|
||||
_link_mosquitto_write();
|
||||
}
|
||||
|
||||
void aclk_lws_connection_data_received()
|
||||
{
|
||||
int rc = mosquitto_loop_read(mosq, 1);
|
||||
if (rc != MOSQ_ERR_SUCCESS)
|
||||
debug(D_ACLK, "ACLK: failure during mosquitto_loop_read %s", mosquitto_strerror(rc));
|
||||
}
|
||||
|
||||
void aclk_lws_connection_closed()
|
||||
{
|
||||
aclk_disconnect();
|
||||
|
||||
}
|
||||
|
||||
|
||||
int mqtt_attempt_connection(char *aclk_hostname, int aclk_port, char *username, char *password)
|
||||
{
|
||||
if(aclk_lws_wss_connect(aclk_hostname, aclk_port))
|
||||
return MOSQ_ERR_UNKNOWN;
|
||||
aclk_lws_wss_service_loop();
|
||||
|
||||
int rc = _mqtt_create_connection(username, password);
|
||||
if (rc!= MOSQ_ERR_SUCCESS)
|
||||
return rc;
|
||||
|
||||
mosquitto_external_callbacks_set(mosq, _mqtt_external_write_hook, _mqtt_external_read_hook);
|
||||
return rc;
|
||||
}
|
||||
|
||||
inline int _link_event_loop()
|
||||
{
|
||||
|
||||
// TODO: Check if we need to flush undelivered messages from libmosquitto on new connection attempts (QoS=1).
|
||||
_link_mosquitto_write();
|
||||
aclk_lws_wss_service_loop();
|
||||
|
||||
// this is because if use LWS we don't want
|
||||
// mqtt to reconnect by itself
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
void _link_shutdown()
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (likely(!mosq))
|
||||
return;
|
||||
|
||||
rc = mosquitto_disconnect(mosq);
|
||||
switch (rc) {
|
||||
case MOSQ_ERR_SUCCESS:
|
||||
info("MQTT disconnected from broker");
|
||||
break;
|
||||
default:
|
||||
info("MQTT invalid structure");
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
int _link_set_lwt(char *sub_topic, int qos)
|
||||
{
|
||||
int rc;
|
||||
char topic[ACLK_MAX_TOPIC + 1];
|
||||
char *final_topic;
|
||||
|
||||
final_topic = get_topic(sub_topic, topic, ACLK_MAX_TOPIC);
|
||||
if (unlikely(!final_topic)) {
|
||||
errno = 0;
|
||||
error("Unable to build outgoing topic; truncated?");
|
||||
return 1;
|
||||
}
|
||||
|
||||
usec_t lwt_time = aclk_session_sec * USEC_PER_SEC + aclk_session_us + 1;
|
||||
BUFFER *b = buffer_create(512);
|
||||
aclk_create_header(b, "disconnect", NULL, lwt_time / USEC_PER_SEC, lwt_time % USEC_PER_SEC, ACLK_VERSION_NEG_VERSION);
|
||||
buffer_strcat(b, ", \"payload\": \"unexpected\" }");
|
||||
rc = mosquitto_will_set(mosq, topic, buffer_strlen(b), buffer_tostring(b), qos, 0);
|
||||
buffer_free(b);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int _link_subscribe(char *topic, int qos)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (unlikely(!mosq))
|
||||
return 1;
|
||||
|
||||
mosquitto_message_callback_set(mosq, mqtt_message_callback);
|
||||
|
||||
rc = mosquitto_subscribe(mosq, NULL, topic, qos);
|
||||
if (unlikely(rc)) {
|
||||
errno = 0;
|
||||
error("Failed to register subscription %d (%s)", rc, mosquitto_strerror(rc));
|
||||
return 1;
|
||||
}
|
||||
|
||||
_link_mosquitto_write();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send a message to the cloud to specific topic
|
||||
*
|
||||
*/
|
||||
|
||||
int _link_send_message(char *topic, const void *message, size_t len, int *mid)
|
||||
{
|
||||
int rc;
|
||||
size_t write_q, write_q_bytes, read_q;
|
||||
|
||||
rc = mosquitto_pub_topic_check(topic);
|
||||
|
||||
if (unlikely(rc != MOSQ_ERR_SUCCESS))
|
||||
return rc;
|
||||
|
||||
lws_wss_check_queues(&write_q, &write_q_bytes, &read_q);
|
||||
rc = mosquitto_publish(mosq, mid, topic, len, message, ACLK_QOS, 0);
|
||||
|
||||
#ifdef NETDATA_INTERNAL_CHECKS
|
||||
char msg_head[64];
|
||||
memset(msg_head, 0, sizeof(msg_head));
|
||||
strncpy(msg_head, (char*)message, 60);
|
||||
for (size_t i = 0; i < sizeof(msg_head); i++)
|
||||
if(msg_head[i] == '\n') msg_head[i] = ' ';
|
||||
info("Sending MQTT len=%d mid=%d wq=%zu (%zu-bytes) readq=%zu: %s", (int)len,
|
||||
*mid, write_q, write_q_bytes, read_q, msg_head);
|
||||
now_realtime_timeval(&sendTimes[ *mid & 0x3ff ]);
|
||||
#endif
|
||||
|
||||
// TODO: Add better handling -- error will flood the logfile here
|
||||
if (unlikely(rc != MOSQ_ERR_SUCCESS)) {
|
||||
errno = 0;
|
||||
error("MQTT message failed : %s", mosquitto_strerror(rc));
|
||||
}
|
||||
_link_mosquitto_write();
|
||||
return rc;
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#ifndef NETDATA_MQTT_H
|
||||
#define NETDATA_MQTT_H
|
||||
|
||||
#ifdef ENABLE_ACLK
|
||||
#include "externaldeps/mosquitto/mosquitto.h"
|
||||
#endif
|
||||
|
||||
void _show_mqtt_info();
|
||||
int _link_event_loop();
|
||||
void _link_shutdown();
|
||||
int mqtt_attempt_connection(char *aclk_hostname, int aclk_port, char *username, char *password);
|
||||
//int _link_lib_init();
|
||||
int _mqtt_lib_init();
|
||||
int _link_subscribe(char *topic, int qos);
|
||||
int _link_send_message(char *topic, const void *message, size_t len, int *mid);
|
||||
const char *_link_strerror(int rc);
|
||||
int _link_set_lwt(char *topic, int qos);
|
||||
|
||||
|
||||
int legacy_aclk_handle_cloud_message(char *);
|
||||
extern char *get_topic(char *sub_topic, char *final_topic, int max_size);
|
||||
|
||||
#endif //NETDATA_MQTT_H
|
|
@ -1,24 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
sleep 45 # Wait until popcorning finishes
|
||||
|
||||
echo "CHART aclk_test.newcol '' 'Generate new collector/chart event' 'units' aclk_test aclk_test lines 900001 1"
|
||||
sleep 5
|
||||
echo "DIMENSION aclk1 '' percentage-of-absolute 1 1"
|
||||
sleep 5
|
||||
echo "BEGIN aclk_test.newcol 1000000"
|
||||
echo "SET aclk1 = 3"
|
||||
echo "END"
|
||||
sleep 5
|
||||
echo "DIMENSION aclk2 '' percentage-of-absolute 1 1"
|
||||
sleep 5
|
||||
echo "BEGIN aclk_test.newcol 1000000"
|
||||
echo "SET aclk1 = 3"
|
||||
echo "SET aclk2 = 3"
|
||||
echo "END"
|
||||
sleep 5
|
||||
echo "CHART aclk_test2.newcol '' 'Generate new collector/chart event' 'units' aclk_test aclk_test lines 900001 1"
|
||||
echo "DIMENSION aclk1 '' percentage-of-absolute 1 1"
|
||||
|
||||
sleep 5
|
||||
exit 0 # Signal that we are done
|
|
@ -1,6 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
TARGET="@pluginsdir_POST@"
|
||||
BASE="$(cd "$(dirname "$0")" && pwd)"
|
||||
|
||||
cp "$BASE/fake-charts.d.plugin" "$TARGET/charts.d.plugin"
|
|
@ -1,4 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
docker build -f paho.Dockerfile . --build-arg "HOST_HOSTNAME=$(ping -c1 "$(hostname).local" | head -n1 | grep -o '[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*')" -t paho-client
|
||||
docker run -it paho-client
|
|
@ -1,59 +0,0 @@
|
|||
import ssl
|
||||
import paho.mqtt.client as mqtt
|
||||
import json
|
||||
import time
|
||||
import sys
|
||||
|
||||
def on_connect(mqttc, obj, flags, rc):
|
||||
if rc==0:
|
||||
print("Successful connection", flush=True)
|
||||
else :
|
||||
print(f"Connection error rc={rc}", flush=True)
|
||||
mqttc.subscribe("/agent/#",0)
|
||||
|
||||
def on_disconnect(mqttc, obj, flags, rc):
|
||||
print("disconnected rc: "+str(rc), flush=True)
|
||||
|
||||
def on_message(mqttc, obj, msg):
|
||||
print(f"{msg.topic} {len(msg.payload)}-bytes qos={msg.qos}", flush=True)
|
||||
try:
|
||||
print(f"Trying decode of {msg.payload[:60]}",flush=True)
|
||||
api_msg = json.loads(msg.payload)
|
||||
except Exception as e:
|
||||
print(e,flush=True)
|
||||
return
|
||||
ts = api_msg["timestamp"]
|
||||
mtype = api_msg["type"]
|
||||
print(f"Message {mtype} time={ts} size {len(api_msg)}", flush=True)
|
||||
now = time.time()
|
||||
print(f"Current {now} -> Delay {now-ts}", flush=True)
|
||||
if mtype=="disconnect":
|
||||
print(f"Message dump: {api_msg}", flush=True)
|
||||
|
||||
def on_publish(mqttc, obj, mid):
|
||||
print("mid: "+str(mid), flush=True)
|
||||
|
||||
def on_subscribe(mqttc, obj, mid, granted_qos):
|
||||
print("Subscribed: "+str(mid)+" "+str(granted_qos), flush=True)
|
||||
|
||||
def on_log(mqttc, obj, level, string):
|
||||
print(string)
|
||||
|
||||
print(f"Starting paho-inspection on {sys.argv[1]}", flush=True)
|
||||
mqttc = mqtt.Client(transport='websockets',client_id="paho")
|
||||
#mqttc.tls_set(certfile="server.crt", keyfile="server.key", cert_reqs=ssl.CERT_REQUIRED, tls_version=ssl.PROTOCOL_TLS, ciphers=None)
|
||||
#mqttc.tls_set(ca_certs="server.crt", cert_reqs=ssl.CERT_REQUIRED, tls_version=ssl.PROTOCOL_TLS, ciphers=None)
|
||||
mqttc.tls_set(cert_reqs=ssl.CERT_NONE, tls_version=ssl.PROTOCOL_TLS, ciphers=None)
|
||||
mqttc.tls_insecure_set(True)
|
||||
mqttc.on_message = on_message
|
||||
mqttc.on_connect = on_connect
|
||||
mqttc.on_disconnect = on_disconnect
|
||||
mqttc.on_publish = on_publish
|
||||
mqttc.on_subscribe = on_subscribe
|
||||
mqttc.username_pw_set("paho","paho")
|
||||
mqttc.connect(sys.argv[1], 8443, 60)
|
||||
|
||||
#mqttc.publish("/agent/mine","Test1")
|
||||
#mqttc.subscribe("$SYS/#", 0)
|
||||
print("Connected successfully, monitoring /agent/#", flush=True)
|
||||
mqttc.loop_forever()
|
|
@ -1,14 +0,0 @@
|
|||
FROM archlinux/base:latest
|
||||
|
||||
RUN pacman -Syyu --noconfirm
|
||||
RUN pacman --noconfirm --needed -S python-pip
|
||||
|
||||
RUN pip install paho-mqtt
|
||||
|
||||
RUN mkdir -p /opt/paho
|
||||
COPY paho-inspection.py /opt/paho/
|
||||
|
||||
WORKDIR /opt/paho
|
||||
ARG HOST_HOSTNAME
|
||||
RUN echo $HOST_HOSTNAME >host
|
||||
CMD ["/bin/bash", "-c", "/usr/sbin/python paho-inspection.py $(cat host)"]
|
135
configure.ac
135
configure.ac
|
@ -212,22 +212,6 @@ AC_ARG_ENABLE(
|
|||
[ enable_cloud="detect" ]
|
||||
)
|
||||
|
||||
AC_ARG_WITH(
|
||||
[aclk-legacy],
|
||||
[AS_HELP_STRING([--with-aclk-legacy],
|
||||
[Requires Legacy ACLK to be used even in case ACLK-NG can run on this system])],
|
||||
[aclk_legacy="$withval"],
|
||||
[aclk_legacy="detect"]
|
||||
)
|
||||
|
||||
AC_ARG_WITH(
|
||||
[aclk-ng],
|
||||
[AS_HELP_STRING([--with-aclk-ng],
|
||||
[Requires ACLK-NG to be used even in case ACLK Legacy can run on this system])],
|
||||
[aclk_ng="$withval"],
|
||||
[aclk_ng="detect"]
|
||||
)
|
||||
|
||||
AC_ARG_WITH(
|
||||
[new-cloud-protocol],
|
||||
[AS_HELP_STRING([--with-new-cloud-protocol],
|
||||
|
@ -721,22 +705,8 @@ fi
|
|||
|
||||
AC_MSG_CHECKING([if Cloud functionality should be enabled])
|
||||
AC_MSG_RESULT([${enable_cloud}])
|
||||
if test "$aclk_ng" = "no"; then
|
||||
AC_DEFINE([ACLK_NG_DISABLED], [1], [ACLK NG was disabled by user request])
|
||||
fi
|
||||
if test "$aclk_legacy" = "no"; then
|
||||
AC_DEFINE([ACLK_LEGACY_DISABLED], [1], [ACLK Legacy was disabled by user request])
|
||||
fi
|
||||
|
||||
if test "$enable_cloud" = "no" -a "$aclk_legacy" = "yes"; then
|
||||
AC_MSG_ERROR([--disable-cloud && --with-aclk-legacy not allowed together (such configuration is self contradicting)])
|
||||
fi
|
||||
|
||||
if test "$enable_cloud" = "no" -a "$aclk_ng" = "yes"; then
|
||||
AC_MSG_ERROR([--disable-cloud && --with-aclk-ng not allowed together (such configuration is self contradicting)])
|
||||
fi
|
||||
|
||||
if test "$enable_cloud" != "no" -a "$aclk_ng" != "no"; then
|
||||
if test "$enable_cloud" != "no"; then
|
||||
AC_MSG_NOTICE([Checking if ACLK Next Generation can be built])
|
||||
can_enable_ng="yes"
|
||||
AC_MSG_CHECKING([if git submodules present for ACLK Next Generation])
|
||||
|
@ -764,18 +734,16 @@ if test "$enable_cloud" != "no" -a "$aclk_ng" != "no"; then
|
|||
|
||||
AC_MSG_CHECKING([ACLK Next Generation can be built])
|
||||
AC_MSG_RESULT([${can_enable_ng}])
|
||||
if test "$can_enable_ng" = "no" -a "$aclk_ng" = "yes"; then
|
||||
AC_MSG_ERROR([You have requested --with-aclk-ng but it can't be built. See reasons in lines above])
|
||||
if test "$can_enable_ng" = "no" -a "$enable_cloud" = "yes"; then
|
||||
AC_MSG_ERROR([You have requested --with-cloud but ACLK can't be built. See reasons in lines above])
|
||||
fi
|
||||
if test "$can_enable_ng" = "yes"; then
|
||||
aclk_ng="yes"
|
||||
enable_aclk="yes"
|
||||
AC_DEFINE([ACLK_NG], [1], [ACLK Next Generation Should be used])
|
||||
AC_DEFINE([ENABLE_ACLK], [1], [netdata ACLK])
|
||||
OPTIONAL_ACLK_NG_CFLAGS="-I \$(abs_top_srcdir)/mqtt_websockets/src/include -I \$(abs_top_srcdir)/mqtt_websockets/c-rbuf/include -I \$(abs_top_srcdir)/mqtt_websockets/MQTT-C/include"
|
||||
OPTIONAL_ACLK_CFLAGS="-I \$(abs_top_srcdir)/mqtt_websockets/src/include -I \$(abs_top_srcdir)/mqtt_websockets/c-rbuf/include -I \$(abs_top_srcdir)/mqtt_websockets/MQTT-C/include"
|
||||
fi
|
||||
|
||||
if test "$aclk_ng" = "yes" -a "$new_cloud_protocol" != "no"; then
|
||||
if "$new_cloud_protocol" != "no"; then
|
||||
can_build_new_cloud_protocol="yes"
|
||||
AC_MSG_CHECKING([if protobuf available for New Cloud Protocol])
|
||||
if test "${have_libprotobuf}" != "yes"; then
|
||||
|
@ -807,7 +775,7 @@ if test "$enable_cloud" != "no" -a "$aclk_ng" != "no"; then
|
|||
if test "$can_build_new_cloud_protocol" = "yes"; then
|
||||
new_cloud_protocol="yes"
|
||||
AC_DEFINE([ENABLE_NEW_CLOUD_PROTOCOL], [1], [New protobuf based Netdata Cloud Protocol Support])
|
||||
OPTIONAL_ACLK_NG_CFLAGS="${OPTIONAL_ACLK_NG_CFLAGS} -I \$(abs_top_srcdir)/aclk/aclk-schemas"
|
||||
OPTIONAL_ACLK_CFLAGS="${OPTIONAL_ACLK_CFLAGS} -I \$(abs_top_srcdir)/aclk/aclk-schemas"
|
||||
OPTIONAL_PROTOBUF_CFLAGS="${PROTOBUF_CFLAGS}"
|
||||
CXX11FLAG="-std=c++11"
|
||||
OPTIONAL_PROTOBUF_LIBS="${PROTOBUF_LIBS}"
|
||||
|
@ -815,96 +783,12 @@ if test "$enable_cloud" != "no" -a "$aclk_ng" != "no"; then
|
|||
fi
|
||||
fi
|
||||
|
||||
if test "$enable_cloud" != "no" -a "$aclk_legacy" != "no"; then
|
||||
AC_MSG_NOTICE([Checking if ACLK Legacy can be built])
|
||||
if test -n "${SSL_LIBS}"; then
|
||||
OPTIONAL_SSL_CFLAGS="${SSL_CFLAGS}"
|
||||
OPTIONAL_SSL_LIBS="${SSL_LIBS}"
|
||||
else
|
||||
AC_MSG_WARN([OpenSSL required for agent-cloud-link but not found. Try installing 'libssl-dev' or 'openssl-devel'.])
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([if libmosquitto static lib is present (and builds)])
|
||||
if test -f "externaldeps/mosquitto/libmosquitto.a"; then
|
||||
LIBS_BKP="${LIBS}"
|
||||
LIBS="externaldeps/mosquitto/libmosquitto.a ${OPTIONAL_SSL_LIBS} ${LIBS_BKP}"
|
||||
AC_LINK_IFELSE([AC_LANG_SOURCE([[#include "externaldeps/mosquitto/mosquitto.h"
|
||||
int main (int argc, char **argv) {
|
||||
int m,mm,r;
|
||||
mosquitto_lib_version(&m, &mm, &r);
|
||||
}]])],
|
||||
[HAVE_libmosquitto_a="yes"],
|
||||
[HAVE_libmosquitto_a="no"])
|
||||
LIBS="${LIBS_BKP}"
|
||||
else
|
||||
HAVE_libmosquitto_a="no"
|
||||
AC_DEFINE([ACLK_NO_LIBMOSQ], [1], [Libmosquitto.a was not found during build.])
|
||||
fi
|
||||
AC_MSG_RESULT([${HAVE_libmosquitto_a}])
|
||||
|
||||
if test "${with_bundled_lws}" = "yes"; then
|
||||
AC_MSG_CHECKING([if libwebsockets static lib is present for ACLK Legacy])
|
||||
if test -f "externaldeps/libwebsockets/libwebsockets.a"; then
|
||||
LWS_CFLAGS="-I \$(abs_top_srcdir)/externaldeps/libwebsockets/include"
|
||||
OPTIONAL_LWS_LIBS="\$(abs_top_srcdir)/externaldeps/libwebsockets/libwebsockets.a"
|
||||
AC_MSG_RESULT([yes])
|
||||
AC_DEFINE([BUNDLED_LWS], [1], [using statically linked libwebsockets])
|
||||
else
|
||||
AC_DEFINE([ACLK_NO_LWS], [1], [libwebsockets.a was not found during build.])
|
||||
# this should be error if installer ever changes default to system
|
||||
# as currently this is default we prefer building netdata without ACLK
|
||||
# instead of error fail
|
||||
AC_MSG_RESULT([no])
|
||||
AC_MSG_WARN([You required static libwebsockets to be used but we can't use it. Disabling ACLK Legacy])
|
||||
fi
|
||||
else
|
||||
AC_CHECK_LIB([websockets],
|
||||
[lws_get_vhost_by_name],
|
||||
[OPTIONAL_LWS_LIBS="-lwebsockets"],
|
||||
[AC_DEFINE([ACLK_NO_LWS], [1], [usable system libwebsockets was not found during build.])])
|
||||
fi
|
||||
|
||||
if test "${build_target}" = "linux"; then
|
||||
if test "${have_libcap}" = "yes" -a "${with_libcap}" = "no"; then
|
||||
AC_MSG_ERROR([agent-cloud-link can't be built without libcap. Disable it by --disable-cloud or enable libcap])
|
||||
fi
|
||||
if test "${with_libcap}" = "yes"; then
|
||||
LWS_CFLAGS+=" ${LIBCAP_CFLAGS}"
|
||||
fi
|
||||
fi
|
||||
|
||||
# next 2 lines are just to have info for ACLK dependencies in common place
|
||||
AC_MSG_CHECKING([if json-c available for ACLK Legacy])
|
||||
AC_MSG_RESULT([${enable_jsonc}])
|
||||
|
||||
AC_MSG_CHECKING([if netdata ACLK Legacy can be built])
|
||||
if test "${HAVE_libmosquitto_a}" = "yes" -a -n "${OPTIONAL_LWS_LIBS}" -a -n "${SSL_LIBS}" -a "${enable_jsonc}" = "yes"; then
|
||||
can_build_legacy="yes"
|
||||
else
|
||||
can_build_legacy="no"
|
||||
fi
|
||||
AC_MSG_RESULT([${can_build_legacy}])
|
||||
|
||||
if test "$can_build_legacy" = "no" -a "$aclk_legacy" = "yes"; then
|
||||
AC_MSG_ERROR([You have requested --with-aclk-legacy but it can't be built. See reasons in lines above])
|
||||
fi
|
||||
|
||||
if test "$can_build_legacy" = "yes"; then
|
||||
AC_DEFINE([ACLK_LEGACY], [1], [ACLK Legacy Should be used])
|
||||
AC_DEFINE([ENABLE_ACLK], [1], [netdata ACLK])
|
||||
aclk_legacy="yes"
|
||||
enable_aclk="yes"
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "$enable_cloud" = "yes" -a "$enable_aclk" != "yes"; then
|
||||
AC_MSG_ERROR([Neither ACLK-NG nor ACLK-Legacy can be built but --enable-cloud was requested])
|
||||
AC_MSG_ERROR([ACLK can't be built but --enable-cloud was requested])
|
||||
fi
|
||||
|
||||
AC_SUBST([enable_cloud])
|
||||
AC_SUBST([enable_aclk])
|
||||
AM_CONDITIONAL([ACLK_NG], [test "${aclk_ng}" = "yes"])
|
||||
AM_CONDITIONAL([ACLK_LEGACY], [test "${aclk_legacy}" = "yes"])
|
||||
AM_CONDITIONAL([ENABLE_ACLK], [test "${enable_aclk}" = "yes"])
|
||||
AM_CONDITIONAL([ENABLE_NEW_CLOUD_PROTOCOL], [test "${can_build_new_cloud_protocol}" = "yes"])
|
||||
|
||||
|
@ -1703,7 +1587,7 @@ CFLAGS="${CFLAGS} ${OPTIONAL_PROTOBUF_CFLAGS} ${OPTIONAL_MATH_CFLAGS} ${OPTIONAL
|
|||
${OPTIONAL_LIBCAP_CFLAGS} ${OPTIONAL_IPMIMONITORING_CFLAGS} ${OPTIONAL_CUPS_CFLAGS} ${OPTIONAL_XENSTAT_FLAGS} \
|
||||
${OPTIONAL_KINESIS_CFLAGS} ${OPTIONAL_PUBSUB_CFLAGS} ${OPTIONAL_PROMETHEUS_REMOTE_WRITE_CFLAGS} \
|
||||
${OPTIONAL_MONGOC_CFLAGS} ${LWS_CFLAGS} ${OPTIONAL_JSONC_STATIC_CFLAGS} ${OPTIONAL_BPF_CFLAGS} ${OPTIONAL_JUDY_CFLAGS} \
|
||||
${OPTIONAL_ACLK_NG_CFLAGS} ${OPTIONAL_ML_CFLAGS} ${OPTIONAL_ML_TESTS_CFLAGS}"
|
||||
${OPTIONAL_ACLK_CFLAGS} ${OPTIONAL_ML_CFLAGS} ${OPTIONAL_ML_TESTS_CFLAGS}"
|
||||
|
||||
CXXFLAGS="${CFLAGS} ${CXX11FLAG}"
|
||||
|
||||
|
@ -1753,7 +1637,7 @@ AC_SUBST([OPTIONAL_PROMETHEUS_REMOTE_WRITE_LIBS])
|
|||
AC_SUBST([OPTIONAL_MONGOC_CFLAGS])
|
||||
AC_SUBST([OPTIONAL_MONGOC_LIBS])
|
||||
AC_SUBST([OPTIONAL_LWS_LIBS])
|
||||
AC_SUBST([OPTIONAL_ACLK_NG_CFLAGS])
|
||||
AC_SUBST([OPTIONAL_ACLK_CFLAGS])
|
||||
AC_SUBST([OPTIONAL_PROTOBUF_CFLAGS])
|
||||
AC_SUBST([OPTIONAL_PROTOBUF_LIBS])
|
||||
AC_SUBST([OPTIONAL_GTEST_CFLAGS])
|
||||
|
@ -1907,7 +1791,6 @@ AC_CONFIG_FILES([
|
|||
web/server/Makefile
|
||||
web/server/static/Makefile
|
||||
claim/Makefile
|
||||
aclk/legacy/Makefile
|
||||
spawn/Makefile
|
||||
parser/Makefile
|
||||
])
|
||||
|
|
|
@ -41,15 +41,13 @@ override_dh_installinit:
|
|||
dh_installinit
|
||||
|
||||
override_dh_auto_configure:
|
||||
packaging/bundle-mosquitto.sh .
|
||||
packaging/bundle-lws.sh .
|
||||
if [ $(HAVE_EBPF) -eq 1 ]; then \
|
||||
packaging/bundle-libbpf.sh . ${TOP}/usr/libexec/netdata/plugins.d; \
|
||||
fi
|
||||
autoreconf -ivf
|
||||
dh_auto_configure -- --prefix=/usr --sysconfdir=/etc --localstatedir=/var --libdir=/usr/lib \
|
||||
--libexecdir=/usr/libexec --with-user=netdata --with-math --with-zlib --with-webdir=/var/lib/netdata/www \
|
||||
--with-bundled-lws $(EBPF_CONFIG)
|
||||
$(EBPF_CONFIG)
|
||||
|
||||
override_dh_install:
|
||||
cp -v $(BASE_CONFIG) debian/netdata.conf
|
||||
|
|
|
@ -494,10 +494,7 @@ void analytics_misc(void)
|
|||
{
|
||||
#ifdef ENABLE_ACLK
|
||||
analytics_set_data(&analytics_data.netdata_host_cloud_available, "true");
|
||||
if (aclk_ng)
|
||||
analytics_set_data_str(&analytics_data.netdata_host_aclk_implementation, "Next Generation");
|
||||
else
|
||||
analytics_set_data_str(&analytics_data.netdata_host_aclk_implementation, "legacy");
|
||||
analytics_set_data_str(&analytics_data.netdata_host_aclk_implementation, "Next Generation");
|
||||
#else
|
||||
analytics_set_data(&analytics_data.netdata_host_cloud_available, "false");
|
||||
analytics_set_data_str(&analytics_data.netdata_host_aclk_implementation, "");
|
||||
|
|
|
@ -19,24 +19,12 @@
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef ACLK_NG
|
||||
#define FEAT_ACLK_NG 1
|
||||
#else
|
||||
#define FEAT_ACLK_NG 0
|
||||
#endif
|
||||
|
||||
#if defined(ACLK_NG) && defined(ENABLE_NEW_CLOUD_PROTOCOL)
|
||||
#ifdef ENABLE_NEW_CLOUD_PROTOCOL
|
||||
#define NEW_CLOUD_PROTO 1
|
||||
#else
|
||||
#define NEW_CLOUD_PROTO 0
|
||||
#endif
|
||||
|
||||
#ifdef ACLK_LEGACY
|
||||
#define FEAT_ACLK_LEGACY 1
|
||||
#else
|
||||
#define FEAT_ACLK_LEGACY 0
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_DBENGINE
|
||||
#define FEAT_DBENGINE 1
|
||||
#else
|
||||
|
@ -104,30 +92,6 @@
|
|||
#define FEAT_LIBCAP 0
|
||||
#endif
|
||||
|
||||
#ifndef ACLK_LEGACY_DISABLED
|
||||
#ifdef ACLK_NO_LIBMOSQ
|
||||
#define FEAT_MOSQUITTO 0
|
||||
#else
|
||||
#define FEAT_MOSQUITTO 1
|
||||
#endif
|
||||
|
||||
#ifdef ACLK_NO_LWS
|
||||
#define FEAT_LWS 0
|
||||
#define FEAT_LWS_MSG ""
|
||||
#else
|
||||
#ifdef ACLK_LEGACY
|
||||
#include <libwebsockets.h>
|
||||
#endif
|
||||
#ifdef BUNDLED_LWS
|
||||
#define FEAT_LWS 1
|
||||
#define FEAT_LWS_MSG "static"
|
||||
#else
|
||||
#define FEAT_LWS 1
|
||||
#define FEAT_LWS_MSG "shared-lib"
|
||||
#endif
|
||||
#endif
|
||||
#endif /* ACLK_LEGACY_DISABLED */
|
||||
|
||||
#ifdef NETDATA_WITH_ZLIB
|
||||
#define FEAT_ZLIB 1
|
||||
#else
|
||||
|
@ -243,9 +207,9 @@ void print_build_info(void) {
|
|||
printf(" dbengine: %s\n", FEAT_YES_NO(FEAT_DBENGINE));
|
||||
printf(" Native HTTPS: %s\n", FEAT_YES_NO(FEAT_NATIVE_HTTPS));
|
||||
printf(" Netdata Cloud: %s %s\n", FEAT_YES_NO(FEAT_CLOUD), FEAT_CLOUD_MSG);
|
||||
printf(" ACLK Next Generation: %s\n", FEAT_YES_NO(FEAT_ACLK_NG));
|
||||
printf(" ACLK Next Generation: %s\n", FEAT_YES_NO(FEAT_CLOUD));
|
||||
printf(" ACLK-NG New Cloud Protocol: %s\n", FEAT_YES_NO(NEW_CLOUD_PROTO));
|
||||
printf(" ACLK Legacy: %s\n", FEAT_YES_NO(FEAT_ACLK_LEGACY));
|
||||
printf(" ACLK Legacy: %s\n", FEAT_YES_NO(0));
|
||||
printf(" TLS Host Verification: %s\n", FEAT_YES_NO(FEAT_TLS_HOST_VERIFY));
|
||||
printf(" Machine Learning: %s\n", FEAT_YES_NO(FEAT_ML));
|
||||
|
||||
|
@ -256,14 +220,6 @@ void print_build_info(void) {
|
|||
printf(" libcap: %s\n", FEAT_YES_NO(FEAT_LIBCAP));
|
||||
printf(" libcrypto: %s\n", FEAT_YES_NO(FEAT_CRYPTO));
|
||||
printf(" libm: %s\n", FEAT_YES_NO(FEAT_LIBM));
|
||||
#ifndef ACLK_LEGACY_DISABLED
|
||||
#if defined(ACLK_LEGACY)
|
||||
printf(" LWS: %s %s v%d.%d.%d\n", FEAT_YES_NO(FEAT_LWS), FEAT_LWS_MSG, LWS_LIBRARY_VERSION_MAJOR, LWS_LIBRARY_VERSION_MINOR, LWS_LIBRARY_VERSION_PATCH);
|
||||
#else
|
||||
printf(" LWS: %s %s\n", FEAT_YES_NO(FEAT_LWS), FEAT_LWS_MSG);
|
||||
#endif
|
||||
printf(" mosquitto: %s\n", FEAT_YES_NO(FEAT_MOSQUITTO));
|
||||
#endif
|
||||
printf(" tcalloc: %s\n", FEAT_YES_NO(FEAT_TCMALLOC));
|
||||
printf(" zlib: %s\n", FEAT_YES_NO(FEAT_ZLIB));
|
||||
|
||||
|
@ -303,9 +259,9 @@ void print_build_info_json(void) {
|
|||
#else
|
||||
printf(" \"cloud-disabled\": false,\n");
|
||||
#endif
|
||||
printf(" \"aclk-ng\": %s,\n", FEAT_JSON_BOOL(FEAT_ACLK_NG));
|
||||
printf(" \"aclk-ng\": %s,\n", FEAT_JSON_BOOL(FEAT_CLOUD));
|
||||
printf(" \"aclk-ng-new-cloud-proto\": %s,\n", FEAT_JSON_BOOL(NEW_CLOUD_PROTO));
|
||||
printf(" \"aclk-legacy\": %s,\n", FEAT_JSON_BOOL(FEAT_ACLK_LEGACY));
|
||||
printf(" \"aclk-legacy\": %s,\n", FEAT_JSON_BOOL(0));
|
||||
|
||||
printf(" \"tls-host-verify\": %s,\n", FEAT_JSON_BOOL(FEAT_TLS_HOST_VERIFY));
|
||||
printf(" \"machine-learning\": %s\n", FEAT_JSON_BOOL(FEAT_ML));
|
||||
|
@ -319,16 +275,6 @@ void print_build_info_json(void) {
|
|||
printf(" \"libcap\": %s,\n", FEAT_JSON_BOOL(FEAT_LIBCAP));
|
||||
printf(" \"libcrypto\": %s,\n", FEAT_JSON_BOOL(FEAT_CRYPTO));
|
||||
printf(" \"libm\": %s,\n", FEAT_JSON_BOOL(FEAT_LIBM));
|
||||
#ifndef ACLK_NG
|
||||
#if defined(ENABLE_ACLK)
|
||||
printf(" \"lws\": %s,\n", FEAT_JSON_BOOL(FEAT_LWS));
|
||||
printf(" \"lws-version\": \"%d.%d.%d\",\n", LWS_LIBRARY_VERSION_MAJOR, LWS_LIBRARY_VERSION_MINOR, LWS_LIBRARY_VERSION_PATCH);
|
||||
printf(" \"lws-type\": \"%s\",\n", FEAT_LWS_MSG);
|
||||
#else
|
||||
printf(" \"lws\": %s,\n", FEAT_JSON_BOOL(FEAT_LWS));
|
||||
#endif
|
||||
printf(" \"mosquitto\": %s,\n", FEAT_JSON_BOOL(FEAT_MOSQUITTO));
|
||||
#endif
|
||||
printf(" \"tcmalloc\": %s,\n", FEAT_JSON_BOOL(FEAT_TCMALLOC));
|
||||
printf(" \"zlib\": %s\n", FEAT_JSON_BOOL(FEAT_ZLIB));
|
||||
printf(" },\n");
|
||||
|
@ -361,9 +307,8 @@ void analytics_build_info(BUFFER *b) {
|
|||
if(FEAT_DBENGINE) buffer_strcat (b, "dbengine");
|
||||
if(FEAT_NATIVE_HTTPS) buffer_strcat (b, "|Native HTTPS");
|
||||
if(FEAT_CLOUD) buffer_strcat (b, "|Netdata Cloud");
|
||||
if(FEAT_ACLK_NG) buffer_strcat (b, "|ACLK Next Generation");
|
||||
if(FEAT_CLOUD) buffer_strcat (b, "|ACLK Next Generation");
|
||||
if(NEW_CLOUD_PROTO) buffer_strcat (b, "|New Cloud Protocol Support");
|
||||
if(FEAT_ACLK_LEGACY) buffer_strcat (b, "|ACLK Legacy");
|
||||
if(FEAT_TLS_HOST_VERIFY) buffer_strcat (b, "|TLS Host Verification");
|
||||
if(FEAT_ML) buffer_strcat (b, "|Machine Learning");
|
||||
|
||||
|
@ -374,18 +319,6 @@ void analytics_build_info(BUFFER *b) {
|
|||
if(FEAT_CRYPTO) buffer_strcat (b, "|libcrypto");
|
||||
if(FEAT_LIBM) buffer_strcat (b, "|libm");
|
||||
|
||||
#ifndef ACLK_LEGACY_DISABLED
|
||||
#if defined(ENABLE_ACLK) && defined(ACLK_LEGACY)
|
||||
{
|
||||
char buf[20];
|
||||
snprintfz(buf, 19, "|LWS v%d.%d.%d", LWS_LIBRARY_VERSION_MAJOR, LWS_LIBRARY_VERSION_MINOR, LWS_LIBRARY_VERSION_PATCH);
|
||||
if(FEAT_LWS) buffer_strcat(b, buf);
|
||||
}
|
||||
#else
|
||||
if(FEAT_LWS) buffer_strcat(b, "|LWS");
|
||||
#endif
|
||||
if(FEAT_MOSQUITTO) buffer_strcat(b, "|mosquitto");
|
||||
#endif
|
||||
if(FEAT_TCMALLOC) buffer_strcat(b, "|tcalloc");
|
||||
if(FEAT_ZLIB) buffer_strcat(b, "|zlib");
|
||||
|
||||
|
|
|
@ -216,7 +216,6 @@ USAGE: ${PROGRAM} [options]
|
|||
--disable-ebpf Disable eBPF Kernel plugin (Default: enabled)
|
||||
--disable-cloud Disable all Netdata Cloud functionality.
|
||||
--require-cloud Fail the install if it can't build Netdata Cloud support.
|
||||
--aclk-legacy Forces build of ACLK Legacy which is fallback by default.
|
||||
--enable-plugin-freeipmi Enable the FreeIPMI plugin. Default: enable it when libipmimonitoring is available.
|
||||
--disable-plugin-freeipmi
|
||||
--disable-https Explicitly disable TLS support
|
||||
|
@ -344,10 +343,6 @@ while [ -n "${1}" ]; do
|
|||
"--enable-ebpf") NETDATA_DISABLE_EBPF=0 ;;
|
||||
"--disable-ebpf") NETDATA_DISABLE_EBPF=1 NETDATA_CONFIGURE_OPTIONS="${NETDATA_CONFIGURE_OPTIONS//--disable-ebpf/} --disable-ebpf" ;;
|
||||
"--skip-available-ram-check") SKIP_RAM_CHECK=1 ;;
|
||||
"--aclk-ng") ;;
|
||||
"--aclk-legacy")
|
||||
NETDATA_CONFIGURE_OPTIONS="${NETDATA_CONFIGURE_OPTIONS//--with-aclk-legacy/} --with-aclk-legacy"
|
||||
;;
|
||||
"--disable-cloud")
|
||||
if [ -n "${NETDATA_REQUIRE_CLOUD}" ]; then
|
||||
echo "Cloud explicitly enabled, ignoring --disable-cloud."
|
||||
|
@ -610,187 +605,6 @@ trap build_error EXIT
|
|||
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
build_libmosquitto() {
|
||||
local env_cmd=''
|
||||
|
||||
if [ -z "${DONT_SCRUB_CFLAGS_EVEN_THOUGH_IT_MAY_BREAK_THINGS}" ]; then
|
||||
env_cmd="env CFLAGS=-fPIC CXXFLAGS= LDFLAGS="
|
||||
fi
|
||||
|
||||
if [ "$(uname -s)" = Linux ]; then
|
||||
run ${env_cmd} ${make} ${MAKEOPTS} -C "${1}/lib"
|
||||
else
|
||||
pushd ${1} > /dev/null || return 1
|
||||
if [ "$(uname)" = "Darwin" ] && [ -d /usr/local/opt/openssl ]; then
|
||||
run ${env_cmd} cmake \
|
||||
-D OPENSSL_ROOT_DIR=/usr/local/opt/openssl \
|
||||
-D OPENSSL_LIBRARIES=/usr/local/opt/openssl/lib \
|
||||
-D WITH_STATIC_LIBRARIES:boolean=YES \
|
||||
.
|
||||
else
|
||||
run ${env_cmd} cmake -D WITH_STATIC_LIBRARIES:boolean=YES .
|
||||
fi
|
||||
run ${env_cmd} ${make} ${MAKEOPTS} -C lib
|
||||
run mv lib/libmosquitto_static.a lib/libmosquitto.a
|
||||
popd || return 1
|
||||
fi
|
||||
}
|
||||
|
||||
copy_libmosquitto() {
|
||||
target_dir="${PWD}/externaldeps/mosquitto"
|
||||
|
||||
run mkdir -p "${target_dir}"
|
||||
|
||||
run cp "${1}/lib/libmosquitto.a" "${target_dir}"
|
||||
run cp "${1}/lib/mosquitto.h" "${target_dir}"
|
||||
}
|
||||
|
||||
bundle_libmosquitto() {
|
||||
if [ -n "${NETDATA_DISABLE_CLOUD}" ]; then
|
||||
echo "Skipping libmosquitto"
|
||||
return 0
|
||||
fi
|
||||
|
||||
[ -n "${GITHUB_ACTIONS}" ] && echo "::group::Bundling libmosquitto."
|
||||
|
||||
progress "Prepare custom libmosquitto version"
|
||||
|
||||
MOSQUITTO_PACKAGE_VERSION="$(cat packaging/mosquitto.version)"
|
||||
|
||||
tmp="$(mktemp -d -t netdata-mosquitto-XXXXXX)"
|
||||
MOSQUITTO_PACKAGE_BASENAME="${MOSQUITTO_PACKAGE_VERSION}.tar.gz"
|
||||
|
||||
if fetch_and_verify "mosquitto" \
|
||||
"https://github.com/netdata/mosquitto/archive/${MOSQUITTO_PACKAGE_BASENAME}" \
|
||||
"${MOSQUITTO_PACKAGE_BASENAME}" \
|
||||
"${tmp}" \
|
||||
"${NETDATA_LOCAL_TARBALL_OVERRIDE_MOSQUITTO}"; then
|
||||
if run tar -xf "${tmp}/${MOSQUITTO_PACKAGE_BASENAME}" -C "${tmp}" &&
|
||||
build_libmosquitto "${tmp}/mosquitto-${MOSQUITTO_PACKAGE_VERSION}" &&
|
||||
copy_libmosquitto "${tmp}/mosquitto-${MOSQUITTO_PACKAGE_VERSION}" &&
|
||||
rm -rf "${tmp}"; then
|
||||
run_ok "libmosquitto built and prepared."
|
||||
else
|
||||
run_failed "Failed to build libmosquitto."
|
||||
defer_error_highlighted "Unable to fetch sources for libmosquitto. You will not be able to connect this node to Netdata Cloud."
|
||||
fi
|
||||
else
|
||||
run_failed "Unable to fetch sources for libmosquitto."
|
||||
defer_error_highlighted "Unable to fetch sources for libmosquitto. You will not be able to connect this node to Netdata Cloud."
|
||||
fi
|
||||
|
||||
[ -n "${GITHUB_ACTIONS}" ] && echo "::endgroup::"
|
||||
}
|
||||
|
||||
bundle_libmosquitto
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
build_libwebsockets() {
|
||||
local env_cmd=''
|
||||
|
||||
if [ -z "${DONT_SCRUB_CFLAGS_EVEN_THOUGH_IT_MAY_BREAK_THINGS}" ]; then
|
||||
env_cmd="env CFLAGS=-fPIC CXXFLAGS= LDFLAGS="
|
||||
fi
|
||||
|
||||
pushd "${1}" > /dev/null || exit 1
|
||||
|
||||
if [ "$(uname)" = "Darwin" ]; then
|
||||
run patch -p1 << "EOF"
|
||||
--- a/lib/plat/unix/private.h
|
||||
+++ b/lib/plat/unix/private.h
|
||||
@@ -164,6 +164,8 @@ delete_from_fd(const struct lws_context *context, int fd);
|
||||
* but happily have something equivalent in the SO_NOSIGPIPE flag.
|
||||
*/
|
||||
#ifdef __APPLE__
|
||||
+/* iOS SDK 12+ seems to define it, undef it for compatibility both ways */
|
||||
+#undef MSG_NOSIGNAL
|
||||
#define MSG_NOSIGNAL SO_NOSIGPIPE
|
||||
#endif
|
||||
EOF
|
||||
|
||||
# shellcheck disable=SC2181
|
||||
if [ $? -ne 0 ]; then
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$(uname)" = "Darwin" ] && [ -d /usr/local/opt/openssl ]; then
|
||||
run ${env_cmd} cmake \
|
||||
-D OPENSSL_ROOT_DIR=/usr/local/opt/openssl \
|
||||
-D OPENSSL_LIBRARIES=/usr/local/opt/openssl/lib \
|
||||
-D LWS_WITH_SOCKS5:bool=ON \
|
||||
-D LWS_IPV6:bool=ON \
|
||||
$CMAKE_FLAGS \
|
||||
.
|
||||
else
|
||||
run ${env_cmd} cmake \
|
||||
-D LWS_WITH_SOCKS5:bool=ON \
|
||||
-D LWS_IPV6:bool=ON \
|
||||
$CMAKE_FLAGS \
|
||||
.
|
||||
fi
|
||||
run ${env_cmd} ${make} ${MAKEOPTS}
|
||||
popd > /dev/null || exit 1
|
||||
}
|
||||
|
||||
copy_libwebsockets() {
|
||||
target_dir="${PWD}/externaldeps/libwebsockets"
|
||||
|
||||
run mkdir -p "${target_dir}" || return 1
|
||||
|
||||
run cp "${1}/lib/libwebsockets.a" "${target_dir}/libwebsockets.a" || return 1
|
||||
run cp -r "${1}/include" "${target_dir}" || return 1
|
||||
}
|
||||
|
||||
bundle_libwebsockets() {
|
||||
if [ -n "${NETDATA_DISABLE_CLOUD}" ] || [ -n "${USE_SYSTEM_LWS}" ]; then
|
||||
echo "Skipping libwebsockets"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [ -z "$(command -v cmake)" ]; then
|
||||
run_failed "Could not find cmake, which is required to build libwebsockets. The install process will continue, but you may not be able to connect this node to Netdata Cloud."
|
||||
defer_error_highlighted "Could not find cmake, which is required to build libwebsockets. The install process will continue, but you may not be able to connect this node to Netdata Cloud."
|
||||
return 0
|
||||
fi
|
||||
|
||||
[ -n "${GITHUB_ACTIONS}" ] && echo "::group::Bundling libwebsockets."
|
||||
|
||||
progress "Prepare libwebsockets"
|
||||
|
||||
LIBWEBSOCKETS_PACKAGE_VERSION="$(cat packaging/libwebsockets.version)"
|
||||
|
||||
tmp="$(mktemp -d -t netdata-libwebsockets-XXXXXX)"
|
||||
LIBWEBSOCKETS_PACKAGE_BASENAME="v${LIBWEBSOCKETS_PACKAGE_VERSION}.tar.gz"
|
||||
|
||||
if fetch_and_verify "libwebsockets" \
|
||||
"https://github.com/warmcat/libwebsockets/archive/${LIBWEBSOCKETS_PACKAGE_BASENAME}" \
|
||||
"${LIBWEBSOCKETS_PACKAGE_BASENAME}" \
|
||||
"${tmp}" \
|
||||
"${NETDATA_LOCAL_TARBALL_OVERRIDE_LIBWEBSOCKETS}"; then
|
||||
if run tar -xf "${tmp}/${LIBWEBSOCKETS_PACKAGE_BASENAME}" -C "${tmp}" &&
|
||||
build_libwebsockets "${tmp}/libwebsockets-${LIBWEBSOCKETS_PACKAGE_VERSION}" &&
|
||||
copy_libwebsockets "${tmp}/libwebsockets-${LIBWEBSOCKETS_PACKAGE_VERSION}" &&
|
||||
rm -rf "${tmp}"; then
|
||||
run_ok "libwebsockets built and prepared."
|
||||
NETDATA_CONFIGURE_OPTIONS="${NETDATA_CONFIGURE_OPTIONS} --with-bundled-lws"
|
||||
else
|
||||
run_failed "Failed to build libwebsockets."
|
||||
defer_error_highlighted "Failed to build libwebsockets. You may not be able to connect this node to Netdata Cloud."
|
||||
fi
|
||||
else
|
||||
run_failed "Unable to fetch sources for libwebsockets."
|
||||
defer_error_highlighted "Unable to fetch sources for libwebsockets. You may not be able to connect this node to Netdata Cloud."
|
||||
fi
|
||||
|
||||
[ -n "${GITHUB_ACTIONS}" ] && echo "::endgroup::"
|
||||
}
|
||||
|
||||
bundle_libwebsockets
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
build_protobuf() {
|
||||
local env_cmd=''
|
||||
|
||||
|
|
|
@ -138,9 +138,6 @@ BuildRequires: zlib-devel
|
|||
BuildRequires: libuuid-devel
|
||||
BuildRequires: libuv-devel >= 1
|
||||
BuildRequires: openssl-devel
|
||||
%if 0%{?fedora}
|
||||
BuildRequires: libwebsockets-devel >= 3.2
|
||||
%endif
|
||||
%if 0%{?suse_version}
|
||||
BuildRequires: judy-devel
|
||||
BuildRequires: liblz4-devel
|
||||
|
@ -226,10 +223,6 @@ happened, on your systems and applications.
|
|||
|
||||
%prep
|
||||
%setup -q -n %{name}-%{version}
|
||||
export CFLAGS="${CFLAGS} -fPIC" && ${RPM_BUILD_DIR}/%{name}-%{version}/packaging/bundle-mosquitto.sh ${RPM_BUILD_DIR}/%{name}-%{version}
|
||||
%if 0%{!?fedora:1}
|
||||
export CFLAGS="${CFLAGS} -fPIC" && ${RPM_BUILD_DIR}/%{name}-%{version}/packaging/bundle-lws.sh ${RPM_BUILD_DIR}/%{name}-%{version}
|
||||
%endif
|
||||
# Only bundle libJudy if this isn't Fedora or SUSE
|
||||
%if 0%{!?fedora:1} && 0%{!?suse_version:1}
|
||||
export CFLAGS="${CFLAGS} -fPIC" && ${RPM_BUILD_DIR}/%{name}-%{version}/packaging/bundle-judy.sh ${RPM_BUILD_DIR}/%{name}-%{version}
|
||||
|
@ -256,9 +249,6 @@ autoreconf -ivf
|
|||
%if 0%{!?fedora:1} && 0%{!?suse_version:1}
|
||||
--with-bundled-libJudy \
|
||||
%endif
|
||||
%if 0%{?centos_ver} < 8 || 0%{!?fedora:1}
|
||||
--with-bundled-lws \
|
||||
%endif
|
||||
--prefix="%{_prefix}" \
|
||||
--sysconfdir="%{_sysconfdir}" \
|
||||
--localstatedir="%{_localstatedir}" \
|
||||
|
@ -554,6 +544,8 @@ are sensor monitoring, system event monitoring, power control, and serial-over-L
|
|||
%attr(4750,root,netdata) %{_libexecdir}/%{name}/plugins.d/freeipmi.plugin
|
||||
|
||||
%changelog
|
||||
* Mon Oct 11 2021 Austin Hemmelgarn <austin@netdata.cloud> 0.0.0-15
|
||||
- Remove support code for legacy ACLK implementation.
|
||||
* Wed Sep 16 2020 Austin Hemmelgarn <austin@netdata.cloud> 0.0.0-14
|
||||
- Convert to using 'AutoReq: yes' for library dependencies.
|
||||
* Thu Feb 13 2020 Austin Hemmelgarn <austin@netdata.cloud> 0.0.0-13
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
startdir="${PWD}"
|
||||
|
||||
LWS_TARBALL="v$(cat "${1}/packaging/libwebsockets.version").tar.gz"
|
||||
LWS_BUILD_PATH="${1}/externaldeps/libwebsockets/libwebsockets-$(cat "${1}/packaging/libwebsockets.version")"
|
||||
|
||||
mkdir -p "${1}/externaldeps/libwebsockets" || exit 1
|
||||
curl -sSL --connect-timeout 10 --retry 3 "https://github.com/warmcat/libwebsockets/archive/${LWS_TARBALL}" > "${LWS_TARBALL}" || exit 1
|
||||
sha256sum -c "${1}/packaging/libwebsockets.checksums" || exit 1
|
||||
tar -xzf "${LWS_TARBALL}" -C "${1}/externaldeps/libwebsockets" || exit 1
|
||||
cd "${LWS_BUILD_PATH}" || exit 1
|
||||
cmake -Wno-dev -Wno-deprecated -D LWS_WITH_SOCKS5:boolean=YES -D WITHOUT_LWS_TESTAPPS:boolean=YES . || exit 1
|
||||
make || exit 1
|
||||
cd "${startdir}" || exit 1
|
||||
cp -a "${LWS_BUILD_PATH}/lib/libwebsockets.a" "${1}/externaldeps/libwebsockets" || exit 1
|
||||
cp -a "${LWS_BUILD_PATH}/include" "${1}/externaldeps/libwebsockets" || exit 1
|
|
@ -1,12 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
MOSQUITTO_TARBALL="$(cat "${1}/packaging/mosquitto.version").tar.gz"
|
||||
MOSQUITTO_BUILD_PATH="${1}/externaldeps/mosquitto/mosquitto-$(cat "${1}/packaging/mosquitto.version")/lib"
|
||||
|
||||
mkdir -p "${1}/externaldeps/mosquitto" || exit 1
|
||||
curl -sSL --connect-timeout 10 --retry 3 "https://github.com/netdata/mosquitto/archive/${MOSQUITTO_TARBALL}" > "${MOSQUITTO_TARBALL}" || exit 1
|
||||
sha256sum -c "${1}/packaging/mosquitto.checksums" || exit 1
|
||||
tar -xzf "${MOSQUITTO_TARBALL}" -C "${1}/externaldeps/mosquitto" || exit 1
|
||||
make -C "${MOSQUITTO_BUILD_PATH}" || exit 1
|
||||
cp -a "${MOSQUITTO_BUILD_PATH}/libmosquitto.a" "${1}/externaldeps/mosquitto" || exit 1
|
||||
cp -a "${MOSQUITTO_BUILD_PATH}/mosquitto.h" "${1}/externaldeps/mosquitto" || exit 1
|
|
@ -1 +0,0 @@
|
|||
166d6e17cab64bfc10c2a71799c298284540a1fa63f6ea3de5caccb34502243c v3.2.2.tar.gz
|
|
@ -1 +0,0 @@
|
|||
3.2.2
|
|
@ -1 +0,0 @@
|
|||
532665f163348019909bd47f3e51a8ca8c9c26a01c08c09c51b903688f78cc11 v.1.6.8_Netdata-5.tar.gz
|
|
@ -1 +0,0 @@
|
|||
v.1.6.8_Netdata-5
|
|
@ -995,13 +995,7 @@ inline int web_client_api_request_v1_info_fill_buffer(RRDHOST *host, BUFFER *wb)
|
|||
#else
|
||||
buffer_strcat(wb, "\t\"aclk-legacy-available\": false,\n");
|
||||
#endif
|
||||
buffer_strcat(wb, "\t\"aclk-implementation\": \"");
|
||||
if (aclk_ng) {
|
||||
buffer_strcat(wb, "Next Generation");
|
||||
} else {
|
||||
buffer_strcat(wb, "legacy");
|
||||
}
|
||||
buffer_strcat(wb, "\",\n");
|
||||
buffer_strcat(wb, "\t\"aclk-implementation\": \"Next Generation\",\n");
|
||||
#else
|
||||
buffer_strcat(wb, "\t\"cloud-available\": false,\n");
|
||||
#endif
|
||||
|
|
Loading…
Add table
Reference in a new issue