qubes.vm – Different Virtual Machine types

Qubes is composed of several virtual machines that are interconnected in several ways. From now on they will be called „domains”, as they may not actually be true virtual machines – we plan to support LXC containers for example. Because of Xen-only legacy of Qubes code, it is custom to refer to them in long/plural as domains and in short/singular as vm.

Domain object

There are couple of programming objects that refer to domain. The main is the instance of qubes.vm.QubesVM. This is the main „porcelain” object, which carries other objects and supplies convenience methods like qubes.vm.qubesvm.QubesVM.start(). This class is actually divided in two, the qubes.vm.qubesvm.QubesVM cares about Qubes-specific actions, that are more or less directly related to security model. It is intended to be easily auditable by non-expert programmers (ie. we don’t use Python’s magic there). The second class is its parent, qubes.vm.LocalVM, which is concerned about technicalities like XML serialising/deserialising. It is of less concern to threat model auditors, but still relevant to overall security of the Qubes OS. It is written for programmers by programmers.

The second object is the XML node that refers to the domain. It can be accessed as Qubes.vm.LocalVM.xml attribute of the domain object. The third one is Qubes.vm.qubesvm.QubesVM.libvirt_domain object for directly interacting with libvirt. Those objects are intended to be used from core and/or plugins, but not directly by user or from qvm-tools. They are however public, so there are no restrictions.

Domain classes

There are several different types of VM, because not every Qubes domain is equal – some of them perform specific functions, like NetVM; others have different life cycle, like DisposableVM. For that, different domains have different Python classes. They are all defined in this package, generally one class per module, but some modules contain private globals that serve this particular class.

Package contents

Main public classes

class qubes.vm.LocalVM(app, xml, features=None, devices=None, tags=None, **kwargs)[source]

Bases: BaseVM

Base class for all local VMs

Parameters:
  • app (qubes.Qubes) – Qubes application context

  • xml (lxml.etree._Element or None) – xml node from which to deserialize

This class is responsible for serializing and deserializing machines and provides basic framework. It contains no management logic. For that, see qubes.vm.qubesvm.QubesVM.

create_config_file()[source]

Create libvirt’s XML domain config file

get_provided_assignments(required_only: bool = False) List[DeviceAssignment][source]

List device assignments from this VM.

start_qdb_watch(loop=None)[source]

Start watching QubesDB

Calling this method in appropriate time is responsibility of child class.

watch_qdb_path(path)[source]

Add a QubesDB path to be watched.

Each change to the path will cause domain-qdb-change:path event to be fired. You can call this method for example in response to domain-init and domain-load events.

app

mother qubes.Qubes object

devices

DeviceManager object keeping devices that are attached to this domain

storage

storage manager

volumes

storage volumes

Helper classes and functions

class qubes.features.Features(subject, other=None, **kwargs)[source]

Bases: dict

Manager of the features.

Features can have three distinct values: no value (not present in mapping, which is closest thing to None), empty string (which is interpreted as False) and non-empty string, which is True. Anything assigned to the mapping is coerced to strings, however if you assign instances of bool, they are converted as described above. Be aware that assigning the number 0 (which is considered false in Python) will result in string ‘0’, which is considered true.

This class inherits from dict, but has most of the methods that manipulate the item disarmed (they raise NotImplementedError). The ones that are left fire appropriate events on the qube that owns an instance of this class.

check_with_adminvm(feature, default=<object object>)[source]

Check for the specified feature; if this VM does not have it, it checks with the AdminVM.

check_with_netvm(feature, default=<object object>)[source]

Check for the specified feature; if this VM does not have it, it checks with its netvm.

check_with_template(feature, default=<object object>)[source]

Check for the specified feature; if this VM does not have it, it checks with its template.

check_with_template_and_adminvm(feature, default=<object object>)[source]

Check for the specified feature; if this VM does not have it, it checks with its template. If the template does not have it, it checks with the AdminVM.

clear() None.  Remove all items from D.[source]
pop(_key, _default=None)[source]

Not implemented :raises: NotImplementedError

popitem()[source]

Not implemented :raises: NotImplementedError

setdefault(_key, _default=None)[source]

Not implemented :raises: NotImplementedError

update([E, ]**F) None.  Update D from dict/iterable E and F.[source]

If E is present and has a .keys() method, then does: for k in E: D[k] = E[k] If E is present and lacks a .keys() method, then does: for k, v in E: D[k] = v In either case, this is followed by: for k in F: D[k] = F[k]

class qubes.vm.mix.net.NetVMMixin(*args, **kwargs)[source]

