storage: add Pool.included_in() method for checking nested pools
It may happen that one pool is inside a volume of other pool. This is the case for example for varlibqubes pool (file driver, dir_path=/var/lib/qubes) and default lvm pool (lvm_thin driver). The latter include whole root filesystem, so /var/lib/qubes too. This is relevant for proper disk space calculation - to not count some space twice. QubesOS/qubes-issues#3240 QubesOS/qubes-issues#3241
This commit is contained in:
parent
99f430511a
commit
d40fae9756
@ -815,6 +815,17 @@ class Pool(object):
|
||||
'''
|
||||
raise self._not_implemented("get_volume")
|
||||
|
||||
def included_in(self, app):
|
||||
''' Check if this pool is physically included in another one
|
||||
|
||||
This works on best-effort basis, because one pool driver may not know
|
||||
all the other drivers.
|
||||
|
||||
:param app: Qubes() object to lookup other pools in
|
||||
:returns pool or None
|
||||
'''
|
||||
pass
|
||||
|
||||
@property
|
||||
def size(self):
|
||||
''' Storage pool size in bytes '''
|
||||
@ -865,6 +876,27 @@ def isodate(seconds=time.time()):
|
||||
''' Helper method which returns an iso date '''
|
||||
return datetime.utcfromtimestamp(seconds).isoformat("T")
|
||||
|
||||
def search_pool_containing_dir(pools, dir_path):
|
||||
''' Helper function looking for a pool containing given directory.
|
||||
|
||||
This is useful for implementing Pool.included_in method
|
||||
'''
|
||||
|
||||
# prefer filesystem pools
|
||||
for pool in pools:
|
||||
if hasattr(pool, 'dir_path'):
|
||||
if dir_path.startswith(pool.dir_path):
|
||||
return pool
|
||||
|
||||
# then look for lvm
|
||||
for pool in pools:
|
||||
if hasattr(pool, 'thin_pool') and hasattr(pool, 'volume_group'):
|
||||
if (pool.volume_group, pool.thin_pool) == \
|
||||
DirectoryThinPool.thin_pool(dir_path):
|
||||
return pool
|
||||
|
||||
return None
|
||||
|
||||
|
||||
class VmCreationManager(object):
|
||||
''' A `ContextManager` which cleans up if volume creation fails.
|
||||
|
@ -163,6 +163,12 @@ class FilePool(qubes.storage.Pool):
|
||||
statvfs = os.statvfs(self.dir_path)
|
||||
return statvfs.f_frsize * (statvfs.f_blocks - statvfs.f_bfree)
|
||||
|
||||
def included_in(self, app):
|
||||
''' Check if there is pool containing this one - either as a
|
||||
filesystem or its LVM volume'''
|
||||
return qubes.storage.search_pool_containing_dir(
|
||||
[pool for pool in app.pools.values() if pool is not self],
|
||||
self.dir_path)
|
||||
|
||||
class FileVolume(qubes.storage.Volume):
|
||||
''' Parent class for the xen volumes implementation which expects a
|
||||
|
@ -24,6 +24,7 @@
|
||||
import os
|
||||
|
||||
import qubes.exc
|
||||
import qubes.storage
|
||||
from qubes.storage import Pool, StoragePoolException, Volume
|
||||
|
||||
|
||||
@ -202,6 +203,12 @@ class LinuxKernel(Pool):
|
||||
raise qubes.exc.QubesValueError(
|
||||
'LinuxModules supports only revisions_to_keep=0')
|
||||
|
||||
def included_in(self, app):
|
||||
''' Check if there is pool containing /var/lib/qubes/vm-kernels '''
|
||||
return qubes.storage.search_pool_containing_dir(
|
||||
[pool for pool in app.pools.values() if pool is not self],
|
||||
self.dir_path)
|
||||
|
||||
@property
|
||||
def volumes(self):
|
||||
''' Return all known kernel volumes '''
|
||||
|
@ -108,6 +108,12 @@ class ReflinkPool(qubes.storage.Pool):
|
||||
statvfs = os.statvfs(self.dir_path)
|
||||
return statvfs.f_frsize * (statvfs.f_blocks - statvfs.f_bfree)
|
||||
|
||||
def included_in(self, app):
|
||||
''' Check if there is pool containing this one - either as a
|
||||
filesystem or its LVM volume'''
|
||||
return qubes.storage.search_pool_containing_dir(
|
||||
[pool for pool in app.pools.values() if pool is not self],
|
||||
self.dir_path)
|
||||
|
||||
class ReflinkVolume(qubes.storage.Volume):
|
||||
def create(self):
|
||||
|
Loading…
Reference in New Issue
Block a user