qubes: fix Qubes instantiation
This commit is contained in:
parent
8e16dd2b28
commit
d937d39c9e
@ -16,7 +16,9 @@ __version__ = 'R3'
|
||||
import ast
|
||||
import atexit
|
||||
import collections
|
||||
import errno
|
||||
import grp
|
||||
import logging
|
||||
import os
|
||||
import os.path
|
||||
import sys
|
||||
@ -102,7 +104,7 @@ class VMMConnection(object):
|
||||
self._xs = xen.lowlevel.xs.xs()
|
||||
if 'xen.lowlevel.cs' in sys.modules:
|
||||
self._xc = xen.lowlevel.xc.xc()
|
||||
self._libvirt_conn = libvirt.open(defaults['libvirt_uri'])
|
||||
self._libvirt_conn = libvirt.open(qubes.config.defaults['libvirt_uri'])
|
||||
if self._libvirt_conn is None:
|
||||
raise QubesException("Failed connect to libvirt driver")
|
||||
libvirt.registerErrorHandler(self._libvirt_error_handler, None)
|
||||
@ -150,7 +152,7 @@ class QubesHost(object):
|
||||
'''
|
||||
|
||||
def __init__(self, app):
|
||||
self._app = app
|
||||
self.app = app
|
||||
self._no_cpus = None
|
||||
|
||||
|
||||
@ -159,7 +161,7 @@ class QubesHost(object):
|
||||
return
|
||||
|
||||
(model, memory, cpus, mhz, nodes, socket, cores, threads) = \
|
||||
self._app.vmm.libvirt_conn.getInfo()
|
||||
self.app.vmm.libvirt_conn.getInfo()
|
||||
self._total_mem = long(memory) * 1024
|
||||
self._no_cpus = cpus
|
||||
|
||||
@ -214,7 +216,7 @@ class QubesHost(object):
|
||||
previous_time = time.time()
|
||||
previous = {}
|
||||
try:
|
||||
info = self._app.vmm.xc.domain_getinfo(0, qubes_max_qid)
|
||||
info = self.app.vmm.xc.domain_getinfo(0, qubes_max_qid)
|
||||
except AttributeError:
|
||||
raise NotImplementedError(
|
||||
'This function requires Xen hypervisor')
|
||||
@ -761,9 +763,12 @@ class PropertyHolder(qubes.events.Emitter):
|
||||
'''
|
||||
|
||||
def __init__(self, xml, *args, **kwargs):
|
||||
super(PropertyHolder, self).__init__(*args, **kwargs)
|
||||
super(PropertyHolder, self).__init__(*args)
|
||||
self.xml = xml
|
||||
|
||||
for key, value in kwargs.items():
|
||||
setattr(self, key, value)
|
||||
|
||||
|
||||
@classmethod
|
||||
def get_props_list(cls, load_stage=None):
|
||||
@ -1051,11 +1056,15 @@ class Qubes(PropertyHolder):
|
||||
|
||||
|
||||
def __init__(self, store='/var/lib/qubes/qubes.xml'):
|
||||
super(Qubes, self).__init__(xml=None)
|
||||
|
||||
self.log = logging.getLogger('app')
|
||||
|
||||
self._extensions = set(ext(self)
|
||||
for ext in qubes.ext.Extension.register.values())
|
||||
|
||||
#: collection of all VMs managed by this Qubes instance
|
||||
self.domains = VMCollection()
|
||||
self.domains = VMCollection(self)
|
||||
|
||||
#: collection of all available labels for VMs
|
||||
self.labels = {}
|
||||
@ -1067,28 +1076,46 @@ class Qubes(PropertyHolder):
|
||||
self.host = QubesHost(self)
|
||||
|
||||
self._store = store
|
||||
|
||||
try:
|
||||
self.load()
|
||||
except IOError:
|
||||
self._init()
|
||||
|
||||
super(Qubes, self).__init__(
|
||||
xml=lxml.etree.parse(self.qubes_store_file))
|
||||
self.load()
|
||||
|
||||
|
||||
def _open_store(self):
|
||||
'''Open qubes.xml
|
||||
|
||||
This method takes care of creation of the store when it does not exist.
|
||||
|
||||
:raises OSError: on failure
|
||||
:raises lxml.etree.XMLSyntaxError: on syntax error in qubes.xml
|
||||
'''
|
||||
if hasattr(self, '_storefd'):
|
||||
return
|
||||
|
||||
self._storefd = open(self._store, 'r+')
|
||||
try:
|
||||
fd = os.open(self._store,
|
||||
os.O_RDWR | os.O_CREAT | os.O_EXCL | 0o660)
|
||||
parsexml = False
|
||||
except OSError as e:
|
||||
if e.errno != errno.EEXIST:
|
||||
raise
|
||||
|
||||
# file does exist
|
||||
fd = os.open(self._store, os.O_RDWR)
|
||||
parsexml = True
|
||||
|
||||
self._storefd = os.fdopen(fd, 'r+b')
|
||||
|
||||
if os.name == 'posix':
|
||||
fcntl.lockf(self.qubes_store_file, fcntl.LOCK_EX)
|
||||
fcntl.lockf(self._storefd, fcntl.LOCK_EX)
|
||||
elif os.name == 'nt':
|
||||
overlapped = pywintypes.OVERLAPPED()
|
||||
win32file.LockFileEx(win32file._get_osfhandle(self.qubes_store_file.fileno()),
|
||||
win32con.LOCKFILE_EXCLUSIVE_LOCK, 0, -0x10000, overlapped)
|
||||
win32file.LockFileEx(
|
||||
win32file._get_osfhandle(self._storefd.fileno()),
|
||||
win32con.LOCKFILE_EXCLUSIVE_LOCK,
|
||||
0, -0x10000,
|
||||
pywintypes.OVERLAPPED())
|
||||
|
||||
if parsexml:
|
||||
self.xml = lxml.etree.parse(self._storefd)
|
||||
# else: it will remain None, as set by PropertyHolder
|
||||
|
||||
|
||||
def load(self):
|
||||
@ -1098,6 +1125,10 @@ class Qubes(PropertyHolder):
|
||||
'''
|
||||
self._open_store()
|
||||
|
||||
if self.xml is None:
|
||||
self._init()
|
||||
return
|
||||
|
||||
# stage 1: load labels
|
||||
for node in self._xml.xpath('./labels/label'):
|
||||
label = Label.fromxml(node)
|
||||
@ -1110,7 +1141,8 @@ class Qubes(PropertyHolder):
|
||||
self.domains.add(vm)
|
||||
|
||||
if not 0 in self.domains:
|
||||
self.domains.add(qubes.vm.adminvm.AdminVM(self))
|
||||
self.domains.add(qubes.vm.adminvm.AdminVM(
|
||||
self, None, qid=0, name='dom0'))
|
||||
|
||||
# stage 3: load global properties
|
||||
self.load_properties(self.xml, load_stage=3)
|
||||
@ -1153,12 +1185,16 @@ class Qubes(PropertyHolder):
|
||||
8: Label(8, '0x000000', 'black'),
|
||||
}
|
||||
|
||||
self.domains.add(qubes.vm.adminvm.AdminVM(
|
||||
self, None, qid=0, name='dom0'))
|
||||
|
||||
|
||||
def __del__(self):
|
||||
# intentionally do not call explicit unlock to not unlock the file
|
||||
# before all buffers are flushed
|
||||
self._storefd.close()
|
||||
del self._storefd
|
||||
if hasattr(self, '_storefd'):
|
||||
self._storefd.close()
|
||||
del self._storefd
|
||||
|
||||
|
||||
def __xml__(self):
|
||||
|
@ -120,6 +120,10 @@ class DeviceCollection(object):
|
||||
return item in self._set
|
||||
|
||||
|
||||
def __len__(self):
|
||||
return len(self._set)
|
||||
|
||||
|
||||
class DeviceManager(dict):
|
||||
'''Device manager that hold all devices by their classess.
|
||||
|
||||
|
@ -54,9 +54,9 @@ except ImportError:
|
||||
|
||||
|
||||
def _setter_qid(self, prop, value):
|
||||
if not 0 <= value <= qubes.MAX_QID:
|
||||
if not 0 <= value <= qubes.config.max_qid:
|
||||
raise ValueError(
|
||||
'{} value must be between 0 and qubes.MAX_QID'.format(
|
||||
'{} value must be between 0 and qubes.config.max_qid'.format(
|
||||
prop.__name__))
|
||||
return value
|
||||
|
||||
@ -182,7 +182,8 @@ class QubesVM(qubes.vm.BaseVM):
|
||||
# XXX not applicable to HVM?
|
||||
kernelopts = qubes.property('kernelopts', type=str, load_stage=4,
|
||||
default=(lambda self: defaults['kernelopts_pcidevs'] \
|
||||
if len(self.devices['pci']) > 0 else defaults['kernelopts']),
|
||||
if len(self.devices['pci']) > 0 \
|
||||
else qubes.config.defaults['kernelopts']),
|
||||
doc='Kernel command line passed to domain.')
|
||||
|
||||
mac = qubes.property('mac', type=str,
|
||||
@ -398,25 +399,17 @@ class QubesVM(qubes.vm.BaseVM):
|
||||
# constructor
|
||||
#
|
||||
|
||||
def __init__(self, app, xml):
|
||||
super(QubesVM, self).__init__(app, xml)
|
||||
def __init__(self, app, xml, **kwargs):
|
||||
super(QubesVM, self).__init__(app, xml, **kwargs)
|
||||
|
||||
#Init private attrs
|
||||
|
||||
self._libvirt_domain = None
|
||||
self._qdb_connection = None
|
||||
|
||||
assert self.__qid < qubes_max_qid, "VM id out of bounds!"
|
||||
assert self.qid < qubes.config.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, "
|
||||
"or one of 'none', 'true', 'false')") % self.name
|
||||
if xml is not None:
|
||||
print >>sys.stderr, "WARNING: %s" % msg
|
||||
else:
|
||||
raise QubesException(msg)
|
||||
|
||||
# Not in generic way to not create QubesHost() to frequently
|
||||
# XXX this doesn't apply, host is instantiated once
|
||||
if self.maxmem is None and not self.app.vmm.offline_mode:
|
||||
|
Loading…
Reference in New Issue
Block a user