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