[lxc-devel] [lxd/master] Storage: Image volume regeneration

tomponline on Github lxc-bot at linuxcontainers.org
Thu Apr 23 15:13:40 UTC 2020


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 1562 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20200423/44c76170/attachment-0001.bin>
-------------- next part --------------
From 566ce23e2641004b243dd675393e1a50c22e2724 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Wed, 22 Apr 2020 16:49:40 +0100
Subject: [PATCH 01/11] lxd/migration/migrate/proto: Fix alignment

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/migration/migrate.proto | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/lxd/migration/migrate.proto b/lxd/migration/migrate.proto
index a337d90cef..b334781ef5 100644
--- a/lxd/migration/migrate.proto
+++ b/lxd/migration/migrate.proto
@@ -65,9 +65,9 @@ message MigrationHeader {
 	repeated string				snapshotNames	= 4;
 	repeated Snapshot			snapshots	= 5;
 	optional bool				predump		= 7;
-	optional rsyncFeatures		rsyncFeatures = 8;
+	optional rsyncFeatures			rsyncFeatures 	= 8;
 	optional bool				refresh		= 9;
-	optional zfsFeatures		zfsFeatures = 10;
+	optional zfsFeatures			zfsFeatures 	= 10;
 }
 
 message MigrationControl {

From 1b02d01a88321a331cb4c7b888faa4ead7b4538c Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Wed, 22 Apr 2020 16:50:26 +0100
Subject: [PATCH 02/11] lxd/migration: Adds volumeSize field to MigrationHeader

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/migration/migrate.pb.go | 145 +++++++++++++++++++-----------------
 lxd/migration/migrate.proto |   1 +
 2 files changed, 78 insertions(+), 68 deletions(-)

diff --git a/lxd/migration/migrate.pb.go b/lxd/migration/migrate.pb.go
index 379acefa4f..cf1b5fbe4c 100644
--- a/lxd/migration/migrate.pb.go
+++ b/lxd/migration/migrate.pb.go
@@ -492,6 +492,7 @@ type MigrationHeader struct {
 	RsyncFeatures        *RsyncFeatures   `protobuf:"bytes,8,opt,name=rsyncFeatures" json:"rsyncFeatures,omitempty"`
 	Refresh              *bool            `protobuf:"varint,9,opt,name=refresh" json:"refresh,omitempty"`
 	ZfsFeatures          *ZfsFeatures     `protobuf:"bytes,10,opt,name=zfsFeatures" json:"zfsFeatures,omitempty"`
+	VolumeSize           *int64           `protobuf:"varint,11,opt,name=volumeSize" json:"volumeSize,omitempty"`
 	XXX_NoUnkeyedLiteral struct{}         `json:"-"`
 	XXX_unrecognized     []byte           `json:"-"`
 	XXX_sizecache        int32            `json:"-"`
@@ -585,6 +586,13 @@ func (m *MigrationHeader) GetZfsFeatures() *ZfsFeatures {
 	return nil
 }
 
+func (m *MigrationHeader) GetVolumeSize() int64 {
+	if m != nil && m.VolumeSize != nil {
+		return *m.VolumeSize
+	}
+	return 0
+}
+
 type MigrationControl struct {
 	Success *bool `protobuf:"varint,1,req,name=success" json:"success,omitempty"`
 	// optional failure message if sending a failure
@@ -930,72 +938,73 @@ func init() {
 func init() { proto.RegisterFile("lxd/migration/migrate.proto", fileDescriptor_fe8772548dc4b615) }
 
 var fileDescriptor_fe8772548dc4b615 = []byte{
-	// 1063 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x55, 0xdd, 0x6e, 0xdb, 0x36,
-	0x14, 0x9e, 0x6d, 0x39, 0xb1, 0x8e, 0xec, 0xc4, 0x65, 0x82, 0x42, 0x68, 0xf7, 0xe3, 0xa9, 0x1d,
-	0xe6, 0xe6, 0x22, 0xe9, 0x5c, 0x0c, 0xe8, 0xd5, 0x80, 0xc6, 0x5e, 0xd6, 0x62, 0xa9, 0x1b, 0xd0,
-	0x09, 0x86, 0xed, 0x46, 0x60, 0xa5, 0x23, 0x87, 0x88, 0xfe, 0x40, 0xca, 0x49, 0x9c, 0x9b, 0x61,
-	0x8f, 0xb1, 0x07, 0xd8, 0xf3, 0xec, 0x6a, 0xef, 0x33, 0x90, 0x94, 0x14, 0x39, 0x1d, 0xb0, 0x3b,
-	0x9e, 0xef, 0x7c, 0xfa, 0x0e, 0x79, 0xfe, 0x04, 0x4f, 0xe3, 0xdb, 0xf0, 0x28, 0xe1, 0x4b, 0xc1,
-	0x0a, 0x9e, 0xa5, 0xe5, 0x09, 0x0f, 0x73, 0x91, 0x15, 0x19, 0xb1, 0x6b, 0x87, 0xf7, 0x3b, 0xd8,
-	0xef, 0x66, 0xef, 0x59, 0x7e, 0xbe, 0xce, 0x91, 0xec, 0x43, 0x97, 0xcb, 0x15, 0x0f, 0xdd, 0xd6,
-	0xa8, 0x3d, 0xee, 0x51, 0x63, 0x18, 0x74, 0xc9, 0x43, 0xb7, 0x5d, 0xa1, 0x4b, 0x1e, 0x92, 0xc7,
-	0xb0, 0x75, 0x99, 0xc9, 0x82, 0x87, 0x6e, 0x67, 0xd4, 0x1e, 0x77, 0x69, 0x69, 0x11, 0x02, 0x56,
-	0x2a, 0x79, 0xe8, 0x5a, 0x1a, 0xd5, 0x67, 0xf2, 0x04, 0x7a, 0x09, 0xcb, 0x05, 0x4b, 0x97, 0xe8,
-	0x76, 0x35, 0x5e, 0xdb, 0xde, 0x4b, 0xd8, 0x9a, 0x66, 0x69, 0xc4, 0x97, 0x64, 0x08, 0x9d, 0x2b,
-	0x5c, 0xeb, 0xd8, 0x36, 0x55, 0x47, 0x15, 0xf9, 0x9a, 0xc5, 0x2b, 0xd4, 0x91, 0x6d, 0x6a, 0x0c,
-	0xef, 0x27, 0xd8, 0x9a, 0xe1, 0x35, 0x0f, 0x50, 0xc7, 0x62, 0x09, 0x96, 0x9f, 0xe8, 0x33, 0x79,
-	0x01, 0x5b, 0x81, 0xd6, 0x73, 0xdb, 0xa3, 0xce, 0xd8, 0x99, 0x3c, 0x3a, 0xac, 0x1f, 0x7b, 0x68,
-	0x02, 0xd1, 0x92, 0xe0, 0xfd, 0xdd, 0x86, 0xde, 0x22, 0x65, 0xb9, 0xbc, 0xcc, 0x8a, 0xff, 0xd4,
-	0x7a, 0x05, 0x4e, 0x9c, 0x05, 0x2c, 0x9e, 0xfe, 0x8f, 0x60, 0x93, 0xa5, 0x1e, 0x9b, 0x8b, 0x2c,
-	0xe2, 0x31, 0x4a, 0xb7, 0x33, 0xea, 0x8c, 0x6d, 0x5a, 0xdb, 0xe4, 0x73, 0xb0, 0x31, 0xbf, 0xc4,
-	0x04, 0x05, 0x8b, 0x75, 0x86, 0x7a, 0xf4, 0x1e, 0x20, 0xdf, 0x43, 0x5f, 0x0b, 0x99, 0xd7, 0x49,
-	0xb7, 0xfb, 0x49, 0x3c, 0xe3, 0xa1, 0x1b, 0x34, 0xe2, 0x41, 0x9f, 0x89, 0xe0, 0x92, 0x17, 0x18,
-	0x14, 0x2b, 0x81, 0xee, 0x96, 0xce, 0xf0, 0x06, 0xa6, 0x2e, 0x25, 0x0b, 0x56, 0x60, 0xb4, 0x8a,
-	0xdd, 0x6d, 0x1d, 0xb7, 0xb6, 0xc9, 0x33, 0x18, 0x04, 0x02, 0x75, 0x00, 0x3f, 0x64, 0x05, 0xba,
-	0xbd, 0x51, 0x6b, 0xdc, 0xa1, 0xfd, 0x0a, 0x9c, 0xb1, 0x02, 0xc9, 0x73, 0xd8, 0x89, 0x99, 0x2c,
-	0xfc, 0x95, 0xc4, 0xd0, 0xb0, 0x6c, 0xc3, 0x52, 0xe8, 0x85, 0xc4, 0x50, 0xb1, 0xbc, 0x3f, 0x5a,
-	0x30, 0x10, 0x72, 0x9d, 0x06, 0x27, 0xc8, 0x54, 0x5c, 0xa9, 0xda, 0xe4, 0x96, 0x15, 0x85, 0x90,
-	0x6e, 0x6b, 0xd4, 0x1a, 0xf7, 0x68, 0x69, 0x29, 0x3c, 0xc4, 0x18, 0x0b, 0x55, 0x5b, 0x8d, 0x1b,
-	0x4b, 0x5d, 0x34, 0xc8, 0x92, 0x5c, 0xa0, 0x54, 0xd9, 0x53, 0x9e, 0xda, 0x26, 0xcf, 0x61, 0xf0,
-	0x91, 0x87, 0x5c, 0x60, 0xa0, 0xae, 0xa5, 0x33, 0xa8, 0x08, 0x9b, 0xa0, 0xf7, 0x02, 0x9c, 0xbb,
-	0x48, 0xd6, 0x17, 0x68, 0x0a, 0xb6, 0x36, 0x05, 0xbd, 0x3f, 0x3b, 0xb0, 0xfb, 0xbe, 0x4a, 0xee,
-	0x5b, 0x64, 0x21, 0x0a, 0x72, 0x00, 0xed, 0x48, 0xea, 0x2e, 0xd8, 0x99, 0x3c, 0x69, 0xa4, 0xbe,
-	0xe6, 0x9d, 0x2c, 0xd4, 0xac, 0xd0, 0x76, 0x24, 0xc9, 0xb7, 0x60, 0x05, 0x82, 0xaf, 0xf4, 0x13,
-	0x76, 0x26, 0x7b, 0xcd, 0xc6, 0xa0, 0xef, 0x2e, 0x34, 0x4d, 0x13, 0xc8, 0x01, 0x74, 0x79, 0x98,
-	0xb0, 0x5c, 0x37, 0x84, 0x33, 0xd9, 0x6f, 0x30, 0xeb, 0xe9, 0xa3, 0x86, 0xa2, 0x5e, 0x29, 0xcb,
-	0xa6, 0x9c, 0xb3, 0x04, 0xa5, 0x6b, 0xe9, 0x26, 0xda, 0x04, 0xc9, 0x77, 0x60, 0x57, 0x40, 0xd5,
-	0x28, 0xcd, 0xf8, 0x55, 0x5b, 0xd3, 0x7b, 0x16, 0x71, 0x61, 0x3b, 0x17, 0x18, 0xae, 0x92, 0xdc,
-	0xdd, 0xd6, 0x89, 0xa8, 0x4c, 0xf2, 0xc3, 0x83, 0xaa, 0xe9, 0x0e, 0x70, 0x26, 0x6e, 0x43, 0x70,
-	0xc3, 0x4f, 0x1f, 0x14, 0xd9, 0x85, 0x6d, 0x81, 0x91, 0x40, 0x79, 0xa9, 0xbb, 0xa2, 0x47, 0x2b,
-	0x93, 0xbc, 0xde, 0x28, 0x86, 0x0b, 0x5a, 0xf7, 0x71, 0x43, 0xb7, 0xe1, 0xa5, 0x4d, 0xaa, 0x77,
-	0x02, 0xc3, 0x3a, 0xe5, 0xd3, 0x2c, 0x2d, 0x44, 0x16, 0xab, 0x38, 0x72, 0x15, 0x04, 0xa6, 0x94,
-	0xaa, 0x89, 0x2b, 0x53, 0x79, 0x12, 0x94, 0x92, 0x2d, 0x4d, 0x3f, 0xd9, 0xb4, 0x32, 0xbd, 0x57,
-	0x30, 0xa8, 0x75, 0x16, 0xeb, 0x34, 0x50, 0xe3, 0x12, 0xf1, 0x94, 0xc5, 0x67, 0x02, 0x67, 0x2a,
-	0x17, 0x46, 0x69, 0x03, 0xf3, 0xfe, 0xea, 0xc0, 0x50, 0x65, 0xc6, 0x57, 0x43, 0x22, 0x7d, 0x4c,
-	0x0b, 0xb1, 0x56, 0x73, 0x12, 0x09, 0xc4, 0x3b, 0x9e, 0x2e, 0xfd, 0x82, 0x97, 0xab, 0x62, 0x40,
-	0xfb, 0x15, 0x78, 0xce, 0x13, 0x24, 0x5f, 0x81, 0x13, 0x89, 0xec, 0x0e, 0x53, 0x43, 0x69, 0x6b,
-	0x0a, 0x18, 0x48, 0x13, 0xbe, 0x86, 0x7e, 0x82, 0x89, 0x16, 0xd7, 0x8c, 0x8e, 0x66, 0x38, 0x25,
-	0xa6, 0x29, 0xcf, 0x60, 0x90, 0x60, 0x72, 0x23, 0x78, 0x81, 0x86, 0x63, 0x99, 0x40, 0x15, 0x58,
-	0x91, 0x72, 0xb6, 0x44, 0xe9, 0xcb, 0x80, 0xa5, 0x29, 0x86, 0x7a, 0xb1, 0x5a, 0xb4, 0xaf, 0xc1,
-	0x85, 0xc1, 0xc8, 0x4b, 0xd8, 0x2f, 0x49, 0x57, 0x3c, 0xcf, 0x31, 0xf4, 0x73, 0x26, 0x30, 0x2d,
-	0xf4, 0x8a, 0xb0, 0x28, 0x31, 0x5c, 0xe3, 0x3a, 0xd3, 0x9e, 0x7b, 0x59, 0x15, 0xa9, 0xc0, 0x54,
-	0x6f, 0x8b, 0x4a, 0xf6, 0x17, 0x83, 0x29, 0x12, 0x17, 0x09, 0xcb, 0x7d, 0x81, 0x32, 0x8b, 0xaf,
-	0xcd, 0xc6, 0x18, 0xd0, 0xbe, 0x06, 0xa9, 0xc1, 0xc8, 0x17, 0x00, 0x46, 0x29, 0x66, 0x77, 0x6b,
-	0xd7, 0xd6, 0x32, 0xb6, 0x46, 0x4e, 0xd9, 0xdd, 0xba, 0x72, 0xfb, 0x39, 0xcf, 0xcb, 0xc6, 0x28,
-	0xdd, 0x67, 0x0a, 0x50, 0xfb, 0xa6, 0x76, 0xfb, 0x1f, 0x57, 0x91, 0x74, 0x1d, 0x4d, 0xe9, 0x57,
-	0x94, 0xe3, 0x55, 0x24, 0xbd, 0x7f, 0x5a, 0xb0, 0x27, 0x50, 0x16, 0x99, 0xc0, 0x8d, 0x52, 0x7d,
-	0x63, 0xbe, 0x96, 0xbe, 0x1a, 0x75, 0x26, 0xd0, 0xfc, 0xd1, 0x2c, 0x6a, 0xde, 0x36, 0x2d, 0x41,
-	0x72, 0x00, 0x8f, 0x36, 0xd3, 0x13, 0x64, 0x37, 0xba, 0x64, 0x16, 0xdd, 0x6d, 0xe6, 0x66, 0x9a,
-	0xdd, 0xa8, 0xba, 0x45, 0x99, 0xb8, 0xaa, 0x8b, 0x5f, 0xd6, 0xad, 0xc4, 0xaa, 0xd2, 0x56, 0x97,
-	0x69, 0x94, 0xcd, 0x29, 0x31, 0x4d, 0xa9, 0x2f, 0x56, 0x82, 0xaa, 0x6c, 0xad, 0xfa, 0x62, 0xb4,
-	0x04, 0xbd, 0x5b, 0x70, 0x9a, 0xcf, 0x39, 0x02, 0x2b, 0x34, 0xad, 0xaa, 0xc6, 0xe7, 0x69, 0x63,
-	0x7c, 0x1e, 0x36, 0x29, 0xd5, 0x44, 0xf2, 0x5a, 0x0d, 0xa4, 0xd6, 0xd2, 0xe3, 0xe0, 0x4c, 0xbe,
-	0x6c, 0x8e, 0xf2, 0xa7, 0x09, 0xa3, 0x15, 0xfd, 0x60, 0xde, 0xd8, 0x88, 0x66, 0xd3, 0x11, 0x1b,
-	0xba, 0x74, 0xf1, 0xeb, 0x7c, 0x3a, 0xfc, 0x4c, 0x1d, 0x8f, 0xcf, 0xe9, 0xc9, 0x62, 0xd8, 0x22,
-	0xdb, 0xd0, 0xf9, 0xed, 0x64, 0x31, 0x6c, 0xab, 0x03, 0x3d, 0x9e, 0x0d, 0x3b, 0x64, 0x0f, 0x76,
-	0x8f, 0x4f, 0x3f, 0x4c, 0x7f, 0xf6, 0xdf, 0xcc, 0x67, 0xbe, 0xf9, 0xc2, 0x3a, 0x38, 0x82, 0x5e,
-	0xb5, 0x0b, 0xc9, 0x0e, 0x80, 0x3a, 0xfb, 0x0d, 0xb5, 0xb3, 0xb7, 0x6f, 0x2e, 0x4e, 0x87, 0x2d,
-	0xd2, 0x03, 0x6b, 0xfe, 0x61, 0xfe, 0xe3, 0xb0, 0xfd, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xc9,
-	0x83, 0x44, 0xf9, 0xb9, 0x08, 0x00, 0x00,
+	// 1080 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x55, 0xcd, 0x6e, 0xdb, 0x46,
+	0x17, 0xfd, 0x24, 0x51, 0xb6, 0x78, 0x25, 0x39, 0xca, 0xc4, 0x08, 0x88, 0xe4, 0x6b, 0xaa, 0x32,
+	0x29, 0xaa, 0x78, 0x61, 0xa7, 0x0a, 0x0a, 0x64, 0x55, 0x20, 0x96, 0xea, 0x26, 0xa8, 0xa3, 0x18,
+	0x23, 0x1b, 0x45, 0xbb, 0x21, 0x26, 0xe4, 0xa5, 0x3c, 0x30, 0xff, 0x30, 0x43, 0xd9, 0x96, 0x36,
+	0x45, 0x1f, 0xa6, 0x0f, 0xd1, 0xa7, 0xe8, 0xaa, 0xef, 0x53, 0xcc, 0x0c, 0x49, 0x93, 0x4e, 0x81,
+	0xee, 0xe6, 0x9e, 0x7b, 0x78, 0xee, 0xcc, 0xfd, 0x23, 0x3c, 0x8d, 0x6e, 0x83, 0xa3, 0x98, 0xaf,
+	0x04, 0xcb, 0x79, 0x9a, 0x14, 0x27, 0x3c, 0xcc, 0x44, 0x9a, 0xa7, 0xc4, 0xae, 0x1c, 0xee, 0x6f,
+	0x60, 0xbf, 0x9f, 0x7f, 0x60, 0xd9, 0xf9, 0x26, 0x43, 0xb2, 0x0f, 0x5d, 0x2e, 0xd7, 0x3c, 0x70,
+	0x5a, 0xe3, 0xf6, 0xa4, 0x47, 0x8d, 0x61, 0xd0, 0x15, 0x0f, 0x9c, 0x76, 0x89, 0xae, 0x78, 0x40,
+	0x1e, 0xc3, 0xce, 0x65, 0x2a, 0x73, 0x1e, 0x38, 0x9d, 0x71, 0x7b, 0xd2, 0xa5, 0x85, 0x45, 0x08,
+	0x58, 0x89, 0xe4, 0x81, 0x63, 0x69, 0x54, 0x9f, 0xc9, 0x13, 0xe8, 0xc5, 0x2c, 0x13, 0x2c, 0x59,
+	0xa1, 0xd3, 0xd5, 0x78, 0x65, 0xbb, 0xaf, 0x60, 0x67, 0x96, 0x26, 0x21, 0x5f, 0x91, 0x11, 0x74,
+	0xae, 0x70, 0xa3, 0x63, 0xdb, 0x54, 0x1d, 0x55, 0xe4, 0x6b, 0x16, 0xad, 0x51, 0x47, 0xb6, 0xa9,
+	0x31, 0xdc, 0x1f, 0x61, 0x67, 0x8e, 0xd7, 0xdc, 0x47, 0x1d, 0x8b, 0xc5, 0x58, 0x7c, 0xa2, 0xcf,
+	0xe4, 0x25, 0xec, 0xf8, 0x5a, 0xcf, 0x69, 0x8f, 0x3b, 0x93, 0xfe, 0xf4, 0xe1, 0x61, 0xf5, 0xd8,
+	0x43, 0x13, 0x88, 0x16, 0x04, 0xf7, 0xaf, 0x36, 0xf4, 0x96, 0x09, 0xcb, 0xe4, 0x65, 0x9a, 0xff,
+	0xab, 0xd6, 0x6b, 0xe8, 0x47, 0xa9, 0xcf, 0xa2, 0xd9, 0x7f, 0x08, 0xd6, 0x59, 0xea, 0xb1, 0x99,
+	0x48, 0x43, 0x1e, 0xa1, 0x74, 0x3a, 0xe3, 0xce, 0xc4, 0xa6, 0x95, 0x4d, 0xfe, 0x0f, 0x36, 0x66,
+	0x97, 0x18, 0xa3, 0x60, 0x91, 0xce, 0x50, 0x8f, 0xde, 0x01, 0xe4, 0x3b, 0x18, 0x68, 0x21, 0xf3,
+	0x3a, 0xe9, 0x74, 0x3f, 0x8b, 0x67, 0x3c, 0xb4, 0x41, 0x23, 0x2e, 0x0c, 0x98, 0xf0, 0x2f, 0x79,
+	0x8e, 0x7e, 0xbe, 0x16, 0xe8, 0xec, 0xe8, 0x0c, 0x37, 0x30, 0x75, 0x29, 0x99, 0xb3, 0x1c, 0xc3,
+	0x75, 0xe4, 0xec, 0xea, 0xb8, 0x95, 0x4d, 0x9e, 0xc3, 0xd0, 0x17, 0xa8, 0x03, 0x78, 0x01, 0xcb,
+	0xd1, 0xe9, 0x8d, 0x5b, 0x93, 0x0e, 0x1d, 0x94, 0xe0, 0x9c, 0xe5, 0x48, 0x5e, 0xc0, 0x5e, 0xc4,
+	0x64, 0xee, 0xad, 0x25, 0x06, 0x86, 0x65, 0x1b, 0x96, 0x42, 0x2f, 0x24, 0x06, 0x8a, 0xe5, 0xfe,
+	0xde, 0x82, 0xa1, 0x90, 0x9b, 0xc4, 0x3f, 0x41, 0xa6, 0xe2, 0x4a, 0xd5, 0x26, 0xb7, 0x2c, 0xcf,
+	0x85, 0x74, 0x5a, 0xe3, 0xd6, 0xa4, 0x47, 0x0b, 0x4b, 0xe1, 0x01, 0x46, 0x98, 0xab, 0xda, 0x6a,
+	0xdc, 0x58, 0xea, 0xa2, 0x7e, 0x1a, 0x67, 0x02, 0xa5, 0xca, 0x9e, 0xf2, 0x54, 0x36, 0x79, 0x01,
+	0xc3, 0x4f, 0x3c, 0xe0, 0x02, 0x7d, 0x75, 0x2d, 0x9d, 0x41, 0x45, 0x68, 0x82, 0xee, 0x4b, 0xe8,
+	0x6f, 0x43, 0x59, 0x5d, 0xa0, 0x2e, 0xd8, 0x6a, 0x0a, 0xba, 0x7f, 0x76, 0xe0, 0xc1, 0x87, 0x32,
+	0xb9, 0xef, 0x90, 0x05, 0x28, 0xc8, 0x01, 0xb4, 0x43, 0xa9, 0xbb, 0x60, 0x6f, 0xfa, 0xa4, 0x96,
+	0xfa, 0x8a, 0x77, 0xb2, 0x54, 0xb3, 0x42, 0xdb, 0xa1, 0x24, 0xdf, 0x80, 0xe5, 0x0b, 0xbe, 0xd6,
+	0x4f, 0xd8, 0x9b, 0x3e, 0xaa, 0x37, 0x06, 0x7d, 0x7f, 0xa1, 0x69, 0x9a, 0x40, 0x0e, 0xa0, 0xcb,
+	0x83, 0x98, 0x65, 0xba, 0x21, 0xfa, 0xd3, 0xfd, 0x1a, 0xb3, 0x9a, 0x3e, 0x6a, 0x28, 0xea, 0x95,
+	0xb2, 0x68, 0xca, 0x05, 0x8b, 0x51, 0x3a, 0x96, 0x6e, 0xa2, 0x26, 0x48, 0xbe, 0x05, 0xbb, 0x04,
+	0xca, 0x46, 0xa9, 0xc7, 0x2f, 0xdb, 0x9a, 0xde, 0xb1, 0x88, 0x03, 0xbb, 0x99, 0xc0, 0x60, 0x1d,
+	0x67, 0xce, 0xae, 0x4e, 0x44, 0x69, 0x92, 0xef, 0xef, 0x55, 0x4d, 0x77, 0x40, 0x7f, 0xea, 0xd4,
+	0x04, 0x1b, 0x7e, 0x7a, 0xaf, 0xc8, 0x0e, 0xec, 0x0a, 0x0c, 0x05, 0xca, 0x4b, 0xdd, 0x15, 0x3d,
+	0x5a, 0x9a, 0xe4, 0x4d, 0xa3, 0x18, 0x0e, 0x68, 0xdd, 0xc7, 0x35, 0xdd, 0x9a, 0x97, 0x36, 0xea,
+	0xf6, 0x0c, 0xe0, 0x3a, 0x8d, 0xd6, 0x31, 0x2e, 0xf9, 0x16, 0x9d, 0xbe, 0x6e, 0xb6, 0x1a, 0xe2,
+	0x9e, 0xc0, 0xa8, 0x2a, 0xc9, 0x2c, 0x4d, 0x72, 0x91, 0x46, 0xea, 0x1e, 0x72, 0xed, 0xfb, 0xa6,
+	0xd4, 0xaa, 0xc9, 0x4b, 0x53, 0x79, 0x62, 0x94, 0x92, 0xad, 0x4c, 0xbf, 0xd9, 0xb4, 0x34, 0xdd,
+	0xd7, 0x30, 0xac, 0x74, 0x96, 0x9b, 0xc4, 0x57, 0xe3, 0x14, 0xf2, 0x84, 0x45, 0x67, 0x02, 0xe7,
+	0x2a, 0x57, 0x46, 0xa9, 0x81, 0xb9, 0x7f, 0x74, 0x60, 0xa4, 0x32, 0xe7, 0xa9, 0x21, 0x92, 0x1e,
+	0x26, 0xb9, 0xd8, 0xa8, 0x39, 0x0a, 0x05, 0xe2, 0x96, 0x27, 0x2b, 0x2f, 0xe7, 0xc5, 0x2a, 0x19,
+	0xd2, 0x41, 0x09, 0x9e, 0xf3, 0x18, 0xc9, 0x97, 0xd0, 0x0f, 0x45, 0xba, 0xc5, 0xc4, 0x50, 0xda,
+	0x9a, 0x02, 0x06, 0xd2, 0x84, 0xaf, 0x60, 0x10, 0x63, 0xac, 0xc5, 0x35, 0xa3, 0xa3, 0x19, 0xfd,
+	0x02, 0xd3, 0x94, 0xe7, 0x30, 0x8c, 0x31, 0xbe, 0x11, 0x3c, 0x47, 0xc3, 0xb1, 0x4c, 0xa0, 0x12,
+	0x2c, 0x49, 0x19, 0x5b, 0xa1, 0xf4, 0xa4, 0xcf, 0x92, 0x04, 0x03, 0xbd, 0x78, 0x2d, 0x3a, 0xd0,
+	0xe0, 0xd2, 0x60, 0xe4, 0x15, 0xec, 0x17, 0xa4, 0x2b, 0x9e, 0x65, 0x18, 0x78, 0x19, 0x13, 0x98,
+	0xe4, 0x7a, 0x85, 0x58, 0x94, 0x18, 0xae, 0x71, 0x9d, 0x69, 0xcf, 0x9d, 0xac, 0x8a, 0x94, 0x63,
+	0xa2, 0xb7, 0x49, 0x29, 0xfb, 0xb3, 0xc1, 0x14, 0x89, 0x8b, 0x98, 0x65, 0x9e, 0x40, 0x99, 0x46,
+	0xd7, 0x66, 0xa3, 0x0c, 0xe9, 0x40, 0x83, 0xd4, 0x60, 0xe4, 0x0b, 0x00, 0xa3, 0x14, 0xb1, 0xed,
+	0xc6, 0xb1, 0xb5, 0x8c, 0xad, 0x91, 0x53, 0xb6, 0xdd, 0x94, 0x6e, 0x2f, 0xe3, 0x59, 0xd1, 0x38,
+	0x85, 0xfb, 0x4c, 0x01, 0x6a, 0x1f, 0x55, 0x6e, 0xef, 0xd3, 0x3a, 0x94, 0xba, 0x45, 0x8a, 0x8b,
+	0x28, 0xca, 0xf1, 0x3a, 0x94, 0xee, 0xdf, 0x2d, 0x78, 0x24, 0x50, 0xe6, 0xa9, 0xc0, 0x46, 0xa9,
+	0xbe, 0x36, 0x5f, 0x4b, 0x4f, 0xad, 0x02, 0x26, 0xd0, 0xfc, 0xf1, 0x2c, 0x6a, 0xde, 0x36, 0x2b,
+	0x40, 0x72, 0x00, 0x0f, 0x9b, 0xe9, 0xf1, 0xd3, 0x1b, 0x5d, 0x32, 0x8b, 0x3e, 0xa8, 0xe7, 0x66,
+	0x96, 0xde, 0xa8, 0xba, 0x85, 0xa9, 0xb8, 0xaa, 0x8a, 0x5f, 0xd4, 0xad, 0xc0, 0xca, 0xd2, 0x96,
+	0x97, 0xa9, 0x95, 0xad, 0x5f, 0x60, 0x9a, 0x52, 0x5d, 0xac, 0x00, 0x55, 0xd9, 0x5a, 0xd5, 0xc5,
+	0x68, 0x01, 0xba, 0xb7, 0xd0, 0xaf, 0x3f, 0xe7, 0x08, 0xac, 0xc0, 0xb4, 0xaa, 0x1a, 0xaf, 0xa7,
+	0xb5, 0xf1, 0xba, 0xdf, 0xa4, 0x54, 0x13, 0xc9, 0x1b, 0x35, 0xb0, 0x5a, 0x4b, 0x8f, 0x43, 0x7f,
+	0xfa, 0xac, 0x3e, 0xea, 0x9f, 0x27, 0x8c, 0x96, 0xf4, 0x83, 0x45, 0x6d, 0x63, 0x9a, 0x4d, 0x48,
+	0x6c, 0xe8, 0xd2, 0xe5, 0x2f, 0x8b, 0xd9, 0xe8, 0x7f, 0xea, 0x78, 0x7c, 0x4e, 0x4f, 0x96, 0xa3,
+	0x16, 0xd9, 0x85, 0xce, 0xaf, 0x27, 0xcb, 0x51, 0x5b, 0x1d, 0xe8, 0xf1, 0x7c, 0xd4, 0x21, 0x8f,
+	0xe0, 0xc1, 0xf1, 0xe9, 0xc7, 0xd9, 0x4f, 0xde, 0xdb, 0xc5, 0xdc, 0x33, 0x5f, 0x58, 0x07, 0x47,
+	0xd0, 0x2b, 0x77, 0x25, 0xd9, 0x03, 0x50, 0x67, 0xaf, 0xa6, 0x76, 0xf6, 0xee, 0xed, 0xc5, 0xe9,
+	0xa8, 0x45, 0x7a, 0x60, 0x2d, 0x3e, 0x2e, 0x7e, 0x18, 0xb5, 0xff, 0x09, 0x00, 0x00, 0xff, 0xff,
+	0x6c, 0x4d, 0xa0, 0xee, 0xd9, 0x08, 0x00, 0x00,
 }
diff --git a/lxd/migration/migrate.proto b/lxd/migration/migrate.proto
index b334781ef5..721662e424 100644
--- a/lxd/migration/migrate.proto
+++ b/lxd/migration/migrate.proto
@@ -68,6 +68,7 @@ message MigrationHeader {
 	optional rsyncFeatures			rsyncFeatures 	= 8;
 	optional bool				refresh		= 9;
 	optional zfsFeatures			zfsFeatures 	= 10;
+	optional int64				volumeSize	= 11;
 }
 
 message MigrationControl {

From 4ae6045863b54bd41660f9be53f2c16e9432caf7 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Wed, 22 Apr 2020 17:13:43 +0100
Subject: [PATCH 03/11] lxd/migrate: Adds VolumeSize to MigrationSinkArgs

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/migrate.go | 1 +
 1 file changed, 1 insertion(+)

diff --git a/lxd/migrate.go b/lxd/migrate.go
index 30739cd766..7f72810f7e 100644
--- a/lxd/migrate.go
+++ b/lxd/migrate.go
@@ -273,6 +273,7 @@ type MigrationSinkArgs struct {
 
 	// Storage specific fields
 	VolumeOnly bool
+	VolumeSize int64
 
 	// Transport specific fields
 	RsyncFeatures []string

From 8382f56055eb6240890eb40dda0dd061e28f5560 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Wed, 22 Apr 2020 17:14:05 +0100
Subject: [PATCH 04/11] lxd/migration/migration/volumes: Adds VolumeSize to
 VolumeTargetArgs

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/migration/migration_volumes.go | 1 +
 1 file changed, 1 insertion(+)

diff --git a/lxd/migration/migration_volumes.go b/lxd/migration/migration_volumes.go
index 936d659f2d..331b003c22 100644
--- a/lxd/migration/migration_volumes.go
+++ b/lxd/migration/migration_volumes.go
@@ -38,6 +38,7 @@ type VolumeTargetArgs struct {
 	TrackProgress bool
 	Refresh       bool
 	Live          bool
+	VolumeSize    int64
 }
 
 // TypesToHeader converts one or more Types to a MigrationHeader. It uses the first type argument

From 8ed605fe3086d5735e0b8c5894217a2cc2552ad6 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Wed, 22 Apr 2020 17:14:22 +0100
Subject: [PATCH 05/11] lxd/migrate/instance: Use VolumeSize from offer header
 in Do()

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/migrate_instance.go | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/lxd/migrate_instance.go b/lxd/migrate_instance.go
index a370d52b1e..451215e1a6 100644
--- a/lxd/migrate_instance.go
+++ b/lxd/migrate_instance.go
@@ -864,6 +864,7 @@ func (c *migrationSink) Do(state *state.State, migrateOp *operations.Operation)
 			Refresh:       args.Refresh, // Indicate to receiver volume should exist.
 			TrackProgress: false,        // Do not use a progress tracker on receiver.
 			Live:          args.Live,    // Indicates we will get a final rootfs sync.
+			VolumeSize:    args.VolumeSize,
 		}
 
 		// At this point we have already figured out the parent container's root
@@ -1033,6 +1034,7 @@ func (c *migrationSink) Do(state *state.State, migrateOp *operations.Operation)
 				Refresh:       c.refresh,
 				RsyncFeatures: rsyncFeatures,
 				Snapshots:     snapshots,
+				VolumeSize:    offerHeader.GetVolumeSize(),
 			}
 
 			err = myTarget(fsConn, migrateOp, args)

From d48d62fcaa96f425ead19924f07aa418308ec303 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 23 Apr 2020 09:10:21 +0100
Subject: [PATCH 06/11] lxd/storage/backend/lxd: Use VolumeSize from migration
 header in CreateInstanceFromMigration

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/storage/backend_lxd.go | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/lxd/storage/backend_lxd.go b/lxd/storage/backend_lxd.go
index 8718bb7733..98a769544b 100644
--- a/lxd/storage/backend_lxd.go
+++ b/lxd/storage/backend_lxd.go
@@ -1044,6 +1044,14 @@ func (b *lxdBackend) CreateInstanceFromMigration(inst instance.Instance, conn io
 	args.Config = rootDiskConf
 	args.Name = inst.Name()
 
+	// If migration header supplies a volume size, then use that as block volume size instead of pool default.
+	// This way if the volume being received is larger than the pool default size, the block volume created
+	// will still be able to accommodate it.
+	if args.VolumeSize > 0 && contentType == drivers.ContentTypeBlock {
+		b.logger.Debug("Setting volume size from offer header", log.Ctx{"size": args.VolumeSize})
+		args.Config["size"] = fmt.Sprintf("%d", args.VolumeSize)
+	}
+
 	// Get the volume name on storage.
 	volStorageName := project.Instance(inst.Project(), args.Name)
 

From 30c9e74780e8aa28432e6078f2cdcfa7d41cf161 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 23 Apr 2020 11:12:44 +0100
Subject: [PATCH 07/11] lxd/storage/drivers: Exports BlockDevSizeBytes function

So can be used by migration header generation.

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/storage/drivers/driver_ceph_volumes.go | 2 +-
 lxd/storage/drivers/generic_vfs.go         | 2 +-
 lxd/storage/drivers/utils.go               | 4 ++--
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/lxd/storage/drivers/driver_ceph_volumes.go b/lxd/storage/drivers/driver_ceph_volumes.go
index 7af0b8a4ff..623a12b182 100644
--- a/lxd/storage/drivers/driver_ceph_volumes.go
+++ b/lxd/storage/drivers/driver_ceph_volumes.go
@@ -757,7 +757,7 @@ func (d *ceph) SetVolumeQuota(vol Volume, size string, op *operations.Operation)
 		vol.keepDevice = oldKeepDevice
 	}()
 
-	oldSizeBytes, err := blockDevSizeBytes(RBDDevPath)
+	oldSizeBytes, err := BlockDevSizeBytes(RBDDevPath)
 	if err != nil {
 		return errors.Wrapf(err, "Error getting current size")
 	}
diff --git a/lxd/storage/drivers/generic_vfs.go b/lxd/storage/drivers/generic_vfs.go
index 75f344c484..7303e9e770 100644
--- a/lxd/storage/drivers/generic_vfs.go
+++ b/lxd/storage/drivers/generic_vfs.go
@@ -458,7 +458,7 @@ func genericVFSBackupVolume(d Driver, vol Volume, tarWriter *instancewriter.Inst
 
 				if shared.IsBlockdevPath(blockPath) {
 					// Get size of disk block device for tarball header.
-					blockDiskSize, err = blockDevSizeBytes(blockPath)
+					blockDiskSize, err = BlockDevSizeBytes(blockPath)
 					if err != nil {
 						return errors.Wrapf(err, "Error getting block device size %q", blockPath)
 					}
diff --git a/lxd/storage/drivers/utils.go b/lxd/storage/drivers/utils.go
index 9f1e55c275..9552d12222 100644
--- a/lxd/storage/drivers/utils.go
+++ b/lxd/storage/drivers/utils.go
@@ -740,8 +740,8 @@ func ShiftZFSSkipper(dir string, absPath string, fi os.FileInfo) bool {
 	return false
 }
 
-// blockDevSizeBytes returns the size of a block device.
-func blockDevSizeBytes(blockDevPath string) (int64, error) {
+// BlockDevSizeBytes returns the size of a block device.
+func BlockDevSizeBytes(blockDevPath string) (int64, error) {
 	// Attempt to open the device path.
 	f, err := os.Open(blockDevPath)
 	if err != nil {

From dd37ad8ea0e126255b3ec886f9904526ed570bdd Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 23 Apr 2020 12:15:01 +0100
Subject: [PATCH 08/11] lxd/storage/utils: Adds InstanceDiskBlockSize

Allows getting disk size of block devices.

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/storage/utils.go | 36 ++++++++++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/lxd/storage/utils.go b/lxd/storage/utils.go
index 28a2bd03e7..7065b98708 100644
--- a/lxd/storage/utils.go
+++ b/lxd/storage/utils.go
@@ -16,6 +16,7 @@ import (
 	"github.com/lxc/lxd/lxd/instance/instancetype"
 	"github.com/lxc/lxd/lxd/migration"
 	"github.com/lxc/lxd/lxd/node"
+	"github.com/lxc/lxd/lxd/operations"
 	"github.com/lxc/lxd/lxd/rsync"
 	"github.com/lxc/lxd/lxd/state"
 	"github.com/lxc/lxd/lxd/storage/drivers"
@@ -649,3 +650,38 @@ func RenderSnapshotUsage(s *state.State, snapInst instance.Instance) func(respon
 		return nil
 	}
 }
+
+// InstanceDiskBlockSize returns the block device size for the instance's disk.
+// This will mount the instance if not already mounted and will unmount at the end if needed.
+func InstanceDiskBlockSize(pool Pool, inst instance.Instance, op *operations.Operation) (int64, error) {
+	ourMount, err := pool.MountInstance(inst, op)
+	if err != nil {
+		return -1, err
+	}
+
+	if ourMount {
+		defer pool.UnmountInstance(inst, op)
+	}
+
+	rootDrivePath, err := pool.GetInstanceDisk(inst)
+	if err != nil {
+		return -1, err
+	}
+
+	var blockDiskSize int64
+
+	if shared.IsBlockdevPath(rootDrivePath) {
+		blockDiskSize, err = drivers.BlockDevSizeBytes(rootDrivePath)
+		if err != nil {
+			return -1, errors.Wrapf(err, "Error getting block device size %q", rootDrivePath)
+		}
+	} else {
+		fi, err := os.Lstat(rootDrivePath)
+		if err != nil {
+			return -1, errors.Wrapf(err, "Error getting block file size %q", rootDrivePath)
+		}
+		blockDiskSize = fi.Size()
+	}
+
+	return blockDiskSize, nil
+}

From 85eb5a5a09a848431333035124374b303bf09249 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 23 Apr 2020 11:31:24 +0100
Subject: [PATCH 09/11] lxd/migrate/instance: Populate offerHeader.VolumeSize
 for VMs

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/migrate_instance.go | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/lxd/migrate_instance.go b/lxd/migrate_instance.go
index 451215e1a6..f633eae312 100644
--- a/lxd/migrate_instance.go
+++ b/lxd/migrate_instance.go
@@ -408,6 +408,17 @@ func (s *migrationSourceWs) Do(state *state.State, migrateOp *operations.Operati
 	offerHeader.SnapshotNames = snapshotNames
 	offerHeader.Snapshots = snapshots
 
+	// For VMs, send block device size hint in offer header so that target can create the volume the same size.
+	if s.instance.Type() == instancetype.VM {
+		blockSize, err := storagePools.InstanceDiskBlockSize(pool, s.instance, migrateOp)
+		if err != nil {
+			return errors.Wrapf(err, "Failed getting source disk size")
+		}
+
+		logger.Debugf("Set migration offer volume size for %q: %d", s.instance.Name(), blockSize)
+		offerHeader.VolumeSize = &blockSize
+	}
+
 	// Add predump info to source header.
 	offerUsePreDumps := false
 	maxDumpIterations := 0

From 08ce1da1558257a4320bf7f6a9206f14ec3f0e2f Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 23 Apr 2020 13:23:30 +0100
Subject: [PATCH 10/11] lxd/storage/backend/lxd: Adds VM volume size hint to
 CreateInstanceFromCopy

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/storage/backend_lxd.go | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/lxd/storage/backend_lxd.go b/lxd/storage/backend_lxd.go
index 98a769544b..574ff172d7 100644
--- a/lxd/storage/backend_lxd.go
+++ b/lxd/storage/backend_lxd.go
@@ -688,6 +688,16 @@ func (b *lxdBackend) CreateInstanceFromCopy(inst instance.Instance, src instance
 			return fmt.Errorf("Failed to negotiate copy migration type: %v", err)
 		}
 
+		var srcVolumeSize int64
+
+		// For VMs, get source volume size so that target can create the volume the same size.
+		if src.Type() == instancetype.VM {
+			srcVolumeSize, err = InstanceDiskBlockSize(srcPool, src, op)
+			if err != nil {
+				return errors.Wrapf(err, "Failed getting source disk size")
+			}
+		}
+
 		ctx, cancel := context.WithCancel(context.Background())
 
 		// Use in-memory pipe pair to simulate a connection between the sender and receiver.
@@ -715,6 +725,7 @@ func (b *lxdBackend) CreateInstanceFromCopy(inst instance.Instance, src instance
 				Name:          inst.Name(),
 				Snapshots:     snapshotNames,
 				MigrationType: migrationTypes[0],
+				VolumeSize:    srcVolumeSize,
 				TrackProgress: false, // Do not use a progress tracker on receiver.
 			}, op)
 

From 8f4cb9f078c76c46a03cf2f280574e5cd12bf561 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 23 Apr 2020 16:05:21 +0100
Subject: [PATCH 11/11] lxd/storage/backend/lxd: Adds
 prepareImageVolumeRegeneration used in EnsureImage

The prepareImageVolumeRegeneration renames an image volume to a random name and then deletes the volume.
The reason for the initial rename before delete is to ensure that if the underlying storage driver has an 'undelete' feature, whereby the actual image volume isn't deleted (because it is a parent of another volume) then subsequent calls to EnsureImage() will actually just undelete the image volume which isn't what we want when regenerating a volume.

By calling prepareImageVolumeRegeneration before EnsureImage we can be sure that the driver will have to regenerate a fresh image volume (using the current pool's settings) and not use an existing volume.

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/storage/backend_lxd.go | 87 ++++++++++++++++++++++++++++++--------
 1 file changed, 69 insertions(+), 18 deletions(-)

diff --git a/lxd/storage/backend_lxd.go b/lxd/storage/backend_lxd.go
index 574ff172d7..225480093d 100644
--- a/lxd/storage/backend_lxd.go
+++ b/lxd/storage/backend_lxd.go
@@ -9,6 +9,7 @@ import (
 	"strings"
 	"time"
 
+	"github.com/pborman/uuid"
 	"github.com/pkg/errors"
 	yaml "gopkg.in/yaml.v2"
 
@@ -2034,7 +2035,7 @@ func (b *lxdBackend) EnsureImage(fingerprint string, op *operations.Operation) e
 	if imgDBVol != nil && contentType == drivers.ContentTypeFS {
 		if b.Driver().Info().BlockBacking && imgDBVol.Config["block.filesystem"] != b.poolBlockFilesystem() {
 			logger.Debug("Filesystem of pool has changed since cached image volume created, regenerating image volume")
-			err = b.DeleteImage(fingerprint, op)
+			err = b.prepareImageVolumeRegeneration(fingerprint, contentType, op)
 			if err != nil {
 				return err
 			}
@@ -2068,30 +2069,59 @@ func (b *lxdBackend) EnsureImage(fingerprint string, op *operations.Operation) e
 	return nil
 }
 
-// DeleteImage removes an image from the database and underlying storage device if needed.
-func (b *lxdBackend) DeleteImage(fingerprint string, op *operations.Operation) error {
-	logger := logging.AddContext(b.logger, log.Ctx{"fingerprint": fingerprint})
-	logger.Debug("DeleteImage started")
-	defer logger.Debug("DeleteImage finished")
+// prepareImageVolumeRegeneration renames the existing image volume to a random temporary name and then deletes
+// the volume to make way for a regenerated volume to take its place. The rename to a temporary name before the
+// deletion is to ensure that storage drivers that have an 'undelete' feature (whereby an image volume that is a
+// parent of other volumes cannot be deleted and so is kept around and can be resurrected) cannot be used to
+// resurrect this image volume and a fresh one has to be generated.
+func (b *lxdBackend) prepareImageVolumeRegeneration(fingerprint string, contentType drivers.ContentType, op *operations.Operation) error {
+	tmpName := strings.Replace(uuid.New(), "-", "", -1)
+	err := b.renameImageVolume(fingerprint, tmpName, contentType, op)
+	if err != nil {
+		return err
+	}
 
-	// We need to lock this operation to ensure that the image is not being
-	// deleted multiple times.
-	unlock := locking.Lock(b.name, string(drivers.VolumeTypeImage), fingerprint)
-	defer unlock()
+	return b.deleteImageVolume(tmpName, contentType, op)
+}
 
-	// Load image info from database.
-	_, image, err := b.state.Cluster.ImageGetFromAnyProject(fingerprint)
+// renameImageVolume renames an image volume. As this is an internal function, the caller is expected to lookup
+// the image volume's content type from the database first to avoid needing additional database lookups.
+func (b *lxdBackend) renameImageVolume(fingerprint string, newName string, contentType drivers.ContentType, op *operations.Operation) error {
+	logger := logging.AddContext(b.logger, log.Ctx{"fingerprint": fingerprint, "newName": newName})
+	logger.Debug("renameImageVolume started")
+	defer logger.Debug("renameImageVolume finished")
+
+	revert := revert.New()
+	defer revert.Fail()
+
+	err := b.state.Cluster.StoragePoolVolumeRename(project.Default, fingerprint, newName, db.StoragePoolVolumeTypeImage, b.ID())
 	if err != nil {
 		return err
 	}
 
-	contentType := drivers.ContentTypeFS
+	revert.Add(func() {
+		b.state.Cluster.StoragePoolVolumeRename(project.Default, newName, fingerprint, db.StoragePoolVolumeTypeImage, b.ID())
+	})
 
-	// Image types are not the same as instance types, so don't use instance type constants.
-	if image.Type == "virtual-machine" {
-		contentType = drivers.ContentTypeBlock
+	// There's no need to pass the config as it's not needed when renaming a volume.
+	vol := b.newVolume(drivers.VolumeTypeImage, contentType, fingerprint, nil)
+
+	err = b.driver.RenameVolume(vol, newName, op)
+	if err != nil {
+		return err
 	}
 
+	revert.Success()
+	return nil
+}
+
+// deleteImageVolume deletes an image volume. As this is an internal function, the caller is expected to lookup
+// the image volume's content type from the database first to avoid needing additional database looups.
+func (b *lxdBackend) deleteImageVolume(fingerprint string, contentType drivers.ContentType, op *operations.Operation) error {
+	logger := logging.AddContext(b.logger, log.Ctx{"fingerprint": fingerprint})
+	logger.Debug("deleteImageVolume started")
+	defer logger.Debug("deleteImageVolume finished")
+
 	// Load the storage volume in order to get the volume config which is needed for some drivers.
 	_, storageVol, err := b.state.Cluster.StoragePoolNodeVolumeGetTypeByProject(project.Default, fingerprint, db.StoragePoolVolumeTypeImage, b.ID())
 	if err != nil {
@@ -2107,12 +2137,33 @@ func (b *lxdBackend) DeleteImage(fingerprint string, op *operations.Operation) e
 		}
 	}
 
-	err = b.state.Cluster.StoragePoolVolumeDelete(project.Default, fingerprint, db.StoragePoolVolumeTypeImage, b.ID())
+	return b.state.Cluster.StoragePoolVolumeDelete(project.Default, fingerprint, db.StoragePoolVolumeTypeImage, b.ID())
+}
+
+// DeleteImage removes an image from the database and underlying storage device if needed.
+func (b *lxdBackend) DeleteImage(fingerprint string, op *operations.Operation) error {
+	logger := logging.AddContext(b.logger, log.Ctx{"fingerprint": fingerprint})
+	logger.Debug("DeleteImage started")
+	defer logger.Debug("DeleteImage finished")
+
+	// We need to lock this operation to ensure that the image is not being deleted multiple times.
+	unlock := locking.Lock(b.name, string(drivers.VolumeTypeImage), fingerprint)
+	defer unlock()
+
+	// Load image info from database.
+	_, image, err := b.state.Cluster.ImageGetFromAnyProject(fingerprint)
 	if err != nil {
 		return err
 	}
 
-	return nil
+	contentType := drivers.ContentTypeFS
+
+	// Image types are not the same as instance types, so don't use instance type constants.
+	if image.Type == "virtual-machine" {
+		contentType = drivers.ContentTypeBlock
+	}
+
+	return b.deleteImageVolume(fingerprint, contentType, op)
 }
 
 // updateVolumeDescriptionOnly is a helper function used when handling update requests for volumes


More information about the lxc-devel mailing list