[lxc-devel] [lxd/master] lxd/storage: Port volume attach/detach
stgraber on Github
lxc-bot at linuxcontainers.org
Thu Dec 12 01:06:51 UTC 2019
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 354 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20191211/e16c9091/attachment.bin>
-------------- next part --------------
From 63f1dea8ceb0dc8d265b32def4c07522a554545d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Fri, 6 Dec 2019 00:59:34 -0500
Subject: [PATCH] lxd/storage: Port volume attach/detach
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
lxd/storage.go | 148 +++++++++++++++++++++++++++++--------------------
1 file changed, 89 insertions(+), 59 deletions(-)
diff --git a/lxd/storage.go b/lxd/storage.go
index 86ad48d88a..842ee72577 100644
--- a/lxd/storage.go
+++ b/lxd/storage.go
@@ -33,11 +33,12 @@ import (
func init() {
// Expose storageVolumeMount to the device package as StorageVolumeMount.
device.StorageVolumeMount = storageVolumeMount
+
// Expose storageVolumeUmount to the device package as StorageVolumeUmount.
device.StorageVolumeUmount = storageVolumeUmount
+
// Expose storageRootFSApplyQuota to the device package as StorageRootFSApplyQuota.
device.StorageRootFSApplyQuota = storageRootFSApplyQuota
-
}
// lxdStorageLockMap is a hashmap that allows functions to check whether the
@@ -413,18 +414,24 @@ func storagePoolInit(s *state.State, poolName string) (storage, error) {
return storageInit(s, "default", poolName, "", -1)
}
-func storagePoolVolumeAttachInit(s *state.State, poolName string, volumeName string, volumeType int, c *containerLXC) (storage, error) {
- st, err := storageInit(s, "default", poolName, volumeName, volumeType)
+func storagePoolVolumeAttachPrepare(s *state.State, poolName string, volumeName string, volumeType int, c *containerLXC) error {
+ // Load the DB records
+ poolID, pool, err := s.Cluster.StoragePoolGet(poolName)
if err != nil {
- return nil, err
+ return err
}
- poolVolumePut := st.GetStoragePoolVolumeWritable()
+ _, volume, err := s.Cluster.StoragePoolNodeVolumeGetTypeByProject("default", volumeName, volumeType, poolID)
+ if err != nil {
+ return err
+ }
+
+ poolVolumePut := volume.Writable()
// Check if unmapped
if shared.IsTrue(poolVolumePut.Config["security.unmapped"]) {
// No need to look at containers and maps for unmapped volumes
- return st, nil
+ return nil
}
// Get the on-disk idmap for the volume
@@ -433,7 +440,7 @@ func storagePoolVolumeAttachInit(s *state.State, poolName string, volumeName str
lastIdmap, err = idmapsetFromString(poolVolumePut.Config["volatile.idmap.last"])
if err != nil {
logger.Errorf("Failed to unmarshal last idmapping: %s", poolVolumePut.Config["volatile.idmap.last"])
- return nil, err
+ return err
}
}
@@ -447,19 +454,19 @@ func storagePoolVolumeAttachInit(s *state.State, poolName string, volumeName str
nextIdmap, err = c.NextIdmap()
}
if err != nil {
- return nil, err
+ return err
}
if nextIdmap != nil {
nextJsonMap, err = idmapsetToJSON(nextIdmap)
if err != nil {
- return nil, err
+ return err
}
}
}
poolVolumePut.Config["volatile.idmap.next"] = nextJsonMap
- // get mountpoint of storage volume
+ // Get mountpoint of storage volume
remapPath := storagePools.GetStoragePoolVolumeMountPoint(poolName, volumeName)
if !nextIdmap.Equals(lastIdmap) {
@@ -468,7 +475,7 @@ func storagePoolVolumeAttachInit(s *state.State, poolName string, volumeName str
if !shared.IsTrue(poolVolumePut.Config["security.shifted"]) {
volumeUsedBy, err := storagePoolVolumeUsedByInstancesGet(s, "default", poolName, volumeName)
if err != nil {
- return nil, err
+ return err
}
if len(volumeUsedBy) > 1 {
@@ -491,11 +498,11 @@ func storagePoolVolumeAttachInit(s *state.State, poolName string, volumeName str
ctNextIdmap, err = ct.NextIdmap()
}
if err != nil {
- return nil, fmt.Errorf("Failed to retrieve idmap of container")
+ return fmt.Errorf("Failed to retrieve idmap of container")
}
if !nextIdmap.Equals(ctNextIdmap) {
- return nil, fmt.Errorf("Idmaps of container %v and storage volume %v are not identical", ctName, volumeName)
+ return fmt.Errorf("Idmaps of container %v and storage volume %v are not identical", ctName, volumeName)
}
}
} else if len(volumeUsedBy) == 1 {
@@ -503,54 +510,44 @@ func storagePoolVolumeAttachInit(s *state.State, poolName string, volumeName str
// we can shift the storage volume.
// I'm not sure if we want some locking here.
if volumeUsedBy[0] != c.Name() {
- return nil, fmt.Errorf("idmaps of container and storage volume are not identical")
+ return fmt.Errorf("idmaps of container and storage volume are not identical")
}
}
}
- // mount storage volume
- ourMount, err := st.StoragePoolVolumeMount()
- if err != nil {
- return nil, err
- }
- if ourMount {
- defer func() {
- _, err := st.StoragePoolVolumeUmount()
- if err != nil {
- logger.Warnf("Failed to unmount storage volume")
- }
- }()
- }
-
- // unshift rootfs
+ // Unshift rootfs
if lastIdmap != nil {
var err error
- if st.GetStorageType() == storageTypeZfs {
+ if pool.Driver == "zfs" {
err = lastIdmap.UnshiftRootfs(remapPath, zfsIdmapSetSkipper)
} else {
err = lastIdmap.UnshiftRootfs(remapPath, nil)
}
+
if err != nil {
logger.Errorf("Failed to unshift \"%s\"", remapPath)
- return nil, err
+ return err
}
+
logger.Debugf("Unshifted \"%s\"", remapPath)
}
- // shift rootfs
+ // Shift rootfs
if nextIdmap != nil {
var err error
- if st.GetStorageType() == storageTypeZfs {
+ if pool.Driver == "zfs" {
err = nextIdmap.ShiftRootfs(remapPath, zfsIdmapSetSkipper)
} else {
err = nextIdmap.ShiftRootfs(remapPath, nil)
}
+
if err != nil {
logger.Errorf("Failed to shift \"%s\"", remapPath)
- return nil, err
+ return err
}
+
logger.Debugf("Shifted \"%s\"", remapPath)
}
logger.Debugf("Shifted storage volume")
@@ -562,25 +559,19 @@ func storagePoolVolumeAttachInit(s *state.State, poolName string, volumeName str
jsonIdmap, err = idmapsetToJSON(nextIdmap)
if err != nil {
logger.Errorf("Failed to marshal idmap")
- return nil, err
+ return err
}
}
- // update last idmap
+ // Update last idmap
poolVolumePut.Config["volatile.idmap.last"] = jsonIdmap
- st.SetStoragePoolVolumeWritable(&poolVolumePut)
-
- poolID, err := s.Cluster.StoragePoolGetID(poolName)
- if err != nil {
- return nil, err
- }
err = s.Cluster.StoragePoolVolumeUpdate(volumeName, volumeType, poolID, poolVolumePut.Description, poolVolumePut.Config)
if err != nil {
- return nil, err
+ return err
}
- return st, nil
+ return nil
}
func storagePoolVolumeInit(s *state.State, project, poolName, volumeName string, volumeType int) (storage, error) {
@@ -834,14 +825,45 @@ func storageVolumeMount(state *state.State, poolName string, volumeName string,
}
volumeType, _ := storagePools.VolumeTypeNameToType(volumeTypeName)
- s, err := storagePoolVolumeAttachInit(state, poolName, volumeName, volumeType, c)
- if err != nil {
- return err
- }
+ pool, err := storagePools.GetPoolByName(state, poolName)
+ if err != storageDrivers.ErrUnknownDriver && err != storageDrivers.ErrNotImplemented {
+ // Mount the storage volume
+ ourMount, err := pool.MountCustomVolume(volumeName, nil)
+ if err != nil {
+ return err
+ }
- _, err = s.StoragePoolVolumeMount()
- if err != nil {
- return err
+ if ourMount {
+ defer pool.UnmountCustomVolume(volumeName, nil)
+ }
+
+ // Custom storage volumes do not currently support projects, so hardcode "default" project.
+ err = storagePoolVolumeAttachPrepare(state, poolName, volumeName, volumeType, c)
+ if err != nil {
+ return err
+ }
+ } else {
+ // Load the volume
+ s, err := storageInit(state, "default", poolName, volumeName, volumeType)
+ if err != nil {
+ return err
+ }
+
+ // Mount the storage volume
+ ourMount, err := s.StoragePoolVolumeMount()
+ if err != nil {
+ return err
+ }
+
+ if ourMount {
+ defer s.StoragePoolVolumeUmount()
+ }
+
+ // Custom storage volumes do not currently support projects, so hardcode "default" project.
+ err = storagePoolVolumeAttachPrepare(state, poolName, volumeName, volumeType, c)
+ if err != nil {
+ return err
+ }
}
return nil
@@ -849,15 +871,23 @@ func storageVolumeMount(state *state.State, poolName string, volumeName string,
// storageVolumeUmount unmounts a storage volume on a pool.
func storageVolumeUmount(state *state.State, poolName string, volumeName string, volumeType int) error {
- // Custom storage volumes do not currently support projects, so hardcode "default" project.
- s, err := storagePoolVolumeInit(state, "default", poolName, volumeName, volumeType)
- if err != nil {
- return err
- }
+ pool, err := storagePools.GetPoolByName(state, poolName)
+ if err != storageDrivers.ErrUnknownDriver && err != storageDrivers.ErrNotImplemented {
+ _, err = pool.UnmountCustomVolume(volumeName, nil)
+ if err != nil {
+ return err
+ }
+ } else {
+ // Custom storage volumes do not currently support projects, so hardcode "default" project.
+ s, err := storagePoolVolumeInit(state, "default", poolName, volumeName, volumeType)
+ if err != nil {
+ return err
+ }
- _, err = s.StoragePoolVolumeUmount()
- if err != nil {
- return err
+ _, err = s.StoragePoolVolumeUmount()
+ if err != nil {
+ return err
+ }
}
return nil
More information about the lxc-devel
mailing list