[Devel] [PATCH] rootfs automatic preparation by lxc
Dmitry Mishin
dim at parallels.com
Wed Oct 29 08:48:51 PDT 2008
Add the ability to automatically create the container fs.
We use OpenVZ precreated template for this - these are just regular
tarballs with all the files required for container work. So in this
patch we just untar it into a specified root dir (and destroy one
after container destruction).
Signed-off-by: Sergey Krasnov <krasnov at openvz.org>
Reviewed-by: Pavel Emelyanov <xemul at openvz.org>
Acked-by: Dmitry Mishin <dim at openvz.org>
---
--- ./src/lxc/lxc_conf.c.cache 2008-10-08 18:15:58.000000000 +0400
+++ ./src/lxc/lxc_conf.c 2008-10-29 13:04:23.000000000 +0300
@@ -419,27 +419,69 @@
return 0;
}
-static int configure_rootfs(const char *name, const char *rootfs)
+static int configure_cache(const char *name, struct lxc_conf *conf)
{
+ int rc;
+ char cmd[BUFSIZ];
char path[MAXPATHLEN];
- char absrootfs[MAXPATHLEN];
- char *pwd;
- snprintf(path, MAXPATHLEN, LXCPATH "/%s/rootfs", name);
+ if (strlen(conf->cachefile) == 0)
+ return 0;
- pwd = get_current_dir_name();
+ if (strlen(conf->rootfs) == 0) {
+ /* special case : rootfs in container home dir */
+ snprintf(conf->rootfs, sizeof(conf->rootfs),
+ LXCPATH "/%s/root", name);
+ if (mkdir(conf->rootfs, 0755)) {
+ lxc_log_syserror("mkdir(%s, 0755)", conf->rootfs);
+ return -1;
+ }
+ }
- snprintf(absrootfs, MAXPATHLEN, "%s/%s", pwd, rootfs);
+ if (access(conf->rootfs, F_OK)) {
+ lxc_log_syserror("'%s' is not accessible", conf->rootfs);
+ return -1;
+ }
- free(pwd);
+ snprintf(path, MAXPATHLEN, LXCPATH "/%s/cachefile", name);
+ if (symlink(conf->cachefile, path)) {
+ lxc_log_syserror("symlink(%s,%s)", conf->cachefile, path);
+ return -1;
+ }
- if (access(absrootfs, F_OK)) {
- lxc_log_syserror("'%s' is not accessible", absrootfs);
+ snprintf(cmd, sizeof(cmd), "tar -C %s -xzf %s", conf->rootfs, path);
+ lxc_log_debug("system(%s)", cmd);
+ rc = system(cmd);
+ if (rc == -1) {
+ lxc_log_error("system(%s) error : %m", cmd);
+ return -1;
+ }
+ if (!WIFEXITED(rc)) {
+ lxc_log_error("\"%s\" failed", cmd);
return -1;
}
+ if (WEXITSTATUS(rc)) {
+ lxc_log_error("\"%s\" return %d", cmd, WEXITSTATUS(rc));
+ return -1;
+ }
+ return 0;
+}
+
+static int configure_rootfs(const char *name, const char *rootfs)
+{
+ char path[MAXPATHLEN];
- return symlink(absrootfs, path);
+ if (access(rootfs, F_OK)) {
+ lxc_log_syserror("'%s' is not accessible", rootfs);
+ return -1;
+ }
+ snprintf(path, MAXPATHLEN, LXCPATH "/%s/rootfs", name);
+ if (symlink(rootfs, path)) {
+ lxc_log_syserror("symlink(%s,%s) : %m", rootfs, path);
+ return -1;
+ }
+ return 0;
}
static int configure_mount(const char *name, const char *fstab)
@@ -574,6 +616,27 @@
return 0;
}
+static int unconfigure_cache(const char *name)
+{
+ char buf[BUFSIZ];
+ char path[MAXPATHLEN+1];
+
+ snprintf(path, sizeof(path), LXCPATH "/%s/rootfs", name);
+ if (readlink(path, buf, sizeof(buf)) == -1) {
+ lxc_log_syserror("readlink(%s)", path);
+ return -1;
+ }
+ strncpy(path, buf, sizeof(path));
+
+ snprintf(buf, sizeof(buf), "rm -rf %s/*", path);
+ system(buf);
+ snprintf(path, sizeof(path), LXCPATH "/%s/root", name);
+ rmdir(path);
+ snprintf(path, sizeof(path), LXCPATH "/%s", name);
+ delete_info(path, "cachefile");
+ return 0;
+}
+
static int unconfigure_rootfs(const char *name)
{
char path[MAXPATHLEN];
@@ -950,9 +1013,18 @@
return -1;
}
- if (conf->rootfs && configure_rootfs(name, conf->rootfs)) {
- lxc_log_error("failed to configure the rootfs");
- return -1;
+ if (strlen(conf->cachefile)) {
+ if (configure_cache(name, conf)) {
+ lxc_log_error("failed to configure the cache");
+ return -1;
+ }
+ }
+
+ if (strlen(conf->rootfs)) {
+ if (configure_rootfs(name, conf->rootfs)) {
+ lxc_log_error("failed to configure the rootfs");
+ return -1;
+ }
}
if (conf->fstab && configure_mount(name, conf->fstab)) {
@@ -974,6 +1046,9 @@
if (conf_has_cgroup(name) && unconfigure_cgroup(name))
lxc_log_error("failed to cleanup cgroup");
+ if (conf_has_cachefile(name) && unconfigure_cache(name))
+ lxc_log_error("failed to cleanup rootfs");
+
if (conf_has_rootfs(name) && unconfigure_rootfs(name))
lxc_log_error("failed to cleanup rootfs");
--- ./src/lxc/lxc_conf.h.cache 2008-10-06 22:47:19.000000000 +0400
+++ ./src/lxc/lxc_conf.h 2008-10-29 13:04:23.000000000 +0300
@@ -24,6 +24,7 @@
#define _conf_h
#include <netinet/in.h>
+#include <sys/param.h>
enum {
EMPTY,
@@ -115,7 +116,8 @@
* @utsname : the container utsname
*/
struct lxc_conf {
- char *rootfs;
+ char rootfs[MAXPATHLEN+1];
+ char cachefile[MAXPATHLEN+1];
char *fstab;
struct utsname *utsname;
struct lxc_list cgroup;
@@ -145,6 +147,7 @@
#define conf_has_fstab(__name) conf_has(__name, "fstab")
#define conf_has_rootfs(__name) conf_has(__name, "rootfs")
+#define conf_has_cachefile(__name) conf_has(__name, "cachefile")
#define conf_has_utsname(__name) conf_has(__name, "utsname")
#define conf_has_network(__name) conf_has(__name, "network")
#define conf_has_cgroup(__name) conf_has(__name, "cgroup")
--- ./src/lxc/lxc_config.c.cache 2008-10-06 22:47:19.000000000 +0400
+++ ./src/lxc/lxc_config.c 2008-10-29 13:04:23.000000000 +0300
@@ -40,6 +40,7 @@
static int config_cgroup(const char *, char *, struct lxc_conf *);
static int config_mount(const char *, char *, struct lxc_conf *);
static int config_rootfs(const char *, char *, struct lxc_conf *);
+static int config_cachefile(const char *, char *, struct lxc_conf *);
static int config_utsname(const char *, char *, struct lxc_conf *);
static int config_network_type(const char *, char *, struct lxc_conf *);
static int config_network_flags(const char *, char *, struct lxc_conf *);
@@ -59,6 +60,7 @@
{ "lxc.cgroup", config_cgroup },
{ "lxc.mount", config_mount },
{ "lxc.rootfs", config_rootfs },
+ { "lxc.cachefile", config_cachefile },
{ "lxc.utsname", config_utsname },
{ "lxc.network.type", config_network_type },
{ "lxc.network.flags", config_network_flags },
@@ -478,12 +480,43 @@
lxc_log_error("%s path is too long", value);
return -1;
}
+ /* if rootfs is relative path, add it on current dir */
+ if (value[0] != '/') {
+ char path[MAXPATHLEN+1];
+ if (getcwd(path, sizeof(path)) == NULL) {
+ lxc_log_error("getcwd() error : %m");
+ return -1;
+ }
+ snprintf(lxc_conf->rootfs, sizeof(lxc_conf->rootfs),
+ "%s/%s", path, value);
+ } else {
+ strncpy(lxc_conf->rootfs, value, sizeof(lxc_conf->rootfs));
+ }
- lxc_conf->rootfs = strdup(value);
- if (!lxc_conf->rootfs) {
- lxc_log_syserror("failed to duplicate string %s", value);
+ return 0;
+}
+
+static int config_cachefile(
+ const char *key,
+ char *value,
+ struct lxc_conf *lxc_conf)
+{
+ if (strlen(value) >= MAXPATHLEN) {
+ lxc_log_error("%s path is too long", value);
return -1;
}
+ /* if cachefile is relative path, add it on current dir */
+ if (value[0] != '/') {
+ char path[MAXPATHLEN+1];
+ if (getcwd(path, sizeof(path)) == NULL) {
+ lxc_log_error("getcwd() error : %m");
+ return -1;
+ }
+ snprintf(lxc_conf->cachefile, sizeof(lxc_conf->cachefile),
+ "%s/%s", path, value);
+ } else {
+ strncpy(lxc_conf->cachefile, value, sizeof(lxc_conf->cachefile));
+ }
return 0;
}
@@ -577,7 +610,8 @@
int lxc_config_init(struct lxc_conf *conf)
{
- conf->rootfs = NULL;
+ conf->rootfs[0] = '\0';
+ conf->cachefile[0] = '\0';
conf->fstab = NULL;
conf->utsname = NULL;
lxc_list_init(&conf->cgroup);
--- ./src/lxc/start.c.cache 2008-10-08 18:15:17.000000000 +0400
+++ ./src/lxc/start.c 2008-10-29 13:04:23.000000000 +0300
@@ -126,9 +126,11 @@
return -1;
}
- if (mount(ttyname, "/dev/console", "none", MS_BIND, 0)) {
- lxc_log_syserror("failed to mount '/dev/console'");
- return -1;
+ if (access("/dev/console", F_OK)) {
+ if (mount(ttyname, "/dev/console", "none", MS_BIND, 0)) {
+ lxc_log_syserror("failed to mount '/dev/console'");
+ return -1;
+ }
}
/* If a callback has been passed, call it before doing exec */
--- ./README.cache 2008-10-15 11:30:09.000000000 +0400
+++ ./README 2008-10-29 13:04:23.000000000 +0300
@@ -150,6 +150,10 @@
# the rootfs if needed for the running application
lxc.rootfs = /mnt/root
+# OpenVZ precreated OS template cache (see http://wiki.openvz.org ,
+# http://wiki.openvz.org/Download/template/precreated)
+lxc.cachefiles = /var/tmp/ubuntu-8.04-x86.tar.gz
+
# The network has several of kind of configuration:
#
# * veth : the network will use the veth virtual device, the
--
Thanks,
Dmitry.
_______________________________________________
Containers mailing list
Containers at lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/containers
More information about the Devel
mailing list