Discussion:
[lxc-devel] [lxd/master] lxd/migration: Cleanup feature negotiation
stgraber on Github
2018-11-30 01:00:27 UTC
Permalink
From e514b2466705a6318b716badc4523251e06e84fa Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <***@ubuntu.com>
Date: Thu, 29 Nov 2018 19:57:35 -0500
Subject: [PATCH] lxd/migration: Cleanup feature negotiation
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <***@ubuntu.com>
---
lxd/migrate.go | 7 ++--
lxd/migrate_container.go | 59 ++++++++--------------------------
lxd/migrate_storage_volumes.go | 50 ++++++----------------------
lxd/migration/utils.go | 43 +++++++++++++++++++++++++
lxd/rsync.go | 34 +++++++++++++++-----
lxd/storage_migration.go | 32 +++++++++---------
lxd/storage_zfs.go | 16 ++++++---
7 files changed, 123 insertions(+), 118 deletions(-)
create mode 100644 lxd/migration/utils.go

diff --git a/lxd/migrate.go b/lxd/migrate.go
index 2b4bcc2437..ee20aab7f9 100644
--- a/lxd/migrate.go
+++ b/lxd/migrate.go
@@ -250,7 +250,6 @@ type migrationSink struct {
dialer websocket.Dialer
allConnected chan bool
push bool
- rsyncArgs []string
refresh bool
}

@@ -273,7 +272,7 @@ type MigrationSinkArgs struct {
Storage storage

// Transport specific fields
- RsyncArgs []string
+ RsyncFeatures []string
}

