[lxc-devel] [lxd/master] [RFC] zfs: Set canmount=noauto on all mountable datasets
stgraber on Github
lxc-bot at linuxcontainers.org
Sat Jul 8 05:08:00 UTC 2017
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 447 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20170708/82e6df84/attachment.bin>
-------------- next part --------------
From abae8e083e4f25d228aa55ba994ae619904f3d8b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Fri, 7 Jul 2017 17:41:24 -0400
Subject: [PATCH] zfs: Set canmount=noauto on all mountable datasets
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
We don't want the container host to randomly mount stuff behind our back.
Closes #3437
Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
lxd/patches.go | 58 ++++++++++++++++++++++++++++++++++++++++++++++++
lxd/storage_zfs.go | 49 +++++++++++++++++++++++++++++++++++++---
lxd/storage_zfs_utils.go | 12 +++++++---
test/suites/snapshots.sh | 2 +-
4 files changed, 114 insertions(+), 7 deletions(-)
diff --git a/lxd/patches.go b/lxd/patches.go
index 9c3786799..ce2f54989 100644
--- a/lxd/patches.go
+++ b/lxd/patches.go
@@ -44,6 +44,7 @@ var patches = []patch{
{name: "storage_api_lxd_on_btrfs", run: patchStorageApiLxdOnBtrfs},
{name: "storage_api_lvm_detect_lv_size", run: patchStorageApiDetectLVSize},
{name: "storage_api_insert_zfs_driver", run: patchStorageApiInsertZfsDriver},
+ {name: "storage_zfs_noauto", run: patchStorageZFSnoauto},
}
type patch struct {
@@ -2247,6 +2248,63 @@ func patchStorageApiInsertZfsDriver(name string, d *Daemon) error {
return nil
}
+func patchStorageZFSnoauto(name string, d *Daemon) error {
+ pools, err := dbStoragePools(d.db)
+ if err != nil {
+ if err == NoSuchObjectError {
+ return nil
+ }
+ logger.Errorf("Failed to query database: %s", err)
+ return err
+ }
+
+ for _, poolName := range pools {
+ _, pool, err := dbStoragePoolGet(d.db, poolName)
+ if err != nil {
+ logger.Errorf("Failed to query database: %s", err)
+ return err
+ }
+
+ if pool.Driver != "zfs" {
+ continue
+ }
+
+ zpool := pool.Config["zfs.pool_name"]
+ if zpool == "" {
+ continue
+ }
+ path := fmt.Sprintf("%s/containers", zpool)
+
+ output, err := shared.RunCommand(
+ "zfs",
+ "list",
+ "-t", "filesystem",
+ "-o", "name",
+ "-H",
+ "-r", path)
+ if err != nil {
+ return fmt.Errorf("Unable to list containers on zpool: %s", zpool)
+ }
+
+ for _, entry := range strings.Split(output, "\n") {
+ if entry == "" {
+ continue
+ }
+
+ if entry == path {
+ continue
+ }
+
+ _, err := shared.RunCommand("zfs", "set", "canmount=noauto", entry)
+ if err != nil {
+ return fmt.Errorf("Unable to set canmount=noauto on: %s", entry)
+ }
+ }
+ }
+
+ return nil
+}
+
// Patches end here
// Here are a couple of legacy patches that were originally in
diff --git a/lxd/storage_zfs.go b/lxd/storage_zfs.go
index 5d6b3fb2e..6e6eac9be 100644
--- a/lxd/storage_zfs.go
+++ b/lxd/storage_zfs.go
@@ -192,7 +192,7 @@ func (s *storageZfs) StoragePoolVolumeCreate() error {
dataset := fmt.Sprintf("%s/%s", poolName, fs)
customPoolVolumeMntPoint := getStoragePoolVolumeMountPoint(s.pool.Name, s.volume.Name)
- msg, err := zfsPoolVolumeCreate(dataset, "mountpoint=none")
+ msg, err := zfsPoolVolumeCreate(dataset, "mountpoint=none", "canmount=noauto")
if err != nil {
logger.Errorf("failed to create ZFS storage volume \"%s\" on storage pool \"%s\": %s", s.volume.Name, s.pool.Name, msg)
return err
@@ -535,11 +535,12 @@ func (s *storageZfs) ContainerCreate(container container) error {
containerPoolVolumeMntPoint := getContainerMountPoint(s.pool.Name, containerName)
// Create volume.
- msg, err := zfsPoolVolumeCreate(dataset, "mountpoint=none")
+ msg, err := zfsPoolVolumeCreate(dataset, "mountpoint=none", "canmount=noauto")
if err != nil {
logger.Errorf("failed to create ZFS storage volume for container \"%s\" on storage pool \"%s\": %s", s.volume.Name, s.pool.Name, msg)
return err
}
+
revert := true
defer func() {
if !revert {
@@ -554,6 +555,14 @@ func (s *storageZfs) ContainerCreate(container container) error {
return err
}
+ ourMount, err := s.ContainerMount(container)
+ if err != nil {
+ return err
+ }
+ if ourMount {
+ defer s.ContainerUmount(containerName, containerPath)
+ }
+
err = createContainerMountpoint(containerPoolVolumeMntPoint, containerPath, container.IsPrivileged())
if err != nil {
return err
@@ -620,6 +629,14 @@ func (s *storageZfs) ContainerCreateFromImage(container container, fingerprint s
s.ContainerDelete(container)
}()
+ ourMount, err := s.ContainerMount(container)
+ if err != nil {
+ return err
+ }
+ if ourMount {
+ defer s.ContainerUmount(containerName, containerPath)
+ }
+
privileged := container.IsPrivileged()
err = createContainerMountpoint(containerPoolVolumeMntPoint, containerPath, privileged)
if err != nil {
@@ -922,6 +939,12 @@ func (s *storageZfs) copyWithoutSnapshotFull(target container, source container)
targetContainerMountPoint := getContainerMountPoint(s.pool.Name, targetName)
targetfs := fmt.Sprintf("containers/%s", targetName)
+
+ err = s.zfsPoolVolumeSet(targetfs, "canmount", "noauto")
+ if err != nil {
+ return err
+ }
+
err = s.zfsPoolVolumeSet(targetfs, "mountpoint", targetContainerMountPoint)
if err != nil {
return err
@@ -932,6 +955,14 @@ func (s *storageZfs) copyWithoutSnapshotFull(target container, source container)
return err
}
+ ourMount, err := s.ContainerMount(target)
+ if err != nil {
+ return err
+ }
+ if ourMount {
+ defer s.ContainerUmount(targetName, targetContainerMountPoint)
+ }
+
err = createContainerMountpoint(targetContainerMountPoint, target.Path(), target.IsPrivileged())
if err != nil {
return err
@@ -1093,11 +1124,16 @@ func (s *storageZfs) ContainerCopy(target container, source container, container
s.zfsPoolVolumeSnapshotDestroy(fmt.Sprintf("containers/%s", target.Name()), tmpSnapshotName)
fs := fmt.Sprintf("containers/%s", target.Name())
- err = s.zfsPoolVolumeSet(fs, "mountpoint", targetContainerMountPoint)
+
+ err = s.zfsPoolVolumeSet(fs, "canmount", "noauto")
if err != nil {
return err
}
+ err = s.zfsPoolVolumeSet(fs, "mountpoint", targetContainerMountPoint)
+ if err != nil {
+ return err
+ }
}
logger.Debugf("Copied ZFS container storage %s -> %s.", source.Name(), target.Name())
@@ -1501,6 +1537,11 @@ func (s *storageZfs) ContainerSnapshotStart(container container) (bool, error) {
return false, err
}
+ err = s.zfsPoolVolumeMount(destFs)
+ if err != nil {
+ return false, err
+ }
+
logger.Debugf("Initialized ZFS storage volume for snapshot \"%s\" on storage pool \"%s\".", s.volume.Name, s.pool.Name)
return true, nil
}
@@ -1947,6 +1988,7 @@ func (s *storageZfs) zfsPoolVolumeClone(source string, name string, dest string,
"clone",
"-p",
"-o", fmt.Sprintf("mountpoint=%s", mountpoint),
+ "-o", "canmount=noauto",
fmt.Sprintf("%s/%s@%s", poolName, source, name),
fmt.Sprintf("%s/%s", poolName, dest))
if err != nil {
@@ -1977,6 +2019,7 @@ func (s *storageZfs) zfsPoolVolumeClone(source string, name string, dest string,
"clone",
"-p",
"-o", fmt.Sprintf("mountpoint=%s", snapshotMntPoint),
+ "-o", "canmount=noauto",
fmt.Sprintf("%s/%s@%s", poolName, sub, name),
fmt.Sprintf("%s/%s", poolName, destSubvol))
if err != nil {
diff --git a/lxd/storage_zfs_utils.go b/lxd/storage_zfs_utils.go
index c13229543..599a37a6e 100644
--- a/lxd/storage_zfs_utils.go
+++ b/lxd/storage_zfs_utils.go
@@ -2,15 +2,21 @@ package main
import (
"fmt"
- "strings"
"github.com/lxc/lxd/shared"
)
// zfsPoolVolumeCreate creates a ZFS dataset with a set of given properties.
func zfsPoolVolumeCreate(dataset string, properties ...string) (string, error) {
- p := strings.Join(properties, ",")
- return shared.RunCommand("zfs", "create", "-o", p, "-p", dataset)
+ cmd := []string{"zfs", "create"}
+
+ for _, prop := range properties {
+ cmd = append(cmd, []string{"-o", prop}...)
+ }
+
+ cmd = append(cmd, []string{"-p", dataset}...)
+
+ return shared.RunCommand(cmd[0], cmd[1:]...)
}
func zfsPoolVolumeSet(dataset string, key string, value string) (string, error) {
diff --git a/test/suites/snapshots.sh b/test/suites/snapshots.sh
index d3f8c598b..bf188f18c 100644
--- a/test/suites/snapshots.sh
+++ b/test/suites/snapshots.sh
@@ -44,7 +44,7 @@ snapshots() {
lxc copy foo/tester foosnap1
# FIXME: make this backend agnostic
- if [ "$lxd_backend" != "lvm" ]; then
+ if [ "$lxd_backend" != "lvm" ] && [ "${lxd_backend}" != "zfs" ]; then
[ -d "${LXD_DIR}/containers/foosnap1/rootfs" ]
fi
More information about the lxc-devel
mailing list