qubes/tools: qvm-prefs

This commit is contained in:
Wojtek Porczyk 2015-09-21 23:20:49 +02:00
parent 0fbee4dc10
commit e7cba0214f
5 changed files with 179 additions and 616 deletions

View File

@ -1,37 +1,51 @@
.. program:: qvm-prefs .. program:: qvm-prefs
==========================================================
:program:`qvm-prefs` -- List/set various per-VM properties :program:`qvm-prefs` -- List/set various per-VM properties
========================================================== ==========================================================
Synopsis Synopsis
======== --------
| :command:`qvm-prefs` [*options*] -l <*vm-name*>
| :command:`qvm-prefs` [*options*] -g <*vm-name*> <*property*>
| :command:`qvm-prefs` [*options*] -s <*vm-name*> <*property*> [*...*]
:command:`qvm-prefs` qvm-prefs [-h] [--xml *XMLFILE*] [--verbose] [--quiet] [--force-root] [--help-properties] *VMNAME* [*PROPERTY* [*VALUE*]]
Options Options
======= -------
.. option:: --help, -h .. option:: --help, -h
Show this help message and exit Show help message and exit.
.. option:: --list, -l .. option:: --help-properties
List properties of a specified VM List available properties with short descriptions and exit.
.. option:: --get, -g .. option:: --xml=XMLFILE
Get a single property of a specified VM Qubes OS store file.
.. option:: --set, -s .. option:: --verbose, -v
Set properties of a specified VM Increase verbosity.
Properties .. option:: --quiet, -q
==========
Decrease verbosity.
.. option:: --force-root
Force to run as root.
Common properties
=================
This list is non-exhaustive. For authoritative listing, see
:option:`--help-properties` and documentation of the source code.
.. warning::
This list is from the core2. It is wrong in many cases, some of them obvious,
some of them not.
include_in_backups include_in_backups
Accepted values: ``True``, ``False`` Accepted values: ``True``, ``False``
@ -40,11 +54,11 @@ include_in_backups
works only in qubes-manager). You can always manually select or deselect works only in qubes-manager). You can always manually select or deselect
any VM for backup. any VM for backup.
pcidevs pcidevs
PCI devices assigned to the VM. Should be edited using PCI devices assigned to the VM. Should be edited using
:manpage:`qvm-pci(1)` tool. :manpage:`qvm-pci(1)` tool.
pci_strictreset pci_strictreset
Accepted values: ``True``, ``False`` Accepted values: ``True``, ``False``
Control whether prevent assigning to VM a device which does not support any Control whether prevent assigning to VM a device which does not support any
@ -212,7 +226,11 @@ timezone
proper timezone set). proper timezone set).
Authors Authors
======= -------
| Joanna Rutkowska <joanna at invisiblethingslab dot com> | Joanna Rutkowska <joanna at invisiblethingslab dot com>
| Rafal Wojtczuk <rafal at invisiblethingslab dot com> | Rafal Wojtczuk <rafal at invisiblethingslab dot com>
| Marek Marczykowski <marmarek at invisiblethingslab dot com> | Marek Marczykowski <marmarek at invisiblethingslab dot com>
| Wojtek Porczyk <woju at invisiblethingslab dot com>
.. vim: ts=3 sw=3 et tw=80

View File

@ -56,6 +56,7 @@ endif
tools/qubes_create.py* \ tools/qubes_create.py* \
tools/qvm_create.py* \ tools/qvm_create.py* \
tools/qvm_ls.py* \ tools/qvm_ls.py* \
tools/qvm_prefs.py* \
$(DESTDIR)$(PYTHON_QUBESPATH)/tools $(DESTDIR)$(PYTHON_QUBESPATH)/tools
cp ext/__init__.py* $(DESTDIR)$(PYTHON_QUBESPATH)/ext cp ext/__init__.py* $(DESTDIR)$(PYTHON_QUBESPATH)/ext

137
qubes/tools/qvm_prefs.py Normal file
View File

