Returns thin pool free space calculated from actual usage
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
This commit is contained in:
parent
d72914f739
commit
1679acd53d
|
@ -64,6 +64,7 @@ class LVM(executor.Executor):
|
||||||
self.vg_uuid = None
|
self.vg_uuid = None
|
||||||
self.vg_thin_pool = None
|
self.vg_thin_pool = None
|
||||||
self.vg_thin_pool_size = 0
|
self.vg_thin_pool_size = 0
|
||||||
|
self.vg_thin_pool_free_space = 0
|
||||||
self._supports_snapshot_lv_activation = None
|
self._supports_snapshot_lv_activation = None
|
||||||
self._supports_lvchange_ignoreskipactivation = None
|
self._supports_lvchange_ignoreskipactivation = None
|
||||||
|
|
||||||
|
@ -121,6 +122,41 @@ class LVM(executor.Executor):
|
||||||
else:
|
else:
|
||||||
return []
|
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
|
@staticmethod
|
||||||
def get_lvm_version(root_helper):
|
def get_lvm_version(root_helper):
|
||||||
"""Static method to get LVM version from system.
|
"""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):
|
for lv in self.get_all_volumes(self._root_helper, self.vg_name):
|
||||||
if lv['name'] == self.vg_thin_pool:
|
if lv['name'] == self.vg_thin_pool:
|
||||||
self.vg_thin_pool_size = lv['size']
|
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):
|
def _calculate_thin_pool_size(self):
|
||||||
"""Calculates the correct size for a thin pool.
|
"""Calculates the correct size for a thin pool.
|
||||||
|
|
|
@ -101,6 +101,9 @@ class BrickLvmTestCase(test.TestCase):
|
||||||
data = " fake-volumes:/dev/sda:10.00g:8.99g\n"
|
data = " fake-volumes:/dev/sda:10.00g:8.99g\n"
|
||||||
data += " fake-volumes-2:/dev/sdb: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"
|
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:
|
else:
|
||||||
raise AssertionError('unexpected command called: %s' % cmd_string)
|
raise AssertionError('unexpected command called: %s' % cmd_string)
|
||||||
|
|
||||||
|
@ -225,6 +228,13 @@ class BrickLvmTestCase(test.TestCase):
|
||||||
for size in ("1g", "1.2g", "1.75g"):
|
for size in ("1g", "1.2g", "1.75g"):
|
||||||
self.assertEqual(size, self.vg.create_thin_pool(size_str=size))
|
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):
|
def test_volume_create_after_thin_creation(self):
|
||||||
"""Test self.vg.vg_thin_pool is set to pool_name
|
"""Test self.vg.vg_thin_pool is set to pool_name
|
||||||
|
|
||||||
|
|
|
@ -368,6 +368,9 @@ class LVMVolumeDriver(driver.VolumeDriver):
|
||||||
|
|
||||||
data['total_capacity_gb'] = float(self.vg.vg_size)
|
data['total_capacity_gb'] = float(self.vg.vg_size)
|
||||||
data['free_capacity_gb'] = float(self.vg.vg_free_space)
|
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['reserved_percentage'] = self.configuration.reserved_percentage
|
||||||
data['QoS_support'] = False
|
data['QoS_support'] = False
|
||||||
data['location_info'] =\
|
data['location_info'] =\
|
||||||
|
|
Loading…
Reference in New Issue