@cryptotaxi247 / netdata-1 / commits / 82f668106

daemon status 25 (#20026)

added DMI HW information (anonymous - no serial numbers)

Costa Tsaousis committed Apr 1, 2025 at 21:42 UTC 82f668106e6b11af6759d66271300b8fb036e614
2 files changed +255 -1
src/daemon/status-file.c
+222
@@ -84,6 +84,144 @@ static void set_stack_trace_message_if_empty(DAEMON_STATUS_FILE *ds, const char
84 strncpyz(ds->fatal.stack_trace, msg, sizeof(ds->fatal.stack_trace) - 1);
85 }
86
87 +// --------------------------------------------------------------------------------------------------------------------
88 +// DMI data
89 +
90 +static void dmi_info(const char *file, const char *alt, char *dst, size_t dst_size) {
91 + char filename[FILENAME_MAX];
92 +
93 + if(netdata_configured_host_prefix && *netdata_configured_host_prefix) {
94 + snprintfz(filename, sizeof(filename), "%s/sys/class/dmi/id/%s", netdata_configured_host_prefix, file);
95 + if(access(filename, R_OK) != 0) {
96 + snprintfz(filename, sizeof(filename), "%s/sys/devices/virtual/dmi/id/%s", netdata_configured_host_prefix, file);
97 + if (access(filename, R_OK) != 0)
98 + filename[0] = '\0';
99 + }
100 + }
101 + else
102 + filename[0] = '\0';
103 +
104 + if(!filename[0]) {
105 + snprintfz(filename, sizeof(filename), "/sys/class/dmi/id/%s", file);
106 + if (access(filename, R_OK) != 0) {
107 + snprintfz(filename, sizeof(filename), "/sys/devices/virtual/dmi/id/%s", file);
108 + if (access(filename, R_OK) != 0) {
109 + if (alt && *alt) {
110 + strncpyz(filename, alt, sizeof(filename) - 1);
111 + if (access(filename, R_OK) != 0)
112 + filename[0] = '\0';
113 + }
114 + else
115 + filename[0] = '\0';
116 + }
117 + }
118 + }
119 +
120 + if(!filename[0]) {
121 + dst[0] = '\0';
122 + return;
123 + }
124 +
125 + if(read_txt_file(filename, dst, dst_size) != 0) {
126 + dst[0] = '\0';
127 + return;
128 + }
129 +
130 + char *s = trim_all(dst);
131 + if(s != dst)
132 + memmove(dst, s, strlen(s) + 1);
133 +
134 + struct {
135 + const char *found;
136 + const char *replace;
137 + } replacements[] = {
138 + {"Default string", ""},
139 + {"To be filled by O.E.M.", ""},
140 + {"x.x", ""},
141 + {"System Product Name", ""},
142 + {"System Version", ""},
143 + {"System UUID", ""},
144 + };
145 +
146 + for(size_t i = 0; i < _countof(replacements) ;i++) {
147 + if(strcasecmp(dst, replacements[i].found) == 0) {
148 + strncpyz(dst, replacements[i].replace, dst_size - 1);
149 + break;
150 + }
151 + }
152 +}
153 +
154 +static void fill_dmi_info(DAEMON_STATUS_FILE *ds) {
155 + dmi_info("sys_vendor", NULL, ds->hw.sys.vendor, sizeof(ds->hw.sys.vendor));
156 +
157 + dmi_info("product_name", "/proc/device-tree/model", ds->hw.product.name, sizeof(ds->hw.product.name));
158 + dmi_info("product_version", NULL, ds->hw.product.version, sizeof(ds->hw.product.version));
159 + dmi_info("product_sku", NULL, ds->hw.product.sku, sizeof(ds->hw.product.sku));
160 + dmi_info("product_family", NULL, ds->hw.product.family, sizeof(ds->hw.product.family));
161 +
162 + dmi_info("chassis_type", NULL, ds->hw.chassis.type, sizeof(ds->hw.chassis.type));
163 + dmi_info("chassis_vendor", NULL, ds->hw.chassis.vendor, sizeof(ds->hw.chassis.vendor));
164 + dmi_info("chassis_version", NULL, ds->hw.chassis.version, sizeof(ds->hw.chassis.version));
165 +
166 + dmi_info("board_vendor", NULL, ds->hw.board.vendor, sizeof(ds->hw.board.vendor));
167 + dmi_info("board_name", NULL, ds->hw.board.name, sizeof(ds->hw.board.name));
168 + dmi_info("board_version", NULL, ds->hw.board.version, sizeof(ds->hw.board.version));
169 +
170 + dmi_info("bios_vendor", NULL, ds->hw.bios.vendor, sizeof(ds->hw.bios.vendor));
171 + dmi_info("bios_version", NULL, ds->hw.bios.version, sizeof(ds->hw.bios.version));
172 + dmi_info("bios_date", NULL, ds->hw.bios.date, sizeof(ds->hw.bios.date));
173 + dmi_info("bios_release", NULL, ds->hw.bios.release, sizeof(ds->hw.bios.release));
174 +
175 + struct {
176 + const char *found;
177 + const char *replace;
178 + } chassis_types[] = {
179 + {"1", "other"},
180 + {"2", "unknown"},
181 + {"3", "desktop"},
182 + {"4", "low-profile-desktop"},
183 + {"5", "pizza-box"},
184 + {"6", "mini-tower-desktop"},
185 + {"7", "tower-desktop"},
186 + {"8", "portable"},
187 + {"9", "laptop"},
188 + {"10", "notebook"},
189 + {"11", "hand-held"},
190 + {"12", "docking-station"},
191 + {"13", "all-in-one"},
192 + {"14", "sub-notebook"},
193 + {"15", "space-saving-desktop"},
194 + {"16", "lunch-box"},
195 + {"17", "main-server-chassis"},
196 + {"18", "expansion-chassis"},
197 + {"19", "sub-chassis"},
198 + {"20", "bus-expansion-chassis"},
199 + {"21", "peripheral-chassis"},
200 + {"22", "raid-chassis"},
201 + {"23", "rack-mount-server"},
202 + {"24", "sealed-desktop"},
203 + {"25", "multi-chassis"},
204 + {"26", "compact-pci"},
205 + {"27", "advanced-tca"},
206 + {"28", "blade"},
207 + {"29", "blade-enclosure"},
208 + {"30", "tablet"},
209 + {"31", "convertible"},
210 + {"32", "detachable"},
211 + {"33", "iot-gateway"},
212 + {"34", "embedded-pc"},
213 + {"35", "mini-pc"},
214 + {"36", "stick-pc"},
215 + };
216 +
217 + for(size_t i = 0; i < _countof(chassis_types) ;i++) {
218 + if(strcasecmp(ds->hw.chassis.type, chassis_types[i].found) == 0) {
219 + strncpyz(ds->hw.chassis.type, chassis_types[i].replace, sizeof(ds->hw.chassis.type) - 1);
220 + break;
221 + }
222 + }
223 +}
224 +
225 // --------------------------------------------------------------------------------------------------------------------
226 // json generation
227
@@ -209,6 +347,50 @@ static void daemon_status_file_to_json(BUFFER *wb, DAEMON_STATUS_FILE *ds) {
347 }
348 buffer_json_object_close(wb);
349
350 + buffer_json_member_add_object(wb, "hw");
351 + {
352 + buffer_json_member_add_object(wb, "sys");
353 + {
354 + buffer_json_member_add_string(wb, "vendor", ds->hw.sys.vendor);
355 + }
356 + buffer_json_object_close(wb);
357 +
358 + buffer_json_member_add_object(wb, "product");
359 + {
360 + buffer_json_member_add_string(wb, "name", ds->hw.product.name);
361 + buffer_json_member_add_string(wb, "version", ds->hw.product.version);
362 + buffer_json_member_add_string(wb, "sku", ds->hw.product.sku);
363 + buffer_json_member_add_string(wb, "family", ds->hw.product.family);
364 + }
365 + buffer_json_object_close(wb);
366 +
367 + buffer_json_member_add_object(wb, "board");
368 + {
369 + buffer_json_member_add_string(wb, "name", ds->hw.board.name);
370 + buffer_json_member_add_string(wb, "version", ds->hw.board.version);
371 + buffer_json_member_add_string(wb, "vendor", ds->hw.board.vendor);
372 + }
373 + buffer_json_object_close(wb);
374 +
375 + buffer_json_member_add_object(wb, "chassis");
376 + {
377 + buffer_json_member_add_string(wb, "type", ds->hw.chassis.type);
378 + buffer_json_member_add_string(wb, "vendor", ds->hw.chassis.vendor);
379 + buffer_json_member_add_string(wb, "version", ds->hw.chassis.version);
380 + }
381 + buffer_json_object_close(wb);
382 +
383 + buffer_json_member_add_object(wb, "bios");
384 + {
385 + buffer_json_member_add_string(wb, "date", ds->hw.bios.date);
386 + buffer_json_member_add_string(wb, "release", ds->hw.bios.release);
387 + buffer_json_member_add_string(wb, "version", ds->hw.bios.version);
388 + buffer_json_member_add_string(wb, "vendor", ds->hw.bios.vendor);
389 + }
390 + buffer_json_object_close(wb);
391 + }
392 + buffer_json_object_close(wb);
393 +
394 buffer_json_member_add_object(wb, "fatal");
395 {
396 buffer_json_member_add_uint64(wb, "line", ds->fatal.line);
@@ -276,6 +458,7 @@ static bool daemon_status_file_from_json(json_object *jobj, void *data, BUFFER *
458 bool required_v22 = version >= 22 ? strict : false;
459 bool required_v23 = version >= 23 ? strict : false;
460 bool required_v24 = version >= 24 ? strict : false;
461 + bool required_v25 = version >= 25 ? strict : false;
462
463 // Parse timestamp
464 JSONC_PARSE_TXT2RFC3339_USEC_OR_ERROR_AND_RETURN(jobj, path, "@timestamp", ds->timestamp_ut, error, required_v1);
@@ -402,6 +585,39 @@ static bool daemon_status_file_from_json(json_object *jobj, void *data, BUFFER *
585 JSONC_PARSE_TXT2CHAR_OR_ERROR_AND_RETURN(jobj, path, "platform", ds->os_id_like, error, required_v1);
586 });
587
588 + // Parse the hw object
589 + JSONC_PARSE_SUBOBJECT(jobj, path, "hw", error, required_v25, {
590 + JSONC_PARSE_SUBOBJECT(jobj, path, "sys", error, required_v25, {
591 + JSONC_PARSE_TXT2CHAR_OR_ERROR_AND_RETURN(jobj, path, "vendor", ds->hw.sys.vendor, error, required_v25);
592 + });
593 +
594 + JSONC_PARSE_SUBOBJECT(jobj, path, "product", error, required_v25, {
595 + JSONC_PARSE_TXT2CHAR_OR_ERROR_AND_RETURN(jobj, path, "name", ds->hw.product.name, error, required_v25);
596 + JSONC_PARSE_TXT2CHAR_OR_ERROR_AND_RETURN(jobj, path, "version", ds->hw.product.version, error, required_v25);
597 + JSONC_PARSE_TXT2CHAR_OR_ERROR_AND_RETURN(jobj, path, "sku", ds->hw.product.sku, error, required_v25);
598 + JSONC_PARSE_TXT2CHAR_OR_ERROR_AND_RETURN(jobj, path, "family", ds->hw.product.family, error, required_v25);
599 + });
600 +
601 + JSONC_PARSE_SUBOBJECT(jobj, path, "board", error, required_v25, {
602 + JSONC_PARSE_TXT2CHAR_OR_ERROR_AND_RETURN(jobj, path, "name", ds->hw.board.name, error, required_v25);
603 + JSONC_PARSE_TXT2CHAR_OR_ERROR_AND_RETURN(jobj, path, "version", ds->hw.board.version, error, required_v25);
604 + JSONC_PARSE_TXT2CHAR_OR_ERROR_AND_RETURN(jobj, path, "vendor", ds->hw.board.vendor, error, required_v25);
605 + });
606 +
607 + JSONC_PARSE_SUBOBJECT(jobj, path, "chassis", error, required_v25, {
608 + JSONC_PARSE_TXT2CHAR_OR_ERROR_AND_RETURN(jobj, path,"type", ds->hw.chassis.type ,error ,required_v25);
609 + JSONC_PARSE_TXT2CHAR_OR_ERROR_AND_RETURN(jobj,path,"vendor" ,ds->hw.chassis.vendor ,error ,required_v25);
610 + JSONC_PARSE_TXT2CHAR_OR_ERROR_AND_RETURN(jobj,path,"version" ,ds->hw.chassis.version ,error ,required_v25);
611 + });
612 +
613 + JSONC_PARSE_SUBOBJECT(jobj,path,"bios" ,error ,required_v25,{
614 + JSONC_PARSE_TXT2CHAR_OR_ERROR_AND_RETURN(jobj, path, "date", ds->hw.bios.date, error, required_v25);
615 + JSONC_PARSE_TXT2CHAR_OR_ERROR_AND_RETURN(jobj, path, "release", ds->hw.bios.release, error, required_v25);
616 + JSONC_PARSE_TXT2CHAR_OR_ERROR_AND_RETURN(jobj, path, "version", ds->hw.bios.version, error, required_v25);
617 + JSONC_PARSE_TXT2CHAR_OR_ERROR_AND_RETURN(jobj, path, "vendor", ds->hw.bios.vendor, error, required_v25);
618 + });
619 + });
620 +
621 // Parse fatal object
622 JSONC_PARSE_SUBOBJECT(jobj, path, "fatal", error, required_v1, {
623 JSONC_PARSE_TXT2CHAR_OR_ERROR_AND_RETURN(jobj, path, "filename", ds->fatal.filename, error, required_v1);
@@ -507,6 +723,8 @@ static void daemon_status_file_migrate_once(void) {
723
724 strncpyz(session_status.stack_traces, capture_stack_trace_backend(), sizeof(session_status.stack_traces) - 1);
725
726 + fill_dmi_info(&session_status);
727 +
728 dsf_release(last_session_status);
729 dsf_release(session_status);
730 }
@@ -801,7 +1019,11 @@ static enum crash_report_t check_crash_reports_config(void) {
1019 void daemon_status_file_init(void) {
1020 static_save_buffer_init();
1021 mallocz_register_out_of_memory_cb(daemon_status_file_out_of_memory);
1022 +
1023 status_file_io_load(STATUS_FILENAME, status_file_load_and_parse, &last_session_status);
1024 + if(last_session_status.v < 25)
1025 + fill_dmi_info(&last_session_status);
1026 +
1027 daemon_status_file_migrate_once();
1028 }
1029
src/daemon/status-file.h
+33 -1
@@ -9,7 +9,7 @@
9 #include "claim/cloud-status.h"
10 #include "machine-guid.h"
11
12 -#define STATUS_FILE_VERSION 24
12 +#define STATUS_FILE_VERSION 25
13
14 typedef enum {
15 DAEMON_STATUS_NONE,
@@ -87,6 +87,38 @@ typedef struct daemon_status_file {
87 char cloud_instance_region[32];
88 bool read_system_info;
89
90 + struct {
91 + struct {
92 + char vendor[64];
93 + } sys;
94 +
95 + struct {
96 + char name[64];
97 + char version[64];
98 + char sku[64];
99 + char family[64];
100 + } product;
101 +
102 + struct {
103 + char name[64];
104 + char version[64];
105 + char vendor[64];
106 + } board;
107 +
108 + struct {
109 + char type[64];
110 + char vendor[64];
111 + char version[64];
112 + } chassis;
113 +
114 + struct {
115 + char date[16];
116 + char release[64];
117 + char version[64];
118 + char vendor[64];
119 + } bios;
120 + } hw;
121 +
122 char stack_traces[63]; // the backend for capturing stack traces
123
124 struct {