Storage move rename() logic to XenPool

- Fix config renaming
This commit is contained in:
Bahtiar `kalkin-` Gadimov 2016-04-15 17:11:42 +02:00
parent e3ae6cdc1b
commit 49b4951389
3 changed files with 86 additions and 25 deletions

View File

@ -56,7 +56,11 @@ class Volume(object):
script = None
usage = 0
def __init__(self, name=None, pool=None, volume_type=None, vid=None,
def __init__(self,
name=None,
pool=None,
volume_type=None,
vid=None,
size=0):
assert name and pool and volume_type
self.name = str(name)
@ -167,23 +171,12 @@ class Storage(object):
volume)
self.vm.volumes[name] = volume
# TODO migrate this
@staticmethod
def rename(newpath, oldpath):
'''Move storage directory, most likely during domain's rename.
.. note::
The arguments are in different order than in :program:`cp` utility.
.. versionchange:: 4.0
This is now dummy method that just passes everything to
:py:func:`os.rename`.
:param str newpath: New path
:param str oldpath: Old path
'''
os.rename(oldpath, newpath)
def rename(self, old_name, new_name):
''' Notify the pools that the domain was renamed '''
volumes = self.vm.volumes
for name, volume in volumes.items():
pool = self.get_pool(volume)
volumes[name] = pool.rename(volume, old_name, new_name)
def verify_files(self):
'''Verify that the storage is sane.
@ -271,6 +264,11 @@ class Pool(object):
raise NotImplementedError("Pool %s has remove() not implemented" %
self.name)
def rename(self, volume, old_name, new_name):
''' Called when the domain changes its name '''
raise NotImplementedError("Pool %s has rename() not implemented" %
self.name)
def start(self, volume):
''' Do what ever is needed on start '''
raise NotImplementedError("Pool %s has start() not implemented" %

View File

@ -114,6 +114,23 @@ class XenPool(Pool):
_remove_if_exists(volume.vid)
_remove_if_exists(volume.path_cow)
def rename(self, volume, old_name, new_name):
assert issubclass(volume.__class__, XenVolume)
old_dir = os.path.dirname(volume.path)
new_dir = os.path.join(os.path.dirname(old_dir), new_name)
if not os.path.exists(new_dir):
os.makedirs(new_dir)
if volume.volume_type == 'read-write':
volume.rename_target_dir(new_name, new_dir)
elif volume.volume_type == 'read-only':
volume.rename_target_dir(old_name, new_dir)
elif volume.volume_type in ['origin', 'volatile']:
volume.rename_target_dir(new_dir)
return volume
def _resize_loop_device(self, path):
# find loop device if any
p = subprocess.Popen(
@ -275,6 +292,17 @@ class ReadWriteFile(SizeMixIn):
self.path = os.path.join(self.target_dir, self.name + '.img')
self.vid = self.path
def rename_target_dir(self, new_name, new_dir):
# :pylint: disable=unused-argument
old_path = self.path
file_name = os.path.basename(self.path)
new_path = os.path.join(new_dir, file_name)
os.rename(old_path, new_path)
self.target_dir = new_dir
self.path = new_path
self.vid = self.path
class ReadOnlyFile(XenVolume):
# :pylint: disable=missing-docstring
@ -285,6 +313,20 @@ class ReadOnlyFile(XenVolume):
super(ReadOnlyFile, self).__init__(size=int(size), **kwargs)
self.path = self.vid
def rename_target_dir(self, old_name, new_dir):
# only copy the read-only volume if it's "owned" by the current vm
# "owned" means that it's in a directory named the same as the vm
if os.path.basename(self.target_dir) == old_name:
file_name = os.path.basename(self.path)
new_path = os.path.join(new_dir, file_name)
old_path = self.path
os.rename(old_path, new_path)
self.target_dir = new_dir
self.path = new_path
self.vid = self.path
class OriginFile(SizeMixIn):
# :pylint: disable=missing-docstring
@ -300,6 +342,19 @@ class OriginFile(SizeMixIn):
def commit(self):
raise NotImplementedError
def rename_target_dir(self, new_dir):
old_path_origin = self.path_origin
old_path_cow = self.path_cow
new_path_origin = os.path.join(new_dir, self.name + '.img')
new_path_cow = os.path.join(new_dir, self.name + '-cow.img')
os.rename(old_path_origin, new_path_origin)
os.rename(old_path_cow, new_path_cow)
self.target_dir = new_dir
self.path_origin = new_path_origin
self.path_cow = new_path_cow
self.path = '%s:%s' % (self.path_origin, self.path_cow)
self.vid = self.path_origin
@property
def usage(self):
result = 0
@ -335,7 +390,15 @@ class VolatileFile(SizeMixIn):
def __init__(self, **kwargs):
super(VolatileFile, self).__init__(**kwargs)
self.path = os.path.join(self.target_dir, 'volatile.img')
self.path = os.path.join(self.target_dir, self.name + '.img')
self.vid = self.path
def rename_target_dir(self, new_dir):
_remove_if_exists(self)
file_name = os.path.basename(self.path)
self.target_dir = new_dir
new_path = os.path.join(new_dir, file_name)
self.path = new_path
self.vid = self.path

View File

@ -566,18 +566,18 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
self._qdb_connection.close()
self._qdb_connection = None
self.storage.rename(
os.path.join(qubes.config.system_path['qubes_base_dir'],
self.dir_path_prefix, new_name),
os.path.join(qubes.config.system_path['qubes_base_dir'],
self.dir_path_prefix, old_name))
self.storage.rename(old_name, new_name)
prefix = os.path.join(qubes.config.system_path['qubes_base_dir'], self.dir_path_prefix)
old_config = os.path.join(prefix, old_name, old_name + '.conf')
new_config = os.path.join(prefix, new_name, new_name + '.conf')
os.rename(old_config, new_config)
self._update_libvirt_domain()
if self.autostart:
self.autostart = self.autostart
@qubes.events.handler('property-pre-set:autostart')
def on_property_pre_set_autostart(self, event, prop, name, value,
oldvalue=None):