فهرست منبع

Remove core2 code

This all either have been migrated to core3, or is not needed anymore.

There is still qvm-tools directory with a few tools that needs to be
migrated, or installed as is.
Marek Marczykowski-Górecki 7 سال پیش
والد
کامیت
8992e71f85
51فایلهای تغییر یافته به همراه0 افزوده شده و 7220 حذف شده
  1. 0 7
      Makefile
  2. 0 2158
      core-modules/000QubesVm.py
  3. 0 77
      core-modules/001QubesResizableVm.py
  4. 0 54
      core-modules/01QubesAppVm.py
  5. 0 248
      core-modules/01QubesDisposableVm.py
  6. 0 283
      core-modules/01QubesHVm.py
  7. 0 110
      core-modules/02QubesTemplateHVm.py
  8. 0 15
      core-modules/Makefile
  9. 0 5
      core-modules/README.txt
  10. 0 0
      core-modules/__init__.py
  11. 0 1
      core/.gitignore
  12. 0 31
      core/Makefile
  13. 0 0
      core/__init__.py
  14. 0 57
      core/guihelpers.py
  15. 0 1
      core/modules
  16. 0 187
      core/qubes.py
  17. 0 844
      core/qubesutils.py
  18. 0 11
      core/settings-xen-Linux.py
  19. 0 24
      core/storage/Makefile
  20. 0 48
      core/tests/test_qubesutils.py
  21. 0 2
      dispvm/.gitignore
  22. 0 21
      dispvm/Makefile
  23. 0 61
      dispvm/block.qubes
  24. 0 200
      dispvm/qfile-daemon-dvm
  25. 0 86
      dispvm/qubes-prepare-saved-domain.sh
  26. 0 12
      dispvm/qubes-setupdvm.service
  27. 0 23
      dispvm/qubes-update-dispvm-savefile-with-progress.sh
  28. 0 22
      dispvm/startup-dvm.sh
  29. 0 1
      linux/system-config/Makefile
  30. 0 7
      linux/system-config/qubes-guid.desktop
  31. 0 161
      qvm-tools/qubes-prefs
  32. 0 85
      qvm-tools/qubes-set-updates
  33. 0 86
      qvm-tools/qvm-add-appvm
  34. 0 83
      qvm-tools/qvm-add-template
  35. 0 218
      qvm-tools/qvm-backup
  36. 0 313
      qvm-tools/qvm-backup-restore
  37. 0 152
      qvm-tools/qvm-block
  38. 0 81
      qvm-tools/qvm-check
  39. 0 105
      qvm-tools/qvm-clone
  40. 0 72
      qvm-tools/qvm-create-default-dvm
  41. 0 321
      qvm-tools/qvm-firewall
  42. 0 66
      qvm-tools/qvm-grow-private
  43. 0 72
      qvm-tools/qvm-grow-root
  44. 0 35
      qvm-tools/qvm-init-storage
  45. 0 141
      qvm-tools/qvm-pci
  46. 0 142
      qvm-tools/qvm-revert-template-changes
  47. 0 98
      qvm-tools/qvm-service
  48. 0 73
      qvm-tools/qvm-template-commit
  49. 0 171
      qvm-tools/qvm-trim-template
  50. 0 141
      qvm-tools/qvm-usb
  51. 0 8
      rpm_spec/core-dom0.spec

+ 0 - 7
Makefile

@@ -40,16 +40,10 @@ rpms-dom0:
 		$(RPMS_DIR)/x86_64/qubes-core-dom0-$(VERSION)*.rpm \
 		$(RPMS_DIR)/noarch/qubes-core-dom0-doc-$(VERSION)*rpm
 
-clean:
-	make -C dispvm clean
-
 all:
 	$(PYTHON) setup.py build
 #	make all -C tests
 	# Currently supported only on xen
-ifeq ($(BACKEND_VMM),xen)
-	make all -C dispvm
-endif
 
 install:
 ifeq ($(OS),Linux)
@@ -67,7 +61,6 @@ ifeq ($(BACKEND_VMM),xen)
 	# Currently supported only on xen
 	cp etc/qmemman.conf $(DESTDIR)/etc/qubes/
 endif
-	$(MAKE) install -C dispvm
 	mkdir -p $(DESTDIR)/etc/qubes-rpc/policy
 	mkdir -p $(DESTDIR)/usr/libexec/qubes
 	cp qubes-rpc-policy/qubes.FeaturesRequest.policy $(DESTDIR)/etc/qubes-rpc/policy/qubes.FeaturesRequest

+ 0 - 2158
core-modules/000QubesVm.py

