[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.


More information about the Containers mailing list