Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions linux/aux-tools/preload-dispvm
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
#!/usr/bin/env python3

"""
This script is outside of qubesd because it relies on systemd to:

- Order this action after the autostart or standard qubes;
- Skip preloading if kernel command line prevents autostart.
"""

import asyncio
import concurrent.futures
import qubesadmin
Expand Down
25 changes: 20 additions & 5 deletions qubes/tests/integ/dispvm.py
Original file line number Diff line number Diff line change
Expand Up @@ -548,9 +548,7 @@ def test_015_preload_race_more(self):
self.loop.run_until_complete(self._test_015_preload_race_more())

async def _test_015_preload_race_more(self):
# The limiting factor is how much memory is available on OpenQA and the
# unreasonable memory allocated before the qube is paused due to:
# https://github.com/QubesOS/qubes-issues/issues/9917
# The limiting factor is how much memory is available on OpenQA:
# Whonix (Kicksecure) 17 fail more due to higher memory consumption.
# From the templates deployed by default, only Debian and Fedora
# survives due to using less memory than the other OSes.
Expand Down Expand Up @@ -587,7 +585,13 @@ async def _test_016_preload_race_less(self):
logger.info("end")

def test_017_preload_autostart(self):
"""The script triggers the API call
'admin.vm.CreateDisposable+preload-autostart' which fires the event
'domain-preload-dispvm-autostart', clearing the current preload list
and filling with new ones."""
logger.info("start")
self.app.default_dispvm = self.disp_base

preload_max = 1
proc = self.loop.run_until_complete(
asyncio.create_subprocess_exec("/usr/lib/qubes/preload-dispvm")
Expand All @@ -612,13 +616,24 @@ def test_017_preload_autostart(self):
f"old_preload={old_preload} preload_dispvm={preload_dispvm}",
)

self.adminvm.features["preload-dispvm-max"] = "0"
preload_max += 1
self.adminvm.features["preload-dispvm-max"] = str(preload_max)
self.loop.run_until_complete(self.wait_preload(preload_max))
del self.disp_base.features["preload-dispvm-max"]
old_preload = self.disp_base.get_feat_preload()
proc = self.loop.run_until_complete(
asyncio.create_subprocess_exec("/usr/lib/qubes/preload-dispvm")
)
self.loop.run_until_complete(asyncio.wait_for(proc.wait(), timeout=30))
self.assertEqual(self.disp_base.get_feat_preload(), [])
preload_dispvm = self.disp_base.get_feat_preload()
self.assertEqual(len(old_preload), preload_max)
self.assertEqual(len(preload_dispvm), preload_max)
self.assertTrue(
set(old_preload).isdisjoint(preload_dispvm),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is it supposed to be disjoint? I don't see anything using or killing preloaded between collecging old_preload and preload_dispvm? You just unset the feature on the disposable template, but it's still set via global property at that time, so it shouldn't matter, no?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This unsets the feature:

        proc = self.loop.run_until_complete(
            asyncio.create_subprocess_exec("/usr/lib/qubes/preload-dispvm")
        )

In other words, event domain-preload-dispvm-autostart does it.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, this could use a comment then, next to calling that script here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added as a doctstring because there is another disjoint on the block before and I prefer to consider both blocks with a single comment.

f"old_preload={old_preload} preload_dispvm={preload_dispvm}",
)

self.app.default_dispvm = None
logger.info("end")

def test_018_preload_global(self):
Expand Down