@@ -1,2158 +0,0 @@
-#!/usr/bin/python2
-# -*- coding: utf-8 -*-
-#
-# The Qubes OS Project, http://www.qubes-os.org
-#
-# Copyright (C) 2010  Joanna Rutkowska <joanna@invisiblethingslab.com>
-# Copyright (C) 2013  Marek Marczykowski <marmarek@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.
-#
-#
-
-import datetime
-import base64
-import hashlib
-import logging
-import grp
-import lxml.etree
-import os
-import os.path
-import re
-import shutil
-import subprocess
-import sys
-import time
-import uuid
-import xml.parsers.expat
-import signal
-import pwd
-from qubes import qmemman
-from qubes import qmemman_algo
-import libvirt
-
-from qubes.qubes import dry_run,vmm
-from qubes.qubes import register_qubes_vm_class
-from qubes.qubes import QubesVmCollection,QubesException,QubesHost,QubesVmLabels
-from qubes.qubes import defaults,system_path,vm_files,qubes_max_qid
-from qubes.storage import get_pool
-
-qmemman_present = False
-try:
-    from qubes.qmemman_client import QMemmanClient
-    qmemman_present = True
-except ImportError:
-    pass
-
-import qubes.qubesutils
-
-xid_to_name_cache = {}
-
-class QubesVm(object):
-    """
-    A representation of one Qubes VM
-    Only persistent information are stored here, while all the runtime
-    information, e.g. Xen dom id, etc, are to be retrieved via Xen API
-    Note that qid is not the same as Xen's domid!
-    """
-
-    # In which order load this VM type from qubes.xml
-    load_order = 100
-
-    # hooks for plugins (modules) which want to influence existing classes,
-    # without introducing new ones
-    hooks_clone_disk_files = []
-    hooks_create_on_disk = []
-    hooks_create_qubesdb_entries = []
-    hooks_get_attrs_config = []
-    hooks_get_clone_attrs = []
-    hooks_get_config_params = []
-    hooks_init = []
-    hooks_label_setter = []
-    hooks_netvm_setter = []
-    hooks_post_rename = []
-    hooks_pre_rename = []
-    hooks_remove_from_disk = []
-    hooks_start = []
-    hooks_verify_files = []
-    hooks_set_attr = []
-
-    def get_attrs_config(self):
-        """ Object attributes for serialization/deserialization
-            inner dict keys:
-             - order: initialization order (to keep dependency intact)
-                      attrs without order will be evaluated at the end
-             - default: default value used when attr not given to object constructor
-             - attr: set value to this attribute instead of parameter name
-             - eval: (DEPRECATED) assign result of this expression instead of
-                      value directly; local variable 'value' contains
-                      attribute value (or default if it was not given)
-             - func: callable used to parse the value retrieved from XML
-             - save: use evaluation result as value for XML serialization; only attrs with 'save' key will be saved in XML
-             - save_skip: if present and evaluates to true, attr will be omitted in XML
-             - save_attr: save to this XML attribute instead of parameter name
-             """
-
-        attrs = {
-            # __qid cannot be accessed by setattr, so must be set manually in __init__
-            "qid": { "attr": "_qid", "order": 0 },
-            "name": { "order": 1 },
-            "uuid": { "order": 0, "eval": 'uuid.UUID(value) if value else None' },
-            "dir_path": { "default": None, "order": 2 },
-            "pool_name": { "default":"default" },
-            "conf_file": {
-                "func": lambda value: self.absolute_path(value, self.name +
-                                                                 ".conf"),
-                "order": 3 },
-            ### order >= 10: have base attrs set
-            "firewall_conf": {
-                "func": self._absolute_path_gen(vm_files["firewall_conf"]),
-                "order": 10 },
-            "installed_by_rpm": { "default": False, 'order': 10 },
-            "template": { "default": None, "attr": '_template', 'order': 10 },
-            ### order >= 20: have template set
-            "uses_default_netvm": { "default": True, 'order': 20 },
-            "netvm": { "default": None, "attr": "_netvm", 'order': 20 },
-            "label": { "attr": "_label", "default": defaults["appvm_label"], 'order': 20,
-                'xml_deserialize': lambda _x: QubesVmLabels[_x] },
-            "memory": { "default": defaults["memory"], 'order': 20 },
-            "maxmem": { "default": None, 'order': 25 },
-            "pcidevs": {
-                "default": '[]',
-                "order": 25,
-                "func": lambda value: [] if value in ["none", None]  else
-                    eval(value) if value.find("[") >= 0 else
-                    eval("[" + value + "]") },
-            "pci_strictreset": {"default": True},
-            "pci_e820_host": {"default": True},
-            # Internal VM (not shown in qubes-manager, doesn't create appmenus entries
-            "internal": { "default": False, 'attr': '_internal' },
-            "vcpus": { "default": 2 },
-            "uses_default_kernel": { "default": True, 'order': 30 },
-            "uses_default_kernelopts": { "default": True, 'order': 30 },
-            "kernel": {
-                "attr": "_kernel",
-                "default": None,
-                "order": 31,
-                "func": lambda value: self._collection.get_default_kernel() if
-                  self.uses_default_kernel else value },
-            "kernelopts": {
-                "default": "",
-                "order": 31,
-                "func": lambda value: value if not self.uses_default_kernelopts\
-                    else defaults["kernelopts_pcidevs"] if len(self.pcidevs)>0 \
-                    else self.template.kernelopts if self.template
-                    else defaults["kernelopts"] },
-            "mac": { "attr": "_mac", "default": None },
-            "include_in_backups": {
-                "func": lambda x: x if x is not None
-                else not self.installed_by_rpm },
-            "services": {
-                "default": {},
-                "func": lambda value: eval(str(value)) },
-            "debug": { "default": False },
-            "default_user": { "default": "user", "attr": "_default_user" },
-            "qrexec_timeout": { "default": 60 },
-            "autostart": { "default": False, "attr": "_autostart" },
-            "uses_default_dispvm_netvm": {"default": True, "order": 30},
-            "dispvm_netvm": {"attr": "_dispvm_netvm", "default": None},
-            "backup_content" : { 'default': False },
-            "backup_size" : {
-                "default": 0,
-                "func": int },
-            "backup_path" : { 'default': "" },
-            "backup_timestamp": {
-                "func": lambda value:
-                    datetime.datetime.fromtimestamp(int(value)) if value
-                    else None },
-            ##### Internal attributes - will be overridden in __init__ regardless of args
-            "config_file_template": {
-                "func": lambda x: system_path["config_template_pv"] },
-            "icon_path": {
-                "func": lambda x: os.path.join(self.dir_path, "icon.png") if
-                               self.dir_path is not None else None },
-            # used to suppress side effects of clone_attrs
-            "_do_not_reset_firewall": { "func": lambda x: False },
-            "kernels_dir": {
-                # for backward compatibility (or another rare case): kernel=None -> kernel in VM dir
-                "func": lambda x: \
-                    os.path.join(system_path["qubes_kernels_base_dir"],
-                                 self.kernel) if self.kernel is not None \
-                        else os.path.join(self.dir_path,
-                                          vm_files["kernels_subdir"]) },
-            }
-
-        ### Mark attrs for XML inclusion
-        # Simple string attrs
-        for prop in ['qid', 'uuid', 'name', 'dir_path', 'memory', 'maxmem',
-            'pcidevs', 'pci_strictreset', 'vcpus', 'internal',\
-            'uses_default_kernel', 'kernel', 'uses_default_kernelopts',\
-            'kernelopts', 'services', 'installed_by_rpm',\
-            'uses_default_netvm', 'include_in_backups', 'debug',\
-            'qrexec_timeout', 'autostart', 'uses_default_dispvm_netvm',
-            'backup_content', 'backup_size', 'backup_path', 'pool_name',\
-            'pci_e820_host']:
-            attrs[prop]['save'] = lambda prop=prop: str(getattr(self, prop))
-        # Simple paths
-        for prop in ['conf_file', 'firewall_conf']:
-            attrs[prop]['save'] = \
-                lambda prop=prop: self.relative_path(getattr(self, prop))
-            attrs[prop]['save_skip'] = \
-                lambda prop=prop: getattr(self, prop) is None
-
-        # Can happen only if VM created in offline mode
-        attrs['maxmem']['save_skip'] = lambda: self.maxmem is None
-        attrs['vcpus']['save_skip'] = lambda: self.vcpus is None
-
-        attrs['uuid']['save_skip'] = lambda: self.uuid is None
-        attrs['mac']['save'] = lambda: str(self._mac)
-        attrs['mac']['save_skip'] = lambda: self._mac is None
-
-        attrs['default_user']['save'] = lambda: str(self._default_user)
-
-        attrs['backup_timestamp']['save'] = \
-            lambda: self.backup_timestamp.strftime("%s")
-        attrs['backup_timestamp']['save_skip'] = \
-            lambda: self.backup_timestamp is None
-
-        attrs['netvm']['save'] = \
-            lambda: str(self.netvm.qid) if self.netvm is not None else "none"
-        attrs['netvm']['save_attr'] = "netvm_qid"
-        attrs['dispvm_netvm']['save'] = \
-            lambda: str(self.dispvm_netvm.qid) \
-                if self.dispvm_netvm is not None \
-                else "none"
-        attrs['template']['save'] = \
-            lambda: str(self.template.qid) if self.template else "none"
-        attrs['template']['save_attr'] = "template_qid"
-        attrs['label']['save'] = lambda: self.label.name
-
-        # fire hooks
-        for hook in self.hooks_get_attrs_config:
-            attrs = hook(self, attrs)
-        return attrs
-
-    def post_set_attr(self, attr, newvalue, oldvalue):
-        for hook in self.hooks_set_attr:
-            hook(self, attr, newvalue, oldvalue)
-
-    def __basic_parse_xml_attr(self, value):
-        if value is None:
-            return None
-        if value.lower() == "none":
-            return None
-        if value.lower() == "true":
-            return True
-        if value.lower() == "false":
-            return False
-        if value.isdigit():
-            return int(value)
-        return value
-
-    def __init__(self, **kwargs):
-        self._collection = None
-        if 'collection' in kwargs:
-            self._collection = kwargs['collection']
-        else:
-            raise ValueError("No collection given to QubesVM constructor")
-
-        # Special case for template b/c it is given in "template_qid" property
-        if "xml_element" in kwargs and kwargs["xml_element"].get("template_qid"):
-            template_qid = kwargs["xml_element"].get("template_qid")
-            if template_qid.lower() != "none":
-                if int(template_qid) in self._collection:
-                    kwargs["template"] = self._collection[int(template_qid)]
-                else:
-                    raise ValueError("Unknown template with QID %s" % template_qid)
-        attrs = self.get_attrs_config()
-        for attr_name in sorted(attrs, key=lambda _x: attrs[_x]['order'] if 'order' in attrs[_x] else 1000):
-            attr_config = attrs[attr_name]
-            attr = attr_name
-            if 'attr' in attr_config:
-                attr = attr_config['attr']
-            value = None
-            if attr_name in kwargs:
-                value = kwargs[attr_name]
-            elif 'xml_element' in kwargs and kwargs['xml_element'].get(attr_name) is not None:
-                if 'xml_deserialize' in attr_config and callable(attr_config['xml_deserialize']):
-                    value = attr_config['xml_deserialize'](kwargs['xml_element'].get(attr_name))
-                else:
-                    value = self.__basic_parse_xml_attr(kwargs['xml_element'].get(attr_name))
-            else:
-                if 'default' in attr_config:
-                    value = attr_config['default']
-            if 'func' in attr_config:
-                setattr(self, attr, attr_config['func'](value))
-            elif 'eval' in attr_config:
-                setattr(self, attr, eval(attr_config['eval']))
-            else:
-                #print "setting %s to %s" % (attr, value)
-                setattr(self, attr, value)
-
-        #Init private attrs
-        self.__qid = self._qid
-
-        self._libvirt_domain = None
-        self._qdb_connection = None
-
-        assert self.__qid < qubes_max_qid, "VM id out of bounds!"
-        assert self.name is not None
-
-        if not self.verify_name(self.name):
-            msg = ("'%s' is invalid VM name (invalid characters, over 31 chars long, "
-                   "ends with '-dm', or one of 'none', 'true', 'false')") % self.name
-            if 'xml_element' in kwargs:
-                print >>sys.stderr, "WARNING: %s" % msg
-            else:
-                raise QubesException(msg)
-
-        if self.netvm is not None:
-            self.netvm.connected_vms[self.qid] = self
-
-        # Not in generic way to not create QubesHost() to frequently
-        if self.maxmem is None and not vmm.offline_mode:
-            qubes_host = QubesHost()
-            total_mem_mb = qubes_host.memory_total/1024
-            self.maxmem = total_mem_mb/2
-
-        # Linux specific cap: max memory can't scale beyond 10.79*init_mem
-        if self.maxmem > self.memory * 10:
-            self.maxmem = self.memory * 10
-
-        # Always set if meminfo-writer should be active or not
-        if 'meminfo-writer' not in self.services:
-            self.services['meminfo-writer'] = not (len(self.pcidevs) > 0)
-
-        # Additionally force meminfo-writer disabled when VM have PCI devices
-        if len(self.pcidevs) > 0:
-            self.services['meminfo-writer'] = False
-
-        if 'xml_element' not in kwargs:
-            # New VM, disable updates check if requested for new VMs
-            if os.path.exists(qubes.qubesutils.UPDATES_DEFAULT_VM_DISABLE_FLAG):
-                self.services['qubes-update-check'] = False
-
-        # Initialize VM image storage class
-        self.storage = get_pool(self.pool_name, self).getStorage()
-        self.dir_path = self.storage.vmdir
-        self.icon_path = os.path.join(self.storage.vmdir, 'icon.png')
-        self.conf_file = os.path.join(self.storage.vmdir, self.name + '.conf')
-
-        if hasattr(self, 'kernels_dir'):
-            modules_path = os.path.join(self.kernels_dir,
-                    "modules.img")
-            if os.path.exists(modules_path):
-                self.storage.modules_img = modules_path
-                self.storage.modules_img_rw = self.kernel is None
-
-        # Some additional checks for template based VM
-        if self.template is not None:
-            if not self.template.is_template():
-                print >> sys.stderr, "ERROR: template_qid={0} doesn't point to a valid TemplateVM".\
-                    format(self.template.qid)
-                return
-            self.template.appvms[self.qid] = self
-        else:
-            assert self.root_img is not None, "Missing root_img for standalone VM!"
-
-        self.log = logging.getLogger('qubes.vm.{}'.format(self.qid))
-        self.log.debug('instantiated name={!r} class={}'.format(
-            self.name, self.__class__.__name__))
-
-        # fire hooks
-        for hook in self.hooks_init:
-            hook(self)
-
-    def __repr__(self):
-        return '<{} at {:#0x} qid={!r} name={!r}>'.format(
-            self.__class__.__name__,
-            id(self),
-            self.qid,
-            self.name)
-
-    def absolute_path(self, arg, default):
-        if arg is not None and os.path.isabs(arg):
-            return arg
-        elif self.dir_path is not None:
-            return os.path.join(self.dir_path, (arg if arg is not None else default))
-        else:
-            # cannot provide any meaningful value without dir_path; this is
-            # only to import some older format of `qubes.xml` (for example
-            # during migration from older release)
-            return None
-
-    def _absolute_path_gen(self, default):
-        return lambda value: self.absolute_path(value, default)
-
-    def relative_path(self, arg):
-        return arg.replace(self.dir_path + '/', '')
-
-    @property
-    def qid(self):
-        return self.__qid
-
-    @property
-    def label(self):
-        return self._label
-
-    @label.setter
-    def label(self, new_label):
-        self._label = new_label
-        if self.icon_path:
-            try:
-                os.remove(self.icon_path)
-            except:
-                pass
-            if hasattr(os, "symlink"):
-                os.symlink (new_label.icon_path, self.icon_path)
-                # FIXME: some os-independent wrapper?
-                subprocess.call(['sudo', 'xdg-icon-resource', 'forceupdate'])
-            else:
-                shutil.copy(new_label.icon_path, self.icon_path)
-
-        # fire hooks
-        for hook in self.hooks_label_setter:
-            hook(self, new_label)
-
-    @property
-    def netvm(self):
-        return self._netvm
-
-    # Don't know how properly call setter from base class, so workaround it...
-    @netvm.setter
-    def netvm(self, new_netvm):
-        self._set_netvm(new_netvm)
-        # fire hooks
-        for hook in self.hooks_netvm_setter:
-            hook(self, new_netvm)
-
-    def _set_netvm(self, new_netvm):
-        self.log.debug('netvm = {!r}'.format(new_netvm))
-        if new_netvm and not new_netvm.is_netvm():
-            raise ValueError("Vm {!r} does not provide network".format(
-                new_netvm))
-        if self.is_running() and new_netvm is not None and not new_netvm.is_running():
-            raise QubesException("Cannot dynamically attach to stopped NetVM")
-        if self.netvm is not None:
-            self.netvm.connected_vms.pop(self.qid)
-            if self.is_running():
-                self.detach_network()
-
-                if hasattr(self.netvm, 'post_vm_net_detach'):
-                    self.netvm.post_vm_net_detach(self)
-
-        if new_netvm is not None:
-            new_netvm.connected_vms[self.qid]=self
-
-        self._netvm = new_netvm
-
-        if new_netvm is None:
-            return
-
-        if self.is_running():
-            # refresh IP, DNS etc
-            self.create_qubesdb_entries()
-            self.attach_network()
-            if hasattr(self.netvm, 'post_vm_net_attach'):
-                self.netvm.post_vm_net_attach(self)
-
-    @property
-    def ip(self):
-        if self.netvm is not None:
-            return self.netvm.get_ip_for_vm(self.qid)
-        else:
-            return None
-
-    @property
-    def netmask(self):
-        if self.netvm is not None:
-            return self.netvm.netmask
-        else:
-            return None
-
-    @property
-    def gateway(self):
-        # This is gateway IP for _other_ VMs, so make sense only in NetVMs
-        return None
-
-    @property
-    def secondary_dns(self):
-        if self.netvm is not None:
-            return self.netvm.secondary_dns
-        else:
-            return None
-
-    @property
-    def vif(self):
-        if self.xid < 0:
-            return None
-        if self.netvm is None:
-            return None
-        return "vif{0}.+".format(self.xid)
-
-    @property
-    def mac(self):
-        if self._mac is not None:
-            return self._mac
-        else:
-            return "00:16:3E:5E:6C:{qid:02X}".format(qid=self.qid)
-
-    @mac.setter
-    def mac(self, new_mac):
-        self._mac = new_mac
-
-    @property
-    def kernel(self):
-        return self._kernel
-
-    @kernel.setter
-    def kernel(self, new_value):
-        if new_value is not None:
-            if not os.path.exists(os.path.join(system_path[
-                'qubes_kernels_base_dir'], new_value)):
-                raise QubesException("Kernel '%s' not installed" % new_value)
-            for f in ('vmlinuz', 'initramfs'):
-                if not os.path.exists(os.path.join(
-                        system_path['qubes_kernels_base_dir'], new_value, f)):
-                    raise QubesException(
-                        "Kernel '%s' not properly installed: missing %s "
-                        "file" % (new_value, f))
-        self._kernel = new_value
-        self.uses_default_kernel = False
-
-    @property
-    def updateable(self):
-        return self.template is None
-
-    # Leaved for compatibility
-    def is_updateable(self):
-        return self.updateable
-
-    @property
-    def default_user(self):
-        if self.template is not None:
-            return self.template.default_user
-        else:
-            return self._default_user
-
-    @default_user.setter
-    def default_user(self, value):
-        self._default_user = value
-
-    def is_networked(self):
-        if self.is_netvm():
-            return True
-
-        if self.netvm is not None:
-            return True
-        else:
-            return False
-
-    def verify_name(self, name):
-        if not isinstance(self.__basic_parse_xml_attr(name), str):
-            return False
-        if len(name) > 31:
-            return False
-        if name == 'lost+found':
-            # avoid conflict when /var/lib/qubes/appvms is mounted on
-            # separate partition
-            return False
-        if name.endswith('-dm'):
-            # avoid conflict with device model stubdomain names for HVMs
-            return False
-        return re.match(r"^[a-zA-Z][a-zA-Z0-9_.-]*$", name) is not None
-
-    def pre_rename(self, new_name):
-        if self.autostart:
-            subprocess.check_call(['sudo', 'systemctl', '-q', 'disable',
-                                   'qubes-vm@{}.service'.format(self.name)])
-        # fire hooks
-        for hook in self.hooks_pre_rename:
-            hook(self, new_name)
-
-    def set_name(self, name):
-        self.log.debug('name = {!r}'.format(name))
-        if self.is_running():
-            raise QubesException("Cannot change name of running VM!")
-
-        if not self.verify_name(name):
-            raise QubesException("Invalid VM name")
-
-        if self.installed_by_rpm:
-            raise QubesException("Cannot rename VM installed by RPM -- first clone VM and then use yum to remove package.")
-
-        assert self._collection is not None
-        if self._collection.get_vm_by_name(name):
-            raise QubesException("VM with this name already exists")
-
-        self.pre_rename(name)
-        try:
-            self.libvirt_domain.undefine()
-        except libvirt.libvirtError as e:
-            if e.get_error_code() == libvirt.VIR_ERR_NO_DOMAIN:
-                pass
-            else:
-                raise
-        if self._qdb_connection:
-            self._qdb_connection.close()
-            self._qdb_connection = None
-
-        new_conf = os.path.join(self.dir_path, name + '.conf')
-        if os.path.exists(self.conf_file):
-            os.rename(self.conf_file, new_conf)
-        old_dirpath = self.dir_path
-        self.storage.rename(self.name, name)
-        new_dirpath = self.storage.vmdir
-        self.dir_path = new_dirpath
-        old_name = self.name
-        self.name = name
-        if self.conf_file is not None:
-            self.conf_file = new_conf.replace(old_dirpath, new_dirpath)
-        if self.icon_path is not None:
-            self.icon_path = self.icon_path.replace(old_dirpath, new_dirpath)
-        if hasattr(self, 'kernels_dir') and self.kernels_dir is not None:
-            self.kernels_dir = self.kernels_dir.replace(old_dirpath, new_dirpath)
-        if self.firewall_conf is not None:
-            self.firewall_conf = self.firewall_conf.replace(old_dirpath,
-                                                            new_dirpath)
-
-        self._update_libvirt_domain()
-        self.post_rename(old_name)
-
-    def post_rename(self, old_name):
-        if self.autostart:
-            # force setter to be called again
-            self.autostart = self.autostart
-        # fire hooks
-        for hook in self.hooks_post_rename:
-            hook(self, old_name)
-
-    @property
-    def internal(self):
-        return self._internal
-
-    @internal.setter
-    def internal(self, value):
-        oldvalue = self._internal
-        self._internal = value
-        self.post_set_attr('internal', value, oldvalue)
-
-    @property
-    def dispvm_netvm(self):
-        if self.uses_default_dispvm_netvm:
-            return self.netvm
-        else:
-            if isinstance(self._dispvm_netvm, int):
-                return self._collection[self._dispvm_netvm]
-            else:
-                return self._dispvm_netvm
-
-    @dispvm_netvm.setter
-    def dispvm_netvm(self, value):
-        if value and not value.is_netvm():
-            raise ValueError("Vm {!r} does not provide network".format(
-                value))
-        self._dispvm_netvm = value
-
-    @property
-    def autostart(self):
-        return self._autostart
-
-    @autostart.setter
-    def autostart(self, value):
-        if value:
-            retcode = subprocess.call(["sudo", "ln", "-sf",
-                                       "/usr/lib/systemd/system/qubes-vm@.service",
-                                       "/etc/systemd/system/multi-user.target.wants/qubes-vm@%s.service" % self.name])
-        else:
-            retcode = subprocess.call(["sudo", "systemctl", "disable", "qubes-vm@%s.service" % self.name])
-        if retcode != 0:
-            raise QubesException("Failed to set autostart for VM via systemctl")
-        self._autostart = bool(value)
-
-    @classmethod
-    def is_template_compatible(cls, template):
-        """Check if given VM can be a template for this VM"""
-        # FIXME: check if the value is instance of QubesTemplateVM, not the VM
-        # type. The problem is while this file is loaded, QubesTemplateVM is
-        # not defined yet.
-        if template and (not template.is_template() or template.type != "TemplateVM"):
-            return False
-        return True
-
-    @property
-    def template(self):
-        return self._template
-
-    @template.setter
-    def template(self, value):
-        if self._template is None and value is not None:
-            raise QubesException("Cannot set template for standalone VM")
-        if value and not self.is_template_compatible(value):
-            raise QubesException("Incompatible template type %s with VM of type %s" % (value.type, self.type))
-        self._template = value
-
-    def is_template(self):
-        return False
-
-    def is_appvm(self):
-        return False
-
-    def is_netvm(self):
-        return False
-
-    def is_proxyvm(self):
-        return False
-
-    def is_disposablevm(self):
-        return False
-
-    @property
-    def qdb(self):
-        if self._qdb_connection is None:
-            from qubes.qdb import QubesDB
-            self._qdb_connection = QubesDB(self.name)
-        return self._qdb_connection
-
-    @property
-    def xid(self):
-        try:
-            return self.libvirt_domain.ID()
-        except libvirt.libvirtError as e:
-            if e.get_error_code() == libvirt.VIR_ERR_NO_DOMAIN:
-                return -1
-            else:
-                print >>sys.stderr, "libvirt error code: {!r}".format(
-                    e.get_error_code())
-                raise
-
-
-    def get_xid(self):
-        # obsoleted
-        return self.xid
-
-    def _update_libvirt_domain(self):
-        domain_config = self.create_config_file()
-        try:
-            self._libvirt_domain = vmm.libvirt_conn.defineXML(domain_config)
-        except libvirt.libvirtError as e:
-            # shouldn't this be in QubesHVm implementation?
-            if e.get_error_code() == libvirt.VIR_ERR_OS_TYPE and \
-                    e.get_str2() == 'hvm':
-                raise QubesException("HVM domains not supported on this "
-                                     "machine. Check BIOS settings for "
-                                     "VT-x/AMD-V extensions.")
-            else:
-                raise e
-        self.uuid = uuid.UUID(bytes=self._libvirt_domain.UUID())
-
-    @property
-    def libvirt_domain(self):
-        if self._libvirt_domain is None:
-            if self.uuid is not None:
-                self._libvirt_domain = vmm.libvirt_conn.lookupByUUID(self.uuid.bytes)
-            else:
-                self._libvirt_domain = vmm.libvirt_conn.lookupByName(self.name)
-                self.uuid = uuid.UUID(bytes=self._libvirt_domain.UUID())
-        return self._libvirt_domain
-
-    def get_uuid(self):
-        # obsoleted
-        return self.uuid
-
-    def refresh(self):
-        self._libvirt_domain = None
-        self._qdb_connection = None
-
-    def get_mem(self):
-        if dry_run:
-            return 666
-
-        try:
-            if not self.libvirt_domain.isActive():
-                return 0
-            return self.libvirt_domain.info()[1]
-        except libvirt.libvirtError as e:
-            if e.get_error_code() == libvirt.VIR_ERR_NO_DOMAIN:
-                return 0
-                # libxl_domain_info failed - domain no longer exists
-            elif e.get_error_code() == libvirt.VIR_ERR_INTERNAL_ERROR:
-                return 0
-            elif e.get_error_code() is None:  # unknown...
-                return 0
-            else:
-                print >>sys.stderr, "libvirt error code: {!r}".format(
-                    e.get_error_code())
-                raise
-
-    def get_cputime(self):
-        if dry_run:
-            return 666
-
-        try:
-            if not self.libvirt_domain.isActive():
-                return 0
-            return self.libvirt_domain.info()[4]
-        except libvirt.libvirtError as e:
-            if e.get_error_code() == libvirt.VIR_ERR_NO_DOMAIN:
-                return 0
-                # libxl_domain_info failed - domain no longer exists
-            elif e.get_error_code() == libvirt.VIR_ERR_INTERNAL_ERROR:
-                return 0
-            elif e.get_error_code() is None:  # unknown...
-                return 0
-            else:
-                print >>sys.stderr, "libvirt error code: {!r}".format(
-                    e.get_error_code())
-                raise
-
-    def get_mem_static_max(self):
-        if dry_run:
-            return 666
-
-        try:
-            return self.libvirt_domain.maxMemory()
-        except libvirt.libvirtError as e:
-            if e.get_error_code() == libvirt.VIR_ERR_NO_DOMAIN:
-                return 0
-            else:
-                raise
-
-    def get_prefmem(self):
-        # TODO: qmemman is still xen specific
-        untrusted_meminfo_key = vmm.xs.read('',
-                                            '/local/domain/%s/memory/meminfo'
-                                            % self.xid)
-        if untrusted_meminfo_key is None or untrusted_meminfo_key == '':
-            return 0
-        domain = qmemman.DomainState(self.xid)
-        qmemman_algo.refresh_meminfo_for_domain(domain, untrusted_meminfo_key)
-        domain.memory_maximum = self.get_mem_static_max()*1024
-        return qmemman_algo.prefmem(domain)/1024
-
-    def get_per_cpu_time(self):
-        if dry_run:
-            import random
-            return random.random() * 100
-
-        try:
-            if self.libvirt_domain.isActive():
-                return self.libvirt_domain.getCPUStats(
-                        libvirt.VIR_NODE_CPU_STATS_ALL_CPUS, 0)[0]['cpu_time']/10**9
-            else:
-                return 0
-        except libvirt.libvirtError as e:
-            if e.get_error_code() == libvirt.VIR_ERR_NO_DOMAIN:
-                return 0
-            else:
-                print >>sys.stderr, "libvirt error code: {!r}".format(
-                    e.get_error_code())
-                raise
-
-    def get_disk_utilization_root_img(self):
-        return qubes.qubesutils.get_disk_usage(self.root_img)
-
-    def get_root_img_sz(self):
-        if not os.path.exists(self.root_img):
-            return 0
-
-        return os.path.getsize(self.root_img)
-
-    def get_power_state(self):
-        if dry_run:
-            return "NA"
-
-        try:
-            libvirt_domain = self.libvirt_domain
-            if libvirt_domain.isActive():
-                if libvirt_domain.state()[0] == libvirt.VIR_DOMAIN_PAUSED:
-                    return "Paused"
-                elif libvirt_domain.state()[0] == libvirt.VIR_DOMAIN_CRASHED:
-                    return "Crashed"
-                elif libvirt_domain.state()[0] == libvirt.VIR_DOMAIN_SHUTDOWN:
-                    return "Halting"
-                elif libvirt_domain.state()[0] == libvirt.VIR_DOMAIN_SHUTOFF:
-                    return "Dying"
-                elif libvirt_domain.state()[0] == libvirt.VIR_DOMAIN_PMSUSPENDED:
-                    return "Suspended"
-                else:
-                    if not self.is_fully_usable():
-                        return "Transient"
-                    else:
-                        return "Running"
-            else:
-                return 'Halted'
-        except libvirt.libvirtError as e:
-            if e.get_error_code() == libvirt.VIR_ERR_NO_DOMAIN:
-                return "Halted"
-            else:
-                raise
-
-
-    def is_guid_running(self):
-        xid = self.xid
-        if xid < 0:
-            return False
-        if not os.path.exists('/var/run/qubes/guid-running.%d' % xid):
-            return False
-        return True
-
-    def is_qrexec_running(self):
-        if self.xid < 0:
-            return False
-        return os.path.exists('/var/run/qubes/qrexec.%s' % self.name)
-
-    def is_fully_usable(self):
-        # Running gui-daemon implies also VM running
-        if not self.is_guid_running():
-            return False
-        if not self.is_qrexec_running():
-            return False
-        return True
-
-    def is_running(self):
-        if vmm.offline_mode:
-            return False
-        try:
-            if self.libvirt_domain.isActive():
-                return True
-            else:
-                return False
-        except libvirt.libvirtError as e:
-            if e.get_error_code() == libvirt.VIR_ERR_NO_DOMAIN:
-                return False
-                # libxl_domain_info failed - domain no longer exists
-            elif e.get_error_code() == libvirt.VIR_ERR_INTERNAL_ERROR:
-                return False
-            elif e.get_error_code() is None:  # unknown...
-                return False
-            else:
-                print >>sys.stderr, "libvirt error code: {!r}".format(
-                    e.get_error_code())
-                raise
-
-    def is_paused(self):
-        try:
-            if self.libvirt_domain.state()[0] == libvirt.VIR_DOMAIN_PAUSED:
-                return True
-            else:
-                return False
-        except libvirt.libvirtError as e:
-            if e.get_error_code() == libvirt.VIR_ERR_NO_DOMAIN:
-                return False
-                # libxl_domain_info failed - domain no longer exists
-            elif e.get_error_code() == libvirt.VIR_ERR_INTERNAL_ERROR:
-                return False
-            elif e.get_error_code() is None:  # unknown...
-                return False
-            else:
-                print >>sys.stderr, "libvirt error code: {!r}".format(
-                    e.get_error_code())
-                raise
-
-    def get_start_time(self):
-        if not self.is_running():
-            return None
-
-        # TODO
-        uuid = self.uuid
-
-        start_time = vmm.xs.read('', "/vm/%s/start_time" % str(uuid))
-        if start_time:
-            return datetime.datetime.fromtimestamp(float(start_time))
-        else:
-            return None
-
-    def is_outdated(self):
-        # Makes sense only on VM based on template
-        if self.template is None:
-            return False
-
-        if not self.is_running():
-            return False
-
-        if not hasattr(self.template, 'rootcow_img'):
-            return False
-
-        rootimg_inode = os.stat(self.template.root_img)
-        try:
-            rootcow_inode = os.stat(self.template.rootcow_img)
-        except OSError:
-            # The only case when rootcow_img doesn't exists is in the middle of
-            # commit_changes, so VM is outdated right now
-            return True
-
-        current_dmdev = "/dev/mapper/snapshot-{0:x}:{1}-{2:x}:{3}".format(
-                rootimg_inode[2], rootimg_inode[1],
-                rootcow_inode[2], rootcow_inode[1])
-
-        # FIXME
-        # 51712 (0xCA00) is xvda
-        #  backend node name not available through xenapi :(
-        used_dmdev = vmm.xs.read('', "/local/domain/0/backend/vbd/{0}/51712/node".format(self.xid))
-
-        return used_dmdev != current_dmdev
-
-    @property
-    def private_img(self):
-        return self.storage.private_img
-
-    @property
-    def root_img(self):
-        return self.storage.root_img
-
-    @property
-    def volatile_img(self):
-        return self.storage.volatile_img
-
-    def get_disk_utilization(self):
-        return qubes.qubesutils.get_disk_usage(self.dir_path)
-
-    def get_disk_utilization_private_img(self):
-        return qubes.qubesutils.get_disk_usage(self.private_img)
-
-    def get_private_img_sz(self):
-        return self.storage.get_private_img_sz()
-
-    def resize_private_img(self, size):
-        assert size >= self.get_private_img_sz(), "Cannot shrink private.img"
-
-        # resize the image
-        self.storage.resize_private_img(size)
-
-        # and then the filesystem
-        retcode = 0
-        if self.is_running():
-            retcode = self.run("while [ \"`blockdev --getsize64 /dev/xvdb`\" -lt {0} ]; do ".format(size) +
-                "head /dev/xvdb > /dev/null; sleep 0.2; done; resize2fs /dev/xvdb", user="root", wait=True)
-        if retcode != 0:
-            raise QubesException("resize2fs failed")
-
-
-
-    # FIXME: should be outside of QubesVM?
-    def get_timezone(self):
-        # fc18
-        if os.path.islink('/etc/localtime'):
-            return '/'.join(os.readlink('/etc/localtime').split('/')[-2:])
-        # <=fc17
-        elif os.path.exists('/etc/sysconfig/clock'):
-            clock_config = open('/etc/sysconfig/clock', "r")
-            clock_config_lines = clock_config.readlines()
-            clock_config.close()
-            zone_re = re.compile(r'^ZONE="(.*)"')
-            for line in clock_config_lines:
-                line_match = zone_re.match(line)
-                if line_match:
-                    return line_match.group(1)
-        else:
-            # last resort way, some applications makes /etc/localtime
-            # hardlink instead of symlink...
-            tz_info = os.stat('/etc/localtime')
-            if not tz_info:
-                return None
-            if tz_info.st_nlink > 1:
-                p = subprocess.Popen(['find', '/usr/share/zoneinfo',
-                                      '-inum', str(tz_info.st_ino),
-                                      '-print', '-quit'],
-                                     stdout=subprocess.PIPE)
-                tz_path = p.communicate()[0].strip()
-                return tz_path.replace('/usr/share/zoneinfo/', '')
-        return None
-
-    def cleanup_vifs(self):
-        """
-        Xend does not remove vif when backend domain is down, so we must do it
-        manually
-        """
-
-        # FIXME: remove this?
-        if not self.is_running():
-            return
-
-        dev_basepath = '/local/domain/%d/device/vif' % self.xid
-        for dev in (vmm.xs.ls('', dev_basepath) or []):
-            # check if backend domain is alive
-            backend_xid = int(vmm.xs.read('', '%s/%s/backend-id' % (dev_basepath, dev)))
-            if backend_xid in vmm.libvirt_conn.listDomainsID():
-                # check if device is still active
-                if vmm.xs.read('', '%s/%s/state' % (dev_basepath, dev)) == '4':
-                    continue
-            # remove dead device
-            vmm.xs.rm('', '%s/%s' % (dev_basepath, dev))
-
-    def create_qubesdb_entries(self):
-        if dry_run:
-            return
-
-        self.qdb.write("/name", self.name)
-        self.qdb.write("/qubes-vm-type", self.type)
-        self.qdb.write("/qubes-vm-updateable", str(self.updateable))
-        self.qdb.write("/qubes-vm-persistence",
-                       "full" if self.updateable else "rw-only")
-        self.qdb.write("/qubes-base-template",
-                       self.template.name if self.template else '')
-
-        if self.is_netvm():
-            self.qdb.write("/qubes-netvm-gateway", self.gateway)
-            self.qdb.write("/qubes-netvm-primary-dns", self.gateway)
-            self.qdb.write("/qubes-netvm-secondary-dns", self.secondary_dns)
-            self.qdb.write("/qubes-netvm-netmask", self.netmask)
-            self.qdb.write("/qubes-netvm-network", self.network)
-
-        if self.netvm is not None:
-            self.qdb.write("/qubes-ip", self.ip)
-            self.qdb.write("/qubes-netmask", self.netvm.netmask)
-            self.qdb.write("/qubes-gateway", self.netvm.gateway)
-            self.qdb.write("/qubes-primary-dns", self.netvm.gateway)
-            self.qdb.write("/qubes-secondary-dns", self.netvm.secondary_dns)
-
-        tzname = self.get_timezone()
-        if tzname:
-             self.qdb.write("/qubes-timezone", tzname)
-
-        for srv in self.services.keys():
-            # convert True/False to "1"/"0"
-            self.qdb.write("/qubes-service/{0}".format(srv),
-                    str(int(self.services[srv])))
-
-        self.qdb.write("/qubes-block-devices", '')
-
-        self.qdb.write("/qubes-usb-devices", '')
-
-        self.qdb.write("/qubes-debug-mode", str(int(self.debug)))
-
-        self.provide_random_seed_to_vm()
-
-        # TODO: Currently the whole qmemman is quite Xen-specific, so stay with
-        # xenstore for it until decided otherwise
-        if qmemman_present:
-            vmm.xs.set_permissions('', '/local/domain/{0}/memory'.format(self.xid),
-                    [{ 'dom': self.xid }])
-
-        # fire hooks
-        for hook in self.hooks_create_qubesdb_entries:
-            hook(self)
-
-    def provide_random_seed_to_vm(self):
-        f = open('/dev/urandom', 'r')
-        s = f.read(64)
-        if len(s) != 64:
-            raise IOError("failed to read seed from /dev/urandom")
-        f.close()
-        self.qdb.write("/qubes-random-seed", base64.b64encode(hashlib.sha512(s).digest()))
-
-    def _format_net_dev(self, ip, mac, backend):
-        template = "    <interface type='ethernet'>\n" \
-                   "      <mac address='{mac}'/>\n" \
-                   "      <ip address='{ip}'/>\n" \
-                   "      <script path='vif-route-qubes'/>\n" \
-                   "      <backenddomain name='{backend}'/>\n" \
-                   "    </interface>\n"
-        return template.format(ip=ip, mac=mac, backend=backend)
-
-    def _format_pci_dev(self, address):
-        template = "    <hostdev type='pci' managed='yes'{strictreset}>\n" \
-                   "      <source>\n" \
-                   "        <address bus='0x{bus}' slot='0x{slot}' function='0x{fun}'/>\n" \
-                   "      </source>\n" \
-                   "    </hostdev>\n"
-        dev_match = re.match('([0-9a-f]+):([0-9a-f]+)\.([0-9a-f]+)', address)
-        if not dev_match:
-            raise QubesException("Invalid PCI device address: %s" % address)
-        return template.format(
-                bus=dev_match.group(1),
-                slot=dev_match.group(2),
-                fun=dev_match.group(3),
-                strictreset=("" if self.pci_strictreset else
-                             " nostrictreset='yes'"),
-        )
-
-    def get_config_params(self):
-        args = {}
-        args['name'] = self.name
-        if hasattr(self, 'kernels_dir'):
-            args['kerneldir'] = self.kernels_dir
-        args['uuidnode'] = "<uuid>%s</uuid>" % str(self.uuid) if self.uuid else ""
-        args['vmdir'] = self.dir_path
-        args['pcidevs'] = ''.join(map(self._format_pci_dev, self.pcidevs))
-        args['mem'] = str(self.memory)
-        if self.maxmem < self.memory:
-            args['mem'] = str(self.maxmem)
-        args['maxmem'] = str(self.maxmem)
-        if 'meminfo-writer' in self.services and not self.services['meminfo-writer']:
-            # If dynamic memory management disabled, set maxmem=mem
-            args['maxmem'] = args['mem']
-        args['vcpus'] = str(self.vcpus)
-        args['features'] = ''
-        if self.netvm is not None:
-            args['ip'] = self.ip
-            args['mac'] = self.mac
-            args['gateway'] = self.netvm.gateway
-            args['dns1'] = self.netvm.gateway
-            args['dns2'] = self.secondary_dns
-            args['netmask'] = self.netmask
-            args['netdev'] = self._format_net_dev(self.ip, self.mac, self.netvm.name)
-            args['network_begin'] = ''
-            args['network_end'] = ''
-            args['no_network_begin'] = '<!--'
-            args['no_network_end'] = '-->'
-        else:
-            args['ip'] = ''
-            args['mac'] = ''
-            args['gateway'] = ''
-            args['dns1'] = ''
-            args['dns2'] = ''
-            args['netmask'] = ''
-            args['netdev'] = ''
-            args['network_begin'] = '<!--'
-            args['network_end'] = '-->'
-            args['no_network_begin'] = ''
-            args['no_network_end'] = ''
-        if len(self.pcidevs) and self.pci_e820_host:
-            args['features'] = '<xen><e820_host state=\'on\'/></xen>'
-        args.update(self.storage.get_config_params())
-        if hasattr(self, 'kernelopts'):
-            args['kernelopts'] = self.kernelopts
-            if self.debug:
-                print >> sys.stderr, "--> Debug mode: adding 'earlyprintk=xen' to kernel opts"
-                args['kernelopts'] += ' earlyprintk=xen'
-
-        # fire hooks
-        for hook in self.hooks_get_config_params:
-            args = hook(self, args)
-
-        return args
-
-    @property
-    def uses_custom_config(self):
-        return self.conf_file != self.absolute_path(self.name + ".conf", None)
-
-    def create_config_file(self, file_path = None, prepare_dvm = False):
-        if file_path is None:
-            file_path = self.conf_file
-        if self.uses_custom_config:
-            conf_appvm = open(file_path, "r")
-            domain_config = conf_appvm.read()
-            conf_appvm.close()
-            return domain_config
-
-        f_conf_template = open(self.config_file_template, 'r')
-        conf_template = f_conf_template.read()
-        f_conf_template.close()
-
-        template_params = self.get_config_params()
-        if prepare_dvm:
-            template_params['name'] = '%NAME%'
-            template_params['privatedev'] = ''
-            template_params['netdev'] = re.sub(r"address='[0-9.]*'", "address='%IP%'", template_params['netdev'])
-        domain_config = conf_template.format(**template_params)
-
-        # FIXME: This is only for debugging purposes
-        old_umask = os.umask(002)
-        try:
-            if os.path.exists(file_path):
-                os.unlink(file_path)
-            conf_appvm = open(file_path, "w")
-            conf_appvm.write(domain_config)
-            conf_appvm.close()
-        except:
-            # Ignore errors
-            pass
-        finally:
-            os.umask(old_umask)
-
-        return domain_config
-
-    def create_on_disk(self, verbose=False, source_template = None):
-        self.log.debug('create_on_disk(source_template={!r})'.format(
-            source_template))
-        if source_template is None:
-            source_template = self.template
-        assert source_template is not None
-
-        if dry_run:
-            return
-
-        self.storage.create_on_disk(verbose, source_template)
-
-        if self.updateable:
-            kernels_dir = source_template.kernels_dir
-            if verbose:
-                print >> sys.stderr, "--> Copying the kernel (set kernel \"none\" to use it): {0}".\
-                        format(kernels_dir)
-
-            os.mkdir (self.dir_path + '/kernels')
-            for f in ("vmlinuz", "initramfs", "modules.img"):
-                shutil.copy(os.path.join(kernels_dir, f),
-                        os.path.join(self.dir_path, vm_files["kernels_subdir"], f))
-
-        if verbose:
-            print >> sys.stderr, "--> Creating icon symlink: {0} -> {1}".format(self.icon_path, self.label.icon_path)
-        if hasattr(os, "symlink"):
-            os.symlink (self.label.icon_path, self.icon_path)
-        else:
-            shutil.copy(self.label.icon_path, self.icon_path)
-
-        # Make sure that we have UUID allocated
-        if not vmm.offline_mode:
-            self._update_libvirt_domain()
-        else:
-            self.uuid = uuid.uuid4()
-
-        # fire hooks
-        for hook in self.hooks_create_on_disk:
-            hook(self, verbose, source_template=source_template)
-
-    def get_clone_attrs(self):
-        attrs = ['kernel', 'uses_default_kernel', 'netvm', 'uses_default_netvm',
-                 'memory', 'maxmem', 'kernelopts', 'uses_default_kernelopts',
-                 'services', 'vcpus', '_mac', 'pcidevs', 'include_in_backups',
-                 '_label', 'default_user', 'qrexec_timeout']
-
-        # fire hooks
-        for hook in self.hooks_get_clone_attrs:
-            attrs = hook(self, attrs)
-
-        return attrs
-
-    def clone_attrs(self, src_vm, fail_on_error=True):
-        self._do_not_reset_firewall = True
-        for prop in self.get_clone_attrs():
-            try:
-                val = getattr(src_vm, prop)
-                if isinstance(val, dict):
-                    val = val.copy()
-                setattr(self, prop, val)
-            except Exception as e:
-                if fail_on_error:
-                    self._do_not_reset_firewall = False
-                    raise
-                else:
-                    print >>sys.stderr, "WARNING: %s" % str(e)
-        self._do_not_reset_firewall = False
-
-    def clone_disk_files(self, src_vm, verbose):
-        if dry_run:
-            return
-
-        if src_vm.is_running():
-            raise QubesException("Attempt to clone a running VM!")
-
-        self.storage.clone_disk_files(src_vm, verbose)
-
-        if src_vm.icon_path is not None and self.icon_path is not None:
-            if os.path.exists (src_vm.dir_path):
-                if os.path.islink(src_vm.icon_path):
-                    icon_path = os.readlink(src_vm.icon_path)
-                    if verbose:
-                        print >> sys.stderr, "--> Creating icon symlink: {0} -> {1}".format(self.icon_path, icon_path)
-                    os.symlink (icon_path, self.icon_path)
-                else:
-                    if verbose:
-                        print >> sys.stderr, "--> Copying icon: {0} -> {1}".format(src_vm.icon_path, self.icon_path)
-                    shutil.copy(src_vm.icon_path, self.icon_path)
-
-        if src_vm.has_firewall():
-            self.write_firewall_conf(src_vm.get_firewall_conf())
-
-        # Make sure that we have UUID allocated
-        self._update_libvirt_domain()
-
-        # fire hooks
-        for hook in self.hooks_clone_disk_files:
-            hook(self, src_vm, verbose)
-
-    def verify_files(self):
-        if dry_run:
-            return
-
-        self.storage.verify_files()
-
-        if not os.path.exists (os.path.join(self.kernels_dir, 'vmlinuz')):
-            raise QubesException (
-                "VM kernel does not exist: {0}".\
-                format(os.path.join(self.kernels_dir, 'vmlinuz')))
-
-        if not os.path.exists (os.path.join(self.kernels_dir, 'initramfs')):
-            raise QubesException (
-                "VM initramfs does not exist: {0}".\
-                format(os.path.join(self.kernels_dir, 'initramfs')))
-
-        # fire hooks
-        for hook in self.hooks_verify_files:
-            hook(self)
-
-        return True
-
-    def remove_from_disk(self):
-        self.log.debug('remove_from_disk()')
-        if dry_run:
-            return
-
-        # fire hooks
-        for hook in self.hooks_remove_from_disk:
-            hook(self)
-
-        try:
-            self.libvirt_domain.undefine()
-        except libvirt.libvirtError as e:
-            if e.get_error_code() == libvirt.VIR_ERR_NO_DOMAIN:
-                # already undefined
-                pass
-            else:
-                print >>sys.stderr, "libvirt error code: {!r}".format(
-                    e.get_error_code())
-                raise
-
-        if os.path.exists("/etc/systemd/system/multi-user.target.wants/qubes-vm@" + self.name + ".service"):
-            retcode = subprocess.call(["sudo", "systemctl", "-q", "disable",
-                "qubes-vm@" + self.name + ".service"])
-            if retcode != 0:
-                raise QubesException("Failed to delete autostart entry for VM")
-
-        self.storage.remove_from_disk()
-
-    def write_firewall_conf(self, conf):
-        defaults = self.get_firewall_conf()
-        expiring_rules_present = False
-        for item in defaults.keys():
-            if item not in conf:
-                conf[item] = defaults[item]
-
-        root = lxml.etree.Element(
-                "QubesFirewallRules",
-                policy = "allow" if conf["allow"] else "deny",
-                dns = "allow" if conf["allowDns"] else "deny",
-                icmp = "allow" if conf["allowIcmp"] else "deny",
-                yumProxy = "allow" if conf["allowYumProxy"] else "deny"
-        )
-
-        for rule in conf["rules"]:
-            # For backward compatibility
-            if "proto" not in rule:
-                if rule["portBegin"] is not None and rule["portBegin"] > 0:
-                    rule["proto"] = "tcp"
-                else:
-                    rule["proto"] = "any"
-            element = lxml.etree.Element(
-                    "rule",
-                    address=rule["address"],
-                    proto=str(rule["proto"]),
-            )
-            if rule["netmask"] is not None and rule["netmask"] != 32:
-                element.set("netmask", str(rule["netmask"]))
-            if rule.get("portBegin", None) is not None and \
-                            rule["portBegin"] > 0:
-                element.set("port", str(rule["portBegin"]))
-            if rule.get("portEnd", None) is not None and rule["portEnd"] > 0:
-                element.set("toport", str(rule["portEnd"]))
-            if "expire" in rule:
-                element.set("expire", str(rule["expire"]))
-                expiring_rules_present = True
-
-            root.append(element)
-
-        tree = lxml.etree.ElementTree(root)
-
-        try:
-            old_umask = os.umask(002)
-            with open(self.firewall_conf, 'w') as f:
-                tree.write(f, encoding="UTF-8", pretty_print=True)
-            f.close()
-            os.umask(old_umask)
-        except EnvironmentError as err:
-            print >> sys.stderr, "{0}: save error: {1}".format(
-                    os.path.basename(sys.argv[0]), err)
-            return False
-
-        # Automatically enable/disable 'yum-proxy-setup' service based on allowYumProxy
-        if conf['allowYumProxy']:
-            self.services['yum-proxy-setup'] = True
-        else:
-            if self.services.has_key('yum-proxy-setup'):
-                self.services.pop('yum-proxy-setup')
-
-        if expiring_rules_present:
-            subprocess.call(["sudo", "systemctl", "start",
-                             "qubes-reload-firewall@%s.timer" % self.name])
-
-        return True
-
-    def has_firewall(self):
-        return os.path.exists (self.firewall_conf)
-
-    def get_firewall_defaults(self):
-        return { "rules": list(), "allow": True, "allowDns": True, "allowIcmp": True, "allowYumProxy": False }
-
-    def get_firewall_conf(self):
-        conf = self.get_firewall_defaults()
-
-        try:
-            tree = lxml.etree.parse(self.firewall_conf)
-            root = tree.getroot()
-
-            conf["allow"] = (root.get("policy") == "allow")
-            conf["allowDns"] = (root.get("dns") == "allow")
-            conf["allowIcmp"] = (root.get("icmp") == "allow")
-            conf["allowYumProxy"] = (root.get("yumProxy") == "allow")
-
-            for element in root:
-                rule = {}
-                attr_list = ("address", "netmask", "proto", "port", "toport",
-                             "expire")
-
-                for attribute in attr_list:
-                    rule[attribute] = element.get(attribute)
-
-                if rule["netmask"] is not None:
-                    rule["netmask"] = int(rule["netmask"])
-                else:
-                    rule["netmask"] = 32
-
-                if rule["port"] is not None:
-                    rule["portBegin"] = int(rule["port"])
-                else:
-                    # backward compatibility
-                    rule["portBegin"] = 0
-
-                # For backward compatibility
-                if rule["proto"] is None:
-                    if rule["portBegin"] > 0:
-                        rule["proto"] = "tcp"
-                    else:
-                        rule["proto"] = "any"
-
-                if rule["toport"] is not None:
-                    rule["portEnd"] = int(rule["toport"])
-                else:
-                    rule["portEnd"] = None
-
-                if rule["expire"] is not None:
-                    rule["expire"] = int(rule["expire"])
-                    if rule["expire"] <= int(datetime.datetime.now().strftime(
-                            "%s")):
-                        continue
-                else:
-                    del(rule["expire"])
-
-                del(rule["port"])
-                del(rule["toport"])
-
-                conf["rules"].append(rule)
-
-        except EnvironmentError as err:
-            return conf
-        except (xml.parsers.expat.ExpatError,
-                ValueError, LookupError) as err:
-            print("{0}: load error: {1}".format(
-                os.path.basename(sys.argv[0]), err))
-            return None
-
-        return conf
-
-    def pci_add(self, pci):
-        self.log.debug('pci_add(pci={!r})'.format(pci))
-        if not os.path.exists('/sys/bus/pci/devices/0000:%s' % pci):
-            raise QubesException("Invalid PCI device: %s" % pci)
-        if self.pcidevs.count(pci):
-            # already added
-            return
-        self.pcidevs.append(pci)
-        if self.is_running():
-            try:
-                subprocess.check_call(['sudo', system_path["qubes_pciback_cmd"], pci])
-                subprocess.check_call(['sudo', 'xl', 'pci-attach', str(self.xid), pci])
-            except Exception as e:
-                print >>sys.stderr, "Failed to attach PCI device on the fly " \
-                    "(%s), changes will be seen after VM restart" % str(e)
-
-    def pci_remove(self, pci):
-        self.log.debug('pci_remove(pci={!r})'.format(pci))
-        if not self.pcidevs.count(pci):
-            # not attached
-            return
-        self.pcidevs.remove(pci)
-        if self.is_running():
-            p = subprocess.Popen(['xl', 'pci-list', str(self.xid)],
-                    stdout=subprocess.PIPE)
-            result = p.communicate()
-            m = re.search(r"^(\d+.\d+)\s+0000:%s$" % pci, result[0], flags=re.MULTILINE)
-            if not m:
-                print >>sys.stderr, "Device %s already detached" % pci
-                return
-            vmdev = m.group(1)
-            try:
-                self.run_service("qubes.DetachPciDevice",
-                                 user="root", input="00:%s" % vmdev)
-                subprocess.check_call(['sudo', 'xl', 'pci-detach', str(self.xid), pci])
-            except Exception as e:
-                print >>sys.stderr, "Failed to detach PCI device on the fly " \
-                    "(%s), changes will be seen after VM restart" % str(e)
-
-    def run(self, command, user = None, verbose = True, autostart = False,
-            notify_function = None,
-            passio = False, passio_popen = False, passio_stderr=False,
-            ignore_stderr=False, localcmd = None, wait = False, gui = True,
-            filter_esc = False):
-        """command should be in form 'cmdline'
-            When passio_popen=True, popen object with stdout connected to pipe.
-            When additionally passio_stderr=True, stderr also is connected to pipe.
-            When ignore_stderr=True, stderr is connected to /dev/null.
-            """
-
-        self.log.debug(
-            'run(command={!r}, user={!r}, passio={!r}, wait={!r})'.format(
-                command, user, passio, wait))
-
-        if user is None:
-            user = self.default_user
-        null = None
-        if not self.is_running() and not self.is_paused():
-            if not autostart:
-                raise QubesException("VM not running")
-
-            try:
-                if notify_function is not None:
-                    notify_function ("info", "Starting the '{0}' VM...".format(self.name))
-                elif verbose:
-                    print >> sys.stderr, "Starting the VM '{0}'...".format(self.name)
-                self.start(verbose=verbose, start_guid = gui, notify_function=notify_function)
-
-            except (IOError, OSError, QubesException) as err:
-                raise QubesException("Error while starting the '{0}' VM: {1}".format(self.name, err))
-            except (MemoryError) as err:
-                raise QubesException("Not enough memory to start '{0}' VM! "
-                                     "Close one or more running VMs and try "
-                                     "again.".format(self.name))
-
-        if self.is_paused():
-            raise QubesException("VM is paused")
-        if not self.is_qrexec_running():
-            raise QubesException(
-                "Domain '{}': qrexec not connected.".format(self.name))
-
-        if gui and os.getenv("DISPLAY") is not None and not self.is_guid_running():
-            self.start_guid(verbose = verbose, notify_function = notify_function)
-
-        args = [system_path["qrexec_client_path"], "-d", str(self.name), "%s:%s" % (user, command)]
-        if localcmd is not None:
-            args += [ "-l", localcmd]
-        if filter_esc:
-            args += ["-t"]
-        if os.isatty(sys.stderr.fileno()):
-            args += ["-T"]
-
-        call_kwargs = {}
-        if ignore_stderr or not passio:
-            null = open("/dev/null", "w+")
-            call_kwargs['stderr'] = null
-        if not passio:
-            call_kwargs['stdin'] = null
-            call_kwargs['stdout'] = null
-
-        if passio_popen:
-            popen_kwargs={'stdout': subprocess.PIPE}
-            popen_kwargs['stdin'] = subprocess.PIPE
-            if passio_stderr:
-                popen_kwargs['stderr'] = subprocess.PIPE
-            else:
-                popen_kwargs['stderr'] = call_kwargs.get('stderr', None)
-            p = subprocess.Popen (args, **popen_kwargs)
-            if null:
-                null.close()
-            return p
-        if not wait and not passio:
-            args += ["-e"]
-        retcode = subprocess.call(args, **call_kwargs)
-        if null:
-            null.close()
-        return retcode
-
-    def run_service(self, service, source="dom0", user=None,
-                    passio_popen=False, input=None, localcmd=None, gui=False,
-                    wait=True):
-        if bool(input) + bool(passio_popen) + bool(localcmd) > 1:
-            raise ValueError("'input', 'passio_popen', 'localcmd' cannot be "
-                             "used together")
-        if not wait and (localcmd or input):
-            raise ValueError("Cannot use wait=False with input or "
-                             "localcmd specified")
-        if localcmd:
-            return self.run("QUBESRPC %s %s" % (service, source),
-                            localcmd=localcmd, user=user, wait=wait, gui=gui)
-        elif input:
-            p = self.run("QUBESRPC %s %s" % (service, source),
-                user=user, wait=wait, gui=gui, passio_popen=True,
-                passio_stderr=True)
-            p.communicate(input)
-            return p.returncode
-        else:
-            return self.run("QUBESRPC %s %s" % (service, source),
-                            passio_popen=passio_popen, user=user, wait=wait,
-                            gui=gui, passio_stderr=passio_popen)
-
-    def attach_network(self, verbose = False, wait = True, netvm = None):
-        self.log.debug('attach_network(netvm={!r})'.format(netvm))
-        if dry_run:
-            return
-
-        if not self.is_running():
-            raise QubesException ("VM not running!")
-
-        if netvm is None:
-            netvm = self.netvm
-
-        if netvm is None:
-            raise QubesException ("NetVM not set!")
-
-        if netvm.qid != 0:
-            if not netvm.is_running():
-                if verbose:
-                    print >> sys.stderr, "--> Starting NetVM {0}...".format(netvm.name)
-                netvm.start()
-
-        self.libvirt_domain.attachDevice(
-                self._format_net_dev(self.ip, self.mac, self.netvm.name))
-
-    def detach_network(self, verbose = False, netvm = None):
-        self.log.debug('detach_network(netvm={!r})'.format(netvm))
-        if dry_run:
-            return
-
-        if not self.is_running():
-            raise QubesException ("VM not running!")
-
-        if netvm is None:
-            netvm = self.netvm
-
-        if netvm is None:
-            raise QubesException ("NetVM not set!")
-
-        self.libvirt_domain.detachDevice( self._format_net_dev(self.ip,
-            self.mac, self.netvm.name))
-
-    def wait_for_session(self, notify_function = None):
-        self.log.debug('wait_for_session()')
-        #self.run('echo $$ >> /tmp/qubes-session-waiter; [ ! -f /tmp/qubes-session-env ] && exec sleep 365d', ignore_stderr=True, gui=False, wait=True)
-
-        # Note : User root is redefined to SYSTEM in the Windows agent code
-        p = self.run('QUBESRPC qubes.WaitForSession none', user="root", passio_popen=True, gui=False, wait=True)
-        p.communicate(input=self.default_user)
-
-    def start_guid(self, verbose = True, notify_function = None,
-            extra_guid_args=None, before_qrexec=False):
-        self.log.debug(
-            'start_guid(extra_guid_args={!r}, before_qrexec={!r})'.format(
-                extra_guid_args, before_qrexec))
-        if before_qrexec:
-            # On PV start GUId only after qrexec-daemon
-            return
-
-        if verbose:
-            print >> sys.stderr, "--> Starting Qubes GUId..."
-
-        guid_cmd = []
-        if os.getuid() == 0:
-            # try to always have guid running as normal user, otherwise
-            # clipboard file may be created as root and other permission
-            # problems
-            qubes_group = grp.getgrnam('qubes')
-            guid_cmd = ['runuser', '-u', qubes_group.gr_mem[0], '--']
-
-        guid_cmd += [system_path["qubes_guid_path"],
-            "-d", str(self.xid), "-N", self.name,
-            "-c", self.label.color,
-            "-i", self.label.icon_path,
-            "-l", str(self.label.index)]
-        if extra_guid_args is not None:
-            guid_cmd += extra_guid_args
-        if self.debug:
-            guid_cmd += ['-v', '-v']
-        elif not verbose:
-            guid_cmd += ['-q']
-        # Avoid using environment variables for checking the current session,
-        #  because this script may be called with cleared env (like with sudo).
-        if subprocess.check_output(
-                ['xprop', '-root', '-notype', 'KWIN_RUNNING']) == \
-                'KWIN_RUNNING = 0x1\n':
-            # native decoration plugins is used, so adjust window properties
-            # accordingly
-            guid_cmd += ['-T']  # prefix window titles with VM name
-            # get owner of X11 session
-            session_owner = None
-            for line in subprocess.check_output(['xhost']).splitlines():
-                if line == 'SI:localuser:root':
-                    pass
-                elif line.startswith('SI:localuser:'):
-                    session_owner = line.split(":")[2]
-            if session_owner is not None:
-                data_dir = os.path.expanduser(
-                    '~{}/.local/share'.format(session_owner))
-            else:
-                # fallback to current user
-                data_dir = os.path.expanduser('~/.local/share')
-
-            guid_cmd += ['-p',
-                '_KDE_NET_WM_COLOR_SCHEME=s:{}'.format(
-                    os.path.join(data_dir,
-                        'qubes-kde', self.label.name + '.colors'))]
-
-        retcode = subprocess.call (guid_cmd)
-        if (retcode != 0) :
-            raise QubesException("Cannot start qubes-guid!")
-
-        if not self.is_qrexec_running():
-            return
-
-        try:
-            import qubes.monitorlayoutnotify
-            if verbose:
-                print >> sys.stderr, "--> Sending monitor layout..."
-            monitor_layout = qubes.monitorlayoutnotify.get_monitor_layout()
-            # Notify VM only if we've got a monitor_layout which is not empty
-            # or else we break proper VM resolution set by gui-agent
-            if len(monitor_layout) > 0:
-                qubes.monitorlayoutnotify.notify_vm(self, monitor_layout)
-        except ImportError as e:
-            print >>sys.stderr, "ERROR: %s" % e
-
-        if verbose:
-            print >> sys.stderr, "--> Waiting for qubes-session..."
-
-        self.wait_for_session(notify_function)
-
-    def start_qrexec_daemon(self, verbose = False, notify_function = None):
-        self.log.debug('start_qrexec_daemon()')
-        if verbose:
-            print >> sys.stderr, "--> Starting the qrexec daemon..."
-        qrexec = []
-        if os.getuid() == 0:
-            # try to always have qrexec running as normal user, otherwise
-            # many qrexec services would need to deal with root/user
-            # permission problems
-            qubes_group = grp.getgrnam('qubes')
-            qrexec = ['runuser', '-u', qubes_group.gr_mem[0], '--']
-
-        qrexec += ['env', 'QREXEC_STARTUP_TIMEOUT=' + str(self.qrexec_timeout),
-            system_path["qrexec_daemon_path"]]
-
-        qrexec_args = [str(self.xid), self.name, self.default_user]
-        if not verbose:
-            qrexec_args.insert(0, "-q")
-        retcode = subprocess.call(qrexec + qrexec_args)
-        if (retcode != 0) :
-            raise OSError ("Cannot execute qrexec-daemon!")
-
-    def start_qubesdb(self):
-        self.log.debug('start_qubesdb()')
-        pidfile = '/var/run/qubes/qubesdb.{}.pid'.format(self.name)
-        try:
-            if os.path.exists(pidfile):
-                old_qubesdb_pid = open(pidfile, 'r').read()
-                try:
-                    os.kill(int(old_qubesdb_pid), signal.SIGTERM)
-                except OSError:
-                    raise QubesException(
-                        "Failed to kill old QubesDB instance (PID {}). "
-                        "Terminate it manually and retry. "
-                        "If that isn't QubesDB process, "
-                        "remove the pidfile: {}".format(old_qubesdb_pid,
-                                                        pidfile))
-                timeout = 25
-                while os.path.exists(pidfile) and timeout:
-                    time.sleep(0.2)
-                    timeout -= 1
-        except IOError:  # ENOENT (pidfile)
-            pass
-
-        # force connection to a new daemon
-        self._qdb_connection = None
-
-        qubesdb_cmd = []
-        if os.getuid() == 0:
-            # try to always have qubesdb running as normal user, otherwise
-            # killing it at VM restart (see above) will always fail
-            qubes_group = grp.getgrnam('qubes')
-            qubesdb_cmd = ['runuser', '-u', qubes_group.gr_mem[0], '--']
-
-        qubesdb_cmd += [
-            system_path["qubesdb_daemon_path"],
-            str(self.xid),
-            self.name]
-
-        retcode = subprocess.call (qubesdb_cmd)
-        if retcode != 0:
-            raise OSError("ERROR: Cannot execute qubesdb-daemon!")
-
-    def request_memory(self, mem_required = None):
-        # Overhead of per-VM/per-vcpu Xen structures, taken from OpenStack nova/virt/xenapi/driver.py
-        # see https://wiki.openstack.org/wiki/XenServer/Overhead
-        # add an extra MB because Nova rounds up to MBs
-        MEM_OVERHEAD_BASE = (3 + 1) * 1024 * 1024
-        MEM_OVERHEAD_PER_VCPU = 3 * 1024 * 1024 / 2
-        if mem_required is None:
-            mem_required = int(self.memory) * 1024 * 1024
-        if qmemman_present:
-            qmemman_client = QMemmanClient()
-            try:
-                mem_required_with_overhead = mem_required + MEM_OVERHEAD_BASE + self.vcpus * MEM_OVERHEAD_PER_VCPU
-                got_memory = qmemman_client.request_memory(mem_required_with_overhead)
-            except IOError as e:
-                raise IOError("ERROR: Failed to connect to qmemman: %s" % str(e))
-            if not got_memory:
-                qmemman_client.close()
-                raise MemoryError ("ERROR: insufficient memory to start VM '%s'" % self.name)
-            return qmemman_client
-
-    def start(self, verbose = False, preparing_dvm = False, start_guid = True,
-            notify_function = None, mem_required = None):
-        self.log.debug('start('
-            'preparing_dvm={!r}, start_guid={!r}, mem_required={!r})'.format(
-                preparing_dvm, start_guid, mem_required))
-        if dry_run:
-            return
-
-        # Intentionally not used is_running(): eliminate also "Paused", "Crashed", "Halting"
-        if self.get_power_state() != "Halted":
-            raise QubesException ("VM is already running!")
-
-        self.verify_files()
-
-        if self.netvm is not None:
-            if self.netvm.qid != 0:
-                if not self.netvm.is_running():
-                    if verbose:
-                        print >> sys.stderr, "--> Starting NetVM {0}...".format(self.netvm.name)
-                    self.netvm.start(verbose = verbose, start_guid = start_guid, notify_function = notify_function)
-
-        self.storage.prepare_for_vm_startup(verbose=verbose)
-        if verbose:
-            print >> sys.stderr, "--> Loading the VM (type = {0})...".format(self.type)
-
-        self._update_libvirt_domain()
-
-        qmemman_client = self.request_memory(mem_required)
-
-        # Bind pci devices to pciback driver
-        for pci in self.pcidevs:
-            try:
-                nd = vmm.libvirt_conn.nodeDeviceLookupByName('pci_0000_' + pci.replace(':','_').replace('.','_'))
-            except libvirt.libvirtError as e:
-                if e.get_error_code() == libvirt.VIR_ERR_NO_NODE_DEVICE:
-                    raise QubesException(
-                        "PCI device {} does not exist (domain {})".
-                        format(pci, self.name))
-                else:
-                    raise
-            try:
-                nd.dettach()
-            except libvirt.libvirtError as e:
-                if e.get_error_code() == libvirt.VIR_ERR_INTERNAL_ERROR:
-                    # already detached
-                    pass
-                else:
-                    raise
-
-        self.libvirt_domain.createWithFlags(libvirt.VIR_DOMAIN_START_PAUSED)
-
-        try:
-            if verbose:
-                print >> sys.stderr, "--> Starting Qubes DB..."
-            self.start_qubesdb()
-
-            xid = self.xid
-            self.log.debug('xid={}'.format(xid))
-
-            if preparing_dvm:
-                self.services['qubes-dvm'] = True
-            if verbose:
-                print >> sys.stderr, "--> Setting Qubes DB info for the VM..."
-            self.create_qubesdb_entries()
-
-            if verbose:
-                print >> sys.stderr, "--> Updating firewall rules..."
-            netvm = self.netvm
-            while netvm is not None:
-                if netvm.is_proxyvm() and netvm.is_running():
-                    netvm.write_iptables_qubesdb_entry()
-                netvm = netvm.netvm
-
-            # fire hooks
-            for hook in self.hooks_start:
-                hook(self, verbose = verbose, preparing_dvm =  preparing_dvm,
-                     start_guid = start_guid, notify_function = notify_function)
-        except:
-            self.force_shutdown()
-            raise
-
-        if verbose:
-            print >> sys.stderr, "--> Starting the VM..."
-        self.libvirt_domain.resume()
-
-# close() is not really needed, because the descriptor is close-on-exec
-# anyway, the reason to postpone close() is that possibly xl is not done
-# constructing the domain after its main process exits
-# so we close() when we know the domain is up
-# the successful unpause is some indicator of it
-        if qmemman_present:
-            qmemman_client.close()
-
-        extra_guid_args = []
-        if preparing_dvm:
-            # Run GUI daemon in "invisible" mode, so applications started by
-            # prerun script will not disturb the user
-            extra_guid_args = ['-I']
-        elif not os.path.exists('/var/run/qubes/shm.id') \
-                and not os.path.exists('/var/run/shm.id'):
-            # Start GUI daemon only when shmoverride is loaded; unless
-            # preparing DispVM, where it isn't needed because of "invisible"
-            # mode
-            start_guid = False
-        if start_guid and 'DISPLAY' not in os.environ:
-            if verbose:
-                print >> sys.stderr, \
-                    "WARNING: not starting GUI, because DISPLAY not set"
-            start_guid = False
-
-        if start_guid:
-            self.start_guid(verbose=verbose, notify_function=notify_function,
-                            before_qrexec=True, extra_guid_args=extra_guid_args)
-
-        if not preparing_dvm:
-            self.start_qrexec_daemon(verbose=verbose,notify_function=notify_function)
-
-        if start_guid:
-            self.start_guid(verbose=verbose, notify_function=notify_function,
-                            extra_guid_args=extra_guid_args)
-
-        return xid
-
-    def _cleanup_zombie_domains(self):
-        """
-        This function is workaround broken libxl (which leaves not fully
-        created domain on failure) and vchan on domain crash behaviour
-        @return: None
-        """
-        xc = self.get_xc_dominfo()
-        if xc and xc['dying'] == 1:
-            # GUID still running?
-            guid_pidfile = '/var/run/qubes/guid-running.%d' % xc['domid']
-            if os.path.exists(guid_pidfile):
-                guid_pid = open(guid_pidfile).read().strip()
-                os.kill(int(guid_pid), 15)
-            # qrexec still running?
-            if self.is_qrexec_running():
-                #TODO: kill qrexec daemon
-                pass
-
-    def shutdown(self, force=False, xid = None):
-        self.log.debug('shutdown()')
-        if dry_run:
-            return
-
-        if not self.is_running():
-            raise QubesException ("VM already stopped!")
-
-        self.libvirt_domain.shutdown()
-
-    def force_shutdown(self, xid = None):
-        self.log.debug('force_shutdown()')
-        if dry_run:
-            return
-
-        if not self.is_running() and not self.is_paused():
-            raise QubesException ("VM already stopped!")
-
-        self.libvirt_domain.destroy()
-        self.refresh()
-
-    def suspend(self):
-        self.log.debug('suspend()')
-        if dry_run:
-            return
-
-        if not self.is_running() and not self.is_paused() or \
-                self.get_power_state() == "Suspended":
-            raise QubesException ("VM not running!")
-
-        if len (self.pcidevs) > 0:
-            self.libvirt_domain.pMSuspendForDuration(
-                libvirt.VIR_NODE_SUSPEND_TARGET_MEM, 0, 0)
-        else:
-            self.pause()
-
-    def resume(self):
-        self.log.debug('resume()')
-        if dry_run:
-            return
-
-        if self.get_power_state() == "Suspended":
-            self.libvirt_domain.pMWakeup()
-        else:
-            self.unpause()
-
-    def pause(self):
-        self.log.debug('pause()')
-        if dry_run:
-            return
-
-        if not self.is_running():
-            raise QubesException ("VM not running!")
-
-        self.libvirt_domain.suspend()
-
-    def unpause(self):
-        self.log.debug('unpause()')
-        if dry_run:
-            return
-
-        if not self.is_paused():
-            raise QubesException ("VM not paused!")
-
-        self.libvirt_domain.resume()
-
-    def get_xml_attrs(self):
-        attrs = {}
-        attrs_config = self.get_attrs_config()
-        for attr in attrs_config:
-            attr_config = attrs_config[attr]
-            if 'save' in attr_config:
-                if 'save_skip' in attr_config:
-                    if callable(attr_config['save_skip']):
-                        if attr_config['save_skip']():
-                            continue
-                    elif eval(attr_config['save_skip']):
-                        continue
-                if callable(attr_config['save']):
-                    value = attr_config['save']()
-                else:
-                    value = eval(attr_config['save'])
-                if 'save_attr' in attr_config:
-                    attrs[attr_config['save_attr']] = value
-                else:
-                    attrs[attr] = value
-        return attrs
-
-    def create_xml_element(self):
-
-        attrs = self.get_xml_attrs()
-        element = lxml.etree.Element(
-            # Compatibility hack (Qubes*VM in type vs Qubes*Vm in XML)...
-            "Qubes" + self.type.replace("VM", "Vm"),
-            **attrs)
-        return element
-
-register_qubes_vm_class(QubesVm)

