Add 'gui-emulated' feature
Add an explicit method for forcing emulated VGA output. Previously it was possible only by removing `gui` feature (setting it to false had a different effect), or enabling debug mode. Using lack of a feature as a third state was a bad idea. QubesOS/qubes-issues#3585
This commit is contained in:
parent
95ce30a9e3
commit
4d61407f5d
@ -59,13 +59,28 @@ List of known features
|
||||
gui
|
||||
^^^
|
||||
|
||||
Qube provide any kind of GUI. Setting this feature to :py:obj:`False` disable
|
||||
GUI for given qubes - both gui-agent based and emulated VGA based one. Setting
|
||||
this feature to :py:obj:`True` enable gui-agent based GUI (i.e. with support of
|
||||
tools installed inside of qube). Not setting this feature at all, enable showing
|
||||
VGA emulated output.
|
||||
Qube has gui-agent installed. Setting this feature to :py:obj:`True` enables GUI
|
||||
based on a gui-agent installed inside the VM.
|
||||
See also `gui-emulated` feature.
|
||||
|
||||
Default: show emulated VGA output only
|
||||
If neither `gui` nor `gui-emulated` is set, emulated VGA is used (if
|
||||
applicable for given VM virtualization mode).
|
||||
|
||||
gui-emulated
|
||||
^^^^^^^^^^^^
|
||||
|
||||
Qube provides GUI through emulated VGA. Setting this feature to
|
||||
:py:obj:`True` enables emulated VGA output. Note that when gui-agent connects to
|
||||
actual VM, emulated VGA output is closed (unless `debug` property is set to
|
||||
:py:obj:`True`). It's possible to open emulated VGA output for a running qube,
|
||||
regardless of this feature, using `qvm-start-gui --force-stubdomain QUBE_NAME`
|
||||
command.
|
||||
|
||||
This feature is applicable only when qube's `virt_mode` is set to `hvm`.
|
||||
See also `gui` feature.
|
||||
|
||||
If neither `gui` nor `gui-emulated` is set, emulated VGA is used (if
|
||||
applicable for given VM virtualization mode).
|
||||
|
||||
qrexec
|
||||
^^^^^^
|
||||
|
@ -309,6 +309,43 @@ class TC_00_qvm_start_gui(qubesadmin.tests.QubesTestCase):
|
||||
self.app.expected_calls[
|
||||
('test-vm', 'admin.vm.feature.CheckWithTemplate', 'gui', None)] = \
|
||||
b'2\x00QubesFeatureNotFoundError\x00\x00Feature not set\x00'
|
||||
self.app.expected_calls[
|
||||
('test-vm', 'admin.vm.feature.CheckWithTemplate', 'gui-emulated',
|
||||
None)] = \
|
||||
b'2\x00QubesFeatureNotFoundError\x00\x00Feature not set\x00'
|
||||
proc_mock = unittest.mock.Mock()
|
||||
with unittest.mock.patch('asyncio.create_subprocess_exec',
|
||||
lambda *args: self.mock_coroutine(proc_mock, *args)):
|
||||
with unittest.mock.patch.object(self.launcher,
|
||||
'common_guid_args', lambda vm: []):
|
||||
loop.run_until_complete(self.launcher.start_gui_for_stubdomain(
|
||||
self.app.domains['test-vm']))
|
||||
# common arguments dropped for simplicity
|
||||
proc_mock.assert_called_once_with('-d', '3001', '-t', '3000')
|
||||
|
||||
self.assertAllCalled()
|
||||
|
||||
def test_031_start_gui_for_stubdomain_forced(self):
|
||||
loop = asyncio.new_event_loop()
|
||||
asyncio.set_event_loop(loop)
|
||||
self.addCleanup(loop.close)
|
||||
|
||||
self.app.expected_calls[
|
||||
('dom0', 'admin.vm.List', None, None)] = \
|
||||
b'0\x00test-vm class=AppVM state=Running\n'
|
||||
self.app.expected_calls[
|
||||
('test-vm', 'admin.vm.property.Get', 'xid', None)] = \
|
||||
b'0\x00default=False type=int 3000'
|
||||
self.app.expected_calls[
|
||||
('test-vm', 'admin.vm.property.Get', 'stubdom_xid', None)] = \
|
||||
b'0\x00default=False type=int 3001'
|
||||
# self.app.expected_calls[
|
||||
# ('test-vm', 'admin.vm.feature.CheckWithTemplate', 'gui', None)] = \
|
||||
# b'0\x00'
|
||||
self.app.expected_calls[
|
||||
('test-vm', 'admin.vm.feature.CheckWithTemplate', 'gui-emulated',
|
||||
None)] = \
|
||||
b'0\x001'
|
||||
proc_mock = unittest.mock.Mock()
|
||||
with unittest.mock.patch('asyncio.create_subprocess_exec',
|
||||
lambda *args: self.mock_coroutine(proc_mock, *args)):
|
||||
|
@ -214,9 +214,13 @@ class GUILauncher(object):
|
||||
This function is a coroutine.
|
||||
'''
|
||||
want_stubdom = force
|
||||
# if no 'gui' feature set at all, assume no gui agent installed
|
||||
if not want_stubdom and \
|
||||
vm.features.check_with_template('gui', None) is None:
|
||||
vm.features.check_with_template('gui-emulated', False):
|
||||
want_stubdom = True
|
||||
# if no 'gui' or 'gui-emulated' feature set at all, use emulated GUI
|
||||
if not want_stubdom and \
|
||||
vm.features.check_with_template('gui', None) is None and \
|
||||
vm.features.check_with_template('gui-emulated', None) is None:
|
||||
want_stubdom = True
|
||||
if not want_stubdom and vm.debug:
|
||||
want_stubdom = True
|
||||
@ -240,13 +244,13 @@ class GUILauncher(object):
|
||||
:param force_stubdom: Force GUI daemon for stubdomain, even if the
|
||||
one for target AppVM is running.
|
||||
'''
|
||||
if not vm.features.check_with_template('gui', True):
|
||||
return
|
||||
|
||||
if vm.virt_mode == 'hvm':
|
||||
yield from self.start_gui_for_stubdomain(vm,
|
||||
force=force_stubdom)
|
||||
|
||||
if not vm.features.check_with_template('gui', True):
|
||||
return
|
||||
|
||||
if not os.path.exists(self.guid_pidfile(vm.xid)):
|
||||
yield from self.start_gui_for_vm(vm, monitor_layout=monitor_layout)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user