storage: make default pool configurable
Do not always use pool named 'default'. Instead, have global `default_pool` property to specify default storage pools. Additionally add `default_pool_*` properties for each VM property, so those can be set separately. QubesOS/qubes-issues#2256
This commit is contained in:
parent
82c3f85042
commit
1a1dd3dba2
64
qubes/app.py
64
qubes/app.py
@ -28,6 +28,7 @@ import grp
|
|||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import random
|
import random
|
||||||
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
import time
|
import time
|
||||||
@ -548,6 +549,46 @@ class VMCollection(object):
|
|||||||
'https://xkcd.com/221/',
|
'https://xkcd.com/221/',
|
||||||
'http://dilbert.com/strip/2001-10-25')[random.randint(0, 1)])
|
'http://dilbert.com/strip/2001-10-25')[random.randint(0, 1)])
|
||||||
|
|
||||||
|
def _default_pool(app):
|
||||||
|
''' Default storage pool.
|
||||||
|
|
||||||
|
1. If there is one named 'default', use it.
|
||||||
|
2. Check if root fs is on LVM thin - use that
|
||||||
|
3. Look for file-based pool pointing /var/lib/qubes
|
||||||
|
4. Fail
|
||||||
|
'''
|
||||||
|
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'])
|
||||||
|
if any((str(root_major), str(root_minor)) == thin_vol.split()
|
||||||
|
for thin_vol in thin_volumes.splitlines()):
|
||||||
|
return pool
|
||||||
|
# not a thin volume? look for file pools
|
||||||
|
for pool in app.pools.values():
|
||||||
|
if pool.config.get('driver', None) != 'file':
|
||||||
|
continue
|
||||||
|
if pool.config['dir_path'] == '/var/lib/qubes':
|
||||||
|
return pool
|
||||||
|
raise AttributeError('Cannot determine default storage pool')
|
||||||
|
|
||||||
|
def _setter_pool(app, prop, value):
|
||||||
|
if isinstance(value, qubes.storage.Pool):
|
||||||
|
return value
|
||||||
|
try:
|
||||||
|
return app.pools[value]
|
||||||
|
except KeyError:
|
||||||
|
raise qubes.exc.QubesPropertyValueError(app, prop, value,
|
||||||
|
'No such storage pool')
|
||||||
|
|
||||||
class Qubes(qubes.PropertyHolder):
|
class Qubes(qubes.PropertyHolder):
|
||||||
'''Main Qubes application
|
'''Main Qubes application
|
||||||
@ -629,6 +670,27 @@ class Qubes(qubes.PropertyHolder):
|
|||||||
default_dispvm = qubes.VMProperty('default_dispvm', load_stage=3,
|
default_dispvm = qubes.VMProperty('default_dispvm', load_stage=3,
|
||||||
doc='Default DispVM base for service calls')
|
doc='Default DispVM base for service calls')
|
||||||
|
|
||||||
|
default_pool = qubes.property('default_pool', load_stage=3,
|
||||||
|
default=_default_pool,
|
||||||
|
doc='Default storage pool')
|
||||||
|
|
||||||
|
default_pool_private = qubes.property('default_pool_private', load_stage=3,
|
||||||
|
default=lambda app: app.default_pool,
|
||||||
|
doc='Default storage pool for private volumes')
|
||||||
|
|
||||||
|
default_pool_root = qubes.property('default_pool_root', load_stage=3,
|
||||||
|
default=lambda app: app.default_pool,
|
||||||
|
doc='Default storage pool for root volumes')
|
||||||
|
|
||||||
|
default_pool_volatile = qubes.property('default_pool_volatile',
|
||||||
|
load_stage=3,
|
||||||
|
default=lambda app: app.default_pool,
|
||||||
|
doc='Default storage pool for volatile volumes')
|
||||||
|
|
||||||
|
default_pool_kernel = qubes.property('default_pool_kernel', load_stage=3,
|
||||||
|
default=lambda app: app.default_pool,
|
||||||
|
doc='Default storage pool for kernel volumes')
|
||||||
|
|
||||||
# TODO #1637 #892
|
# TODO #1637 #892
|
||||||
check_updates_vm = qubes.property('check_updates_vm',
|
check_updates_vm = qubes.property('check_updates_vm',
|
||||||
type=bool, setter=qubes.property.bool,
|
type=bool, setter=qubes.property.bool,
|
||||||
@ -907,6 +969,8 @@ class Qubes(qubes.PropertyHolder):
|
|||||||
for name, config in qubes.config.defaults['pool_configs'].items():
|
for name, config in qubes.config.defaults['pool_configs'].items():
|
||||||
self.pools[name] = self._get_pool(**config)
|
self.pools[name] = self._get_pool(**config)
|
||||||
|
|
||||||
|
self.default_pool_kernel = 'linux-kernel'
|
||||||
|
|
||||||
self.domains.add(
|
self.domains.add(
|
||||||
qubes.vm.adminvm.AdminVM(self, None, label='black'))
|
qubes.vm.adminvm.AdminVM(self, None, label='black'))
|
||||||
|
|
||||||
|
@ -369,7 +369,10 @@ class Storage(object):
|
|||||||
|
|
||||||
if 'name' not in volume_config:
|
if 'name' not in volume_config:
|
||||||
volume_config['name'] = name
|
volume_config['name'] = name
|
||||||
pool = self.vm.app.get_pool(volume_config['pool'])
|
if 'pool' not in volume_config:
|
||||||
|
pool = getattr(self.vm.app, 'default_pool_' + name)
|
||||||
|
else:
|
||||||
|
pool = self.vm.app.get_pool(volume_config['pool'])
|
||||||
volume = pool.init_volume(self.vm, volume_config)
|
volume = pool.init_volume(self.vm, volume_config)
|
||||||
self.vm.volumes[name] = volume
|
self.vm.volumes[name] = volume
|
||||||
return volume
|
return volume
|
||||||
|
Loading…
Reference in New Issue
Block a user