@cryptotaxi247 / netdata-1 / commits / d005dee55

ACLK-NG New Cloud NodeInstance related msgs (#11234)

Adds new cloud arch NodeInstance messages as per design. Co-authored-by: Stelios Fragkakis <52996999+stelfrag@users.noreply.github.com>

Timotej S committed Jul 7, 2021 at 16:32 UTC d005dee55800818b26f6308c433e6aed8079f7fe
31 files changed +934 -93
.gitmodules
+3
@@ -1,3 +1,6 @@
1 [submodule "mqtt_websockets"]
2 path = mqtt_websockets
3 url = https://github.com/underhood/mqtt_websockets.git
4 +[submodule "aclk/aclk-schemas"]
5 + path = aclk/aclk-schemas
6 + url = https://github.com/netdata/aclk-schemas.git
CMakeLists.txt
+58 -1
@@ -796,6 +796,14 @@ set(ACLK_NG_FILES
796 mqtt_websockets/c-rbuf/src/ringbuffer_internal.h
797 mqtt_websockets/MQTT-C/src/mqtt.c
798 mqtt_websockets/MQTT-C/include/mqtt.h
799 + aclk/schema-wrappers/connection.cc
800 + aclk/schema-wrappers/connection.h
801 + aclk/schema-wrappers/node_connection.cc
802 + aclk/schema-wrappers/node_connection.h
803 + aclk/schema-wrappers/node_creation.cc
804 + aclk/schema-wrappers/node_creation.h
805 + aclk/schema-wrappers/schema_wrappers.h
806 + aclk/schema-wrappers/schema_wrapper_utils.h
807 )
808
809 set(SPAWN_PLUGIN_FILES
@@ -1038,9 +1046,58 @@ ELSE()
1046 message(STATUS "agent-cloud-link Legacy: disabled")
1047 ENDIF()
1048
1049 +find_package(Protobuf REQUIRED)
1050 +
1051 +function(PROTOBUF_ACLK_GENERATE_CPP SRCS HDRS)
1052 + if(NOT ARGN)
1053 + message(SEND_ERROR "Error: PROTOBUF_ACLK_GENERATE_CPP() called without any proto files")
1054 + return()
1055 + endif()
1056 +
1057 + set(${SRCS})
1058 + set(${HDRS})
1059 + foreach(FIL ${ARGN})
1060 + get_filename_component(ABS_FIL ${FIL} ABSOLUTE)
1061 + get_filename_component(DIR ${ABS_FIL} DIRECTORY)
1062 + get_filename_component(FIL_WE ${FIL} NAME_WE)
1063 + set(GENERATED_PB_CC "${DIR}/${FIL_WE}.pb.cc")
1064 + set(GENERATED_PB_H "${DIR}/${FIL_WE}.pb.h")
1065 +# cmake > 3.20 required :(
1066 +# cmake_path(SET GENERATED_PB_CC "${DIR}")
1067 +# cmake_path(SET GENERATED_PB_H "${DIR}")
1068 +# cmake_path(APPEND GENERATED_PB_CC "${FIL_WE}.pb.cc")
1069 +# cmake_path(APPEND GENERATED_PB_H "${FIL_WE}.pb.h")
1070 +
1071 + list(APPEND ${SRCS} ${GENERATED_PB_CC})
1072 + list(APPEND ${HDRS} ${GENERATED_PB_H})
1073 + add_custom_command(
1074 + OUTPUT ${GENERATED_PB_CC}
1075 + ${GENERATED_PB_H}
1076 + COMMAND ${PROTOBUF_PROTOC_EXECUTABLE}
1077 + ARGS -I=${CMAKE_SOURCE_DIR}/aclk/aclk-schemas --cpp_out=${CMAKE_SOURCE_DIR}/aclk/aclk-schemas ${ABS_FIL}
1078 + DEPENDS ${ABS_FIL} ${PROTOBUF_PROTOC_EXECUTABLE}
1079 + COMMENT "Running C++ protocol buffer compiler on ${FIL}"
1080 + VERBATIM )
1081 + endforeach()
1082 + set_source_files_properties(${${SRCS}} ${${HDRS}} PROPERTIES GENERATED TRUE)
1083 + set(${SRCS} ${${SRCS}} PARENT_SCOPE)
1084 + set(${HDRS} ${${HDRS}} PARENT_SCOPE)
1085 +endfunction()
1086 +
1087 +set(ACLK_NG_PROTO_DEFS
1088 + aclk/aclk-schemas/proto/agent/v1/connection.proto
1089 + aclk/aclk-schemas/proto/nodeinstance/connection/v1/connection.proto
1090 + aclk/aclk-schemas/proto/nodeinstance/create/v1/creation.proto
1091 + )
1092 +PROTOBUF_ACLK_GENERATE_CPP(ACLK_NG_PROTO_BUILT_SRCS ACLK_NG_PROTO_BUILT_HDRS ${ACLK_NG_PROTO_DEFS})
1093 +
1094 +list(APPEND NETDATA_COMMON_LIBRARIES ${PROTOBUF_LIBRARIES})
1095 +list(APPEND NETDATA_COMMON_INCLUDE_DIRS ${PROTOBUF_INCLUDE_DIRS})
1096 +list(APPEND NETDATA_COMMON_CFLAGS ${PROTOBUF_CFLAGS_OTHER})
1097 list(APPEND NETDATA_FILES ${ACLK_ALWAYS_BUILD})
1042 -list(APPEND NETDATA_FILES ${ACLK_NG_FILES})
1098 +list(APPEND NETDATA_FILES ${ACLK_NG_FILES} ${ACLK_NG_PROTO_BUILT_SRCS} ${ACLK_NG_PROTO_BUILT_HDRS})
1099 list(APPEND NETDATA_FILES ${ACLK_COMMON_FILES})
1100 +include_directories(BEFORE ${CMAKE_SOURCE_DIR}/aclk/aclk-schemas)
1101 include_directories(BEFORE ${CMAKE_SOURCE_DIR}/mqtt_websockets/MQTT-C/include)
1102 include_directories(BEFORE ${CMAKE_SOURCE_DIR}/mqtt_websockets/src/include)
1103 include_directories(BEFORE ${CMAKE_SOURCE_DIR}/mqtt_websockets/c-rbuf/include)
Makefile.am
+50 -6
@@ -3,6 +3,9 @@
3 AUTOMAKE_OPTIONS = foreign subdir-objects 1.11
4 ACLOCAL_AMFLAGS = -I build/m4
5
6 +nodist_netdata_SOURCES=$(NULL)
7 +BUILT_SOURCES=$(NULL)
8 +
9 MAINTAINERCLEANFILES = \
10 config.log config.status \
11 $(srcdir)/Makefile.in \
@@ -572,7 +575,39 @@ ACLK_NG_FILES = \
575 mqtt_websockets/c-rbuf/src/ringbuffer_internal.h \
576 mqtt_websockets/MQTT-C/src/mqtt.c \
577 mqtt_websockets/MQTT-C/include/mqtt.h \
578 + aclk/schema-wrappers/connection.cc \
579 + aclk/schema-wrappers/connection.h \
580 + aclk/schema-wrappers/node_connection.cc \
581 + aclk/schema-wrappers/node_connection.h \
582 + aclk/schema-wrappers/node_creation.cc \
583 + aclk/schema-wrappers/node_creation.h \
584 + aclk/schema-wrappers/schema_wrappers.h \
585 + aclk/schema-wrappers/schema_wrapper_utils.h \
586 + $(NULL)
587 +
588 +ACLK_NG_PROTO_BUILT_FILES = aclk/aclk-schemas/proto/agent/v1/connection.pb.cc \
589 + aclk/aclk-schemas/proto/agent/v1/connection.pb.h \
590 + aclk/aclk-schemas/proto/nodeinstance/connection/v1/connection.pb.cc \
591 + aclk/aclk-schemas/proto/nodeinstance/connection/v1/connection.pb.h \
592 + aclk/aclk-schemas/proto/nodeinstance/create/v1/creation.pb.cc \
593 + aclk/aclk-schemas/proto/nodeinstance/create/v1/creation.pb.h \
594 $(NULL)
595 +
596 +BUILT_SOURCES += $(ACLK_NG_PROTO_BUILT_FILES)
597 +nodist_netdata_SOURCES += $(ACLK_NG_PROTO_BUILT_FILES)
598 +
599 +aclk/aclk-schemas/proto/agent/v1/connection.pb.cc \
600 +aclk/aclk-schemas/proto/agent/v1/connection.pb.h: aclk/aclk-schemas/proto/agent/v1/connection.proto
601 + $(PROTOC) -I=aclk/aclk-schemas --cpp_out=$(builddir)/aclk/aclk-schemas $^
602 +
603 +aclk/aclk-schemas/proto/nodeinstance/connection/v1/connection.pb.cc \
604 +aclk/aclk-schemas/proto/nodeinstance/connection/v1/connection.pb.h: aclk/aclk-schemas/proto/nodeinstance/connection/v1/connection.proto
605 + $(PROTOC) -I=aclk/aclk-schemas --cpp_out=$(builddir)/aclk/aclk-schemas $^
606 +
607 +aclk/aclk-schemas/proto/nodeinstance/create/v1/creation.pb.cc \
608 +aclk/aclk-schemas/proto/nodeinstance/create/v1/creation.pb.h: aclk/aclk-schemas/proto/nodeinstance/create/v1/creation.proto
609 + $(PROTOC) -I=aclk/aclk-schemas --cpp_out=$(builddir)/aclk/aclk-schemas $^
610 +
611 endif #ACLK_NG
612
613 if ENABLE_ACLK
@@ -784,12 +819,15 @@ netdata_LDADD = \
819 $(NETDATA_COMMON_LIBS) \
820 $(NULL)
821
822 +if ACLK_NG
823 + netdata_LDADD += $(OPTIONAL_PROTOBUF_LIBS)
824 +endif
825 +
826 if ACLK_LEGACY
827 netdata_LDADD += \
828 $(abs_top_srcdir)/externaldeps/mosquitto/libmosquitto.a \
829 $(OPTIONAL_LIBCAP_LIBS) \
830 $(OPTIONAL_LWS_LIBS) \
792 - $(NETDATA_COMMON_LIBS) \
831 $(NULL)
832 endif #ACLK_LEGACY
833
@@ -899,12 +937,15 @@ endif
937
938 if ENABLE_BACKEND_PROMETHEUS_REMOTE_WRITE
939 netdata_SOURCES += $(PROMETHEUS_REMOTE_WRITE_BACKEND_FILES) $(PROMETHEUS_REMOTE_WRITE_EXPORTING_FILES)
902 - netdata_LDADD += $(OPTIONAL_PROMETHEUS_REMOTE_WRITE_LIBS)
903 - BUILT_SOURCES = \
940 + netdata_LDADD += $(OPTIONAL_PROMETHEUS_REMOTE_WRITE_LIBS) \
941 + $(OPTIONAL_PROTOBUF_LIBS) \
942 + $(NULL)
943 + BACKEND_PROMETHEUS_BUILT_SOURCES = \
944 exporting/prometheus/remote_write/remote_write.pb.cc \
945 exporting/prometheus/remote_write/remote_write.pb.h \
946 $(NULL)
907 - nodist_netdata_SOURCES = $(BUILT_SOURCES)
947 + BUILT_SOURCES += $(BACKEND_PROMETHEUS_BUILT_SOURCES)
948 + nodist_netdata_SOURCES += $(BACKEND_PROMETHEUS_BUILT_SOURCES)
949
950 exporting/prometheus/remote_write/remote_write.pb.cc \
951 exporting/prometheus/remote_write/remote_write.pb.h: exporting/prometheus/remote_write/remote_write.proto
@@ -1033,14 +1074,17 @@ if ENABLE_UNITTESTS
1074 exporting_tests_exporting_engine_testdriver_LDADD = $(NETDATA_COMMON_LIBS) $(TEST_LIBS)
1075 if ENABLE_BACKEND_PROMETHEUS_REMOTE_WRITE
1076 exporting_tests_exporting_engine_testdriver_SOURCES += $(PROMETHEUS_REMOTE_WRITE_EXPORTING_FILES)
1036 - exporting_tests_exporting_engine_testdriver_LDADD += $(OPTIONAL_PROMETHEUS_REMOTE_WRITE_LIBS)
1077 + exporting_tests_exporting_engine_testdriver_LDADD += \
1078 + $(OPTIONAL_PROMETHEUS_REMOTE_WRITE_LIBS) \
1079 + $(OPTIONAL_PROTOBUF_LIBS) \
1080 + $(NULL)
1081 exporting_tests_exporting_engine_testdriver_LDFLAGS += \
1082 -Wl,--wrap=init_write_request \
1083 -Wl,--wrap=add_host_info \
1084 -Wl,--wrap=add_label \
1085 -Wl,--wrap=add_metric \
1086 $(NULL)
1043 - nodist_exporting_tests_exporting_engine_testdriver_SOURCES = $(BUILT_SOURCES)
1087 + nodist_exporting_tests_exporting_engine_testdriver_SOURCES = $(BACKEND_PROMETHEUS_BUILT_SOURCES)
1088 endif
1089 if ENABLE_BACKEND_KINESIS
1090 exporting_tests_exporting_engine_testdriver_SOURCES += $(KINESIS_EXPORTING_FILES)
aclk/aclk-schemas new
+1
@@ -0,0 +1 @@
1 +Subproject commit b5fef3f3a84e6a5013b36b906f4677012c734416
aclk/aclk.c
+173 -25
@@ -223,6 +223,45 @@ static void msg_callback(const char *topic, const void *msg, size_t msglen, int
223 aclk_handle_cloud_message(cmsg);
224 }
225
226 +
227 +static void msg_callback_new(const char *topic, const void *msg, size_t msglen, int qos)
228 +{
229 + if (msglen > RX_MSGLEN_MAX)
230 + error("Incoming ACLK message was bigger than MAX of %d and got truncated.", RX_MSGLEN_MAX);
231 +
232 + debug(D_ACLK, "Got Message From Broker Topic \"%s\" QOS %d", topic, qos);
233 +
234 + if (aclk_shared_state.mqtt_shutdown_msg_id > 0) {
235 + error("Link is shutting down. Ignoring message.");
236 + return;
237 + }
238 +
239 + const char *msgtype = strrchr(topic, '/');
240 + if (unlikely(!msgtype)) {
241 + error_report("Cannot get message type from topic. Ignoring message from topic \"%s\"", topic);
242 + return;
243 + }
244 + msgtype++;
245 + if (unlikely(!*msgtype)) {
246 + error_report("Message type empty. Ignoring message from topic \"%s\"", topic);
247 + return;
248 + }
249 +
250 +#ifdef ACLK_LOG_CONVERSATION_DIR
251 +#define FN_MAX_LEN 512
252 + char filename[FN_MAX_LEN];
253 + int logfd;
254 + snprintf(filename, FN_MAX_LEN, ACLK_LOG_CONVERSATION_DIR "/%010d-rx-%s.bin", ACLK_GET_CONV_LOG_NEXT(), msgtype);
255 + logfd = open(filename, O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR );
256 + if(logfd < 0)
257 + error("Error opening ACLK Conversation logfile \"%s\" for RX message.", filename);
258 + write(logfd, msg, msglen);
259 + close(logfd);
260 +#endif
261 +
262 + aclk_handle_new_cloud_msg(msgtype, msg, msglen);
263 +}
264 +
265 static void puback_callback(uint16_t packet_id)
266 {
267 if (++aclk_pubacks_per_conn == ACLK_PUBACKS_CONN_STABLE)
@@ -306,11 +345,6 @@ static inline void queue_connect_payloads(void)
345
346 static inline void mqtt_connected_actions(mqtt_wss_client client)
347 {
309 - // TODO global vars?
310 - usec_t now = now_realtime_usec();
311 - aclk_session_sec = now / USEC_PER_SEC;
312 - aclk_session_us = now % USEC_PER_SEC;
313 -
348 const char *topic = aclk_get_topic(ACLK_TOPICID_COMMAND);
349
350 if (!topic)
@@ -318,16 +352,28 @@ static inline void mqtt_connected_actions(mqtt_wss_client client)
352 else
353 mqtt_wss_subscribe(client, topic, 1);
354
355 + if (aclk_use_new_cloud_arch) {
356 + topic = aclk_get_topic(ACLK_TOPICID_CMD_NG_V1);
357 + if (!topic)
358 + error("Unable to fetch topic for protobuf COMMAND (to subscribe)");
359 + else
360 + mqtt_wss_subscribe(client, topic, 1);
361 + }
362 +
363 aclk_stats_upd_online(1);
364 aclk_connected = 1;
365 aclk_pubacks_per_conn = 0;
366
325 - ACLK_SHARED_STATE_LOCK;
326 - if (aclk_shared_state.agent_state != ACLK_HOST_INITIALIZING) {
327 - error("Sending `connect` payload immediately as popcorning was finished already.");
328 - queue_connect_payloads();
367 + if (!aclk_use_new_cloud_arch) {
368 + ACLK_SHARED_STATE_LOCK;
369 + if (aclk_shared_state.agent_state != ACLK_HOST_INITIALIZING) {
370 + error("Sending `connect` payload immediately as popcorning was finished already.");
371 + queue_connect_payloads();
372 + }
373 + ACLK_SHARED_STATE_UNLOCK;
374 + } else {
375 + aclk_send_agent_connection_update(client, 1);
376 }
330 - ACLK_SHARED_STATE_UNLOCK;
377 }
378
379 /* Waits until agent is ready or needs to exit
@@ -337,10 +383,13 @@ static inline void mqtt_connected_actions(mqtt_wss_client client)
383 * @return 0 - Popcorning Finished - Agent STABLE,
384 * !0 - netdata_exit
385 */
340 -static int wait_popcorning_finishes(mqtt_wss_client client, struct aclk_query_threads *query_threads)
386 +static int wait_popcorning_finishes()
387 {
388 time_t elapsed;
389 int need_wait;
390 + if (aclk_use_new_cloud_arch)
391 + return 0;
392 +
393 while (!netdata_exit) {
394 ACLK_SHARED_STATE_LOCK;
395 if (likely(aclk_shared_state.agent_state != ACLK_HOST_INITIALIZING)) {
@@ -352,9 +401,6 @@ static int wait_popcorning_finishes(mqtt_wss_client client, struct aclk_query_th
401 aclk_shared_state.agent_state = ACLK_HOST_STABLE;
402 ACLK_SHARED_STATE_UNLOCK;
403 error("ACLK localhost popocorn finished");
355 - if (unlikely(!query_threads->thread_list))
356 - aclk_query_threads_start(query_threads, client);
357 - queue_connect_payloads();
404 return 0;
405 }
406 ACLK_SHARED_STATE_UNLOCK;
@@ -370,7 +416,11 @@ void aclk_graceful_disconnect(mqtt_wss_client client)
416 error("Preparing to Gracefully Shutdown the ACLK");
417 aclk_queue_lock();
418 aclk_queue_flush();
373 - aclk_shared_state.mqtt_shutdown_msg_id = aclk_send_app_layer_disconnect(client, "graceful");
419 + if (aclk_use_new_cloud_arch)
420 + aclk_shared_state.mqtt_shutdown_msg_id = aclk_send_agent_connection_update(client, 0);
421 + else
422 + aclk_shared_state.mqtt_shutdown_msg_id = aclk_send_app_layer_disconnect(client, "graceful");
423 +
424 time_t t = now_monotonic_sec();
425 while (!mqtt_wss_service(client, 100)) {
426 if (now_monotonic_sec() - t >= 2) {
@@ -481,7 +531,7 @@ static int aclk_attempt_to_connect(mqtt_wss_client client)
531 url_t mqtt_url;
532 #endif
533
484 - json_object *lwt;
534 + json_object *lwt = NULL;
535
536 while (!netdata_exit) {
537 char *cloud_base_url = appconfig_get(&cloud_config, CONFIG_SECTION_GLOBAL, "cloud base url", NULL);
@@ -546,7 +596,11 @@ static int aclk_attempt_to_connect(mqtt_wss_client client)
596
597 // aclk_get_topic moved here as during OTP we
598 // generate the topic cache
549 - mqtt_conn_params.will_topic = aclk_get_topic(ACLK_TOPICID_METADATA);
599 + if (aclk_use_new_cloud_arch)
600 + mqtt_conn_params.will_topic = aclk_get_topic(ACLK_TOPICID_AGENT_CONN);
601 + else
602 + mqtt_conn_params.will_topic = aclk_get_topic(ACLK_TOPICID_METADATA);
603 +
604 if (!mqtt_conn_params.will_topic) {
605 error("Couldn't get LWT topic. Will not send LWT.");
606 continue;
@@ -567,9 +621,17 @@ static int aclk_attempt_to_connect(mqtt_wss_client client)
621 }
622 #endif
623
570 - lwt = aclk_generate_disconnect(NULL);
571 - mqtt_conn_params.will_msg = json_object_to_json_string_ext(lwt, JSON_C_TO_STRING_PLAIN);
572 - mqtt_conn_params.will_msg_len = strlen(mqtt_conn_params.will_msg);
624 + aclk_session_newarch = now_realtime_usec();
625 + aclk_session_sec = aclk_session_newarch / USEC_PER_SEC;
626 + aclk_session_us = aclk_session_newarch % USEC_PER_SEC;
627 +
628 + if (aclk_use_new_cloud_arch) {
629 + mqtt_conn_params.will_msg = aclk_generate_lwt(&mqtt_conn_params.will_msg_len);
630 + } else {
631 + lwt = aclk_generate_disconnect(NULL);
632 + mqtt_conn_params.will_msg = json_object_to_json_string_ext(lwt, JSON_C_TO_STRING_PLAIN);
633 + mqtt_conn_params.will_msg_len = strlen(mqtt_conn_params.will_msg);
634 + }
635
636 #ifdef ACLK_DISABLE_CHALLENGE
637 ret = mqtt_wss_connect(client, base_url.host, base_url.port, &mqtt_conn_params, ACLK_SSL_FLAGS, &proxy_conf);
@@ -583,7 +645,10 @@ static int aclk_attempt_to_connect(mqtt_wss_client client)
645 freez((char*)mqtt_conn_params.username);
646 #endif
647
586 - json_object_put(lwt);
648 + if (aclk_use_new_cloud_arch)
649 + freez((char *)mqtt_conn_params.will_msg);
650 + else
651 + json_object_put(lwt);
652
653 if (!ret) {
654 info("MQTTWSS connection succeeded");
@@ -609,6 +674,9 @@ static int aclk_attempt_to_connect(mqtt_wss_client client)
674 */
675 void *aclk_main(void *ptr)
676 {
677 +#ifdef ACLK_NEWARCH_DEVMODE
678 + aclk_use_new_cloud_arch = 1;
679 +#endif
680 struct netdata_static_thread *static_thread = (struct netdata_static_thread *)ptr;
681
682 struct aclk_stats_thread *stats_thread = NULL;
@@ -642,7 +710,7 @@ void *aclk_main(void *ptr)
710 if (wait_till_agent_claim_ready())
711 goto exit;
712
645 - if (!(mqttwss_client = mqtt_wss_new("mqtt_wss", aclk_mqtt_wss_log_cb, msg_callback, puback_callback))) {
713 + if (!(mqttwss_client = mqtt_wss_new("mqtt_wss", aclk_mqtt_wss_log_cb, (aclk_use_new_cloud_arch ? msg_callback_new : msg_callback), puback_callback))) {
714 error("Couldn't initialize MQTT_WSS network library");
715 goto exit;
716 }
@@ -666,8 +734,14 @@ void *aclk_main(void *ptr)
734 // warning this assumes the popcorning is relative short (3s)
735 // if that changes call mqtt_wss_service from within
736 // to keep OpenSSL, WSS and MQTT connection alive
669 - if (wait_popcorning_finishes(mqttwss_client, &query_threads))
737 + if (wait_popcorning_finishes())
738 goto exit_full;
739 +
740 + if (unlikely(!query_threads.thread_list))
741 + aclk_query_threads_start(&query_threads, mqttwss_client);
742 +
743 + if (!aclk_use_new_cloud_arch)
744 + queue_connect_payloads();
745
746 if (!handle_connection(mqttwss_client)) {
747 aclk_stats_upd_online(0);
@@ -775,7 +849,7 @@ void ng_aclk_add_collector(RRDHOST *host, const char *plugin_name, const char *m
849 {
850 struct aclk_query *query;
851 struct _collector *tmp_collector;
778 - if (unlikely(!netdata_ready)) {
852 + if (unlikely(!netdata_ready || aclk_use_new_cloud_arch)) {
853 return;
854 }
855
@@ -818,7 +892,7 @@ void ng_aclk_del_collector(RRDHOST *host, const char *plugin_name, const char *m
892 {
893 struct aclk_query *query;
894 struct _collector *tmp_collector;
821 - if (unlikely(!netdata_ready)) {
895 + if (unlikely(!netdata_ready || aclk_use_new_cloud_arch)) {
896 return;
897 }
898
@@ -854,3 +928,77 @@ void ng_aclk_del_collector(RRDHOST *host, const char *plugin_name, const char *m
928 query->data.metadata_alarms.initial_on_connect = 0;
929 aclk_queue_query(query);
930 }
931 +
932 +void ng_aclk_host_state_update(RRDHOST *host, int cmd)
933 +{
934 + uuid_t node_id;
935 + int ret;
936 +
937 + if (!aclk_connected || !aclk_use_new_cloud_arch)
938 + return;
939 +
940 + ret = get_node_id(&host->host_uuid, &node_id);
941 + if (ret > 0) {
942 + // this means we were not able to check if node_id already present
943 + error("Unable to check for node_id. Ignoring the host state update.");
944 + return;
945 + }
946 + if (ret < 0) {
947 + // node_id not found
948 + aclk_query_t create_query;
949 + create_query = aclk_query_new(REGISTER_NODE);
950 + rrdhost_aclk_state_lock(localhost);
951 + create_query->data.node_creation.claim_id = strdupz(localhost->aclk_state.claimed_id);
952 + rrdhost_aclk_state_unlock(localhost);
953 + create_query->data.node_creation.hops = 1; //TODO - real hop count instead of hardcoded
954 + create_query->data.node_creation.hostname = strdupz(host->hostname);
955 + create_query->data.node_creation.machine_guid = strdupz(host->machine_guid);
956 + aclk_queue_query(create_query);
957 + return;
958 + }
959 +
960 + aclk_query_t query = aclk_query_new(NODE_STATE_UPDATE);
961 + query->data.node_update.hops = 1; //TODO - real hop count instead of hardcoded
962 + rrdhost_aclk_state_lock(localhost);
963 + query->data.node_update.claim_id = strdupz(localhost->aclk_state.claimed_id);
964 + rrdhost_aclk_state_unlock(localhost);
965 + query->data.node_update.live = cmd;
966 + query->data.node_update.node_id = mallocz(UUID_STR_LEN);
967 + uuid_unparse_lower(node_id, (char*)query->data.node_update.node_id);
968 + query->data.node_update.queryable = 1;
969 + query->data.node_update.session_id = aclk_session_newarch;
970 + aclk_queue_query(query);
971 +}
972 +
973 +void aclk_send_node_instances()
974 +{
975 + struct node_instance_list *list = get_node_list();
976 + while (!uuid_is_null(list->host_id)) {
977 + if (!uuid_is_null(list->node_id)) {
978 + aclk_query_t query = aclk_query_new(NODE_STATE_UPDATE);
979 + rrdhost_aclk_state_lock(localhost);
980 + query->data.node_update.claim_id = strdupz(localhost->aclk_state.claimed_id);
981 + rrdhost_aclk_state_unlock(localhost);
982 + query->data.node_update.live = list->live;
983 + query->data.node_update.hops = list->hops;
984 + query->data.node_update.node_id = mallocz(UUID_STR_LEN);
985 + uuid_unparse_lower(list->node_id, (char*)query->data.node_update.node_id);
986 + query->data.node_update.queryable = 1;
987 + query->data.node_update.session_id = aclk_session_newarch;
988 + aclk_queue_query(query);
989 + } else {
990 + aclk_query_t create_query;
991 + create_query = aclk_query_new(REGISTER_NODE);
992 + rrdhost_aclk_state_lock(localhost);
993 + create_query->data.node_creation.claim_id = strdupz(localhost->aclk_state.claimed_id);
994 + rrdhost_aclk_state_unlock(localhost);
995 + create_query->data.node_creation.hops = uuid_compare(list->host_id, localhost->host_uuid) ? 1 : 0; // TODO - when streaming supports hops
996 + create_query->data.node_creation.hostname = list->hostname;
997 + create_query->data.node_creation.machine_guid = mallocz(UUID_STR_LEN);
998 + uuid_unparse_lower(list->host_id, (char*)create_query->data.node_creation.machine_guid);
999 + aclk_queue_query(create_query);
1000 + }
1001 +
1002 + list++;
1003 + }
1004 +}
aclk/aclk.h
+4
@@ -43,4 +43,8 @@ int ng_aclk_update_chart(RRDHOST *host, char *chart_name, int create);
43 void ng_aclk_add_collector(RRDHOST *host, const char *plugin_name, const char *module_name);
44 void ng_aclk_del_collector(RRDHOST *host, const char *plugin_name, const char *module_name);
45
46 +void ng_aclk_host_state_update(RRDHOST *host, int cmd);
47 +
48 +void aclk_send_node_instances(void);
49 +
50 #endif /* ACLK_H */
aclk/aclk_api.c
+13
@@ -146,6 +146,19 @@ void aclk_del_collector(RRDHOST *host, const char *plugin_name, const char *modu
146 error_report("No usable aclk_del_collector implementation");
147 }
148
149 +void aclk_host_state_update(RRDHOST *host, int connect)
150 +{
151 +#ifdef ACLK_NG
152 + if (aclk_ng)
153 + return ng_aclk_host_state_update(host, connect);
154 +#endif
155 +#ifdef ACLK_LEGACY
156 + if (!aclk_ng)
157 + return legacy_aclk_host_state_update(host, connect);
158 +#endif
159 + error_report("Couldn't use any version of aclk_host_state_update");
160 +}
161 +
162 #endif /* ENABLE_ACLK */
163
164 struct label *add_aclk_host_labels(struct label *label) {
aclk/aclk_api.h
+2
@@ -35,6 +35,8 @@ int aclk_update_alarm(RRDHOST *host, ALARM_ENTRY *ae);
35 void aclk_add_collector(RRDHOST *host, const char *plugin_name, const char *module_name);
36 void aclk_del_collector(RRDHOST *host, const char *plugin_name, const char *module_name);
37
38 +void aclk_host_state_update(RRDHOST *host, int connect);
39 +
40 #define NETDATA_ACLK_HOOK \
41 { .name = "ACLK_Main", \
42 .config_section = NULL, \
aclk/aclk_query.c
+59 -1
@@ -55,11 +55,33 @@ static usec_t aclk_web_api_v1_request(RRDHOST *host, struct web_client *w, char
55 return t;
56 }
57
58 +static RRDHOST *node_id_2_rrdhost(const char *node_id)
59 +{
60 + int res;
61 + uuid_t node_id_bin, host_id_bin;
62 + char host_id[UUID_STR_LEN];
63 + if (uuid_parse(node_id, node_id_bin)) {
64 + error("Couldn't parse UUID %s", node_id);
65 + return NULL;
66 + }
67 + if ((res = get_host_id(&node_id_bin, &host_id_bin))) {
68 + error("node not found rc=%d", res);
69 + return NULL;
70 + }
71 + uuid_unparse_lower(host_id_bin, host_id);
72 + return rrdhost_find_by_guid(host_id, 0);
73 +}
74 +
75 +#define NODE_ID_QUERY "/node/"
76 +// TODO this function should be quarantied and written nicely
77 +// lots of skeletons from initial ACLK Legacy impl.
78 +// quick and dirty from the start
79 static int http_api_v2(mqtt_wss_client client, aclk_query_t query)
80 {
81 int retval = 0;
82 usec_t t;
83 BUFFER *local_buffer = NULL;
84 + RRDHOST *query_host = localhost;
85
86 #ifdef NETDATA_WITH_ZLIB
87 int z_ret;
@@ -76,6 +98,24 @@ static int http_api_v2(mqtt_wss_client client, aclk_query_t query)
98 w->cookie2[0] = 0; // Simulate web_client_create_on_fd()
99 w->acl = 0x1f;
100
101 + if (!strncmp(query->data.http_api_v2.query, NODE_ID_QUERY, strlen(NODE_ID_QUERY))) {
102 + char *node_uuid = query->data.http_api_v2.query + strlen(NODE_ID_QUERY);
103 + char nodeid[UUID_STR_LEN];
104 + if (strlen(node_uuid) < (UUID_STR_LEN - 1)) {
105 + error("URL requests node_id but there is not enough chars following");
106 + retval = 1;
107 + goto cleanup;
108 + }
109 + strncpyz(nodeid, node_uuid, UUID_STR_LEN - 1);
110 +
111 + query_host = node_id_2_rrdhost(nodeid);
112 + if (!query_host) {
113 + error("Host with node_id \"%s\" not found! Query Ignored!", node_uuid);
114 + retval = 1;
115 + goto cleanup;
116 + }
117 + }
118 +
119 char *mysep = strchr(query->data.http_api_v2.query, '?');
120 if (mysep) {
121 url_decode_r(w->decoded_query_string, mysep, NETDATA_WEB_REQUEST_URL_SIZE + 1);
@@ -86,7 +126,7 @@ static int http_api_v2(mqtt_wss_client client, aclk_query_t query)
126 mysep = strrchr(query->data.http_api_v2.query, '/');
127
128 // execute the query
89 - t = aclk_web_api_v1_request(localhost, w, mysep ? mysep + 1 : "noop");
129 + t = aclk_web_api_v1_request(query_host, w, mysep ? mysep + 1 : "noop");
130
131 #ifdef NETDATA_WITH_ZLIB
132 // check if gzip encoding can and should be used
@@ -187,6 +227,22 @@ static int alarm_state_update_query(mqtt_wss_client client, aclk_query_t query)
227 return 0;
228 }
229
230 +static int register_node(mqtt_wss_client client, aclk_query_t query) {
231 + // TODO create a pending registrations list
232 + // with some timeouts to detect registration requests that
233 + // go unanswered from the cloud
234 + aclk_generate_node_registration(client, &query->data.node_creation);
235 + return 0;
236 +}
237 +
238 +static int node_state_update(mqtt_wss_client client, aclk_query_t query) {
239 + // TODO create a pending registrations list
240 + // with some timeouts to detect registration requests that
241 + // go unanswered from the cloud
242 + aclk_generate_node_state_update(client, &query->data.node_update);
243 + return 0;
244 +}
245 +
246 aclk_query_handler aclk_query_handlers[] = {
247 { .type = HTTP_API_V2, .name = "http api request v2", .fnc = http_api_v2 },
248 { .type = ALARM_STATE_UPDATE, .name = "alarm state update", .fnc = alarm_state_update_query },
@@ -194,6 +250,8 @@ aclk_query_handler aclk_query_handlers[] = {
250 { .type = METADATA_ALARMS, .name = "alarms metadata", .fnc = alarms_metadata },
251 { .type = CHART_NEW, .name = "chart new", .fnc = chart_query },
252 { .type = CHART_DEL, .name = "chart delete", .fnc = info_metadata },
253 + { .type = REGISTER_NODE, .name = "register node", .fnc = register_node },
254 + { .type = NODE_STATE_UPDATE, .name = "node state update", .fnc = node_state_update },
255 { .type = UNKNOWN, .name = NULL, .fnc = NULL }
256 };
257
aclk/aclk_query_queue.c
+11
@@ -114,6 +114,17 @@ void aclk_query_free(aclk_query_t query)
114 if (query->type == ALARM_STATE_UPDATE && query->data.alarm_update)
115 json_object_put(query->data.alarm_update);
116
117 + if (query->type == NODE_STATE_UPDATE) {
118 + freez((void*)query->data.node_update.claim_id);
119 + freez((void*)query->data.node_update.node_id);
120 + }
121 +
122 + if (query->type == REGISTER_NODE) {
123 + freez((void*)query->data.node_creation.claim_id);
124 + freez((void*)query->data.node_creation.hostname);
125 + freez((void*)query->data.node_creation.machine_guid);
126 + }
127 +
128 freez(query->dedup_id);
129 freez(query->callback_topic);
130 freez(query->msg_id);
aclk/aclk_query_queue.h
+6 -1
@@ -5,6 +5,7 @@
5
6 #include "libnetdata/libnetdata.h"
7 #include "daemon/common.h"
8 +#include "schema-wrappers/schema_wrappers.h"
9
10 typedef enum {
11 UNKNOWN,
@@ -13,7 +14,9 @@ typedef enum {
14 HTTP_API_V2,
15 CHART_NEW,
16 CHART_DEL,
16 - ALARM_STATE_UPDATE
17 + ALARM_STATE_UPDATE,
18 + REGISTER_NODE,
19 + NODE_STATE_UPDATE
20 } aclk_query_type_t;
21
22 struct aclk_query_metadata {
@@ -55,6 +58,8 @@ struct aclk_query {
58 struct aclk_query_metadata metadata_alarms;
59 struct aclk_query_http_api_v2 http_api_v2;
60 struct aclk_query_chart_add_del chart_add_del;
61 + node_instance_creation_t node_creation;
62 + node_instance_connection_t node_update;
63 json_object *alarm_update;
64 } data;
65 };
aclk/aclk_rx_msgs.c
+59 -2
@@ -7,7 +7,7 @@
7 #include "aclk.h"
8
9 #define ACLK_V2_PAYLOAD_SEPARATOR "\x0D\x0A\x0D\x0A"
10 -#define ACLK_CLOUD_REQ_V2_PREFIX "GET /api/v1/"
10 +#define ACLK_CLOUD_REQ_V2_PREFIX "GET /"
11
12 #define ACLK_V_COMPRESSION 2
13
@@ -91,6 +91,7 @@ static inline int aclk_v2_payload_get_query(const char *payload, char **query_ur
91 {
92 const char *start, *end;
93
94 + // TODO better check of URL
95 if(strncmp(payload, ACLK_CLOUD_REQ_V2_PREFIX, strlen(ACLK_CLOUD_REQ_V2_PREFIX))) {
96 errno = 0;
97 error("Only accepting requests that start with \"%s\" from CLOUD.", ACLK_CLOUD_REQ_V2_PREFIX);
@@ -120,7 +121,9 @@ static inline int aclk_v2_payload_get_query(const char *payload, char **query_ur
121
122 static int aclk_handle_cloud_request_v2(struct aclk_request *cloud_to_agent, char *raw_payload)
123 {
123 - HTTP_CHECK_AGENT_INITIALIZED();
124 + if (!aclk_use_new_cloud_arch) {
125 + HTTP_CHECK_AGENT_INITIALIZED();
126 + }
127
128 aclk_query_t query;
129
@@ -256,3 +259,57 @@ err_cleanup_nojson:
259
260 return 1;
261 }
262 +
263 +void aclk_handle_new_cloud_msg(const char *message_type, const char *msg, size_t msg_len)
264 +{
265 + // TODO do the look up table with hashes to optimize when there are more
266 + // than few
267 + if (!strcmp(message_type, "cmd")) {
268 + aclk_handle_cloud_message((char *)msg);
269 + return;
270 + }
271 + if (!strcmp(message_type, "CreateNodeInstanceResult")) {
272 + node_instance_creation_result_t res = parse_create_node_instance_result(msg, msg_len);
273 + debug(D_ACLK, "CreateNodeInstanceResult: guid:%s nodeid:%s", res.machine_guid, res.node_id);
274 + uuid_t host_id, node_id;
275 + uuid_parse(res.machine_guid, host_id);
276 + uuid_parse(res.node_id, node_id);
277 + update_node_id(&host_id, &node_id);
278 +
279 + aclk_query_t query = aclk_query_new(NODE_STATE_UPDATE);
280 + query->data.node_update.hops = 1; //TODO - real hop count instead of hardcoded
281 + rrdhost_aclk_state_lock(localhost);
282 + query->data.node_update.claim_id = strdupz(localhost->aclk_state.claimed_id);
283 + rrdhost_aclk_state_unlock(localhost);
284 +
285 + RRDHOST *host = rrdhost_find_by_guid(res.machine_guid, 0);
286 + query->data.node_update.live = 0;
287 +
288 + if (host) {
289 + // not all host must have RRDHOST struct created for them
290 + // if they never connected during runtime of agent
291 + if (host == localhost) {
292 + query->data.node_update.live = 1;
293 + query->data.node_update.hops = 0;
294 + } else {
295 + netdata_mutex_lock(&host->receiver_lock);
296 + query->data.node_update.live = (host->receiver != NULL);
297 + netdata_mutex_unlock(&host->receiver_lock);
298 + }
299 + }
300 +
301 + query->data.node_update.node_id = res.node_id; // aclk_query_free will free it
302 + query->data.node_update.queryable = 1;
303 + query->data.node_update.session_id = aclk_session_newarch;
304 + aclk_queue_query(query);
305 + freez(res.machine_guid);
306 + return;
307 + }
308 + if (!strcmp(message_type, "SendNodeInstances")) {
309 + debug(D_ACLK, "Got SendNodeInstances");
310 + aclk_send_node_instances();
311 + return;
312 + }
313 +
314 + error ("Unknown new cloud arch message type received \"%s\"", message_type);
315 +}
aclk/aclk_rx_msgs.h
+2
@@ -10,4 +10,6 @@
10
11 int aclk_handle_cloud_message(char *payload);
12
13 +void aclk_handle_new_cloud_msg(const char *message_type, const char *msg, size_t msg_len);
14 +
15 #endif /* ACLK_RX_MSGS_H */
aclk/aclk_tx_msgs.c
+110
@@ -36,6 +36,37 @@ static void aclk_send_message_subtopic(mqtt_wss_client client, json_object *msg,
36 #endif
37 }
38
39 +static uint16_t aclk_send_bin_message_subtopic_pid(mqtt_wss_client client, char *msg, size_t msg_len, enum aclk_topics subtopic, const char *msgname)
40 +{
41 +#ifndef ACLK_LOG_CONVERSATION_DIR
42 + UNUSED(msgname);
43 +#endif
44 + uint16_t packet_id;
45 + const char *topic = aclk_get_topic(subtopic);
46 +
47 + if (unlikely(!topic)) {
48 + error("Couldn't get topic. Aborting message send.");
49 + return 0;
50 + }
51 +
52 + mqtt_wss_publish_pid(client, topic, msg, msg_len, MQTT_WSS_PUB_QOS1, &packet_id);
53 +#ifdef NETDATA_INTERNAL_CHECKS
54 + aclk_stats_msg_published(packet_id);
55 +#endif
56 +#ifdef ACLK_LOG_CONVERSATION_DIR
57 +#define FN_MAX_LEN 1024
58 + char filename[FN_MAX_LEN];
59 + snprintf(filename, FN_MAX_LEN, ACLK_LOG_CONVERSATION_DIR "/%010d-tx-%s.bin", ACLK_GET_CONV_LOG_NEXT(), msgname);
60 + FILE *fptr;
61 + if (fptr = fopen(filename,"w")) {
62 + fwrite(msg, msg_len, 1, fptr);
63 + fclose(fptr);
64 + }
65 +#endif
66 +
67 + return packet_id;
68 +}
69 +
70 static uint16_t aclk_send_message_subtopic_pid(mqtt_wss_client client, json_object *msg, enum aclk_topics subtopic)
71 {
72 uint16_t packet_id;
@@ -372,6 +403,85 @@ int aclk_send_app_layer_disconnect(mqtt_wss_client client, const char *message)
403 return pid;
404 }
405
406 +// new protobuf msgs
407 +uint16_t aclk_send_agent_connection_update(mqtt_wss_client client, int reachable) {
408 + size_t len;
409 + uint16_t pid;
410 + update_agent_connection_t conn = {
411 + .reachable = (reachable ? 1 : 0),
412 + .lwt = 0,
413 + .session_id = aclk_session_newarch
414 + };
415 +
416 + rrdhost_aclk_state_lock(localhost);
417 + if (unlikely(!localhost->aclk_state.claimed_id)) {
418 + error("Internal error. Should not come here if not claimed");
419 + rrdhost_aclk_state_unlock(localhost);
420 + return 0;
421 + }
422 + conn.claim_id = localhost->aclk_state.claimed_id;
423 +
424 + char *msg = generate_update_agent_connection(&len, &conn);
425 + rrdhost_aclk_state_unlock(localhost);
426 +
427 + if (!msg) {
428 + error("Error generating agent::v1::UpdateAgentConnection payload");
429 + return 0;
430 + }
431 +
432 + pid = aclk_send_bin_message_subtopic_pid(client, msg, len, ACLK_TOPICID_AGENT_CONN, "UpdateAgentConnection");
433 + freez(msg);
434 + return pid;
435 +}
436 +
437 +char *aclk_generate_lwt(size_t *size) {
438 + update_agent_connection_t conn = {
439 + .reachable = 0,
440 + .lwt = 1,
441 + .session_id = aclk_session_newarch
442 + };
443 +
444 + rrdhost_aclk_state_lock(localhost);
445 + if (unlikely(!localhost->aclk_state.claimed_id)) {
446 + error("Internal error. Should not come here if not claimed");
447 + rrdhost_aclk_state_unlock(localhost);
448 + return NULL;
449 + }
450 + conn.claim_id = localhost->aclk_state.claimed_id;
451 +
452 + char *msg = generate_update_agent_connection(size, &conn);
453 + rrdhost_aclk_state_unlock(localhost);
454 +
455 + if (!msg)
456 + error("Error generating agent::v1::UpdateAgentConnection payload for LWT");
457 +
458 + return msg;
459 +}
460 +
461 +void aclk_generate_node_registration(mqtt_wss_client client, node_instance_creation_t *node_creation) {
462 + size_t len;
463 + char *msg = generate_node_instance_creation(&len, node_creation);
464 + if (!msg) {
465 + error("Error generating nodeinstance::create::v1::CreateNodeInstance");
466 + return;
467 + }
468 +
469 + aclk_send_bin_message_subtopic_pid(client, msg, len, ACLK_TOPICID_CREATE_NODE, "CreateNodeInstance");
470 + freez(msg);
471 +}
472 +
473 +void aclk_generate_node_state_update(mqtt_wss_client client, node_instance_connection_t *node_connection) {
474 + size_t len;
475 + char *msg = generate_node_instance_connection(&len, node_connection);
476 + if (!msg) {
477 + error("Error generating nodeinstance::v1::UpdateNodeInstanceConnection");
478 + return;
479 + }
480 +
481 + aclk_send_bin_message_subtopic_pid(client, msg, len, ACLK_TOPICID_NODE_CONN, "UpdateNodeInstanceConnection");
482 + freez(msg);
483 +}
484 +
485 #ifndef __GNUC__
486 #pragma endregion
487 #endif
aclk/aclk_tx_msgs.h
+8
@@ -6,6 +6,7 @@
6 #include "libnetdata/libnetdata.h"
7 #include "daemon/common.h"
8 #include "mqtt_wss_client.h"
9 +#include "schema-wrappers/schema_wrappers.h"
10
11 void aclk_send_info_metadata(mqtt_wss_client client, int metadata_submitted, RRDHOST *host);
12 void aclk_send_alarm_metadata(mqtt_wss_client client, int metadata_submitted);
@@ -19,4 +20,11 @@ void aclk_alarm_state_msg(mqtt_wss_client client, json_object *msg);
20 json_object *aclk_generate_disconnect(const char *message);
21 int aclk_send_app_layer_disconnect(mqtt_wss_client client, const char *message);
22
23 +// new protobuf msgs
24 +uint16_t aclk_send_agent_connection_update(mqtt_wss_client client, int reachable);
25 +char *aclk_generate_lwt(size_t *size);
26 +
27 +void aclk_generate_node_registration(mqtt_wss_client client, node_instance_creation_t *node_creation);
28 +void aclk_generate_node_state_update(mqtt_wss_client client, node_instance_connection_t *node_connection);
29 +
30 #endif
aclk/aclk_util.c
+29 -7
@@ -10,6 +10,9 @@
10 #define UUID_STR_LEN 37
11 #endif
12
13 +int aclk_use_new_cloud_arch = 0;
14 +usec_t aclk_session_newarch = 0;
15 +
16 aclk_encoding_type_t aclk_encoding_type_t_from_str(const char *str) {
17 if (!strcmp(str, "json")) {
18 return ACLK_ENC_JSON;
@@ -107,14 +110,18 @@ struct topic_name {
110 // in answer to /password endpoint
111 const char *name;
112 } topic_names[] = {
110 - { .id = ACLK_TOPICID_CHART, .name = "chart" },
111 - { .id = ACLK_TOPICID_ALARMS, .name = "alarms" },
112 - { .id = ACLK_TOPICID_METADATA, .name = "meta" },
113 - { .id = ACLK_TOPICID_COMMAND, .name = "inbox-cmd" },
114 - { .id = ACLK_TOPICID_UNKNOWN, .name = NULL }
113 + { .id = ACLK_TOPICID_CHART, .name = "chart" },
114 + { .id = ACLK_TOPICID_ALARMS, .name = "alarms" },
115 + { .id = ACLK_TOPICID_METADATA, .name = "meta" },
116 + { .id = ACLK_TOPICID_COMMAND, .name = "inbox-cmd" },
117 + { .id = ACLK_TOPICID_AGENT_CONN, .name = "agent-connection" },
118 + { .id = ACLK_TOPICID_CMD_NG_V1, .name = "inbox-cmd-v1" },
119 + { .id = ACLK_TOPICID_CREATE_NODE, .name = "create-node-instance" },
120 + { .id = ACLK_TOPICID_NODE_CONN, .name = "node-instance-connection" },
121 + { .id = ACLK_TOPICID_UNKNOWN, .name = NULL }
122 };
123
117 -enum aclk_topics compulsory_topics[] = {
124 +enum aclk_topics compulsory_topics_legacy[] = {
125 ACLK_TOPICID_CHART,
126 ACLK_TOPICID_ALARMS,
127 ACLK_TOPICID_METADATA,
@@ -122,6 +129,19 @@ enum aclk_topics compulsory_topics[] = {
129 ACLK_TOPICID_UNKNOWN
130 };
131
132 +enum aclk_topics compulsory_topics_new_cloud_arch[] = {
133 +// TODO remove old topics once not needed anymore
134 + ACLK_TOPICID_CHART,
135 + ACLK_TOPICID_ALARMS,
136 + ACLK_TOPICID_METADATA,
137 + ACLK_TOPICID_COMMAND,
138 + ACLK_TOPICID_AGENT_CONN,
139 + ACLK_TOPICID_CMD_NG_V1,
140 + ACLK_TOPICID_CREATE_NODE,
141 + ACLK_TOPICID_NODE_CONN,
142 + ACLK_TOPICID_UNKNOWN
143 +};
144 +
145 static enum aclk_topics topic_name_to_id(const char *name) {
146 struct topic_name *topic = topic_names;
147 while (topic->name) {
@@ -186,7 +206,7 @@ static int topic_cache_add_topic(struct json_object *json, struct aclk_topic *to
206 }
207 topic->topic_id = topic_name_to_id(json_object_get_string(json_object_iter_peek_value(&it)));
208 if (topic->topic_id == ACLK_TOPICID_UNKNOWN) {
189 - info("topic dictionary has unknown topic name \"%s\"", json_object_get_string(json_object_iter_peek_value(&it)));
209 + debug(D_ACLK, "topic dictionary has unknown topic name \"%s\"", json_object_get_string(json_object_iter_peek_value(&it)));
210 }
211 json_object_iter_next(&it);
212 continue;
@@ -244,6 +264,8 @@ int aclk_generate_topic_cache(struct json_object *json)
264 }
265 }
266
267 + enum aclk_topics *compulsory_topics = aclk_use_new_cloud_arch ? compulsory_topics_new_cloud_arch : compulsory_topics_legacy;
268 +
269 for (int i = 0; compulsory_topics[i] != ACLK_TOPICID_UNKNOWN; i++) {
270 if (!aclk_get_topic(compulsory_topics[i])) {
271 error("missing compulsory topic \"%s\" in password response from cloud", topic_id_to_name(compulsory_topics[i]));
aclk/aclk_util.h
+12 -5
@@ -8,6 +8,9 @@
8 // Helper stuff which should not have any further inside ACLK dependency
9 // and are supposed not to be needed outside of ACLK
10
11 +extern int aclk_use_new_cloud_arch;
12 +extern usec_t aclk_session_newarch;
13 +
14 typedef enum {
15 ACLK_ENC_UNKNOWN = 0,
16 ACLK_ENC_JSON,
@@ -51,11 +54,15 @@ void aclk_transport_desc_t_destroy(aclk_transport_desc_t *trp_desc);
54 void aclk_env_t_destroy(aclk_env_t *env);
55
56 enum aclk_topics {
54 - ACLK_TOPICID_UNKNOWN = 0,
55 - ACLK_TOPICID_CHART = 1,
56 - ACLK_TOPICID_ALARMS = 2,
57 - ACLK_TOPICID_METADATA = 3,
58 - ACLK_TOPICID_COMMAND = 4
57 + ACLK_TOPICID_UNKNOWN = 0,
58 + ACLK_TOPICID_CHART = 1,
59 + ACLK_TOPICID_ALARMS = 2,
60 + ACLK_TOPICID_METADATA = 3,
61 + ACLK_TOPICID_COMMAND = 4,
62 + ACLK_TOPICID_AGENT_CONN = 5,
63 + ACLK_TOPICID_CMD_NG_V1 = 6,
64 + ACLK_TOPICID_CREATE_NODE = 7,
65 + ACLK_TOPICID_NODE_CONN = 8
66 };
67
68 const char *aclk_get_topic(enum aclk_topics topic);
aclk/legacy/agent_cloud_link.c
+9 -14
@@ -1269,7 +1269,7 @@ int aclk_send_info_child_connection(RRDHOST *host, ACLK_CMD cmd)
1269 return 0;
1270 }
1271
1272 -void aclk_host_state_update(RRDHOST *host, ACLK_CMD cmd)
1272 +void legacy_aclk_host_state_update(RRDHOST *host, int connect)
1273 {
1274 #if ACLK_VERSION_MIN < ACLK_V_CHILDRENSTATE
1275 if (legacy_aclk_shared_state.version_neg < ACLK_V_CHILDRENSTATE)
@@ -1281,19 +1281,14 @@ void aclk_host_state_update(RRDHOST *host, ACLK_CMD cmd)
1281 if (unlikely(aclk_host_initializing(localhost)))
1282 return;
1283
1284 - switch (cmd) {
1285 - case ACLK_CMD_CHILD_CONNECT:
1286 - debug(D_ACLK, "Child Connected %s %s.", host->hostname, host->machine_guid);
1287 - aclk_start_host_popcorning(host);
1288 - legacy_aclk_queue_query("add_child", host, NULL, NULL, 0, 1, ACLK_CMD_CHILD_CONNECT);
1289 - break;
1290 - case ACLK_CMD_CHILD_DISCONNECT:
1291 - debug(D_ACLK, "Child Disconnected %s %s.", host->hostname, host->machine_guid);
1292 - aclk_stop_host_popcorning(host);
1293 - legacy_aclk_queue_query("del_child", host, NULL, NULL, 0, 1, ACLK_CMD_CHILD_DISCONNECT);
1294 - break;
1295 - default:
1296 - error("Unknown command for aclk_host_state_update %d.", (int)cmd);
1284 + if (connect) {
1285 + debug(D_ACLK, "Child Connected %s %s.", host->hostname, host->machine_guid);
1286 + aclk_start_host_popcorning(host);
1287 + legacy_aclk_queue_query("add_child", host, NULL, NULL, 0, 1, ACLK_CMD_CHILD_CONNECT);
1288 + } else {
1289 + debug(D_ACLK, "Child Disconnected %s %s.", host->hostname, host->machine_guid);
1290 + aclk_stop_host_popcorning(host);
1291 + legacy_aclk_queue_query("del_child", host, NULL, NULL, 0, 1, ACLK_CMD_CHILD_DISCONNECT);
1292 }
1293 }
1294
aclk/legacy/agent_cloud_link.h
+1 -1
@@ -73,7 +73,7 @@ void legacy_aclk_alarm_reload(void);
73 unsigned long int aclk_reconnect_delay(int mode);
74 extern void health_alarm_entry2json_nolock(BUFFER *wb, ALARM_ENTRY *ae, RRDHOST *host);
75
76 -void aclk_host_state_update(RRDHOST *host, ACLK_CMD cmd);
76 +void legacy_aclk_host_state_update(RRDHOST *host, int connect);
77 int aclk_send_info_child_connection(RRDHOST *host, ACLK_CMD cmd);
78 void aclk_update_next_child_to_popcorn(void);
79
aclk/schema-wrappers/connection.cc new
+34
@@ -0,0 +1,34 @@
1 +// SPDX-License-Identifier: GPL-3.0-or-later
2 +
3 +#include "proto/agent/v1/connection.pb.h"
4 +#include "connection.h"
5 +
6 +#include "schema_wrapper_utils.h"
7 +
8 +#include <sys/time.h>
9 +#include <stdlib.h>
10 +
11 +char *generate_update_agent_connection(size_t *len, const update_agent_connection_t *data)
12 +{
13 + agent::v1::UpdateAgentConnection connupd;
14 +
15 + connupd.set_claim_id(data->claim_id);
16 + connupd.set_reachable(data->reachable);
17 + connupd.set_session_id(data->session_id);
18 +
19 + connupd.set_update_source((data->lwt) ? agent::v1::CONNECTION_UPDATE_SOURCE_LWT : agent::v1::CONNECTION_UPDATE_SOURCE_AGENT);
20 +
21 + struct timeval tv;
22 + gettimeofday(&tv, NULL);
23 +
24 + google::protobuf::Timestamp *timestamp = connupd.mutable_updated_at();
25 + timestamp->set_seconds(tv.tv_sec);
26 + timestamp->set_nanos(tv.tv_usec * 1000);
27 +
28 + *len = PROTO_COMPAT_MSG_SIZE(connupd);
29 + char *msg = (char*)malloc(*len);
30 + if (msg)
31 + connupd.SerializeToArray(msg, *len);
32 +
33 + return msg;
34 +}
aclk/schema-wrappers/connection.h new
+34
@@ -0,0 +1,34 @@
1 +// SPDX-License-Identifier: GPL-3.0-or-later
2 +
3 +#ifndef ACLK_SCHEMA_WRAPPER_CONNECTION_H
4 +#define ACLK_SCHEMA_WRAPPER_CONNECTION_H
5 +
6 +#ifdef __cplusplus
7 +extern "C" {
8 +#endif
9 +
10 +typedef struct {
11 + const char *claim_id;
12 + unsigned int reachable:1;
13 +
14 + int64_t session_id;
15 +
16 + unsigned int lwt:1;
17 +
18 +// TODO in future optional fields
19 +// > 15 optional fields:
20 +// How long the system was running until connection (only applicable when reachable=true)
21 +// google.protobuf.Duration system_uptime = 15;
22 +// How long the netdata agent was running until connection (only applicable when reachable=true)
23 +// google.protobuf.Duration agent_uptime = 16;
24 +
25 +
26 +} update_agent_connection_t;
27 +
28 +char *generate_update_agent_connection(size_t *len, const update_agent_connection_t *data);
29 +
30 +#ifdef __cplusplus
31 +}
32 +#endif
33 +
34 +#endif /* ACLK_SCHEMA_WRAPPER_CONNECTION_H */
aclk/schema-wrappers/node_connection.cc new
+37
@@ -0,0 +1,37 @@
1 +// SPDX-License-Identifier: GPL-3.0-or-later
2 +
3 +#include "proto/nodeinstance/connection/v1/connection.pb.h"
4 +#include "node_connection.h"
5 +
6 +#include "schema_wrapper_utils.h"
7 +
8 +#include <sys/time.h>
9 +#include <stdlib.h>
10 +
11 +char *generate_node_instance_connection(size_t *len, const node_instance_connection_t *data) {
12 + nodeinstance::v1::UpdateNodeInstanceConnection msg;
13 +
14 + if(data->claim_id)
15 + msg.set_claim_id(data->claim_id);
16 + msg.set_node_id(data->node_id);
17 +
18 + msg.set_liveness(data->live);
19 + msg.set_queryable(data->queryable);
20 +
21 + msg.set_session_id(data->session_id);
22 + msg.set_hops(data->hops);
23 +
24 + struct timeval tv;
25 + gettimeofday(&tv, NULL);
26 +
27 + google::protobuf::Timestamp *timestamp = msg.mutable_updated_at();
28 + timestamp->set_seconds(tv.tv_sec);
29 + timestamp->set_nanos(tv.tv_usec * 1000);
30 +
31 + *len = PROTO_COMPAT_MSG_SIZE(msg);
32 + char *bin = (char*)malloc(*len);
33 + if (bin)
34 + msg.SerializeToArray(bin, *len);
35 +
36 + return bin;
37 +}
aclk/schema-wrappers/node_connection.h new
+29
@@ -0,0 +1,29 @@
1 +// SPDX-License-Identifier: GPL-3.0-or-later
2 +
3 +#ifndef ACLK_SCHEMA_WRAPPER_NODE_CONNECTION_H
4 +#define ACLK_SCHEMA_WRAPPER_NODE_CONNECTION_H
5 +
6 +#ifdef __cplusplus
7 +extern "C" {
8 +#endif
9 +
10 +typedef struct {
11 + const char* claim_id;
12 + const char* node_id;
13 +
14 + unsigned int live:1;
15 + unsigned int queryable:1;
16 +
17 + int64_t session_id;
18 +
19 + int32_t hops;
20 +} node_instance_connection_t;
21 +
22 +char *generate_node_instance_connection(size_t *len, const node_instance_connection_t *data);
23 +
24 +
25 +#ifdef __cplusplus
26 +}
27 +#endif
28 +
29 +#endif /* ACLK_SCHEMA_WRAPPER_NODE_CONNECTION_H */
aclk/schema-wrappers/node_creation.cc new
+39
@@ -0,0 +1,39 @@
1 +// SPDX-License-Identifier: GPL-3.0-or-later
2 +
3 +#include "proto/nodeinstance/create/v1/creation.pb.h"
4 +#include "node_creation.h"
5 +
6 +#include "schema_wrapper_utils.h"
7 +
8 +#include <stdlib.h>
9 +
10 +char *generate_node_instance_creation(size_t *len, const node_instance_creation_t *data)
11 +{
12 + nodeinstance::create::v1::CreateNodeInstance msg;
13 +
14 + if (data->claim_id)
15 + msg.set_claim_id(data->claim_id);
16 + msg.set_machine_guid(data->machine_guid);
17 + msg.set_hostname(data->hostname);
18 + msg.set_hops(data->hops);
19 +
20 + *len = PROTO_COMPAT_MSG_SIZE(msg);
21 + char *bin = (char*)malloc(*len);
22 + if (bin)
23 + msg.SerializeToArray(bin, *len);
24 +
25 + return bin;
26 +}
27 +
28 +node_instance_creation_result_t parse_create_node_instance_result(const char *data, size_t len)
29 +{
30 + nodeinstance::create::v1::CreateNodeInstanceResult msg;
31 + node_instance_creation_result_t res = { .node_id = NULL, .machine_guid = NULL };
32 +
33 + if (!msg.ParseFromArray(data, len))
34 + return res;
35 +
36 + res.node_id = strdup(msg.node_id().c_str());
37 + res.machine_guid = strdup(msg.machine_guid().c_str());
38 + return res;
39 +}
aclk/schema-wrappers/node_creation.h new
+31
@@ -0,0 +1,31 @@
1 +// SPDX-License-Identifier: GPL-3.0-or-later
2 +
3 +#ifndef ACLK_SCHEMA_WRAPPER_NODE_CREATION_H
4 +#define ACLK_SCHEMA_WRAPPER_NODE_CREATION_H
5 +
6 +#ifdef __cplusplus
7 +extern "C" {
8 +#endif
9 +
10 +typedef struct {
11 + const char* claim_id;
12 + const char* machine_guid;
13 + const char* hostname;
14 +
15 + int32_t hops;
16 +} node_instance_creation_t;
17 +
18 +typedef struct {
19 + char *node_id;
20 + char *machine_guid;
21 +} node_instance_creation_result_t;
22 +
23 +char *generate_node_instance_creation(size_t *len, const node_instance_creation_t *data);
24 +node_instance_creation_result_t parse_create_node_instance_result(const char *data, size_t len);
25 +
26 +
27 +#ifdef __cplusplus
28 +}
29 +#endif
30 +
31 +#endif /* ACLK_SCHEMA_WRAPPER_NODE_CREATION_H */
aclk/schema-wrappers/schema_wrapper_utils.h new
+12
@@ -0,0 +1,12 @@
1 +// SPDX-License-Identifier: GPL-3.0-or-later
2 +
3 +#ifndef SCHEMA_WRAPPER_UTILS_H
4 +#define SCHEMA_WRAPPER_UTILS_H
5 +
6 +#if GOOGLE_PROTOBUF_VERSION < 3001000
7 +#define PROTO_COMPAT_MSG_SIZE(msg) (size_t)msg.ByteSize();
8 +#else
9 +#define PROTO_COMPAT_MSG_SIZE(msg) msg.ByteSizeLong();
10 +#endif
11 +
12 +#endif /* SCHEMA_WRAPPER_UTILS_H */
aclk/schema-wrappers/schema_wrappers.h new
+12
@@ -0,0 +1,12 @@
1 +// SPDX-License-Identifier: GPL-3.0-or-later
2 +
3 +// utility header to include all the message wrappers at once
4 +
5 +#ifndef SCHEMA_WRAPPERS_H
6 +#define SCHEMA_WRAPPERS_H
7 +
8 +#include "connection.h"
9 +#include "node_connection.h"
10 +#include "node_creation.h"
11 +
12 +#endif /* SCHEMA_WRAPPERS_H */
configure.ac
+55 -26
@@ -642,6 +642,27 @@ AM_CONDITIONAL([ENABLE_CAPABILITY], [test "${with_libcap}" = "yes"])
642 # -----------------------------------------------------------------------------
643 # ACLK
644
645 +PKG_CHECK_MODULES(
646 + [PROTOBUF],
647 + [protobuf >= 3],
648 + [have_libprotobuf=yes],
649 + [have_libprotobuf=no]
650 +)
651 +
652 +AC_PATH_PROG([PROTOC], [protoc], [no])
653 +AS_IF(
654 + [test x"${PROTOC}" == x"no"],
655 + [have_protoc=no],
656 + [have_protoc=yes]
657 +)
658 +
659 +AC_PATH_PROG([CXX_BINARY], [${CXX}], [no])
660 +AS_IF(
661 + [test x"${CXX_BINARY}" == x"no"],
662 + [have_CXX_compiler=no],
663 + [have_CXX_compiler=yes]
664 +)
665 +
666 AC_MSG_CHECKING([if Cloud functionality should be enabled])
667 AC_MSG_RESULT([${enable_cloud}])
668 if test "$aclk_ng" = "no"; then
@@ -684,6 +705,27 @@ if test "$enable_cloud" != "no" -a "$aclk_ng" != "no"; then
705 else
706 AC_MSG_RESULT([yes])
707 fi
708 + AC_MSG_CHECKING([if protobuf available for ACLK Next Generation])
709 + if test "${have_libprotobuf}" != "yes"; then
710 + AC_MSG_RESULT([no])
711 + can_enable_ng="no"
712 + else
713 + AC_MSG_RESULT([yes])
714 + fi
715 + AC_MSG_CHECKING([if protoc available for ACLK Next Generation])
716 + if test "${have_protoc}" != "yes"; then
717 + AC_MSG_RESULT([no])
718 + can_enable_ng="no"
719 + else
720 + AC_MSG_RESULT([yes])
721 + fi
722 + AC_MSG_CHECKING([if C++ compiler available for ACLK Next Generation])
723 + if test "${have_CXX_compiler}" != "yes"; then
724 + AC_MSG_RESULT([no])
725 + can_enable_ng="no"
726 + else
727 + AC_MSG_RESULT([yes])
728 + fi
729 AC_MSG_CHECKING([ACLK Next Generation can be built])
730 AC_MSG_RESULT([${can_enable_ng}])
731 if test "$can_enable_ng" = "no" -a "$aclk_ng" = "yes"; then
@@ -694,7 +736,10 @@ if test "$enable_cloud" != "no" -a "$aclk_ng" != "no"; then
736 enable_aclk="yes"
737 AC_DEFINE([ACLK_NG], [1], [ACLK Next Generation Should be used])
738 AC_DEFINE([ENABLE_ACLK], [1], [netdata ACLK])
697 - 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"
739 + 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 -I \$(abs_top_srcdir)/aclk/aclk-schemas"
740 + OPTIONAL_PROTOBUF_CFLAGS="${PROTOBUF_CFLAGS}"
741 + CXX11FLAG="-std=c++11"
742 + OPTIONAL_PROTOBUF_LIBS="${PROTOBUF_LIBS}"
743 fi
744 fi
745
@@ -1291,13 +1336,6 @@ AM_CONDITIONAL([ENABLE_EXPORTING_PUBSUB], [test "${enable_exporting_pubsub}" = "
1336 # -----------------------------------------------------------------------------
1337 # Prometheus remote write backend - libprotobuf, libsnappy, protoc
1338
1294 -PKG_CHECK_MODULES(
1295 - [PROTOBUF],
1296 - [protobuf >= 3],
1297 - [have_libprotobuf=yes],
1298 - [have_libprotobuf=no]
1299 -)
1300 -
1339 AC_MSG_CHECKING([for snappy::RawCompress in -lsnappy])
1340
1341 AC_LANG_SAVE
@@ -1333,20 +1371,6 @@ AC_MSG_CHECKING([for snappy::RawCompress in -lsnappy])
1371
1372 AC_MSG_RESULT([${have_libsnappy}])
1373
1336 -AC_PATH_PROG([PROTOC], [protoc], [no])
1337 -AS_IF(
1338 - [test x"${PROTOC}" == x"no"],
1339 - [have_protoc=no],
1340 - [have_protoc=yes]
1341 -)
1342 -
1343 -AC_PATH_PROG([CXX_BINARY], [${CXX}], [no])
1344 -AS_IF(
1345 - [test x"${CXX_BINARY}" == x"no"],
1346 - [have_CXX_compiler=no],
1347 - [have_CXX_compiler=yes]
1348 -)
1349 -
1374 test "${enable_backend_prometheus_remote_write}" = "yes" -a "${have_libprotobuf}" != "yes" && \
1375 AC_MSG_ERROR([libprotobuf required but not found. try installing protobuf])
1376
@@ -1364,9 +1388,11 @@ if test "${enable_backend_prometheus_remote_write}" != "no" -a "${have_libprotob
1388 -a "${have_protoc}" = "yes" -a "${have_CXX_compiler}" = "yes"; then
1389 enable_backend_prometheus_remote_write="yes"
1390 AC_DEFINE([ENABLE_PROMETHEUS_REMOTE_WRITE], [1], [Prometheus remote write API usability])
1367 - OPTIONAL_PROMETHEUS_REMOTE_WRITE_CFLAGS="${PROTOBUF_CFLAGS} ${SNAPPY_CFLAGS} -I \$(abs_top_srcdir)/exporting/prometheus/remote_write"
1391 + OPTIONAL_PROMETHEUS_REMOTE_WRITE_CFLAGS="${SNAPPY_CFLAGS} -I \$(abs_top_srcdir)/exporting/prometheus/remote_write"
1392 CXX11FLAG="-std=c++11"
1369 - OPTIONAL_PROMETHEUS_REMOTE_WRITE_LIBS="${PROTOBUF_LIBS} ${SNAPPY_LIBS}"
1393 + OPTIONAL_PROMETHEUS_REMOTE_WRITE_LIBS="${SNAPPY_LIBS}"
1394 + OPTIONAL_PROTOBUF_CFLAGS="${PROTOBUF_CFLAGS}"
1395 + OPTIONAL_PROTOBUF_LIBS="${PROTOBUF_LIBS}"
1396 else
1397 enable_backend_prometheus_remote_write="no"
1398 fi
@@ -1449,7 +1475,8 @@ AC_MSG_RESULT([${enable_lto}])
1475
1476 AM_CONDITIONAL([ENABLE_CXX_LINKER], [test "${enable_backend_kinesis}" = "yes" \
1477 -o "${enable_exporting_pubsub}" = "yes" \
1452 - -o "${enable_backend_prometheus_remote_write}" = "yes"])
1478 + -o "${enable_backend_prometheus_remote_write}" = "yes" \
1479 + -o "${aclk_ng}" = "yes"])
1480
1481 AC_DEFINE_UNQUOTED([NETDATA_USER], ["${with_user}"], [use this user to drop privileged])
1482
@@ -1481,7 +1508,7 @@ CFLAGS="${CFLAGS} ${OPTIONAL_MATH_CFLAGS} ${OPTIONAL_NFACCT_CFLAGS} ${OPTIONAL_Z
1508 ${OPTIONAL_LIBCAP_CFLAGS} ${OPTIONAL_IPMIMONITORING_CFLAGS} ${OPTIONAL_CUPS_CFLAGS} ${OPTIONAL_XENSTAT_FLAGS} \
1509 ${OPTIONAL_KINESIS_CFLAGS} ${OPTIONAL_PUBSUB_CFLAGS} ${OPTIONAL_PROMETHEUS_REMOTE_WRITE_CFLAGS} \
1510 ${OPTIONAL_MONGOC_CFLAGS} ${LWS_CFLAGS} ${OPTIONAL_JSONC_STATIC_CFLAGS} ${OPTIONAL_BPF_CFLAGS} ${OPTIONAL_JUDY_CFLAGS} \
1484 - ${OPTIONAL_ACLK_NG_CFLAGS}"
1511 + ${OPTIONAL_ACLK_NG_CFLAGS} ${OPTIONAL_PROTOBUF_CFLAGS}"
1512
1513 CXXFLAGS="${CFLAGS} ${CXX11FLAG}"
1514
@@ -1532,6 +1559,8 @@ AC_SUBST([OPTIONAL_MONGOC_CFLAGS])
1559 AC_SUBST([OPTIONAL_MONGOC_LIBS])
1560 AC_SUBST([OPTIONAL_LWS_LIBS])
1561 AC_SUBST([OPTIONAL_ACLK_NG_CFLAGS])
1562 +AC_SUBST([OPTIONAL_PROTOBUF_CFLAGS])
1563 +AC_SUBST([OPTIONAL_PROTOBUF_LIBS])
1564
1565 # -----------------------------------------------------------------------------
1566 # Check if cmocka is available - needed for unit testing
database/sqlite/sqlite_functions.c
+36
@@ -1430,6 +1430,42 @@ failed:
1430 return rc - 1;
1431 }
1432
1433 +#define SQL_SELECT_HOST_BY_NODE_ID "select host_id from node_instance where node_id = @node_id;"
1434 +
1435 +int get_host_id(uuid_t *node_id, uuid_t *host_id)
1436 +{
1437 + sqlite3_stmt *res = NULL;
1438 + int rc;
1439 +
1440 + if (unlikely(!db_meta)) {
1441 + if (default_rrd_memory_mode == RRD_MEMORY_MODE_DBENGINE)
1442 + error_report("Database has not been initialized");
1443 + return 1;
1444 + }
1445 +
1446 + rc = sqlite3_prepare_v2(db_meta, SQL_SELECT_HOST_BY_NODE_ID, -1, &res, 0);
1447 + if (unlikely(rc != SQLITE_OK)) {
1448 + error_report("Failed to prepare statement to select node instance information for a node");
1449 + return 1;
1450 + }
1451 +
1452 + rc = sqlite3_bind_blob(res, 1, node_id, sizeof(*node_id), SQLITE_STATIC);
1453 + if (unlikely(rc != SQLITE_OK)) {
1454 + error_report("Failed to bind host_id parameter to select node instance information");
1455 + goto failed;
1456 + }
1457 +
1458 + rc = sqlite3_step(res);
1459 + if (likely(rc == SQLITE_ROW && host_id))
1460 + uuid_copy(*host_id, *((uuid_t *) sqlite3_column_blob(res, 0)));
1461 +
1462 +failed:
1463 + if (unlikely(sqlite3_finalize(res) != SQLITE_OK))
1464 + error_report("Failed to finalize the prepared statement when selecting node instance information");
1465 +
1466 + return (rc == SQLITE_ROW) ? 0 : -1;
1467 +}
1468 +
1469 #define SQL_SELECT_NODE_ID "select node_id from node_instance where host_id = @host_id and node_id not null;"
1470
1471 int get_node_id(uuid_t *host_id, uuid_t *node_id)
database/sqlite/sqlite_functions.h
+1
@@ -74,6 +74,7 @@ extern void sql_build_context_param_list(struct context_param **param_list, RRDH
74 extern void store_claim_id(uuid_t *host_id, uuid_t *claim_id);
75 extern int update_node_id(uuid_t *host_id, uuid_t *node_id);
76 extern int get_node_id(uuid_t *host_id, uuid_t *node_id);
77 +extern int get_host_id(uuid_t *node_id, uuid_t *host_id);
78 extern void invalidate_node_instances(uuid_t *host_id, uuid_t *claim_id);
79 extern struct node_instance_list *get_node_list(void);
80 extern void sql_load_node_id(RRDHOST *host);
streaming/receiver.c
+4 -4
@@ -454,11 +454,11 @@ static int rrdpush_receive(struct receiver_state *rpt)
454
455 cd.version = rpt->stream_version;
456
457 -#if defined(ENABLE_ACLK) && !defined(ACLK_NG)
457 +#if defined(ENABLE_ACLK)
458 // in case we have cloud connection we inform cloud
459 // new slave connected
460 if (netdata_cloud_setting)
461 - aclk_host_state_update(rpt->host, ACLK_CMD_CHILD_CONNECT);
461 + aclk_host_state_update(rpt->host, 1);
462 #endif
463
464 size_t count = streaming_parser(rpt, &cd, fp);
@@ -468,11 +468,11 @@ static int rrdpush_receive(struct receiver_state *rpt)
468 error("STREAM %s [receive from [%s]:%s]: disconnected (completed %zu updates).", rpt->hostname, rpt->client_ip,
469 rpt->client_port, count);
470
471 -#if defined(ENABLE_ACLK) && !defined(ACLK_NG)
471 +#if defined(ENABLE_ACLK)
472 // in case we have cloud connection we inform cloud
473 // new slave connected
474 if (netdata_cloud_setting)
475 - aclk_host_state_update(rpt->host, ACLK_CMD_CHILD_DISCONNECT);
475 + aclk_host_state_update(rpt->host, 0);
476 #endif
477
478 // During a shutdown there is cleanup code in rrdhost that will cancel the sender thread