[lxc-devel] [lxd/master] Revert helper

tomponline on Github lxc-bot at linuxcontainers.org
Thu Dec 19 15:11:48 UTC 2019


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 1407 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20191219/92ba04c8/attachment.bin>
-------------- next part --------------
From 40a26daa80f7b29c266d070100320afaca27b5a0 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 19 Dec 2019 14:50:31 +0000
Subject: [PATCH 1/4] lxd/revert: Adds revert helper package for running revert
 functions in reverse order

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/revert/revert.go | 33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)
 create mode 100644 lxd/revert/revert.go

diff --git a/lxd/revert/revert.go b/lxd/revert/revert.go
new file mode 100644
index 0000000000..df4a3b2578
--- /dev/null
+++ b/lxd/revert/revert.go
@@ -0,0 +1,33 @@
+package revert
+
+// Reverter is a helper type to manage revert functions.
+type Reverter struct {
+	revertFuncs []func()
+}
+
+// New returns a new Reverter.
+func New() *Reverter {
+	return &Reverter{}
+}
+
+// Add adds a revert function to the list to be run when Revert() is called.
+func (r *Reverter) Add(f func()) {
+	r.revertFuncs = append(r.revertFuncs, f)
+}
+
+// Fail runs any revert functions in the reverse order they were added.
+// Should be used with defer or when a task has encountered an error and needs to be reverted.
+func (r *Reverter) Fail() {
+	funcCount := len(r.revertFuncs)
+	for k := range r.revertFuncs {
+		// Run the revert functions in reverse order.
+		k = funcCount - 1 - k
+		r.revertFuncs[k]()
+	}
+}
+
+// Success clears the revert functions previously added.
+// Should be called on successful completion of a task to prevent revert functions from being run.
+func (r *Reverter) Success() {
+	r.revertFuncs = nil
+}

From 9acf534017cb167ca134ffe99abcf2a388b63df3 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 19 Dec 2019 15:05:19 +0000
Subject: [PATCH 2/4] lxd/revert/revert/test: Adds revert tests

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/revert/revert_test.go | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)
 create mode 100644 lxd/revert/revert_test.go

diff --git a/lxd/revert/revert_test.go b/lxd/revert/revert_test.go
new file mode 100644
index 0000000000..aa46597536
--- /dev/null
+++ b/lxd/revert/revert_test.go
@@ -0,0 +1,31 @@
+package revert_test
+
+import (
+	"fmt"
+
+	"github.com/lxc/lxd/lxd/revert"
+)
+
+func ExampleRevertFail() {
+	revert := revert.New()
+	defer revert.Fail()
+
+	revert.Add(func() { fmt.Println("1st step") })
+	revert.Add(func() { fmt.Println("2nd step") })
+
+	return // Revert functions are run in reverse order on return.
+	// Output: 2nd step
+	// 1st step
+}
+
+func ExampleRevertSuccess() {
+	revert := revert.New()
+	defer revert.Fail()
+
+	revert.Add(func() { fmt.Println("1st step") })
+	revert.Add(func() { fmt.Println("2nd step") })
+
+	revert.Success() // Revert functions added are not run on return.
+	return
+	// Output:
+}

From 2ffc42d15112051f6f6ea272bc655700a0b68762 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 19 Dec 2019 14:59:34 +0000
Subject: [PATCH 3/4] lxd/storage/backend/lxd: Updates to use revert pkg rather
 than custom revertFuncs slice

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/storage/backend_lxd.go | 17 +++++++----------
 1 file changed, 7 insertions(+), 10 deletions(-)

