|
@@ -176,11 +176,14 @@ class FilePool(qubes.storage.Pool):
|
|
|
class FileVolume(qubes.storage.Volume):
|
|
|
''' Parent class for the xen volumes implementation which expects a
|
|
|
`target_dir` param on initialization. '''
|
|
|
+ _marker_running = object()
|
|
|
+ _marker_exported = object()
|
|
|
|
|
|
def __init__(self, dir_path, **kwargs):
|
|
|
self.dir_path = dir_path
|
|
|
assert self.dir_path, "dir_path not specified"
|
|
|
self._revisions_to_keep = 0
|
|
|
+ self._locked = None
|
|
|
super().__init__(**kwargs)
|
|
|
|
|
|
if self.snap_on_start:
|
|
@@ -265,10 +268,18 @@ class FileVolume(qubes.storage.Volume):
|
|
|
return self
|
|
|
|
|
|
def export(self):
|
|
|
- if self.is_dirty():
|
|
|
+ if self._locked is not None:
|
|
|
+ assert self._locked is FileVolume._marker_running, \
|
|
|
+ 'nested calls to export()'
|
|
|
self._not_implemented('exporting a dirty volume')
|
|
|
+ self._locked = FileVolume._marker_exported
|
|
|
return self.path
|
|
|
|
|
|
+ def export_end(self, path):
|
|
|
+ assert self._locked is FileVolume._marker_exported, \
|
|
|
+ 'cannot end an export that never began'
|
|
|
+ self._locked = None
|
|
|
+
|
|
|
@asyncio.coroutine
|
|
|
def import_volume(self, src_volume):
|
|
|
if src_volume.snap_on_start:
|
|
@@ -311,6 +322,11 @@ class FileVolume(qubes.storage.Volume):
|
|
|
return self
|
|
|
|
|
|
def start(self):
|
|
|
+ if self._locked is not None:
|
|
|
+ assert self._locked is FileVolume._marker_exported, \
|
|
|
+ 'nested calls to start()'
|
|
|
+ self._not_implemented('starting a VM with an exported volume')
|
|
|
+ self._locked = FileVolume._marker_running
|
|
|
if not self.save_on_stop and not self.snap_on_start:
|
|
|
self.reset()
|
|
|
else:
|
|
@@ -328,12 +344,15 @@ class FileVolume(qubes.storage.Volume):
|
|
|
return self
|
|
|
|
|
|
def stop(self):
|
|
|
+ assert self._locked is FileVolume._marker_running, \
|
|
|
+ 'cannot stop a volume that has not been started'
|
|
|
if self.save_on_stop:
|
|
|
self.commit()
|
|
|
elif self.snap_on_start:
|
|
|
_remove_if_exists(self.path_cow)
|
|
|
else:
|
|
|
_remove_if_exists(self.path)
|
|
|
+ self._locked = None
|
|
|
return self
|
|
|
|
|
|
@property
|