Skip to content

Commit

Permalink
tools: add qvm-run --service
Browse files Browse the repository at this point in the history
Make it convenient wrapper around qrexec-client{-vm}, which would start
a VM, wait for user session etc.
  • Loading branch information
marmarek committed May 20, 2017
1 parent f5e1021 commit 38abd81
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 8 deletions.
6 changes: 6 additions & 0 deletions doc/manpages/qvm-run.rst
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,12 @@ Options
Run the command without GUI forwarding enabled. Can be switched back with
: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

Mark the qube output with given ANSI colour (ie. "31" for red). The exact
Expand Down
32 changes: 32 additions & 0 deletions qubesadmin/tests/tools/qvm_run.py
Original file line number Diff line number Diff line change
Expand Up @@ -262,3 +262,35 @@ def test_006_run_single_with_gui(self):
('test-vm', 'qubes.VMShell', b'command; exit\n')
])
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()
27 changes: 19 additions & 8 deletions qubesadmin/tools/qvm_run.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,10 @@
help='do not filter terminal escape sequences; DANGEROUS when output is a'
' 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',
help='command to run')

Expand Down Expand Up @@ -136,7 +140,7 @@ def main(args=None, app=None):
run_kwargs['stderr'] = None

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
# simultaneous vchan connections
run_kwargs['wait'] = False
Expand Down Expand Up @@ -172,13 +176,20 @@ def main(args=None, app=None):
if args.passio and not args.localcmd:
loop = asyncio.new_event_loop()
loop.add_signal_handler(signal.SIGCHLD, loop.stop)
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.service:
proc = vm.run_service(args.cmd,
user=args.user,
localcmd=args.localcmd,
filter_esc=args.filter_esc,
**run_kwargs)
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:
asyncio.ensure_future(loop.connect_read_pipe(
functools.partial(DataCopyProtocol, proc.stdin,
Expand Down

0 comments on commit 38abd81

Please sign in to comment.