[lxc-devel] [lxd/master] lxd/storage: Support deleting snapshots during restore
stgraber on Github
lxc-bot at linuxcontainers.org
Wed Jan 8 21:39:06 UTC 2020
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 354 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20200108/52151a14/attachment-0001.bin>
-------------- next part --------------
From 993886156574bdf1bb62530acc6bddbf3bb925ed Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Wed, 8 Jan 2020 15:57:05 -0500
Subject: [PATCH] lxd/storage: Support deleting snapshots during restore
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/backend_lxd.go | 60 ++++++++++++++++++++++++++++++++++-
lxd/storage/drivers/errors.go | 9 ++++++
2 files changed, 68 insertions(+), 1 deletion(-)
diff --git a/lxd/storage/backend_lxd.go b/lxd/storage/backend_lxd.go
index 89f6882817..1ec8fc2025 100644
--- a/lxd/storage/backend_lxd.go
+++ b/lxd/storage/backend_lxd.go
@@ -1699,6 +1699,35 @@ func (b *lxdBackend) RestoreInstanceSnapshot(inst instance.Instance, src instanc
vol := b.newVolume(volType, contentType, volStorageName, rootDiskConf)
err = b.driver.RestoreVolume(vol, snapshotName, op)
if err != nil {
+ snapErr, ok := err.(drivers.ErrDeleteSnapshots)
+ if ok {
+ // We need to delete some snapshots and try again.
+ snaps, err := inst.Snapshots()
+ if err != nil {
+ return err
+ }
+
+ // Go through all the snapshots.
+ for _, snap := range snaps {
+ _, snapName, _ := shared.InstanceGetParentAndSnapshotName(src.Name())
+ if !shared.StringInSlice(snapName, snapErr.Snapshots) {
+ continue
+ }
+
+ // Delete if listed.
+ err := b.DeleteInstanceSnapshot(snap, op)
+ if err != nil {
+ return err
+ }
+ }
+
+ // Now try again.
+ err = b.driver.RestoreVolume(vol, snapshotName, op)
+ if err != nil {
+ return err
+ }
+ }
+
return err
}
@@ -2607,6 +2636,7 @@ func (b *lxdBackend) RestoreCustomVolume(volName string, snapshotName string, op
logger.Debug("RestoreCustomVolume started")
defer logger.Debug("RestoreCustomVolume finished")
+ // Sanity checks.
if shared.IsSnapshot(volName) {
return fmt.Errorf("Volume cannot be snapshot")
}
@@ -2615,6 +2645,7 @@ func (b *lxdBackend) RestoreCustomVolume(volName string, snapshotName string, op
return fmt.Errorf("Invalid snapshot name")
}
+ // Check that the volume isn't in use.
usingVolume, err := VolumeUsedByInstancesWithProfiles(b.state, b.Name(), volName, db.StoragePoolVolumeTypeNameCustom, true)
if err != nil {
return err
@@ -2624,8 +2655,35 @@ func (b *lxdBackend) RestoreCustomVolume(volName string, snapshotName string, op
return fmt.Errorf("Cannot restore custom volume used by running instances")
}
- err = b.driver.RestoreVolume(b.newVolume(drivers.VolumeTypeCustom, drivers.ContentTypeFS, volName, nil), snapshotName, op)
+ // Get the volume config.
+ _, dbVol, err := b.state.Cluster.StoragePoolNodeVolumeGetTypeByProject("default", volName, db.StoragePoolVolumeTypeCustom, b.ID())
+ if err != nil {
+ if err == db.ErrNoSuchObject {
+ return fmt.Errorf("Volume doesn't exist")
+ }
+
+ return err
+ }
+
+ err = b.driver.RestoreVolume(b.newVolume(drivers.VolumeTypeCustom, drivers.ContentTypeFS, volName, dbVol.Config), snapshotName, op)
if err != nil {
+ snapErr, ok := err.(drivers.ErrDeleteSnapshots)
+ if ok {
+ // We need to delete some snapshots and try again.
+ for _, snapName := range snapErr.Snapshots {
+ err := b.DeleteCustomVolumeSnapshot(fmt.Sprintf("%s/%s", volName, snapName), op)
+ if err != nil {
+ return err
+ }
+ }
+
+ // Now try again.
+ err = b.driver.RestoreVolume(b.newVolume(drivers.VolumeTypeCustom, drivers.ContentTypeFS, volName, dbVol.Config), snapshotName, op)
+ if err != nil {
+ return err
+ }
+ }
+
return err
}
diff --git a/lxd/storage/drivers/errors.go b/lxd/storage/drivers/errors.go
index e9fb157bc6..cae5eba16a 100644
--- a/lxd/storage/drivers/errors.go
+++ b/lxd/storage/drivers/errors.go
@@ -12,3 +12,12 @@ var ErrUnknownDriver = fmt.Errorf("Unknown driver")
// ErrNotSupported is the "Not supported" error
var ErrNotSupported = fmt.Errorf("Not supported")
+
+// ErrDeleteSnapshots is a special error used to tell the backend to delete more recent snapshots
+type ErrDeleteSnapshots struct {
+ Snapshots []string
+}
+
+func (e ErrDeleteSnapshots) Error() string {
+ return fmt.Sprintf("More recent snapshots must be deleted: %+v", e.Snapshots)
+}
More information about the lxc-devel
mailing list