storage: move remove() to Volume

This is continuation of 0f12870 "storage: use direct object references,
not only identifiers".

QubesOS/qubes-issues#2256
This commit is contained in:
Marek Marczykowski-Górecki 2017-06-26 11:39:02 +02:00
parent ae600e24bf
commit a748b393f4
No known key found for this signature in database
GPG Key ID: 063938BA42CFA724
5 changed files with 35 additions and 36 deletions

View File

@ -146,6 +146,12 @@ class Volume(object):
''' '''
raise self._not_implemented("create") raise self._not_implemented("create")
def remove(self):
''' Remove volume.
This can be implemented as a coroutine.'''
raise self._not_implemented("remove")
def commit(self): def commit(self):
''' Write the snapshot to disk ''' Write the snapshot to disk
@ -520,7 +526,7 @@ class Storage(object):
for name, volume in self.vm.volumes.items(): for name, volume in self.vm.volumes.items():
self.log.info('Removing volume %s: %s' % (name, volume.vid)) self.log.info('Removing volume %s: %s' % (name, volume.vid))
try: try:
ret = volume.pool.remove(volume) ret = volume.remove()
if asyncio.iscoroutine(ret): if asyncio.iscoroutine(ret):
futures.append(ret) futures.append(ret)
except (IOError, OSError) as e: except (IOError, OSError) as e:
@ -719,12 +725,6 @@ class Pool(object):
''' '''
raise self._not_implemented("init_volume") raise self._not_implemented("init_volume")
def remove(self, volume):
''' Remove volume.
This can be implemented as a coroutine.'''
raise self._not_implemented("remove")
def rename(self, volume, old_name, new_name): def rename(self, volume, old_name, new_name):
''' Called when the domain changes its name ''' ''' Called when the domain changes its name '''
raise self._not_implemented("rename") raise self._not_implemented("rename")
@ -804,8 +804,7 @@ class VmCreationManager(object):
if type is not None and value is not None and tb is not None: if type is not None and value is not None and tb is not None:
for volume in self.vm.volumes.values(): for volume in self.vm.volumes.values():
try: try:
pool = volume.pool volume.remove()
pool.remove(volume)
except Exception: # pylint: disable=broad-except except Exception: # pylint: disable=broad-except
pass pass
os.rmdir(self.vm.dir_path) os.rmdir(self.vm.dir_path)

View File

@ -79,16 +79,6 @@ class FilePool(qubes.storage.Pool):
self._volumes += [volume] self._volumes += [volume]
return volume return volume
def remove(self, volume):
if not volume.internal:
return # do not remove random attached file volumes
elif volume._is_snapshot:
return # no need to remove, because it's just a snapshot
else:
_remove_if_exists(volume.path)
if volume._is_origin:
_remove_if_exists(volume.path_cow)
def rename(self, volume, old_name, new_name): def rename(self, volume, old_name, new_name):
assert issubclass(volume.__class__, FileVolume) assert issubclass(volume.__class__, FileVolume)
subdir, _, volume_path = volume.vid.split('/', 2) subdir, _, volume_path = volume.vid.split('/', 2)
@ -201,6 +191,16 @@ class FileVolume(qubes.storage.Volume):
else: else:
create_sparse_file(self.path, self.size) create_sparse_file(self.path, self.size)
def remove(self):
if not self.internal:
return # do not remove random attached file volumes
elif self._is_snapshot:
return # no need to remove, because it's just a snapshot
else:
_remove_if_exists(self.path)
if self._is_origin:
_remove_if_exists(self.path_cow)
def is_dirty(self): def is_dirty(self):
return False # TODO: How to implement this? return False # TODO: How to implement this?

View File

@ -93,6 +93,9 @@ class LinuxModules(Volume):
def create(self): def create(self):
return self return self
def remove(self):
pass
def commit(self): def commit(self):
return self return self
@ -154,9 +157,6 @@ class LinuxKernel(Pool):
def import_volume(self, dst_pool, dst_volume, src_pool, src_volume): def import_volume(self, dst_pool, dst_volume, src_pool, src_volume):
pass pass
def remove(self, volume):
pass
def rename(self, volume, old_name, new_name): def rename(self, volume, old_name, new_name):
return volume return volume

View File

@ -88,18 +88,6 @@ class ThinPool(qubes.storage.Pool):
volume_config['pool'] = self volume_config['pool'] = self
return ThinVolume(**volume_config) return ThinVolume(**volume_config)
def remove(self, volume):
assert volume.vid
if volume.is_dirty():
cmd = ['remove', volume._vid_snap]
qubes_lvm(cmd, self.log)
if not os.path.exists(volume.path):
return
cmd = ['remove', volume.vid]
qubes_lvm(cmd, self.log)
reset_cache()
def rename(self, volume, old_name, new_name): def rename(self, volume, old_name, new_name):
''' Called when the domain changes its name ''' ''' Called when the domain changes its name '''
new_vid = "{!s}/vm-{!s}-{!s}".format(self.volume_group, new_name, new_vid = "{!s}/vm-{!s}-{!s}".format(self.volume_group, new_name,
@ -296,6 +284,18 @@ class ThinVolume(qubes.storage.Volume):
reset_cache() reset_cache()
return self return self
def remove(self):
assert self.vid
if self.is_dirty():
cmd = ['remove', self._vid_snap]
qubes_lvm(cmd, self.log)
if not os.path.exists(self.path):
return
cmd = ['remove', self.vid]
qubes_lvm(cmd, self.log)
reset_cache()
def export(self): def export(self):
''' Returns an object that can be `open()`. ''' ''' Returns an object that can be `open()`. '''
devpath = '/dev/' + self.vid devpath = '/dev/' + self.vid

View File

@ -137,7 +137,7 @@ class TC_00_ThinPool(ThinPoolBase):
volume.create() volume.create()
path = "/dev/%s" % volume.vid path = "/dev/%s" % volume.vid
self.assertTrue(os.path.exists(path)) self.assertTrue(os.path.exists(path))
self.pool.remove(volume) volume.remove()
def test_003_read_write_volume(self): def test_003_read_write_volume(self):
''' Test read-write volume creation ''' ''' Test read-write volume creation '''
@ -157,7 +157,7 @@ class TC_00_ThinPool(ThinPoolBase):
volume.create() volume.create()
path = "/dev/%s" % volume.vid path = "/dev/%s" % volume.vid
self.assertTrue(os.path.exists(path)) self.assertTrue(os.path.exists(path))
self.pool.remove(volume) volume.remove()
@skipUnlessLvmPoolExists @skipUnlessLvmPoolExists
class TC_01_ThinPool(qubes.tests.SystemTestsMixin, ThinPoolBase): class TC_01_ThinPool(qubes.tests.SystemTestsMixin, ThinPoolBase):