tools: add qvm-run --service

Make it convenient wrapper around qrexec-client{-vm}, which would start
a VM, wait for user session etc.
Šī revīzija ir iekļauta:
Marek Marczykowski-Górecki 2017-05-19 19:41:39 +02:00
vecāks f5e102177c
revīzija 38abd81ea8
Šim parakstam datu bāzē netika atrasta zināma atslēga
GPG atslēgas ID: 063938BA42CFA724
3 mainīti faili ar 57 papildinājumiem un 8 dzēšanām

Parādīt failu

@ -63,6 +63,12 @@ Options
Run the command without GUI forwarding enabled. Can be switched back with Run the command without GUI forwarding enabled. Can be switched back with
:option:`--gui`. :option:`--gui`.
.. option:: --service
Start RPC service instead of shell command. Specify name of the service in
place of *COMMAND* argument. You can also specify service argument, appending
it to the service name after `+` character.
.. option:: --colour-output=COLOUR, --color-output=COLOR .. option:: --colour-output=COLOUR, --color-output=COLOR
Mark the qube output with given ANSI colour (ie. "31" for red). The exact Mark the qube output with given ANSI colour (ie. "31" for red). The exact

Parādīt failu

@ -262,3 +262,35 @@ class TC_00_qvm_run(qubesadmin.tests.QubesTestCase):
('test-vm', 'qubes.VMShell', b'command; exit\n') ('test-vm', 'qubes.VMShell', b'command; exit\n')
]) ])
self.assertAllCalled() self.assertAllCalled()
def test_007_run_service_with_gui(self):
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', 'default_user', None)] = \
b'0\x00default=yes type=str user'
# self.app.expected_calls[
# ('test-vm', 'admin.vm.List', None, None)] = \
# b'0\x00test-vm class=AppVM state=Running\n'
ret = qubesadmin.tools.qvm_run.main(
['--service', 'test-vm', 'service.name'],
app=self.app)
self.assertEqual(ret, 0)
# make sure we have the same instance below
self.assertEqual(self.app.service_calls, [
('test-vm', 'qubes.WaitForSession', {
'stdout': subprocess.DEVNULL,
'stderr': subprocess.DEVNULL,
}),
('test-vm', 'qubes.WaitForSession', b'user'),
('test-vm', 'service.name', {
'filter_esc': True,
'localcmd': None,
'stdout': subprocess.DEVNULL,
'stderr': subprocess.DEVNULL,
'user': None,
}),
('test-vm', 'service.name', b''),
])
self.assertAllCalled()

Parādīt failu

@ -86,6 +86,10 @@ parser.add_argument('--no-filter-escape-chars',
help='do not filter terminal escape sequences; DANGEROUS when output is a' help='do not filter terminal escape sequences; DANGEROUS when output is a'
' terminal emulator') ' terminal emulator')
parser.add_argument('--service',
action='store_true', dest='service',
help='run a qrexec service (named by COMMAND) instead of shell command')
parser.add_argument('cmd', metavar='COMMAND', parser.add_argument('cmd', metavar='COMMAND',
help='command to run') help='command to run')
@ -136,7 +140,7 @@ def main(args=None, app=None):
run_kwargs['stderr'] = None run_kwargs['stderr'] = None
if isinstance(args.app, qubesadmin.app.QubesLocal) and \ if isinstance(args.app, qubesadmin.app.QubesLocal) and \
not args.passio and not args.localcmd: not args.passio and not args.localcmd and args.service:
# wait=False works only in dom0; but it's still useful, to save on # wait=False works only in dom0; but it's still useful, to save on
# simultaneous vchan connections # simultaneous vchan connections
run_kwargs['wait'] = False run_kwargs['wait'] = False
@ -172,13 +176,20 @@ def main(args=None, app=None):
if args.passio and not args.localcmd: if args.passio and not args.localcmd:
loop = asyncio.new_event_loop() loop = asyncio.new_event_loop()
loop.add_signal_handler(signal.SIGCHLD, loop.stop) loop.add_signal_handler(signal.SIGCHLD, loop.stop)
proc = vm.run_service('qubes.VMShell', if args.service:
user=args.user, proc = vm.run_service(args.cmd,
localcmd=args.localcmd, user=args.user,
filter_esc=args.filter_esc, localcmd=args.localcmd,
**run_kwargs) filter_esc=args.filter_esc,
proc.stdin.write(vm.prepare_input_for_vmshell(args.cmd)) **run_kwargs)
proc.stdin.flush() else:
proc = vm.run_service('qubes.VMShell',
user=args.user,
localcmd=args.localcmd,
filter_esc=args.filter_esc,
**run_kwargs)
proc.stdin.write(vm.prepare_input_for_vmshell(args.cmd))
proc.stdin.flush()
if args.passio and not args.localcmd: if args.passio and not args.localcmd:
asyncio.ensure_future(loop.connect_read_pipe( asyncio.ensure_future(loop.connect_read_pipe(
functools.partial(DataCopyProtocol, proc.stdin, functools.partial(DataCopyProtocol, proc.stdin,