qubes
– Common concepts¶
Global Qubes object¶
Because all objects in Qubes’ world are interconnected, there is no possibility
to instantiate them separately. They are all loaded together and contained in
the one app
object, an instance of qubes.Qubes
class.
Loading¶
The objects may come to existence in two ways: by explicit instantiation or by loading from XML file.
The loading from XML is done in stages, because Qubes domains are dependent on each other in what can be even a circular dependency. Therefore some properties (especialy those that refer to another domains) are loaded later.
Refer to qubes.Qubes
class documentation to get description of every
stage.
Properties¶
Many parameters of Qubes can be changed – from names of particular domains to default NetVM for all AppVMs. All of those configurable parameters are called properties and can be accessed like Python attributes on their owners:
>>> import qubes
>>> app = qubes.Qubes()
>>> app.domains[0] # docutils: +ELLIPSIS
<AdminVM ...>
>>> app.domains[0].name
'dom0'
Definition¶
Properties are defined on global qubes.Qubes
application object and
on every domain. Those classes inherit from PropertyHolder
class,
which is responsible for operation of properties.
Each Qubes property is actually a data descriptor (a Python term), which means
they are attributes of their classes, but when trying to access it from
instance, they return its underlying value instead. They can be thought of as
Python’s builtin property
, but greatly enhanced. They are defined in
definition of their class:
>>> import qubes
>>> class MyTestHolder(qubes.PropertyHolder):
>>> testprop = qubes.property('testprop')
>>> instance = MyTestHolder()
>>> instance.testprop = 'aqq'
>>> instance.testprop
'aqq'
If you like to access some attributes of the property itself, you should refer to instance’s class:
>>> import qubes
>>> class MyTestHolder(qubes.PropertyHolder):
>>> testprop = qubes.property('testprop')
>>> instance = MyTestHolder()
>>> instance.testprop = 'aqq'
>>> type(instance.testprop)
<type 'str'>
>>> type(instance.__class__.testprop)
<class 'qubes.property'>
>>> instance.__class__.testprop.__name__
'testprop'
As a rule, properties are intended to be serialised and deserialised to/from XML
file. There are very few exceptions, but if you don’t intend to save the
property to XML, you should generally go for builtin property
.
One important difference from builtin properties is that there is no getter function, only setter. In other words, they are not dynamic, you cannot return different value every time something wants to access it. This is to ensure that while saving the property is not a moving target.
Property’s properties¶
You can specify some parameters while defining the property. The most important
is the type: on setting, the value is coerced to this type. It is well suited
to builtin types like int
:
>>> import qubes
>>> class MyTestHolder(qubes.PropertyHolder):
>>> testprop = qubes.property('testprop')
>>> intprop = qubes.property('intprop', type=int)
>>> instance = MyTestHolder()
>>> instance.testprop = '123'
>>> instance.intprop = '123'
>>> instance.testprop
'123'
>>> instance.intprop
123
Every property should be documented. You should add a short description to your property, which will appear, among others, in qvm-prefs and qvm-ls programs. It should not use any Sphinx-specific markup:
>>> import qubes
>>> class MyTestHolder(qubes.PropertyHolder):
>>> testprop = qubes.property('testprop',
>>> doc='My new and shiny property.')
>>> MyTestHolder.testprop.__doc__
'My new and shiny property.'
In addition to type, properties also support setter parameter. It acts similar to type, but is always executed (not only when types don’t agree) and accepts more parameters: self, prop and value being respectively: owners’ instance, property’s instance and the value being set. There is also saver, which does reverse: given value of the property it should return a string that can be parsed by setter.
Unset properties and default values¶
Properties may be unset, even if they are defined (that is, on access they raise
AttributeError
– that is the normal Python way to tell that the
attribute is absent). You can manually unset a property using Python’s del
statement:
>>> import qubes
>>> class MyTestHolder(qubes.PropertyHolder):
>>> testprop = qubes.property('testprop')
>>> instance = MyTestHolder()
>>> instance.testprop
AttributeError: ...
>>> instance.testprop = 123
>>> instance.testprop
123
>>> del instance.testprop
>>> instance.testprop
AttributeError: ...
Alternatively, some properties may return some other value instead, if that’s
the reasonable thing to do. For example, when
qubes.vm.qubesvm.QubesVM.netvm
is unset, we check global setting
qubes.Qubes.default_netvm
instead. Returning None
as
default would be wrong, as it is marker that means „no NetVM, machine
disconnected”.
You can define a default value either as constant or as a callable. In the second case, the callable should accept one argument, the instance that owns the property:
>>> import qubes
>>> class MyTestHolder(qubes.PropertyHolder):
>>> testprop = qubes.property('testprop')
>>> def1prop = qubes.property('testprop', default=123)
>>> netvm = qubes.property('testprop',
>>> default=(lambda self: self.app.default_netvm))
>>> instance = MyTestHolder()
>>> instance.testprop
AttributeError: ...
>>> instance.def1prop
123
>>> instance.netvm
<NetVM ...>
Setting netvm on particular domain of course does not affect global default, but only this instance. But there are two problems:
You don’t know if the value of the property you just accessed was its true or default value.
After
del
’ing a property, you still will get a value on access. You cannot count on AttributeError raised from them.
Therefore Qubes support alternative semantics. You can (and probably should,
wherever applicable) use not del
, but assignment of special magic object
qubes.property.DEFAULT
. There is also method
qubes.PropertyHolder.property_is_default()
, which can be used to
distinguish unset from set properties:
>>> import qubes
>>> class MyTestHolder(qubes.PropertyHolder):
>>> testprop = qubes.property('testprop', default=123)
>>> instance.testprop
123
>>> instance.property_is_default('testprop')
True
>>> instance.testprop = 123
>>> instance.testprop
>>> instance.property_is_default('testprop')
False
>>> instance.testprop = qubes.property.DEFAULT
>>> instance.property_is_default('testprop')
True
Inheritance¶
Properties in subclasses overload properties from their parents, like expected:
>>> import qubes
>>> class MyTestHolder(qubes.PropertyHolder):
>>> testprop = qubes.property('testprop')
>>> class MyOtherHolder(MyTestHolder):
>>> testprop = qubes.property('testprop', setter=qubes.property.forbidden)
>>> instance = MyOtherHolder()
>>> instane.testprop = 123
TypeError: ...
Module contents¶
Qubes OS
- copyright:
© 2010-2015 Invisible Things Lab
- class qubes.Label(index, color, name)[source]¶
Bases:
object
Label definition for virtual machines
Label specifies colour of the padlock displayed next to VM’s name. When this is a
qubes.vm.dispvm.DispVM
, padlock is overlayed with recycling pictogram.- Parameters:
- classmethod fromxml(xml)[source]¶
Create label definition from XML node
- Parameters:
xml (lxml.etree._Element) – XML node reference
- Return type:
- color¶
colour specification as in HTML (
#abcdef
)
- icon¶
freedesktop icon name, suitable for use in
PyQt4.QtGui.QIcon.fromTheme()
- icon_dispvm¶
freedesktop icon name, suitable for use in
PyQt4.QtGui.QIcon.fromTheme()
on DispVMs
- property icon_path¶
Icon path
Deprecated since version 2.0: use
PyQt4.QtGui.QIcon.fromTheme()
andicon
- property icon_path_dispvm¶
Icon path
Deprecated since version 2.0: use
PyQt4.QtGui.QIcon.fromTheme()
andicon_dispvm
- index¶
numeric identificator of label
- name¶
label’s name like “red” or “green”
- class qubes.PropertyHolder(xml, **kwargs)[source]¶
Bases:
Emitter
Abstract class for holding
qubes.property
Events fired by instances of this class:
- property-load(subject, event)¶
Fired once after all properties are loaded from XML. Individual
property-set
events are not fired.
- property-set:<propname>(subject, event, name, newvalue[, oldvalue])¶
Fired when property changes state. Signature is variable, oldvalue is present only if there was an old value.
- Parameters:
name – Property name
newvalue – New value of the property
oldvalue – Old value of the property
- property-pre-set:<propname>(subject, event, name, newvalue[, oldvalue])¶
Fired before property changes state. Signature is variable, oldvalue is present only if there was an old value.
- Parameters:
name – Property name
newvalue – New value of the property
oldvalue – Old value of the property
- property-del:<propname>(subject, event, name[, oldvalue])¶
Fired when property gets deleted (is set to default). Signature is variable, oldvalue is present only if there was an old value.
This event is deprecated and will be removed in Qubes 5.0. Use property-reset instead.
- Parameters:
name – Property name
oldvalue – Old value of the property
- property-pre-del:<propname>(subject, event, name[, oldvalue])¶
Fired before property gets deleted (is set to default). Signature is variable, oldvalue is present only if there was an old value.
This event is deprecated and will be removed in Qubes 5.0. Use property-pre-reset instead.
- Parameters:
name – Property name
oldvalue – Old value of the property
- property-reset:<propname>(subject, event, name[, oldvalue])¶
Fired when property gets reset to the (possibly dynamic) default. This even may be also fired when the property is already in “default” state, but the calculated default value changes. Signature is variable, oldvalue is present only if there was an old value.
- Parameters:
name – Property name
oldvalue – Old value of the property
- property-pre-reset:<propname>(subject, event, name[, oldvalue])¶
Fired before property gets reset to the (possibly dynamic) default. Signature is variable, oldvalue is present only if there was an old value.
- Parameters:
name – Property name
oldvalue – Old value of the property
- clone-properties(subject, event, src, proplist)¶
- Parameters:
src – object, from which we are cloning
proplist – list of properties
Members:
- clone_properties(src, proplist=None)[source]¶
Clone properties from other object.
- Parameters:
src (PropertyHolder) – source object
proplist (iterable) – list of properties (
None
or omit for all properties except those withproperty.clone
set toFalse
)
- load_properties(load_stage=None)[source]¶
Load properties from immediate children of XML node.
property-set
events are not fired for each individual property.- Parameters:
load_stage (int) – Stage of loading.
- classmethod property_dict(load_stage=None)[source]¶
List all properties attached to this VM’s class
- Parameters:
load_stage (
int()
orNone
) – Filter by load stage
- classmethod property_get_def(prop)[source]¶
Return property definition object.
If prop is already
qubes.property
instance, return the same object.- Parameters:
prop (qubes.property or str) – property object or name
- Return type:
- property_get_default(prop)[source]¶
Get property default value.
- Parameters:
prop (qubes.property or str) – property object of particular
interest
- property_is_default(prop)[source]¶
Check whether property is in it’s default value.
Properties when unset may return some default value, so
hasattr(vm, prop.__name__)
is wrong in some circumstances. This method allows for checking if the value returned is in fact it’s default value.- Parameters:
prop (qubes.property) – property object of particular interest
- Return type:
- classmethod property_list(load_stage=None)[source]¶
List all properties attached to this VM’s class
- Parameters:
load_stage (
int()
orNone
) – Filter by load stage
- property_require(prop, allow_none=False, hard=False)[source]¶
Complain badly when property is not set.
- Parameters:
prop (qubes.property or str) – property name or object
allow_none (bool) – if
True
, don’t complain ifNone
is foundhard (bool) – if
True
, raiseAssertionError
; ifFalse
, log warning instead
- class qubes.Qubes(store=None, load=True, offline_mode=None, lock=False, **kwargs)[source]¶
Bases:
PropertyHolder
Main Qubes application
- Parameters:
store (str) – path to
qubes.xml
The store is loaded in stages:
In the first stage there are loaded some basic features from store (currently labels).
In the second stage stubs for all VMs are loaded. They are filled with their basic properties, like
qid
andname
.In the third stage all global properties are loaded. They often reference VMs, like default netvm, so they should be filled after loading VMs.
In the fourth stage all remaining VM properties are loaded. They also need all VMs loaded, because they represent dependencies between VMs like aforementioned netvm.
In the fifth stage there are some fixups to ensure sane system operation.
This class emits following events:
- domain-add(subject, event, vm)¶
When domain is added.
- Parameters:
subject – Event emitter
event – Event name (
'domain-add'
)vm – Domain object
- domain-pre-delete(subject, event, vm)¶
When domain is deleted. VM still has reference to
app
object, and is contained within VMCollection. You may prevent removal by raising an exception.- Parameters:
subject – Event emitter
event – Event name (
'domain-pre-delete'
)vm – Domain object
- domain-delete(subject, event, vm)¶
When domain is deleted. VM still has reference to
app
object, but is not contained within VMCollection.- Parameters:
subject – Event emitter
event – Event name (
'domain-delete'
)vm – Domain object
- pool-add(subject, event, pool)¶
When storage pool is added.
Handler for this event may be asynchronous.
- Parameters:
subject – Event emitter
event – Event name (
'pool-add'
)pool – Pool object
- pool-pre-delete(subject, event, pool)¶
When pool is deleted. Pool is still contained within app.pools dictionary. You may prevent removal by raising an exception.
Handler for this event may be asynchronous.
- Parameters:
subject – Event emitter
event – Event name (
'pool-pre-delete'
)pool – Pool object
- pool-delete(subject, event, pool)¶
When storage pool is deleted. The pool is already removed at this point.
Handler for this event may be asynchronous.
- Parameters:
subject – Event emitter
event – Event name (
'pool-delete'
)pool – Pool object
- qubes-close(subject, event)¶
Fired when this Qubes() object instance is going to be closed and destroyed. In practice it is called only during tests, to cleanup objects from one test, before another. It is _not_ called when qubesd daemon is stopped.
- Parameters:
subject – Event emitter
event – Event name (
'qubes-close'
)
Methods and attributes:
- close()[source]¶
Deconstruct the object and break circular references
After calling this the object is unusable, not even for saving.
- get_label(label)[source]¶
Get label as identified by index or name
- Throws KeyError:
when label is not found
- get_pool(pool)[source]¶
Returns a
qubes.storage.Pool
instance
- static get_vm_class(clsname)[source]¶
Find the class for a domain.
Classes are registered as setuptools’ entry points in
qubes.vm
group. Any package may supply their own classes.- Parameters:
clsname (str) – name of the class
- Return type:
class
- load(lock=False)[source]¶
Open qubes.xml
- Throws EnvironmentError:
failure on parsing store
- Throws xml.parsers.expat.ExpatError:
failure on parsing store
- Raises:
lxml.etree.XMLSyntaxError – on syntax error in qubes.xml
- register_event_handlers(old_connection=None)[source]¶
Register libvirt event handlers, which will translate libvirt events into qubes.events. This function should be called only in ‘qubesd’ process and only when mainloop has been already set.
- save(lock=True)[source]¶
Save all data to qubes.xml
There are several problems with saving
qubes.xml
which must be mitigated:Running out of disk space. No space left should not result in empty file. This is done by writing to temporary file and then renaming.
Attempts to write two or more files concurrently. This is done by sophisticated locking.
- Parameters:
lock (bool) – keep file locked after saving
- Throws EnvironmentError:
failure on saving
- check_updates_vm¶
Check for updates inside qubes
- clockvm¶
Which VM to use as NTP proxy for updating AdminVM
- default_audiovm¶
Default AudioVM for VMs.
- default_dispvm¶
Default DispVM base for service calls
- default_guivm¶
Default GuiVM for VMs.
- default_kernel¶
Which kernel to use when not overriden in VM
- default_netvm¶
Default NetVM for AppVMs. Initial state is None, which means that AppVMs are not connected to the Internet.
- default_pool¶
Default storage pool
- default_pool_kernel¶
Default storage pool for kernel volumes
- default_pool_private¶
Default storage pool for private volumes
- default_pool_root¶
Default storage pool for root volumes
- default_pool_volatile¶
Default storage pool for volatile volumes
- default_qrexec_timeout¶
Default time in seconds after which qrexec connection attempt is deemed failed
- default_shutdown_timeout¶
Default time in seconds for VM shutdown to complete
- default_template¶
Default template for new AppVMs
- domains¶
collection of all VMs managed by this Qubes instance
- env¶
jinja2 environment for libvirt XML templates
- host¶
Information about host system
- labels¶
collection of all available labels for VMs
- log¶
logger instance for logging global messages
- management_dispvm¶
Default DispVM base for managing VMs
- pools¶
collection of all pools
- stats_interval¶
Interval in seconds for VM stats reporting (memory, CPU usage)
- updatevm¶
Which VM to use as yum proxy for updating AdminVM and TemplateVMs
- vmm¶
Connection to VMM
- class qubes.VMProperty(name, vmclass=<class 'qubes.vm.BaseVM'>, allow_none=False, **kwargs)[source]¶
Bases:
property
Property that is referring to a VM
- Parameters:
vmclass (type) – class that returned VM is supposed to be instance of
and all supported by
property
with the exception oftype
andsetter
- class qubes.property(name, setter=None, saver=None, type=None, *, default=<object object>, write_once=False, load_stage=2, order=0, save_via_ref=False, clone=True, doc=None)[source]¶
Bases:
object
Qubes property.
This class holds one property that can be saved to and loaded from
qubes.xml
. It is used for both global and per-VM properties.Property can be unset by ordinary
del
statement or assigningDEFAULT
special value to it. After deletion (or before first assignment/load) attempting to read a property will get its default value or, when no default, py:class:exceptions.AttributeError.- Parameters:
name (str) – name of the property
setter (collections.abc.Callable) – if not
None
, this is used to initialise value; first parameter to the function is holder instance and the second is value; this is called beforetype
saver (collections.abc.Callable) – function to coerce value to something readable by setter
default (object) – default value; if callable, will be called with holder as first argument
load_stage (int) – stage when property should be loaded (see
Qubes
for description of stages)order (int) – order of evaluation (bigger order values are later)
clone (bool) –
PropertyHolder.clone_properties()
will not include this property by default ifFalse
doc (str) – docstring; this should be one paragraph of plain RST, no sphinx-specific features
Setters and savers have following signatures:
- exception DontSave[source]¶
Bases:
Exception
This exception may be raised from saver to sign that property should not be saved.
- static bool(self, prop, value)[source]¶
Property setter for boolean properties.
It accepts (case-insensitive)
'0'
,'no'
andfalse
asFalse
and'1'
,'yes'
and'true'
asTrue
.
- static forbidden(self, prop, value)[source]¶
Property setter that forbids loading a property.
This is used to effectively disable property in classes which inherit unwanted property. When someone attempts to load such a property, it
- Throws qubes.exc.QubesPropertyValueError:
always
- sanitize(*, untrusted_newvalue)[source]¶
Coarse sanitization of value to be set, before sending it to a setter. Can raise QubesValueError if the value is invalid.
- Parameters:
untrusted_newvalue – value to be validated
- Returns:
sanitized value
- Raises:
qubes.exc.QubesValueError
- DEFAULT = <object object>¶
Assigning this value to property means setting it to its default value. If property has no default value, this will unset it.