summaryrefslogtreecommitdiff
path: root/src/machine/machinectl.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2015-02-17 17:19:57 +0100
committerLennart Poettering <lennart@poettering.net>2015-02-17 17:49:21 +0100
commit90adaa25e894a580930ef2c3e65ab8db8295515a (patch)
tree32cefc482936a9dc4d6f6183fa900d917b443504 /src/machine/machinectl.c
parent0974a682d155a5874123ba7de9c1e314c6681e0f (diff)
machined: move logic for bind mounting into containers from machinectl to machined
This extends the bus interface, adding BindMountMachine() for bind mounting directories from the host into the container.
Diffstat (limited to 'src/machine/machinectl.c')
-rw-r--r--src/machine/machinectl.c211
1 files changed, 27 insertions, 184 deletions
diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c
index 9f8c68b184..c1cc5e7eb5 100644
--- a/src/machine/machinectl.c
+++ b/src/machine/machinectl.c
@@ -901,14 +901,14 @@ static int show_image(int argc, char *argv[], void *userdata) {
const char *path = NULL;
r = sd_bus_call_method(
- bus,
- "org.freedesktop.machine1",
- "/org/freedesktop/machine1",
- "org.freedesktop.machine1.Manager",
- "GetImage",
- &error,
- &reply,
- "s", argv[i]);
+ bus,
+ "org.freedesktop.machine1",
+ "/org/freedesktop/machine1",
+ "org.freedesktop.machine1.Manager",
+ "GetImage",
+ &error,
+ &reply,
+ "s", argv[i]);
if (r < 0) {
log_error("Could not get path to image: %s", bus_error_message(&error, -r));
return r;
@@ -930,7 +930,7 @@ static int show_image(int argc, char *argv[], void *userdata) {
static int kill_machine(int argc, char *argv[], void *userdata) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
sd_bus *bus = userdata;
- int i;
+ int r, i;
assert(bus);
@@ -940,8 +940,6 @@ static int kill_machine(int argc, char *argv[], void *userdata) {
arg_kill_who = "all";
for (i = 1; i < argc; i++) {
- int r;
-
r = sd_bus_call_method(
bus,
"org.freedesktop.machine1",
@@ -1143,187 +1141,32 @@ static int copy_files(int argc, char *argv[], void *userdata) {
}
static int bind_mount(int argc, char *argv[], void *userdata) {
- char mount_slave[] = "/tmp/propagate.XXXXXX", *mount_tmp, *mount_outside, *p;
+ _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
sd_bus *bus = userdata;
- pid_t child, leader;
- const char *dest;
- siginfo_t si;
- bool mount_slave_created = false, mount_slave_mounted = false,
- mount_tmp_created = false, mount_tmp_mounted = false,
- mount_outside_created = false, mount_outside_mounted = false;
int r;
assert(bus);
- /* One day, when bind mounting /proc/self/fd/n works across
- * namespace boundaries we should rework this logic to make
- * use of it... */
-
- dest = argv[3] ?: argv[2];
- if (!path_is_absolute(dest)) {
- log_error("Destination path not absolute.");
- return -EINVAL;
- }
-
- p = strjoina("/run/systemd/nspawn/propagate/", argv[1], "/");
- if (access(p, F_OK) < 0) {
- log_error("Container does not allow propagation of mount points.");
- return -ENOTSUP;
- }
-
- r = machine_get_leader(bus, argv[1], &leader);
- if (r < 0)
- return r;
-
- /* Our goal is to install a new bind mount into the container,
- possibly read-only. This is irritatingly complex
- unfortunately, currently.
-
- First, we start by creating a private playground in /tmp,
- that we can mount MS_SLAVE. (Which is necessary, since
- MS_MOUNT cannot be applied to mounts with MS_SHARED parent
- mounts.) */
-
- if (!mkdtemp(mount_slave))
- return log_error_errno(errno, "Failed to create playground: %m");
-
- mount_slave_created = true;
-
- if (mount(mount_slave, mount_slave, NULL, MS_BIND, NULL) < 0) {
- r = log_error_errno(errno, "Failed to make bind mount: %m");
- goto finish;
- }
-
- mount_slave_mounted = true;
-
- if (mount(NULL, mount_slave, NULL, MS_SLAVE, NULL) < 0) {
- r = log_error_errno(errno, "Failed to remount slave: %m");
- goto finish;
- }
-
- /* Second, we mount the source directory to a directory inside
- of our MS_SLAVE playground. */
- mount_tmp = strjoina(mount_slave, "/mount");
- if (mkdir(mount_tmp, 0700) < 0) {
- r = log_error_errno(errno, "Failed to create temporary mount: %m");
- goto finish;
- }
-
- mount_tmp_created = true;
-
- if (mount(argv[2], mount_tmp, NULL, MS_BIND, NULL) < 0) {
- r = log_error_errno(errno, "Failed to overmount: %m");
- goto finish;
- }
-
- mount_tmp_mounted = true;
-
- /* Third, we remount the new bind mount read-only if requested. */
- if (arg_read_only)
- if (mount(NULL, mount_tmp, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY, NULL) < 0) {
- r = log_error_errno(errno, "Failed to mark read-only: %m");
- goto finish;
- }
-
- /* Fourth, we move the new bind mount into the propagation
- * directory. This way it will appear there read-only
- * right-away. */
-
- mount_outside = strjoina("/run/systemd/nspawn/propagate/", argv[1], "/XXXXXX");
- if (!mkdtemp(mount_outside)) {
- r = log_error_errno(errno, "Cannot create propagation directory: %m");
- goto finish;
- }
-
- mount_outside_created = true;
-
- if (mount(mount_tmp, mount_outside, NULL, MS_MOVE, NULL) < 0) {
- r = log_error_errno(errno, "Failed to move: %m");
- goto finish;
- }
-
- mount_outside_mounted = true;
- mount_tmp_mounted = false;
-
- (void) rmdir(mount_tmp);
- mount_tmp_created = false;
-
- (void) umount(mount_slave);
- mount_slave_mounted = false;
-
- (void) rmdir(mount_slave);
- mount_slave_created = false;
-
- child = fork();
- if (child < 0) {
- r = log_error_errno(errno, "Failed to fork(): %m");
- goto finish;
- }
-
- if (child == 0) {
- const char *mount_inside;
- int mntfd;
- const char *q;
-
- q = procfs_file_alloca(leader, "ns/mnt");
- mntfd = open(q, O_RDONLY|O_NOCTTY|O_CLOEXEC);
- if (mntfd < 0) {
- log_error_errno(errno, "Failed to open mount namespace of leader: %m");
- _exit(EXIT_FAILURE);
- }
-
- if (setns(mntfd, CLONE_NEWNS) < 0) {
- log_error_errno(errno, "Failed to join namespace of leader: %m");
- _exit(EXIT_FAILURE);
- }
-
- if (arg_mkdir)
- mkdir_p(dest, 0755);
-
- /* Fifth, move the mount to the right place inside */
- mount_inside = strjoina("/run/systemd/nspawn/incoming/", basename(mount_outside));
- if (mount(mount_inside, dest, NULL, MS_MOVE, NULL) < 0) {
- log_error_errno(errno, "Failed to mount: %m");
- _exit(EXIT_FAILURE);
- }
-
- _exit(EXIT_SUCCESS);
- }
-
- r = wait_for_terminate(child, &si);
+ r = sd_bus_call_method(
+ bus,
+ "org.freedesktop.machine1",
+ "/org/freedesktop/machine1",
+ "org.freedesktop.machine1.Manager",
+ "BindMountMachine",
+ &error,
+ NULL,
+ "sssbb",
+ argv[1],
+ argv[2],
+ argv[3],
+ arg_read_only,
+ arg_mkdir);
if (r < 0) {
- log_error_errno(r, "Failed to wait for client: %m");
- goto finish;
- }
- if (si.si_code != CLD_EXITED) {
- log_error("Client died abnormally.");
- r = -EIO;
- goto finish;
- }
- if (si.si_status != EXIT_SUCCESS) {
- r = -EIO;
- goto finish;
+ log_error("Failed to bind mount: %s", bus_error_message(&error, -r));
+ return r;
}
- r = 0;
-
-finish:
- if (mount_outside_mounted)
- umount(mount_outside);
- if (mount_outside_created)
- rmdir(mount_outside);
-
- if (mount_tmp_mounted)
- umount(mount_tmp);
- if (mount_tmp_created)
- umount(mount_tmp);
-
- if (mount_slave_mounted)
- umount(mount_slave);
- if (mount_slave_created)
- umount(mount_slave);
-
- return r;
+ return 0;
}
static int on_machine_removed(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {