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

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) ===
Supposedly closes #6273
From c3dc603edb8538ba309d620b644ebf3cecc4d3d1 Mon Sep 17 00:00:00 2001
From: Uzi Erdenebileg <lzijb...@gmail.com>
Date: Sat, 26 Oct 2019 05:47:36 +0000
Subject: [PATCH 1/5] api: Add compression_squashfs extension

Signed-off-by: Uzi Erdenebileg <lzijb...@gmail.com>
---
 doc/api-extensions.md | 3 +++
 shared/version/api.go | 1 +
 2 files changed, 4 insertions(+)

diff --git a/doc/api-extensions.md b/doc/api-extensions.md
index e33d9ecced..1ffb73084e 100644
--- a/doc/api-extensions.md
+++ b/doc/api-extensions.md
@@ -866,3 +866,6 @@ Adds the `security.syscalls.intercept.mount`,
 `security.syscalls.intercept.mount.shift` configuration keys to control whether
 and how the mount system call will be interecepted by LXD and processed with
 elevated permissions.
+
+## compression_squashfs
+Adds support for importing/exporting of images/backups using SquashFS file 
system format.
diff --git a/shared/version/api.go b/shared/version/api.go
index f6f64cb741..6498b1d156 100644
--- a/shared/version/api.go
+++ b/shared/version/api.go
@@ -173,6 +173,7 @@ var APIExtensions = []string{
        "backup_compression_algorithm",
        "ceph_data_pool_name",
        "container_syscall_intercept_mount",
+       "compression_squashfs",
 }
 
 // APIExtensionsCount returns the number of available API extensions.

From be109f623f0b7db4a3537a1c5cbaafaa4adcc57d Mon Sep 17 00:00:00 2001
From: Uzi Erdenebileg <lzijb...@gmail.com>
Date: Sat, 26 Oct 2019 05:58:46 +0000
Subject: [PATCH 2/5] lxd/cluster: Validate squashfs-tools-ng executables

Signed-off-by: Uzi Erdenebileg <lzijb...@gmail.com>
---
 lxd/cluster/config.go | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/lxd/cluster/config.go b/lxd/cluster/config.go
index dacd9fb186..2a7381664b 100644
--- a/lxd/cluster/config.go
+++ b/lxd/cluster/config.go
@@ -321,6 +321,11 @@ func validateCompression(value string) error {
                return nil
        }
 
+       // Going to look up tar2sqfs executable binary
+       if value == "squashfs" {
+               value = "tar2sqfs"
+       }
+
        _, err := exec.LookPath(value)
        return err
 }

From f3ebcfbbe7cc0c51b068dc16d5b12fe31df27e1b Mon Sep 17 00:00:00 2001
From: Uzi Erdenebileg <lzijb...@gmail.com>
Date: Sat, 26 Oct 2019 20:24:00 +0000
Subject: [PATCH 3/5] lxd: Modify compressFile() to support SquashFS

Signed-off-by: Uzi Erdenebileg <lzijb...@gmail.com>
---
 lxd/images.go | 47 +++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 39 insertions(+), 8 deletions(-)

