@@ -1632,6 +1632,8 @@ def _domain_event_callback(self, _conn, domain, event, _detail, _opaque):
16321632 @qubes .events .handler ("domain-pre-delete" )
16331633 def on_domain_pre_deleted (self , event , vm ):
16341634 # pylint: disable=unused-argument
1635+ preloads = set ()
1636+ dependencies = []
16351637 for obj in itertools .chain (self .domains , (self ,)):
16361638 if obj is vm :
16371639 # allow removed VM to reference itself
@@ -1642,18 +1644,33 @@ def on_domain_pre_deleted(self, event, vm):
16421644 isinstance (prop , qubes .vm .VMProperty )
16431645 and getattr (obj , prop .__name__ ) == vm
16441646 ):
1645- self .log .error (
1646- "Cannot remove %s, used by %s.%s" ,
1647- vm ,
1648- obj ,
1649- prop .__name__ ,
1650- )
1651- raise qubes .exc .QubesVMInUseError (
1652- vm ,
1653- "Domain is in use: {!r};"
1654- "see 'journalctl -u qubesd -e' in dom0 for "
1655- "details" .format (vm .name ),
1656- )
1647+ if getattr (obj , "is_preload" , False ) and (
1648+ prop .__name__ == "template"
1649+ or (
1650+ prop .__name__ == "default_dispvm"
1651+ and getattr (obj , "template" , None ) == vm
1652+ )
1653+ ):
1654+ preloads .add (obj .name )
1655+ continue
1656+ if isinstance (obj , qubes .app .Qubes ):
1657+ dependencies .append (('"GLOBAL"' , prop .__name__ ))
1658+ elif not obj .property_is_default (prop ):
1659+ dependencies .append ((obj .name , prop .__name__ ))
1660+ if dependencies :
1661+ self .log .error (
1662+ "Cannot remove %s, used by %s" ,
1663+ vm ,
1664+ ", " .join (
1665+ "." .join (str (i ) for i in tup ) for tup in dependencies
1666+ ),
1667+ )
1668+ raise qubes .exc .QubesVMInUseError (
1669+ vm ,
1670+ "Domain is in use: {!r};"
1671+ "see 'journalctl -u qubesd -e' in dom0 for "
1672+ "details" .format (vm .name ),
1673+ )
16571674 if isinstance (vm , qubes .vm .qubesvm .QubesVM ):
16581675 assignments = vm .get_provided_assignments ()
16591676 else :
@@ -1664,6 +1681,9 @@ def on_domain_pre_deleted(self, event, vm):
16641681 vm , "VM has devices assigned to other VMs: " + desc
16651682 )
16661683
1684+ if preloads :
1685+ vm .remove_preload_excess (0 , reason = "domain will be deleted" )
1686+
16671687 @qubes .events .handler ("domain-delete" )
16681688 def on_domain_deleted (self , event , vm ):
16691689 # pylint: disable=unused-argument
0 commit comments