Add agent CLI command to remove a stale node (#17691)
* Mark the node as ephemeral in the database Remove node command * Do not unregister the localhost Do not unregister a live node Make sure we rewrite the ephemeral value when a child reconnects
Stelios Fragkakis committed
May 20, 2024 at 12:13 UTC
9726ca103cca75236fb090eff97843403b3ed430
5 files changed
+94
-4
src/collectors/plugins.d/pluginsd_parser.c
+5
-3
@@ -649,10 +649,12 @@ static inline PARSER_RC pluginsd_label(char **words, size_t num_words, PARSER *p
649
650
if (strcmp(name,HOST_LABEL_IS_EPHEMERAL) == 0) {
651
int is_ephemeral = appconfig_test_boolean_value((char *) value);
652
- if (is_ephemeral) {
653
- RRDHOST *host = pluginsd_require_scope_host(parser, PLUGINSD_KEYWORD_LABEL);
654
- if (likely(host))
652
+ RRDHOST *host = pluginsd_require_scope_host(parser, PLUGINSD_KEYWORD_LABEL);
653
+ if (host) {
654
+ if (is_ephemeral)
655
rrdhost_option_set(host, RRDHOST_OPTION_EPHEMERAL_HOST);
656
+ else
657
+ rrdhost_option_clear(host, RRDHOST_OPTION_EPHEMERAL_HOST);
658
}
659
}
660
src/daemon/commands.c
+53
-1
@@ -47,6 +47,7 @@ static cmd_status_t cmd_ping_execute(char *args, char **message);
47
static cmd_status_t cmd_aclk_state(char *args, char **message);
48
static cmd_status_t cmd_version(char *args, char **message);
49
static cmd_status_t cmd_dumpconfig(char *args, char **message);
50
+static cmd_status_t cmd_remove_node(char *args, char **message);
51
52
static command_info_t command_info_array[] = {
53
{"help", cmd_help_execute, CMD_TYPE_HIGH_PRIORITY}, // show help menu
@@ -61,7 +62,8 @@ static command_info_t command_info_array[] = {
62
{"ping", cmd_ping_execute, CMD_TYPE_ORTHOGONAL},
63
{"aclk-state", cmd_aclk_state, CMD_TYPE_ORTHOGONAL},
64
{"version", cmd_version, CMD_TYPE_ORTHOGONAL},
64
- {"dumpconfig", cmd_dumpconfig, CMD_TYPE_ORTHOGONAL}
65
+ {"dumpconfig", cmd_dumpconfig, CMD_TYPE_ORTHOGONAL},
66
+ {"remove-stale-node", cmd_remove_node, CMD_TYPE_ORTHOGONAL}
67
};
68
69
/* Mutexes for commands of type CMD_TYPE_ORTHOGONAL */
@@ -129,6 +131,8 @@ static cmd_status_t cmd_help_execute(char *args, char **message)
131
" Returns current state of ACLK and Cloud connection. (optionally in json).\n"
132
"dumpconfig\n"
133
" Returns the current netdata.conf on stdout.\n"
134
+ "remove-stale-node node_id|machine_guid\n"
135
+ " Unregisters and removes a node from the cloud.\n"
136
"version\n"
137
" Returns the netdata version.\n",
138
MAX_COMMAND_LENGTH - 1);
@@ -326,6 +330,54 @@ static cmd_status_t cmd_dumpconfig(char *args, char **message)
330
return CMD_STATUS_SUCCESS;
331
}
332
333
+static cmd_status_t cmd_remove_node(char *args, char **message)
334
+{
335
+ (void)args;
336
+
337
+ BUFFER *wb = buffer_create(1024, NULL);
338
+ if (strlen(args) == 0) {
339
+ buffer_sprintf(wb, "Please specify a machine or node UUID");
340
+ goto done;
341
+ }
342
+
343
+ RRDHOST *host = NULL;
344
+ host = rrdhost_find_by_guid(args);
345
+ if (!host)
346
+ host = find_host_by_node_id(args);
347
+
348
+ if (!host)
349
+ buffer_sprintf(wb, "Node with machine or node UUID \"%s\" not found", args);
350
+ else {
351
+
352
+ if (host == localhost) {
353
+ buffer_sprintf(wb, "You cannot unregister the parent node");
354
+ goto done;
355
+ }
356
+
357
+ if (rrdhost_is_online(host)) {
358
+ buffer_sprintf(wb, "Cannot unregister a live node");
359
+ goto done;
360
+ }
361
+
362
+ if (!rrdhost_option_check(host, RRDHOST_OPTION_EPHEMERAL_HOST)) {
363
+ rrdhost_option_set(host, RRDHOST_OPTION_EPHEMERAL_HOST);
364
+ sql_set_host_label(&host->host_uuid, "_is_ephemeral", "true");
365
+ aclk_host_state_update(host, 0, 0);
366
+ unregister_node(host->machine_guid);
367
+ freez(host->node_id);
368
+ host->node_id = NULL;
369
+ buffer_sprintf(wb, "Unregistering node with machine guid %s, hostname = %s", host->machine_guid, rrdhost_hostname(host));
370
+ }
371
+ else
372
+ buffer_sprintf(wb, "Node with machine guid %s, hostname = %s is already unregistered", host->machine_guid, rrdhost_hostname(host));
373
+ }
374
+
375
+done:
376
+ *message = strdupz(buffer_tostring(wb));
377
+ buffer_free(wb);
378
+ return CMD_STATUS_SUCCESS;
379
+}
380
+
381
static void cmd_lock_exclusive(unsigned index)
382
{
383
(void)index;
src/daemon/commands.h
+1
@@ -20,6 +20,7 @@ typedef enum cmd {
20
CMD_ACLK_STATE,
21
CMD_VERSION,
22
CMD_DUMPCONFIG,
23
+ CMD_REMOVE_NODE,
24
CMD_TOTAL_COMMANDS
25
} cmd_t;
26
src/database/sqlite/sqlite_metadata.c
+34
@@ -256,6 +256,40 @@ static inline void set_host_node_id(RRDHOST *host, nd_uuid_t *node_id)
256
uuid_unparse_lower(*node_id, wc->node_id);
257
}
258
259
+#define SQL_SET_HOST_LABEL \
260
+ "INSERT INTO host_label (host_id, source_type, label_key, label_value, date_created) " \
261
+ "VALUES (@host_id, @source_type, @label_key, @label_value, UNIXEPOCH()) ON CONFLICT (host_id, label_key) " \
262
+ " DO UPDATE SET source_type = excluded.source_type, label_value=excluded.label_value, date_created=UNIXEPOCH()"
263
+
264
+bool sql_set_host_label(nd_uuid_t *host_id, const char *label_key, const char *label_value)
265
+{
266
+ sqlite3_stmt *res = NULL;
267
+ bool status = false;
268
+
269
+ if (!label_key || !label_value || !host_id)
270
+ return false;
271
+
272
+ if (!PREPARE_STATEMENT(db_meta, SQL_SET_HOST_LABEL, &res))
273
+ return 1;
274
+
275
+ int param = 0;
276
+ SQLITE_BIND_FAIL(done, sqlite3_bind_blob(res, ++param, host_id, sizeof(*host_id), SQLITE_STATIC));
277
+ SQLITE_BIND_FAIL(done, sqlite3_bind_int(res, ++param, RRDLABEL_SRC_AUTO));
278
+ SQLITE_BIND_FAIL(done, sqlite3_bind_text(res, ++param, label_key, -1, SQLITE_STATIC));
279
+ SQLITE_BIND_FAIL(done, sqlite3_bind_text(res, ++param, label_value, -1, SQLITE_STATIC));
280
+
281
+ param = 0;
282
+ int rc = execute_insert(res);
283
+ status = (rc == SQLITE_DONE);
284
+ if (false == status)
285
+ error_report("Failed to store node instance information, rc = %d", rc);
286
+done:
287
+ REPORT_BIND_FAIL(res, param);
288
+ SQLITE_FINALIZE(res);
289
+ return status;
290
+}
291
+
292
+
293
#define SQL_UPDATE_NODE_ID "UPDATE node_instance SET node_id = @node_id WHERE host_id = @host_id"
294
295
int update_node_id(nd_uuid_t *host_id, nd_uuid_t *node_id)
src/database/sqlite/sqlite_metadata.h
+1
@@ -49,6 +49,7 @@ void sql_load_node_id(RRDHOST *host);
49
void sql_build_host_system_info(nd_uuid_t *host_id, struct rrdhost_system_info *system_info);
50
void invalidate_node_instances(nd_uuid_t *host_id, nd_uuid_t *claim_id);
51
RRDLABELS *sql_load_host_labels(nd_uuid_t *host_id);
52
+bool sql_set_host_label(nd_uuid_t *host_id, const char *label_key, const char *label_value);
53
54
uint64_t sqlite_get_meta_space(void);
55
int sql_init_meta_database(db_check_action_type_t rebuild, int memory);