Browse Source

qubes/vm: Implement Disposable VM

Implement DispVM as a VM based on AppVM.

QubesOS/qubes-issues#866
Marek Marczykowski-Górecki 8 years ago
parent
commit
c965024287
4 changed files with 64 additions and 8 deletions
  1. 14 5
      qubes/tests/storage_file.py
  2. 1 1
      qubes/vm/appvm.py
  3. 48 2
      qubes/vm/dispvm.py
  4. 1 0
      setup.py

+ 14 - 5
qubes/tests/storage_file.py

@@ -162,12 +162,13 @@ class TC_01_FileVolumes(SystemTestsMixin, QubesTestCase):
 
         volumes = vm.volumes
         self.assertIsInstance(volumes['root'], SnapshotFile)
-        self.assertIsInstance(volumes['private'], ReadWriteFile)
+        self.assertIsInstance(volumes['private'], OriginFile)
         self.assertIsInstance(volumes['volatile'], VolatileFile)
         expected = vm.template.dir_path + '/root.img:' + vm.template.dir_path \
             + '/root-cow.img'
         self.assertVolumePath(vm, 'root', expected, rw=False)
-        expected = vm.dir_path + '/private.img'
+        expected = vm.dir_path + '/private.img:' + \
+            vm.dir_path + '/private-cow.img'
         self.assertVolumePath(vm, 'private', expected, rw=True)
         expected = vm.dir_path + '/volatile.img'
         self.assertVolumePath(vm, 'volatile', expected, rw=True)
@@ -264,9 +265,17 @@ class TC_03_FilePool(SystemTestsMixin, QubesTestCase):
 
         expected_vmdir = os.path.join(self.APPVMS_DIR, vm.name)
 
-        expected_private_path = os.path.join(expected_vmdir, 'private.img')
-        self.assertEqualsAndExists(vm.volumes['private'].path,
-                                   expected_private_path)
+        expected_private_origin_path = \
+            os.path.join(expected_vmdir, 'private.img')
+        expected_private_cow_path = \
+            os.path.join(expected_vmdir, 'private-cow.img')
+        expected_private_path = '%s:%s' % (expected_private_origin_path,
+                                        expected_private_cow_path)
+        self.assertEquals(vm.volumes['private'].path, expected_private_path)
+        self.assertEqualsAndExists(vm.volumes['private'].path_origin,
+            expected_private_origin_path)
+        self.assertEqualsAndExists(vm.volumes['private'].path_cow,
+            expected_private_cow_path)
 
         expected_volatile_path = os.path.join(expected_vmdir, 'volatile.img')
         self.assertEqualsAndExists(vm.volumes['volatile'].path,

+ 1 - 1
qubes/vm/appvm.py

@@ -26,7 +26,7 @@ class AppVM(qubes.vm.qubesvm.QubesVM):
             'private': {
                 'name': 'private',
                 'pool': 'default',
-                'volume_type': 'read-write',
+                'volume_type': 'origin',
                 'size': defaults['private_img_size'],
             },
             'volatile': {

+ 48 - 2
qubes/vm/dispvm.py

@@ -2,8 +2,54 @@
 # vim: fileencoding=utf-8
 
 import qubes.vm.qubesvm
+import qubes.vm.appvm
+import qubes.config
 
 class DispVM(qubes.vm.qubesvm.QubesVM):
     '''Disposable VM'''
-    def __init__(self, D):
-        super(DispVM, self).__init__(D)
+
+    template = qubes.VMProperty('template',
+                                load_stage=4,
+                                vmclass=qubes.vm.appvm.AppVM,
+                                ls_width=31,
+                                doc='AppVM, on which this DispVM is based.')
+
+    dispid = qubes.property('dispid', type=int, write_once=True,
+        clone=False,
+        ls_width=3,
+        doc='''Internal, persistent identifier of particular DispVM.''')
+
+    def __init__(self, *args, **kwargs):
+        self.volumes = {}
+        self.volume_config = {
+            'root': {
+                'name': 'root',
+                'pool': 'default',
+                'volume_type': 'snapshot',
+            },
+            'private': {
+                'name': 'private',
+                'pool': 'default',
+                'volume_type': 'snapshot',
+            },
+            'volatile': {
+                'name': 'volatile',
+                'pool': 'default',
+                'volume_type': 'volatile',
+                'size': qubes.config.defaults['root_img_size'] +
+                        qubes.config.defaults['private_img_size'],
+            },
+            'kernel': {
+                'name': 'kernel',
+                'pool': 'linux-kernel',
+                'volume_type': 'read-only',
+            }
+        }
+        super(DispVM, self).__init__(*args, **kwargs)
+
+    @qubes.events.handler('domain-load')
+    def on_domain_loaded(self, event):
+        # pylint: disable=unused-argument
+        # Some additional checks for template based VM
+        assert self.template
+        # self.template.appvms.add(self) # XXX

+ 1 - 0
setup.py

@@ -34,6 +34,7 @@ if __name__ == '__main__':
                 'TemplateVM = qubes.vm.templatevm:TemplateVM',
                 'StandaloneVM = qubes.vm.standalonevm:StandaloneVM',
                 'AdminVM = qubes.vm.adminvm:AdminVM',
+                'DispVM = qubes.vm.dispvm:DispVM',
             ],
             'qubes.ext': [
                 'qubes.ext.qubesmanager = qubes.ext.qubesmanager:QubesManager',