[lxc-devel] [lxd/master] Storage LVM utils - create pool
tomponline on Github
lxc-bot at linuxcontainers.org
Tue Dec 17 11:35:19 UTC 2019
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 412 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20191217/81580585/attachment-0001.bin>
-------------- next part --------------
From d8097a52c38000d7ec4d2b65889fb5b04926997c Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 13 Dec 2019 11:40:08 +0000
Subject: [PATCH 01/18] lxd/storage/drivers/interface: Comments on pool
mount/unmount definitions
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/storage/drivers/interface.go | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/lxd/storage/drivers/interface.go b/lxd/storage/drivers/interface.go
index c5f7d063ec..1ecc052068 100644
--- a/lxd/storage/drivers/interface.go
+++ b/lxd/storage/drivers/interface.go
@@ -28,7 +28,12 @@ type Driver interface {
// Pool.
Create() error
Delete(op *operations.Operation) error
+ // Mount mounts a storage pool if needed, returns true if we caused a new mount, false if
+ // already mounted.
Mount() (bool, error)
+
+ // Unmount unmounts a storage pool if needed, returns true if unmounted, false if was not
+ // mounted.
Unmount() (bool, error)
GetResources() (*api.ResourcesStoragePool, error)
Validate(config map[string]string) error
From e2f4052dcf7242716f61dc7dfbc54229fc4ee886 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 13 Dec 2019 14:13:29 +0000
Subject: [PATCH 02/18] shared/util: Adds comment to TryRunCommand
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
shared/util.go | 2 ++
1 file changed, 2 insertions(+)
diff --git a/shared/util.go b/shared/util.go
index e307f985fe..0a80f5dd7e 100644
--- a/shared/util.go
+++ b/shared/util.go
@@ -861,6 +861,8 @@ func RunCommandWithFds(stdin io.Reader, stdout io.Writer, name string, arg ...st
return nil
}
+// TryRunCommand runs the specified command up to 20 times with a 500ms delay between each call
+// until it runs without an error. If after 20 times it is still failing then returns the error.
func TryRunCommand(name string, arg ...string) (string, error) {
var err error
var output string
From c399ff35a6d226088a3e4ef7b1d0b66b845afab7 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Tue, 17 Dec 2019 11:22:34 +0000
Subject: [PATCH 03/18] lxd/storage/drivers/utils/lvm: Adds LVM util functions
for creating pools
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/storage/drivers/utils_lvm.go | 262 +++++++++++++++++++++++++++++++
1 file changed, 262 insertions(+)
create mode 100644 lxd/storage/drivers/utils_lvm.go
diff --git a/lxd/storage/drivers/utils_lvm.go b/lxd/storage/drivers/utils_lvm.go
new file mode 100644
index 0000000000..e9f1088e72
--- /dev/null
+++ b/lxd/storage/drivers/utils_lvm.go
@@ -0,0 +1,262 @@
+package drivers
+
+import (
+ "fmt"
+ "os/exec"
+ "strconv"
+ "strings"
+ "syscall"
+
+ "github.com/lxc/lxd/lxd/project"
+ "github.com/lxc/lxd/shared"
+ "github.com/lxc/lxd/shared/units"
+ "github.com/lxc/lxd/shared/version"
+)
+
+// LVMPysicalVolumeExists checks if an LVM Physical Volume exists.
+func LVMPysicalVolumeExists(pvName string) (bool, error) {
+ _, err := shared.RunCommand("pvs", "--noheadings", "-o", "lv_attr", pvName)
+ if err != nil {
+ runErr, ok := err.(shared.RunError)
+ if ok {
+ exitError, ok := runErr.Err.(*exec.ExitError)
+ if ok {
+ waitStatus := exitError.Sys().(syscall.WaitStatus)
+ if waitStatus.ExitStatus() == 5 {
+ // physical volume not found
+ return false, nil
+ }
+ }
+ }
+ return false, fmt.Errorf("error checking for physical volume \"%s\"", pvName)
+ }
+
+ return true, nil
+}
+
+// LVMVolumeGroupExists checks if an LVM Volume Group exists.
+func LVMVolumeGroupExists(vgName string) (bool, error) {
+ _, err := shared.RunCommand("vgs", "--noheadings", "-o", "lv_attr", vgName)
+ if err != nil {
+ runErr, ok := err.(shared.RunError)
+ if ok {
+ exitError, ok := runErr.Err.(*exec.ExitError)
+ if ok {
+ waitStatus := exitError.Sys().(syscall.WaitStatus)
+ if waitStatus.ExitStatus() == 5 {
+ // volume group not found
+ return false, nil
+ }
+ }
+ }
+
+ return false, fmt.Errorf("error checking for volume group \"%s\"", vgName)
+ }
+
+ return true, nil
+}
+
+// LVMGetLVCount gets the count of volumes in a volume group.
+func LVMGetLVCount(vgName string) (int, error) {
+ output, err := shared.TryRunCommand("vgs", "--noheadings", "-o", "lv_count", vgName)
+ if err != nil {
+ return -1, err
+ }
+
+ output = strings.TrimSpace(output)
+ return strconv.Atoi(output)
+}
+
+// LVMThinpoolExists checks whether the specified thinpool exists in a volume group.
+func LVMThinpoolExists(vgName string, poolName string) (bool, error) {
+ output, err := shared.RunCommand("vgs", "--noheadings", "-o", "lv_attr", fmt.Sprintf("%s/%s", vgName, poolName))
+ if err != nil {
+ runErr, ok := err.(shared.RunError)
+ if ok {
+ exitError, ok := runErr.Err.(*exec.ExitError)
+ if 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 pool \"%s\"", poolName)
+ }
+ // Found LV named poolname, check type:
+ attrs := strings.TrimSpace(string(output[:]))
+ if strings.HasPrefix(attrs, "t") {
+ return true, nil
+ }
+
+ return false, fmt.Errorf("pool named \"%s\" exists but is not a thin pool", poolName)
+}
+
+// LVMDevPath returns the path to the LVM volume device.
+func LVMDevPath(projectName, lvmPool string, volumeDBTypeName string, lvmVolume string) string {
+ lvmVolume = project.Prefix(projectName, lvmVolume)
+ if volumeDBTypeName == "" {
+ return fmt.Sprintf("/dev/%s/%s", lvmPool, lvmVolume)
+ }
+
+ return fmt.Sprintf("/dev/%s/%s_%s", lvmPool, volumeDBTypeName, lvmVolume)
+}
+
+// LVMVolumeExists checks whether the specified logical volume exists.
+func LVMVolumeExists(lvDevPath string) (bool, error) {
+ _, err := shared.RunCommand("lvs", "--noheadings", "-o", "lv_attr", lvDevPath)
+ if err != nil {
+ runErr, ok := err.(shared.RunError)
+ if ok {
+ exitError, ok := runErr.Err.(*exec.ExitError)
+ if ok {
+ waitStatus := exitError.Sys().(syscall.WaitStatus)
+ if waitStatus.ExitStatus() == 5 {
+ // logical volume not found.
+ return false, nil
+ }
+ }
+ }
+
+ return false, fmt.Errorf("error checking for logical volume \"%s\"", lvDevPath)
+ }
+
+ return true, nil
+}
+
+// LVMCreateThinpool creates a thin pool logical volume.
+func LVMCreateThinpool(lvmVersion string, vgName string, thinPoolName string) error {
+ exists, err := LVMThinpoolExists(vgName, thinPoolName)
+ if err != nil {
+ return err
+ }
+
+ if exists {
+ return nil
+ }
+
+ err = lvmCreateDefaultThinPool(lvmVersion, vgName, thinPoolName)
+ if err != nil {
+ return err
+ }
+
+ poolExists, err := LVMThinpoolExists(vgName, thinPoolName)
+ if err != nil {
+ return fmt.Errorf("Error checking for thin pool \"%s\" in \"%s\": %v", thinPoolName, vgName, err)
+ }
+
+ if !poolExists {
+ return fmt.Errorf("Thin pool \"'%s\" does not exist in Volume Group \"%s\"", thinPoolName, vgName)
+ }
+
+ return nil
+}
+
+func lvmCreateDefaultThinPool(lvmVersion string, vgName string, thinPoolName string) error {
+ isRecent, err := LVMVersionIsAtLeast(lvmVersion, "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)
+ if isRecent {
+ _, err = shared.TryRunCommand(
+ "lvcreate",
+ "-Wy", "--yes",
+ "--poolmetadatasize", "1G",
+ "-l", "100%FREE",
+ "--thinpool", lvmThinPool)
+ } else {
+ _, err = shared.TryRunCommand(
+ "lvcreate",
+ "-Wy", "--yes",
+ "--poolmetadatasize", "1G",
+ "-L", "1G",
+ "--thinpool", lvmThinPool)
+ }
+
+ if err != nil {
+ return fmt.Errorf("Could not create LVM thin pool named %s: %v", thinPoolName, err)
+ }
+
+ if !isRecent {
+ // Grow it to the maximum VG size (two step process required by old LVM)
+ _, err = shared.TryRunCommand("lvextend", "--alloc", "anywhere", "-l", "100%FREE", lvmThinPool)
+
+ if err != nil {
+ return fmt.Errorf("Could not grow LVM thin pool named %s: %v", thinPoolName, err)
+ }
+ }
+
+ return nil
+}
+
+// LVMVersionIsAtLeast checks whether the installed version of LVM is at least the specific version.
+func LVMVersionIsAtLeast(sTypeVersion string, versionString string) (bool, error) {
+ lvmVersionString := strings.Split(sTypeVersion, "/")[0]
+
+ lvmVersion, err := version.Parse(lvmVersionString)
+ if err != nil {
+ return false, err
+ }
+
+ inVersion, err := version.Parse(versionString)
+ if err != nil {
+ return false, err
+ }
+
+ if lvmVersion.Compare(inVersion) < 0 {
+ return false, nil
+ }
+
+ return true, nil
+}
+
+// LVMCreateLogicalVolume creates a logical volume.
+func LVMCreateLogicalVolume(projectName, vgName string, thinPoolName string, lvName string, lvFsType string, lvSize string, volumeType string, makeThinLv bool) error {
+ var output string
+ var err error
+
+ // Round the size to closest 512 bytes
+ lvSizeInt, err := units.ParseByteSizeString(lvSize)
+ if err != nil {
+ return err
+ }
+
+ lvSizeInt = int64(lvSizeInt/512) * 512
+ lvSizeString := units.GetByteSizeString(lvSizeInt, 0)
+
+ lvmPoolVolumeName := lvmFullVolumeName(projectName, volumeType, lvName)
+ if makeThinLv {
+ targetVg := fmt.Sprintf("%s/%s", vgName, thinPoolName)
+ _, err = shared.TryRunCommand("lvcreate", "-Wy", "--yes", "--thin", "-n", lvmPoolVolumeName, "--virtualsize", lvSizeString, targetVg)
+ } else {
+ _, err = shared.TryRunCommand("lvcreate", "-Wy", "--yes", "-n", lvmPoolVolumeName, "--size", lvSizeString, vgName)
+ }
+ if err != nil {
+ return fmt.Errorf("Could not create thin LV named %s: %v", lvmPoolVolumeName, err)
+ }
+
+ fsPath := LVMDevPath(projectName, vgName, volumeType, lvName)
+
+ output, err = MakeFSType(fsPath, lvFsType, nil)
+ if err != nil {
+ return fmt.Errorf("Error making filesystem on image LV: %v (%s)", err, output)
+ }
+
+ return nil
+}
+
+// lvmFullVolumeName returns the logical volume's full name with project and volume type prefix.
+func lvmFullVolumeName(projectName, volumeType string, lvmVolume string) string {
+ storageName := project.Prefix(projectName, lvmVolume)
+
+ if volumeType != "" {
+ storageName = fmt.Sprintf("%s_%s", volumeType, storageName)
+ }
+
+ return storageName
+}
From a9a5f082446224da11f2ddace9486403ba7cf057 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Tue, 17 Dec 2019 11:23:02 +0000
Subject: [PATCH 04/18] lxd/api/internal: LVMVolumeExists usage
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/api_internal.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lxd/api_internal.go b/lxd/api_internal.go
index 4a5e8e6d3f..949f0a5e89 100644
--- a/lxd/api_internal.go
+++ b/lxd/api_internal.go
@@ -752,7 +752,7 @@ func internalImport(d *Daemon, r *http.Request) response.Response {
ctLvName := getLVName(poolName,
storagePoolVolumeAPIEndpointContainers,
ctLvmName)
- exists, err := storageLVExists(ctLvName)
+ exists, err := storageDrivers.LVMVolumeExists(ctLvName)
if err != nil {
return response.InternalError(err)
}
From 03439cd6a3921a83f4942205805f2e64682f2e33 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Tue, 17 Dec 2019 11:23:36 +0000
Subject: [PATCH 05/18] lxd/patches: LVMVolumeExists usage
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/patches.go | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/lxd/patches.go b/lxd/patches.go
index 3049b08896..81826071f2 100644
--- a/lxd/patches.go
+++ b/lxd/patches.go
@@ -20,6 +20,7 @@ import (
"github.com/lxc/lxd/lxd/instance"
"github.com/lxc/lxd/lxd/rsync"
driver "github.com/lxc/lxd/lxd/storage"
+ storageDrivers "github.com/lxc/lxd/lxd/storage/drivers"
"github.com/lxc/lxd/shared"
log "github.com/lxc/lxd/shared/log15"
"github.com/lxc/lxd/shared/logger"
@@ -162,7 +163,7 @@ func patchRenameCustomVolumeLVs(name string, d *Daemon) error {
oldName := fmt.Sprintf("%s/custom_%s", vgName, volume)
newName := fmt.Sprintf("%s/custom_%s", vgName, containerNameToLVName(volume))
- exists, err := storageLVExists(newName)
+ exists, err := storageDrivers.LVMVolumeExists(newName)
if err != nil {
return err
}
From 6c59543e1ccf81759b7582d1caeb4958bac55b65 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Tue, 17 Dec 2019 11:23:50 +0000
Subject: [PATCH 06/18] lxd/patches: LVMDevPath usage
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/patches.go | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/lxd/patches.go b/lxd/patches.go
index 81826071f2..c9bde13539 100644
--- a/lxd/patches.go
+++ b/lxd/patches.go
@@ -1109,7 +1109,7 @@ func upgradeFromStorageTypeLvm(name string, d *Daemon, defaultPoolName string, d
newContainerMntPoint := driver.GetContainerMountPoint("default", defaultPoolName, ct)
ctLvName := containerNameToLVName(ct)
newContainerLvName := fmt.Sprintf("%s_%s", storagePoolVolumeAPIEndpointContainers, ctLvName)
- containerLvDevPath := getLvmDevPath("default", defaultPoolName, storagePoolVolumeAPIEndpointContainers, ctLvName)
+ containerLvDevPath := storageDrivers.LVMDevPath("default", defaultPoolName, storagePoolVolumeAPIEndpointContainers, ctLvName)
if !shared.PathExists(containerLvDevPath) {
oldLvDevPath := fmt.Sprintf("/dev/%s/%s", defaultPoolName, ctLvName)
// If the old LVM device path for the logical volume
@@ -1265,7 +1265,7 @@ func upgradeFromStorageTypeLvm(name string, d *Daemon, defaultPoolName string, d
// Make sure we use a valid lv name.
csLvName := containerNameToLVName(cs)
newSnapshotLvName := fmt.Sprintf("%s_%s", storagePoolVolumeAPIEndpointContainers, csLvName)
- snapshotLvDevPath := getLvmDevPath("default", defaultPoolName, storagePoolVolumeAPIEndpointContainers, csLvName)
+ snapshotLvDevPath := storageDrivers.LVMDevPath("default", defaultPoolName, storagePoolVolumeAPIEndpointContainers, csLvName)
if !shared.PathExists(snapshotLvDevPath) {
oldLvDevPath := fmt.Sprintf("/dev/%s/%s", defaultPoolName, csLvName)
if shared.PathExists(oldLvDevPath) {
@@ -1445,7 +1445,7 @@ func upgradeFromStorageTypeLvm(name string, d *Daemon, defaultPoolName string, d
// Rename the logical volume device.
newImageLvName := fmt.Sprintf("%s_%s", storagePoolVolumeAPIEndpointImages, img)
- imageLvDevPath := getLvmDevPath("default", defaultPoolName, storagePoolVolumeAPIEndpointImages, img)
+ imageLvDevPath := storageDrivers.LVMDevPath("default", defaultPoolName, storagePoolVolumeAPIEndpointImages, img)
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
@@ -2422,7 +2422,7 @@ func patchStorageApiDetectLVSize(name string, d *Daemon) error {
// exist in the db, so it's safe to ignore the error.
volumeTypeApiEndpoint, _ := storagePoolVolumeTypeNameToAPIEndpoint(volume.Type)
lvmName := containerNameToLVName(volume.Name)
- lvmLvDevPath := getLvmDevPath("default", poolName, volumeTypeApiEndpoint, lvmName)
+ lvmLvDevPath := storageDrivers.LVMDevPath("default", poolName, volumeTypeApiEndpoint, lvmName)
size, err := lvmGetLVSize(lvmLvDevPath)
if err != nil {
logger.Errorf("Failed to detect size of logical volume: %s", err)
From e0ba747e5de9fedbad78e1da1a4c755c94430f41 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Tue, 17 Dec 2019 11:25:57 +0000
Subject: [PATCH 07/18] lxd/storage/lvm: LVMVolumeGroupExists usage
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/storage_lvm.go | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/lxd/storage_lvm.go b/lxd/storage_lvm.go
index e4cab25c5e..0224323299 100644
--- a/lxd/storage_lvm.go
+++ b/lxd/storage_lvm.go
@@ -95,7 +95,7 @@ func (s *storageLvm) StoragePoolInit() error {
}
if source != "" && !filepath.IsAbs(source) {
- ok, err := storageVGExists(source)
+ ok, err := drivers.LVMVolumeGroupExists(source)
if err != nil {
// Internal error.
return err
@@ -210,7 +210,7 @@ func (s *storageLvm) StoragePoolCreate() error {
}
// Check if the volume group already exists.
- vgExisted, globalErr = storageVGExists(poolName)
+ vgExisted, globalErr = drivers.LVMVolumeGroupExists(poolName)
if globalErr != nil {
return globalErr
}
@@ -236,7 +236,7 @@ func (s *storageLvm) StoragePoolCreate() error {
}
// Check if the volume group already exists.
- vgExisted, globalErr = storageVGExists(poolName)
+ vgExisted, globalErr = drivers.LVMVolumeGroupExists(poolName)
if globalErr != nil {
return globalErr
}
@@ -252,7 +252,7 @@ func (s *storageLvm) StoragePoolCreate() error {
s.pool.Config["lvm.vg_name"] = vgName
s.vgName = vgName
- vgExisted, globalErr = storageVGExists(vgName)
+ vgExisted, globalErr = drivers.LVMVolumeGroupExists(vgName)
if globalErr != nil {
return globalErr
}
@@ -359,15 +359,15 @@ func (s *storageLvm) StoragePoolDelete() error {
}
poolName := s.getOnDiskPoolName()
- poolExists, _ := storageVGExists(poolName)
+ poolExists, _ := drivers.LVMVolumeGroupExists(poolName)
// Delete the thinpool.
if s.useThinpool && poolExists {
// Check that the thinpool actually exists. For example, it
// won't when the user has never created a storage volume in the
// storage pool.
- devPath := getLvmDevPath("default", poolName, "", s.thinPoolName)
- ok, _ := storageLVExists(devPath)
+ devPath := drivers.LVMDevPath("default", poolName, "", s.thinPoolName)
+ ok, _ := drivers.LVMVolumeExists(devPath)
if ok {
msg, err := shared.TryRunCommand("lvremove", "-f", devPath)
if err != nil {
From e9b7a66bc9614f7a811b29e58cb902e431c3e2e1 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Tue, 17 Dec 2019 11:26:36 +0000
Subject: [PATCH 08/18] lxd/storage/lvm: LVMPysicalVolumeExists usage
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/storage_lvm.go | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lxd/storage_lvm.go b/lxd/storage_lvm.go
index 0224323299..c629987a6c 100644
--- a/lxd/storage_lvm.go
+++ b/lxd/storage_lvm.go
@@ -204,7 +204,7 @@ func (s *storageLvm) StoragePoolCreate() error {
// Check if the physical volume already exists.
pvName = s.loopInfo.Name()
- pvExisted, globalErr = storagePVExists(pvName)
+ pvExisted, globalErr = drivers.LVMPysicalVolumeExists(pvName)
if globalErr != nil {
return globalErr
}
@@ -230,7 +230,7 @@ func (s *storageLvm) StoragePoolCreate() error {
s.pool.Config["source"] = poolName
// Check if the physical volume already exists.
- pvExisted, globalErr = storagePVExists(pvName)
+ pvExisted, globalErr = drivers.LVMPysicalVolumeExists(pvName)
if globalErr != nil {
return globalErr
}
From e624ff5450fecea8aa807e779a04bd95b18d6a45 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Tue, 17 Dec 2019 11:27:13 +0000
Subject: [PATCH 09/18] lxd/storage/lvm: LVMGetLVCount usage
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/storage_lvm.go | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lxd/storage_lvm.go b/lxd/storage_lvm.go
index c629987a6c..044f77d98a 100644
--- a/lxd/storage_lvm.go
+++ b/lxd/storage_lvm.go
@@ -285,7 +285,7 @@ func (s *storageLvm) StoragePoolCreate() error {
if vgExisted {
// Check that the volume group is empty.
// Otherwise we will refuse to use it.
- count, err := lvmGetLVCount(poolName)
+ count, err := drivers.LVMGetLVCount(poolName)
if err != nil {
logger.Errorf("Failed to determine whether the volume group \"%s\" is empty", poolName)
return err
@@ -381,7 +381,7 @@ func (s *storageLvm) StoragePoolDelete() error {
// assume that other users are using the volume group, so don't remove
// it. This actually goes against policy since we explicitly state: our
// pool, and nothing but our pool but still, let's not hurt users.
- count, err := lvmGetLVCount(poolName)
+ count, err := drivers.LVMGetLVCount(poolName)
if err != nil {
return err
}
From 7aff5a90fa0904e2da23255c09cb31d7ebd0407b Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Tue, 17 Dec 2019 11:28:00 +0000
Subject: [PATCH 10/18] lxd/storage/lvm: LVMThinpoolExists usage
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/storage_lvm.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lxd/storage_lvm.go b/lxd/storage_lvm.go
index 044f77d98a..f3a169c4e8 100644
--- a/lxd/storage_lvm.go
+++ b/lxd/storage_lvm.go
@@ -297,7 +297,7 @@ func (s *storageLvm) StoragePoolCreate() error {
}
if count > 0 && s.useThinpool {
- ok, err := storageLVMThinpoolExists(poolName, s.thinPoolName)
+ ok, err := drivers.LVMThinpoolExists(poolName, s.thinPoolName)
if err != nil {
logger.Errorf("Failed to determine whether thinpool \"%s\" exists in volume group \"%s\": %s", poolName, s.thinPoolName, err)
return err
From 8b6704a10826479c52f131e22b097d4f817bc1ef Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Tue, 17 Dec 2019 11:28:44 +0000
Subject: [PATCH 11/18] lxd/storage/lvm: LVMCreateThinpool usage
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/storage_lvm.go | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/lxd/storage_lvm.go b/lxd/storage_lvm.go
index f3a169c4e8..122e2689fd 100644
--- a/lxd/storage_lvm.go
+++ b/lxd/storage_lvm.go
@@ -508,7 +508,7 @@ func (s *storageLvm) StoragePoolVolumeCreate() error {
}
if s.useThinpool {
- err = lvmCreateThinpool(s.s, s.sTypeVersion, poolName, thinPoolName, lvFsType)
+ err = drivers.LVMCreateThinpool(s.sTypeVersion, poolName, thinPoolName)
if err != nil {
return err
}
@@ -1833,7 +1833,7 @@ func (s *storageLvm) doContainerBackupLoad(projectName, containerName string, pr
poolName := s.getOnDiskPoolName()
if s.useThinpool {
- err = lvmCreateThinpool(s.s, s.sTypeVersion, poolName, thinPoolName, lvFsType)
+ err = drivers.LVMCreateThinpool(s.sTypeVersion, poolName, thinPoolName)
if err != nil {
return "", err
}
@@ -1921,7 +1921,7 @@ func (s *storageLvm) ImageCreate(fingerprint string, tracker *ioprogress.Progres
}()
if s.useThinpool {
- err = lvmCreateThinpool(s.s, s.sTypeVersion, poolName, thinPoolName, lvFsType)
+ err = drivers.LVMCreateThinpool(s.sTypeVersion, poolName, thinPoolName)
if err != nil {
return err
}
From 5844672725204ad398d2ecb656a7a19ba4ea69d0 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Tue, 17 Dec 2019 11:29:22 +0000
Subject: [PATCH 12/18] lxd/storage/lvm: LVMCreateLogicalVolume usage
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/storage_lvm.go | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/lxd/storage_lvm.go b/lxd/storage_lvm.go
index 122e2689fd..19c53c67e9 100644
--- a/lxd/storage_lvm.go
+++ b/lxd/storage_lvm.go
@@ -514,7 +514,7 @@ func (s *storageLvm) StoragePoolVolumeCreate() error {
}
}
- err = lvmCreateLv("default", poolName, thinPoolName, volumeLvmName, lvFsType, lvSize, volumeType, s.useThinpool)
+ err = drivers.LVMCreateLogicalVolume("default", poolName, thinPoolName, volumeLvmName, lvFsType, lvSize, volumeType, s.useThinpool)
if err != nil {
return fmt.Errorf("Error Creating LVM LV for new image: %v", err)
}
@@ -950,13 +950,13 @@ func (s *storageLvm) ContainerCreate(container instance.Instance) error {
poolName := s.getOnDiskPoolName()
if s.useThinpool {
- err = lvmCreateThinpool(s.s, s.sTypeVersion, poolName, thinPoolName, lvFsType)
+ err = drivers.LVMCreateThinpool(s.sTypeVersion, poolName, thinPoolName)
if err != nil {
return err
}
}
- err = lvmCreateLv(container.Project(), poolName, thinPoolName, containerLvmName, lvFsType, lvSize, storagePoolVolumeAPIEndpointContainers, s.useThinpool)
+ err = drivers.LVMCreateLogicalVolume(container.Project(), poolName, thinPoolName, containerLvmName, lvFsType, lvSize, storagePoolVolumeAPIEndpointContainers, s.useThinpool)
if err != nil {
return err
}
@@ -1840,7 +1840,7 @@ func (s *storageLvm) doContainerBackupLoad(projectName, containerName string, pr
}
if !snapshot {
- err = lvmCreateLv(projectName, poolName, thinPoolName, containerLvmName, lvFsType, lvSize,
+ err = drivers.LVMCreateLogicalVolume(projectName, poolName, thinPoolName, containerLvmName, lvFsType, lvSize,
storagePoolVolumeAPIEndpointContainers, s.useThinpool)
} else {
cname, _, _ := shared.InstanceGetParentAndSnapshotName(containerName)
@@ -1926,7 +1926,7 @@ func (s *storageLvm) ImageCreate(fingerprint string, tracker *ioprogress.Progres
return err
}
- err = lvmCreateLv("default", poolName, thinPoolName, fingerprint, lvFsType, lvSize, storagePoolVolumeAPIEndpointImages, true)
+ err = drivers.LVMCreateLogicalVolume("default", poolName, thinPoolName, fingerprint, lvFsType, lvSize, storagePoolVolumeAPIEndpointImages, true)
if err != nil {
return fmt.Errorf("Error Creating LVM LV for new image: %v", err)
}
From 7162baf9b0e1a31abd809405c7c3ed900266e9aa Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Tue, 17 Dec 2019 11:30:06 +0000
Subject: [PATCH 13/18] lxd/storage/lvm: LVMDevPath usage
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/storage_lvm.go | 30 +++++++++++++++---------------
1 file changed, 15 insertions(+), 15 deletions(-)
diff --git a/lxd/storage_lvm.go b/lxd/storage_lvm.go
index 19c53c67e9..7f24cd04b5 100644
--- a/lxd/storage_lvm.go
+++ b/lxd/storage_lvm.go
@@ -554,7 +554,7 @@ func (s *storageLvm) StoragePoolVolumeDelete() error {
volumeLvmName := containerNameToLVName(s.volume.Name)
poolName := s.getOnDiskPoolName()
- customLvmDevPath := getLvmDevPath("default", poolName,
+ customLvmDevPath := drivers.LVMDevPath("default", poolName,
storagePoolVolumeAPIEndpointCustom, volumeLvmName)
lvExists, _ := storageLVExists(customLvmDevPath)
@@ -609,7 +609,7 @@ func (s *storageLvm) StoragePoolVolumeMount() (bool, error) {
if err != nil {
return false, err
}
- lvmVolumePath := getLvmDevPath("default", poolName, volumeType, volumeLvmName)
+ lvmVolumePath := drivers.LVMDevPath("default", poolName, volumeType, volumeLvmName)
customMountLockID := getCustomMountLockID(s.pool.Name, s.volume.Name)
lxdStorageMapLock.Lock()
@@ -929,8 +929,8 @@ func (s *storageLvm) StoragePoolVolumeRename(newName string) error {
func (s *storageLvm) ContainerStorageReady(container instance.Instance) bool {
containerLvmName := containerNameToLVName(container.Name())
poolName := s.getOnDiskPoolName()
- containerLvmPath := getLvmDevPath(container.Project(), poolName, storagePoolVolumeAPIEndpointContainers, containerLvmName)
- ok, _ := storageLVExists(containerLvmPath)
+ containerLvmPath := drivers.LVMDevPath(container.Project(), poolName, storagePoolVolumeAPIEndpointContainers, containerLvmName)
+ ok, _ := drivers.LVMVolumeExists(containerLvmPath)
return ok
}
@@ -1035,7 +1035,7 @@ func (s *storageLvm) ContainerCreateFromImage(container instance.Instance, finge
}
poolName := s.getOnDiskPoolName()
- containerLvDevPath := getLvmDevPath(container.Project(), poolName, storagePoolVolumeAPIEndpointContainers, containerLvmName)
+ containerLvDevPath := drivers.LVMDevPath(container.Project(), poolName, storagePoolVolumeAPIEndpointContainers, containerLvmName)
// Generate a new xfs's UUID
lvFsType := s.getLvmFilesystem()
msg, err := driver.FSGenerateNewUUID(lvFsType, containerLvDevPath)
@@ -1086,7 +1086,7 @@ func lvmContainerDeleteInternal(projectName, poolName string, ctName string, isS
}
}
- containerLvmDevPath := getLvmDevPath(projectName, vgName,
+ containerLvmDevPath := drivers.LVMDevPath(projectName, vgName,
storagePoolVolumeAPIEndpointContainers, containerLvmName)
lvExists, _ := storageLVExists(containerLvmDevPath)
@@ -1247,7 +1247,7 @@ func (s *storageLvm) doContainerMount(project, name string, snap bool) (bool, er
containerLvmName := containerNameToLVName(name)
lvFsType := s.getLvmFilesystem()
poolName := s.getOnDiskPoolName()
- containerLvmPath := getLvmDevPath(project, poolName, storagePoolVolumeAPIEndpointContainers, containerLvmName)
+ containerLvmPath := drivers.LVMDevPath(project, poolName, storagePoolVolumeAPIEndpointContainers, containerLvmName)
containerMntPoint := driver.GetContainerMountPoint(project, s.pool.Name, name)
if shared.IsSnapshot(name) {
containerMntPoint = driver.GetSnapshotMountPoint(project, s.pool.Name, name)
@@ -1583,7 +1583,7 @@ func (s *storageLvm) ContainerSnapshotStart(container instance.Instance) (bool,
poolName := s.getOnDiskPoolName()
containerName := container.Name()
containerLvmName := containerNameToLVName(containerName)
- containerLvmPath := getLvmDevPath(container.Project(), poolName, storagePoolVolumeAPIEndpointContainers, containerLvmName)
+ containerLvmPath := drivers.LVMDevPath(container.Project(), poolName, storagePoolVolumeAPIEndpointContainers, containerLvmName)
wasWritableAtCheck, err := lvmLvIsWritable(containerLvmPath)
if err != nil {
@@ -1642,7 +1642,7 @@ func (s *storageLvm) ContainerSnapshotStop(container instance.Instance) (bool, e
}
}
- containerLvmPath := getLvmDevPath(container.Project(), poolName, storagePoolVolumeAPIEndpointContainers, containerNameToLVName(containerName))
+ containerLvmPath := drivers.LVMDevPath(container.Project(), poolName, storagePoolVolumeAPIEndpointContainers, containerNameToLVName(containerName))
wasWritableAtCheck, err := lvmLvIsWritable(containerLvmPath)
if err != nil {
return false, err
@@ -1973,7 +1973,7 @@ func (s *storageLvm) ImageDelete(fingerprint string) error {
if s.useThinpool {
poolName := s.getOnDiskPoolName()
- imageLvmDevPath := getLvmDevPath("default", poolName,
+ imageLvmDevPath := drivers.LVMDevPath("default", poolName,
storagePoolVolumeAPIEndpointImages, fingerprint)
lvExists, _ := storageLVExists(imageLvmDevPath)
@@ -2022,7 +2022,7 @@ func (s *storageLvm) ImageMount(fingerprint string) (bool, error) {
}
poolName := s.getOnDiskPoolName()
- lvmVolumePath := getLvmDevPath("default", poolName, storagePoolVolumeAPIEndpointImages, fingerprint)
+ lvmVolumePath := drivers.LVMDevPath("default", poolName, storagePoolVolumeAPIEndpointImages, fingerprint)
mountFlags, mountOptions := drivers.ResolveMountOptions(s.getLvmMountOptions())
err := driver.TryMount(lvmVolumePath, imageMntPoint, lvmFstype, mountFlags, mountOptions)
if err != nil {
@@ -2092,11 +2092,11 @@ func (s *storageLvm) StorageEntitySetQuota(volumeType int, size int64, data inte
}
ctLvmName := containerNameToLVName(ctName)
- lvDevPath = getLvmDevPath("default", poolName, storagePoolVolumeAPIEndpointContainers, ctLvmName)
+ lvDevPath = drivers.LVMDevPath("default", poolName, storagePoolVolumeAPIEndpointContainers, ctLvmName)
mountpoint = driver.GetContainerMountPoint(c.Project(), s.pool.Name, ctName)
default:
customLvmName := containerNameToLVName(s.volume.Name)
- lvDevPath = getLvmDevPath("default", poolName, storagePoolVolumeAPIEndpointCustom, customLvmName)
+ lvDevPath = drivers.LVMDevPath("default", poolName, storagePoolVolumeAPIEndpointCustom, customLvmName)
mountpoint = driver.GetStoragePoolVolumeMountPoint(s.pool.Name, s.volume.Name)
}
@@ -2306,8 +2306,8 @@ func (s *storageLvm) StoragePoolVolumeSnapshotDelete() error {
}
poolName := s.getOnDiskPoolName()
- snapshotLVDevPath := getLvmDevPath("default", poolName, storagePoolVolumeAPIEndpointCustom, snapshotLVName)
- lvExists, _ := storageLVExists(snapshotLVDevPath)
+ snapshotLVDevPath := drivers.LVMDevPath("default", poolName, storagePoolVolumeAPIEndpointCustom, snapshotLVName)
+ lvExists, _ := drivers.LVMVolumeExists(snapshotLVDevPath)
if lvExists {
err := removeLV("default", poolName, storagePoolVolumeAPIEndpointCustom, snapshotLVName)
if err != nil {
From f8d6eade0ecd52b9bf5807b86a2818534797ce10 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Tue, 17 Dec 2019 11:30:23 +0000
Subject: [PATCH 14/18] lxd/storage/lvm: LVMVolumeExists usage
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/storage_lvm.go | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/lxd/storage_lvm.go b/lxd/storage_lvm.go
index 7f24cd04b5..36f21f52c6 100644
--- a/lxd/storage_lvm.go
+++ b/lxd/storage_lvm.go
@@ -556,7 +556,7 @@ func (s *storageLvm) StoragePoolVolumeDelete() error {
poolName := s.getOnDiskPoolName()
customLvmDevPath := drivers.LVMDevPath("default", poolName,
storagePoolVolumeAPIEndpointCustom, volumeLvmName)
- lvExists, _ := storageLVExists(customLvmDevPath)
+ lvExists, _ := drivers.LVMVolumeExists(customLvmDevPath)
if lvExists {
_, err := s.StoragePoolVolumeUmount()
@@ -1089,7 +1089,7 @@ func lvmContainerDeleteInternal(projectName, poolName string, ctName string, isS
containerLvmDevPath := drivers.LVMDevPath(projectName, vgName,
storagePoolVolumeAPIEndpointContainers, containerLvmName)
- lvExists, _ := storageLVExists(containerLvmDevPath)
+ lvExists, _ := drivers.LVMVolumeExists(containerLvmDevPath)
if lvExists {
err := removeLV(projectName, vgName, storagePoolVolumeAPIEndpointContainers, containerLvmName)
if err != nil {
@@ -1975,7 +1975,7 @@ func (s *storageLvm) ImageDelete(fingerprint string) error {
poolName := s.getOnDiskPoolName()
imageLvmDevPath := drivers.LVMDevPath("default", poolName,
storagePoolVolumeAPIEndpointImages, fingerprint)
- lvExists, _ := storageLVExists(imageLvmDevPath)
+ lvExists, _ := drivers.LVMVolumeExists(imageLvmDevPath)
if lvExists {
_, err := s.ImageUmount(fingerprint)
From a76b5e515c266a76bd60d08e201903a4417da22e Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Tue, 17 Dec 2019 11:31:37 +0000
Subject: [PATCH 15/18] lxd/storage/lvm/utils: Removes LVM utils moved to
storage pkg
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/storage_lvm_utils.go | 232 ---------------------------------------
1 file changed, 232 deletions(-)
diff --git a/lxd/storage_lvm_utils.go b/lxd/storage_lvm_utils.go
index ae3085f8e6..ca71f7df5b 100644
--- a/lxd/storage_lvm_utils.go
+++ b/lxd/storage_lvm_utils.go
@@ -3,10 +3,8 @@ package main
import (
"fmt"
"os"
- "os/exec"
"strconv"
"strings"
- "syscall"
"github.com/pkg/errors"
@@ -22,7 +20,6 @@ import (
"github.com/lxc/lxd/shared/api"
"github.com/lxc/lxd/shared/logger"
"github.com/lxc/lxd/shared/units"
- "github.com/lxc/lxd/shared/version"
)
func (s *storageLvm) lvExtend(lvPath string, lvSize int64, fsType string, fsMntPoint string, volumeType int, data interface{}) error {
@@ -577,16 +574,6 @@ func (s *storageLvm) containerCreateFromImageThinLv(c instance.Instance, fp stri
return nil
}
-func lvmGetLVCount(vgName string) (int, error) {
- output, err := shared.TryRunCommand("vgs", "--noheadings", "-o", "lv_count", vgName)
- if err != nil {
- return -1, err
- }
-
- output = strings.TrimSpace(output)
- return strconv.Atoi(output)
-}
-
func lvmLvIsWritable(lvName string) (bool, error) {
output, err := shared.TryRunCommand("lvs", "--noheadings", "-o", "lv_attr", lvName)
if err != nil {
@@ -615,68 +602,6 @@ func storageLVActivate(lvmVolumePath string) error {
return nil
}
-func storagePVExists(pvName string) (bool, error) {
- _, err := shared.RunCommand("pvs", "--noheadings", "-o", "lv_attr", pvName)
- if err != nil {
- runErr, ok := err.(shared.RunError)
- if ok {
- exitError, ok := runErr.Err.(*exec.ExitError)
- if ok {
- waitStatus := exitError.Sys().(syscall.WaitStatus)
- if waitStatus.ExitStatus() == 5 {
- // physical volume not found
- return false, nil
- }
- }
- }
- return false, fmt.Errorf("error checking for physical volume \"%s\"", pvName)
- }
-
- return true, nil
-}
-
-func storageVGExists(vgName string) (bool, error) {
- _, err := shared.RunCommand("vgs", "--noheadings", "-o", "lv_attr", vgName)
- if err != nil {
- runErr, ok := err.(shared.RunError)
- if ok {
- exitError, ok := runErr.Err.(*exec.ExitError)
- if ok {
- waitStatus := exitError.Sys().(syscall.WaitStatus)
- if waitStatus.ExitStatus() == 5 {
- // volume group not found
- return false, nil
- }
- }
- }
-
- return false, fmt.Errorf("error checking for volume group \"%s\"", vgName)
- }
-
- return true, nil
-}
-
-func storageLVExists(lvName string) (bool, error) {
- _, err := shared.RunCommand("lvs", "--noheadings", "-o", "lv_attr", lvName)
- if err != nil {
- runErr, ok := err.(shared.RunError)
- if ok {
- exitError, ok := runErr.Err.(*exec.ExitError)
- if ok {
- waitStatus := exitError.Sys().(syscall.WaitStatus)
- if waitStatus.ExitStatus() == 5 {
- // logical volume not found
- return false, nil
- }
- }
- }
-
- return false, fmt.Errorf("error checking for logical volume \"%s\"", lvName)
- }
-
- return true, nil
-}
-
func lvmGetLVSize(lvPath string) (string, error) {
msg, err := shared.TryRunCommand("lvs", "--noheadings", "-o", "size", "--nosuffix", "--units", "b", lvPath)
if err != nil {
@@ -695,32 +620,6 @@ func lvmGetLVSize(lvPath string) (string, error) {
return detectedSize, nil
}
-func storageLVMThinpoolExists(vgName string, poolName string) (bool, error) {
- output, err := shared.RunCommand("vgs", "--noheadings", "-o", "lv_attr", fmt.Sprintf("%s/%s", vgName, poolName))
- if err != nil {
- runErr, ok := err.(shared.RunError)
- if ok {
- exitError, ok := runErr.Err.(*exec.ExitError)
- if 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 pool \"%s\"", poolName)
- }
- // Found LV named poolname, check type:
- attrs := strings.TrimSpace(string(output[:]))
- if strings.HasPrefix(attrs, "t") {
- return true, nil
- }
-
- return false, fmt.Errorf("pool named \"%s\" exists but is not a thin pool", poolName)
-}
-
func storageLVMGetThinPoolUsers(s *state.State) ([]string, error) {
results := []string{}
@@ -808,15 +707,6 @@ func containerNameToLVName(containerName string) string {
return strings.Replace(lvName, shared.SnapshotDelimiter, "-", -1)
}
-func getLvmDevPath(projectName, lvmPool string, volumeType string, lvmVolume string) string {
- lvmVolume = project.Prefix(projectName, lvmVolume)
- if volumeType == "" {
- return fmt.Sprintf("/dev/%s/%s", lvmPool, lvmVolume)
- }
-
- return fmt.Sprintf("/dev/%s/%s_%s", lvmPool, volumeType, lvmVolume)
-}
-
func getLVName(lvmPool string, volumeType string, lvmVolume string) string {
if volumeType == "" {
return fmt.Sprintf("%s/%s", lvmPool, lvmVolume)
@@ -830,128 +720,6 @@ func getPrefixedLvName(projectName, volumeType string, lvmVolume string) string
return fmt.Sprintf("%s_%s", volumeType, lvmVolume)
}
-func lvmCreateLv(projectName, vgName string, thinPoolName string, lvName string, lvFsType string, lvSize string, volumeType string, makeThinLv bool) error {
- var output string
- var err error
-
- // Round the size to closest 512 bytes
- lvSizeInt, err := units.ParseByteSizeString(lvSize)
- if err != nil {
- return err
- }
-
- lvSizeInt = int64(lvSizeInt/512) * 512
- lvSizeString := units.GetByteSizeString(lvSizeInt, 0)
-
- lvmPoolVolumeName := getPrefixedLvName(projectName, volumeType, lvName)
- if makeThinLv {
- targetVg := fmt.Sprintf("%s/%s", vgName, thinPoolName)
- _, err = shared.TryRunCommand("lvcreate", "-Wy", "--yes", "--thin", "-n", lvmPoolVolumeName, "--virtualsize", lvSizeString, targetVg)
- } else {
- _, err = shared.TryRunCommand("lvcreate", "-Wy", "--yes", "-n", lvmPoolVolumeName, "--size", lvSizeString, vgName)
- }
- if err != nil {
- logger.Errorf("Could not create LV \"%s\": %v", lvmPoolVolumeName, err)
- return fmt.Errorf("Could not create thin LV named %s: %v", lvmPoolVolumeName, err)
- }
-
- fsPath := getLvmDevPath(projectName, vgName, volumeType, lvName)
-
- output, err = storageDrivers.MakeFSType(fsPath, lvFsType, nil)
- if err != nil {
- logger.Errorf("Filesystem creation failed: %v (%s)", err, output)
- return fmt.Errorf("Error making filesystem on image LV: %v (%s)", err, output)
- }
-
- return nil
-}
-
-func lvmCreateThinpool(s *state.State, 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(s, vgName, thinPoolName)
- if err != nil {
- logger.Errorf("Setting thin pool name: %s", err)
- return fmt.Errorf("Error setting LVM thin pool config: %v", err)
- }
-
- return nil
-}
-
-func createDefaultThinPool(sTypeVersion string, vgName string, thinPoolName string, lvFsType string) error {
- isRecent, err := lvmVersionIsAtLeast(sTypeVersion, "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)
- if isRecent {
- _, err = shared.TryRunCommand(
- "lvcreate",
- "-Wy", "--yes",
- "--poolmetadatasize", "1G",
- "-l", "100%FREE",
- "--thinpool", lvmThinPool)
- } else {
- _, err = shared.TryRunCommand(
- "lvcreate",
- "-Wy", "--yes",
- "--poolmetadatasize", "1G",
- "-L", "1G",
- "--thinpool", lvmThinPool)
- }
-
- if err != nil {
- logger.Errorf("Could not create thin pool \"%s\": %v", thinPoolName, err)
- return fmt.Errorf("Could not create LVM thin pool named %s: %v", thinPoolName, err)
- }
-
- if !isRecent {
- // Grow it to the maximum VG size (two step process required by old LVM)
- _, err = shared.TryRunCommand("lvextend", "--alloc", "anywhere", "-l", "100%FREE", lvmThinPool)
-
- if err != nil {
- logger.Errorf("Could not grow thin pool: \"%s\": %v", thinPoolName, err)
- return fmt.Errorf("Could not grow LVM thin pool named %s: %v", thinPoolName, err)
- }
- }
-
- return nil
-}
-
-func lvmVersionIsAtLeast(sTypeVersion string, versionString string) (bool, error) {
- lvmVersionString := strings.Split(sTypeVersion, "/")[0]
-
- lvmVersion, err := version.Parse(lvmVersionString)
- if err != nil {
- return false, err
- }
-
- inVersion, err := version.Parse(versionString)
- if err != nil {
- return false, err
- }
-
- if lvmVersion.Compare(inVersion) < 0 {
- return false, nil
- }
-
- return true, nil
-}
-
// Copy an LVM custom volume.
func (s *storageLvm) copyVolume(sourcePool string, source string) error {
targetMntPoint := driver.GetStoragePoolVolumeMountPoint(s.pool.Name, s.volume.Name)
From b766478db727e3378766fb285e679984330db118 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Tue, 17 Dec 2019 11:32:14 +0000
Subject: [PATCH 16/18] lxd/storage/lvm/utils: LVMDevPath usage
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/storage_lvm_utils.go | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/lxd/storage_lvm_utils.go b/lxd/storage_lvm_utils.go
index ca71f7df5b..dba9888a6a 100644
--- a/lxd/storage_lvm_utils.go
+++ b/lxd/storage_lvm_utils.go
@@ -177,7 +177,7 @@ func (s *storageLvm) renameLVByPath(project, oldName string, newName string, vol
}
func removeLV(project, vgName string, volumeType string, lvName string) error {
- lvmVolumePath := getLvmDevPath(project, vgName, volumeType, lvName)
+ lvmVolumePath := storageDrivers.LVMDevPath(project, vgName, volumeType, lvName)
_, err := shared.TryRunCommand("lvremove", "-f", lvmVolumePath)
if err != nil {
@@ -195,8 +195,8 @@ func (s *storageLvm) createSnapshotLV(project, vgName string, origLvName string,
sourceProject = "default"
}
- sourceLvmVolumePath := getLvmDevPath(sourceProject, vgName, origVolumeType, origLvName)
- isRecent, err := lvmVersionIsAtLeast(s.sTypeVersion, "2.02.99")
+ sourceLvmVolumePath := storageDrivers.LVMDevPath(sourceProject, vgName, origVolumeType, origLvName)
+ isRecent, err := storageDrivers.LVMVersionIsAtLeast(s.sTypeVersion, "2.02.99")
if err != nil {
return "", fmt.Errorf("Error checking LVM version: %v", err)
}
@@ -241,7 +241,7 @@ func (s *storageLvm) createSnapshotLV(project, vgName string, origLvName string,
return "", fmt.Errorf("Could not create snapshot LV named %s: %v", lvName, err)
}
- targetLvmVolumePath := getLvmDevPath(project, vgName, volumeType, lvName)
+ targetLvmVolumePath := storageDrivers.LVMDevPath(project, vgName, volumeType, lvName)
if makeThinLv {
// Snapshots of thin logical volumes can be directly activated.
// Normal snapshots will complain about changing the origin
@@ -315,7 +315,7 @@ func (s *storageLvm) copyContainerThinpool(target instance.Instance, source inst
poolName := s.getOnDiskPoolName()
containerName := target.Name()
containerLvmName := containerNameToLVName(containerName)
- containerLvDevPath := getLvmDevPath(target.Project(), poolName,
+ containerLvDevPath := storageDrivers.LVMDevPath(target.Project(), poolName,
storagePoolVolumeAPIEndpointContainers, containerLvmName)
// If btrfstune sees two btrfs filesystems with the same UUID it
@@ -518,7 +518,7 @@ func (s *storageLvm) containerCreateFromImageLv(c instance.Instance, fp string)
func (s *storageLvm) containerCreateFromImageThinLv(c instance.Instance, fp string) error {
poolName := s.getOnDiskPoolName()
// Check if the image already exists.
- imageLvmDevPath := getLvmDevPath("default", poolName, storagePoolVolumeAPIEndpointImages, fp)
+ imageLvmDevPath := storageDrivers.LVMDevPath("default", poolName, storagePoolVolumeAPIEndpointImages, fp)
imageStoragePoolLockID := getImageCreateLockID(poolName, fp)
lxdStorageMapLock.Lock()
@@ -847,7 +847,7 @@ func (s *storageLvm) copyVolumeThinpool(source string, target string, readOnly b
return err
}
- lvDevPath := getLvmDevPath("default", poolName, storagePoolVolumeAPIEndpointCustom, targetLvmName)
+ lvDevPath := storageDrivers.LVMDevPath("default", poolName, storagePoolVolumeAPIEndpointCustom, targetLvmName)
msg, err := driver.FSGenerateNewUUID(lvFsType, lvDevPath)
if err != nil {
From 695324fe7d32e87e05eb449488efba6d0054526a Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Tue, 17 Dec 2019 11:32:33 +0000
Subject: [PATCH 17/18] lxd/storage/lvm/utils: LVMVolumeExists usage
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/storage_lvm_utils.go | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lxd/storage_lvm_utils.go b/lxd/storage_lvm_utils.go
index dba9888a6a..e0ae2c3329 100644
--- a/lxd/storage_lvm_utils.go
+++ b/lxd/storage_lvm_utils.go
@@ -371,7 +371,7 @@ func (s *storageLvm) copySnapshot(target instance.Instance, source instance.Inst
// Copy a container on a storage pool that does not use a thinpool.
func (s *storageLvm) copyContainerLv(target instance.Instance, source instance.Instance, readonly bool, refresh bool) error {
- exists, err := storageLVExists(getLvmDevPath(target.Project(), s.getOnDiskPoolName(),
+ exists, err := storageDrivers.LVMVolumeExists(storageDrivers.LVMDevPath(target.Project(), s.getOnDiskPoolName(),
storagePoolVolumeAPIEndpointContainers, containerNameToLVName(target.Name())))
if err != nil {
return err
@@ -532,7 +532,7 @@ func (s *storageLvm) containerCreateFromImageThinLv(c instance.Instance, fp stri
lxdStorageMapLock.Unlock()
var imgerr error
- ok, _ := storageLVExists(imageLvmDevPath)
+ ok, _ := storageDrivers.LVMVolumeExists(imageLvmDevPath)
if ok {
_, volume, err := s.s.Cluster.StoragePoolNodeVolumeGetType(fp, db.StoragePoolVolumeTypeImage, s.poolID)
if err != nil {
From 998e2a7846647fe9dca7a6783221e2473ba6712a Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Tue, 17 Dec 2019 11:32:54 +0000
Subject: [PATCH 18/18] lxd/storage/lvm/utils: LVMThinpoolExists usage
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/storage_lvm_utils.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lxd/storage_lvm_utils.go b/lxd/storage_lvm_utils.go
index e0ae2c3329..a7d52ad7eb 100644
--- a/lxd/storage_lvm_utils.go
+++ b/lxd/storage_lvm_utils.go
@@ -671,7 +671,7 @@ func storageLVMValidateThinPoolName(s *state.State, vgName string, value string)
return fmt.Errorf("can not set lvm.thinpool_name without lvm.vg_name set")
}
- poolExists, err := storageLVMThinpoolExists(vgName, value)
+ poolExists, err := storageDrivers.LVMThinpoolExists(vgName, value)
if err != nil {
return fmt.Errorf("error checking for thin pool \"%s\" in \"%s\": %v", value, vgName, err)
}
More information about the lxc-devel
mailing list