conf: execute hooks based on lxc.hooks.version

Unblocks #2013. Unblocks #2015. Closes #1766. Signed-off-by: 's avatarChristian Brauner <christian.brauner@ubuntu.com>
parent a2c09be0
...@@ -308,84 +308,114 @@ static int run_buffer(char *buffer) ...@@ -308,84 +308,114 @@ static int run_buffer(char *buffer)
f = lxc_popen(buffer); f = lxc_popen(buffer);
if (!f) { if (!f) {
SYSERROR("Failed to popen() %s.", buffer); SYSERROR("Failed to popen() %s", buffer);
return -1; return -1;
} }
output = malloc(LXC_LOG_BUFFER_SIZE); output = malloc(LXC_LOG_BUFFER_SIZE);
if (!output) { if (!output) {
ERROR("Failed to allocate memory for %s.", buffer); ERROR("Failed to allocate memory for %s", buffer);
lxc_pclose(f); lxc_pclose(f);
return -1; return -1;
} }
while (fgets(output, LXC_LOG_BUFFER_SIZE, f->f)) while (fgets(output, LXC_LOG_BUFFER_SIZE, f->f))
DEBUG("Script %s with output: %s.", buffer, output); DEBUG("Script %s with output: %s", buffer, output);
free(output); free(output);
ret = lxc_pclose(f); ret = lxc_pclose(f);
if (ret == -1) { if (ret == -1) {
SYSERROR("Script exited with error."); SYSERROR("Script exited with error");
return -1; return -1;
} else if (WIFEXITED(ret) && WEXITSTATUS(ret) != 0) { } else if (WIFEXITED(ret) && WEXITSTATUS(ret) != 0) {
ERROR("Script exited with status %d.", WEXITSTATUS(ret)); ERROR("Script exited with status %d", WEXITSTATUS(ret));
return -1; return -1;
} else if (WIFSIGNALED(ret)) { } else if (WIFSIGNALED(ret)) {
ERROR("Script terminated by signal %d.", WTERMSIG(ret)); ERROR("Script terminated by signal %d", WTERMSIG(ret));
return -1; return -1;
} }
return 0; return 0;
} }
static int run_script_argv(const char *name, const char *section, static int run_script_argv(const char *name, unsigned int hook_version,
const char *script, const char *hook, const char *section, const char *script,
const char *lxcpath, char **argsin) const char *hookname, const char *lxcpath,
char **argsin)
{ {
int ret, i; int buf_pos, i, ret;
char *buffer; char *buffer;
size_t size = 0; size_t size = 0, size_legacy_args = 0;
INFO("Executing script \"%s\" for container \"%s\", config section \"%s\".", if (hook_version == 0)
script, name, section); INFO("Executing script \"%s\" for container \"%s\", config "
"section \"%s\"", script, name, section);
else
INFO("Executing script \"%s\" for container \"%s\"", script, name);
for (i = 0; argsin && argsin[i]; i++) for (i = 0; argsin && argsin[i]; i++)
size += strlen(argsin[i]) + 1; size += strlen(argsin[i]) + 1;
size += strlen(hook) + 1; size += sizeof("exec");
size += strlen("exec");
size += strlen(script); size += strlen(script);
size += strlen(name); size++;
size += strlen(section);
size += 4; size_legacy_args += strlen(section);
size_legacy_args++;
size_legacy_args += strlen(name);
size_legacy_args++;
size_legacy_args += strlen(hookname);
size_legacy_args++;
if (size > INT_MAX) if (size > INT_MAX)
return -1; return -EFBIG;
buffer = alloca(size); buffer = alloca(size);
if (!buffer) {
ERROR("Failed to allocate memory."); if (hook_version == 0) {
size += size_legacy_args;
buf_pos = snprintf(buffer, size, "exec %s %s %s %s", script, name, section, hookname);
if (buf_pos < 0 || (size_t)buf_pos >= size) {
ERROR("Failed to create command line for script \"%s\"", script);
return -1;
}
} else {
buf_pos = snprintf(buffer, size, "exec %s", script);
if (buf_pos < 0 || (size_t)buf_pos >= size) {
ERROR("Failed to create command line for script \"%s\"", script);
return -1; return -1;
} }
ret = ret = setenv("LXC_HOOK_TYPE", hookname, 1);
snprintf(buffer, size, "exec %s %s %s %s", script, name, section, hook); if (ret < 0) {
if (ret < 0 || (size_t)ret >= size) { SYSERROR("Failed to set environment variable: "
ERROR("Script name too long."); "LXC_HOOK_TYPE=%s", hookname);
return -1;
}
TRACE("Set environment variable: LXC_HOOK_TYPE=%s", section);
ret = setenv("LXC_HOOK_SECTION", section, 1);
if (ret < 0) {
SYSERROR("Failed to set environment variable: "
"LXC_HOOK_SECTION=%s", section);
return -1; return -1;
} }
TRACE("Set environment variable: LXC_HOOK_SECTION=%s", section);
}
for (i = 0; argsin && argsin[i]; i++) { for (i = 0; argsin && argsin[i]; i++) {
int len = size - ret; size_t len = size - buf_pos;
int rc;
rc = snprintf(buffer + ret, len, " %s", argsin[i]); ret = snprintf(buffer + buf_pos, len, " %s", argsin[i]);
if (rc < 0 || rc >= len) { if (ret < 0 || (size_t)ret >= len) {
ERROR("Script args too long."); ERROR("Failed to create command line for script \"%s\"", script);
return -1; return -1;
} }
ret += rc; buf_pos += ret;
} }
return run_buffer(buffer); return run_buffer(buffer);
...@@ -3261,41 +3291,45 @@ int lxc_setup(struct lxc_handler *handler) ...@@ -3261,41 +3291,45 @@ int lxc_setup(struct lxc_handler *handler)
return 0; return 0;
} }
int run_lxc_hooks(const char *name, char *hook, struct lxc_conf *conf, int run_lxc_hooks(const char *name, char *hookname, struct lxc_conf *conf,
const char *lxcpath, char *argv[]) const char *lxcpath, char *argv[])
{ {
int which = -1;
struct lxc_list *it; struct lxc_list *it;
int which = -1;
if (strcmp(hook, "pre-start") == 0) if (strcmp(hookname, "pre-start") == 0)
which = LXCHOOK_PRESTART; which = LXCHOOK_PRESTART;
else if (strcmp(hook, "start-host") == 0) else if (strcmp(hookname, "start-host") == 0)
which = LXCHOOK_START_HOST; which = LXCHOOK_START_HOST;
else if (strcmp(hook, "pre-mount") == 0) else if (strcmp(hookname, "pre-mount") == 0)
which = LXCHOOK_PREMOUNT; which = LXCHOOK_PREMOUNT;
else if (strcmp(hook, "mount") == 0) else if (strcmp(hookname, "mount") == 0)
which = LXCHOOK_MOUNT; which = LXCHOOK_MOUNT;
else if (strcmp(hook, "autodev") == 0) else if (strcmp(hookname, "autodev") == 0)
which = LXCHOOK_AUTODEV; which = LXCHOOK_AUTODEV;
else if (strcmp(hook, "start") == 0) else if (strcmp(hookname, "start") == 0)
which = LXCHOOK_START; which = LXCHOOK_START;
else if (strcmp(hook, "stop") == 0) else if (strcmp(hookname, "stop") == 0)
which = LXCHOOK_STOP; which = LXCHOOK_STOP;
else if (strcmp(hook, "post-stop") == 0) else if (strcmp(hookname, "post-stop") == 0)
which = LXCHOOK_POSTSTOP; which = LXCHOOK_POSTSTOP;
else if (strcmp(hook, "clone") == 0) else if (strcmp(hookname, "clone") == 0)
which = LXCHOOK_CLONE; which = LXCHOOK_CLONE;
else if (strcmp(hook, "destroy") == 0) else if (strcmp(hookname, "destroy") == 0)
which = LXCHOOK_DESTROY; which = LXCHOOK_DESTROY;
else else
return -1; return -1;
lxc_list_for_each(it, &conf->hooks[which]) { lxc_list_for_each(it, &conf->hooks[which]) {
int ret; int ret;
char *hookname = it->elem; char *hook = it->elem;
ret = run_script_argv(name, "lxc", hookname, hook, lxcpath, argv);
if (ret) ret = run_script_argv(name, conf->hooks_version, "lxc", hook,
return ret; hookname, lxcpath, argv);
if (ret < 0)
return -1;
} }
return 0; return 0;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment