The following pull request was submitted through Github. It can be accessed and reviewed at: https://github.com/lxc/lxd/pull/7073
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) ===
From 3e70f31d8a7bfa03f862b487837ef8a3a0db7d28 Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Fri, 20 Mar 2020 16:26:03 +0000 Subject: [PATCH 1/5] lxd/backup: Removes Privileged field from backup.Info struct It is unused on restoration, and not relevant for VMs as well. Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/backup.go | 9 ++++----- lxd/backup/backup.go | 1 - 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/lxd/backup.go b/lxd/backup.go index 306af17109..e91cb4d27c 100644 --- a/lxd/backup.go +++ b/lxd/backup.go @@ -177,11 +177,10 @@ func backupCreate(s *state.State, args db.InstanceBackupArgs, sourceInst instanc // backupWriteIndex generates an index.yaml file and then writes it to the root of the backup tarball. func backupWriteIndex(sourceInst instance.Instance, pool storagePools.Pool, instanceOnly bool, indexFile string, tarWriter *instancewriter.InstanceTarWriter) error { indexInfo := backup.Info{ - Name: sourceInst.Name(), - Privileged: sourceInst.IsPrivileged(), - Pool: pool.Name(), - Snapshots: []string{}, - Backend: pool.Driver().Info().Name, + Name: sourceInst.Name(), + Pool: pool.Name(), + Snapshots: []string{}, + Backend: pool.Driver().Info().Name, } if !instanceOnly { diff --git a/lxd/backup/backup.go b/lxd/backup/backup.go index f0cec28c62..4de3f0d740 100644 --- a/lxd/backup/backup.go +++ b/lxd/backup/backup.go @@ -29,7 +29,6 @@ type Info struct { Project string `json:"project" yaml:"project"` Name string `json:"name" yaml:"name"` Backend string `json:"backend" yaml:"backend"` - Privileged bool `json:"privileged" yaml:"privileged"` Pool string `json:"pool" yaml:"pool"` Snapshots []string `json:"snapshots,omitempty" yaml:"snapshots,omitempty"` OptimizedStorage bool `json:"-" yaml:"-"` From 983a2b9b8e1f5750c4b7f238af4e6e97f4a4f0ed Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Mon, 23 Mar 2020 12:21:40 +0000 Subject: [PATCH 2/5] lxd/backup: Updates GetInfo to handle new fields in index.yaml Handles `type` field in, and defaults to container type if not specified. Handles `optimized` field, defaults to false if not specified (but still supports old style optimized hint using presence of container.bin file). Adds optimisation to avoid reading whole tarball once index.yaml is read and if `optimized` is provided in the yaml file. Adds optimisation to avoid reading whole tarball if the container.bin optimized hint file is found. Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/backup/backup.go | 49 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 39 insertions(+), 10 deletions(-) diff --git a/lxd/backup/backup.go b/lxd/backup/backup.go index 4de3f0d740..805383a6a9 100644 --- a/lxd/backup/backup.go +++ b/lxd/backup/backup.go @@ -2,6 +2,7 @@ package backup import ( "archive/tar" + "context" "fmt" "io" "os" @@ -26,21 +27,25 @@ type Instance interface { // Info represents exported backup information. type Info struct { - Project string `json:"project" yaml:"project"` - Name string `json:"name" yaml:"name"` - Backend string `json:"backend" yaml:"backend"` - Pool string `json:"pool" yaml:"pool"` - Snapshots []string `json:"snapshots,omitempty" yaml:"snapshots,omitempty"` - OptimizedStorage bool `json:"-" yaml:"-"` + Project string `json:"project" yaml:"project"` + Name string `json:"name" yaml:"name"` + Backend string `json:"backend" yaml:"backend"` + Pool string `json:"pool" yaml:"pool"` + Snapshots []string `json:"snapshots,omitempty" yaml:"snapshots,omitempty"` + OptimizedStorage *bool `json:"optimized,omitempty" yaml:"optimized,omitempty"` // Optional field to handle older optimized backups that don't have this field. + Type api.InstanceType `json:"type" yaml:"type"` } // GetInfo extracts backup information from a given ReadSeeker. func GetInfo(r io.ReadSeeker) (*Info, error) { var tr *tar.Reader result := Info{} - optimizedStorage := false hasIndexFile := false + // Define some bools used to create points for OptimizedStorage field. + optimizedStorageTrue := true + optimizedStorageFalse := false + // Extract r.Seek(0, 0) _, _, unpacker, err := shared.DetectCompressionFile(r) @@ -53,8 +58,10 @@ func GetInfo(r io.ReadSeeker) (*Info, error) { return nil, fmt.Errorf("Unsupported backup compression") } + ctx, cancelFunc := context.WithCancel(context.Background()) + if len(unpacker) > 0 { - cmd := exec.Command(unpacker[0], unpacker[1:]...) + cmd := exec.CommandContext(ctx, unpacker[0], unpacker[1:]...) cmd.Stdin = r stdout, err := cmd.StdoutPipe() @@ -90,10 +97,33 @@ func GetInfo(r io.ReadSeeker) (*Info, error) { } hasIndexFile = true + + // Default to container if index doesn't specify instance type. + if result.Type == api.InstanceTypeAny { + result.Type = api.InstanceTypeContainer + } + + if result.OptimizedStorage != nil { + // No need to continue looking for optimized storage hint using the presence of the + // container.bin file below, as the index.yaml file tells us directly. + cancelFunc() + break + } else { + // Default to non-optimized if not specified and continue reading to see if + // optimized container.bin file present. + result.OptimizedStorage = &optimizedStorageFalse + } } + // If the tarball contains a binary dump of the container, then this is an optimized backup. if hdr.Name == "backup/container.bin" { - optimizedStorage = true + result.OptimizedStorage = &optimizedStorageTrue + + // Stop read loop if index.yaml already parsed. + if hasIndexFile { + cancelFunc() + break + } } } @@ -101,7 +131,6 @@ func GetInfo(r io.ReadSeeker) (*Info, error) { return nil, fmt.Errorf("Backup is missing index.yaml") } - result.OptimizedStorage = optimizedStorage return &result, nil } From c08e8dc41d675f5d0f5f30789efb1111bbaa2bc0 Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Mon, 23 Mar 2020 12:24:17 +0000 Subject: [PATCH 3/5] lxd/instances/post: bInfo.OptimizedStorage pointer usage Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/instances_post.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lxd/instances_post.go b/lxd/instances_post.go index a4fcc8f036..87e6be7235 100644 --- a/lxd/instances_post.go +++ b/lxd/instances_post.go @@ -604,7 +604,7 @@ func createFromBackup(d *Daemon, project string, data io.Reader, pool string) re // The storage pool doesn't exist. If backup is in binary format (so we cannot alter // the backup.yaml) or the pool has been specified directly from the user restoring // the backup then we cannot proceed so return an error. - if bInfo.OptimizedStorage || pool != "" { + if *bInfo.OptimizedStorage || pool != "" { return response.InternalError(errors.Wrap(err, "Storage pool not found")) } From 708edfbe58ebf4c5397ad47a95601203eff23160 Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Mon, 23 Mar 2020 12:24:46 +0000 Subject: [PATCH 4/5] lxd/storage/backend/lxd: b.driver.CreateVolumeFromBackup OptimizedStorage pointer usage Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/storage/backend_lxd.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lxd/storage/backend_lxd.go b/lxd/storage/backend_lxd.go index 8b2403d9c0..07b8391e13 100644 --- a/lxd/storage/backend_lxd.go +++ b/lxd/storage/backend_lxd.go @@ -492,7 +492,7 @@ func (b *lxdBackend) CreateInstanceFromBackup(srcBackup backup.Info, srcData io. defer revert.Fail() // Unpack the backup into the new storage volume(s). - volPostHook, revertHook, err := b.driver.CreateVolumeFromBackup(vol, srcBackup.Snapshots, srcData, srcBackup.OptimizedStorage, op) + volPostHook, revertHook, err := b.driver.CreateVolumeFromBackup(vol, srcBackup.Snapshots, srcData, *srcBackup.OptimizedStorage, op) if err != nil { return nil, nil, err } From 4fef9d2f4749e80d0b8ecd2c02a1a6d454a42004 Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Mon, 23 Mar 2020 12:19:44 +0000 Subject: [PATCH 5/5] lxd/backup: Updates backupWriteIndex index.yaml fields Changes instanceOnly arg to snapshots. Removes `privileged` field. Adds `optimized` field to indicate if optimized backup format is used. Adds `type` field to indicate the instance type being backed up. Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/backup.go | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/lxd/backup.go b/lxd/backup.go index e91cb4d27c..f1f93ea033 100644 --- a/lxd/backup.go +++ b/lxd/backup.go @@ -25,6 +25,7 @@ import ( storagePools "github.com/lxc/lxd/lxd/storage" "github.com/lxc/lxd/lxd/task" "github.com/lxc/lxd/shared" + "github.com/lxc/lxd/shared/api" "github.com/lxc/lxd/shared/idmap" "github.com/lxc/lxd/shared/instancewriter" log "github.com/lxc/lxd/shared/log15" @@ -143,7 +144,7 @@ func backupCreate(s *state.State, args db.InstanceBackupArgs, sourceInst instanc // Write index file. indexFile := filepath.Join(tmpDirPath, "index.yaml") logger.Debug("Adding backup index file", log.Ctx{"path": indexFile}) - err = backupWriteIndex(sourceInst, pool, b.InstanceOnly(), indexFile, tarWriter) + err = backupWriteIndex(sourceInst, pool, b.OptimizedStorage(), !b.InstanceOnly(), indexFile, tarWriter) if err != nil { return errors.Wrapf(err, "Error writing backup index file") } @@ -175,15 +176,18 @@ func backupCreate(s *state.State, args db.InstanceBackupArgs, sourceInst instanc } // backupWriteIndex generates an index.yaml file and then writes it to the root of the backup tarball. -func backupWriteIndex(sourceInst instance.Instance, pool storagePools.Pool, instanceOnly bool, indexFile string, tarWriter *instancewriter.InstanceTarWriter) error { +func backupWriteIndex(sourceInst instance.Instance, pool storagePools.Pool, optimized bool, snapshots bool, indexFile string, tarWriter *instancewriter.InstanceTarWriter) error { + indexInfo := backup.Info{ - Name: sourceInst.Name(), - Pool: pool.Name(), - Snapshots: []string{}, - Backend: pool.Driver().Info().Name, + Name: sourceInst.Name(), + Pool: pool.Name(), + Snapshots: []string{}, + Backend: pool.Driver().Info().Name, + Type: api.InstanceType(sourceInst.Type().String()), + OptimizedStorage: &optimized, } - if !instanceOnly { + if snapshots { snaps, err := sourceInst.Snapshots() if err != nil { return err
_______________________________________________ lxc-devel mailing list lxc-devel@lists.linuxcontainers.org http://lists.linuxcontainers.org/listinfo/lxc-devel