]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
Returns thin pool free space calculated from actual usage
authorGiulio Fidente <gfidente@redhat.com>
Tue, 3 Dec 2013 12:44:20 +0000 (13:44 +0100)
committerGiulio Fidente <gfidente@redhat.com>
Fri, 6 Dec 2013 00:09:53 +0000 (01:09 +0100)
This change adds a hidden method which calculates the thin
pool free space from the data_percent LVM options and reports it
accordingly in _update_volume_stats()

Change-Id: Id6a69644505ca10811db458ea90ed10f643054b2
Closes-Bug: 1249782

cinder/brick/local_dev/lvm.py
cinder/tests/brick/test_brick_lvm.py
cinder/volume/drivers/lvm.py

index 433251e2d60c700719547f87448e26eb57a94d56..d0f41097dca2a7c2d1272bd5789dffeaa8382602 100644 (file)
@@ -64,6 +64,7 @@ class LVM(executor.Executor):
         self.vg_uuid = None
         self.vg_thin_pool = None
         self.vg_thin_pool_size = 0
+        self.vg_thin_pool_free_space = 0
         self._supports_snapshot_lv_activation = None
         self._supports_lvchange_ignoreskipactivation = None
 
@@ -121,6 +122,41 @@ class LVM(executor.Executor):
         else:
             return []
 
+    def _get_thin_pool_free_space(self, vg_name, thin_pool_name):
+        """Returns available thin pool free space.
+
+        :param vg_name: the vg where the pool is placed
+        :param thin_pool_name: the thin pool to gather info for
+        :returns: Free space, calculated after the data_percent value
+
+        """
+        cmd = ['env', 'LC_ALL=C', 'LANG=C', 'lvs', '--noheadings', '--unit=g',
+               '-o', 'size,data_percent', '--separator', ':', '--nosuffix']
+
+        # NOTE(gfidente): data_percent only applies to some types of LV so we
+        # make sure to append the actual thin pool name
+        cmd.append("/dev/%s/%s" % (vg_name, thin_pool_name))
+
+        free_space = 0
+
+        try:
+            (out, err) = self._execute(*cmd,
+                                       root_helper=self._root_helper,
+                                       run_as_root=True)
+            if out is not None:
+                out = out.strip()
+                data = out.split(':')
+                consumed_space = float(data[0]) / 100 * (float(data[1]))
+                free_space = float(data[0]) - consumed_space
+                free_space = round(free_space, 2)
+        except putils.ProcessExecutionError as err:
+            LOG.exception(_('Error querying thin pool about data_percent'))
+            LOG.error(_('Cmd     :%s') % err.cmd)
+            LOG.error(_('StdOut  :%s') % err.stdout)
+            LOG.error(_('StdErr  :%s') % err.stderr)
+
+        return free_space
+
     @staticmethod
     def get_lvm_version(root_helper):
         """Static method to get LVM version from system.
@@ -355,6 +391,9 @@ class LVM(executor.Executor):
             for lv in self.get_all_volumes(self._root_helper, self.vg_name):
                 if lv['name'] == self.vg_thin_pool:
                     self.vg_thin_pool_size = lv['size']
+                    tpfs = self._get_thin_pool_free_space(self.vg_name,
+                                                          self.vg_thin_pool)
+                    self.vg_thin_pool_free_space = tpfs
 
     def _calculate_thin_pool_size(self):
         """Calculates the correct size for a thin pool.
index beb60ecd93c30ee2561059a84f1f5f92eb90ed97..6a6f3acb48923da70e2963fa9ee8616f80e31850 100644 (file)
@@ -101,6 +101,9 @@ class BrickLvmTestCase(test.TestCase):
             data = "  fake-volumes:/dev/sda:10.00g:8.99g\n"
             data += "  fake-volumes-2:/dev/sdb:10.00g:8.99g\n"
             data += "  fake-volumes-3:/dev/sdc:10.00g:8.99g\n"
+        elif 'lvs, --noheadings, --unit=g, -o, size,data_percent, ' \
+             '--separator, :' in cmd_string:
+            data = "  9:12\n"
         else:
             raise AssertionError('unexpected command called: %s' % cmd_string)
 
@@ -225,6 +228,13 @@ class BrickLvmTestCase(test.TestCase):
         for size in ("1g", "1.2g", "1.75g"):
             self.assertEqual(size, self.vg.create_thin_pool(size_str=size))
 
+    def test_thin_pool_free_space(self):
+        # The size of fake-volumes-pool is 9g and the allocated data sums up to
+        # 12% so the calculated free space should be 7.92
+        self.assertEqual(float("7.92"),
+                         self.vg._get_thin_pool_free_space("fake-vg",
+                                                           "fake-vg-pool"))
+
     def test_volume_create_after_thin_creation(self):
         """Test self.vg.vg_thin_pool is set to pool_name
 
index 29fc556fca56cf320b894c7d1f1d31b1fa316246..0c1b65992bf636427801e7c5943bb9526ccb12f9 100644 (file)
@@ -368,6 +368,9 @@ class LVMVolumeDriver(driver.VolumeDriver):
 
         data['total_capacity_gb'] = float(self.vg.vg_size)
         data['free_capacity_gb'] = float(self.vg.vg_free_space)
+        if self.configuration.lvm_type == 'thin':
+            data['total_capacity_gb'] = float(self.vg.vg_thin_pool_size)
+            data['free_capacity_gb'] = float(self.vg.vg_thin_pool_free_space)
         data['reserved_percentage'] = self.configuration.reserved_percentage
         data['QoS_support'] = False
         data['location_info'] =\