[lxc-devel] [lxd/master] Rework ZFS utility functions
albertodonato on Github
lxc-bot at linuxcontainers.org
Tue Aug 8 09:32:30 UTC 2017
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 505 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20170808/a7763d4b/attachment.bin>
-------------- next part --------------
From 8d4208ef81731d0dac5659534b77ec742914c21b Mon Sep 17 00:00:00 2001
From: Alberto Donato <alberto.donato at canonical.com>
Date: Mon, 7 Aug 2017 10:07:01 +0200
Subject: [PATCH 01/21] storage/zfs: move some helper functions to
storage_zfs_utils.go
Signed-off-by: Alberto Donato <alberto.donato at canonical.com>
---
lxd/storage_zfs.go | 18 ------------------
lxd/storage_zfs_utils.go | 22 ++++++++++++++++++++++
2 files changed, 22 insertions(+), 18 deletions(-)
diff --git a/lxd/storage_zfs.go b/lxd/storage_zfs.go
index e74958356..643d675bf 100644
--- a/lxd/storage_zfs.go
+++ b/lxd/storage_zfs.go
@@ -36,24 +36,6 @@ func (s *storageZfs) getOnDiskPoolName() string {
return s.pool.Name
}
-func zfsIsEnabled() bool {
- out, err := exec.LookPath("zfs")
- if err != nil || len(out) == 0 {
- return false
- }
-
- return true
-}
-
-func zfsModuleVersionGet() (string, error) {
- zfsVersion, err := ioutil.ReadFile("/sys/module/zfs/version")
- if err != nil {
- return "", fmt.Errorf("could not determine ZFS module version")
- }
-
- return strings.TrimSpace(string(zfsVersion)), nil
-}
-
// Only initialize the minimal information we need about a given storage type.
func (s *storageZfs) StorageCoreInit() error {
s.sType = storageTypeZfs
diff --git a/lxd/storage_zfs_utils.go b/lxd/storage_zfs_utils.go
index 03ff896fb..fb827ff49 100644
--- a/lxd/storage_zfs_utils.go
+++ b/lxd/storage_zfs_utils.go
@@ -2,7 +2,9 @@ package main
import (
"fmt"
+ "io/ioutil"
"os"
+ "os/exec"
"path/filepath"
"strconv"
"strings"
@@ -13,6 +15,26 @@ import (
"github.com/lxc/lxd/shared/logger"
)
+// zfsIsEnabled returns whether zfs backend is supported.
+func zfsIsEnabled() bool {
+ out, err := exec.LookPath("zfs")
+ if err != nil || len(out) == 0 {
+ return false
+ }
+
+ return true
+}
+
+// zfsModuleVersionGet returhs the ZFS module version
+func zfsModuleVersionGet() (string, error) {
+ zfsVersion, err := ioutil.ReadFile("/sys/module/zfs/version")
+ if err != nil {
+ return "", fmt.Errorf("could not determine ZFS module version")
+ }
+
+ return strings.TrimSpace(string(zfsVersion)), nil
+}
+
// zfsPoolVolumeCreate creates a ZFS dataset with a set of given properties.
func zfsPoolVolumeCreate(dataset string, properties ...string) (string, error) {
cmd := []string{"zfs", "create"}
From 413b08bcdeb6b743290cf487b5319e1fbd8a4c2d Mon Sep 17 00:00:00 2001
From: Alberto Donato <alberto.donato at canonical.com>
Date: Mon, 7 Aug 2017 11:07:09 +0200
Subject: [PATCH 02/21] storage/zfs: make zfsPoolCheck a standalone function
Signed-off-by: Alberto Donato <alberto.donato at canonical.com>
---
lxd/storage_zfs_utils.go | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lxd/storage_zfs_utils.go b/lxd/storage_zfs_utils.go
index fb827ff49..0b77e2086 100644
--- a/lxd/storage_zfs_utils.go
+++ b/lxd/storage_zfs_utils.go
@@ -55,7 +55,7 @@ func zfsPoolVolumeSet(dataset string, key string, value string) (string, error)
dataset)
}
-func (s *storageZfs) zfsPoolCheck(pool string) error {
+func zfsPoolCheck(pool string) error {
output, err := shared.RunCommand(
"zfs", "get", "type", "-H", "-o", "value", pool)
if err != nil {
@@ -165,7 +165,7 @@ func (s *storageZfs) zfsPoolCreate() error {
}
}
} else {
- err := s.zfsPoolCheck(vdev)
+ err := zfsPoolCheck(vdev)
if err != nil {
return err
}
From d785aba42beeaf375f412ba10dabd1f7e204e5cb Mon Sep 17 00:00:00 2001
From: Alberto Donato <alberto.donato at canonical.com>
Date: Mon, 7 Aug 2017 11:21:31 +0200
Subject: [PATCH 03/21] storage/zfs: make zfsFilesystemEntityDelete a
standalone function
Signed-off-by: Alberto Donato <alberto.donato at canonical.com>
---
lxd/storage_zfs.go | 2 +-
lxd/storage_zfs_utils.go | 10 ++++------
2 files changed, 5 insertions(+), 7 deletions(-)
diff --git a/lxd/storage_zfs.go b/lxd/storage_zfs.go
index 643d675bf..019cd042c 100644
--- a/lxd/storage_zfs.go
+++ b/lxd/storage_zfs.go
@@ -140,7 +140,7 @@ func (s *storageZfs) StoragePoolCreate() error {
func (s *storageZfs) StoragePoolDelete() error {
logger.Infof("Deleting ZFS storage pool \"%s\".", s.pool.Name)
- err := s.zfsFilesystemEntityDelete()
+ err := zfsFilesystemEntityDelete(s.pool.Config["source"], s.getOnDiskPoolName())
if err != nil {
return err
}
diff --git a/lxd/storage_zfs_utils.go b/lxd/storage_zfs_utils.go
index 0b77e2086..2f58f40ed 100644
--- a/lxd/storage_zfs_utils.go
+++ b/lxd/storage_zfs_utils.go
@@ -320,23 +320,21 @@ func (s *storageZfs) zfsPoolVolumeClone(source string, name string, dest string,
return nil
}
-func (s *storageZfs) zfsFilesystemEntityDelete() error {
+func zfsFilesystemEntityDelete(vdev string, pool string) error {
var output string
var err error
- poolName := s.getOnDiskPoolName()
- if strings.Contains(poolName, "/") {
+ if strings.Contains(pool, "/") {
// Command to destroy a zfs dataset.
- output, err = shared.RunCommand("zfs", "destroy", "-r", poolName)
+ output, err = shared.RunCommand("zfs", "destroy", "-r", pool)
} else {
// Command to destroy a zfs pool.
- output, err = shared.RunCommand("zpool", "destroy", "-f", poolName)
+ output, err = shared.RunCommand("zpool", "destroy", "-f", pool)
}
if err != nil {
return fmt.Errorf("Failed to delete the ZFS pool: %s", output)
}
// Cleanup storage
- vdev := s.pool.Config["source"]
if filepath.IsAbs(vdev) && !shared.IsBlockdevPath(vdev) {
os.RemoveAll(vdev)
}
From e87df547d40a3d3792039917700f50fc714b129b Mon Sep 17 00:00:00 2001
From: Alberto Donato <alberto.donato at canonical.com>
Date: Mon, 7 Aug 2017 11:31:17 +0200
Subject: [PATCH 04/21] storage/zfs: drop zfsPoolVolumeMount
Signed-off-by: Alberto Donato <alberto.donato at canonical.com>
---
lxd/storage_zfs.go | 10 +++++-----
lxd/storage_zfs_utils.go | 4 ----
2 files changed, 5 insertions(+), 9 deletions(-)
diff --git a/lxd/storage_zfs.go b/lxd/storage_zfs.go
index 019cd042c..3b8078d02 100644
--- a/lxd/storage_zfs.go
+++ b/lxd/storage_zfs.go
@@ -192,7 +192,7 @@ func (s *storageZfs) StoragePoolVolumeCreate() error {
}
if !shared.IsMountPoint(customPoolVolumeMntPoint) {
- s.zfsPoolVolumeMount(fs)
+ zfsMount(poolName, fs)
}
// apply quota
@@ -271,7 +271,7 @@ func (s *storageZfs) StoragePoolVolumeMount() (bool, error) {
var customerr error
ourMount := false
if !shared.IsMountPoint(customPoolVolumeMntPoint) {
- customerr = s.zfsPoolVolumeMount(fs)
+ customerr = zfsMount(s.getOnDiskPoolName(), fs)
ourMount = true
}
@@ -1521,7 +1521,7 @@ func (s *storageZfs) ContainerSnapshotStart(container container) (bool, error) {
return false, err
}
- err = s.zfsPoolVolumeMount(destFs)
+ err = zfsMount(s.getOnDiskPoolName(), destFs)
if err != nil {
return false, err
}
@@ -1649,7 +1649,7 @@ func (s *storageZfs) ImageCreate(fingerprint string) error {
// Make sure that the image actually got mounted.
if !shared.IsMountPoint(tmpImageDir) {
- s.zfsPoolVolumeMount(fs)
+ zfsMount(poolName, fs)
}
// Unpack the image into the temporary mountpoint.
@@ -2078,7 +2078,7 @@ func (s *storageZfs) MigrationSink(live bool, container container, snapshots []*
* but sometimes it doesn't. Let's try to mount, but not complain about
* failure.
*/
- s.zfsPoolVolumeMount(zfsName)
+ zfsMount(poolName, zfsName)
return nil
}
diff --git a/lxd/storage_zfs_utils.go b/lxd/storage_zfs_utils.go
index 2f58f40ed..885556209 100644
--- a/lxd/storage_zfs_utils.go
+++ b/lxd/storage_zfs_utils.go
@@ -620,10 +620,6 @@ func zfsMount(poolName string, path string) error {
return nil
}
-func (s *storageZfs) zfsPoolVolumeMount(path string) error {
- return zfsMount(s.getOnDiskPoolName(), path)
-}
-
func zfsUmount(poolName string, path string, mountpoint string) error {
output, err := shared.TryRunCommand(
"zfs",
From f379576a30c3fa641a182a4b7768015050be0a20 Mon Sep 17 00:00:00 2001
From: Alberto Donato <alberto.donato at canonical.com>
Date: Mon, 7 Aug 2017 11:34:46 +0200
Subject: [PATCH 05/21] storage/zfs: drop zfsPoolVolumeUmount
Signed-off-by: Alberto Donato <alberto.donato at canonical.com>
---
lxd/storage_zfs.go | 8 ++++----
lxd/storage_zfs_utils.go | 4 ----
2 files changed, 4 insertions(+), 8 deletions(-)
diff --git a/lxd/storage_zfs.go b/lxd/storage_zfs.go
index 3b8078d02..bfd27f07e 100644
--- a/lxd/storage_zfs.go
+++ b/lxd/storage_zfs.go
@@ -314,7 +314,7 @@ func (s *storageZfs) StoragePoolVolumeUmount() (bool, error) {
var customerr error
ourUmount := false
if shared.IsMountPoint(customPoolVolumeMntPoint) {
- customerr = s.zfsPoolVolumeUmount(fs, customPoolVolumeMntPoint)
+ customerr = zfsUmount(s.getOnDiskPoolName(), fs, customPoolVolumeMntPoint)
ourUmount = true
}
@@ -514,7 +514,7 @@ func (s *storageZfs) ContainerUmount(name string, path string) (bool, error) {
var imgerr error
ourUmount := false
if shared.IsMountPoint(containerPoolVolumeMntPoint) {
- imgerr = s.zfsPoolVolumeUmount(fs, containerPoolVolumeMntPoint)
+ imgerr = zfsUmount(s.getOnDiskPoolName(), fs, containerPoolVolumeMntPoint)
ourUmount = true
}
@@ -1672,7 +1672,7 @@ func (s *storageZfs) ImageCreate(fingerprint string) error {
// Make sure that the image actually got unmounted.
if shared.IsMountPoint(tmpImageDir) {
- s.zfsPoolVolumeUmount(fs, tmpImageDir)
+ zfsUmount(poolName, fs, tmpImageDir)
}
// Create a snapshot of that image on the storage pool which we clone for
@@ -1975,7 +1975,7 @@ func (s *storageZfs) MigrationSink(live bool, container container, snapshots []*
zfsName := fmt.Sprintf("containers/%s", container.Name())
containerMntPoint := getContainerMountPoint(s.pool.Name, container.Name())
if shared.IsMountPoint(containerMntPoint) {
- err := s.zfsPoolVolumeUmount(zfsName, containerMntPoint)
+ err := zfsUmount(poolName, zfsName, containerMntPoint)
if err != nil {
return err
}
diff --git a/lxd/storage_zfs_utils.go b/lxd/storage_zfs_utils.go
index 885556209..ce1c9f13c 100644
--- a/lxd/storage_zfs_utils.go
+++ b/lxd/storage_zfs_utils.go
@@ -637,10 +637,6 @@ func zfsUmount(poolName string, path string, mountpoint string) error {
return nil
}
-func (s *storageZfs) zfsPoolVolumeUmount(path string, mountpoint string) error {
- return zfsUmount(s.getOnDiskPoolName(), path, mountpoint)
-}
-
func (s *storageZfs) zfsPoolListSubvolumes(path string) ([]string, error) {
output, err := shared.RunCommand(
"zfs",
From 105d447947b07fb4de86c3614bd699c71b980981 Mon Sep 17 00:00:00 2001
From: Alberto Donato <alberto.donato at canonical.com>
Date: Mon, 7 Aug 2017 11:41:19 +0200
Subject: [PATCH 06/21] storage/zfs: make zfsPoolListSnapshots a standalone
function
Signed-off-by: Alberto Donato <alberto.donato at canonical.com>
---
lxd/storage_zfs.go | 6 +++---
lxd/storage_zfs_utils.go | 13 ++++++-------
2 files changed, 9 insertions(+), 10 deletions(-)
diff --git a/lxd/storage_zfs.go b/lxd/storage_zfs.go
index bfd27f07e..5055b3efd 100644
--- a/lxd/storage_zfs.go
+++ b/lxd/storage_zfs.go
@@ -710,7 +710,7 @@ func (s *storageZfs) ContainerDelete(container container) error {
if s.zfsFilesystemEntityExists(fs, true) {
removable := true
- snaps, err := s.zfsPoolListSnapshots(fs)
+ snaps, err := zfsPoolListSnapshots(s.getOnDiskPoolName(), fs)
if err != nil {
return err
}
@@ -1898,7 +1898,7 @@ func (s *storageZfs) MigrationSource(ct container, containerOnly bool) (Migratio
* is that we send the oldest to newest snapshot, hopefully saving on
* xfer costs. Then, after all that, we send the container itself.
*/
- snapshots, err := s.zfsPoolListSnapshots(fmt.Sprintf("containers/%s", ct.Name()))
+ snapshots, err := zfsPoolListSnapshots(s.getOnDiskPoolName(), fmt.Sprintf("containers/%s", ct.Name()))
if err != nil {
return nil, err
}
@@ -2043,7 +2043,7 @@ func (s *storageZfs) MigrationSink(live bool, container container, snapshots []*
defer func() {
/* clean up our migration-send snapshots that we got from recv. */
- zfsSnapshots, err := s.zfsPoolListSnapshots(fmt.Sprintf("containers/%s", container.Name()))
+ zfsSnapshots, err := zfsPoolListSnapshots(poolName, fmt.Sprintf("containers/%s", container.Name()))
if err != nil {
logger.Errorf("failed listing snapshots post migration: %s.", err)
return
diff --git a/lxd/storage_zfs_utils.go b/lxd/storage_zfs_utils.go
index ce1c9f13c..21adaefd9 100644
--- a/lxd/storage_zfs_utils.go
+++ b/lxd/storage_zfs_utils.go
@@ -291,7 +291,7 @@ func (s *storageZfs) zfsPoolVolumeClone(source string, name string, dest string,
}
for _, sub := range subvols {
- snaps, err := s.zfsPoolListSnapshots(sub)
+ snaps, err := zfsPoolListSnapshots(poolName, sub)
if err != nil {
return err
}
@@ -391,7 +391,7 @@ func (s *storageZfs) zfsPoolVolumeCleanup(path string) error {
// Check if the parent can now be deleted
subPath := strings.SplitN(path, "@", 2)[0]
- snaps, err := s.zfsPoolListSnapshots(subPath)
+ snaps, err := zfsPoolListSnapshots(s.getOnDiskPoolName(), subPath)
if err != nil {
return err
}
@@ -570,7 +570,7 @@ func (s *storageZfs) zfsPoolVolumeSnapshotRestore(path string, name string) erro
}
for _, sub := range subvols {
- snaps, err := s.zfsPoolListSnapshots(sub)
+ snaps, err := zfsPoolListSnapshots(poolName, sub)
if err != nil {
return err
}
@@ -667,12 +667,11 @@ func (s *storageZfs) zfsPoolListSubvolumes(path string) ([]string, error) {
return children, nil
}
-func (s *storageZfs) zfsPoolListSnapshots(path string) ([]string, error) {
- poolName := s.getOnDiskPoolName()
+func zfsPoolListSnapshots(pool string, path string) ([]string, error) {
path = strings.TrimRight(path, "/")
- fullPath := poolName
+ fullPath := pool
if path != "" {
- fullPath = fmt.Sprintf("%s/%s", poolName, path)
+ fullPath = fmt.Sprintf("%s/%s", pool, path)
}
output, err := shared.RunCommand(
From 9584d741868b19f6ef75fe9d504cbda0646a1459 Mon Sep 17 00:00:00 2001
From: Alberto Donato <alberto.donato at canonical.com>
Date: Mon, 7 Aug 2017 12:00:52 +0200
Subject: [PATCH 07/21] storage/zfs: make zfsPoolListSubvolumes a standalone
function
Signed-off-by: Alberto Donato <alberto.donato at canonical.com>
---
lxd/storage_zfs_utils.go | 13 ++++++-------
1 file changed, 6 insertions(+), 7 deletions(-)
diff --git a/lxd/storage_zfs_utils.go b/lxd/storage_zfs_utils.go
index 21adaefd9..d816c0e32 100644
--- a/lxd/storage_zfs_utils.go
+++ b/lxd/storage_zfs_utils.go
@@ -170,7 +170,7 @@ func (s *storageZfs) zfsPoolCreate() error {
return err
}
- subvols, err := s.zfsPoolListSubvolumes(vdev)
+ subvols, err := zfsPoolListSubvolumes(zpoolName, vdev)
if err != nil {
return err
}
@@ -285,7 +285,7 @@ func (s *storageZfs) zfsPoolVolumeClone(source string, name string, dest string,
return fmt.Errorf("Failed to clone the filesystem: %s", output)
}
- subvols, err := s.zfsPoolListSubvolumes(fmt.Sprintf("%s/%s", poolName, source))
+ subvols, err := zfsPoolListSubvolumes(poolName, fmt.Sprintf("%s/%s", poolName, source))
if err != nil {
return err
}
@@ -564,7 +564,7 @@ func (s *storageZfs) zfsPoolVolumeSnapshotRestore(path string, name string) erro
return fmt.Errorf("Failed to restore ZFS snapshot: %s", output)
}
- subvols, err := s.zfsPoolListSubvolumes(fmt.Sprintf("%s/%s", poolName, path))
+ subvols, err := zfsPoolListSubvolumes(poolName, fmt.Sprintf("%s/%s", poolName, path))
if err != nil {
return err
}
@@ -637,7 +637,7 @@ func zfsUmount(poolName string, path string, mountpoint string) error {
return nil
}
-func (s *storageZfs) zfsPoolListSubvolumes(path string) ([]string, error) {
+func zfsPoolListSubvolumes(pool string, path string) ([]string, error) {
output, err := shared.RunCommand(
"zfs",
"list",
@@ -660,8 +660,7 @@ func (s *storageZfs) zfsPoolListSubvolumes(path string) ([]string, error) {
continue
}
- poolName := s.getOnDiskPoolName()
- children = append(children, strings.TrimPrefix(entry, fmt.Sprintf("%s/", poolName)))
+ children = append(children, strings.TrimPrefix(entry, fmt.Sprintf("%s/", pool)))
}
return children, nil
@@ -726,7 +725,7 @@ func (s *storageZfs) zfsPoolVolumeSnapshotRemovable(path string, name string) (b
func (s *storageZfs) zfsPoolGetUsers() ([]string, error) {
poolName := s.getOnDiskPoolName()
- subvols, err := s.zfsPoolListSubvolumes(poolName)
+ subvols, err := zfsPoolListSubvolumes(poolName, poolName)
if err != nil {
return []string{}, err
}
From a9b41e81d94351236606439e10f714933d384cbd Mon Sep 17 00:00:00 2001
From: Alberto Donato <alberto.donato at canonical.com>
Date: Mon, 7 Aug 2017 12:19:20 +0200
Subject: [PATCH 08/21] storage/zfs: make zfsFilesystemEntityPropertyGet a
standalone function
Signed-off-by: Alberto Donato <alberto.donato at canonical.com>
---
lxd/storage_zfs.go | 14 +++++++++-----
lxd/storage_zfs_utils.go | 28 +++++++++++++++-------------
2 files changed, 24 insertions(+), 18 deletions(-)
diff --git a/lxd/storage_zfs.go b/lxd/storage_zfs.go
index 5055b3efd..3927474d4 100644
--- a/lxd/storage_zfs.go
+++ b/lxd/storage_zfs.go
@@ -704,13 +704,14 @@ func (s *storageZfs) ContainerCanRestore(container container, sourceContainer co
func (s *storageZfs) ContainerDelete(container container) error {
logger.Debugf("Deleting ZFS storage volume for container \"%s\" on storage pool \"%s\".", s.volume.Name, s.pool.Name)
+ poolName := s.getOnDiskPoolName()
containerName := container.Name()
fs := fmt.Sprintf("containers/%s", containerName)
containerPoolVolumeMntPoint := getContainerMountPoint(s.pool.Name, containerName)
if s.zfsFilesystemEntityExists(fs, true) {
removable := true
- snaps, err := zfsPoolListSnapshots(s.getOnDiskPoolName(), fs)
+ snaps, err := zfsPoolListSnapshots(poolName, fs)
if err != nil {
return err
}
@@ -728,7 +729,7 @@ func (s *storageZfs) ContainerDelete(container container) error {
}
if removable {
- origin, err := s.zfsFilesystemEntityPropertyGet(fs, "origin", true)
+ origin, err := zfsFilesystemEntityPropertyGet(poolName, fs, "origin", true)
if err != nil {
return err
}
@@ -1309,7 +1310,7 @@ func (s *storageZfs) ContainerGetUsage(container container) (int64, error) {
property = "usedbydataset"
}
- value, err := s.zfsFilesystemEntityPropertyGet(fs, property, true)
+ value, err := zfsFilesystemEntityPropertyGet(s.getOnDiskPoolName(), fs, property, true)
if err != nil {
return -1, err
}
@@ -1381,7 +1382,9 @@ func (s *storageZfs) ContainerSnapshotDelete(snapshotContainer container) error
return err
}
} else {
- err = s.zfsPoolVolumeSnapshotRename(fmt.Sprintf("containers/%s", sourceContainerName), snapName, fmt.Sprintf("copy-%s", uuid.NewRandom().String()))
+ err = zfsPoolVolumeSnapshotRename(
+ s.getOnDiskPoolName(), fmt.Sprintf("containers/%s", sourceContainerName), snapName,
+ fmt.Sprintf("copy-%s", uuid.NewRandom().String()))
if err != nil {
return err
}
@@ -1455,7 +1458,8 @@ func (s *storageZfs) ContainerSnapshotRename(snapshotContainer container, newNam
newZfsDatasetName := fmt.Sprintf("snapshot-%s", newSnapOnlyName)
if oldZfsDatasetName != newZfsDatasetName {
- err := s.zfsPoolVolumeSnapshotRename(fmt.Sprintf("containers/%s", oldcName), oldZfsDatasetName, newZfsDatasetName)
+ err := zfsPoolVolumeSnapshotRename(
+ s.getOnDiskPoolName(), fmt.Sprintf("containers/%s", oldcName), oldZfsDatasetName, newZfsDatasetName)
if err != nil {
return err
}
diff --git a/lxd/storage_zfs_utils.go b/lxd/storage_zfs_utils.go
index d816c0e32..8cbc6e584 100644
--- a/lxd/storage_zfs_utils.go
+++ b/lxd/storage_zfs_utils.go
@@ -343,7 +343,8 @@ func zfsFilesystemEntityDelete(vdev string, pool string) error {
}
func (s *storageZfs) zfsPoolVolumeDestroy(path string) error {
- mountpoint, err := s.zfsFilesystemEntityPropertyGet(path, "mountpoint", true)
+ poolName := s.getOnDiskPoolName()
+ mountpoint, err := zfsFilesystemEntityPropertyGet(poolName, path, "mountpoint", true)
if err != nil {
return err
}
@@ -356,7 +357,6 @@ func (s *storageZfs) zfsPoolVolumeDestroy(path string) error {
}
}
- poolName := s.getOnDiskPoolName()
// Due to open fds or kernel refs, this may fail for a bit, give it 10s
output, err := shared.TryRunCommand(
"zfs",
@@ -373,6 +373,8 @@ func (s *storageZfs) zfsPoolVolumeDestroy(path string) error {
}
func (s *storageZfs) zfsPoolVolumeCleanup(path string) error {
+ poolName := s.getOnDiskPoolName()
+
if strings.HasPrefix(path, "deleted/") {
// Cleanup of filesystems kept for refcount reason
removablePath, err := s.zfsPoolVolumeSnapshotRemovable(path, "")
@@ -391,7 +393,7 @@ func (s *storageZfs) zfsPoolVolumeCleanup(path string) error {
// Check if the parent can now be deleted
subPath := strings.SplitN(path, "@", 2)[0]
- snaps, err := zfsPoolListSnapshots(s.getOnDiskPoolName(), subPath)
+ snaps, err := zfsPoolListSnapshots(poolName, subPath)
if err != nil {
return err
}
@@ -404,7 +406,7 @@ func (s *storageZfs) zfsPoolVolumeCleanup(path string) error {
}
} else {
// Cleanup filesystems
- origin, err := s.zfsFilesystemEntityPropertyGet(path, "origin", true)
+ origin, err := zfsFilesystemEntityPropertyGet(poolName, path, "origin", true)
if err != nil {
return err
}
@@ -439,13 +441,14 @@ func (s *storageZfs) zfsPoolVolumeCleanup(path string) error {
}
func (s *storageZfs) zfsFilesystemEntityExists(path string, prefixPathWithPool bool) bool {
- output, _ := s.zfsFilesystemEntityPropertyGet(path, "name", prefixPathWithPool)
+ poolName := s.getOnDiskPoolName()
+ output, _ := zfsFilesystemEntityPropertyGet(poolName, path, "name", prefixPathWithPool)
// If prefixPathWithPool is false we assume that the path passed in
// already is a valid zfs entity we want to check for.
fsToCheck := path
if prefixPathWithPool {
- fsToCheck = fmt.Sprintf("%s/%s", s.getOnDiskPoolName(), path)
+ fsToCheck = fmt.Sprintf("%s/%s", poolName, path)
}
if output == fsToCheck {
return true
@@ -454,12 +457,12 @@ func (s *storageZfs) zfsFilesystemEntityExists(path string, prefixPathWithPool b
return false
}
-func (s *storageZfs) zfsFilesystemEntityPropertyGet(path string, key string, prefixPathWithPool bool) (string, error) {
+func zfsFilesystemEntityPropertyGet(pool string, path string, key string, prefixPathWithPool bool) (string, error) {
// If prefixPathWithPool is false we assume that the path passed in
// already is a valid zfs entity we want to check for.
fsToCheck := path
if prefixPathWithPool {
- fsToCheck = fmt.Sprintf("%s/%s", s.getOnDiskPoolName(), path)
+ fsToCheck = fmt.Sprintf("%s/%s", pool, path)
}
output, err := shared.RunCommand(
@@ -592,14 +595,13 @@ func (s *storageZfs) zfsPoolVolumeSnapshotRestore(path string, name string) erro
return nil
}
-func (s *storageZfs) zfsPoolVolumeSnapshotRename(path string, oldName string, newName string) error {
- poolName := s.getOnDiskPoolName()
+func zfsPoolVolumeSnapshotRename(pool string, path string, oldName string, newName string) error {
output, err := shared.RunCommand(
"zfs",
"rename",
"-r",
- fmt.Sprintf("%s/%s@%s", poolName, path, oldName),
- fmt.Sprintf("%s/%s@%s", poolName, path, newName))
+ fmt.Sprintf("%s/%s@%s", pool, path, oldName),
+ fmt.Sprintf("%s/%s@%s", pool, path, newName))
if err != nil {
logger.Errorf("zfs snapshot rename failed: %s.", output)
return fmt.Errorf("Failed to rename ZFS snapshot: %s", output)
@@ -711,7 +713,7 @@ func (s *storageZfs) zfsPoolVolumeSnapshotRemovable(path string, name string) (b
snap = fmt.Sprintf("%s@%s", path, name)
}
- clones, err := s.zfsFilesystemEntityPropertyGet(snap, "clones", true)
+ clones, err := zfsFilesystemEntityPropertyGet(s.getOnDiskPoolName(), snap, "clones", true)
if err != nil {
return false, err
}
From 03cc6ba61304dcc6c87a6ad185d690af523408ba Mon Sep 17 00:00:00 2001
From: Alberto Donato <alberto.donato at canonical.com>
Date: Mon, 7 Aug 2017 12:28:27 +0200
Subject: [PATCH 09/21] storage/zfs: make zfsPoolVolumeDestroy a standalone
function
Signed-off-by: Alberto Donato <alberto.donato at canonical.com>
---
lxd/storage_zfs.go | 14 ++++++++------
lxd/storage_zfs_utils.go | 14 ++++++--------
2 files changed, 14 insertions(+), 14 deletions(-)
diff --git a/lxd/storage_zfs.go b/lxd/storage_zfs.go
index 3927474d4..e134d1d2b 100644
--- a/lxd/storage_zfs.go
+++ b/lxd/storage_zfs.go
@@ -220,7 +220,7 @@ func (s *storageZfs) StoragePoolVolumeDelete() error {
fs := fmt.Sprintf("custom/%s", s.volume.Name)
customPoolVolumeMntPoint := getStoragePoolVolumeMountPoint(s.pool.Name, s.volume.Name)
- err := s.zfsPoolVolumeDestroy(fs)
+ err := zfsPoolVolumeDestroy(s.getOnDiskPoolName(), fs)
if err != nil {
return err
}
@@ -736,7 +736,7 @@ func (s *storageZfs) ContainerDelete(container container) error {
poolName := s.getOnDiskPoolName()
origin = strings.TrimPrefix(origin, fmt.Sprintf("%s/", poolName))
- err = s.zfsPoolVolumeDestroy(fs)
+ err = zfsPoolVolumeDestroy(poolName, fs)
if err != nil {
return err
}
@@ -764,7 +764,7 @@ func (s *storageZfs) ContainerDelete(container container) error {
}
snapshotZfsDataset := fmt.Sprintf("snapshots/%s", containerName)
- s.zfsPoolVolumeDestroy(snapshotZfsDataset)
+ zfsPoolVolumeDestroy(poolName, snapshotZfsDataset)
// Delete potential leftover snapshot mountpoints.
snapshotMntPoint := getSnapshotMountPoint(s.pool.Name, containerName)
@@ -790,6 +790,8 @@ func (s *storageZfs) ContainerDelete(container container) error {
}
func (s *storageZfs) copyWithoutSnapshotsSparse(target container, source container) error {
+ poolName := s.getOnDiskPoolName()
+
sourceContainerName := source.Name()
sourceContainerPath := source.Path()
@@ -839,7 +841,7 @@ func (s *storageZfs) copyWithoutSnapshotsSparse(target container, source contain
if !revert {
return
}
- s.zfsPoolVolumeDestroy(targetZfsDataset)
+ zfsPoolVolumeDestroy(poolName, targetZfsDataset)
}()
ourMount, err := s.ContainerMount(target)
@@ -1540,7 +1542,7 @@ func (s *storageZfs) ContainerSnapshotStop(container container) (bool, error) {
cName, sName, _ := containerGetParentAndSnapshotName(container.Name())
destFs := fmt.Sprintf("snapshots/%s/%s", cName, sName)
- err := s.zfsPoolVolumeDestroy(destFs)
+ err := zfsPoolVolumeDestroy(s.getOnDiskPoolName(), destFs)
if err != nil {
return false, err
}
@@ -1704,7 +1706,7 @@ func (s *storageZfs) ImageDelete(fingerprint string) error {
}
if removable {
- err := s.zfsPoolVolumeDestroy(fs)
+ err := zfsPoolVolumeDestroy(s.getOnDiskPoolName(), fs)
if err != nil {
return err
}
diff --git a/lxd/storage_zfs_utils.go b/lxd/storage_zfs_utils.go
index 8cbc6e584..a963fc45d 100644
--- a/lxd/storage_zfs_utils.go
+++ b/lxd/storage_zfs_utils.go
@@ -342,9 +342,8 @@ func zfsFilesystemEntityDelete(vdev string, pool string) error {
return nil
}
-func (s *storageZfs) zfsPoolVolumeDestroy(path string) error {
- poolName := s.getOnDiskPoolName()
- mountpoint, err := zfsFilesystemEntityPropertyGet(poolName, path, "mountpoint", true)
+func zfsPoolVolumeDestroy(pool string, path string) error {
+ mountpoint, err := zfsFilesystemEntityPropertyGet(pool, path, "mountpoint", true)
if err != nil {
return err
}
@@ -362,7 +361,7 @@ func (s *storageZfs) zfsPoolVolumeDestroy(path string) error {
"zfs",
"destroy",
"-r",
- fmt.Sprintf("%s/%s", poolName, path))
+ fmt.Sprintf("%s/%s", pool, path))
if err != nil {
logger.Errorf("zfs destroy failed: %s.", output)
@@ -386,7 +385,7 @@ func (s *storageZfs) zfsPoolVolumeCleanup(path string) error {
if removablePath {
if strings.Contains(path, "@") {
// Cleanup snapshots
- err = s.zfsPoolVolumeDestroy(path)
+ err = zfsPoolVolumeDestroy(poolName, path)
if err != nil {
return err
}
@@ -410,10 +409,9 @@ func (s *storageZfs) zfsPoolVolumeCleanup(path string) error {
if err != nil {
return err
}
- poolName := s.getOnDiskPoolName()
origin = strings.TrimPrefix(origin, fmt.Sprintf("%s/", poolName))
- err = s.zfsPoolVolumeDestroy(path)
+ err = zfsPoolVolumeDestroy(poolName, path)
if err != nil {
return err
}
@@ -431,7 +429,7 @@ func (s *storageZfs) zfsPoolVolumeCleanup(path string) error {
}
} else if strings.HasPrefix(path, "containers") && strings.Contains(path, "@copy-") {
// Just remove the copy- snapshot for copies of active containers
- err := s.zfsPoolVolumeDestroy(path)
+ err := zfsPoolVolumeDestroy(poolName, path)
if err != nil {
return err
}
From abca18bf9295c05da834ed2d7bb390443c066b01 Mon Sep 17 00:00:00 2001
From: Alberto Donato <alberto.donato at canonical.com>
Date: Mon, 7 Aug 2017 12:35:09 +0200
Subject: [PATCH 10/21] storage/zfs: make zfsPoolVolumeSnapshotRemovable a
standalone function
Signed-off-by: Alberto Donato <alberto.donato at canonical.com>
---
lxd/storage_zfs.go | 9 +++++----
lxd/storage_zfs_utils.go | 6 +++---
2 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/lxd/storage_zfs.go b/lxd/storage_zfs.go
index e134d1d2b..868818926 100644
--- a/lxd/storage_zfs.go
+++ b/lxd/storage_zfs.go
@@ -718,7 +718,7 @@ func (s *storageZfs) ContainerDelete(container container) error {
for _, snap := range snaps {
var err error
- removable, err = s.zfsPoolVolumeSnapshotRemovable(fs, snap)
+ removable, err = zfsPoolVolumeSnapshotRemovable(poolName, fs, snap)
if err != nil {
return err
}
@@ -1377,7 +1377,7 @@ func (s *storageZfs) ContainerSnapshotDelete(snapshotContainer container) error
snapName := fmt.Sprintf("snapshot-%s", sourceContainerSnapOnlyName)
if s.zfsFilesystemEntityExists(fmt.Sprintf("containers/%s@%s", sourceContainerName, snapName), true) {
- removable, err := s.zfsPoolVolumeSnapshotRemovable(fmt.Sprintf("containers/%s", sourceContainerName), snapName)
+ removable, err := zfsPoolVolumeSnapshotRemovable(s.getOnDiskPoolName(), fmt.Sprintf("containers/%s", sourceContainerName), snapName)
if removable {
err = s.zfsPoolVolumeSnapshotDestroy(fmt.Sprintf("containers/%s", sourceContainerName), snapName)
if err != nil {
@@ -1697,16 +1697,17 @@ func (s *storageZfs) ImageCreate(fingerprint string) error {
func (s *storageZfs) ImageDelete(fingerprint string) error {
logger.Debugf("Deleting ZFS storage volume for image \"%s\" on storage pool \"%s\".", fingerprint, s.pool.Name)
+ poolName := s.getOnDiskPoolName()
fs := fmt.Sprintf("images/%s", fingerprint)
if s.zfsFilesystemEntityExists(fs, true) {
- removable, err := s.zfsPoolVolumeSnapshotRemovable(fs, "readonly")
+ removable, err := zfsPoolVolumeSnapshotRemovable(poolName, fs, "readonly")
if err != nil {
return err
}
if removable {
- err := zfsPoolVolumeDestroy(s.getOnDiskPoolName(), fs)
+ err := zfsPoolVolumeDestroy(poolName, fs)
if err != nil {
return err
}
diff --git a/lxd/storage_zfs_utils.go b/lxd/storage_zfs_utils.go
index a963fc45d..370ed7191 100644
--- a/lxd/storage_zfs_utils.go
+++ b/lxd/storage_zfs_utils.go
@@ -376,7 +376,7 @@ func (s *storageZfs) zfsPoolVolumeCleanup(path string) error {
if strings.HasPrefix(path, "deleted/") {
// Cleanup of filesystems kept for refcount reason
- removablePath, err := s.zfsPoolVolumeSnapshotRemovable(path, "")
+ removablePath, err := zfsPoolVolumeSnapshotRemovable(poolName, path, "")
if err != nil {
return err
}
@@ -703,7 +703,7 @@ func zfsPoolListSnapshots(pool string, path string) ([]string, error) {
return children, nil
}
-func (s *storageZfs) zfsPoolVolumeSnapshotRemovable(path string, name string) (bool, error) {
+func zfsPoolVolumeSnapshotRemovable(pool string, path string, name string) (bool, error) {
var snap string
if name == "" {
snap = path
@@ -711,7 +711,7 @@ func (s *storageZfs) zfsPoolVolumeSnapshotRemovable(path string, name string) (b
snap = fmt.Sprintf("%s@%s", path, name)
}
- clones, err := zfsFilesystemEntityPropertyGet(s.getOnDiskPoolName(), snap, "clones", true)
+ clones, err := zfsFilesystemEntityPropertyGet(pool, snap, "clones", true)
if err != nil {
return false, err
}
From 55e250124fd4e5e701c9ae22be949bfd3951e0af Mon Sep 17 00:00:00 2001
From: Alberto Donato <alberto.donato at canonical.com>
Date: Mon, 7 Aug 2017 12:37:14 +0200
Subject: [PATCH 11/21] storage/zfs: make zfsPoolVolumeCleanup a standalone
function
Signed-off-by: Alberto Donato <alberto.donato at canonical.com>
---
lxd/storage_zfs.go | 2 +-
lxd/storage_zfs_utils.go | 22 ++++++++++------------
2 files changed, 11 insertions(+), 13 deletions(-)
diff --git a/lxd/storage_zfs.go b/lxd/storage_zfs.go
index 868818926..c480c90ea 100644
--- a/lxd/storage_zfs.go
+++ b/lxd/storage_zfs.go
@@ -741,7 +741,7 @@ func (s *storageZfs) ContainerDelete(container container) error {
return err
}
- err = s.zfsPoolVolumeCleanup(origin)
+ err = zfsPoolVolumeCleanup(poolName, origin)
if err != nil {
return err
}
diff --git a/lxd/storage_zfs_utils.go b/lxd/storage_zfs_utils.go
index 370ed7191..2781ec148 100644
--- a/lxd/storage_zfs_utils.go
+++ b/lxd/storage_zfs_utils.go
@@ -371,12 +371,10 @@ func zfsPoolVolumeDestroy(pool string, path string) error {
return nil
}
-func (s *storageZfs) zfsPoolVolumeCleanup(path string) error {
- poolName := s.getOnDiskPoolName()
-
+func zfsPoolVolumeCleanup(pool string, path string) error {
if strings.HasPrefix(path, "deleted/") {
// Cleanup of filesystems kept for refcount reason
- removablePath, err := zfsPoolVolumeSnapshotRemovable(poolName, path, "")
+ removablePath, err := zfsPoolVolumeSnapshotRemovable(pool, path, "")
if err != nil {
return err
}
@@ -385,40 +383,40 @@ func (s *storageZfs) zfsPoolVolumeCleanup(path string) error {
if removablePath {
if strings.Contains(path, "@") {
// Cleanup snapshots
- err = zfsPoolVolumeDestroy(poolName, path)
+ err = zfsPoolVolumeDestroy(pool, path)
if err != nil {
return err
}
// Check if the parent can now be deleted
subPath := strings.SplitN(path, "@", 2)[0]
- snaps, err := zfsPoolListSnapshots(poolName, subPath)
+ snaps, err := zfsPoolListSnapshots(pool, subPath)
if err != nil {
return err
}
if len(snaps) == 0 {
- err := s.zfsPoolVolumeCleanup(subPath)
+ err := zfsPoolVolumeCleanup(pool, subPath)
if err != nil {
return err
}
}
} else {
// Cleanup filesystems
- origin, err := zfsFilesystemEntityPropertyGet(poolName, path, "origin", true)
+ origin, err := zfsFilesystemEntityPropertyGet(pool, path, "origin", true)
if err != nil {
return err
}
- origin = strings.TrimPrefix(origin, fmt.Sprintf("%s/", poolName))
+ origin = strings.TrimPrefix(origin, fmt.Sprintf("%s/", pool))
- err = zfsPoolVolumeDestroy(poolName, path)
+ err = zfsPoolVolumeDestroy(pool, path)
if err != nil {
return err
}
// Attempt to remove its parent
if origin != "-" {
- err := s.zfsPoolVolumeCleanup(origin)
+ err := zfsPoolVolumeCleanup(pool, origin)
if err != nil {
return err
}
@@ -429,7 +427,7 @@ func (s *storageZfs) zfsPoolVolumeCleanup(path string) error {
}
} else if strings.HasPrefix(path, "containers") && strings.Contains(path, "@copy-") {
// Just remove the copy- snapshot for copies of active containers
- err := zfsPoolVolumeDestroy(poolName, path)
+ err := zfsPoolVolumeDestroy(pool, path)
if err != nil {
return err
}
From fdae529d644c4f028be4b393716c1c1d24a4f364 Mon Sep 17 00:00:00 2001
From: Alberto Donato <alberto.donato at canonical.com>
Date: Mon, 7 Aug 2017 12:50:40 +0200
Subject: [PATCH 12/21] storage/zfs: make zfsPoolVolumeSnapshotRestore a
standalone function
Signed-off-by: Alberto Donato <alberto.donato at canonical.com>
---
lxd/storage_zfs.go | 2 +-
lxd/storage_zfs_utils.go | 11 +++++------
2 files changed, 6 insertions(+), 7 deletions(-)
diff --git a/lxd/storage_zfs.go b/lxd/storage_zfs.go
index c480c90ea..78f7ab805 100644
--- a/lxd/storage_zfs.go
+++ b/lxd/storage_zfs.go
@@ -1285,7 +1285,7 @@ func (s *storageZfs) ContainerRestore(target container, source container) error
cName, snapOnlyName, _ := containerGetParentAndSnapshotName(source.Name())
snapName := fmt.Sprintf("snapshot-%s", snapOnlyName)
- err = s.zfsPoolVolumeSnapshotRestore(fmt.Sprintf("containers/%s", cName), snapName)
+ err = zfsPoolVolumeSnapshotRestore(s.getOnDiskPoolName(), fmt.Sprintf("containers/%s", cName), snapName)
if err != nil {
return err
}
diff --git a/lxd/storage_zfs_utils.go b/lxd/storage_zfs_utils.go
index 2781ec148..dcfcd8dd7 100644
--- a/lxd/storage_zfs_utils.go
+++ b/lxd/storage_zfs_utils.go
@@ -552,24 +552,23 @@ func (s *storageZfs) zfsPoolVolumeSnapshotDestroy(path string, name string) erro
return nil
}
-func (s *storageZfs) zfsPoolVolumeSnapshotRestore(path string, name string) error {
- poolName := s.getOnDiskPoolName()
+func zfsPoolVolumeSnapshotRestore(pool string, path string, name string) error {
output, err := shared.TryRunCommand(
"zfs",
"rollback",
- fmt.Sprintf("%s/%s@%s", poolName, path, name))
+ fmt.Sprintf("%s/%s@%s", pool, path, name))
if err != nil {
logger.Errorf("zfs rollback failed: %s.", output)
return fmt.Errorf("Failed to restore ZFS snapshot: %s", output)
}
- subvols, err := zfsPoolListSubvolumes(poolName, fmt.Sprintf("%s/%s", poolName, path))
+ subvols, err := zfsPoolListSubvolumes(pool, fmt.Sprintf("%s/%s", pool, path))
if err != nil {
return err
}
for _, sub := range subvols {
- snaps, err := zfsPoolListSnapshots(poolName, sub)
+ snaps, err := zfsPoolListSnapshots(pool, sub)
if err != nil {
return err
}
@@ -581,7 +580,7 @@ func (s *storageZfs) zfsPoolVolumeSnapshotRestore(path string, name string) erro
output, err := shared.TryRunCommand(
"zfs",
"rollback",
- fmt.Sprintf("%s/%s@%s", poolName, sub, name))
+ fmt.Sprintf("%s/%s@%s", pool, sub, name))
if err != nil {
logger.Errorf("zfs rollback failed: %s.", output)
return fmt.Errorf("Failed to restore ZFS sub-volume snapshot: %s", output)
From 29b6ef3fc8af49c448d0eb3b823217d673a0df14 Mon Sep 17 00:00:00 2001
From: Alberto Donato <alberto.donato at canonical.com>
Date: Mon, 7 Aug 2017 12:54:32 +0200
Subject: [PATCH 13/21] storage/zfs: make zfsPoolVolumeSnapshotDestroy a
standalone function
Signed-off-by: Alberto Donato <alberto.donato at canonical.com>
---
lxd/storage_zfs.go | 24 +++++++++++++-----------
lxd/storage_zfs_utils.go | 5 ++---
2 files changed, 15 insertions(+), 14 deletions(-)
diff --git a/lxd/storage_zfs.go b/lxd/storage_zfs.go
index 78f7ab805..2faac6b5c 100644
--- a/lxd/storage_zfs.go
+++ b/lxd/storage_zfs.go
@@ -822,7 +822,7 @@ func (s *storageZfs) copyWithoutSnapshotsSparse(target container, source contain
if !revert {
return
}
- s.zfsPoolVolumeSnapshotDestroy(sourceZfsDataset, sourceZfsDatasetSnapshot)
+ zfsPoolVolumeSnapshotDestroy(poolName, sourceZfsDataset, sourceZfsDatasetSnapshot)
}()
}
} else {
@@ -921,7 +921,7 @@ func (s *storageZfs) copyWithoutSnapshotFull(target container, source container)
return err
}
defer func() {
- err := s.zfsPoolVolumeSnapshotDestroy(fs, snapshotSuffix)
+ err := zfsPoolVolumeSnapshotDestroy(poolName, fs, snapshotSuffix)
if err != nil {
logger.Warnf("Failed to delete temporary ZFS snapshot \"%s\". Manual cleanup needed.", sourceDataset)
}
@@ -970,7 +970,7 @@ func (s *storageZfs) copyWithoutSnapshotFull(target container, source container)
return err
}
- err = s.zfsPoolVolumeSnapshotDestroy(targetfs, snapshotSuffix)
+ err = zfsPoolVolumeSnapshotDestroy(poolName, targetfs, snapshotSuffix)
if err != nil {
return err
}
@@ -1140,8 +1140,8 @@ func (s *storageZfs) ContainerCopy(target container, source container, container
return err
}
- s.zfsPoolVolumeSnapshotDestroy(fmt.Sprintf("containers/%s", source.Name()), tmpSnapshotName)
- s.zfsPoolVolumeSnapshotDestroy(fmt.Sprintf("containers/%s", target.Name()), tmpSnapshotName)
+ zfsPoolVolumeSnapshotDestroy(poolName, fmt.Sprintf("containers/%s", source.Name()), tmpSnapshotName)
+ zfsPoolVolumeSnapshotDestroy(poolName, fmt.Sprintf("containers/%s", target.Name()), tmpSnapshotName)
fs := fmt.Sprintf("containers/%s", target.Name())
@@ -1373,19 +1373,21 @@ func (s *storageZfs) ContainerSnapshotCreate(snapshotContainer container, source
func (s *storageZfs) ContainerSnapshotDelete(snapshotContainer container) error {
logger.Debugf("Deleting ZFS storage volume for snapshot \"%s\" on storage pool \"%s\".", s.volume.Name, s.pool.Name)
+ poolName := s.getOnDiskPoolName()
+
sourceContainerName, sourceContainerSnapOnlyName, _ := containerGetParentAndSnapshotName(snapshotContainer.Name())
snapName := fmt.Sprintf("snapshot-%s", sourceContainerSnapOnlyName)
if s.zfsFilesystemEntityExists(fmt.Sprintf("containers/%s@%s", sourceContainerName, snapName), true) {
removable, err := zfsPoolVolumeSnapshotRemovable(s.getOnDiskPoolName(), fmt.Sprintf("containers/%s", sourceContainerName), snapName)
if removable {
- err = s.zfsPoolVolumeSnapshotDestroy(fmt.Sprintf("containers/%s", sourceContainerName), snapName)
+ err = zfsPoolVolumeSnapshotDestroy(poolName, fmt.Sprintf("containers/%s", sourceContainerName), snapName)
if err != nil {
return err
}
} else {
err = zfsPoolVolumeSnapshotRename(
- s.getOnDiskPoolName(), fmt.Sprintf("containers/%s", sourceContainerName), snapName,
+ poolName, fmt.Sprintf("containers/%s", sourceContainerName), snapName,
fmt.Sprintf("copy-%s", uuid.NewRandom().String()))
if err != nil {
return err
@@ -1865,12 +1867,12 @@ func (s *zfsMigrationSourceDriver) SendAfterCheckpoint(conn *websocket.Conn, bwl
}
func (s *zfsMigrationSourceDriver) Cleanup() {
+ poolName := s.zfs.getOnDiskPoolName()
if s.stoppedSnapName != "" {
- s.zfs.zfsPoolVolumeSnapshotDestroy(fmt.Sprintf("containers/%s", s.container.Name()), s.stoppedSnapName)
+ zfsPoolVolumeSnapshotDestroy(poolName, fmt.Sprintf("containers/%s", s.container.Name()), s.stoppedSnapName)
}
-
if s.runningSnapName != "" {
- s.zfs.zfsPoolVolumeSnapshotDestroy(fmt.Sprintf("containers/%s", s.container.Name()), s.runningSnapName)
+ zfsPoolVolumeSnapshotDestroy(poolName, fmt.Sprintf("containers/%s", s.container.Name()), s.runningSnapName)
}
}
@@ -2062,7 +2064,7 @@ func (s *storageZfs) MigrationSink(live bool, container container, snapshots []*
continue
}
- s.zfsPoolVolumeSnapshotDestroy(fmt.Sprintf("containers/%s", container.Name()), snap)
+ zfsPoolVolumeSnapshotDestroy(poolName, fmt.Sprintf("containers/%s", container.Name()), snap)
}
}()
diff --git a/lxd/storage_zfs_utils.go b/lxd/storage_zfs_utils.go
index dcfcd8dd7..5e1ffc9cb 100644
--- a/lxd/storage_zfs_utils.go
+++ b/lxd/storage_zfs_utils.go
@@ -537,13 +537,12 @@ func (s *storageZfs) zfsPoolVolumeSnapshotCreate(path string, name string) error
return nil
}
-func (s *storageZfs) zfsPoolVolumeSnapshotDestroy(path string, name string) error {
- poolName := s.getOnDiskPoolName()
+func zfsPoolVolumeSnapshotDestroy(pool, path string, name string) error {
output, err := shared.RunCommand(
"zfs",
"destroy",
"-r",
- fmt.Sprintf("%s/%s@%s", poolName, path, name))
+ fmt.Sprintf("%s/%s@%s", pool, path, name))
if err != nil {
logger.Errorf("zfs destroy failed: %s.", output)
return fmt.Errorf("Failed to destroy ZFS snapshot: %s", output)
From f3a1073b648e03c35942407d0b4edf846d11d571 Mon Sep 17 00:00:00 2001
From: Alberto Donato <alberto.donato at canonical.com>
Date: Mon, 7 Aug 2017 12:59:33 +0200
Subject: [PATCH 14/21] storage/zfs: make zfsPoolVolumeSnapshotCreate a
standalone function
Signed-off-by: Alberto Donato <alberto.donato at canonical.com>
---
lxd/storage_zfs.go | 17 +++++++++--------
lxd/storage_zfs_utils.go | 5 ++---
2 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/lxd/storage_zfs.go b/lxd/storage_zfs.go
index 2faac6b5c..35f48c3d2 100644
--- a/lxd/storage_zfs.go
+++ b/lxd/storage_zfs.go
@@ -814,7 +814,7 @@ func (s *storageZfs) copyWithoutSnapshotsSparse(target container, source contain
if s.zfsFilesystemEntityExists(fmt.Sprintf("containers/%s", sourceName), true) {
sourceZfsDatasetSnapshot = fmt.Sprintf("copy-%s", uuid.NewRandom().String())
sourceZfsDataset = fmt.Sprintf("containers/%s", sourceName)
- err := s.zfsPoolVolumeSnapshotCreate(sourceZfsDataset, sourceZfsDatasetSnapshot)
+ err := zfsPoolVolumeSnapshotCreate(poolName, sourceZfsDataset, sourceZfsDatasetSnapshot)
if err != nil {
return err
}
@@ -916,7 +916,7 @@ func (s *storageZfs) copyWithoutSnapshotFull(target container, source container)
targetSnapshotDataset = fmt.Sprintf("%s/containers/%s@%s", poolName, targetName, snapshotSuffix)
fs := fmt.Sprintf("containers/%s", sourceName)
- err := s.zfsPoolVolumeSnapshotCreate(fs, snapshotSuffix)
+ err := zfsPoolVolumeSnapshotCreate(poolName, fs, snapshotSuffix)
if err != nil {
return err
}
@@ -1102,14 +1102,15 @@ func (s *storageZfs) ContainerCopy(target container, source container, container
}
}
+ poolName := s.getOnDiskPoolName()
+
// send actual container
tmpSnapshotName := fmt.Sprintf("copy-send-%s", uuid.NewRandom().String())
- err = s.zfsPoolVolumeSnapshotCreate(fmt.Sprintf("containers/%s", source.Name()), tmpSnapshotName)
+ err = zfsPoolVolumeSnapshotCreate(poolName, fmt.Sprintf("containers/%s", source.Name()), tmpSnapshotName)
if err != nil {
return err
}
- poolName := s.getOnDiskPoolName()
currentSnapshotDataset := fmt.Sprintf("%s/containers/%s@%s", poolName, source.Name(), tmpSnapshotName)
args := []string{"send", currentSnapshotDataset}
if prevSnapOnlyName != "" {
@@ -1335,7 +1336,7 @@ func (s *storageZfs) ContainerSnapshotCreate(snapshotContainer container, source
snapName := fmt.Sprintf("snapshot-%s", snapshotSnapOnlyName)
sourceZfsDataset := fmt.Sprintf("containers/%s", cName)
- err := s.zfsPoolVolumeSnapshotCreate(sourceZfsDataset, snapName)
+ err := zfsPoolVolumeSnapshotCreate(s.getOnDiskPoolName(), sourceZfsDataset, snapName)
if err != nil {
return err
}
@@ -1685,7 +1686,7 @@ func (s *storageZfs) ImageCreate(fingerprint string) error {
// Create a snapshot of that image on the storage pool which we clone for
// container creation.
- err = s.zfsPoolVolumeSnapshotCreate(fs, "readonly")
+ err = zfsPoolVolumeSnapshotCreate(poolName, fs, "readonly")
if err != nil {
return err
}
@@ -1841,7 +1842,7 @@ func (s *zfsMigrationSourceDriver) SendWhileRunning(conn *websocket.Conn, op *op
}
s.runningSnapName = fmt.Sprintf("migration-send-%s", uuid.NewRandom().String())
- if err := s.zfs.zfsPoolVolumeSnapshotCreate(fmt.Sprintf("containers/%s", s.container.Name()), s.runningSnapName); err != nil {
+ if err := zfsPoolVolumeSnapshotCreate(s.zfs.getOnDiskPoolName(), fmt.Sprintf("containers/%s", s.container.Name()), s.runningSnapName); err != nil {
return err
}
@@ -1855,7 +1856,7 @@ func (s *zfsMigrationSourceDriver) SendWhileRunning(conn *websocket.Conn, op *op
func (s *zfsMigrationSourceDriver) SendAfterCheckpoint(conn *websocket.Conn, bwlimit string) error {
s.stoppedSnapName = fmt.Sprintf("migration-send-%s", uuid.NewRandom().String())
- if err := s.zfs.zfsPoolVolumeSnapshotCreate(fmt.Sprintf("containers/%s", s.container.Name()), s.stoppedSnapName); err != nil {
+ if err := zfsPoolVolumeSnapshotCreate(s.zfs.getOnDiskPoolName(), fmt.Sprintf("containers/%s", s.container.Name()), s.stoppedSnapName); err != nil {
return err
}
diff --git a/lxd/storage_zfs_utils.go b/lxd/storage_zfs_utils.go
index 5e1ffc9cb..a9b6c66f4 100644
--- a/lxd/storage_zfs_utils.go
+++ b/lxd/storage_zfs_utils.go
@@ -522,13 +522,12 @@ func (s *storageZfs) zfsPoolVolumeSet(path string, key string, value string) err
return nil
}
-func (s *storageZfs) zfsPoolVolumeSnapshotCreate(path string, name string) error {
- poolName := s.getOnDiskPoolName()
+func zfsPoolVolumeSnapshotCreate(pool string, path string, name string) error {
output, err := shared.RunCommand(
"zfs",
"snapshot",
"-r",
- fmt.Sprintf("%s/%s@%s", poolName, path, name))
+ fmt.Sprintf("%s/%s@%s", pool, path, name))
if err != nil {
logger.Errorf("zfs snapshot failed: %s.", output)
return fmt.Errorf("Failed to create ZFS snapshot: %s", output)
From 4f9e393a6d2c22726f7928d6e0c3d4d2a042bab2 Mon Sep 17 00:00:00 2001
From: Alberto Donato <alberto.donato at canonical.com>
Date: Mon, 7 Aug 2017 13:21:57 +0200
Subject: [PATCH 15/21] storage/zfs: make zfsPoolVolumeClone a standalone
function
Signed-off-by: Alberto Donato <alberto.donato at canonical.com>
---
lxd/storage_zfs.go | 10 ++++++----
lxd/storage_zfs_utils.go | 17 ++++++++---------
2 files changed, 14 insertions(+), 13 deletions(-)
diff --git a/lxd/storage_zfs.go b/lxd/storage_zfs.go
index 35f48c3d2..abf6c3a4b 100644
--- a/lxd/storage_zfs.go
+++ b/lxd/storage_zfs.go
@@ -603,6 +603,7 @@ func (s *storageZfs) ContainerCreateFromImage(container container, fingerprint s
fs := fmt.Sprintf("containers/%s", containerName)
containerPoolVolumeMntPoint := getContainerMountPoint(s.pool.Name, containerName)
+ poolName := s.getOnDiskPoolName()
fsImage := fmt.Sprintf("images/%s", fingerprint)
imageStoragePoolLockID := getImageCreateLockID(s.pool.Name, fingerprint)
@@ -633,7 +634,7 @@ func (s *storageZfs) ContainerCreateFromImage(container container, fingerprint s
}
}
- err := s.zfsPoolVolumeClone(fsImage, "readonly", fs, containerPoolVolumeMntPoint)
+ err := zfsPoolVolumeClone(poolName, fsImage, "readonly", fs, containerPoolVolumeMntPoint)
if err != nil {
return err
}
@@ -833,7 +834,7 @@ func (s *storageZfs) copyWithoutSnapshotsSparse(target container, source contain
}
if sourceZfsDataset != "" {
- err := s.zfsPoolVolumeClone(sourceZfsDataset, sourceZfsDatasetSnapshot, targetZfsDataset, targetContainerMountPoint)
+ err := zfsPoolVolumeClone(poolName, sourceZfsDataset, sourceZfsDatasetSnapshot, targetZfsDataset, targetContainerMountPoint)
if err != nil {
return err
}
@@ -1524,13 +1525,14 @@ func (s *storageZfs) ContainerSnapshotStart(container container) (bool, error) {
sourceSnap := fmt.Sprintf("snapshot-%s", sName)
destFs := fmt.Sprintf("snapshots/%s/%s", cName, sName)
+ poolName := s.getOnDiskPoolName()
snapshotMntPoint := getSnapshotMountPoint(s.pool.Name, container.Name())
- err := s.zfsPoolVolumeClone(sourceFs, sourceSnap, destFs, snapshotMntPoint)
+ err := zfsPoolVolumeClone(poolName, sourceFs, sourceSnap, destFs, snapshotMntPoint)
if err != nil {
return false, err
}
- err = zfsMount(s.getOnDiskPoolName(), destFs)
+ err = zfsMount(poolName, destFs)
if err != nil {
return false, err
}
diff --git a/lxd/storage_zfs_utils.go b/lxd/storage_zfs_utils.go
index a9b6c66f4..c0490da9d 100644
--- a/lxd/storage_zfs_utils.go
+++ b/lxd/storage_zfs_utils.go
@@ -270,28 +270,27 @@ func (s *storageZfs) zfsPoolCreate() error {
return nil
}
-func (s *storageZfs) zfsPoolVolumeClone(source string, name string, dest string, mountpoint string) error {
- poolName := s.getOnDiskPoolName()
+func zfsPoolVolumeClone(pool string, source string, name string, dest string, mountpoint string) error {
output, err := shared.RunCommand(
"zfs",
"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))
+ fmt.Sprintf("%s/%s@%s", pool, source, name),
+ fmt.Sprintf("%s/%s", pool, dest))
if err != nil {
logger.Errorf("zfs clone failed: %s.", output)
return fmt.Errorf("Failed to clone the filesystem: %s", output)
}
- subvols, err := zfsPoolListSubvolumes(poolName, fmt.Sprintf("%s/%s", poolName, source))
+ subvols, err := zfsPoolListSubvolumes(pool, fmt.Sprintf("%s/%s", pool, source))
if err != nil {
return err
}
for _, sub := range subvols {
- snaps, err := zfsPoolListSnapshots(poolName, sub)
+ snaps, err := zfsPoolListSnapshots(pool, sub)
if err != nil {
return err
}
@@ -301,7 +300,7 @@ func (s *storageZfs) zfsPoolVolumeClone(source string, name string, dest string,
}
destSubvol := dest + strings.TrimPrefix(sub, source)
- snapshotMntPoint := getSnapshotMountPoint(s.pool.Name, destSubvol)
+ snapshotMntPoint := getSnapshotMountPoint(pool, destSubvol)
output, err := shared.RunCommand(
"zfs",
@@ -309,8 +308,8 @@ func (s *storageZfs) zfsPoolVolumeClone(source string, name string, dest string,
"-p",
"-o", fmt.Sprintf("mountpoint=%s", snapshotMntPoint),
"-o", "canmount=noauto",
- fmt.Sprintf("%s/%s@%s", poolName, sub, name),
- fmt.Sprintf("%s/%s", poolName, destSubvol))
+ fmt.Sprintf("%s/%s@%s", pool, sub, name),
+ fmt.Sprintf("%s/%s", pool, destSubvol))
if err != nil {
logger.Errorf("zfs clone failed: %s.", output)
return fmt.Errorf("Failed to clone the sub-volume: %s", output)
From 90baa25bddcc8ab67f2b1106ca25e5984ca40e60 Mon Sep 17 00:00:00 2001
From: Alberto Donato <alberto.donato at canonical.com>
Date: Mon, 7 Aug 2017 15:52:04 +0200
Subject: [PATCH 16/21] storage/zfs: make zfsPoolVolumeSet a standalone
function
Signed-off-by: Alberto Donato <alberto.donato at canonical.com>
---
lxd/storage_zfs.go | 38 ++++++++++++++++++--------------------
lxd/storage_zfs_utils.go | 24 ++++++++----------------
2 files changed, 26 insertions(+), 36 deletions(-)
diff --git a/lxd/storage_zfs.go b/lxd/storage_zfs.go
index abf6c3a4b..24b1e2956 100644
--- a/lxd/storage_zfs.go
+++ b/lxd/storage_zfs.go
@@ -186,7 +186,7 @@ func (s *storageZfs) StoragePoolVolumeCreate() error {
s.StoragePoolVolumeDelete()
}()
- err = s.zfsPoolVolumeSet(fs, "mountpoint", customPoolVolumeMntPoint)
+ err = zfsPoolVolumeSet(poolName, fs, "mountpoint", customPoolVolumeMntPoint)
if err != nil {
return err
}
@@ -566,7 +566,7 @@ func (s *storageZfs) ContainerCreate(container container) error {
}()
// Set mountpoint.
- err = s.zfsPoolVolumeSet(fs, "mountpoint", containerPoolVolumeMntPoint)
+ err = zfsPoolVolumeSet(poolName, fs, "mountpoint", containerPoolVolumeMntPoint)
if err != nil {
return err
}
@@ -747,7 +747,7 @@ func (s *storageZfs) ContainerDelete(container container) error {
return err
}
} else {
- err := s.zfsPoolVolumeSet(fs, "mountpoint", "none")
+ err := zfsPoolVolumeSet(poolName, fs, "mountpoint", "none")
if err != nil {
return err
}
@@ -961,12 +961,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")
+ err = zfsPoolVolumeSet(poolName, targetfs, "canmount", "noauto")
if err != nil {
return err
}
- err = s.zfsPoolVolumeSet(targetfs, "mountpoint", targetContainerMountPoint)
+ err = zfsPoolVolumeSet(poolName, targetfs, "mountpoint", targetContainerMountPoint)
if err != nil {
return err
}
@@ -1146,13 +1146,12 @@ func (s *storageZfs) ContainerCopy(target container, source container, container
zfsPoolVolumeSnapshotDestroy(poolName, fmt.Sprintf("containers/%s", target.Name()), tmpSnapshotName)
fs := fmt.Sprintf("containers/%s", target.Name())
-
- err = s.zfsPoolVolumeSet(fs, "canmount", "noauto")
+ err = zfsPoolVolumeSet(poolName, fs, "canmount", "noauto")
if err != nil {
return err
}
- err = s.zfsPoolVolumeSet(fs, "mountpoint", targetContainerMountPoint)
+ err = zfsPoolVolumeSet(poolName, fs, "mountpoint", targetContainerMountPoint)
if err != nil {
return err
}
@@ -1166,6 +1165,7 @@ func (s *storageZfs) ContainerCopy(target container, source container, container
func (s *storageZfs) ContainerRename(container container, newName string) error {
logger.Debugf("Renaming ZFS storage volume for container \"%s\" from %s -> %s.", s.volume.Name, s.volume.Name, newName)
+ poolName := s.getOnDiskPoolName()
oldName := container.Name()
// Unmount the dataset.
@@ -1191,7 +1191,7 @@ func (s *storageZfs) ContainerRename(container container, newName string) error
// Set the new mountpoint for the dataset.
newContainerMntPoint := getContainerMountPoint(s.pool.Name, newName)
- err = s.zfsPoolVolumeSet(newZfsDataset, "mountpoint", newContainerMntPoint)
+ err = zfsPoolVolumeSet(poolName, newZfsDataset, "mountpoint", newContainerMntPoint)
if err != nil {
return err
}
@@ -1571,6 +1571,7 @@ func (s *storageZfs) ContainerSnapshotCreateEmpty(snapshotContainer container) e
func (s *storageZfs) ImageCreate(fingerprint string) error {
logger.Debugf("Creating ZFS storage volume for image \"%s\" on storage pool \"%s\".", fingerprint, s.pool.Name)
+ poolName := s.getOnDiskPoolName()
imageMntPoint := getImageMountPoint(s.pool.Name, fingerprint)
fs := fmt.Sprintf("images/%s", fingerprint)
revert := true
@@ -1602,7 +1603,7 @@ func (s *storageZfs) ImageCreate(fingerprint string) error {
// In case this is an image from an older lxd instance, wipe the
// mountpoint.
- err = s.zfsPoolVolumeSet(fs, "mountpoint", "none")
+ err = zfsPoolVolumeSet(poolName, fs, "mountpoint", "none")
if err != nil {
return err
}
@@ -1637,7 +1638,6 @@ func (s *storageZfs) ImageCreate(fingerprint string) error {
imagePath := shared.VarPath("images", fingerprint)
// Create a new storage volume on the storage pool for the image.
- poolName := s.getOnDiskPoolName()
dataset := fmt.Sprintf("%s/%s", poolName, fs)
msg, err := zfsPoolVolumeCreate(dataset, "mountpoint=none")
if err != nil {
@@ -1653,7 +1653,7 @@ func (s *storageZfs) ImageCreate(fingerprint string) error {
}()
// Set a temporary mountpoint for the image.
- err = s.zfsPoolVolumeSet(fs, "mountpoint", tmpImageDir)
+ err = zfsPoolVolumeSet(poolName, fs, "mountpoint", tmpImageDir)
if err != nil {
return err
}
@@ -1670,14 +1670,12 @@ func (s *storageZfs) ImageCreate(fingerprint string) error {
}
// Mark the new storage volume for the image as readonly.
- err = s.zfsPoolVolumeSet(fs, "readonly", "on")
- if err != nil {
+ if err = zfsPoolVolumeSet(poolName, fs, "readonly", "on"); err != nil {
return err
}
// Remove the temporary mountpoint from the image storage volume.
- err = s.zfsPoolVolumeSet(fs, "mountpoint", "none")
- if err != nil {
+ if err = zfsPoolVolumeSet(poolName, fs, "mountpoint", "none"); err != nil {
return err
}
@@ -1717,8 +1715,7 @@ func (s *storageZfs) ImageDelete(fingerprint string) error {
return err
}
} else {
- err := s.zfsPoolVolumeSet(fs, "mountpoint", "none")
- if err != nil {
+ if err := zfsPoolVolumeSet(poolName, fs, "mountpoint", "none"); err != nil {
return err
}
@@ -2124,11 +2121,12 @@ func (s *storageZfs) StorageEntitySetQuota(volumeType int, size int64, data inte
property = "refquota"
}
+ poolName := s.getOnDiskPoolName()
var err error
if size > 0 {
- err = s.zfsPoolVolumeSet(fs, property, fmt.Sprintf("%d", size))
+ err = zfsPoolVolumeSet(poolName, fs, property, fmt.Sprintf("%d", size))
} else {
- err = s.zfsPoolVolumeSet(fs, property, "none")
+ err = zfsPoolVolumeSet(poolName, fs, property, "none")
}
if err != nil {
diff --git a/lxd/storage_zfs_utils.go b/lxd/storage_zfs_utils.go
index c0490da9d..d3b16beca 100644
--- a/lxd/storage_zfs_utils.go
+++ b/lxd/storage_zfs_utils.go
@@ -48,13 +48,6 @@ func zfsPoolVolumeCreate(dataset string, properties ...string) (string, error) {
return shared.RunCommand(cmd[0], cmd[1:]...)
}
-func zfsPoolVolumeSet(dataset string, key string, value string) (string, error) {
- return shared.RunCommand("zfs",
- "set",
- fmt.Sprintf("%s=%s", key, value),
- dataset)
-}
-
func zfsPoolCheck(pool string) error {
output, err := shared.RunCommand(
"zfs", "get", "type", "-H", "-o", "value", pool)
@@ -158,9 +151,7 @@ func (s *storageZfs) zfsPoolCreate() error {
return fmt.Errorf("Failed to create ZFS filesystem: %s", output)
}
} else {
- msg, err := zfsPoolVolumeSet(vdev, "mountpoint", "none")
- if err != nil {
- logger.Errorf("zfs set failed to unset dataset mountpoint %s", msg)
+ if err := zfsPoolVolumeSet(vdev, "", "mountpoint", "none"); err != nil {
return err
}
}
@@ -179,9 +170,7 @@ func (s *storageZfs) zfsPoolCreate() error {
return fmt.Errorf("Provided ZFS pool (or dataset) isn't empty")
}
- msg, err := zfsPoolVolumeSet(vdev, "mountpoint", "none")
- if err != nil {
- logger.Errorf("zfs set failed to unset dataset mountpoint %s", msg)
+ if err := zfsPoolVolumeSet(vdev, "", "mountpoint", "none"); err != nil {
return err
}
}
@@ -506,13 +495,16 @@ func (s *storageZfs) zfsPoolVolumeRename(source string, dest string) error {
return fmt.Errorf("Failed to rename ZFS filesystem: %s", output)
}
-func (s *storageZfs) zfsPoolVolumeSet(path string, key string, value string) error {
- poolName := s.getOnDiskPoolName()
+func zfsPoolVolumeSet(pool string, path string, key string, value string) error {
+ vdev := pool
+ if path != "" {
+ vdev = fmt.Sprintf("%s/%s", pool, path)
+ }
output, err := shared.RunCommand(
"zfs",
"set",
fmt.Sprintf("%s=%s", key, value),
- fmt.Sprintf("%s/%s", poolName, path))
+ vdev)
if err != nil {
logger.Errorf("zfs set failed: %s.", output)
return fmt.Errorf("Failed to set ZFS config: %s", output)
From 265e69ada96534b31726dfcfbe3ce6ee32372db0 Mon Sep 17 00:00:00 2001
From: Alberto Donato <alberto.donato at canonical.com>
Date: Mon, 7 Aug 2017 18:40:45 +0200
Subject: [PATCH 17/21] storage/zfs: drop unused zfsPoolGetUsers
Signed-off-by: Alberto Donato <alberto.donato at canonical.com>
---
lxd/storage_zfs_utils.go | 35 -----------------------------------
1 file changed, 35 deletions(-)
diff --git a/lxd/storage_zfs_utils.go b/lxd/storage_zfs_utils.go
index d3b16beca..3373fae9f 100644
--- a/lxd/storage_zfs_utils.go
+++ b/lxd/storage_zfs_utils.go
@@ -709,41 +709,6 @@ func zfsPoolVolumeSnapshotRemovable(pool string, path string, name string) (bool
return false, nil
}
-func (s *storageZfs) zfsPoolGetUsers() ([]string, error) {
- poolName := s.getOnDiskPoolName()
- subvols, err := zfsPoolListSubvolumes(poolName, poolName)
- if err != nil {
- return []string{}, err
- }
-
- exceptions := []string{
- "containers",
- "images",
- "snapshots",
- "deleted",
- "deleted/containers",
- "deleted/images"}
-
- users := []string{}
- for _, subvol := range subvols {
- path := strings.Split(subvol, "/")
-
- // Only care about plausible LXD paths
- if !shared.StringInSlice(path[0], exceptions) {
- continue
- }
-
- // Ignore empty paths
- if shared.StringInSlice(subvol, exceptions) {
- continue
- }
-
- users = append(users, subvol)
- }
-
- return users, nil
-}
-
func zfsFilesystemEntityExists(zfsEntity string) bool {
output, err := shared.RunCommand(
"zfs",
From 245fb1ac6c7e96c5ef0961ed49f395ef090a5a42 Mon Sep 17 00:00:00 2001
From: Alberto Donato <alberto.donato at canonical.com>
Date: Mon, 7 Aug 2017 19:02:02 +0200
Subject: [PATCH 18/21] storage/zfs: make zfsFilesystemEntityExists a
standalone function
Signed-off-by: Alberto Donato <alberto.donato at canonical.com>
---
lxd/storage_zfs.go | 21 ++++++++++-----------
lxd/storage_zfs_utils.go | 36 +++++++++---------------------------
2 files changed, 19 insertions(+), 38 deletions(-)
diff --git a/lxd/storage_zfs.go b/lxd/storage_zfs.go
index 24b1e2956..af78fdb6e 100644
--- a/lxd/storage_zfs.go
+++ b/lxd/storage_zfs.go
@@ -85,7 +85,7 @@ func (s *storageZfs) StoragePoolCheck() error {
poolName := s.getOnDiskPoolName()
if filepath.IsAbs(source) {
- if zfsFilesystemEntityExists(poolName) {
+ if zfsFilesystemEntityExists(poolName, "") {
return nil
}
logger.Debugf("ZFS storage pool \"%s\" does not exist. Trying to import it.", poolName)
@@ -535,9 +535,8 @@ func (s *storageZfs) ContainerUmount(name string, path string) (bool, error) {
// Things we do have to care about
func (s *storageZfs) ContainerStorageReady(name string) bool {
- poolName := s.getOnDiskPoolName()
- fs := fmt.Sprintf("%s/containers/%s", poolName, name)
- return s.zfsFilesystemEntityExists(fs, false)
+ fs := fmt.Sprintf("containers/%s", name)
+ return zfsFilesystemEntityExists(s.getOnDiskPoolName(), fs)
}
func (s *storageZfs) ContainerCreate(container container) error {
@@ -618,7 +617,7 @@ func (s *storageZfs) ContainerCreateFromImage(container container, fingerprint s
lxdStorageMapLock.Unlock()
var imgerr error
- if !s.zfsFilesystemEntityExists(fsImage, true) {
+ if !zfsFilesystemEntityExists(poolName, fsImage) {
imgerr = s.ImageCreate(fingerprint)
}
@@ -710,7 +709,7 @@ func (s *storageZfs) ContainerDelete(container container) error {
fs := fmt.Sprintf("containers/%s", containerName)
containerPoolVolumeMntPoint := getContainerMountPoint(s.pool.Name, containerName)
- if s.zfsFilesystemEntityExists(fs, true) {
+ if zfsFilesystemEntityExists(poolName, fs) {
removable := true
snaps, err := zfsPoolListSnapshots(poolName, fs)
if err != nil {
@@ -812,7 +811,7 @@ func (s *storageZfs) copyWithoutSnapshotsSparse(target container, source contain
revert := true
if sourceZfsDatasetSnapshot == "" {
- if s.zfsFilesystemEntityExists(fmt.Sprintf("containers/%s", sourceName), true) {
+ if zfsFilesystemEntityExists(poolName, fmt.Sprintf("containers/%s", sourceName)) {
sourceZfsDatasetSnapshot = fmt.Sprintf("copy-%s", uuid.NewRandom().String())
sourceZfsDataset = fmt.Sprintf("containers/%s", sourceName)
err := zfsPoolVolumeSnapshotCreate(poolName, sourceZfsDataset, sourceZfsDatasetSnapshot)
@@ -827,7 +826,7 @@ func (s *storageZfs) copyWithoutSnapshotsSparse(target container, source contain
}()
}
} else {
- if s.zfsFilesystemEntityExists(fmt.Sprintf("containers/%s at snapshot-%s", sourceName, sourceZfsDatasetSnapshot), true) {
+ if zfsFilesystemEntityExists(poolName, fmt.Sprintf("containers/%s at snapshot-%s", sourceName, sourceZfsDatasetSnapshot)) {
sourceZfsDataset = fmt.Sprintf("containers/%s", sourceName)
sourceZfsDatasetSnapshot = fmt.Sprintf("snapshot-%s", sourceZfsDatasetSnapshot)
}
@@ -1380,7 +1379,7 @@ func (s *storageZfs) ContainerSnapshotDelete(snapshotContainer container) error
sourceContainerName, sourceContainerSnapOnlyName, _ := containerGetParentAndSnapshotName(snapshotContainer.Name())
snapName := fmt.Sprintf("snapshot-%s", sourceContainerSnapOnlyName)
- if s.zfsFilesystemEntityExists(fmt.Sprintf("containers/%s@%s", sourceContainerName, snapName), true) {
+ if zfsFilesystemEntityExists(poolName, fmt.Sprintf("containers/%s@%s", sourceContainerName, snapName)) {
removable, err := zfsPoolVolumeSnapshotRemovable(s.getOnDiskPoolName(), fmt.Sprintf("containers/%s", sourceContainerName), snapName)
if removable {
err = zfsPoolVolumeSnapshotDestroy(poolName, fmt.Sprintf("containers/%s", sourceContainerName), snapName)
@@ -1588,7 +1587,7 @@ func (s *storageZfs) ImageCreate(fingerprint string) error {
s.deleteImageDbPoolVolume(fingerprint)
}()
- if s.zfsFilesystemEntityExists(fmt.Sprintf("deleted/%s", fs), true) {
+ if zfsFilesystemEntityExists(poolName, fmt.Sprintf("deleted/%s", fs)) {
err := s.zfsPoolVolumeRename(fmt.Sprintf("deleted/%s", fs), fs)
if err != nil {
return err
@@ -1703,7 +1702,7 @@ func (s *storageZfs) ImageDelete(fingerprint string) error {
poolName := s.getOnDiskPoolName()
fs := fmt.Sprintf("images/%s", fingerprint)
- if s.zfsFilesystemEntityExists(fs, true) {
+ if zfsFilesystemEntityExists(poolName, fs) {
removable, err := zfsPoolVolumeSnapshotRemovable(poolName, fs, "readonly")
if err != nil {
return err
diff --git a/lxd/storage_zfs_utils.go b/lxd/storage_zfs_utils.go
index 3373fae9f..7c003d04b 100644
--- a/lxd/storage_zfs_utils.go
+++ b/lxd/storage_zfs_utils.go
@@ -137,8 +137,7 @@ func (s *storageZfs) zfsPoolCreate() error {
s.dataset = vdev
if strings.Contains(vdev, "/") {
- ok := s.zfsFilesystemEntityExists(vdev, false)
- if !ok {
+ if !zfsFilesystemEntityExists(vdev, "") {
output, err := shared.RunCommand(
"zfs",
"create",
@@ -424,23 +423,6 @@ func zfsPoolVolumeCleanup(pool string, path string) error {
return nil
}
-func (s *storageZfs) zfsFilesystemEntityExists(path string, prefixPathWithPool bool) bool {
- poolName := s.getOnDiskPoolName()
- output, _ := zfsFilesystemEntityPropertyGet(poolName, path, "name", prefixPathWithPool)
-
- // If prefixPathWithPool is false we assume that the path passed in
- // already is a valid zfs entity we want to check for.
- fsToCheck := path
- if prefixPathWithPool {
- fsToCheck = fmt.Sprintf("%s/%s", poolName, path)
- }
- if output == fsToCheck {
- return true
- }
-
- return false
-}
-
func zfsFilesystemEntityPropertyGet(pool string, path string, key string, prefixPathWithPool bool) (string, error) {
// If prefixPathWithPool is false we assume that the path passed in
// already is a valid zfs entity we want to check for.
@@ -483,7 +465,7 @@ func (s *storageZfs) zfsPoolVolumeRename(source string, dest string) error {
}
// zfs rename can fail because of descendants, yet still manage the rename
- if !s.zfsFilesystemEntityExists(source, true) && s.zfsFilesystemEntityExists(dest, true) {
+ if !zfsFilesystemEntityExists(poolName, source) && zfsFilesystemEntityExists(poolName, dest) {
return nil
}
@@ -709,7 +691,11 @@ func zfsPoolVolumeSnapshotRemovable(pool string, path string, name string) (bool
return false, nil
}
-func zfsFilesystemEntityExists(zfsEntity string) bool {
+func zfsFilesystemEntityExists(pool string, path string) bool {
+ vdev := pool
+ if path != "" {
+ vdev = fmt.Sprintf("%s/%s", pool, path)
+ }
output, err := shared.RunCommand(
"zfs",
"get",
@@ -717,15 +703,11 @@ func zfsFilesystemEntityExists(zfsEntity string) bool {
"-H",
"-o",
"name",
- zfsEntity)
+ vdev)
if err != nil {
return false
}
detectedName := strings.TrimSpace(output)
- if detectedName != zfsEntity {
- return false
- }
-
- return true
+ return detectedName == vdev
}
From 3ce40ca7acc7a4e58faf6adbae48c8be8e44bcd9 Mon Sep 17 00:00:00 2001
From: Alberto Donato <alberto.donato at canonical.com>
Date: Tue, 8 Aug 2017 10:38:04 +0200
Subject: [PATCH 19/21] storage/zfs: drop unneeded param from
zfsFilesystemEntityPropertyGet
Signed-off-by: Alberto Donato <alberto.donato at canonical.com>
---
lxd/storage_zfs.go | 4 ++--
lxd/storage_zfs_utils.go | 17 +++++------------
2 files changed, 7 insertions(+), 14 deletions(-)
diff --git a/lxd/storage_zfs.go b/lxd/storage_zfs.go
index af78fdb6e..e42e38183 100644
--- a/lxd/storage_zfs.go
+++ b/lxd/storage_zfs.go
@@ -729,7 +729,7 @@ func (s *storageZfs) ContainerDelete(container container) error {
}
if removable {
- origin, err := zfsFilesystemEntityPropertyGet(poolName, fs, "origin", true)
+ origin, err := zfsFilesystemEntityPropertyGet(poolName, fs, "origin")
if err != nil {
return err
}
@@ -1313,7 +1313,7 @@ func (s *storageZfs) ContainerGetUsage(container container) (int64, error) {
property = "usedbydataset"
}
- value, err := zfsFilesystemEntityPropertyGet(s.getOnDiskPoolName(), fs, property, true)
+ value, err := zfsFilesystemEntityPropertyGet(s.getOnDiskPoolName(), fs, property)
if err != nil {
return -1, err
}
diff --git a/lxd/storage_zfs_utils.go b/lxd/storage_zfs_utils.go
index 7c003d04b..5cc06c0fa 100644
--- a/lxd/storage_zfs_utils.go
+++ b/lxd/storage_zfs_utils.go
@@ -330,7 +330,7 @@ func zfsFilesystemEntityDelete(vdev string, pool string) error {
}
func zfsPoolVolumeDestroy(pool string, path string) error {
- mountpoint, err := zfsFilesystemEntityPropertyGet(pool, path, "mountpoint", true)
+ mountpoint, err := zfsFilesystemEntityPropertyGet(pool, path, "mountpoint")
if err != nil {
return err
}
@@ -390,7 +390,7 @@ func zfsPoolVolumeCleanup(pool string, path string) error {
}
} else {
// Cleanup filesystems
- origin, err := zfsFilesystemEntityPropertyGet(pool, path, "origin", true)
+ origin, err := zfsFilesystemEntityPropertyGet(pool, path, "origin")
if err != nil {
return err
}
@@ -423,14 +423,7 @@ func zfsPoolVolumeCleanup(pool string, path string) error {
return nil
}
-func zfsFilesystemEntityPropertyGet(pool string, path string, key string, prefixPathWithPool bool) (string, error) {
- // If prefixPathWithPool is false we assume that the path passed in
- // already is a valid zfs entity we want to check for.
- fsToCheck := path
- if prefixPathWithPool {
- fsToCheck = fmt.Sprintf("%s/%s", pool, path)
- }
-
+func zfsFilesystemEntityPropertyGet(pool string, path string, key string) (string, error) {
output, err := shared.RunCommand(
"zfs",
"get",
@@ -438,7 +431,7 @@ func zfsFilesystemEntityPropertyGet(pool string, path string, key string, prefix
"-p",
"-o", "value",
key,
- fsToCheck)
+ fmt.Sprintf("%s/%s", pool, path))
if err != nil {
return "", fmt.Errorf("Failed to get ZFS config: %s", output)
}
@@ -679,7 +672,7 @@ func zfsPoolVolumeSnapshotRemovable(pool string, path string, name string) (bool
snap = fmt.Sprintf("%s@%s", path, name)
}
- clones, err := zfsFilesystemEntityPropertyGet(pool, snap, "clones", true)
+ clones, err := zfsFilesystemEntityPropertyGet(pool, snap, "clones")
if err != nil {
return false, err
}
From 81034aa68848765a9bf49228c3f6f688750217bd Mon Sep 17 00:00:00 2001
From: Alberto Donato <alberto.donato at canonical.com>
Date: Tue, 8 Aug 2017 10:43:09 +0200
Subject: [PATCH 20/21] storage/zfs: make zfsPoolVolumeRename a standalone
function
Signed-off-by: Alberto Donato <alberto.donato at canonical.com>
---
lxd/storage_zfs.go | 10 ++++------
lxd/storage_zfs_utils.go | 9 ++++-----
2 files changed, 8 insertions(+), 11 deletions(-)
diff --git a/lxd/storage_zfs.go b/lxd/storage_zfs.go
index e42e38183..3218c863c 100644
--- a/lxd/storage_zfs.go
+++ b/lxd/storage_zfs.go
@@ -751,7 +751,7 @@ func (s *storageZfs) ContainerDelete(container container) error {
return err
}
- err = s.zfsPoolVolumeRename(fs, fmt.Sprintf("deleted/containers/%s", uuid.NewRandom().String()))
+ err = zfsPoolVolumeRename(poolName, fs, fmt.Sprintf("deleted/containers/%s", uuid.NewRandom().String()))
if err != nil {
return err
}
@@ -1176,7 +1176,7 @@ func (s *storageZfs) ContainerRename(container container, newName string) error
// Rename the dataset.
oldZfsDataset := fmt.Sprintf("containers/%s", oldName)
newZfsDataset := fmt.Sprintf("containers/%s", newName)
- err = s.zfsPoolVolumeRename(oldZfsDataset, newZfsDataset)
+ err = zfsPoolVolumeRename(poolName, oldZfsDataset, newZfsDataset)
if err != nil {
return err
}
@@ -1588,8 +1588,7 @@ func (s *storageZfs) ImageCreate(fingerprint string) error {
}()
if zfsFilesystemEntityExists(poolName, fmt.Sprintf("deleted/%s", fs)) {
- err := s.zfsPoolVolumeRename(fmt.Sprintf("deleted/%s", fs), fs)
- if err != nil {
+ if err := zfsPoolVolumeRename(poolName, fmt.Sprintf("deleted/%s", fs), fs); err != nil {
return err
}
@@ -1718,8 +1717,7 @@ func (s *storageZfs) ImageDelete(fingerprint string) error {
return err
}
- err = s.zfsPoolVolumeRename(fs, fmt.Sprintf("deleted/%s", fs))
- if err != nil {
+ if err := zfsPoolVolumeRename(poolName, fs, fmt.Sprintf("deleted/%s", fs)); err != nil {
return err
}
}
diff --git a/lxd/storage_zfs_utils.go b/lxd/storage_zfs_utils.go
index 5cc06c0fa..423b3b6a6 100644
--- a/lxd/storage_zfs_utils.go
+++ b/lxd/storage_zfs_utils.go
@@ -439,18 +439,17 @@ func zfsFilesystemEntityPropertyGet(pool string, path string, key string) (strin
return strings.TrimRight(output, "\n"), nil
}
-func (s *storageZfs) zfsPoolVolumeRename(source string, dest string) error {
+func zfsPoolVolumeRename(pool string, source string, dest string) error {
var err error
var output string
- poolName := s.getOnDiskPoolName()
for i := 0; i < 20; i++ {
output, err = shared.RunCommand(
"zfs",
"rename",
"-p",
- fmt.Sprintf("%s/%s", poolName, source),
- fmt.Sprintf("%s/%s", poolName, dest))
+ fmt.Sprintf("%s/%s", pool, source),
+ fmt.Sprintf("%s/%s", pool, dest))
// Success
if err == nil {
@@ -458,7 +457,7 @@ func (s *storageZfs) zfsPoolVolumeRename(source string, dest string) error {
}
// zfs rename can fail because of descendants, yet still manage the rename
- if !zfsFilesystemEntityExists(poolName, source) && zfsFilesystemEntityExists(poolName, dest) {
+ if !zfsFilesystemEntityExists(pool, source) && zfsFilesystemEntityExists(pool, dest) {
return nil
}
From cb788dbb1b96bc9cbba9c0b86885c9247a025c58 Mon Sep 17 00:00:00 2001
From: Alberto Donato <alberto.donato at canonical.com>
Date: Tue, 8 Aug 2017 11:22:19 +0200
Subject: [PATCH 21/21] storage/zfs: extract some logic to a standalone
zfsPoolCreate function
Signed-off-by: Alberto Donato <alberto.donato at canonical.com>
---
lxd/storage_zfs.go | 179 ++++++++++++++++++++++++++++++++++++++++++
lxd/storage_zfs_utils.go | 198 +++--------------------------------------------
2 files changed, 191 insertions(+), 186 deletions(-)
diff --git a/lxd/storage_zfs.go b/lxd/storage_zfs.go
index 3218c863c..04761ec7c 100644
--- a/lxd/storage_zfs.go
+++ b/lxd/storage_zfs.go
@@ -137,6 +137,185 @@ func (s *storageZfs) StoragePoolCreate() error {
return nil
}
+func (s *storageZfs) zfsPoolCreate() error {
+ zpoolName := s.getOnDiskPoolName()
+ vdev := s.pool.Config["source"]
+ if vdev == "" {
+ vdev = filepath.Join(shared.VarPath("disks"), fmt.Sprintf("%s.img", s.pool.Name))
+ s.pool.Config["source"] = vdev
+
+ if s.pool.Config["zfs.pool_name"] == "" {
+ s.pool.Config["zfs.pool_name"] = zpoolName
+ }
+
+ f, err := os.Create(vdev)
+ if err != nil {
+ return fmt.Errorf("Failed to open %s: %s", vdev, err)
+ }
+ defer f.Close()
+
+ err = f.Chmod(0600)
+ if err != nil {
+ return fmt.Errorf("Failed to chmod %s: %s", vdev, err)
+ }
+
+ size, err := shared.ParseByteSizeString(s.pool.Config["size"])
+ if err != nil {
+ return err
+ }
+ err = f.Truncate(size)
+ if err != nil {
+ return fmt.Errorf("Failed to create sparse file %s: %s", vdev, err)
+ }
+
+ if err := zfsPoolCreate(zpoolName, vdev); err != nil {
+ return err
+ }
+ } else {
+ // Unset size property since it doesn't make sense.
+ s.pool.Config["size"] = ""
+
+ if filepath.IsAbs(vdev) {
+ if !shared.IsBlockdevPath(vdev) {
+ return fmt.Errorf("custom loop file locations are not supported")
+ }
+
+ if s.pool.Config["zfs.pool_name"] == "" {
+ s.pool.Config["zfs.pool_name"] = zpoolName
+ }
+
+ // This is a block device. Note, that we do not store the
+ // block device path or UUID or PARTUUID or similar in
+ // the database. All of those might change or might be
+ // used in a special way (For example, zfs uses a single
+ // UUID in a multi-device pool for all devices.). The
+ // safest way is to just store the name of the zfs pool
+ // we create.
+ s.pool.Config["source"] = zpoolName
+ if err := zfsPoolCreate(zpoolName, vdev); err != nil {
+ return err
+ }
+ } else {
+ if s.pool.Config["zfs.pool_name"] != "" {
+ return fmt.Errorf("invalid combination of \"source\" and \"zfs.pool_name\" property")
+ }
+ s.pool.Config["zfs.pool_name"] = vdev
+ s.dataset = vdev
+
+ if strings.Contains(vdev, "/") {
+ if !zfsFilesystemEntityExists(vdev, "") {
+ if err := zfsPoolCreate("", vdev); err != nil {
+ return err
+ }
+ } else {
+ if err := zfsPoolVolumeSet(vdev, "", "mountpoint", "none"); err != nil {
+ return err
+ }
+ }
+ } else {
+ err := zfsPoolCheck(vdev)
+ if err != nil {
+ return err
+ }
+
+ subvols, err := zfsPoolListSubvolumes(zpoolName, vdev)
+ if err != nil {
+ return err
+ }
+
+ if len(subvols) > 0 {
+ return fmt.Errorf("Provided ZFS pool (or dataset) isn't empty")
+ }
+
+ if err := zfsPoolVolumeSet(vdev, "", "mountpoint", "none"); err != nil {
+ return err
+ }
+ }
+ }
+ }
+
+ // Create default dummy datasets to avoid zfs races during container
+ // creation.
+ poolName := s.getOnDiskPoolName()
+ dataset := fmt.Sprintf("%s/containers", poolName)
+ msg, err := zfsPoolVolumeCreate(dataset, "mountpoint=none")
+ if err != nil {
+ logger.Errorf("failed to create containers dataset: %s", msg)
+ return err
+ }
+
+ fixperms := shared.VarPath("storage-pools", s.pool.Name, "containers")
+ err = os.MkdirAll(fixperms, containersDirMode)
+ if err != nil && !os.IsNotExist(err) {
+ return err
+ }
+
+ err = os.Chmod(fixperms, containersDirMode)
+ if err != nil {
+ logger.Warnf("failed to chmod \"%s\" to \"0%s\": %s", fixperms, strconv.FormatInt(int64(containersDirMode), 8), err)
+ }
+
+ dataset = fmt.Sprintf("%s/images", poolName)
+ msg, err = zfsPoolVolumeCreate(dataset, "mountpoint=none")
+ if err != nil {
+ logger.Errorf("failed to create images dataset: %s", msg)
+ return err
+ }
+
+ fixperms = shared.VarPath("storage-pools", s.pool.Name, "images")
+ err = os.MkdirAll(fixperms, imagesDirMode)
+ if err != nil && !os.IsNotExist(err) {
+ return err
+ }
+ err = os.Chmod(fixperms, imagesDirMode)
+ if err != nil {
+ logger.Warnf("failed to chmod \"%s\" to \"0%s\": %s", fixperms, strconv.FormatInt(int64(imagesDirMode), 8), err)
+ }
+
+ dataset = fmt.Sprintf("%s/custom", poolName)
+ msg, err = zfsPoolVolumeCreate(dataset, "mountpoint=none")
+ if err != nil {
+ logger.Errorf("failed to create custom dataset: %s", msg)
+ return err
+ }
+
+ fixperms = shared.VarPath("storage-pools", s.pool.Name, "custom")
+ err = os.MkdirAll(fixperms, customDirMode)
+ if err != nil && !os.IsNotExist(err) {
+ return err
+ }
+ err = os.Chmod(fixperms, customDirMode)
+ if err != nil {
+ logger.Warnf("failed to chmod \"%s\" to \"0%s\": %s", fixperms, strconv.FormatInt(int64(customDirMode), 8), err)
+ }
+
+ dataset = fmt.Sprintf("%s/deleted", poolName)
+ msg, err = zfsPoolVolumeCreate(dataset, "mountpoint=none")
+ if err != nil {
+ logger.Errorf("failed to create deleted dataset: %s", msg)
+ return err
+ }
+
+ dataset = fmt.Sprintf("%s/snapshots", poolName)
+ msg, err = zfsPoolVolumeCreate(dataset, "mountpoint=none")
+ if err != nil {
+ logger.Errorf("failed to create snapshots dataset: %s", msg)
+ return err
+ }
+
+ fixperms = shared.VarPath("storage-pools", s.pool.Name, "snapshots")
+ err = os.MkdirAll(fixperms, snapshotsDirMode)
+ if err != nil && !os.IsNotExist(err) {
+ return err
+ }
+ err = os.Chmod(fixperms, snapshotsDirMode)
+ if err != nil {
+ logger.Warnf("failed to chmod \"%s\" to \"0%s\": %s", fixperms, strconv.FormatInt(int64(snapshotsDirMode), 8), err)
+ }
+
+ return nil
+}
+
func (s *storageZfs) StoragePoolDelete() error {
logger.Infof("Deleting ZFS storage pool \"%s\".", s.pool.Name)
diff --git a/lxd/storage_zfs_utils.go b/lxd/storage_zfs_utils.go
index 423b3b6a6..77a86e910 100644
--- a/lxd/storage_zfs_utils.go
+++ b/lxd/storage_zfs_utils.go
@@ -6,7 +6,6 @@ import (
"os"
"os/exec"
"path/filepath"
- "strconv"
"strings"
"syscall"
"time"
@@ -63,198 +62,25 @@ func zfsPoolCheck(pool string) error {
return nil
}
-func (s *storageZfs) zfsPoolCreate() error {
- zpoolName := s.getOnDiskPoolName()
- vdev := s.pool.Config["source"]
- if vdev == "" {
- vdev = filepath.Join(shared.VarPath("disks"), fmt.Sprintf("%s.img", s.pool.Name))
- s.pool.Config["source"] = vdev
-
- if s.pool.Config["zfs.pool_name"] == "" {
- s.pool.Config["zfs.pool_name"] = zpoolName
- }
-
- f, err := os.Create(vdev)
- if err != nil {
- return fmt.Errorf("Failed to open %s: %s", vdev, err)
- }
- defer f.Close()
-
- err = f.Chmod(0600)
- if err != nil {
- return fmt.Errorf("Failed to chmod %s: %s", vdev, err)
- }
-
- size, err := shared.ParseByteSizeString(s.pool.Config["size"])
- if err != nil {
- return err
- }
- err = f.Truncate(size)
- if err != nil {
- return fmt.Errorf("Failed to create sparse file %s: %s", vdev, err)
- }
-
+func zfsPoolCreate(pool string, vdev string) error {
+ var output string
+ var err error
+ if pool == "" {
output, err := shared.RunCommand(
- "zpool",
- "create", zpoolName, vdev,
- "-f", "-m", "none", "-O", "compression=on")
+ "zfs", "create", "-p", "-o", "mountpoint=none", vdev)
if err != nil {
- return fmt.Errorf("Failed to create the ZFS pool: %s", output)
+ logger.Errorf("zfs create failed: %s.", output)
+ return fmt.Errorf("Failed to create ZFS filesystem: %s", output)
}
} else {
- // Unset size property since it doesn't make sense.
- s.pool.Config["size"] = ""
-
- if filepath.IsAbs(vdev) {
- if !shared.IsBlockdevPath(vdev) {
- return fmt.Errorf("custom loop file locations are not supported")
- }
-
- if s.pool.Config["zfs.pool_name"] == "" {
- s.pool.Config["zfs.pool_name"] = zpoolName
- }
-
- // This is a block device. Note, that we do not store the
- // block device path or UUID or PARTUUID or similar in
- // the database. All of those might change or might be
- // used in a special way (For example, zfs uses a single
- // UUID in a multi-device pool for all devices.). The
- // safest way is to just store the name of the zfs pool
- // we create.
- s.pool.Config["source"] = zpoolName
- output, err := shared.RunCommand(
- "zpool",
- "create", zpoolName, vdev,
- "-f", "-m", "none", "-O", "compression=on")
- if err != nil {
- return fmt.Errorf("Failed to create the ZFS pool: %s", output)
- }
- } else {
- if s.pool.Config["zfs.pool_name"] != "" {
- return fmt.Errorf("invalid combination of \"source\" and \"zfs.pool_name\" property")
- }
- s.pool.Config["zfs.pool_name"] = vdev
- s.dataset = vdev
-
- if strings.Contains(vdev, "/") {
- if !zfsFilesystemEntityExists(vdev, "") {
- output, err := shared.RunCommand(
- "zfs",
- "create",
- "-p",
- "-o",
- "mountpoint=none",
- vdev)
- if err != nil {
- logger.Errorf("zfs create failed: %s.", output)
- return fmt.Errorf("Failed to create ZFS filesystem: %s", output)
- }
- } else {
- if err := zfsPoolVolumeSet(vdev, "", "mountpoint", "none"); err != nil {
- return err
- }
- }
- } else {
- err := zfsPoolCheck(vdev)
- if err != nil {
- return err
- }
-
- subvols, err := zfsPoolListSubvolumes(zpoolName, vdev)
- if err != nil {
- return err
- }
-
- if len(subvols) > 0 {
- return fmt.Errorf("Provided ZFS pool (or dataset) isn't empty")
- }
-
- if err := zfsPoolVolumeSet(vdev, "", "mountpoint", "none"); err != nil {
- return err
- }
- }
+ output, err = shared.RunCommand(
+ "zpool", "create", pool, vdev, "-f", "-m", "none", "-O", "compression=on")
+ if err != nil {
+ logger.Errorf("zfs create failed: %s.", output)
+ return fmt.Errorf("Failed to create the ZFS pool: %s", output)
}
}
- // Create default dummy datasets to avoid zfs races during container
- // creation.
- poolName := s.getOnDiskPoolName()
- dataset := fmt.Sprintf("%s/containers", poolName)
- msg, err := zfsPoolVolumeCreate(dataset, "mountpoint=none")
- if err != nil {
- logger.Errorf("failed to create containers dataset: %s", msg)
- return err
- }
-
- fixperms := shared.VarPath("storage-pools", s.pool.Name, "containers")
- err = os.MkdirAll(fixperms, containersDirMode)
- if err != nil && !os.IsNotExist(err) {
- return err
- }
-
- err = os.Chmod(fixperms, containersDirMode)
- if err != nil {
- logger.Warnf("failed to chmod \"%s\" to \"0%s\": %s", fixperms, strconv.FormatInt(int64(containersDirMode), 8), err)
- }
-
- dataset = fmt.Sprintf("%s/images", poolName)
- msg, err = zfsPoolVolumeCreate(dataset, "mountpoint=none")
- if err != nil {
- logger.Errorf("failed to create images dataset: %s", msg)
- return err
- }
-
- fixperms = shared.VarPath("storage-pools", s.pool.Name, "images")
- err = os.MkdirAll(fixperms, imagesDirMode)
- if err != nil && !os.IsNotExist(err) {
- return err
- }
- err = os.Chmod(fixperms, imagesDirMode)
- if err != nil {
- logger.Warnf("failed to chmod \"%s\" to \"0%s\": %s", fixperms, strconv.FormatInt(int64(imagesDirMode), 8), err)
- }
-
- dataset = fmt.Sprintf("%s/custom", poolName)
- msg, err = zfsPoolVolumeCreate(dataset, "mountpoint=none")
- if err != nil {
- logger.Errorf("failed to create custom dataset: %s", msg)
- return err
- }
-
- fixperms = shared.VarPath("storage-pools", s.pool.Name, "custom")
- err = os.MkdirAll(fixperms, customDirMode)
- if err != nil && !os.IsNotExist(err) {
- return err
- }
- err = os.Chmod(fixperms, customDirMode)
- if err != nil {
- logger.Warnf("failed to chmod \"%s\" to \"0%s\": %s", fixperms, strconv.FormatInt(int64(customDirMode), 8), err)
- }
-
- dataset = fmt.Sprintf("%s/deleted", poolName)
- msg, err = zfsPoolVolumeCreate(dataset, "mountpoint=none")
- if err != nil {
- logger.Errorf("failed to create deleted dataset: %s", msg)
- return err
- }
-
- dataset = fmt.Sprintf("%s/snapshots", poolName)
- msg, err = zfsPoolVolumeCreate(dataset, "mountpoint=none")
- if err != nil {
- logger.Errorf("failed to create snapshots dataset: %s", msg)
- return err
- }
-
- fixperms = shared.VarPath("storage-pools", s.pool.Name, "snapshots")
- err = os.MkdirAll(fixperms, snapshotsDirMode)
- if err != nil && !os.IsNotExist(err) {
- return err
- }
- err = os.Chmod(fixperms, snapshotsDirMode)
- if err != nil {
- logger.Warnf("failed to chmod \"%s\" to \"0%s\": %s", fixperms, strconv.FormatInt(int64(snapshotsDirMode), 8), err)
- }
-
return nil
}
More information about the lxc-devel
mailing list