+ 0 - 77
core-modules/001QubesResizableVm.py

@@ -1,77 +0,0 @@
-#!/usr/bin/python2
-# -*- encoding: utf8 -*-
-#
-# The Qubes OS Project, http://www.qubes-os.org
-#
-# 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 __future__ import (
-    absolute_import,
-    division,
-    print_function,
-    unicode_literals,
-)
-
-from qubes.qubes import (
-    register_qubes_vm_class,
-    QubesException,
-    QubesVm,
-)
-from time import sleep
-
-
-class QubesResizableVm(QubesVm):
-
-    def resize_root_img(self, size, allow_start=False):
-        if self.template:
-            raise QubesException("Cannot resize root.img of template-based VM"
-                                 ". Resize the root.img of the template "
-                                 "instead.")
-
-        if self.is_running():
-            raise QubesException("Cannot resize root.img of running VM")
-
-        if size < self.get_root_img_sz():
-            raise QubesException(
-                "For your own safety shringing of root.img is disabled. If "
-                "you really know what you are doing, use 'truncate' manually.")
-
-        f_root = open(self.root_img, "a+b")
-        f_root.truncate(size)
-        f_root.close()
-
-
-class QubesResizableVmWithResize2fs(QubesResizableVm):
-
-    def resize_root_img(self, size, allow_start=False):
-        super(QubesResizableVmWithResize2fs, self).\
-            resize_root_img(size, allow_start=allow_start)
-        if not allow_start:
-            raise QubesException("VM start required to complete the "
-                                 "operation, but not allowed. Either run the "
-                                 "operation again allowing VM start this "
-                                 "time, or run resize2fs in the VM manually.")
-        self.start(start_guid=False)
-        self.run("resize2fs /dev/mapper/dmroot", user="root", wait=True,
-                 gui=False)
-        self.shutdown()
-        while self.is_running():
-            sleep(1)
-
-
-register_qubes_vm_class(QubesResizableVm)
-register_qubes_vm_class(QubesResizableVmWithResize2fs)

+ 0 - 54
core-modules/01QubesAppVm.py

@@ -1,54 +0,0 @@
-#!/usr/bin/python2
-# -*- coding: utf-8 -*-
-#
-# The Qubes OS Project, http://www.qubes-os.org
-#
-# Copyright (C) 2010  Joanna Rutkowska <joanna@invisiblethingslab.com>
-# Copyright (C) 2013  Marek Marczykowski <marmarek@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.
-#
-#
-
-import os.path
-
-from qubes.qubes import (
-    register_qubes_vm_class,
-    system_path,
-    QubesResizableVmWithResize2fs,
-    QubesVmLabel,
-)
-
-
-class QubesAppVm(QubesResizableVmWithResize2fs):
-    """
-    A class that represents an AppVM. A child of QubesVm.
-    """
-    def get_attrs_config(self):
-        attrs_config = super(QubesAppVm, self).get_attrs_config()
-        attrs_config['dir_path']['func'] = \
-            lambda value: value if value is not None else \
-                os.path.join(system_path["qubes_appvms_dir"], self.name)
-
-        return attrs_config
-
-    @property
-    def type(self):
-        return "AppVM"
-
-    def is_appvm(self):
-        return True
-
-register_qubes_vm_class(QubesAppVm)

+ 0 - 248
core-modules/01QubesDisposableVm.py

@@ -1,248 +0,0 @@
-#!/usr/bin/python2
-# -*- coding: utf-8 -*-
-#
-# The Qubes OS Project, http://www.qubes-os.org
-#
-# Copyright (C) 2010  Joanna Rutkowska <joanna@invisiblethingslab.com>
-# Copyright (C) 2013  Marek Marczykowski <marmarek@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.
-#
-#
-
-import os
-import sys
-import libvirt
-import time
-from qubes.qubes import QubesVm,QubesVmLabel,register_qubes_vm_class, \
-    QubesException
-from qubes.qubes import QubesDispVmLabels
-from qubes.qubes import dry_run,vmm
-import grp
-
-qmemman_present = False
-try:
-    from qubes.qmemman_client import QMemmanClient
-    qmemman_present = True
-except ImportError:
-    pass
-
-DISPID_STATE_FILE = '/var/run/qubes/dispid'
-GUID_SHMID_FILE = ['/var/run/qubes/shm.id', '/var/run/shm.id']
-
-class QubesDisposableVm(QubesVm):
-    """
-    A class that represents an DisposableVM. A child of QubesVm.
-    """
-
-    # In which order load this VM type from qubes.xml
-    load_order = 120
-
-
-    def _assign_new_dispid(self):
-        # This method in called while lock on qubes.xml is held, so no need for
-        # additional lock
-        if os.path.exists(DISPID_STATE_FILE):
-            f = open(DISPID_STATE_FILE, 'r+')
-            dispid = int(f.read())
-            f.seek(0)
-            f.truncate(0)
-            f.write(str(dispid+1))
-            f.close()
-        else:
-            dispid = 1
-            f = open(DISPID_STATE_FILE, 'w')
-            f.write(str(dispid+1))
-            f.close()
-            os.chown(DISPID_STATE_FILE, -1, grp.getgrnam('qubes').gr_gid)
-            os.chmod(DISPID_STATE_FILE, 0664)
-        return dispid
-
-    def get_attrs_config(self):
-        attrs_config = super(QubesDisposableVm, self).get_attrs_config()
-
-        attrs_config['name']['func'] = \
-            lambda x: "disp%d" % self.dispid if x is None else x
-
-        # New attributes
-        attrs_config['dispid'] = {
-            'func': lambda x: (self._assign_new_dispid() if x is None
-                               else int(x)),
-            'save': lambda: str(self.dispid),
-            # needs to be set before name
-            'order': 0
-        }
-        attrs_config['include_in_backups']['func'] = lambda x: False
-        attrs_config['disp_savefile'] = {
-                'default': '/var/run/qubes/current-savefile',
-                'save': lambda: str(self.disp_savefile) }
-
-        return attrs_config
-
-    def __init__(self, **kwargs):
-
-        disp_template = None
-        if 'disp_template' in kwargs.keys():
-            disp_template = kwargs['disp_template']
-            kwargs['template'] = disp_template.template
-            kwargs['dir_path'] = disp_template.dir_path
-            kwargs['kernel'] = disp_template.kernel
-            kwargs['uses_default_kernel'] = disp_template.uses_default_kernel
-            kwargs['kernelopts'] = disp_template.kernelopts
-            kwargs['uses_default_kernelopts'] = \
-                disp_template.uses_default_kernelopts
-        super(QubesDisposableVm, self).__init__(**kwargs)
-
-        assert self.template is not None, "Missing template for DisposableVM!"
-
-        if disp_template:
-            self.clone_attrs(disp_template)
-
-        # Use DispVM icon with the same color
-        if self._label:
-            self._label = QubesDispVmLabels[self._label.name]
-            self.icon_path = self._label.icon_path
-
-    @property
-    def type(self):
-        return "DisposableVM"
-
-    def is_disposablevm(self):
-        return True
-
-    @property
-    def ip(self):
-        if self.netvm is not None:
-            return self.netvm.get_ip_for_dispvm(self.dispid)
-        else:
-            return None
-
-    def get_clone_attrs(self):
-        attrs = super(QubesDisposableVm, self).get_clone_attrs()
-        attrs.remove('_label')
-        return attrs
-
-    def do_not_use_get_xml_attrs(self):
-        # Minimal set - do not inherit rest of attributes
-        attrs = {}
-        attrs["qid"] = str(self.qid)
-        attrs["name"] = self.name
-        attrs["dispid"] = str(self.dispid)
-        attrs["template_qid"] = str(self.template.qid)
-        attrs["label"] = self.label.name
-        attrs["firewall_conf"] = self.relative_path(self.firewall_conf)
-        attrs["netvm_qid"] = str(self.netvm.qid) if self.netvm is not None else "none"
-        return attrs
-
-    def verify_files(self):
-        return True
-
-    def get_config_params(self):
-        attrs = super(QubesDisposableVm, self).get_config_params()
-        attrs['privatedev'] = ''
-        return attrs
-
-    def create_qubesdb_entries(self):
-        super(QubesDisposableVm, self).create_qubesdb_entries()
-
-        self.qdb.write("/qubes-vm-persistence", "none")
-        self.qdb.write('/qubes-restore-complete', '1')
-
-    def start(self, verbose = False, **kwargs):
-        self.log.debug('start()')
-        if dry_run:
-            return
-
-        # Intentionally not used is_running(): eliminate also "Paused", "Crashed", "Halting"
-        if self.get_power_state() != "Halted":
-            raise QubesException ("VM is already running!")
-
-        if self.netvm is not None:
-            if self.netvm.qid != 0:
-                if not self.netvm.is_running():
-                    if verbose:
-                        print >> sys.stderr, "--> Starting NetVM {0}...".\
-                            format(self.netvm.name)
-                    self.netvm.start(verbose=verbose, **kwargs)
-
-        if verbose:
-            print >> sys.stderr, "--> Loading the VM (type = {0})...".format(self.type)
-
-        print >>sys.stderr, "time=%s, creating config file" % (str(time.time()))
-        # refresh config file
-        domain_config = self.create_config_file()
-
-        qmemman_client = self.request_memory()
-
-        # dispvm cannot have PCI devices
-        assert (len(self.pcidevs) == 0), "DispVM cannot have PCI devices"
-
-        print >>sys.stderr, "time=%s, calling restore" % (str(time.time()))
-        vmm.libvirt_conn.restoreFlags(self.disp_savefile,
-                domain_config, libvirt.VIR_DOMAIN_SAVE_PAUSED)
-
-        print >>sys.stderr, "time=%s, done" % (str(time.time()))
-        self._libvirt_domain = None
-
-        if verbose:
-            print >> sys.stderr, "--> Starting Qubes DB..."
-        self.start_qubesdb()
-
-        self.services['qubes-dvm'] = True
-        if verbose:
-            print >> sys.stderr, "--> Setting Qubes DB info for the VM..."
-        self.create_qubesdb_entries()
-        print >>sys.stderr, "time=%s, done qubesdb" % (str(time.time()))
-
-        # fire hooks
-        for hook in self.hooks_start:
-            hook(self, verbose = verbose, **kwargs)
-
-        if verbose:
-            print >> sys.stderr, "--> Starting the VM..."
-        self.libvirt_domain.resume()
-        print >>sys.stderr, "time=%s, resumed" % (str(time.time()))
-
-# close() is not really needed, because the descriptor is close-on-exec
-# anyway, the reason to postpone close() is that possibly xl is not done
-# constructing the domain after its main process exits
-# so we close() when we know the domain is up
-# the successful unpause is some indicator of it
-        if qmemman_present:
-            qmemman_client.close()
-
-        if kwargs.get('start_guid', True) and \
-                any(os.path.exists(x) for x in GUID_SHMID_FILE):
-            self.start_guid(verbose=verbose, before_qrexec=True,
-                    notify_function=kwargs.get('notify_function', None))
-
-        self.start_qrexec_daemon(verbose=verbose,
-                notify_function=kwargs.get('notify_function', None))
-        print >>sys.stderr, "time=%s, qrexec done" % (str(time.time()))
-
-        if kwargs.get('start_guid', True) and \
-                any(os.path.exists(x) for x in GUID_SHMID_FILE):
-            self.start_guid(verbose=verbose,
-                    notify_function=kwargs.get('notify_function', None))
-        print >>sys.stderr, "time=%s, guid done" % (str(time.time()))
-
-        return self.xid
-
-    def remove_from_disk(self):
-        # nothing to remove
-        pass
-
-# register classes
-register_qubes_vm_class(QubesDisposableVm)

+ 0 - 283
core-modules/01QubesHVm.py