@ -0,0 +1,137 @@
#!/usr/bin/python2
# -*- encoding: utf8 -*-
#
# The Qubes OS Project, http://www.qubes-os.org
#
# Copyright (C) 2010-2015 Joanna Rutkowska <joanna@invisiblethingslab.com>
# Copyright (C) 2015 Wojtek Porczyk <woju@invisiblethingslab.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 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 General Public License for more details.
#
# You should have received a copy of the GNU 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.
#
# TODO list properties for all classes
# TODO indicate default values
from __future__ import print_function
import argparse
import os
import subprocess
import sys
import textwrap
import qubes
import qubes.tools
import qubes.utils
import qubes.vm
class _HelpPropertiesAction(argparse.Action):
'''Action for argument parser that displays all properties and exits.'''
# pylint: disable=redefined-builtin
def __init__(self,
option_strings,
dest=argparse.SUPPRESS,
default=argparse.SUPPRESS,
help='list all available properties with short descriptions'
' and exit'):
super(_HelpPropertiesAction, self).__init__(
option_strings=option_strings,
dest=dest,
default=default,
nargs=0,
help=help)
def __call__(self, parser, namespace, values, option_string=None):
properties = qubes.vm.qubesvm.QubesVM.property_list()
width = max(len(prop.__name__) for prop in properties)
wrapper = textwrap.TextWrapper(width=80,
initial_indent=' ', subsequent_indent=' ' * (width + 6))
text = 'Common properties:\n' + '\n'.join(
wrapper.fill('{name:{width}s} {doc}'.format(
name=prop.__name__,
doc=qubes.utils.format_doc(prop.__doc__) if prop.__doc__ else'',
width=width))
for prop in sorted(properties))
parser.exit(message=text
+ '\n\nThere may be more properties in specific domain classes.\n')
parser = qubes.tools.get_parser_base(want_force_root=True)
#parser.add_argument('--property', '--prop', '-p',
# action=qubes.tools.PropertyAction,
# help='set domain\'s property (may be given multiple times)')
parser.add_argument('name', metavar='VMNAME',
help='name of the domain to change')
parser.add_argument('property', metavar='PROPERTY',
nargs='?',
help='name of the property to show or change')
parser.add_argument('value', metavar='VALUE',
nargs='?',
help='new value of the property')
parser.add_argument('--help-properties', action=_HelpPropertiesAction)
def main():
args = parser.parse_args()
qubes.tools.set_verbosity(parser, args)
qubes.tools.dont_run_as_root(parser, args)
app = qubes.Qubes(args.xml)
try:
domain = app.domains[args.name]
except KeyError:
parser.error('no such domain: {!r}'.format(args.name))
if args.property is None:
properties = domain.property_list()
width = max(len(prop.__name__) for prop in properties)
for prop in sorted(properties):
try:
value = getattr(domain, prop.__name__)
except AttributeError:
print('{name:{width}s} U'.format(
name=prop.__name__, width=width))
continue
if domain.property_is_default(prop):
print('{name:{width}s} D {value!r}'.format(
name=prop.__name__, width=width, value=value))
else:
print('{name:{width}s} - {value!r}'.format(
name=prop.__name__, width=width, value=value))
return True
if args.value is None:
print(str(getattr(domain, args.property)))
return True
setattr(domain, args.property, args.value)
app.save()
return True
if __name__ == '__main__':
sys.exit(not main())

View File

