AM_CONDITIONAL([ENABLE_TESTS], [test "x$enable_tests" = "xyes"])
# LXC container path, where the containers are actually stored
+# This is overriden by an entry in the file called LXCCONF
+# (i.e. /etc/lxc/lxc.conf)
AC_ARG_WITH([config-path],
[AC_HELP_STRING(
[--with-config-path=dir],
[lxc configuration repository path]
)], [], [with_config_path=['${localstatedir}/lib/lxc']])
+# The path of the global lxc configuration file.
+AC_ARG_WITH([global-conf],
+ [AC_HELP_STRING(
+ [--with-global-conf=dir],
+ [global lxc configuration file]
+ )], [], [with_global_conf=['${sysconfdir}/lxc/lxc.conf']])
+
# Rootfs path, where the container mount structure is assembled
AC_ARG_WITH([rootfs-path],
[AC_HELP_STRING(
AS_AC_EXPAND(LXC_DEFAULT_CONF, "$defaultconf")
AS_AC_EXPAND(LXC_GENERATE_DATE, "$(date)")
AS_AC_EXPAND(LXCPATH, "$with_config_path")
+AS_AC_EXPAND(LXC_GLOBAL_CONF, "$with_global_conf")
AS_AC_EXPAND(LXCROOTFSMOUNT, "$with_rootfs_path")
AS_AC_EXPAND(LXCTEMPLATEDIR, "$datadir/lxc/templates")
AS_AC_EXPAND(LXCINITDIR, "$libexecdir")
src/lxc/lxc-start-ephemeral
src/lxc/lxc-destroy
src/lxc/legacy/lxc-ls
+ src/lxc/lxc.functions
src/python-lxc/Makefile
src/python-lxc/lxc/__init__.py
}
static int lxc_path_get(lua_State *L) {
- lua_pushstring(L, LXCPATH);
+ struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME);
+ const char *lxcpath;
+
+ lxcpath = c->get_config_path(c);
+ lua_pushstring(L, lxcpath);
return 1;
}
AM_CFLAGS=-I$(top_srcdir)/src \
-DLXCROOTFSMOUNT=\"$(LXCROOTFSMOUNT)\" \
-DLXCPATH=\"$(LXCPATH)\" \
+ -DLXC_GLOBAL_CONF=\"$(LXC_GLOBAL_CONF)\" \
-DLXCINITDIR=\"$(LXCINITDIR)\" \
-DLXCTEMPLATEDIR=\"$(LXCTEMPLATEDIR)\" \
-DLOGPATH=\"$(LOGPATH)\"
pkglibexec_PROGRAMS = \
lxc-init
+#pkglibexec_SCRIPTS = \
+# lxc.functions
+
AM_LDFLAGS = -Wl,-E
if ENABLE_RPATH
AM_LDFLAGS += -Wl,-rpath -Wl,$(libdir)
lxc_kill_SOURCES = lxc_kill.c
install-exec-local: install-soPROGRAMS
+ mkdir -p $(DESTDIR)$(datadir)/lxc
+ install -c -m 644 lxc.functions $(DESTDIR)$(datadir)/lxc
mv $(DESTDIR)$(libdir)/liblxc.so $(DESTDIR)$(libdir)/liblxc.so.$(VERSION)
/sbin/ldconfig -l $(DESTDIR)$(libdir)/liblxc.so.$(VERSION)
cd $(DESTDIR)$(libdir); \
#include <sys/un.h>
#include <sys/poll.h>
#include <sys/param.h>
+#include <malloc.h>
+#include <stdlib.h>
#include <lxc/log.h>
#include <lxc/conf.h>
#include <lxc/start.h> /* for struct lxc_handler */
+#include <lxc/utils.h>
#include "commands.h"
#include "mainloop.h"
lxc_log_define(lxc_commands, lxc);
-#define abstractname LXCPATH "/%s/command"
+static int fill_sock_name(char *path, int len, const char *name) {
+ char *lxcpath = default_lxc_path();
+ int ret;
+ if (!lxcpath) {
+ ERROR("Out of memory getting lxcpath");
+ return -1;
+ }
+ ret = snprintf(path, len, "%s/%s/command", lxcpath, name);
+ if (ret < 0 || ret >= len) {
+ ERROR("Name too long");
+ return -1;
+ }
+ return 0;
+}
static int receive_answer(int sock, struct lxc_answer *answer)
{
int sock, ret = -1;
char path[sizeof(((struct sockaddr_un *)0)->sun_path)] = { 0 };
char *offset = &path[1];
- int rc, len;
+ int len;
len = sizeof(path)-1;
- rc = snprintf(offset, len, abstractname, name);
- if (rc < 0 || rc >= len) {
- ERROR("Name too long");
+ if (fill_sock_name(offset, len, name))
return -1;
- }
sock = lxc_af_unix_connect(path);
if (sock < 0 && errno == ECONNREFUSED) {
int fd;
char path[sizeof(((struct sockaddr_un *)0)->sun_path)] = { 0 };
char *offset = &path[1];
- int rc, len;
+ int len;
len = sizeof(path)-1;
- rc = snprintf(offset, len, abstractname, name);
- if (rc < 0 || rc >= len) {
- ERROR("Name too long");
+ if (fill_sock_name(offset, len, name))
return -1;
- }
fd = lxc_af_unix_open(path, SOCK_STREAM, 0);
if (fd < 0) {
unsigned long mntflags;
char *mntdata;
int r, ret = 0, offset;
+ char *lxcpath;
if (parse_mntopts(mntent->mnt_opts, &mntflags, &mntdata) < 0) {
ERROR("failed to parse mount option '%s'", mntent->mnt_opts);
return -1;
}
+ lxcpath = default_lxc_path();
+ if (!lxcpath) {
+ ERROR("Out of memory");
+ return -1;
+ }
+
/* if rootfs->path is a blockdev path, allow container fstab to
- * use $LXCPATH/CN/rootfs as the target prefix */
- r = snprintf(path, MAXPATHLEN, LXCPATH "/%s/rootfs", lxc_name);
+ * use $lxcpath/CN/rootfs as the target prefix */
+ r = snprintf(path, MAXPATHLEN, "%s/%s/rootfs", lxcpath, lxc_name);
+ free(lxcpath);
if (r < 0 || r >= MAXPATHLEN)
goto skipvarlib;
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-lxc_path=@LXCPATH@
+. @DATADIR@/lxc/lxc.functions
usage()
{
[ -n "$2" ] || usage_err "option $1 requires an argument"
}
-lxc_path=@LXCPATH@
-bindir=@BINDIR@
+. @DATADIR@/lxc/lxc.functions
snapshot=no
lxc_defsize=2G
lxc_size=_unset
fi
}
-lxc_path=@LXCPATH@
-bindir=@BINDIR@
-templatedir=@LXCTEMPLATEDIR@
+. @DATADIR@/lxc/lxc.functions
backingstore=_unset
fstype=ext4
fssize=500M
fi
}
-lxc_path=@LXCPATH@
+. @DATADIR@/lxc/lxc.functions
force=0
while [ $# -gt 0 ]; do
# When the capabilities are set, a non root user can manage the containers.
#
+. @DATADIR@/lxc/lxc.functions
+
LXC_ATTACH_CAPS="cap_sys_admin,cap_dac_override"
LXC_CREATE_CAPS="cap_sys_admin"
LXC_NETSTAT_CAPS="cap_sys_admin"
setcap $LXC_CHECKPOINT_CAPS=ep @BINDIR@/lxc-checkpoint
setcap $LXC_INIT_CAPS=ep @LXCINITDIR@/lxc/lxc-init
- test -e @LXCPATH@ || mkdir -p @LXCPATH@
- chmod 0777 @LXCPATH@
+ test -e $lxc_path || mkdir -p $lxc_path
+ chmod 0777 $lxc_path
}
lxc_dropcaps()
{
- setcap -r @BINDIR@/lxc-attach
- setcap -r @BINDIR@/lxc-create
- setcap -r @BINDIR@/lxc-execute
- setcap -r @BINDIR@/lxc-start
- setcap -r @BINDIR@/lxc-restart
- setcap -r @BINDIR@/lxc-unshare
- setcap -r @BINDIR@/lxc-netstat
- setcap -r @BINDIR@/lxc-checkpoint
- setcap -r @LXCINITDIR@/lxc/lxc-init
-
- chmod 0755 @LXCPATH@
+ setcap -r $bindir/lxc-attach
+ setcap -r $bindir/lxc-create
+ setcap -r $bindir/lxc-execute
+ setcap -r $bindir/lxc-start
+ setcap -r $bindir/lxc-restart
+ setcap -r $bindir/lxc-unshare
+ setcap -r $bindir/lxc-netstat
+ setcap -r $bindir/lxc-checkpoint
+ setcap -r $lxcinitdir/lxc/lxc-init
+
+ chmod 0755 $lxc_path
}
usage_err() {
# When the capabilities are set, a non root user can manage the containers.
#
+. @DATADIR@/lxc/lxc.functions
+
usage() {
echo "usage: $(basename $0) [-d]" >&2
}
lxc_setuid()
{
- setuid @BINDIR@/lxc-attach
- setuid @BINDIR@/lxc-create
- setuid @BINDIR@/lxc-execute
- setuid @BINDIR@/lxc-start
- setuid @BINDIR@/lxc-restart
- setuid @BINDIR@/lxc-unshare
- setuid @BINDIR@/lxc-netstat
- setuid @BINDIR@/lxc-checkpoint
- setuid @LXCINITDIR@/lxc-init
-
- test -e @LXCPATH@ || mkdir -p @LXCPATH@
- chmod 0777 @LXCPATH@
+ setuid $bindir/lxc-attach
+ setuid $bindir/lxc-create
+ setuid $bindir/lxc-execute
+ setuid $bindir/lxc-start
+ setuid $bindir/lxc-restart
+ setuid $bindir/lxc-unshare
+ setuid $bindir/lxc-netstat
+ setuid $bindir/lxc-checkpoint
+ setuid $lxcinitdir/lxc-init
+
+ test -e $lxc_path || mkdir -p $lxc_path
+ chmod 0777 $lxc_path
}
lxc_dropuid()
{
- setuid -r @BINDIR@/lxc-attach
- setuid -r @BINDIR@/lxc-create
- setuid -r @BINDIR@/lxc-execute
- setuid -r @BINDIR@/lxc-start
- setuid -r @BINDIR@/lxc-restart
- setuid -r @BINDIR@/lxc-unshare
- setuid -r @BINDIR@/lxc-netstat
- setuid -r @BINDIR@/lxc-checkpoint
- setuid -r @LXCINITDIR@/lxc-init
-
- chmod 0755 @LXCPATH@
+ setuid -r $bindir/lxc-attach
+ setuid -r $bindir/lxc-create
+ setuid -r $bindir/lxc-execute
+ setuid -r $bindir/lxc-start
+ setuid -r $bindir/lxc-restart
+ setuid -r $bindir/lxc-unshare
+ setuid -r $bindir/lxc-netstat
+ setuid -r $bindir/lxc-checkpoint
+ setuid -r $lxcinitdir/lxc-init
+
+ chmod 0755 $lxc_path
}
usage_err() {
--- /dev/null
+#!/bin/sh
+
+#
+# lxc: linux Container library
+
+# Authors:
+# Serge Hallyn <serge.hallyn@ubuntu.com>
+
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+# This file contains helpers for the various lxc shell scripts
+
+globalconf=@LXC_GLOBAL_CONF@
+bindir=@BINDIR@
+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=`get_default_lxcpath`
#include "arguments.h"
#include "config.h"
#include "start.h"
+#include "utils.h"
lxc_log_define(lxc_execute_ui, lxc_execute);
rcfile = (char *)my_args.rcfile;
else {
int rc;
+ char *lxcpath = default_lxc_path();
+ if (!lxcpath) {
+ ERROR("Out of memory");
+ return -1;
+ }
- rc = asprintf(&rcfile, LXCPATH "/%s/config", my_args.name);
+ rc = asprintf(&rcfile, "%s/%s/config", lxcpath, my_args.name);
+ free(lxcpath);
if (rc == -1) {
SYSERROR("failed to allocate memory");
return -1;
#include "config.h"
#include "confile.h"
#include "arguments.h"
+#include "utils.h"
lxc_log_define(lxc_restart_ui, lxc_restart);
rcfile = (char *)my_args.rcfile;
else {
int rc;
+ char *lxcpath = default_lxc_path();
+ if (!lxcpath) {
+ ERROR("Out of memory");
+ return -1;
+ }
- rc = asprintf(&rcfile, LXCPATH "/%s/config", my_args.name);
+ rc = asprintf(&rcfile, "%s/%s/config", lxcpath, my_args.name);
+ free(lxcpath);
if (rc == -1) {
SYSERROR("failed to allocate memory");
return -1;
rcfile = (char *)my_args.rcfile;
else {
int rc;
+ char *lxcpath = default_lxc_path();
+ if (!lxcpath) {
+ ERROR("Out of memory");
+ return -1;
+ }
- rc = asprintf(&rcfile, LXCPATH "/%s/config", my_args.name);
+ rc = asprintf(&rcfile, "%s/%s/config", lxcpath, my_args.name);
+ INFO("using rcfile %s", rcfile);
+ free(lxcpath);
if (rc == -1) {
SYSERROR("failed to allocate memory");
return err;
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
+#include <lxc/utils.h>
lxc_log_define(lxc_container, lxc);
lxc_conf_free(c->lxc_conf);
c->lxc_conf = NULL;
}
+ if (c->config_path) {
+ free(c->config_path);
+ c->config_path = NULL;
+ }
free(c);
}
char *s;
int len, ret;
- len = strlen(LXCPATH) + strlen(c->name) + 2;
+ len = strlen(c->config_path) + strlen(c->name) + 2;
s = malloc(len);
if (!s)
return false;
- ret = snprintf(s, len, "%s/%s", LXCPATH, c->name);
+ ret = snprintf(s, len, "%s/%s", c->config_path, c->name);
if (ret < 0 || ret >= len) {
free(s);
return false;
exit(1);
newargv[0] = t;
- len = strlen(LXCPATH) + strlen(c->name) + strlen("--path=") + 2;
+ len = strlen(c->config_path) + strlen(c->name) + strlen("--path=") + 2;
patharg = malloc(len);
if (!patharg)
exit(1);
- ret = snprintf(patharg, len, "--path=%s/%s", LXCPATH, c->name);
+ ret = snprintf(patharg, len, "--path=%s/%s", c->config_path, c->name);
if (ret < 0 || ret >= len)
exit(1);
newargv[1] = patharg;
return strdup(c->configfile);
}
+static const char *lxcapi_get_config_path(struct lxc_container *c)
+{
+ if (!c || !c->config_path)
+ return NULL;
+ return (const char *)(c->config_path);
+}
+
+static bool lxcapi_set_config_path(struct lxc_container *c, const char *path)
+{
+ char *p;
+ bool b = false;
+
+ if (!c)
+ return b;
+
+ if (lxclock(c->privlock, 0))
+ return b;
+
+ p = strdup(path);
+ if (!p)
+ goto err;
+ b = true;
+ if (c->config_path)
+ free(c->config_path);
+ c->config_path = p;
+err:
+ lxcunlock(c->privlock);
+ return b;
+}
+
+
static bool lxcapi_set_cgroup_item(struct lxc_container *c, const char *subsys, const char *value)
{
int ret;
}
memset(c, 0, sizeof(*c));
+ c->config_path = default_lxc_path();
+ if (!c->config_path) {
+ fprintf(stderr, "Out of memory");
+ goto err;
+ }
+
c->name = malloc(strlen(name)+1);
if (!c->name) {
fprintf(stderr, "Error allocating lxc_container name\n");
goto err;
}
- len = strlen(LXCPATH)+strlen(c->name)+strlen("/config")+2;
+ len = strlen(c->config_path)+strlen(c->name)+strlen("/config")+2;
c->configfile = malloc(len);
if (!c->configfile) {
fprintf(stderr, "Error allocating config file pathname\n");
goto err;
}
- ret = snprintf(c->configfile, len, "%s/%s/config", LXCPATH, c->name);
+ ret = snprintf(c->configfile, len, "%s/%s/config", c->config_path, c->name);
if (ret < 0 || ret >= len) {
fprintf(stderr, "Error printing out config file name\n");
goto err;
c->get_config_item = lxcapi_get_config_item;
c->get_cgroup_item = lxcapi_get_cgroup_item;
c->set_cgroup_item = lxcapi_set_cgroup_item;
+ c->get_config_path = lxcapi_get_config_path;
+ c->set_config_path = lxcapi_set_config_path;
/* we'll allow the caller to update these later */
if (lxc_log_init(NULL, "none", NULL, "lxc_container", 0)) {
goto err;
}
- /*
- * default configuration file is $LXCPATH/$NAME/config
- */
-
return c;
err:
int error_num;
int daemonize;
+ char *config_path;
+
bool (*is_defined)(struct lxc_container *c); // did /var/lib/lxc/$name/config exist
const char *(*state)(struct lxc_container *c);
bool (*is_running)(struct lxc_container *c); // true so long as defined and not stopped
int (*get_cgroup_item)(struct lxc_container *c, const char *subsys, char *retv, int inlen);
bool (*set_cgroup_item)(struct lxc_container *c, const char *subsys, const char *value);
+ /*
+ * Each container can have a custom configuration path. However
+ * by default it will be set to either the LXCPATH configure
+ * variable, or the lxcpath value in the LXC_GLOBAL_CONF configuration
+ * file (i.e. /etc/lxc/lxc.conf).
+ * You can change the value for a specific container with
+ * set_config_path(). Note there is no other way to specify this in
+ * general at the moment.
+ */
+ const char *(*get_config_path)(struct lxc_container *c);
+ bool (*set_config_path)(struct lxc_container *c, const char *path);
+
#if 0
bool (*commit_cgroups)(struct lxc_container *c);
bool (*reread_cgroups)(struct lxc_container *c);
return 0;
}
+
+static char *copypath(char *p)
+{
+ int len = strlen(p);
+ char *retbuf;
+
+ if (len < 1)
+ return NULL;
+ if (p[len-1] == '\n') {
+ p[len-1] = '\0';
+ len--;
+ }
+ retbuf = malloc(len+1);
+ if (!retbuf)
+ return NULL;
+ strcpy(retbuf, p);
+ return retbuf;
+}
+
+char *default_lxc_path(void)
+{
+ char buf[1024], *p, *retbuf;
+ FILE *fin;
+
+ fin = fopen(LXC_GLOBAL_CONF, "r");
+ if (fin) {
+ while (fgets(buf, 1024, fin)) {
+ if (buf[0] == '#')
+ continue;
+ p = strstr(buf, "lxcpath");
+ if (!p)
+ continue;
+ p = strchr(p, '=');
+ if (!p)
+ continue;
+ p++;
+ while (*p && (*p == ' ' || *p == '\t')) p++;
+ if (!*p)
+ continue;
+ retbuf = copypath(p);
+ goto out;
+ }
+ }
+ /* we couldn't open the file, or didn't find a lxcpath
+ * entry there. Return @LXCPATH@ */
+ retbuf = malloc(strlen(LXCPATH)+1);
+ if (!retbuf)
+ goto out;
+ strcpy(retbuf, LXCPATH);
+
+out:
+ if (fin)
+ fclose(fin);
+ INFO("returning %s", (retbuf ? retbuf : "null"));
+ return retbuf;
+}
extern int lxc_setup_fs(void);
extern int get_u16(unsigned short *val, const char *arg, int base);
extern int mkdir_p(const char *dir, mode_t mode);
+/*
+ * Return a newly allocated buffer containing the default container
+ * path. Caller must free this buffer.
+ */
+extern char *default_lxc_path(void);
#endif
AM_CFLAGS=-I$(top_srcdir)/src \
-DLXCROOTFSMOUNT=\"$(LXCROOTFSMOUNT)\" \
-DLXCPATH=\"$(LXCPATH)\" \
+ -DLXC_GLOBAL_CONF=\"$(LXC_GLOBAL_CONF)\" \
-DLXCINITDIR=\"$(LXCINITDIR)\"
bin_PROGRAMS = lxc-test-containertests lxc-test-locktests lxc-test-startone \