Skip to content

Commit 81f455e

Browse files
committed
storage/file: move revisions_to_keep restrictions to property setter
Do not check for accepted value only in constructor, do that in property setter. This will allow enforcing the limit regardless of how the value was set. This is preparation for dynamic revisions_to_keep change. QubesOS/qubes-issues#3256
1 parent 0327b6c commit 81f455e

File tree

2 files changed

+50
-6
lines changed

2 files changed

+50
-6
lines changed

qubes/storage/file.py

+27-6
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ class FilePool(qubes.storage.Pool):
5454
driver = 'file'
5555

5656
def __init__(self, revisions_to_keep=1, dir_path=None, **kwargs):
57+
self._revisions_to_keep = 0
5758
super(FilePool, self).__init__(revisions_to_keep=revisions_to_keep,
5859
**kwargs)
5960
assert dir_path, "No pool dir_path specified"
@@ -85,19 +86,27 @@ def init_volume(self, vm, volume_config):
8586
volume_config['revisions_to_keep'] = 0
8687
except KeyError:
8788
pass
88-
finally:
89-
if 'revisions_to_keep' not in volume_config:
90-
volume_config['revisions_to_keep'] = self.revisions_to_keep
9189

92-
if int(volume_config['revisions_to_keep']) > 1:
93-
raise NotImplementedError(
94-
'FilePool supports maximum 1 volume revision to keep')
90+
if 'revisions_to_keep' not in volume_config:
91+
volume_config['revisions_to_keep'] = self.revisions_to_keep
9592

9693
volume_config['pool'] = self
9794
volume = FileVolume(**volume_config)
9895
self._volumes += [volume]
9996
return volume
10097

98+
@property
99+
def revisions_to_keep(self):
100+
return self._revisions_to_keep
101+
102+
@revisions_to_keep.setter
103+
def revisions_to_keep(self, value):
104+
value = int(value)
105+
if value > 1:
106+
raise NotImplementedError(
107+
'FilePool supports maximum 1 volume revision to keep')
108+
self._revisions_to_keep = value
109+
101110
def destroy(self):
102111
pass
103112

@@ -162,12 +171,24 @@ class FileVolume(qubes.storage.Volume):
162171
def __init__(self, dir_path, **kwargs):
163172
self.dir_path = dir_path
164173
assert self.dir_path, "dir_path not specified"
174+
self._revisions_to_keep = 0
165175
super(FileVolume, self).__init__(**kwargs)
166176

167177
if self.snap_on_start:
168178
img_name = self.source.vid + '-cow.img'
169179
self.path_source_cow = os.path.join(self.dir_path, img_name)
170180

181+
@property
182+
def revisions_to_keep(self):
183+
return self._revisions_to_keep
184+
185+
@revisions_to_keep.setter
186+
def revisions_to_keep(self, value):
187+
if int(value) > 1:
188+
raise NotImplementedError(
189+
'FileVolume supports maximum 1 volume revision to keep')
190+
self._revisions_to_keep = int(value)
191+
171192
def create(self):
172193
assert isinstance(self.size, int) and self.size > 0, \
173194
'Volume size must be > 0'

qubes/tests/storage_file.py

+23
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,22 @@ def test_006_template_volumes(self):
296296
expected = vm_dir + '/volatile.img'
297297
self.assertVolumePath(vm, 'volatile', expected, rw=True)
298298

299+
def test_010_revisions_to_keep_reject_invalid(self):
300+
''' Check if TemplateVM volumes are propertly initialized '''
301+
config = {
302+
'name': 'root',
303+
'pool': self.POOL_NAME,
304+
'save_on_stop': True,
305+
'rw': True,
306+
'size': defaults['root_img_size'],
307+
}
308+
vm = qubes.tests.storage.TestVM(self)
309+
volume = self.app.get_pool(self.POOL_NAME).init_volume(vm, config)
310+
self.assertEqual(volume.revisions_to_keep, 1)
311+
with self.assertRaises((NotImplementedError, ValueError)):
312+
volume.revisions_to_keep = 2
313+
self.assertEqual(volume.revisions_to_keep, 1)
314+
299315
def assertVolumePath(self, vm, dev_name, expected, rw=True):
300316
# :pylint: disable=invalid-name
301317
volumes = vm.volumes
@@ -384,6 +400,13 @@ def test_004_usage(self):
384400
self.assertEqual(usage,
385401
statvfs.f_frsize * (statvfs.f_blocks - statvfs.f_bfree))
386402

403+
def test_005_revisions_to_keep(self):
404+
pool = self.app.get_pool(self.POOL_NAME)
405+
self.assertEqual(pool.revisions_to_keep, 1)
406+
with self.assertRaises((NotImplementedError, ValueError)):
407+
pool.revisions_to_keep = 2
408+
self.assertEqual(pool.revisions_to_keep, 1)
409+
387410
def test_011_appvm_file_images(self):
388411
""" Check if all the needed image files are created for an AppVm"""
389412

0 commit comments

Comments
 (0)