Skip to content

Commit c6e10ea

Browse files
committed
Read disposable performance tests
For: QubesOS/qubes-issues#1512
1 parent a930d4e commit c6e10ea

File tree

7 files changed

+41132
-148
lines changed

7 files changed

+41132
-148
lines changed

qubes/tests/integ/dispvm.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#
44
# Copyright (C) 2016 Marek Marczykowski-Górecki
55
6+
# Copyright (C) 2025 Benjamin Grande <[email protected]>
67
#
78
# This library is free software; you can redistribute it and/or
89
# modify it under the terms of the GNU Lesser General Public
@@ -57,6 +58,8 @@ def setUp(self):
5758
)
5859
self.loop.run_until_complete(self.disp_base.create_on_disk())
5960
self.disp_base.template_for_dispvms = True
61+
self.loop.run_until_complete(self.start_vm(self.disp_base))
62+
self.shutdown_and_wait(self.disp_base)
6063
self.app.default_dispvm = self.disp_base
6164
self.testvm = self.app.add_new_vm(
6265
qubes.vm.appvm.AppVM,
@@ -220,6 +223,16 @@ def setUp(self): # pylint: disable=invalid-name
220223
template_for_dispvms=True,
221224
)
222225
self.loop.run_until_complete(self.disp_base_alt.create_on_disk())
226+
start_tasks = [
227+
self.start_vm(self.disp_base),
228+
self.start_vm(self.disp_base_alt),
229+
]
230+
shutdown_tasks = [
231+
self.disp_base.shutdown(wait=True),
232+
self.disp_base_alt.shutdown(wait=True),
233+
]
234+
self.loop.run_until_complete(asyncio.gather(*start_tasks))
235+
self.loop.run_until_complete(asyncio.gather(*shutdown_tasks))
223236
# Setting "default_dispvm" fires the preload event before patches of
224237
# each test function is applied.
225238
if "_preload_" not in self._testMethodName:

qubes/tests/integ/dispvm_perf.py

Lines changed: 126 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
#
22
# The Qubes OS Project, https://www.qubes-os.org/
33
#
4-
# Copyright (C) 2025 Marek Marczykowski-Górecki
5-
4+
# Copyright (C) 2025 Benjamin Grande <[email protected]>
65
#
76
# This program is free software; you can redistribute it and/or modify
87
# it under the terms of the GNU Lesser General Public License as published by
@@ -19,15 +18,25 @@
1918

2019
import asyncio
2120
import os
21+
import shutil
2222
import sys
23-
import time
23+
import tempfile
2424

2525
import qubes.tests
2626

2727

2828
class TC_00_DispVMPerfMixin:
2929
def setUp(self: qubes.tests.SystemTestCase):
3030
super().setUp()
31+
self.results = os.getenv("QUBES_TEST_PERF_FILE")
32+
self.test_dir = None
33+
if "_reader" in self._testMethodName:
34+
prefix = self.template + "_"
35+
if self.results:
36+
prefix = self.results + "_" + prefix
37+
self.test_dir = tempfile.mkdtemp(prefix=prefix)
38+
self.vm2 = None
39+
return
3140
if "whonix-g" in self.template:
3241
self.skipTest(
3342
"whonix gateway is not supported as DisposableVM Template"
@@ -53,32 +62,42 @@ def setUp(self: qubes.tests.SystemTestCase):
5362
template=self.app.domains[self.template],
5463
default_dispvm=self.dvm,
5564
)
65+
# Necessary to be done post qube creation because of Whonix Admin Addon:
66+
# https://github.com/QubesOS/qubes-core-admin-addon-whonix/pull/25
67+
for qube in [self.dvm, self.vm1, self.vm2]:
68+
qube.default_dispvm = self.dvm
69+
qube.netvm = None
5670
self.loop.run_until_complete(
5771
asyncio.gather(
5872
self.dvm.create_on_disk(),
5973
self.vm1.create_on_disk(),
6074
self.vm2.create_on_disk(),
6175
)
6276
)
77+
self.loop.run_until_complete(self.start_vm(self.dvm))
78+
self.shutdown_and_wait(self.dvm)
6379
start_tasks = [self.vm1.start()]
64-
if self._testMethodName.startswith("vm"):
80+
if "_vm" in self._testMethodName:
6581
start_tasks.append(self.vm2.start())
6682
self.loop.run_until_complete(asyncio.gather(*start_tasks))
6783

