[lxc-devel] [lxd/master] patches: upgrade from LVM LXD instance with DIR containers
brauner on Github
lxc-bot at linuxcontainers.org
Tue Mar 7 15:02:16 UTC 2017
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 301 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20170307/058982a2/attachment.bin>
-------------- next part --------------
From 671166d83b3567b310084dd43314dff7b65cfa95 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Tue, 7 Mar 2017 12:44:44 +0100
Subject: [PATCH 1/2] lvm: dumb down functions from methods to functions
This way we can call them from other places as well.
Closes #3026.
Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
lxd/storage_lvm.go | 137 ++++++++++++++++++++++++++++++-----------------------
1 file changed, 79 insertions(+), 58 deletions(-)
diff --git a/lxd/storage_lvm.go b/lxd/storage_lvm.go
index 75b767c..25a44dd 100644
--- a/lxd/storage_lvm.go
+++ b/lxd/storage_lvm.go
@@ -391,8 +391,8 @@ func versionSplit(versionString string) (int, int, int, error) {
return maj, min, inc, nil
}
-func (s *storageLvm) lvmVersionIsAtLeast(versionString string) (bool, error) {
- lvmVersion := strings.Split(s.sTypeVersion, "/")[0]
+func lvmVersionIsAtLeast(sTypeVersion string, versionString string) (bool, error) {
+ lvmVersion := strings.Split(sTypeVersion, "/")[0]
lvmMaj, lvmMin, lvmInc, err := versionSplit(lvmVersion)
if err != nil {
@@ -716,7 +716,12 @@ func (s *storageLvm) StoragePoolVolumeCreate() error {
return err
}
- err = s.createThinLV(poolName, thinPoolName, s.volume.Name, lvFsType, lvSize, volumeType)
+ err = lvmCreateThinpool(s.d, s.sTypeVersion, poolName, thinPoolName, lvFsType)
+ if err != nil {
+ return err
+ }
+
+ err = lvmCreateThinLV(poolName, thinPoolName, s.volume.Name, lvFsType, lvSize, volumeType)
if err != nil {
shared.LogErrorf("LVMCreateThinLV: %s.", err)
return fmt.Errorf("Error Creating LVM LV for new image: %v", err)
@@ -1028,7 +1033,12 @@ func (s *storageLvm) ContainerCreate(container container) error {
}
poolName := s.getOnDiskPoolName()
- err = s.createThinLV(poolName, thinPoolName, containerLvmName, lvFsType, lvSize, storagePoolVolumeApiEndpointContainers)
+ err = lvmCreateThinpool(s.d, s.sTypeVersion, poolName, thinPoolName, lvFsType)
+ if err != nil {
+ return err
+ }
+
+ err = lvmCreateThinLV(poolName, thinPoolName, containerLvmName, lvFsType, lvSize, storagePoolVolumeApiEndpointContainers)
if err != nil {
return err
}
@@ -1741,7 +1751,12 @@ func (s *storageLvm) ImageCreate(fingerprint string) error {
}
}()
- err = s.createThinLV(poolName, thinPoolName, fingerprint, lvFsType, lvSize, storagePoolVolumeApiEndpointImages)
+ err = lvmCreateThinpool(s.d, s.sTypeVersion, poolName, thinPoolName, lvFsType)
+ if err != nil {
+ return err
+ }
+
+ err = lvmCreateThinLV(poolName, thinPoolName, fingerprint, lvFsType, lvSize, storagePoolVolumeApiEndpointImages)
if err != nil {
shared.LogErrorf("LVMCreateThinLV: %s.", err)
return fmt.Errorf("Error Creating LVM LV for new image: %v", err)
@@ -1856,25 +1871,72 @@ func (s *storageLvm) ImageUmount(fingerprint string) (bool, error) {
return true, nil
}
-func (s *storageLvm) createThinLV(vgName string, thinPoolName string, lvName string, lvFsType string, lvSize string, volumeType string) error {
- exists, err := storageLVMThinpoolExists(vgName, thinPoolName)
+func createDefaultThinPool(sTypeVersion string, vgName string, thinPoolName string, lvFsType string) error {
+ isRecent, err := lvmVersionIsAtLeast(sTypeVersion, "2.02.99")
if err != nil {
- return err
+ return fmt.Errorf("Error checking LVM version: %s", err)
}
- if !exists {
- err := s.createDefaultThinPool(vgName, thinPoolName, lvName, lvFsType)
- if err != nil {
- return err
- }
+ // Create the thin pool
+ lvmThinPool := fmt.Sprintf("%s/%s", vgName, thinPoolName)
+ var output []byte
+ if isRecent {
+ output, err = tryExec(
+ "lvcreate",
+ "--poolmetadatasize", "1G",
+ "-l", "100%FREE",
+ "--thinpool", lvmThinPool)
+ } else {
+ output, err = tryExec(
+ "lvcreate",
+ "--poolmetadatasize", "1G",
+ "-L", "1G",
+ "--thinpool", lvmThinPool)
+ }
+
+ if err != nil {
+ shared.LogErrorf("Could not create thin pool \"%s\": %s.", thinPoolName, string(output))
+ return fmt.Errorf("Could not create LVM thin pool named %s", thinPoolName)
+ }
+
+ if !isRecent {
+ // Grow it to the maximum VG size (two step process required by old LVM)
+ output, err = tryExec("lvextend", "--alloc", "anywhere", "-l", "100%FREE", lvmThinPool)
- err = storageLVMValidateThinPoolName(s.d, vgName, thinPoolName)
if err != nil {
- shared.LogErrorf("Setting thin pool name: %s.", err)
- return fmt.Errorf("Error setting LVM thin pool config: %v", err)
+ shared.LogErrorf("Could not grow thin pool: \"%s\": %s.", thinPoolName, string(output))
+ return fmt.Errorf("Could not grow LVM thin pool named %s", thinPoolName)
}
}
+ return nil
+}
+
+func lvmCreateThinpool(d *Daemon, sTypeVersion string, vgName string, thinPoolName string, lvFsType string) error {
+ exists, err := storageLVMThinpoolExists(vgName, thinPoolName)
+ if err != nil {
+ return err
+ }
+
+ if exists {
+ return nil
+ }
+
+ err = createDefaultThinPool(sTypeVersion, vgName, thinPoolName, lvFsType)
+ if err != nil {
+ return err
+ }
+
+ err = storageLVMValidateThinPoolName(d, vgName, thinPoolName)
+ if err != nil {
+ shared.LogErrorf("Setting thin pool name: %s.", err)
+ return fmt.Errorf("Error setting LVM thin pool config: %v", err)
+ }
+
+ return nil
+}
+
+func lvmCreateThinLV(vgName string, thinPoolName string, lvName string, lvFsType string, lvSize string, volumeType string) error {
lvmThinPoolPath := fmt.Sprintf("%s/%s", vgName, thinPoolName)
lvmPoolVolumeName := getPrefixedLvName(volumeType, lvName)
output, err := tryExec(
@@ -1907,47 +1969,6 @@ func (s *storageLvm) createThinLV(vgName string, thinPoolName string, lvName str
return nil
}
-func (s *storageLvm) createDefaultThinPool(vgName string, thinPoolName string, lvName string, lvFsType string) error {
- isRecent, err := s.lvmVersionIsAtLeast("2.02.99")
- if err != nil {
- return fmt.Errorf("Error checking LVM version: %s", err)
- }
-
- // Create the thin pool
- lvmThinPool := fmt.Sprintf("%s/%s", vgName, thinPoolName)
- var output []byte
- if isRecent {
- output, err = tryExec(
- "lvcreate",
- "--poolmetadatasize", "1G",
- "-l", "100%FREE",
- "--thinpool", lvmThinPool)
- } else {
- output, err = tryExec(
- "lvcreate",
- "--poolmetadatasize", "1G",
- "-L", "1G",
- "--thinpool", lvmThinPool)
- }
-
- if err != nil {
- shared.LogErrorf("Could not create thin pool \"%s\": %s.", thinPoolName, string(output))
- return fmt.Errorf("Could not create LVM thin pool named %s", thinPoolName)
- }
-
- if !isRecent {
- // Grow it to the maximum VG size (two step process required by old LVM)
- output, err = tryExec("lvextend", "--alloc", "anywhere", "-l", "100%FREE", lvmThinPool)
-
- if err != nil {
- shared.LogErrorf("Could not grow thin pool: \"%s\": %s.", thinPoolName, string(output))
- return fmt.Errorf("Could not grow LVM thin pool named %s", thinPoolName)
- }
- }
-
- return nil
-}
-
func (s *storageLvm) removeLV(vgName string, volumeType string, lvName string) error {
lvmVolumePath := getLvmDevPath(vgName, volumeType, lvName)
output, err := tryExec("lvremove", "-f", lvmVolumePath)
@@ -1963,7 +1984,7 @@ func (s *storageLvm) removeLV(vgName string, volumeType string, lvName string) e
func (s *storageLvm) createSnapshotLV(vgName string, origLvName string, origVolumeType string, lvName string, volumeType string, readonly bool) (string, error) {
sourceLvmVolumePath := getLvmDevPath(vgName, origVolumeType, origLvName)
shared.LogDebugf("in createSnapshotLV: %s.", sourceLvmVolumePath)
- isRecent, err := s.lvmVersionIsAtLeast("2.02.99")
+ isRecent, err := lvmVersionIsAtLeast(s.sTypeVersion, "2.02.99")
if err != nil {
return "", fmt.Errorf("Error checking LVM version: %v", err)
}
From aa2fe123504b0e432897dc768aea06769822b5d9 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Tue, 7 Mar 2017 15:43:59 +0100
Subject: [PATCH 2/2] patches: handle mixed-storage <lvm,dir> upgrade
Handle the case where we have a LVM upgrade that has DIR containers.
Closes #3026.
Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
lxd/patches.go | 230 ++++++++++++++++++++++++++++++++++++++++++-----------
lxd/storage_lvm.go | 7 ++
2 files changed, 191 insertions(+), 46 deletions(-)
diff --git a/lxd/patches.go b/lxd/patches.go
index 369860b..d522fc6 100644
--- a/lxd/patches.go
+++ b/lxd/patches.go
@@ -827,7 +827,15 @@ func upgradeFromStorageTypeLvm(name string, d *Daemon, defaultPoolName string, d
poolConfig["volume.block.mount_options"] = fsMntOpts
}
+ thinPoolName := "LXDPool"
poolConfig["lvm.thinpool_name"] = daemonConfig["storage.lvm_thinpool_name"].Get()
+ if poolConfig["lvm.thinpool_name"] != "" {
+ thinPoolName = poolConfig["lvm.thinpool_name"]
+ } else {
+ // If empty we need to set it to the old default.
+ poolConfig["lvm.thinpool_name"] = thinPoolName
+ }
+
poolConfig["lvm.vg_name"] = daemonConfig["storage.lvm_vg_name"].Get()
poolConfig["volume.size"] = daemonConfig["storage.lvm_volume_size"].Get()
@@ -897,6 +905,7 @@ func upgradeFromStorageTypeLvm(name string, d *Daemon, defaultPoolName string, d
return err
}
+ // Create pool mountpoint if it doesn't already exist.
poolMntPoint := getStoragePoolMountPoint(defaultPoolName)
if !shared.PathExists(poolMntPoint) {
err = os.MkdirAll(poolMntPoint, 0711)
@@ -906,6 +915,7 @@ func upgradeFromStorageTypeLvm(name string, d *Daemon, defaultPoolName string, d
}
if len(cRegular) > 0 {
+ // Create generic containers folder on the storage pool.
newContainersMntPoint := getContainerMountPoint(defaultPoolName, "")
if !shared.PathExists(newContainersMntPoint) {
err = os.MkdirAll(newContainersMntPoint, 0711)
@@ -955,6 +965,7 @@ func upgradeFromStorageTypeLvm(name string, d *Daemon, defaultPoolName string, d
if shared.IsMountPoint(oldContainerMntPoint) {
err := tryUnmount(oldContainerMntPoint, syscall.MNT_DETACH)
if err != nil {
+ shared.LogErrorf("Failed to unmount LVM logical volume \"%s\": %s.", oldContainerMntPoint, err)
return err
}
}
@@ -963,28 +974,91 @@ func upgradeFromStorageTypeLvm(name string, d *Daemon, defaultPoolName string, d
// new storage api. We do os.Rename() here to preserve
// permissions and ownership.
newContainerMntPoint := getContainerMountPoint(defaultPoolName, ct)
- if shared.PathExists(oldContainerMntPoint) && !shared.PathExists(newContainerMntPoint) {
- err = os.Rename(oldContainerMntPoint, newContainerMntPoint)
- if err != nil {
- return err
- }
- }
-
- if shared.PathExists(oldContainerMntPoint + ".lv") {
- err := os.Remove(oldContainerMntPoint + ".lv")
- if err != nil {
- return err
- }
- }
-
- // Rename the logical volume device.
ctLvName := containerNameToLVName(ct)
newContainerLvName := fmt.Sprintf("%s_%s", storagePoolVolumeApiEndpointContainers, ctLvName)
containerLvDevPath := getLvmDevPath(defaultPoolName, storagePoolVolumeApiEndpointContainers, ctLvName)
if !shared.PathExists(containerLvDevPath) {
- _, err := tryExec("lvrename", defaultPoolName, ctLvName, newContainerLvName)
- if err != nil {
- return err
+ oldLvDevPath := fmt.Sprintf("/dev/%s/%s", defaultPoolName, ctLvName)
+ // If the old LVM device path for the logical volume
+ // exists we call lvrename. Otherwise this is likely a
+ // mixed-storage LXD instance which we need to deal
+ // with.
+ if shared.PathExists(oldLvDevPath) {
+ // Rename the logical volume mountpoint.
+ if shared.PathExists(oldContainerMntPoint) && !shared.PathExists(newContainerMntPoint) {
+ err = os.Rename(oldContainerMntPoint, newContainerMntPoint)
+ if err != nil {
+ shared.LogErrorf("Failed to rename LVM container mountpoint from %s to %s: %s.", oldContainerMntPoint, newContainerMntPoint, err)
+ return err
+ }
+ }
+
+ // Remove the old container mountpoint.
+ if shared.PathExists(oldContainerMntPoint + ".lv") {
+ err := os.Remove(oldContainerMntPoint + ".lv")
+ if err != nil {
+ shared.LogErrorf("Failed to remove old LVM container mountpoint %s: %s.", oldContainerMntPoint+".lv", err)
+ return err
+ }
+ }
+
+ // Rename the logical volume.
+ msg, err := tryExec("lvrename", defaultPoolName, ctLvName, newContainerLvName)
+ if err != nil {
+ shared.LogErrorf("Failed to rename LVM logical volume from %s to %s: %s.", ctLvName, newContainerLvName, msg)
+ return err
+ }
+ } else if shared.PathExists(oldContainerMntPoint) && shared.IsDir(oldContainerMntPoint) {
+ // This is a directory backed container and it
+ // means that this was a mixed-storage LXD
+ // instance.
+
+ // Initialize storage interface for the new
+ // container.
+ ctStorage, err := storagePoolVolumeContainerLoadInit(d, ct)
+ if err != nil {
+ shared.LogErrorf("Failed to initialize new storage interface for LVM container %s: %s.", ct, err)
+ return err
+ }
+
+ // Load the container from the database.
+ ctStruct, err := containerLoadByName(d, ct)
+ if err != nil {
+ shared.LogErrorf("Failed to load LVM container %s: %s.", ct, err)
+ return err
+ }
+
+ // Create an empty LVM logical volume for the
+ // container.
+ err = ctStorage.ContainerCreate(ctStruct)
+ if err != nil {
+ shared.LogErrorf("Failed to create empty LVM logical volume for container %s: %s.", ct, err)
+ return err
+ }
+
+ // In case the new LVM logical volume for the
+ // container is not mounted mount it.
+ if !shared.IsMountPoint(newContainerMntPoint) {
+ _, err = ctStorage.ContainerMount(ctStruct.Name(), ctStruct.Path())
+ if err != nil {
+ shared.LogErrorf("Failed to mount new empty LVM logical volume for container %s: %s.", ct, err)
+ return err
+ }
+ }
+
+ // Use rsync to fill the empty volume.
+ output, err := storageRsyncCopy(oldContainerMntPoint, newContainerMntPoint)
+ if err != nil {
+ ctStorage.ContainerDelete(ctStruct)
+ return fmt.Errorf("rsync failed: %s", string(output))
+ }
+
+ // Remove the old container.
+ err = os.RemoveAll(oldContainerMntPoint)
+ if err != nil {
+ shared.LogErrorf("Failed to remove old container %s: %s.", oldContainerMntPoint, err)
+ return err
+ }
}
}
@@ -992,6 +1066,7 @@ func upgradeFromStorageTypeLvm(name string, d *Daemon, defaultPoolName string, d
doesntMatter := false
err = createContainerMountpoint(newContainerMntPoint, oldContainerMntPoint, doesntMatter)
if err != nil {
+ shared.LogErrorf("Failed to create container mountpoint \"%s\" for LVM logical volume: %s.", newContainerMntPoint, err)
return err
}
@@ -1003,13 +1078,6 @@ func upgradeFromStorageTypeLvm(name string, d *Daemon, defaultPoolName string, d
mountOptions = "discard"
}
- if !shared.IsMountPoint(newContainerMntPoint) {
- err := tryMount(containerLvDevPath, newContainerMntPoint, lvFsType, 0, mountOptions)
- if err != nil {
- return err
- }
- }
-
// Check if we need to account for snapshots for this container.
ctSnapshots, err := dbContainerGetSnapshots(d.db, ct)
if err != nil {
@@ -1058,24 +1126,7 @@ func upgradeFromStorageTypeLvm(name string, d *Daemon, defaultPoolName string, d
}
}
- // Unmount the logical volume.
oldSnapshotMntPoint := shared.VarPath("snapshots", cs)
- if shared.IsMountPoint(oldSnapshotMntPoint) {
- err := tryUnmount(oldSnapshotMntPoint, syscall.MNT_DETACH)
- if err != nil {
- return err
- }
- }
-
- // Rename the snapshot mountpoint to preserve acl's and
- // so on.
- if shared.PathExists(oldSnapshotMntPoint) && !shared.PathExists(newSnapshotMntPoint) {
- err := os.Rename(oldSnapshotMntPoint, newSnapshotMntPoint)
- if err != nil {
- return err
- }
- }
-
os.Remove(oldSnapshotMntPoint + ".lv")
// Make sure we use a valid lv name.
@@ -1083,9 +1134,85 @@ func upgradeFromStorageTypeLvm(name string, d *Daemon, defaultPoolName string, d
newSnapshotLvName := fmt.Sprintf("%s_%s", storagePoolVolumeApiEndpointContainers, csLvName)
snapshotLvDevPath := getLvmDevPath(defaultPoolName, storagePoolVolumeApiEndpointContainers, csLvName)
if !shared.PathExists(snapshotLvDevPath) {
- _, err := tryExec("lvrename", defaultPoolName, csLvName, newSnapshotLvName)
- if err != nil {
- return err
+ oldLvDevPath := fmt.Sprintf("/dev/%s/%s", defaultPoolName, csLvName)
+ if shared.PathExists(oldLvDevPath) {
+ // Unmount the logical volume.
+ if shared.IsMountPoint(oldSnapshotMntPoint) {
+ err := tryUnmount(oldSnapshotMntPoint, syscall.MNT_DETACH)
+ if err != nil {
+ shared.LogErrorf("Failed to unmount LVM logical volume \"%s\": %s.", oldSnapshotMntPoint, err)
+ return err
+ }
+ }
+
+ // Rename the snapshot mountpoint to preserve acl's and
+ // so on.
+ if shared.PathExists(oldSnapshotMntPoint) && !shared.PathExists(newSnapshotMntPoint) {
+ err := os.Rename(oldSnapshotMntPoint, newSnapshotMntPoint)
+ if err != nil {
+ shared.LogErrorf("Failed to rename LVM container mountpoint from %s to %s: %s.", oldSnapshotMntPoint, newSnapshotMntPoint, err)
+ return err
+ }
+ }
+
+ // Rename the logical volume.
+ msg, err := tryExec("lvrename", defaultPoolName, csLvName, newSnapshotLvName)
+ if err != nil {
+ shared.LogErrorf("Failed to rename LVM logical volume from %s to %s: %s.", csLvName, newSnapshotLvName, msg)
+ return err
+ }
+ } else if shared.PathExists(oldSnapshotMntPoint) && shared.IsDir(oldSnapshotMntPoint) {
+ // This is a directory backed container
+ // and it means that this was a
+ // mixed-storage LXD instance.
+
+ // Initialize storage interface for the new
+ // snapshot.
+ csStorage, err := storagePoolVolumeContainerLoadInit(d, cs)
+ if err != nil {
+ shared.LogErrorf("Failed to initialize new storage interface for LVM container %s: %s.", cs, err)
+ return err
+ }
+
+ // Load the snapshot from the database.
+ csStruct, err := containerLoadByName(d, cs)
+ if err != nil {
+ shared.LogErrorf("Failed to load LVM container %s: %s.", cs, err)
+ return err
+ }
+
+ // Create an empty LVM logical volume
+ // for the snapshot.
+ err = csStorage.ContainerSnapshotCreateEmpty(csStruct)
+ if err != nil {
+ shared.LogErrorf("Failed to create empty LVM logical volume for container %s: %s.", cs, err)
+ return err
+ }
+
+ // In case the new LVM logical volume
+ // for the snapshot is not mounted mount
+ // it.
+ if !shared.IsMountPoint(newSnapshotMntPoint) {
+ _, err = csStorage.ContainerMount(csStruct.Name(), csStruct.Path())
+ if err != nil {
+ shared.LogErrorf("Failed to mount new empty LVM logical volume for container %s: %s.", cs, err)
+ return err
+ }
+ }
+
+ // Use rsync to fill the empty volume.
+ output, err := storageRsyncCopy(oldSnapshotMntPoint, newSnapshotMntPoint)
+ if err != nil {
+ csStorage.ContainerDelete(csStruct)
+ return fmt.Errorf("rsync failed: %s", string(output))
+ }
+
+ // Remove the old snapshot.
+ err = os.RemoveAll(oldSnapshotMntPoint)
+ if err != nil {
+ shared.LogErrorf("Failed to remove old container %s: %s.", oldSnapshotMntPoint, err)
+ return err
+ }
}
}
}
@@ -1113,6 +1240,13 @@ func upgradeFromStorageTypeLvm(name string, d *Daemon, defaultPoolName string, d
}
}
+ if !shared.IsMountPoint(newContainerMntPoint) {
+ err := tryMount(containerLvDevPath, newContainerMntPoint, lvFsType, 0, mountOptions)
+ if err != nil {
+ shared.LogErrorf("Failed to mount LVM logical \"%s\" onto \"%s\" : %s.", containerLvDevPath, newContainerMntPoint, err)
+ return err
+ }
+ }
}
images := append(imgPublic, imgPrivate...)
@@ -1179,7 +1313,11 @@ func upgradeFromStorageTypeLvm(name string, d *Daemon, defaultPoolName string, d
// Rename the logical volume device.
newImageLvName := fmt.Sprintf("%s_%s", storagePoolVolumeApiEndpointImages, img)
imageLvDevPath := getLvmDevPath(defaultPoolName, storagePoolVolumeApiEndpointImages, img)
- if !shared.PathExists(imageLvDevPath) {
+ oldLvDevPath := fmt.Sprintf("/dev/%s/%s", defaultPoolName, img)
+ // Only create logical volumes for images that have a logical
+ // volume on the pre-storage-api LXD instance. If not, we don't
+ // care since LXD will create a logical volume on demand.
+ if !shared.PathExists(imageLvDevPath) && shared.PathExists(oldLvDevPath) {
_, err := tryExec("lvrename", defaultPoolName, img, newImageLvName)
if err != nil {
return err
diff --git a/lxd/storage_lvm.go b/lxd/storage_lvm.go
index 25a44dd..388deb3 100644
--- a/lxd/storage_lvm.go
+++ b/lxd/storage_lvm.go
@@ -1321,7 +1321,11 @@ func (s *storageLvm) ContainerMount(name string, path string) (bool, error) {
poolName := s.getOnDiskPoolName()
containerLvmPath := getLvmDevPath(poolName, storagePoolVolumeApiEndpointContainers, containerLvmName)
mountOptions := s.getLvmBlockMountOptions()
+
containerMntPoint := getContainerMountPoint(s.pool.Name, name)
+ if shared.IsSnapshot(name) {
+ containerMntPoint = getSnapshotMountPoint(s.pool.Name, name)
+ }
containerMountLockID := getContainerMountLockID(s.pool.Name, name)
lxdStorageMapLock.Lock()
@@ -1364,6 +1368,9 @@ func (s *storageLvm) ContainerUmount(name string, path string) (bool, error) {
shared.LogDebugf("Unmounting LVM storage volume for container \"%s\" on storage pool \"%s\".", s.volume.Name, s.pool.Name)
containerMntPoint := getContainerMountPoint(s.pool.Name, name)
+ if shared.IsSnapshot(name) {
+ containerMntPoint = getSnapshotMountPoint(s.pool.Name, name)
+ }
containerUmountLockID := getContainerUmountLockID(s.pool.Name, name)
lxdStorageMapLock.Lock()
More information about the lxc-devel
mailing list