Merge branch 'devel-6'

* devel-6:
  qvm-ls: fix total VM size reporting
  doc: update manpage of qvm-service
  tools: qvm-service tool
  tests: too much copy&paste
  features: serialize True as '1'
  tools/qvm-start-gui: add --force-stubdomain options
  tools/qvm-shutdown: fix help message
  tools/qvm-shutdown: drop --force option, it isn't supported anymore
This commit is contained in:
Marek Marczykowski-Górecki 2017-07-29 05:28:57 +02:00
commit f48321dd98
No known key found for this signature in database
GPG Key ID: 063938BA42CFA724
14 changed files with 380 additions and 200 deletions

View File

@ -8,6 +8,7 @@ Synopsis
========
| :command:`qvm-service` [-l] <*vmname*>
| :command:`qvm-service` [-e|-d|-D] <*vmname*> <*service*>
| :command:`qvm-service` <*vmname*> <*service*> [on|off]
Options
=======
@ -27,11 +28,19 @@ Options
Disable service
.. option:: --default, -D
.. option:: --default, -D, --delete, --unset
Reset service to its default state (remove from the list). Default state
means "lets VM choose" and can depend on VM type (NetVM, AppVM etc).
.. option:: --verbose, -v
increase verbosity
.. option:: --quiet, -q
decrease verbosity
Supported services
==================
@ -50,11 +59,6 @@ meminfo-writer
remove it (reset to default state), will be recreated with the rule: enabled
if VM have no PCI devices assigned, otherwise disabled.
qubes-dvm
Default: disabled
Used internally when creating DispVM savefile.
qubes-firewall
Default: enabled only in ProxyVM
@ -72,14 +76,6 @@ qubes-network
Expose network for other VMs. This includes enabling network forwarding,
MASQUERADE, DNS redirection and basic firewall.
qubes-netwatcher
Default: enabled only in ProxyVM
Monitor IP change notification from NetVM. When received, reload
qubes-firewall service (to force DNS resolution).
This service makes sense only with qubes-firewall enabled.
qubes-update-check
Default: enabled
@ -103,12 +99,12 @@ network-manager
Enable NetworkManager. Only VM with direct access to network device needs
this service, but can be useful in ProxyVM to ease VPN setup.
ntpd
clocksync
Default: disabled
Enable NTPD service. By default Qubes calls ntpdate every 6 minutes in
selected VM (aka ClockVM), then propagate the result using qrexec calls.
Enabling ntpd *do not* disable this behaviour.
Enable NTPD (or equivalent) service. If disabled, VM will sync clock with
selected VM (aka ClockVM) instead. ClockVM for particular VM can be set in
policy of qubes.GetDate service, using target= parameter.
qubes-yum-proxy
Deprecated name for qubes-updates-proxy.
@ -130,9 +126,8 @@ updates-proxy-setup
.. note::
this service is automatically enabled when you allow VM to access yum
proxy (in firewall settings) and disabled when you deny access to yum
proxy.
this service is automatically enabled when you allow VM to access updates
proxy and disabled when you deny access to updates proxy.
disable-default-route
Default: disabled

View File

@ -15,7 +15,7 @@
Synopsis
--------
:command:`qvm-shutdown` [-h] [--verbose] [--quiet] [--all] [--exclude *EXCLUDE*] [--force] [--wait] [--timeout *TIMEOUT*] [*VMNAME*]
:command:`qvm-shutdown` [-h] [--verbose] [--quiet] [--all] [--exclude *EXCLUDE*] [--wait] [--timeout *TIMEOUT*] [*VMNAME*]
Options
-------
@ -40,11 +40,6 @@ Options
exclude the qube from :option:`--all`
.. option:: --force
force operation, even if may damage other VMs (eg. shutdown of network
provider)
.. option:: --wait
wait for the VMs to shut down

View File

@ -15,7 +15,7 @@
Synopsis
--------
:command:`qvm-start-gui` [-h] [--verbose] [--quiet] [--all] [--exclude *EXCLUDE*] [--watch] [--pidfile *PIDFILE*] [--notify-monitory-layout] [*VMNAME* [*VMNAME* ...]]
:command:`qvm-start-gui` [-h] [--verbose] [--quiet] [--all] [--exclude *EXCLUDE*] [--watch] [--force-stubdomain] [--pidfile *PIDFILE*] [--notify-monitory-layout] [*VMNAME* [*VMNAME* ...]]
Options
-------
@ -44,6 +44,10 @@ Options
Keep watching for further domains startups, must be used with --all
.. option:: --force-stubdomain
Start GUI to stubdomain-emulated VGA, even if gui-agent is running in the VM
.. option:: --pidfile
Pidfile path to create in --watch mode