type MigrationSourceArgs struct {
@@ -282,8 +281,8 @@ type MigrationSourceArgs struct {
ContainerOnly bool

// Transport specific fields
- RsyncArgs []string
- ZfsArgs []string
+ RsyncFeatures []string
+ ZfsFeatures []string
}

func (c *migrationSink) connectWithSecret(secret string) (*websocket.Conn, error) {
diff --git a/lxd/migrate_container.go b/lxd/migrate_container.go
index 5ae8bb5282..17ae799972 100644
--- a/lxd/migrate_container.go
+++ b/lxd/migrate_container.go
@@ -220,7 +220,7 @@ type preDumpLoopArgs struct {
preDumpDir string
dumpDir string
final bool
- rsyncArgs []string
+ rsyncFeatures []string
}

// The function preDumpLoop is the main logic behind the pre-copy migration.
@@ -251,7 +251,7 @@ func (s *migrationSourceWs) preDumpLoop(args *preDumpLoopArgs) (bool, error) {
// Send the pre-dump.
ctName, _, _ := containerGetParentAndSnapshotName(s.container.Name())
state := s.container.DaemonState()
- err = RsyncSend(ctName, shared.AddSlash(args.checkpointDir), s.criuConn, nil, args.rsyncArgs, args.bwlimit, state.OS.ExecPath)
+ err = RsyncSend(ctName, shared.AddSlash(args.checkpointDir), s.criuConn, nil, args.rsyncFeatures, args.bwlimit, state.OS.ExecPath)
if err != nil {
return final, err
}
@@ -413,42 +413,22 @@ func (s *migrationSourceWs) Do(migrateOp *operation) error {
}

// Handle rsync options
- rsyncArgs := []string{}
- rsyncFeatures := header.GetRsyncFeatures()
- if !rsyncFeatures.GetBidirectional() {
+ rsyncFeatures := header.GetRsyncFeaturesSlice()
+ if !shared.StringInSlice("bidirectional", rsyncFeatures) {
// If no bi-directional support, assume LXD 3.7 level
// NOTE: Do NOT extend this list of arguments
- rsyncArgs = append(rsyncArgs, "--xattrs")
- rsyncArgs = append(rsyncArgs, "--delete")
- rsyncArgs = append(rsyncArgs, "--compress")
- rsyncArgs = append(rsyncArgs, "--compress-level=2")
- } else {
- if rsyncFeatures.GetXattrs() {
- rsyncArgs = append(rsyncArgs, "--xattrs")
- }
- if rsyncFeatures.GetDelete() {
- rsyncArgs = append(rsyncArgs, "--delete")
- }
- if rsyncFeatures.GetCompress() {
- rsyncArgs = append(rsyncArgs, "--compress")
- rsyncArgs = append(rsyncArgs, "--compress-level=2")
- }
+ rsyncFeatures = []string{"xattrs", "delete", "compress"}
}

// Handle zfs options
- zfsArgs := []string{}
- zfsFeatures := header.GetZfsFeatures()
- if zfsFeatures.GetCompress() && len(zfsVersion) >= 3 && zfsVersion[0:3] != "0.6" {
- zfsArgs = append(zfsArgs, "-c")
- zfsArgs = append(zfsArgs, "-L")
- }
+ zfsFeatures := header.GetZfsFeaturesSlice()

// Set source args
sourceArgs := MigrationSourceArgs{
Container: s.container,
ContainerOnly: s.containerOnly,
- RsyncArgs: rsyncArgs,
- ZfsArgs: zfsArgs,
+ RsyncFeatures: rsyncFeatures,
+ ZfsFeatures: zfsFeatures,
}

// Initialize storage driver
@@ -608,7 +588,7 @@ func (s *migrationSourceWs) Do(migrateOp *operation) error {
preDumpDir: preDumpDir,
dumpDir: dumpDir,
final: final,
- rsyncArgs: rsyncArgs,
+ rsyncFeatures: rsyncFeatures,
}
final, err = s.preDumpLoop(&loop_args)
if err != nil {
@@ -679,7 +659,7 @@ func (s *migrationSourceWs) Do(migrateOp *operation) error {
*/
ctName, _, _ := containerGetParentAndSnapshotName(s.container.Name())
state := s.container.DaemonState()
- err = RsyncSend(ctName, shared.AddSlash(checkpointDir), s.criuConn, nil, rsyncArgs, bwlimit, state.OS.ExecPath)
+ err = RsyncSend(ctName, shared.AddSlash(checkpointDir), s.criuConn, nil, rsyncFeatures, bwlimit, state.OS.ExecPath)
if err != nil {
return abort(err)
}
@@ -833,18 +813,7 @@ func (c *migrationSink) Do(migrateOp *operation) error {
}

// Handle rsync options
- c.rsyncArgs = []string{}
- rsyncFeatures := header.GetRsyncFeatures()
- if rsyncFeatures.GetXattrs() {
- c.rsyncArgs = append(c.rsyncArgs, "--xattrs")
- }
- if rsyncFeatures.GetDelete() {
- c.rsyncArgs = append(c.rsyncArgs, "--delete")
- }
- if rsyncFeatures.GetCompress() {
- c.rsyncArgs = append(c.rsyncArgs, "--compress")
- c.rsyncArgs = append(c.rsyncArgs, "--compress-level=2")
- }
+ rsyncFeatures := header.GetRsyncFeaturesSlice()

live := c.src.live
if c.push {
@@ -1004,7 +973,7 @@ func (c *migrationSink) Do(migrateOp *operation) error {
Idmap: srcIdmap,
Live: sendFinalFsDelta,
Refresh: c.refresh,
- RsyncArgs: c.rsyncArgs,
+ RsyncFeatures: rsyncFeatures,
Snapshots: snapshots,
}

@@ -1048,7 +1017,7 @@ func (c *migrationSink) Do(migrateOp *operation) error {
for !sync.GetFinalPreDump() {
logger.Debugf("About to receive rsync")
// Transfer a CRIU pre-dump
- err = RsyncRecv(shared.AddSlash(imagesDir), criuConn, nil, c.rsyncArgs)
+ err = RsyncRecv(shared.AddSlash(imagesDir), criuConn, nil, rsyncFeatures)
if err != nil {
restore <- err
return
@@ -1076,7 +1045,7 @@ func (c *migrationSink) Do(migrateOp *operation) error {
}

// Final CRIU dump
- err = RsyncRecv(shared.AddSlash(imagesDir), criuConn, nil, c.rsyncArgs)
+ err = RsyncRecv(shared.AddSlash(imagesDir), criuConn, nil, rsyncFeatures)
if err != nil {
restore <- err
return
diff --git a/lxd/migrate_storage_volumes.go b/lxd/migrate_storage_volumes.go
index 3d0f76b836..96e26c429c 100644
--- a/lxd/migrate_storage_volumes.go
+++ b/lxd/migrate_storage_volumes.go
@@ -79,40 +79,20 @@ func (s *migrationSourceWs) DoStorage(migrateOp *operation) error {
}

// Handle rsync options
- rsyncArgs := []string{}
- rsyncFeatures := header.GetRsyncFeatures()
- if !rsyncFeatures.GetBidirectional() {
+ rsyncFeatures := header.GetRsyncFeaturesSlice()
+ if !shared.StringInSlice("bidirectional", rsyncFeatures) {
// If no bi-directional support, assume LXD 3.7 level
// NOTE: Do NOT extend this list of arguments
- rsyncArgs = append(rsyncArgs, "--xattrs")
- rsyncArgs = append(rsyncArgs, "--delete")
- rsyncArgs = append(rsyncArgs, "--compress")
- rsyncArgs = append(rsyncArgs, "--compress-level=2")
- } else {
- if rsyncFeatures.GetXattrs() {
- rsyncArgs = append(rsyncArgs, "--xattrs")
- }
- if rsyncFeatures.GetDelete() {
- rsyncArgs = append(rsyncArgs, "--delete")
- }
- if rsyncFeatures.GetCompress() {
- rsyncArgs = append(rsyncArgs, "--compress")
- rsyncArgs = append(rsyncArgs, "--compress-level=2")
- }
+ rsyncFeatures = []string{"xattrs", "delete", "compress"}
}

// Handle zfs options
- zfsArgs := []string{}
- zfsFeatures := header.GetZfsFeatures()
- if zfsFeatures.GetCompress() && len(zfsVersion) >= 3 && zfsVersion[0:3] != "0.6" {
- zfsArgs = append(zfsArgs, "-c")
- zfsArgs = append(zfsArgs, "-L")
- }
+ zfsFeatures := header.GetZfsFeaturesSlice()

// Set source args
sourceArgs := MigrationSourceArgs{
- RsyncArgs: rsyncArgs,
- ZfsArgs: zfsArgs,
+ RsyncFeatures: rsyncFeatures,
+ ZfsFeatures: zfsFeatures,
}

driver, fsErr := s.storage.StorageMigrationSource(sourceArgs)
@@ -288,24 +268,12 @@ func (c *migrationSink) DoStorage(migrateOp *operation) error {
resp.Fs = &myType
}

- rsyncFeatures := header.GetRsyncFeatures()
-
// Handle rsync options
- rsyncArgs := []string{}
- if rsyncFeatures.GetXattrs() {
- rsyncArgs = append(rsyncArgs, "--xattrs")
- }
- if rsyncFeatures.GetDelete() {
- rsyncArgs = append(rsyncArgs, "--delete")
- }
- if rsyncFeatures.GetCompress() {
- rsyncArgs = append(rsyncArgs, "--compress")
- rsyncArgs = append(rsyncArgs, "--compress-level=2")
- }
+ rsyncFeatures := header.GetRsyncFeaturesSlice()

args := MigrationSinkArgs{
- Storage: c.dest.storage,
- RsyncArgs: rsyncArgs,
+ Storage: c.dest.storage,
+ RsyncFeatures: rsyncFeatures,
}

err = sender(&resp)
diff --git a/lxd/migration/utils.go b/lxd/migration/utils.go
new file mode 100644
index 0000000000..f7843476b8
--- /dev/null
+++ b/lxd/migration/utils.go
@@ -0,0 +1,43 @@
+package migration
+
+func (m *MigrationHeader) GetRsyncFeaturesSlice() []string {
+ features := []string{}
+ if m == nil {
+ return features
+ }
+
+ if m.RsyncFeatures != nil {
+ if m.RsyncFeatures.Xattrs != nil && *m.RsyncFeatures.Xattrs == true {
+ features = append(features, "xattrs")
+ }
+
+ if m.RsyncFeatures.Delete != nil && *m.RsyncFeatures.Delete == true {
+ features = append(features, "delete")
+ }
+
+ if m.RsyncFeatures.Compress != nil && *m.RsyncFeatures.Compress == true {
+ features = append(features, "compress")
+ }
+
+ if m.RsyncFeatures.Bidirectional != nil && *m.RsyncFeatures.Bidirectional == true {
+ features = append(features, "bidirectional")
+ }
+ }
+
+ return features
+}
+
+func (m *MigrationHeader) GetZfsFeaturesSlice() []string {
+ features := []string{}
+ if m == nil {
+ return features
+ }
+
+ if m.ZfsFeatures != nil {
+ if m.ZfsFeatures.Compress != nil && *m.ZfsFeatures.Compress == true {
+ features = append(features, "compress")
+ }
+ }
+
+ return features
+}
diff --git a/lxd/rsync.go b/lxd/rsync.go
index e6bf3543ad..c6e3388ab9 100644
--- a/lxd/rsync.go
+++ b/lxd/rsync.go
@@ -62,7 +62,7 @@ func rsyncLocalCopy(source string, dest string, bwlimit string) (string, error)
return msg, nil
}

-func rsyncSendSetup(name string, path string, bwlimit string, execPath string, extraArgs []string) (*exec.Cmd, net.Conn, io.ReadCloser, error) {
+func rsyncSendSetup(name string, path string, bwlimit string, execPath string, features []string) (*exec.Cmd, net.Conn, io.ReadCloser, error) {
/*
* The way rsync works, it invokes a subprocess that does the actual
* talking (given to it by a -E argument). Since there isn't an easy
@@ -112,8 +112,8 @@ func rsyncSendSetup(name string, path string, bwlimit string, execPath string, e
"--sparse",
}

- if extraArgs != nil && len(extraArgs) > 0 {
- args = append(args, extraArgs...)
+ if features != nil && len(features) > 0 {
+ args = append(args, rsyncFeatureArgs(features)...)
}

args = append(args, []string{
@@ -148,8 +148,8 @@ func rsyncSendSetup(name string, path string, bwlimit string, execPath string, e

// RsyncSend sets up the sending half of an rsync, to recursively send the
// directory pointed to by path over the websocket.
-func RsyncSend(name string, path string, conn *websocket.Conn, readWrapper func(io.ReadCloser) io.ReadCloser, extraArgs []string, bwlimit string, execPath string) error {
- cmd, dataSocket, stderr, err := rsyncSendSetup(name, path, bwlimit, execPath, extraArgs)
+func RsyncSend(name string, path string, conn *websocket.Conn, readWrapper func(io.ReadCloser) io.ReadCloser, features []string, bwlimit string, execPath string) error {
+ cmd, dataSocket, stderr, err := rsyncSendSetup(name, path, bwlimit, execPath, features)
if err != nil {
return err
}
@@ -186,7 +186,7 @@ func RsyncSend(name string, path string, conn *websocket.Conn, readWrapper func(
// RsyncRecv sets up the receiving half of the websocket to rsync (the other
// half set up by RsyncSend), putting the contents in the directory specified
// by path.
-func RsyncRecv(path string, conn *websocket.Conn, writeWrapper func(io.WriteCloser) io.WriteCloser, extraArgs []string) error {
+func RsyncRecv(path string, conn *websocket.Conn, writeWrapper func(io.WriteCloser) io.WriteCloser, features []string) error {
args := []string{
"--server",
"-vlogDtpre.iLsfx",
@@ -196,8 +196,8 @@ func RsyncRecv(path string, conn *websocket.Conn, writeWrapper func(io.WriteClos
"--sparse",
}

- if extraArgs != nil && len(extraArgs) > 0 {
- args = append(args, extraArgs...)
+ if features != nil && len(features) > 0 {
+ args = append(args, rsyncFeatureArgs(features)...)
}

args = append(args, []string{".", path}...)
@@ -246,3 +246,21 @@ func RsyncRecv(path string, conn *websocket.Conn, writeWrapper func(io.WriteClos

return err
}
+
+func rsyncFeatureArgs(features []string) []string {
+ args := []string{}
+ if shared.StringInSlice("xattrs", features) {
+ args = append(args, "--xattrs")
+ }
+
+ if shared.StringInSlice("delete", features) {
+ args = append(args, "--delete")
+ }
+
+ if shared.StringInSlice("compress", features) {
+ args = append(args, "--compress")
+ args = append(args, "--compress-level=2")
+ }
+
+ return args
+}
diff --git a/lxd/storage_migration.go b/lxd/storage_migration.go
index 7ee15ed430..063da9ce9d 100644
--- a/lxd/storage_migration.go
+++ b/lxd/storage_migration.go
@@ -40,9 +40,9 @@ type MigrationStorageSourceDriver interface {
}

type rsyncStorageSourceDriver struct {
- container container
- snapshots []container
- rsyncArgs []string
+ container container
+ snapshots []container
+ rsyncFeatures []string
}

func (s rsyncStorageSourceDriver) Snapshots() []container {
@@ -66,7 +66,7 @@ func (s rsyncStorageSourceDriver) SendStorageVolume(conn *websocket.Conn, op *op
path := getStoragePoolVolumeMountPoint(pool.Name, volume.Name)
path = shared.AddSlash(path)
logger.Debugf("Starting to send storage volume %s on storage pool %s from %s", volume.Name, pool.Name, path)
- return RsyncSend(volume.Name, path, conn, wrapper, s.rsyncArgs, bwlimit, state.OS.ExecPath)
+ return RsyncSend(volume.Name, path, conn, wrapper, s.rsyncFeatures, bwlimit, state.OS.ExecPath)
}

func (s rsyncStorageSourceDriver) SendWhileRunning(conn *websocket.Conn, op *operation, bwlimit string, containerOnly bool) error {
@@ -85,7 +85,7 @@ func (s rsyncStorageSourceDriver) SendWhileRunning(conn *websocket.Conn, op *ope
path := send.Path()
wrapper := StorageProgressReader(op, "fs_progress", send.Name())
state := s.container.DaemonState()
- err = RsyncSend(projectPrefix(s.container.Project(), ctName), shared.AddSlash(path), conn, wrapper, s.rsyncArgs, bwlimit, state.OS.ExecPath)
+ err = RsyncSend(projectPrefix(s.container.Project(), ctName), shared.AddSlash(path), conn, wrapper, s.rsyncFeatures, bwlimit, state.OS.ExecPath)
if err != nil {
return err
}
@@ -94,14 +94,14 @@ func (s rsyncStorageSourceDriver) SendWhileRunning(conn *websocket.Conn, op *ope

wrapper := StorageProgressReader(op, "fs_progress", s.container.Name())
state := s.container.DaemonState()
- return RsyncSend(projectPrefix(s.container.Project(), ctName), shared.AddSlash(s.container.Path()), conn, wrapper, s.rsyncArgs, bwlimit, state.OS.ExecPath)
+ return RsyncSend(projectPrefix(s.container.Project(), ctName), shared.AddSlash(s.container.Path()), conn, wrapper, s.rsyncFeatures, bwlimit, state.OS.ExecPath)
}

func (s rsyncStorageSourceDriver) SendAfterCheckpoint(conn *websocket.Conn, bwlimit string) error {
ctName, _, _ := containerGetParentAndSnapshotName(s.container.Name())
// resync anything that changed between our first send and the checkpoint
state := s.container.DaemonState()
- return RsyncSend(projectPrefix(s.container.Project(), ctName), shared.AddSlash(s.container.Path()), conn, nil, s.rsyncArgs, bwlimit, state.OS.ExecPath)
+ return RsyncSend(projectPrefix(s.container.Project(), ctName), shared.AddSlash(s.container.Path()), conn, nil, s.rsyncFeatures, bwlimit, state.OS.ExecPath)
}

func (s rsyncStorageSourceDriver) Cleanup() {
@@ -109,7 +109,7 @@ func (s rsyncStorageSourceDriver) Cleanup() {
}

func rsyncStorageMigrationSource(args MigrationSourceArgs) (MigrationStorageSourceDriver, error) {
- return rsyncStorageSourceDriver{nil, nil, args.RsyncArgs}, nil
+ return rsyncStorageSourceDriver{nil, nil, args.RsyncFeatures}, nil
}

func rsyncRefreshSource(refreshSnapshots []string, args MigrationSourceArgs) (MigrationStorageSourceDriver, error) {
@@ -130,7 +130,7 @@ func rsyncRefreshSource(refreshSnapshots []string, args MigrationSourceArgs) (Mi
}
}

- return rsyncStorageSourceDriver{args.Container, snapshots, args.RsyncArgs}, nil
+ return rsyncStorageSourceDriver{args.Container, snapshots, args.RsyncFeatures}, nil
}

func rsyncMigrationSource(args MigrationSourceArgs) (MigrationStorageSourceDriver, error) {
@@ -143,7 +143,7 @@ func rsyncMigrationSource(args MigrationSourceArgs) (MigrationStorageSourceDrive
}
}

- return rsyncStorageSourceDriver{args.Container, snapshots, args.RsyncArgs}, nil
+ return rsyncStorageSourceDriver{args.Container, snapshots, args.RsyncFeatures}, nil
}

func snapshotProtobufToContainerArgs(project string, containerName string, snap *migration.Snapshot) db.ContainerArgs {
@@ -208,7 +208,7 @@ func rsyncStorageMigrationSink(conn *websocket.Conn, op *operation, args Migrati
path := getStoragePoolVolumeMountPoint(pool.Name, volume.Name)
path = shared.AddSlash(path)
logger.Debugf("Starting to receive storage volume %s on storage pool %s into %s", volume.Name, pool.Name, path)
- return RsyncRecv(path, conn, wrapper, args.RsyncArgs)
+ return RsyncRecv(path, conn, wrapper, args.RsyncFeatures)
}

func rsyncMigrationSink(conn *websocket.Conn, op *operation, args MigrationSinkArgs) error {
@@ -285,7 +285,7 @@ func rsyncMigrationSink(conn *websocket.Conn, op *operation, args MigrationSinkA
}

wrapper := StorageProgressWriter(op, "fs_progress", s.Name())
- if err := RsyncRecv(shared.AddSlash(s.Path()), conn, wrapper, args.RsyncArgs); err != nil {
+ if err := RsyncRecv(shared.AddSlash(s.Path()), conn, wrapper, args.RsyncFeatures); err != nil {
return err
}

@@ -297,7 +297,7 @@ func rsyncMigrationSink(conn *websocket.Conn, op *operation, args MigrationSinkA
}

wrapper := StorageProgressWriter(op, "fs_progress", args.Container.Name())
- err = RsyncRecv(shared.AddSlash(args.Container.Path()), conn, wrapper, args.RsyncArgs)
+ err = RsyncRecv(shared.AddSlash(args.Container.Path()), conn, wrapper, args.RsyncFeatures)
if err != nil {
return err
}
@@ -335,7 +335,7 @@ func rsyncMigrationSink(conn *websocket.Conn, op *operation, args MigrationSinkA
}

wrapper := StorageProgressWriter(op, "fs_progress", snap.GetName())
- err := RsyncRecv(shared.AddSlash(args.Container.Path()), conn, wrapper, args.RsyncArgs)
+ err := RsyncRecv(shared.AddSlash(args.Container.Path()), conn, wrapper, args.RsyncFeatures)
if err != nil {
return err
}
@@ -357,7 +357,7 @@ func rsyncMigrationSink(conn *websocket.Conn, op *operation, args MigrationSinkA
}

wrapper := StorageProgressWriter(op, "fs_progress", args.Container.Name())
- err = RsyncRecv(shared.AddSlash(args.Container.Path()), conn, wrapper, args.RsyncArgs)
+ err = RsyncRecv(shared.AddSlash(args.Container.Path()), conn, wrapper, args.RsyncFeatures)
if err != nil {
return err
}
@@ -366,7 +366,7 @@ func rsyncMigrationSink(conn *websocket.Conn, op *operation, args MigrationSinkA
if args.Live {
/* now receive the final sync */
wrapper := StorageProgressWriter(op, "fs_progress", args.Container.Name())
- err := RsyncRecv(shared.AddSlash(args.Container.Path()), conn, wrapper, args.RsyncArgs)
+ err := RsyncRecv(shared.AddSlash(args.Container.Path()), conn, wrapper, args.RsyncFeatures)
if err != nil {
return err
}
diff --git a/lxd/storage_zfs.go b/lxd/storage_zfs.go
index b1e587e288..a8d8a5033d 100644
--- a/lxd/storage_zfs.go
+++ b/lxd/storage_zfs.go
@@ -2543,7 +2543,7 @@ type zfsMigrationSourceDriver struct {
zfs *storageZfs
runningSnapName string
stoppedSnapName string
- zfsArgs []string
+ zfsFeatures []string
}

func (s *zfsMigrationSourceDriver) Snapshots() []container {
@@ -2554,7 +2554,15 @@ func (s *zfsMigrationSourceDriver) send(conn *websocket.Conn, zfsName string, zf
sourceParentName, _, _ := containerGetParentAndSnapshotName(s.container.Name())
poolName := s.zfs.getOnDiskPoolName()
args := []string{"send"}
- args = append(args, s.zfsArgs...)
+
+ // Negotiated options
+ if s.zfsFeatures != nil && len(s.zfsFeatures) > 0 {
+ if shared.StringInSlice("compress", s.zfsFeatures) {
+ args = append(args, "-c")
+ args = append(args, "-L")
+ }
+ }
+
args = append(args, []string{fmt.Sprintf("%s/containers/%s@%s", poolName, projectPrefix(s.container.Project(), sourceParentName), zfsName)}...)
if zfsParent != "" {
args = append(args, "-i", fmt.Sprintf("%s/containers/%s@%s", poolName, projectPrefix(s.container.Project(), s.container.Name()), zfsParent))
@@ -2670,7 +2678,7 @@ func (s *storageZfs) MigrationSource(args MigrationSourceArgs) (MigrationStorage
* to send anything else, because that's all the user asked for.
*/
if args.Container.IsSnapshot() {
- return &zfsMigrationSourceDriver{container: args.Container, zfs: s, zfsArgs: args.ZfsArgs}, nil
+ return &zfsMigrationSourceDriver{container: args.Container, zfs: s, zfsFeatures: args.ZfsFeatures}, nil
}

driver := zfsMigrationSourceDriver{
@@ -2678,7 +2686,7 @@ func (s *storageZfs) MigrationSource(args MigrationSourceArgs) (MigrationStorage
snapshots: []container{},
zfsSnapshotNames: []string{},
zfs: s,
- zfsArgs: args.ZfsArgs,
+ zfsFeatures: args.ZfsFeatures,
}

if args.ContainerOnly {

Loading...