diff --git a/lxd/storage/backend_lxd.go b/lxd/storage/backend_lxd.go
index 3bc2029119..1c7a0794cb 100644
--- a/lxd/storage/backend_lxd.go
+++ b/lxd/storage/backend_lxd.go
@@ -15,6 +15,7 @@ import (
 	"github.com/lxc/lxd/lxd/migration"
 	"github.com/lxc/lxd/lxd/operations"
 	"github.com/lxc/lxd/lxd/project"
+	"github.com/lxc/lxd/lxd/revert"
 	"github.com/lxc/lxd/lxd/state"
 	"github.com/lxc/lxd/lxd/storage/drivers"
 	"github.com/lxc/lxd/lxd/storage/locking"
@@ -449,12 +450,8 @@ func (b *lxdBackend) CreateInstanceFromBackup(srcBackup backup.Info, srcData io.
 	// We will apply the config as part of the post hook function returned if driver needs to.
 	vol := b.newVolume(drivers.VolumeTypeContainer, drivers.ContentTypeFS, volStorageName, nil)
 
-	revertFuncs := []func(){}
-	defer func() {
-		for _, revertFunc := range revertFuncs {
-			revertFunc()
-		}
-	}()
+	revert := revert.New()
+	defer revert.Fail()
 
 	// Unpack the backup into the new storage volume(s).
 	volPostHook, revertHook, err := b.driver.CreateVolumeFromBackup(vol, srcBackup.Snapshots, srcData, srcBackup.OptimizedStorage, op)
@@ -463,7 +460,7 @@ func (b *lxdBackend) CreateInstanceFromBackup(srcBackup backup.Info, srcData io.
 	}
 
 	if revertHook != nil {
-		revertFuncs = append(revertFuncs, revertHook)
+		revert.Add(revertHook)
 	}
 
 	err = b.ensureInstanceSymlink(instancetype.Container, srcBackup.Project, srcBackup.Name, vol.MountPath())
@@ -471,7 +468,7 @@ func (b *lxdBackend) CreateInstanceFromBackup(srcBackup backup.Info, srcData io.
 		return nil, nil, err
 	}
 
-	revertFuncs = append(revertFuncs, func() {
+	revert.Add(func() {
 		b.removeInstanceSymlink(instancetype.Container, srcBackup.Project, srcBackup.Name)
 	})
 
@@ -481,7 +478,7 @@ func (b *lxdBackend) CreateInstanceFromBackup(srcBackup backup.Info, srcData io.
 			return nil, nil, err
 		}
 
-		revertFuncs = append(revertFuncs, func() {
+		revert.Add(func() {
 			b.removeInstanceSnapshotSymlinkIfUnused(instancetype.Container, srcBackup.Project, srcBackup.Name)
 		})
 	}
@@ -520,7 +517,7 @@ func (b *lxdBackend) CreateInstanceFromBackup(srcBackup backup.Info, srcData io.
 		}
 	}
 
-	revertFuncs = nil
+	revert.Success()
 	return postHook, revertHook, nil
 }
 

From 5aa391deaf686f9c835d60cf954b9c56de223dcf Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 19 Dec 2019 15:00:08 +0000
Subject: [PATCH 4/4] lxd/storage/drivers/driver/dir: Updates to use revert pkg
 rather than custom revertFuncs slice

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/storage/drivers/driver_dir_utils.go   | 18 +++++++-----------
 lxd/storage/drivers/driver_dir_volumes.go | 20 +++++++-------------
 2 files changed, 14 insertions(+), 24 deletions(-)

diff --git a/lxd/storage/drivers/driver_dir_utils.go b/lxd/storage/drivers/driver_dir_utils.go
index aee2a289d6..f13bb1cae7 100644
--- a/lxd/storage/drivers/driver_dir_utils.go
+++ b/lxd/storage/drivers/driver_dir_utils.go
@@ -3,6 +3,7 @@ package drivers
 import (
 	"fmt"
 
+	"github.com/lxc/lxd/lxd/revert"
 	"github.com/lxc/lxd/lxd/storage/quota"
 	log "github.com/lxc/lxd/shared/log15"
 	"github.com/lxc/lxd/shared/units"
@@ -29,10 +30,8 @@ func (d *dir) setupInitialQuota(vol Volume) (func(), error) {
 		return nil, err
 	}
 
-	// Define a function to revert the quota being setup.
-	revertFunc := func() {
-		d.deleteQuota(volPath, volID)
-	}
+	revert := revert.New()
+	defer revert.Fail()
 
 	// Initialise the volume's quota using the volume ID.
 	err = d.initQuota(volPath, volID)
@@ -40,12 +39,9 @@ func (d *dir) setupInitialQuota(vol Volume) (func(), error) {
 		return nil, err
 	}
 
-	revert := true
-	defer func() {
-		if revert {
-			revertFunc()
-		}
-	}()
+	// Define a function to revert the quota being setup.
+	revertFunc := func() { d.deleteQuota(volPath, volID) }
+	revert.Add(revertFunc)
 
 	// Set the quota.
 	err = d.setQuota(volPath, volID, vol.config["size"])
@@ -53,7 +49,7 @@ func (d *dir) setupInitialQuota(vol Volume) (func(), error) {
 		return nil, err
 	}
 
-	revert = false
+	revert.Success()
 	return revertFunc, nil
 }
 
diff --git a/lxd/storage/drivers/driver_dir_volumes.go b/lxd/storage/drivers/driver_dir_volumes.go
index bda0866ef1..53291ee4a4 100644
--- a/lxd/storage/drivers/driver_dir_volumes.go
+++ b/lxd/storage/drivers/driver_dir_volumes.go
@@ -8,6 +8,7 @@ import (
 
 	"github.com/lxc/lxd/lxd/migration"
 	"github.com/lxc/lxd/lxd/operations"
+	"github.com/lxc/lxd/lxd/revert"
 	"github.com/lxc/lxd/lxd/rsync"
 	"github.com/lxc/lxd/lxd/storage/quota"
 	"github.com/lxc/lxd/shared"
@@ -18,18 +19,15 @@ import (
 func (d *dir) CreateVolume(vol Volume, filler *VolumeFiller, op *operations.Operation) error {
 	volPath := vol.MountPath()
 
+	revert := revert.New()
+	defer revert.Fail()
+
 	// Create the volume itself.
 	err := vol.EnsureMountPath()
 	if err != nil {
 		return err
 	}
-
-	revertPath := true
-	defer func() {
-		if revertPath {
-			os.RemoveAll(volPath)
-		}
-	}()
+	revert.Add(func() { os.RemoveAll(volPath) })
 
 	// Create sparse loopback file if volume is block.
 	rootBlockPath := ""
@@ -46,11 +44,7 @@ func (d *dir) CreateVolume(vol Volume, filler *VolumeFiller, op *operations.Oper
 		}
 
 		if revertFunc != nil {
-			defer func() {
-				if revertPath {
-					revertFunc()
-				}
-			}()
+			revert.Add(revertFunc)
 		}
 	}
 
@@ -72,7 +66,7 @@ func (d *dir) CreateVolume(vol Volume, filler *VolumeFiller, op *operations.Oper
 		}
 	}
 
-	revertPath = false
+	revert.Success()
 	return nil
 }
 


More information about the lxc-devel mailing list