diff --git a/lxd/images.go b/lxd/images.go
index 67b95e67b4..2880cec0c6 100644
--- a/lxd/images.go
+++ b/lxd/images.go
@@ -139,17 +139,48 @@ func unpackImage(imagefname string, destpath string, 
sType storageType, runningI
 
 func compressFile(compress string, infile io.Reader, outfile io.Writer) error {
        reproducible := []string{"gzip"}
+       var cmd *exec.Cmd
 
-       args := []string{"-c"}
-       if shared.StringInSlice(compress, reproducible) {
-               args = append(args, "-n")
-       }
+       if compress == "squashfs" {
+               // 'tar2sqfs' do not support writing to stdout. So write to a 
temporary
+               //  file first and then replay the compressed content to 
outfile.
+               tempfile, err := ioutil.TempFile("", "lxd_compress_")
+               if err != nil {
+                       return err
+               }
+               defer tempfile.Close()
+               defer os.Remove(tempfile.Name())
 
-       cmd := exec.Command(compress, args...)
-       cmd.Stdin = infile
-       cmd.Stdout = outfile
+               // Prepare 'tar2sqfs' arguments
+               args := []string{"tar2sqfs", "--no-skip", "--force",
+                       "--compressor", "xz", tempfile.Name()}
+               cmd = exec.Command(args[0], args[1:]...)
+               cmd.Stdin = infile
 
-       return cmd.Run()
+               err = cmd.Run()
+               if err != nil {
+                       return err
+               }
+               // Replay the result to outfile
+               tempfile.Seek(0, 0)
+               _, err = io.Copy(outfile, tempfile)
+               if err != nil {
+                       return err
+               }
+
+       } else {
+               args := []string{"-c"}
+               if shared.StringInSlice(compress, reproducible) {
+                       args = append(args, "-n")
+               }
+
+               cmd := exec.Command(compress, args...)
+               cmd.Stdin = infile
+               cmd.Stdout = outfile
+               cmd.Run()
+       }
+
+       return nil
 }
 
 /*

From fc7b1b3d9700440b05fae35782a82a051788af19 Mon Sep 17 00:00:00 2001
From: Uzi Erdenebileg <lzijb...@gmail.com>
Date: Sun, 27 Oct 2019 21:44:08 +0000
Subject: [PATCH 4/5] lxd: Support SquashFS compressed backup imports

Signed-off-by: Uzi Erdenebileg <lzijb...@gmail.com>
---
 lxd/backup/backup.go    | 23 +++++++++++++++++-
 lxd/container.go        | 53 +++++++++++++++++++++++++++++++++++++----
 shared/archive_linux.go |  3 ++-
 3 files changed, 72 insertions(+), 7 deletions(-)

diff --git a/lxd/backup/backup.go b/lxd/backup/backup.go
index 8f3fdc1067..79f6b8ab4b 100644
--- a/lxd/backup/backup.go
+++ b/lxd/backup/backup.go
@@ -4,6 +4,7 @@ import (
        "archive/tar"
        "fmt"
        "io"
+       "io/ioutil"
        "os"
        "os/exec"
        "strings"
@@ -47,7 +48,7 @@ func GetInfo(r io.ReadSeeker) (*Info, error) {
 
        // Extract
        r.Seek(0, 0)
-       _, _, unpacker, err := shared.DetectCompressionFile(r)
+       _, algo, unpacker, err := shared.DetectCompressionFile(r)
        if err != nil {
                return nil, err
        }
@@ -58,6 +59,26 @@ func GetInfo(r io.ReadSeeker) (*Info, error) {
        }
 
        if len(unpacker) > 0 {
+               if algo == ".squashfs" {
+                       // 'sqfs2tar' tool does not support reading from stdin. 
So
+                       // create a temporary file to write the compressed data 
and
+                       // pass it to the tool as program argument
+                       tempfile, err := ioutil.TempFile("", "lxd_decompress_")
+                       if err != nil {
+                               return nil, err
+                       }
+                       defer os.Remove(tempfile.Name())
+
+                       // Write compressed data
+                       _, err = io.Copy(tempfile, r)
+                       if err != nil {
+                               return nil, err
+                       }
+
+                       tempfile.Close()
+                       // Prepare to pass the temporary file as program 
argument
+                       unpacker = append(unpacker, tempfile.Name())
+               }
                cmd := exec.Command(unpacker[0], unpacker[1:]...)
                cmd.Stdin = r
 
diff --git a/lxd/container.go b/lxd/container.go
index f4cfe3fe44..ac6948190e 100644
--- a/lxd/container.go
+++ b/lxd/container.go
@@ -4,6 +4,7 @@ import (
        "context"
        "fmt"
        "io"
+       "io/ioutil"
        "os"
        "os/exec"
        "path/filepath"
@@ -316,16 +317,58 @@ func containerCreateFromBackup(s *state.State, info 
backup.Info, data io.ReadSee
        }
 
        // Find the compression algorithm
-       tarArgs, _, _, err := shared.DetectCompressionFile(data)
+       tarArgs, algo, decomArgs, err := shared.DetectCompressionFile(data)
        if err != nil {
                return nil, err
        }
        data.Seek(0, 0)
 
-       // Unpack tarball
-       err = pool.ContainerBackupLoad(info, data, tarArgs)
-       if err != nil {
-               return nil, err
+       if algo == ".squashfs" {
+               // Create a temporary file. 'sqfs2tar' tool do not support 
reading
+               // from stdin. So write the compressed data to the temporary 
file
+               // and pass it as program argument
+               tempfile, err := ioutil.TempFile("", "lxd_decompress_")
+               if err != nil {
+                       return nil, err
+               }
+               defer os.Remove(tempfile.Name())
+
+               // Write the compressed data
+               _, err = io.Copy(tempfile, data)
+               if err != nil {
+                       return nil, err
+               }
+
+               tempfile.Close()
+               // Prepare to pass the temporary file as program argument
+               decomArgs := append(decomArgs, tempfile.Name())
+
+               // Create another temporary file to write the decompressed data
+               tarData, err := ioutil.TempFile("", "lxd_decompress_")
+               if err != nil {
+                       return nil, err
+               }
+               defer os.Remove(tarData.Name())
+               // Decompress to tarData temporary file
+               err = shared.RunCommandWithFds(nil, tarData,
+                       decomArgs[0], decomArgs[1:]...)
+               if err != nil {
+                       return nil, err
+               }
+               tarData.Seek(0, 0)
+
+               // Unpack tarball from decompressed temporary file
+               err = pool.ContainerBackupLoad(info, tarData, tarArgs)
+               if err != nil {
+                       return nil, err
+               }
+
+       } else {
+               // Unpack tarball
+               err = pool.ContainerBackupLoad(info, data, tarArgs)
+               if err != nil {
+                       return nil, err
+               }
        }
 
        if fixBackupFile || customPool {
diff --git a/shared/archive_linux.go b/shared/archive_linux.go
index 1e659d63ba..a77a09b70a 100644
--- a/shared/archive_linux.go
+++ b/shared/archive_linux.go
@@ -50,7 +50,8 @@ func DetectCompressionFile(f io.ReadSeeker) ([]string, 
string, []string, error)
        case bytes.Equal(header[257:262], []byte{'u', 's', 't', 'a', 'r'}):
                return []string{"-xf"}, ".tar", []string{}, nil
        case bytes.Equal(header[0:4], []byte{'h', 's', 'q', 's'}):
-               return []string{""}, ".squashfs", nil, nil
+               return []string{"-xf"}, ".squashfs",
+                       []string{"sqfs2tar", "--no-skip"}, nil
        default:
                return nil, "", nil, fmt.Errorf("Unsupported compression")
        }

From b5f7dcf964fd586993c5a92e2eaab9117df21faa Mon Sep 17 00:00:00 2001
From: Uzi Erdenebileg <lzijb...@gmail.com>
Date: Sun, 27 Oct 2019 23:53:02 +0000
Subject: [PATCH 5/5] lxd: Add SquashFS compressed image publish/export support

Signed-off-by: Uzi Erdenebileg <lzijb...@gmail.com>
---
 lxd/images.go | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/lxd/images.go b/lxd/images.go
index 2880cec0c6..362ee28551 100644
--- a/lxd/images.go
+++ b/lxd/images.go
@@ -152,7 +152,7 @@ func compressFile(compress string, infile io.Reader, 
outfile io.Writer) error {
                defer os.Remove(tempfile.Name())
 
                // Prepare 'tar2sqfs' arguments
-               args := []string{"tar2sqfs", "--no-skip", "--force",
+               args := []string{"tar2sqfs", "--force",
                        "--compressor", "xz", tempfile.Name()}
                cmd = exec.Command(args[0], args[1:]...)
                cmd.Stdin = infile
@@ -839,7 +839,7 @@ func getImageMetadata(fname string) (*api.ImageMetadata, 
string, error) {
        defer r.Close()
 
        // Decompress if needed
-       _, _, unpacker, err := shared.DetectCompressionFile(r)
+       _, algo, unpacker, err := shared.DetectCompressionFile(r)
        if err != nil {
                return nil, "unknown", err
        }
@@ -851,6 +851,9 @@ func getImageMetadata(fname string) (*api.ImageMetadata, 
string, error) {
 
        // Open the tarball
        if len(unpacker) > 0 {
+               if algo == ".squashfs" {
+                       unpacker = append(unpacker, fname)
+               }
                cmd := exec.Command(unpacker[0], unpacker[1:]...)
                cmd.Stdin = r
 
_______________________________________________
lxc-devel mailing list
lxc-devel@lists.linuxcontainers.org
http://lists.linuxcontainers.org/listinfo/lxc-devel

Reply via email to