storage: add Volume.export_end() function

This is a counterpart to Volume.export(). Up until now, no driver needed
any cleanup after exporting data, but it doesn't mean there won't be
any. This is especially relevant because Volume.export() is supposed to
return a path of a snapshot from before VM start - which may be a
different one than currently active one.

QubesOS/qubes-issues#5935
This commit is contained in:
Marek Marczykowski-Górecki 2020-07-06 00:34:10 +02:00
parent f48327f636
commit d96480719f
No known key found for this signature in database
GPG Key ID: 063938BA42CFA724
3 changed files with 31 additions and 1 deletions

View File

@ -99,6 +99,10 @@ Methods and properties required to be implemented by the volume class:
- :py:meth:`~qubes.storage.Volume.export` - return a path to be read to extract - :py:meth:`~qubes.storage.Volume.export` - return a path to be read to extract
volume data; for complex formats, this can be a pipe (connected to some volume data; for complex formats, this can be a pipe (connected to some
data-extracting process) data-extracting process)
- :py:meth:`~qubes.storage.Volume.export_end` - cleanup after exporting the
data; this function is called when the path returned by
:py:meth:`~qubes.storage.Volume.export` is not used anymore. This method
optional - some storage drivers may not implement it if not needed.
- :py:meth:`~qubes.storage.Volume.import_data` - return a path the data should - :py:meth:`~qubes.storage.Volume.import_data` - return a path the data should
be written to, to import volume data; for complex formats, this can be pipe be written to, to import volume data; for complex formats, this can be pipe
(connected to some data-importing process) (connected to some data-importing process)

View File

@ -394,7 +394,8 @@ class Backup:
volume.export, volume.export,
subdir, subdir,
name + '.img', name + '.img',
volume.usage)) volume.usage,
cleanup_func=volume.export_end))
vm_files.extend(self.FileToBackup(i, subdir) vm_files.extend(self.FileToBackup(i, subdir)
for i in vm.fire_event('backup-get-files')) for i in vm.fire_event('backup-get-files'))

View File

@ -206,6 +206,18 @@ class Volume:
''' '''
raise self._not_implemented("export") raise self._not_implemented("export")
def export_end(self, path):
""" Cleanup after exporting data.
This method is called after exporting the volume data (using
:py:meth:`export`), when the *path* is not needed anymore.
This can be implemented as a coroutine.
:param path: path to cleanup, returned by :py:meth:`export`
"""
# do nothing by default (optional method)
def import_data(self, size): def import_data(self, size):
''' Returns a path to overwrite volume data. ''' Returns a path to overwrite volume data.
@ -643,6 +655,19 @@ class Storage:
return self.vm.volumes[volume].export() return self.vm.volumes[volume].export()
@asyncio.coroutine
def export_end(self, volume, export_path):
""" Cleanup after exporting data from the volume
:param volume: volume that was exported
:param export_path: path returned by the export() call
"""
assert isinstance(volume, (Volume, str)), \
"You need to pass a Volume or pool name as str"
if not isinstance(volume, Volume):
volume = self.vm.volumes[volume]
yield from qubes.utils.coro_maybe(volume.export_end(export_path))
@asyncio.coroutine @asyncio.coroutine
def import_data(self, volume, size): def import_data(self, volume, size):
''' '''