[lxc-devel] [lxd/master] lvm: reuse existing volume group

brauner on Github lxc-bot at linuxcontainers.org
Tue Feb 21 14:30:03 UTC 2017


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 364 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20170221/11cdc76b/attachment.bin>
-------------- next part --------------
From 195b63bf4e97d68ef3852bbeb1ede2827fc45d21 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Tue, 21 Feb 2017 00:26:08 +0100
Subject: [PATCH 1/3] lvm: remove volume.lvm.thinpool_name

Will be replaced by storage pool config key lvm.thinpool_name.

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 lxd/storage_pools_config.go   | 6 +++---
 lxd/storage_volumes_config.go | 7 -------
 2 files changed, 3 insertions(+), 10 deletions(-)

diff --git a/lxd/storage_pools_config.go b/lxd/storage_pools_config.go
index 75f34c1..a57e594 100644
--- a/lxd/storage_pools_config.go
+++ b/lxd/storage_pools_config.go
@@ -34,7 +34,7 @@ var storagePoolConfigKeys = map[string]func(value string) error{
 	},
 	"volume.zfs.use_refquota":     shared.IsBool,
 	"volume.zfs.remove_snapshots": shared.IsBool,
-	"volume.lvm.thinpool_name":    shared.IsAny,
+	"lvm.thinpool_name":           shared.IsAny,
 	"zfs.pool_name":               shared.IsAny,
 }
 
