Browse Source

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
Marek Marczykowski-Górecki 6 năm trước cách đây
mục cha
commit
3d4f626515

+ 3 - 0
qubesadmin/app.py

@@ -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)

+ 59 - 0
qubesadmin/tests/tools/qvm_run.py

@@ -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()

+ 8 - 2
qubesadmin/tests/vm/dispvm.py

@@ -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()

+ 4 - 1
qubesadmin/tools/qvm_run.py

@@ -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)

+ 3 - 0
qubesadmin/vm/__init__.py

@@ -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):