Source code for qubes.vm.templatevm

#
# The Qubes OS Project, http://www.qubes-os.org
#
# Copyright (C) 2014-2016  Wojtek Porczyk <woju@invisiblethingslab.com>
# Copyright (C) 2016       Marek Marczykowski <marmarek@invisiblethingslab.com>)
# Copyright (C) 2016       Bahtiar `kalkin-` Gadimov <bahtiar@gadimov.de>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, see <https://www.gnu.org/licenses/>.
#

""" This module contains the TemplateVM implementation """

import qubes
import qubes.config
import qubes.vm.qubesvm
import qubes.vm.mix.net
from qubes.config import defaults
from qubes.vm.qubesvm import QubesVM


def _default_appvm_default_bootmode(self):
    if "boot-mode.appvm-default" in self.features:
        return self.features["boot-mode.appvm-default"]
    return "default"


[docs] class TemplateVM(QubesVM): """Template for AppVM""" dir_path_prefix = qubes.config.system_path["qubes_templates_dir"] @property def appvms(self): """Returns a generator containing all domains based on the current TemplateVM. """ for vm in self.app.domains: if hasattr(vm, "template") and vm.template is self: yield vm appvm_default_bootmode = qubes.property( "appvm_default_bootmode", type=str, load_stage=4, default=_default_appvm_default_bootmode, doc="Default active bootmode for AppVMs based on this template", ) netvm = qubes.VMProperty( "netvm", load_stage=4, allow_none=True, default=None, # pylint: disable=protected-access setter=qubes.vm.qubesvm.QubesVM.netvm._setter, doc="VM that provides network connection to this domain. When " "`None`, machine is disconnected.", ) def __init__(self, *args, **kwargs): assert "template" not in kwargs, "A TemplateVM can not have a template" self.volume_config = { "root": { "name": "root", "snap_on_start": False, "save_on_stop": True, "rw": True, "source": None, "size": defaults["root_img_size"], }, "private": { "name": "private", "snap_on_start": False, "save_on_stop": True, "rw": True, "source": None, "size": defaults["private_img_size"], # For historic reasons, the private VM volume needed to have # this value set to # 'revisions_to_keep': 0, # but now it is fine to simply use whatever the pool driver # uses as default. }, "volatile": { "name": "volatile", "size": defaults["root_img_size"], "snap_on_start": False, "save_on_stop": False, "rw": True, }, "kernel": { "name": "kernel", "snap_on_start": False, "save_on_stop": False, "rw": False, }, } super().__init__(*args, **kwargs) @qubes.events.handler("domain-feature-set:boot-mode.appvm-default") def on_feature_bootmode_appvm_set( self, event, feature, value, oldvalue=None ): # pylint: disable=unused-argument if value == oldvalue: return if self.property_is_default("appvm_default_bootmode"): self.fire_event( "property-reset:appvm_default_bootmode", name="appvm_default_bootmode", ) for appvm in getattr(self, "appvms", []): if appvm.property_is_default("bootmode"): appvm.fire_event("property-reset:bootmode", name="bootmode") @qubes.events.handler( "property-set:appvm_default_bootmode", ) def on_property_bootmode_appvm_set( self, event, name, newvalue, oldvalue=None ): # pylint: disable=unused-argument if newvalue == oldvalue: return for appvm in getattr(self, "appvms", []): if appvm.property_is_default("bootmode"): appvm.fire_event("property-reset:bootmode", name="bootmode") # pylint: disable=invalid-name @qubes.events.handler( "property-reset:appvm_default_bootmode", ) def on_property_bootmode_appvm_reset(self, event, name, oldvalue=None): # pylint: disable=unused-argument for appvm in getattr(self, "appvms", []): if appvm.property_is_default("bootmode"): appvm.fire_event("property-reset:bootmode", name="bootmode")
[docs] @qubes.events.handler( "property-set:default_user", "property-set:kernel", "property-set:kernelopts", "property-set:vcpus", "property-set:memory", "property-set:maxmem", "property-set:qrexec_timeout", "property-set:shutdown_timeout", "property-set:management_dispvm", ) def on_property_set_child(self, _event, name, newvalue, oldvalue=None): """Send event about default value change to child VMs (which use default inherited from the template). This handler is supposed to be set for properties using `_default_with_template()` function for the default value. """ if newvalue == oldvalue: return for vm in self.appvms: if not vm.property_is_default(name): continue vm.fire_event("property-reset:" + name, name=name)