master
c 164 lines 6.5 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 #include "commands.h"
4 #include "../stream-receiver-internals.h"
5 #include "../stream-sender-internals.h"
6 #include "plugins.d/pluginsd_internals.h"
7
8 // the child disconnected from the parent, and it has to clear the parent's claim id
9 void stream_sender_clear_parent_claim_id(RRDHOST *host) {
10 if (!UUIDiszero(host->aclk.claim_id_of_parent)) {
11 nd_log(NDLS_DAEMON, NDLP_INFO,
12 "Host '%s' [PCLAIMID] cleared parent's claim id",
13 rrdhost_hostname(host));
14
15 host->aclk.claim_id_of_parent = UUID_ZERO;
16 }
17 }
18
19 // the parent sends to the child its claim id, node id and cloud url
20 void stream_receiver_send_node_and_claim_id_to_child(RRDHOST *host) {
21 if(rrdhost_is_local(host) || UUIDiszero(host->node_id)) return;
22
23 rrdhost_receiver_lock(host);
24 if(stream_has_capability(host->receiver, STREAM_CAP_NODE_ID)) {
25 char node_id_str[UUID_STR_LEN] = "";
26 uuid_unparse_lower(host->node_id.uuid, node_id_str);
27
28 CLAIM_ID claim_id = claim_id_get();
29
30 if((!claim_id_is_set(claim_id) || !aclk_online())) {
31 // the agent is not claimed or not connected, just use parent claim id
32 // to allow the connection flow.
33 // this may be zero and it is ok.
34 claim_id.uuid = host->aclk.claim_id_of_parent;
35 uuid_unparse_lower(claim_id.uuid.uuid, claim_id.str);
36 }
37
38 char buf[4096];
39 snprintfz(buf, sizeof(buf),
40 PLUGINSD_KEYWORD_NODE_ID " '%s' '%s' '%s'\n",
41 claim_id.str, node_id_str, cloud_config_url_get());
42
43 send_to_plugin(buf, __atomic_load_n(&host->receiver->thread.parser, __ATOMIC_RELAXED), STREAM_TRAFFIC_TYPE_METADATA);
44 }
45 rrdhost_receiver_unlock(host);
46 }
47
48 // the sender of the child receives node id, claim id and cloud url from the receiver of the parent
49 void stream_sender_get_node_and_claim_id_from_parent(struct sender_state *s, const char *claim_id_str, const char *node_id_str, const char *url) {
50
51 bool claimed = is_agent_claimed();
52 bool update_node_id = false;
53
54 // ----------------------------------------------------------------------------------------------------------------
55 // validate the parameters
56
57 ND_UUID claim_id;
58 if (uuid_parse(claim_id_str ? claim_id_str : "", claim_id.uuid) != 0) {
59 nd_log(NDLS_DAEMON, NDLP_ERR,
60 "STREAM SND '%s' [to %s] [PCLAIMID]: received invalid claim id '%s'",
61 rrdhost_hostname(s->host), s->remote_ip,
62 claim_id_str ? claim_id_str : "(unset)");
63 return;
64 }
65
66 if(UUIDiszero(claim_id)) {
67 nd_log(NDLS_DAEMON, NDLP_DEBUG,
68 "STREAM SND '%s' [to %s] [PCLAIMID]: received zero claim id '%s'",
69 rrdhost_hostname(s->host), s->remote_ip,
70 claim_id_str ? claim_id_str : "(unset)");
71 return;
72 }
73
74 ND_UUID node_id;
75 if(uuid_parse(node_id_str ? node_id_str : "", node_id.uuid) != 0) {
76 nd_log(NDLS_DAEMON, NDLP_ERR,
77 "STREAM SND '%s' [to %s] [PCLAIMID] received an invalid node id '%s'",
78 rrdhost_hostname(s->host), s->remote_ip,
79 node_id_str ? node_id_str : "(unset)");
80 return;
81 }
82
83 if(UUIDiszero(node_id)) {
84 nd_log(NDLS_DAEMON, NDLP_DEBUG,
85 "STREAM SND '%s' [to %s] [PCLAIMID]: received zero node id '%s'",
86 rrdhost_hostname(s->host), s->remote_ip,
87 node_id_str ? node_id_str : "(unset)");
88 return;
89 }
90
91 if(!url || !*url) {
92 nd_log(NDLS_DAEMON, NDLP_ERR,
93 "STREAM SND '%s' [to %s] [PCLAIMID] received an invalid cloud URL '%s'",
94 rrdhost_hostname(s->host), s->remote_ip,
95 url ? url : "(unset)");
96 return;
97 }
98
99 // ----------------------------------------------------------------------------------------------------------------
100 // the parameters are ok
101 // apply the changes
102
103 if (!UUIDeq(s->host->aclk.claim_id_of_parent, claim_id)) {
104 if(UUIDiszero(s->host->aclk.claim_id_of_parent))
105 nd_log(NDLS_DAEMON, NDLP_INFO,
106 "STREAM SND '%s' [to %s] [PCLAIMID] set parent's claim id to %s (was empty)",
107 rrdhost_hostname(s->host), s->remote_ip,
108 claim_id_str ? claim_id_str : "(unset)");
109 else
110 nd_log(NDLS_DAEMON, NDLP_INFO,
111 "STREAM SND '%s' [to %s] [PCLAIMID] changed parent's claim id to %s (was set)",
112 rrdhost_hostname(s->host), s->remote_ip,
113 claim_id_str ? claim_id_str : "(unset)");
114
115 s->host->aclk.claim_id_of_parent = claim_id;
116 }
117
118 if(!UUIDiszero(s->host->node_id) && !UUIDeq(s->host->node_id, node_id)) {
119 if(claimed) {
120 update_node_id = false;
121 nd_log(NDLS_DAEMON, NDLP_WARNING,
122 "STREAM SND '%s' [to %s] [PCLAIMID] parent reports different node id '%s', but we are claimed. Ignoring it.",
123 rrdhost_hostname(s->host), s->remote_ip,
124 node_id_str ? node_id_str : "(unset)");
125 }
126 else {
127 update_node_id = true;
128 nd_log(NDLS_DAEMON, NDLP_WARNING,
129 "STREAM SND '%s' [to %s] [PCLAIMID] changed node id to %s",
130 rrdhost_hostname(s->host), s->remote_ip,
131 node_id_str ? node_id_str : "(unset)");
132 }
133 }
134
135 // There are some very strange corner cases here:
136 //
137 // - Agent is claimed but offline, and it receives node_id and cloud_url from a different Netdata Cloud.
138 // - Agent is configured to talk to an on-prem Netdata Cloud, it is offline, but the parent is connected
139 // to a different Netdata Cloud.
140 //
141 // The solution below, tries to get the agent online, using the latest information.
142 // So, if the agent is not claimed or not connected, we inherit whatever information sent from the parent,
143 // to allow the user to work with it.
144
145 if(claimed && aclk_online())
146 // we are directly claimed and connected, ignore node id and cloud url
147 return;
148
149 bool node_id_updated = false;
150 if(UUIDiszero(s->host->node_id) || update_node_id) {
151 s->host->node_id = node_id;
152 node_id_updated = true;
153 }
154
155 // we change the URL, to allow the agent dashboard to work with Netdata Cloud on-prem, if any.
156 if(node_id_updated)
157 cloud_config_url_set(url);
158
159 // send it down the line (to children)
160 stream_receiver_send_node_and_claim_id_to_child(s->host);
161
162 if(node_id_updated)
163 stream_path_node_id_updated(s->host);
164 }