Support for specifying a path prefix to run inside an LXC

This commit is contained in:
Dan Snyder 2025-05-23 17:29:16 -04:00
parent eaff59c2ff
commit 9f9966928a
5 changed files with 54 additions and 32 deletions

View File

@ -24,16 +24,19 @@ int parseLxcConfigFile(lxcinfo *lxc, char *filedata) {
strcpy(lxc->hostname, ptr); strcpy(lxc->hostname, ptr);
} }
int readLxcConfig(lxcinfo *lxc, int lxcid) { int readLxcConfig(lxcinfo *lxc, int lxcid, char *pathPrefix) {
char *fname = malloc(1024); char *fname = malloc(1024);
char *buffer = malloc(4096); char *buffer = malloc(4096);
sprintf(fname, "/etc/pve/lxc/%d.conf", lxcid); sprintf(fname, "%s/etc/pve/lxc/%d.conf", pathPrefix, lxcid);
FILE *file = fopen(fname, "rb"); FILE *file = fopen(fname, "rb");
if (file == NULL) { if (file == NULL) {
printf("Failed to open <%s>: %d\n", fname, errno); fprintf(stderr, "Failed to open <%s>: %d\n", fname, errno);
free(buffer);
free(fname);
return -1; return -1;
} }
fread(buffer, 1, 4096, file); fread(buffer, 1, 4096, file);
fclose(file); fclose(file);
@ -43,14 +46,17 @@ int readLxcConfig(lxcinfo *lxc, int lxcid) {
return 0; return 0;
} }
void getInactiveLXCs(lxcinfo **lxcs) { void getInactiveLXCs(lxcinfo **lxcs, char *pathPrefix) {
struct dirent *pDirent; struct dirent *pDirent;
DIR *pDir; DIR *pDir;
char *fname = malloc(1024);
sprintf(fname, "%s/etc/pve/lxc", pathPrefix);
// Ensure we can open directory. // Ensure we can open directory.
pDir = opendir("/etc/pve/lxc"); pDir = opendir(fname);
if (pDir == NULL) { if (pDir == NULL) {
printf("Cannot open directory '/etc/pve/lxc'\n"); fprintf(stderr, "Cannot open directory '%s'\n", fname);
free(fname);
return; return;
} }
@ -63,13 +69,14 @@ void getInactiveLXCs(lxcinfo **lxcs) {
int argc = sscanf(fname, "%d.%s", &lxcid, (char *) extension); int argc = sscanf(fname, "%d.%s", &lxcid, (char *) extension);
// ensure it's an LXC config // ensure it's an LXC config
if (argc != 2 || strcmp((char *) extension, "conf") != 0) continue; if (argc != 2 || strcmp((char *) extension, "conf") != 0) continue;
getLXCInfo(lxcs, lxcid); // don't care about result getLXCInfo(lxcs, lxcid, pathPrefix); // don't care about result
} }
closedir(pDir); closedir(pDir);
free(fname);
} }
lxcinfo *getLXCInfo(lxcinfo **lxcs, int lxcid) { lxcinfo *getLXCInfo(lxcinfo **lxcs, int lxcid, char *pathPrefix) {
lxcinfo *lxc = *lxcs; lxcinfo *lxc = *lxcs;
while (lxc != NULL) { while (lxc != NULL) {
if (lxc->lxcid == lxcid) return lxc; if (lxc->lxcid == lxcid) return lxc;
@ -80,7 +87,7 @@ lxcinfo *getLXCInfo(lxcinfo **lxcs, int lxcid) {
lxc->lxcid = lxcid; lxc->lxcid = lxcid;
lxc->running = 0; lxc->running = 0;
if (readLxcConfig(lxc, lxcid)) { if (readLxcConfig(lxc, lxcid, pathPrefix)) {
// failed to read LXC // failed to read LXC
free(lxc); free(lxc);
return NULL; return NULL;

View File

@ -13,7 +13,7 @@ typedef struct _lxc_info {
char hostname[128]; char hostname[128];
} lxcinfo; } lxcinfo;
lxcinfo *getLXCInfo(lxcinfo **lxcs, int lxcid); lxcinfo *getLXCInfo(lxcinfo **lxcs, int lxcid, char *pathPrefix);
void getInactiveLXCs(lxcinfo **lxcs); void getInactiveLXCs(lxcinfo **lxcs, char *pathPrefix);
#endif #endif

View File

@ -240,16 +240,19 @@ nextProcess:
} }
} }
char *readProcesses(char *procdir) { char *readProcesses(char *pathPrefix) {
int len; int len;
struct dirent *pDirent; struct dirent *pDirent;
DIR *pDir; DIR *pDir;
// Ensure we can open directory. char *procdir = malloc(1024);
sprintf(procdir, "%s/proc", pathPrefix);
// Ensure we can open directory.
pDir = opendir(procdir); pDir = opendir(procdir);
if (pDir == NULL) { if (pDir == NULL) {
printf("Cannot open directory '%s'\n", procdir); printf("Cannot open directory '%s'\n", procdir);
free(procdir);
return NULL; return NULL;
} }
@ -272,6 +275,7 @@ char *readProcesses(char *procdir) {
while ((pDirent = readdir(pDir)) != NULL) { while ((pDirent = readdir(pDir)) != NULL) {
first = pDirent->d_name[0]; first = pDirent->d_name[0];
// Ignore directories that aren't PIDs
if (first < '0' || first > '9') continue; if (first < '0' || first > '9') continue;
if (cur->visited) { if (cur->visited) {
@ -281,7 +285,7 @@ char *readProcesses(char *procdir) {
cur = cur->next; cur = cur->next;
} }
sprintf(fname, "/proc/%s/status", pDirent->d_name); sprintf(fname, "%s/%s/status", procdir, pDirent->d_name);
file = fopen(fname, "rb"); file = fopen(fname, "rb");
if (file == NULL) continue; if (file == NULL) continue;
fread(buffer, 1, 4096, file); fread(buffer, 1, 4096, file);
@ -299,7 +303,7 @@ char *readProcesses(char *procdir) {
if (parseStatFile(cur, buffer)) continue; if (parseStatFile(cur, buffer)) continue;
sprintf(fname, "/proc/%s/io", pDirent->d_name); sprintf(fname, "%s/%s/io", procdir, pDirent->d_name);
file = fopen(fname, "rb"); file = fopen(fname, "rb");
if (file == NULL) continue; if (file == NULL) continue;
fread(buffer, 1, 4096, file); fread(buffer, 1, 4096, file);
@ -307,7 +311,7 @@ char *readProcesses(char *procdir) {
if (parseIOFile(cur, buffer)) continue; if (parseIOFile(cur, buffer)) continue;
sprintf(fname, "/proc/%s/cpuset", pDirent->d_name); sprintf(fname, "%s/%s/cpuset", procdir, pDirent->d_name);
file = fopen(fname, "rb"); file = fopen(fname, "rb");
if (file == NULL) goto nextProcess; if (file == NULL) goto nextProcess;
fread(cur->cpuset, 1, sizeof(cur->cpuset), file); fread(cur->cpuset, 1, sizeof(cur->cpuset), file);
@ -318,7 +322,7 @@ char *readProcesses(char *procdir) {
if (memcmp(cur->cpuset, lxcTag, strlen(lxcTag)) == 0) { if (memcmp(cur->cpuset, lxcTag, strlen(lxcTag)) == 0) {
// Resides in LXC -- read file and tag // Resides in LXC -- read file and tag
sscanf(cur->cpuset, "/lxc/%d/ns", &cur->lxc); sscanf(cur->cpuset, "/lxc/%d/ns", &cur->lxc);
lxcinfo *lxc = getLXCInfo(&lxcs, cur->lxc); lxcinfo *lxc = getLXCInfo(&lxcs, cur->lxc, pathPrefix);
if (lxc == NULL) { if (lxc == NULL) {
printf("Failed to read LXC config <%d>\n", cur->lxc); printf("Failed to read LXC config <%d>\n", cur->lxc);
} else { } else {
@ -340,7 +344,7 @@ nextProcess:
linkFamily(head); linkFamily(head);
aggregateStats(head); aggregateStats(head);
getInactiveLXCs(&lxcs); getInactiveLXCs(&lxcs, pathPrefix);
int clocks = sysconf(_SC_CLK_TCK); int clocks = sysconf(_SC_CLK_TCK);
char *output = malloc(8 * 1024 * 1024); char *output = malloc(8 * 1024 * 1024);
@ -390,6 +394,7 @@ nextProcess:
} }
closedir(pDir); closedir(pDir);
free(procdir);
free(buffer); free(buffer);
free(fname); free(fname);
return output; return output;

View File

@ -35,7 +35,7 @@ typedef struct st_process {
uint64_t cWrite; uint64_t cWrite;
} Process; } Process;
char *readProcesses(char *procdir); char *readProcesses(char *pathPrefix);
void aggregateStats(Process *head); void aggregateStats(Process *head);
int resetVisits(Process *head); int resetVisits(Process *head);

View File

@ -44,8 +44,8 @@ void *self_connector_thread(void *arg) {
#define BUFFER_SIZE 1024 #define BUFFER_SIZE 1024
void handle_client(int client_socket) { void handle_client(int client_socket, char *pathPrefix) {
char *data = readProcesses("/proc"); char *data = readProcesses(pathPrefix);
int length = strlen(data); int length = strlen(data);
printf("Got data of length: %d\n", length); printf("Got data of length: %d\n", length);
@ -92,22 +92,32 @@ closeConnection:
} }
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
if (argc == 1) { char *portStr = NULL;
char *buf = readProcesses("/proc"); char *pathPrefix = "";
if (buf == NULL) return 1;
printf(buf); for (int i=0; i<argc; i++) {
free(buf); if (strcmp("--port", argv[i]) == 0) {
return 0; portStr = argv[++i];
} }
for (int i=0; i<strlen(argv[1]); i++) { if (strcmp("--path.rootfs", argv[i]) == 0) {
if (argv[1][i] < '0' || argv[1][i] > '9') { pathPrefix = argv[++i];
fprintf(stderr, "Argument '%s' is not a valid port", argv[1]); }
}
if (portStr == NULL) {
fprintf(stderr, "Missing required argument --port\n");
return 1;
}
for (int i=0; i<strlen(portStr); i++) {
if (portStr[i] < '0' || portStr[i] > '9') {
fprintf(stderr, "Argument '%s' is not a valid port\n", portStr);
return 1; return 1;
} }
} }
int port = atoi(argv[1]); int port = atoi(portStr);
// Set up signal handling // Set up signal handling
struct sigaction sa; struct sigaction sa;
sa.sa_handler = handle_signal; sa.sa_handler = handle_signal;
@ -166,7 +176,7 @@ int main(int argc, char *argv[]) {
} }
// Handle the client in a separate function // Handle the client in a separate function
handle_client(client_socket); handle_client(client_socket, pathPrefix);
} }
close(client_socket); close(client_socket);