From 7903dc53f9d77870f227a98691856df8b0630a6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= Date: Wed, 7 Feb 2018 00:19:07 +0100 Subject: [PATCH 1/3] storage/lvm: fix resizing not persistent volumes Even when volume is not persistent (like TemplateBasedVM:root), it should be resizeable. Just the new size, similarly to the volume content, will be reverted after qube shutdown. Additionally, when VM is running, volume resize should affect _only_ its temporary snapshot. This way resize can be properly reverted together with actual volume changes (which include resize2fs call). Fixes QubesOS/qubes-issues#3519 --- qubes/storage/lvm.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/qubes/storage/lvm.py b/qubes/storage/lvm.py index e814bb06..c999795b 100644 --- a/qubes/storage/lvm.py +++ b/qubes/storage/lvm.py @@ -225,6 +225,8 @@ class ThinVolume(qubes.storage.Volume): @property def size(self): try: + if self.is_dirty(): + return qubes.storage.lvm.size_cache[self._vid_snap]['size'] return qubes.storage.lvm.size_cache[self.vid]['size'] except KeyError: return self._size @@ -430,11 +432,12 @@ class ThinVolume(qubes.storage.Volume): if size == self.size: return - cmd = ['extend', self.vid, str(size)] - qubes_lvm(cmd, self.log) if self.is_dirty(): cmd = ['extend', self._vid_snap, str(size)] qubes_lvm(cmd, self.log) + elif self.save_on_stop or not self.snap_on_start: + cmd = ['extend', self.vid, str(size)] + qubes_lvm(cmd, self.log) reset_cache() def _snapshot(self): From 4e314c9792826edae43893eec2c2707da38e8d00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= Date: Wed, 7 Feb 2018 00:53:47 +0100 Subject: [PATCH 2/3] tests: storage/lvm resize QubesOS/qubes-issues#3519 --- qubes/tests/storage_lvm.py | 54 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/qubes/tests/storage_lvm.py b/qubes/tests/storage_lvm.py index f6a4be69..2672a280 100644 --- a/qubes/tests/storage_lvm.py +++ b/qubes/tests/storage_lvm.py @@ -178,6 +178,60 @@ class TC_00_ThinPool(ThinPoolBase): pool_usage = float(pool_usage) self.assertEqual(usage, int(pool_size * pool_usage / 100)) + def _get_size(self, path): + if os.getuid() != 0: + return int( + subprocess.check_output( + ['sudo', 'blockdev', '--getsize64', path])) + fd = os.open(path, os.O_RDONLY) + try: + return os.lseek(fd, 0, os.SEEK_END) + finally: + os.close(fd) + + def test_006_resize(self): + config = { + 'name': 'root', + 'pool': self.pool.name, + 'rw': True, + 'save_on_stop': True, + 'size': 32 * 1024**2, + } + vm = qubes.tests.storage.TestVM(self) + volume = self.app.get_pool(self.pool.name).init_volume(vm, config) + volume.create() + self.addCleanup(volume.remove) + path = "/dev/%s" % volume.vid + new_size = 64 * 1024 ** 2 + volume.resize(new_size) + self.assertEqual(self._get_size(path), new_size) + self.assertEqual(volume.size, new_size) + + def test_007_resize_running(self): + old_size = 32 * 1024**2 + config = { + 'name': 'root', + 'pool': self.pool.name, + 'rw': True, + 'save_on_stop': True, + 'size': old_size, + } + vm = qubes.tests.storage.TestVM(self) + volume = self.app.get_pool(self.pool.name).init_volume(vm, config) + volume.create() + self.addCleanup(volume.remove) + volume.start() + path = "/dev/%s" % volume.vid + path2 = "/dev/%s" % volume._vid_snap + new_size = 64 * 1024 ** 2 + volume.resize(new_size) + self.assertEqual(self._get_size(path), old_size) + self.assertEqual(self._get_size(path2), new_size) + self.assertEqual(volume.size, new_size) + volume.stop() + self.assertEqual(self._get_size(path), new_size) + self.assertEqual(volume.size, new_size) + @skipUnlessLvmPoolExists class TC_01_ThinPool(ThinPoolBase, qubes.tests.SystemTestCase): From e6bb2828f154197103ba72cb3641f2b6a9e0d104 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= Date: Wed, 7 Feb 2018 01:45:53 +0100 Subject: [PATCH 3/3] storage/lvm: add more details to refused volume shrink message Include old and new size. --- qubes/storage/lvm.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qubes/storage/lvm.py b/qubes/storage/lvm.py index c999795b..7b939f60 100644 --- a/qubes/storage/lvm.py +++ b/qubes/storage/lvm.py @@ -425,9 +425,9 @@ class ThinVolume(qubes.storage.Volume): if size < self.size: raise qubes.storage.StoragePoolException( 'For your own safety, shrinking of %s is' - ' disabled. If you really know what you' + ' disabled (%d < %d). If you really know what you' ' are doing, use `lvresize` on %s manually.' % - (self.name, self.vid)) + (self.name, size, self.size, self.vid)) if size == self.size: return