change default pool code to be fast

currently it takes 100ms+ to determine the default pool every time,
including subprocess spawning (!), which is unacceptable since
finding out the default value of properties should be instantaneous

instead of checking every thin pool to see if the root device is in
it, find and cache the name of the root device thin pool and see if
there is a configured pool with that name
This commit is contained in:
qubesuser 2017-11-10 02:40:38 +01:00
parent d183ab1c18
commit 92c452a655

View File

@ -545,6 +545,55 @@ class VMCollection(object):
'https://xkcd.com/221/',
'http://dilbert.com/strip/2001-10-25')[random.randint(0, 1)])
# pylint: disable=too-few-public-methods
class RootThinPool:
'''The thin pool containing the rootfs device'''
_inited = False
_volume_group = None
_thin_pool = None
@classmethod
def _init(cls):
'''Find out the thin pool containing the root device'''
if not cls._inited:
cls._inited = True
try:
rootfs = os.stat('/')
root_major = (rootfs.st_dev & 0xff00) >> 8
root_minor = rootfs.st_dev & 0xff
root_table = subprocess.check_output(["dmsetup",
"-j", str(root_major), "-m", str(root_minor),
"table"])
_start, _sectors, target_type, target_args = \
root_table.decode().split(" ", 3)
if target_type == "thin":
thin_pool_devnum, _thin_pool_id = target_args.split(" ")
with open("/sys/dev/block/{}/dm/name"
.format(thin_pool_devnum), "r") as thin_pool_tpool_f:
thin_pool_tpool = thin_pool_tpool_f.read().rstrip('\n')
if thin_pool_tpool.endswith("-tpool"):
volume_group, thin_pool, _tpool = \
thin_pool_tpool.rsplit("-", 2)
cls._volume_group = volume_group
cls._thin_pool = thin_pool
except: # pylint: disable=bare-except
pass
@classmethod
def volume_group(cls):
'''Volume group of the thin pool containing the rootfs device'''
cls._init()
return cls._volume_group
@classmethod
def thin_pool(cls):
'''Thin pool name containing the rootfs device'''
cls._init()
return cls._thin_pool
def _default_pool(app):
''' Default storage pool.
@ -556,20 +605,16 @@ def _default_pool(app):
if 'default' in app.pools:
return app.pools['default']
else:
rootfs = os.stat('/')
root_major = (rootfs.st_dev & 0xff00) >> 8
root_minor = rootfs.st_dev & 0xff
for pool in app.pools.values():
if pool.config.get('driver', None) != 'lvm_thin':
continue
thin_pool = pool.config['thin_pool']
thin_volumes = subprocess.check_output(
['lvs', '--select', 'pool_lv=' + thin_pool,
'-o', 'lv_kernel_major,lv_kernel_minor', '--noheadings'])
thin_volumes = thin_volumes.decode()
if any([str(root_major), str(root_minor)] == thin_vol.split()
for thin_vol in thin_volumes.splitlines()):
return pool
root_volume_group = RootThinPool.volume_group()
root_thin_pool = RootThinPool.thin_pool()
if root_thin_pool:
for pool in app.pools.values():
if pool.config.get('driver', None) != 'lvm_thin':
continue
if (pool.config['volume_group'] == root_volume_group and
pool.config['thin_pool'] == root_thin_pool):
return pool
# not a thin volume? look for file pools
for pool in app.pools.values():
if pool.config.get('driver', None) != 'file':