Bases: Emitter

Mixin containing network functionality

static get_ip6_for_vm(vm)[source]

Get IPv6 address for (appvm) domain connected to this (netvm) domain.

Default address is constructed with Qubes-specific site-local prefix, and IPv4 suffix (0xa89 is 10.137.).

static get_ip_for_vm(vm)[source]

Get IP address for (appvm) domain connected to this (netvm) domain.

async apply_deferred_netvm()[source]

Apply deferred netvm changes in case qube could not apply it at the time it was requested.

attach_network()[source]

Attach network in this machine to it’s netvm.

detach_network()[source]

Detach machine from it’s netvm

has_firewall()[source]

Return True if there are some vm specific firewall rules set

is_networked()[source]

Check whether this VM can reach network (firewall notwithstanding).

Returns:

True if is machine can reach network, False otherwise.

Return type:

bool

on_domain_pre_shutdown(event, force=False)[source]

Checks before NetVM shutdown if any connected domains are running. If force is True tries to detach network interfaces of connected vms

on_domain_qdb_create(event)[source]

Fills the QubesDB with firewall entries.

on_domain_shutdown_net(event, **kwargs)[source]

Cleanup network interfaces of connected, running VMs.

This will allow re-reconnecting them cleanly later.

async on_domain_started_net(event, **kwargs)[source]

Connect this domain to its downstream domains. Also reload firewall in its netvm.

This is needed when starting netvm after its connected domains.

async on_domain_unpaused_net(event, **kwargs)[source]

Check for deferred netvm changes in case qube was paused while changes happened.

on_firewall_changed(event, **kwargs)[source]

Reloads the firewall if vm is running and has a NetVM assigned

on_net_domain_connect(event, vm)[source]

Reloads the firewall config for vm

on_pre_spawn(event, **kwargs)[source]

Prepare qubesdb in netvm entries before relevant interface is created

on_property_pre_reset_netvm(event, name, oldvalue=None)[source]

Sets the NetVM to default NetVM

on_property_pre_set_netvm(event, name, newvalue, oldvalue=None)[source]

Run sanity checks before setting a new NetVM

on_property_reset_netvm(event, name, oldvalue=None)[source]

Sets the NetVM to default NetVM

on_property_set_netvm(event, name, newvalue, oldvalue=None)[source]

Replaces the current NetVM with a new one and fires net-domain-connect event

reload_connected_ips()[source]

Update list of IPs possibly connected to this machine. This is used by qubes-firewall to implement anti-spoofing.

reload_firewall_for_vm(vm)[source]

Reload the firewall rules for the vm

set_mapped_ip_info_for_vm(vm)[source]

Set configuration to possibly hide real IP from the VM. This needs to be done before executing ‘script’ (/etc/xen/scripts/vif-route-qubes) in network providing VM

property connected_vms

Return a generator containing all domains connected to the current NetVM.

dns

DNS servers set up for this domain.

gateway

Gateway for other domains that use this domain as netvm.

gateway6

Gateway (IPv6) for other domains that use this domain as netvm.

ip

IP address of this domain.

ip6

IPv6 address of this domain.

mac

MAC address of the NIC emulated inside VM

property netmask

Netmask for gateway address.

netvm

VM that provides network connection to this domain. When None, machine is disconnected. When absent, domain uses default NetVM.

provides_network

If this domain can act as network provider (formerly known as NetVM or ProxyVM)

visible_gateway

Default gateway of this domain as seen by the domain.

visible_gateway6

Default (IPv6) gateway of this domain as seen by the domain.

visible_ip

IP address of this domain as seen by the domain.

visible_ip6

IPv6 address of this domain as seen by the domain.

visible_netmask

Netmask as seen by the domain.

class qubes.vm.mix.dvmtemplate.DVMTemplateMixin(*args, **kwargs)[source]

Bases: Emitter

VM class capable of being disposable template.

can_preload() bool[source]

Check if there is preload vacancy.

Return type:

bool

get_feat_global_preload_max() int | None[source]

Get the global preload-dispvm-max feature as an integer if it is set, None otherwise.

Return type:

Optional[int]

get_feat_preload() list[str][source]

Get the preload-dispvm feature as a list.

Return type:

list[str]

get_feat_preload_delay() float[source]

Get the preload-dispvm-delay feature as float.

Return type:

float

get_feat_preload_max(force_local=False) int[source]

Get the preload-dispvm-max feature as an integer.

Parameters:

force_local (bool) – ignore global setting.

Return type:

Optional[int]

get_feat_preload_threshold() int[source]

