diff --git a/qubesadmin/tests/tools/qvm_run.py b/qubesadmin/tests/tools/qvm_run.py index 013a6a3a..9568fb06 100644 --- a/qubesadmin/tests/tools/qvm_run.py +++ b/qubesadmin/tests/tools/qvm_run.py @@ -668,7 +668,7 @@ def test_008_dispvm_remote(self): self.app.service_calls, [ ( - "$dispvm", + "@dispvm", "test.service", { "stdout": subprocess.DEVNULL, @@ -676,7 +676,7 @@ def test_008_dispvm_remote(self): "user": None, }, ), - ("$dispvm", "test.service", b""), + ("@dispvm", "test.service", b""), ], ) self.assertAllCalled() @@ -699,7 +699,7 @@ def test_009_dispvm_remote_specific(self): self.app.service_calls, [ ( - "$dispvm:test-vm", + "@dispvm:test-vm", "test.service", { "stdout": subprocess.DEVNULL, @@ -707,7 +707,7 @@ def test_009_dispvm_remote_specific(self): "user": None, }, ), - ("$dispvm:test-vm", "test.service", b""), + ("@dispvm:test-vm", "test.service", b""), ], ) self.assertAllCalled() @@ -1150,7 +1150,7 @@ def test_022_no_shell(self): def test_023_dispvm_no_shell(self): self.app.expected_calls[ ( - "$dispvm:test-vm", + "@dispvm:test-vm", "admin.vm.feature.CheckWithTemplate", "vmexec", None, @@ -1165,7 +1165,7 @@ def test_023_dispvm_no_shell(self): self.app.service_calls, [ ( - "$dispvm:test-vm", + "@dispvm:test-vm", "qubes.VMExec+command", { "stdout": subprocess.DEVNULL, @@ -1173,7 +1173,7 @@ def test_023_dispvm_no_shell(self): "user": None, }, ), - ("$dispvm:test-vm", "qubes.VMExec+command", b""), + ("@dispvm:test-vm", "qubes.VMExec+command", b""), ], ) self.assertAllCalled() @@ -1277,7 +1277,7 @@ def test_026_no_shell_double_dashdash(self): def test_027_no_shell_dispvm(self): self.app.expected_calls[ ( - "$dispvm:test-vm", + "@dispvm:test-vm", "admin.vm.feature.CheckWithTemplate", "vmexec", None, @@ -1292,7 +1292,7 @@ def test_027_no_shell_dispvm(self): self.app.service_calls, [ ( - "$dispvm:test-vm", + "@dispvm:test-vm", "qubes.VMExec+command+arg", { "stdout": subprocess.DEVNULL, @@ -1300,7 +1300,7 @@ def test_027_no_shell_dispvm(self): "user": None, }, ), - ("$dispvm:test-vm", "qubes.VMExec+command+arg", b""), + ("@dispvm:test-vm", "qubes.VMExec+command+arg", b""), ], ) self.assertAllCalled() @@ -1308,7 +1308,7 @@ def test_027_no_shell_dispvm(self): def test_028_argparse_bug_workaround(self): self.app.expected_calls[ ( - "$dispvm:test-vm", + "@dispvm:test-vm", "admin.vm.feature.CheckWithTemplate", "vmexec", None, @@ -1323,7 +1323,7 @@ def test_028_argparse_bug_workaround(self): self.app.service_calls, [ ( - "$dispvm:test-vm", + "@dispvm:test-vm", "qubes.VMExec+command+----", { "stdout": subprocess.DEVNULL, @@ -1331,7 +1331,7 @@ def test_028_argparse_bug_workaround(self): "user": None, }, ), - ("$dispvm:test-vm", "qubes.VMExec+command+----", b""), + ("@dispvm:test-vm", "qubes.VMExec+command+----", b""), ], ) self.assertAllCalled() @@ -1339,7 +1339,7 @@ def test_028_argparse_bug_workaround(self): def test_029_command_is_dashdash(self): self.app.expected_calls[ ( - "$dispvm:test-vm", + "@dispvm:test-vm", "admin.vm.feature.CheckWithTemplate", "vmexec", None, @@ -1354,7 +1354,7 @@ def test_029_command_is_dashdash(self): self.app.service_calls, [ ( - "$dispvm:test-vm", + "@dispvm:test-vm", "qubes.VMExec+----", { "stdout": subprocess.DEVNULL, @@ -1362,14 +1362,14 @@ def test_029_command_is_dashdash(self): "user": None, }, ), - ("$dispvm:test-vm", "qubes.VMExec+----", b""), + ("@dispvm:test-vm", "qubes.VMExec+----", b""), ], ) self.assertAllCalled() def test_030_no_shell_dispvm(self): self.app.expected_calls[ - ("$dispvm", "admin.vm.feature.CheckWithTemplate", "vmexec", None) + ("@dispvm", "admin.vm.feature.CheckWithTemplate", "vmexec", None) ] = b"0\x001" ret = qubesadmin.tools.qvm_run.main( ["--no-gui", "--dispvm", "--", "test-vm", "command", "arg"], @@ -1380,7 +1380,7 @@ def test_030_no_shell_dispvm(self): self.app.service_calls, [ ( - "$dispvm", + "@dispvm", "qubes.VMExec+test--vm+command+arg", { "stdout": subprocess.DEVNULL, @@ -1388,14 +1388,14 @@ def test_030_no_shell_dispvm(self): "user": None, }, ), - ("$dispvm", "qubes.VMExec+test--vm+command+arg", b""), + ("@dispvm", "qubes.VMExec+test--vm+command+arg", b""), ], ) self.assertAllCalled() def test_031_argparse_bug_workaround(self): self.app.expected_calls[ - ("$dispvm", "admin.vm.feature.CheckWithTemplate", "vmexec", None) + ("@dispvm", "admin.vm.feature.CheckWithTemplate", "vmexec", None) ] = b"0\x001" ret = qubesadmin.tools.qvm_run.main( ["--no-gui", "--dispvm", "--", "test-vm", "command", "--"], @@ -1406,7 +1406,7 @@ def test_031_argparse_bug_workaround(self): self.app.service_calls, [ ( - "$dispvm", + "@dispvm", "qubes.VMExec+test--vm+command+----", { "stdout": subprocess.DEVNULL, @@ -1414,7 +1414,7 @@ def test_031_argparse_bug_workaround(self): "user": None, }, ), - ("$dispvm", "qubes.VMExec+test--vm+command+----", b""), + ("@dispvm", "qubes.VMExec+test--vm+command+----", b""), ], ) self.assertAllCalled() @@ -1422,7 +1422,7 @@ def test_031_argparse_bug_workaround(self): @unittest.expectedFailure def test_032_argparse_bug_workaround_unnamed_dispvm(self): self.app.expected_calls[ - ("$dispvm", "admin.vm.feature.CheckWithTemplate", "vmexec", None) + ("@dispvm", "admin.vm.feature.CheckWithTemplate", "vmexec", None) ] = b"0\x001" ret = qubesadmin.tools.qvm_run.main( ["--no-gui", "--dispvm", "test-vm", "command", "--"], app=self.app @@ -1432,7 +1432,7 @@ def test_032_argparse_bug_workaround_unnamed_dispvm(self): self.app.service_calls, [ ( - "$dispvm", + "@dispvm", "qubes.VMExec+test--vm+command+----", { "stdout": subprocess.DEVNULL, @@ -1440,7 +1440,7 @@ def test_032_argparse_bug_workaround_unnamed_dispvm(self): "user": None, }, ), - ("$dispvm", "qubes.VMExec+test--vm+command+----", b""), + ("@dispvm", "qubes.VMExec+test--vm+command+----", b""), ], ) self.assertAllCalled() diff --git a/qubesadmin/tests/vm/dispvm.py b/qubesadmin/tests/vm/dispvm.py index dccd217d..02d8030a 100644 --- a/qubesadmin/tests/vm/dispvm.py +++ b/qubesadmin/tests/vm/dispvm.py @@ -73,8 +73,8 @@ def test_010_remote_create_default(self): vm.run_service_for_stdio('test.service') vm.cleanup() self.assertEqual(self.app.service_calls, [ - ('$dispvm', 'test.service', {}), - ('$dispvm', 'test.service', b''), + ('@dispvm', 'test.service', {}), + ('@dispvm', 'test.service', b''), ]) self.assertAllCalled() @@ -83,8 +83,8 @@ def test_011_remote_create_specific(self): vm.run_service_for_stdio('test.service') vm.cleanup() self.assertEqual(self.app.service_calls, [ - ('$dispvm:test-vm', 'test.service', {}), - ('$dispvm:test-vm', 'test.service', b''), + ('@dispvm:test-vm', 'test.service', {}), + ('@dispvm:test-vm', 'test.service', b''), ]) self.assertAllCalled() diff --git a/qubesadmin/vm/__init__.py b/qubesadmin/vm/__init__.py index 5a3af452..7543a358 100644 --- a/qubesadmin/vm/__init__.py +++ b/qubesadmin/vm/__init__.py @@ -454,37 +454,34 @@ def set_notes(self, notes: str): class DispVMWrapper(QubesVM): - """Wrapper class for new DispVM, supporting only service call + """ + Wrapper class for new disposable, supporting only service call. - Note that when running in dom0, one need to manually kill the DispVM after - service call ends. + Note that when running in dom0, one need to manually kill the disposable + after service call ends. """ def run_service(self, service, **kwargs): - if self.app.qubesd_connection_type == "socket": - # create dispvm at service call - if self._method_dest.startswith("$dispvm"): - if self._method_dest.startswith("$dispvm:"): - method_dest = self._method_dest[len("$dispvm:") :] - else: - method_dest = "dom0" - dispvm = self.app.qubesd_call( - method_dest, "admin.vm.CreateDisposable" - ) - dispvm = dispvm.decode("ascii") - self._method_dest = dispvm - # Service call may wait for session start, give it more time - # than default 5s - kwargs["connect_timeout"] = self.qrexec_timeout + """Create disposable if absent and run service.""" + if ( + self.app.qubesd_connection_type == "socket" + and self._method_dest.startswith("@dispvm") + ): + self.create_disposable() + # Service call may wait for session start, give it more time + # than default 5s + kwargs["connect_timeout"] = self.qrexec_timeout return super().run_service(service, **kwargs) def cleanup(self): - """Cleanup after DispVM usage""" - # in 'remote' case nothing is needed, as DispVM is cleaned up - # automatically + """ + Cleanup after disposable usage. + + Disposable is cleaned up automatically in 'remote' case. + """ if ( self.app.qubesd_connection_type == "socket" - and not self._method_dest.startswith("$dispvm") + and not self._method_dest.startswith("@dispvm") ): try: self.kill() @@ -492,11 +489,16 @@ def cleanup(self): pass def start(self): - """Start this DispVM""" - # create dispvm - if self._method_dest.startswith("$dispvm"): - if self._method_dest.startswith("$dispvm:"): - method_dest = self._method_dest[len("$dispvm:") :] + """Create disposable if absent and start it.""" + if self._method_dest.startswith("@dispvm"): + self.create_disposable() + super().start() + + def create_disposable(self): + """Create disposable.""" + if self._method_dest.startswith("@dispvm"): + if self._method_dest.startswith("@dispvm:"): + method_dest = self._method_dest[len("@dispvm:") :] else: method_dest = "dom0" dispvm = self.app.qubesd_call( @@ -504,7 +506,7 @@ def start(self): ) dispvm = dispvm.decode("ascii") self._method_dest = dispvm - super().start() + return self class DispVM(QubesVM): @@ -516,9 +518,9 @@ def from_appvm(cls, app, appvm): AppVM. If *appvm* is none, use default DispVM template""" if appvm: - method_dest = "$dispvm:" + str(appvm) + method_dest = "@dispvm:" + str(appvm) else: - method_dest = "$dispvm" + method_dest = "@dispvm" wrapper = DispVMWrapper(app, method_dest) return wrapper