Commit d082b436 by Daniel Lezcano
parents 72280e1c 91f7ea53
......@@ -47,6 +47,7 @@ src/lxc/lxc-create
src/lxc/lxc-destroy
src/lxc/lxc-execute
src/lxc/lxc-freeze
src/lxc/lxc.functions
src/lxc/lxc-info
src/lxc/lxc-init
src/lxc/lxc-kill
......@@ -91,6 +92,7 @@ config/lt*.m4
doc/*.1
doc/*.5
doc/*.7
doc/legacy/*.1
doc/manpage.links
doc/manpage.refs
......
......@@ -4,7 +4,13 @@ ACLOCAL_AMFLAGS = -I config
SUBDIRS = config src templates doc hooks
DIST_SUBDIRS = config src templates doc hooks
EXTRA_DIST = autogen.sh lxc.spec CONTRIBUTING MAINTAINERS ChangeLog
EXTRA_DIST = \
autogen.sh \
lxc.spec \
CONTRIBUTING \
MAINTAINERS \
runapitests.sh
RPMARGS =
if ENABLE_LUA
......
......@@ -194,7 +194,7 @@ AM_CONDITIONAL([USE_CONFIGPATH_LOGS], [test "$use_configpath_logs" = "yes"])
if test "$use_configpath_logs" = "yes"; then
default_log_path="${with_config_path}"
else
default_log_path="/var/log/lxc"
default_log_path="${localstatedir}/log/lxc"
fi
AC_ARG_WITH([log-path],
......
......@@ -2,8 +2,7 @@ SUBDIRS = examples rootfs
DIST_SUBDIRS = examples rootfs
EXTRA_DIST = \
FAQ.txt \
$(man_MANS)
FAQ.txt
if ENABLE_DOCBOOK
man_MANS = \
......@@ -61,6 +60,6 @@ endif
lxc-%.sgml : common_options.sgml see_also.sgml
maintainer-clean-local:
clean-local:
$(RM) manpage.* *.7 *.5 *.1 $(man_MANS)
endif
EXTRA_DIST = $(pkgexamples_DATA)
if ENABLE_EXAMPLES
pkgexamplesdir=$(docdir)/examples
......
......@@ -54,6 +54,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
<arg choice="opt">-e</arg>
<arg choice="opt">-s <replaceable>namespaces</replaceable></arg>
<arg choice="opt">-R</arg>
<arg choice="opt">--keep-env</arg>
<arg choice="opt">--clear-env</arg>
<arg choice="opt">-- <replaceable>command</replaceable></arg>
</cmdsynopsis>
</refsynopsisdiv>
......@@ -173,6 +175,37 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>--keep-env</option>
</term>
<listitem>
<para>
Keep the current environment for attached programs. This is
the current default behaviour (as of version 0.9), but is
is likely to change in the future, since this may leak
undesirable information into the container. If you rely on
the environment being available for the attached program,
please use this option to be future-proof. In addition to
current environment variables, container=lxc will be set.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>--clear-env</option>
</term>
<listitem>
<para>
Clear the environment before attaching, so no undesired
environment variables leak into the container. The variable
container=lxc will be the only environment with which the
attached program starts.
</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
......
......@@ -96,7 +96,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
provided by the kernel which needs to be active. Depending of
the missing functionalities the <command>lxc</command> will
work with a restricted number of functionalities or will simply
fails.
fail.
</para>
<para>
......
......@@ -4,7 +4,6 @@ luadir=$(datadir)/lua/5.1
sodir=$(libdir)/lua/5.1/lxc
lua_SCRIPTS=lxc.lua
EXTRA_DIST=lxc.lua
so_PROGRAMS = core.so
......@@ -24,3 +23,7 @@ core_so_LDADD = -llxc $(LUA_LIBS)
lxc.lua:
endif
EXTRA_DIST= \
lxc.lua \
test/apitest.lua
......@@ -126,9 +126,12 @@ bin_SCRIPTS = \
lxc-shutdown \
lxc-destroy
EXTRA_DIST=
EXTRA_DIST = \
lxc-device \
lxc-ls \
lxc-top
if ENABLE_PYTHON
EXTRA_DIST += lxc-device lxc-ls
bin_SCRIPTS += lxc-device
bin_SCRIPTS += lxc-ls
bin_SCRIPTS += lxc-start-ephemeral
......@@ -137,7 +140,6 @@ else
endif
if ENABLE_LUA
EXTRA_DIST += lxc-top
bin_SCRIPTS += lxc-top
endif
......
......@@ -277,6 +277,36 @@ int lxc_attach_drop_privs(struct lxc_proc_context_info *ctx)
return 0;
}
int lxc_attach_set_environment(enum lxc_attach_env_policy_t policy, char** extra_env, char** extra_keep)
{
/* TODO: implement extra_env, extra_keep
* Rationale:
* - extra_env is an array of strings of the form
* "VAR=VALUE", which are to be set (after clearing or not,
* depending on the value of the policy variable)
* - extra_keep is an array of strings of the form
* "VAR", which are extra environment variables to be kept
* around after clearing (if that is done, otherwise, the
* remain anyway)
*/
(void) extra_env;
(void) extra_keep;
if (policy == LXC_ATTACH_CLEAR_ENV) {
if (clearenv()) {
SYSERROR("failed to clear environment");
/* don't error out though */
}
}
if (putenv("container=lxc")) {
SYSERROR("failed to set environment variable");
return -1;
}
return 0;
}
char *lxc_attach_getpwshell(uid_t uid)
{
/* local variables */
......
......@@ -34,9 +34,15 @@ struct lxc_proc_context_info {
extern struct lxc_proc_context_info *lxc_proc_get_context_info(pid_t pid);
typedef enum lxc_attach_env_policy_t {
LXC_ATTACH_KEEP_ENV,
LXC_ATTACH_CLEAR_ENV
} lxc_attach_env_policy_t;
extern int lxc_attach_to_ns(pid_t other_pid, int which);
extern int lxc_attach_remount_sys_proc();
extern int lxc_attach_drop_privs(struct lxc_proc_context_info *ctx);
extern int lxc_attach_set_environment(enum lxc_attach_env_policy_t policy, char** extra_env, char** extra_keep);
extern char *lxc_attach_getpwshell(uid_t uid);
......
......@@ -1129,8 +1129,13 @@ static int setup_rootfs(struct lxc_conf *conf)
{
const struct lxc_rootfs *rootfs = &conf->rootfs;
if (!rootfs->path)
if (!rootfs->path) {
if (mount("", "/", NULL, MS_SLAVE|MS_REC, 0)) {
SYSERROR("Failed to make / rslave");
return -1;
}
return 0;
}
if (access(rootfs->mount, F_OK)) {
SYSERROR("failed to access to '%s', check it is present",
......
......@@ -1422,6 +1422,9 @@ int lxc_config_readline(char *buffer, struct lxc_conf *conf)
int lxc_config_read(const char *file, struct lxc_conf *conf)
{
if( access(file, R_OK) == -1 ) {
return -1;
}
/* Catch only the top level config file name in the structure */
if( ! conf->rcfile ) {
conf->rcfile = strdup( file );
......
......@@ -251,6 +251,23 @@ elif which btrfs >/dev/null 2>&1 && btrfs subvolume list $oldroot >/dev/null 2>&
# if oldroot is a btrfs subvolume, assume they want a snapshot
btrfs subvolume snapshot "$oldroot" "$rootfs" 2>&1 || { echo "$(basename $0): btrfs snapshot failed" >&2; false; }
echo "lxc.rootfs = $rootfs" >> "$lxc_path/$lxc_new/config"
elif [ -d $lxc_path/$lxc_orig/delta0 ]; then # this is a quasi-ephemeral container
if [ $container_running = "True" ]; then
echo "$(basename $0): container $lxc_orig is running." >&2
cleanup
fi
rsync -Hax $lxc_path/$lxc_orig/delta0 $lxc_path/$lxc_new/
touch $lxc_path/$lxc_new/configured
cp -f $lxc_path/$lxc_orig/pre-mount $lxc_path/$lxc_new/
sed -i "s@$lxc_path/$lxc_orig@$lxc_path/$lxc_new@g" $lxc_path/$lxc_new/config
sed -i "s@$lxc_path/$lxc_orig@$lxc_path/$lxc_new@g" $lxc_path/$lxc_new/pre-mount
sed -i "s@LXC_NAME=\"$lxc_orig@LXC_NAME=\"$lxc_new@" $lxc_path/$lxc_new/pre-mount
# lxc-start-ephemeral will have updated /etc/hostname and such under the
# delta0, so just mounting the delta should suffice.
mkdir -p $rootfs
mount --bind $lxc_path/$lxc_new/delta0 $rootfs
mounted=1
echo "lxc.rootfs = $rootfs" >> "$lxc_path/$lxc_new/config"
else
if [ $snapshot = "yes" ]; then
echo "$(basename $0): cannot snapshot a directory" >&2
......
......@@ -291,7 +291,7 @@ fi
if [ ! -z "$lxc_template" ]; then
# Allow for a path to be provided as the template name
if [ -x "$lxc_template" ]; then
if [ -x "$lxc_template" -a $(echo "$lxc_template" | cut -c 1) = '/' ]; then
template_path=$lxc_template
else
template_path=${templatedir}/lxc-$lxc_template
......
......@@ -28,6 +28,7 @@ usage() {
}
alarm() {
trap 'exit 0' TERM
pid=$1
timeout=$2
sleep $timeout
......@@ -130,7 +131,7 @@ fi
if [ $timeout != "-1" ]; then
trap dolxcstop EXIT
alarm $$ $timeout &
alarm $$ $timeout 2>/dev/null &
alarmpid=$!
fi
......@@ -139,7 +140,10 @@ while ! lxc-info -n $lxc_name --state-is STOPPED; do
done
if [ $timeout != "-1" ]; then
kill $alarmpid
trap - EXIT
# include subprocesses; otherwise, we may have to wait until sleep completes
# if called from a non-interactive context
kill $alarmpid $(ps --no-headers --ppid $alarmpid -o pid) 2>/dev/null || :
fi
echo "Container $lxc_name has shut down"
......
......@@ -70,6 +70,9 @@ parser.add_argument("--lxcpath", "-P", dest="lxcpath", metavar="PATH",
parser.add_argument("--orig", "-o", type=str, required=True,
help=_("name of the original container"))
parser.add_argument("--name", "-n", type=str,
help=_("name of the target container"))
parser.add_argument("--bdir", "-b", type=str,
help=_("directory to bind mount into container"))
......@@ -117,7 +120,13 @@ if not args.lxcpath:
else:
lxc_path = args.lxcpath
dest_path = tempfile.mkdtemp(prefix="%s-" % args.orig, dir=lxc_path)
if args.name:
if os.path.exists("%s/%s" % (lxc_path, args.name)):
parser.error(_("A container named '%s' already exists." % args.name))
dest_path = "%s/%s" % (lxc_path, args.name)
os.mkdir(dest_path)
else:
dest_path = tempfile.mkdtemp(prefix="%s-" % args.orig, dir=lxc_path)
os.mkdir(os.path.join(dest_path, "rootfs"))
# Setup the new container's configuration
......
......@@ -26,8 +26,12 @@ templatedir=@LXCTEMPLATEDIR@
lxcinitdir=@LXCINITDIR@
get_default_lxcpath() {
(grep -v "^#" "$globalconf" 2>/dev/null || echo "lxcpath=@LXCPATH@") | \
grep "[ \t]*lxcpath[ \t]*=" | awk -F= '{ print $2 }'
LXC_PATH=$(grep -v "^#" "$globalconf" 2>/dev/null | grep "[ \t]*lxcpath[ \t]*=")
if [ -n "$LXC_PATH" ]; then
echo $LXC_PATH | awk -F= '{ print $2 }'
else
echo @LXCPATH@
fi
}
lxc_path=`get_default_lxcpath`
......@@ -55,6 +55,9 @@ static const struct option my_longopts[] = {
{"arch", required_argument, 0, 'a'},
{"namespaces", required_argument, 0, 's'},
{"remount-sys-proc", no_argument, 0, 'R'},
/* TODO: decide upon short option names */
{"clear-env", no_argument, 0, 500},
{"keep-env", no_argument, 0, 501},
LXC_COMMON_OPTIONS
};
......@@ -62,6 +65,7 @@ static int elevated_privileges = 0;
static signed long new_personality = -1;
static int namespace_flags = -1;
static int remount_sys_proc = 0;
static lxc_attach_env_policy_t env_policy = LXC_ATTACH_KEEP_ENV;
static int my_parser(struct lxc_arguments* args, int c, char* arg)
{
......@@ -85,6 +89,12 @@ static int my_parser(struct lxc_arguments* args, int c, char* arg)
/* -s implies -e */
elevated_privileges = 1;
break;
case 500: /* clear-env */
env_policy = LXC_ATTACH_CLEAR_ENV;
break;
case 501: /* keep-env */
env_policy = LXC_ATTACH_KEEP_ENV;
break;
}
return 0;
......@@ -116,7 +126,15 @@ Options :\n\
Remount /sys and /proc if not attaching to the\n\
mount namespace when using -s in order to properly\n\
reflect the correct namespace context. See the\n\
lxc-attach(1) manual page for details.\n",
lxc-attach(1) manual page for details.\n\
--clear-env\n\
Clear all environment variables before attaching.\n\
The attached shell/program will start with only\n\
container=lxc set.\n\
--keep-env\n\
Keep all current enivornment variables. This\n\
is the current default behaviour, but is likely to\n\
change in the future.\n",
.options = my_longopts,
.parser = my_parser,
.checker = NULL,
......@@ -411,6 +429,11 @@ int main(int argc, char *argv[])
return -1;
}
if (lxc_attach_set_environment(env_policy, NULL, NULL)) {
ERROR("could not set environment");
return -1;
}
/* tell parent we are done setting up the container and wait
* until we have been put in the container's cgroup, if
* applicable */
......
......@@ -523,14 +523,15 @@ static bool lxcapi_create(struct lxc_container *c, char *t, char *const argv[])
goto out;
}
if (!create_container_dir(c))
goto out;
if (!c->save_config(c, NULL)) {
ERROR("failed to save starting configuration for %s\n", c->name);
goto out;
}
/* container is already created if we have a config and rootfs.path is accessible */
if (lxcapi_is_defined(c) && c->lxc_conf && c->lxc_conf->rootfs.path && access(c->lxc_conf->rootfs.path, F_OK) == 0)
return false;
/* we're going to fork. but since we'll wait for our child, we
don't need to lxc_container_get */
......@@ -767,6 +768,9 @@ static bool lxcapi_save_config(struct lxc_container *c, const char *alt_file)
return false;
}
if (!create_container_dir(c))
return false;
FILE *fout = fopen(alt_file, "w");
if (!fout)
return false;
......@@ -788,6 +792,10 @@ static bool lxcapi_destroy(struct lxc_container *c)
if (!c)
return false;
/* container is already destroyed if we don't have a config and rootfs.path is not accessible */
if (!lxcapi_is_defined(c) && (!c->lxc_conf || !c->lxc_conf->rootfs.path || access(c->lxc_conf->rootfs.path, F_OK) != 0))
return false;
pid = fork();
if (pid < 0)
return false;
......
......@@ -49,7 +49,11 @@
#ifndef CLONE_NEWNET
# define CLONE_NEWNET 0x40000000
#endif
#ifdef IS_BIONIC
#if defined(__ia64__)
int __clone2(int (*__fn) (void *__arg), void *__child_stack_base,
size_t __child_stack_size, int __flags, void *__arg, ...);
#elif defined(IS_BIONIC)
int clone(int (*fn)(void *), void *child_stack,
int flags, void *arg);
#else
......
......@@ -564,7 +564,7 @@ static int must_drop_cap_sys_boot(void)
FILE *f = fopen("/proc/sys/kernel/ctrl-alt-del", "r");
int ret, cmd, v;
long stack_size = 4096;
void *stack = alloca(stack_size) + stack_size;
void *stack = alloca(stack_size);
int status;
pid_t pid;
......@@ -581,7 +581,12 @@ static int must_drop_cap_sys_boot(void)
}
cmd = v ? LINUX_REBOOT_CMD_CAD_ON : LINUX_REBOOT_CMD_CAD_OFF;
#ifdef __ia64__
pid = __clone2(container_reboot_supported, stack, stack_size, CLONE_NEWPID | SIGCHLD, &cmd);
#else
stack += stack_size;
pid = clone(container_reboot_supported, stack, CLONE_NEWPID | SIGCHLD, &cmd);
#endif
if (pid < 0) {
SYSERROR("failed to clone\n");
return -1;
......@@ -785,7 +790,7 @@ int lxc_spawn(struct lxc_handler *handler)
handler->pinfd = pin_rootfs(handler->conf->rootfs.path);
if (handler->pinfd == -1) {
ERROR("failed to pin the container's rootfs");
goto out_abort;
goto out_delete_net;
}
/* Create a process in a new set of namespaces */
......
if ENABLE_PYTHON
EXTRA_DIST = setup.py lxc.c
if HAVE_DEBIAN
DISTSETUPOPTS=--install-layout=deb
else
......@@ -18,7 +16,12 @@ install:
$(PYTHON) setup.py install --root=$(DESTDIR) --prefix=$(prefix) --no-compile $(DISTSETUPOPTS); \
fi
clean:
clean-local:
rm -rf build
endif
EXTRA_DIST = \
setup.py \
lxc.c \
lxc/__init__.py \
examples/api_test.py
......@@ -96,13 +96,13 @@ Container_init(Container *self, PyObject *args, PyObject *kwds)
}
static PyObject *
get_default_config_path(Container *self, PyObject *args, PyObject *kwds)
LXC_get_default_config_path(PyObject *self, PyObject *args)
{
return PyUnicode_FromString(lxc_get_default_config_path());
}
static PyObject *
get_version(Container *self, PyObject *args, PyObject *kwds)
LXC_get_version(PyObject *self, PyObject *args)
{
return PyUnicode_FromString(lxc_get_version());
}
......@@ -496,6 +496,7 @@ static PyGetSetDef Container_getseters[] = {
(getter)Container_state, 0,
"Container state",
NULL},
{NULL, NULL, NULL, NULL, NULL}
};
static PyMethodDef Container_methods[] = {
......@@ -595,7 +596,7 @@ static PyMethodDef Container_methods[] = {
"\n"
"Wait for the container to reach a given state or timeout."
},
{NULL} /* Sentinel */
{NULL, NULL, 0, NULL}
};
static PyTypeObject _lxc_ContainerType = {
......@@ -641,9 +642,9 @@ PyVarObject_HEAD_INIT(NULL, 0)
};
static PyMethodDef LXC_methods[] = {
{"get_default_config_path", (PyCFunction)get_default_config_path, METH_NOARGS,
{"get_default_config_path", (PyCFunction)LXC_get_default_config_path, METH_NOARGS,
"Returns the current LXC config path"},
{"get_version", (PyCFunction)get_version, METH_NOARGS,
{"get_version", (PyCFunction)LXC_get_version, METH_NOARGS,
"Returns the current LXC library version"},
{NULL, NULL, 0, NULL}
};
......
......@@ -166,7 +166,7 @@ else
# precise and later; and are not supported by the query, so we don't actually
# support them yet (see check later on). When Query2 is available,
# we'll use that to enable arm images.
arch="armel"
arch="armhf"
fi
fi
......@@ -206,13 +206,29 @@ if [ "$arch" == "i686" ]; then
arch=i386
fi
if [ $hostarch = "i386" -a $arch = "amd64" ]; then
echo "can't create amd64 container on i386"
if [ $arch != "i386" -a $arch != "amd64" -a $arch != "armhf" -a $arch != "armel" ]; then
echo "Only i386, amd64, armel and armhf are supported by the ubuntu cloud template."
exit 1
fi
if [ $arch != "i386" -a $arch != "amd64" ]; then
echo "Only i386 and amd64 are supported by the ubuntu cloud template."
if [ $hostarch != "i386" -a $hostarch != "amd64" -a $hostarch != "armhf" -a $hostarch != "armel" ]; then
echo "Only i386, amd64, armel and armhf are supported as host."
exit 1
fi
if [ $hostarch = "amd64" -a $arch != "amd64" -a $arch != "i386" ]; then
echo "can't create $arch container on $hostarch"
exit 1
fi
if [ $hostarch = "i386" -a $arch != "i386" ]; then
echo "can't create $arch container on $hostarch"
exit 1
fi
if [ $hostarch = "armhf" -o $hostarch = "armel" ] && \
[ $arch != "armhf" -a $arch != "armel" ]; then
echo "can't create $arch container on $hostarch"
exit 1
fi
......
......@@ -617,7 +617,7 @@ else
elif [ "$arch" = "x86_64" ]; then
arch="amd64"
elif [ "$arch" = "armv7l" ]; then
arch="armel"
arch="armhf"
fi
fi
......@@ -661,7 +661,18 @@ if [ "$arch" == "i686" ]; then
fi
if [ $hostarch = "i386" -a $arch = "amd64" ]; then
echo "can't create amd64 container on i386"
echo "can't create $arch container on $hostarch"
exit 1
fi
if [ $hostarch = "armhf" -o $hostarch = "armel" ] && \
[ $arch != "armhf" -a $arch != "armel" ]; then
echo "can't create $arch container on $hostarch"
exit 1
fi
if [ $hostarch = "powerpc" -a $arch != "powerpc" ]; then
echo "can't create $arch container on $hostarch"
exit 1
fi
......
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