Get the preload-dispvm-threshold feature as int (bytes unit).

Return type:

int

is_global_preload_distinct() bool[source]

Check if global preload feature is distinct compared to local one.

Return type:

bool

is_global_preload_set() bool[source]

Check if this qube is the global default_dispvm and the global preload feature is set.

Return type:

bool

on_domain_loaded(event) None[source]

Cleanup invalid preloaded qubes when domain is loaded.

Parameters:

event (str) – Event which was fired.

async on_domain_preload_dispvm_used(event: str, dispvm: DispVM | None = None, reason: str | None = None, delay: int | float = 0, **kwargs) None[source]

Offloads on excess and preload on vacancy.

Parameters:
  • event (str) – Event which was fired. Events have the prefix domain-preload-dispvm-. It always tries to preload until it fills the gaps if there is enough memory.

  • dispvm (qubes.vm.dispvm.DispVM) – Disposable that was used

  • reason (str) – Why the event was fired

  • delay (float) – Proceed only after sleeping that many seconds

async on_dvmtemplate_domain_shutdown(_event, **_kwargs) None[source]

Refresh preloaded disposables on shutdown.

on_dvmtemplate_property_changed(_event, name, **_kwargs) None[source]

Refresh preloaded disposables if property affects the disposable.

on_feature_delete_preload_dispvm_max(event, feature) None[source]

On deletion of the preload-dispvm-max feature, remove all preloaded disposables if the global preload is not set.

Parameters:
  • event (str) – Event which was fired.

  • feature (str) – Feature name.

on_feature_pre_set_preload_dispvm(event, feature, value, oldvalue=None)[source]

Before accepting the preload-dispvm feature, validate it.

Parameters:
  • event (str) – Event which was fired.

  • feature (str) – Feature name.

  • value (str) – New value of the feature.

  • oldvalue (str) – Old value of the feature.

on_feature_pre_set_preload_dispvm_delay(event, feature, value, oldvalue=None)[source]

Before accepting the preload-dispvm-delay feature, validate it.

Parameters:
  • event (str) – Event which was fired.

  • feature (str) – Feature name.

  • value (int) – New value of the feature.

  • oldvalue (int) – Old value of the feature.

on_feature_pre_set_preload_dispvm_max(event, feature, value, oldvalue=None)[source]

Before accepting the preload-dispvm-max feature, validate it.

Parameters:
  • event (str) – Event which was fired.

  • feature (str) – Feature name.

  • value (int) – New value of the feature.

  • oldvalue (int) – Old value of the feature.

on_feature_set_preload_dispvm(event, feature, value, oldvalue=None)[source]

After setting the preload-dispvm feature, reset the is_preload property.

Parameters:
  • event (str) – Event which was fired.

  • feature (str) – Feature name.

  • value (str) – New value of the feature.

  • oldvalue (str) – Old value of the feature.

on_feature_set_preload_dispvm_max(event, feature, value, oldvalue=None)[source]

After setting the preload-dispvm-max feature, attempt to preload.

Parameters:
  • event (str) – Event which was fired.

  • feature (str) – Feature name.

  • value (int) – New value of the feature.

  • oldvalue (int) – Old value of the feature.

refresh_outdated_preload(skip_check: bool = False, delay: int | float = 4) None[source]

Refresh disposables which have outdated volumes or properties.

Parameters:

skip_check (bool) – Skip check of outdated preloads, refresh all.

remove_preload_excess(max_preload: int | None = None, reason: str | None = None) None[source]

Removes preloaded qubes that exceeds the maximum specified.

Parameters:
  • max_preload (Optional[int]) – Maximum number of preloaded that should exist.

  • reason (Optional[str]) – Explanation of why it is being done.

remove_preload_from_list(disposables: list[str], reason: str | None = None) None[source]

Removes list of preload qubes from the list.

Parameters:
  • disposables (list[str]) – Disposable names to remove from list.

  • reason (Optional[str]) – Explanation of why it is being done.

request_preload() DispVM | None[source]

Request preloaded disposable.

Return type:

Optional[“qubes.vm.dispvm.DispVM”]

supports_preload() Tuple[bool, list][source]

Check if the necessary RPCs are supported.

The first returned value indicates success while the second value is non empty and contains the missing services if they are not supported.

Return type:

(bool, list)

property dispvms: Iterator[DispVM]

Get all disposables based on the current disposable template.

Return type:

Iterator[qubes.vm.dispvm.DispVM]

template_for_dispvms

Should this VM be allowed to start as Disposable VM

Particular VM classes

Main types:

Special VM types: