The following pull request was submitted through Github.
It can be accessed and reviewed at: https://github.com/lxc/lxd/pull/3034

This e-mail was sent by the LXC bot, direct replies will not reach the author
unless they happen to be subscribed to this list.

=== Description (from pull-request) ===

From 671166d83b3567b310084dd43314dff7b65cfa95 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brau...@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.brau...@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.brau...@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.brau...@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()
_______________________________________________
lxc-devel mailing list
lxc-devel@lists.linuxcontainers.org
http://lists.linuxcontainers.org/listinfo/lxc-devel

Reply via email to