@@ -1,283 +0,0 @@
-#!/usr/bin/python2
-# -*- coding: utf-8 -*-
-#
-# The Qubes OS Project, http://www.qubes-os.org
-#
-# Copyright (C) 2010  Joanna Rutkowska <joanna@invisiblethingslab.com>
-# Copyright (C) 2013  Marek Marczykowski <marmarek@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.
-#
-#
-
-import os
-import os.path
-import signal
-import subprocess
-import sys
-import shutil
-from xml.etree import ElementTree
-
-from qubes.qubes import (
-    dry_run,
-    defaults,
-    register_qubes_vm_class,
-    system_path,
-    vmm,
-    QubesException,
-    QubesResizableVm,
-)
-
-
-system_path["config_template_hvm"] = '/usr/share/qubes/vm-template-hvm.xml'
-
-defaults["hvm_disk_size"] = 20*1024*1024*1024
-defaults["hvm_private_img_size"] = 2*1024*1024*1024
-defaults["hvm_memory"] = 512
-
-
-class QubesHVm(QubesResizableVm):
-    """
-    A class that represents an HVM. A child of QubesVm.
-    """
-
-    # FIXME: logically should inherit after QubesAppVm, but none of its methods
-    # are useful for HVM
-
-    def get_attrs_config(self):
-        attrs = super(QubesHVm, self).get_attrs_config()
-        attrs.pop('kernel')
-        attrs.pop('kernels_dir')
-        attrs.pop('kernelopts')
-        attrs.pop('uses_default_kernel')
-        attrs.pop('uses_default_kernelopts')
-        attrs['dir_path']['func'] = lambda value: value if value is not None \
-                else os.path.join(system_path["qubes_appvms_dir"], self.name)
-        attrs['config_file_template']['func'] = \
-            lambda x: system_path["config_template_hvm"]
-        attrs['drive'] = { 'attr': '_drive',
-                           'save': lambda: str(self.drive) }
-        # Remove this two lines when HVM will get qmemman support
-        attrs['maxmem'].pop('save')
-        attrs['maxmem']['func'] = lambda x: self.memory
-        attrs['timezone'] = { 'default': 'localtime',
-                              'save': lambda: str(self.timezone) }
-        attrs['qrexec_installed'] = { 'default': False,
-            'attr': '_qrexec_installed',
-            'save': lambda: str(self._qrexec_installed) }
-        attrs['guiagent_installed'] = { 'default' : False,
-            'attr': '_guiagent_installed',
-            'save': lambda: str(self._guiagent_installed) }
-        attrs['seamless_gui_mode'] = { 'default': False,
-                              'attr': '_seamless_gui_mode',
-                              'save': lambda: str(self._seamless_gui_mode) }
-        attrs['services']['default'] = "{'meminfo-writer': False}"
-
-        return attrs
-
-    @classmethod
-    def is_template_compatible(cls, template):
-        if template and (not template.is_template() or template.type != "TemplateHVM"):
-            return False
-        return True
-
-    def get_clone_attrs(self):
-        attrs = super(QubesHVm, self).get_clone_attrs()
-        attrs.remove('kernel')
-        attrs.remove('uses_default_kernel')
-        attrs.remove('kernelopts')
-        attrs.remove('uses_default_kernelopts')
-        attrs += [ 'timezone' ]
-        attrs += [ 'qrexec_installed' ]
-        attrs += [ 'guiagent_installed' ]
-        return attrs
-
-    @property
-    def seamless_gui_mode(self):
-        if not self.guiagent_installed:
-            return False
-        return self._seamless_gui_mode
-
-    @seamless_gui_mode.setter
-    def seamless_gui_mode(self, value):
-        if self._seamless_gui_mode == value:
-            return
-        if not self.guiagent_installed and value:
-            raise ValueError("Seamless GUI mode requires GUI agent installed")
-
-        self._seamless_gui_mode = value
-        if self.is_running():
-            self.send_gui_mode()
-
-    @property
-    def drive(self):
-        return self._drive
-
-    @drive.setter
-    def drive(self, value):
-        if value is None:
-            self._drive = None
-            return
-
-        # strip type for a moment
-        drv_type = "cdrom"
-        if value.startswith("hd:") or value.startswith("cdrom:"):
-            (drv_type, unused, value) = value.partition(":")
-            drv_type = drv_type.lower()
-
-        # sanity check
-        if drv_type not in ['hd', 'cdrom']:
-            raise QubesException("Unsupported drive type: %s" % type)
-
-        if value.count(":") == 0:
-            value = "dom0:" + value
-        if value.count(":/") == 0:
-            # FIXME: when Windows backend will be supported, improve this
-            raise QubesException("Drive path must be absolute")
-
-        self._drive = drv_type + ":" + value
-
-    def create_on_disk(self, verbose, source_template = None):
-        self.log.debug('create_on_disk(source_template={!r})'.format(
-            source_template))
-        if dry_run:
-            return
-
-        if source_template is None:
-            source_template = self.template
-
-        # create empty disk
-        self.storage.private_img_size = defaults["hvm_private_img_size"]
-        self.storage.root_img_size = defaults["hvm_disk_size"]
-        self.storage.create_on_disk(verbose, source_template)
-
-        if verbose:
-            print >> sys.stderr, "--> Creating icon symlink: {0} -> {1}".format(self.icon_path, self.label.icon_path)
-
-        try:
-            if hasattr(os, "symlink"):
-                os.symlink (self.label.icon_path, self.icon_path)
-            else:
-                shutil.copy(self.label.icon_path, self.icon_path)
-        except Exception as e:
-            print >> sys.stderr, "WARNING: Failed to set VM icon: %s" % str(e)
-
-        # Make sure that we have UUID allocated
-        self._update_libvirt_domain()
-
-        # fire hooks
-        for hook in self.hooks_create_on_disk:
-            hook(self, verbose, source_template=source_template)
-
-    def get_private_img_sz(self):
-        if not os.path.exists(self.private_img):
-            return 0
-
-        return os.path.getsize(self.private_img)
-
-    def resize_private_img(self, size):
-        assert size >= self.get_private_img_sz(), "Cannot shrink private.img"
-
-        if self.is_running():
-            raise NotImplementedError("Online resize of HVM's private.img not implemented, shutdown the VM first")
-
-        self.storage.resize_private_img(size)
-
-    def run(self, command, **kwargs):
-        if self.qrexec_installed:
-            if 'gui' in kwargs and kwargs['gui']==False:
-                command = "nogui:" + command
-            return super(QubesHVm, self).run(command, **kwargs)
-        else:
-            raise QubesException("Needs qrexec agent installed in VM to use this function. See also qvm-prefs.")
-
-    @property
-    def stubdom_xid(self):
-        if self.xid < 0:
-            return -1
-
-        if vmm.xs is None:
-            return -1
-
-        stubdom_xid_str = vmm.xs.read('', '/local/domain/%d/image/device-model-domid' % self.xid)
-        if stubdom_xid_str is not None:
-            return int(stubdom_xid_str)
-        else:
-            return -1
-
-    def validate_drive_path(self, drive):
-        drive_type, drive_domain, drive_path = drive.split(':', 2)
-        if drive_domain == 'dom0':
-            if not os.path.exists(drive_path):
-                raise QubesException("Invalid drive path '{}'".format(
-                    drive_path))
-
-    def start(self, *args, **kwargs):
-        if self.drive:
-            self.validate_drive_path(self.drive)
-        # make it available to storage.prepare_for_vm_startup, which is
-        # called before actually building VM libvirt configuration
-        self.storage.drive = self.drive
-
-        if self.template and self.template.is_running():
-            raise QubesException("Cannot start the HVM while its template is running")
-        try:
-            if 'mem_required' not in kwargs:
-                # Reserve 44MB for stubdomain
-                kwargs['mem_required'] = (self.memory + 44) * 1024 * 1024
-            return super(QubesHVm, self).start(*args, **kwargs)
-        except QubesException as e:
-            capabilities = vmm.libvirt_conn.getCapabilities()
-            tree = ElementTree.fromstring(capabilities)
-            os_types = tree.findall('./guest/os_type')
-            if 'hvm' not in map(lambda x: x.text, os_types):
-                raise QubesException("Cannot start HVM without VT-x/AMD-v enabled")
-            else:
-                raise
-
-    def _cleanup_zombie_domains(self):
-        super(QubesHVm, self)._cleanup_zombie_domains()
-        if not self.is_running():
-            xc_stubdom = self.get_xc_dominfo(name=self.name+'-dm')
-            if xc_stubdom is not None:
-                if xc_stubdom['paused'] == 1:
-                    subprocess.call(['xl', 'destroy', str(xc_stubdom['domid'])])
-                if xc_stubdom['dying'] == 1:
-                    # GUID still running?
-                    guid_pidfile = \
-                        '/var/run/qubes/guid-running.%d' % xc_stubdom['domid']
-                    if os.path.exists(guid_pidfile):
-                        guid_pid = open(guid_pidfile).read().strip()
-                        os.kill(int(guid_pid), 15)
-
-    def is_guid_running(self):
-        # If user force the guiagent, is_guid_running will mimic a standard QubesVM
-        if self.guiagent_installed:
-            return super(QubesHVm, self).is_guid_running()
-        else:
-            xid = self.stubdom_xid
-            if xid < 0:
-                return False
-            if not os.path.exists('/var/run/qubes/guid-running.%d' % xid):
-                return False
-            return True
-
-    def is_fully_usable(self):
-        # Running gui-daemon implies also VM running
-        if not self.is_guid_running():
-            return False
-        if self.qrexec_installed and not self.is_qrexec_running():
-            return False
-        return True

+ 0 - 110
core-modules/02QubesTemplateHVm.py

@@ -1,110 +0,0 @@
-#!/usr/bin/python2
-# -*- coding: utf-8 -*-
-#
-# The Qubes OS Project, http://www.qubes-os.org
-#
-# Copyright (C) 2010  Joanna Rutkowska <joanna@invisiblethingslab.com>
-# Copyright (C) 2013  Marek Marczykowski <marmarek@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.
-#
-#
-
-import os
-import os.path
-import subprocess
-import stat
-import sys
-import re
-
-from qubes.qubes import QubesHVm,register_qubes_vm_class,dry_run,vmm
-from qubes.qubes import QubesException,QubesVmCollection
-from qubes.qubes import system_path,defaults
-
-class QubesTemplateHVm(QubesHVm):
-    """
-    A class that represents an HVM template. A child of QubesHVm.
-    """
-
-    # In which order load this VM type from qubes.xml
-    load_order = 50
-
-    def get_attrs_config(self):
-        attrs_config = super(QubesTemplateHVm, self).get_attrs_config()
-        attrs_config['dir_path']['func'] = \
-            lambda value: value if value is not None else \
-                os.path.join(system_path["qubes_templates_dir"], self.name)
-        attrs_config['label']['default'] = defaults["template_label"]
-        return attrs_config
-
-
-    def __init__(self, **kwargs):
-
-        super(QubesTemplateHVm, self).__init__(**kwargs)
-
-        self.appvms = QubesVmCollection()
-
-    @property
-    def type(self):
-        return "TemplateHVM"
-
-    @property
-    def updateable(self):
-        return True
-
-    def is_template(self):
-        return True
-
-    def is_appvm(self):
-        return False
-
-    @property
-    def rootcow_img(self):
-        return self.storage.rootcow_img
-
-    @classmethod
-    def is_template_compatible(cls, template):
-        if template is None:
-            return True
-        return False
-
-    def resize_root_img(self, size):
-        for vm in self.appvms.values():
-            if vm.is_running():
-                raise QubesException("Cannot resize root.img while any VM "
-                                     "based on this tempate is running")
-        return super(QubesTemplateHVm, self).resize_root_img(size)
-
-    def start(self, *args, **kwargs):
-        for vm in self.appvms.values():
-            if vm.is_running():
-                raise QubesException("Cannot start HVM template while VMs based on it are running")
-        return super(QubesTemplateHVm, self).start(*args, **kwargs)
-
-    def commit_changes (self, verbose = False):
-        self.log.debug('commit_changes()')
-
-        if not vmm.offline_mode:
-            assert not self.is_running(), "Attempt to commit changes on running Template VM!"
-
-        if verbose:
-            print >> sys.stderr, "--> Commiting template updates... COW: {0}...".format (self.rootcow_img)
-
-        if dry_run:
-            return
-
-        self.storage.commit_template_changes()
-
-register_qubes_vm_class(QubesTemplateHVm)

+ 0 - 15
core-modules/Makefile

@@ -1,15 +0,0 @@
-PYTHON_QUBESMODPATH = $(PYTHON_SITEPATH)/qubes/modules
-
-all:
-	python -m compileall .
-	python -O -m compileall .
-
-install:
-ifndef PYTHON_SITEPATH
-	$(error PYTHON_SITEPATH not defined)
-endif
-	mkdir -p $(DESTDIR)$(PYTHON_QUBESMODPATH)
-	cp 0*.py $(DESTDIR)$(PYTHON_QUBESMODPATH)
-	cp 0*.py[co] $(DESTDIR)$(PYTHON_QUBESMODPATH)
-	cp __init__.py $(DESTDIR)$(PYTHON_QUBESMODPATH)
-	cp __init__.py[co] $(DESTDIR)$(PYTHON_QUBESMODPATH)

+ 0 - 5
core-modules/README.txt

@@ -1,5 +0,0 @@
-This directory contains Qubes core modules. It will be loaded in
-lexicographical order, use numeric prefix to force load ordering.
-
-0* - Qubes base modules
-00* - Qubes core VM classes

+ 0 - 0
core-modules/__init__.py


+ 0 - 1
core/.gitignore

@@ -1 +0,0 @@
-*.pyo

+ 0 - 31
core/Makefile

@@ -1,31 +0,0 @@
-OS ?= Linux
-
-PYTHON_QUBESPATH = $(PYTHON_SITEPATH)/qubes
-SETTINGS_SUFFIX = $(BACKEND_VMM)-$(OS)
-
-all:
-	python -m compileall .
-	python -O -m compileall .
-	make -C storage all
-
-install:
-ifndef PYTHON_SITEPATH
-	$(error PYTHON_SITEPATH not defined)
-endif
-	mkdir -p $(DESTDIR)$(PYTHON_QUBESPATH)
-	cp qubes.py $(DESTDIR)$(PYTHON_QUBESPATH)
-	cp qubes.py[co] $(DESTDIR)$(PYTHON_QUBESPATH)
-	cp qubesutils.py $(DESTDIR)$(PYTHON_QUBESPATH)
-	cp qubesutils.py[co] $(DESTDIR)$(PYTHON_QUBESPATH)
-	cp guihelpers.py $(DESTDIR)$(PYTHON_QUBESPATH)
-	cp guihelpers.py[co] $(DESTDIR)$(PYTHON_QUBESPATH)
-	cp backup.py $(DESTDIR)$(PYTHON_QUBESPATH)
-	cp backup.py[co] $(DESTDIR)$(PYTHON_QUBESPATH)
-ifneq ($(BACKEND_VMM),)
-	if [ -r settings-$(SETTINGS_SUFFIX).py ]; then \
-		cp settings-$(SETTINGS_SUFFIX).py $(DESTDIR)$(PYTHON_QUBESPATH)/settings.py && \
-		cp settings-$(SETTINGS_SUFFIX).pyc $(DESTDIR)$(PYTHON_QUBESPATH)/settings.pyc && \
-		cp settings-$(SETTINGS_SUFFIX).pyo $(DESTDIR)$(PYTHON_QUBESPATH)/settings.pyo; \
-	fi
-endif
-	make -C storage install

+ 0 - 0
core/__init__.py


+ 0 - 57
core/guihelpers.py

@@ -1,57 +0,0 @@
-#!/usr/bin/python2
-# -*- coding: utf-8 -*-
-#
-# The Qubes OS Project, http://www.qubes-os.org
-#
-# Copyright (C) 2011  Marek Marczykowski <marmarek@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.
-#
-#
-
-import sys
-from optparse import OptionParser
-from PyQt4.QtGui import QApplication,QMessageBox
-
-app = None
-system_bus = None
-
-def prepare_app():
-    global app
-    app  = QApplication(sys.argv)
-    app.setOrganizationName("The Qubes Project")
-    app.setOrganizationDomain("http://qubes-os.org")
-    app.setApplicationName("Qubes")
-
-def ask(text, title="Question", yestoall=False):
-    global app
-    if app is None:
-        prepare_app()
-
-    buttons = QMessageBox.Yes | QMessageBox.No
-    if yestoall:
-        buttons |= QMessageBox.YesToAll
-
-    reply = QMessageBox.question(None, title, text, buttons, defaultButton=QMessageBox.Yes)
-    if reply == QMessageBox.Yes:
-        return 0
-    elif reply == QMessageBox.No:
-        return 1
-    elif reply == QMessageBox.YesToAll:
-        return 2
-    else:
-        #?!
-        return 127
-

+ 0 - 1
core/modules

@@ -1 +0,0 @@
-../core-modules

+ 0 - 187
core/qubes.py

@@ -1,187 +0,0 @@
-#!/usr/bin/python2
-# -*- coding: 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.
-#
-#
-
-
-qubes_base_dir   = "/var/lib/qubes"
-system_path = {
-    'qubes_guid_path': '/usr/bin/qubes-guid',
-    'qrexec_daemon_path': '/usr/lib/qubes/qrexec-daemon',
-    'qrexec_client_path': '/usr/lib/qubes/qrexec-client',
-    'qubesdb_daemon_path': '/usr/sbin/qubesdb-daemon',
-
-    'qubes_base_dir': qubes_base_dir,
-
-    # Relative to qubes_base_dir
-    'qubes_appvms_dir': 'appvms',
-    'qubes_templates_dir': 'vm-templates',
-    'qubes_servicevms_dir': 'servicevms',
-    'qubes_store_filename': 'qubes.xml',
-    'qubes_kernels_base_dir': 'vm-kernels',
-
-    # qubes_icon_dir is obsolete
-    # use QIcon.fromTheme() where applicable
-    'qubes_icon_dir': '/usr/share/icons/hicolor/128x128/devices',
-
-    'qrexec_policy_dir': '/etc/qubes-rpc/policy',
-
-    'config_template_pv': '/usr/share/qubes/vm-template.xml',
-
-    'qubes_pciback_cmd': '/usr/lib/qubes/unbind-pci-device.sh',
-    'prepare_volatile_img_cmd': '/usr/lib/qubes/prepare-volatile-img.sh',
-}
-
-vm_files = {
-    'root_img': 'root.img',
-    'rootcow_img': 'root-cow.img',
-    'volatile_img': 'volatile.img',
-    'private_img': 'private.img',
-    'kernels_subdir': 'kernels',
-    'firewall_conf': 'firewall.xml',
-    'whitelisted_appmenus': 'whitelisted-appmenus.list',
-    'updates_stat_file': 'updates.stat',
-}
-
-defaults = {
-    'libvirt_uri': 'xen:///',
-    'memory': 400,
-    'kernelopts': "nopat",
-    'kernelopts_pcidevs': "nopat iommu=soft swiotlb=8192",
-
-    'dom0_update_check_interval': 6*3600,
-
-    'private_img_size': 2*1024*1024*1024,
-    'root_img_size': 10*1024*1024*1024,
-
-    'storage_class': None,
-
-    # how long (in sec) to wait for VMs to shutdown,
-    # before killing them (when used qvm-run with --wait option),
-    'shutdown_counter_max': 60,
-
-    'vm_default_netmask': "255.255.255.0",
-
-    # Set later
-    'appvm_label': None,
-    'template_label': None,
-    'servicevm_label': None,
-}
-
-qubes_max_qid = 254
-qubes_max_netid = 254
-
-##########################################
-
-def register_qubes_vm_class(vm_class):
-    QubesVmClasses[vm_class.__name__] = vm_class
-    # register class as local for this module - to make it easy to import from
-    # other modules
-    setattr(sys.modules[__name__], vm_class.__name__, vm_class)
-
-
-class QubesDaemonPidfile(object):
-    def __init__(self, name):
-        self.name = name
-        self.path = "/var/run/qubes/" + name + ".pid"
-
-    def create_pidfile(self):
-        f = open (self.path, 'w')
-        f.write(str(os.getpid()))
-        f.close()
-
-    def pidfile_exists(self):
-        return os.path.exists(self.path)
-
-    def read_pid(self):
-        f = open (self.path)
-        pid = f.read ().strip()
-        f.close()
-        return int(pid)
-
-    def pidfile_is_stale(self):
-        if not self.pidfile_exists():
-            return False
-
-        # check if the pid file is valid...
-        proc_path = "/proc/" + str(self.read_pid()) + "/cmdline"
-        if not os.path.exists (proc_path):
-            print >> sys.stderr, \
-                "Path {0} doesn't exist, assuming stale pidfile.".\
-                    format(proc_path)
-            return True
-
-        return False # It's a good pidfile
-
-    def remove_pidfile(self):
-        os.remove (self.path)
-
-    def __enter__ (self):
-        # assumes the pidfile doesn't exist -- you should ensure it before opening the context
-        self.create_pidfile()
-
-    def __exit__ (self, exc_type, exc_val, exc_tb):
-        self.remove_pidfile()
-        return False
-
-### Initialization code
-
-# Globally defined lables
-QubesVmLabels = {
-    "red":      QubesVmLabel(1, "0xcc0000", "red"     ),
-    "orange":   QubesVmLabel(2, "0xf57900", "orange"  ),
-    "yellow":   QubesVmLabel(3, "0xedd400", "yellow"  ),
-    "green":    QubesVmLabel(4, "0x73d216", "green"   ),
-    "gray":     QubesVmLabel(5, "0x555753", "gray"    ),
-    "blue":     QubesVmLabel(6, "0x3465a4", "blue"    ),
-    "purple":   QubesVmLabel(7, "0x75507b", "purple"  ),
-    "black":    QubesVmLabel(8, "0x000000", "black"   ),
-}
-
-QubesDispVmLabels = {
-    k: QubesVmLabel(index=v.index, color=v.color, name=v.name, dispvm=True)
-        for k, v in QubesVmLabels.iteritems()
-}
-
-defaults["appvm_label"] = QubesVmLabels["red"]
-defaults["template_label"] = QubesVmLabels["black"]
-defaults["servicevm_label"] = QubesVmLabels["red"]
-
-
-QubesVmClasses = {}
-modules_dir = os.path.join(os.path.dirname(__file__), 'modules')
-for module_file in sorted(os.listdir(modules_dir)):
-    if not module_file.endswith(".py") or module_file == "__init__.py":
-        continue
-    __import__('qubes.modules.%s' % module_file[:-3])
-
-try:
-    import qubes.settings
-    qubes.settings.apply(system_path, vm_files, defaults)
-except ImportError:
-    pass
-
-for path_key in system_path.keys():
-    if not os.path.isabs(system_path[path_key]):
-        system_path[path_key] = os.path.join(
-            system_path['qubes_base_dir'], system_path[path_key])
-
-# vim:sw=4:et:

+ 0 - 844
core/qubesutils.py

