Merge remote-tracking branch 'woju/pull/21/head' into core3-devel

Conflicts:
	qubes/storage/__init__.py
This commit is contained in:
Wojtek Porczyk 2016-07-02 11:54:56 +02:00
commit 1ff1ca37a1
4 changed files with 55 additions and 36 deletions

View File

@ -911,6 +911,7 @@ class Qubes(qubes.PropertyHolder):
pool = self._get_pool(**kwargs)
pool.setup()
self.pools[name] = pool
return pool
def remove_pool(self, name):
""" Remove a storage pool from config file. """

View File

@ -42,6 +42,7 @@ STORAGE_ENTRY_POINT = 'qubes.storage'
class StoragePoolException(qubes.exc.QubesException):
''' A general storage exception '''
pass
@ -98,6 +99,9 @@ class Volume(object):
def __hash__(self):
return hash('%s:%s %s' % (self.pool, self.vid, self.volume_type))
def __str__(self):
return "{!s}:{!s}".format(self.pool, self.vid)
class Storage(object):
''' Class for handling VM virtual disks.
@ -198,7 +202,7 @@ class Storage(object):
self.get_pool(volume).resize(volume, size)
def create(self, source_template=None):
''' Creates volumes on disk '''
if source_template is None and hasattr(self.vm, 'template'):
source_template = self.vm.template
@ -213,6 +217,7 @@ class Storage(object):
os.umask(old_umask)
def clone(self, src_vm):
''' Clone volumes from the specified vm '''
self.vm.log.info('Creating directory: {0}'.format(self.vm.dir_path))
if not os.path.exists(self.vm.dir_path):
self.log.info('Creating directory: {0}'.format(self.vm.dir_path))
@ -288,6 +293,7 @@ class Storage(object):
return self.pools[volume.name]
def commit_template_changes(self):
''' Makes changes to an 'origin' volume persistent '''
for volume in self.vm.volumes.values():
if volume.volume_type == 'origin':
self.get_pool(volume).commit_template_changes(volume)
@ -318,15 +324,25 @@ class Pool(object):
private_img_size = qubes.config.defaults['private_img_size']
root_img_size = qubes.config.defaults['root_img_size']
def __eq__(self, other):
return self.name == other.name
def __neq__(self, other):
return not self.__eq__(other)
def __init__(self, name, **kwargs):
super(Pool, self).__init__(**kwargs)
self.name = name
kwargs['name'] = self.name
def __str__(self):
return self.name
def __xml__(self):
return lxml.etree.Element('pool', **self.config)
def create(self, volume, source_volume):
def create(self, volume, source_volume=None):
''' Create the given volume on disk or copy from provided
`source_volume`.
'''
@ -351,6 +367,9 @@ class Pool(object):
self.name)
def destroy(self):
''' Called when removing the pool. Use this for implementation specific
clean up.
'''
raise NotImplementedError("Pool %s has destroy() not implemented" %
self.name)
@ -374,6 +393,9 @@ class Pool(object):
self.name)
def setup(self):
''' Called when adding a pool to the system. Use this for implementation
specific set up.
'''
raise NotImplementedError("Pool %s has setup() not implemented" %
self.name)

View File

@ -91,7 +91,7 @@ class FilePool(Pool):
''' Expands volume, throws
:py:class:`qubst.storage.StoragePoolException` if given size is
less than current_size
'''
''' # pylint: disable=no-self-use
_type = volume.volume_type
if _type not in ['origin', 'read-write', 'volatile']:
raise StoragePoolException('Can not resize a %s volume %s' %
@ -112,7 +112,18 @@ class FilePool(Pool):
with open(path, 'a+b') as fd:
fd.truncate(size)
self._resize_loop_device(path)
p = subprocess.Popen(
['sudo', 'losetup', '--associated', path],
stdout=subprocess.PIPE)
result = p.communicate()
m = re.match(r'^(/dev/loop\d+):\s', result[0])
if m is not None:
loop_dev = m.group(1)
# resize loop device
subprocess.check_call(['sudo', 'losetup', '--set-capacity', loop_dev
])
def remove(self, volume):
if volume.volume_type in ['read-write', 'volatile']:
@ -133,23 +144,6 @@ class FilePool(Pool):
return volume
@staticmethod
def _resize_loop_device(path):
''' Sets the loop device capacity '''
# find loop device if any
p = subprocess.Popen(
['sudo', 'losetup', '--associated', path],
stdout=subprocess.PIPE)
result = p.communicate()
m = re.match(r'^(/dev/loop\d+):\s', result[0])
if m is not None:
loop_dev = m.group(1)
# resize loop device
subprocess.check_call(['sudo', 'losetup', '--set-capacity',
loop_dev])
def commit_template_changes(self, volume):
if volume.volume_type != 'origin':
return volume
@ -175,7 +169,7 @@ class FilePool(Pool):
def start(self, volume):
if volume.volume_type == 'volatile':
self._reset_volume(volume)
_reset_volume(volume)
if volume.volume_type in ['origin', 'snapshot']:
_check_path(volume.path_origin)
_check_path(volume.path_cow)
@ -187,18 +181,6 @@ class FilePool(Pool):
def stop(self, volume):
pass
@staticmethod
def _reset_volume(volume):
''' Remove and recreate a volatile volume '''
assert volume.volume_type == 'volatile', "Not a volatile volume"
assert volume.size
_remove_if_exists(volume.path)
with open(volume.path, "w") as f_volatile:
f_volatile.truncate(volume.size)
return volume
def target_dir(self, vm):
""" Returns the path to vmdir depending on the type of the VM.
@ -259,6 +241,7 @@ class FilePool(Pool):
expected_origin_type
origin_pool = vm.app.get_pool(origin_vm.volume_config[name]['pool'])
assert isinstance(origin_pool,
FilePool), 'Origin volume not a file volume'
@ -558,7 +541,7 @@ def copy_file(source, destination):
def _remove_if_exists(path):
''' Removes a path if it exist, silently succeeds if file does not exist '''
''' Removes a file if it exist, silently succeeds if file does not exist '''
if os.path.exists(path):
os.remove(path)
@ -567,3 +550,16 @@ def _check_path(path):
''' Raise an StoragePoolException if ``path`` does not exist'''
if not os.path.exists(path):
raise StoragePoolException('Missing image file: %s' % path)
def _reset_volume(volume):
''' Remove and recreate a volatile volume '''
assert volume.volume_type == 'volatile', "Not a volatile volume"
assert volume.size
_remove_if_exists(volume.path)
with open(volume.path, "w") as f_volatile:
f_volatile.truncate(volume.size)
return volume

View File

@ -63,7 +63,7 @@ class LinuxKernel(Pool):
def clone(self, source, target):
return target
def create(self, volume, source_volume):
def create(self, volume, source_volume=None):
return volume
def commit_template_changes(self, volume):