[lxc-devel] [lxd/master] Storage: Restore VM generic backups using their original volume size
tomponline on Github
lxc-bot at linuxcontainers.org
Thu Apr 30 15:16:05 UTC 2020
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 724 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20200430/a31383d1/attachment.bin>
-------------- next part --------------
From 259be8515763a0a7a9fdc3dbc4d622a5bb0d9eae Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 30 Apr 2020 15:16:13 +0100
Subject: [PATCH 01/10] lxd/instances/post: Fix revert in createFromBackup
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/instances_post.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lxd/instances_post.go b/lxd/instances_post.go
index 77fba7b94e..d056df29c2 100644
--- a/lxd/instances_post.go
+++ b/lxd/instances_post.go
@@ -663,7 +663,7 @@ func createFromBackup(d *Daemon, project string, data io.Reader, pool string) re
if err != nil {
return errors.Wrap(err, "Create instance from backup")
}
- revert.Add(revertHook)
+ runRevert.Add(revertHook)
body, err := json.Marshal(&internalImportPost{
Name: bInfo.Name,
From 40003d5c942a7dac91bfe8b8493d3f2fab2c2cad Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 30 Apr 2020 15:16:31 +0100
Subject: [PATCH 02/10] lxd/storage/drivers/volume: Adds allowUnsafeResize bool
to Volume struct
Used to indicate unsafe resizing (shrinking) is wanted by the caller and all helpers (such as GPT moving) should be skipped.
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/storage/drivers/volume.go | 19 ++++++++++---------
1 file changed, 10 insertions(+), 9 deletions(-)
diff --git a/lxd/storage/drivers/volume.go b/lxd/storage/drivers/volume.go
index a97a311389..ac98e6e324 100644
--- a/lxd/storage/drivers/volume.go
+++ b/lxd/storage/drivers/volume.go
@@ -62,15 +62,16 @@ var BaseDirectories = map[VolumeType][]string{
// Volume represents a storage volume, and provides functions to mount and unmount it.
type Volume struct {
- name string
- pool string
- poolConfig map[string]string
- volType VolumeType
- contentType ContentType
- config map[string]string
- driver Driver
- keepDevice bool
- customMountPath string
+ name string
+ pool string
+ poolConfig map[string]string
+ volType VolumeType
+ contentType ContentType
+ config map[string]string
+ driver Driver
+ keepDevice bool
+ customMountPath string
+ allowUnsafeResize bool // Whether to allow potentially destructive unchecked resizing of volume.
}
// NewVolume instantiates a new Volume struct.
From 9e63148f3c7c8466511858894997a56762c96579 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 30 Apr 2020 15:17:23 +0100
Subject: [PATCH 03/10] lxd/storage/backend/lxd: Adds cannot shrink error
handling in CreateInstanceFromBackup
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/storage/backend_lxd.go | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/lxd/storage/backend_lxd.go b/lxd/storage/backend_lxd.go
index 574ff172d7..1ff2fbb41b 100644
--- a/lxd/storage/backend_lxd.go
+++ b/lxd/storage/backend_lxd.go
@@ -587,7 +587,17 @@ func (b *lxdBackend) CreateInstanceFromBackup(srcBackup backup.Info, srcData io.
logger.Debug("Applying volume quota from root disk config", log.Ctx{"size": rootDiskConf["size"]})
err = b.driver.SetVolumeQuota(vol, rootDiskConf["size"], op)
if err != nil {
- return err
+ // The restored volume can end up being larger than the root disk config's size
+ // property due to the block boundary rounding some storage drivers use. As such
+ // if the restored volume is larger than the config's size and it cannot be shrunk
+ // to the equivalent size on the target storage driver, don't fail as the backup
+ // has still been restored successfully.
+ if errors.Cause(err) == drivers.ErrCannotBeShrunk {
+ logger.Warn("Could not apply volume quota from root disk config as restored volume cannot be shrunk", log.Ctx{"size": rootDiskConf["size"]})
+
+ } else {
+ return err
+ }
}
}
From 96456f4d7c8b4226756148a33fd31deba7518d91 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 30 Apr 2020 15:17:59 +0100
Subject: [PATCH 04/10] lxd/storage/drivers/generic/vfs: Sets block volume size
to file size of volume in tarball in genericVFSBackupUnpack
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/storage/drivers/generic_vfs.go | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/lxd/storage/drivers/generic_vfs.go b/lxd/storage/drivers/generic_vfs.go
index 966cbb374d..57ad06a62a 100644
--- a/lxd/storage/drivers/generic_vfs.go
+++ b/lxd/storage/drivers/generic_vfs.go
@@ -653,6 +653,17 @@ func genericVFSBackupUnpack(d Driver, vol Volume, snapshots []string, srcData io
}
defer to.Close()
+ // Restore original size of volume from raw block backup file size.
+ d.Logger().Debug("Setting volume size from source", log.Ctx{"source": srcFile, "target": targetPath, "size": hdr.Size})
+
+ // Allow potentially destructive resize of volume as we are going to be
+ // overwriting it entirely anyway. This allows shrinking of block volumes.
+ vol.allowUnsafeResize = true
+ err = d.SetVolumeQuota(vol, fmt.Sprintf("%d", hdr.Size), op)
+ if err != nil {
+ return err
+ }
+
_, err = io.Copy(to, tr)
if err != nil {
return err
From 43b1a64cf91afaed7ea21dcf6141347557c4be26 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 30 Apr 2020 15:18:57 +0100
Subject: [PATCH 05/10] lxd/storage/drivers/driver/btrfs/volumes: No need to
move GPT header if no filler used in CreateVolume
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/storage/drivers/driver_btrfs_volumes.go | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lxd/storage/drivers/driver_btrfs_volumes.go b/lxd/storage/drivers/driver_btrfs_volumes.go
index 0092085c8f..f9748538c0 100644
--- a/lxd/storage/drivers/driver_btrfs_volumes.go
+++ b/lxd/storage/drivers/driver_btrfs_volumes.go
@@ -65,8 +65,8 @@ func (d *btrfs) CreateVolume(vol Volume, filler *VolumeFiller, op *operations.Op
return err
}
- // Move the GPT alt header to end of disk if needed.
- if vol.IsVMBlock() {
+ // Move the GPT alt header to end of disk if needed and if filler specified.
+ if vol.IsVMBlock() && filler != nil && filler.Fill != nil {
err = d.moveGPTAltHeader(rootBlockPath)
if err != nil {
return err
From f8e4bf5d93832678bedcfc71bbee3a81eacaa909 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 30 Apr 2020 15:19:30 +0100
Subject: [PATCH 06/10] lxd/storage/drivers/driver/btrfs/volumes: Skip GPT
header move in SetVolumeQuota when allowUnsafeResize is enabled
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/storage/drivers/driver_btrfs_volumes.go | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/lxd/storage/drivers/driver_btrfs_volumes.go b/lxd/storage/drivers/driver_btrfs_volumes.go
index f9748538c0..a8ca986e9e 100644
--- a/lxd/storage/drivers/driver_btrfs_volumes.go
+++ b/lxd/storage/drivers/driver_btrfs_volumes.go
@@ -461,8 +461,10 @@ func (d *btrfs) SetVolumeQuota(vol Volume, size string, op *operations.Operation
return err
}
- // Move the GPT alt header to end of disk if needed and resize has taken place.
- if vol.IsVMBlock() && resized {
+ // Move the GPT alt header to end of disk if needed and resize has taken place (not needed in
+ // unsafe resize mode as it is expected the caller will do all necessary post resize actions
+ // themselves).
+ if vol.IsVMBlock() && resized && !vol.allowUnsafeResize {
err = d.moveGPTAltHeader(rootBlockPath)
if err != nil {
return err
From 58cdf30ccd7c907ba26167b055bd2c7c165d4b33 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 30 Apr 2020 15:20:25 +0100
Subject: [PATCH 07/10] lxd/storage/drivers/driver/dir/volumes: Skip GPT header
move in SetVolumeQuota when allowUnsafeResize is enabled
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/storage/drivers/driver_dir_volumes.go | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/lxd/storage/drivers/driver_dir_volumes.go b/lxd/storage/drivers/driver_dir_volumes.go
index 7f3fcadb38..58b1d0b157 100644
--- a/lxd/storage/drivers/driver_dir_volumes.go
+++ b/lxd/storage/drivers/driver_dir_volumes.go
@@ -260,8 +260,10 @@ func (d *dir) SetVolumeQuota(vol Volume, size string, op *operations.Operation)
return err
}
- // Move the GPT alt header to end of disk if needed and resize has taken place.
- if vol.IsVMBlock() && resized {
+ // Move the GPT alt header to end of disk if needed and resize has taken place (not needed in
+ // unsafe resize mode as it is expected the caller will do all necessary post resize actions
+ // themselves).
+ if vol.IsVMBlock() && resized && !vol.allowUnsafeResize {
err = d.moveGPTAltHeader(rootBlockPath)
if err != nil {
return err
From 0d7925abb6fb5cb9dea3281fd7d400c1074be008 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 30 Apr 2020 15:20:48 +0100
Subject: [PATCH 08/10] lxd/storage/drivers/driver/lvm/volumes: Allow unsafe
shrinking when allowUnsafeResize is enabled
Also skip GPT header move.
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/storage/drivers/driver_lvm_volumes.go | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/lxd/storage/drivers/driver_lvm_volumes.go b/lxd/storage/drivers/driver_lvm_volumes.go
index 363a6672ae..62ef87fc49 100644
--- a/lxd/storage/drivers/driver_lvm_volumes.go
+++ b/lxd/storage/drivers/driver_lvm_volumes.go
@@ -381,7 +381,7 @@ func (d *lvm) SetVolumeQuota(vol Volume, size string, op *operations.Operation)
d.logger.Debug("Logical volume filesystem grown", logCtx)
}
} else {
- if newSizeBytes < oldSizeBytes {
+ if newSizeBytes < oldSizeBytes && !vol.allowUnsafeResize {
return errors.Wrap(ErrCannotBeShrunk, "You cannot shrink block volumes")
}
@@ -391,8 +391,9 @@ func (d *lvm) SetVolumeQuota(vol Volume, size string, op *operations.Operation)
}
- // Move the GPT alt header to end of disk if needed.
- if vol.IsVMBlock() {
+ // Move the VM GPT alt header to end of disk if needed (not needed in unsafe resize mode as it is
+ // expected the caller will do all necessary post resize actions themselves).
+ if vol.IsVMBlock() && !vol.allowUnsafeResize {
err = d.moveGPTAltHeader(volDevPath)
if err != nil {
return err
From 403f65543e8983160da811cf56eb55ea2c6a74df Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 30 Apr 2020 15:21:43 +0100
Subject: [PATCH 09/10] lxd/storage/drivers/driver/zfs/volumes: Allow unsafe
shrinking when allowUnsafeResize is enabled
Also skip GPT header move.
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/storage/drivers/driver_zfs_volumes.go | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/lxd/storage/drivers/driver_zfs_volumes.go b/lxd/storage/drivers/driver_zfs_volumes.go
index 972c63211e..8ab7c255bf 100644
--- a/lxd/storage/drivers/driver_zfs_volumes.go
+++ b/lxd/storage/drivers/driver_zfs_volumes.go
@@ -914,7 +914,7 @@ func (d *zfs) SetVolumeQuota(vol Volume, size string, op *operations.Operation)
return nil
}
- if sizeBytes < oldVolSizeBytes {
+ if sizeBytes < oldVolSizeBytes && !vol.allowUnsafeResize {
return errors.Wrap(ErrCannotBeShrunk, "You cannot shrink block volumes")
}
@@ -929,8 +929,9 @@ func (d *zfs) SetVolumeQuota(vol Volume, size string, op *operations.Operation)
return err
}
- // Move the GPT alt header to end of disk if needed.
- if vol.IsVMBlock() {
+ // Move the VM GPT alt header to end of disk if needed (not needed in unsafe resize mode as
+ // it is expected the caller will do all necessary post resize actions themselves).
+ if vol.IsVMBlock() && !vol.allowUnsafeResize {
err = d.moveGPTAltHeader(devPath)
if err != nil {
return err
From 4601d72857b58e9cc3bd636c750008cb6a2fd58f Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 30 Apr 2020 15:48:42 +0100
Subject: [PATCH 10/10] lxd/storage/drivers/driver/ceph/volumes: Allow unsafe
shrinking when allowUnsafeResize is enabled
Also skip GPT header move.
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/storage/drivers/driver_ceph_volumes.go | 72 ++++++++++------------
1 file changed, 32 insertions(+), 40 deletions(-)
diff --git a/lxd/storage/drivers/driver_ceph_volumes.go b/lxd/storage/drivers/driver_ceph_volumes.go
index 623a12b182..643b4542e7 100644
--- a/lxd/storage/drivers/driver_ceph_volumes.go
+++ b/lxd/storage/drivers/driver_ceph_volumes.go
@@ -774,50 +774,33 @@ func (d *ceph) SetVolumeQuota(vol Volume, size string, op *operations.Operation)
}
// Resize filesystem if needed.
- if vol.contentType == ContentTypeFS {
- if newSizeBytes < oldSizeBytes {
- err = shrinkFileSystem(fsType, RBDDevPath, vol, newSizeBytes)
- if err != nil {
- return err
- }
+ if newSizeBytes < oldSizeBytes {
+ if vol.contentType == ContentTypeBlock && !vol.allowUnsafeResize {
+ return errors.Wrap(ErrCannotBeShrunk, "You cannot shrink block volumes")
+ }
- _, err = shared.TryRunCommand(
- "rbd",
- "resize",
- "--allow-shrink",
- "--id", d.config["ceph.user.name"],
- "--cluster", d.config["ceph.cluster_name"],
- "--pool", d.config["ceph.osd.pool_name"],
- "--size", fmt.Sprintf("%dB", newSizeBytes),
- d.getRBDVolumeName(vol, "", false, false))
- if err != nil {
- return err
- }
- } else {
- // Grow the block device.
- _, err = shared.TryRunCommand(
- "rbd",
- "resize",
- "--id", d.config["ceph.user.name"],
- "--cluster", d.config["ceph.cluster_name"],
- "--pool", d.config["ceph.osd.pool_name"],
- "--size", fmt.Sprintf("%dB", newSizeBytes),
- d.getRBDVolumeName(vol, "", false, false))
+ // Shrink the filesystem.
+ if vol.contentType == ContentTypeFS {
+ err = shrinkFileSystem(fsType, RBDDevPath, vol, newSizeBytes)
if err != nil {
return err
}
+ }
- // Grow the filesystem.
- err = growFileSystem(fsType, RBDDevPath, vol)
- if err != nil {
- return err
- }
+ // Shrink the block device.
+ _, err = shared.TryRunCommand(
+ "rbd",
+ "resize",
+ "--allow-shrink",
+ "--id", d.config["ceph.user.name"],
+ "--cluster", d.config["ceph.cluster_name"],
+ "--pool", d.config["ceph.osd.pool_name"],
+ "--size", fmt.Sprintf("%dB", newSizeBytes),
+ d.getRBDVolumeName(vol, "", false, false))
+ if err != nil {
+ return err
}
} else {
- if newSizeBytes < oldSizeBytes {
- return errors.Wrap(ErrCannotBeShrunk, "You cannot shrink block volumes")
- }
-
// Grow the block device.
_, err = shared.TryRunCommand(
"rbd",
@@ -831,15 +814,24 @@ func (d *ceph) SetVolumeQuota(vol Volume, size string, op *operations.Operation)
return err
}
- // Move the GPT alt header to end of disk if needed.
- if vol.IsVMBlock() {
- err = d.moveGPTAltHeader(RBDDevPath)
+ // Grow the filesystem.
+ if vol.contentType == ContentTypeFS {
+ err = growFileSystem(fsType, RBDDevPath, vol)
if err != nil {
return err
}
}
}
+ // Move the VM GPT alt header to end of disk if needed (not needed in unsafe resize mode as it is
+ // expected the caller will do all necessary post resize actions themselves).
+ if vol.IsVMBlock() && !vol.allowUnsafeResize {
+ err = d.moveGPTAltHeader(RBDDevPath)
+ if err != nil {
+ return err
+ }
+ }
+
return nil
}
More information about the lxc-devel
mailing list