@@ -1,844 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-#
-# The Qubes OS Project, http://www.qubes-os.org
-#
-# Copyright (C) 2011  Marek Marczykowski <marmarek@invisiblethingslab.com>
-# Copyright (C) 2014  Wojciech Porczyk <wojciech@porczyk.eu>
-#
-# 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 __future__ import absolute_import
-
-import string
-import errno
-from lxml import etree
-from lxml.etree import ElementTree, SubElement, Element
-
-from qubes.qubes import QubesException
-from qubes.qubes import vmm,defaults
-from qubes.qubes import system_path,vm_files
-import sys
-import os
-import subprocess
-import re
-import time
-import stat
-import libvirt
-from qubes.qdb import QubesDB,Error,DisconnectedError
-
-import xen.lowlevel.xc
-import xen.lowlevel.xs
-
-# all frontends, prefer xvdi
-# TODO: get this from libvirt driver?
-AVAILABLE_FRONTENDS = ['xvd'+c for c in
-                       string.lowercase[8:]+string.lowercase[:8]]
-
-class USBProxyNotInstalled(QubesException):
-    pass
-
-def mbytes_to_kmg(size):
-    if size > 1024:
-        return "%d GiB" % (size/1024)
-    else:
-        return "%d MiB" % size
-
-def kbytes_to_kmg(size):
-    if size > 1024:
-        return mbytes_to_kmg(size/1024)
-    else:
-        return "%d KiB" % size
-
-def bytes_to_kmg(size):
-    if size > 1024:
-        return kbytes_to_kmg(size/1024)
-    else:
-        return "%d B" % size
-
-def size_to_human (size):
-    """Humane readable size, with 1/10 precission"""
-    if size < 1024:
-        return str (size);
-    elif size < 1024*1024:
-        return str(round(size/1024.0,1)) + ' KiB'
-    elif size < 1024*1024*1024:
-        return str(round(size/(1024.0*1024),1)) + ' MiB'
-    else:
-        return str(round(size/(1024.0*1024*1024),1)) + ' GiB'
-
-def print_stdout(text):
-    print (text)
-
-def print_stderr(text):
-    print >> sys.stderr, (text)
-
-###### Block devices ########
-
-def block_devid_to_name(devid):
-    major = devid / 256
-    minor = devid % 256
-
-    dev_class = ""
-    if major == 202:
-        dev_class = "xvd"
-    elif major == 8:
-        dev_class = "sd"
-    else:
-        raise QubesException("Unknown device class %d" % major)
-
-    if minor % 16 == 0:
-        return "%s%c" % (dev_class, ord('a')+minor/16)
-    else:
-        return "%s%c%d" % (dev_class, ord('a')+minor/16, minor%16)
-
-def block_name_to_majorminor(name):
-    # check if it is already devid
-    if isinstance(name, int):
-        return (name / 256, name % 256)
-    if name.isdigit():
-        return (int(name) / 256, int(name) % 256)
-
-    if os.path.exists('/dev/%s' % name):
-        blk_info = os.stat(os.path.realpath('/dev/%s' % name))
-        if stat.S_ISBLK(blk_info.st_mode):
-            return (blk_info.st_rdev / 256, blk_info.st_rdev % 256)
-
-    major = 0
-    minor = 0
-    dXpY_style = False
-    disk = True
-
-    if name.startswith("xvd"):
-        major = 202
-    elif name.startswith("sd"):
-        major = 8
-    elif name.startswith("mmcblk"):
-        dXpY_style = True
-        major = 179
-    elif name.startswith("scd"):
-        disk = False
-        major = 11
-    elif name.startswith("sr"):
-        disk = False
-        major = 11
-    elif name.startswith("loop"):
-        dXpY_style = True
-        disk = False
-        major = 7
-    elif name.startswith("md"):
-        dXpY_style = True
-        major = 9
-    elif name.startswith("dm-"):
-        disk = False
-        major = 253
-    else:
-        # Unknown device
-        return (0, 0)
-
-    if not dXpY_style:
-        name_match = re.match(r"^([a-z]+)([a-z-])([0-9]*)$", name)
-    else:
-        name_match = re.match(r"^([a-z]+)([0-9]*)(?:p([0-9]+))?$", name)
-    if not name_match:
-        raise QubesException("Invalid device name: %s" % name)
-
-    if disk:
-        if dXpY_style:
-            minor = int(name_match.group(2))*8
-        else:
-            minor = (ord(name_match.group(2))-ord('a')) * 16
-    else:
-        minor = 0
-    if name_match.group(3):
-        minor += int(name_match.group(3))
-
-    return (major, minor)
-
-
-def block_name_to_devid(name):
-    # check if it is already devid
-    if isinstance(name, int):
-        return name
-    if name.isdigit():
-        return int(name)
-
-    (major, minor) = block_name_to_majorminor(name)
-    return major << 8 | minor
-
-def block_find_unused_frontend(vm = None):
-    assert vm is not None
-    assert vm.is_running()
-
-    xml = vm.libvirt_domain.XMLDesc()
-    parsed_xml = etree.fromstring(xml)
-    used = [target.get('dev', None)  for target in
-            parsed_xml.xpath("//domain/devices/disk/target")]
-    for dev in AVAILABLE_FRONTENDS:
-        if dev not in used:
-            return dev
-    return None
-
-def block_list_vm(vm, system_disks = False):
-    name_re = re.compile(r"^[a-z0-9-]{1,12}$")
-    device_re = re.compile(r"^[a-z0-9/-]{1,64}$")
-    # FIXME: any better idea of desc_re?
-    desc_re = re.compile(r"^.{1,255}$")
-    mode_re = re.compile(r"^[rw]$")
-
-    assert vm is not None
-
-    if not vm.is_running():
-        return []
-
-    devices_list = {}
-
-    try:
-        untrusted_devices = vm.qdb.multiread('/qubes-block-devices/')
-    except Error:
-        vm.refresh()
-        return {}
-
-    def get_dev_item(dev, item):
-        return untrusted_devices.get(
-            '/qubes-block-devices/%s/%s' % (dev, item),
-            None)
-
-    untrusted_devices_names = list(set(map(lambda x: x.split("/")[2],
-        untrusted_devices.keys())))
-    for untrusted_dev_name in untrusted_devices_names:
-        if name_re.match(untrusted_dev_name):
-            dev_name = untrusted_dev_name
-            untrusted_device_size = get_dev_item(dev_name, 'size')
-            untrusted_device_desc = get_dev_item(dev_name, 'desc')
-            untrusted_device_mode = get_dev_item(dev_name, 'mode')
-            untrusted_device_device = get_dev_item(dev_name, 'device')
-            if untrusted_device_desc is None or untrusted_device_mode is None\
-                    or untrusted_device_size is None:
-                print >>sys.stderr, "Missing field in %s device parameters" %\
-                                    dev_name
-                continue
-            if untrusted_device_device is None:
-                untrusted_device_device = '/dev/' + dev_name
-            if not device_re.match(untrusted_device_device):
-                print >> sys.stderr, "Invalid %s device path in VM '%s'" % (
-                    dev_name, vm.name)
-                continue
-            device_device = untrusted_device_device
-            if not untrusted_device_size.isdigit():
-                print >> sys.stderr, "Invalid %s device size in VM '%s'" % (
-                    dev_name, vm.name)
-                continue
-            device_size = int(untrusted_device_size)
-            if not desc_re.match(untrusted_device_desc):
-                print >> sys.stderr, "Invalid %s device desc in VM '%s'" % (
-                    dev_name, vm.name)
-                continue
-            device_desc = untrusted_device_desc
-            if not mode_re.match(untrusted_device_mode):
-                print >> sys.stderr, "Invalid %s device mode in VM '%s'" % (
-                    dev_name, vm.name)
-                continue
-            device_mode = untrusted_device_mode
-
-            if not system_disks:
-                if vm.qid == 0 and device_desc.startswith(system_path[
-                    "qubes_base_dir"]):
-                    continue
-
-            visible_name = "%s:%s" % (vm.name, dev_name)
-            devices_list[visible_name] = {
-                "name":   visible_name,
-                "vm":     vm.name,
-                "device": device_device,
-                "size":   device_size,
-                "desc":   device_desc,
-                "mode":   device_mode
-            }
-
-    return devices_list
-
-def block_list(qvmc = None, vm = None, system_disks = False):
-    if vm is not None:
-        if not vm.is_running():
-            return []
-        else:
-            vm_list = [ vm ]
-    else:
-        if qvmc is None:
-            raise QubesException("You must pass either qvm or vm argument")
-        vm_list = qvmc.values()
-
-    devices_list = {}
-    for vm in vm_list:
-        devices_list.update(block_list_vm(vm, system_disks))
-    return devices_list
-
-def block_check_attached(qvmc, device):
-    """
-
-    @type qvmc: QubesVmCollection
-    """
-    if qvmc is None:
-        # TODO: ValueError
-        raise QubesException("You need to pass qvmc argument")
-
-    for vm in qvmc.values():
-        if vm.qid == 0:
-            # Connecting devices to dom0 not supported
-            continue
-        if not vm.is_running():
-            continue
-        try:
-            libvirt_domain = vm.libvirt_domain
-            if libvirt_domain:
-                xml = libvirt_domain.XMLDesc()
-            else:
-                xml = None
-        except libvirt.libvirtError:
-            if vmm.libvirt_conn.virConnGetLastError()[0] == libvirt.VIR_ERR_NO_DOMAIN:
-                xml = None
-            else:
-                raise
-        if xml:
-            parsed_xml = etree.fromstring(xml)
-            disks = parsed_xml.xpath("//domain/devices/disk")
-            for disk in disks:
-                backend_name = 'dom0'
-                if disk.find('backenddomain') is not None:
-                    backend_name = disk.find('backenddomain').get('name')
-                source = disk.find('source')
-                if disk.get('type') == 'file':
-                    path = source.get('file')
-                elif disk.get('type') == 'block':
-                    path = source.get('dev')
-                else:
-                    # TODO: logger
-                    print >>sys.stderr, "Unknown disk type '%s' attached to " \
-                                        "VM '%s'" % (source.get('type'),
-                                                     vm.name)
-                    continue
-                if backend_name == device['vm'] and (path == device['device']
-                        or not path.startswith('/dev/') and path == device[
-                        'desc']):
-                    return {
-                        "frontend": disk.find('target').get('dev'),
-                        "vm": vm}
-    return None
-
-def device_attach_check(vm, backend_vm, device, frontend, mode):
-    """ Checks all the parameters, dies on errors """
-    if not vm.is_running():
-        raise QubesException("VM %s not running" % vm.name)
-
-    if not backend_vm.is_running():
-        raise QubesException("VM %s not running" % backend_vm.name)
-
-    if device['mode'] == 'r' and mode == 'w':
-        raise QubesException("Cannot attach read-only device in read-write "
-                             "mode")
-
-def block_attach(qvmc, vm, device, frontend=None, mode="w", auto_detach=False, wait=True):
-    backend_vm = qvmc.get_vm_by_name(device['vm'])
-    device_attach_check(vm, backend_vm, device, frontend, mode)
-    if frontend is None:
-        frontend = block_find_unused_frontend(vm)
-        if frontend is None:
-            raise QubesException("No unused frontend found")
-    else:
-        # Check if any device attached at this frontend
-        xml = vm.libvirt_domain.XMLDesc()
-        parsed_xml = etree.fromstring(xml)
-        disks = parsed_xml.xpath("//domain/devices/disk/target[@dev='%s']" %
-                                 frontend)
-        if len(disks):
-            raise QubesException("Frontend %s busy in VM %s, detach it first" % (frontend, vm.name))
-
-    # Check if this device is attached to some domain
-    attached_vm = block_check_attached(qvmc, device)
-    if attached_vm:
-        if auto_detach:
-            block_detach(attached_vm['vm'], attached_vm['frontend'])
-        else:
-            raise QubesException("Device %s from %s already connected to VM "
-                                 "%s as %s" % (device['device'],
-                                               backend_vm.name, attached_vm['vm'], attached_vm['frontend']))
-
-    disk = Element("disk")
-    disk.set('type', 'block')
-    disk.set('device', 'disk')
-    SubElement(disk, 'driver').set('name', 'phy')
-    SubElement(disk, 'source').set('dev', device['device'])
-    SubElement(disk, 'target').set('dev', frontend)
-    if backend_vm.qid != 0:
-        SubElement(disk, 'backenddomain').set('name', device['vm'])
-    if mode == "r":
-        SubElement(disk, 'readonly')
-    vm.libvirt_domain.attachDevice(etree.tostring(disk,  encoding='utf-8'))
-    try:
-        # trigger watches to update device status
-        # FIXME: this should be removed once libvirt will report such
-        # events itself
-        vm.qdb.write('/qubes-block-devices', '')
-    except Error:
-        pass
-
-def block_detach(vm, frontend = "xvdi"):
-
-    xml = vm.libvirt_domain.XMLDesc()
-    parsed_xml = etree.fromstring(xml)
-    attached = parsed_xml.xpath("//domain/devices/disk")
-    for disk in attached:
-        if frontend is not None and disk.find('target').get('dev') != frontend:
-            # Not the device we are looking for
-            continue
-        if frontend is None:
-            # ignore system disks
-            if disk.find('domain') == None and \
-                    disk.find('source').get('dev').startswith(system_path[
-                        "qubes_base_dir"]):
-                continue
-        vm.libvirt_domain.detachDevice(etree.tostring(disk, encoding='utf-8'))
-        try:
-            # trigger watches to update device status
-            # FIXME: this should be removed once libvirt will report such
-            # events itself
-            vm.qdb.write('/qubes-block-devices', '')
-        except Error:
-            pass
-
-def block_detach_all(vm):
-    """ Detach all non-system devices"""
-
-    block_detach(vm, None)
-
-####### USB devices ######
-
-usb_ver_re = re.compile(r"^(1|2)$")
-usb_device_re = re.compile(r"^[0-9]+-[0-9]+(_[0-9]+)?$")
-usb_port_re = re.compile(r"^$|^[0-9]+-[0-9]+(\.[0-9]+)?$")
-usb_desc_re = re.compile(r"^[ -~]{1,255}$")
-# should match valid VM name
-usb_connected_to_re = re.compile(r"^[a-zA-Z][a-zA-Z0-9_.-]*$")
-
-def usb_decode_device_from_qdb(qdb_encoded_device):
-    """ recover actual device name (xenstore doesn't allow dot in key names, so it was translated to underscore) """
-    return qdb_encoded_device.replace('_', '.')
-
-def usb_encode_device_for_qdb(device):
-    """ encode actual device name (xenstore doesn't allow dot in key names, so translated it into underscore) """
-    return device.replace('.', '_')
-
-def usb_list_vm(qvmc, vm):
-    if not vm.is_running():
-        return {}
-
-    try:
-        untrusted_devices = vm.qdb.multiread('/qubes-usb-devices/')
-    except Error:
-        vm.refresh()
-        return {}
-
-    def get_dev_item(dev, item):
-        return untrusted_devices.get(
-            '/qubes-usb-devices/%s/%s' % (dev, item),
-            None)
-
-    devices = {}
-
-    untrusted_devices_names = list(set(map(lambda x: x.split("/")[2],
-        untrusted_devices.keys())))
-    for untrusted_dev_name in untrusted_devices_names:
-        if usb_device_re.match(untrusted_dev_name):
-            dev_name = untrusted_dev_name
-            untrusted_device_desc = get_dev_item(dev_name, 'desc')
-            if not usb_desc_re.match(untrusted_device_desc):
-                print >> sys.stderr, "Invalid %s device desc in VM '%s'" % (
-                    dev_name, vm.name)
-                continue
-            device_desc = untrusted_device_desc
-
-            untrusted_connected_to = get_dev_item(dev_name, 'connected-to')
-            if untrusted_connected_to:
-                if not usb_connected_to_re.match(untrusted_connected_to):
-                    print >>sys.stderr, \
-                        "Invalid %s device 'connected-to' in VM '%s'" % (
-                            dev_name, vm.name)
-                    continue
-                connected_to = qvmc.get_vm_by_name(untrusted_connected_to)
-                if connected_to is None:
-                    print >>sys.stderr, \
-                        "Device {} appears to be connected to {}, " \
-                        "but such VM doesn't exist".format(
-                            dev_name, untrusted_connected_to)
-            else:
-                connected_to = None
-
-            device = usb_decode_device_from_qdb(dev_name)
-
-            full_name = vm.name + ':' + device
-
-            devices[full_name] = {
-                'vm': vm,
-                'device': device,
-                'qdb_path': '/qubes-usb-devices/' + dev_name,
-                'name': full_name,
-                'desc': device_desc,
-                'connected-to': connected_to,
-            }
-    return devices
-
-
-def usb_list(qvmc, vm=None):
-    """
-    Returns a dictionary of USB devices (for PVUSB backends running in all VM).
-    The dictionary is keyed by 'name' (see below), each element is a dictionary itself:
-     vm   = backend domain object
-     device = device ID
-     name = <backend-vm>:<device>
-     desc = description
-    """
-    if vm is not None:
-        if not vm.is_running():
-            return {}
-        else:
-            vm_list = [vm]
-    else:
-        vm_list = qvmc.values()
-
-    devices_list = {}
-    for vm in vm_list:
-        devices_list.update(usb_list_vm(qvmc, vm))
-    return devices_list
-
-def usb_check_attached(qvmc, device):
-    """Reread device attachment status"""
-    vm = device['vm']
-    untrusted_connected_to = vm.qdb.read(
-        '{}/connected-to'.format(device['qdb_path']))
-    if untrusted_connected_to:
-        if not usb_connected_to_re.match(untrusted_connected_to):
-            raise QubesException(
-                "Invalid %s device 'connected-to' in VM '%s'" % (
-                    device['device'], vm.name))
-        connected_to = qvmc.get_vm_by_name(untrusted_connected_to)
-        if connected_to is None:
-            print >>sys.stderr, \
-                "Device {} appears to be connected to {}, " \
-                "but such VM doesn't exist".format(
-                    device['device'], untrusted_connected_to)
-    else:
-        connected_to = None
-    return connected_to
-
-def usb_attach(qvmc, vm, device, auto_detach=False, wait=True):
-    if not vm.is_running():
-        raise QubesException("VM {} not running".format(vm.name))
-
-    if not device['vm'].is_running():
-        raise QubesException("VM {} not running".format(device['vm'].name))
-
-    connected_to = usb_check_attached(qvmc, device)
-    if connected_to:
-        if auto_detach:
-            usb_detach(qvmc, device)
-        else:
-            raise QubesException("Device {} already connected, to {}".format(
-                device['name'], connected_to
-            ))
-
-    # set qrexec policy to allow this device
-    policy_line = '{} {} allow\n'.format(vm.name, device['vm'].name)
-    policy_path = '/etc/qubes-rpc/policy/qubes.USB+{}'.format(device['device'])
-    policy_exists = os.path.exists(policy_path)
-    if not policy_exists:
-        try:
-            fd = os.open(policy_path, os.O_CREAT | os.O_EXCL | os.O_WRONLY)
-            with os.fdopen(fd, 'w') as f:
-                f.write(policy_line)
-        except OSError as e:
-            if e.errno == errno.EEXIST:
-                pass
-            else:
-                raise
-    else:
-        with open(policy_path, 'r+') as f:
-            policy = f.readlines()
-            policy.insert(0, policy_line)
-            f.truncate(0)
-            f.seek(0)
-            f.write(''.join(policy))
-    try:
-        # and actual attach
-        p = vm.run_service('qubes.USBAttach', passio_popen=True, user='root')
-        (stdout, stderr) = p.communicate(
-            '{} {}\n'.format(device['vm'].name, device['device']))
-        if p.returncode == 127:
-            raise USBProxyNotInstalled(
-                "qubes-usb-proxy not installed in the VM")
-        elif p.returncode != 0:
-            # TODO: sanitize and include stdout
-            sanitized_stderr = ''.join([c for c in stderr if ord(c) >= 0x20])
-            raise QubesException('Device attach failed: {}'.format(
-                sanitized_stderr))
-    finally:
-        # FIXME: there is a race condition here - some other process might
-        # modify the file in the meantime. This may result in unexpected
-        # denials, but will not allow too much
-        if not policy_exists:
-            os.unlink(policy_path)
-        else:
-            with open(policy_path, 'r+') as f:
-                policy = f.readlines()
-                policy.remove('{} {} allow\n'.format(vm.name, device['vm'].name))
-                f.truncate(0)
-                f.seek(0)
-                f.write(''.join(policy))
-
-def usb_detach(qvmc, vm, device):
-    connected_to = usb_check_attached(qvmc, device)
-    # detect race conditions; there is still race here, but much smaller
-    if connected_to is None or connected_to.qid != vm.qid:
-        raise QubesException(
-            "Device {} not connected to VM {}".format(
-                device['name'], vm.name))
-
-    p = device['vm'].run_service('qubes.USBDetach', passio_popen=True,
-        user='root')
-    (stdout, stderr) = p.communicate(
-        '{}\n'.format(device['device']))
-    if p.returncode != 0:
-        # TODO: sanitize and include stdout
-        raise QubesException('Device detach failed')
-
-def usb_detach_all(qvmc, vm):
-    for dev in usb_list(qvmc).values():
-        connected_to = dev['connected-to']
-        if connected_to is not None and connected_to.qid == vm.qid:
-            usb_detach(qvmc, connected_to, dev)
-
-####### QubesWatch ######
-
-def only_in_first_list(l1, l2):
-    ret=[]
-    for i in l1:
-        if not i in l2:
-            ret.append(i)
-    return ret
-
-class QubesWatch(object):
-    def __init__(self):
-        self._qdb = {}
-        self._qdb_events = {}
-        self.block_callback = None
-        self.meminfo_callback = None
-        self.domain_callback = None
-        libvirt.virEventRegisterDefaultImpl()
-        # open new libvirt connection because above
-        # virEventRegisterDefaultImpl is in practice effective only for new
-        # connections
-        self.libvirt_conn = libvirt.open(defaults['libvirt_uri'])
-        self.libvirt_conn.domainEventRegisterAny(
-            None,
-            libvirt.VIR_DOMAIN_EVENT_ID_LIFECYCLE,
-            self._domain_list_changed, None)
-        self.libvirt_conn.domainEventRegisterAny(
-            None,
-            libvirt.VIR_DOMAIN_EVENT_ID_DEVICE_REMOVED,
-            self._device_removed, None)
-        # TODO: device attach libvirt event
-        for vm in vmm.libvirt_conn.listAllDomains():
-            try:
-                if vm.isActive():
-                    self._register_watches(vm)
-            except libvirt.libvirtError as e:
-                # this will happen if we loose a race with another tool,
-                # which can just remove the domain
-                if e.get_error_code() == libvirt.VIR_ERR_NO_DOMAIN:
-                    pass
-                else:
-                    raise
-        # and for dom0
-        self._register_watches(None)
-
-    def _qdb_handler(self, watch, fd, events, domain_name):
-        try:
-            path = self._qdb[domain_name].read_watch()
-        except DisconnectedError:
-            libvirt.virEventRemoveHandle(watch)
-            del(self._qdb_events[domain_name])
-            self._qdb[domain_name].close()
-            del(self._qdb[domain_name])
-            return
-        if path.startswith('/qubes-block-devices'):
-            if self.block_callback is not None:
-                self.block_callback(domain_name)
-
-
-    def setup_block_watch(self, callback):
-        self.block_callback = callback
-
-    def setup_meminfo_watch(self, callback):
-        raise NotImplementedError
-
-    def setup_domain_watch(self, callback):
-        self.domain_callback = callback
-
-    def get_meminfo_key(self, xid):
-        return '/local/domain/%s/memory/meminfo' % xid
-
-    def _register_watches(self, libvirt_domain):
-        if libvirt_domain and libvirt_domain.ID() == 0:
-            # don't use libvirt object for dom0, to always have the same
-            # hardcoded "dom0" name
-            libvirt_domain = None
-        if libvirt_domain:
-            name = libvirt_domain.name()
-            if name in self._qdb:
-                return
-            if not libvirt_domain.isActive():
-                return
-            # open separate connection to Qubes DB:
-            # 1. to not confuse pull() with responses to real commands sent from
-            # other threads (like read, write etc) with watch events
-            # 2. to not think whether QubesDB is thread-safe (it isn't)
-            try:
-                self._qdb[name] = QubesDB(name)
-            except Error as e:
-                if e.args[0] != 2:
-                    raise
-                libvirt.virEventAddTimeout(500, self._retry_register_watches,
-                                           libvirt_domain)
-                return
-        else:
-            name = "dom0"
-            if name in self._qdb:
-                return
-            self._qdb[name] = QubesDB(name)
-        try:
-            self._qdb[name].watch('/qubes-block-devices')
-        except Error as e:
-            if e.args[0] == 102: # Connection reset by peer
-                # QubesDB daemon not running - most likely we've connected to
-                #  stale daemon which just exited; retry later
-                libvirt.virEventAddTimeout(500, self._retry_register_watches,
-                                           libvirt_domain)
-                return
-        self._qdb_events[name] = libvirt.virEventAddHandle(
-            self._qdb[name].watch_fd(),
-            libvirt.VIR_EVENT_HANDLE_READABLE,
-            self._qdb_handler, name)
-
-    def _retry_register_watches(self, timer, libvirt_domain):
-        libvirt.virEventRemoveTimeout(timer)
-        self._register_watches(libvirt_domain)
-
-    def _unregister_watches(self, libvirt_domain):
-        if libvirt_domain and libvirt_domain.ID() == 0:
-            name = "dom0"
-        else:
-            name = libvirt_domain.name()
-        if name in self._qdb_events:
-            libvirt.virEventRemoveHandle(self._qdb_events[name])
-            del(self._qdb_events[name])
-        if name in self._qdb:
-            self._qdb[name].close()
-            del(self._qdb[name])
-
-    def _domain_list_changed(self, conn, domain, event, reason, param):
-        # use VIR_DOMAIN_EVENT_RESUMED instead of VIR_DOMAIN_EVENT_STARTED to
-        #  make sure that qubesdb daemon is already running
-        if event == libvirt.VIR_DOMAIN_EVENT_RESUMED:
-            self._register_watches(domain)
-        elif event == libvirt.VIR_DOMAIN_EVENT_STOPPED:
-            self._unregister_watches(domain)
-        else:
-            # ignore other events for now
-            return None
-        if self.domain_callback:
-            self.domain_callback(name=domain.name(), uuid=domain.UUID())
-
-    def _device_removed(self, conn, domain, device, param):
-        if self.block_callback is not None:
-            self.block_callback(domain.name())
-
-    def watch_loop(self):
-        while True:
-            libvirt.virEventRunDefaultImpl()
-
-##### updates check #####
-
-#
-# XXX this whole section is a new global property
-# TODO make event handlers
-#
-
-UPDATES_DOM0_DISABLE_FLAG='/var/lib/qubes/updates/disable-updates'
-UPDATES_DEFAULT_VM_DISABLE_FLAG=\
-    '/var/lib/qubes/updates/vm-default-disable-updates'
-
-def updates_vms_toggle(qvm_collection, value):
-    # Flag for new VMs
-    if value:
-        if os.path.exists(UPDATES_DEFAULT_VM_DISABLE_FLAG):
-            os.unlink(UPDATES_DEFAULT_VM_DISABLE_FLAG)
-    else:
-        open(UPDATES_DEFAULT_VM_DISABLE_FLAG, "w").close()
-
-    # Change for existing VMs
-    for vm in qvm_collection.values():
-        if vm.qid == 0:
-            continue
-        if value:
-            vm.services.pop('qubes-update-check', None)
-            if vm.is_running():
-                try:
-                    vm.run("systemctl start qubes-update-check.timer",
-                           user="root")
-                except:
-                    pass
-        else:
-            vm.services['qubes-update-check'] = False
-            if vm.is_running():
-                try:
-                    vm.run("systemctl stop qubes-update-check.timer",
-                           user="root")
-                except:
-                    pass
-def updates_dom0_toggle(qvm_collection, value):
-    if value:
-        if os.path.exists(UPDATES_DOM0_DISABLE_FLAG):
-            os.unlink(UPDATES_DOM0_DISABLE_FLAG)
-    else:
-        open(UPDATES_DOM0_DISABLE_FLAG, "w").close()
-
-def updates_dom0_status(qvm_collection):
-    return not os.path.exists(UPDATES_DOM0_DISABLE_FLAG)
-
-def updates_vms_status(qvm_collection):
-    # default value:
-    status = not os.path.exists(UPDATES_DEFAULT_VM_DISABLE_FLAG)
-    # check if all the VMs uses the default value
-    for vm in qvm_collection.values():
-        if vm.qid == 0:
-            continue
-        if vm.services.get('qubes-update-check', True) != status:
-            # "mixed"
-            return None
-    return status
-
-# vim:sw=4:et:

+ 0 - 11
core/settings-xen-Linux.py

@@ -1,11 +0,0 @@
-#!/usr/bin/python2
-
-from __future__ import absolute_import
-
-from qubes.storage.xen import XenStorage, XenPool
-
-
-def apply(system_path, vm_files, defaults):
-    defaults['storage_class'] = XenStorage
-    defaults['pool_drivers'] = {'xen': XenPool}
-    defaults['pool_config'] = {'dir_path': '/var/lib/qubes/'}

+ 0 - 24
core/storage/Makefile

@@ -1,24 +0,0 @@
-OS ?= Linux
-
-SYSCONFDIR ?= /etc
-PYTHON_QUBESPATH = $(PYTHON_SITEPATH)/qubes
-
-all:
-	python -m compileall .
-	python -O -m compileall .
-
-install:
-ifndef PYTHON_SITEPATH
-	$(error PYTHON_SITEPATH not defined)
-endif
-	mkdir -p $(DESTDIR)$(PYTHON_QUBESPATH)/storage
-	cp __init__.py $(DESTDIR)$(PYTHON_QUBESPATH)/storage
-	cp __init__.py[co] $(DESTDIR)$(PYTHON_QUBESPATH)/storage
-	mkdir -p $(DESTDIR)$(SYSCONFDIR)/qubes
-	cp storage.conf $(DESTDIR)$(SYSCONFDIR)/qubes/
-ifneq ($(BACKEND_VMM),)
-	if [ -r $(BACKEND_VMM).py ]; then \
-		cp $(BACKEND_VMM).py $(DESTDIR)$(PYTHON_QUBESPATH)/storage && \
-		cp $(BACKEND_VMM).py[co] $(DESTDIR)$(PYTHON_QUBESPATH)/storage; \
-	fi
-endif

+ 0 - 48
core/tests/test_qubesutils.py

@@ -1,48 +0,0 @@
-#!/usr/bin/python -O
-
-#
-# The Qubes OS Project, http://www.qubes-os.org
-#
-# Copyright (C) 2014  Wojciech Porczyk <wojciech@porczyk.eu>
-#
-# 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.
-#
-
-import subprocess
-import unittest
-
-import qubes.qubesutils
-
-
-class TestCaseFunctionsAndConstants(unittest.TestCase):
-    def check_output_int(self, cmd):
-        return int(subprocess.check_output(cmd).strip().split(None, 1)[0])
-
-    def test_00_BLKSIZE(self):
-        # this may fail on systems without st_blocks
-        self.assertEqual(qubes.qubesutils.BLKSIZE, self.check_output_int(['stat', '-c%B', '.']))
-
-    def test_01_get_size_one(self):
-        # this may fail on systems without st_blocks
-        self.assertEqual(qubes.qubesutils.get_disk_usage_one(os.stat('.')),
-            self.check_output_int(['stat', '-c%b', '.']) * qubes.qubesutils.BLKSIZE)
-
-    def test_02_get_size(self):
-        self.assertEqual(qubes.qubesutils.get_disk_usage('.'),
-            self.check_output_int(['du', '-s', '--block-size=1', '.']))
-
-
-if __name__ == '__main__':
-    unittest.main()

+ 0 - 2
dispvm/.gitignore

@@ -1,2 +0,0 @@
-qubes_restore
-xenstore-watch

+ 0 - 21
dispvm/Makefile

@@ -1,21 +0,0 @@
-UNITDIR ?= /usr/lib/systemd/system
-
-all:
-	true
-
-clean:
-	true
-
-install:
-	mkdir -p $(DESTDIR)/etc/xen/scripts
-	cp block.qubes $(DESTDIR)/etc/xen/scripts
-	mkdir -p $(DESTDIR)/usr/bin $(DESTDIR)/usr/lib/qubes
-	cp qubes-prepare-saved-domain.sh  $(DESTDIR)/usr/lib/qubes
-	cp qubes-update-dispvm-savefile-with-progress.sh  $(DESTDIR)/usr/lib/qubes
-	cp qfile-daemon-dvm $(DESTDIR)/usr/lib/qubes
-	mkdir -p $(DESTDIR)$(UNITDIR)
-	cp startup-dvm.sh $(DESTDIR)/usr/lib/qubes
-	cp qubes-setupdvm.service $(DESTDIR)$(UNITDIR)
-
-
-

+ 0 - 61
dispvm/block.qubes

@@ -1,61 +0,0 @@
-#!/bin/bash
-
-HOTPLUG_STORE="/var/run/xen-hotplug/${XENBUS_PATH//\//-}"
-
-hd_arr[10]=a
-hd_arr[11]=b
-hd_arr[12]=c
-hd_arr[13]=d
-hd_arr[14]=e
-hd_arr[15]=f
-
-hexdigit()
-{
-	if [ $1 -lt 10 ] ; then 
-		RET=$1
-	else 
-		RET=${hd_arr[$1]}
-	fi
-}
-
-hexnumber()
-{
-	hexdigit $(($1/16))
-	ret2=$RET
-	hexdigit $(($1%16))
-	HEXNUMBER="$ret2"$RET
-}
-
-
-process()
-{
-	if ! [ "x""$1" = "xfile" ] ; then
-		exec flock /var/run/qubes/hotplug-block /etc/xen/scripts/block $ORIG_ARGS	
-	fi
-	while true ; do
-		dev=$(losetup -f --show $2)
-		if [ -n "$dev" ] ; then break ; fi
-	done
-	hexnumber ${dev:9:70}
-	xenstore-write "$XENBUS_PATH/node" "$dev" \
-		"$XENBUS_PATH/physical-device" "7:"$HEXNUMBER \
- 		"$XENBUS_PATH/hotplug-status" connected
-	echo "$dev" > "$HOTPLUG_STORE-node"
-	echo "file" > "$HOTPLUG_STORE-type"
-}
-
-#exec 2>>/tmp/block.$$
-#set -x
-export PATH="/sbin:/bin:/usr/bin:/usr/sbin:$PATH"
-
-XENBUS_PATH="${XENBUS_PATH:?}"
-if ! [ "$1" = "add" ] || ! [ -f /var/run/qubes/fast-block-attach ] ; then
-	script=$(xenstore-read "$XENBUS_PATH/script")
-	exec flock /var/run/qubes/hotplug-block $script "$@"
-fi
-
-ORIG_ARGS="$@"
-  
-vars=$(xenstore-read "$XENBUS_PATH/type" "$XENBUS_PATH/params")
-process $vars
-exit 0

+ 0 - 200
dispvm/qfile-daemon-dvm

@@ -1,200 +0,0 @@
-#!/usr/bin/python2
-# coding=utf-8
-#
-# The Qubes OS Project, http://www.qubes-os.org
-#
-# Copyright (C) 2010      Rafal Wojtczuk  <rafal@invisiblethingslab.com>
-# Copyright (C) 2013-2015 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 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.
-#
-#
-import os
-import subprocess
-import sys
-import shutil
-import time
-
-from qubes.qubes import QubesVmCollection, QubesException
-from qubes.qubes import QubesDispVmLabels
-from qubes.notify import tray_notify, tray_notify_error, tray_notify_init
-
-
-current_savefile = '/var/run/qubes/current-savefile'
-current_savefile_vmdir = '/var/lib/qubes/dvmdata/vmdir'
-
-
-class QfileDaemonDvm:
-    def __init__(self, name):
-        self.name = name
-
-    @staticmethod
-    def get_disp_templ():
-        vmdir = os.readlink(current_savefile_vmdir)
-        return vmdir.split('/')[-1]
-        
-    def do_get_dvm(self):
-        tray_notify("Starting new DispVM...", "red")
-
-        qvm_collection = QubesVmCollection()
-        qvm_collection.lock_db_for_writing()
-        try:
-
-            tar_process = subprocess.Popen(
-                ['bsdtar', '-C', current_savefile_vmdir,
-                 '-xSUf', os.path.join(current_savefile_vmdir, 'saved-cows.tar')])
-
-            qvm_collection.load()
-            print >>sys.stderr, "time=%s, collection loaded" % (str(time.time()))
-
-            vm = qvm_collection.get_vm_by_name(self.name)
-            if vm is None:
-                sys.stderr.write('Domain ' + self.name + ' does not exist ?')
-                return None
-            label = vm.label
-            if len(sys.argv) > 4 and len(sys.argv[4]) > 0:
-                assert sys.argv[4] in QubesDispVmLabels.keys(), "Invalid label"
-                label = QubesDispVmLabels[sys.argv[4]]
-            disp_templ = self.get_disp_templ()
-            vm_disptempl = qvm_collection.get_vm_by_name(disp_templ)
-            if vm_disptempl is None:
-                sys.stderr.write('Domain ' + disp_templ + ' does not exist ?')
-                return None
-            dispvm = qvm_collection.add_new_vm('QubesDisposableVm',
-                                               disp_template=vm_disptempl,
-                                               label=label)
-            print >>sys.stderr, "time=%s, VM created" % (str(time.time()))
-            # By default inherit firewall rules from calling VM
-            disp_firewall_conf = '/var/run/qubes/%s-firewall.xml' % dispvm.name
-            dispvm.firewall_conf = disp_firewall_conf
-            if os.path.exists(vm.firewall_conf):
-                shutil.copy(vm.firewall_conf, disp_firewall_conf)
-            elif vm.qid == 0 and os.path.exists(vm_disptempl.firewall_conf):
-                # for DispVM called from dom0, copy use rules from DispVM template
-                shutil.copy(vm_disptempl.firewall_conf, disp_firewall_conf)
-            if len(sys.argv) > 5 and len(sys.argv[5]) > 0:
-                assert os.path.exists(sys.argv[5]), "Invalid firewall.conf location"
-                dispvm.firewall_conf = sys.argv[5]
-            if vm.qid != 0:
-                dispvm.uses_default_netvm = False
-                # netvm can be changed before restore,
-                # but cannot be enabled/disabled
-                if (dispvm.netvm is None) == (vm.dispvm_netvm is None):
-                    dispvm.netvm = vm.dispvm_netvm
-            # Wait for tar to finish
-            if tar_process.wait() != 0:
-                sys.stderr.write('Failed to unpack saved-cows.tar')
-                return None
-            print >>sys.stderr, "time=%s, VM starting" % (str(time.time()))
-            try:
-                dispvm.start()
-            except (MemoryError, QubesException) as e:
-                tray_notify_error(str(e))
-                raise
-            if vm.qid != 0:
-                # if need to enable/disable netvm, do it while DispVM is alive
-                if (dispvm.netvm is None) != (vm.dispvm_netvm is None):
-                    dispvm.netvm = vm.dispvm_netvm
-            print >>sys.stderr, "time=%s, VM started" % (str(time.time()))
-            qvm_collection.save()
-        finally:
-            qvm_collection.unlock_db()
-        # Reload firewall rules
-        print >>sys.stderr, "time=%s, reloading firewall" % (str(time.time()))
-        for vm in qvm_collection.values():
-            if vm.is_proxyvm() and vm.is_running():
-                vm.write_iptables_qubesdb_entry()
-
-        return dispvm
-
-    @staticmethod
-    def dvm_setup_ok():
-        dvmdata_dir = '/var/lib/qubes/dvmdata/'
-        if not os.path.isfile(current_savefile):
-            return False
-        if not os.path.isfile(dvmdata_dir+'default-savefile') or \
-                not os.path.isfile(dvmdata_dir+'savefile-root'):
-            return False
-        dvm_mtime = os.stat(current_savefile).st_mtime
-        root_mtime = os.stat(dvmdata_dir+'savefile-root').st_mtime
-        if dvm_mtime < root_mtime:
-            template_name = os.path.basename(
-                os.path.dirname(os.readlink(dvmdata_dir+'savefile-root')))
-            if subprocess.call(["xl", "domid", template_name],
-                               stdout=open(os.devnull, "w")) == 0:
-                tray_notify("For optimum performance, you should not "
-                            "start DispVM when its template is running.", "red")
-            return False       
-        return True
-
-    def get_dvm(self):
-        if not self.dvm_setup_ok():
-            if os.system("/usr/lib/qubes/"
-                         "qubes-update-dispvm-savefile-with-progress.sh"
-                         " >/dev/null </dev/null") != 0:
-                tray_notify_error("DVM savefile creation failed")
-                return None 
-        return self.do_get_dvm()
-
-    @staticmethod
-    def finish_disposable(name):
-        qvm_collection = QubesVmCollection()
-        qvm_collection.lock_db_for_writing()
-        qvm_collection.load()
-        vm = qvm_collection.get_vm_by_name(name)
-        if vm is None:
-            qvm_collection.unlock_db()
-            return False
-
-        try:
-            vm.force_shutdown()
-        except QubesException:
-            # VM already destroyed
-            pass
-        qvm_collection.pop(vm.qid)
-        qvm_collection.save()
-        qvm_collection.unlock_db()
-
-
-def main():
-    exec_index = sys.argv[1]
-    if exec_index == "FINISH":
-        QfileDaemonDvm.finish_disposable(sys.argv[2])
-        return
-
-    src_vmname = sys.argv[2]
-    user = sys.argv[3]
-    # accessed directly by get_dvm()
-    #  sys.argv[4] - override label
-    #  sys.argv[5] - override firewall
-
-    print >>sys.stderr, "time=%s, qfile-daemon-dvm init" % (str(time.time()))
-    tray_notify_init()
-    print >>sys.stderr, "time=%s, creating DispVM" % (str(time.time()))
-    qfile = QfileDaemonDvm(src_vmname)
-    dispvm = qfile.get_dvm()
-    if dispvm is not None:
-        if exec_index == "LAUNCH":
-            print dispvm.name
-            return
-
-        print >>sys.stderr, "time=%s, starting VM process" % (str(time.time()))
-        subprocess.call(['/usr/lib/qubes/qrexec-client', '-d', dispvm.name,
-                         user+':exec /usr/lib/qubes/qubes-rpc-multiplexer ' +
-                         exec_index + " " + src_vmname])
-        QfileDaemonDvm.finish_disposable(dispvm.name)
-
-main()