@@ -148,8 +148,8 @@ func storagePoolFillDefault(name string, driver string, config map[string]string
 	}
 
 	if driver == "lvm" {
-		if config["volume.lvm.thinpool_name"] == "" {
-			config["volume.lvm.thinpool_name"] = "LXDThinpool"
+		if config["lvm.thinpool_name"] == "" {
+			config["lvm.thinpool_name"] = "LXDThinpool"
 		}
 
 		if config["volume.block.filesystem"] == "" {
diff --git a/lxd/storage_volumes_config.go b/lxd/storage_volumes_config.go
index 435457e..e20e6cf 100644
--- a/lxd/storage_volumes_config.go
+++ b/lxd/storage_volumes_config.go
@@ -121,13 +121,6 @@ func storageVolumeFillDefault(name string, config map[string]string, parentPool
 		if config["block.mount_options"] == "" && config["block.filesystem"] == "ext4" {
 			config["block.mount_options"] = "discard"
 		}
-
-		if config["lvm.thinpool_name"] == "" {
-			config["lvm.thinpool_name"] = parentPool.Config["volume.lvm.thinpool_name"]
-			if config["lvm.thinpool_name"] == "" {
-				config["lvm.thinpool_name"] = "LXDThinPool"
-			}
-		}
 	}
 
 	return nil

From ee7972f01fd5bf7f5a276ebcc556bcc0ddfa0579 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Tue, 21 Feb 2017 00:34:18 +0100
Subject: [PATCH 2/3] lvm: add lvm.thinpool_name + lvm.vg_name

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 lxd/storage_lvm.go          | 16 ++++++++++------
 lxd/storage_pools_config.go |  5 +++++
 lxd/storage_zfs.go          |  8 ++++++--
 3 files changed, 21 insertions(+), 8 deletions(-)

diff --git a/lxd/storage_lvm.go b/lxd/storage_lvm.go
index e3c1f7b..d93fb20 100644
--- a/lxd/storage_lvm.go
+++ b/lxd/storage_lvm.go
@@ -86,7 +86,7 @@ func storageLVMValidateThinPoolName(d *Daemon, vgName string, value string) erro
 
 	if value != "" {
 		if vgName == "" {
-			return fmt.Errorf("Can not set lvm_thinpool_name without lvm_vg_name set.")
+			return fmt.Errorf("Can not set lvm.thinpool_name without lvm.vg_name set.")
 		}
 
 		poolExists, err := storageLVMThinpoolExists(vgName, value)
@@ -311,7 +311,7 @@ func (s *storageLvm) StoragePoolVolumeCreate() error {
 	tryUndo := true
 
 	vgName := s.pool.Name
-	thinPoolName := s.volume.Config["lvm.thinpool_name"]
+	thinPoolName := s.pool.Config["lvm.thinpool_name"]
 	lvFsType := s.volume.Config["block.filesystem"]
 	lvSize := s.volume.Config["size"]
 
@@ -467,8 +467,12 @@ func (s *storageLvm) StoragePoolUpdate(changedConfig []string) error {
 		// noop
 	}
 
-	if shared.StringInSlice("volume.lvm.thinpool_name", changedConfig) {
-		return fmt.Errorf("The \"volume.lvm.thinpool_name\" property cannot be changed.")
+	if shared.StringInSlice("lvm.thinpool_name", changedConfig) {
+		return fmt.Errorf("The \"lvm.thinpool_name\" property cannot be changed.")
+	}
+
+	if shared.StringInSlice("lvm.vg_name", changedConfig) {
+		return fmt.Errorf("The \"lvm.vg_name\" property cannot be changed.")
 	}
 
 	return nil
@@ -489,7 +493,7 @@ func (s *storageLvm) ContainerCreate(container container) error {
 
 	containerName := container.Name()
 	containerLvmName := containerNameToLVName(containerName)
-	thinPoolName := s.volume.Config["lvm.thinpool_name"]
+	thinPoolName := s.pool.Config["lvm.thinpool_name"]
 	lvFsType := s.volume.Config["block.filesystem"]
 	lvSize := s.volume.Config["size"]
 
@@ -1124,7 +1128,7 @@ func (s *storageLvm) ImageCreate(fingerprint string) error {
 	tryUndo := true
 
 	vgName := s.pool.Name
-	thinPoolName := s.volume.Config["lvm.thinpool_name"]
+	thinPoolName := s.pool.Config["lvm.thinpool_name"]
 	lvFsType := s.volume.Config["block.filesystem"]
 	lvSize := s.volume.Config["size"]
 
diff --git a/lxd/storage_pools_config.go b/lxd/storage_pools_config.go
index a57e594..b1d12e5 100644
--- a/lxd/storage_pools_config.go
+++ b/lxd/storage_pools_config.go
@@ -35,6 +35,7 @@ var storagePoolConfigKeys = map[string]func(value string) error{
 	"volume.zfs.use_refquota":     shared.IsBool,
 	"volume.zfs.remove_snapshots": shared.IsBool,
 	"lvm.thinpool_name":           shared.IsAny,
+	"lvm.vg_name":                 shared.IsAny,
 	"zfs.pool_name":               shared.IsAny,
 }
 
@@ -148,6 +149,10 @@ func storagePoolFillDefault(name string, driver string, config map[string]string
 	}
 
 	if driver == "lvm" {
+		if config["lvm.vg_name"] == "" {
+			config["lvm.vg_name"] == "LXDVGroup"
+		}
+
 		if config["lvm.thinpool_name"] == "" {
 			config["lvm.thinpool_name"] = "LXDThinpool"
 		}
diff --git a/lxd/storage_zfs.go b/lxd/storage_zfs.go
index b615298..951381e 100644
--- a/lxd/storage_zfs.go
+++ b/lxd/storage_zfs.go
@@ -307,8 +307,12 @@ func (s *storageZfs) StoragePoolUpdate(changedConfig []string) error {
 		return fmt.Errorf("The \"volume.block.filesystem\" property cannot be changed.")
 	}
 
-	if shared.StringInSlice("volume.lvm.thinpool_name", changedConfig) {
-		return fmt.Errorf("The \"volume.lvm.thinpool_name\" property cannot be changed.")
+	if shared.StringInSlice("lvm.thinpool_name", changedConfig) {
+		return fmt.Errorf("The \"lvm.thinpool_name\" property cannot be changed.")
+	}
+
+	if shared.StringInSlice("lvm.vg_name", changedConfig) {
+		return fmt.Errorf("The \"lvm.vg_name\" property cannot be changed.")
 	}
 
 	if shared.StringInSlice("volume.zfs.use_refquota", changedConfig) {

From 621b290a972b49bb245eda020f8a983e25105780 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Tue, 21 Feb 2017 15:22:51 +0100
Subject: [PATCH 3/3] lvm: allow to reuse existing volume groups

Reuse an already existing LVM volume group:
- lxc storage create <pool_name> lvm lvm.vg_name=LXDvg lvm.thinpool_name=LXDthin

Create a new LVM volume group or reuse an existing one:
- lxc storage create <pool_name> lvm source=/dev/sdb lvm.vg_name=LXDvg lvm.thinpool_name=LXDthin
- lxc storage create <pool_name> lvm source=/dev/sdb

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 lxd/storage_lvm.go          | 192 +++++++++++++++++++++++++++++++++-----------
 lxd/storage_pools_config.go |   5 +-
 test/suites/storage.sh      |   3 +
 3 files changed, 153 insertions(+), 47 deletions(-)

diff --git a/lxd/storage_lvm.go b/lxd/storage_lvm.go
index d93fb20..2792166 100644
--- a/lxd/storage_lvm.go
+++ b/lxd/storage_lvm.go
@@ -17,6 +17,38 @@ import (
 	log "gopkg.in/inconshreveable/log15.v2"
 )
 
+func storageVGExists(vgName string) (bool, error) {
+	err := exec.Command("vgs", "--noheadings", "-o", "lv_attr", vgName).Run()
+	if err != nil {
+		if exitError, ok := err.(*exec.ExitError); ok {
+			waitStatus := exitError.Sys().(syscall.WaitStatus)
+			if waitStatus.ExitStatus() == 5 {
+				// pool LV was not found
+				return false, nil
+			}
+		}
+		return false, fmt.Errorf("Error checking for volume group '%s'", vgName)
+	}
+
+	return true, nil
+}
+
+func storagePVExists(pvName string) (bool, error) {
+	err := exec.Command("pvs", "--noheadings", "-o", "lv_attr", pvName).Run()
+	if err != nil {
+		if exitError, ok := err.(*exec.ExitError); ok {
+			waitStatus := exitError.Sys().(syscall.WaitStatus)
+			if waitStatus.ExitStatus() == 5 {
+				// pool LV was not found
+				return false, nil
+			}
+		}
+		return false, fmt.Errorf("Error checking for volume group '%s'", pvName)
+	}
+
+	return true, nil
+}
+
 func storageLVMThinpoolExists(vgName string, poolName string) (bool, error) {
 	output, err := exec.Command("vgs", "--noheadings", "-o", "lv_attr", fmt.Sprintf("%s/%s", vgName, poolName)).Output()
 	if err != nil {
@@ -120,9 +152,19 @@ func containerNameToLVName(containerName string) string {
 }
 
 type storageLvm struct {
+	vgName       string
+	thinPoolName string
 	storageShared
 }
 
+func (s *storageLvm) getOnDiskPoolName() string {
+	if s.vgName != "" {
+		return s.vgName
+	}
+
+	return s.pool.Name
+}
+
 func getLvmDevPath(lvmPool string, volumeType string, lvmVolume string) string {
 	return fmt.Sprintf("/dev/%s/%s_%s", lvmPool, volumeType, lvmVolume)
 }
@@ -179,6 +221,26 @@ func (s *storageLvm) StoragePoolInit(config map[string]interface{}) (storage, er
 		return s, err
 	}
 
+	source := s.pool.Config["source"]
+	s.vgName = s.pool.Config["lvm.vg_name"]
+	s.thinPoolName = s.pool.Config["lvm.thinpool_name"]
+	if source == "" {
+		// Source property is empty, so the user wants us to reuse an
+		// already existing volume group.
+		s.log.Debug(fmt.Sprintf("Source property of this lvm storage pool empty: Checking that volume group \"lvm.vg_name=%s\" already exists.", s.vgName))
+		ok, err := storageVGExists(s.vgName)
+		if err != nil {
+			// Internal error.
+			return s, err
+		} else if !ok {
+			// Volume group does not exist.
+			return s, fmt.Errorf("The \"source\" property of the storage pool is empty and the \"lvm.vg_name=%s\" volume group does not exist.", s.vgName)
+		}
+		s.log.Debug(fmt.Sprintf("Source property of this lvm storage pool empty: Detected that volume group \"lvm.vg_name=%s\" already exists.", s.vgName))
+	} else if filepath.IsAbs(source) && !shared.IsBlockdevPath(source) {
+		return s, fmt.Errorf("Loop backed lvm storage volumes are currently not supported.")
+	}
+
 	return s, nil
 }
 
@@ -232,9 +294,6 @@ func (s *storageLvm) StoragePoolCreate() error {
 	tryUndo := true
 
 	source := s.pool.Config["source"]
-	if source == "" {
-		return fmt.Errorf("No \"source\" property found for the storage pool.")
-	}
 
 	// Create the mountpoint for the storage pool.
 	poolMntPoint := getStoragePoolMountPoint(s.pool.Name)
@@ -248,28 +307,56 @@ func (s *storageLvm) StoragePoolCreate() error {
 		}
 	}()
 
-	if !shared.IsBlockdevPath(source) {
-		return fmt.Errorf("Loop backed lvm storage volumes are currently not supported.")
-	}
+	poolName := s.getOnDiskPoolName()
+	if filepath.IsAbs(source) {
+		// Check whether we have been given a block device.
+		if !shared.IsBlockdevPath(source) {
+			return fmt.Errorf("Loop backed lvm storage volumes are currently not supported.")
+		}
 
-	// Create a lvm physical volume.
-	output, err := exec.Command("pvcreate", source).CombinedOutput()
-	if err != nil {
-		return fmt.Errorf("Failed to create the physical volume for the lvm storage pool: %s.", output)
-	}
-	defer func() {
-		if tryUndo {
-			exec.Command("pvremove", source).Run()
+		ok, err := storagePVExists(source)
+		if err == nil && !ok {
+			// Create a new lvm physical volume.
+			output, err := exec.Command("pvcreate", source).CombinedOutput()
+			if err != nil {
+				return fmt.Errorf("Failed to create the physical volume for the lvm storage pool: %s.", output)
+			}
+			defer func() {
+				if tryUndo {
+					exec.Command("pvremove", source).Run()
+				}
+			}()
 		}
-	}()
 
-	// Create a volume group on the physical volume.
-	output, err = exec.Command("vgcreate", s.pool.Name, source).CombinedOutput()
-	if err != nil {
-		return fmt.Errorf("Failed to create the volume group for the lvm storage pool: %s.", output)
-	}
+		ok, err = storageVGExists(poolName)
+		if err == nil && !ok {
+			// Create a volume group on the physical volume.
+			output, err := exec.Command("vgcreate", poolName, source).CombinedOutput()
+			if err != nil {
+				return fmt.Errorf("Failed to create the volume group for the lvm storage pool: %s.", output)
+			}
+		}
 
-	s.pool.Config["source"] = s.pool.Name
+		s.pool.Config["source"] = s.pool.Name
+	} else {
+		if source == "" || source == s.vgName && s.vgName != "" && s.thinPoolName != "" {
+			// Source property is empty, so the user wants us to
+			// reuse an already existing volume group.
+			ok, err := storageVGExists(s.vgName)
+			if err != nil {
+				// Internal error.
+				return err
+			} else if !ok {
+				// Volume group does not exist.
+				return fmt.Errorf("The \"source\" property of the storage pool is empty and the \"lvm.vg_name=%s\" volume group does not exist.", s.vgName)
+			}
+		} else if source != "" {
+			return fmt.Errorf("Inconsistent LVM request. The \"source\" property can only be a non absolute path when it matches the \"lvm.vg_name\" property.")
+		}
+		// Set source to the volume group name since we can't
+		// rely on the existence of the block device.
+		s.pool.Config["source"] = s.vgName
+	}
 
 	// Deregister cleanup.
 	tryUndo = false
@@ -283,8 +370,9 @@ func (s *storageLvm) StoragePoolDelete() error {
 		return fmt.Errorf("No \"source\" property found for the storage pool.")
 	}
 
+	poolName := s.getOnDiskPoolName()
 	// Remove the volume group.
-	output, err := exec.Command("vgremove", "-f", s.pool.Name).CombinedOutput()
+	output, err := exec.Command("vgremove", "-f", poolName).CombinedOutput()
 	if err != nil {
 		return fmt.Errorf("Failed to destroy the volume group for the lvm storage pool: %s.", output)
 	}
@@ -310,7 +398,7 @@ func (s *storageLvm) StoragePoolUmount() (bool, error) {
 func (s *storageLvm) StoragePoolVolumeCreate() error {
 	tryUndo := true
 
-	vgName := s.pool.Name
+	poolName := s.getOnDiskPoolName()
 	thinPoolName := s.pool.Config["lvm.thinpool_name"]
 	lvFsType := s.volume.Config["block.filesystem"]
 	lvSize := s.volume.Config["size"]
@@ -320,7 +408,7 @@ func (s *storageLvm) StoragePoolVolumeCreate() error {
 		return err
 	}
 
-	err = s.createThinLV(vgName, thinPoolName, s.volume.Name, lvFsType, lvSize, volumeType)
+	err = s.createThinLV(poolName, thinPoolName, s.volume.Name, lvFsType, lvSize, volumeType)
 	if err != nil {
 		s.log.Error("LVMCreateThinLV", log.Ctx{"err": err})
 		return fmt.Errorf("Error Creating LVM LV for new image: %v", err)
@@ -359,7 +447,8 @@ func (s *storageLvm) StoragePoolVolumeDelete() error {
 		return err
 	}
 
-	err = s.removeLV(s.pool.Name, volumeType, s.volume.Name)
+	poolName := s.getOnDiskPoolName()
+	err = s.removeLV(poolName, volumeType, s.volume.Name)
 	if err != nil {
 		return err
 	}
@@ -386,7 +475,8 @@ func (s *storageLvm) StoragePoolVolumeMount() (bool, error) {
 		return false, err
 	}
 
-	lvmVolumePath := getLvmDevPath(s.pool.Name, volumeType, s.volume.Name)
+	poolName := s.getOnDiskPoolName()
+	lvmVolumePath := getLvmDevPath(poolName, volumeType, s.volume.Name)
 	mountOptions := s.volume.Config["block.mount_options"]
 	err = tryMount(lvmVolumePath, customPoolVolumeMntPoint, lvFsType, 0, mountOptions)
 	if err != nil {
@@ -497,7 +587,8 @@ func (s *storageLvm) ContainerCreate(container container) error {
 	lvFsType := s.volume.Config["block.filesystem"]
 	lvSize := s.volume.Config["size"]
 
-	err := s.createThinLV(s.pool.Name, thinPoolName, containerLvmName, lvFsType, lvSize, storagePoolVolumeApiEndpointContainers)
+	poolName := s.getOnDiskPoolName()
+	err := s.createThinLV(poolName, thinPoolName, containerLvmName, lvFsType, lvSize, storagePoolVolumeApiEndpointContainers)
 	if err != nil {
 		return err
 	}
@@ -542,11 +633,13 @@ func (s *storageLvm) ContainerCreate(container container) error {
 func (s *storageLvm) ContainerCreateFromImage(container container, fingerprint string) error {
 	tryUndo := true
 
+	poolName := s.getOnDiskPoolName()
+
 	// Check if the image already exists.
-	imageMntPoint := getImageMountPoint(s.pool.Name, fingerprint)
-	imageLvmDevPath := getLvmDevPath(s.pool.Name, storagePoolVolumeApiEndpointImages, fingerprint)
+	imageMntPoint := getImageMountPoint(poolName, fingerprint)
+	imageLvmDevPath := getLvmDevPath(poolName, storagePoolVolumeApiEndpointImages, fingerprint)
 
-	imageStoragePoolLockID := getImageCreateLockID(s.pool.Name, fingerprint)
+	imageStoragePoolLockID := getImageCreateLockID(poolName, fingerprint)
 	lxdStorageMapLock.Lock()
 	if waitChannel, ok := lxdStorageOngoingOperationMap[imageStoragePoolLockID]; ok {
 		lxdStorageMapLock.Unlock()
@@ -576,7 +669,7 @@ func (s *storageLvm) ContainerCreateFromImage(container container, fingerprint s
 
 	containerName := container.Name()
 	containerLvmName := containerNameToLVName(containerName)
-	containerLvSnapshotPath, err := s.createSnapshotLV(s.pool.Name, fingerprint, storagePoolVolumeApiEndpointImages, containerLvmName, storagePoolVolumeApiEndpointContainers, false)
+	containerLvSnapshotPath, err := s.createSnapshotLV(poolName, fingerprint, storagePoolVolumeApiEndpointImages, containerLvmName, storagePoolVolumeApiEndpointContainers, false)
 	if err != nil {
 		return err
 	}
@@ -665,7 +758,8 @@ func (s *storageLvm) ContainerDelete(container container) error {
 		}
 	}
 
-	err := s.removeLV(s.pool.Name, storagePoolVolumeApiEndpointContainers, containerLvmName)
+	poolName := s.getOnDiskPoolName()
+	err := s.removeLV(poolName, storagePoolVolumeApiEndpointContainers, containerLvmName)
 	if err != nil {
 		return err
 	}
@@ -762,7 +856,8 @@ func (s *storageLvm) ContainerCopy(container container, sourceContainer containe
 func (s *storageLvm) ContainerMount(name string, path string) (bool, error) {
 	containerLvmName := containerNameToLVName(name)
 	lvFsType := s.volume.Config["block.filesystem"]
-	containerLvmPath := getLvmDevPath(s.pool.Name, storagePoolVolumeApiEndpointContainers, containerLvmName)
+	poolName := s.getOnDiskPoolName()
+	containerLvmPath := getLvmDevPath(poolName, storagePoolVolumeApiEndpointContainers, containerLvmName)
 	mountOptions := s.volume.Config["block.mount_options"]
 	containerMntPoint := getContainerMountPoint(s.pool.Name, name)
 
@@ -945,12 +1040,13 @@ func (s *storageLvm) ContainerRestore(container container, sourceContainer conta
 		return err
 	}
 
-	err = s.removeLV(s.pool.Name, storagePoolVolumeApiEndpointContainers, destName)
+	poolName := s.getOnDiskPoolName()
+	err = s.removeLV(poolName, storagePoolVolumeApiEndpointContainers, destName)
 	if err != nil {
 		s.log.Error(fmt.Sprintf("Failed to remove \"%s\": %s.", destName, err))
 	}
 
-	_, err = s.createSnapshotLV(s.pool.Name, srcLvName, storagePoolVolumeApiEndpointContainers, destLvName, storagePoolVolumeApiEndpointContainers, false)
+	_, err = s.createSnapshotLV(poolName, srcLvName, storagePoolVolumeApiEndpointContainers, destLvName, storagePoolVolumeApiEndpointContainers, false)
 	if err != nil {
 		return fmt.Errorf("Error creating snapshot LV: %v", err)
 	}
@@ -979,7 +1075,8 @@ func (s *storageLvm) createSnapshotContainer(snapshotContainer container, source
 	targetContainerLvmName := containerNameToLVName(targetContainerName)
 	s.log.Debug("Creating snapshot", log.Ctx{"srcName": sourceContainerName, "destName": targetContainerName})
 
-	_, err := s.createSnapshotLV(s.pool.Name, sourceContainerLvmName, storagePoolVolumeApiEndpointContainers, targetContainerLvmName, storagePoolVolumeApiEndpointContainers, readonly)
+	poolName := s.getOnDiskPoolName()
+	_, err := s.createSnapshotLV(poolName, sourceContainerLvmName, storagePoolVolumeApiEndpointContainers, targetContainerLvmName, storagePoolVolumeApiEndpointContainers, readonly)
 	if err != nil {
 		return fmt.Errorf("Error creating snapshot LV: %s", err)
 	}
@@ -1064,18 +1161,19 @@ func (s *storageLvm) ContainerSnapshotStart(container container) error {
 
 	s.log.Debug("Creating snapshot", log.Ctx{"srcName": sourceLvmName, "destName": targetLvmName})
 
-	lvpath, err := s.createSnapshotLV(s.pool.Name, sourceLvmName, storagePoolVolumeApiEndpointContainers, tmpTargetLvmName, storagePoolVolumeApiEndpointContainers, false)
+	poolName := s.getOnDiskPoolName()
+	lvpath, err := s.createSnapshotLV(poolName, sourceLvmName, storagePoolVolumeApiEndpointContainers, tmpTargetLvmName, storagePoolVolumeApiEndpointContainers, false)
 	if err != nil {
 		return fmt.Errorf("Error creating snapshot LV: %s", err)
 	}
 	defer func() {
 		if tryUndo {
-			s.removeLV(s.pool.Name, storagePoolVolumeApiEndpointContainers, tmpTargetLvmName)
+			s.removeLV(poolName, storagePoolVolumeApiEndpointContainers, tmpTargetLvmName)
 		}
 	}()
 
 	lvFsType := s.volume.Config["block.filesystem"]
-	containerLvmPath := getLvmDevPath(s.pool.Name, storagePoolVolumeApiEndpointContainers, tmpTargetLvmName)
+	containerLvmPath := getLvmDevPath(poolName, storagePoolVolumeApiEndpointContainers, tmpTargetLvmName)
 	mountOptions := s.volume.Config["block.mount_options"]
 	containerMntPoint := getSnapshotMountPoint(s.pool.Name, sourceName)
 
@@ -1112,7 +1210,8 @@ func (s *storageLvm) ContainerSnapshotStop(container container) error {
 
 	lvName := containerNameToLVName(name)
 	tmpLvName := getTmpSnapshotName(lvName)
-	err := s.removeLV(s.pool.Name, storagePoolVolumeApiEndpointContainers, tmpLvName)
+	poolName := s.getOnDiskPoolName()
+	err := s.removeLV(poolName, storagePoolVolumeApiEndpointContainers, tmpLvName)
 	if err != nil {
 		return err
 	}
@@ -1127,7 +1226,7 @@ func (s *storageLvm) ContainerSnapshotCreateEmpty(snapshotContainer container) e
 func (s *storageLvm) ImageCreate(fingerprint string) error {
 	tryUndo := true
 
-	vgName := s.pool.Name
+	poolName := s.getOnDiskPoolName()
 	thinPoolName := s.pool.Config["lvm.thinpool_name"]
 	lvFsType := s.volume.Config["block.filesystem"]
 	lvSize := s.volume.Config["size"]
@@ -1137,7 +1236,7 @@ func (s *storageLvm) ImageCreate(fingerprint string) error {
 		return err
 	}
 
-	err = s.createThinLV(vgName, thinPoolName, fingerprint, lvFsType, lvSize, storagePoolVolumeApiEndpointImages)
+	err = s.createThinLV(poolName, thinPoolName, fingerprint, lvFsType, lvSize, storagePoolVolumeApiEndpointImages)
 	if err != nil {
 		s.log.Error("LVMCreateThinLV", log.Ctx{"err": err})
 		return fmt.Errorf("Error Creating LVM LV for new image: %v", err)
@@ -1181,7 +1280,8 @@ func (s *storageLvm) ImageDelete(fingerprint string) error {
 		return err
 	}
 
-	err = s.removeLV(s.pool.Name, storagePoolVolumeApiEndpointImages, fingerprint)
+	poolName := s.getOnDiskPoolName()
+	err = s.removeLV(poolName, storagePoolVolumeApiEndpointImages, fingerprint)
 	if err != nil {
 		return err
 	}
@@ -1214,7 +1314,8 @@ func (s *storageLvm) ImageMount(fingerprint string) (bool, error) {
 		return false, fmt.Errorf("No filesystem type specified.")
 	}
 
-	lvmVolumePath := getLvmDevPath(s.pool.Name, storagePoolVolumeApiEndpointImages, fingerprint)
+	poolName := s.getOnDiskPoolName()
+	lvmVolumePath := getLvmDevPath(poolName, storagePoolVolumeApiEndpointImages, fingerprint)
 	lvmMountOptions := s.volume.Config["block.mount_options"]
 	// Shouldn't be necessary since it should be validated in the config
 	// checks.
@@ -1393,7 +1494,8 @@ func (s *storageLvm) createSnapshotLV(vgName string, origLvName string, origVolu
 func (s *storageLvm) renameLV(oldName string, newName string, volumeType string) (string, error) {
 	oldLvmName := getPrefixedLvName(volumeType, oldName)
 	newLvmName := getPrefixedLvName(volumeType, newName)
-	output, err := tryExec("lvrename", s.pool.Name, oldLvmName, newLvmName)
+	poolName := s.getOnDiskPoolName()
+	output, err := tryExec("lvrename", poolName, oldLvmName, newLvmName)
 	return string(output), err
 }
 
diff --git a/lxd/storage_pools_config.go b/lxd/storage_pools_config.go
index b1d12e5..840ff89 100644
--- a/lxd/storage_pools_config.go
+++ b/lxd/storage_pools_config.go
@@ -50,7 +50,7 @@ func storagePoolValidateConfig(name string, driver string, config map[string]str
 	if config["source"] == "" {
 		if driver == "dir" {
 			config["source"] = filepath.Join(shared.VarPath("storage-pools"), name)
-		} else {
+		} else if driver != "lvm" {
 			config["source"] = filepath.Join(shared.VarPath("disks"), name)
 		}
 	}
@@ -150,7 +150,8 @@ func storagePoolFillDefault(name string, driver string, config map[string]string
 
 	if driver == "lvm" {
 		if config["lvm.vg_name"] == "" {
-			config["lvm.vg_name"] == "LXDVGroup"
+			// Default is to set this to the pool name if empty.
+			config["lvm.vg_name"] = name
 		}
 
 		if config["lvm.thinpool_name"] == "" {
diff --git a/test/suites/storage.sh b/test/suites/storage.sh
index b32ddf9..2eb2ffa 100644
--- a/test/suites/storage.sh
+++ b/test/suites/storage.sh
@@ -53,6 +53,9 @@ test_storage() {
       configure_lvm_loop_device loop_file_3 loop_device_3
       # shellcheck disable=SC2154
       lxc storage create "lxdtest-$(basename "${LXD_DIR}")-pool6" lvm source="${loop_device_3}" volume.size=10MB
+
+      configure_lvm_loop_device loop_file_3 loop_device_3
+      lxc storage create "lxdtest-$(basename "${LXD_DIR}")-pool7" lvm source="${loop_device_3}" volume.size=10MB
     fi
 
     # Set default storage pool for image import.


More information about the lxc-devel mailing list