[lxc-devel] [lxd/master] Storage Migration Types - accept fallback type
tomponline on Github
lxc-bot at linuxcontainers.org
Thu Oct 31 11:30:34 UTC 2019
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 423 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20191031/87e34def/attachment.bin>
-------------- next part --------------
From 7629ef9b9e808fc9b89b0e7babb7bf159a7734f1 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 31 Oct 2019 11:27:01 +0000
Subject: [PATCH 1/3] lxd/migration/migration/volumes: Updates MatchTypes to
accept fallback type
This is used when the sender prefers a different transport method than the recipient.
The fallback type specified on the recipient is then sent back to the sender and they are expected to accept it.
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/migration/migration_volumes.go | 62 ++++++++++++++++++------------
1 file changed, 38 insertions(+), 24 deletions(-)
diff --git a/lxd/migration/migration_volumes.go b/lxd/migration/migration_volumes.go
index 8b504922b4..415ecac98d 100644
--- a/lxd/migration/migration_volumes.go
+++ b/lxd/migration/migration_volumes.go
@@ -96,44 +96,58 @@ func TypesToHeader(types ...Type) MigrationHeader {
// MatchTypes attempts to find a matching migration transport type between an offered type sent
// from a remote source and the types supported by a local storage pool. If a match is found then
// a Type is returned containing the method and the matching optional features present in both.
-func MatchTypes(offer MigrationHeader, ourTypes []Type) (Type, error) {
+// The function also takes a fallback type which is used as an additional offer type preference
+// in case the preferred remote type is not compatible with the local type available.
+// It is expected that both sides of the migration will support the fallback type for the volume's
+// content type that is being migrated.
+func MatchTypes(offer MigrationHeader, fallbackType MigrationFSType, ourTypes []Type) (Type, error) {
+ // Generate an offer types slice from the preferred type supplied from remote and the
+ // fallback type supplied based on the content type of the transfer.
+ offeredFSTypes := []MigrationFSType{offer.GetFs(), fallbackType}
+
// Find first matching type.
- offerFSType := offer.GetFs()
for _, ourType := range ourTypes {
- if offerFSType != ourType.FSType {
- continue // Not a match, try the next one.
- }
+ for _, offerFSType := range offeredFSTypes {
+ if offerFSType != ourType.FSType {
+ continue // Not a match, try the next one.
+ }
- // We got a match, now extract the relevant offered features.
- var offeredFeatures []string
- if offerFSType == MigrationFSType_ZFS {
- offeredFeatures = offer.GetZfsFeaturesSlice()
- } else if offerFSType == MigrationFSType_RSYNC {
- offeredFeatures = offer.GetRsyncFeaturesSlice()
- }
+ // We got a match, now extract the relevant offered features.
+ var offeredFeatures []string
+ if offerFSType == MigrationFSType_ZFS {
+ offeredFeatures = offer.GetZfsFeaturesSlice()
+ } else if offerFSType == MigrationFSType_RSYNC {
+ offeredFeatures = offer.GetRsyncFeaturesSlice()
+ }
- // Find common features in both our type and offered type.
- commonFeatures := []string{}
- for _, ourFeature := range ourType.Features {
- if shared.StringInSlice(ourFeature, offeredFeatures) {
- commonFeatures = append(commonFeatures, ourFeature)
+ // Find common features in both our type and offered type.
+ commonFeatures := []string{}
+ for _, ourFeature := range ourType.Features {
+ if shared.StringInSlice(ourFeature, offeredFeatures) {
+ commonFeatures = append(commonFeatures, ourFeature)
+ }
}
+
+ // Return type with combined features.
+ return Type{
+ FSType: ourType.FSType,
+ Features: commonFeatures,
+ }, nil
}
+ }
- // Return type with combined features.
- return Type{
- FSType: ourType.FSType,
- Features: commonFeatures,
- }, nil
+ // No matching transport type found, generate an error with offered types and our types.
+ offeredTypeStrings := make([]string, 0, len(offeredFSTypes))
+ for _, offerFSType := range offeredFSTypes {
+ offeredTypeStrings = append(offeredTypeStrings, offerFSType.String())
}
- // No matching transport type found, generate an error with offered type and our types.
ourTypeStrings := make([]string, 0, len(ourTypes))
for _, ourType := range ourTypes {
ourTypeStrings = append(ourTypeStrings, ourType.FSType.String())
}
- return Type{}, fmt.Errorf("No matching migration type found. Offered type: %v, our types: %v", offerFSType, ourTypeStrings)
+ return Type{}, fmt.Errorf("No matching migration type found. Offered types: %v, our types: %v", offeredTypeStrings, ourTypeStrings)
}
func progressWrapperRender(op *operations.Operation, key string, description string, progressInt int64, speedInt int64) {
From 512430104f75780b4b92549c2b524a7c4bfd3e44 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 31 Oct 2019 11:28:10 +0000
Subject: [PATCH 2/3] lxd/migration/storage/volumes: Updates MatchTypes usage
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/migrate_storage_volumes.go | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lxd/migrate_storage_volumes.go b/lxd/migrate_storage_volumes.go
index a6d69cafce..978d95ed88 100644
--- a/lxd/migrate_storage_volumes.go
+++ b/lxd/migrate_storage_volumes.go
@@ -143,7 +143,7 @@ func (s *migrationSourceWs) DoStorage(state *state.State, poolName string, volNa
// Use new storage layer for migration if supported.
if pool != nil {
- migrationType, err := migration.MatchTypes(respHeader, poolMigrationTypes)
+ migrationType, err := migration.MatchTypes(respHeader, migration.MigrationFSType_RSYNC, poolMigrationTypes)
if err != nil {
logger.Errorf("Failed to neogotiate migration type: %v", err)
s.sendControl(err)
@@ -343,7 +343,7 @@ func (c *migrationSink) DoStorage(state *state.State, poolName string, req *api.
// Extract the source's migration type and then match it against our pool's
// supported types and features. If a match is found the combined features list
// will be sent back to requester.
- respType, err := migration.MatchTypes(offerHeader, pool.MigrationTypes(storageDrivers.ContentTypeFS))
+ respType, err := migration.MatchTypes(offerHeader, migration.MigrationFSType_RSYNC, pool.MigrationTypes(storageDrivers.ContentTypeFS))
if err != nil {
return err
}
From 1a6f324d905ec9ff01b31cd4a36a39adb30238ff Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 31 Oct 2019 11:28:27 +0000
Subject: [PATCH 3/3] lxd/storage/backend/lxd: Updates MatchTypes usage
Signed-off-by: Thomas Parrott <thomas.parrott at 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 68c39a6baf..9f91ab84d9 100644
--- a/lxd/storage/backend_lxd.go
+++ b/lxd/storage/backend_lxd.go
@@ -340,7 +340,7 @@ func (b *lxdBackend) CreateCustomVolumeFromCopy(volName, desc string, config map
// Negotiate the migration type to use.
offeredTypes := srcPool.MigrationTypes(drivers.ContentTypeFS)
offerHeader := migration.TypesToHeader(offeredTypes...)
- migrationType, err := migration.MatchTypes(offerHeader, b.MigrationTypes(drivers.ContentTypeFS))
+ migrationType, err := migration.MatchTypes(offerHeader, migration.MigrationFSType_RSYNC, b.MigrationTypes(drivers.ContentTypeFS))
if err != nil {
return fmt.Errorf("Failed to neogotiate copy migration type: %v", err)
}
More information about the lxc-devel
mailing list