[lxc-devel] [lxd/master] Storage containerLXC linking

tomponline on Github lxc-bot at linuxcontainers.org
Thu Dec 5 17:14:34 UTC 2019


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 602 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20191205/051dbc8e/attachment-0001.bin>
-------------- next part --------------
From 3e7bad04011c95f7c92f2b60ae72a27c2367cae4 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 5 Dec 2019 15:41:39 +0000
Subject: [PATCH 1/4] lxd/container/lxc: Unexport storageStartSensitive

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

diff --git a/lxd/container_lxc.go b/lxd/container_lxc.go
index 09120cfca4..3dc126200f 100644
--- a/lxd/container_lxc.go
+++ b/lxd/container_lxc.go
@@ -2572,7 +2572,7 @@ func (c *containerLXC) OnStart() error {
 	c.fromHook = true
 
 	// Start the storage for this container
-	ourStart, err := c.StorageStartSensitive()
+	ourStart, err := c.storageStartSensitive()
 	if err != nil {
 		return err
 	}
@@ -6216,7 +6216,7 @@ func (c *containerLXC) StorageStart() (bool, error) {
 		return false, err
 	}
 
-	isOurOperation, err := c.StorageStartSensitive()
+	isOurOperation, err := c.storageStartSensitive()
 	// Remove this as soon as zfs is fixed
 	if c.storage.GetStorageType() == storageTypeZfs && err == unix.EBUSY {
 		return isOurOperation, nil
@@ -6226,7 +6226,7 @@ func (c *containerLXC) StorageStart() (bool, error) {
 }
 
 // Kill this function as soon as zfs is fixed.
-func (c *containerLXC) StorageStartSensitive() (bool, error) {
+func (c *containerLXC) storageStartSensitive() (bool, error) {
 	// Initialize storage interface for the container.
 	err := c.initStorage()
 	if err != nil {

From 57aa879f7a965db338a6da0e11e4cd0a580af3ef Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 5 Dec 2019 17:08:54 +0000
Subject: [PATCH 2/4] lxd/vm/qemu: Makes mount and unmount functions behave the
 same as containerLXC's

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

diff --git a/lxd/vm_qemu.go b/lxd/vm_qemu.go
index 284ef6df37..c362f6355b 100644
--- a/lxd/vm_qemu.go
+++ b/lxd/vm_qemu.go
@@ -345,7 +345,7 @@ func (vm *vmQemu) getMonitorEventHandler() func(event string, data map[string]in
 	}
 }
 
-// mount mounts the instance's config volume if needed.
+// mount the instance's config volume if needed.
 func (vm *vmQemu) mount() (ourMount bool, err error) {
 	var pool storagePools.Pool
 	pool, err = vm.getStoragePool()
@@ -361,19 +361,20 @@ func (vm *vmQemu) mount() (ourMount bool, err error) {
 	return
 }
 
-// unmount unmounts the instance's config volume if needed.
-func (vm *vmQemu) unmount() error {
-	pool, err := vm.getStoragePool()
+// unmount the instance's config volume if needed.
+func (vm *vmQemu) unmount() (unmounted bool, err error) {
+	var pool storagePools.Pool
+	pool, err = vm.getStoragePool()
 	if err != nil {
-		return err
+		return
 	}
 
-	_, err = pool.UnmountInstance(vm, nil)
+	unmounted, err = pool.UnmountInstance(vm, nil)
 	if err != nil {
-		return err
+		return
 	}
 
-	return nil
+	return
 }
 
 // generateAgentCert creates the necessary server key and certificate if needed.

From 4ae3f43d52f35c1350c2014972f20557e90c3205 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 5 Dec 2019 17:09:26 +0000
Subject: [PATCH 3/4] lxd/storage/backend/lxd: Fixes
 MountInstanceSnapshot/UnmountInstanceSnapshot functions

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

diff --git a/lxd/storage/backend_lxd.go b/lxd/storage/backend_lxd.go
index c6f40d6345..fadbd99ded 100644
--- a/lxd/storage/backend_lxd.go
+++ b/lxd/storage/backend_lxd.go
@@ -1461,11 +1461,11 @@ func (b *lxdBackend) MountInstanceSnapshot(inst instance.Instance, op *operation
 		return false, err
 	}
 
-	// Get the volume name on storage.
-	volStorageName := project.Prefix(inst.Project(), inst.Name())
+	// Get the parent and snapshot name.
+	parentName, snapName, _ := shared.InstanceGetParentAndSnapshotName(inst.Name())
 
-	// Get the snapshot name.
-	_, snapName, _ := shared.InstanceGetParentAndSnapshotName(inst.Name())
+	// Get the volume name on storage.
+	volStorageName := project.Prefix(inst.Project(), parentName)
 
 	return b.driver.MountVolumeSnapshot(volType, volStorageName, snapName, op)
 }
@@ -1486,11 +1486,11 @@ func (b *lxdBackend) UnmountInstanceSnapshot(inst instance.Instance, op *operati
 		return false, err
 	}
 
-	// Get the volume name on storage.
-	volStorageName := project.Prefix(inst.Project(), inst.Name())
+	// Get the parent and snapshot name.
+	parentName, snapName, _ := shared.InstanceGetParentAndSnapshotName(inst.Name())
 
-	// Get the snapshot name.
-	_, snapName, _ := shared.InstanceGetParentAndSnapshotName(inst.Name())
+	// Get the volume name on storage.
+	volStorageName := project.Prefix(inst.Project(), parentName)
 
 	return b.driver.UnmountVolumeSnapshot(volType, volStorageName, snapName, op)
 }

From 2087c449e1c9aba80eba1c89b113bd7d5990e2f4 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 5 Dec 2019 17:10:16 +0000
Subject: [PATCH 4/4] lxd/container/lxc: Links to new storage pkg

- Creates unexported mount/unmount functions the same as vmQemu (that are new storage pkg aware).
- Links StorageStart/StorageStop functions to them and marks functions as deprecated.
- Removes internal use of StorageStart/StorageStop (plan to eventually remove these once external uses are changed).
- Adds new storage pool loader and cache.
- Adds storage pool type function (that is new storage pkg aware), and updates usage.

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/container_lxc.go | 193 +++++++++++++++++++++++++++++++++----------
 1 file changed, 151 insertions(+), 42 deletions(-)

diff --git a/lxd/container_lxc.go b/lxd/container_lxc.go
index 3dc126200f..1185fd506e 100644
--- a/lxd/container_lxc.go
+++ b/lxd/container_lxc.go
@@ -541,7 +541,10 @@ type containerLXC struct {
 	idmapset *idmap.IdmapSet
 
 	// Storage
-	storage storage
+	// Do not use these variables directly, instead use their associated get functions so they
+	// will be initialised on demand.
+	storage     storage
+	storagePool storagePools.Pool
 
 	// Clustering
 	node string
@@ -2083,38 +2086,43 @@ func (c *containerLXC) startCommon() (string, []func() error, error) {
 		logger.Debugf("Container idmap changed, remapping")
 		c.updateProgress("Remapping container filesystem")
 
-		ourStart, err = c.StorageStart()
+		ourStart, err = c.mount()
 		if err != nil {
 			return "", postStartHooks, errors.Wrap(err, "Storage start")
 		}
 
+		storageType, err := c.getStorageType()
+		if err != nil {
+			return "", postStartHooks, errors.Wrap(err, "Storage type")
+		}
+
 		if diskIdmap != nil {
-			if c.Storage().GetStorageType() == storageTypeZfs {
+			if storageType == "zfs" {
 				err = diskIdmap.UnshiftRootfs(c.RootfsPath(), zfsIdmapSetSkipper)
-			} else if c.Storage().GetStorageType() == storageTypeBtrfs {
+			} else if storageType == "btrfs" {
 				err = UnshiftBtrfsRootfs(c.RootfsPath(), diskIdmap)
 			} else {
 				err = diskIdmap.UnshiftRootfs(c.RootfsPath(), nil)
 			}
 			if err != nil {
 				if ourStart {
-					c.StorageStop()
+					c.unmount()
 				}
 				return "", postStartHooks, err
 			}
 		}
 
 		if nextIdmap != nil && !c.state.OS.Shiftfs {
-			if c.Storage().GetStorageType() == storageTypeZfs {
+			if storageType == "zfs" {
 				err = nextIdmap.ShiftRootfs(c.RootfsPath(), zfsIdmapSetSkipper)
-			} else if c.Storage().GetStorageType() == storageTypeBtrfs {
+			} else if storageType == "btrfs" {
 				err = ShiftBtrfsRootfs(c.RootfsPath(), nextIdmap)
 			} else {
 				err = nextIdmap.ShiftRootfs(c.RootfsPath(), nil)
 			}
 			if err != nil {
 				if ourStart {
-					c.StorageStop()
+					c.unmount()
 				}
 				return "", postStartHooks, err
 			}
@@ -2327,7 +2335,7 @@ func (c *containerLXC) startCommon() (string, []func() error, error) {
 	}
 
 	// Storage is guaranteed to be mountable now (must be called after devices setup).
-	ourStart, err = c.StorageStart()
+	ourStart, err = c.mount()
 	if err != nil {
 		return "", postStartHooks, err
 	}
@@ -2344,7 +2352,7 @@ func (c *containerLXC) startCommon() (string, []func() error, error) {
 	currentIdmapset, err := c.CurrentIdmap()
 	if err != nil {
 		if ourStart {
-			c.StorageStop()
+			c.unmount()
 		}
 		return "", postStartHooks, err
 	}
@@ -2357,7 +2365,7 @@ func (c *containerLXC) startCommon() (string, []func() error, error) {
 	err = os.Chown(c.Path(), int(uid), 0)
 	if err != nil {
 		if ourStart {
-			c.StorageStop()
+			c.unmount()
 		}
 		return "", postStartHooks, err
 	}
@@ -2366,7 +2374,7 @@ func (c *containerLXC) startCommon() (string, []func() error, error) {
 	err = os.Chmod(c.Path(), 0100)
 	if err != nil {
 		if ourStart {
-			c.StorageStop()
+			c.unmount()
 		}
 		return "", postStartHooks, err
 	}
@@ -2375,7 +2383,7 @@ func (c *containerLXC) startCommon() (string, []func() error, error) {
 	err = writeBackupFile(c)
 	if err != nil {
 		if ourStart {
-			c.StorageStop()
+			c.unmount()
 		}
 		return "", postStartHooks, err
 	}
@@ -2437,7 +2445,7 @@ func (c *containerLXC) Start(stateful bool) error {
 	}
 
 	// Ensure that the container storage volume is mounted.
-	_, err = c.StorageStart()
+	_, err = c.mount()
 	if err != nil {
 		return errors.Wrap(err, "Storage start")
 	}
@@ -2581,7 +2589,7 @@ func (c *containerLXC) OnStart() error {
 	err = apparmor.LoadProfile(c)
 	if err != nil {
 		if ourStart {
-			c.StorageStop()
+			c.unmount()
 		}
 		return err
 	}
@@ -2594,7 +2602,7 @@ func (c *containerLXC) OnStart() error {
 		if err != nil {
 			apparmor.Destroy(c)
 			if ourStart {
-				c.StorageStop()
+				c.unmount()
 			}
 			return err
 		}
@@ -2604,7 +2612,7 @@ func (c *containerLXC) OnStart() error {
 		if err != nil {
 			apparmor.Destroy(c)
 			if ourStart {
-				c.StorageStop()
+				c.unmount()
 			}
 			return err
 		}
@@ -2614,7 +2622,7 @@ func (c *containerLXC) OnStart() error {
 	if err != nil {
 		apparmor.Destroy(c)
 		if ourStart {
-			c.StorageStop()
+			c.unmount()
 		}
 		return err
 	}
@@ -2905,7 +2913,7 @@ func (c *containerLXC) OnStop(target string) error {
 	}
 
 	// Stop the storage for this container
-	_, err = c.StorageStop()
+	_, err = c.unmount()
 	if err != nil {
 		if op != nil {
 			op.Done(err)
@@ -3342,12 +3350,12 @@ func (c *containerLXC) Restore(sourceContainer instance.Instance, stateful bool)
 			return err
 		}
 
-		ourStart, err := c.StorageStart()
+		ourStart, err := c.mount()
 		if err != nil {
 			return err
 		}
 		if ourStart {
-			defer c.StorageStop()
+			defer c.unmount()
 		}
 	}
 
@@ -3407,12 +3415,12 @@ func (c *containerLXC) Restore(sourceContainer instance.Instance, stateful bool)
 				defer pool.UnmountInstance(c, nil)
 			}
 		} else {
-			ourStart, err := c.StorageStart()
+			ourStart, err := c.mount()
 			if err != nil {
 				return err
 			}
 			if ourStart {
-				defer c.StorageStop()
+				defer c.unmount()
 			}
 		}
 	}
@@ -4885,13 +4893,13 @@ func (c *containerLXC) Export(w io.Writer, properties map[string]string) error {
 	logger.Info("Exporting container", ctxMap)
 
 	// Start the storage
-	ourStart, err := c.StorageStart()
+	ourStart, err := c.mount()
 	if err != nil {
 		logger.Error("Failed exporting container", ctxMap)
 		return err
 	}
 	if ourStart {
-		defer c.StorageStop()
+		defer c.unmount()
 	}
 
 	// Unshift the container
@@ -5231,20 +5239,25 @@ func (c *containerLXC) Migrate(args *CriuMigrationArgs) error {
 		}
 
 		if idmapset != nil {
-			ourStart, err := c.StorageStart()
+			ourStart, err := c.mount()
 			if err != nil {
 				return err
 			}
 
-			if c.Storage().GetStorageType() == storageTypeZfs {
+			storageType, err := c.getStorageType()
+			if err != nil {
+				return errors.Wrap(err, "Storage type")
+			}
+
+			if storageType == "zfs" {
 				err = idmapset.ShiftRootfs(args.stateDir, zfsIdmapSetSkipper)
-			} else if c.Storage().GetStorageType() == storageTypeBtrfs {
+			} else if storageType == "btrfs" {
 				err = ShiftBtrfsRootfs(args.stateDir, idmapset)
 			} else {
 				err = idmapset.ShiftRootfs(args.stateDir, nil)
 			}
 			if ourStart {
-				_, err2 := c.StorageStop()
+				_, err2 := c.unmount()
 				if err != nil {
 					return err
 				}
@@ -5514,7 +5527,7 @@ func (c *containerLXC) FileExists(path string) error {
 	var ourStart bool
 	var err error
 	if !c.IsRunning() {
-		ourStart, err = c.StorageStart()
+		ourStart, err = c.mount()
 		if err != nil {
 			return err
 		}
@@ -5533,7 +5546,7 @@ func (c *containerLXC) FileExists(path string) error {
 
 	// Tear down container storage if needed
 	if !c.IsRunning() && ourStart {
-		_, err := c.StorageStop()
+		_, err := c.unmount()
 		if err != nil {
 			return err
 		}
@@ -5562,7 +5575,7 @@ func (c *containerLXC) FilePull(srcpath string, dstpath string) (int64, int64, o
 	var err error
 	// Setup container storage if needed
 	if !c.IsRunning() {
-		ourStart, err = c.StorageStart()
+		ourStart, err = c.mount()
 		if err != nil {
 			return -1, -1, 0, "", nil, err
 		}
@@ -5582,7 +5595,7 @@ func (c *containerLXC) FilePull(srcpath string, dstpath string) (int64, int64, o
 
 	// Tear down container storage if needed
 	if !c.IsRunning() && ourStart {
-		_, err := c.StorageStop()
+		_, err := c.unmount()
 		if err != nil {
 			return -1, -1, 0, "", nil, err
 		}
@@ -5702,7 +5715,7 @@ func (c *containerLXC) FilePush(type_ string, srcpath string, dstpath string, ui
 	var err error
 	// Setup container storage if needed
 	if !c.IsRunning() {
-		ourStart, err = c.StorageStart()
+		ourStart, err = c.mount()
 		if err != nil {
 			return err
 		}
@@ -5735,7 +5748,7 @@ func (c *containerLXC) FilePush(type_ string, srcpath string, dstpath string, ui
 
 	// Tear down container storage if needed
 	if !c.IsRunning() && ourStart {
-		_, err := c.StorageStop()
+		_, err := c.unmount()
 		if err != nil {
 			return err
 		}
@@ -5777,7 +5790,7 @@ func (c *containerLXC) FileRemove(path string) error {
 
 	// Setup container storage if needed
 	if !c.IsRunning() {
-		ourStart, err = c.StorageStart()
+		ourStart, err = c.mount()
 		if err != nil {
 			return err
 		}
@@ -5796,7 +5809,7 @@ func (c *containerLXC) FileRemove(path string) error {
 
 	// Tear down container storage if needed
 	if !c.IsRunning() && ourStart {
-		_, err := c.StorageStop()
+		_, err := c.unmount()
 		if err != nil {
 			return err
 		}
@@ -6200,8 +6213,13 @@ func (c *containerLXC) processesState() int64 {
 	return int64(len(pids))
 }
 
-// Storage functions
+// Storage gets instance's legacy storage pool. Deprecated.
 func (c *containerLXC) Storage() storage {
+	return c.legacyStorage()
+}
+
+// legacyStorage returns the instance's legacy storage pool. Deprecated.
+func (c *containerLXC) legacyStorage() storage {
 	if c.storage == nil {
 		c.initStorage()
 	}
@@ -6209,9 +6227,70 @@ func (c *containerLXC) Storage() storage {
 	return c.storage
 }
 
+// getStoragePool returns the current storage pool handle. To avoid a DB lookup each time this
+// function is called, the handle is cached internally in the vmQemu struct.
+func (c *containerLXC) getStoragePool() (storagePools.Pool, error) {
+	if c.storagePool != nil {
+		return c.storagePool, nil
+	}
+
+	pool, err := storagePools.GetPoolByInstance(c.state, c)
+	if err != nil {
+		return nil, err
+	}
+	c.storagePool = pool
+
+	return c.storagePool, nil
+}
+
+// getStorageType returns the storage type of the instance's storage pool.
+func (c *containerLXC) getStorageType() (string, error) {
+	// Check if we can load new storage layer for pool driver type.
+	pool, err := c.getStoragePool()
+	if err != storageDrivers.ErrUnknownDriver && err != storageDrivers.ErrNotImplemented {
+		if err != nil {
+			return "", err
+		}
+
+		return pool.Driver().Info().Name, nil
+	}
+
+	return storageTypeToString(c.legacyStorage().GetStorageType())
+}
+
+// StorageStart mounts the instance's rootfs volume. Deprecated.
 func (c *containerLXC) StorageStart() (bool, error) {
-	// Initialize storage interface for the container.
-	err := c.initStorage()
+	return c.mount()
+}
+
+// mount the instance's rootfs volume if needed.
+func (c *containerLXC) mount() (bool, error) {
+	// Check if we can load new storage layer for pool driver type.
+	pool, err := c.getStoragePool()
+	if err != storageDrivers.ErrUnknownDriver && err != storageDrivers.ErrNotImplemented {
+		if err != nil {
+			return false, err
+		}
+
+		if c.IsSnapshot() {
+			ourMount, err := pool.MountInstanceSnapshot(c, nil)
+			if err != nil {
+				return false, err
+			}
+
+			return ourMount, nil
+		}
+
+		ourMount, err := pool.MountInstance(c, nil)
+		if err != nil {
+			return false, err
+		}
+
+		return ourMount, nil
+	}
+
+	// Initialize legacy storage interface for the container.
+	err = c.initStorage()
 	if err != nil {
 		return false, err
 	}
@@ -6243,9 +6322,39 @@ func (c *containerLXC) storageStartSensitive() (bool, error) {
 	return isOurOperation, err
 }
 
+// StorageStop unmounts the instance's rootfs volume. Deprecated.
 func (c *containerLXC) StorageStop() (bool, error) {
-	// Initialize storage interface for the container.
-	err := c.initStorage()
+	return c.unmount()
+}
+
+// unmount the instance's rootfs volume if needed.
+func (c *containerLXC) unmount() (bool, error) {
+	// Check if we can load new storage layer for pool driver type.
+	pool, err := c.getStoragePool()
+	if err != storageDrivers.ErrUnknownDriver && err != storageDrivers.ErrNotImplemented {
+		if err != nil {
+			return false, err
+		}
+
+		if c.IsSnapshot() {
+			unmounted, err := pool.UnmountInstanceSnapshot(c, nil)
+			if err != nil {
+				return false, err
+			}
+
+			return unmounted, nil
+		}
+
+		unmounted, err := pool.UnmountInstance(c, nil)
+		if err != nil {
+			return false, err
+		}
+
+		return unmounted, nil
+	}
+
+	// Initialize legacy storage interface for the container.
+	err = c.initStorage()
 	if err != nil {
 		return false, err
 	}


More information about the lxc-devel mailing list