Wrap all VMM connection related object into QubesVMMConnection class

This makes easier to import right objects in submodules (only one
object). This also implement lazy connection - at first access, not at
module import, which speeds up tools, which doesn't need runtime
information (like qvm-prefs or qvm-service). In the future this will
ease migration from xenstore to QubesDB.

Also implement "offline mode" - operate on qubes.xml without connecting
to VMM - raise exception at such try.
This is needed to run tools during installation, where only minimal
set of services are started, especially no libvirt.
This commit is contained in:
Marek Marczykowski 2013-05-17 04:06:29 +02:00 committed by Marek Marczykowski-Górecki
parent 9f90106db4
commit b8c62c0279
10 changed files with 196 additions and 136 deletions

View File

@ -39,7 +39,7 @@ from qubes import qmemman_algo
import libvirt import libvirt
import warnings import warnings
from qubes.qubes import xs,dry_run,libvirt_conn from qubes.qubes import dry_run,vmm
from qubes.qubes import register_qubes_vm_class from qubes.qubes import register_qubes_vm_class
from qubes.qubes import QubesVmCollection,QubesException,QubesHost,QubesVmLabels from qubes.qubes import QubesVmCollection,QubesException,QubesHost,QubesVmLabels
from qubes.qubes import defaults,system_path,vm_files,qubes_max_qid from qubes.qubes import defaults,system_path,vm_files,qubes_max_qid
@ -202,6 +202,10 @@ class QubesVm(object):
attrs[prop]['save_skip'] = \ attrs[prop]['save_skip'] = \
lambda prop=prop: getattr(self, prop) is None 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['uuid']['save_skip'] = lambda: self.uuid is None
attrs['mac']['save'] = lambda: str(self._mac) attrs['mac']['save'] = lambda: str(self._mac)
attrs['mac']['save_skip'] = lambda: self._mac is None attrs['mac']['save_skip'] = lambda: self._mac is None
@ -304,7 +308,7 @@ class QubesVm(object):
self.netvm.connected_vms[self.qid] = self self.netvm.connected_vms[self.qid] = self
# Not in generic way to not create QubesHost() to frequently # Not in generic way to not create QubesHost() to frequently
if self.maxmem is None: if self.maxmem is None and not vmm.offline_mode:
qubes_host = QubesHost() qubes_host = QubesHost()
total_mem_mb = qubes_host.memory_total/1024 total_mem_mb = qubes_host.memory_total/1024
self.maxmem = total_mem_mb/2 self.maxmem = total_mem_mb/2
@ -314,7 +318,7 @@ class QubesVm(object):
self.maxmem = self.memory * 10 self.maxmem = self.memory * 10
# By default allow use all VCPUs # By default allow use all VCPUs
if self.vcpus is None: if self.vcpus is None and not vmm.offline_mode:
qubes_host = QubesHost() qubes_host = QubesHost()
self.vcpus = qubes_host.no_cpus self.vcpus = qubes_host.no_cpus
@ -648,7 +652,7 @@ class QubesVm(object):
def _update_libvirt_domain(self): def _update_libvirt_domain(self):
domain_config = self.create_config_file() domain_config = self.create_config_file()
self._libvirt_domain = libvirt_conn.defineXML(domain_config) self._libvirt_domain = vmm.libvirt_conn.defineXML(domain_config)
self.uuid = uuid.UUID(bytes=self._libvirt_domain.UUID()) self.uuid = uuid.UUID(bytes=self._libvirt_domain.UUID())
@property @property
@ -658,9 +662,9 @@ class QubesVm(object):
try: try:
if self.uuid is not None: if self.uuid is not None:
self._libvirt_domain = libvirt_conn.lookupByUUID(self.uuid.bytes) self._libvirt_domain = vmm.libvirt_conn.lookupByUUID(self.uuid.bytes)
else: else:
self._libvirt_domain = libvirt_conn.lookupByName(self.name) self._libvirt_domain = vmm.libvirt_conn.lookupByName(self.name)
self.uuid = uuid.UUID(bytes=self._libvirt_domain.UUID()) self.uuid = uuid.UUID(bytes=self._libvirt_domain.UUID())
except libvirt.libvirtError: except libvirt.libvirtError:
if libvirt.virGetLastError()[0] == libvirt.VIR_ERR_NO_DOMAIN: if libvirt.virGetLastError()[0] == libvirt.VIR_ERR_NO_DOMAIN:
@ -788,7 +792,7 @@ class QubesVm(object):
# TODO # TODO
uuid = self.uuid uuid = self.uuid
start_time = xs.read('', "/vm/%s/start_time" % str(uuid)) start_time = vmm.xs.read('', "/vm/%s/start_time" % str(uuid))
if start_time != '': if start_time != '':
return datetime.datetime.fromtimestamp(float(start_time)) return datetime.datetime.fromtimestamp(float(start_time))
else: else:
@ -820,7 +824,7 @@ class QubesVm(object):
# FIXME # FIXME
# 51712 (0xCA00) is xvda # 51712 (0xCA00) is xvda
# backend node name not available through xenapi :( # backend node name not available through xenapi :(
used_dmdev = xs.read('', "/local/domain/0/backend/vbd/{0}/51712/node".format(self.xid)) used_dmdev = vmm.xs.read('', "/local/domain/0/backend/vbd/{0}/51712/node".format(self.xid))
return used_dmdev != current_dmdev return used_dmdev != current_dmdev
@ -905,15 +909,15 @@ class QubesVm(object):
return return
dev_basepath = '/local/domain/%d/device/vif' % self.xid dev_basepath = '/local/domain/%d/device/vif' % self.xid
for dev in xs.ls('', dev_basepath): for dev in vmm.xs.ls('', dev_basepath):
# check if backend domain is alive # check if backend domain is alive
backend_xid = int(xs.read('', '%s/%s/backend-id' % (dev_basepath, dev))) backend_xid = int(vmm.xs.read('', '%s/%s/backend-id' % (dev_basepath, dev)))
if backend_xid in libvirt_conn.listDomainsID(): if backend_xid in vmm.libvirt_conn.listDomainsID():
# check if device is still active # check if device is still active
if xs.read('', '%s/%s/state' % (dev_basepath, dev)) == '4': if vmm.xs.read('', '%s/%s/state' % (dev_basepath, dev)) == '4':
continue continue
# remove dead device # remove dead device
xs.rm('', '%s/%s' % (dev_basepath, dev)) vmm.xs.rm('', '%s/%s' % (dev_basepath, dev))
def create_xenstore_entries(self, xid = None): def create_xenstore_entries(self, xid = None):
if dry_run: if dry_run:
@ -924,69 +928,69 @@ class QubesVm(object):
assert xid >= 0, "Invalid XID value" assert xid >= 0, "Invalid XID value"
domain_path = xs.get_domain_path(xid) domain_path = vmm.xs.get_domain_path(xid)
# Set Xen Store entires with VM networking info: # Set Xen Store entires with VM networking info:
xs.write('', "{0}/qubes-vm-type".format(domain_path), vmm.xs.write('', "{0}/qubes-vm-type".format(domain_path),
self.type) self.type)
xs.write('', "{0}/qubes-vm-updateable".format(domain_path), vmm.xs.write('', "{0}/qubes-vm-updateable".format(domain_path),
str(self.updateable)) str(self.updateable))
if self.is_netvm(): if self.is_netvm():
xs.write('', vmm.xs.write('',
"{0}/qubes-netvm-gateway".format(domain_path), "{0}/qubes-netvm-gateway".format(domain_path),
self.gateway) self.gateway)
xs.write('', vmm.xs.write('',
"{0}/qubes-netvm-secondary-dns".format(domain_path), "{0}/qubes-netvm-secondary-dns".format(domain_path),
self.secondary_dns) self.secondary_dns)
xs.write('', vmm.xs.write('',
"{0}/qubes-netvm-netmask".format(domain_path), "{0}/qubes-netvm-netmask".format(domain_path),
self.netmask) self.netmask)
xs.write('', vmm.xs.write('',
"{0}/qubes-netvm-network".format(domain_path), "{0}/qubes-netvm-network".format(domain_path),
self.network) self.network)
if self.netvm is not None: if self.netvm is not None:
xs.write('', "{0}/qubes-ip".format(domain_path), self.ip) vmm.xs.write('', "{0}/qubes-ip".format(domain_path), self.ip)
xs.write('', "{0}/qubes-netmask".format(domain_path), vmm.xs.write('', "{0}/qubes-netmask".format(domain_path),
self.netvm.netmask) self.netvm.netmask)
xs.write('', "{0}/qubes-gateway".format(domain_path), vmm.xs.write('', "{0}/qubes-gateway".format(domain_path),
self.netvm.gateway) self.netvm.gateway)
xs.write('', vmm.xs.write('',
"{0}/qubes-secondary-dns".format(domain_path), "{0}/qubes-secondary-dns".format(domain_path),
self.netvm.secondary_dns) self.netvm.secondary_dns)
tzname = self.get_timezone() tzname = self.get_timezone()
if tzname: if tzname:
xs.write('', vmm.xs.write('',
"{0}/qubes-timezone".format(domain_path), "{0}/qubes-timezone".format(domain_path),
tzname) tzname)
for srv in self.services.keys(): for srv in self.services.keys():
# convert True/False to "1"/"0" # convert True/False to "1"/"0"
xs.write('', "{0}/qubes-service/{1}".format(domain_path, srv), vmm.xs.write('', "{0}/qubes-service/{1}".format(domain_path, srv),
str(int(self.services[srv]))) str(int(self.services[srv])))
xs.write('', vmm.xs.write('',
"{0}/qubes-block-devices".format(domain_path), "{0}/qubes-block-devices".format(domain_path),
'') '')
xs.write('', vmm.xs.write('',
"{0}/qubes-usb-devices".format(domain_path), "{0}/qubes-usb-devices".format(domain_path),
'') '')
xs.write('', "{0}/qubes-debug-mode".format(domain_path), vmm.xs.write('', "{0}/qubes-debug-mode".format(domain_path),
str(int(self.debug))) str(int(self.debug)))
# Fix permissions # Fix permissions
xs.set_permissions('', '{0}/device'.format(domain_path), vmm.xs.set_permissions('', '{0}/device'.format(domain_path),
[{ 'dom': xid }]) [{ 'dom': xid }])
xs.set_permissions('', '{0}/memory'.format(domain_path), vmm.xs.set_permissions('', '{0}/memory'.format(domain_path),
[{ 'dom': xid }]) [{ 'dom': xid }])
xs.set_permissions('', '{0}/qubes-block-devices'.format(domain_path), vmm.xs.set_permissions('', '{0}/qubes-block-devices'.format(domain_path),
[{ 'dom': xid }]) [{ 'dom': xid }])
xs.set_permissions('', '{0}/qubes-usb-devices'.format(domain_path), vmm.xs.set_permissions('', '{0}/qubes-usb-devices'.format(domain_path),
[{ 'dom': xid }]) [{ 'dom': xid }])
# fire hooks # fire hooks
@ -1743,7 +1747,7 @@ class QubesVm(object):
# Bind pci devices to pciback driver # Bind pci devices to pciback driver
for pci in self.pcidevs: for pci in self.pcidevs:
nd = libvirt_conn.nodeDeviceLookupByName('pci_0000_' + pci.replace(':','_').replace('.','_')) nd = vmm.libvirt_conn.nodeDeviceLookupByName('pci_0000_' + pci.replace(':','_').replace('.','_'))
nd.dettach() nd.dettach()
self.libvirt_domain.createWithFlags(libvirt.VIR_DOMAIN_START_PAUSED) self.libvirt_domain.createWithFlags(libvirt.VIR_DOMAIN_START_PAUSED)