@ -1,601 +1,7 @@
#!/usr/bin/python2 #!/usr/bin/python2 -O
# -*- encoding: utf8 -*- # vim: fileencoding=utf-8
#
# The Qubes OS Project, http://www.qubes-os.org
#
# Copyright (C) 2010 Joanna Rutkowska <joanna@invisiblethingslab.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# 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 General Public License for more details.
#
# You should have received a copy of the GNU 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.
#
#
from qubes.qubes import QubesVmCollection
from qubes.qubes import QubesVmLabels
from qubes.qubes import QubesHost
from qubes.qubes import system_path
from optparse import OptionParser
import subprocess
import os
import sys import sys
import re import qubes.tools.qvm_prefs
def do_list(vm): sys.exit(not qubes.tools.qvm_prefs.main())
label_width = 19
fmt="{{0:<{0}}}: {{1}}".format(label_width)
print fmt.format ("name", vm.name)
print fmt.format ("label", vm.label.name)
print fmt.format ("type", vm.type)
if vm.template is not None:
print fmt.format ("template", vm.template.name)
if vm.netvm is not None:
print fmt.format ("netvm", vm.netvm.name)
if vm.qid != 0:
print fmt.format("dispvm_netvm", "%s%s" % (
vm.dispvm_netvm.name if vm.dispvm_netvm
else "none",
" (default)" if vm.uses_default_dispvm_netvm else ""))
print fmt.format ("updateable", vm.updateable)
print fmt.format ("autostart", vm.autostart)
print fmt.format ("installed_by_rpm", vm.installed_by_rpm)
print fmt.format ("include_in_backups", vm.include_in_backups)
print fmt.format ("last_backup", vm.backup_timestamp)
print fmt.format ("dir", vm.dir_path)
print fmt.format ("config", vm.conf_file)
print fmt.format ("pcidevs", vm.pcidevs)
print fmt.format ("pci_strictreset", vm.pci_strictreset)
if vm.template is None:
print fmt.format ("root_img", vm.root_img)
if hasattr(vm, "rootcow_img") and vm.rootcow_img is not None:
print fmt.format ("root_cow_img", vm.rootcow_img)
if vm.template is not None:
print fmt.format ("root_img", vm.template.root_img)
if hasattr(vm, 'volatile_img') and vm.volatile_img is not None:
print fmt.format ("root_volatile_img", vm.volatile_img)
if hasattr(vm, 'private_img') and vm.private_img is not None:
print fmt.format ("private_img", vm.private_img)
print fmt.format ("vcpus", str(vm.vcpus))
print fmt.format ("memory", vm.memory)
if hasattr(vm, 'maxmem'):
print fmt.format ("maxmem", vm.maxmem)
print fmt.format ("MAC", "%s%s" % (vm.mac, " (auto)" if vm._mac is None else ""))
if hasattr(vm, 'kernel'):
if vm.uses_default_kernel:
print fmt.format ("kernel", "%s (default)" % vm.kernel)
else:
print fmt.format ("kernel", vm.kernel)
if hasattr(vm, 'kernelopts'):
if vm.uses_default_kernelopts:
print fmt.format ("kernelopts", "%s (default)" % vm.kernelopts)
else:
print fmt.format ("kernelopts", vm.kernelopts)
if hasattr(vm, 'debug'):
print fmt.format("debug", "on" if vm.debug else "off")
if hasattr(vm, 'default_user'):
print fmt.format("default_user", str(vm.default_user))
if hasattr(vm, 'qrexec_installed'):
print fmt.format("qrexec_installed", str(vm.qrexec_installed))
if hasattr(vm, 'qrexec_timeout'):
print fmt.format("qrexec_timeout", str(vm.qrexec_timeout))
if hasattr(vm, 'guiagent_installed'):
print fmt.format("guiagent_installed", str(vm.guiagent_installed))
if hasattr(vm, 'seamless_gui_mode'):
print fmt.format("seamless_gui_mode", str(vm.seamless_gui_mode))
if hasattr(vm, 'drive'):
print fmt.format("drive", str(vm.drive))
if hasattr(vm, 'timezone'):
print fmt.format("timezone", str(vm.timezone))
print fmt.format ("internal", vm.internal)
def do_get(vms, vm, prop):
if prop == 'config':
prop = 'conf_file'
elif prop == 'dir':
prop = 'dir_path'
elif prop == 'last_backup':
prop = 'backup_timestamp'
if not hasattr(vm, prop):
print >>sys.stderr, "VM '{}' has no attribute '{}'".format(vm.name,
prop)
return
if getattr(vm, prop, None) is None:
# not set or set to None
return
if prop in ['template', 'netvm', 'dispvm_netvm']:
print getattr(vm, prop).name
else:
print str(getattr(vm, prop))
def set_label(vms, vm, args):
if len (args) != 1:
print >> sys.stderr, "Missing label name argument!"
return False
label = args[0]
if label not in QubesVmLabels:
print >> sys.stderr, "Wrong label name, supported values are the following:"
for l in QubesVmLabels.values():
print >> sys.stderr, "* {0}".format(l.name)
return False
vm.label = QubesVmLabels[label]
return True
def set_memory(vms, vm, args):
if len (args) != 1:
print >> sys.stderr, "Missing memory argument!"
return False
new_memory = int(args[0])
if new_memory <= 0:
print >>sys.stderr, "Memory size must be positive"
return False
qubes_host = QubesHost()
if new_memory > qubes_host.memory_total/1024:
print >> sys.stderr, "This host has only {0} MB of RAM".format(qubes_host.memory_total/1024)
return False
vm.memory = new_memory
return True
def set_maxmem(vms, vm, args):
if len (args) != 1:
print >> sys.stderr, "Missing maxmem argument!"
exit (1)
new_maxmem = int(args[0])
if new_maxmem <= 0:
print >>sys.stderr, "Memory size must be positive"
return False
qubes_host = QubesHost()
if new_maxmem > qubes_host.memory_total/1024:
print >> sys.stderr, "This host has only {0} MB of RAM".format(qubes_host.memory_total/1024)
return False
if new_maxmem < vm.memory:
print >> sys.stderr, "WARNING: new maxmem smaller than memory property - VM will be able to use only 'maxmem' memory amount"
vm.maxmem = new_maxmem
return True
def set_mac(vms, vm, args):
if len (args) != 1:
print >> sys.stderr, "Missing MAC argument!"
return False
if not re.match("[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}|auto", args[0]):
print >> sys.stderr, "Invalid MAC argument!"
print >> sys.stderr, "Possible values:"
print >> sys.stderr, "1) auto"
print >> sys.stderr, "2) MAC in format: XX:XX:XX:XX:XX:XX"
return False
mac = args[0]
if mac == "auto":
mac = None
vm.mac = mac
return True
def set_pcidevs(vms, vm, args):
if len (args) != 1:
print >> sys.stderr, "Missing pcidevs argument!"
return False
if vm.is_running():
print >>sys.stderr, "Cannot modify PCI devices of running VM, " \
"use qvm-pci instead"
return False
vm.pcidevs = list(eval(args[0]))
return True
def set_pci_strictreset(vms, vm, args):
if len (args) != 1:
print >> sys.stderr, "Missing value (True/False)!"
return False
vm.pci_strictreset = bool(eval(args[0].capitalize()))
return True
def set_netvm(vms, vm, args):
if len (args) != 1:
print >> sys.stderr, "Missing netvm name argument!"
print >> sys.stderr, "Possible values:"
print >> sys.stderr, "1) default"
print >> sys.stderr, "2) none"
print >> sys.stderr, "3) <vmaname>"
return
netvm = args[0]
if netvm == "none":
netvm = None
vm.uses_default_netvm = False
elif netvm == "default":
netvm = vms.get_default_netvm()
vm.uses_default_netvm = True
else:
netvm = vms.get_vm_by_name (netvm)
if netvm is None:
print >> sys.stderr, "A VM with the name '{0}' does not exist in the system.".format(netvm)
return False
if not netvm.is_netvm():
print >> sys.stderr, "VM '{0}' is not a NetVM".format(netvm)
return False
vm.uses_default_netvm = False
vm.netvm = netvm
return True
def set_dispvm_netvm(vms, vm, args):
if len (args) != 1:
print >> sys.stderr, "Missing netvm name argument!"
print >> sys.stderr, "Possible values:"
print >> sys.stderr, "1) default (the same as VM own netvm)"
print >> sys.stderr, "2) none"
print >> sys.stderr, "3) <vmaname>"
return
netvm = args[0]
if netvm == "none":
vm.netvm = None
vm.uses_default_dispvm_netvm = False
elif netvm == "default":
vm.uses_default_dispvm_netvm = True
else:
netvm = vms.get_vm_by_name (netvm)
if netvm is None:
print >> sys.stderr, "A VM with the name '{0}' does not exist in the system.".format(netvm)
return False
if not netvm.is_netvm():
print >> sys.stderr, "VM '{0}' is not a NetVM".format(netvm)
return False
vm.dispvm_netvm = netvm
vm.uses_default_dispvm_netvm = False
return True
def set_kernel(vms, vm, args):
if len (args) != 1:
print >> sys.stderr, "Missing kernel version argument!"
print >> sys.stderr, "Possible values:"
print >> sys.stderr, "1) default"
print >> sys.stderr, "2) none (kernels subdir in VM)"
print >> sys.stderr, "3) <kernel version>, one of:"
for k in os.listdir(system_path["qubes_kernels_base_dir"]):
print >> sys.stderr, " -", k
return False
kernel = args[0]
if kernel == "default":
kernel = vms.get_default_kernel()
vm.uses_default_kernel = True
elif kernel == "none":
kernel = None
vm.uses_default_kernel = False
else:
if not os.path.exists(os.path.join(system_path["qubes_kernels_base_dir"], kernel)):
print >> sys.stderr, "Kernel version {0} not installed.".format(kernel)
return False
vm.uses_default_kernel = False
vm.kernel = kernel
return True
def set_template(vms, vm, args):
if len (args) != 1:
print >> sys.stderr, "Missing template name argument!"
return False
template_name = args[0];
template = vms.get_vm_by_name(template_name)
if template is None or template.qid not in vms:
print >> sys.stderr, "A VM with the name '{0}' does not exist in the system.".format(template_name)
return False
if not template.is_template():
print >> sys.stderr, "VM '{0}' is not a TemplateVM".format(template_name)
return False
print >> sys.stderr, "Setting template for VM '{0}' to '{1}'...".format (vm.name, template_name)
vm.template = template
return True
def set_vcpus(vms, vm, args):
if len (args) != 1:
print >> sys.stderr, "Missing vcpus count argument!"
return False
vcpus = int(args[0])
if vcpus <= 0:
print >> sys.stderr, "A vcpus count must be positive."
return False
qubes_host = QubesHost()
if vcpus > qubes_host.no_cpus:
print >> sys.stderr, "This host has only {0} cpus".format(
qubes_host.no_cpus)
return False
print >> sys.stderr, "Setting vcpus count for VM '{0}' to '{1}'...".format (vm.name, vcpus)
vm.vcpus = vcpus
return True
def set_kernelopts(vms, vm, args):
if len (args) != 1:
print >> sys.stderr, "Missing kernel opts argument!"
print >> sys.stderr, "Possible values:"
print >> sys.stderr, "1) default"
print >> sys.stderr, "2) <opts>"
return False
if args[0] == 'default':
vm.uses_default_kernelopts = True
else:
vm.uses_default_kernelopts = False
vm.kernelopts = args[0]
return True
def set_name(vms, vm, args):
if len (args) != 1:
print >> sys.stderr, "Missing new name!"
return False
if args[0] == vm.name:
return False
vm.set_name(args[0])
return True
def set_drive(vms, vm, args):
if len (args) != 1:
print >> sys.stderr, "Missing new drive content (file/device)!"
return False
if args[0] == '' or args[0].lower() == 'none':
vm.drive = None
else:
vm.drive = args[0]
return True
def set_debug(vms, vm, args):
if len (args) != 1:
print >> sys.stderr, "Missing value (True/False or on/off)!"
return False
if args[0].lower() == "on":
vm.debug = True
elif args[0].lower() == "off":
vm.debug = False
else:
vm.debug = bool(eval(args[0].capitalize()))
return True
def set_default_user(vms, vm, args):
if len (args) != 1:
print >> sys.stderr, "Missing user name!"
return False
vm.default_user = args[0]
return True
def set_include_in_backups(vms, vm, args):
if len (args) != 1:
print >> sys.stderr, "Missing value (True/False)!"
return False
vm.include_in_backups = bool(eval(args[0].capitalize()))
return True
def set_qrexec_installed(vms, vm, args):
if len (args) != 1:
print >> sys.stderr, "Missing value (True/False)!"
return False
vm.qrexec_installed = bool(eval(args[0].capitalize()))
return True
def set_internal(vms, vm, args):
if len (args) != 1:
print >> sys.stderr, "Missing value (True/False)!"
return False
vm.internal = bool(eval(args[0].capitalize()))
return True
def set_guiagent_installed(vms, vm, args):
if len (args) != 1:
print >> sys.stderr, "Missing value (True/False)!"
return False
vm.guiagent_installed = bool(eval(args[0].capitalize()))
return True
def set_seamless_gui_mode(vms, vm, args):
if len(args) != 1:
print >> sys.stderr, "Missing value (true/false)!"
return False
if not args[0].lower() in ['true', 'false']:
print >> sys.stderr, "Invalid value, expected 'true' or 'false'"
return False
if args[0].lower() == 'true':
vm.seamless_gui_mode = True
else:
vm.seamless_gui_mode = False
return True
def set_autostart(vms, vm, args):
if len (args) != 1:
print >> sys.stderr, "Missing value (True/False)!"
return False
vm.autostart = bool(eval(args[0].capitalize()))
return True
def set_qrexec_timeout(vms, vm, args):
if len (args) != 1:
print >> sys.stderr, "Missing timeout value (seconds)!"
return False
vm.qrexec_timeout = int(args[0])
return True
def set_timezone(vms, vm, args):
if len (args) != 1:
print >> sys.stderr, "Missing value ('localtime' or timeoffset in seconds)!"
return False
if not args[0].isdigit() and args[0].lower() == 'localtime':
print >> sys.stderr, "Invalid timezone value!"
return False
vm.timezone = args[0]
return True
properties = {
"include_in_backups": set_include_in_backups,
"pcidevs": set_pcidevs,
"pci_strictreset": set_pci_strictreset,
"label" : set_label,
"netvm" : set_netvm,
"dispvm_netvm" : set_dispvm_netvm,
"maxmem" : set_maxmem,
"memory" : set_memory,
"kernel" : set_kernel,
"template" : set_template,
"vcpus" : set_vcpus,
"kernelopts": set_kernelopts,
"name": set_name,
"drive": set_drive,
"mac": set_mac,
"debug": set_debug,
"default_user": set_default_user,
"qrexec_installed": set_qrexec_installed,
"guiagent_installed": set_guiagent_installed,
"seamless_gui_mode": set_seamless_gui_mode,
"qrexec_timeout": set_qrexec_timeout,
"timezone": set_timezone,
"internal": set_internal,
"autostart": set_autostart,
}
def do_set(vms, vm, property, args):
if property not in properties.keys():
print >> sys.stderr, "ERROR: Wrong property name: '{0}'".format(property)
return False
if not hasattr(vm, property):
print >> sys.stderr, "ERROR: Property '{0}' not available for this VM".format(property)
return False
try:
return properties[property](vms, vm, args)
except Exception as err:
print >> sys.stderr, "ERROR: %s" % str(err)
return False
def main():
usage = "usage: %prog -l [options] <vm-name>\n"\
"usage: %prog -g [options] <vm-name> <property>\n"\
"usage: %prog -s [options] <vm-name> <property> [...]\n"\
"List/set various per-VM properties."
parser = OptionParser (usage)
parser.add_option("-l", "--list", action="store_true", dest="do_list",
default=False)
parser.add_option("-s", "--set", action="store_true", dest="do_set",
default=False)
parser.add_option ("-g", "--gry", action="store_true", dest="do_get",
default=False)
parser.add_option("--force-root", action="store_true", dest="force_root",
default=False,
help="Force to run, even with root privileges")
(options, args) = parser.parse_args ()
if (len (args) < 1):
parser.error ("You must provide at least the vmname!")
vmname = args[0]
if hasattr(os, "geteuid") and os.geteuid() == 0:
if not options.force_root:
print >> sys.stderr, "*** Running this tool as root is strongly discouraged, this will lead you in permissions problems."
print >> sys.stderr, "Retry as unprivileged user."
print >> sys.stderr, "... or use --force-root to continue anyway."
exit(1)
if options.do_list + options.do_set + options.do_get > 1:
print >> sys.stderr, "You can provide at most one of -l, -g and -s at " \
"the same time!"
exit(1)
if options.do_set:
qvm_collection = QubesVmCollection()
qvm_collection.lock_db_for_writing()
qvm_collection.load()
else:
qvm_collection = QubesVmCollection()
qvm_collection.lock_db_for_reading()
qvm_collection.load()
qvm_collection.unlock_db()
vm = qvm_collection.get_vm_by_name(vmname)
if vm is None or vm.qid not in qvm_collection:
print >> sys.stderr, "A VM with the name '{0}' does not exist in the system.".format(vmname)
exit(1)
if options.do_set:
if len (args) < 2:
print >> sys.stderr, "You must specify the property you wish to set..."
print >> sys.stderr, "Available properties:"
for p in properties.keys():
if hasattr(vm, p):
print >> sys.stderr, "--> '{0}'".format(p)
exit (1)
property = args[1]
if do_set(qvm_collection, vm, property, args[2:]):
qvm_collection.save()
qvm_collection.unlock_db()
else:
qvm_collection.unlock_db()
exit(1)
elif options.do_get or len(args) == 2:
do_get(qvm_collection, vm, args[1])
else:
# do_list
do_list(vm)
main()

View File

@ -219,6 +219,7 @@ fi
%{python_sitearch}/qubes/tools/qubes_create.py* %{python_sitearch}/qubes/tools/qubes_create.py*
%{python_sitearch}/qubes/tools/qvm_create.py* %{python_sitearch}/qubes/tools/qvm_create.py*
%{python_sitearch}/qubes/tools/qvm_ls.py* %{python_sitearch}/qubes/tools/qvm_ls.py*
%{python_sitearch}/qubes/tools/qvm_prefs.py*
%dir %{python_sitearch}/qubes/ext %dir %{python_sitearch}/qubes/ext
%{python_sitearch}/qubes/ext/__init__.py* %{python_sitearch}/qubes/ext/__init__.py*