+ 0 - 86
dispvm/qubes-prepare-saved-domain.sh

@@ -1,86 +0,0 @@
-#!/bin/bash
-
-set -o pipefail
-
-get_encoded_script()
-{
-	ENCODED_SCRIPT=`
-		if [ "$1" == "vm-default" ]; then
-			echo /usr/lib/qubes/dispvm-prerun.sh
-		else
-			cat "$1"
-		fi | base64 -w0` || exit 1
-}
-
-if [ $# != 2 -a $# != 3 ] ; then
-	echo "usage: $0 domainname savefile_to_be_created [preload script]" >&2
-	exit 1
-fi
-export PATH=$PATH:/sbin:/usr/sbin
-if [ $# = 3 ] ; then
-	get_encoded_script $3
-fi
-VMDIR=/var/lib/qubes/appvms/$1
-if ! [ -d $VMDIR ] ; then
-	echo "$VMDIR does not exist ?" >&2
-	exit 1
-fi
-if ! qvm-start $1 --dvm ; then
-	exit 1
-fi
-
-ID=`virsh -c xen:/// domid $1`
-echo "Waiting for DVM $1 ..." >&2
-if [ -n "$ENCODED_SCRIPT" ] ; then
-	qubesdb-write -d $1 /qubes-save-script "$ENCODED_SCRIPT"
-fi
-#set -x
-qubesdb-write -d $1 /qubes-save-request 1
-qubesdb-watch -d $1 /qubes-used-mem
-qubesdb-read -d $1 /qubes-gateway | \
-	cut -d . -f 3 | tr -d "\n" > $VMDIR/netvm-id.txt
-kill `cat /var/run/qubes/guid-running.$ID`
-# FIXME: get connection URI from core scripts
-virsh -c xen:/// detach-disk $1 xvdb
-MEM=$(qubesdb-read -d $1 /qubes-used-mem | grep '^[0-9]\+$' | head -n 1)
-echo "DVM boot complete, memory used=$MEM. Saving image..." >&2
-QMEMMAN_STOP=/var/run/qubes/do-not-membalance
-touch $QMEMMAN_STOP
-virsh -c xen:/// setmem $1 $MEM
-# Add some safety margin
-virsh -c xen:/// setmaxmem $1 $[ $MEM + 1024 ]
-# Stop qubesdb daemon now, so VM can restart it later
-kill `cat /var/run/qubes/qubesdb.$1.pid`
-sleep 1
-touch $2
-if ! virsh -c xen:/// save $1 $2; then
-	rm -f $QMEMMAN_STOP
-	qvm-kill $1
-	exit 1
-fi
-rm -f $QMEMMAN_STOP
-# Do not allow smaller allocation than 400MB. If that small number comes from
-# an error, it would prevent further savefile regeneration (because VM would
-# not start with too little memory). Also 'maxmem' depends on 'memory', so
-# 400MB is sane compromise.
-if [ "$MEM" -lt 409600 ]; then
-    qvm-prefs -s $1 memory 400
-else
-    qvm-prefs -s $1 memory $[ $MEM / 1024 ]
-fi
-ln -snf $VMDIR /var/lib/qubes/dvmdata/vmdir
-cd $VMDIR
-fstype=`df --output=fstype $VMDIR | tail -n 1`
-if [ "$fstype" = "tmpfs" ]; then
-    # bsdtar doesn't work on tmpfs because FS_IOC_FIEMAP ioctl isn't supported
-    # there
-    tar -cSf saved-cows.tar volatile.img || exit 1
-else
-    errors=`bsdtar -cSf saved-cows.tar volatile.img 2>&1`
-    if [ -n "$errors" ]; then
-        echo "Failed to create saved-cows.tar: $errors" >&2
-        rm -f saved-cows.tar
-        exit 1
-    fi
-fi
-echo "DVM savefile created successfully."

+ 0 - 12
dispvm/qubes-setupdvm.service

@@ -1,12 +0,0 @@
-[Unit]
-Description=Qubes DispVM startup setup
-After=qubes-core.service
-
-[Service]
-Type=oneshot
-ExecStart=/usr/lib/qubes/startup-dvm.sh
-
-[Install]
-WantedBy=multi-user.target
-# Cover legacy init.d script
-Alias=qubes_setupdvm.service

+ 0 - 23
dispvm/qubes-update-dispvm-savefile-with-progress.sh

@@ -1,23 +0,0 @@
-#!/bin/sh
-
-line1="<b>Please wait (up to 120s) while the DispVM savefile is being updated.</b>"
-line2="<i><small>This only happens when you have updated the template.</small></i>"
-line3="<i><small>Next time will be much faster.</small></i>"
-
-if [ -n "$KDE_FULL_SESSION" ]; then
-    br="<br/>"
-else
-    br="
-"
-fi
-notify-send --icon=/usr/share/qubes/icons/qubes.png --expire-time=120000 \
-                   "Updating default DispVM savefile" "$line1$br$line2$br$line3"
-
-ret=0
-
-rm -f /var/run/qubes/qvm-create-default-dvm.stdout
-if ! qvm-create-default-dvm --used-template --default-script >/var/run/qubes/qvm-create-default-dvm.stdout </dev/null ; then
-	ret=1
-fi
-
-exit $ret

+ 0 - 22
dispvm/startup-dvm.sh

@@ -1,22 +0,0 @@
-#!/bin/sh
-
-# Setup DispVM things at Qubes system startup
-
-printf "\x00\x00\x00\x00" > /var/run/qubes/dispVM.seq
-chown root:qubes /var/run/qubes/dispVM.seq
-chmod 660 /var/run/qubes/dispVM.seq
-DEFAULT=/var/lib/qubes/dvmdata/default-savefile
-# setup DispVM files only when they exists
-if [ -r $DEFAULT ]; then
-    if [ -f /var/lib/qubes/dvmdata/dont-use-shm ] ; then
-	ln -s $DEFAULT /var/run/qubes/current-savefile
-    else
-	mkdir -m 770 /dev/shm/qubes
-	chown root.qubes /dev/shm/qubes
-	cp -a $(readlink $DEFAULT) /dev/shm/qubes/current-savefile
-	chown root.qubes /dev/shm/qubes/current-savefile
-	chmod 660 /dev/shm/qubes/current-savefile
-	ln -s /dev/shm/qubes/current-savefile /var/run/qubes/current-savefile
-    fi
-fi
-

+ 0 - 1
linux/system-config/Makefile

@@ -7,7 +7,6 @@ install:
 	cp block-snapshot $(DESTDIR)/etc/xen/scripts
 	ln -s block-snapshot $(DESTDIR)/etc/xen/scripts/block-origin
 	install -d $(DESTDIR)/etc/xdg/autostart
-	install -m 0644 qubes-guid.desktop $(DESTDIR)/etc/xdg/autostart/
 	install -m 0644 qrexec-policy-agent.desktop $(DESTDIR)/etc/xdg/autostart/
 	install -m 0644 -D tmpfiles-qubes.conf $(DESTDIR)/usr/lib/tmpfiles.d/qubes.conf
 	install -d $(DESTDIR)/etc/dbus-1/system.d

+ 0 - 7
linux/system-config/qubes-guid.desktop

@@ -1,7 +0,0 @@
-[Desktop Entry]
-Name=Qubes Guid
-Comment=Starts Dom0 GUI daemon for Qubes VMs
-Icon=qubes
-Exec=qvm-run --all true
-Terminal=false
-Type=Application

+ 0 - 161
qvm-tools/qubes-prefs

@@ -1,161 +0,0 @@
-#!/usr/bin/python
-# -*- encoding: utf8 -*-
-#
-# The Qubes OS Project, http://www.qubes-os.org
-#
-# Copyright (C) 2012  Marek Marczykowski <marmarek@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 QubesHost
-from qubes.qubes import system_path
-from optparse import OptionParser
-import subprocess
-import os
-import sys
-from qubes.qubes import vmm
-
-
-def handle_vm(vms, label, new_value = None):
-    functions = { # label: [ getter, setter ],
-        'default-netvm': [ 'get_default_netvm', 'set_default_netvm' ],
-        'default-fw-netvm': [ 'get_default_fw_netvm', 'set_default_fw_netvm' ],
-        'default-template': [ 'get_default_template', 'set_default_template' ],
-        'clockvm': [ 'get_clockvm_vm', 'set_clockvm_vm' ],
-        'updatevm': [ 'get_updatevm_vm', 'set_updatevm_vm' ],
-    }
-    assert label in functions.keys()
-
-    if new_value:
-        if new_value == "none":
-            try:
-                vms.__getattribute__(functions[label][1])(None)
-            except Exception as e:
-                print >> sys.stderr, "ERROR: {0}".format(str(e))
-                exit(1)
-        else:
-            vm = vms.get_vm_by_name (new_value)
-            if vm is None:
-                print >> sys.stderr, "A VM with the name '{0}' does not exist in the system.".format(new_value)
-                exit(1)
-            try:
-                vms.__getattribute__(functions[label][1])(vm)
-            except Exception as e:
-                print >> sys.stderr, "ERROR: {0}".format(str(e))
-                exit(1)
-    else:
-        vm = vms.__getattribute__(functions[label][0])()
-        if vm is not None:
-            return vm.name
-        else:
-            return ""
-
-def handle_kernel(vms, label, new_value = None):
-    if new_value is not None:
-        if not os.path.exists(os.path.join(system_path["qubes_kernels_base_dir"], new_value)):
-            print >> sys.stderr, "Kernel version {0} not installed.".format(new_value)
-            print >> sys.stderr, "Available versions:"
-            for k in os.listdir(system_path["qubes_kernels_base_dir"]):
-                print >> sys.stderr, "  -", k
-            exit(1)
-        vms.set_default_kernel(new_value)
-    else:
-        return vms.get_default_kernel()
-
-preferences = {
-    "default-netvm": handle_vm,
-    "default-fw-netvm": handle_vm,
-    "default-template": handle_vm,
-    "clockvm": handle_vm,
-    "updatevm": handle_vm,
-    "default-kernel": handle_kernel,
-}
-
-def do_list(vms):
-    label_width = 18
-    fmt="{{0:<{0}}}: {{1}}".format(label_width)
-    for pref in sorted(preferences.items()):
-        print fmt.format (pref[0], pref[1](vms, pref[0]))
-
-def main():
-    usage = "usage: %prog [-l]\n"\
-            "usage: %prog [-g] <property>\n"\
-            "usage: %prog [-s] <property> <new-value>\n"\
-            "List/set various global 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", "--get", action="store_true", dest="do_get", default=False)
-
-    (options, args) = parser.parse_args ()
-
-    if options.do_list + options.do_set + options.do_get > 1:
-        print >> sys.stderr, "You can provide only one action at once!"
-        exit (1)
-
-    # Select action based on args count:
-    if not options.do_list and not options.do_get and not options.do_set:
-        if (len (args) < 1):
-            options.do_list = True
-        elif (len (args) == 1):
-            options.do_get = True
-        else:
-            options.do_set = True
-
-    vmm.offline_mode = True
-
-    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()
-
-    if options.do_set:
-        if len (args) < 2 or args[0] not in preferences.keys():
-            print >> sys.stderr, "You must specify the property and the new value you wish to set..."
-            print >> sys.stderr, "Available properties:"
-            for p in sorted(preferences.keys()):
-                print >> sys.stderr, "--> '{0}'".format(p)
-            exit (1)
-
-        pref = args[0]
-        new_value = args[1]
-        preferences[pref](qvm_collection, pref, new_value)
-        qvm_collection.save()
-        qvm_collection.unlock_db()
-
-    elif options.do_get:
-        if len (args) < 1 or args[0] not in preferences.keys():
-            print >> sys.stderr, "You must specify the property you wish to get..."
-            print >> sys.stderr, "Available properties:"
-            for p in sorted(preferences.keys()):
-                print >> sys.stderr, "--> '{0}'".format(p)
-            exit (1)
-        pref = args[0]
-        print preferences[pref](qvm_collection, pref)
-
-    else:
-        # do_list
-        do_list(qvm_collection)
-
-main()

+ 0 - 85
qvm-tools/qubes-set-updates

@@ -1,85 +0,0 @@
-#!/usr/bin/python2
-# -*- encoding: utf8 -*-
-#
-# The Qubes OS Project, http://www.qubes-os.org
-#
-# Copyright (C) 2014  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 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 optparse import OptionParser
-import optparse
-
-import os
-import sys
-from qubes.qubes import QubesVmCollection
-from qubes.qubesutils import updates_vms_toggle,updates_dom0_toggle,\
-    updates_dom0_status,updates_vms_status
-from qubes.qubes import vmm
-
-
-def main():
-
-    usage = "%prog enable|disable|status\n"\
-            "  Enable or disable globally checking for updates (both dom0 and VM)"
-    parser = OptionParser (usage)
-    parser.add_option("--offline-mode", dest="offline_mode",
-                      action="store_true", default=False,
-                      help=optparse.SUPPRESS_HELP)
-
-    (options, args) = parser.parse_args()
-
-    if len(args) < 1:
-        parser.error("You must provide an action")
-
-    action = args[0]
-    if action not in ['enable', 'disable', 'status']:
-        parser.error("Invalid action")
-
-    if options.offline_mode:
-        vmm.offline_mode = True
-
-    qvm_collection = QubesVmCollection()
-    if action == 'status':
-        qvm_collection.lock_db_for_reading()
-    else:
-        qvm_collection.lock_db_for_writing()
-    qvm_collection.load()
-    if action == 'enable':
-        updates_dom0_toggle(qvm_collection, True)
-        updates_vms_toggle(qvm_collection, True)
-    elif action == 'disable':
-        updates_dom0_toggle(qvm_collection, False)
-        updates_vms_toggle(qvm_collection, False)
-    else:
-        if updates_dom0_status(qvm_collection):
-            print "dom0: enabled"
-        else:
-            print "dom0: disabled"
-        status_vms = updates_vms_status(qvm_collection)
-        if status_vms is None:
-            print "vms: mixed"
-        elif status_vms:
-            print "vms: enabled"
-        else:
-            print "vms: disabled"
-
-    if action != 'status':
-        qvm_collection.save()
-    qvm_collection.unlock_db()
-
-if __name__ == "__main__":
-    main()

+ 0 - 86
qvm-tools/qvm-add-appvm

@@ -1,86 +0,0 @@
-#!/usr/bin/python2
-# -*- encoding: utf8 -*-
-#
-# 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 QubesException
-from optparse import OptionParser;
-import sys
-import os
-
-def main():
-    usage = "usage: %prog [options] <appvm-name> <vm-template-name>\n\n"\
-            "Adds an already installed appvm to the Qubes DB\n"\
-            "WARNING: Noramlly you would not need this command,\n"\
-            "and you would use qvm-create instead!"
-
-    parser = OptionParser (usage)
-    parser.add_option ("-p", "--path", dest="dir_path",
-                       help="Specify path to the template directory")
-    parser.add_option ("-c", "--conf", dest="conf_file",
-                       help="Specify the Xen VM .conf file to use\
-                       (relative to the template dir path)")
-    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) != 2):
-        parser.error ("You must specify at least the AppVM and TemplateVM names!")
-    vmname = args[0]
-    templatename = args[1]
-
-    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)
-
-    qvm_collection = QubesVmCollection()
-    qvm_collection.lock_db_for_writing()
-    qvm_collection.load()
-
-    if qvm_collection.get_vm_by_name(vmname) is not None:
-        print >> sys.stderr, "ERROR: A VM with the name '{0}' already exists in the system.".format(vmname)
-        exit(1)
-
-    template = qvm_collection.get_vm_by_name(templatename)
-    if template is None:
-        print >> sys.stderr, "ERROR: A Template VM with the name '{0}' does not exist in the system.".format(templatename)
-        exit(1)
-
-
-    vm = qvm_collection.add_new_vm("QubesAppVm", name=vmname, template=template,
-                                      conf_file=options.conf_file,
-                                      dir_path=options.dir_path)
-
-    try:
-        vm.verify_files()
-    except QubesException as err:
-        print >> sys.stderr, "ERROR: {0}".format(err)
-        qvm_collection.pop(vm.qid)
-        exit (1)
-
-    qvm_collection.save()
-    qvm_collection.unlock_db()
-    
-main()

+ 0 - 83
qvm-tools/qvm-add-template

@@ -1,83 +0,0 @@
-#!/usr/bin/python2
-# -*- encoding: utf8 -*-
-#
-# 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,vmm
-from qubes.qubes import QubesException
-from optparse import OptionParser;
-import sys
-import os
-
-def main():
-    usage = "usage: %prog [options] <vm-template-name>\n"\
-            "Adds an already installed template to the Qubes DB"
-          
-    parser = OptionParser (usage)
-    parser.add_option ("-p", "--path", dest="dir_path",
-                       help="Specify path to the template directory")
-    parser.add_option ("-c", "--conf", dest="conf_file",
-                       help="Specify the Xen VM .conf file to use\
-                       (relative to the template dir path)")
-
-    parser.add_option ("--rpm", action="store_true", dest="installed_by_rpm",
-                       help="Template files have been installed by RPM", 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 specify at least the TemplateVM name!")
-    vmname = args[0]
-
-    if hasattr(os, "geteuid") and os.geteuid() == 0:
-        if not options.force_root and not options.installed_by_rpm:
-            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)
-
-    vmm.offline_mode = True
-    qvm_collection = QubesVmCollection()
-    qvm_collection.lock_db_for_writing()
-    qvm_collection.load()
-
-    if qvm_collection.get_vm_by_name(vmname) is not None:
-        print >> sys.stderr, "ERROR: A VM with the name '{0}' already exists in the system.".format(vmname)
-        exit(1)
-
-    vm = qvm_collection.add_new_vm("QubesTemplateVm", name=vmname,
-                                         conf_file=options.conf_file,
-                                         dir_path=options.dir_path,
-                                         installed_by_rpm=options.installed_by_rpm)
-
-    try:
-        vm.verify_files()
-    except QubesException as err:
-        print >> sys.stderr, "ERROR: {0}".format(err)
-        qvm_collection.pop(vm.qid)
-        exit (1)
-
-    qvm_collection.save()
-    qvm_collection.unlock_db()
-    
-main()

+ 0 - 218
qvm-tools/qvm-backup

@@ -1,218 +0,0 @@
-#!/usr/bin/python2
-# -*- encoding: utf8 -*-
-#
-# 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 QubesException
-from qubes.backup import backup_prepare, backup_do
-from qubes.qubesutils import size_to_human
-from optparse import OptionParser
-import qubes.backup
-import os
-import sys
-import getpass
-from locale import getpreferredencoding
-
-def print_progress(progress):
-    print >> sys.stderr, "\r-> Backing up files: {0}%...".format (progress),
-
-def main():
-    usage = "usage: %prog [options] <backup-dir-path> [vms-to-be-included ...]"
-    parser = OptionParser (usage)
-
-    parser.add_option ("-x", "--exclude", action="append",
-                       dest="exclude_list", default=[],
-                       help="Exclude the specified VM from the backup (may be "
-                            "repeated)")
-    parser.add_option ("--force-root", action="store_true", dest="force_root", default=False,
-                       help="Force to run with root privileges")
-    parser.add_option ("-d", "--dest-vm", action="store", dest="appvm",
-                       help="Specify the destination VM to which the backup "
-                            "will be sent (implies -e)")
-    parser.add_option ("-e", "--encrypt", action="store_true", dest="encrypt", default=False,
-                       help="Encrypt the backup")
-    parser.add_option ("--no-encrypt", action="store_true",
-                       dest="no_encrypt", default=False,
-                       help="Skip encryption even if sending the backup to a "
-                            "VM")
-    parser.add_option ("-p", "--passphrase-file", action="store",
-                       dest="pass_file", default=None,
-                       help="Read passphrase from a file, or use '-' to read "
-                            "from stdin")
-    parser.add_option ("-E", "--enc-algo", action="store",
-                       dest="crypto_algorithm", default=None,
-                       help="Specify a non-default encryption algorithm. For a "
-                            "list of supported algorithms, execute 'openssl "
-                            "list-cipher-algorithms' (implies -e)")
-    parser.add_option ("-H", "--hmac-algo", action="store",
-                       dest="hmac_algorithm", default=None,
-                       help="Specify a non-default HMAC algorithm. For a list "
-                            "of supported algorithms, execute 'openssl "
-                            "list-message-digest-algorithms'")
-    parser.add_option ("-z", "--compress", action="store_true", dest="compress", default=False,
-                       help="Compress the backup")
-    parser.add_option ("-Z", "--compress-filter", action="store",
-                       dest="compress_filter", default=False,
-                       help="Specify a non-default compression filter program "
-                            "(default: gzip)")
-    parser.add_option("--tmpdir", action="store", dest="tmpdir", default=None,
-                      help="Specify a temporary directory (if you have at least "
-                           "1GB free RAM in dom0, use of /tmp is advised) ("
-                           "default: /var/tmp)")
-    parser.add_option ("--debug", action="store_true", dest="debug",
-                       default=False, help="Enable (a lot of) debug output")
-
-    (options, args) = parser.parse_args ()
-
-    if (len (args) < 1):
-        print >> sys.stderr, "You must specify the target backup directory "\
-                             " (e.g. /mnt/backup)."
-        print >> sys.stderr, "qvm-backup will create a subdirectory there for "\
-                             " each individual backup."
-        exit (0)
-
-    base_backup_dir = 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 to permissions "\
-                                 "problems."
-            print >> sys.stderr, "Retry as an unprivileged user, or use "\
-                                 "--force-root to continue anyway."
-            exit(1)
-
-    # Only for locking
-    qvm_collection = QubesVmCollection()
-    qvm_collection.lock_db_for_reading()
-    qvm_collection.load()
-
-    vms = None
-    if (len (args) > 1):
-        vms = [qvm_collection.get_vm_by_name(vmname) for vmname in args[1:]]
-
-    if options.appvm:
-        options.exclude_list.append(options.appvm)
-
-    if options.appvm or options.crypto_algorithm:
-        options.encrypt = True
-    if options.no_encrypt:
-        options.encrypt = False
-    if options.debug:
-        qubes.backup.BACKUP_DEBUG = True
-    files_to_backup = None
-    try:
-        files_to_backup = backup_prepare(
-                vms_list=vms,
-                exclude_list=options.exclude_list,
-                hide_vm_names=options.encrypt)
-    except QubesException as e:
-        print >>sys.stderr, "ERROR: %s" % str(e)
-        exit(1)
-
-    total_backup_sz = reduce(lambda size, file: size+file["size"],
-            files_to_backup, 0)
-
-    if not options.appvm:
-        appvm = None
-
-        if os.path.isdir(base_backup_dir):
-            stat = os.statvfs(base_backup_dir)
-        else:
-            stat = os.statvfs(os.path.dirname(base_backup_dir))
-        backup_fs_free_sz = stat.f_bsize * stat.f_bavail
-        print
-        if (total_backup_sz > backup_fs_free_sz):
-            print >>sys.stderr, "ERROR: Not enough space available on the "\
-                                "backup filesystem!"
-            exit(1)
-
-        print "-> Available space: {0}".format(size_to_human(backup_fs_free_sz))
-    else:
-        appvm = qvm_collection.get_vm_by_name(options.appvm)
-        if appvm is None:
-            print >>sys.stderr, "ERROR: VM {0} does not exist!".format(options.appvm)
-            exit(1)
-
-        stat = os.statvfs('/var/tmp')
-        backup_fs_free_sz = stat.f_bsize * stat.f_bavail
-        print
-        if (backup_fs_free_sz < 1000000000):
-            print >>sys.stderr, "ERROR: Not enough space available " \
-                "on the local filesystem (1GB required for temporary files)!"
-            exit(1)
-
-        if not appvm.is_running():
-            appvm.start(verbose=True)
-
-    if options.appvm:
-        print >>sys.stderr, ("NOTE: VM {} will be excluded because it is "
-                             "the backup destination.").format(options.appvm)
-        options.exclude_list.append(options.appvm)
-
-    if not options.encrypt:
-        print >>sys.stderr, "WARNING: The backup will NOT be encrypted!"
-
-    if options.pass_file is not None:
-        f = open(options.pass_file) if options.pass_file != "-" else sys.stdin
-        passphrase = f.readline().rstrip()
-        if f is not sys.stdin:
-            f.close()
-
-    else:
-        if raw_input("Do you want to proceed? [y/N] ").upper() != "Y":
-            exit(0)
-
-        s = ("Please enter the passphrase that will be used to {}verify "
-             "the backup: ").format('encrypt and ' if options.encrypt else '')
-        passphrase = getpass.getpass(s)
-
-        if getpass.getpass("Enter again for verification: ") != passphrase:
-            print >>sys.stderr, "ERROR: Passphrase mismatch!"
-            exit(1)
-
-    encoding = sys.stdin.encoding or getpreferredencoding()
-    passphrase = passphrase.decode(encoding)
-
-    kwargs = {}
-    if options.hmac_algorithm:
-        kwargs['hmac_algorithm'] = options.hmac_algorithm
-    if options.crypto_algorithm:
-        kwargs['crypto_algorithm'] = options.crypto_algorithm
-    if options.tmpdir:
-        kwargs['tmpdir'] = options.tmpdir
-
-    try:
-        backup_do(base_backup_dir, files_to_backup, passphrase,
-                progress_callback=print_progress,
-                encrypted=options.encrypt,
-                compressed=options.compress_filter or options.compress,
-                appvm=appvm, **kwargs)
-    except QubesException as e:
-        print >>sys.stderr, "ERROR: %s" % str(e)
-        exit(1)
-
-    print
-    print "-> Backup completed."
-
-    qvm_collection.unlock_db()
-main()

+ 0 - 313
qvm-tools/qvm-backup-restore

