storage: add size and usage properties to pool object
Add Pool.size and Pool.usage to the API. Implement them for LVM and File pools. Add appropriate tests. QubesOS/qubes-issues#3240
This commit is contained in:
parent
682d9503ee
commit
e76372b934
@ -815,6 +815,16 @@ class Pool(object):
|
|||||||
'''
|
'''
|
||||||
raise self._not_implemented("get_volume")
|
raise self._not_implemented("get_volume")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def size(self):
|
||||||
|
''' Storage pool size in bytes '''
|
||||||
|
raise self._not_implemented("size")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def usage(self):
|
||||||
|
''' Space used in the pool, in bytes '''
|
||||||
|
raise self._not_implemented("usage")
|
||||||
|
|
||||||
def _not_implemented(self, method_name):
|
def _not_implemented(self, method_name):
|
||||||
''' Helper for emitting helpful `NotImplementedError` exceptions '''
|
''' Helper for emitting helpful `NotImplementedError` exceptions '''
|
||||||
msg = "Pool driver {!s} has {!s}() not implemented"
|
msg = "Pool driver {!s} has {!s}() not implemented"
|
||||||
|
@ -144,6 +144,16 @@ class FilePool(qubes.storage.Pool):
|
|||||||
def list_volumes(self):
|
def list_volumes(self):
|
||||||
return self._volumes
|
return self._volumes
|
||||||
|
|
||||||
|
@property
|
||||||
|
def size(self):
|
||||||
|
statvfs = os.statvfs(self.dir_path)
|
||||||
|
return statvfs.f_frsize * statvfs.f_blocks
|
||||||
|
|
||||||
|
@property
|
||||||
|
def usage(self):
|
||||||
|
statvfs = os.statvfs(self.dir_path)
|
||||||
|
return statvfs.f_frsize * (statvfs.f_blocks - statvfs.f_bfree)
|
||||||
|
|
||||||
|
|
||||||
class FileVolume(qubes.storage.Volume):
|
class FileVolume(qubes.storage.Volume):
|
||||||
''' Parent class for the xen volumes implementation which expects a
|
''' Parent class for the xen volumes implementation which expects a
|
||||||
|
@ -137,6 +137,22 @@ class ThinPool(qubes.storage.Pool):
|
|||||||
volumes += [ThinVolume(**config)]
|
volumes += [ThinVolume(**config)]
|
||||||
return volumes
|
return volumes
|
||||||
|
|
||||||
|
@property
|
||||||
|
def size(self):
|
||||||
|
try:
|
||||||
|
return qubes.storage.lvm.size_cache[
|
||||||
|
self.volume_group + '/' + self.thin_pool]['size']
|
||||||
|
except KeyError:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
@property
|
||||||
|
def usage(self):
|
||||||
|
try:
|
||||||
|
return qubes.storage.lvm.size_cache[
|
||||||
|
self.volume_group + '/' + self.thin_pool]['usage']
|
||||||
|
except KeyError:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
def init_cache(log=logging.getLogger('qubes.storage.lvm')):
|
def init_cache(log=logging.getLogger('qubes.storage.lvm')):
|
||||||
cmd = ['lvs', '--noheadings', '-o',
|
cmd = ['lvs', '--noheadings', '-o',
|
||||||
@ -159,7 +175,7 @@ def init_cache(log=logging.getLogger('qubes.storage.lvm')):
|
|||||||
line = line.decode().strip()
|
line = line.decode().strip()
|
||||||
pool_name, pool_lv, name, size, usage_percent, attr, \
|
pool_name, pool_lv, name, size, usage_percent, attr, \
|
||||||
origin = line.split(';', 6)
|
origin = line.split(';', 6)
|
||||||
if '' in [pool_name, pool_lv, name, size, usage_percent]:
|
if '' in [pool_name, name, size, usage_percent]:
|
||||||
continue
|
continue
|
||||||
name = pool_name + "/" + name
|
name = pool_name + "/" + name
|
||||||
size = int(size[:-1]) # Remove 'B' suffix
|
size = int(size[:-1]) # Remove 'B' suffix
|
||||||
|
@ -369,6 +369,21 @@ class TC_03_FilePool(qubes.tests.QubesTestCase):
|
|||||||
|
|
||||||
shutil.rmtree(pool_dir, ignore_errors=True)
|
shutil.rmtree(pool_dir, ignore_errors=True)
|
||||||
|
|
||||||
|
def test_003_size(self):
|
||||||
|
pool = self.app.get_pool(self.POOL_NAME)
|
||||||
|
with self.assertNotRaises(NotImplementedError):
|
||||||
|
size = pool.size
|
||||||
|
statvfs = os.statvfs(self.POOL_DIR)
|
||||||
|
self.assertEqual(size, statvfs.f_blocks * statvfs.f_frsize)
|
||||||
|
|
||||||
|
def test_004_usage(self):
|
||||||
|
pool = self.app.get_pool(self.POOL_NAME)
|
||||||
|
with self.assertNotRaises(NotImplementedError):
|
||||||
|
usage = pool.usage
|
||||||
|
statvfs = os.statvfs(self.POOL_DIR)
|
||||||
|
self.assertEqual(usage,
|
||||||
|
statvfs.f_frsize * (statvfs.f_blocks - statvfs.f_bfree))
|
||||||
|
|
||||||
def test_011_appvm_file_images(self):
|
def test_011_appvm_file_images(self):
|
||||||
""" Check if all the needed image files are created for an AppVm"""
|
""" Check if all the needed image files are created for an AppVm"""
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
import subprocess
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
import qubes.tests
|
import qubes.tests
|
||||||
@ -158,6 +159,26 @@ class TC_00_ThinPool(ThinPoolBase):
|
|||||||
self.assertTrue(os.path.exists(path))
|
self.assertTrue(os.path.exists(path))
|
||||||
volume.remove()
|
volume.remove()
|
||||||
|
|
||||||
|
def test_004_size(self):
|
||||||
|
with self.assertNotRaises(NotImplementedError):
|
||||||
|
size = self.pool.size
|
||||||
|
pool_size = subprocess.check_output(['sudo', 'lvs', '--noheadings',
|
||||||
|
'-o', 'lv_size',
|
||||||
|
'--units', 'b', self.pool.volume_group + '/' + self.pool.thin_pool])
|
||||||
|
self.assertEqual(size, int(pool_size.strip()[:-1]))
|
||||||
|
|
||||||
|
def test_005_usage(self):
|
||||||
|
with self.assertNotRaises(NotImplementedError):
|
||||||
|
usage = self.pool.usage
|
||||||
|
pool_info = subprocess.check_output(['sudo', 'lvs', '--noheadings',
|
||||||
|
'-o', 'lv_size,data_percent',
|
||||||
|
'--units', 'b', self.pool.volume_group + '/' + self.pool.thin_pool])
|
||||||
|
pool_size, pool_usage = pool_info.strip().split()
|
||||||
|
pool_size = int(pool_size[:-1])
|
||||||
|
pool_usage = float(pool_usage)
|
||||||
|
self.assertEqual(usage, int(pool_size * pool_usage / 100))
|
||||||
|
|
||||||
|
|
||||||
@skipUnlessLvmPoolExists
|
@skipUnlessLvmPoolExists
|
||||||
class TC_01_ThinPool(ThinPoolBase, qubes.tests.SystemTestCase):
|
class TC_01_ThinPool(ThinPoolBase, qubes.tests.SystemTestCase):
|
||||||
''' Sanity tests for :py:class:`qubes.storage.lvm.ThinPool` '''
|
''' Sanity tests for :py:class:`qubes.storage.lvm.ThinPool` '''
|
||||||
|
Loading…
Reference in New Issue
Block a user