View File

@ -42,9 +42,10 @@ class Features(object):
self.vm.qubesd_call(self.vm.name, 'admin.vm.feature.Remove', key)
def __setitem__(self, key, value):
if value is False:
if isinstance(value, bool):
# False value needs to be serialized as empty string
self.vm.qubesd_call(self.vm.name, 'admin.vm.feature.Set', key, b'')
self.vm.qubesd_call(self.vm.name, 'admin.vm.feature.Set', key,
b'1' if value else b'')
else:
self.vm.qubesd_call(self.vm.name, 'admin.vm.feature.Set', key,
str(value).encode())

View File

@ -1350,6 +1350,8 @@ class TC_10_BackupCompatibility(qubesadmin.tests.backup.BackupTestCase):
for feature, value in vm['features'].items():
if value is False:
value = ''
elif value is True:
value = '1'
self.app.expected_calls[
(name, 'admin.vm.feature.Set', feature,
str(value).encode())] = b'0\0'

View File

@ -78,7 +78,7 @@ class TC_00_Features(qubesadmin.tests.QubesTestCase):
def test_021_set_bool(self):
self.app.expected_calls[
('test-vm', 'admin.vm.feature.Set', 'feature1', b'True')] = \
('test-vm', 'admin.vm.feature.Set', 'feature1', b'1')] = \
b'0\0'
self.vm.features['feature1'] = True
self.assertAllCalled()

View File

