[lxc-devel] [lxd/master] Storage migration volume pre-filler
tomponline on Github
lxc-bot at linuxcontainers.org
Thu Dec 5 09:24:02 UTC 2019
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 1022 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20191205/3897b814/attachment-0001.bin>
-------------- next part --------------
From 2bce8df7fe9c0b583536dd1a4847e031997b5092 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 5 Dec 2019 09:16:29 +0000
Subject: [PATCH 1/7] lxd/storage/drivers/driver/types: Moves Info definition
and adds VolumeFiller type
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/storage/drivers/driver_types.go | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
create mode 100644 lxd/storage/drivers/driver_types.go
diff --git a/lxd/storage/drivers/driver_types.go b/lxd/storage/drivers/driver_types.go
new file mode 100644
index 0000000000..61c5dd6084
--- /dev/null
+++ b/lxd/storage/drivers/driver_types.go
@@ -0,0 +1,21 @@
+package drivers
+
+// Info represents information about a storage driver.
+type Info struct {
+ Name string
+ Version string
+ VolumeTypes []VolumeType // Supported volume types.
+ Remote bool // Whether the driver uses a remote backing store.
+ OptimizedImages bool // Whether driver stores images as separate volume.
+ PreservesInodes bool // Whether driver preserves inodes when volumes are moved hosts.
+ BlockBacking bool // Whether driver uses block devices as backing store.
+ RunningQuotaResize bool // Whether quota resize is supported whilst instance running.
+ RunningSnapshotFreeze bool // Whether instance should be frozen during snapshot if running.
+}
+
+// VolumeFiller provides a struct for filling a volume.
+type VolumeFiller struct {
+ Fill func(mountPath, rootBlockPath string) error // Function to fill the volume.
+
+ Fingerprint string // If the Filler will unpack an image, it should be this fingerprint.
+}
From adcdceb9d1532e20817bc8d23f8fbc51b25f8048 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 5 Dec 2019 09:17:19 +0000
Subject: [PATCH 2/7] lxd/storage/drivers/load: Removes non-load related types
from this file
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/storage/drivers/load.go | 13 -------------
1 file changed, 13 deletions(-)
diff --git a/lxd/storage/drivers/load.go b/lxd/storage/drivers/load.go
index 3f851a90bc..84e8dc2cc7 100644
--- a/lxd/storage/drivers/load.go
+++ b/lxd/storage/drivers/load.go
@@ -27,19 +27,6 @@ func Load(state *state.State, driverName string, name string, config map[string]
return d, nil
}
-// Info represents information about a storage driver.
-type Info struct {
- Name string
- Version string
- VolumeTypes []VolumeType // Supported volume types.
- Remote bool // Whether the driver uses a remote backing store.
- OptimizedImages bool // Whether driver stores images as separate volume.
- PreservesInodes bool // Whether driver preserves inodes when volumes are moved hosts.
- BlockBacking bool // Whether driver uses block devices as backing store.
- RunningQuotaResize bool // Whether quota resize is supported whilst instance running.
- RunningSnapshotFreeze bool // Whether instance should be frozen during snapshot if running.
-}
-
// SupportedDrivers returns a list of supported storage drivers.
func SupportedDrivers() []Info {
supportedDrivers := []Info{}
From ca0dac25b7a46bdd98a5d1b4a5c29e56c6c3860e Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 5 Dec 2019 09:17:45 +0000
Subject: [PATCH 3/7] lxd/storage/drivers/interface: Updates
CreateVolumeFromMigration and CreateVolume to use VolumeFiller
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/storage/drivers/interface.go | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lxd/storage/drivers/interface.go b/lxd/storage/drivers/interface.go
index 8297b2d7b9..bc2c4cca36 100644
--- a/lxd/storage/drivers/interface.go
+++ b/lxd/storage/drivers/interface.go
@@ -34,7 +34,7 @@ type Driver interface {
// Volumes.
ValidateVolume(vol Volume, removeUnknownKeys bool) error
- CreateVolume(vol Volume, filler func(mountPath, rootBlockPath string) error, op *operations.Operation) error
+ CreateVolume(vol Volume, filler *VolumeFiller, op *operations.Operation) error
CreateVolumeFromCopy(vol Volume, srcVol Volume, copySnapshots bool, op *operations.Operation) error
RefreshVolume(vol Volume, srcVol Volume, srcSnapshots []Volume, op *operations.Operation) error
DeleteVolume(volType VolumeType, volName string, op *operations.Operation) error
@@ -69,7 +69,7 @@ type Driver interface {
// Migration.
MigrationTypes(contentType ContentType) []migration.Type
MigrateVolume(vol Volume, conn io.ReadWriteCloser, volSrcArgs migration.VolumeSourceArgs, op *operations.Operation) error
- CreateVolumeFromMigration(vol Volume, conn io.ReadWriteCloser, volTargetArgs migration.VolumeTargetArgs, op *operations.Operation) error
+ CreateVolumeFromMigration(vol Volume, conn io.ReadWriteCloser, volTargetArgs migration.VolumeTargetArgs, preFiller *VolumeFiller, op *operations.Operation) error
// Backup.
BackupVolume(vol Volume, targetPath string, optimized bool, snapshots bool, op *operations.Operation) error
From 7f84989bf39455a10402d127463aa572531fdaf0 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 5 Dec 2019 09:18:38 +0000
Subject: [PATCH 4/7] lxd/storage/drivers/driver/cephfs: Updates
CreateVolumeFromMigration and CreateVolume to use VolumeFiller
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/storage/drivers/driver_cephfs.go | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/lxd/storage/drivers/driver_cephfs.go b/lxd/storage/drivers/driver_cephfs.go
index 75e589ea68..3568d00d42 100644
--- a/lxd/storage/drivers/driver_cephfs.go
+++ b/lxd/storage/drivers/driver_cephfs.go
@@ -313,7 +313,7 @@ func (d *cephfs) GetVolumeDiskPath(volType VolumeType, volName string) (string,
return "", ErrNotImplemented
}
-func (d *cephfs) CreateVolume(vol Volume, filler func(mountPath, rootBlockPath string) error, op *operations.Operation) error {
+func (d *cephfs) CreateVolume(vol Volume, filler *VolumeFiller, op *operations.Operation) error {
if vol.volType != VolumeTypeCustom {
return fmt.Errorf("Volume type not supported")
}
@@ -336,8 +336,9 @@ func (d *cephfs) CreateVolume(vol Volume, filler func(mountPath, rootBlockPath s
}
}()
- if filler != nil {
- err = filler(volPath, "")
+ if filler != nil && filler.Fill != nil {
+ d.logger.Debug("Running filler function")
+ err = filler.Fill(volPath, "")
if err != nil {
return err
}
@@ -824,7 +825,7 @@ func (d *cephfs) MigrateVolume(vol Volume, conn io.ReadWriteCloser, volSrcArgs m
}, op)
}
-func (d *cephfs) CreateVolumeFromMigration(vol Volume, conn io.ReadWriteCloser, volTargetArgs migration.VolumeTargetArgs, op *operations.Operation) error {
+func (d *cephfs) CreateVolumeFromMigration(vol Volume, conn io.ReadWriteCloser, volTargetArgs migration.VolumeTargetArgs, preFiller *VolumeFiller, op *operations.Operation) error {
if vol.volType != VolumeTypeCustom {
return fmt.Errorf("Volume type not supported")
}
From 76289e3afa79cd1ef224ab5d40d62f432753d17b Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 5 Dec 2019 09:19:15 +0000
Subject: [PATCH 5/7] lxd/storage/drivers/driver/dir: Updates CreateVolume to
use VolumeFiller
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/storage/drivers/driver_dir.go | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/lxd/storage/drivers/driver_dir.go b/lxd/storage/drivers/driver_dir.go
index 7d8a0563bd..4a08a3871d 100644
--- a/lxd/storage/drivers/driver_dir.go
+++ b/lxd/storage/drivers/driver_dir.go
@@ -220,7 +220,7 @@ func (d *dir) setupInitialQuota(vol Volume) (func(), error) {
// CreateVolume creates an empty volume and can optionally fill it by executing the supplied
// filler function.
-func (d *dir) CreateVolume(vol Volume, filler func(mountPath, rootBlockPath string) error, op *operations.Operation) error {
+func (d *dir) CreateVolume(vol Volume, filler *VolumeFiller, op *operations.Operation) error {
volPath := vol.MountPath()
err := vol.CreateMountPath()
if err != nil {
@@ -258,8 +258,9 @@ func (d *dir) CreateVolume(vol Volume, filler func(mountPath, rootBlockPath stri
}
// Run the volume filler function if supplied.
- if filler != nil {
- err = filler(volPath, rootBlockPath)
+ if filler != nil && filler.Fill != nil {
+ d.logger.Debug("Running filler function")
+ err = filler.Fill(volPath, rootBlockPath)
if err != nil {
return err
}
From 35f8fa5dc31325589e108c9eff4021907eabb997 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 5 Dec 2019 09:19:45 +0000
Subject: [PATCH 6/7] lxd/storage/drivers/driver/dir: Updates
CreateVolumeFromMigration to accept a pre-VolumeFiller argument
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/storage/drivers/driver_dir.go | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/lxd/storage/drivers/driver_dir.go b/lxd/storage/drivers/driver_dir.go
index 4a08a3871d..194dc96665 100644
--- a/lxd/storage/drivers/driver_dir.go
+++ b/lxd/storage/drivers/driver_dir.go
@@ -350,7 +350,7 @@ func (d *dir) MigrateVolume(vol Volume, conn io.ReadWriteCloser, volSrcArgs migr
}
// CreateVolumeFromMigration creates a volume being sent via a migration.
-func (d *dir) CreateVolumeFromMigration(vol Volume, conn io.ReadWriteCloser, volTargetArgs migration.VolumeTargetArgs, op *operations.Operation) error {
+func (d *dir) CreateVolumeFromMigration(vol Volume, conn io.ReadWriteCloser, volTargetArgs migration.VolumeTargetArgs, preFiller *VolumeFiller, op *operations.Operation) error {
if vol.contentType != ContentTypeFS {
return fmt.Errorf("Content type not supported")
}
@@ -391,6 +391,16 @@ func (d *dir) CreateVolumeFromMigration(vol Volume, conn io.ReadWriteCloser, vol
err = vol.MountTask(func(mountPath string, op *operations.Operation) error {
path := shared.AddSlash(mountPath)
+ // Run the volume pre-filler function if supplied.
+ if preFiller != nil && preFiller.Fill != nil {
+ d.logger.Debug("Running pre-filler function", log.Ctx{"volume": vol.name, "path": path})
+ err = preFiller.Fill(path, "")
+ if err != nil {
+ return err
+ }
+ d.logger.Debug("Finished pre-filler function", log.Ctx{"volume": vol.name})
+ }
+
// Snapshots are sent first by the sender, so create these first.
for _, snapName := range volTargetArgs.Snapshots {
// Receive the snapshot
@@ -399,6 +409,7 @@ func (d *dir) CreateVolumeFromMigration(vol Volume, conn io.ReadWriteCloser, vol
wrapper = migration.ProgressTracker(op, "fs_progress", snapName)
}
+ d.logger.Debug("Receiving volume", log.Ctx{"volume": vol.name, "snapshot": snapName, "path": path})
err = rsync.Recv(path, conn, wrapper, volTargetArgs.MigrationType.Features)
if err != nil {
return err
@@ -432,6 +443,7 @@ func (d *dir) CreateVolumeFromMigration(vol Volume, conn io.ReadWriteCloser, vol
wrapper = migration.ProgressTracker(op, "fs_progress", vol.name)
}
+ d.logger.Debug("Receiving volume", log.Ctx{"volume": vol.name, "path": path})
err = rsync.Recv(path, conn, wrapper, volTargetArgs.MigrationType.Features)
if err != nil {
return err
@@ -443,6 +455,7 @@ func (d *dir) CreateVolumeFromMigration(vol Volume, conn io.ReadWriteCloser, vol
wrapper = migration.ProgressTracker(op, "fs_progress", vol.name)
}
+ d.logger.Debug("Receiving volume (final stage)", log.Ctx{"vol": vol.name, "path": path})
err = rsync.Recv(path, conn, wrapper, volTargetArgs.MigrationType.Features)
if err != nil {
return err
From 99872c5a27437f2bbc8a7eb1cbc5e0f013b5e065 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 5 Dec 2019 09:20:21 +0000
Subject: [PATCH 7/7] lxd/storage/backend/lxd: Updates to use VolumeFillers
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/storage/backend_lxd.go | 37 +++++++++++++++++++++++++++++++------
1 file changed, 31 insertions(+), 6 deletions(-)
diff --git a/lxd/storage/backend_lxd.go b/lxd/storage/backend_lxd.go
index 8173a7a450..c6f40d6345 100644
--- a/lxd/storage/backend_lxd.go
+++ b/lxd/storage/backend_lxd.go
@@ -761,7 +761,12 @@ func (b *lxdBackend) CreateInstanceFromImage(inst instance.Instance, fingerprint
// If the driver doesn't support optimized image volumes then create a new empty volume and
// populate it with the contents of the image archive.
if !b.driver.Info().OptimizedImages {
- err = b.driver.CreateVolume(vol, b.imageFiller(fingerprint, op), op)
+ volFiller := drivers.VolumeFiller{
+ Fingerprint: fingerprint,
+ Fill: b.imageFiller(fingerprint, op),
+ }
+
+ err = b.driver.CreateVolume(vol, &volFiller, op)
if err != nil {
return err
}
@@ -832,7 +837,10 @@ func (b *lxdBackend) CreateInstanceFromMigration(inst instance.Instance, conn io
vol := b.newVolume(volType, contentType, volStorageName, args.Config)
+ var preFiller drivers.VolumeFiller
+
revert := true
+
if !args.Refresh {
defer func() {
if !revert {
@@ -842,7 +850,7 @@ func (b *lxdBackend) CreateInstanceFromMigration(inst instance.Instance, conn io
}()
// If the negotiated migration method is rsync and the instance's base image is
- // already on the host then pre-create the instance's volume using the local image
+ // already on the host then setup a pre-filler that will unpack the local image
// to try and speed up the rsync of the incoming volume by avoiding the need to
// transfer the base image files too.
if args.MigrationType.FSType == migration.MigrationFSType_RSYNC {
@@ -854,7 +862,18 @@ func (b *lxdBackend) CreateInstanceFromMigration(inst instance.Instance, conn io
if err == nil {
logger.Debug("Using optimised migration from existing image", log.Ctx{"fingerprint": fingerprint})
- err = b.driver.CreateVolume(vol, b.imageFiller(fingerprint, op), op)
+
+ // Populate the volume filler with the fingerprint and image filler
+ // function that can be used by the driver to pre-populate the
+ // volume with the contents of the image.
+ preFiller = drivers.VolumeFiller{
+ Fingerprint: fingerprint,
+ Fill: b.imageFiller(fingerprint, op),
+ }
+
+ // Ensure if the image doesn't yet exist on a driver which supports
+ // optimized storage, then it gets created first.
+ err = b.EnsureImage(preFiller.Fingerprint, op)
if err != nil {
return err
}
@@ -862,7 +881,7 @@ func (b *lxdBackend) CreateInstanceFromMigration(inst instance.Instance, conn io
}
}
- err = b.driver.CreateVolumeFromMigration(vol, conn, args, op)
+ err = b.driver.CreateVolumeFromMigration(vol, conn, args, &preFiller, op)
if err != nil {
conn.Close()
return err
@@ -1507,7 +1526,13 @@ func (b *lxdBackend) EnsureImage(fingerprint string, op *operations.Operation) e
// Create the new image volume. No config for an image volume so set to nil.
imgVol := b.newVolume(drivers.VolumeTypeImage, contentType, fingerprint, nil)
- err = b.driver.CreateVolume(imgVol, b.imageFiller(fingerprint, op), op)
+
+ volFiller := drivers.VolumeFiller{
+ Fingerprint: fingerprint,
+ Fill: b.imageFiller(fingerprint, op),
+ }
+
+ err = b.driver.CreateVolume(imgVol, &volFiller, op)
if err != nil {
return err
}
@@ -1816,7 +1841,7 @@ func (b *lxdBackend) CreateCustomVolumeFromMigration(conn io.ReadWriteCloser, ar
}
vol := b.newVolume(drivers.VolumeTypeCustom, drivers.ContentTypeFS, args.Name, args.Config)
- err = b.driver.CreateVolumeFromMigration(vol, conn, args, op)
+ err = b.driver.CreateVolumeFromMigration(vol, conn, args, nil, op)
if err != nil {
conn.Close()
return err
More information about the lxc-devel
mailing list