View File

@ -25,7 +25,7 @@ import sys
import os.path import os.path
import xen.lowlevel.xs import xen.lowlevel.xs
from qubes.qubes import QubesVm,register_qubes_vm_class,xs,dry_run from qubes.qubes import QubesVm,register_qubes_vm_class,vmm,dry_run
from qubes.qubes import defaults,system_path,vm_files from qubes.qubes import defaults,system_path,vm_files
from qubes.qubes import QubesVmCollection,QubesException from qubes.qubes import QubesVmCollection,QubesException
@ -115,7 +115,7 @@ class QubesNetVm(QubesVm):
super(QubesNetVm, self).create_xenstore_entries(xid) super(QubesNetVm, self).create_xenstore_entries(xid)
xs.write('', "/local/domain/{0}/qubes-netvm-external-ip".format(xid), '') vmm.xs.write('', "/local/domain/{0}/qubes-netvm-external-ip".format(xid), '')
self.update_external_ip_permissions(xid) self.update_external_ip_permissions(xid)
def update_external_ip_permissions(self, xid = -1): def update_external_ip_permissions(self, xid = -1):
@ -130,7 +130,7 @@ class QubesNetVm(QubesVm):
perms.append({ 'dom': xid, 'read': True }) perms.append({ 'dom': xid, 'read': True })
try: try:
xs.set_permissions('', '/local/domain/{0}/qubes-netvm-external-ip'.format(xid), vmm.xs.set_permissions('', '/local/domain/{0}/qubes-netvm-external-ip'.format(xid),
perms) perms)
except xen.lowlevel.xs.Error as e: except xen.lowlevel.xs.Error as e:
print >>sys.stderr, "WARNING: failed to update external IP " \ print >>sys.stderr, "WARNING: failed to update external IP " \

View File