@@ -1,313 +0,0 @@
-#!/usr/bin/python2
-# -*- encoding: utf8 -*-
-#
-# 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 multiprocessing import Event
-
-from qubes.qubes import QubesVmCollection
-from qubes.qubes import QubesException
-from qubes.backup import backup_restore_header
-from qubes.backup import backup_restore_prepare
-from qubes.backup import backup_restore_print_summary
-from qubes.backup import backup_restore_do
-import qubes.backup
-import sys
-from optparse import OptionParser
-from locale import getpreferredencoding
-
-import os
-import sys
-import getpass
-
-def main():
-    usage = "usage: %prog [options] <backup-dir> [vms-to-be-restored ...]"
-    parser = OptionParser (usage)
-
-    parser.add_option ("--verify-only", action="store_true",
-                       dest="verify_only", default=False,
-                       help="Verify backup integrity without restoring any "
-                            "data")
-
-    parser.add_option ("--skip-broken", action="store_true", dest="skip_broken", default=False,
-                       help="Do not restore VMs that have missing TemplateVMs "
-                            "or NetVMs")
-
-    parser.add_option ("--ignore-missing", action="store_true", dest="ignore_missing", default=False,
-                       help="Restore VMs even if their associated TemplateVMs "
-                            "and NetVMs are missing")
-
-    parser.add_option ("--skip-conflicting", action="store_true", dest="skip_conflicting", default=False,
-                       help="Do not restore VMs that are already present on "
-                            "the host")
-
-    parser.add_option ("--rename-conflicting", action="store_true",
-                       dest="rename_conflicting", default=False,
-                       help="Restore VMs that are already present on the host "
-                            "under different names")
-
-    parser.add_option ("--force-root", action="store_true", dest="force_root", default=False,
-                       help="Force to run with root privileges")
-
-    parser.add_option ("--replace-template", action="append", dest="replace_template", default=[],
-                       help="Restore VMs using another TemplateVM; syntax: "
-                            "old-template-name:new-template-name (may be "
-                            "repeated)")
-
-    parser.add_option ("-x", "--exclude", action="append", dest="exclude", default=[],
-                       help="Skip restore of specified VM (may be repeated)")
-
-    parser.add_option ("--skip-dom0-home", action="store_false", dest="dom0_home", default=True,
-                       help="Do not restore dom0 user home directory")
-
-    parser.add_option ("--ignore-username-mismatch", action="store_true", dest="ignore_username_mismatch", default=False,
-                       help="Ignore dom0 username mismatch when restoring home "
-                            "directory")
-
-    parser.add_option ("-d", "--dest-vm", action="store", dest="appvm",
-                       help="Specify VM containing the backup to be restored")
-
-    parser.add_option ("-e", "--encrypted", action="store_true", dest="decrypt", default=False,
-                       help="The backup is encrypted")
-
-    parser.add_option ("-p", "--passphrase-file", action="store",
-                       dest="pass_file", default=None,
-                       help="Read passphrase from file, or use '-' to read from stdin")
-
-    parser.add_option ("-z", "--compressed", action="store_true", dest="compressed", default=False,
-                       help="The backup is compressed")
-
-    parser.add_option ("--debug", action="store_true", dest="debug",
-                       default=False, help="Enable (a lot of) debug output")
-
-    (options, args) = parser.parse_args ()
-
-    if (len (args) < 1):
-        print >> sys.stderr, "You must specify the backup directory "\
-                             "(e.g. /mnt/backup/qubes-2010-12-01-235959)"
-        exit (0)
-
-    backup_dir = args[0]
-    vmlist = args[1:]
-
-    #if not os.path.exists (backup_dir):
-    #    print >> sys.stderr, "The backup directory doesn't exist!"
-    #    exit(1)
-
-    host_collection = QubesVmCollection()
-    host_collection.lock_db_for_writing()
-    host_collection.load()
-
-    restore_options = {}
-    if options.ignore_missing:
-        restore_options['use-default-template'] = True
-        restore_options['use-default-netvm'] = True
-    if options.replace_template:
-        restore_options['replace-template'] = options.replace_template
-    if options.rename_conflicting:
-        restore_options['rename-conflicting'] = True
-    if not options.dom0_home:
-        restore_options['dom0-home'] = False
-    if options.ignore_username_mismatch:
-        restore_options['ignore-username-mismatch'] = True
-    if options.exclude:
-        restore_options['exclude'] = options.exclude
-    if options.verify_only:
-        restore_options['verify-only'] = True
-    if options.debug:
-        qubes.backup.BACKUP_DEBUG = True
-
-    appvm = None
-    if options.appvm is not None:
-        appvm = host_collection.get_vm_by_name(options.appvm)
-        if appvm is None:
-            print >>sys.stderr, "ERROR: VM {0} does not exist".format(options.appvm)
-            exit(1)
-
-    if options.pass_file is not None:
-        f = open(options.pass_file) if options.pass_file != "-" else sys.stdin
-        passphrase = f.readline().rstrip()
-        if f is not sys.stdin:
-            f.close()
-    else:
-        passphrase = getpass.getpass("Please enter the passphrase to verify "
-                                     "and (if encrypted) decrypt the backup: ")
-
-    encoding = sys.stdin.encoding or getpreferredencoding()
-    passphrase = passphrase.decode(encoding)
-
-    print >> sys.stderr, "Checking backup content..."
-
-    error_detected = Event()
-    def error_callback(message):
-        error_detected.set()
-        print >> sys.stderr, message
-
-    restore_info = None
-    try:
-        restore_info = backup_restore_prepare(
-                backup_dir,
-                passphrase=passphrase,
-                options=restore_options,
-                host_collection=host_collection,
-                encrypted=options.decrypt,
-                compressed=options.compressed,
-                appvm=appvm,
-                error_callback=error_callback)
-    except QubesException as e:
-        print >> sys.stderr, "ERROR: %s" % str(e)
-        exit(1)
-
-    if len(vmlist) > 0:
-        for vm in restore_info.keys():
-            if vm.startswith('$'):
-                continue
-            if not vm in vmlist:
-                restore_info.pop(vm)
-
-    backup_restore_print_summary(restore_info)
-
-    there_are_conflicting_vms = False
-    there_are_missing_templates = False
-    there_are_missing_netvms = False
-    dom0_username_mismatch = False
-
-    for vm_info in restore_info.values():
-        if 'excluded' in vm_info and vm_info['excluded']:
-            continue
-        if 'missing-template' in vm_info.keys():
-            there_are_missing_templates = True
-        if 'missing-netvm' in vm_info.keys():
-            there_are_missing_netvms = True
-        if 'already-exists' in vm_info.keys():
-            there_are_conflicting_vms = True
-        if 'username-mismatch' in vm_info.keys():
-            dom0_username_mismatch = True
-
-    print
-
-    if hasattr(os, "geteuid") and os.geteuid() == 0:
-        print >> sys.stderr, "*** Running this tool as root is strongly "\
-                             "discouraged. This will lead to permissions "\
-                             "problems."
-        if options.force_root:
-            print >> sys.stderr, "Continuing as commanded. You have been "\
-                                 "warned."
-        else:
-            print >> sys.stderr, "Retry as an unprivileged user, or use "\
-                                 "--force-root to continue anyway."
-            exit(1)
-
-    if there_are_conflicting_vms:
-        print >> sys.stderr, "*** There are VMs with conflicting names on the "\
-                             "host! ***"
-        if options.skip_conflicting:
-            print >> sys.stderr, "Those VMs will not be restored. The host "\
-                                 "VMs will NOT be overwritten."
-        else:
-            print >> sys.stderr, "Remove VMs with conflicting names from the "\
-                                 "host before proceeding."
-            print >> sys.stderr, "Or use --skip-conflicting to restore only "\
-                                 "those VMs that do not exist on the host."
-            print >> sys.stderr, "Or use --rename-conflicting to restore " \
-                                 "those VMs under modified names (with "\
-                                 "numbers at the end)."
-            exit (1)
-
-    print "The above VMs will be copied and added to your system."
-    print "Exisiting VMs will NOT be removed."
-
-    if there_are_missing_templates:
-        print >> sys.stderr, "*** One or more TemplateVMs are missing on the"\
-                             "host! ***"
-        if not (options.skip_broken or options.ignore_missing):
-            print >> sys.stderr, "Install them before proceeding with the "\
-                                 "restore."
-            print >> sys.stderr, "Or pass: --skip-broken or --ignore-missing."
-            exit (1)
-        elif options.skip_broken:
-            print >> sys.stderr, "Skipping broken entries: VMs that depend on "\
-                                 "missing TemplateVMs will NOT be restored."
-        elif options.ignore_missing:
-            print >> sys.stderr, "Ignoring missing entries: VMs that depend "\
-                                 "on missing TemplateVMs will NOT be restored."
-        else:
-            print >> sys.stderr, "INTERNAL ERROR! Please report this to the "\
-                                 "Qubes OS team!"
-            exit (1)
-
-    if there_are_missing_netvms:
-        print >> sys.stderr, "*** One or more NetVMs are missing on the "\
-                             "host! ***"
-        if not (options.skip_broken or options.ignore_missing):
-            print >> sys.stderr, "Install them before proceeding with the "\
-                                 "restore."
-            print >> sys.stderr, "Or pass: --skip-broken or --ignore-missing."
-            exit (1)
-        elif options.skip_broken:
-            print >> sys.stderr, "Skipping broken entries: VMs that depend on "\
-                                 "missing NetVMs will NOT be restored."
-        elif options.ignore_missing:
-            print >> sys.stderr, "Ignoring missing entries: VMs that depend "\
-                                 "on missing NetVMs will NOT be restored."
-        else:
-            print >> sys.stderr, "INTERNAL ERROR! Please report this to the "\
-                                 "Qubes OS team!"
-            exit (1)
-
-    if 'dom0' in restore_info.keys() and options.dom0_home:
-        if dom0_username_mismatch:
-            print >> sys.stderr, "*** Dom0 username mismatch! This can break "\
-                                 "some settings! ***"
-            if not options.ignore_username_mismatch:
-                print >> sys.stderr, "Skip restoring the dom0 home directory "\
-                                     "(--skip-dom0-home), or pass "\
-                                     "--ignore-username-mismatch to continue "\
-                                     "anyway."
-                exit(1)
-            else:
-                print >> sys.stderr, "Continuing as directed."
-        print >> sys.stderr, "NOTE: Before restoring the dom0 home directory, "\
-                             "a new directory named "\
-                             "'home-pre-restore-<current-time>' will be "\
-                             "created inside the dom0 home directory. If any "\
-                             "restored files conflict with existing files, "\
-                             "the existing files will be moved to this new "\
-                             "directory."
-
-    if options.pass_file is None:
-        if raw_input("Do you want to proceed? [y/N] ").upper() != "Y":
-            exit(0)
-
-    try:
-        backup_restore_do(restore_info,
-                host_collection=host_collection,
-                error_callback=error_callback)
-    except QubesException as e:
-        print >> sys.stderr, "ERROR: %s" % str(e)
-
-    host_collection.unlock_db()
-
-    if error_detected.is_set():
-        print "-> Completed with errors!"
-        exit(1)
-    else:
-        print "-> Done."
-main()

+ 0 - 152
qvm-tools/qvm-block

@@ -1,152 +0,0 @@
-#!/usr/bin/python2
-# -*- encoding: utf8 -*-
-#
-# The Qubes OS Project, http://www.qubes-os.org
-#
-# Copyright (C) 2010  Marek Marczykowski <marmarek@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, QubesException
-from qubes.qubesutils import block_list,block_attach,block_detach,block_detach_all,block_check_attached
-from qubes.qubesutils import kbytes_to_kmg, bytes_to_kmg
-from optparse import OptionParser
-import subprocess
-import sys
-import os
-
-def main():
-    usage = "usage: %prog -l [options]\n"\
-            "usage: %prog -a [options] <vm-name> <device-vm-name>:<device>\n"\
-            "usage: %prog -A [options] <vm-name> <file-vm-name>:<file>\n"\
-            "usage: %prog -d [options] <device-vm-name>:<device>\n"\
-            "usage: %prog -d [options] <vm-name>\n"\
-            "List/set VM block devices."
-
-    parser = OptionParser (usage)
-    parser.add_option ("-l", "--list", action="store_true", dest="do_list", default=False)
-    parser.add_option ("-A", "--attach-file", action="store_true", dest="do_file_attach", default=False,
-                        help="Attach specified file instead of physical device")
-    parser.add_option ("-a", "--attach", action="store_true", dest="do_attach", default=False)
-    parser.add_option ("-d", "--detach", action="store_true", dest="do_detach", default=False)
-    parser.add_option ("-f", "--frontend", dest="frontend", 
-                        help="Specify device name at destination VM [default: xvdi]")
-    parser.add_option ("--ro", dest="ro", action="store_true", default=False,
-                        help="Force read-only mode")
-    parser.add_option ("--no-auto-detach", dest="auto_detach", action="store_false", default=True,
-                        help="Fail when device already connected to other VM")
-    parser.add_option ("--show-system-disks", dest="system_disks", action="store_true", default=False,
-                        help="List also system disks")
-    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 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_file_attach:
-        options.do_attach = True
-
-    if options.do_list + options.do_attach + options.do_detach > 1:
-        print >> sys.stderr, "Only one of -l -a/-A -d is allowed!"
-        exit (1)
-
-    qvm_collection = QubesVmCollection()
-    qvm_collection.lock_db_for_reading()
-    qvm_collection.load()
-    qvm_collection.unlock_db()
-
-    if options.do_attach:
-        if len(args) != 2:
-            parser.error ("You must provide vm name and device!")
-        vm = qvm_collection.get_vm_by_name(args[0])
-        if vm is None:
-            parser.error ("Invalid VM name: %s" % args[0])
-        # FIXME: here we assume that device is always in form "domain:dev", which can be changed in the future
-        if args[1].find(":") < 0:
-            parser.error ("Invalid device syntax (missing VM name): %s" % args[1])
-        if options.do_file_attach:
-            dev = {}
-            (dev['vm'], dev['device']) = args[1].split(":")
-            dev['desc'] = dev['device']
-            dev['mode'] = 'w'
-        else:
-            dev_list = block_list(qvm_collection)
-            if not args[1] in dev_list.keys():
-                parser.error ("Invalid device name: %s" % args[1])
-            dev = dev_list[args[1]]
-        kwargs = {}
-        if options.frontend:
-            kwargs['frontend'] = options.frontend
-        if options.ro:
-            kwargs['mode'] = "r"
-        else:
-            kwargs['mode'] = dev['mode']
-        kwargs['auto_detach'] = options.auto_detach
-        try:
-            block_attach(qvm_collection, vm, dev, **kwargs)
-        except QubesException as e:
-            print >> sys.stderr, "ERROR: %s" % str(e)
-            sys.exit(1)
-    elif options.do_detach:
-        if (len (args) < 1):
-            parser.error ("You must provide device or vm name!")
-        if len(args) > 1:
-             parser.error ("Too many parameters")
-        # Check if provided name is VM
-        vm = qvm_collection.get_vm_by_name(args[0])
-        if vm is not None:
-            kwargs = {}
-            if options.frontend:
-                kwargs['frontend'] = options.frontend
-                block_detach(vm, **kwargs)
-            else:
-                block_detach_all(vm)
-        else:
-            # Maybe device?
-            dev_list = block_list(qvm_collection)
-            if not args[0] in dev_list.keys():
-                parser.error ("Invalid VM or device name: %s" % args[0])
-            dev = dev_list[args[0]]
-            attached_to = block_check_attached(qvm_collection, dev)
-            if attached_to is None:
-                print >> sys.stderr, "WARNING: Device not connected to any VM"
-                exit(0)
-            block_detach(attached_to['vm'], attached_to['frontend'])
-    else:
-        # do_list
-        if len(args) > 0:
-            parser.error ("Too many parameters")
-        kwargs = {}
-        kwargs['qvmc'] = qvm_collection
-        kwargs['system_disks'] = options.system_disks
-        for dev in block_list(**kwargs).values():
-            attached_to = block_check_attached(qvm_collection, dev)
-            attached_to_str = ""
-            if attached_to:
-                attached_to_str = " (attached to '%s' as '%s')" % (
-                    attached_to['vm'].name, attached_to['frontend'])
-            size_str = bytes_to_kmg(dev['size'])
-            print "%s\t%s %s%s" % (dev['name'], dev['desc'], size_str, attached_to_str)
-        exit (0)
-
-main()

+ 0 - 81
qvm-tools/qvm-check

@@ -1,81 +0,0 @@
-#!/usr/bin/python2
-# -*- encoding: utf8 -*-
-#
-# The Qubes OS Project, http://www.qubes-os.org
-#
-# Copyright (C) 2011  Marek Marczykowski <marmarek@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,QubesException
-from optparse import OptionParser
-import sys
-import time
-
-def main():
-    usage = """usage: %prog [options] <vm-name>\n
-Specify no state options to check if VM exists"""
-    parser = OptionParser (usage)
-
-    parser.add_option ("-q", "--quiet", action="store_false", dest="verbose", default=True)
-    parser.add_option ("--running", action="store_true", dest="running", default=False,
-    help="Determine if VM is running")
-    parser.add_option ("--paused", action="store_true", dest="paused", default=False,
-    help="Determine if VM is paused")
-    parser.add_option ("--template", action="store_true", dest="template", default=False,
-    help="Determine if VM is a template")
-
-    (options, args) = parser.parse_args ()
-    if (len (args) != 1):
-        parser.error ("You must specify VM name!")
-
-    qvm_collection = QubesVmCollection()
-    qvm_collection.lock_db_for_reading()
-    qvm_collection.load()
-    qvm_collection.unlock_db()
-
-    vmname = args[0]
-    vm = qvm_collection.get_vm_by_name(vmname)
-    if vm is None:
-        if options.verbose:
-            print >> sys.stderr, "A VM with the name '{0}' does not exist in the system!".format(vmname)
-        exit(1)
-
-    elif options.running:
-        vm_state = not vm.is_running()
-        if options.verbose:
-            print >> sys.stderr, "A VM with the name {0} is {1}running.".format(vmname, "not " * vm_state)
-        exit(vm_state)
-
-    elif options.paused:
-        vm_state = not vm.is_paused()
-        if options.verbose:
-            print >> sys.stderr, "A VM with the name {0} is {1}paused.".format(vmname, "not " * vm_state)
-        exit(vm_state)
-
-    elif options.template:
-        vm_state = not vm.is_template()
-        if options.verbose:
-            print >> sys.stderr, "A VM with the name {0} is {1}a template.".format(vmname, "not " * vm_state)
-        exit(vm_state)
-
-    else:
-        if options.verbose:
-            print >> sys.stderr, "A VM with the name '{0}' does exist.".format(vmname)
-        exit(0)
-
-main()

+ 0 - 105
qvm-tools/qvm-clone

@@ -1,105 +0,0 @@
-#!/usr/bin/python2
-# -*- encoding: utf8 -*-
-#
-# 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.
-
-import os
-import sys
-from optparse import OptionParser
-
-from qubes.qubes import QubesVmCollection
-
-
-def main():
-    usage = "usage: %prog [options] <src-name> <new-name>\n"\
-            "Clones an existing VM by copying all its disk files"
-
-    parser = OptionParser(usage)
-    parser.add_option("-q", "--quiet", action="store_false", dest="verbose",
-                      default=True)
-    parser.add_option("-p", "--path", dest="dir_path",
-                      help="Specify path to the template directory")
-    parser.add_option("--force-root", action="store_true", dest="force_root",
-                      default=False,
-                      help="Force to run, even with root privileges")
-    parser.add_option("-P", "--pool", dest="pool_name",
-                      help="Specify in to which storage pool to clone")
-
-    (options, args) = parser.parse_args()
-    if (len(args) != 2):
-        parser.error(
-            "You must specify at least the src and dst TemplateVM names!")
-    srcname = args[0]
-    dstname = args[1]
-
-    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)
-
-    qvm_collection = QubesVmCollection()
-    qvm_collection.lock_db_for_writing()
-    qvm_collection.load()
-
-    src_vm = qvm_collection.get_vm_by_name(srcname)
-    if src_vm is None:
-        print >> sys.stderr, \
-            "ERROR: A VM with the name '{0}' does not exist in the system." \
-            .format(srcname)
-        exit(1)
-
-    if options.pool_name is None:
-        pool_name = src_vm.pool_name
-    else:
-        pool_name = options.pool_name
-
-    if qvm_collection.get_vm_by_name(dstname) is not None:
-        print >> sys.stderr, \
-            "ERROR: A VM with the name '{0}' already exists in the system." \
-            .format(dstname)
-        exit(1)
-
-    if src_vm.is_disposablevm():
-        print >> sys.stderr, "ERROR: Clone not supported for this type of VM"
-        exit(1)
-
-    dst_vm = qvm_collection.add_new_vm(src_vm.__class__.__name__,
-                                       name=dstname, template=src_vm.template,
-                                       pool_name=pool_name,
-                                       dir_path=options.dir_path,
-                                       installed_by_rpm=False)
-
-    try:
-        dst_vm.clone_attrs(src_vm)
-        dst_vm.clone_disk_files(src_vm=src_vm, verbose=options.verbose)
-    except (IOError, OSError) as err:
-        print >> sys.stderr, "ERROR: {0}".format(err)
-        qvm_collection.pop(dst_vm.qid)
-        dst_vm.remove_from_disk()
-        exit(1)
-
-    qvm_collection.save()
-    qvm_collection.unlock_db()
-
-main()

+ 0 - 72
qvm-tools/qvm-create-default-dvm

