The following pull request was submitted through Github. It can be accessed and reviewed at: https://github.com/lxc/lxd/pull/7951
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) === Adds a `--name` flag to `lxc import` and `lxc storage volume import` commands to allow importing an existing backup as a different instance or volume name respectively.
From dff5ed87fc1ec382d3c04bef8df1df5fa295141d Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Tue, 29 Sep 2020 11:55:36 +0100 Subject: [PATCH 01/18] client/interfaces: Adds Name field to InstanceBackupArgs Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- client/interfaces.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/client/interfaces.go b/client/interfaces.go index e676a12cdc..0067ac826b 100644 --- a/client/interfaces.go +++ b/client/interfaces.go @@ -446,6 +446,9 @@ type InstanceBackupArgs struct { // Storage pool to use PoolName string + + // Name to import backup as + Name string } // The InstanceCopyArgs struct is used to pass additional options during instance copy. From b93ee8f20e4123486480e08aa65e1b076f440961 Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Tue, 29 Sep 2020 11:56:07 +0100 Subject: [PATCH 02/18] client/lxd/instances: Adds custom name restore support to CreateInstanceFromBackup Utilising a new `X-LXD-name` header. Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- client/lxd_instances.go | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/client/lxd_instances.go b/client/lxd_instances.go index eba694e410..0195d7504d 100644 --- a/client/lxd_instances.go +++ b/client/lxd_instances.go @@ -145,7 +145,7 @@ func (r *ProtocolLXD) CreateInstanceFromBackup(args InstanceBackupArgs) (Operati return nil, err } - if args.PoolName == "" { + if args.PoolName == "" && args.Name == "" { // Send the request op, _, err := r.queryOperation("POST", path, args.BackupFile, "") if err != nil { @@ -155,8 +155,12 @@ func (r *ProtocolLXD) CreateInstanceFromBackup(args InstanceBackupArgs) (Operati return op, nil } - if !r.HasExtension("container_backup_override_pool") { - return nil, fmt.Errorf("The server is missing the required \"container_backup_override_pool\" API extension") + if args.PoolName != "" && !r.HasExtension("container_backup_override_pool") { + return nil, fmt.Errorf(`The server is missing the required "container_backup_override_pool" API extension`) + } + + if args.Name != "" && !r.HasExtension("backup_override_name") { + return nil, fmt.Errorf(`The server is missing the required "backup_override_name" API extension`) } // Prepare the HTTP request @@ -171,7 +175,14 @@ func (r *ProtocolLXD) CreateInstanceFromBackup(args InstanceBackupArgs) (Operati } req.Header.Set("Content-Type", "application/octet-stream") - req.Header.Set("X-LXD-pool", args.PoolName) + + if args.PoolName != "" { + req.Header.Set("X-LXD-pool", args.PoolName) + } + + if args.Name != "" { + req.Header.Set("X-LXD-name", args.Name) + } // Set the user agent if r.httpUserAgent != "" { From ae9b5d5fc19cd58b89f14bab37a838e3097ec6e7 Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Tue, 29 Sep 2020 11:56:42 +0100 Subject: [PATCH 03/18] lxc/import: Adds --name and -n flags to lxc import command Allows importing an instance backup as a different instance name. Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxc/import.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lxc/import.go b/lxc/import.go index edbb137428..0fa0437995 100644 --- a/lxc/import.go +++ b/lxc/import.go @@ -19,6 +19,7 @@ type cmdImport struct { global *cmdGlobal flagStorage string + flagName string } func (c *cmdImport) Command() *cobra.Command { @@ -33,6 +34,7 @@ func (c *cmdImport) Command() *cobra.Command { cmd.RunE = c.Run cmd.Flags().StringVarP(&c.flagStorage, "storage", "s", "", i18n.G("Storage pool name")+"``") + cmd.Flags().StringVarP(&c.flagName, "name", "n", "", i18n.G("Instance name")+"``") return cmd } @@ -84,6 +86,7 @@ func (c *cmdImport) Run(cmd *cobra.Command, args []string) error { }, }, PoolName: c.flagStorage, + Name: c.flagName, } op, err := resource.server.CreateInstanceFromBackup(createArgs) From fea3c86a6aab864bb1e1a827ac2f7845ca4668fe Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Tue, 29 Sep 2020 11:57:43 +0100 Subject: [PATCH 04/18] lxd/instances/post: Adds custom name support for backup import to createFromBackup Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/instances_post.go | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/lxd/instances_post.go b/lxd/instances_post.go index cbe58a1bba..bdbac617b8 100644 --- a/lxd/instances_post.go +++ b/lxd/instances_post.go @@ -545,7 +545,7 @@ func createFromCopy(d *Daemon, project string, req *api.InstancesPost) response. return operations.OperationResponse(op) } -func createFromBackup(d *Daemon, project string, data io.Reader, pool string) response.Response { +func createFromBackup(d *Daemon, project string, data io.Reader, pool string, instanceName string) response.Response { revert := revert.New() defer revert.Fail() @@ -609,6 +609,11 @@ func createFromBackup(d *Daemon, project string, data io.Reader, pool string) re bInfo.Pool = pool } + // Override instance name. + if instanceName != "" { + bInfo.Name = instanceName + } + logger.Debug("Backup file info loaded", log.Ctx{ "type": bInfo.Type, "name": bInfo.Name, @@ -675,8 +680,9 @@ func createFromBackup(d *Daemon, project string, data io.Reader, pool string) re runRevert.Add(revertHook) body, err := json.Marshal(&internalImportPost{ - Name: bInfo.Name, - Force: true, + Name: bInfo.Name, + Force: true, + AllowNameOverride: instanceName != "", }) if err != nil { return errors.Wrap(err, "Marshal internal import request") From 210833514474bfe3bf81ba67e9b7889598cf00c5 Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Tue, 29 Sep 2020 11:58:05 +0100 Subject: [PATCH 05/18] lxd/instances/post: createFromBackup usage in containersPost for custom backup name restore 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 bdbac617b8..ebbff5c700 100644 --- a/lxd/instances_post.go +++ b/lxd/instances_post.go @@ -742,7 +742,7 @@ func containersPost(d *Daemon, r *http.Request) response.Response { // If we're getting binary content, process separately if r.Header.Get("Content-Type") == "application/octet-stream" { - return createFromBackup(d, project, r.Body, r.Header.Get("X-LXD-pool")) + return createFromBackup(d, project, r.Body, r.Header.Get("X-LXD-pool"), r.Header.Get("X-LXD-name")) } // Parse the request From bcb7a54dd022aa2ed8a21b791cfedac3fe6e3d83 Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Tue, 29 Sep 2020 11:58:38 +0100 Subject: [PATCH 06/18] lxd/api/internal: Adds AllowNameOverride to internalImportPost Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/api_internal.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lxd/api_internal.go b/lxd/api_internal.go index 320f09a955..b912f6cc3b 100644 --- a/lxd/api_internal.go +++ b/lxd/api_internal.go @@ -415,8 +415,9 @@ func internalSQLExec(tx *sql.Tx, query string, result *internalSQLResult) error } type internalImportPost struct { - Name string `json:"name" yaml:"name"` - Force bool `json:"force" yaml:"force"` + Name string `json:"name" yaml:"name"` + Force bool `json:"force" yaml:"force"` + AllowNameOverride bool `json:"allow_name_override" yaml:"allow_name_override"` } func internalImport(d *Daemon, r *http.Request) response.Response { From 691bc053e4fed9843074440b18edaa3ec593af1c Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Tue, 29 Sep 2020 11:59:10 +0100 Subject: [PATCH 07/18] lxd/api/internal: Override instance name in internalImport when AllowNameOverride is set Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/api_internal.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lxd/api_internal.go b/lxd/api_internal.go index b912f6cc3b..e10e3404c0 100644 --- a/lxd/api_internal.go +++ b/lxd/api_internal.go @@ -501,6 +501,10 @@ func internalImport(d *Daemon, r *http.Request) response.Response { return response.SmartError(err) } + if req.AllowNameOverride && req.Name != "" { + backupConf.Container.Name = req.Name + } + if req.Name != backupConf.Container.Name { return response.InternalError(fmt.Errorf("Instance name in request %q doesn't match instance name in backup config %q", req.Name, backupConf.Container.Name)) } From c1c7c8003ab1467cb9bf3cc7c8445c23f1b76737 Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Tue, 29 Sep 2020 14:03:37 +0100 Subject: [PATCH 08/18] client/interfaces: Changes CreateStoragePoolVolumeFromBackup args to bring in to line with CreateInstanceFromBackup Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- client/interfaces.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/interfaces.go b/client/interfaces.go index 0067ac826b..726be7712e 100644 --- a/client/interfaces.go +++ b/client/interfaces.go @@ -291,7 +291,7 @@ type InstanceServer interface { RenameStoragePoolVolumeBackup(pool string, volName string, name string, backup api.StoragePoolVolumeBackupPost) (op Operation, err error) DeleteStoragePoolVolumeBackup(pool string, volName string, name string) (op Operation, err error) GetStoragePoolVolumeBackupFile(pool string, volName string, name string, req *BackupFileRequest) (resp *BackupFileResponse, err error) - CreateStoragePoolVolumeFromBackup(pool string, args StoragePoolVolumeBackupArgs) (op Operation, err error) + CreateStoragePoolVolumeFromBackup(args StoragePoolVolumeBackupArgs) (op Operation, err error) // Cluster functions ("cluster" API extensions) GetCluster() (cluster *api.Cluster, ETag string, err error) From df6e9fbbc76ff394defe82b954f76ecbbee3fffb Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Tue, 29 Sep 2020 14:04:31 +0100 Subject: [PATCH 09/18] client/interfaces: Adds PoolName and Name fields to StoragePoolVolumeBackupArgs to bring in line with InstanceBackupArgs Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- client/interfaces.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/client/interfaces.go b/client/interfaces.go index 726be7712e..9b0bffcf18 100644 --- a/client/interfaces.go +++ b/client/interfaces.go @@ -437,6 +437,12 @@ type StoragePoolVolumeMoveArgs struct { type StoragePoolVolumeBackupArgs struct { // The backup file BackupFile io.Reader + + // Storage pool to use + PoolName string + + // Name to import backup as + Name string } // The InstanceBackupArgs struct is used when creating a instance from a backup. From cfeffbd7c6460225b62bece2b94b810500e8f1e2 Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Tue, 29 Sep 2020 14:07:32 +0100 Subject: [PATCH 10/18] client/lxd/storage/volumes: Updates CreateStoragePoolVolumeFromBackup usage to accept only StoragePoolVolumeBackupArgs Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- client/lxd_storage_volumes.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/lxd_storage_volumes.go b/client/lxd_storage_volumes.go index 3a3725c398..e7966ed68a 100644 --- a/client/lxd_storage_volumes.go +++ b/client/lxd_storage_volumes.go @@ -779,13 +779,13 @@ func (r *ProtocolLXD) GetStoragePoolVolumeBackupFile(pool string, volName string } // CreateStoragePoolVolumeFromBackup creates a custom volume from a backup file. -func (r *ProtocolLXD) CreateStoragePoolVolumeFromBackup(pool string, args StoragePoolVolumeBackupArgs) (Operation, error) { +func (r *ProtocolLXD) CreateStoragePoolVolumeFromBackup(args StoragePoolVolumeBackupArgs) (Operation, error) { if !r.HasExtension("custom_volume_backup") { return nil, fmt.Errorf("The server is missing the required \"custom_volume_backup\" API extension") } // Send the request - op, _, err := r.queryOperation("POST", fmt.Sprintf("/storage-pools/%s/volumes/custom", url.PathEscape(pool)), args.BackupFile, "") + op, _, err := r.queryOperation("POST", fmt.Sprintf("/storage-pools/%s/volumes/custom", url.PathEscape(args.PoolName)), args.BackupFile, "") if err != nil { return nil, err } From f422b6258f09628bfcf17020d3f3873158885554 Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Tue, 29 Sep 2020 14:08:25 +0100 Subject: [PATCH 11/18] client/lxd/storage/volumes: Updates CreateStoragePoolVolumeFromBackup to accept volume name override via X-LXD-name header Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- client/lxd_storage_volumes.go | 56 ++++++++++++++++++++++++++++++++--- 1 file changed, 52 insertions(+), 4 deletions(-) diff --git a/client/lxd_storage_volumes.go b/client/lxd_storage_volumes.go index e7966ed68a..882e3a723c 100644 --- a/client/lxd_storage_volumes.go +++ b/client/lxd_storage_volumes.go @@ -781,14 +781,62 @@ func (r *ProtocolLXD) GetStoragePoolVolumeBackupFile(pool string, volName string // CreateStoragePoolVolumeFromBackup creates a custom volume from a backup file. func (r *ProtocolLXD) CreateStoragePoolVolumeFromBackup(args StoragePoolVolumeBackupArgs) (Operation, error) { if !r.HasExtension("custom_volume_backup") { - return nil, fmt.Errorf("The server is missing the required \"custom_volume_backup\" API extension") + return nil, fmt.Errorf(`The server is missing the required "custom_volume_backup" API extension`) } - // Send the request - op, _, err := r.queryOperation("POST", fmt.Sprintf("/storage-pools/%s/volumes/custom", url.PathEscape(args.PoolName)), args.BackupFile, "") + if args.Name != "" && !r.HasExtension("backup_override_name") { + return nil, fmt.Errorf(`The server is missing the required "backup_override_name" API extension`) + } + + path := fmt.Sprintf("/storage-pools/%s/volumes/custom", url.PathEscape(args.PoolName)) + + // Prepare the HTTP request. + reqURL, err := r.setQueryAttributes(fmt.Sprintf("%s/1.0%s", r.httpHost, path)) if err != nil { return nil, err } - return op, nil + req, err := http.NewRequest("POST", reqURL, args.BackupFile) + if err != nil { + return nil, err + } + + req.Header.Set("Content-Type", "application/octet-stream") + + if args.Name != "" { + req.Header.Set("X-LXD-name", args.Name) + } + + // Set the user agent. + if r.httpUserAgent != "" { + req.Header.Set("User-Agent", r.httpUserAgent) + } + + // Send the request. + resp, err := r.do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + // Handle errors. + response, _, err := lxdParseResponse(resp) + if err != nil { + return nil, err + } + + // Get to the operation. + respOperation, err := response.MetadataAsOperation() + if err != nil { + return nil, err + } + + // Setup an Operation wrapper. + op := operation{ + Operation: *respOperation, + r: r, + chActive: make(chan bool), + } + + return &op, nil } From 4485133f5c97ff0c8d6be057cfa44b66e0ce9f23 Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Tue, 29 Sep 2020 14:09:36 +0100 Subject: [PATCH 12/18] lxc/storage/volume: Adds --name flag to lxc storage volume import Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxc/storage_volume.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lxc/storage_volume.go b/lxc/storage_volume.go index 7bb6229d06..07103cd9d5 100644 --- a/lxc/storage_volume.go +++ b/lxc/storage_volume.go @@ -1788,6 +1788,7 @@ type cmdStorageVolumeImport struct { global *cmdGlobal storage *cmdStorage storageVolume *cmdStorageVolume + flagName string } func (c *cmdStorageVolumeImport) Command() *cobra.Command { @@ -1800,6 +1801,7 @@ func (c *cmdStorageVolumeImport) Command() *cobra.Command { `lxc storage volume import default backup0.tar.gz Create a new custom volume using backup0.tar.gz as the source.`)) cmd.RunE = c.Run + cmd.Flags().StringVarP(&c.flagName, "name", "n", "", i18n.G("Volume name")+"``") return cmd } @@ -1814,7 +1816,7 @@ func (c *cmdStorageVolumeImport) Run(cmd *cobra.Command, args []string) error { } // Connect to LXD - remote, name, err := conf.ParseRemote(args[0]) + remote, pool, err := conf.ParseRemote(args[0]) if err != nil { return err } @@ -1850,9 +1852,11 @@ func (c *cmdStorageVolumeImport) Run(cmd *cobra.Command, args []string) error { }, }, }, + PoolName: pool, + Name: c.flagName, } - op, err := d.CreateStoragePoolVolumeFromBackup(name, createArgs) + op, err := d.CreateStoragePoolVolumeFromBackup(createArgs) if err != nil { return err } From 724d1e6d4dc5a7efa41e08fc1cbffa61cce91526 Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Tue, 29 Sep 2020 14:10:33 +0100 Subject: [PATCH 13/18] lxd/storage/volumes: Adds volName arg to createStoragePoolVolumeFromBackup And re-orders arguments to resemble createFromBackup. Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/storage_volumes.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lxd/storage_volumes.go b/lxd/storage_volumes.go index 0e6e6a5827..713abc8fda 100644 --- a/lxd/storage_volumes.go +++ b/lxd/storage_volumes.go @@ -1232,7 +1232,7 @@ func storagePoolVolumeTypeImageDelete(d *Daemon, r *http.Request) response.Respo return storagePoolVolumeTypeDelete(d, r, "image") } -func createStoragePoolVolumeFromBackup(d *Daemon, project string, pool string, data io.Reader) response.Response { +func createStoragePoolVolumeFromBackup(d *Daemon, project string, data io.Reader, pool string, volName string) response.Response { revert := revert.New() defer revert.Fail() @@ -1296,6 +1296,11 @@ func createStoragePoolVolumeFromBackup(d *Daemon, project string, pool string, d bInfo.Pool = pool } + // Override volume name. + if volName != "" { + bInfo.Name = volName + } + logger.Debug("Backup file info loaded", log.Ctx{ "type": bInfo.Type, "name": bInfo.Name, From 09970e9cbfef61ee70009472fc9727a02446cb7f Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Tue, 29 Sep 2020 14:11:53 +0100 Subject: [PATCH 14/18] lxd/storage/volumes: createStoragePoolVolumeFromBackup usage in storagePoolVolumesTypePost Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/storage_volumes.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lxd/storage_volumes.go b/lxd/storage_volumes.go index 713abc8fda..a7c0f6c4ca 100644 --- a/lxd/storage_volumes.go +++ b/lxd/storage_volumes.go @@ -294,7 +294,7 @@ func storagePoolVolumesTypePost(d *Daemon, r *http.Request) response.Response { // If we're getting binary content, process separately. if r.Header.Get("Content-Type") == "application/octet-stream" { - return createStoragePoolVolumeFromBackup(d, projectName, poolName, r.Body) + return createStoragePoolVolumeFromBackup(d, projectName, r.Body, poolName, r.Header.Get("X-LXD-name")) } req := api.StorageVolumesPost{} From eaf66ca2e5d3ee5d33b031d223c4117a9b98c90b Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Tue, 29 Sep 2020 14:16:27 +0100 Subject: [PATCH 15/18] lxd/storage/backend/lxd: Updates CreateCustomVolumeFromBackup to support custom volume import name Ensure only uses srcBackup.Name as volume name and snapshot prefix, and not the names in the encoded index.yaml Config field. Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/storage/backend_lxd.go | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/lxd/storage/backend_lxd.go b/lxd/storage/backend_lxd.go index a1b8b99ab2..379c644874 100644 --- a/lxd/storage/backend_lxd.go +++ b/lxd/storage/backend_lxd.go @@ -3469,7 +3469,7 @@ func (b *lxdBackend) CreateCustomVolumeFromBackup(srcBackup backup.Info, srcData StorageVolumePut: api.StorageVolumePut{ Config: srcBackup.Config.Volume.Config, }, - Name: srcBackup.Config.Volume.Name, + Name: srcBackup.Name, } err := b.state.Cluster.Transaction(func(tx *db.ClusterTx) error { return project.AllowVolumeCreation(tx, srcBackup.Project, req) @@ -3494,7 +3494,7 @@ func (b *lxdBackend) CreateCustomVolumeFromBackup(srcBackup backup.Info, srcData } // Create database entry for new storage volume using the validated config. - err = VolumeDBCreate(b.state, srcBackup.Project, b.name, srcBackup.Config.Volume.Name, srcBackup.Config.Volume.Description, db.StoragePoolVolumeTypeNameCustom, false, vol.Config(), time.Time{}, string(vol.ContentType())) + err = VolumeDBCreate(b.state, srcBackup.Project, b.name, srcBackup.Name, srcBackup.Config.Volume.Description, db.StoragePoolVolumeTypeNameCustom, false, vol.Config(), time.Time{}, string(vol.ContentType())) if err != nil { return err } @@ -3506,7 +3506,9 @@ func (b *lxdBackend) CreateCustomVolumeFromBackup(srcBackup backup.Info, srcData // Create database entries fro new storage volume snapshots. for _, s := range srcBackup.Config.VolumeSnapshots { snapshot := s // Local var for revert. - snapVolStorageName := project.StorageVolume(srcBackup.Project, snapshot.Name) + _, snapName, _ := shared.InstanceGetParentAndSnapshotName(snapshot.Name) + fullSnapName := drivers.GetSnapshotVolumeName(srcBackup.Name, snapName) + snapVolStorageName := project.StorageVolume(srcBackup.Project, fullSnapName) snapVol := b.newVolume(drivers.VolumeTypeCustom, drivers.ContentType(srcBackup.Config.Volume.ContentType), snapVolStorageName, srcBackup.Config.Volume.Config) // Strip any unsupported config keys (in case the export was made from a different type of storage pool). @@ -3515,13 +3517,13 @@ func (b *lxdBackend) CreateCustomVolumeFromBackup(srcBackup backup.Info, srcData return err } - err = VolumeDBCreate(b.state, srcBackup.Project, b.name, snapshot.Name, snapshot.Description, db.StoragePoolVolumeTypeNameCustom, true, snapVol.Config(), *snapshot.ExpiresAt, string(snapVol.ContentType())) + err = VolumeDBCreate(b.state, srcBackup.Project, b.name, fullSnapName, snapshot.Description, db.StoragePoolVolumeTypeNameCustom, true, snapVol.Config(), *snapshot.ExpiresAt, string(snapVol.ContentType())) if err != nil { return err } revert.Add(func() { - b.state.Cluster.RemoveStoragePoolVolume(srcBackup.Project, snapshot.Name, db.StoragePoolVolumeTypeCustom, b.ID()) + b.state.Cluster.RemoveStoragePoolVolume(srcBackup.Project, fullSnapName, db.StoragePoolVolumeTypeCustom, b.ID()) }) } From aa873809f7b3dd5cb868bc89c0fc9bdaa6c664ed Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Tue, 29 Sep 2020 14:19:21 +0100 Subject: [PATCH 16/18] api: Adds backup_override_name extension Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- doc/api-extensions.md | 6 ++++++ shared/version/api.go | 1 + 2 files changed, 7 insertions(+) diff --git a/doc/api-extensions.md b/doc/api-extensions.md index 52be415f36..a0cd6ec30c 100644 --- a/doc/api-extensions.md +++ b/doc/api-extensions.md @@ -1176,3 +1176,9 @@ This includes the following new endpoints (see [RESTful API](rest-api.md) for de The following existing endpoint has been modified: * `POST /1.0/storage-pools/<pool>/<type>/<volume>` accepts the new source type `backup` + +## backup\_override\_name +Adds `Name` field to `InstanceBackupArgs` to allow specifying a different instance name when restoring a backup. + +Adds `Name` and `PoolName` fields to `StoragePoolVolumeBackupArgs` to allow specifying a different volume name +when restoring a custom volume backup. diff --git a/shared/version/api.go b/shared/version/api.go index dfe5156e54..41a64fac67 100644 --- a/shared/version/api.go +++ b/shared/version/api.go @@ -227,6 +227,7 @@ var APIExtensions = []string{ "projects_networks", "projects_networks_restricted_uplinks", "custom_volume_backup", + "backup_override_name", } // APIExtensionsCount returns the number of available API extensions. From e15e949b2ef7494b6bb38745fd2a939ccbbeacc9 Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Tue, 29 Sep 2020 14:30:12 +0100 Subject: [PATCH 17/18] test/suites/backup: Adds tests for custom volume import name override Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- test/suites/backup.sh | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/test/suites/backup.sh b/test/suites/backup.sh index f8781d58f7..65de390338 100644 --- a/test/suites/backup.sh +++ b/test/suites/backup.sh @@ -551,38 +551,52 @@ test_backup_volume_export_with_project() { lxc storage volume detach "${pool}" testvol c1 lxc storage volume delete "${pool}" testvol lxc storage volume import "${pool}" "${LXD_DIR}/testvol.tar.gz" + lxc storage volume import "${pool}" "${LXD_DIR}/testvol.tar.gz" --name testvol2 lxc storage volume attach "${pool}" testvol c1 /mnt + lxc storage volume attach "${pool}" testvol2 c1 /mnt2 lxc start c1 lxc exec c1 --project "$project" -- stat /mnt/test + lxc exec c1 --project "$project" -- stat /mnt2/test lxc stop -f c1 if [ "$#" -ne 0 ]; then # Import into different project (before deleting earlier import). lxc storage volume import "${pool}" "${LXD_DIR}/testvol.tar.gz" --project "$project-b" + lxc storage volume import "${pool}" "${LXD_DIR}/testvol.tar.gz" --project "$project-b" --name testvol2 lxc storage volume delete "${pool}" testvol --project "$project-b" + lxc storage volume delete "${pool}" testvol2 --project "$project-b" fi # Test optimized import. if [ "$lxd_backend" = "btrfs" ] || [ "$lxd_backend" = "zfs" ]; then lxc storage volume detach "${pool}" testvol c1 + lxc storage volume detach "${pool}" testvol2 c1 lxc storage volume delete "${pool}" testvol + lxc storage volume delete "${pool}" testvol2 lxc storage volume import "${pool}" "${LXD_DIR}/testvol-optimized.tar.gz" + lxc storage volume import "${pool}" "${LXD_DIR}/testvol-optimized.tar.gz" --name testvol2 lxc storage volume attach "${pool}" testvol c1 /mnt + lxc storage volume attach "${pool}" testvol2 c1 /mnt2 lxc start c1 lxc exec c1 --project "$project" -- stat /mnt/test + lxc exec c1 --project "$project" -- stat /mnt2/test lxc stop -f c1 if [ "$#" -ne 0 ]; then # Import into different project (before deleting earlier import). lxc storage volume import "${pool}" "${LXD_DIR}/testvol-optimized.tar.gz" --project "$project-b" + lxc storage volume import "${pool}" "${LXD_DIR}/testvol-optimized.tar.gz" --project "$project-b" --name testvol2 lxc storage volume delete "${pool}" testvol --project "$project-b" + lxc storage volume delete "${pool}" testvol2 --project "$project-b" fi fi # Clean up. rm -rf "${LXD_DIR}/non-optimized/"* "${LXD_DIR}/optimized/"* lxc storage volume detach "${pool}" testvol c1 + lxc storage volume detach "${pool}" testvol2 c1 lxc storage volume rm "${pool}" testvol + lxc storage volume rm "${pool}" testvol2 lxc rm -f c1 rmdir "${LXD_DIR}/optimized" rmdir "${LXD_DIR}/non-optimized" From ffe8afdf3e1d8bfca3926c150f31b1a9f7b20d7b Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Tue, 29 Sep 2020 14:39:12 +0100 Subject: [PATCH 18/18] test/suites/backup: Adds instance import name override tests Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- test/suites/backup.sh | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/test/suites/backup.sh b/test/suites/backup.sh index 65de390338..2d9095b01d 100644 --- a/test/suites/backup.sh +++ b/test/suites/backup.sh @@ -221,33 +221,53 @@ test_backup_import_with_project() { lxc delete --force c2 lxc import "${LXD_DIR}/c2.tar.gz" + lxc import "${LXD_DIR}/c2.tar.gz" --name c3 lxc info c2 | grep snap0 + lxc info c3 | grep snap0 lxc start c2 + lxc start c3 lxc stop c2 --force + lxc stop c3 --force if [ "$#" -ne 0 ]; then # Import into different project (before deleting earlier import). lxc import "${LXD_DIR}/c2.tar.gz" --project "$project-b" + lxc import "${LXD_DIR}/c2.tar.gz" --project "$project-b" --name c3 lxc info c2 --project "$project-b" | grep snap0 + lxc info c3 --project "$project-b" | grep snap0 lxc start c2 --project "$project-b" + lxc start c3 --project "$project-b" lxc stop c2 --project "$project-b" --force + lxc stop c3 --project "$project-b" --force lxc restore c2 snap0 --project "$project-b" + lxc restore c3 snap0 --project "$project-b" lxc delete --force c2 --project "$project-b" + lxc delete --force c3 --project "$project-b" fi lxc restore c2 snap0 + lxc restore c3 snap0 lxc start c2 + lxc start c3 lxc delete --force c2 + lxc delete --force c3 + if [ "$lxd_backend" = "btrfs" ] || [ "$lxd_backend" = "zfs" ]; then lxc import "${LXD_DIR}/c2-optimized.tar.gz" + lxc import "${LXD_DIR}/c2-optimized.tar.gz" --name c3 lxc info c2 | grep snap0 + lxc info c3 | grep snap0 lxc start c2 + lxc start c3 lxc stop c2 --force - + lxc stop c3 --force lxc restore c2 snap0 + lxc restore c3 snap0 lxc start c2 + lxc start c3 lxc delete --force c2 + lxc delete --force c3 fi # Test hyphenated container and snapshot names
_______________________________________________ lxc-devel mailing list lxc-devel@lists.linuxcontainers.org http://lists.linuxcontainers.org/listinfo/lxc-devel