chiark / gitweb /
nspawn: allow spawning ephemeral nspawn containers based on the root file system...
authorLennart Poettering <lennart@poettering.net>
Fri, 12 Dec 2014 15:59:15 +0000 (16:59 +0100)
committerLennart Poettering <lennart@poettering.net>
Fri, 12 Dec 2014 16:30:25 +0000 (17:30 +0100)
This works now:

        # systemd-nspawn -xb -D / -M foobar

Which boots up an ephemeral container, based on the host's root file
system. Or in other words: you can now run the very same host OS you
booted your system with also in a container, on top of it, without
having it interfere. Great for testing whether the init system you are
hacking on still boots without reboot the system!

src/nspawn/nspawn.c
src/shared/util.c
src/shared/util.h

index f6f20abdaf23b1db88865e4db0897f06d43a34d2..651a45126b8585b7e0037e76a53c553318b2fdf5 100644 (file)
@@ -2942,8 +2942,8 @@ int main(int argc, char *argv[]) {
         if (arg_directory) {
                 assert(!arg_image);
 
         if (arg_directory) {
                 assert(!arg_image);
 
-                if (path_equal(arg_directory, "/")) {
-                        log_error("Spawning container on root directory not supported.");
+                if (path_equal(arg_directory, "/") && !arg_ephemeral) {
+                        log_error("Spawning container on root directory is not supported. Consider using --ephemeral.");
                         r = -EINVAL;
                         goto finish;
                 }
                         r = -EINVAL;
                         goto finish;
                 }
@@ -2964,7 +2964,21 @@ int main(int argc, char *argv[]) {
                 } else if (arg_ephemeral) {
                         char *np;
 
                 } else if (arg_ephemeral) {
                         char *np;
 
-                        r = tempfn_random(arg_directory, &np);
+                        /* If the specified path is a mount point we
+                         * generate the new snapshot immediately
+                         * inside it under a random name. However if
+                         * the specified is not a mount point we
+                         * create the new snapshot in the parent
+                         * directory, just next to it. */
+                        r = path_is_mount_point(arg_directory, false);
+                        if (r < 0) {
+                                log_error_errno(r, "Failed to determine whether directory %s is mount point: %m", arg_directory);
+                                goto finish;
+                        }
+                        if (r > 0)
+                                r = tempfn_random_child(arg_directory, &np);
+                        else
+                                r = tempfn_random(arg_directory, &np);
                         if (r < 0) {
                                 log_error_errno(r, "Failed to generate name for snapshot: %m");
                                 goto finish;
                         if (r < 0) {
                                 log_error_errno(r, "Failed to generate name for snapshot: %m");
                                 goto finish;
index 254b5637ae8c161acbcc581b929c8207db8c95a2..ee95a4b6f71c67bb7ff3f5c3e8ce736bfaa98113 100644 (file)
@@ -6977,6 +6977,14 @@ int tempfn_xxxxxx(const char *p, char **ret) {
         assert(p);
         assert(ret);
 
         assert(p);
         assert(ret);
 
+        /*
+         * Turns this:
+         *         /foo/bar/waldo
+         *
+         * Into this:
+         *         /foo/bar/.waldoXXXXXX
+         */
+
         fn = basename(p);
         if (!filename_is_valid(fn))
                 return -EINVAL;
         fn = basename(p);
         if (!filename_is_valid(fn))
                 return -EINVAL;
@@ -6987,7 +6995,7 @@ int tempfn_xxxxxx(const char *p, char **ret) {
 
         strcpy(stpcpy(stpcpy(mempcpy(t, p, fn - p), "."), fn), "XXXXXX");
 
 
         strcpy(stpcpy(stpcpy(mempcpy(t, p, fn - p), "."), fn), "XXXXXX");
 
-        *ret = t;
+        *ret = path_kill_slashes(t);
         return 0;
 }
 
         return 0;
 }
 
@@ -7000,6 +7008,14 @@ int tempfn_random(const char *p, char **ret) {
         assert(p);
         assert(ret);
 
         assert(p);
         assert(ret);
 
+        /*
+         * Turns this:
+         *         /foo/bar/waldo
+         *
+         * Into this:
+         *         /foo/bar/.waldobaa2a261115984a9
+         */
+
         fn = basename(p);
         if (!filename_is_valid(fn))
                 return -EINVAL;
         fn = basename(p);
         if (!filename_is_valid(fn))
                 return -EINVAL;
@@ -7018,7 +7034,39 @@ int tempfn_random(const char *p, char **ret) {
 
         *x = 0;
 
 
         *x = 0;
 
-        *ret = t;
+        *ret = path_kill_slashes(t);
+        return 0;
+}
+
+int tempfn_random_child(const char *p, char **ret) {
+        char *t, *x;
+        uint64_t u;
+        unsigned i;
+
+        assert(p);
+        assert(ret);
+
+        /* Turns this:
+         *         /foo/bar/waldo
+         * Into this:
+         *         /foo/bar/waldo/.3c2b6219aa75d7d0
+         */
+
+        t = new(char, strlen(p) + 2 + 16 + 1);
+        if (!t)
+                return -ENOMEM;
+
+        x = stpcpy(stpcpy(t, p), "/.");
+
+        u = random_u64();
+        for (i = 0; i < 16; i++) {
+                *(x++) = hexchar(u & 0xF);
+                u >>= 4;
+        }
+
+        *x = 0;
+
+        *ret = path_kill_slashes(t);
         return 0;
 }
 
         return 0;
 }
 
index 9a878ca1ac13a00a02a0dffe7b198b59160d4dd8..a8ccf20bb8268f4ed65246b45372968a9d27df0f 100644 (file)
@@ -1018,6 +1018,7 @@ int fflush_and_check(FILE *f);
 
 int tempfn_xxxxxx(const char *p, char **ret);
 int tempfn_random(const char *p, char **ret);
 
 int tempfn_xxxxxx(const char *p, char **ret);
 int tempfn_random(const char *p, char **ret);
+int tempfn_random_child(const char *p, char **ret);
 
 bool is_localhost(const char *hostname);
 
 
 bool is_localhost(const char *hostname);