Browse Source

Introduce management_dispvm property

The new property is meant for management stack (Salt) to set which DVM
template should be used to maintain given VM. Since the DispVM based on
it will be given ultimate control over target VM (qubes.VMShell
service), it should be trusted. The one pointed to by default_dispvm
not necessary is one.

The property defaults to the value from the template (if any), and then
to a global management_dispvm property. By default it is set to None.

Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
Marek Marczykowski-Górecki 5 years ago
parent
commit
7d1bcaf64c
3 changed files with 41 additions and 0 deletions
  1. 4 0
      qubes/app.py
  2. 30 0
      qubes/tests/vm/qubesvm.py
  3. 7 0
      qubes/vm/qubesvm.py

+ 4 - 0
qubes/app.py

@@ -692,6 +692,10 @@ class Qubes(qubes.PropertyHolder):
         default=None,
         doc='Default DispVM base for service calls', allow_none=True)
 
+    management_dispvm = qubes.VMProperty('management_dispvm', load_stage=3,
+        default=None,
+        doc='Default DispVM base for managing VMs', allow_none=True)
+
     default_pool = qubes.property('default_pool', load_stage=3,
         default=_default_pool,
         setter=_setter_pool,

+ 30 - 0
qubes/tests/vm/qubesvm.py

@@ -498,6 +498,36 @@ class TC_90_QubesVM(QubesVMTestsMixin, qubes.tests.QubesTestCase):
             'qubes-vm@{}.service'.format(vm.name)),
             "systemd service not disabled by resetting autostart")
 
+    def test_290_management_dispvm(self):
+        vm = self.get_vm()
+        vm2 = self.get_vm('test2', qid=2)
+        self.app.management_dispvm = None
+        self.assertPropertyDefaultValue(vm, 'management_dispvm', None)
+        self.app.management_dispvm = vm
+        try:
+            self.assertPropertyDefaultValue(vm, 'management_dispvm', vm)
+            self.assertPropertyValue(vm, 'management_dispvm',
+                'test-inst-test2', vm2)
+        finally:
+            self.app.management_dispvm = None
+
+    def test_291_management_dispvm_template_based(self):
+        tpl = self.get_vm(name='tpl', cls=qubes.vm.templatevm.TemplateVM)
+        vm = self.get_vm(cls=qubes.vm.appvm.AppVM, template=tpl, qid=2)
+        vm2 = self.get_vm('test2', qid=3)
+        del vm.volumes
+        self.app.management_dispvm = None
+        try:
+            self.assertPropertyDefaultValue(vm, 'management_dispvm', None)
+            self.app.management_dispvm = vm
+            self.assertPropertyDefaultValue(vm, 'management_dispvm', vm)
+            tpl.management_dispvm = vm2
+            self.assertPropertyDefaultValue(vm, 'management_dispvm', vm2)
+            self.assertPropertyValue(vm, 'management_dispvm',
+                'test-inst-test2', vm2)
+        finally:
+            self.app.management_dispvm = None
+
     @unittest.skip('TODO')
     def test_320_seamless_gui_mode(self):
         vm = self.get_vm()

+ 7 - 0
qubes/vm/qubesvm.py

@@ -554,6 +554,13 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
         default=(lambda self: self.app.default_dispvm),
         doc='Default VM to be used as Disposable VM for service calls.')
 
+    management_dispvm = qubes.VMProperty('management_dispvm',
+        load_stage=4,
+        allow_none=True,
+        default=_default_with_template('management_dispvm',
+            (lambda self: self.app.management_dispvm)),
+        doc='Default DVM template for Disposable VM for managing this VM.')
+
     updateable = qubes.property('updateable',
         default=(lambda self: not hasattr(self, 'template')),
         type=bool,