Răsfoiți Sursa

Merge branch 'devel-storage-fixes'

* devel-storage-fixes:
  storage/file: use proper exception instead of assert
  storage/file: import data into temporary volume
  storage/lvm: check for LVM LV existence and type when creating ThinPool
  storage/lvm: fix size reporting just after creating LV
Marek Marczykowski-Górecki 6 ani în urmă
părinte
comite
6469705196
4 a modificat fișierele cu 74 adăugiri și 7 ștergeri
  1. 22 5
      qubes/storage/file.py
  2. 9 1
      qubes/storage/lvm.py
  3. 1 1
      qubes/tests/api_admin.py
  4. 42 0
      qubes/tests/storage_file.py

+ 22 - 5
qubes/storage/file.py

@@ -267,17 +267,29 @@ class FileVolume(qubes.storage.Volume):
         return self.path
 
     def import_volume(self, src_volume):
-        msg = "Can not import snapshot volume {!s} in to pool {!s} "
-        msg = msg.format(src_volume, self)
-        assert not src_volume.snap_on_start, msg
+        if src_volume.snap_on_start:
+            raise qubes.storage.StoragePoolException(
+                "Can not import snapshot volume {!s} in to pool {!s} ".format(
+                    src_volume, self))
         if self.save_on_stop:
             _remove_if_exists(self.path)
             copy_file(src_volume.export(), self.path)
         return self
 
-
     def import_data(self):
-        return self.path
+        if not self.save_on_stop:
+            raise qubes.storage.StoragePoolException(
+                "Can not import into save_on_stop=False volume {!s}".format(
+                    self))
+        create_sparse_file(self.path_import, self.size)
+        return self.path_import
+
+    def import_data_end(self, success):
+        if success:
+            os.rename(self.path_import, self.path)
+        else:
+            os.unlink(self.path_import)
+        return self
 
     def reset(self):
         ''' Remove and recreate a volatile volume '''
@@ -327,6 +339,11 @@ class FileVolume(qubes.storage.Volume):
         img_name = self.vid + '-cow.img'
         return os.path.join(self.dir_path, img_name)
 
+    @property
+    def path_import(self):
+        img_name = self.vid + '-import.img'
+        return os.path.join(self.dir_path, img_name)
+
     def verify(self):
         ''' Verifies the volume. '''
         if not os.path.exists(self.path) and \

+ 9 - 1
qubes/storage/lvm.py

@@ -99,7 +99,15 @@ class ThinPool(qubes.storage.Pool):
         return volume
 
     def setup(self):
-        pass  # TODO Should we create a non existing pool?
+        reset_cache()
+        cache_key = self.volume_group + '/' + self.thin_pool
+        if cache_key not in size_cache:
+            raise qubes.storage.StoragePoolException(
+                'Thin pool {} does not exist'.format(cache_key))
+        if size_cache[cache_key]['attr'][0] != 't':
+            raise qubes.storage.StoragePoolException(
+                'Volume {} is not a thin pool'.format(cache_key))
+        # TODO Should we create a non existing pool?
 
     def get_volume(self, vid):
         ''' Return a volume with given vid'''

+ 1 - 1
qubes/tests/api_admin.py

@@ -1645,7 +1645,7 @@ class TC_00_VMs(AdminAPITestCase):
         value = self.call_mgmt_func(b'admin.vm.volume.Import', b'test-vm1',
             b'private')
         self.assertEqual(value, '{} {}'.format(
-            2*2**30, '/tmp/qubes-test-dir/appvms/test-vm1/private.img'))
+            2*2**30, '/tmp/qubes-test-dir/appvms/test-vm1/private-import.img'))
         self.assertFalse(self.app.save.called)
 
     def test_511_vm_volume_import_running(self):

+ 42 - 0
qubes/tests/storage_file.py

@@ -312,6 +312,48 @@ class TC_01_FileVolumes(qubes.tests.QubesTestCase):
             volume.revisions_to_keep = 2
         self.assertEqual(volume.revisions_to_keep, 1)
 
+    def test_020_import_data(self):
+        config = {
+            'name': 'root',
+            'pool': self.POOL_NAME,
+            'save_on_stop': True,
+            'rw': True,
+            'size': 1024 * 1024,
+        }
+        vm = qubes.tests.storage.TestVM(self)
+        volume = self.app.get_pool(self.POOL_NAME).init_volume(vm, config)
+        volume.create()
+        import_path = volume.import_data()
+        self.assertNotEqual(volume.path, import_path)
+        with open(import_path, 'w+') as import_file:
+            import_file.write('test')
+        volume.import_data_end(True)
+        self.assertFalse(os.path.exists(import_path), import_path)
+        with open(volume.path) as volume_file:
+            volume_data = volume_file.read().strip('\0')
+        self.assertEqual(volume_data, 'test')
+
+    def test_021_import_data_fail(self):
+        config = {
+            'name': 'root',
+            'pool': self.POOL_NAME,
+            'save_on_stop': True,
+            'rw': True,
+            'size': 1024 * 1024,
+        }
+        vm = qubes.tests.storage.TestVM(self)
+        volume = self.app.get_pool(self.POOL_NAME).init_volume(vm, config)
+        volume.create()
+        import_path = volume.import_data()
+        self.assertNotEqual(volume.path, import_path)
+        with open(import_path, 'w+') as import_file:
+            import_file.write('test')
+        volume.import_data_end(False)
+        self.assertFalse(os.path.exists(import_path), import_path)
+        with open(volume.path) as volume_file:
+            volume_data = volume_file.read().strip('\0')
+        self.assertNotEqual(volume_data, 'test')
+
     def assertVolumePath(self, vm, dev_name, expected, rw=True):
         # :pylint: disable=invalid-name
         volumes = vm.volumes