@@ -1,72 +0,0 @@
-#!/bin/sh
-if [ $# != 1 -a $# != 2 -o $1 == "--help" -o $1 == "-h" ] ; then
-	echo 'Usage: qvm-create-default-dvm templatename|--default-template|--used-template [script-name|--default-script]'
-	exit 1
-fi
-export ROOT=/var/lib/qubes/dvmdata/savefile-root
-TEMPLATENAME=$1
-if [ "$TEMPLATENAME" = --used-template ] ; then
-	if [ -e $ROOT ] ; then
-		TEMPLATENAME=$(readlink $ROOT | sed -e 's/.root.img//' -e 's/.*\///')
-	else
-		TEMPLATENAME=--default-template
-	fi
-fi
-if [ "$TEMPLATENAME" = --default-template ] ; then
-	TEMPLATENAME=$(qubes-prefs --get default-template)
-	if [ "X"$TEMPLATENAME = "X" ] ; then
-		echo No default template ?
-		exit 1
-	fi
-fi
-
-if [ -z "$2" -o "X""$2" = "X""--default-script" ] ; then
-	SCRIPTNAME="vm-default"
-else
-	SCRIPTNAME=$2
-fi
-
-if ! [ -d "/var/lib/qubes/vm-templates/$TEMPLATENAME" ] ; then
-	echo /var/lib/qubes/vm-templates/$TEMPLATENAME is not a directory
-	exit 1
-fi
-DVMTMPL="$TEMPLATENAME"-dvm
-DVMTMPLDIR="/var/lib/qubes/appvms/$DVMTMPL"
-if ! [ -d "$DVMTMPLDIR" ] ; then
-	# unfortunately, currently there are reliability issues with save of a domain
-	# with multiple CPUs and/or more than 4000M RAM
-	if ! qvm-create --force-root --vcpus=1 --internal -t "$TEMPLATENAME" -l gray "$DVMTMPL" ; then exit 1 ; fi
-	MAXMEM=`qvm-prefs --force-root $DVMTMPL|grep ^maxmem|awk '{print $3}'`
-	if [ "$MAXMEM" -ge 4000 ]; then
-		qvm-prefs --force-root -s $DVMTMPL maxmem 4000
-	fi
-fi
-if ! /usr/lib/qubes/qubes-prepare-saved-domain.sh \
-	"$DVMTMPL" "/var/lib/qubes/appvms/$DVMTMPL/dvm-savefile" $SCRIPTNAME ; then
-	exit 1
-fi
-DEFAULT=/var/lib/qubes/dvmdata/default-savefile
-CURRENT=/var/run/qubes/current-savefile
-SHMDIR=/dev/shm/qubes
-SHMCOPY=$SHMDIR/current-savefile
-rm -f $ROOT $DEFAULT $CURRENT
-ln -s "/var/lib/qubes/appvms/$DVMTMPL/dvm-savefile" $DEFAULT
-ln -s "/var/lib/qubes/vm-templates/$TEMPLATENAME/root.img" $ROOT
-if [ -f /var/lib/qubes/dvmdata/dont-use-shm ] ; then
-	ln -s $DEFAULT $CURRENT
-else
-	mkdir -m 770 $SHMDIR 2>/dev/null
-	chgrp qubes $SHMDIR 2>/dev/null
-	rm -f $SHMCOPY
-	cp $DEFAULT $SHMCOPY || exit 1
-	chgrp qubes $SHMCOPY
-	chmod 660 $SHMCOPY
-	ln -s $SHMCOPY $CURRENT
-fi 
-
-if [ $(whoami) = "root" ] ; then
-	chgrp qubes "$DVMTMPLDIR" "$DVMTMPLDIR"/*
-	chmod 660 "$DVMTMPLDIR"/*
-	chmod 770 "$DVMTMPLDIR"
-fi
-

+ 0 - 321
qvm-tools/qvm-firewall

@@ -1,321 +0,0 @@
-#!/usr/bin/python2
-# -*- encoding: utf8 -*-
-#
-# The Qubes OS Project, http://www.qubes-os.org
-#
-# Copyright (C) 2012  Marek Marczykowski <marmarek@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.
-#
-#
-import datetime
-
-from qubes.qubes import QubesVmCollection
-from optparse import OptionParser;
-import subprocess
-import sys
-import re
-import os
-import socket
-
-def parse_rule(args):
-    if len(args) < 2:
-        print >>sys.stderr, "ERROR: Rule must have at least address and protocol"
-        return None
-
-    address = args[0]
-    netmask = 32
-    proto = args[1]
-    port = args[2] if len(args) > 2 else None
-    port_end = None
-
-    unmask = address.split("/", 1)
-    if len(unmask) == 2:
-        address = unmask[0]
-        netmask = unmask[1]
-        if netmask.isdigit():
-            if re.match("^([0-9]{1,3}\.){3}[0-9]{1,3}$", address) is None:
-                print >>sys.stderr, "ERROR: Only IP is allowed when specyfying netmask"
-                return None
-            if netmask != "":
-                netmask = int(unmask[1])
-                if netmask < 0 or netmask > 32:
-                    print >>sys.stderr, "ERROR: Invalid netmask"
-                    return None
-        else:
-            print >>sys.stderr, "ERROR: Invalid netmask"
-            return None
-
-    if address[-1:] == ".":
-        address = address[:-1]
-
-    allowed = re.compile("(?!-)[A-Z\d-]{1,63}(?<!-)$", re.IGNORECASE)
-    if not all(allowed.match(x) for x in address.split(".")):
-        print >>sys.stderr, "ERROR: Invalid hostname"
-        return None
-
-    proto_split = proto.split('/', 1)
-    if len(proto_split) == 2:
-        proto = proto_split[0]
-        port = proto_split[1]
-
-    if proto not in ['tcp', 'udp', 'any']:
-        print >>sys.stderr, "ERROR: Protocol must be one of: 'tcp', 'udp', 'any'"
-        return None
-
-    if proto != "any" and port is None:
-        print >>sys.stderr, "ERROR: Port required for protocol %s" % args[1]
-        return None
-
-    if port is not None:
-        port_range = port.split('-', 1)
-        if len(port_range) == 2:
-            port = port_range[0]
-            port_end = port_range[1]
-
-        if port.isdigit():
-            port = int(port)
-        else:
-            try:
-                port = socket.getservbyname(port)
-            except socket.error:
-                print >>sys.stderr, "ERROR: Invalid port/service name '%s'" % port
-                return None
-
-        if port_end is not None and not port_end.isdigit():
-            print >>sys.stderr, "ERROR: Invalid port '%s'" % port_end
-            return None
-
-        if port_end is not None:
-            port_end = int(port_end)
-
-    rule = {}
-    rule['address'] = address
-    rule['netmask'] = netmask
-    rule['proto'] = proto
-    rule['portBegin'] = port
-    rule['portEnd'] = port_end
-    return rule
-
-def list_rules(rules, numeric=False):
-    fields = [ "num", "address", "proto", "port(s)" ]
-
-    rules_to_display = list()
-    counter = 1
-    for rule in rules:
-        parsed_rule = {
-            'num': "{0:>2}".format(counter),
-            'address': rule['address'] + ('/' + str(rule['netmask']) if rule['netmask'] < 32 else ""),
-            'proto': rule['proto'],
-            'port(s)': '',
-        }
-        if rule['proto'] in ['tcp', 'udp']:
-            parsed_rule['port(s)'] = str(rule['portBegin']) + \
-                ('-' + str(rule['portEnd']) if rule['portEnd'] is not None else '')
-            if not numeric and rule['portBegin'] is not None and rule['portEnd'] is None:
-                try:
-                    parsed_rule['port(s)'] = str(socket.getservbyport(rule['portBegin']))
-                except socket.error:
-                    pass
-
-        if 'expire' in rule:
-            parsed_rule['expire'] = str(datetime.datetime.fromtimestamp(rule[
-                'expire']))
-
-        rules_to_display.append(parsed_rule)
-        counter += 1
-
-    fields_width = {}
-    for f in fields:
-        fields_width[f] = len(f)
-        for r in rules_to_display:
-            if len(r[f]) > fields_width[f]:
-                fields_width[f] = len(r[f])
-
-    # Display the header
-    s = ""
-    for f in fields:
-        fmt="{{0:-^{0}}}-+".format(fields_width[f] + 1)
-        s += fmt.format('-')
-    print s
-
-    s = ""
-    for f in fields:
-        fmt=" {{0:^{0}}} |".format(fields_width[f])
-        s += fmt.format(f)
-    print s
-
-    s = ""
-    for f in fields:
-        fmt="{{0:-^{0}}}-+".format(fields_width[f] + 1)
-        s += fmt.format('-')
-    print s
-
-    # And the content
-    for r in rules_to_display:
-        s = ""
-        for f in fields:
-            fmt=" {{0:<{0}}} |".format(fields_width[f])
-            s += fmt.format(r[f])
-        if 'expire' in r:
-            s += " <-- expires at %s" % r['expire']
-        print s
-
-def display_firewall(conf, numeric=False):
-    print "Firewall policy: %s" % (
-            "ALLOW all traffic except" if conf['allow'] else "DENY all traffic except")
-    print "ICMP: %s" % ("ALLOW" if conf['allowIcmp'] else 'DENY')
-    print "DNS: %s" % ("ALLOW" if conf['allowDns'] else 'DENY')
-    print "Qubes yum proxy: %s" % ("ALLOW" if conf['allowYumProxy'] else 'DENY')
-    list_rules(conf['rules'], numeric)
-
-def add_rule(conf, args):
-    rule = parse_rule(args)
-    if rule is None:
-        return False
-
-    conf['rules'].append(rule)
-    return True
-
-def del_rule(conf, args):
-    if len(args) == 1 and args[0].isdigit():
-        rulenum = int(args[0])
-        if rulenum < 1 or rulenum > len(conf['rules']):
-            print >>sys.stderr, "ERROR: Rule number out of range"
-            return False
-        conf['rules'].pop(rulenum-1)
-    else:
-        rule = parse_rule(args)
-        #print "PARSED: %s" % str(rule)
-        #print "ALL: %s" % str(conf['rules'])
-        if rule is None:
-            return False
-        try:
-            conf['rules'].remove(rule)
-        except ValueError:
-            print >>sys.stderr, "ERROR: Rule not found"
-            return False
-
-    return True
-
-def allow_deny_value(s):
-    value = None
-    if s == "allow":
-        value = True
-    elif s == "deny":
-        value = False
-    else:
-        print >>sys.stderr, 'ERROR: Only "allow" or "deny" allowed'
-        exit(1)
-    return value
-
-def main():
-    usage =  "usage: %prog [-n] <vm-name> [action] [rule spec]\n"
-    usage += "       rule specification can be one of:\n"
-    usage += "         address|hostname[/netmask] tcp|udp port[-port]\n"
-    usage += "         address|hostname[/netmask] tcp|udp service_name\n"
-    usage += "         address|hostname[/netmask] any\n"
-    parser = OptionParser (usage)
-    parser.add_option ("-l", "--list", dest="do_list", action="store_true", default=True,
-            help="List firewall settings (default action)")
-    parser.add_option ("-a", "--add", dest="do_add", action="store_true", default=False,
-            help="Add rule")
-    parser.add_option ("-d", "--del", dest="do_del", action="store_true", default=False,
-            help="Remove rule (given by number or by rule spec)")
-    parser.add_option ("-P", "--policy", dest="set_policy", action="store", default=None,
-            help="Set firewall policy (allow/deny)")
-    parser.add_option ("-i", "--icmp", dest="set_icmp", action="store", default=None,
-            help="Set ICMP access (allow/deny)")
-    parser.add_option ("-D", "--dns", dest="set_dns", action="store", default=None,
-            help="Set DNS access (allow/deny)")
-    parser.add_option ("-Y", "--yum-proxy", dest="set_yum_proxy", action="store", default=None,
-            help="Set access to Qubes yum proxy (allow/deny)")
-    parser.add_option ("-r", "--reload", dest="reload", action="store_true",
-                       default=False, help="Reload firewall (implied by any "
-                                           "change action")
-
-    parser.add_option ("-n", "--numeric", dest="numeric", action="store_true", default=False,
-            help="Display port numbers instead of services (makes sense only with --list)")
-    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 specify VM name!")
-    vmname = args[0]
-    args = args[1:]
-
-    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_add or options.do_del or options.set_policy or \
-            options.set_icmp or options.set_dns or options.set_yum_proxy:
-        options.do_list = False
-    qvm_collection = QubesVmCollection()
-    if options.do_list:
-        qvm_collection.lock_db_for_reading()
-        qvm_collection.load()
-        qvm_collection.unlock_db()
-    else:
-        qvm_collection.lock_db_for_writing()
-        qvm_collection.load()
-
-    vm = qvm_collection.get_vm_by_name(vmname)
-    if vm is None:
-        print >> sys.stderr, "A VM with the name '{0}' does not exist in the system.".format(vmname)
-        exit(1)
-
-    changed = False
-    conf = vm.get_firewall_conf()
-
-    if options.set_policy:
-        conf['allow'] = allow_deny_value(options.set_policy)
-        changed = True
-    if options.set_icmp:
-        conf['allowIcmp'] = allow_deny_value(options.set_icmp)
-        changed = True
-    if options.set_dns:
-        conf['allowDns'] = allow_deny_value(options.set_dns)
-        changed = True
-    if options.set_yum_proxy:
-        conf['allowYumProxy'] = allow_deny_value(options.set_yum_proxy)
-        changed = True
-
-    if options.do_add:
-        changed = add_rule(conf, args)
-    elif options.do_del:
-        changed = del_rule(conf, args)
-    elif options.do_list and not options.reload:
-        if not vm.has_firewall():
-            print "INFO: This VM has no firewall rules set, below defaults are listed"
-        display_firewall(conf, options.numeric)
-
-    if changed:
-        vm.write_firewall_conf(conf)
-        qvm_collection.save()
-    if changed or options.reload:
-        if vm.is_running():
-            if vm.netvm is not None and vm.netvm.is_proxyvm():
-                vm.netvm.write_iptables_qubesdb_entry()
-
-    if not options.do_list:
-        qvm_collection.unlock_db()
-
-
-main()

+ 0 - 66
qvm-tools/qvm-grow-private

@@ -1,66 +0,0 @@
-#!/usr/bin/python2
-# -*- encoding: utf8 -*-
-#
-# The Qubes OS Project, http://www.qubes-os.org
-#
-# Copyright (C) 2011  Marek Marczykowski <marmarek@mimuw.edu.pl>
-#
-# 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 QubesException
-from qubes.qubesutils import parse_size
-from optparse import OptionParser
-import subprocess
-import os
-import re
-import sys
-
-qvm_run_path = "/usr/bin/qvm-run"
-
-def main():
-    usage = "usage: %prog <vm-name> <size>"
-    parser = OptionParser (usage)
-
-    (options, args) = parser.parse_args ()
-    if (len (args) != 2):
-        parser.error ("You must specify VM name and new size!")
-    vmname = args[0]
-    size = args[1]
-
-    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:
-        print >> sys.stderr, "A VM with the name '{0}' does not exist in the system.".format(vmname)
-        exit(1)
-
-    size_bytes = parse_size(size)
-
-    try:
-        vm.resize_private_img(size_bytes)
-    except (IOError, OSError, QubesException) as err:
-        print >> sys.stderr, "ERROR: {0}".format(err)
-        exit (1)
-
-    exit (0)
-
-
-main()

+ 0 - 72
qvm-tools/qvm-grow-root

@@ -1,72 +0,0 @@
-#!/usr/bin/python2
-# -*- encoding: utf8 -*-
-#
-# The Qubes OS Project, http://www.qubes-os.org
-#
-# Copyright (C) 2014  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 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 QubesException
-from qubes.qubesutils import parse_size
-from optparse import OptionParser
-import subprocess
-import os
-import re
-import sys
-
-def main():
-    usage = "usage: %prog <vm-name> <size>"
-    parser = OptionParser (usage)
-
-    parser.add_option("--allow-start", action="store_true",
-                      dest="allow_start", default=False,
-                      help="Allow VM to be started to complete the operation")
-
-    (options, args) = parser.parse_args ()
-    if (len (args) != 2):
-        parser.error ("You must specify VM name and new size!")
-    vmname = args[0]
-    size = args[1]
-
-    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:
-        print >> sys.stderr, "A VM with the name '{0}' does not exist in the system.".format(vmname)
-        exit(1)
-
-    size_bytes = parse_size(size)
-
-    if not hasattr(vm, 'resize_root_img'):
-        print >> sys.stderr, "Operation not supported for this VM type"
-        exit(1)
-
-    try:
-        vm.resize_root_img(size_bytes, allow_start=options.allow_start)
-    except (IOError, OSError, QubesException) as err:
-        print >> sys.stderr, "ERROR: {0}".format(err)
-        exit (1)
-
-    exit (0)
-
-
-main()

+ 0 - 35
qvm-tools/qvm-init-storage

@@ -1,35 +0,0 @@
-#!/usr/bin/python2
-# -*- encoding: utf8 -*-
-#
-# 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,vmm
-import sys
-
-def main():
-    vmm.offline_mode = True
-    qvm_collection = QubesVmCollection()
-    if qvm_collection.check_if_storage_exists():
-        print >> sys.stderr, "Storage exists, not overwriting."
-        exit(1)
-    qvm_collection.create_empty_storage()
-
-main()

+ 0 - 141
qvm-tools/qvm-pci

@@ -1,141 +0,0 @@
-#!/usr/bin/python2
-# -*- encoding: utf8 -*-
-#
-# The Qubes OS Project, http://www.qubes-os.org
-#
-# Copyright (C) 2010  Marek Marczykowski <marmarek@mimuw.edu.pl>
-#
-# 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 optparse import OptionParser
-import subprocess
-import os
-import sys
-from qubes.qubes import vmm
-import re
-
-
-def find_devices_of_class(klass):
-    p = subprocess.Popen(["/sbin/lspci", "-mm", "-n"], stdout=subprocess.PIPE)
-    result = p.communicate()
-    retcode = p.returncode
-    if retcode != 0:
-        print "ERROR when executing lspci!"
-        raise IOError
-
-    rx_netdev = re.compile(r"^([0-9a-f]{2}:[0-9a-f]{2}.[0-9a-f]) \"" +
-                           klass)
-    for dev in str(result[0]).splitlines():
-        match = rx_netdev.match(dev)
-        if match is not None:
-            dev_bdf = match.group(1)
-            assert dev_bdf is not None
-            yield dev_bdf
-
-
-def main():
-    usage = "usage: %prog -l [options] <vm-name>\n"\
-            "usage: %prog -a [options] <vm-name> <device>\n"\
-            "usage: %prog -d [options] <vm-name> <device>\n"\
-            "List/set VM PCI devices."
-
-    parser = OptionParser (usage)
-    parser.add_option ("-l", "--list", action="store_true", dest="do_list", default=False)
-    parser.add_option ("-a", "--add", action="store_true", dest="do_add", default=False)
-    parser.add_option ("-d", "--delete", action="store_true", dest="do_delete", default=False)
-    parser.add_option("-C", "--add-class", action="store_true",
-                      dest="do_add_class", default=False,
-                      help="Add all devices of given class (net, usb)")
-    parser.add_option ("--offline-mode", dest="offline_mode",
-                       action="store_true", default=False,
-                       help="Offline mode")
-
-    (options, args) = parser.parse_args ()
-    if (len (args) < 1):
-        parser.error ("You must provide at least the vmname!")
-
-    vmname = args[0]
-
-    if options.do_list + options.do_add + options.do_delete + \
-            options.do_add_class > 1:
-        print >> sys.stderr, "Only one of -l -a -d -C is allowed!"
-        exit(1)
-
-    if options.offline_mode:
-        vmm.offline_mode = True
-
-    if options.do_add or options.do_delete or options.do_add_class:
-        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_add:
-        if len (args) < 2:
-            print >> sys.stderr, "You must specify the PCI device to add"
-            exit (1)
-
-        pci = args[1]
-        vm.pci_add(pci)
-        qvm_collection.save()
-        qvm_collection.unlock_db()
-
-    elif options.do_add_class:
-        if len(args) < 2:
-            print >> sys.stderr, "You must specify the PCI device class to add"
-            exit(1)
-
-        klass = args[1]
-
-        if klass == 'net':
-            devs = find_devices_of_class("02")
-        elif klass == 'usb':
-            devs = find_devices_of_class("0c03")
-        else:
-            print >> sys.stderr, "Supported classes: net, usb"
-            exit(1)
-
-        for dev in devs:
-            vm.pci_add(dev)
-        qvm_collection.save()
-        qvm_collection.unlock_db()
-
-    elif options.do_delete:
-        if len (args) < 2:
-            print >> sys.stderr, "You must specify the PCI device to delete"
-            exit (1)
-
-        pci = args[1]
-        vm.pci_remove(pci)
-        qvm_collection.save()
-        qvm_collection.unlock_db()
-
-    else: 
-        # do_list
-        print str(vm.pcidevs)
-
-main()

+ 0 - 142
qvm-tools/qvm-revert-template-changes

@@ -1,142 +0,0 @@
-#!/usr/bin/python2
-# -*- encoding: utf8 -*-
-#
-# The Qubes OS Project, http://www.qubes-os.org
-#
-# Copyright (C) 2011  Marek Marczykowski <marmarek@mimuw.edu.pl>
-#
-# 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 QubesException
-from optparse import OptionParser
-import subprocess
-import os
-import time
-import glob
-import sys
-
-def main():
-    usage = "usage: %prog [options] <template-name>"
-    parser = OptionParser (usage)
-    parser.add_option ("--force", action="store_true", dest="force", default=False,
-            help="Do not prompt for confirmation")
-
-    (options, args) = parser.parse_args ()
-    if (len (args) != 1):
-        parser.error ("You must specify TemplateVM name!")
-    vmname = args[0]
-
-    if hasattr(os, "geteuid") and os.geteuid() != 0:
-        print >> sys.stderr, "ERROR: This tool must be run as root!"
-        exit(1)
-
-    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:
-        print >> sys.stderr, "A VM with the name '{0}' does not exist in the system.".format(vmname)
-        exit(1)
-
-    if not vm.is_template():
-        print >> sys.stderr, "A VM '{0}' is not template.".format(vmname)
-        exit(1)
-
-    if vm.is_running():
-        print >> sys.stderr, "You must stop VM first."
-        exit(1)
-
-    oldcow_img = vm.rootcow_img + '.old'
-    oldcow_stat = os.stat(oldcow_img)
-    oldcow_time_str = time.strftime("%F %T", time.gmtime(oldcow_stat.st_mtime))
-
-    root_stat = os.stat(vm.root_img)
-    old_dmdev = "/dev/mapper/snapshot-{0:x}:{1}-{2:x}:{3}".format(
-        root_stat[2], root_stat[1],
-        oldcow_stat[2], oldcow_stat[1])
-
-    snapshots = glob.glob('/dev/mapper/snapshot-{0:x}:{1}-*'.format(root_stat[2], root_stat[1]))
-    snapshot_present = False
-    for dev in snapshots:
-        if dev == old_dmdev:
-            snapshot_present = True
-        else:
-            print >> sys.stderr, "ERROR: You must shutdown all VMs running system older/newer than last good one."
-            exit(1)
-
-    root_blocks = os.path.getsize(vm.root_img)/512
-    if not snapshot_present:
-        p = subprocess.Popen (["/etc/xen/scripts/block-snapshot", "prepare",
-            "snapshot", "{0}:{1}".format(vm.root_img, oldcow_img)],
-            stdout=subprocess.PIPE)
-        result = p.communicate()
-        if result[0].strip() != old_dmdev:
-            print >> sys.stderr, "ERROR: Cannot create snapshot device ({0} != {1})".format(
-                    result[0].strip(), old_dmdev)
-            exit(1)
-
-
-    print "INFO: Reverting template changes done at {0}".format(oldcow_time_str)
-    if not options.force:
-        prompt = raw_input ("Do you want to proceed? [y/N] ")
-        if not (prompt == "y" or prompt == "Y"):
-            exit (0)
-
-    p = subprocess.Popen(["/sbin/dmsetup", "table", old_dmdev], stdout=subprocess.PIPE)
-    result = p.communicate()
-    dm_table = result[0]
-    dm_table_elements = dm_table.split(' ')
-    if dm_table_elements[2] != 'snapshot':
-        print >> sys.stderr, "ERROR: Unexpected device-mapper type ({0}). Template changes reverting already running".format(dm_table_elements[2])
-        exit(1)
-
-    dm_table_elements[2] = 'snapshot-merge'
-    dm_table = ' '.join(dm_table_elements)
-    subprocess.check_call(["/sbin/dmsetup", "reload", old_dmdev, "--table", dm_table])
-    # Reload new table into LIVE slot
-    subprocess.check_call(["/sbin/dmsetup", "suspend", old_dmdev])
-    subprocess.check_call(["/sbin/dmsetup", "resume", old_dmdev])
-    # Wait to snapshot merge completed
-    while True:
-        p = subprocess.Popen(["/sbin/dmsetup", "status", old_dmdev], stdout=subprocess.PIPE)
-        result = p.communicate()
-        status_details = result[0].split(' ')
-        blocks_used = status_details[3].split('/')[0]
-        if int(blocks_used) == int(status_details[4]):
-            break
-        print "\r-> Reverting template changes: {0} of {1} left".format(blocks_used, root_blocks),
-        time.sleep(1)
-    print "\r-> Reverting template changes: done                  ".format(blocks_used, root_blocks)
-
-    dm_table_elements[2] = 'snapshot'
-    dm_table = ' '.join(dm_table_elements)
-    subprocess.check_call(["/sbin/dmsetup", "reload", old_dmdev, "--table", dm_table])
-    # Reload new table into LIVE slot
-    subprocess.check_call(["/sbin/dmsetup", "suspend", old_dmdev])
-    subprocess.check_call(["/sbin/dmsetup", "resume", old_dmdev])
-
-    subprocess.check_call(["/etc/xen/scripts/block-snapshot", "cleanup",
-            "snapshot", old_dmdev])
-
-    os.rename(oldcow_img, vm.rootcow_img)
-    exit(0)
-
-
-main()

+ 0 - 98
qvm-tools/qvm-service

@@ -1,98 +0,0 @@
-#!/usr/bin/python
-# -*- encoding: utf8 -*-
-#
-# The Qubes OS Project, http://www.qubes-os.org
-#
-# Copyright (C) 2012  Marek Marczykowski <marmarek@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 optparse import OptionParser;
-import subprocess
-import sys
-import re
-
-def do_list(vm):
-    max_len = 0
-    for s in vm.services.keys():
-        max_len = max(max_len, len(s))
-    fmt="{{0:<{0}}}: {{1}}".format(max_len)
-
-    for s in vm.services.keys():
-        print fmt.format (s, "Enabled" if vm.services[s] else "Disabled")
-
-
-def main():
-    usage =  "usage: %prog <vm-name> [action] [service]\n"
-    parser = OptionParser (usage)
-    parser.add_option ("-l", "--list", dest="do_list", action="store_true", default=True,
-            help="List services (default action)")
-    parser.add_option ("-e", "--enable", dest="set_enable", action="store_true", default=False,
-            help="Enable service")
-    parser.add_option ("-d", "--disable", dest="set_disable", action="store_true", default=False,
-            help="Disable service")
-    parser.add_option ("-D", "--default", dest="set_default", action="store_true", default=False,
-            help="Reset service to its default state (remove from the list)")
-
-    (options, args) = parser.parse_args ()
-    if (len (args) < 1):
-        parser.error ("You must specify VM name!")
-    vmname = args[0]
-    args = args[1:]
-
-    if options.set_enable or options.set_disable or options.set_default:
-        if (len(args) < 1):
-            parser.error("You must specify service name!")
-        options.do_list = False
-
-    qvm_collection = QubesVmCollection()
-    if options.do_list:
-        qvm_collection.lock_db_for_reading()
-        qvm_collection.load()
-        qvm_collection.unlock_db()
-    else:
-        qvm_collection.lock_db_for_writing()
-        qvm_collection.load()
-
-    vm = qvm_collection.get_vm_by_name(vmname)
-    if vm is None:
-        print >> sys.stderr, "A VM with the name '{0}' does not exist in the system.".format(vmname)
-        exit(1)
-
-    changed = False
-    if options.do_list:
-        do_list(vm)
-    elif options.set_enable:
-        vm.services[args[0]] = True
-        changed = True
-    elif options.set_disable:
-        vm.services[args[0]] = False
-        changed = True
-    elif options.set_default:
-        if vm.services.has_key(args[0]):
-            vm.services.pop(args[0])
-            changed = True
-
-    if changed:
-        qvm_collection.save()
-
-    if not options.do_list:
-        qvm_collection.unlock_db()
-
-
-main()

+ 0 - 73
qvm-tools/qvm-template-commit

@@ -1,73 +0,0 @@
-#!/usr/bin/python2
-# -*- encoding: utf8 -*-
-#
-# The Qubes OS Project, http://www.qubes-os.org
-#
-# Copyright (C) 2011  Marek Marczykowski <marmarek@mimuw.edu.pl>
-#
-# 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,vmm
-from qubes.qubes import QubesException
-from optparse import OptionParser
-import subprocess
-import sys
-
-def main():
-    usage = "usage: %prog [options] <vm-name>"
-    parser = OptionParser (usage)
-    parser.add_option ("--offline-mode", dest="offline_mode",
-                       action="store_true", default=False,
-                       help="Offline mode")
-
-    (options, args) = parser.parse_args ()
-    if (len (args) != 1):
-        parser.error ("You must specify VM name!")
-    vmname = args[0]
-
-    if options.offline_mode:
-        vmm.offline_mode = True
-
-    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:
-        print >> sys.stderr, "A VM with the name '{0}' does not exist in the system.".format(vmname)
-        exit(1)
-
-    if not vm.is_template():
-        print >> sys.stderr, "A VM '{0}' is not template.".format(vmname)
-        exit(1)
-
-    if not vmm.offline_mode and vm.is_running():
-        print >> sys.stderr, "You must stop VM first."
-        exit(1)
-
-    try:
-        vm.verify_files()
-        vm.commit_changes()
-    except (IOError, OSError, QubesException) as err:
-        print >> sys.stderr, "ERROR: {0}".format(err)
-        exit (1)
-
-	exit (0)
-
-
-main()

+ 0 - 171
qvm-tools/qvm-trim-template

@@ -1,171 +0,0 @@
-#!/usr/bin/python2
-# -*- encoding: utf8 -*-
-#
-# The Qubes OS Project, http://www.qubes-os.org
-#
-# Copyright (C) 2014 Matt McCutchen <matt@mattmccutchen.net>
-# Copyright (C) 2015 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 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.
-#
-#
-
-import os
-import subprocess
-import sys
-import time
-from qubes import qubes
-from qubes import qubesutils
-
-
-def is_dvm_up_to_date(tmpl, dvm_tmpl):
-    dvm_savefile_path = os.path.join(dvm_tmpl.dir_path, "dvm-savefile")
-    if not os.path.isfile(dvm_savefile_path):
-        return False
-
-    dvm_mtime = os.path.getmtime(dvm_savefile_path)
-    root_mtime = os.path.getmtime(tmpl.root_img)
-    if dvm_mtime < root_mtime:
-        return False
-    else:
-        return True
-
-
-def main():
-    if len(sys.argv) != 2:
-        print >> sys.stderr, 'Usage: qvm-trim-template TEMPLATEVM_NAME'
-        sys.exit(1)
-
-    tvm_name = sys.argv[1]
-
-    qvm_collection = qubes.QubesVmCollection()
-    qvm_collection.lock_db_for_writing()
-    qvm_collection.load()
-
-    tvm = qvm_collection.get_vm_by_name(tvm_name)
-    if tvm is None:
-        print >> sys.stderr, 'VM \'{}\' does not exists'.format(tvm_name)
-        sys.exit(1)
-
-    if not tvm.is_template():
-        print >> sys.stderr, '{} is not template'.format(tvm_name)
-        sys.exit(1)
-
-    if tvm.is_running():
-        print >> sys.stderr, 'Please stop the TemplateVM first.'
-        sys.exit(1)
-
-    outdated_children = [c for c in qvm_collection.get_vms_based_on(tvm.qid) if
-                         c.is_outdated()]
-    if outdated_children:
-        print >> sys.stderr, 'Please stop (or restart) the following outdated VMs based on the template first:\n%s' % ', '.join(
-
-            c.name for c in outdated_children)
-        sys.exit(1)
-
-    rootcow_old = tvm.rootcow_img + '.old'
-    print 'Disk usage before:'
-    subprocess.check_call(['du', tvm.root_img] + (
-        ['--total', rootcow_old] if os.path.exists(rootcow_old) else []))
-
-    # root-cow.img.old is likely to be invalid once we trim root.img, so go ahead and delete it.
-    # (Note, root-cow.img should be logically empty because the TemplateVM is not running.)
-    if os.path.exists(rootcow_old):
-        os.remove(rootcow_old)
-
-    dvm_tmpl = qvm_collection.get_vm_by_name(tvm.name + '-dvm')
-    if dvm_tmpl is None:
-        touch_dvm_savefile = False
-    else:
-        touch_dvm_savefile = is_dvm_up_to_date(tvm, dvm_tmpl)
-
-    print >> sys.stderr, "Creating temporary VM..."
-    trim_vmname = "trim-{}".format(tvm_name[:31 - len('trim-')])
-    fstrim_vm = qvm_collection.get_vm_by_name(trim_vmname)
-    if fstrim_vm is not None:
-        if not fstrim_vm.internal:
-            print >>sys.stderr, \
-                "ERROR: VM '{}' already exists and is not marked as internal. " \
-                "Remove it manually."
-        fstrim_vm.remove_from_disk()
-        qvm_collection.pop(fstrim_vm.qid)
-    fstrim_vm = qvm_collection.add_new_vm(
-        "QubesAppVm",
-        template=tvm,
-        name=trim_vmname,
-        netvm=None,
-        internal=True,
-    )
-    if not fstrim_vm:
-        print >> sys.stderr, "ERROR: Failed to create new VM"
-        sys.exit(1)
-
-    fstrim_vm.create_on_disk()
-    fstrim_vm.start(start_guid=False, verbose=True)
-
-    print >> sys.stderr, "Performing fstrim now..."
-    fstrim_process = fstrim_vm.run("/bin/sh", user="root", passio_popen=True,
-                                   gui=False)
-    fstrim_process.stdin.write('''
-    until [ -r /dev/xvdi ]; do
-      sleep 1
-    done
-    mkdir /tmp/root
-    mount -o ro /dev/xvdi /tmp/root
-    fstrim -v /tmp/root
-    poweroff
-    ''')
-    fstrim_process.stdin.close()
-
-    qubesutils.block_attach(qvm_collection, fstrim_vm,
-                            {
-                                'vm': 'dom0',
-                                'device': tvm.root_img,
-                                'mode': 'w',
-                            },
-                            mode='w',
-                            frontend='xvdi')
-
-    # At this point, the trim should run and the vm should shut down by itself and
-    # detach the block device.
-
-    fstrim_process.wait()
-    print >> sys.stderr, "fstrim done, cleaning up..."
-
-    while fstrim_vm.is_running():
-        time.sleep(1)
-
-    fstrim_vm.remove_from_disk()
-    qvm_collection.pop(fstrim_vm.qid)
-
-    # if DispVM template was up to date, keep that state
-    if touch_dvm_savefile:
-        dvm_savefile_path = os.path.join(dvm_tmpl.dir_path, 'dvm-savefile')
-        os.utime(dvm_savefile_path, None)
-        # If this is default DispVM, make sure that tmpfs copy of the file
-        # (if enabled) also has mtime updated
-        if os.stat('/var/lib/qubes/dvmdata/default-savefile').st_ino == \
-                os.stat(dvm_savefile_path).st_ino:
-            os.utime('/var/run/qubes/current-savefile', None)
-
-    # do not save, all changes to qubes.xml should be reversed
-    qvm_collection.unlock_db()
-
-    print 'Disk usage after:'
-    subprocess.check_call(['du', tvm.root_img])
-
-
-if __name__ == "__main__":
-    main()

+ 0 - 141
qvm-tools/qvm-usb

@@ -1,141 +0,0 @@
-#!/usr/bin/python2
-# -*- encoding: utf8 -*-
-#
-# The Qubes OS Project, http://www.qubes-os.org
-#
-# Copyright (C) 2010  Marek Marczykowski <marmarek@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, QubesException
-from qubes.qubesutils import usb_list,usb_attach,usb_detach,usb_detach_all,usb_check_attached
-from optparse import OptionParser
-import sys
-import os
-
-def main():
-    usage = "usage: %prog -l [options]\n"\
-            "usage: %prog -a [options] <vm-name> <device-vm-name>:<device>\n"\
-            "usage: %prog -d [options] <device-vm-name>:<device>\n"\
-            "List/set VM USB devices."
-#            "usage: %prog -d [options] <vm-name>\n"\
-
-    parser = OptionParser (usage)
-    parser.add_option ("-l", "--list", action="store_true", dest="do_list", default=False)
-    parser.add_option ("-a", "--attach", action="store_true", dest="do_attach", default=False)
-    parser.add_option ("-d", "--detach", action="store_true", dest="do_detach", default=False)
-#    parser.add_option ("-f", "--frontend", dest="frontend", 
-#                        help="Specify device id at destination VM [default: first unused]")
-    parser.add_option ("--no-auto-detach", dest="auto_detach", action="store_false", default=True,
-                        help="Fail when device already connected to other VM")
-    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 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_attach + options.do_detach > 1:
-        print >> sys.stderr, "Only one of -l -a -d is allowed!"
-        exit (1)
-
-    qvm_collection = QubesVmCollection()
-    qvm_collection.lock_db_for_reading()
-    qvm_collection.load()
-    qvm_collection.unlock_db()
-
-    if options.do_attach:
-        if (len (args) != 2):
-            parser.error ("You must provide vm name and device!")
-        vm = qvm_collection.get_vm_by_name(args[0])
-        if vm is None:
-            parser.error ("Invalid VM name: %s" % args[0])
-
-        # FIXME: here we assume that device is always in form "domain:dev",
-        # which can be changed in the future
-        if args[1].find(":") < 0:
-            parser.error("Invalid device syntax: %s" % args[1])
-        backend_vm = qvm_collection.get_vm_by_name(args[1].split(":")[0])
-        if backend_vm is None:
-            parser.error("No such VM: {}".format(args[1].split(":")[0]))
-        dev_list = usb_list(qvm_collection, vm=backend_vm)
-        if not args[1] in dev_list.keys():
-            parser.error("Invalid device name: %s" % args[1])
-        dev = dev_list[args[1]]
-        assert backend_vm is not None
-
-        kwargs = {}
-#        if options.frontend:
-#            kwargs['frontend'] = options.frontend
-        kwargs['auto_detach'] = options.auto_detach
-        try:
-            usb_attach(qvm_collection, vm, dev, **kwargs)
-        except QubesException as e:
-            print >> sys.stderr, "ERROR: %s" % str(e)
-            sys.exit(1)
-    elif options.do_detach:
-        if (len (args) < 1):
-            parser.error ("You must provide device or vm name!")
-        if len(args) > 1:
-            parser.error ("Too many parameters")
-        # Check if provided name is VM
-        vm = qvm_collection.get_vm_by_name(args[0])
-        if vm is not None:
-            #kwargs = {}
-            #if options.frontend:
-            #    kwargs['frontend'] = options.frontend
-            #    usb_detach(vm, **kwargs)
-            #else:
-            usb_detach_all(qvm_collection, vm)
-        else:
-            # Maybe usbvm:device?
-
-            # FIXME: nasty copy-paste from attach code half a page above
-            # FIXME: here we assume that device is always in form "domain:dev",
-            # which can be changed in the future
-            if args[0].find(":") < 0:
-                parser.error("Invalid device syntax: %s" % args[0])
-            backend_vm = qvm_collection.get_vm_by_name(args[0].split(":")[0])
-            if backend_vm is None:
-                parser.error("No such VM: {}".format(args[0].split(":")[0]))
-            dev_list = usb_list(qvm_collection, vm=backend_vm)
-            if not args[0] in dev_list.keys():
-                parser.error("Invalid device name: %s" % args[0])
-            dev = dev_list[args[0]]
-            attached_to = usb_check_attached(qvm_collection, dev)
-            if attached_to is None:
-                print >> sys.stderr, "WARNING: Device not connected to any VM"
-                exit(0)
-            usb_detach(qvm_collection, attached_to, dev)
-    else:
-        if len(args) > 0:
-            parser.error("Too many parameters")
-        # do_list
-        for dev in usb_list(qvm_collection).values():
-            attached_to = dev['connected-to']
-            attached_to_str = ""
-            if attached_to:
-                attached_to_str = " (attached to %s)" % (attached_to.name)
-            print "%s\t%s%s" % (dev['name'], dev['desc'], attached_to_str)
-        exit (0)
-
-main()

+ 0 - 8
rpm_spec/core-dom0.spec

@@ -148,7 +148,6 @@ fi
 
 systemctl --no-reload enable qubes-core.service >/dev/null 2>&1
 systemctl --no-reload enable qubes-netvm.service >/dev/null 2>&1
-systemctl --no-reload enable qubes-setupdvm.service >/dev/null 2>&1
 
 # Conflicts with libxl stack, so disable it
 systemctl --no-reload disable xend.service >/dev/null 2>&1
@@ -404,20 +403,17 @@ fi
 
 /usr/lib/qubes/unbind-pci-device.sh
 /usr/lib/qubes/cleanup-dispvms
-/usr/lib/qubes/qfile-daemon-dvm*
 /usr/lib/qubes/block-cleaner-daemon.py*
 /usr/lib/qubes/vusb-ctl.py*
 /usr/lib/qubes/xl-qvm-usb-attach.py*
 /usr/lib/qubes/xl-qvm-usb-detach.py*
 /usr/lib/qubes/fix-dir-perms.sh
-/usr/lib/qubes/startup-dvm.sh
 /usr/lib/qubes/startup-misc.sh
 /usr/lib/qubes/prepare-volatile-img.sh
 /usr/libexec/qubes/qubes-notify-tools
 /usr/libexec/qubes/qubes-notify-updates
 %{_unitdir}/qubes-block-cleaner.service
 %{_unitdir}/qubes-core.service
-%{_unitdir}/qubes-setupdvm.service
 %{_unitdir}/qubes-netvm.service
 %{_unitdir}/qubes-qmemman.service
 %{_unitdir}/qubes-vm@.service
@@ -435,9 +431,6 @@ fi
 /usr/share/qubes/templates/libvirt/devices/pci.xml
 /usr/share/qubes/templates/libvirt/devices/net.xml
 /usr/lib/tmpfiles.d/qubes.conf
-/usr/lib/qubes/qubes-prepare-saved-domain.sh
-/usr/lib/qubes/qubes-update-dispvm-savefile-with-progress.sh
-/etc/xen/scripts/block.qubes
 /etc/xen/scripts/block-snapshot
 /etc/xen/scripts/block-origin
 /etc/xen/scripts/vif-route-qubes
@@ -456,7 +449,6 @@ fi
 /etc/qubes-rpc/qubes.NotifyUpdates
 %attr(2770,root,qubes) %dir /var/log/qubes
 %attr(0770,root,qubes) %dir /var/run/qubes
-/etc/xdg/autostart/qubes-guid.desktop
 /etc/xdg/autostart/qrexec-policy-agent.desktop
 
 /usr/share/doc/qubes/relaxng/*.rng