summaryrefslogtreecommitdiffstats
path: root/src/collectors/cgroups.plugin
diff options
context:
space:
mode:
Diffstat (limited to 'src/collectors/cgroups.plugin')
-rw-r--r--src/collectors/cgroups.plugin/README.md9
-rw-r--r--src/collectors/cgroups.plugin/cgroup-discovery.c6
-rw-r--r--src/collectors/cgroups.plugin/cgroup-internals.h8
-rwxr-xr-xsrc/collectors/cgroups.plugin/cgroup-name.sh.in4
-rw-r--r--src/collectors/cgroups.plugin/cgroup-network.c257
-rw-r--r--src/collectors/cgroups.plugin/cgroup-top.c4
-rw-r--r--src/collectors/cgroups.plugin/sys_fs_cgroup.c37
7 files changed, 199 insertions, 126 deletions
diff --git a/src/collectors/cgroups.plugin/README.md b/src/collectors/cgroups.plugin/README.md
index efa868bfb..dc58973af 100644
--- a/src/collectors/cgroups.plugin/README.md
+++ b/src/collectors/cgroups.plugin/README.md
@@ -1,12 +1,3 @@
-<!--
-title: "Monitor Cgroups (cgroups.plugin)"
-custom_edit_url: "https://github.com/netdata/netdata/edit/master/src/collectors/cgroups.plugin/README.md"
-sidebar_label: "Monitor Cgroups"
-learn_status: "Published"
-learn_topic_type: "References"
-learn_rel_path: "Integrations/Monitor/Virtualized environments/Containers"
--->
-
# Monitor Cgroups (cgroups.plugin)
You can monitor containers and virtual machines using **cgroups**.
diff --git a/src/collectors/cgroups.plugin/cgroup-discovery.c b/src/collectors/cgroups.plugin/cgroup-discovery.c
index d880f8a71..5d3027a47 100644
--- a/src/collectors/cgroups.plugin/cgroup-discovery.c
+++ b/src/collectors/cgroups.plugin/cgroup-discovery.c
@@ -23,7 +23,7 @@ struct cgroup *discovered_cgroup_root = NULL;
char cgroup_chart_id_prefix[] = "cgroup_";
char services_chart_id_prefix[] = "systemd_";
-char *cgroups_rename_script = NULL;
+const char *cgroups_rename_script = NULL;
// Shared memory with information from detected cgroups
netdata_ebpf_cgroup_shm_t shm_cgroup_ebpf = {NULL, NULL};
@@ -188,7 +188,7 @@ static inline void discovery_rename_cgroup(struct cgroup *cg) {
}
char buffer[CGROUP_CHARTID_LINE_MAX + 1];
- char *new_name = fgets(buffer, CGROUP_CHARTID_LINE_MAX, instance->child_stdout_fp);
+ char *new_name = fgets(buffer, CGROUP_CHARTID_LINE_MAX, spawn_popen_stdout(instance));
int exit_code = spawn_popen_wait(instance);
switch (exit_code) {
@@ -1101,7 +1101,7 @@ static inline void read_cgroup_network_interfaces(struct cgroup *cg) {
char *s;
char buffer[CGROUP_NETWORK_INTERFACE_MAX_LINE + 1];
- while((s = fgets(buffer, CGROUP_NETWORK_INTERFACE_MAX_LINE, instance->child_stdout_fp))) {
+ while((s = fgets(buffer, CGROUP_NETWORK_INTERFACE_MAX_LINE, spawn_popen_stdout(instance)))) {
trim(s);
if(*s && *s != '\n') {
diff --git a/src/collectors/cgroups.plugin/cgroup-internals.h b/src/collectors/cgroups.plugin/cgroup-internals.h
index e0d53dc93..cdb5837bd 100644
--- a/src/collectors/cgroups.plugin/cgroup-internals.h
+++ b/src/collectors/cgroups.plugin/cgroup-internals.h
@@ -273,7 +273,7 @@ struct discovery_thread {
extern struct discovery_thread discovery_thread;
-extern char *cgroups_rename_script;
+extern const char *cgroups_rename_script;
extern char cgroup_chart_id_prefix[];
extern char services_chart_id_prefix[];
extern uv_mutex_t cgroup_root_mutex;
@@ -313,7 +313,7 @@ extern SIMPLE_PATTERN *enabled_cgroup_renames;
extern SIMPLE_PATTERN *systemd_services_cgroups;
extern SIMPLE_PATTERN *entrypoint_parent_process_comm;
-extern char *cgroups_network_interface_script;
+extern const char *cgroups_network_interface_script;
extern int cgroups_check;
@@ -394,8 +394,8 @@ static inline char *cgroup_chart_type(char *buffer, struct cgroup *cg) {
#define RRDFUNCTIONS_CGTOP_HELP "View running containers"
#define RRDFUNCTIONS_SYSTEMD_SERVICES_HELP "View systemd services"
-int cgroup_function_cgroup_top(BUFFER *wb, const char *function);
-int cgroup_function_systemd_top(BUFFER *wb, const char *function);
+int cgroup_function_cgroup_top(BUFFER *wb, const char *function, BUFFER *payload, const char *source);
+int cgroup_function_systemd_top(BUFFER *wb, const char *function, BUFFER *payload, const char *source);
void cgroup_netdev_link_init(void);
const DICTIONARY_ITEM *cgroup_netdev_get(struct cgroup *cg);
diff --git a/src/collectors/cgroups.plugin/cgroup-name.sh.in b/src/collectors/cgroups.plugin/cgroup-name.sh.in
index 0f8b63256..18755b622 100755
--- a/src/collectors/cgroups.plugin/cgroup-name.sh.in
+++ b/src/collectors/cgroups.plugin/cgroup-name.sh.in
@@ -155,7 +155,7 @@ function docker_like_get_name_api() {
info "Running API command: curl \"${host}${path}\""
JSON=$(curl -sS "${host}${path}")
fi
- if OUTPUT=$(echo "${JSON}" | jq -r '.Config.Env[],"CONT_NAME=\(.Name)","IMAGE_NAME=\(.Config.Image)"') && [ -n "$OUTPUT" ]; then
+ if OUTPUT=$(echo "${JSON}" | jq -r '.Config.Env[]?,"CONT_NAME=\(.Name)","IMAGE_NAME=\(.Config.Image)"') && [ -n "$OUTPUT" ]; then
parse_docker_like_inspect_output "$OUTPUT"
fi
return 0
@@ -610,7 +610,7 @@ function podman_validate_id() {
DOCKER_HOST="${DOCKER_HOST:=/var/run/docker.sock}"
PODMAN_HOST="${PODMAN_HOST:=/run/podman/podman.sock}"
CGROUP_PATH="${1}" # the path as it is (e.g. '/docker/efcf4c409')
-CGROUP="${2}" # the modified path (e.g. 'docker_efcf4c409')
+CGROUP="${2//\//_}" # the modified path (e.g. 'docker_efcf4c409')
EXIT_SUCCESS=0
EXIT_RETRY=2
EXIT_DISABLE=3
diff --git a/src/collectors/cgroups.plugin/cgroup-network.c b/src/collectors/cgroups.plugin/cgroup-network.c
index 4cb5cbabe..d64b31288 100644
--- a/src/collectors/cgroups.plugin/cgroup-network.c
+++ b/src/collectors/cgroups.plugin/cgroup-network.c
@@ -3,6 +3,8 @@
#include "libnetdata/libnetdata.h"
#include "libnetdata/required_dummies.h"
+SPAWN_SERVER *spawn_server = NULL;
+
char env_netdata_host_prefix[FILENAME_MAX + 50] = "";
char env_netdata_log_method[FILENAME_MAX + 50] = "";
char env_netdata_log_format[FILENAME_MAX + 50] = "";
@@ -42,7 +44,7 @@ unsigned int read_iface_iflink(const char *prefix, const char *iface) {
unsigned long long iflink = 0;
int ret = read_single_number_file(filename, &iflink);
- if(ret) collector_error("Cannot read '%s'.", filename);
+ if(ret) nd_log(NDLS_COLLECTORS, NDLP_ERR, "Cannot read '%s'.", filename);
return (unsigned int)iflink;
}
@@ -55,7 +57,7 @@ unsigned int read_iface_ifindex(const char *prefix, const char *iface) {
unsigned long long ifindex = 0;
int ret = read_single_number_file(filename, &ifindex);
- if(ret) collector_error("Cannot read '%s'.", filename);
+ if(ret) nd_log(NDLS_COLLECTORS, NDLP_ERR, "Cannot read '%s'.", filename);
return (unsigned int)ifindex;
}
@@ -68,19 +70,15 @@ struct iface *read_proc_net_dev(const char *scope __maybe_unused, const char *pr
snprintfz(filename, FILENAME_MAX, "%s%s", prefix, (*prefix)?"/proc/1/net/dev":"/proc/net/dev");
-#ifdef NETDATA_INTERNAL_CHECKS
- collector_info("parsing '%s'", filename);
-#endif
-
ff = procfile_open(filename, " \t,:|", PROCFILE_FLAG_DEFAULT);
if(unlikely(!ff)) {
- collector_error("Cannot open file '%s'", filename);
+ nd_log(NDLS_COLLECTORS, NDLP_ERR, "Cannot open file '%s'", filename);
return NULL;
}
ff = procfile_readall(ff);
if(unlikely(!ff)) {
- collector_error("Cannot read file '%s'", filename);
+ nd_log(NDLS_COLLECTORS, NDLP_ERR, "Cannot read file '%s'", filename);
return NULL;
}
@@ -97,9 +95,7 @@ struct iface *read_proc_net_dev(const char *scope __maybe_unused, const char *pr
t->next = root;
root = t;
-#ifdef NETDATA_INTERNAL_CHECKS
- collector_info("added %s interface '%s', ifindex %u, iflink %u", scope, t->device, t->ifindex, t->iflink);
-#endif
+ nd_log(NDLS_COLLECTORS, NDLP_DEBUG, "added %s interface '%s', ifindex %u, iflink %u", scope, t->device, t->ifindex, t->iflink);
}
procfile_close(ff);
@@ -143,13 +139,18 @@ static void continue_as_child(void) {
int status;
pid_t ret;
- if (child < 0)
- collector_error("fork() failed");
+ if (child < 0) {
+ nd_log(NDLS_COLLECTORS, NDLP_ERR, "fork() failed");
+ exit(1);
+ }
- /* Only the child returns */
- if (child == 0)
+ if (child == 0) {
+ // the child returns
+ gettid_uncached();
return;
+ }
+ // here is the parent
for (;;) {
ret = waitpid(child, &status, WUNTRACED);
if ((ret == child) && (WIFSTOPPED(status))) {
@@ -159,9 +160,36 @@ static void continue_as_child(void) {
} else {
break;
}
+ tinysleep();
}
/* Return the child's exit code if possible */
+
+#ifdef __SANITIZE_ADDRESS__
+ /*
+ * With sanitization, exiting leads to an infinite loop (100% cpu) here:
+ *
+ * #0 0x00007ffff690ea8b in sched_yield () from /usr/lib/libc.so.6
+ * #1 0x00007ffff792c4a6 in __sanitizer::StopTheWorld (callback=<optimized out>, argument=<optimized out>) at /usr/src/debug/gcc/gcc/libsanitizer/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp:457
+ * #2 0x00007ffff793f6f9 in __lsan::LockStuffAndStopTheWorldCallback (info=<optimized out>, size=<optimized out>, data=0x7fffffffde20) at /usr/src/debug/gcc/gcc/libsanitizer/lsan/lsan_common_linux.cpp:127
+ * #3 0x00007ffff6977909 in dl_iterate_phdr () from /usr/lib/libc.so.6
+ * #4 0x00007ffff793fb24 in __lsan::LockStuffAndStopTheWorld (callback=callback@entry=0x7ffff793d9d0 <__lsan::CheckForLeaksCallback(__sanitizer::SuspendedThreadsList const&, void*)>, argument=argument@entry=0x7fffffffdea0)
+ * at /usr/src/debug/gcc/gcc/libsanitizer/lsan/lsan_common_linux.cpp:142
+ * #5 0x00007ffff793c965 in __lsan::CheckForLeaks () at /usr/src/debug/gcc/gcc/libsanitizer/lsan/lsan_common.cpp:778
+ * #6 0x00007ffff793cc68 in __lsan::DoLeakCheck () at /usr/src/debug/gcc/gcc/libsanitizer/lsan/lsan_common.cpp:821
+ * #7 0x00007ffff684e340 in __cxa_finalize () from /usr/lib/libc.so.6
+ * #8 0x00007ffff7838c58 in __do_global_dtors_aux () from /usr/lib/libasan.so.8
+ * #9 0x00007fffffffdfe0 in ?? ()
+ *
+ * Probably is something related to switching name spaces.
+ * So, we kill -9 self.
+ *
+ */
+
+ nd_log(NDLS_COLLECTORS, NDLP_DEBUG, "sanitizers detected, killing myself to avoid lockup");
+ kill(getpid(), SIGKILL);
+#endif
+
if (WIFEXITED(status)) {
exit(WEXITSTATUS(status));
} else if (WIFSIGNALED(status)) {
@@ -179,7 +207,7 @@ int proc_pid_fd(const char *prefix, const char *ns, pid_t pid) {
int fd = open(filename, O_RDONLY | O_CLOEXEC);
if(fd == -1)
- collector_error("Cannot open proc_pid_fd() file '%s'", filename);
+ nd_log(NDLS_COLLECTORS, NDLP_ERR, "Cannot open proc_pid_fd() file '%s'", filename);
return fd;
}
@@ -203,10 +231,8 @@ static struct ns {
{ .nstype = 0, .fd = -1, .status = -1, .name = NULL, .path = NULL }
};
-int switch_namespace(const char *prefix, pid_t pid) {
-
+static int switch_namespace(const char *prefix, pid_t pid) {
#ifdef HAVE_SETNS
-
int i;
for(i = 0; all_ns[i].name ; i++)
all_ns[i].fd = proc_pid_fd(prefix, all_ns[i].path, pid);
@@ -229,7 +255,9 @@ int switch_namespace(const char *prefix, pid_t pid) {
if(setns(all_ns[i].fd, all_ns[i].nstype) == -1) {
if(pass == 1) {
all_ns[i].status = 0;
- collector_error("Cannot switch to %s namespace of pid %d", all_ns[i].name, (int) pid);
+ nd_log(NDLS_COLLECTORS, NDLP_ERR,
+ "Cannot switch to %s namespace of pid %d",
+ all_ns[i].name, (int) pid);
}
}
else
@@ -238,21 +266,22 @@ int switch_namespace(const char *prefix, pid_t pid) {
}
}
+ gettid_uncached();
setgroups(0, NULL);
if(root_fd != -1) {
if(fchdir(root_fd) < 0)
- collector_error("Cannot fchdir() to pid %d root directory", (int)pid);
+ nd_log(NDLS_COLLECTORS, NDLP_ERR, "Cannot fchdir() to pid %d root directory", (int)pid);
if(chroot(".") < 0)
- collector_error("Cannot chroot() to pid %d root directory", (int)pid);
+ nd_log(NDLS_COLLECTORS, NDLP_ERR, "Cannot chroot() to pid %d root directory", (int)pid);
close(root_fd);
}
if(cwd_fd != -1) {
if(fchdir(cwd_fd) < 0)
- collector_error("Cannot fchdir() to pid %d current working directory", (int)pid);
+ nd_log(NDLS_COLLECTORS, NDLP_ERR, "Cannot fchdir() to pid %d current working directory", (int)pid);
close(cwd_fd);
}
@@ -276,9 +305,8 @@ int switch_namespace(const char *prefix, pid_t pid) {
#else
errno = ENOSYS;
- collector_error("setns() is missing on this system.");
+ nd_log(NDLS_COLLECTORS, NDLP_ERR, "setns() is missing on this system.");
return 1;
-
#endif
}
@@ -286,13 +314,13 @@ pid_t read_pid_from_cgroup_file(const char *filename) {
int fd = open(filename, procfile_open_flags);
if(fd == -1) {
if (errno != ENOENT)
- collector_error("Cannot open pid_from_cgroup() file '%s'.", filename);
+ nd_log(NDLS_COLLECTORS, NDLP_ERR, "Cannot open pid_from_cgroup() file '%s'.", filename);
return 0;
}
FILE *fp = fdopen(fd, "r");
if(!fp) {
- collector_error("Cannot upgrade fd to fp for file '%s'.", filename);
+ nd_log(NDLS_COLLECTORS, NDLP_ERR, "Cannot upgrade fd to fp for file '%s'.", filename);
return 0;
}
@@ -307,9 +335,8 @@ pid_t read_pid_from_cgroup_file(const char *filename) {
fclose(fp);
-#ifdef NETDATA_INTERNAL_CHECKS
- if(pid > 0) collector_info("found pid %d on file '%s'", pid, filename);
-#endif
+ if(pid > 0)
+ nd_log(NDLS_COLLECTORS, NDLP_DEBUG, "found pid %d on file '%s'", pid, filename);
return pid;
}
@@ -331,7 +358,7 @@ pid_t read_pid_from_cgroup(const char *path) {
DIR *dir = opendir(path);
if (!dir) {
- collector_error("cannot read directory '%s'", path);
+ nd_log(NDLS_COLLECTORS, NDLP_ERR, "cannot read directory '%s'", path);
return 0;
}
@@ -368,9 +395,8 @@ struct found_device {
} *detected_devices = NULL;
void add_device(const char *host, const char *guest) {
-#ifdef NETDATA_INTERNAL_CHECKS
- collector_info("adding device with host '%s', guest '%s'", host, guest);
-#endif
+ errno_clear();
+ nd_log(NDLS_COLLECTORS, NDLP_DEBUG, "adding device with host '%s', guest '%s'", host, guest);
uint32_t hash = simple_hash(host);
@@ -422,36 +448,34 @@ void detect_veth_interfaces(pid_t pid) {
host = read_proc_net_dev("host", netdata_configured_host_prefix);
if(!host) {
errno_clear();
- collector_error("cannot read host interface list.");
+ nd_log(NDLS_COLLECTORS, NDLP_WARNING, "no host interface list.");
goto cleanup;
}
if(!eligible_ifaces(host)) {
errno_clear();
- collector_info("there are no double-linked host interfaces available.");
+ nd_log(NDLS_COLLECTORS, NDLP_WARNING, "no double-linked host interfaces available.");
goto cleanup;
}
if(switch_namespace(netdata_configured_host_prefix, pid)) {
errno_clear();
- collector_error("cannot switch to the namespace of pid %u", (unsigned int) pid);
+ nd_log(NDLS_COLLECTORS, NDLP_ERR, "cannot switch to the namespace of pid %u", (unsigned int) pid);
goto cleanup;
}
-#ifdef NETDATA_INTERNAL_CHECKS
- collector_info("switched to namespaces of pid %d", pid);
-#endif
+ nd_log(NDLS_COLLECTORS, NDLP_DEBUG, "switched to namespaces of pid %d", pid);
cgroup = read_proc_net_dev("cgroup", NULL);
if(!cgroup) {
errno_clear();
- collector_error("cannot read cgroup interface list.");
+ nd_log(NDLS_COLLECTORS, NDLP_ERR, "cannot read cgroup interface list.");
goto cleanup;
}
if(!eligible_ifaces(cgroup)) {
errno_clear();
- collector_error("there are not double-linked cgroup interfaces available.");
+ nd_log(NDLS_COLLECTORS, NDLP_ERR, "there are not double-linked cgroup interfaces available.");
goto cleanup;
}
@@ -478,66 +502,113 @@ void detect_veth_interfaces(pid_t pid) {
if(iface_is_eligible(h)) {
for (c = cgroup; c; c = c->next) {
if(iface_is_eligible(c) && h->ifindex == c->iflink && h->iflink == c->ifindex) {
- add_device(h->device, c->device);
+ printf("%s %s\n", h->device, c->device);
+ // add_device(h->device, c->device);
}
}
}
}
+ printf("EXIT DONE\n");
+ fflush(stdout);
+
cleanup:
free_host_ifaces(cgroup);
free_host_ifaces(host);
}
+struct send_to_spawned_process {
+ pid_t pid;
+ char host_prefix[FILENAME_MAX];
+};
+
+
+static int spawn_callback(SPAWN_REQUEST *request) {
+ const struct send_to_spawned_process *d = request->data;
+ detect_veth_interfaces(d->pid);
+ return 0;
+}
+
+#define CGROUP_NETWORK_INTERFACE_MAX_LINE 2048
+static void read_from_spawned(SPAWN_INSTANCE *si, const char *name __maybe_unused) {
+ char buffer[CGROUP_NETWORK_INTERFACE_MAX_LINE + 1];
+ char *s;
+ FILE *fp = fdopen(spawn_server_instance_read_fd(si), "r");
+ while((s = fgets(buffer, CGROUP_NETWORK_INTERFACE_MAX_LINE, fp))) {
+ trim(s);
+
+ if(*s && *s != '\n') {
+ char *t = s;
+ while(*t && *t != ' ') t++;
+ if(*t == ' ') {
+ *t = '\0';
+ t++;
+ }
+
+ if(strcmp(s, "EXIT") == 0)
+ break;
+
+ if(!*s || !*t) continue;
+ add_device(s, t);
+ }
+ }
+ fclose(fp);
+ spawn_server_instance_read_fd_unset(si);
+ spawn_server_exec_kill(spawn_server, si);
+}
+
+void detect_veth_interfaces_spawn(pid_t pid) {
+ struct send_to_spawned_process d = {
+ .pid = pid,
+ };
+ strncpyz(d.host_prefix, netdata_configured_host_prefix, sizeof(d.host_prefix) - 1);
+ SPAWN_INSTANCE *si = spawn_server_exec(spawn_server, STDERR_FILENO, 0, NULL, &d, sizeof(d), SPAWN_INSTANCE_TYPE_CALLBACK);
+ if(si)
+ read_from_spawned(si, "switch namespace callback");
+ else
+ nd_log(NDLS_COLLECTORS, NDLP_ERR, "cgroup-network cannot spawn switch namespace callback");
+}
+
// ----------------------------------------------------------------------------
// call the external helper
#define CGROUP_NETWORK_INTERFACE_MAX_LINE 2048
void call_the_helper(pid_t pid, const char *cgroup) {
- if(setresuid(0, 0, 0) == -1)
- collector_error("setresuid(0, 0, 0) failed.");
-
char command[CGROUP_NETWORK_INTERFACE_MAX_LINE + 1];
if(cgroup)
snprintfz(command, CGROUP_NETWORK_INTERFACE_MAX_LINE, "exec " PLUGINS_DIR "/cgroup-network-helper.sh --cgroup '%s'", cgroup);
else
snprintfz(command, CGROUP_NETWORK_INTERFACE_MAX_LINE, "exec " PLUGINS_DIR "/cgroup-network-helper.sh --pid %d", pid);
- collector_info("running: %s", command);
+ nd_log(NDLS_COLLECTORS, NDLP_DEBUG, "running: %s", command);
- POPEN_INSTANCE *pi;
+ SPAWN_INSTANCE *si;
- if(cgroup)
- pi = spawn_popen_run_variadic(PLUGINS_DIR "/cgroup-network-helper.sh", "--cgroup", cgroup, NULL);
+ if(cgroup) {
+ const char *argv[] = {
+ PLUGINS_DIR "/cgroup-network-helper.sh",
+ "--cgroup",
+ cgroup,
+ NULL,
+ };
+ si = spawn_server_exec(spawn_server, nd_log_collectors_fd(), 0, argv, NULL, 0, SPAWN_INSTANCE_TYPE_EXEC);
+ }
else {
char buffer[100];
snprintfz(buffer, sizeof(buffer) - 1, "%d", pid);
- pi = spawn_popen_run_variadic(PLUGINS_DIR "/cgroup-network-helper.sh", "--pid", buffer, NULL);
+ const char *argv[] = {
+ PLUGINS_DIR "/cgroup-network-helper.sh",
+ "--pid",
+ buffer,
+ NULL,
+ };
+ si = spawn_server_exec(spawn_server, nd_log_collectors_fd(), 0, argv, NULL, 0, SPAWN_INSTANCE_TYPE_EXEC);
}
- if(pi) {
- char buffer[CGROUP_NETWORK_INTERFACE_MAX_LINE + 1];
- char *s;
- while((s = fgets(buffer, CGROUP_NETWORK_INTERFACE_MAX_LINE, pi->child_stdout_fp))) {
- trim(s);
-
- if(*s && *s != '\n') {
- char *t = s;
- while(*t && *t != ' ') t++;
- if(*t == ' ') {
- *t = '\0';
- t++;
- }
-
- if(!*s || !*t) continue;
- add_device(s, t);
- }
- }
-
- spawn_popen_kill(pi);
- }
+ if(si)
+ read_from_spawned(si, command);
else
- collector_error("cannot execute cgroup-network helper script: %s", command);
+ nd_log(NDLS_COLLECTORS, NDLP_ERR, "cannot execute cgroup-network helper script: %s", command);
}
int is_valid_path_symbol(char c) {
@@ -568,33 +639,33 @@ int verify_path(const char *path) {
const char *s = path;
while((c = *s++)) {
if(!( isalnum(c) || is_valid_path_symbol(c) )) {
- collector_error("invalid character in path '%s'", path);
+ nd_log(NDLS_COLLECTORS, NDLP_ERR, "invalid character in path '%s'", path);
return -1;
}
}
if(strstr(path, "\\") && !strstr(path, "\\x")) {
- collector_error("invalid escape sequence in path '%s'", path);
+ nd_log(NDLS_COLLECTORS, NDLP_ERR, "invalid escape sequence in path '%s'", path);
return 1;
}
if(strstr(path, "/../")) {
- collector_error("invalid parent path sequence detected in '%s'", path);
+ nd_log(NDLS_COLLECTORS, NDLP_ERR, "invalid parent path sequence detected in '%s'", path);
return 1;
}
if(path[0] != '/') {
- collector_error("only absolute path names are supported - invalid path '%s'", path);
+ nd_log(NDLS_COLLECTORS, NDLP_ERR, "only absolute path names are supported - invalid path '%s'", path);
return -1;
}
if (stat(path, &sb) == -1) {
- collector_error("cannot stat() path '%s'", path);
+ nd_log(NDLS_COLLECTORS, NDLP_ERR, "cannot stat() path '%s'", path);
return -1;
}
if((sb.st_mode & S_IFMT) != S_IFDIR) {
- collector_error("path '%s' is not a directory", path);
+ nd_log(NDLS_COLLECTORS, NDLP_ERR, "path '%s' is not a directory", path);
return -1;
}
@@ -616,10 +687,10 @@ char *fix_path_variable(void) {
char *s = strsep(&ptr, ":");
if(s && *s) {
if(verify_path(s) == -1) {
- collector_error("the PATH variable includes an invalid path '%s' - removed it.", s);
+ nd_log(NDLS_COLLECTORS, NDLP_ERR, "the PATH variable includes an invalid path '%s' - removed it.", s);
}
else {
- collector_info("the PATH variable includes a valid path '%s'.", s);
+ nd_log(NDLS_COLLECTORS, NDLP_DEBUG, "the PATH variable includes a valid path '%s'.", s);
if(added) strcat(safe_path, ":");
strcat(safe_path, s);
added++;
@@ -627,8 +698,8 @@ char *fix_path_variable(void) {
}
}
- collector_info("unsafe PATH: '%s'.", path);
- collector_info(" safe PATH: '%s'.", safe_path);
+ nd_log(NDLS_COLLECTORS, NDLP_DEBUG, "unsafe PATH: '%s'.", path);
+ nd_log(NDLS_COLLECTORS, NDLP_DEBUG, " safe PATH: '%s'.", safe_path);
freez(p);
return safe_path;
@@ -643,11 +714,14 @@ void usage(void) {
exit(1);
}
-int main(int argc, char **argv) {
+int main(int argc, const char **argv) {
pid_t pid = 0;
- clocks_init();
+ if (setresuid(0, 0, 0) == -1)
+ collector_error("setresuid(0, 0, 0) failed.");
+
nd_log_initialize_for_external_plugins("cgroup-network");
+ spawn_server = spawn_server_create(SPAWN_SERVER_OPTION_EXEC | SPAWN_SERVER_OPTION_CALLBACK, NULL, spawn_callback, argc, argv);
// since cgroup-network runs as root, prevent it from opening symbolic links
procfile_open_flags = O_RDONLY|O_NOFOLLOW;
@@ -700,16 +774,16 @@ int main(int argc, char **argv) {
if(pid <= 0) {
errno_clear();
- collector_error("Invalid pid %d given", (int) pid);
+ nd_log(NDLS_COLLECTORS, NDLP_ERR, "Invalid pid %d given", (int) pid);
return 2;
}
if(helper) call_the_helper(pid, NULL);
}
else if(!strcmp(argv[arg], "--cgroup")) {
- char *cgroup = argv[arg+1];
+ const char *cgroup = argv[arg+1];
if(verify_path(cgroup) == -1) {
- collector_error("cgroup '%s' does not exist or is not valid.", cgroup);
+ nd_log(NDLS_COLLECTORS, NDLP_ERR, "cgroup '%s' does not exist or is not valid.", cgroup);
return 1;
}
@@ -718,16 +792,19 @@ int main(int argc, char **argv) {
if(pid <= 0 && !detected_devices) {
errno_clear();
- collector_error("Cannot find a cgroup PID from cgroup '%s'", cgroup);
+ nd_log(NDLS_COLLECTORS, NDLP_ERR, "Cannot find a cgroup PID from cgroup '%s'", cgroup);
}
}
else
usage();
if(pid > 0)
- detect_veth_interfaces(pid);
+ detect_veth_interfaces_spawn(pid);
int found = send_devices();
+
+ spawn_server_destroy(spawn_server);
+
if(found <= 0) return 1;
return 0;
}
diff --git a/src/collectors/cgroups.plugin/cgroup-top.c b/src/collectors/cgroups.plugin/cgroup-top.c
index aa413dad1..7b98502b5 100644
--- a/src/collectors/cgroups.plugin/cgroup-top.c
+++ b/src/collectors/cgroups.plugin/cgroup-top.c
@@ -98,7 +98,7 @@ void cgroup_netdev_get_bandwidth(struct cgroup *cg, NETDATA_DOUBLE *received, NE
*sent = t->sent[slot];
}
-int cgroup_function_cgroup_top(BUFFER *wb, const char *function __maybe_unused) {
+int cgroup_function_cgroup_top(BUFFER *wb, const char *function __maybe_unused, BUFFER *payload __maybe_unused, const char *source __maybe_unused) {
buffer_flush(wb);
wb->content_type = CT_APPLICATION_JSON;
buffer_json_initialize(wb, "\"", "\"", 0, true, BUFFER_JSON_OPTIONS_DEFAULT);
@@ -341,7 +341,7 @@ int cgroup_function_cgroup_top(BUFFER *wb, const char *function __maybe_unused)
return HTTP_RESP_OK;
}
-int cgroup_function_systemd_top(BUFFER *wb, const char *function __maybe_unused) {
+int cgroup_function_systemd_top(BUFFER *wb, const char *function __maybe_unused, BUFFER *payload __maybe_unused, const char *source __maybe_unused) {
buffer_flush(wb);
wb->content_type = CT_APPLICATION_JSON;
buffer_json_initialize(wb, "\"", "\"", 0, true, BUFFER_JSON_OPTIONS_DEFAULT);
diff --git a/src/collectors/cgroups.plugin/sys_fs_cgroup.c b/src/collectors/cgroups.plugin/sys_fs_cgroup.c
index 5fdefa863..d41575fa6 100644
--- a/src/collectors/cgroups.plugin/sys_fs_cgroup.c
+++ b/src/collectors/cgroups.plugin/sys_fs_cgroup.c
@@ -39,7 +39,7 @@ SIMPLE_PATTERN *search_cgroup_paths = NULL;
SIMPLE_PATTERN *enabled_cgroup_renames = NULL;
SIMPLE_PATTERN *systemd_services_cgroups = NULL;
SIMPLE_PATTERN *entrypoint_parent_process_comm = NULL;
-char *cgroups_network_interface_script = NULL;
+const char *cgroups_network_interface_script = NULL;
int cgroups_check = 0;
uint32_t Read_hash = 0;
uint32_t Write_hash = 0;
@@ -82,7 +82,7 @@ static enum cgroups_systemd_setting cgroups_detect_systemd(const char *exec)
return retval;
struct pollfd pfd;
- pfd.fd = spawn_server_instance_read_fd(pi->si);
+ pfd.fd = spawn_popen_read_fd(pi);
pfd.events = POLLIN;
int timeout = 3000; // milliseconds
@@ -93,7 +93,7 @@ static enum cgroups_systemd_setting cgroups_detect_systemd(const char *exec)
} else if (ret == 0) {
collector_info("Cannot get the output of \"%s\" within timeout (%d ms)", exec, timeout);
} else {
- while (fgets(buf, MAXSIZE_PROC_CMDLINE, pi->child_stdout_fp) != NULL) {
+ while (fgets(buf, MAXSIZE_PROC_CMDLINE, spawn_popen_stdout(pi)) != NULL) {
if ((begin = strstr(buf, SYSTEMD_HIERARCHY_STRING))) {
end = begin = begin + strlen(SYSTEMD_HIERARCHY_STRING);
if (!*begin)
@@ -153,18 +153,18 @@ static enum cgroups_type cgroups_try_detect_version()
int cgroups2_available = 0;
// 1. check if cgroups2 available on system at all
- POPEN_INSTANCE *instance = spawn_popen_run("grep cgroup /proc/filesystems");
- if(!instance) {
+ POPEN_INSTANCE *pi = spawn_popen_run("grep cgroup /proc/filesystems");
+ if(!pi) {
collector_error("cannot run 'grep cgroup /proc/filesystems'");
return CGROUPS_AUTODETECT_FAIL;
}
- while (fgets(buf, MAXSIZE_PROC_CMDLINE, instance->child_stdout_fp) != NULL) {
+ while (fgets(buf, MAXSIZE_PROC_CMDLINE, spawn_popen_stdout(pi)) != NULL) {
if (strstr(buf, "cgroup2")) {
cgroups2_available = 1;
break;
}
}
- if(spawn_popen_wait(instance) != 0)
+ if(spawn_popen_wait(pi) != 0)
return CGROUPS_AUTODETECT_FAIL;
if(!cgroups2_available)
@@ -229,13 +229,17 @@ void read_cgroup_plugin_configuration() {
throttled_time_hash = simple_hash("throttled_time");
throttled_usec_hash = simple_hash("throttled_usec");
- cgroup_update_every = (int)config_get_number("plugin:cgroups", "update every", localhost->rrd_update_every);
- if(cgroup_update_every < localhost->rrd_update_every)
+ cgroup_update_every = (int)config_get_duration_seconds("plugin:cgroups", "update every", localhost->rrd_update_every);
+ if(cgroup_update_every < localhost->rrd_update_every) {
cgroup_update_every = localhost->rrd_update_every;
+ config_set_duration_seconds("plugin:cgroups", "update every", localhost->rrd_update_every);
+ }
- cgroup_check_for_new_every = (int)config_get_number("plugin:cgroups", "check for new cgroups every", cgroup_check_for_new_every);
- if(cgroup_check_for_new_every < cgroup_update_every)
+ cgroup_check_for_new_every = (int)config_get_duration_seconds("plugin:cgroups", "check for new cgroups every", cgroup_check_for_new_every);
+ if(cgroup_check_for_new_every < cgroup_update_every) {
cgroup_check_for_new_every = cgroup_update_every;
+ config_set_duration_seconds("plugin:cgroups", "check for new cgroups every", cgroup_check_for_new_every);
+ }
cgroup_use_unified_cgroups = config_get_boolean_ondemand("plugin:cgroups", "use unified cgroups", CONFIG_BOOLEAN_AUTO);
if (cgroup_use_unified_cgroups == CONFIG_BOOLEAN_AUTO)
@@ -1401,24 +1405,25 @@ void *cgroups_main(void *ptr) {
cgroup_netdev_link_init();
rrd_function_add_inline(localhost, NULL, "containers-vms", 10,
- RRDFUNCTIONS_PRIORITY_DEFAULT / 2, RRDFUNCTIONS_CGTOP_HELP,
+ RRDFUNCTIONS_PRIORITY_DEFAULT / 2, RRDFUNCTIONS_VERSION_DEFAULT,
+ RRDFUNCTIONS_CGTOP_HELP,
"top", HTTP_ACCESS_ANONYMOUS_DATA,
cgroup_function_cgroup_top);
rrd_function_add_inline(localhost, NULL, "systemd-services", 10,
- RRDFUNCTIONS_PRIORITY_DEFAULT / 3, RRDFUNCTIONS_SYSTEMD_SERVICES_HELP,
+ RRDFUNCTIONS_PRIORITY_DEFAULT / 3, RRDFUNCTIONS_VERSION_DEFAULT,
+ RRDFUNCTIONS_SYSTEMD_SERVICES_HELP,
"top", HTTP_ACCESS_ANONYMOUS_DATA,
cgroup_function_systemd_top);
heartbeat_t hb;
- heartbeat_init(&hb);
- usec_t step = cgroup_update_every * USEC_PER_SEC;
+ heartbeat_init(&hb, cgroup_update_every * USEC_PER_SEC);
usec_t find_every = cgroup_check_for_new_every * USEC_PER_SEC, find_dt = 0;
while(service_running(SERVICE_COLLECTORS)) {
worker_is_idle();
- usec_t hb_dt = heartbeat_next(&hb, step);
+ usec_t hb_dt = heartbeat_next(&hb);
if (unlikely(!service_running(SERVICE_COLLECTORS)))
break;