[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