diff --git a/qubes/vm/dispvm.py b/qubes/vm/dispvm.py index cd64ffff..6e089f48 100644 --- a/qubes/vm/dispvm.py +++ b/qubes/vm/dispvm.py @@ -145,14 +145,33 @@ class DispVM(qubes.vm.qubesvm.QubesVM): ''' # pylint: disable=unused-argument assert self.template - @qubes.events.handler('property-pre-set:template', - 'property-pre-reset:template') - def on_property_pre_set_template(self, event, name, newvalue=None, + @qubes.events.handler('property-pre-reset:template') + def on_property_pre_reset_template(self, event, name, oldvalue=None): + '''Forbid deleting template of running VM + ''' # pylint: disable=unused-argument,no-self-use + raise qubes.exc.QubesValueError('Cannot unset template') + + @qubes.events.handler('property-pre-set:template') + def on_property_pre_set_template(self, event, name, newvalue, oldvalue=None): - ''' Disposable VM cannot have template changed ''' - # pylint: disable=unused-argument - raise qubes.exc.QubesValueError(self, - 'Cannot change template of Disposable VM') + '''Forbid changing template of running VM + ''' # pylint: disable=unused-argument + if not self.is_halted(): + raise qubes.exc.QubesVMNotHaltedError(self, + 'Cannot change template while qube is running') + + @qubes.events.handler('property-set:template') + def on_property_set_template(self, event, name, newvalue, oldvalue=None): + ''' Adjust root (and possibly other snap_on_start=True) volume + on template change. + ''' # pylint: disable=unused-argument + + for volume_name, conf in self.default_volume_config.items(): + if conf.get('snap_on_start', False) and \ + conf.get('source', None) is None: + config = conf.copy() + self.volume_config[volume_name] = config + self.storage.init_volume(volume_name, config) @qubes.events.handler('domain-shutdown') @asyncio.coroutine diff --git a/qubes/vm/mix/dvmtemplate.py b/qubes/vm/mix/dvmtemplate.py index ffff5e54..07b9103b 100644 --- a/qubes/vm/mix/dvmtemplate.py +++ b/qubes/vm/mix/dvmtemplate.py @@ -45,14 +45,12 @@ class DVMTemplateMixin(qubes.events.Emitter): self.__on_pre_set_dvmtemplate( event, name, False, oldvalue) - @qubes.events.handler('property-pre-set:template') - def __on_property_pre_set_template(self, event, name, newvalue, + @qubes.events.handler('property-set:template') + def __on_property_set_template(self, event, name, newvalue, oldvalue=None): # pylint: disable=unused-argument - if any(self.dispvms): - raise qubes.exc.QubesVMInUseError(self, - 'Cannot change template ' - 'while there are DispVMs based on this qube') + for vm in self.dispvms: + vm.on_property_set_template(event, name, newvalue, oldvalue) @property def dispvms(self):