@ -24,7 +24,7 @@
from qubes.qubes import QubesNetVm,register_qubes_vm_class from qubes.qubes import QubesNetVm,register_qubes_vm_class
from qubes.qubes import defaults from qubes.qubes import defaults
from qubes.qubes import QubesException,dry_run,libvirt_conn from qubes.qubes import QubesException,dry_run,vmm
import psutil import psutil
class QubesAdminVm(QubesNetVm): class QubesAdminVm(QubesNetVm):
@ -62,7 +62,7 @@ class QubesAdminVm(QubesNetVm):
return psutil.virtual_memory().total/1024 return psutil.virtual_memory().total/1024
def get_mem_static_max(self): def get_mem_static_max(self):
return libvirt_conn.getInfo()[1] return vmm.libvirt_conn.getInfo()[1]
def get_disk_usage(self, file_or_dir): def get_disk_usage(self, file_or_dir):
return 0 return 0

View File

@ -24,7 +24,7 @@
from datetime import datetime from datetime import datetime
from qubes.qubes import QubesNetVm,register_qubes_vm_class,xs,dry_run from qubes.qubes import QubesNetVm,register_qubes_vm_class,vmm,dry_run
from qubes.qubes import QubesVmCollection,QubesException from qubes.qubes import QubesVmCollection,QubesException
yum_proxy_ip = '10.137.255.254' yum_proxy_ip = '10.137.255.254'
@ -99,8 +99,8 @@ class QubesProxyVm(QubesNetVm):
super(QubesProxyVm, self).create_xenstore_entries(xid) super(QubesProxyVm, self).create_xenstore_entries(xid)
xs.write('', "/local/domain/{0}/qubes-iptables-error".format(xid), '') vmm.xs.write('', "/local/domain/{0}/qubes-iptables-error".format(xid), '')
xs.set_permissions('', "/local/domain/{0}/qubes-iptables-error".format(xid), vmm.xs.set_permissions('', "/local/domain/{0}/qubes-iptables-error".format(xid),
[{ 'dom': xid, 'write': True }]) [{ 'dom': xid, 'write': True }])
self.write_iptables_xenstore_entry() self.write_iptables_xenstore_entry()
@ -112,13 +112,13 @@ class QubesProxyVm(QubesNetVm):
xid = self.get_xid() xid = self.get_xid()
if self.netvm is None: if self.netvm is None:
xs.write('', "/local/domain/{0}/qubes-netvm-domid".format(xid), '') vmm.xs.write('', "/local/domain/{0}/qubes-netvm-domid".format(xid), '')
else: else:
xs.write('', "/local/domain/{0}/qubes-netvm-domid".format(xid), vmm.xs.write('', "/local/domain/{0}/qubes-netvm-domid".format(xid),
"{0}".format(self.netvm.get_xid())) "{0}".format(self.netvm.get_xid()))
def write_iptables_xenstore_entry(self): def write_iptables_xenstore_entry(self):
xs.rm('', "/local/domain/{0}/qubes-iptables-domainrules".format(self.get_xid())) vmm.xs.rm('', "/local/domain/{0}/qubes-iptables-domainrules".format(self.get_xid()))
iptables = "# Generated by Qubes Core on {0}\n".format(datetime.now().ctime()) iptables = "# Generated by Qubes Core on {0}\n".format(datetime.now().ctime())
iptables += "*filter\n" iptables += "*filter\n"
iptables += ":INPUT DROP [0:0]\n" iptables += ":INPUT DROP [0:0]\n"
@ -140,7 +140,7 @@ class QubesProxyVm(QubesNetVm):
# Deny inter-VMs networking # Deny inter-VMs networking
iptables += "-A FORWARD -i vif+ -o vif+ -j DROP\n" iptables += "-A FORWARD -i vif+ -o vif+ -j DROP\n"
iptables += "COMMIT\n" iptables += "COMMIT\n"
xs.write('', "/local/domain/{0}/qubes-iptables-header".format(self.get_xid()), iptables) vmm.xs.write('', "/local/domain/{0}/qubes-iptables-header".format(self.get_xid()), iptables)
vms = [vm for vm in self.connected_vms.values()] vms = [vm for vm in self.connected_vms.values()]
for vm in vms: for vm in vms:
@ -201,12 +201,12 @@ class QubesProxyVm(QubesNetVm):
iptables += "-A FORWARD -s {0} -j {1}\n".format(ip, default_action) iptables += "-A FORWARD -s {0} -j {1}\n".format(ip, default_action)
iptables += "COMMIT\n" iptables += "COMMIT\n"
xs.write('', "/local/domain/"+str(self.get_xid())+"/qubes-iptables-domainrules/"+str(xid), iptables) vmm.xs.write('', "/local/domain/"+str(self.get_xid())+"/qubes-iptables-domainrules/"+str(xid), iptables)
# no need for ending -A FORWARD -j DROP, cause default action is DROP # no need for ending -A FORWARD -j DROP, cause default action is DROP
self.write_netvm_domid_entry() self.write_netvm_domid_entry()
self.rules_applied = None self.rules_applied = None
xs.write('', "/local/domain/{0}/qubes-iptables".format(self.get_xid()), 'reload') vmm.xs.write('', "/local/domain/{0}/qubes-iptables".format(self.get_xid()), 'reload')
register_qubes_vm_class(QubesProxyVm) register_qubes_vm_class(QubesProxyVm)

View File

@ -28,7 +28,7 @@ import libvirt
import time import time
from qubes.qubes import QubesVm,QubesVmLabel,register_qubes_vm_class from qubes.qubes import QubesVm,QubesVmLabel,register_qubes_vm_class
from qubes.qubes import QubesDispVmLabels from qubes.qubes import QubesDispVmLabels
from qubes.qubes import dry_run,libvirt_conn from qubes.qubes import dry_run,vmm
from qubes.qmemman_client import QMemmanClient from qubes.qmemman_client import QMemmanClient
class QubesDisposableVm(QubesVm): class QubesDisposableVm(QubesVm):
@ -146,7 +146,7 @@ class QubesDisposableVm(QubesVm):
assert (len(self.pcidevs) == 0), "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())) print >>sys.stderr, "time=%s, calling restore" % (str(time.time()))
libvirt_conn.restoreFlags(self.disp_savefile, vmm.libvirt_conn.restoreFlags(self.disp_savefile,
domain_config, libvirt.VIR_DOMAIN_SAVE_PAUSED) domain_config, libvirt.VIR_DOMAIN_SAVE_PAUSED)
print >>sys.stderr, "time=%s, done, getting xid" % (str(time.time())) print >>sys.stderr, "time=%s, done, getting xid" % (str(time.time()))

View File

