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

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) ===
Addresses #3036.

Signed-off-by: Christian Brauner <christian.brau...@ubuntu.com>
From fa23309bb02473491c7be5db9e8220b786df614a Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brau...@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.brau...@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 {
_______________________________________________
lxc-devel mailing list
lxc-devel@lists.linuxcontainers.org
http://lists.linuxcontainers.org/listinfo/lxc-devel

Reply via email to