[lxc-devel] [lxd/master] patches: detect logical volume size
brauner on Github
lxc-bot at linuxcontainers.org
Tue Mar 7 23:44:12 UTC 2017
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 384 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20170307/7a8dab66/attachment.bin>
-------------- next part --------------
From fa23309bb02473491c7be5db9e8220b786df614a Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Wed, 8 Mar 2017 00:42:59 +0100
Subject: [PATCH] patches: detect logical volume size
Addresses #3036.
Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
lxd/patches.go | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
lxd/storage_lvm.go | 18 +++++++++++
2 files changed, 110 insertions(+)
diff --git a/lxd/patches.go b/lxd/patches.go
index 3c527ba..4105ebe 100644
--- a/lxd/patches.go
+++ b/lxd/patches.go
@@ -40,6 +40,7 @@ var patches = []patch{
{name: "storage_api_keys", run: patchStorageApiKeys},
{name: "storage_api_update_storage_configs", run: patchStorageApiUpdateStorageConfigs},
{name: "storage_api_lxd_on_btrfs", run: patchStorageApiLxdOnBtrfs},
+ {name: "storage_api_lvm_detect_lv_size", run: patchStorageApiDetectLVSize},
}
type patch struct {
@@ -2130,3 +2131,94 @@ func patchStorageApiLxdOnBtrfs(name string, d *Daemon) error {
return nil
}
+
+func patchStorageApiDetectLVSize(name string, d *Daemon) error {
+ pools, err := dbStoragePools(d.db)
+ if err != nil {
+ if err == NoSuchObjectError {
+ return nil
+ }
+ shared.LogErrorf("Failed to query database: %s", err)
+ return err
+ }
+
+ for _, poolName := range pools {
+ poolID, pool, err := dbStoragePoolGet(d.db, poolName)
+ if err != nil {
+ shared.LogErrorf("Failed to query database: %s", err)
+ return err
+ }
+
+ // Make sure that config is not empty.
+ if pool.Config == nil {
+ pool.Config = map[string]string{}
+
+ // Insert default values.
+ err = storagePoolFillDefault(poolName, pool.Driver, pool.Config)
+ if err != nil {
+ return err
+ }
+ }
+
+ // We're only interested in LVM pools.
+ if pool.Driver != "lvm" {
+ continue
+ }
+
+ // Get all storage volumes on the storage pool.
+ volumes, err := dbStoragePoolVolumesGet(d.db, poolID, supportedVolumeTypes)
+ if err != nil {
+ if err == NoSuchObjectError {
+ continue
+ }
+ return err
+ }
+
+ poolName := pool.Config["lvm.vg_name"]
+ if poolName == "" {
+ shared.LogErrorf("The \"lvm.vg_name\" key should not be empty.")
+ return fmt.Errorf("The \"lvm.vg_name\" key should not be empty.")
+ }
+
+ for _, volume := range volumes {
+ // Make sure that config is not empty.
+ if volume.Config == nil {
+ volume.Config = map[string]string{}
+
+ // Insert default values.
+ err := storageVolumeFillDefault(volume.Name, volume.Config, pool)
+ if err != nil {
+ return err
+ }
+ }
+
+ // It shouldn't be possible that false volume types
+ // exist in the db, so it's safe to ignore the error.
+ volumeTypeApiEndpoint, _ := storagePoolVolumeTypeNameToApiEndpoint(volume.Type)
+ lvmName := containerNameToLVName(volume.Name)
+ lvmLvDevPath := getLvmDevPath(poolName, volumeTypeApiEndpoint, lvmName)
+ size, err := lvmGetLVSize(lvmLvDevPath)
+ if err != nil {
+ shared.LogErrorf("Failed to detect size of logical volume: %s.", err)
+ return err
+ }
+
+ if volume.Config["size"] == size {
+ continue
+ }
+
+ volume.Config["size"] = size
+
+ // It shouldn't be possible that false volume types
+ // exist in the db, so it's safe to ignore the error.
+ volumeType, _ := storagePoolVolumeTypeNameToType(volume.Type)
+ // Update the volume config.
+ err = dbStoragePoolVolumeUpdate(d.db, volume.Name, volumeType, poolID, volume.Config)
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ return nil
+}
diff --git a/lxd/storage_lvm.go b/lxd/storage_lvm.go
index 60ecaa5..2784156 100644
--- a/lxd/storage_lvm.go
+++ b/lxd/storage_lvm.go
@@ -88,6 +88,24 @@ func storageLVExists(lvName string) (bool, error) {
return true, nil
}
+func lvmGetLVSize(lvPath string) (string, error) {
+ msg, err := shared.TryRunCommand("lvs", "--noheadings", "-o", "size", "--nosuffix", "--units", "b", lvPath)
+ if err != nil {
+ return "", fmt.Errorf("Failed to retrieve size of logical volume: %s: %s.", string(msg), err)
+ }
+
+ sizeString := string(msg)
+ sizeString = strings.TrimSpace(sizeString)
+ size, err := strconv.ParseInt(sizeString, 10, 64)
+ if err != nil {
+ return "", err
+ }
+
+ detectedSize := shared.GetByteSizeString(size, 0)
+
+ return detectedSize, 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 {
More information about the lxc-devel
mailing list