@ -30,7 +30,8 @@ import stat
import sys import sys
import re import re
import stat import stat
from qubes.qubes import QubesVm,register_qubes_vm_class,xs,dry_run
from qubes.qubes import QubesVm,register_qubes_vm_class,vmm,dry_run
from qubes.qubes import system_path,defaults from qubes.qubes import system_path,defaults
from qubes.qubes import QubesException from qubes.qubes import QubesException
@ -397,7 +398,7 @@ class QubesHVm(QubesVm):
if self.xid < 0: if self.xid < 0:
return -1 return -1
stubdom_xid_str = xs.read('', '/local/domain/%d/image/device-model-domid' % self.xid) stubdom_xid_str = vmm.xs.read('', '/local/domain/%d/image/device-model-domid' % self.xid)
if stubdom_xid_str is not None: if stubdom_xid_str is not None:
return int(stubdom_xid_str) return int(stubdom_xid_str)
else: else:

View File

@ -38,7 +38,6 @@ import atexit
dry_run = False dry_run = False
#dry_run = True #dry_run = True
if not dry_run: if not dry_run:
import libvirt import libvirt
import xen.lowlevel.xc import xen.lowlevel.xc
@ -108,22 +107,76 @@ qubes_max_netid = 254
class QubesException (Exception): class QubesException (Exception):
pass pass
def libvirt_error_handler(ctx, error): class QubesVMMConnection(object):
pass def __init__(self):
self._libvirt_conn = None
self._xs = None
self._xc = None
self._offline_mode = False
@property
def offline_mode(self):
return self._offline_mode
@offline_mode.setter
def offline_mode(self, value):
if not value and self._libvirt_conn is not None:
raise QubesException("Cannot change offline mode while already connected")
self._offline_mode = value
def _libvirt_error_handler(self, ctx, error):
pass
def init_vmm_connection(self):
if self._libvirt_conn is not None:
# Already initialized
return
if self._offline_mode:
# Do not initialize in offline mode
return
self._xc = xen.lowlevel.xc.xc()
self._xs = xen.lowlevel.xs.xs()
self._libvirt_conn = libvirt.open(defaults['libvirt_uri'])
if self._libvirt_conn == None:
raise QubesException("Failed connect to libvirt driver")
libvirt.registerErrorHandler(self._libvirt_error_handler, None)
atexit.register(self._libvirt_conn.close)
def _common_getter(self, name):
if self._offline_mode:
# Do not initialize in offline mode
raise QubesException("VMM operations disabled in offline mode")
if self._libvirt_conn is None:
self.init_vmm_connection()
return getattr(self, name)
@property
def libvirt_conn(self):
return self._common_getter('_libvirt_conn')
@property
def xs(self):
return self._common_getter('_xs')
@property
def xc(self):
return self._common_getter('_xc')
##### VMM global variable definition #####
if not dry_run: if not dry_run:
xc = xen.lowlevel.xc.xc() vmm = QubesVMMConnection()
xs = xen.lowlevel.xs.xs()
libvirt_conn = libvirt.open(defaults['libvirt_uri']) ##########################################
if libvirt_conn == None:
raise QubesException("Failed connect to libvirt driver")
libvirt.registerErrorHandler(libvirt_error_handler, None)
atexit.register(libvirt_conn.close)
class QubesHost(object): class QubesHost(object):
def __init__(self): def __init__(self):
(model, memory, cpus, mhz, nodes, socket, cores, threads) = libvirt_conn.getInfo() (model, memory, cpus, mhz, nodes, socket, cores, threads) = vmm.libvirt_conn.getInfo()
self.physinfo = xc.physinfo() self.physinfo = vmm.xc.physinfo()
self._total_mem = long(memory)*1024 self._total_mem = long(memory)*1024
self._no_cpus = cpus self._no_cpus = cpus
@ -152,7 +205,7 @@ class QubesHost(object):
if previous is None: if previous is None:
previous_time = time.time() previous_time = time.time()
previous = {} previous = {}
info = xc.domain_getinfo(0, qubes_max_qid) info = vmm.xc.domain_getinfo(0, qubes_max_qid)
for vm in info: for vm in info:
previous[vm['domid']] = {} previous[vm['domid']] = {}
previous[vm['domid']]['cpu_time'] = ( previous[vm['domid']]['cpu_time'] = (
@ -162,7 +215,7 @@ class QubesHost(object):
current_time = time.time() current_time = time.time()
current = {} current = {}
info = xc.domain_getinfo(0, qubes_max_qid) info = vmm.xc.domain_getinfo(0, qubes_max_qid)
for vm in info: for vm in info:
current[vm['domid']] = {} current[vm['domid']] = {}
current[vm['domid']]['cpu_time'] = ( current[vm['domid']]['cpu_time'] = (

View File

@ -24,7 +24,7 @@
from qubes import QubesVm,QubesException,QubesVmCollection from qubes import QubesVm,QubesException,QubesVmCollection
from qubes import QubesVmClasses from qubes import QubesVmClasses
from qubes import xs from qubes import vmm
from qubes import system_path,vm_files from qubes import system_path,vm_files
import sys import sys
import os import os
@ -208,7 +208,7 @@ def block_find_unused_frontend(vm = None):
assert vm is not None assert vm is not None
assert vm.is_running() assert vm.is_running()
vbd_list = xs.ls('', '/local/domain/%d/device/vbd' % vm.xid) vbd_list = vmm.xs.ls('', '/local/domain/%d/device/vbd' % vm.xid)
# xvd* devices # xvd* devices
major = 202 major = 202
# prefer xvdi # prefer xvdi
@ -223,22 +223,22 @@ def block_list(vm = None, system_disks = False):
desc_re = re.compile(r"^.{1,255}$") desc_re = re.compile(r"^.{1,255}$")
mode_re = re.compile(r"^[rw]$") mode_re = re.compile(r"^[rw]$")
xs_trans = xs.transaction_start() xs_trans = vmm.xs.transaction_start()
vm_list = [] vm_list = []
if vm is not None: if vm is not None:
if not vm.is_running(): if not vm.is_running():
xs.transaction_end(xs_trans) vmm.xs.transaction_end(xs_trans)
return [] return []
else: else:
vm_list = [ str(vm.xid) ] vm_list = [ str(vm.xid) ]
else: else:
vm_list = xs.ls(xs_trans, '/local/domain') vm_list = vmm.xs.ls(xs_trans, '/local/domain')
devices_list = {} devices_list = {}
for xid in vm_list: for xid in vm_list:
vm_name = xs.read(xs_trans, '/local/domain/%s/name' % xid) vm_name = vmm.xs.read(xs_trans, '/local/domain/%s/name' % xid)
vm_devices = xs.ls(xs_trans, '/local/domain/%s/qubes-block-devices' % xid) vm_devices = vmm.xs.ls(xs_trans, '/local/domain/%s/qubes-block-devices' % xid)
if vm_devices is None: if vm_devices is None:
continue continue
for device in vm_devices: for device in vm_devices:
@ -247,9 +247,9 @@ def block_list(vm = None, system_disks = False):
print >> sys.stderr, "Invalid device name in VM '%s'" % vm_name print >> sys.stderr, "Invalid device name in VM '%s'" % vm_name
continue continue
device_size = xs.read(xs_trans, '/local/domain/%s/qubes-block-devices/%s/size' % (xid, device)) device_size = vmm.xs.read(xs_trans, '/local/domain/%s/qubes-block-devices/%s/size' % (xid, device))
device_desc = xs.read(xs_trans, '/local/domain/%s/qubes-block-devices/%s/desc' % (xid, device)) device_desc = vmm.xs.read(xs_trans, '/local/domain/%s/qubes-block-devices/%s/desc' % (xid, device))
device_mode = xs.read(xs_trans, '/local/domain/%s/qubes-block-devices/%s/mode' % (xid, device)) device_mode = vmm.xs.read(xs_trans, '/local/domain/%s/qubes-block-devices/%s/mode' % (xid, device))
if device_size is None or device_desc is None or device_mode is None: if device_size is None or device_desc is None or device_mode is None:
print >> sys.stderr, "Missing field in %s device parameters" % device print >> sys.stderr, "Missing field in %s device parameters" % device
@ -277,16 +277,16 @@ def block_list(vm = None, system_disks = False):
"vm": vm_name, "device":device, "size":int(device_size), "vm": vm_name, "device":device, "size":int(device_size),
"desc":device_desc, "mode":device_mode} "desc":device_desc, "mode":device_mode}
xs.transaction_end(xs_trans) vmm.xs.transaction_end(xs_trans)
return devices_list return devices_list
def block_check_attached(backend_vm, device, backend_xid = None): def block_check_attached(backend_vm, device, backend_xid = None):
if backend_xid is None: if backend_xid is None:
backend_xid = backend_vm.xid backend_xid = backend_vm.xid
xs_trans = xs.transaction_start() xs_trans = vmm.xs.transaction_start()
vm_list = xs.ls(xs_trans, '/local/domain/%d/backend/vbd' % backend_xid) vm_list = vmm.xs.ls(xs_trans, '/local/domain/%d/backend/vbd' % backend_xid)
if vm_list is None: if vm_list is None:
xs.transaction_end(xs_trans) vmm.xs.transaction_end(xs_trans)
return None return None
device_majorminor = None device_majorminor = None
try: try:
@ -295,10 +295,10 @@ def block_check_attached(backend_vm, device, backend_xid = None):
# Unknown devices will be compared directly - perhaps it is a filename? # Unknown devices will be compared directly - perhaps it is a filename?
pass pass
for vm_xid in vm_list: for vm_xid in vm_list:
for devid in xs.ls(xs_trans, '/local/domain/%d/backend/vbd/%s' % (backend_xid, vm_xid)): for devid in vmm.xs.ls(xs_trans, '/local/domain/%d/backend/vbd/%s' % (backend_xid, vm_xid)):
(tmp_major, tmp_minor) = (0, 0) (tmp_major, tmp_minor) = (0, 0)
phys_device = xs.read(xs_trans, '/local/domain/%d/backend/vbd/%s/%s/physical-device' % (backend_xid, vm_xid, devid)) phys_device = vmm.xs.read(xs_trans, '/local/domain/%d/backend/vbd/%s/%s/physical-device' % (backend_xid, vm_xid, devid))
dev_params = xs.read(xs_trans, '/local/domain/%d/backend/vbd/%s/%s/params' % (backend_xid, vm_xid, devid)) dev_params = vmm.xs.read(xs_trans, '/local/domain/%d/backend/vbd/%s/%s/params' % (backend_xid, vm_xid, devid))
if phys_device and phys_device.find(':'): if phys_device and phys_device.find(':'):
(tmp_major, tmp_minor) = phys_device.split(":") (tmp_major, tmp_minor) = phys_device.split(":")
tmp_major = int(tmp_major, 16) tmp_major = int(tmp_major, 16)
@ -319,9 +319,9 @@ def block_check_attached(backend_vm, device, backend_xid = None):
#TODO #TODO
vm_name = xl_ctx.domid_to_name(int(vm_xid)) vm_name = xl_ctx.domid_to_name(int(vm_xid))
frontend = block_devid_to_name(int(devid)) frontend = block_devid_to_name(int(devid))
xs.transaction_end(xs_trans) vmm.xs.transaction_end(xs_trans)
return {"xid":int(vm_xid), "frontend": frontend, "devid": int(devid), "vm": vm_name} return {"xid":int(vm_xid), "frontend": frontend, "devid": int(devid), "vm": vm_name}
xs.transaction_end(xs_trans) vmm.xs.transaction_end(xs_trans)
return None return None
def block_attach(vm, backend_vm, device, frontend=None, mode="w", auto_detach=False, wait=True): def block_attach(vm, backend_vm, device, frontend=None, mode="w", auto_detach=False, wait=True):
@ -343,7 +343,7 @@ def do_block_attach(vm, backend_vm, device, frontend, mode, auto_detach, wait):
raise QubesException("No unused frontend found") raise QubesException("No unused frontend found")
else: else:
# Check if any device attached at this frontend # Check if any device attached at this frontend
if xs.read('', '/local/domain/%d/device/vbd/%d/state' % (vm.xid, block_name_to_devid(frontend))) == '4': if vmm.xs.read('', '/local/domain/%d/device/vbd/%d/state' % (vm.xid, block_name_to_devid(frontend))) == '4':
raise QubesException("Frontend %s busy in VM %s, detach it first" % (frontend, vm.name)) raise QubesException("Frontend %s busy in VM %s, detach it first" % (frontend, vm.name))
# Check if this device is attached to some domain # Check if this device is attached to some domain
@ -368,8 +368,8 @@ def do_block_attach(vm, backend_vm, device, frontend, mode, auto_detach, wait):
# 5sec timeout # 5sec timeout
timeout = 5/interval timeout = 5/interval
while timeout > 0: while timeout > 0:
be_state = xs.read('', be_path + '/state') be_state = vmm.xs.read('', be_path + '/state')
hotplug_state = xs.read('', be_path + '/hotplug-status') hotplug_state = vmm.xs.read('', be_path + '/hotplug-status')
if be_state is None: if be_state is None:
raise QubesException("Backend device disappeared, something weird happened") raise QubesException("Backend device disappeared, something weird happened")
elif int(be_state) == 4: elif int(be_state) == 4:
@ -377,13 +377,13 @@ def do_block_attach(vm, backend_vm, device, frontend, mode, auto_detach, wait):
return return
elif int(be_state) > 4: elif int(be_state) > 4:
# Error # Error
error = xs.read('', '/local/domain/%d/error/backend/vbd/%d/%d/error' % (backend_vm.xid, vm.xid, block_name_to_devid(frontend))) error = vmm.xs.read('', '/local/domain/%d/error/backend/vbd/%d/%d/error' % (backend_vm.xid, vm.xid, block_name_to_devid(frontend)))
if error is not None: if error is not None:
raise QubesException("Error while connecting block device: " + error) raise QubesException("Error while connecting block device: " + error)
else: else:
raise QubesException("Unknown error while connecting block device") raise QubesException("Unknown error while connecting block device")
elif hotplug_state == 'error': elif hotplug_state == 'error':
hotplug_error = xs.read('', be_path + '/hotplug-error') hotplug_error = vmm.xs.read('', be_path + '/hotplug-error')
if hotplug_error: if hotplug_error:
raise QubesException("Error while connecting block device: " + hotplug_error) raise QubesException("Error while connecting block device: " + hotplug_error)
else: else:
@ -401,7 +401,7 @@ def block_detach(vm, frontend = "xvdi", vm_xid = None):
vm_xid = vm.xid vm_xid = vm.xid
# Check if this device is really connected # Check if this device is really connected
if not xs.read('', '/local/domain/%d/device/vbd/%d/state' % (vm_xid, block_name_to_devid(frontend))) == '4': if not vmm.xs.read('', '/local/domain/%d/device/vbd/%d/state' % (vm_xid, block_name_to_devid(frontend))) == '4':
# Do nothing - device already detached # Do nothing - device already detached
return return
@ -417,21 +417,21 @@ def block_detach_all(vm, vm_xid = None):
# FIXME: potential race # FIXME: potential race
vm_xid = vm.xid vm_xid = vm.xid
xs_trans = xs.transaction_start() xs_trans = vmm.xs.transaction_start()
devices = xs.ls(xs_trans, '/local/domain/%d/device/vbd' % vm_xid) devices = vmm.xs.ls(xs_trans, '/local/domain/%d/device/vbd' % vm_xid)
if devices is None: if devices is None:
return return
devices_to_detach = [] devices_to_detach = []
for devid in devices: for devid in devices:
# check if this is system disk # check if this is system disk
be_path = xs.read(xs_trans, '/local/domain/%d/device/vbd/%s/backend' % (vm_xid, devid)) be_path = vmm.xs.read(xs_trans, '/local/domain/%d/device/vbd/%s/backend' % (vm_xid, devid))
assert be_path is not None assert be_path is not None
be_params = xs.read(xs_trans, be_path + '/params') be_params = vmm.xs.read(xs_trans, be_path + '/params')
if be_path.startswith('/local/domain/0/') and be_params is not None and be_params.startswith(system_path["qubes_base_dir"]): if be_path.startswith('/local/domain/0/') and be_params is not None and be_params.startswith(system_path["qubes_base_dir"]):
# system disk # system disk
continue continue
devices_to_detach.append(devid) devices_to_detach.append(devid)
xs.transaction_end(xs_trans) vmm.xs.transaction_end(xs_trans)
for devid in devices_to_detach: for devid in devices_to_detach:
xl_cmd = [ '/usr/sbin/xl', 'block-detach', str(vm_xid), devid] xl_cmd = [ '/usr/sbin/xl', 'block-detach', str(vm_xid), devid]
subprocess.check_call(xl_cmd) subprocess.check_call(xl_cmd)
@ -450,7 +450,7 @@ def usb_setup(backend_vm_xid, vm_xid, devid, usb_ver):
devid - id of the pvusb controller devid - id of the pvusb controller
""" """
num_ports = 8 num_ports = 8
trans = xs.transaction_start() trans = vmm.xs.transaction_start()
be_path = "/local/domain/%d/backend/vusb/%d/%d" % (backend_vm_xid, vm_xid, devid) be_path = "/local/domain/%d/backend/vusb/%d/%d" % (backend_vm_xid, vm_xid, devid)
fe_path = "/local/domain/%d/device/vusb/%d" % (vm_xid, devid) fe_path = "/local/domain/%d/device/vusb/%d" % (vm_xid, devid)
@ -459,35 +459,35 @@ def usb_setup(backend_vm_xid, vm_xid, devid, usb_ver):
fe_perm = [{'dom': vm_xid}, {'dom': backend_vm_xid, 'read': True} ] fe_perm = [{'dom': vm_xid}, {'dom': backend_vm_xid, 'read': True} ]
# Create directories and set permissions # Create directories and set permissions
xs.write(trans, be_path, "") vmm.xs.write(trans, be_path, "")
xs.set_permissions(trans, be_path, be_perm) vmm.xs.set_permissions(trans, be_path, be_perm)
xs.write(trans, fe_path, "") vmm.xs.write(trans, fe_path, "")
xs.set_permissions(trans, fe_path, fe_perm) vmm.xs.set_permissions(trans, fe_path, fe_perm)
# Write backend information into the location that frontend looks for # Write backend information into the location that frontend looks for
xs.write(trans, "%s/backend-id" % fe_path, str(backend_vm_xid)) vmm.xs.write(trans, "%s/backend-id" % fe_path, str(backend_vm_xid))
xs.write(trans, "%s/backend" % fe_path, be_path) vmm.xs.write(trans, "%s/backend" % fe_path, be_path)
# Write frontend information into the location that backend looks for # Write frontend information into the location that backend looks for
xs.write(trans, "%s/frontend-id" % be_path, str(vm_xid)) vmm.xs.write(trans, "%s/frontend-id" % be_path, str(vm_xid))
xs.write(trans, "%s/frontend" % be_path, fe_path) vmm.xs.write(trans, "%s/frontend" % be_path, fe_path)
# Write USB Spec version field. # Write USB Spec version field.
xs.write(trans, "%s/usb-ver" % be_path, usb_ver) vmm.xs.write(trans, "%s/usb-ver" % be_path, usb_ver)
# Write virtual root hub field. # Write virtual root hub field.
xs.write(trans, "%s/num-ports" % be_path, str(num_ports)) vmm.xs.write(trans, "%s/num-ports" % be_path, str(num_ports))
for port in range(1, num_ports+1): for port in range(1, num_ports+1):
# Set all port to disconnected state # Set all port to disconnected state
xs.write(trans, "%s/port/%d" % (be_path, port), "") vmm.xs.write(trans, "%s/port/%d" % (be_path, port), "")
# Set state to XenbusStateInitialising # Set state to XenbusStateInitialising
xs.write(trans, "%s/state" % fe_path, "1") vmm.xs.write(trans, "%s/state" % fe_path, "1")
xs.write(trans, "%s/state" % be_path, "1") vmm.xs.write(trans, "%s/state" % be_path, "1")
xs.write(trans, "%s/online" % be_path, "1") vmm.xs.write(trans, "%s/online" % be_path, "1")
xs.transaction_end(trans) vmm.xs.transaction_end(trans)
def usb_decode_device_from_xs(xs_encoded_device): def usb_decode_device_from_xs(xs_encoded_device):
""" recover actual device name (xenstore doesn't allow dot in key names, so it was translated to underscore) """ """ recover actual device name (xenstore doesn't allow dot in key names, so it was translated to underscore) """
@ -512,12 +512,12 @@ def usb_list():
devices_list = {} devices_list = {}
xs_trans = xs.transaction_start() xs_trans = vmm.xs.transaction_start()
vm_list = xs.ls(xs_trans, '/local/domain') vm_list = vmm.xs.ls(xs_trans, '/local/domain')
for xid in vm_list: for xid in vm_list:
vm_name = xs.read(xs_trans, '/local/domain/%s/name' % xid) vm_name = vmm.xs.read(xs_trans, '/local/domain/%s/name' % xid)
vm_devices = xs.ls(xs_trans, '/local/domain/%s/qubes-usb-devices' % xid) vm_devices = vmm.xs.ls(xs_trans, '/local/domain/%s/qubes-usb-devices' % xid)
if vm_devices is None: if vm_devices is None:
continue continue
# when listing devices in xenstore we get encoded names # when listing devices in xenstore we get encoded names
@ -527,13 +527,13 @@ def usb_list():
print >> sys.stderr, "Invalid device id in backend VM '%s'" % vm_name print >> sys.stderr, "Invalid device id in backend VM '%s'" % vm_name
continue continue
device = usb_decode_device_from_xs(xs_encoded_device) device = usb_decode_device_from_xs(xs_encoded_device)
device_desc = xs.read(xs_trans, '/local/domain/%s/qubes-usb-devices/%s/desc' % (xid, xs_encoded_device)) device_desc = vmm.xs.read(xs_trans, '/local/domain/%s/qubes-usb-devices/%s/desc' % (xid, xs_encoded_device))
if not desc_re.match(device_desc): if not desc_re.match(device_desc):
print >> sys.stderr, "Invalid %s device desc in VM '%s'" % (device, vm_name) print >> sys.stderr, "Invalid %s device desc in VM '%s'" % (device, vm_name)
continue continue
visible_name = "%s:%s" % (vm_name, device) visible_name = "%s:%s" % (vm_name, device)
# grab version # grab version
usb_ver = xs.read(xs_trans, '/local/domain/%s/qubes-usb-devices/%s/usb-ver' % (xid, xs_encoded_device)) usb_ver = vmm.xs.read(xs_trans, '/local/domain/%s/qubes-usb-devices/%s/usb-ver' % (xid, xs_encoded_device))
if usb_ver is None or not usb_ver_re.match(usb_ver): if usb_ver is None or not usb_ver_re.match(usb_ver):
print >> sys.stderr, "Invalid %s device USB version in VM '%s'" % (device, vm_name) print >> sys.stderr, "Invalid %s device USB version in VM '%s'" % (device, vm_name)
continue continue
@ -542,7 +542,7 @@ def usb_list():
"desc":device_desc, "desc":device_desc,
"usb_ver":usb_ver} "usb_ver":usb_ver}
xs.transaction_end(xs_trans) vmm.xs.transaction_end(xs_trans)
return devices_list return devices_list
def usb_check_attached(xs_trans, backend_vm, device): def usb_check_attached(xs_trans, backend_vm, device):
@ -559,21 +559,21 @@ def usb_check_attached(xs_trans, backend_vm, device):
""" """
# sample xs content: /local/domain/0/backend/vusb/4/0/port/1 = "7-5" # sample xs content: /local/domain/0/backend/vusb/4/0/port/1 = "7-5"
attached_dev = None attached_dev = None
vms = xs.ls(xs_trans, '/local/domain/%d/backend/vusb' % backend_vm) vms = vmm.xs.ls(xs_trans, '/local/domain/%d/backend/vusb' % backend_vm)
if vms is None: if vms is None:
return None return None
for vm in vms: for vm in vms:
if not vm.isdigit(): if not vm.isdigit():
print >> sys.stderr, "Invalid VM id" print >> sys.stderr, "Invalid VM id"
continue continue
frontend_devs = xs.ls(xs_trans, '/local/domain/%d/backend/vusb/%s' % (backend_vm, vm)) frontend_devs = vmm.xs.ls(xs_trans, '/local/domain/%d/backend/vusb/%s' % (backend_vm, vm))
if frontend_devs is None: if frontend_devs is None:
continue continue
for frontend_dev in frontend_devs: for frontend_dev in frontend_devs:
if not frontend_dev.isdigit(): if not frontend_dev.isdigit():
print >> sys.stderr, "Invalid frontend in VM %s" % vm print >> sys.stderr, "Invalid frontend in VM %s" % vm
continue continue
ports = xs.ls(xs_trans, '/local/domain/%d/backend/vusb/%s/%s/port' % (backend_vm, vm, frontend_dev)) ports = vmm.xs.ls(xs_trans, '/local/domain/%d/backend/vusb/%s/%s/port' % (backend_vm, vm, frontend_dev))
if ports is None: if ports is None:
continue continue
for port in ports: for port in ports:
@ -581,7 +581,7 @@ def usb_check_attached(xs_trans, backend_vm, device):
if not port.isdigit(): if not port.isdigit():
print >> sys.stderr, "Invalid port in VM %s frontend %s" % (vm, frontend) print >> sys.stderr, "Invalid port in VM %s frontend %s" % (vm, frontend)
continue continue
dev = xs.read(xs_trans, '/local/domain/%d/backend/vusb/%s/%s/port/%s' % (backend_vm, vm, frontend_dev, port)) dev = vmm.xs.read(xs_trans, '/local/domain/%d/backend/vusb/%s/%s/port/%s' % (backend_vm, vm, frontend_dev, port))
if dev == "": if dev == "":
continue continue
# Sanitize device id # Sanitize device id
@ -605,7 +605,7 @@ def usb_check_attached(xs_trans, backend_vm, device):
# if len(devport) != 2: # if len(devport) != 2:
# raise QubesException("Malformed frontend syntax, must be in device-port format") # raise QubesException("Malformed frontend syntax, must be in device-port format")
# # FIXME: # # FIXME:
# # return xs.read('', '/local/domain/%d/device/vusb/%d/state' % (vm.xid, frontend)) == '4' # # return vmm.xs.read('', '/local/domain/%d/device/vusb/%d/state' % (vm.xid, frontend)) == '4'
# return False # return False
def usb_find_unused_frontend(xs_trans, backend_vm_xid, vm_xid, usb_ver): def usb_find_unused_frontend(xs_trans, backend_vm_xid, vm_xid, usb_ver):
@ -619,7 +619,7 @@ def usb_find_unused_frontend(xs_trans, backend_vm_xid, vm_xid, usb_ver):
# If nothing found, this value will be used to derive the index of a new frontend. # If nothing found, this value will be used to derive the index of a new frontend.
last_frontend_dev = -1 last_frontend_dev = -1
frontend_devs = xs.ls(xs_trans, "/local/domain/%d/device/vusb" % vm_xid) frontend_devs = vmm.xs.ls(xs_trans, "/local/domain/%d/device/vusb" % vm_xid)
if frontend_devs is not None: if frontend_devs is not None:
for frontend_dev in frontend_devs: for frontend_dev in frontend_devs:
if not frontend_dev.isdigit(): if not frontend_dev.isdigit():
@ -627,12 +627,12 @@ def usb_find_unused_frontend(xs_trans, backend_vm_xid, vm_xid, usb_ver):
continue continue
frontend_dev = int(frontend_dev) frontend_dev = int(frontend_dev)
fe_path = "/local/domain/%d/device/vusb/%d" % (vm_xid, frontend_dev) fe_path = "/local/domain/%d/device/vusb/%d" % (vm_xid, frontend_dev)
if xs.read(xs_trans, "%s/backend-id" % fe_path) == str(backend_vm_xid): if vmm.xs.read(xs_trans, "%s/backend-id" % fe_path) == str(backend_vm_xid):
if xs.read(xs_trans, '/local/domain/%d/backend/vusb/%d/%d/usb-ver' % (backend_vm_xid, vm_xid, frontend_dev)) != usb_ver: if vmm.xs.read(xs_trans, '/local/domain/%d/backend/vusb/%d/%d/usb-ver' % (backend_vm_xid, vm_xid, frontend_dev)) != usb_ver:
last_frontend_dev = frontend_dev last_frontend_dev = frontend_dev
continue continue
# here: found an existing frontend already connected to right backend using an appropriate USB version # here: found an existing frontend already connected to right backend using an appropriate USB version
ports = xs.ls(xs_trans, '/local/domain/%d/backend/vusb/%d/%d/port' % (backend_vm_xid, vm_xid, frontend_dev)) ports = vmm.xs.ls(xs_trans, '/local/domain/%d/backend/vusb/%d/%d/port' % (backend_vm_xid, vm_xid, frontend_dev))
if ports is None: if ports is None:
print >> sys.stderr, "No ports in VM %d frontend_dev %d?" % (vm_xid, frontend_dev) print >> sys.stderr, "No ports in VM %d frontend_dev %d?" % (vm_xid, frontend_dev)
last_frontend_dev = frontend_dev last_frontend_dev = frontend_dev
@ -643,7 +643,7 @@ def usb_find_unused_frontend(xs_trans, backend_vm_xid, vm_xid, usb_ver):
print >> sys.stderr, "Invalid port in VM %d frontend_dev %d" % (vm_xid, frontend_dev) print >> sys.stderr, "Invalid port in VM %d frontend_dev %d" % (vm_xid, frontend_dev)
continue continue
port = int(port) port = int(port)
dev = xs.read(xs_trans, '/local/domain/%d/backend/vusb/%d/%s/port/%s' % (backend_vm_xid, vm_xid, frontend_dev, port)) dev = vmm.xs.read(xs_trans, '/local/domain/%d/backend/vusb/%d/%s/port/%s' % (backend_vm_xid, vm_xid, frontend_dev, port))
# Sanitize device id # Sanitize device id
if not usb_port_re.match(dev): if not usb_port_re.match(dev):
print >> sys.stderr, "Invalid device id in backend VM %d @ %d/%d/port/%d" % \ print >> sys.stderr, "Invalid device id in backend VM %d @ %d/%d/port/%d" % \
@ -661,12 +661,12 @@ def usb_find_unused_frontend(xs_trans, backend_vm_xid, vm_xid, usb_ver):
def usb_attach(vm, backend_vm, device, frontend=None, auto_detach=False, wait=True): def usb_attach(vm, backend_vm, device, frontend=None, auto_detach=False, wait=True):
device_attach_check(vm, backend_vm, device, frontend) device_attach_check(vm, backend_vm, device, frontend)
xs_trans = xs.transaction_start() xs_trans = vmm.xs.transaction_start()
xs_encoded_device = usb_encode_device_for_xs(device) xs_encoded_device = usb_encode_device_for_xs(device)
usb_ver = xs.read(xs_trans, '/local/domain/%s/qubes-usb-devices/%s/usb-ver' % (backend_vm.xid, xs_encoded_device)) usb_ver = vmm.xs.read(xs_trans, '/local/domain/%s/qubes-usb-devices/%s/usb-ver' % (backend_vm.xid, xs_encoded_device))
if usb_ver is None or not usb_ver_re.match(usb_ver): if usb_ver is None or not usb_ver_re.match(usb_ver):
xs.transaction_end(xs_trans) vmm.xs.transaction_end(xs_trans)
raise QubesException("Invalid %s device USB version in VM '%s'" % (device, backend_vm.name)) raise QubesException("Invalid %s device USB version in VM '%s'" % (device, backend_vm.name))
if frontend is None: if frontend is None:
@ -675,12 +675,12 @@ def usb_attach(vm, backend_vm, device, frontend=None, auto_detach=False, wait=Tr
# Check if any device attached at this frontend # Check if any device attached at this frontend
#if usb_check_frontend_busy(vm, frontend): #if usb_check_frontend_busy(vm, frontend):
# raise QubesException("Frontend %s busy in VM %s, detach it first" % (frontend, vm.name)) # raise QubesException("Frontend %s busy in VM %s, detach it first" % (frontend, vm.name))
xs.transaction_end(xs_trans) vmm.xs.transaction_end(xs_trans)
raise NotImplementedError("Explicit USB frontend specification is not implemented yet") raise NotImplementedError("Explicit USB frontend specification is not implemented yet")
# Check if this device is attached to some domain # Check if this device is attached to some domain
attached_vm = usb_check_attached(xs_trans, backend_vm.xid, device) attached_vm = usb_check_attached(xs_trans, backend_vm.xid, device)
xs.transaction_end(xs_trans) vmm.xs.transaction_end(xs_trans)
if attached_vm: if attached_vm:
if auto_detach: if auto_detach:

View File

@ -21,7 +21,7 @@
# #
# #
from qubes.qubes import QubesVmCollection from qubes.qubes import QubesVmCollection,vmm
from qubes.qubes import QubesException from qubes.qubes import QubesException
from optparse import OptionParser; from optparse import OptionParser;
import sys import sys
@ -56,6 +56,7 @@ def main():
print >> sys.stderr, "... or use --force-root to continue anyway." print >> sys.stderr, "... or use --force-root to continue anyway."
exit(1) exit(1)
vmm.offline_mode = True
qvm_collection = QubesVmCollection() qvm_collection = QubesVmCollection()
qvm_collection.lock_db_for_writing() qvm_collection.lock_db_for_writing()
qvm_collection.load() qvm_collection.load()

View File

@ -21,10 +21,11 @@
# #
# #
from qubes.qubes import QubesVmCollection from qubes.qubes import QubesVmCollection,vmm
import sys import sys
def main(): def main():
vmm.offline_mode = True
qvm_collection = QubesVmCollection() qvm_collection = QubesVmCollection()
if qvm_collection.check_if_storage_exists(): if qvm_collection.check_if_storage_exists():
print >> sys.stderr, "Storage exists, not overwriting." print >> sys.stderr, "Storage exists, not overwriting."