@ -91,162 +91,3 @@ class TC_00_qvm_features(qubesadmin.tests.QubesTestCase):
self.assertEqual(stdout.getvalue(),
'')
self.assertAllCalled()
def test_004_running_verbose(self):
self.app.expected_calls[
('dom0', 'admin.vm.List', None, None)] = \
b'0\x00some-vm class=AppVM state=Running\n' \
b'some-vm2 class=AppVM state=Running\n' \
b'some-vm3 class=AppVM state=Halted\n'
self.app.expected_calls[
('some-vm', 'admin.vm.List', None, None)] = \
b'0\x00some-vm class=AppVM state=Running\n'
with qubesadmin.tests.tools.StdoutBuffer() as stdout:
self.assertEqual(
qubesadmin.tools.qvm_check.main(['--running',
'some-vm'], app=self.app),
0)
self.assertEqual(stdout.getvalue(),
'VM some-vm is running\n')
self.assertAllCalled()
def test_005_running_multi_verbose(self):
self.app.expected_calls[
('dom0', 'admin.vm.List', None, None)] = \
b'0\x00some-vm class=AppVM state=Running\n' \
b'some-vm2 class=AppVM state=Running\n' \
b'some-vm3 class=AppVM state=Halted\n'
self.app.expected_calls[
('some-vm', 'admin.vm.List', None, None)] = \
b'0\x00some-vm class=AppVM state=Running\n'
self.app.expected_calls[
('some-vm2', 'admin.vm.List', None, None)] = \
b'0\x00some-vm2 class=AppVM state=Running\n'
with qubesadmin.tests.tools.StdoutBuffer() as stdout:
self.assertEqual(
qubesadmin.tools.qvm_check.main(['--running',
'some-vm', 'some-vm2'],
app=self.app),
0)
self.assertEqual(stdout.getvalue(),
'VMs some-vm, some-vm2 are running\n')
self.assertAllCalled()
def test_006_running_multi_verbose2(self):
self.app.expected_calls[
('dom0', 'admin.vm.List', None, None)] = \
b'0\x00some-vm class=AppVM state=Running\n' \
b'some-vm2 class=AppVM state=Running\n' \
b'some-vm3 class=AppVM state=Halted\n'
self.app.expected_calls[
('some-vm', 'admin.vm.List', None, None)] = \
b'0\x00some-vm class=AppVM state=Running\n'
self.app.expected_calls[
('some-vm2', 'admin.vm.List', None, None)] = \
b'0\x00some-vm2 class=AppVM state=Running\n'
self.app.expected_calls[
('some-vm3', 'admin.vm.List', None, None)] = \
b'0\x00some-vm3 class=AppVM state=Halted\n'
with qubesadmin.tests.tools.StdoutBuffer() as stdout:
self.assertEqual(
qubesadmin.tools.qvm_check.main(['--running',
'--all'],
app=self.app),
0)
self.assertEqual(stdout.getvalue(),
'VMs some-vm, some-vm2 are running\n')
self.assertAllCalled()
def test_007_not_running_verbose(self):
self.app.expected_calls[
('dom0', 'admin.vm.List', None, None)] = \
b'0\x00some-vm class=AppVM state=Running\n' \
b'some-vm2 class=AppVM state=Running\n' \
b'some-vm3 class=AppVM state=Halted\n'
self.app.expected_calls[
('some-vm3', 'admin.vm.List', None, None)] = \
b'0\x00some-vm3 class=AppVM state=Halted\n'
with qubesadmin.tests.tools.StdoutBuffer() as stdout:
self.assertEqual(
qubesadmin.tools.qvm_check.main(['--running',
'some-vm3'],
app=self.app),
1)
self.assertEqual(stdout.getvalue(),
'None of given VM is running\n')
self.assertAllCalled()
def test_008_paused(self):
self.app.expected_calls[
('dom0', 'admin.vm.List', None, None)] = \
b'0\x00some-vm class=AppVM state=Running\n' \
b'some-vm2 class=AppVM state=Paused\n' \
b'some-vm3 class=AppVM state=Halted\n'
self.app.expected_calls[
('some-vm2', 'admin.vm.List', None, None)] = \
b'0\x00some-vm2 class=AppVM state=Paused\n'
with qubesadmin.tests.tools.StdoutBuffer() as stdout:
self.assertEqual(
qubesadmin.tools.qvm_check.main(['--paused',
'some-vm2'],
app=self.app),
0)
self.assertEqual(stdout.getvalue(),
'VM some-vm2 is paused\n')
self.assertAllCalled()
def test_009_paused_multi(self):
self.app.expected_calls[
('dom0', 'admin.vm.List', None, None)] = \
b'0\x00some-vm class=AppVM state=Running\n' \
b'some-vm2 class=AppVM state=Paused\n' \
b'some-vm3 class=AppVM state=Halted\n'
self.app.expected_calls[
('some-vm2', 'admin.vm.List', None, None)] = \
b'0\x00some-vm2 class=AppVM state=Paused\n'
self.app.expected_calls[
('some-vm', 'admin.vm.List', None, None)] = \
b'0\x00some-vm class=AppVM state=Running\n'
with qubesadmin.tests.tools.StdoutBuffer() as stdout:
self.assertEqual(
qubesadmin.tools.qvm_check.main(['--paused',
'some-vm2', 'some-vm'],
app=self.app),
0)
self.assertEqual(stdout.getvalue(),
'VM some-vm2 is paused\n')
self.assertAllCalled()
def test_010_template(self):
self.app.expected_calls[
('dom0', 'admin.vm.List', None, None)] = \
b'0\x00some-vm class=AppVM state=Running\n' \
b'some-vm2 class=AppVM state=Paused\n' \
b'some-vm3 class=TemplateVM state=Halted\n'
with qubesadmin.tests.tools.StdoutBuffer() as stdout:
self.assertEqual(
qubesadmin.tools.qvm_check.main(['--template',
'some-vm3'],
app=self.app),
0)
self.assertEqual(stdout.getvalue(),
'VM some-vm3 is a template\n')
self.assertAllCalled()
def test_011_template_multi(self):
self.app.expected_calls[
('dom0', 'admin.vm.List', None, None)] = \
b'0\x00some-vm class=AppVM state=Running\n' \
b'some-vm2 class=AppVM state=Paused\n' \
b'some-vm3 class=TemplateVM state=Halted\n'
with qubesadmin.tests.tools.StdoutBuffer() as stdout:
self.assertEqual(
qubesadmin.tools.qvm_check.main(['--template',
'some-vm2', 'some-vm3'],
app=self.app),
0)
self.assertEqual(stdout.getvalue(),
'VM some-vm3 is a template\n')
self.assertAllCalled()

View File

