[lxc-devel] [lxd/master] Backup: Allow import of instances and custom volume under different names
tomponline on Github
lxc-bot at linuxcontainers.org
Tue Sep 29 13:46:05 UTC 2020
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 469 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20200929/dbc9aacd/attachment.bin>
-------------- next part --------------
From dff5ed87fc1ec382d3c04bef8df1df5fa295141d Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at 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.parrott at 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.parrott at 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.parrott at 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.parrott at 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.parrott at 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.parrott at 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.parrott at 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.parrott at 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.parrott at 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.parrott at 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.parrott at 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.parrott at 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.parrott at 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.parrott at 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.parrott at 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.parrott at 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.parrott at 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.parrott at 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.parrott at 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.parrott at 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.parrott at 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.parrott at 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.parrott at 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.parrott at 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.parrott at 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.parrott at 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.parrott at 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.parrott at 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.parrott at 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.parrott at 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.parrott at 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.parrott at 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.parrott at 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.parrott at 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.parrott at 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
More information about the lxc-devel
mailing list