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")
|
||||
|
||||
@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):
|
||||
''' Helper for emitting helpful `NotImplementedError` exceptions '''
|
||||
msg = "Pool driver {!s} has {!s}() not implemented"
|
||||
|
@ -144,6 +144,16 @@ class FilePool(qubes.storage.Pool):
|
||||
def list_volumes(self):
|
||||
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):
|
||||
''' Parent class for the xen volumes implementation which expects a
|
||||
|
@ -137,6 +137,22 @@ class ThinPool(qubes.storage.Pool):
|
||||
volumes += [ThinVolume(**config)]
|
||||
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')):
|
||||
cmd = ['lvs', '--noheadings', '-o',
|
||||
@ -159,7 +175,7 @@ def init_cache(log=logging.getLogger('qubes.storage.lvm')):
|
||||
line = line.decode().strip()
|
||||
pool_name, pool_lv, name, size, usage_percent, attr, \
|
||||
origin = line.split(';', 6)
|
||||
if '' in [pool_name, pool_lv, name, size, usage_percent]:
|
||||
if '' in [pool_name, name, size, usage_percent]:
|
||||
continue
|
||||
name = pool_name + "/" + name
|
||||
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)
|
||||
|
||||
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):
|
||||
""" Check if all the needed image files are created for an AppVm"""
|
||||
|
||||
|
@ -26,6 +26,7 @@
|
||||
'''
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
import unittest
|
||||
|
||||
import qubes.tests
|
||||
@ -158,6 +159,26 @@ class TC_00_ThinPool(ThinPoolBase):
|
||||
self.assertTrue(os.path.exists(path))
|
||||
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
|
||||
class TC_01_ThinPool(ThinPoolBase, qubes.tests.SystemTestCase):
|
||||
''' Sanity tests for :py:class:`qubes.storage.lvm.ThinPool` '''
|
||||
|
Loading…
Reference in New Issue
Block a user