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)
f = lxc_popen(buffer);
if (!f) {
SYSERROR("Failed to popen() %s.", buffer);
SYSERROR("Failed to popen() %s", buffer);
return -1;
}
output = malloc(LXC_LOG_BUFFER_SIZE);
if (!output) {
ERROR("Failed to allocate memory for %s.", buffer);
ERROR("Failed to allocate memory for %s", buffer);
lxc_pclose(f);
return -1;
}
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);
ret = lxc_pclose(f);
if (ret == -1) {
SYSERROR("Script exited with error.");
SYSERROR("Script exited with error");
return -1;
} 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;
} else if (WIFSIGNALED(ret)) {
ERROR("Script terminated by signal %d.", WTERMSIG(ret));
ERROR("Script terminated by signal %d", WTERMSIG(ret));
return -1;
}
return 0;
}
static int run_script_argv(const char *name, const char *section,
const char *script, const char *hook,
const char *lxcpath, char **argsin)
static int run_script_argv(const char *name, unsigned int hook_version,
const char *section, const char *script,
const char *hookname, const char *lxcpath,
char **argsin)
{
int ret, i;
int buf_pos, i, ret;
char *buffer;
size_t size = 0;
size_t size = 0, size_legacy_args = 0;
INFO("Executing script \"%s\" for container \"%s\", config section \"%s\".",
script, name, section);
if (hook_version == 0)
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++)
size += strlen(argsin[i]) + 1;
size += strlen(hook) + 1;
size += strlen("exec");
size += sizeof("exec");
size += strlen(script);
size += strlen(name);
size += strlen(section);
size += 4;
size++;
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)
return -1;
return -EFBIG;
buffer = alloca(size);
if (!buffer) {
ERROR("Failed to allocate memory.");
return -1;
}
ret =
snprintf(buffer, size, "exec %s %s %s %s", script, name, section, hook);
if (ret < 0 || (size_t)ret >= size) {
ERROR("Script name too long.");
return -1;
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;
}
ret = setenv("LXC_HOOK_TYPE", hookname, 1);
if (ret < 0) {
SYSERROR("Failed to set environment variable: "
"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;
}
TRACE("Set environment variable: LXC_HOOK_SECTION=%s", section);
}
for (i = 0; argsin && argsin[i]; i++) {
int len = size - ret;
int rc;
rc = snprintf(buffer + ret, len, " %s", argsin[i]);
if (rc < 0 || rc >= len) {
ERROR("Script args too long.");
size_t len = size - buf_pos;
ret = snprintf(buffer + buf_pos, len, " %s", argsin[i]);
if (ret < 0 || (size_t)ret >= len) {
ERROR("Failed to create command line for script \"%s\"", script);
return -1;
}
ret += rc;
buf_pos += ret;
}
return run_buffer(buffer);
......@@ -3261,41 +3291,45 @@ int lxc_setup(struct lxc_handler *handler)
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[])
{
int which = -1;
struct lxc_list *it;
int which = -1;
if (strcmp(hook, "pre-start") == 0)
if (strcmp(hookname, "pre-start") == 0)
which = LXCHOOK_PRESTART;
else if (strcmp(hook, "start-host") == 0)
else if (strcmp(hookname, "start-host") == 0)
which = LXCHOOK_START_HOST;
else if (strcmp(hook, "pre-mount") == 0)
else if (strcmp(hookname, "pre-mount") == 0)
which = LXCHOOK_PREMOUNT;
else if (strcmp(hook, "mount") == 0)
else if (strcmp(hookname, "mount") == 0)
which = LXCHOOK_MOUNT;
else if (strcmp(hook, "autodev") == 0)
else if (strcmp(hookname, "autodev") == 0)
which = LXCHOOK_AUTODEV;
else if (strcmp(hook, "start") == 0)
else if (strcmp(hookname, "start") == 0)
which = LXCHOOK_START;
else if (strcmp(hook, "stop") == 0)
else if (strcmp(hookname, "stop") == 0)
which = LXCHOOK_STOP;
else if (strcmp(hook, "post-stop") == 0)
else if (strcmp(hookname, "post-stop") == 0)
which = LXCHOOK_POSTSTOP;
else if (strcmp(hook, "clone") == 0)
else if (strcmp(hookname, "clone") == 0)
which = LXCHOOK_CLONE;
else if (strcmp(hook, "destroy") == 0)
else if (strcmp(hookname, "destroy") == 0)
which = LXCHOOK_DESTROY;
else
return -1;
lxc_list_for_each(it, &conf->hooks[which]) {
int ret;
char *hookname = it->elem;
ret = run_script_argv(name, "lxc", hookname, hook, lxcpath, argv);
if (ret)
return ret;
char *hook = it->elem;
ret = run_script_argv(name, conf->hooks_version, "lxc", hook,
hookname, lxcpath, argv);
if (ret < 0)
return -1;
}
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