@ -0,0 +1,203 @@
# -*- encoding: utf8 -*-
#
# The Qubes OS Project, http://www.qubes-os.org
#
# Copyright (C) 2017 Marek Marczykowski-Górecki
# <marmarek@invisiblethingslab.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License along
# with this program; if not, see <http://www.gnu.org/licenses/>.
import unittest
import qubesadmin.tests
import qubesadmin.tools.qvm_service
class TC_00_qvm_service(qubesadmin.tests.QubesTestCase):
def test_000_list(self):
self.app.expected_calls[
('dom0', 'admin.vm.List', None, None)] = \
b'0\x00some-vm class=AppVM state=Running\n'
self.app.expected_calls[
('some-vm', 'admin.vm.feature.List', None, None)] = \
b'0\x00feature1\nservice.service1\nservice.service2\n'
self.app.expected_calls[
('some-vm', 'admin.vm.feature.Get', 'service.service1', None)] = \
b'0\x00value1'
self.app.expected_calls[
('some-vm', 'admin.vm.feature.Get', 'service.service2', None)] = \
b'0\x00'
with qubesadmin.tests.tools.StdoutBuffer() as stdout:
self.assertEqual(
qubesadmin.tools.qvm_service.main(['some-vm'], app=self.app),
0)
self.assertEqual(stdout.getvalue(),
'service1 on\n'
'service2 off\n')
self.assertAllCalled()
def test_001_list_l(self):
self.app.expected_calls[
('dom0', 'admin.vm.List', None, None)] = \
b'0\x00some-vm class=AppVM state=Running\n'
self.app.expected_calls[
('some-vm', 'admin.vm.feature.List', None, None)] = \
b'0\x00feature1\nservice.service1\nservice.service2\n'
self.app.expected_calls[
('some-vm', 'admin.vm.feature.Get', 'service.service1', None)] = \
b'0\x00value1'
self.app.expected_calls[
('some-vm', 'admin.vm.feature.Get', 'service.service2', None)] = \
b'0\x00'
with qubesadmin.tests.tools.StdoutBuffer() as stdout:
self.assertEqual(
qubesadmin.tools.qvm_service.main(['-l', 'some-vm'],
app=self.app),
0)
self.assertEqual(stdout.getvalue(),
'service1 on\n'
'service2 off\n')
self.assertAllCalled()
def test_002_enable(self):
self.app.expected_calls[
('dom0', 'admin.vm.List', None, None)] = \
b'0\x00some-vm class=AppVM state=Running\n'
self.app.expected_calls[
('some-vm', 'admin.vm.feature.Set',
'service.service1', b'1')] = b'0\x00'
self.assertEqual(
qubesadmin.tools.qvm_service.main(['some-vm', 'service1',
'on'],
app=self.app),
0)
self.assertAllCalled()
def test_003_enable_opt(self):
self.app.expected_calls[
('dom0', 'admin.vm.List', None, None)] = \
b'0\x00some-vm class=AppVM state=Running\n'
self.app.expected_calls[
('some-vm', 'admin.vm.feature.Set',
'service.service1', b'1')] = b'0\x00'
self.assertEqual(
qubesadmin.tools.qvm_service.main(['--enable', 'some-vm',
'service1'],
app=self.app),
0)
self.assertAllCalled()
@unittest.expectedFailure
def test_004_enable_opt_mixed(self):
self.app.expected_calls[
('dom0', 'admin.vm.List', None, None)] = \
b'0\x00some-vm class=AppVM state=Running\n'
self.app.expected_calls[
('some-vm', 'admin.vm.feature.Set',
'service.service1', b'1')] = b'0\x00'
with self.assertNotRaises(SystemExit):
self.assertEqual(
qubesadmin.tools.qvm_service.main(
['some-vm', '--enable', 'service1'],
app=self.app),
0)
self.assertAllCalled()
def test_005_disable(self):
self.app.expected_calls[
('dom0', 'admin.vm.List', None, None)] = \
b'0\x00some-vm class=AppVM state=Running\n'
self.app.expected_calls[
('some-vm', 'admin.vm.feature.Set',
'service.service1', b'')] = b'0\x00'
self.assertEqual(
qubesadmin.tools.qvm_service.main(
['some-vm', 'service1', 'off'],
app=self.app),
0)
self.assertAllCalled()
def test_006_disable_opt(self):
self.app.expected_calls[
('dom0', 'admin.vm.List', None, None)] = \
b'0\x00some-vm class=AppVM state=Running\n'
self.app.expected_calls[
('some-vm', 'admin.vm.feature.Set',
'service.service1', b'')] = b'0\x00'
with self.assertNotRaises(SystemExit):
self.assertEqual(
qubesadmin.tools.qvm_service.main(
['--disable', 'some-vm', 'service1'],
app=self.app),
0)
self.assertAllCalled()
def test_007_get(self):
self.app.expected_calls[
('dom0', 'admin.vm.List', None, None)] = \
b'0\x00some-vm class=AppVM state=Running\n'
self.app.expected_calls[
('some-vm', 'admin.vm.feature.Get', 'service.service3', None)] = \
b'0\x00value2 with spaces'
with qubesadmin.tests.tools.StdoutBuffer() as stdout:
self.assertEqual(
qubesadmin.tools.qvm_service.main(['some-vm', 'service3'],
app=self.app),
0)
self.assertEqual(stdout.getvalue(),
'on\n')
self.assertAllCalled()
def test_008_del(self):
self.app.expected_calls[
('dom0', 'admin.vm.List', None, None)] = \
b'0\x00some-vm class=AppVM state=Running\n'
self.app.expected_calls[
('some-vm', 'admin.vm.feature.Remove', 'service.srv4', None)] = \
b'0\x00'
with qubesadmin.tests.tools.StdoutBuffer() as stdout:
self.assertEqual(
qubesadmin.tools.qvm_service.main(
['--unset', 'some-vm', 'srv4'],
app=self.app),
0)
self.assertEqual(stdout.getvalue(),
'')
self.assertAllCalled()
def test_009_del_legacy(self):
self.app.expected_calls[
('dom0', 'admin.vm.List', None, None)] = \
b'0\x00some-vm class=AppVM state=Running\n'
self.app.expected_calls[
('some-vm', 'admin.vm.feature.Remove', 'service.srv4', None)] = \
b'0\x00'
with qubesadmin.tests.tools.StdoutBuffer() as stdout:
self.assertEqual(
qubesadmin.tools.qvm_service.main(
['--default', 'some-vm', 'srv4'],
app=self.app),
0)
self.assertEqual(stdout.getvalue(),
'')
self.assertAllCalled()
def test_010_set_invalid(self):
self.app.expected_calls[
('dom0', 'admin.vm.List', None, None)] = \
b'0\x00some-vm class=AppVM state=Running\n'
with self.assertRaises(SystemExit):
qubesadmin.tools.qvm_service.main(
['some-vm', 'service1', 'invalid-value'],
app=self.app),
self.assertAllCalled()

