[prev in list] [next in list] [prev in thread] [next in thread] 

List:       lxc-devel
Subject:    [lxc-devel] [lxd/master] lxd/backups: Make compression configurable
From:       stgraber on Github <lxc-bot () linuxcontainers ! org>
Date:       2018-08-24 4:08:01
Message-ID: 20180824040801.C9F335E131 () mailman01 ! srv ! dcmtl ! stgraber ! net
[Download RAW message or body]

[Attachment #2 (text/x-mailbox)]

The following pull request was submitted through Github.
It can be accessed and reviewed at: https://github.com/lxc/lxd/pull/4972

This e-mail was sent by the LXC bot, direct replies will not reach the author
unless they happen to be subscribed to this list.

=== Description (from pull-request) ===
Closes #4966

Signed-off-by: Stéphane Graber <stgraber@ubuntu.com>

[Attachment #3 (text/plain)]

From da3d4565fd1d38827fb3508ffff3d081459fab36 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stéphane Graber?= <stgraber@ubuntu.com>
Date: Fri, 24 Aug 2018 00:07:01 -0400
Subject: [PATCH] lxd/backups: Make compression configurable
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Closes #4966

Signed-off-by: Stéphane Graber <stgraber@ubuntu.com>
---
 doc/api-extensions.md   |  4 ++++
 doc/server.md           |  1 +
 lxd/backup.go           | 49 ++++++++++++++++++++++++++++++-----------
 lxd/cluster/config.go   |  1 +
 lxd/container.go        |  9 +++++++-
 lxd/storage.go          |  2 +-
 lxd/storage_btrfs.go    | 48 +++++++++++++++++++++++++++++-----------
 lxd/storage_ceph.go     | 29 ++++++++++++++++++------
 lxd/storage_dir.go      | 26 +++++++++++++++++-----
 lxd/storage_lvm.go      | 26 +++++++++++++++++-----
 lxd/storage_mock.go     |  2 +-
 lxd/storage_zfs.go      | 45 ++++++++++++++++++++++++++++---------
 scripts/bash/lxd-client |  3 ++-
 shared/version/api.go   |  1 +
 test/suites/backup.sh   | 32 +++++++++++++--------------
 15 files changed, 202 insertions(+), 76 deletions(-)

diff --git a/doc/api-extensions.md b/doc/api-extensions.md
index 1a867b13fe..426b388407 100644
--- a/doc/api-extensions.md
+++ b/doc/api-extensions.md
@@ -575,3 +575,7 @@ This effectively allows for "lxc list" to get all it needs in one \
query.  ## candid\_authentication
 This introduces the new candid.api.url config option and removes
 core.macaroon.endpoint.
+
+## backup\_compression
+This introduces a new backups.compression\_algorithm config key which
+allows configuration of backup compression.
diff --git a/doc/server.md b/doc/server.md
index 7216031d8e..afda09b248 100644
--- a/doc/server.md
+++ b/doc/server.md
@@ -10,6 +10,7 @@ currently supported:

 Key                             | Type      | Default   | API extension            | \
Description  :--                             | :---      | :------   | :------------  \
| :---------- +backups.compression\_algorithm  | string    | gzip      | \
backup\_compression      | Compression algorithm to use for new images (bzip2, gzip, \
lzma, xz or none)  candid.api.url                  | string    | -         | \
candid\_authentication   | URL of the the external authentication endpoint using \
Candid  cluster.offline\_threshold      | integer   | 20        | clustering          \
| Number of seconds after which an unresponsive node is considered offline  \
core.debug\_address             | string    | -         | pprof\_http              | \
                Address to bind the pprof debug server to (HTTP)
diff --git a/lxd/backup.go b/lxd/backup.go
index d17b256a64..f313b7cd7e 100644
--- a/lxd/backup.go
+++ b/lxd/backup.go
@@ -12,6 +12,7 @@ import (

 	"gopkg.in/yaml.v2"

+	"github.com/lxc/lxd/lxd/cluster"
 	"github.com/lxc/lxd/lxd/db"
 	"github.com/lxc/lxd/lxd/state"
 	"github.com/lxc/lxd/shared"
@@ -176,7 +177,6 @@ func (b *backup) Render() *api.ContainerBackup {
 }

 func backupGetInfo(r io.ReadSeeker) (*backupInfo, error) {
-	var buf bytes.Buffer
 	var tr *tar.Reader
 	result := backupInfo{}
 	hasBinaryFormat := false
@@ -184,13 +184,29 @@ func backupGetInfo(r io.ReadSeeker) (*backupInfo, error) {

 	// Extract
 	r.Seek(0, 0)
-
-	err := shared.RunCommandWithFds(r, &buf, "xz", "-d")
+	_, _, unpacker, err := shared.DetectCompressionFile(r)
 	if err != nil {
 		return nil, err
 	}
+	r.Seek(0, 0)
+
+	if unpacker == nil {
+		return nil, fmt.Errorf("Unsupported backup compression")
+	}
+
+	if len(unpacker) > 0 {
+		var buf bytes.Buffer
+
+		err := shared.RunCommandWithFds(r, &buf, unpacker[0], unpacker[1:]...)
+		if err != nil {
+			return nil, err
+		}
+
+		tr = tar.NewReader(&buf)
+	} else {
+		tr = tar.NewReader(r)
+	}

-	tr = tar.NewReader(&buf)
 	for {
 		hdr, err := tr.Next()
 		if err == io.EOF {
@@ -288,7 +304,7 @@ func backupFixStoragePool(c *db.Cluster, b backupInfo) error {
 	return nil
 }

-func backupCreateTarball(path string, backup backup) error {
+func backupCreateTarball(s *state.State, path string, backup backup) error {
 	container := backup.container

 	// Create the index
@@ -351,19 +367,26 @@ func backupCreateTarball(path string, backup backup) error {
 	}

 	// Compress it
-	compressedPath, err := compressFile(backupPath, "xz")
+	compress, err := cluster.ConfigGetString(s.Cluster, \
"backups.compression_algorithm")  if err != nil {
 		return err
 	}

-	err = os.Remove(backupPath)
-	if err != nil {
-		return err
-	}
+	if compress != "none" {
+		compressedPath, err := compressFile(backupPath, compress)
+		if err != nil {
+			return err
+		}

-	err = os.Rename(compressedPath, backupPath)
-	if err != nil {
-		return err
+		err = os.Remove(backupPath)
+		if err != nil {
+			return err
+		}
+
+		err = os.Rename(compressedPath, backupPath)
+		if err != nil {
+			return err
+		}
 	}

 	// Set permissions
diff --git a/lxd/cluster/config.go b/lxd/cluster/config.go
index f41dceb3d3..0b12b46ac4 100644
--- a/lxd/cluster/config.go
+++ b/lxd/cluster/config.go
@@ -201,6 +201,7 @@ func configGet(cluster *db.Cluster) (*Config, error) {

 // ConfigSchema defines available server configuration keys.
 var ConfigSchema = config.Schema{
+	"backups.compression_algorithm":  {Default: "gzip", Validator: \
validateCompression},  "cluster.offline_threshold":      {Type: config.Int64, \
Default: offlineThresholdDefault(), Validator: offlineThresholdValidator},  \
"core.https_allowed_headers":     {},  "core.https_allowed_methods":     {},
diff --git a/lxd/container.go b/lxd/container.go
index 40956b360c..a6136eb16b 100644
--- a/lxd/container.go
+++ b/lxd/container.go
@@ -707,8 +707,15 @@ func containerCreateFromBackup(s *state.State, info backupInfo, \
data io.ReadSeek  fixBackupFile = true
 	}

+	// Find the compression algorithm
+	tarArgs, _, _, err := shared.DetectCompressionFile(data)
+	if err != nil {
+		return err
+	}
+	data.Seek(0, 0)
+
 	// Unpack tarball
-	err := pool.ContainerBackupLoad(info, data)
+	err = pool.ContainerBackupLoad(info, data, tarArgs)
 	if err != nil {
 		return err
 	}
diff --git a/lxd/storage.go b/lxd/storage.go
index 6d6b98baac..1785ce5a3a 100644
--- a/lxd/storage.go
+++ b/lxd/storage.go
@@ -188,7 +188,7 @@ type storage interface {
 	ContainerSnapshotStop(c container) (bool, error)

 	ContainerBackupCreate(backup backup, sourceContainer container) error
-	ContainerBackupLoad(info backupInfo, data io.ReadSeeker) error
+	ContainerBackupLoad(info backupInfo, data io.ReadSeeker, tarArgs []string) error

 	// For use in migrating snapshots.
 	ContainerSnapshotCreateEmpty(c container) error
diff --git a/lxd/storage_btrfs.go b/lxd/storage_btrfs.go
index a39b4cb21f..1559321483 100644
--- a/lxd/storage_btrfs.go
+++ b/lxd/storage_btrfs.go
@@ -1692,7 +1692,7 @@ func (s *storageBtrfs) ContainerBackupCreate(backup backup, \
source container) er  }

 	// Pack the backup
-	err = backupCreateTarball(tmpPath, backup)
+	err = backupCreateTarball(s.s, tmpPath, backup)
 	if err != nil {
 		return err
 	}
@@ -1700,7 +1700,7 @@ func (s *storageBtrfs) ContainerBackupCreate(backup backup, \
source container) er  return nil
 }

-func (s *storageBtrfs) doContainerBackupLoadOptimized(info backupInfo, data \
io.ReadSeeker) error { +func (s *storageBtrfs) doContainerBackupLoadOptimized(info \
backupInfo, data io.ReadSeeker, tarArgs []string) error {  containerName, _, _ := \
containerGetParentAndSnapshotName(info.Name)

 	containerMntPoint := getContainerMountPoint(s.pool.Name, "")
@@ -1721,10 +1721,16 @@ func (s *storageBtrfs) doContainerBackupLoadOptimized(info \
backupInfo, data io.R  return err
 	}

+	// Prepare tar arguments
+	args := append(tarArgs, []string{
+		"-",
+		"--strip-components=1",
+		"-C", unpackPath, "backup",
+	}...)
+
 	// Extract container
 	data.Seek(0, 0)
-	err = shared.RunCommandWithFds(data, nil, "tar", "-xJf", "-",
-		"--strip-components=1", "-C", unpackPath, "backup")
+	err = shared.RunCommandWithFds(data, nil, "tar", args...)
 	if err != nil {
 		logger.Errorf("Failed to untar \"%s\" into \"%s\": %s", "backup", unpackPath, err)
 		return err
@@ -1792,7 +1798,7 @@ func (s *storageBtrfs) doContainerBackupLoadOptimized(info \
backupInfo, data io.R  return nil
 }

-func (s *storageBtrfs) doContainerBackupLoadVanilla(info backupInfo, data \
io.ReadSeeker) error { +func (s *storageBtrfs) doContainerBackupLoadVanilla(info \
backupInfo, data io.ReadSeeker, tarArgs []string) error {  // create the main \
container  err := s.doContainerCreate(info.Name, info.Privileged)
 	if err != nil {
@@ -1802,11 +1808,20 @@ func (s *storageBtrfs) doContainerBackupLoadVanilla(info \
backupInfo, data io.Rea  containerMntPoint := getContainerMountPoint(s.pool.Name, \
info.Name)  // Extract container
 	for _, snap := range info.Snapshots {
-		// Extract snapshots
 		cur := fmt.Sprintf("backup/snapshots/%s", snap)
+
+		// Prepare tar arguments
+		args := append(tarArgs, []string{
+			"-",
+			"--recursive-unlink",
+			"--xattrs-include=*",
+			"--strip-components=3",
+			"-C", containerMntPoint, cur,
+		}...)
+
+		// Extract snapshots
 		data.Seek(0, 0)
-		err = shared.RunCommandWithFds(data, nil, "tar", "-xJf", "-",
-			"--recursive-unlink", "--xattrs-include=*", "--strip-components=3", "-C", \
containerMntPoint, cur) +		err = shared.RunCommandWithFds(data, nil, "tar", args...)
 		if err != nil {
 			logger.Errorf("Failed to untar \"%s\" into \"%s\": %s", cur, containerMntPoint, \
err)  return err
@@ -1819,10 +1834,17 @@ func (s *storageBtrfs) doContainerBackupLoadVanilla(info \
backupInfo, data io.Rea  }
 	}

+	// Prepare tar arguments
+	args := append(tarArgs, []string{
+		"-",
+		"--strip-components=2",
+		"--xattrs-include=*",
+		"-C", containerMntPoint, "backup/container",
+	}...)
+
 	// Extract container
 	data.Seek(0, 0)
-	err = shared.RunCommandWithFds(data, nil, "tar", "-xJf", "-",
-		"--strip-components=2", "--xattrs-include=*", "-C", containerMntPoint, \
"backup/container") +	err = shared.RunCommandWithFds(data, nil, "tar", args...)
 	if err != nil {
 		logger.Errorf("Failed to untar \"backup/container\" into \"%s\": %s", \
containerMntPoint, err)  return err
@@ -1831,14 +1853,14 @@ func (s *storageBtrfs) doContainerBackupLoadVanilla(info \
backupInfo, data io.Rea  return nil
 }

-func (s *storageBtrfs) ContainerBackupLoad(info backupInfo, data io.ReadSeeker) \
error { +func (s *storageBtrfs) ContainerBackupLoad(info backupInfo, data \
io.ReadSeeker, tarArgs []string) error {  logger.Debugf("Loading BTRFS storage volume \
for backup \"%s\" on storage pool \"%s\"", info.Name, s.pool.Name)

 	if info.HasBinaryFormat {
-		return s.doContainerBackupLoadOptimized(info, data)
+		return s.doContainerBackupLoadOptimized(info, data, tarArgs)
 	}

-	return s.doContainerBackupLoadVanilla(info, data)
+	return s.doContainerBackupLoadVanilla(info, data, tarArgs)
 }

 func (s *storageBtrfs) ImageCreate(fingerprint string) error {
diff --git a/lxd/storage_ceph.go b/lxd/storage_ceph.go
index 2dd3ccd0af..f34ca55409 100644
--- a/lxd/storage_ceph.go
+++ b/lxd/storage_ceph.go
@@ -1918,7 +1918,7 @@ func (s *storageCeph) ContainerBackupCreate(backup backup, \
source container) err  }

 	// Pack the backup
-	err = backupCreateTarball(tmpPath, backup)
+	err = backupCreateTarball(s.s, tmpPath, backup)
 	if err != nil {
 		return err
 	}
@@ -1932,7 +1932,7 @@ func (s *storageCeph) ContainerBackupCreate(backup backup, \
source container) err  // - for each snapshot dump the contents into the empty \
storage volume and  //   after each dump take a snapshot of the rbd storage volume
 // - dump the container contents into the rbd storage volume.
-func (s *storageCeph) ContainerBackupLoad(info backupInfo, data io.ReadSeeker) error \
{ +func (s *storageCeph) ContainerBackupLoad(info backupInfo, data io.ReadSeeker, \
tarArgs []string) error {  // create the main container
 	err := s.doContainerCreate(info.Name, info.Privileged)
 	if err != nil {
@@ -1948,12 +1948,20 @@ func (s *storageCeph) ContainerBackupLoad(info backupInfo, \
data io.ReadSeeker) e  containerMntPoint := getContainerMountPoint(s.pool.Name, \
info.Name)  // Extract container
 	for _, snap := range info.Snapshots {
-		// Extract snapshots
 		cur := fmt.Sprintf("backup/snapshots/%s", snap)

+		// Prepare tar arguments
+		args := append(tarArgs, []string{
+			"-",
+			"--recursive-unlink",
+			"--strip-components=3",
+			"--xattrs-include=*",
+			"-C", containerMntPoint, cur,
+		}...)
+
+		// Extract snapshots
 		data.Seek(0, 0)
-		err = shared.RunCommandWithFds(data, nil, "tar", "-xJf", "-",
-			"--recursive-unlink", "--strip-components=3", "--xattrs-include=*", "-C", \
containerMntPoint, cur) +		err = shared.RunCommandWithFds(data, nil, "tar", args...)
 		if err != nil {
 			logger.Errorf("Failed to untar \"%s\" into \"%s\": %s", cur, containerMntPoint, \
err)  return err
@@ -1979,10 +1987,17 @@ func (s *storageCeph) ContainerBackupLoad(info backupInfo, \
data io.ReadSeeker) e  }
 	}

+	// Prepare tar arguments
+	args := append(tarArgs, []string{
+		"-",
+		"--strip-components=2",
+		"--xattrs-include=*",
+		"-C", containerMntPoint, "backup/container",
+	}...)
+
 	// Extract container
 	data.Seek(0, 0)
-	err = shared.RunCommandWithFds(data, nil, "tar", "-xJf", "-",
-		"--strip-components=2", "--xattrs-include=*", "-C", containerMntPoint, \
"backup/container") +	err = shared.RunCommandWithFds(data, nil, "tar", args...)
 	if err != nil {
 		logger.Errorf("Failed to untar \"backup/container\" into \"%s\": %s", \
containerMntPoint, err)  return err
diff --git a/lxd/storage_dir.go b/lxd/storage_dir.go
index ba63a7597d..0e2fa6efae 100644
--- a/lxd/storage_dir.go
+++ b/lxd/storage_dir.go
@@ -1113,7 +1113,7 @@ func (s *storageDir) ContainerBackupCreate(backup backup, \
source container) erro  }

 	// Pack the backup
-	err = backupCreateTarball(tmpPath, backup)
+	err = backupCreateTarball(s.s, tmpPath, backup)
 	if err != nil {
 		return err
 	}
@@ -1121,7 +1121,7 @@ func (s *storageDir) ContainerBackupCreate(backup backup, \
source container) erro  return nil
 }

-func (s *storageDir) ContainerBackupLoad(info backupInfo, data io.ReadSeeker) error \
{ +func (s *storageDir) ContainerBackupLoad(info backupInfo, data io.ReadSeeker, \
tarArgs []string) error {  _, err := s.StoragePoolMount()
 	if err != nil {
 		return err
@@ -1140,10 +1140,17 @@ func (s *storageDir) ContainerBackupLoad(info backupInfo, \
data io.ReadSeeker) er  return err
 	}

+	// Prepare tar arguments
+	args := append(tarArgs, []string{
+		"-",
+		"--strip-components=2",
+		"--xattrs-include=*",
+		"-C", containerMntPoint, "backup/container",
+	}...)
+
 	// Extract container
 	data.Seek(0, 0)
-	err = shared.RunCommandWithFds(data, nil, "tar", "-xJf",
-		"-", "--strip-components=2", "--xattrs-include=*", "-C", containerMntPoint, \
"backup/container") +	err = shared.RunCommandWithFds(data, nil, "tar", args...)
 	if err != nil {
 		return err
 	}
@@ -1160,10 +1167,17 @@ func (s *storageDir) ContainerBackupLoad(info backupInfo, \
data io.ReadSeeker) er  return err
 		}

+		// Prepare tar arguments
+		args := append(tarArgs, []string{
+			"-",
+			"--strip-components=2",
+			"--xattrs-include=*",
+			"-C", containerMntPoint, "backup/snapshots",
+		}...)
+
 		// Extract snapshots
 		data.Seek(0, 0)
-		err = shared.RunCommandWithFds(data, nil, "tar", "-xJf", "-",
-			"--strip-components=2", "--xattrs-include=*", "-C", snapshotMntPoint, \
"backup/snapshots") +		err = shared.RunCommandWithFds(data, nil, "tar", args...)
 		if err != nil {
 			return err
 		}
diff --git a/lxd/storage_lvm.go b/lxd/storage_lvm.go
index 036761210e..18e986b0db 100644
--- a/lxd/storage_lvm.go
+++ b/lxd/storage_lvm.go
@@ -1679,7 +1679,7 @@ func (s *storageLvm) ContainerBackupCreate(backup backup, \
source container) erro  }

 	// Pack the backup
-	err = backupCreateTarball(tmpPath, backup)
+	err = backupCreateTarball(s.s, tmpPath, backup)
 	if err != nil {
 		return err
 	}
@@ -1687,16 +1687,23 @@ func (s *storageLvm) ContainerBackupCreate(backup backup, \
source container) erro  return nil
 }

-func (s *storageLvm) ContainerBackupLoad(info backupInfo, data io.ReadSeeker) error \
{ +func (s *storageLvm) ContainerBackupLoad(info backupInfo, data io.ReadSeeker, \
tarArgs []string) error {  containerPath, err := s.doContainerBackupLoad(info.Name, \
info.Privileged, false)  if err != nil {
 		return err
 	}

+	// Prepare tar arguments
+	args := append(tarArgs, []string{
+		"-",
+		"--strip-components=2",
+		"--xattrs-include=*",
+		"-C", containerPath, "backup/container",
+	}...)
+
 	// Extract container
 	data.Seek(0, 0)
-	err = shared.RunCommandWithFds(data, nil, "tar", "-xJf", "-", \
                "--strip-components=2", "--xattrs-include=*",
-		"-C", containerPath, "backup/container")
+	err = shared.RunCommandWithFds(data, nil, "tar", args...)
 	if err != nil {
 		return err
 	}
@@ -1708,10 +1715,17 @@ func (s *storageLvm) ContainerBackupLoad(info backupInfo, \
data io.ReadSeeker) er  return err
 		}

+		// Prepare tar arguments
+		args := append(tarArgs, []string{
+			"-",
+			"--strip-components=3",
+			"--xattrs-include=*",
+			"-C", containerPath, fmt.Sprintf("backup/snapshots/%s", snap),
+		}...)
+
 		// Extract snapshots
 		data.Seek(0, 0)
-		err = shared.RunCommandWithFds(data, nil, "tar", "-xJf", "-",
-			"--strip-components=3", "--xattrs-include=*", "-C", containerPath, \
fmt.Sprintf("backup/snapshots/%s", snap)) +		err = shared.RunCommandWithFds(data, \
nil, "tar", args...)  if err != nil {
 			return err
 		}
diff --git a/lxd/storage_mock.go b/lxd/storage_mock.go
index 201ea1d065..11e60b1212 100644
--- a/lxd/storage_mock.go
+++ b/lxd/storage_mock.go
@@ -194,7 +194,7 @@ func (s *storageMock) ContainerBackupCreate(backup backup, \
sourceContainer conta  return nil
 }

-func (s *storageMock) ContainerBackupLoad(info backupInfo, data io.ReadSeeker) error \
{ +func (s *storageMock) ContainerBackupLoad(info backupInfo, data io.ReadSeeker, \
tarArgs []string) error {  return nil
 }

diff --git a/lxd/storage_zfs.go b/lxd/storage_zfs.go
index d96eaae42e..d7cf6829f9 100644
--- a/lxd/storage_zfs.go
+++ b/lxd/storage_zfs.go
@@ -2044,7 +2044,7 @@ func (s *storageZfs) ContainerBackupCreate(backup backup, \
source container) erro  }

 	// Pack the backup
-	err = backupCreateTarball(tmpPath, backup)
+	err = backupCreateTarball(s.s, tmpPath, backup)
 	if err != nil {
 		return err
 	}
@@ -2052,7 +2052,7 @@ func (s *storageZfs) ContainerBackupCreate(backup backup, \
source container) erro  return nil
 }

-func (s *storageZfs) doContainerBackupLoadOptimized(info backupInfo, data \
io.ReadSeeker) error { +func (s *storageZfs) doContainerBackupLoadOptimized(info \
backupInfo, data io.ReadSeeker, tarArgs []string) error {  containerName, _, _ := \
containerGetParentAndSnapshotName(info.Name)  containerMntPoint := \
getContainerMountPoint(s.pool.Name, containerName)  err := \
createContainerMountpoint(containerMntPoint, containerPath(info.Name, false), \
info.Privileged) @@ -2073,9 +2073,16 @@ func (s *storageZfs) \
doContainerBackupLoadOptimized(info backupInfo, data io.Rea  return err
 	}

+	// Prepare tar arguments
+	args := append(tarArgs, []string{
+		"-",
+		"--strip-components=1",
+		"-C", unpackPath, "backup",
+	}...)
+
 	// Extract container
 	data.Seek(0, 0)
-	err = shared.RunCommandWithFds(data, nil, "tar", "-xJf", "-", \
"--strip-components=1", "-C", unpackPath, "backup") +	err = \
shared.RunCommandWithFds(data, nil, "tar", args...)  if err != nil {
 		// can't use defer because it needs to run before the mount
 		os.RemoveAll(unpackPath)
@@ -2155,7 +2162,7 @@ func (s *storageZfs) doContainerBackupLoadOptimized(info \
backupInfo, data io.Rea  return nil
 }

-func (s *storageZfs) doContainerBackupLoadVanilla(info backupInfo, data \
io.ReadSeeker) error { +func (s *storageZfs) doContainerBackupLoadVanilla(info \
backupInfo, data io.ReadSeeker, tarArgs []string) error {  // create the main \
container  err := s.doContainerCreate(info.Name, info.Privileged)
 	if err != nil {
@@ -2174,9 +2181,18 @@ func (s *storageZfs) doContainerBackupLoadVanilla(info \
backupInfo, data io.ReadS  // Extract snapshots
 		cur := fmt.Sprintf("backup/snapshots/%s", snap)

+		// Prepare tar arguments
+		args := append(tarArgs, []string{
+			"-",
+			"--recursive-unlink",
+			"--strip-components=3",
+			"--xattrs-include=*",
+			"-C", containerMntPoint, cur,
+		}...)
+
+		// Unpack
 		data.Seek(0, 0)
-		err = shared.RunCommandWithFds(data, nil, "tar", "-xJf", "-",
-			"--recursive-unlink", "--strip-components=3", "--xattrs-include=*", "-C", \
containerMntPoint, cur) +		err = shared.RunCommandWithFds(data, nil, "tar", args...)
 		if err != nil {
 			logger.Errorf("Failed to untar \"%s\" into \"%s\": %s", cur, containerMntPoint, \
err)  return err
@@ -2189,10 +2205,17 @@ func (s *storageZfs) doContainerBackupLoadVanilla(info \
backupInfo, data io.ReadS  }
 	}

+	// Prepare tar arguments
+	args := append(tarArgs, []string{
+		"-",
+		"--strip-components=2",
+		"--xattrs-include=*",
+		"-C", containerMntPoint, "backup/container",
+	}...)
+
 	// Extract container
 	data.Seek(0, 0)
-	err = shared.RunCommandWithFds(data, nil, "tar", "-xJf", "-",
-		"--strip-components=2", "--xattrs-include=*", "-C", containerMntPoint, \
"backup/container") +	err = shared.RunCommandWithFds(data, nil, "tar", args...)
 	if err != nil {
 		logger.Errorf("Failed to untar \"backup/container\" into \"%s\": %s", \
containerMntPoint, err)  return err
@@ -2201,14 +2224,14 @@ func (s *storageZfs) doContainerBackupLoadVanilla(info \
backupInfo, data io.ReadS  return nil
 }

-func (s *storageZfs) ContainerBackupLoad(info backupInfo, data io.ReadSeeker) error \
{ +func (s *storageZfs) ContainerBackupLoad(info backupInfo, data io.ReadSeeker, \
tarArgs []string) error {  logger.Debugf("Loading ZFS storage volume for backup \
\"%s\" on storage pool \"%s\"", info.Name, s.pool.Name)

 	if info.HasBinaryFormat {
-		return s.doContainerBackupLoadOptimized(info, data)
+		return s.doContainerBackupLoadOptimized(info, data, tarArgs)
 	}

-	return s.doContainerBackupLoadVanilla(info, data)
+	return s.doContainerBackupLoadVanilla(info, data, tarArgs)
 }

 // - create temporary directory ${LXD_DIR}/images/lxd_images_
diff --git a/scripts/bash/lxd-client b/scripts/bash/lxd-client
index 0657c74bcf..8003717efc 100644
--- a/scripts/bash/lxd-client
+++ b/scripts/bash/lxd-client
@@ -64,7 +64,8 @@ _have lxc && {
       list manpage monitor move network profile publish query remote rename \
       restart restore shell snapshot start stop storage version"

-    global_keys="core.https_address core.https_allowed_credentials \
+    global_keys="backups.compression_algorithm,
+      core.https_address core.https_allowed_credentials \
       core.https_allowed_headers core.https_allowed_methods \
       core.https_allowed_origin candid.api.url core.proxy_https \
       core.proxy_http core.proxy_ignore_hosts core.trust_password \
diff --git a/shared/version/api.go b/shared/version/api.go
index a81f75099e..0ac1c116c7 100644
--- a/shared/version/api.go
+++ b/shared/version/api.go
@@ -121,6 +121,7 @@ var APIExtensions = []string{
 	"network_nat_order",
 	"container_full",
 	"candid_authentication",
+	"backup_compression",
 }

 // APIExtensionsCount returns the number of available API extensions.
diff --git a/test/suites/backup.sh b/test/suites/backup.sh
index d11b90fdc6..3eb89f8999 100644
--- a/test/suites/backup.sh
+++ b/test/suites/backup.sh
@@ -203,20 +203,20 @@ test_backup_import() {

   # create backup
   if [ "$lxd_backend" = "btrfs" ] || [ "$lxd_backend" = "zfs" ]; then
-    lxc export b1 "${LXD_DIR}/c1-optimized.tar.xz" --optimized-storage \
--container-only +    lxc export b1 "${LXD_DIR}/c1-optimized.tar.gz" \
--optimized-storage --container-only  fi

-  lxc export b1 "${LXD_DIR}/c1.tar.xz" --container-only
+  lxc export b1 "${LXD_DIR}/c1.tar.gz" --container-only
   lxc delete --force b1

   # import backup, and ensure it's valid and runnable
-  lxc import "${LXD_DIR}/c1.tar.xz"
+  lxc import "${LXD_DIR}/c1.tar.gz"
   lxc info b1
   lxc start b1
   lxc delete --force b1

   if [ "$lxd_backend" = "btrfs" ] || [ "$lxd_backend" = "zfs" ]; then
-    lxc import "${LXD_DIR}/c1-optimized.tar.xz"
+    lxc import "${LXD_DIR}/c1-optimized.tar.gz"
     lxc info b1
     lxc start b1
     lxc delete --force b1
@@ -225,13 +225,13 @@ test_backup_import() {
   # with snapshots

   if [ "$lxd_backend" = "btrfs" ] || [ "$lxd_backend" = "zfs" ]; then
-    lxc export b2 "${LXD_DIR}/c2-optimized.tar.xz" --optimized-storage
+    lxc export b2 "${LXD_DIR}/c2-optimized.tar.gz" --optimized-storage
   fi

-  lxc export b2 "${LXD_DIR}/c2.tar.xz"
+  lxc export b2 "${LXD_DIR}/c2.tar.gz"
   lxc delete --force b2

-  lxc import "${LXD_DIR}/c2.tar.xz"
+  lxc import "${LXD_DIR}/c2.tar.gz"
   lxc info b2 | grep snap0
   lxc start b2
   lxc stop b2 --force
@@ -241,7 +241,7 @@ test_backup_import() {
   lxc delete --force b2

   if [ "$lxd_backend" = "btrfs" ] || [ "$lxd_backend" = "zfs" ]; then
-    lxc import "${LXD_DIR}/c2-optimized.tar.xz"
+    lxc import "${LXD_DIR}/c2-optimized.tar.gz"
     lxc info b2 | grep snap0
     lxc start b2
     lxc stop b2 --force
@@ -265,16 +265,16 @@ test_backup_export() {
   # container only

   if [ "$lxd_backend" = "btrfs" ] || [ "$lxd_backend" = "zfs" ]; then
-    lxc export b1 "${LXD_DIR}/c1-optimized.tar.xz" --optimized-storage \
                --container-only
-    tar -xJf "${LXD_DIR}/c1-optimized.tar.xz" -C "${LXD_DIR}/optimized"
+    lxc export b1 "${LXD_DIR}/c1-optimized.tar.gz" --optimized-storage \
--container-only +    tar -xzf "${LXD_DIR}/c1-optimized.tar.gz" -C \
"${LXD_DIR}/optimized"

     [ -f "${LXD_DIR}/optimized/backup/index.yaml" ]
     [ -f "${LXD_DIR}/optimized/backup/container.bin" ]
     [ ! -d "${LXD_DIR}/optimized/backup/snapshots" ]
   fi

-  lxc export b1 "${LXD_DIR}/c1.tar.xz" --container-only
-  tar -xJf "${LXD_DIR}/c1.tar.xz" -C "${LXD_DIR}/non-optimized"
+  lxc export b1 "${LXD_DIR}/c1.tar.gz" --container-only
+  tar -xzf "${LXD_DIR}/c1.tar.gz" -C "${LXD_DIR}/non-optimized"

   # check tarball content
   [ -f "${LXD_DIR}/non-optimized/backup/index.yaml" ]
@@ -286,16 +286,16 @@ test_backup_export() {
   # with snapshots

   if [ "$lxd_backend" = "btrfs" ] || [ "$lxd_backend" = "zfs" ]; then
-    lxc export b1 "${LXD_DIR}/c2-optimized.tar.xz" --optimized-storage
-    tar -xJf "${LXD_DIR}/c2-optimized.tar.xz" -C "${LXD_DIR}/optimized"
+    lxc export b1 "${LXD_DIR}/c2-optimized.tar.gz" --optimized-storage
+    tar -xzf "${LXD_DIR}/c2-optimized.tar.gz" -C "${LXD_DIR}/optimized"

     [ -f "${LXD_DIR}/optimized/backup/index.yaml" ]
     [ -f "${LXD_DIR}/optimized/backup/container.bin" ]
     [ -f "${LXD_DIR}/optimized/backup/snapshots/snap0.bin" ]
   fi

-  lxc export b1 "${LXD_DIR}/c2.tar.xz"
-  tar -xJf "${LXD_DIR}/c2.tar.xz" -C "${LXD_DIR}/non-optimized"
+  lxc export b1 "${LXD_DIR}/c2.tar.gz"
+  tar -xzf "${LXD_DIR}/c2.tar.gz" -C "${LXD_DIR}/non-optimized"

   # check tarball content
   [ -f "${LXD_DIR}/non-optimized/backup/index.yaml" ]


[Attachment #4 (text/plain)]

_______________________________________________
lxc-devel mailing list
lxc-devel@lists.linuxcontainers.org
http://lists.linuxcontainers.org/listinfo/lxc-devel


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic