Merge remote-tracking branch 'qubesos/pr/51'

* qubesos/pr/51:
  qvm-run: wait for X11 in --dispvm --gui case
  vm/DispVM: use 'qrexec_timeout' also for call connection timeout
This commit is contained in:
Marek Marczykowski-Górecki 2018-01-15 03:23:54 +01:00
commit 3d4f626515
No known key found for this signature in database
GPG Key ID: 063938BA42CFA724
5 changed files with 77 additions and 3 deletions

View File

@ -494,6 +494,7 @@ class QubesLocal(QubesBase):
:param str user: username to run service as
:param str localcmd: Command to connect stdin/stdout to
:param bool wait: wait for remote process to finish
:param int connect_timeout: qrexec client connection timeout
:rtype: subprocess.Popen
'''
@ -516,6 +517,8 @@ class QubesLocal(QubesBase):
user = 'DEFAULT'
if not wait:
qrexec_opts.extend(['-e'])
if 'connect_timeout' in kwargs:
qrexec_opts.extend(['-w', str(kwargs.pop('connect_timeout'))])
kwargs.setdefault('stdin', subprocess.PIPE)
kwargs.setdefault('stdout', subprocess.PIPE)
kwargs.setdefault('stderr', subprocess.PIPE)

View File

@ -343,6 +343,9 @@ class TC_00_qvm_run(qubesadmin.tests.QubesTestCase):
b'0\0disp123'
self.app.expected_calls[('disp123', 'admin.vm.Kill', None, None)] = \
b'0\0'
self.app.expected_calls[
('disp123', 'admin.vm.property.Get', 'qrexec_timeout', None)] = \
b'0\0default=yes type=int 30'
ret = qubesadmin.tools.qvm_run.main(
['--dispvm', '--service', 'test.service'], app=self.app)
self.assertEqual(ret, 0)
@ -352,6 +355,7 @@ class TC_00_qvm_run(qubesadmin.tests.QubesTestCase):
'stdout': subprocess.DEVNULL,
'stderr': subprocess.DEVNULL,
'user': None,
'connect_timeout': 30,
}),
('disp123', 'test.service', b''),
])
@ -364,6 +368,9 @@ class TC_00_qvm_run(qubesadmin.tests.QubesTestCase):
b'0\0disp123'
self.app.expected_calls[('disp123', 'admin.vm.Kill', None, None)] = \
b'0\0'
self.app.expected_calls[
('disp123', 'admin.vm.property.Get', 'qrexec_timeout', None)] = \
b'0\0default=yes type=int 30'
ret = qubesadmin.tools.qvm_run.main(
['--dispvm=test-vm', '--service', 'test.service'], app=self.app)
self.assertEqual(ret, 0)
@ -373,6 +380,7 @@ class TC_00_qvm_run(qubesadmin.tests.QubesTestCase):
'stdout': subprocess.DEVNULL,
'stderr': subprocess.DEVNULL,
'user': None,
'connect_timeout': 30,
}),
('disp123', 'test.service', b''),
])
@ -420,3 +428,54 @@ class TC_00_qvm_run(qubesadmin.tests.QubesTestCase):
self.assertEqual(ret, 0)
self.assertEqual(self.app.service_calls, [])
self.assertAllCalled()
def test_014_dispvm_local_gui(self):
self.app.qubesd_connection_type = 'socket'
self.app.expected_calls[
('dom0', 'admin.vm.CreateDisposable', None, None)] = \
b'0\0disp123'
self.app.expected_calls[('disp123', 'admin.vm.Kill', None, None)] = \
b'0\0'
self.app.expected_calls[
('disp123', 'admin.vm.property.Get', 'qrexec_timeout', None)] = \
b'0\0default=yes type=int 30'
ret = qubesadmin.tools.qvm_run.main(
['--dispvm', '--', 'test.command'], app=self.app)
self.assertEqual(ret, 0)
self.assertEqual(self.app.service_calls, [
('disp123', 'qubes.VMShell+WaitForSession', {
'localcmd': None,
'stdout': subprocess.DEVNULL,
'stderr': subprocess.DEVNULL,
'user': None,
'connect_timeout': 30,
}),
('disp123', 'qubes.VMShell+WaitForSession',
b'test.command; exit\n'),
])
self.assertAllCalled()
def test_015_dispvm_local_no_gui(self):
self.app.qubesd_connection_type = 'socket'
self.app.expected_calls[
('dom0', 'admin.vm.CreateDisposable', None, None)] = \
b'0\0disp123'
self.app.expected_calls[('disp123', 'admin.vm.Kill', None, None)] = \
b'0\0'
self.app.expected_calls[
('disp123', 'admin.vm.property.Get', 'qrexec_timeout', None)] = \
b'0\0default=yes type=int 30'
ret = qubesadmin.tools.qvm_run.main(
['--dispvm', '--no-gui', 'test.command'], app=self.app)
self.assertEqual(ret, 0)
self.assertEqual(self.app.service_calls, [
('disp123', 'qubes.VMShell', {
'localcmd': None,
'stdout': subprocess.DEVNULL,
'stderr': subprocess.DEVNULL,
'user': None,
'connect_timeout': 30,
}),
('disp123', 'qubes.VMShell', b'test.command; exit\n'),
])
self.assertAllCalled()

View File

@ -28,11 +28,14 @@ class TC_00_Dispvm(qubesadmin.tests.QubesTestCase):
('dom0', 'admin.vm.CreateDisposable', None, None)] = b'0\0disp123'
self.app.expected_calls[
('disp123', 'admin.vm.Kill', None, None)] = b'0\0'
self.app.expected_calls[
('disp123', 'admin.vm.property.Get', 'qrexec_timeout', None)] = \
b'0\0default=yes type=int 30'
vm = qubesadmin.vm.DispVM.from_appvm(self.app, None)
(stdout, stderr) = vm.run_service_for_stdio('test.service')
vm.cleanup()
self.assertEqual(self.app.service_calls, [
('disp123', 'test.service', {}),
('disp123', 'test.service', {'connect_timeout': 30}),
('disp123', 'test.service', b''),
])
self.assertAllCalled()
@ -44,11 +47,14 @@ class TC_00_Dispvm(qubesadmin.tests.QubesTestCase):
b'0\0disp123'
self.app.expected_calls[
('disp123', 'admin.vm.Kill', None, None)] = b'0\0'
self.app.expected_calls[
('disp123', 'admin.vm.property.Get', 'qrexec_timeout', None)] = \
b'0\0default=yes type=int 30'
vm = qubesadmin.vm.DispVM.from_appvm(self.app, 'test-vm')
(stdout, stderr) = vm.run_service_for_stdio('test.service')
vm.cleanup()
self.assertEqual(self.app.service_calls, [
('disp123', 'test.service', {}),
('disp123', 'test.service', {'connect_timeout': 30}),
('disp123', 'test.service', b''),
])
self.assertAllCalled()

View File

@ -209,7 +209,10 @@ def main(args=None, app=None):
localcmd=args.localcmd,
**run_kwargs)
else:
proc = vm.run_service('qubes.VMShell',
service = 'qubes.VMShell'
if args.gui and args.dispvm:
service += '+WaitForSession'
proc = vm.run_service(service,
user=args.user,
localcmd=args.localcmd,
**run_kwargs)

View File

@ -350,6 +350,9 @@ class DispVMWrapper(QubesVM):
'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
return super(DispVMWrapper, self).run_service(service, **kwargs)
def cleanup(self):