View File

@ -243,7 +243,7 @@ class TC_00_qvm_template_postprocess(qubesadmin.tests.QubesTestCase):
self.app.expected_calls[
('test-vm', 'admin.vm.property.Reset', 'netvm', None)] = b'0\0'
self.app.expected_calls[
('test-vm', 'admin.vm.feature.Set', 'qrexec', b'True')] = b'0\0'
('test-vm', 'admin.vm.feature.Set', 'qrexec', b'1')] = b'0\0'
self.app.expected_calls[
('test-vm', 'admin.vm.Start', None, None)] = b'0\0'
self.app.expected_calls[
@ -293,7 +293,7 @@ class TC_00_qvm_template_postprocess(qubesadmin.tests.QubesTestCase):
self.app.expected_calls[
('test-vm', 'admin.vm.property.Reset', 'netvm', None)] = b'0\0'
self.app.expected_calls[
('test-vm', 'admin.vm.feature.Set', 'qrexec', b'True')] = b'0\0'
('test-vm', 'admin.vm.feature.Set', 'qrexec', b'1')] = b'0\0'
self.app.expected_calls[
('test-vm', 'admin.vm.Start', None, None)] = b'0\0'
self.app.expected_calls[

View File

@ -351,7 +351,7 @@ Column('MEMORY',
doc='Memory currently used by VM')
Column('DISK',
attr=(lambda vm: vm.storage.get_disk_utilization() / 1024 / 1024),
attr=(lambda vm: vm.get_disk_utilization() // 1024 // 1024),
doc='Total disk utilisation.')

View File

@ -0,0 +1,136 @@
# coding=utf-8
#
# The Qubes OS Project, https://www.qubes-os.org/
#
# Copyright (C) 2010-2016 Joanna Rutkowska <joanna@invisiblethingslab.com>
# Copyright (C) 2016 Wojtek Porczyk <woju@invisiblethingslab.com>
# Copyright (C) 2017 Marek Marczykowski-Górecki
# <marmarek@invisiblethingslab.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
'''qvm-service - Manage domain's services'''
from __future__ import print_function
import argparse
import sys
import qubesadmin
import qubesadmin.exc
import qubesadmin.tools
parser = qubesadmin.tools.QubesArgumentParser(
vmname_nargs=1,
argument_default=argparse.SUPPRESS,
description='manage domain\'s services')
parser.add_argument('service', metavar='FEATURE',
action='store', nargs='?',
help='name of the feature')
parser.add_argument('value', metavar='VALUE',
action='store', nargs='?',
help='new value of the service')
parser.add_argument('--unset', '--default', '--delete', '-D',
dest='delete', default=False,
action='store_true',
help='unset service (default to VM preference)')
parser.add_argument('--list', '-l',
dest='list',
action='store_true',
help='list services (default action)')
parser.add_argument('--enable', '-e',
dest='value',
action='store_const', const='1',
help='enable service')
parser.add_argument('--disable', '-d',
dest='value',
action='store_const', const='0',
help='disable service')
def parse_bool(value):
'''Convert string value to bool according to well known representations
It accepts (case-insensitive) ``'0'``, ``'no'`` and ``false`` as
:py:obj:`False` and ``'1'``, ``'yes'`` and ``'true'`` as
:py:obj:`True`.
'''
if isinstance(value, str):
lcvalue = value.lower()
if lcvalue in ('0', 'no', 'false', 'off'):
return False
if lcvalue in ('1', 'yes', 'true', 'on'):
return True
raise qubesadmin.exc.QubesValueError(
'Invalid literal for boolean value: {!r}'.format(value))
return bool(value)
def main(args=None, app=None):
'''Main routine of :program:`qvm-features`.
:param list args: Optional arguments to override those delivered from \
command line.
'''
args = parser.parse_args(args, app=app)
vm = args.domains[0]
if not hasattr(args, 'service'):
if args.delete:
parser.error('--unset requires a feature')
services = [(feat[len('service.'):],
'on' if vm.features[feat] else 'off') for feat in
vm.features if feat.startswith('service.')]
qubesadmin.tools.print_table(services)
elif args.delete:
if hasattr(args, 'value'):
parser.error('cannot both set and unset a value')
try:
del vm.features['service.' + args.service]
except KeyError:
pass
except qubesadmin.exc.QubesException as err:
parser.error_runtime(str(err))
elif hasattr(args, 'value'):
try:
vm.features['service.' + args.service] = parse_bool(args.value)
except qubesadmin.exc.QubesException as err:
parser.error_runtime(str(err))
else:
try:
print('on' if vm.features['service.' + args.service] else 'off')
return 0
except KeyError:
return 1
except qubesadmin.exc.QubesException as err:
parser.error_runtime(str(err))
return 0
if __name__ == '__main__':
sys.exit(main())

View File

@ -40,11 +40,6 @@ import qubesadmin.exc
parser = qubesadmin.tools.QubesArgumentParser(
description=__doc__, vmname_nargs='+')
parser.add_argument('--force',
action='store_true', default=False,
help='force operation, even if may damage other VMs (eg. shutdown of'
' network provider)')
parser.add_argument('--wait',
action='store_true', default=False,
help='wait for the VMs to shut down')
@ -53,7 +48,7 @@ parser.add_argument('--timeout',
action='store', type=float,
default=60,
help='timeout after which domains are killed when using --wait'
' (default: %d)')
' (default: %(default)d)')
def main(args=None, app=None): # pylint: disable=missing-docstring

View File

@ -347,6 +347,9 @@ parser = qubesadmin.tools.QubesArgumentParser(
description='start GUI for qube(s)', vmname_nargs='*')
parser.add_argument('--watch', action='store_true',
help='Keep watching for further domains startups, must be used with --all')
parser.add_argument('--force-stubdomain', action='store_true',
help='Start GUI to stubdomain-emulated VGA, even if gui-agent is running '
'in the VM')
parser.add_argument('--pidfile', action='store', default=pidfile_path,
help='Pidfile path to create in --watch mode')
parser.add_argument('--notify-monitor-layout', action='store_true',
@ -400,7 +403,8 @@ def main(args=None):
tasks = []
for vm in args.domains:
if vm.is_running():
tasks.append(asyncio.ensure_future(launcher.start_gui(vm)))
tasks.append(asyncio.ensure_future(launcher.start_gui(
vm, force_stubdom=args.force_stubdomain)))
if tasks:
loop.run_until_complete(asyncio.wait(tasks))
loop.stop()

View File

@ -257,6 +257,10 @@ class QubesVM(qubesadmin.base.PropertyHolder):
vm=self.name, vm_name=volname)
return self._volumes
def get_disk_utilization(self):
'''Get total disk usage of the VM'''
return sum(vol.usage for vol in self.volumes.values())
def run_service(self, service, **kwargs):
'''Run service on this VM