Skip to content

Commit cb5d91f

Browse files
committed
EXPERIMENTAL Test early startup error of insufficient reserve
The "request_mem" is done very early on "QubesVM.start", the error handling doesn't have "self.kill" as the domain is not running yet, and therefore it was skipping "_auto_cleanup". Make sure that early startup failures are property handled, not remaining disposable in the domains collection nor in the preload-dispvm list.
1 parent a82f4f2 commit cb5d91f

2 files changed

Lines changed: 47 additions & 2 deletions

File tree

qubes/tests/integ/dispvm.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1104,6 +1104,52 @@ def mock_open_mem_threshold(file, *args, **kwargs):
11041104
)
11051105
self.assertEqual(1, len(self.disp_base.get_feat_preload()))
11061106

1107+
def test_012_preload_low_mem_eary_startup(self):
1108+
"""Test preloading with low memory on early startup"""
1109+
self.loop.run_until_complete(self._test_012_preload_low_mem_early_startup())
1110+
1111+
async def _test_012_preload_low_mem_early_startup(self):
1112+
# pylint: disable=unspecified-encoding
1113+
logger.info("start")
1114+
unpatched_open = open
1115+
1116+
def mock_open_mem_raise(file, *args, **kwargs):
1117+
if file == qubes.config.qmemman_avail_mem_file:
1118+
raise FileNotFoundError(2, "No such file or directory", file)
1119+
return unpatched_open(file, *args, **kwargs)
1120+
1121+
await self.cleanup_preload_run(self.disp_base)
1122+
self.disp_base.features["preload-dispvm-max"] = "0"
1123+
with patch("builtins.open", side_effect=mock_open_mem_raise):
1124+
logger.info("insufficient memory reserve (early startup failure)")
1125+
old_memory = self.disp_base.memory
1126+
old_dispvms = [
1127+
qube.name
1128+
for qube in self.app.domains
1129+
if getattr(qube, "is_preload", False)
1130+
]
1131+
self.disp_base.memory = 999999999999999999999
1132+
self.disp_base.features["preload-dispvm-max"] = str(preload_max)
1133+
await self.wait_preload(
1134+
preload_max, fail_on_timeout=False, timeout=15
1135+
)
1136+
self.assertEqual(0, len(self.disp_base.get_feat_preload()))
1137+
new_dispvms = [
1138+
qube.name
1139+
for qube in self.app.domains
1140+
if getattr(qube, "is_preload", False)
1141+
]
1142+
self.assertEqual(new_dispvms, old_dispvms)
1143+
1144+
# Nothing will be done here, just to prepare to the next test.
1145+
self.disp_base.features["preload-dispvm-max"] = "0"
1146+
with patch("builtins.open", side_effect=mock_open_mem_raise):
1147+
logger.info("enough memory reserve but no avail-mem file")
1148+
self.disp_base.memory = old_memory
1149+
self.disp_base.features["preload-dispvm-max"] = str(preload_max)
1150+
await self.wait_preload(preload_max)
1151+
self.assertEqual(2, len(self.disp_base.get_feat_preload()))
1152+
11071153
logger.info("end")
11081154

11091155
def test_015_preload_race_more(self):

qubes/vm/mix/dvmtemplate.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -516,7 +516,6 @@ async def on_domain_preload_dispvm_used(
516516
return
517517

518518
avail_mem_file = qubes.config.qmemman_avail_mem_file
519-
available_memory = None
520519
try:
521520
with open(avail_mem_file, "r", encoding="ascii") as file:
522521
available_memory = max(
@@ -525,7 +524,7 @@ async def on_domain_preload_dispvm_used(
525524
except FileNotFoundError:
526525
can_preload = want_preload
527526
self.log.warning("File containing available memory was not found")
528-
if available_memory is not None:
527+
else:
529528
memory = getattr(self, "memory", 0) * 1024**2
530529
unrestricted_preload = int(available_memory / memory)
531530
can_preload = min(unrestricted_preload, want_preload)

0 commit comments

Comments
 (0)