6884
def tearDown(self: qubes.tests.SystemTestCase):
6985
super().tearDown()
70-
if self.vm2.is_running():
71-
self.loop.run_until_complete(
72-
asyncio.gather(
73-
self.vm2.shutdown(),
86+
if self.test_dir and os.getenv("QUBES_TEST_PERF_GRAPH_DELETE"):
87+
shutil.rmtree(self.test_dir)
88+
if self.vm2:
89+
if self.vm2.is_running():
90+
self.loop.run_until_complete(
91+
asyncio.gather(
92+
self.vm2.shutdown(),
93+
)
7494
)
75-
)
7695

7796
def run_test(self, name):
7897
dvm = self.dvm.name
7998
vm1 = self.vm1.name
8099
vm2 = ""
81-
if name.startswith("vm"):
100+
if "-vm" in name:
82101
vm2 = self.vm2.name
83102
cmd = [
84103
"/usr/lib/qubes/tests/dispvm_perf.py",
@@ -92,141 +111,169 @@ def run_test(self, name):
92111
if p.returncode:
93112
self.fail(f"'{' '.join(cmd)}' failed: {p.returncode}")
94113

95-
def test_000_dispvm(self):
114+
def run_reader(self, args: list):
115+
if not self.results:
116+
self.skipTest("Did not set QUBES_TEST_PERF_FILE")
117+
cmd = [
118+
"/usr/lib/qubes/tests/dispvm_perf_reader.py",
119+
f"--template={self.template}",
120+
f"--output-dir={self.test_dir}",
121+
*args,
122+
"--",
123+
self.results,
124+
]
125+
p = self.loop.run_until_complete(asyncio.create_subprocess_exec(*cmd))
126+
self.loop.run_until_complete(p.wait())
127+
if p.returncode:
128+
self.fail(f"'{' '.join(cmd)}' failed: {p.returncode}")
129+
130+
def test_000_vm_dispvm(self):
96131
"""Latency of vm-dispvm calls"""
97-
self.run_test("dispvm")
132+
self.run_test("vm-dispvm")
98133

99-
def test_001_dispvm_gui(self):
134+
def test_001_vm_dispvm_gui(self):
100135
"""Latency of vm-dispvm GUI calls"""
101-
self.run_test("dispvm-gui")
136+
self.run_test("vm-dispvm-gui")
102137

103-
def test_002_dispvm_concurrent(self):
138+
def test_002_vm_dispvm_concurrent(self):
104139
"""Latency of vm-dispvm concurrent calls"""
105-
self.run_test("dispvm-concurrent")
140+
self.run_test("vm-dispvm-concurrent")
106141

107-
def test_003_dispvm_gui_concurrent(self):
142+
def test_003_vm_dispvm_gui_concurrent(self):
108143
"""Latency of vm-dispvm concurrent GUI calls"""
109-
self.run_test("dispvm-gui-concurrent")
144+
self.run_test("vm-dispvm-gui-concurrent")
110145

111-
def test_006_dispvm_from_dom0(self):
146+
def test_006_dom0_dispvm(self):
112147
"""Latency of dom0-dispvm calls"""
113-
self.run_test("dispvm-dom0")
148+
self.run_test("dom0-dispvm")
114149

115-
def test_007_dispvm_from_dom0_gui(self):
150+
def test_007_dom0_dispvm_gui(self):
116151
"""Latency of dom0-dispvm GUI calls"""
117-
self.run_test("dispvm-dom0-gui")
152+
self.run_test("dom0-dispvm-gui")
118153

119-
def test_008_dispvm_from_dom0_concurrent(self):
154+
def test_008_dom0_dispvm_concurrent(self):
120155
"""Latency of dom0-dispvm concurrent calls"""
121-
self.run_test("dispvm-dom0-concurrent")
156+
self.run_test("dom0-dispvm-concurrent")
122157

123-
def test_009_dispvm_from_dom0_gui_concurrent(self):
158+
def test_009_dom0_dispvm_gui_concurrent(self):
124159
"""Latency of dom0-dispvm concurrent GUI calls"""
125-
self.run_test("dispvm-dom0-gui-concurrent")
160+
self.run_test("dom0-dispvm-gui-concurrent")
126161

127-
def test_020_dispvm_preload(self):
162+
def test_020_vm_dispvm_preload(self):
128163
"""Latency of vm-dispvm (preload) calls"""
129-
self.run_test("dispvm-preload")
164+
self.run_test("vm-dispvm-preload")
130165

131-
def test_021_dispvm_preload_gui(self):
166+
def test_021_vm_dispvm_preload_gui(self):
132167
"""Latency of vm-dispvm (preload) GUI calls"""
133-
self.run_test("dispvm-preload-gui")
168+
self.run_test("vm-dispvm-preload-gui")
134169

135-
def test_022_dispvm_preload_concurrent(self):
170+
def test_022_vm_dispvm_preload_concurrent(self):
136171
"""Latency of vm-dispvm (preload) concurrent calls"""
137-
self.run_test("dispvm-preload-concurrent")
172+
self.run_test("vm-dispvm-preload-concurrent")
138173

139-
def test_023_dispvm_preload_gui_concurrent(self):
174+
def test_023_vm_dispvm_preload_gui_concurrent(self):
140175
"""Latency of vm-dispvm (preload) concurrent GUI calls"""
141-
self.run_test("dispvm-preload-gui-concurrent")
176+
self.run_test("vm-dispvm-preload-gui-concurrent")
142177

143-
def test_026_dispvm_from_dom0_preload(self):
178+
def test_026_dom0_dispvm_preload(self):
144179
"""Latency of dom0-dispvm (preload) calls"""
145-
self.run_test("dispvm-preload-dom0")
180+
self.run_test("dom0-dispvm-preload")
146181

147-
def test_027_dispvm_from_dom0_preload_gui(self):
182+
def test_027_dom0_dispvm_preload_gui(self):
148183
"""Latency of dom0-dispvm (preload) GUI calls"""
149-
self.run_test("dispvm-preload-dom0-gui")
184+
self.run_test("dom0-dispvm-preload-gui")
150185

151-
def test_028_dispvm_from_dom0_preload_concurrent(self):
186+
def test_028_dom0_dispvm_preload_concurrent(self):
152187
"""Latency of dom0-dispvm (preload) concurrent calls"""
153-
self.run_test("dispvm-preload-dom0-concurrent")
188+
self.run_test("dom0-dispvm-preload-concurrent")
154189

155-
def test_029_dispvm_from_dom0_preload_gui_concurrent(self):
190+
def test_029_dom0_dispvm_preload_gui_concurrent(self):
156191
"""Latency of dom0-dispvm (preload) concurrent GUI calls"""
157-
self.run_test("dispvm-preload-dom0-gui-concurrent")
192+
self.run_test("dom0-dispvm-preload-gui-concurrent")
158193

159-
def test_400_dispvm_api(self):
194+
def test_400_dom0_dispvm_api(self):
160195
"""Latency of dom0-dispvm API calls"""
161-
self.run_test("dispvm-api")
196+
self.run_test("dom0-dispvm-api")
162197

163-
def test_401_dispvm_gui_api(self):
198+
def test_401_dom0_dispvm_gui_api(self):
164199
"""Latency of dom0-dispvm GUI API calls"""
165-
self.run_test("dispvm-gui-api")
200+
self.run_test("dom0-dispvm-gui-api")
166201

167-
def test_402_dispvm_concurrent_api(self):
202+
def test_402_dom0_dispvm_concurrent_api(self):
168203
"""Latency of dom0-dispvm concurrent API calls"""
169-
self.run_test("dispvm-concurrent-api")
204+
self.run_test("dom0-dispvm-concurrent-api")
170205

171-
def test_403_dispvm_gui_concurrent_api(self):
206+
def test_403_dom0_dispvm_gui_concurrent_api(self):
172207
"""Latency of dom0-dispvm concurrent GUI API calls"""
173-
self.run_test("dispvm-gui-concurrent-api")
208+
self.run_test("dom0-dispvm-gui-concurrent-api")
174209

175-
def test_404_dispvm_preload_more_api(self):
176-
"""Latency of dom0-dispvm (preload more) API calls"""
177-
self.run_test("dispvm-preload-more-api")
210+
def test_404_dom0_dispvm_preload_less_less_api(self):
211+
"""Latency of dom0-dispvm (preload less less) API calls"""
212+
self.run_test("dom0-dispvm-preload-less-less-api")
178213

179-
def test_404_dispvm_preload_less_api(self):
214+
def test_405_dom0_dispvm_preload_less_api(self):
180215
"""Latency of dom0-dispvm (preload less) API calls"""
181-
self.run_test("dispvm-preload-less-api")
216+
self.run_test("dom0-dispvm-preload-less-api")
182217

183-
def test_404_dispvm_preload_api(self):
218+
def test_406_dom0_dispvm_preload_api(self):
184219
"""Latency of dom0-dispvm (preload) API calls"""
185-
self.run_test("dispvm-preload-api")
220+
self.run_test("dom0-dispvm-preload-api")
221+
222+
def test_407_dom0_dispvm_preload_more_api(self):
223+
"""Latency of dom0-dispvm (preload more) API calls"""
224+
self.run_test("dom0-dispvm-preload-more-api")
225+
226+
def test_408_dom0_dispvm_preload_more_more_api(self):
227+
"""Latency of dom0-dispvm (preload more more) API calls"""
228+
self.run_test("dom0-dispvm-preload-more-more-api")
186229

187-
def test_405_dispvm_preload_gui_api(self):
230+
def test_409_dom0_dispvm_preload_gui_api(self):
188231
"""Latency of dom0-dispvm (preload) GUI API calls"""
189-
self.run_test("dispvm-preload-gui-api")
232+
self.run_test("dom0-dispvm-preload-gui-api")
190233

191-
def test_406_dispvm_preload_concurrent_api(self):
234+
def test_410_dom0_dispvm_preload_concurrent_api(self):
192235
"""Latency of dom0-dispvm (preload) concurrent GUI API calls"""
193-
self.run_test("dispvm-preload-concurrent-api")
236+
self.run_test("dom0-dispvm-preload-concurrent-api")
194237

195-
def test_407_dispvm_preload_gui_concurrent_api(self):
238+
def test_411_dom0_dispvm_preload_gui_concurrent_api(self):
196239
"""Latency of dom0-dispvm (preload) concurrent GUI API calls"""
197-
self.run_test("dispvm-preload-gui-concurrent-api")
240+
self.run_test("dom0-dispvm-preload-gui-concurrent-api")
198241

199-
def test_900_vm(self):
242+
def test_800_vm_vm(self):
200243
"""Latency of vm-vm calls"""
201-
self.run_test("vm")
244+
self.run_test("vm-vm")
202245

203-
def test_901_vm_gui(self):
246+
def test_801_vm_vm_gui(self):
204247
"""Latency of vm-vm GUI calls"""
205-
self.run_test("vm-gui")
248+
self.run_test("vm-vm-gui")
206249

207-
def test_902_vm_concurrent(self):
250+
def test_802_vm_vm_concurrent(self):
208251
"""Latency of vm-vm concurrent calls"""
209-
self.run_test("vm-concurrent")
252+
self.run_test("vm-vm-concurrent")
210253

211-
def test_903_vm_gui_concurrent(self):
254+
def test_803_vm_vm_gui_concurrent(self):
212255
"""Latency of vm-vm concurrent GUI calls"""
213-
self.run_test("vm-gui-concurrent")
256+
self.run_test("vm-vm-gui-concurrent")
214257

215-
def test_904_vm_api(self):
258+
def test_804_dom0_vm_api(self):
216259
"""Latency of dom0-vm API calls"""
217-
self.run_test("vm-api")
260+
self.run_test("dom0-vm-api")
218261

219-
def test_905_vm_gui_api(self):
262+
def test_805_dom0_vm_gui_api(self):
220263
"""Latency of dom0-vm GUI API calls"""
221-
self.run_test("vm-gui-api")
264+
self.run_test("dom0-vm-gui-api")
222265

223-
def test_906_vm_concurrent_api(self):
266+
def test_806_dom0_vm_concurrent_api(self):
224267
"""Latency of dom0-vm concurrent API calls"""
225-
self.run_test("vm-concurrent-api")
268+
self.run_test("dom0-vm-concurrent-api")
226269

227-
def test_907_vm_gui_concurrent_api(self):
270+
def test_807_dom0_vm_gui_concurrent_api(self):
228271
"""Latency of dom0-vm concurrent GUI API calls"""
229-
self.run_test("vm-gui-concurrent-api")
272+
self.run_test("dom0-vm-gui-concurrent-api")
273+
274+
def test_900_reader(self):
275+
"""Render performance graphs."""
276+
self.run_reader(["--log-level=INFO", "--no-show"])
230277

231278

232279
def create_testcases_for_templates():

rpm_spec/core-dom0.spec.in

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,7 @@ done
567567
/usr/lib/qubes/fix-dir-perms.sh
568568
/usr/lib/qubes/startup-misc.sh
569569
/usr/lib/qubes/tests/dispvm_perf.py
570+
/usr/lib/qubes/tests/dispvm_perf_reader.py
570571
/usr/lib/qubes/tests/qrexec_perf.py
571572
/usr/lib/qubes/tests/storage_perf.py
572573
%{_unitdir}/[email protected]/30_qubes.conf
@@ -585,6 +586,8 @@ done
585586
/usr/share/qubes/templates/libvirt/devices/pci.xml
586587
/usr/share/qubes/templates/libvirt/devices/net.xml
587588
/usr/share/qubes/tests-data/dispvm-open-thunderbird-attachment
589+
%dir /usr/share/qubes/tests-data/dispvm_perf/
590+
/usr/share/qubes/tests-data/dispvm_perf/*
588591
/usr/share/qubes/tests-data/sysfs
589592
/usr/lib/tmpfiles.d/qubes.conf
590593
%attr(0755,root,root) /usr/lib/qubes/create-snapshot

0 commit comments

Comments
 (0)