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:
parent
9f90106db4
commit
b8c62c0279
@ -39,7 +39,7 @@ from qubes import qmemman_algo
|
||||
import libvirt
|
||||
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 QubesVmCollection,QubesException,QubesHost,QubesVmLabels
|
||||
from qubes.qubes import defaults,system_path,vm_files,qubes_max_qid
|
||||
@ -202,6 +202,10 @@ class QubesVm(object):
|
||||
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
|
||||
@ -304,7 +308,7 @@ class QubesVm(object):
|
||||
self.netvm.connected_vms[self.qid] = self
|
||||
|
||||
# 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()
|
||||
total_mem_mb = qubes_host.memory_total/1024
|
||||
self.maxmem = total_mem_mb/2
|
||||
@ -314,7 +318,7 @@ class QubesVm(object):
|
||||
self.maxmem = self.memory * 10
|
||||
|
||||
# By default allow use all VCPUs
|
||||
if self.vcpus is None:
|
||||
if self.vcpus is None and not vmm.offline_mode:
|
||||
qubes_host = QubesHost()
|
||||
self.vcpus = qubes_host.no_cpus
|
||||
|
||||
@ -648,7 +652,7 @@ class QubesVm(object):
|
||||
|
||||
def _update_libvirt_domain(self):
|
||||
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())
|
||||
|
||||
@property
|
||||
@ -658,9 +662,9 @@ class QubesVm(object):
|
||||
|
||||
try:
|
||||
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:
|
||||
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())
|
||||
except libvirt.libvirtError:
|
||||
if libvirt.virGetLastError()[0] == libvirt.VIR_ERR_NO_DOMAIN:
|
||||
@ -788,7 +792,7 @@ class QubesVm(object):
|
||||
# TODO
|
||||
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 != '':
|
||||
return datetime.datetime.fromtimestamp(float(start_time))
|
||||
else:
|
||||
@ -820,7 +824,7 @@ class QubesVm(object):
|
||||
# FIXME
|
||||
# 51712 (0xCA00) is xvda
|
||||
# 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
|
||||
|
||||
@ -905,15 +909,15 @@ class QubesVm(object):
|
||||
return
|
||||
|
||||
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
|
||||
backend_xid = int(xs.read('', '%s/%s/backend-id' % (dev_basepath, dev)))
|
||||
if backend_xid in libvirt_conn.listDomainsID():
|
||||
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 xs.read('', '%s/%s/state' % (dev_basepath, dev)) == '4':
|
||||
if vmm.xs.read('', '%s/%s/state' % (dev_basepath, dev)) == '4':
|
||||
continue
|
||||
# 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):
|
||||
if dry_run:
|
||||
@ -924,69 +928,69 @@ class QubesVm(object):
|
||||
|
||||
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:
|
||||
|
||||
xs.write('', "{0}/qubes-vm-type".format(domain_path),
|
||||
vmm.xs.write('', "{0}/qubes-vm-type".format(domain_path),
|
||||
self.type)
|
||||
xs.write('', "{0}/qubes-vm-updateable".format(domain_path),
|
||||
vmm.xs.write('', "{0}/qubes-vm-updateable".format(domain_path),
|
||||
str(self.updateable))
|
||||
|
||||
if self.is_netvm():
|
||||
xs.write('',
|
||||
vmm.xs.write('',
|
||||
"{0}/qubes-netvm-gateway".format(domain_path),
|
||||
self.gateway)
|
||||
xs.write('',
|
||||
vmm.xs.write('',
|
||||
"{0}/qubes-netvm-secondary-dns".format(domain_path),
|
||||
self.secondary_dns)
|
||||
xs.write('',
|
||||
vmm.xs.write('',
|
||||
"{0}/qubes-netvm-netmask".format(domain_path),
|
||||
self.netmask)
|
||||
xs.write('',
|
||||
vmm.xs.write('',
|
||||
"{0}/qubes-netvm-network".format(domain_path),
|
||||
self.network)
|
||||
|
||||
if self.netvm is not None:
|
||||
xs.write('', "{0}/qubes-ip".format(domain_path), self.ip)
|
||||
xs.write('', "{0}/qubes-netmask".format(domain_path),
|
||||
vmm.xs.write('', "{0}/qubes-ip".format(domain_path), self.ip)
|
||||
vmm.xs.write('', "{0}/qubes-netmask".format(domain_path),
|
||||
self.netvm.netmask)
|
||||
xs.write('', "{0}/qubes-gateway".format(domain_path),
|
||||
vmm.xs.write('', "{0}/qubes-gateway".format(domain_path),
|
||||
self.netvm.gateway)
|
||||
xs.write('',
|
||||
vmm.xs.write('',
|
||||
"{0}/qubes-secondary-dns".format(domain_path),
|
||||
self.netvm.secondary_dns)
|
||||
|
||||
tzname = self.get_timezone()
|
||||
if tzname:
|
||||
xs.write('',
|
||||
vmm.xs.write('',
|
||||
"{0}/qubes-timezone".format(domain_path),
|
||||
tzname)
|
||||
|
||||
for srv in self.services.keys():
|
||||
# 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])))
|
||||
|
||||
xs.write('',
|
||||
vmm.xs.write('',
|
||||
"{0}/qubes-block-devices".format(domain_path),
|
||||
'')
|
||||
|
||||
xs.write('',
|
||||
vmm.xs.write('',
|
||||
"{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)))
|
||||
|
||||
# Fix permissions
|
||||
xs.set_permissions('', '{0}/device'.format(domain_path),
|
||||
vmm.xs.set_permissions('', '{0}/device'.format(domain_path),
|
||||
[{ 'dom': xid }])
|
||||
xs.set_permissions('', '{0}/memory'.format(domain_path),
|
||||
vmm.xs.set_permissions('', '{0}/memory'.format(domain_path),
|
||||
[{ '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 }])
|
||||
xs.set_permissions('', '{0}/qubes-usb-devices'.format(domain_path),
|
||||
vmm.xs.set_permissions('', '{0}/qubes-usb-devices'.format(domain_path),
|
||||
[{ 'dom': xid }])
|
||||
|
||||
# fire hooks
|
||||
@ -1743,7 +1747,7 @@ class QubesVm(object):
|
||||
|
||||
# Bind pci devices to pciback driver
|
||||
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()
|
||||
|
||||
self.libvirt_domain.createWithFlags(libvirt.VIR_DOMAIN_START_PAUSED)
|
||||
|
@ -25,7 +25,7 @@ import sys
|
||||
import os.path
|
||||
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 QubesVmCollection,QubesException
|
||||
|
||||
@ -115,7 +115,7 @@ class QubesNetVm(QubesVm):
|
||||
|
||||
|
||||
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)
|
||||
|
||||
def update_external_ip_permissions(self, xid = -1):
|
||||
@ -130,7 +130,7 @@ class QubesNetVm(QubesVm):
|
||||
perms.append({ 'dom': xid, 'read': True })
|
||||
|
||||
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)
|
||||
except xen.lowlevel.xs.Error as e:
|
||||
print >>sys.stderr, "WARNING: failed to update external IP " \
|
||||
|
@ -24,7 +24,7 @@
|
||||
|
||||
from qubes.qubes import QubesNetVm,register_qubes_vm_class
|
||||
from qubes.qubes import defaults
|
||||
from qubes.qubes import QubesException,dry_run,libvirt_conn
|
||||
from qubes.qubes import QubesException,dry_run,vmm
|
||||
import psutil
|
||||
|
||||
class QubesAdminVm(QubesNetVm):
|
||||
@ -62,7 +62,7 @@ class QubesAdminVm(QubesNetVm):
|
||||
return psutil.virtual_memory().total/1024
|
||||
|
||||
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):
|
||||
return 0
|
||||
|
@ -24,7 +24,7 @@
|
||||
|
||||
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
|
||||
|
||||
yum_proxy_ip = '10.137.255.254'
|
||||
@ -99,8 +99,8 @@ class QubesProxyVm(QubesNetVm):
|
||||
|
||||
|
||||
super(QubesProxyVm, self).create_xenstore_entries(xid)
|
||||
xs.write('', "/local/domain/{0}/qubes-iptables-error".format(xid), '')
|
||||
xs.set_permissions('', "/local/domain/{0}/qubes-iptables-error".format(xid),
|
||||
vmm.xs.write('', "/local/domain/{0}/qubes-iptables-error".format(xid), '')
|
||||
vmm.xs.set_permissions('', "/local/domain/{0}/qubes-iptables-error".format(xid),
|
||||
[{ 'dom': xid, 'write': True }])
|
||||
self.write_iptables_xenstore_entry()
|
||||
|
||||
@ -112,13 +112,13 @@ class QubesProxyVm(QubesNetVm):
|
||||
xid = self.get_xid()
|
||||
|
||||
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:
|
||||
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()))
|
||||
|
||||
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 += "*filter\n"
|
||||
iptables += ":INPUT DROP [0:0]\n"
|
||||
@ -140,7 +140,7 @@ class QubesProxyVm(QubesNetVm):
|
||||
# Deny inter-VMs networking
|
||||
iptables += "-A FORWARD -i vif+ -o vif+ -j DROP\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()]
|
||||
for vm in vms:
|
||||
@ -201,12 +201,12 @@ class QubesProxyVm(QubesNetVm):
|
||||
|
||||
iptables += "-A FORWARD -s {0} -j {1}\n".format(ip, default_action)
|
||||
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
|
||||
|
||||
self.write_netvm_domid_entry()
|
||||
|
||||
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)
|
||||
|
@ -28,7 +28,7 @@ import libvirt
|
||||
import time
|
||||
from qubes.qubes import QubesVm,QubesVmLabel,register_qubes_vm_class
|
||||
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
|
||||
|
||||
class QubesDisposableVm(QubesVm):
|
||||
@ -146,7 +146,7 @@ class QubesDisposableVm(QubesVm):
|
||||
assert (len(self.pcidevs) == 0), "DispVM cannot have PCI devices"
|
||||
|
||||
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)
|
||||
|
||||
print >>sys.stderr, "time=%s, done, getting xid" % (str(time.time()))
|
||||
|
@ -30,7 +30,8 @@ import stat
|
||||
import sys
|
||||
import re
|
||||
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 QubesException
|
||||
|
||||
@ -397,7 +398,7 @@ class QubesHVm(QubesVm):
|
||||
if self.xid < 0:
|
||||
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:
|
||||
return int(stubdom_xid_str)
|
||||
else:
|
||||
|
@ -38,7 +38,6 @@ import atexit
|
||||
dry_run = False
|
||||
#dry_run = True
|
||||
|
||||
|
||||
if not dry_run:
|
||||
import libvirt
|
||||
import xen.lowlevel.xc
|
||||
@ -108,22 +107,76 @@ qubes_max_netid = 254
|
||||
class QubesException (Exception):
|
||||
pass
|
||||
|
||||
def libvirt_error_handler(ctx, error):
|
||||
pass
|
||||
class QubesVMMConnection(object):
|
||||
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:
|
||||
xc = xen.lowlevel.xc.xc()
|
||||
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)
|
||||
vmm = QubesVMMConnection()
|
||||
|
||||
##########################################
|
||||
|
||||
class QubesHost(object):
|
||||
def __init__(self):
|
||||
(model, memory, cpus, mhz, nodes, socket, cores, threads) = libvirt_conn.getInfo()
|
||||
self.physinfo = xc.physinfo()
|
||||
(model, memory, cpus, mhz, nodes, socket, cores, threads) = vmm.libvirt_conn.getInfo()
|
||||
self.physinfo = vmm.xc.physinfo()
|
||||
|
||||
self._total_mem = long(memory)*1024
|
||||
self._no_cpus = cpus
|
||||
@ -152,7 +205,7 @@ class QubesHost(object):
|
||||
if previous is None:
|
||||
previous_time = time.time()
|
||||
previous = {}
|
||||
info = xc.domain_getinfo(0, qubes_max_qid)
|
||||
info = vmm.xc.domain_getinfo(0, qubes_max_qid)
|
||||
for vm in info:
|
||||
previous[vm['domid']] = {}
|
||||
previous[vm['domid']]['cpu_time'] = (
|
||||
@ -162,7 +215,7 @@ class QubesHost(object):
|
||||
|
||||
current_time = time.time()
|
||||
current = {}
|
||||
info = xc.domain_getinfo(0, qubes_max_qid)
|
||||
info = vmm.xc.domain_getinfo(0, qubes_max_qid)
|
||||
for vm in info:
|
||||
current[vm['domid']] = {}
|
||||
current[vm['domid']]['cpu_time'] = (
|
||||
|
@ -24,7 +24,7 @@
|
||||
|
||||
from qubes import QubesVm,QubesException,QubesVmCollection
|
||||
from qubes import QubesVmClasses
|
||||
from qubes import xs
|
||||
from qubes import vmm
|
||||
from qubes import system_path,vm_files
|
||||
import sys
|
||||
import os
|
||||
@ -208,7 +208,7 @@ def block_find_unused_frontend(vm = None):
|
||||
assert vm is not None
|
||||
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
|
||||
major = 202
|
||||
# prefer xvdi
|
||||
@ -223,22 +223,22 @@ def block_list(vm = None, system_disks = False):
|
||||
desc_re = re.compile(r"^.{1,255}$")
|
||||
mode_re = re.compile(r"^[rw]$")
|
||||
|
||||
xs_trans = xs.transaction_start()
|
||||
xs_trans = vmm.xs.transaction_start()
|
||||
|
||||
vm_list = []
|
||||
if vm is not None:
|
||||
if not vm.is_running():
|
||||
xs.transaction_end(xs_trans)
|
||||
vmm.xs.transaction_end(xs_trans)
|
||||
return []
|
||||
else:
|
||||
vm_list = [ str(vm.xid) ]
|
||||
else:
|
||||
vm_list = xs.ls(xs_trans, '/local/domain')
|
||||
vm_list = vmm.xs.ls(xs_trans, '/local/domain')
|
||||
|
||||
devices_list = {}
|
||||
for xid in vm_list:
|
||||
vm_name = xs.read(xs_trans, '/local/domain/%s/name' % xid)
|
||||
vm_devices = xs.ls(xs_trans, '/local/domain/%s/qubes-block-devices' % xid)
|
||||
vm_name = vmm.xs.read(xs_trans, '/local/domain/%s/name' % xid)
|
||||
vm_devices = vmm.xs.ls(xs_trans, '/local/domain/%s/qubes-block-devices' % xid)
|
||||
if vm_devices is None:
|
||||
continue
|
||||
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
|
||||
continue
|
||||
|
||||
device_size = 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_mode = xs.read(xs_trans, '/local/domain/%s/qubes-block-devices/%s/mode' % (xid, device))
|
||||
device_size = vmm.xs.read(xs_trans, '/local/domain/%s/qubes-block-devices/%s/size' % (xid, device))
|
||||
device_desc = vmm.xs.read(xs_trans, '/local/domain/%s/qubes-block-devices/%s/desc' % (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:
|
||||
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),
|
||||
"desc":device_desc, "mode":device_mode}
|
||||
|
||||
xs.transaction_end(xs_trans)
|
||||
vmm.xs.transaction_end(xs_trans)
|
||||
return devices_list
|
||||
|
||||
def block_check_attached(backend_vm, device, backend_xid = None):
|
||||
if backend_xid is None:
|
||||
backend_xid = backend_vm.xid
|
||||
xs_trans = xs.transaction_start()
|
||||
vm_list = xs.ls(xs_trans, '/local/domain/%d/backend/vbd' % backend_xid)
|
||||
xs_trans = vmm.xs.transaction_start()
|
||||
vm_list = vmm.xs.ls(xs_trans, '/local/domain/%d/backend/vbd' % backend_xid)
|
||||
if vm_list is None:
|
||||
xs.transaction_end(xs_trans)
|
||||
vmm.xs.transaction_end(xs_trans)
|
||||
return None
|
||||
device_majorminor = None
|
||||
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?
|
||||
pass
|
||||
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)
|
||||
phys_device = 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))
|
||||
phys_device = vmm.xs.read(xs_trans, '/local/domain/%d/backend/vbd/%s/%s/physical-device' % (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(':'):
|
||||
(tmp_major, tmp_minor) = phys_device.split(":")
|
||||
tmp_major = int(tmp_major, 16)
|
||||
@ -319,9 +319,9 @@ def block_check_attached(backend_vm, device, backend_xid = None):
|
||||
#TODO
|
||||
vm_name = xl_ctx.domid_to_name(int(vm_xid))
|
||||
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}
|
||||
xs.transaction_end(xs_trans)
|
||||
vmm.xs.transaction_end(xs_trans)
|
||||
return None
|
||||
|
||||
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")
|
||||
else:
|
||||
# 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))
|
||||
|
||||
# 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
|
||||
timeout = 5/interval
|
||||
while timeout > 0:
|
||||
be_state = xs.read('', be_path + '/state')
|
||||
hotplug_state = xs.read('', be_path + '/hotplug-status')
|
||||
be_state = vmm.xs.read('', be_path + '/state')
|
||||
hotplug_state = vmm.xs.read('', be_path + '/hotplug-status')
|
||||
if be_state is None:
|
||||
raise QubesException("Backend device disappeared, something weird happened")
|
||||
elif int(be_state) == 4:
|
||||
@ -377,13 +377,13 @@ def do_block_attach(vm, backend_vm, device, frontend, mode, auto_detach, wait):
|
||||
return
|
||||
elif int(be_state) > 4:
|
||||
# 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:
|
||||
raise QubesException("Error while connecting block device: " + error)
|
||||
else:
|
||||
raise QubesException("Unknown error while connecting block device")
|
||||
elif hotplug_state == 'error':
|
||||
hotplug_error = xs.read('', be_path + '/hotplug-error')
|
||||
hotplug_error = vmm.xs.read('', be_path + '/hotplug-error')
|
||||
if hotplug_error:
|
||||
raise QubesException("Error while connecting block device: " + hotplug_error)
|
||||
else:
|
||||
@ -401,7 +401,7 @@ def block_detach(vm, frontend = "xvdi", vm_xid = None):
|
||||
vm_xid = vm.xid
|
||||
|
||||
# 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
|
||||
return
|
||||
|
||||
@ -417,21 +417,21 @@ def block_detach_all(vm, vm_xid = None):
|
||||
# FIXME: potential race
|
||||
vm_xid = vm.xid
|
||||
|
||||
xs_trans = xs.transaction_start()
|
||||
devices = xs.ls(xs_trans, '/local/domain/%d/device/vbd' % vm_xid)
|
||||
xs_trans = vmm.xs.transaction_start()
|
||||
devices = vmm.xs.ls(xs_trans, '/local/domain/%d/device/vbd' % vm_xid)
|
||||
if devices is None:
|
||||
return
|
||||
devices_to_detach = []
|
||||
for devid in devices:
|
||||
# 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
|
||||
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"]):
|
||||
# system disk
|
||||
continue
|
||||
devices_to_detach.append(devid)
|
||||
xs.transaction_end(xs_trans)
|
||||
vmm.xs.transaction_end(xs_trans)
|
||||
for devid in devices_to_detach:
|
||||
xl_cmd = [ '/usr/sbin/xl', 'block-detach', str(vm_xid), devid]
|
||||
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
|
||||
"""
|
||||
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)
|
||||
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} ]
|
||||
|
||||
# Create directories and set permissions
|
||||
xs.write(trans, be_path, "")
|
||||
xs.set_permissions(trans, be_path, be_perm)
|
||||
vmm.xs.write(trans, be_path, "")
|
||||
vmm.xs.set_permissions(trans, be_path, be_perm)
|
||||
|
||||
xs.write(trans, fe_path, "")
|
||||
xs.set_permissions(trans, fe_path, fe_perm)
|
||||
vmm.xs.write(trans, fe_path, "")
|
||||
vmm.xs.set_permissions(trans, fe_path, fe_perm)
|
||||
|
||||
# Write backend information into the location that frontend looks for
|
||||
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-id" % fe_path, str(backend_vm_xid))
|
||||
vmm.xs.write(trans, "%s/backend" % fe_path, be_path)
|
||||
|
||||
# Write frontend information into the location that backend looks for
|
||||
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-id" % be_path, str(vm_xid))
|
||||
vmm.xs.write(trans, "%s/frontend" % be_path, fe_path)
|
||||
|
||||
# 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.
|
||||
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):
|
||||
# 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
|
||||
xs.write(trans, "%s/state" % fe_path, "1")
|
||||
xs.write(trans, "%s/state" % be_path, "1")
|
||||
xs.write(trans, "%s/online" % be_path, "1")
|
||||
vmm.xs.write(trans, "%s/state" % fe_path, "1")
|
||||
vmm.xs.write(trans, "%s/state" % 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):
|
||||
""" 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 = {}
|
||||
|
||||
xs_trans = xs.transaction_start()
|
||||
vm_list = xs.ls(xs_trans, '/local/domain')
|
||||
xs_trans = vmm.xs.transaction_start()
|
||||
vm_list = vmm.xs.ls(xs_trans, '/local/domain')
|
||||
|
||||
for xid in vm_list:
|
||||
vm_name = xs.read(xs_trans, '/local/domain/%s/name' % xid)
|
||||
vm_devices = xs.ls(xs_trans, '/local/domain/%s/qubes-usb-devices' % xid)
|
||||
vm_name = vmm.xs.read(xs_trans, '/local/domain/%s/name' % xid)
|
||||
vm_devices = vmm.xs.ls(xs_trans, '/local/domain/%s/qubes-usb-devices' % xid)
|
||||
if vm_devices is None:
|
||||
continue
|
||||
# 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
|
||||
continue
|
||||
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):
|
||||
print >> sys.stderr, "Invalid %s device desc in VM '%s'" % (device, vm_name)
|
||||
continue
|
||||
visible_name = "%s:%s" % (vm_name, device)
|
||||
# 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):
|
||||
print >> sys.stderr, "Invalid %s device USB version in VM '%s'" % (device, vm_name)
|
||||
continue
|
||||
@ -542,7 +542,7 @@ def usb_list():
|
||||
"desc":device_desc,
|
||||
"usb_ver":usb_ver}
|
||||
|
||||
xs.transaction_end(xs_trans)
|
||||
vmm.xs.transaction_end(xs_trans)
|
||||
return devices_list
|
||||
|
||||
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"
|
||||
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:
|
||||
return None
|
||||
for vm in vms:
|
||||
if not vm.isdigit():
|
||||
print >> sys.stderr, "Invalid VM id"
|
||||
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:
|
||||
continue
|
||||
for frontend_dev in frontend_devs:
|
||||
if not frontend_dev.isdigit():
|
||||
print >> sys.stderr, "Invalid frontend in VM %s" % vm
|
||||
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:
|
||||
continue
|
||||
for port in ports:
|
||||
@ -581,7 +581,7 @@ def usb_check_attached(xs_trans, backend_vm, device):
|
||||
if not port.isdigit():
|
||||
print >> sys.stderr, "Invalid port in VM %s frontend %s" % (vm, frontend)
|
||||
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 == "":
|
||||
continue
|
||||
# Sanitize device id
|
||||
@ -605,7 +605,7 @@ def usb_check_attached(xs_trans, backend_vm, device):
|
||||
# if len(devport) != 2:
|
||||
# raise QubesException("Malformed frontend syntax, must be in device-port format")
|
||||
# # 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
|
||||
|
||||
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.
|
||||
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:
|
||||
for frontend_dev in frontend_devs:
|
||||
if not frontend_dev.isdigit():
|
||||
@ -627,12 +627,12 @@ def usb_find_unused_frontend(xs_trans, backend_vm_xid, vm_xid, usb_ver):
|
||||
continue
|
||||
frontend_dev = int(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 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, "%s/backend-id" % fe_path) == str(backend_vm_xid):
|
||||
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
|
||||
continue
|
||||
# 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:
|
||||
print >> sys.stderr, "No ports in VM %d frontend_dev %d?" % (vm_xid, 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)
|
||||
continue
|
||||
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
|
||||
if not usb_port_re.match(dev):
|
||||
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):
|
||||
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)
|
||||
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):
|
||||
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))
|
||||
|
||||
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
|
||||
#if usb_check_frontend_busy(vm, frontend):
|
||||
# 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")
|
||||
|
||||
# Check if this device is attached to some domain
|
||||
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 auto_detach:
|
||||
|
@ -21,7 +21,7 @@
|
||||
#
|
||||
#
|
||||
|
||||
from qubes.qubes import QubesVmCollection
|
||||
from qubes.qubes import QubesVmCollection,vmm
|
||||
from qubes.qubes import QubesException
|
||||
from optparse import OptionParser;
|
||||
import sys
|
||||
@ -56,6 +56,7 @@ def main():
|
||||
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()
|
||||
|
@ -21,10 +21,11 @@
|
||||
#
|
||||
#
|
||||
|
||||
from qubes.qubes import QubesVmCollection
|
||||
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."
|
||||
|
Loading…
Reference in New Issue
Block a user