mirror of
https://git.proxmox.com/git/mirror_lxc
synced 2025-08-14 17:12:14 +00:00
Merge pull request #2026 from brauner/2017-12-12/lxc_hook_version
confile: add lxc.hook.version
This commit is contained in:
commit
81b10e37c9
@ -308,9 +308,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|||||||
<title>Init ID</title>
|
<title>Init ID</title>
|
||||||
<para>
|
<para>
|
||||||
Sets the UID/GID to use for the init system, and subsequent commands.
|
Sets the UID/GID to use for the init system, and subsequent commands.
|
||||||
Note that using a non-root uid when booting a system container will
|
Note that using a non-root UID when booting a system container will
|
||||||
likely not work due to missing privileges. Setting the UID/GID is mostly
|
likely not work due to missing privileges. Setting the UID/GID is mostly
|
||||||
useful when running application container.
|
useful when running application containers.
|
||||||
|
|
||||||
Defaults to: UID(0), GID(0)
|
Defaults to: UID(0), GID(0)
|
||||||
</para>
|
</para>
|
||||||
@ -608,7 +608,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term>
|
<term>
|
||||||
<option>lxc.net.[i].ipv6.address</option>
|
<option>lxc.net.[i].ipv6.address</option>
|
||||||
@ -651,15 +650,56 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|||||||
<para>
|
<para>
|
||||||
Add a configuration option to specify a script to be
|
Add a configuration option to specify a script to be
|
||||||
executed after creating and configuring the network used
|
executed after creating and configuring the network used
|
||||||
from the host side. The following arguments are passed
|
from the host side.
|
||||||
to the script: container name and config section name
|
|
||||||
(net) Additional arguments depend on the config section
|
|
||||||
employing a script hook; the following are used by the
|
|
||||||
network system: execution context (up), network type
|
|
||||||
(empty/veth/macvlan/phys), Depending on the network
|
|
||||||
type, other arguments may be passed:
|
|
||||||
veth/macvlan/phys. And finally (host-sided) device name.
|
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
In addition to the information available to all hooks. The
|
||||||
|
following information is provided to the script:
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
LXC_HOOK_TYPE: the hook type. This is either 'up' or 'down'.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
LXC_HOOK_SECTION: the section type 'net'.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
LXC_NET_TYPE: the network type. This is one of the valid
|
||||||
|
network types listed here (e.g. 'macvlan', 'veth').
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
LXC_NET_PARENT: the parent device on the host. This is only
|
||||||
|
set for network types 'mavclan', 'veth', 'phys'.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
LXC_NET_PEER: the name of the peer device on the host. This is
|
||||||
|
only set for 'veth' network types. Note that this information
|
||||||
|
is only available when <option>lxc.hook.version</option> is set
|
||||||
|
to 1.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
|
||||||
|
Whether this information is provided in the form of environment
|
||||||
|
variables or as arguments to the script depends on the value of
|
||||||
|
<option>lxc.hook.version</option>. If set to 1 then information is
|
||||||
|
provided in the form of environment variables. If set to 0
|
||||||
|
information is provided as arguments to the script.
|
||||||
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Standard output from the script is logged at debug level.
|
Standard output from the script is logged at debug level.
|
||||||
Standard error is not logged, but can be captured by the
|
Standard error is not logged, but can be captured by the
|
||||||
@ -676,15 +716,56 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|||||||
<para>
|
<para>
|
||||||
Add a configuration option to specify a script to be
|
Add a configuration option to specify a script to be
|
||||||
executed before destroying the network used from the
|
executed before destroying the network used from the
|
||||||
host side. The following arguments are passed to the
|
host side.
|
||||||
script: container name and config section name (net)
|
|
||||||
Additional arguments depend on the config section
|
|
||||||
employing a script hook; the following are used by the
|
|
||||||
network system: execution context (down), network type
|
|
||||||
(empty/veth/macvlan/phys), Depending on the network
|
|
||||||
type, other arguments may be passed:
|
|
||||||
veth/macvlan/phys. And finally (host-sided) device name.
|
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
In addition to the information available to all hooks. The
|
||||||
|
following information is provided to the script:
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
LXC_HOOK_TYPE: the hook type. This is either 'up' or 'down'.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
LXC_HOOK_SECTION: the section type 'net'.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
LXC_NET_TYPE: the network type. This is one of the valid
|
||||||
|
network types listed here (e.g. 'macvlan', 'veth').
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
LXC_NET_PARENT: the parent device on the host. This is only
|
||||||
|
set for network types 'mavclan', 'veth', 'phys'.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
LXC_NET_PEER: the name of the peer device on the host. This is
|
||||||
|
only set for 'veth' network types. Note that this information
|
||||||
|
is only available when <option>lxc.hook.version</option> is set
|
||||||
|
to 1.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
|
||||||
|
Whether this information is provided in the form of environment
|
||||||
|
variables or as arguments to the script depends on the value of
|
||||||
|
<option>lxc.hook.version</option>. If set to 1 then information is
|
||||||
|
provided in the form of environment variables. If set to 0
|
||||||
|
information is provided as arguments to the script.
|
||||||
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Standard output from the script is logged at debug level.
|
Standard output from the script is logged at debug level.
|
||||||
Standard error is not logged, but can be captured by the
|
Standard error is not logged, but can be captured by the
|
||||||
@ -1636,9 +1717,10 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|||||||
at various times in a container's lifetime.
|
at various times in a container's lifetime.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
When a container hook is executed, information is passed both
|
When a container hook is executed, additional information is passed
|
||||||
as command line arguments and through environment variables.
|
along. The <option>lxc.hook.version</option> argument can be used to
|
||||||
The arguments are:
|
determine if the following arguments are passed as command line
|
||||||
|
arguments or through environment variables. The arguments are:
|
||||||
<itemizedlist>
|
<itemizedlist>
|
||||||
<listitem><para> Container name. </para></listitem>
|
<listitem><para> Container name. </para></listitem>
|
||||||
<listitem><para> Section (always 'lxc'). </para></listitem>
|
<listitem><para> Section (always 'lxc'). </para></listitem>
|
||||||
@ -1652,13 +1734,38 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
The following environment variables are set:
|
The following environment variables are set:
|
||||||
<itemizedlist>
|
<itemizedlist>
|
||||||
|
<listitem><para> LXC_CGNS_AWARE: indicator whether the container is
|
||||||
|
cgroup namespace aware. </para></listitem>
|
||||||
|
<listitem><para> LXC_CONFIG_FILE: the path to the container
|
||||||
|
configuration file. </para></listitem>
|
||||||
|
<listitem><para> LXC_HOOK_TYPE: the hook type (e.g. 'clone', 'mount',
|
||||||
|
'pre-mount'). Note that the existence of this environment variable is
|
||||||
|
conditional on the value of <option>lxc.hook.version</option>. If it
|
||||||
|
is set to 1 then LXC_HOOK_TYPE will be set.
|
||||||
|
</para></listitem>
|
||||||
|
<listitem><para> LXC_HOOK_SECTION: the section type (e.g. 'lxc',
|
||||||
|
'net'). Note that the existence of this environment variable is
|
||||||
|
conditional on the value of <option>lxc.hook.version</option>. If it
|
||||||
|
is set to 1 then LXC_HOOK_SECTION will be set.
|
||||||
|
</para></listitem>
|
||||||
|
<listitem><para> LXC_HOOK_VERSION: the version of the hooks. This
|
||||||
|
value is identical to the value of the container's
|
||||||
|
<option>lxc.hook.version</option> config item. If it is set to 0 then
|
||||||
|
old-style hooks are used. If it is set to 1 then new-style hooks are
|
||||||
|
used. </para></listitem>
|
||||||
|
<listitem><para> LXC_LOG_LEVEL: the container's log level. </para></listitem>
|
||||||
<listitem><para> LXC_NAME: is the container's name. </para></listitem>
|
<listitem><para> LXC_NAME: is the container's name. </para></listitem>
|
||||||
|
<listitem><para> LXC_[NAMESPACE IDENTIFIER]_NS: path under
|
||||||
|
/proc/PID/fd/ to a file descriptor referring to the container's
|
||||||
|
namespace. For each preserved namespace type there will be a separate
|
||||||
|
environment variable. These environment variables will only be set if
|
||||||
|
<option>lxc.hook.version</option> is set to 1. </para></listitem>
|
||||||
<listitem><para> LXC_ROOTFS_MOUNT: the path to the mounted root filesystem. </para></listitem>
|
<listitem><para> LXC_ROOTFS_MOUNT: the path to the mounted root filesystem. </para></listitem>
|
||||||
<listitem><para> LXC_CONFIG_FILE: the path to the container configuration file. </para></listitem>
|
<listitem><para> LXC_ROOTFS_PATH: this is the lxc.rootfs.path entry
|
||||||
<listitem><para> LXC_SRC_NAME: in the case of the clone hook, this is the original container's name. </para></listitem>
|
for the container. Note this is likely not where the mounted rootfs is
|
||||||
<listitem><para> LXC_ROOTFS_PATH: this is the lxc.rootfs.path entry for the container. Note this is likely not where the mounted rootfs is to be found, use LXC_ROOTFS_MOUNT for that. </para></listitem>
|
to be found, use LXC_ROOTFS_MOUNT for that. </para></listitem>
|
||||||
<listitem><para> LXC_CGNS_AWARE: indicated whether the container is cgroup namespace aware. </para></listitem>
|
<listitem><para> LXC_SRC_NAME: in the case of the clone hook, this is
|
||||||
<listitem><para> LXC_LOG_LEVEL: the container's log level. </para></listitem>
|
the original container's name. </para></listitem>
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
@ -1666,6 +1773,33 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|||||||
Standard error is not logged, but can be captured by the
|
Standard error is not logged, but can be captured by the
|
||||||
hook redirecting its standard error to standard output.
|
hook redirecting its standard error to standard output.
|
||||||
</para>
|
</para>
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term>
|
||||||
|
<option>lxc.hook.version</option>
|
||||||
|
</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
To pass the arguments in new style via environment variables set to
|
||||||
|
1 otherwise set to 0 to pass them as arguments.
|
||||||
|
This setting affects all hooks arguments that were traditionally
|
||||||
|
passed as arguments to the script. Specifically, it affects the
|
||||||
|
container name, section (e.g. 'lxc', 'net') and hook type (e.g.
|
||||||
|
'clone', 'mount', 'pre-mount') arguments. If new-style hooks are
|
||||||
|
used then the arguments will be available as environment variables.
|
||||||
|
The container name will be set in LXC_NAME. (This is set
|
||||||
|
independently of the value used for this config item.) The section
|
||||||
|
will be set in LXC_HOOK_SECTION and the hook type will be set in
|
||||||
|
LXC_HOOK_TYPE.
|
||||||
|
It also affects how the paths to file descriptors referring to the
|
||||||
|
container's namespaces are passed. If set to 1 then for each
|
||||||
|
namespace a separate environment variable LXC_[NAMESPACE
|
||||||
|
IDENTIFIER]_NS will be set. If set to 0 then the paths will be
|
||||||
|
passed as arguments to the stop hook.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
<variablelist>
|
<variablelist>
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term>
|
<term>
|
||||||
|
196
src/lxc/conf.c
196
src/lxc/conf.c
@ -308,84 +308,167 @@ 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,
|
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, char **argsin)
|
||||||
{
|
{
|
||||||
int ret, i;
|
int buf_pos, i, ret;
|
||||||
char *buffer;
|
char *buffer;
|
||||||
size_t size = 0;
|
size_t size = 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;
|
|
||||||
|
|
||||||
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.");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret =
|
if (hook_version == 0) {
|
||||||
snprintf(buffer, size, "exec %s %s %s %s", script, name, section, hook);
|
size += strlen(hookname);
|
||||||
if (ret < 0 || (size_t)ret >= size) {
|
size++;
|
||||||
ERROR("Script name too long.");
|
|
||||||
return -1;
|
size += strlen(name);
|
||||||
|
size++;
|
||||||
|
|
||||||
|
size += strlen(section);
|
||||||
|
size++;
|
||||||
|
|
||||||
|
if (size > INT_MAX)
|
||||||
|
return -EFBIG;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
if (strcmp(section, "net") == 0) {
|
||||||
|
char *parent;
|
||||||
|
|
||||||
|
if (!argsin[0])
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
ret = setenv("LXC_NET_TYPE", argsin[0], 1);
|
||||||
|
if (ret < 0) {
|
||||||
|
SYSERROR("Failed to set environment variable: "
|
||||||
|
"LXC_NET_TYPE=%s", argsin[0]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
TRACE("Set environment variable: LXC_NET_TYPE=%s", argsin[0]);
|
||||||
|
|
||||||
|
parent = argsin[1] ? argsin[1] : "";
|
||||||
|
|
||||||
|
if (strcmp(argsin[0], "macvlan")) {
|
||||||
|
ret = setenv("LXC_NET_PARENT", parent, 1);
|
||||||
|
if (ret < 0) {
|
||||||
|
SYSERROR("Failed to set environment "
|
||||||
|
"variable: LXC_NET_PARENT=%s", parent);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
TRACE("Set environment variable: LXC_NET_PARENT=%s", parent);
|
||||||
|
} else if (strcmp(argsin[0], "phys")) {
|
||||||
|
ret = setenv("LXC_NET_PARENT", parent, 1);
|
||||||
|
if (ret < 0) {
|
||||||
|
SYSERROR("Failed to set environment "
|
||||||
|
"variable: LXC_NET_PARENT=%s", parent);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
TRACE("Set environment variable: LXC_NET_PARENT=%s", parent);
|
||||||
|
} else if (strcmp(argsin[0], "veth")) {
|
||||||
|
char *peer = argsin[2] ? argsin[2] : "";
|
||||||
|
|
||||||
|
ret = setenv("LXC_NET_PEER", peer, 1);
|
||||||
|
if (ret < 0) {
|
||||||
|
SYSERROR("Failed to set environment "
|
||||||
|
"variable: LXC_NET_PEER=%s", peer);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
TRACE("Set environment variable: LXC_NET_PEER=%s", peer);
|
||||||
|
|
||||||
|
ret = setenv("LXC_NET_PARENT", parent, 1);
|
||||||
|
if (ret < 0) {
|
||||||
|
SYSERROR("Failed to set environment "
|
||||||
|
"variable: LXC_NET_PARENT=%s", parent);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
TRACE("Set environment variable: LXC_NET_PARENT=%s", parent);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
@ -2484,6 +2567,7 @@ struct lxc_conf *lxc_conf_init(void)
|
|||||||
lxc_list_init(&new->limits);
|
lxc_list_init(&new->limits);
|
||||||
lxc_list_init(&new->sysctls);
|
lxc_list_init(&new->sysctls);
|
||||||
lxc_list_init(&new->procs);
|
lxc_list_init(&new->procs);
|
||||||
|
new->hooks_version = 0;
|
||||||
for (i = 0; i < NUM_LXC_HOOKS; i++)
|
for (i = 0; i < NUM_LXC_HOOKS; i++)
|
||||||
lxc_list_init(&new->hooks[i]);
|
lxc_list_init(&new->hooks[i]);
|
||||||
lxc_list_init(&new->groups);
|
lxc_list_init(&new->groups);
|
||||||
@ -3068,7 +3152,7 @@ int do_rootfs_setup(struct lxc_conf *conf, const char *name, const char *lxcpath
|
|||||||
|
|
||||||
remount_all_slave();
|
remount_all_slave();
|
||||||
|
|
||||||
if (run_lxc_hooks(name, "pre-mount", conf, lxcpath, NULL)) {
|
if (run_lxc_hooks(name, "pre-mount", conf, NULL)) {
|
||||||
ERROR("failed to run pre-mount hooks for container '%s'.", name);
|
ERROR("failed to run pre-mount hooks for container '%s'.", name);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -3177,13 +3261,13 @@ int lxc_setup(struct lxc_handler *handler)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (run_lxc_hooks(name, "mount", lxc_conf, lxcpath, NULL)) {
|
if (run_lxc_hooks(name, "mount", lxc_conf, NULL)) {
|
||||||
ERROR("failed to run mount hooks for container '%s'.", name);
|
ERROR("failed to run mount hooks for container '%s'.", name);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lxc_conf->autodev > 0) {
|
if (lxc_conf->autodev > 0) {
|
||||||
if (run_lxc_hooks(name, "autodev", lxc_conf, lxcpath, NULL)) {
|
if (run_lxc_hooks(name, "autodev", lxc_conf, NULL)) {
|
||||||
ERROR("failed to run autodev hooks for container '%s'.", name);
|
ERROR("failed to run autodev hooks for container '%s'.", name);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -3260,41 +3344,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[])
|
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, argv);
|
||||||
|
if (ret < 0)
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -295,7 +295,11 @@ struct lxc_conf {
|
|||||||
struct lxc_rootfs rootfs;
|
struct lxc_rootfs rootfs;
|
||||||
char *ttydir;
|
char *ttydir;
|
||||||
int close_all_fds;
|
int close_all_fds;
|
||||||
struct lxc_list hooks[NUM_LXC_HOOKS];
|
|
||||||
|
struct {
|
||||||
|
unsigned int hooks_version;
|
||||||
|
struct lxc_list hooks[NUM_LXC_HOOKS];
|
||||||
|
};
|
||||||
|
|
||||||
char *lsm_aa_profile;
|
char *lsm_aa_profile;
|
||||||
unsigned int lsm_aa_allow_incomplete;
|
unsigned int lsm_aa_allow_incomplete;
|
||||||
@ -408,7 +412,7 @@ extern struct lxc_conf *current_config;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern int run_lxc_hooks(const char *name, char *hook, struct lxc_conf *conf,
|
extern int run_lxc_hooks(const char *name, char *hook, struct lxc_conf *conf,
|
||||||
const char *lxcpath, char *argv[]);
|
char *argv[]);
|
||||||
extern int detect_shared_rootfs(void);
|
extern int detect_shared_rootfs(void);
|
||||||
extern struct lxc_conf *lxc_conf_init(void);
|
extern struct lxc_conf *lxc_conf_init(void);
|
||||||
extern void lxc_conf_free(struct lxc_conf *conf);
|
extern void lxc_conf_free(struct lxc_conf *conf);
|
||||||
@ -453,6 +457,9 @@ extern unsigned long add_required_remount_flags(const char *s, const char *d,
|
|||||||
unsigned long flags);
|
unsigned long flags);
|
||||||
extern int run_script(const char *name, const char *section, const char *script,
|
extern int run_script(const char *name, const char *section, const char *script,
|
||||||
...);
|
...);
|
||||||
|
extern int run_script_argv(const char *name, unsigned int hook_version,
|
||||||
|
const char *section, const char *script,
|
||||||
|
const char *hookname, char **argsin);
|
||||||
extern int in_caplist(int cap, struct lxc_list *caps);
|
extern int in_caplist(int cap, struct lxc_list *caps);
|
||||||
extern int setup_sysctl_parameters(struct lxc_list *sysctls);
|
extern int setup_sysctl_parameters(struct lxc_list *sysctls);
|
||||||
extern int lxc_clear_sysctls(struct lxc_conf *c, const char *key);
|
extern int lxc_clear_sysctls(struct lxc_conf *c, const char *key);
|
||||||
|
@ -92,6 +92,7 @@ lxc_config_define(ephemeral);
|
|||||||
lxc_config_define(execute_cmd);
|
lxc_config_define(execute_cmd);
|
||||||
lxc_config_define(group);
|
lxc_config_define(group);
|
||||||
lxc_config_define(hooks);
|
lxc_config_define(hooks);
|
||||||
|
lxc_config_define(hooks_version);
|
||||||
lxc_config_define(idmaps);
|
lxc_config_define(idmaps);
|
||||||
lxc_config_define(includefiles);
|
lxc_config_define(includefiles);
|
||||||
lxc_config_define(init_cmd);
|
lxc_config_define(init_cmd);
|
||||||
@ -168,11 +169,12 @@ static struct lxc_config_t config[] = {
|
|||||||
{ "lxc.hook.destroy", false, set_config_hooks, get_config_hooks, clr_config_hooks, },
|
{ "lxc.hook.destroy", false, set_config_hooks, get_config_hooks, clr_config_hooks, },
|
||||||
{ "lxc.hook.mount", false, set_config_hooks, get_config_hooks, clr_config_hooks, },
|
{ "lxc.hook.mount", false, set_config_hooks, get_config_hooks, clr_config_hooks, },
|
||||||
{ "lxc.hook.post-stop", false, set_config_hooks, get_config_hooks, clr_config_hooks, },
|
{ "lxc.hook.post-stop", false, set_config_hooks, get_config_hooks, clr_config_hooks, },
|
||||||
{ "lxc.hook.start-host", false, set_config_hooks, get_config_hooks, clr_config_hooks, },
|
|
||||||
{ "lxc.hook.pre-start", false, set_config_hooks, get_config_hooks, clr_config_hooks, },
|
|
||||||
{ "lxc.hook.pre-mount", false, set_config_hooks, get_config_hooks, clr_config_hooks, },
|
{ "lxc.hook.pre-mount", false, set_config_hooks, get_config_hooks, clr_config_hooks, },
|
||||||
|
{ "lxc.hook.pre-start", false, set_config_hooks, get_config_hooks, clr_config_hooks, },
|
||||||
{ "lxc.hook.start", false, set_config_hooks, get_config_hooks, clr_config_hooks, },
|
{ "lxc.hook.start", false, set_config_hooks, get_config_hooks, clr_config_hooks, },
|
||||||
|
{ "lxc.hook.start-host", false, set_config_hooks, get_config_hooks, clr_config_hooks, },
|
||||||
{ "lxc.hook.stop", false, set_config_hooks, get_config_hooks, clr_config_hooks, },
|
{ "lxc.hook.stop", false, set_config_hooks, get_config_hooks, clr_config_hooks, },
|
||||||
|
{ "lxc.hook.version", false, set_config_hooks_version, get_config_hooks_version, clr_config_hooks_version, },
|
||||||
{ "lxc.hook", false, set_config_hooks, get_config_hooks, clr_config_hooks, },
|
{ "lxc.hook", false, set_config_hooks, get_config_hooks, clr_config_hooks, },
|
||||||
{ "lxc.idmap", false, set_config_idmaps, get_config_idmaps, clr_config_idmaps, },
|
{ "lxc.idmap", false, set_config_idmaps, get_config_idmaps, clr_config_idmaps, },
|
||||||
{ "lxc.include", false, set_config_includefiles, get_config_includefiles, clr_config_includefiles, },
|
{ "lxc.include", false, set_config_includefiles, get_config_includefiles, clr_config_includefiles, },
|
||||||
@ -980,6 +982,29 @@ static int set_config_hooks(const char *key, const char *value,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int set_config_hooks_version(const char *key, const char *value,
|
||||||
|
struct lxc_conf *lxc_conf, void *data)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
unsigned int tmp;
|
||||||
|
|
||||||
|
if (lxc_config_value_empty(value))
|
||||||
|
return clr_config_hooks_version(key, lxc_conf, NULL);
|
||||||
|
|
||||||
|
ret = lxc_safe_uint(value, &tmp);
|
||||||
|
if (ret < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (tmp > 1) {
|
||||||
|
ERROR("Invalid hook version specified. Currently only 0 "
|
||||||
|
"(legacy) and 1 are supported");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
lxc_conf->hooks_version = tmp;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int set_config_personality(const char *key, const char *value,
|
static int set_config_personality(const char *key, const char *value,
|
||||||
struct lxc_conf *lxc_conf, void *data)
|
struct lxc_conf *lxc_conf, void *data)
|
||||||
{
|
{
|
||||||
@ -3154,6 +3179,12 @@ static int get_config_hooks(const char *key, char *retv, int inlen,
|
|||||||
return fulllen;
|
return fulllen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int get_config_hooks_version(const char *key, char *retv, int inlen,
|
||||||
|
struct lxc_conf *c, void *data)
|
||||||
|
{
|
||||||
|
return lxc_get_conf_int(c, retv, inlen, c->hooks_version);
|
||||||
|
}
|
||||||
|
|
||||||
static int get_config_net(const char *key, char *retv, int inlen,
|
static int get_config_net(const char *key, char *retv, int inlen,
|
||||||
struct lxc_conf *c, void *data)
|
struct lxc_conf *c, void *data)
|
||||||
{
|
{
|
||||||
@ -3688,6 +3719,14 @@ static inline int clr_config_hooks(const char *key, struct lxc_conf *c,
|
|||||||
return lxc_clear_hooks(c, key);
|
return lxc_clear_hooks(c, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int clr_config_hooks_version(const char *key, struct lxc_conf *c,
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
/* default to legacy hooks version */
|
||||||
|
c->hooks_version = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static inline int clr_config_net(const char *key, struct lxc_conf *c,
|
static inline int clr_config_net(const char *key, struct lxc_conf *c,
|
||||||
void *data)
|
void *data)
|
||||||
{
|
{
|
||||||
|
@ -2746,7 +2746,7 @@ static bool container_destroy(struct lxc_container *c,
|
|||||||
SYSERROR("Failed to set environment variable for console log");
|
SYSERROR("Failed to set environment variable for console log");
|
||||||
/* End of environment variable setup for hooks */
|
/* End of environment variable setup for hooks */
|
||||||
|
|
||||||
if (run_lxc_hooks(c->name, "destroy", conf, c->get_config_path(c), NULL)) {
|
if (run_lxc_hooks(c->name, "destroy", conf, NULL)) {
|
||||||
ERROR("Failed to execute clone hook for \"%s\"", c->name);
|
ERROR("Failed to execute clone hook for \"%s\"", c->name);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@ -3458,7 +3458,7 @@ static int clone_update_rootfs(struct clone_update_data *data)
|
|||||||
SYSERROR("failed to set environment variable for rootfs mount");
|
SYSERROR("failed to set environment variable for rootfs mount");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (run_lxc_hooks(c->name, "clone", conf, c->get_config_path(c), hookargs)) {
|
if (run_lxc_hooks(c->name, "clone", conf, hookargs)) {
|
||||||
ERROR("Error executing clone hook for %s", c->name);
|
ERROR("Error executing clone hook for %s", c->name);
|
||||||
storage_put(bdev);
|
storage_put(bdev);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -87,13 +87,13 @@ pid_t lxc_clone(int (*fn)(void *), void *arg, int flags)
|
|||||||
* linux/fs/namespace.c:mntns_install().
|
* linux/fs/namespace.c:mntns_install().
|
||||||
*/
|
*/
|
||||||
const struct ns_info ns_info[LXC_NS_MAX] = {
|
const struct ns_info ns_info[LXC_NS_MAX] = {
|
||||||
[LXC_NS_USER] = {"user", CLONE_NEWUSER, "CLONE_NEWUSER"},
|
[LXC_NS_USER] = { "user", CLONE_NEWUSER, "CLONE_NEWUSER", "LXC_USER_NS" },
|
||||||
[LXC_NS_MNT] = {"mnt", CLONE_NEWNS, "CLONE_NEWNS"},
|
[LXC_NS_MNT] = { "mnt", CLONE_NEWNS, "CLONE_NEWNS", "LXC_MNT_NS" },
|
||||||
[LXC_NS_PID] = {"pid", CLONE_NEWPID, "CLONE_NEWPID"},
|
[LXC_NS_PID] = { "pid", CLONE_NEWPID, "CLONE_NEWPID", "LXC_PID_NS" },
|
||||||
[LXC_NS_UTS] = {"uts", CLONE_NEWUTS, "CLONE_NEWUTS"},
|
[LXC_NS_UTS] = { "uts", CLONE_NEWUTS, "CLONE_NEWUTS", "LXC_UTS_NS" },
|
||||||
[LXC_NS_IPC] = {"ipc", CLONE_NEWIPC, "CLONE_NEWIPC"},
|
[LXC_NS_IPC] = { "ipc", CLONE_NEWIPC, "CLONE_NEWIPC", "LXC_IPC_NS" },
|
||||||
[LXC_NS_NET] = {"net", CLONE_NEWNET, "CLONE_NEWNET"},
|
[LXC_NS_NET] = { "net", CLONE_NEWNET, "CLONE_NEWNET", "LXC_NET_NS" },
|
||||||
[LXC_NS_CGROUP] = {"cgroup", CLONE_NEWCGROUP, "CLONE_NEWCGROUP"}
|
[LXC_NS_CGROUP] = { "cgroup", CLONE_NEWCGROUP, "CLONE_NEWCGROUP", "LXC_CGROUP_NS" }
|
||||||
};
|
};
|
||||||
|
|
||||||
int lxc_namespace_2_cloneflag(const char *namespace)
|
int lxc_namespace_2_cloneflag(const char *namespace)
|
||||||
|
@ -68,6 +68,7 @@ extern const struct ns_info {
|
|||||||
const char *proc_name;
|
const char *proc_name;
|
||||||
int clone_flag;
|
int clone_flag;
|
||||||
const char *flag_name;
|
const char *flag_name;
|
||||||
|
const char *env_name;
|
||||||
} ns_info[LXC_NS_MAX];
|
} ns_info[LXC_NS_MAX];
|
||||||
|
|
||||||
#if defined(__ia64__)
|
#if defined(__ia64__)
|
||||||
|
@ -204,9 +204,17 @@ static int instantiate_veth(struct lxc_handler *handler, struct lxc_netdev *netd
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (netdev->upscript) {
|
if (netdev->upscript) {
|
||||||
err = run_script(handler->name, "net", netdev->upscript, "up",
|
char *argv[] = {
|
||||||
"veth", veth1, (char*) NULL);
|
"veth",
|
||||||
if (err)
|
netdev->link,
|
||||||
|
veth1,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
err = run_script_argv(handler->name,
|
||||||
|
handler->conf->hooks_version, "net",
|
||||||
|
netdev->upscript, "up", argv);
|
||||||
|
if (err < 0)
|
||||||
goto out_delete;
|
goto out_delete;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -254,9 +262,16 @@ static int instantiate_macvlan(struct lxc_handler *handler, struct lxc_netdev *n
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (netdev->upscript) {
|
if (netdev->upscript) {
|
||||||
err = run_script(handler->name, "net", netdev->upscript, "up",
|
char *argv[] = {
|
||||||
"macvlan", netdev->link, (char*) NULL);
|
"macvlan",
|
||||||
if (err)
|
netdev->link,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
err = run_script_argv(handler->name,
|
||||||
|
handler->conf->hooks_version, "net",
|
||||||
|
netdev->upscript, "up", argv);
|
||||||
|
if (err < 0)
|
||||||
goto on_error;
|
goto on_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -323,6 +338,13 @@ static int instantiate_vlan(struct lxc_handler *handler, struct lxc_netdev *netd
|
|||||||
|
|
||||||
static int instantiate_phys(struct lxc_handler *handler, struct lxc_netdev *netdev)
|
static int instantiate_phys(struct lxc_handler *handler, struct lxc_netdev *netdev)
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
|
char *argv[] = {
|
||||||
|
"phys",
|
||||||
|
netdev->link,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
if (netdev->link[0] == '\0') {
|
if (netdev->link[0] == '\0') {
|
||||||
ERROR("No link for physical interface specified");
|
ERROR("No link for physical interface specified");
|
||||||
return -1;
|
return -1;
|
||||||
@ -346,27 +368,34 @@ static int instantiate_phys(struct lxc_handler *handler, struct lxc_netdev *netd
|
|||||||
*/
|
*/
|
||||||
netdev->priv.phys_attr.ifindex = netdev->ifindex;
|
netdev->priv.phys_attr.ifindex = netdev->ifindex;
|
||||||
|
|
||||||
if (netdev->upscript) {
|
if (!netdev->upscript)
|
||||||
int err;
|
return 0;
|
||||||
err = run_script(handler->name, "net", netdev->upscript,
|
|
||||||
"up", "phys", netdev->link, (char*) NULL);
|
ret = run_script_argv(handler->name, handler->conf->hooks_version,
|
||||||
if (err)
|
"net", netdev->upscript, "up", argv);
|
||||||
return -1;
|
if (ret < 0)
|
||||||
}
|
return -1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int instantiate_empty(struct lxc_handler *handler, struct lxc_netdev *netdev)
|
static int instantiate_empty(struct lxc_handler *handler, struct lxc_netdev *netdev)
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
|
char *argv[] = {
|
||||||
|
"empty",
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
netdev->ifindex = 0;
|
netdev->ifindex = 0;
|
||||||
if (netdev->upscript) {
|
if (!netdev->upscript)
|
||||||
int err;
|
return 0;
|
||||||
err = run_script(handler->name, "net", netdev->upscript,
|
|
||||||
"up", "empty", (char*) NULL);
|
ret = run_script_argv(handler->name, handler->conf->hooks_version,
|
||||||
if (err)
|
"net", netdev->upscript, "up", argv);
|
||||||
return -1;
|
if (ret < 0)
|
||||||
}
|
return -1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -387,34 +416,48 @@ static instantiate_cb netdev_conf[LXC_NET_MAXCONFTYPE + 1] = {
|
|||||||
|
|
||||||
static int shutdown_veth(struct lxc_handler *handler, struct lxc_netdev *netdev)
|
static int shutdown_veth(struct lxc_handler *handler, struct lxc_netdev *netdev)
|
||||||
{
|
{
|
||||||
char *veth1;
|
int ret;
|
||||||
int err;
|
char *argv[] = {
|
||||||
|
"veth",
|
||||||
|
netdev->link,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!netdev->downscript)
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (netdev->priv.veth_attr.pair[0] != '\0')
|
if (netdev->priv.veth_attr.pair[0] != '\0')
|
||||||
veth1 = netdev->priv.veth_attr.pair;
|
argv[2] = netdev->priv.veth_attr.pair;
|
||||||
else
|
else
|
||||||
veth1 = netdev->priv.veth_attr.veth1;
|
argv[2] = netdev->priv.veth_attr.veth1;
|
||||||
|
|
||||||
|
ret = run_script_argv(handler->name,
|
||||||
|
handler->conf->hooks_version, "net",
|
||||||
|
netdev->downscript, "down", argv);
|
||||||
|
if (ret < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
if (netdev->downscript) {
|
|
||||||
err = run_script(handler->name, "net", netdev->downscript,
|
|
||||||
"down", "veth", veth1, (char*) NULL);
|
|
||||||
if (err)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int shutdown_macvlan(struct lxc_handler *handler, struct lxc_netdev *netdev)
|
static int shutdown_macvlan(struct lxc_handler *handler, struct lxc_netdev *netdev)
|
||||||
{
|
{
|
||||||
int err;
|
int ret;
|
||||||
|
char *argv[] = {
|
||||||
|
"macvlan",
|
||||||
|
netdev->link,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!netdev->downscript)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ret = run_script_argv(handler->name, handler->conf->hooks_version,
|
||||||
|
"net", netdev->downscript, "down", argv);
|
||||||
|
if (ret < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
if (netdev->downscript) {
|
|
||||||
err = run_script(handler->name, "net", netdev->downscript,
|
|
||||||
"down", "macvlan", netdev->link,
|
|
||||||
(char*) NULL);
|
|
||||||
if (err)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -425,27 +468,40 @@ static int shutdown_vlan(struct lxc_handler *handler, struct lxc_netdev *netdev)
|
|||||||
|
|
||||||
static int shutdown_phys(struct lxc_handler *handler, struct lxc_netdev *netdev)
|
static int shutdown_phys(struct lxc_handler *handler, struct lxc_netdev *netdev)
|
||||||
{
|
{
|
||||||
int err;
|
int ret;
|
||||||
|
char *argv[] = {
|
||||||
|
"phys",
|
||||||
|
netdev->link,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!netdev->downscript)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ret = run_script_argv(handler->name, handler->conf->hooks_version,
|
||||||
|
"net", netdev->downscript, "down", argv);
|
||||||
|
if (ret < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
if (netdev->downscript) {
|
|
||||||
err = run_script(handler->name, "net", netdev->downscript,
|
|
||||||
"down", "phys", netdev->link, (char*) NULL);
|
|
||||||
if (err)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int shutdown_empty(struct lxc_handler *handler, struct lxc_netdev *netdev)
|
static int shutdown_empty(struct lxc_handler *handler, struct lxc_netdev *netdev)
|
||||||
{
|
{
|
||||||
int err;
|
int ret;
|
||||||
|
char *argv[] = {
|
||||||
|
"empty",
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!netdev->downscript)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ret = run_script_argv(handler->name, handler->conf->hooks_version,
|
||||||
|
"net", netdev->downscript, "down", argv);
|
||||||
|
if (ret < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
if (netdev->downscript) {
|
|
||||||
err = run_script(handler->name, "net", netdev->downscript,
|
|
||||||
"down", "empty", (char*) NULL);
|
|
||||||
if (err)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -612,6 +612,7 @@ on_error:
|
|||||||
|
|
||||||
int lxc_init(const char *name, struct lxc_handler *handler)
|
int lxc_init(const char *name, struct lxc_handler *handler)
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
const char *loglevel;
|
const char *loglevel;
|
||||||
struct lxc_conf *conf = handler->conf;
|
struct lxc_conf *conf = handler->conf;
|
||||||
|
|
||||||
@ -656,11 +657,18 @@ int lxc_init(const char *name, struct lxc_handler *handler)
|
|||||||
loglevel = lxc_log_priority_to_string(lxc_log_get_level());
|
loglevel = lxc_log_priority_to_string(lxc_log_get_level());
|
||||||
if (setenv("LXC_LOG_LEVEL", loglevel, 1))
|
if (setenv("LXC_LOG_LEVEL", loglevel, 1))
|
||||||
SYSERROR("Failed to set environment variable LXC_LOG_LEVEL=%s", loglevel);
|
SYSERROR("Failed to set environment variable LXC_LOG_LEVEL=%s", loglevel);
|
||||||
|
|
||||||
|
if (conf->hooks_version == 0)
|
||||||
|
ret = setenv("LXC_HOOK_VERSION", "0", 1);
|
||||||
|
else
|
||||||
|
ret = setenv("LXC_HOOK_VERSION", "1", 1);
|
||||||
|
if (ret < 0)
|
||||||
|
SYSERROR("Failed to set environment variable LXC_HOOK_VERSION=%u", conf->hooks_version);
|
||||||
/* End of environment variable setup for hooks. */
|
/* End of environment variable setup for hooks. */
|
||||||
|
|
||||||
TRACE("set environment variables");
|
TRACE("set environment variables");
|
||||||
|
|
||||||
if (run_lxc_hooks(name, "pre-start", conf, handler->lxcpath, NULL)) {
|
if (run_lxc_hooks(name, "pre-start", conf, NULL)) {
|
||||||
ERROR("Failed to run lxc.hook.pre-start for container \"%s\".", name);
|
ERROR("Failed to run lxc.hook.pre-start for container \"%s\".", name);
|
||||||
goto out_aborting;
|
goto out_aborting;
|
||||||
}
|
}
|
||||||
@ -708,8 +716,8 @@ out_close_maincmd_fd:
|
|||||||
void lxc_fini(const char *name, struct lxc_handler *handler)
|
void lxc_fini(const char *name, struct lxc_handler *handler)
|
||||||
{
|
{
|
||||||
int i, rc;
|
int i, rc;
|
||||||
|
pid_t self;
|
||||||
struct lxc_list *cur, *next;
|
struct lxc_list *cur, *next;
|
||||||
pid_t self = getpid();
|
|
||||||
char *namespaces[LXC_NS_MAX + 1];
|
char *namespaces[LXC_NS_MAX + 1];
|
||||||
size_t namespace_count = 0;
|
size_t namespace_count = 0;
|
||||||
|
|
||||||
@ -718,16 +726,37 @@ void lxc_fini(const char *name, struct lxc_handler *handler)
|
|||||||
*/
|
*/
|
||||||
lxc_set_state(name, handler, STOPPING);
|
lxc_set_state(name, handler, STOPPING);
|
||||||
|
|
||||||
|
self = getpid();
|
||||||
for (i = 0; i < LXC_NS_MAX; i++) {
|
for (i = 0; i < LXC_NS_MAX; i++) {
|
||||||
if (handler->nsfd[i] != -1) {
|
if (handler->nsfd[i] < 0)
|
||||||
rc = asprintf(&namespaces[namespace_count], "%s:/proc/%d/fd/%d",
|
continue;
|
||||||
ns_info[i].proc_name, self, handler->nsfd[i]);
|
|
||||||
if (rc == -1) {
|
if (handler->conf->hooks_version == 0)
|
||||||
SYSERROR("Failed to allocate memory.");
|
rc = asprintf(&namespaces[namespace_count],
|
||||||
break;
|
"%s:/proc/%d/fd/%d", ns_info[i].proc_name,
|
||||||
}
|
self, handler->nsfd[i]);
|
||||||
++namespace_count;
|
else
|
||||||
|
rc = asprintf(&namespaces[namespace_count],
|
||||||
|
"/proc/%d/fd/%d", self, handler->nsfd[i]);
|
||||||
|
if (rc == -1) {
|
||||||
|
SYSERROR("Failed to allocate memory.");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (handler->conf->hooks_version == 0) {
|
||||||
|
namespace_count++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = setenv(ns_info[i].env_name, namespaces[namespace_count], 1);
|
||||||
|
if (rc < 0)
|
||||||
|
SYSERROR("Failed to set environment variable %s=%s",
|
||||||
|
ns_info[i].env_name, namespaces[namespace_count]);
|
||||||
|
else
|
||||||
|
TRACE("Set environment variable %s=%s",
|
||||||
|
ns_info[i].env_name, namespaces[namespace_count]);
|
||||||
|
|
||||||
|
namespace_count++;
|
||||||
}
|
}
|
||||||
namespaces[namespace_count] = NULL;
|
namespaces[namespace_count] = NULL;
|
||||||
|
|
||||||
@ -737,8 +766,10 @@ void lxc_fini(const char *name, struct lxc_handler *handler)
|
|||||||
if (!handler->conf->reboot && setenv("LXC_TARGET", "stop", 1))
|
if (!handler->conf->reboot && setenv("LXC_TARGET", "stop", 1))
|
||||||
SYSERROR("Failed to set environment variable: LXC_TARGET=stop.");
|
SYSERROR("Failed to set environment variable: LXC_TARGET=stop.");
|
||||||
|
|
||||||
if (run_lxc_hooks(name, "stop", handler->conf, handler->lxcpath, namespaces))
|
if (handler->conf->hooks_version == 0)
|
||||||
ERROR("Failed to run lxc.hook.stop for container \"%s\".", name);
|
rc = run_lxc_hooks(name, "stop", handler->conf, namespaces);
|
||||||
|
else
|
||||||
|
rc = run_lxc_hooks(name, "stop", handler->conf, NULL);
|
||||||
|
|
||||||
while (namespace_count--)
|
while (namespace_count--)
|
||||||
free(namespaces[namespace_count]);
|
free(namespaces[namespace_count]);
|
||||||
@ -761,7 +792,7 @@ void lxc_fini(const char *name, struct lxc_handler *handler)
|
|||||||
handler->conf->maincmd_fd = -1;
|
handler->conf->maincmd_fd = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (run_lxc_hooks(name, "post-stop", handler->conf, handler->lxcpath, NULL)) {
|
if (run_lxc_hooks(name, "post-stop", handler->conf, NULL)) {
|
||||||
ERROR("Failed to run lxc.hook.post-stop for container \"%s\".", name);
|
ERROR("Failed to run lxc.hook.post-stop for container \"%s\".", name);
|
||||||
if (handler->conf->reboot) {
|
if (handler->conf->reboot) {
|
||||||
WARN("Container will be stopped instead of rebooted.");
|
WARN("Container will be stopped instead of rebooted.");
|
||||||
@ -1022,7 +1053,7 @@ static int do_start(void *data)
|
|||||||
if (lxc_seccomp_load(handler->conf) != 0)
|
if (lxc_seccomp_load(handler->conf) != 0)
|
||||||
goto out_warn_father;
|
goto out_warn_father;
|
||||||
|
|
||||||
if (run_lxc_hooks(handler->name, "start", handler->conf, handler->lxcpath, NULL)) {
|
if (run_lxc_hooks(handler->name, "start", handler->conf, NULL)) {
|
||||||
ERROR("Failed to run lxc.hook.start for container \"%s\".", handler->name);
|
ERROR("Failed to run lxc.hook.start for container \"%s\".", handler->name);
|
||||||
goto out_warn_father;
|
goto out_warn_father;
|
||||||
}
|
}
|
||||||
@ -1482,7 +1513,7 @@ static int lxc_spawn(struct lxc_handler *handler)
|
|||||||
SYSERROR("Failed to set environment variable: LXC_PID=%s.", pidstr);
|
SYSERROR("Failed to set environment variable: LXC_PID=%s.", pidstr);
|
||||||
|
|
||||||
/* Run any host-side start hooks */
|
/* Run any host-side start hooks */
|
||||||
if (run_lxc_hooks(name, "start-host", conf, handler->lxcpath, NULL)) {
|
if (run_lxc_hooks(name, "start-host", conf, NULL)) {
|
||||||
ERROR("Failed to run lxc.hook.start-host for container \"%s\".", name);
|
ERROR("Failed to run lxc.hook.start-host for container \"%s\".", name);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -301,16 +301,16 @@ static int set_get_compare_clear_save_load_network(
|
|||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
struct lxc_container *c;
|
struct lxc_container *c;
|
||||||
int fd = -1;
|
int fd = -1, fret = EXIT_FAILURE;
|
||||||
int ret = EXIT_FAILURE;
|
|
||||||
char tmpf[] = "lxc-parse-config-file-XXXXXX";
|
char tmpf[] = "lxc-parse-config-file-XXXXXX";
|
||||||
char retval[4096] = {0};
|
char retval[4096] = {0};
|
||||||
|
|
||||||
fd = mkstemp(tmpf);
|
fd = mkstemp(tmpf);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
lxc_error("%s\n", "Could not create temporary file");
|
lxc_error("%s\n", "Could not create temporary file");
|
||||||
exit(ret);
|
exit(fret);
|
||||||
}
|
}
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
@ -1110,10 +1110,23 @@ int main(int argc, char *argv[])
|
|||||||
goto non_test_error;
|
goto non_test_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = EXIT_SUCCESS;
|
ret = set_get_compare_clear_save_load(c, "lxc.hook.version", "1", tmpf, true);
|
||||||
|
if (ret < 0) {
|
||||||
|
lxc_error("%s\n", "lxc.hook.version");
|
||||||
|
goto non_test_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = set_get_compare_clear_save_load(c, "lxc.hook.version", "2", tmpf, true);
|
||||||
|
if (ret == 0) {
|
||||||
|
lxc_error("%s\n", "lxc.hook.version");
|
||||||
|
goto non_test_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
fret = EXIT_SUCCESS;
|
||||||
|
|
||||||
non_test_error:
|
non_test_error:
|
||||||
(void)unlink(tmpf);
|
(void)unlink(tmpf);
|
||||||
(void)rmdir(dirname(c->configfile));
|
(void)rmdir(dirname(c->configfile));
|
||||||
lxc_container_put(c);
|
lxc_container_put(c);
|
||||||
exit(ret);
|
exit(fret);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user