[lxc-devel] [lxd/master] Storage fixes on the way to removing old drivers
stgraber on Github
lxc-bot at linuxcontainers.org
Sun Dec 8 02:58:07 UTC 2019
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 301 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20191207/e94b6249/attachment.bin>
-------------- next part --------------
From 574fcef04e767595bdd647a168c60b9127b2bf84 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Sat, 7 Dec 2019 20:35:27 -0500
Subject: [PATCH 1/8] tests: Remove pointless loop/check
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
test/suites/storage_local_volume_handling.sh | 75 ++++++++++----------
1 file changed, 36 insertions(+), 39 deletions(-)
diff --git a/test/suites/storage_local_volume_handling.sh b/test/suites/storage_local_volume_handling.sh
index 12cf50a186..fa5805f9c6 100644
--- a/test/suites/storage_local_volume_handling.sh
+++ b/test/suites/storage_local_volume_handling.sh
@@ -49,50 +49,47 @@ test_storage_local_volume_handling() {
# zfs | x | x | x | x | x |
# -------|-------|-------|-------|-------|-------|
- for driver in "btrfs" "ceph" "dir" "lvm" "zfs"; do
- if [ "$lxd_backend" = "$driver" ]; then
- pool_opts=
+ driver="${lxd_backend}"
+ pool_opts=
- if [ "$driver" = "btrfs" ] || [ "$driver" = "zfs" ]; then
- pool_opts="size=100GB"
- fi
+ if [ "$driver" = "btrfs" ] || [ "$driver" = "zfs" ]; then
+ pool_opts="size=100GB"
+ fi
- if [ "$driver" = "ceph" ]; then
- pool_opts="volume.size=25MB ceph.osd.pg_num=1"
- fi
+ if [ "$driver" = "ceph" ]; then
+ pool_opts="volume.size=25MB ceph.osd.pg_num=1"
+ fi
- if [ "$driver" = "lvm" ]; then
- pool_opts="volume.size=25MB"
- fi
+ if [ "$driver" = "lvm" ]; then
+ pool_opts="volume.size=25MB"
+ fi
- if [ -n "${pool_opts}" ]; then
- # shellcheck disable=SC2086
- lxc storage create "lxdtest-$(basename "${LXD_DIR}")-${driver}1" "${driver}" $pool_opts
- else
- lxc storage create "lxdtest-$(basename "${LXD_DIR}")-${driver}1" "${driver}"
- fi
+ if [ -n "${pool_opts}" ]; then
+ # shellcheck disable=SC2086
+ lxc storage create "lxdtest-$(basename "${LXD_DIR}")-${driver}1" "${driver}" $pool_opts
+ else
+ lxc storage create "lxdtest-$(basename "${LXD_DIR}")-${driver}1" "${driver}"
+ fi
- lxc storage volume create "lxdtest-$(basename "${LXD_DIR}")-${driver}" vol1
- # This will create the snapshot vol1/snap0
- lxc storage volume snapshot "lxdtest-$(basename "${LXD_DIR}")-${driver}" vol1
- # Copy volume with snapshots
- lxc storage volume copy "lxdtest-$(basename "${LXD_DIR}")-${driver}/vol1" "lxdtest-$(basename "${LXD_DIR}")-${driver}1/vol1"
- # Ensure the target snapshot is there
- lxc storage volume show "lxdtest-$(basename "${LXD_DIR}")-${driver}1" vol1/snap0
- # Copy volume only
- lxc storage volume copy --volume-only "lxdtest-$(basename "${LXD_DIR}")-${driver}/vol1" "lxdtest-$(basename "${LXD_DIR}")-${driver}1/vol2"
- # Copy snapshot to volume
- lxc storage volume copy "lxdtest-$(basename "${LXD_DIR}")-${driver}/vol1/snap0" "lxdtest-$(basename "${LXD_DIR}")-${driver}1/vol3"
- lxc storage volume delete "lxdtest-$(basename "${LXD_DIR}")-${driver}1" vol1
- lxc storage volume delete "lxdtest-$(basename "${LXD_DIR}")-${driver}1" vol2
- lxc storage volume delete "lxdtest-$(basename "${LXD_DIR}")-${driver}1" vol3
- lxc storage volume move "lxdtest-$(basename "${LXD_DIR}")-${driver}/vol1" "lxdtest-$(basename "${LXD_DIR}")-${driver}1/vol1"
- ! lxc storage volume show "lxdtest-$(basename "${LXD_DIR}")-${driver}" vol1 || false
- lxc storage volume show "lxdtest-$(basename "${LXD_DIR}")-${driver}1" vol1
- lxc storage volume delete "lxdtest-$(basename "${LXD_DIR}")-${driver}1" vol1
- lxc storage delete "lxdtest-$(basename "${LXD_DIR}")-${driver}1"
- fi
- done
+ lxc storage volume create "lxdtest-$(basename "${LXD_DIR}")-${driver}" vol1
+ # This will create the snapshot vol1/snap0
+ lxc storage volume snapshot "lxdtest-$(basename "${LXD_DIR}")-${driver}" vol1
+ # Copy volume with snapshots
+ lxc storage volume copy "lxdtest-$(basename "${LXD_DIR}")-${driver}/vol1" "lxdtest-$(basename "${LXD_DIR}")-${driver}1/vol1"
+ # Ensure the target snapshot is there
+ lxc storage volume show "lxdtest-$(basename "${LXD_DIR}")-${driver}1" vol1/snap0
+ # Copy volume only
+ lxc storage volume copy --volume-only "lxdtest-$(basename "${LXD_DIR}")-${driver}/vol1" "lxdtest-$(basename "${LXD_DIR}")-${driver}1/vol2"
+ # Copy snapshot to volume
+ lxc storage volume copy "lxdtest-$(basename "${LXD_DIR}")-${driver}/vol1/snap0" "lxdtest-$(basename "${LXD_DIR}")-${driver}1/vol3"
+ lxc storage volume delete "lxdtest-$(basename "${LXD_DIR}")-${driver}1" vol1
+ lxc storage volume delete "lxdtest-$(basename "${LXD_DIR}")-${driver}1" vol2
+ lxc storage volume delete "lxdtest-$(basename "${LXD_DIR}")-${driver}1" vol3
+ lxc storage volume move "lxdtest-$(basename "${LXD_DIR}")-${driver}/vol1" "lxdtest-$(basename "${LXD_DIR}")-${driver}1/vol1"
+ ! lxc storage volume show "lxdtest-$(basename "${LXD_DIR}")-${driver}" vol1 || false
+ lxc storage volume show "lxdtest-$(basename "${LXD_DIR}")-${driver}1" vol1
+ lxc storage volume delete "lxdtest-$(basename "${LXD_DIR}")-${driver}1" vol1
+ lxc storage delete "lxdtest-$(basename "${LXD_DIR}")-${driver}1"
for source_driver in "btrfs" "ceph" "dir" "lvm" "zfs"; do
for target_driver in "btrfs" "ceph" "dir" "lvm" "zfs"; do
From bb3b5de86c6bf4323b3fac134848c5ac1c68f8db Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Sat, 7 Dec 2019 21:55:24 -0500
Subject: [PATCH 2/8] tests: Test copy on cephfs
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
test/suites/storage_local_volume_handling.sh | 19 +++----------------
1 file changed, 3 insertions(+), 16 deletions(-)
diff --git a/test/suites/storage_local_volume_handling.sh b/test/suites/storage_local_volume_handling.sh
index fa5805f9c6..b5d861e7df 100644
--- a/test/suites/storage_local_volume_handling.sh
+++ b/test/suites/storage_local_volume_handling.sh
@@ -34,20 +34,7 @@ test_storage_local_volume_handling() {
lxc storage create "lxdtest-$(basename "${LXD_DIR}")-zfs" zfs size=100GB
fi
- # This looks complex but is basically just the following test matrix:
- #
- # | btrfs | ceph | dir | lvm | zfs |
- # -------|-------|-------|-------|-------|-------|
- # btrfs | x | x | x | x | x |
- # -------|-------|-------|-------|-------|-------|
- # ceph | x | x | x | x | x |
- # -------|-------|-------|-------|-------|-------|
- # dir | x | x | x | x | x |
- # -------|-------|-------|-------|-------|-------|
- # lvm | x | x | x | x | x |
- # -------|-------|-------|-------|-------|-------|
- # zfs | x | x | x | x | x |
- # -------|-------|-------|-------|-------|-------|
+ # Test all combinations of our storage drivers
driver="${lxd_backend}"
pool_opts=
@@ -91,8 +78,8 @@ test_storage_local_volume_handling() {
lxc storage volume delete "lxdtest-$(basename "${LXD_DIR}")-${driver}1" vol1
lxc storage delete "lxdtest-$(basename "${LXD_DIR}")-${driver}1"
- for source_driver in "btrfs" "ceph" "dir" "lvm" "zfs"; do
- for target_driver in "btrfs" "ceph" "dir" "lvm" "zfs"; do
+ for source_driver in "btrfs" "ceph" "cephfs" "dir" "lvm" "zfs"; do
+ for target_driver in "btrfs" "ceph" "cephfs" "dir" "lvm" "zfs"; do
if [ "$source_driver" != "$target_driver" ] && [ "$lxd_backend" = "$source_driver" ] && storage_backend_available "$target_driver"; then
# source_driver -> target_driver
lxc storage volume create "lxdtest-$(basename "${LXD_DIR}")-${source_driver}" vol1
From 061126ef15867564ac825a6a027ddecf3db279cd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Fri, 6 Dec 2019 00:11:31 -0500
Subject: [PATCH 3/8] lxd/container: Cleanup mount logic
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
lxd/container_lxc.go | 21 ++-------------------
1 file changed, 2 insertions(+), 19 deletions(-)
diff --git a/lxd/container_lxc.go b/lxd/container_lxc.go
index 4c6bb2999d..c27404edb0 100644
--- a/lxd/container_lxc.go
+++ b/lxd/container_lxc.go
@@ -2408,7 +2408,7 @@ func (c *containerLXC) OnStart() error {
c.fromHook = true
// Start the storage for this container
- ourStart, err := c.storageStartSensitive()
+ ourStart, err := c.mount()
if err != nil {
return err
}
@@ -6017,25 +6017,8 @@ func (c *containerLXC) mount() (bool, error) {
return ourMount, nil
}
- // Initialize legacy storage interface for the container.
- err = c.initStorage()
- if err != nil {
- return false, err
- }
-
- isOurOperation, err := c.storageStartSensitive()
- // Remove this as soon as zfs is fixed
- if c.storage.GetStorageType() == storageTypeZfs && err == unix.EBUSY {
- return isOurOperation, nil
- }
-
- return isOurOperation, err
-}
-
-// Kill this function as soon as zfs is fixed.
-func (c *containerLXC) storageStartSensitive() (bool, error) {
// Initialize storage interface for the container.
- err := c.initStorage()
+ err = c.initStorage()
if err != nil {
return false, err
}
From 200dd1a7f1f993aa5522f55b722d7f3633e6ee59 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Fri, 6 Dec 2019 00:59:34 -0500
Subject: [PATCH 4/8] lxd/storage: Port volume attach/detach
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
lxd/storage.go | 53 ++++++++++++++++++++++++++++++++++----------------
1 file changed, 36 insertions(+), 17 deletions(-)
diff --git a/lxd/storage.go b/lxd/storage.go
index 86ad48d88a..841889b0ee 100644
--- a/lxd/storage.go
+++ b/lxd/storage.go
@@ -33,11 +33,12 @@ import (
func init() {
// Expose storageVolumeMount to the device package as StorageVolumeMount.
device.StorageVolumeMount = storageVolumeMount
+
// Expose storageVolumeUmount to the device package as StorageVolumeUmount.
device.StorageVolumeUmount = storageVolumeUmount
+
// Expose storageRootFSApplyQuota to the device package as StorageRootFSApplyQuota.
device.StorageRootFSApplyQuota = storageRootFSApplyQuota
-
}
// lxdStorageLockMap is a hashmap that allows functions to check whether the
@@ -833,15 +834,25 @@ func storageVolumeMount(state *state.State, poolName string, volumeName string,
return fmt.Errorf("Received non-LXC container instance")
}
- volumeType, _ := storagePools.VolumeTypeNameToType(volumeTypeName)
- s, err := storagePoolVolumeAttachInit(state, poolName, volumeName, volumeType, c)
- if err != nil {
- return err
- }
+ pool, err := storagePools.GetPoolByName(state, poolName)
+ if err != storageDrivers.ErrUnknownDriver && err != storageDrivers.ErrNotImplemented {
+ // FIXME: need equivalent to AttachInit
+ _, err = pool.MountCustomVolume(volumeName, nil)
+ if err != nil {
+ return err
+ }
+ } else {
+ // Custom storage volumes do not currently support projects, so hardcode "default" project.
+ volumeType, _ := storagePools.VolumeTypeNameToType(volumeTypeName)
+ s, err := storagePoolVolumeAttachInit(state, poolName, volumeName, volumeType, c)
+ if err != nil {
+ return err
+ }
- _, err = s.StoragePoolVolumeMount()
- if err != nil {
- return err
+ _, err = s.StoragePoolVolumeMount()
+ if err != nil {
+ return err
+ }
}
return nil
@@ -849,15 +860,23 @@ func storageVolumeMount(state *state.State, poolName string, volumeName string,
// storageVolumeUmount unmounts a storage volume on a pool.
func storageVolumeUmount(state *state.State, poolName string, volumeName string, volumeType int) error {
- // Custom storage volumes do not currently support projects, so hardcode "default" project.
- s, err := storagePoolVolumeInit(state, "default", poolName, volumeName, volumeType)
- if err != nil {
- return err
- }
+ pool, err := storagePools.GetPoolByName(state, poolName)
+ if err != storageDrivers.ErrUnknownDriver && err != storageDrivers.ErrNotImplemented {
+ _, err = pool.UnmountCustomVolume(volumeName, nil)
+ if err != nil {
+ return err
+ }
+ } else {
+ // Custom storage volumes do not currently support projects, so hardcode "default" project.
+ s, err := storagePoolVolumeInit(state, "default", poolName, volumeName, volumeType)
+ if err != nil {
+ return err
+ }
- _, err = s.StoragePoolVolumeUmount()
- if err != nil {
- return err
+ _, err = s.StoragePoolVolumeUmount()
+ if err != nil {
+ return err
+ }
}
return nil
From 3f42e6287531179a7e305157a6d62d2e119e985b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Fri, 6 Dec 2019 01:04:02 -0500
Subject: [PATCH 5/8] lxd/container: Remove unused initStorage
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
lxd/container_lxc.go | 6 ------
1 file changed, 6 deletions(-)
diff --git a/lxd/container_lxc.go b/lxd/container_lxc.go
index c27404edb0..33d1bb1cd5 100644
--- a/lxd/container_lxc.go
+++ b/lxd/container_lxc.go
@@ -4079,12 +4079,6 @@ func (c *containerLXC) Update(args db.InstanceArgs, userRequested bool) error {
return errors.Wrap(err, "Initialize LXC")
}
- // Initialize storage interface for the container.
- err = c.initStorage()
- if err != nil {
- return errors.Wrap(err, "Initialize storage")
- }
-
// If apparmor changed, re-validate the apparmor profile
if shared.StringInSlice("raw.apparmor", changedConfig) || shared.StringInSlice("security.nesting", changedConfig) {
err = apparmor.ParseProfile(c)
From 8bfc4f0c16f978d3d5cab791afed3e325d0747a8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Sat, 7 Dec 2019 21:38:21 -0500
Subject: [PATCH 6/8] lxd/import: Fix handling of new drivers
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
lxd/api_internal.go | 46 ++++++++++++++++++++++++++++-----------------
1 file changed, 29 insertions(+), 17 deletions(-)
diff --git a/lxd/api_internal.go b/lxd/api_internal.go
index 1740f1bfb0..4a5e8e6d3f 100644
--- a/lxd/api_internal.go
+++ b/lxd/api_internal.go
@@ -26,6 +26,8 @@ import (
"github.com/lxc/lxd/lxd/project"
"github.com/lxc/lxd/lxd/response"
driver "github.com/lxc/lxd/lxd/storage"
+ storagePools "github.com/lxc/lxd/lxd/storage"
+ storageDrivers "github.com/lxc/lxd/lxd/storage/drivers"
"github.com/lxc/lxd/shared"
"github.com/lxc/lxd/shared/api"
log "github.com/lxc/lxd/shared/log15"
@@ -518,30 +520,40 @@ func internalImport(d *Daemon, r *http.Request) response.Response {
}
}
- initPool, err := storagePoolInit(d.State(), backup.Pool.Name)
- if err != nil {
- err = errors.Wrap(err, "Initialize storage")
- return response.InternalError(err)
- }
+ var poolName string
+ _, err = storagePools.GetPoolByName(d.State(), backup.Pool.Name)
+ if err != storageDrivers.ErrUnknownDriver && err != db.ErrNoSuchObject {
+ if err != nil {
+ return response.InternalError(err)
+ }
- ourMount, err := initPool.StoragePoolMount()
- if err != nil {
- return response.InternalError(err)
- }
- if ourMount {
- defer initPool.StoragePoolUmount()
+ // FIXME: In the new world, we don't expose the on-disk pool
+ // name, instead we need to change the per-driver logic below to using
+ // clean storage functions.
+ poolName = backup.Pool.Name
+ } else {
+ initPool, err := storagePoolInit(d.State(), backup.Pool.Name)
+ if err != nil {
+ err = errors.Wrap(err, "Initialize storage")
+ return response.InternalError(err)
+ }
+
+ ourMount, err := initPool.StoragePoolMount()
+ if err != nil {
+ return response.InternalError(err)
+ }
+ if ourMount {
+ defer initPool.StoragePoolUmount()
+ }
+
+ // retrieve on-disk pool name
+ _, _, poolName = initPool.GetContainerPoolInfo()
}
existingSnapshots := []*api.InstanceSnapshot{}
needForce := fmt.Errorf(`The snapshot does not exist on disk. Pass ` +
`"force" to discard non-existing snapshots`)
- // retrieve on-disk pool name
- _, _, poolName := initPool.GetContainerPoolInfo()
- if err != nil {
- return response.InternalError(err)
- }
-
// Retrieve all snapshots that exist on disk.
onDiskSnapshots := []string{}
if len(backup.Snapshots) > 0 {
From cdaf567ceaf7a5c402d6bb5c5ae835e3660d9511 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Sat, 7 Dec 2019 21:38:37 -0500
Subject: [PATCH 7/8] lxd/backup: Fix backup creation on new drivers
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
lxd/backup.go | 20 +++++++++++++++-----
1 file changed, 15 insertions(+), 5 deletions(-)
diff --git a/lxd/backup.go b/lxd/backup.go
index 07805ceb16..b784e9129e 100644
--- a/lxd/backup.go
+++ b/lxd/backup.go
@@ -104,7 +104,7 @@ func backupCreate(s *state.State, args db.InstanceBackupArgs, sourceInst instanc
func backupCreateTarball(s *state.State, path string, b backup.Backup, c instance.Instance) error {
// Create the index
- pool, err := c.StoragePool()
+ poolName, err := c.StoragePool()
if err != nil {
return err
}
@@ -113,16 +113,26 @@ func backupCreateTarball(s *state.State, path string, b backup.Backup, c instanc
return fmt.Errorf("Instance type must be container")
}
- ct := c.(*containerLXC)
-
indexFile := backup.Info{
Name: c.Name(),
- Backend: ct.Storage().GetStorageTypeName(),
Privileged: c.IsPrivileged(),
- Pool: pool,
+ Pool: poolName,
Snapshots: []string{},
}
+ pool, err := storagePools.GetPoolByInstance(s, c)
+ if err != storageDrivers.ErrUnknownDriver && err != db.ErrNoSuchObject {
+ if err != nil {
+ return err
+ }
+
+ info := pool.Driver().Info()
+ indexFile.Backend = info.Name
+ } else {
+ ct := c.(*containerLXC)
+ indexFile.Backend = ct.Storage().GetStorageTypeName()
+ }
+
if !b.InstanceOnly() {
snaps, err := c.Snapshots()
if err != nil {
From a688cd9b4dd601cc56ab804920a126993b5487d3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Sat, 7 Dec 2019 21:48:05 -0500
Subject: [PATCH 8/8] lxd/storage/zfs: Use StoragePool to get pool name
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
lxd/storage_zfs.go | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/lxd/storage_zfs.go b/lxd/storage_zfs.go
index 16b74562ea..12c6776022 100644
--- a/lxd/storage_zfs.go
+++ b/lxd/storage_zfs.go
@@ -1274,8 +1274,16 @@ func (s *storageZfs) ContainerCopy(target instance.Instance, source instance.Ins
srcCt := source.(*containerLXC)
targetCt := target.(*containerLXC)
- _, sourcePool, _ := srcCt.Storage().GetContainerPoolInfo()
- _, targetPool, _ := targetCt.Storage().GetContainerPoolInfo()
+ sourcePool, err := srcCt.StoragePool()
+ if err != nil {
+ return err
+ }
+
+ targetPool, err := targetCt.StoragePool()
+ if err != nil {
+ return err
+ }
+
if sourcePool != targetPool {
err := s.doCrossPoolContainerCopy(target, source, containerOnly, false, nil)
if err != nil {
More information about the lxc-devel
mailing list