[lxc-devel] [lxd/master] Add `rebase` mode for `zfs.clone_copy`

stgraber on Github lxc-bot at linuxcontainers.org
Sat Oct 31 01:16:56 UTC 2020


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/20201030/7cfe91c6/attachment.bin>
-------------- next part --------------
From 3f965e407fc42df23a43432721d24b106cd10d5b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Fri, 30 Oct 2020 18:35:16 -0400
Subject: [PATCH 1/4] api: Add storage_zfs_clone_copy_rebase extension
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>
---
 doc/api-extensions.md | 5 +++++
 shared/version/api.go | 1 +
 2 files changed, 6 insertions(+)

diff --git a/doc/api-extensions.md b/doc/api-extensions.md
index 1742003087..555e83d8c6 100644
--- a/doc/api-extensions.md
+++ b/doc/api-extensions.md
@@ -1217,3 +1217,8 @@ both at the network and NIC level.
 
 ## tpm\_device\_type
 This introduces the `tpm` device type.
+
+## storage\_zfs\_clone\_copy\_rebase
+This introduces `rebase` as a value for zfs.clone\_copy causing LXD to
+track down any "image" dataset in the ancestry line and then perform
+send/receive on top of that.
diff --git a/shared/version/api.go b/shared/version/api.go
index 2ff1e77db4..2c986fa5f0 100644
--- a/shared/version/api.go
+++ b/shared/version/api.go
@@ -234,6 +234,7 @@ var APIExtensions = []string{
 	"network_ovn_nat",
 	"network_ovn_external_routes_remove",
 	"tpm_device_type",
+	"storage_zfs_clone_copy_rebase",
 }
 
 // APIExtensionsCount returns the number of available API extensions.

From a12c58c769865dba839680d63def728dcfc74991 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Fri, 30 Oct 2020 18:35:34 -0400
Subject: [PATCH 2/4] doc/storage: Allow 'rebase' in zfs.clone_copy
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>
---
 doc/storage.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/doc/storage.md b/doc/storage.md
index 67dc5786f1..5d95e3808e 100644
--- a/doc/storage.md
+++ b/doc/storage.md
@@ -35,7 +35,7 @@ volume.block.mount\_options     | string    | block based driver (lvm)
 volume.size                     | string    | appropriate driver                | unlimited (10GB for block) | storage                            | Default volume size
 volume.zfs.remove\_snapshots    | bool      | zfs driver                        | false                      | storage                            | Remove snapshots as needed
 volume.zfs.use\_refquota        | bool      | zfs driver                        | false                      | storage                            | Use refquota instead of quota for space.
-zfs.clone\_copy                 | bool      | zfs driver                        | true                       | storage\_zfs\_clone\_copy          | Whether to use ZFS lightweight clones rather than full dataset copies.
+zfs.clone\_copy                 | string    | zfs driver                        | true                       | storage\_zfs\_clone\_copy          | Whether to use ZFS lightweight clones rather than full dataset copies (boolean) or "rebase" to copy based on the initial image.
 zfs.pool\_name                  | string    | zfs driver                        | name of the pool           | storage                            | Name of the zpool
 
 Storage pool configuration keys can be set using the lxc tool with:

From ca89ffbcbaeeb33bf4dd5fd2562aba77fe2aac2f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Fri, 30 Oct 2020 18:42:22 -0400
Subject: [PATCH 3/4] lxd/storage: Allow 'rebase' as value for zfs.clone_copy
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_pools_config.go | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/lxd/storage_pools_config.go b/lxd/storage_pools_config.go
index 5c6892bd12..ba4470d50a 100644
--- a/lxd/storage_pools_config.go
+++ b/lxd/storage_pools_config.go
@@ -78,7 +78,13 @@ var storagePoolConfigKeys = map[string]func(value string) error{
 	"volume.zfs.use_refquota":     validate.Optional(validate.IsBool),
 
 	// valid drivers: zfs
-	"zfs.clone_copy": validate.Optional(validate.IsBool),
+	"zfs.clone_copy": validate.Optional(func(value string) error {
+		if value == "rebase" {
+			return nil
+		}
+
+		return validate.IsBool(value)
+	}),
 	"zfs.pool_name":  validate.IsAny,
 	"rsync.bwlimit":  validate.IsAny,
 

From 5b2865972244ebac85d521c666cd1526c6312839 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Fri, 30 Oct 2020 19:19:30 -0400
Subject: [PATCH 4/4] lxd/storage/zfs: Add support for clone_copy rebase
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Closes #8096

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 lxd/storage/drivers/driver_zfs.go         | 10 ++++++--
 lxd/storage/drivers/driver_zfs_volumes.go | 31 ++++++++++++++++++++++-
 lxd/storage_pools_config.go               |  4 +--
 3 files changed, 40 insertions(+), 5 deletions(-)

diff --git a/lxd/storage/drivers/driver_zfs.go b/lxd/storage/drivers/driver_zfs.go
index 956f8297fb..31c4f3e771 100644
--- a/lxd/storage/drivers/driver_zfs.go
+++ b/lxd/storage/drivers/driver_zfs.go
@@ -342,8 +342,14 @@ func (d *zfs) Delete(op *operations.Operation) error {
 // Validate checks that all provide keys are supported and that no conflicting or missing configuration is present.
 func (d *zfs) Validate(config map[string]string) error {
 	rules := map[string]func(value string) error{
-		"zfs.pool_name":               validate.IsAny,
-		"zfs.clone_copy":              validate.Optional(validate.IsBool),
+		"zfs.pool_name": validate.IsAny,
+		"zfs.clone_copy": validate.Optional(func(value string) error {
+			if value == "rebase" {
+				return nil
+			}
+
+			return validate.IsBool(value)
+		}),
 		"volume.zfs.remove_snapshots": validate.Optional(validate.IsBool),
 		"volume.zfs.use_refquota":     validate.Optional(validate.IsBool),
 	}
diff --git a/lxd/storage/drivers/driver_zfs_volumes.go b/lxd/storage/drivers/driver_zfs_volumes.go
index 811fb11450..bcf0c016d2 100644
--- a/lxd/storage/drivers/driver_zfs_volumes.go
+++ b/lxd/storage/drivers/driver_zfs_volumes.go
@@ -510,7 +510,36 @@ func (d *zfs) CreateVolumeFromCopy(vol Volume, srcVol Volume, copySnapshots bool
 		if len(snapshots) > 0 {
 			sender = exec.Command("zfs", "send", "-R", srcSnapshot)
 		} else {
-			sender = exec.Command("zfs", "send", srcSnapshot)
+			if d.config["zfs.clone_copy"] == "rebase" {
+				var err error
+				origin := d.dataset(srcVol, false)
+				for {
+					fields := strings.SplitN(origin, "@", 2)
+
+					// If the origin is a @readonly snapshot under a /images/ path (/images or deleted/images), we're done.
+					if len(fields) > 1 && strings.Contains(fields[0], "/images/") && fields[1] == "readonly" {
+						break
+					}
+
+					origin, err = d.getDatasetProperty(origin, "origin")
+					if err != nil {
+						return err
+					}
+
+					if origin == "" || origin == "-" {
+						origin = ""
+						break
+					}
+				}
+
+				if origin != "" && origin != srcSnapshot {
+					sender = exec.Command("zfs", "send", "-i", origin, srcSnapshot)
+				} else {
+					sender = exec.Command("zfs", "send", srcSnapshot)
+				}
+			} else {
+				sender = exec.Command("zfs", "send", srcSnapshot)
+			}
 		}
 
 		// Configure the pipes.
diff --git a/lxd/storage_pools_config.go b/lxd/storage_pools_config.go
index ba4470d50a..d593655bfd 100644
--- a/lxd/storage_pools_config.go
+++ b/lxd/storage_pools_config.go
@@ -85,8 +85,8 @@ var storagePoolConfigKeys = map[string]func(value string) error{
 
 		return validate.IsBool(value)
 	}),
-	"zfs.pool_name":  validate.IsAny,
-	"rsync.bwlimit":  validate.IsAny,
+	"zfs.pool_name": validate.IsAny,
+	"rsync.bwlimit": validate.IsAny,
 
 	// valid drivers: btrfs, ceph, cephfs, zfs
 	"rsync.compression": validate.Optional(validate.IsBool),


More information about the lxc-devel mailing list