[lxc-devel] [lxd/master] Add `shift` property on disk devices
stgraber on Github
lxc-bot at linuxcontainers.org
Wed Jul 24 20:38:07 UTC 2019
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 512 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20190724/80f01c8a/attachment.bin>
-------------- next part --------------
From a2016b362a2058d50f0d58fbdd067d0ec4e7950d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Wed, 17 Jul 2019 23:35:06 -0400
Subject: [PATCH 1/6] api: Add container_disk_shift extension
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
doc/api-extensions.md | 3 +++
shared/version/api.go | 1 +
2 files changed, 4 insertions(+)
diff --git a/doc/api-extensions.md b/doc/api-extensions.md
index 3bf3d1adad..3202ad3e1b 100644
--- a/doc/api-extensions.md
+++ b/doc/api-extensions.md
@@ -803,3 +803,6 @@ Adds support for specifying User, Group and Cwd during `POST /1.0/containers/NAM
Adds the `security.syscalls.intercept.\*` configuration keys to control
what system calls will be interecepted by LXD and processed with
elevated permissions.
+
+## container\_disk\_shift
+Adds the `shift` property on `disk` devices which controls the use of the shiftfs overlay.
diff --git a/shared/version/api.go b/shared/version/api.go
index 99fef0b913..fdf8a5921f 100644
--- a/shared/version/api.go
+++ b/shared/version/api.go
@@ -160,6 +160,7 @@ var APIExtensions = []string{
"resources_v2",
"container_exec_user_group_cwd",
"container_syscall_intercept",
+ "container_disk_shift",
}
// APIExtensionsCount returns the number of available API extensions.
From 1df04cfd26b3d975788bba99c59af6da2222da3c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Wed, 17 Jul 2019 23:35:44 -0400
Subject: [PATCH 2/6] doc: Add shift option to disk device
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
doc/containers.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/doc/containers.md b/doc/containers.md
index 4c33c2c254..c3741f416b 100644
--- a/doc/containers.md
+++ b/doc/containers.md
@@ -493,6 +493,7 @@ size | string | - | no | Disk size in bytes
recursive | boolean | false | no | Whether or not to recursively mount the source path
pool | string | - | no | The storage pool the disk device belongs to. This is only applicable for storage volumes managed by LXD.
propagation | string | - | no | Controls how a bind-mount is shared between the container and the host. (Can be one of `private`, the default, or `shared`, `slave`, `unbindable`, `rshared`, `rslave`, `runbindable`, `rprivate`. Please see the Linux Kernel [shared subtree](https://www.kernel.org/doc/Documentation/filesystems/sharedsubtree.txt) documentation for a full explanation)
+shift | boolean | false | no | Setup a shifting overlay to translate the source uid/gid to match the container
If multiple disks, backed by the same block device, have I/O limits set,
the average of the limits will be used.
From 3f04a1e092074fdd5a62d68fa55b2612d910f438 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Wed, 17 Jul 2019 23:40:42 -0400
Subject: [PATCH 3/6] lxd/container: Don't validate liblxc version during
config parsing
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
lxd/container.go | 5 -----
lxd/container_lxc.go | 4 ++++
2 files changed, 4 insertions(+), 5 deletions(-)
diff --git a/lxd/container.go b/lxd/container.go
index a690fff70c..d6e1cb8a5e 100644
--- a/lxd/container.go
+++ b/lxd/container.go
@@ -22,7 +22,6 @@ import (
"github.com/lxc/lxd/lxd/state"
"github.com/lxc/lxd/lxd/sys"
"github.com/lxc/lxd/lxd/task"
- "github.com/lxc/lxd/lxd/util"
"github.com/lxc/lxd/shared"
"github.com/lxc/lxd/shared/api"
"github.com/lxc/lxd/shared/idmap"
@@ -515,10 +514,6 @@ func containerValidDevices(cluster *db.Cluster, devices config.Devices, profile
}
if m["propagation"] != "" {
- if !util.RuntimeLiblxcVersionAtLeast(3, 0, 0) {
- return fmt.Errorf("liblxc 3.0 is required for mount propagation configuration")
- }
-
if !shared.StringInSlice(m["propagation"], []string{"private", "shared", "slave", "unbindable", "rprivate", "rshared", "rslave", "runbindable"}) {
return fmt.Errorf("Invalid propagation mode '%s'", m["propagation"])
}
diff --git a/lxd/container_lxc.go b/lxd/container_lxc.go
index 1b5ca2ccd0..31354ce189 100644
--- a/lxd/container_lxc.go
+++ b/lxd/container_lxc.go
@@ -1843,6 +1843,10 @@ func (c *containerLXC) initLXC(config bool) error {
}
if m["propagation"] != "" {
+ if !util.RuntimeLiblxcVersionAtLeast(3, 0, 0) {
+ return fmt.Errorf("liblxc 3.0 is required for mount propagation configuration")
+ }
+
options = append(options, m["propagation"])
}
From ef59832e811f83d2771764e5dc8cc037ea8c889b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Wed, 17 Jul 2019 23:59:28 -0400
Subject: [PATCH 4/6] lxd: Add shift disk option
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
lxd/container.go | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/lxd/container.go b/lxd/container.go
index d6e1cb8a5e..4d4df4b91d 100644
--- a/lxd/container.go
+++ b/lxd/container.go
@@ -185,6 +185,8 @@ func containerValidDeviceConfigKey(t, k string) bool {
return true
case "propagation":
return true
+ case "shift":
+ return true
default:
return false
}
@@ -518,6 +520,12 @@ func containerValidDevices(cluster *db.Cluster, devices config.Devices, profile
return fmt.Errorf("Invalid propagation mode '%s'", m["propagation"])
}
}
+
+ if m["shift"] != "" {
+ if m["pool"] != "" {
+ return fmt.Errorf("The \"shift\" property cannot be used with custom storage volumes")
+ }
+ }
} else if shared.StringInSlice(m["type"], []string{"unix-char", "unix-block"}) {
if m["source"] == "" && m["path"] == "" {
return fmt.Errorf("Unix device entry is missing the required \"source\" or \"path\" property")
From 12f16a412240f03222860bf31be7a38ca211a473 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Thu, 18 Jul 2019 01:23:03 -0400
Subject: [PATCH 5/6] lxd/containers: Add shiftfs for disk devices
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
lxd/container_lxc.go | 44 ++++++++++++++++++++++++++++++++++---------
lxd/main_forkmount.go | 24 ++++++++++++++++++++++-
2 files changed, 58 insertions(+), 10 deletions(-)
diff --git a/lxd/container_lxc.go b/lxd/container_lxc.go
index 31354ce189..003b453e9c 100644
--- a/lxd/container_lxc.go
+++ b/lxd/container_lxc.go
@@ -1828,6 +1828,23 @@ func (c *containerLXC) initLXC(config bool) error {
}
}
} else {
+ if shared.IsTrue(m["shift"]) {
+ err = lxcSetConfigItem(cc, "lxc.hook.pre-start", fmt.Sprintf("/bin/mount -t shiftfs -o mark,passthrough=3 %s %s", sourceDevPath, sourceDevPath))
+ if err != nil {
+ return err
+ }
+
+ err = lxcSetConfigItem(cc, "lxc.hook.pre-mount", fmt.Sprintf("/bin/mount -t shiftfs -o passthrough=3 %s %s", sourceDevPath, sourceDevPath))
+ if err != nil {
+ return err
+ }
+
+ err = lxcSetConfigItem(cc, "lxc.hook.start-host", fmt.Sprintf("/bin/umount -l %s", sourceDevPath))
+ if err != nil {
+ return err
+ }
+ }
+
rbind := ""
options := []string{}
if isReadOnly {
@@ -5130,7 +5147,7 @@ func (c *containerLXC) Update(args db.ContainerArgs, userRequested bool) error {
}
} else if key == "security.devlxd" {
if value == "" || shared.IsTrue(value) {
- err = c.insertMount(shared.VarPath("devlxd"), "/dev/lxd", "none", unix.MS_BIND)
+ err = c.insertMount(shared.VarPath("devlxd"), "/dev/lxd", "none", unix.MS_BIND, false)
if err != nil {
return err
}
@@ -7274,7 +7291,7 @@ func (c *containerLXC) StorageStop() (bool, error) {
}
// Mount handling
-func (c *containerLXC) insertMountLXD(source, target, fstype string, flags int, mntnsPID int) error {
+func (c *containerLXC) insertMountLXD(source, target, fstype string, flags int, mntnsPID int, shiftfs bool) error {
pid := mntnsPID
if pid <= 0 {
// Get the init PID
@@ -7311,11 +7328,20 @@ func (c *containerLXC) insertMountLXD(source, target, fstype string, flags int,
}
defer unix.Unmount(tmpMount, unix.MNT_DETACH)
+ // Setup host side shiftfs as needed
+ if shiftfs {
+ err = unix.Mount(tmpMount, tmpMount, "shiftfs", 0, "mark,passthrough=3")
+ if err != nil {
+ return fmt.Errorf("Failed to setup host side shiftfs mount: %s", err)
+ }
+ defer unix.Unmount(tmpMount, unix.MNT_DETACH)
+ }
+
// Move the mount inside the container
mntsrc := filepath.Join("/dev/.lxd-mounts", filepath.Base(tmpMount))
pidStr := fmt.Sprintf("%d", pid)
- _, err = shared.RunCommand(c.state.OS.ExecPath, "forkmount", "lxd-mount", pidStr, mntsrc, target)
+ _, err = shared.RunCommand(c.state.OS.ExecPath, "forkmount", "lxd-mount", pidStr, mntsrc, target, fmt.Sprintf("%v", shiftfs))
if err != nil {
return err
}
@@ -7342,12 +7368,12 @@ func (c *containerLXC) insertMountLXC(source, target, fstype string, flags int)
return nil
}
-func (c *containerLXC) insertMount(source, target, fstype string, flags int) error {
- if c.state.OS.LXCFeatures["mount_injection_file"] {
+func (c *containerLXC) insertMount(source, target, fstype string, flags int, shiftfs bool) error {
+ if c.state.OS.LXCFeatures["mount_injection_file"] && !shiftfs {
return c.insertMountLXC(source, target, fstype, flags)
}
- return c.insertMountLXD(source, target, fstype, flags, -1)
+ return c.insertMountLXD(source, target, fstype, flags, -1, shiftfs)
}
func (c *containerLXC) removeMount(mount string) error {
@@ -7549,7 +7575,7 @@ func (c *containerLXC) insertUnixDevice(prefix string, m config.Device, defaultM
tgtPath := paths[1]
// Bind-mount it into the container
- err = c.insertMount(devPath, tgtPath, "none", unix.MS_BIND)
+ err = c.insertMount(devPath, tgtPath, "none", unix.MS_BIND, false)
if err != nil {
return fmt.Errorf("Failed to add mount for device: %s", err)
}
@@ -7642,7 +7668,7 @@ func (c *containerLXC) InsertSeccompUnixDevice(prefix string, m config.Device, p
// Bind-mount it into the container
defer os.Remove(devPath)
- return c.insertMountLXD(devPath, tgtPath, "none", unix.MS_BIND, pid)
+ return c.insertMountLXD(devPath, tgtPath, "none", unix.MS_BIND, pid, false)
}
func (c *containerLXC) insertUnixDeviceNum(name string, m config.Device, major int, minor int, path string, defaultMode bool) error {
@@ -9334,7 +9360,7 @@ func (c *containerLXC) insertDiskDevice(name string, m config.Device) error {
// Bind-mount it into the container
destPath := strings.TrimSuffix(m["path"], "/")
- err = c.insertMount(devPath, destPath, "none", flags)
+ err = c.insertMount(devPath, destPath, "none", flags, shared.IsTrue(m["shift"]))
if err != nil {
return fmt.Errorf("Failed to add mount for device: %s", err)
}
diff --git a/lxd/main_forkmount.go b/lxd/main_forkmount.go
index 5b0209895b..c42bfa1f2d 100644
--- a/lxd/main_forkmount.go
+++ b/lxd/main_forkmount.go
@@ -128,7 +128,7 @@ void create(char *src, char *dest)
}
void do_lxd_forkmount(pid_t pid) {
- char *src, *dest, *opts;
+ char *src, *dest, *opts, *shiftfs;
attach_userns(pid);
@@ -139,6 +139,7 @@ void do_lxd_forkmount(pid_t pid) {
src = advance_arg(true);
dest = advance_arg(true);
+ shiftfs = advance_arg(true);
create(src, dest);
@@ -152,14 +153,35 @@ void do_lxd_forkmount(pid_t pid) {
_exit(1);
}
+ if (strcmp(shiftfs, "true") == 0) {
+ // Setup shiftfs inside the container
+ if (mount(src, src, "shiftfs", 0, "passthrough=3") < 0) {
+ fprintf(stderr, "Failed shiftfs setup for %s: %s\n", src, strerror(errno));
+ _exit(1);
+ }
+ }
+
// Here, we always move recursively, because we sometimes allow
// recursive mounts. If the mount has no kids then it doesn't matter,
// but if it does, we want to move those too.
if (mount(src, dest, "none", MS_MOVE | MS_REC, NULL) < 0) {
+ // If using shiftfs, undo the shiftfs mount
+ if (strcmp(shiftfs, "true") == 0) {
+ umount2(src, MNT_DETACH);
+ }
+
fprintf(stderr, "Failed mounting %s onto %s: %s\n", src, dest, strerror(errno));
_exit(1);
}
+ if (strcmp(shiftfs, "true") == 0) {
+ // Clear source mount as target is now in place
+ if (umount2(src, MNT_DETACH) < 0) {
+ fprintf(stderr, "Failed shiftfs source unmount for %s: %s\n", src, strerror(errno));
+ _exit(1);
+ }
+ }
+
_exit(0);
}
From 6ff7c7c1d0f94e8293116d70c35c6ce5286ee843 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Wed, 24 Jul 2019 16:29:06 -0400
Subject: [PATCH 6/6] tests: Test the shift disk property
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
test/main.sh | 1 +
test/suites/container_devices_disk.sh | 32 +++++++++++++++++++++++++++
2 files changed, 33 insertions(+)
create mode 100644 test/suites/container_devices_disk.sh
diff --git a/test/main.sh b/test/main.sh
index 1e1e1b0578..6e0b6369f9 100755
--- a/test/main.sh
+++ b/test/main.sh
@@ -188,6 +188,7 @@ run_test test_projects_images "images inside projects"
run_test test_projects_images_default "images from the global default project"
run_test test_projects_storage "projects and storage pools"
run_test test_projects_network "projects and networks"
+run_test test_container_devices_disk "container devices - disk"
run_test test_container_devices_nic_p2p "container devices - nic - p2p"
run_test test_container_devices_nic_bridged "container devices - nic - bridged"
run_test test_container_devices_nic_bridged_filtering "container devices - nic - bridged - filtering"
diff --git a/test/suites/container_devices_disk.sh b/test/suites/container_devices_disk.sh
new file mode 100644
index 0000000000..e0368b25eb
--- /dev/null
+++ b/test/suites/container_devices_disk.sh
@@ -0,0 +1,32 @@
+test_container_devices_disk() {
+ ensure_import_testimage
+ ensure_has_localhost_remote "${LXD_ADDR}"
+
+ lxc launch testimage foo
+
+ test_container_devices_disk_shift
+
+ lxc delete -f foo
+}
+
+test_container_devices_disk_shift() {
+ if ! grep -q shiftfs /proc/filesystems; then
+ return
+ fi
+
+ mkdir -p "${TEST_DIR}/shift-source"
+ touch "${TEST_DIR}/shift-source/a"
+ chown 123:456 "${TEST_DIR}/shift-source/a"
+
+ lxc config device add foo shiftfs disk source="${TEST_DIR}/shift-source" path=/mnt
+ [ "$(lxc exec foo -- stat /mnt/a -c '%u:%g')" = "65534:65534" ] || false
+ lxc config device remove foo shiftfs
+
+ lxc config device add foo shiftfs disk source="${TEST_DIR}/shift-source" path=/mnt shift=true
+ [ "$(lxc exec foo -- stat /mnt/a -c '%u:%g')" = "123:456" ] || false
+
+ lxc stop foo -f
+ lxc start foo
+ [ "$(lxc exec foo -- stat /mnt/a -c '%u:%g')" = "123:456" ] || false
+ lxc stop foo -f
+}
More information about the lxc-devel
mailing list