Skip to content

Commit 4026719

Browse files
committed
More preloaded dispvm tests
1 parent e6cffff commit 4026719

12 files changed

Lines changed: 467 additions & 130 deletions

File tree

linux/aux-tools/preload-dispvm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ def main():
1414
]
1515
method = "admin.vm.CreateDisposable"
1616
for qube in appvms:
17-
qube.qubesd_call("dom0", method, "preload-autostart")
17+
qube.qubesd_call(qube.name, method, "preload-autostart")
1818

1919

2020
if __name__ == "__main__":

linux/systemd/qubes-vm@.service

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[Unit]
22
Description=Start Qubes VM %i
33
After=qubesd.service qubes-meminfo-writer-dom0.service
4-
Before=qubes-vm@.service
4+
Before=qubes-preload-dispvm.service
55
ConditionKernelCommandLine=!qubes.skip_autostart
66

77
[Service]

qubes/api/admin.py

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -298,9 +298,7 @@ async def vm_property_set(self, untrusted_payload):
298298
async def property_set(self, untrusted_payload):
299299
"""Set property value"""
300300
self.enforce(self.dest.name == "dom0")
301-
return self._property_set(
302-
self.app, untrusted_payload=untrusted_payload
303-
)
301+
return self._property_set(self.app, untrusted_payload=untrusted_payload)
304302

305303
def _property_set(self, dest, untrusted_payload):
306304
if self.arg not in dest.property_list():
@@ -486,9 +484,7 @@ async def vm_volume_clone_to(self, untrusted_payload):
486484

487485
# make sure the volume still exists, but invalidate token anyway
488486
self.enforce(str(src_volume.pool) in self.app.pools)
489-
self.enforce(
490-
src_volume in self.app.pools[str(src_volume.pool)].volumes
491-
)
487+
self.enforce(src_volume in self.app.pools[str(src_volume.pool)].volumes)
492488

493489
dst_volume = self.dest.volumes[self.arg]
494490

@@ -770,9 +766,7 @@ async def pool_add(self, untrusted_payload):
770766

771767
driver_parameters = qubes.storage.driver_parameters(self.arg)
772768
unexpected_parameters = [
773-
key
774-
for key in untrusted_pool_config
775-
if key not in driver_parameters
769+
key for key in untrusted_pool_config if key not in driver_parameters
776770
]
777771
if unexpected_parameters:
778772
raise qubes.exc.QubesException(
@@ -1120,9 +1114,7 @@ async def vm_feature_checkwithtpladminvm(self):
11201114

11211115
self.fire_event_for_permission()
11221116
try:
1123-
value = self.dest.features.check_with_template_and_adminvm(
1124-
self.arg
1125-
)
1117+
value = self.dest.features.check_with_template_and_adminvm(self.arg)
11261118
except KeyError:
11271119
raise qubes.exc.QubesFeatureNotFoundError(self.dest, self.arg)
11281120
return value
@@ -1280,7 +1272,7 @@ async def _vm_create(
12801272

12811273
@qubes.api.method("admin.vm.CreateDisposable", scope="global", write=True)
12821274
async def create_disposable(self, untrusted_payload):
1283-
self.enforce(self.arg in [None, "preload", "preload-autostart"])
1275+
self.enforce(self.arg in [None, "", "preload", "preload-autostart"])
12841276
preload = False
12851277
preload_autostart = False
12861278
if self.arg == "preload":
@@ -1304,9 +1296,9 @@ async def create_disposable(self, untrusted_payload):
13041296
await appvm.fire_event_async("domain-preloaded-dispvm-autostart")
13051297
return
13061298

1307-
dispvm = await qubes.vm.dispvm.DispVM.from_appvm(
1308-
appvm, preload=preload
1309-
)
1299+
dispvm = await qubes.vm.dispvm.DispVM.from_appvm(appvm, preload=preload)
1300+
if preload:
1301+
await dispvm.start()
13101302
# TODO: move this to extension (in race-free fashion, better than here)
13111303
dispvm.tags.add("created-by-" + str(self.src))
13121304
dispvm.tags.add("disp-created-by-" + str(self.src))
@@ -1967,9 +1959,7 @@ async def backup_info(self):
19671959
"Backup profile {} does not exist".format(self.arg)
19681960
)
19691961

1970-
backup = await self._load_backup_profile(
1971-
self.arg, skip_passphrase=True
1972-
)
1962+
backup = await self._load_backup_profile(self.arg, skip_passphrase=True)
19731963
return backup.get_backup_summary()
19741964

19751965
def _send_stats_single(

qubes/tests/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1796,6 +1796,8 @@ def load_tests(loader, tests, pattern): # pylint: disable=unused-argument
17961796
"qubes.tests.ext",
17971797
"qubes.tests.vm.qubesvm",
17981798
"qubes.tests.vm.mix.net",
1799+
# TODO: Ben
1800+
#"qubes.tests.vm.mix.dvmtemplate",
17991801
"qubes.tests.vm.adminvm",
18001802
"qubes.tests.vm.appvm",
18011803
"qubes.tests.vm.dispvm",

qubes/tests/api_admin.py

Lines changed: 92 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -578,9 +578,9 @@ def test_080_vm_volume_info(self):
578578
volumes_conf["__getitem__.return_value.{}".format(prop)] = (
579579
prop + "-value"
580580
)
581-
volumes_conf["__getitem__.return_value.is_outdated.return_value"] = (
582-
False
583-
)
581+
volumes_conf[
582+
"__getitem__.return_value.is_outdated.return_value"
583+
] = False
584584
self.vm.volumes.configure_mock(**volumes_conf)
585585
value = self.call_mgmt_func(
586586
b"admin.vm.volume.Info", b"test-vm1", b"private"
@@ -608,9 +608,9 @@ def test_081_vm_volume_info_unsupported_is_outdated(self):
608608
volumes_conf["__getitem__.return_value.{}".format(prop)] = (
609609
prop + "-value"
610610
)
611-
volumes_conf["__getitem__.return_value.is_outdated.side_effect"] = (
612-
NotImplementedError
613-
)
611+
volumes_conf[
612+
"__getitem__.return_value.is_outdated.side_effect"
613+
] = NotImplementedError
614614
self.vm.volumes.configure_mock(**volumes_conf)
615615
value = self.call_mgmt_func(
616616
b"admin.vm.volume.Info", b"test-vm1", b"private"
@@ -672,7 +672,9 @@ def test_090_vm_volume_listsnapshots_invalid_volume(self):
672672
self.vm.volumes.configure_mock(**volumes_conf)
673673
with self.assertRaises(qubes.exc.PermissionDenied):
674674
self.call_mgmt_func(
675-
b"admin.vm.volume.ListSnapshots", b"test-vm1", b"no-such-volume"
675+
b"admin.vm.volume.ListSnapshots",
676+
b"test-vm1",
677+
b"no-such-volume",
676678
)
677679
self.assertEqual(
678680
self.vm.volumes.mock_calls, [unittest.mock.call.keys()]
@@ -1293,7 +1295,10 @@ def test_200_label_create_invalid_name(self):
12931295
)
12941296
with self.assertRaises(qubes.exc.PermissionDenied):
12951297
self.call_mgmt_func(
1296-
b"admin.label.Create", b"dom0", b"strange-name!@#$", b"0xff0000"
1298+
b"admin.label.Create",
1299+
b"dom0",
1300+
b"strange-name!@#$",
1301+
b"0xff0000",
12971302
)
12981303

12991304
self.assertEqual(self.app.get_label.mock_calls, [])
@@ -1675,7 +1680,9 @@ def test_316_feature_checkwithnetvm_netvm(self):
16751680
def test_317_feature_checkwithnetvm_none(self):
16761681
with self.assertRaises(qubes.exc.QubesFeatureNotFoundError):
16771682
self.call_mgmt_func(
1678-
b"admin.vm.feature.CheckWithNetvm", b"test-vm1", b"test-feature"
1683+
b"admin.vm.feature.CheckWithNetvm",
1684+
b"test-vm1",
1685+
b"test-feature",
16791686
)
16801687
self.assertFalse(self.app.save.called)
16811688

@@ -1708,7 +1715,10 @@ def test_319_feature_checkwithtpladminvm(self):
17081715

17091716
def test_320_feature_set(self):
17101717
value = self.call_mgmt_func(
1711-
b"admin.vm.feature.Set", b"test-vm1", b"test-feature", b"some-value"
1718+
b"admin.vm.feature.Set",
1719+
b"test-vm1",
1720+
b"test-feature",
1721+
b"some-value",
17121722
)
17131723
self.assertIsNone(value)
17141724
self.assertEqual(self.vm.features["test-feature"], "some-value")
@@ -1961,7 +1971,8 @@ def test_340_vm_create_in_pool_app(self, storage_mock):
19611971
# setting pool= affect only volumes actually created for this VM,
19621972
# not used from a template or so
19631973
self.assertEqual(
1964-
vm.volume_config["root"]["pool"], self.template.volumes["root"].pool
1974+
vm.volume_config["root"]["pool"],
1975+
self.template.volumes["root"].pool,
19651976
)
19661977
self.assertEqual(vm.volume_config["private"]["pool"], "test")
19671978
self.assertEqual(vm.volume_config["volatile"]["pool"], "test")
@@ -1993,11 +2004,13 @@ def test_341_vm_create_in_pool_private(self, storage_mock):
19932004
self.assertEqual(vm.label, self.app.get_label("red"))
19942005
self.assertEqual(vm.template, self.app.domains["test-template"])
19952006
self.assertEqual(
1996-
vm.volume_config["root"]["pool"], self.template.volumes["root"].pool
2007+
vm.volume_config["root"]["pool"],
2008+
self.template.volumes["root"].pool,
19972009
)
19982010
self.assertEqual(vm.volume_config["private"]["pool"], "test")
19992011
self.assertEqual(
2000-
vm.volume_config["volatile"]["pool"], self.app.default_pool_volatile
2012+
vm.volume_config["volatile"]["pool"],
2013+
self.app.default_pool_volatile,
20012014
)
20022015
self.assertEqual(vm.volume_config["kernel"]["pool"], "linux-kernel")
20032016
self.assertEqual(
@@ -2283,7 +2296,9 @@ def test_473_vm_device_list_assigned_specific(self):
22832296
self.vm.devices["testclass"].assign(assignment)
22842297
)
22852298
value = self.call_mgmt_func(
2286-
b"admin.vm.device.testclass.Assigned", b"test-vm1", b"test-vm1+1234"
2299+
b"admin.vm.device.testclass.Assigned",
2300+
b"test-vm1",
2301+
b"test-vm1+1234",
22872302
)
22882303
self.assertEqual(
22892304
value,
@@ -2310,7 +2325,9 @@ def test_474_vm_device_list_attached_specific(self):
23102325
self.device_list_multiple_attached_testclass,
23112326
)
23122327
value = self.call_mgmt_func(
2313-
b"admin.vm.device.testclass.Attached", b"test-vm1", b"test-vm1+1234"
2328+
b"admin.vm.device.testclass.Attached",
2329+
b"test-vm1",
2330+
b"test-vm1+1234",
23142331
)
23152332
self.assertEqual(
23162333
value,
@@ -2946,9 +2963,10 @@ def test_516_vm_volume_import_fire_event_with_size(self):
29462963
)
29472964

29482965
def test_510_vm_volume_import_end_success(self):
2949-
import_data_end_mock, self.vm.storage.import_data_end = (
2950-
self.coroutine_mock()
2951-
)
2966+
(
2967+
import_data_end_mock,
2968+
self.vm.storage.import_data_end,
2969+
) = self.coroutine_mock()
29522970
self.call_internal_mgmt_func(
29532971
b"internal.vm.volume.ImportEnd",
29542972
b"test-vm1",
@@ -2961,9 +2979,10 @@ def test_510_vm_volume_import_end_success(self):
29612979
)
29622980

29632981
def test_510_vm_volume_import_end_failure(self):
2964-
import_data_end_mock, self.vm.storage.import_data_end = (
2965-
self.coroutine_mock()
2966-
)
2982+
(
2983+
import_data_end_mock,
2984+
self.vm.storage.import_data_end,
2985+
) = self.coroutine_mock()
29672986
with self.assertRaisesRegex(qubes.exc.QubesException, "error message"):
29682987
self.call_internal_mgmt_func(
29692988
b"internal.vm.volume.ImportEnd",
@@ -3008,9 +3027,9 @@ def setup_for_clone(self):
30083027
self.vm.volumes["private"].import_volume.return_value = self.vm.volumes[
30093028
"private"
30103029
]
3011-
self.vm2.volumes["private"].import_volume.return_value = (
3012-
self.vm2.volumes["private"]
3013-
)
3030+
self.vm2.volumes[
3031+
"private"
3032+
].import_volume.return_value = self.vm2.volumes["private"]
30143033

30153034
self.addCleanup(self.cleanup_for_clone)
30163035

@@ -3716,9 +3735,13 @@ def test_642_vm_create_disposable_not_allowed(self, storage_mock):
37163735
self.call_mgmt_func(b"admin.vm.CreateDisposable", b"test-vm1")
37173736
self.assertFalse(self.app.save.called)
37183737

3738+
@unittest.mock.patch("qubes.vm.dispvm.DispVM.start")
37193739
@unittest.mock.patch("qubes.storage.Storage.create")
3720-
def test_643_vm_create_disposable_preload(self, mock_storage):
3740+
def test_643_vm_create_disposable_preload(
3741+
self, mock_storage, mock_dispvm_start
3742+
):
37213743
mock_storage.side_effect = self.dummy_coro
3744+
mock_dispvm_start.side_effect = self.dummy_coro
37223745
self.vm.template_for_dispvms = True
37233746
self.vm.features["preload-dispvm-max"] = "1"
37243747
self.app.default_dispvm = self.vm
@@ -3731,29 +3754,58 @@ def test_643_vm_create_disposable_preload(self, mock_storage):
37313754
self.assertIn("created-by-dom0", dispvm.tags)
37323755
self.assertIn("disp-created-by-dom0", dispvm.tags)
37333756
mock_storage.assert_called_once_with()
3757+
mock_dispvm_start.assert_called_once_with()
37343758
self.assertTrue(self.app.save.called)
37353759

3760+
@unittest.mock.patch("qubes.vm.dispvm.DispVM.start")
37363761
@unittest.mock.patch("qubes.storage.Storage.create")
3737-
def test_643_vm_create_disposable_preload_autostart(self, mock_storage):
3762+
def test_643_vm_create_disposable_preload_autostart(
3763+
self, mock_storage, mock_dispvm_start
3764+
):
37383765
mock_storage.side_effect = self.dummy_coro
3766+
mock_dispvm_start.side_effect = self.dummy_coro
37393767
self.vm.template_for_dispvms = True
37403768
self.app.domains[self.vm].fire_event = self.emitter.fire_event
37413769
self.vm.features["preload-dispvm-max"] = "1"
37423770
self.app.default_dispvm = self.vm
3743-
# TODO: how to mock start of a qube that we don't have its object?
3744-
# Looked as test_220_start(), but 'self.vm.start = corountine_mock'
3745-
# won't help if we don't have the dispvm object.
37463771
retval = self.call_mgmt_func(
37473772
b"admin.vm.CreateDisposable", b"dom0", arg=b"preload-autostart"
37483773
)
3774+
# TODO: why event is not being fired?
37493775
self.assertEventFired(self.emitter, "domain-preloaded-dispvm-autostart")
37503776
dispvm_preload = self.vm.get_feat_preload()
37513777
self.assertEqual(len(dispvm_preload), 1)
37523778
self.assertIsNone(retval)
37533779
mock_storage.assert_called_once_with()
3780+
mock_dispvm_start.assert_called_once_with()
37543781
self.assertTrue(self.app.save.called)
37553782

3756-
## TODO: test return of the preloaded dispvm
3783+
# TODO: test return of the preloaded dispvm
3784+
@unittest.mock.patch("qubes.vm.dispvm.DispVM.start")
3785+
@unittest.mock.patch("qubes.storage.Storage.create")
3786+
def test_643_vm_create_disposable_preload_use(
3787+
self, mock_storage, mock_dispvm_start
3788+
):
3789+
mock_storage.side_effect = self.dummy_coro
3790+
mock_dispvm_start.side_effect = self.dummy_coro
3791+
self.vm.template_for_dispvms = True
3792+
self.app.domains[self.vm].fire_event = self.emitter.fire_event
3793+
self.vm.features["preload-dispvm-max"] = "1"
3794+
self.app.default_dispvm = self.vm
3795+
self.call_mgmt_func(
3796+
b"admin.vm.CreateDisposable", b"dom0", arg=b"preload"
3797+
)
3798+
dispvm_preload = self.vm.get_feat_preload()
3799+
dispvm = dispvm_preload[0]
3800+
self.assertEqual(len(dispvm_preload), 1)
3801+
mock_storage.assert_called_once_with()
3802+
mock_dispvm_start.assert_called_once_with()
3803+
self.assertTrue(self.app.save.called)
3804+
retval = self.call_mgmt_func(b"admin.vm.CreateDisposable", b"dom0")
3805+
# TODO: why event is not being fired?
3806+
self.assertEventFired(self.emitter, "domain-preloaded-dispvm-used")
3807+
self.assertEqual(retval, dispvm)
3808+
self.assertFalse(self.vm.get_feat_preload())
37573809

37583810
def test_650_vm_device_set_mode_required(self):
37593811
assignment = DeviceAssignment(
@@ -4104,7 +4156,10 @@ def test_702_pool_set_revisions_to_keep_not_a_number(self):
41044156
def test_703_pool_set_ephemeral(self):
41054157
self.app.pools["test-pool"] = unittest.mock.Mock()
41064158
value = self.call_mgmt_func(
4107-
b"admin.pool.Set.ephemeral_volatile", b"dom0", b"test-pool", b"true"
4159+
b"admin.pool.Set.ephemeral_volatile",
4160+
b"dom0",
4161+
b"test-pool",
4162+
b"true",
41084163
)
41094164
self.assertIsNone(value)
41104165
self.assertEqual(self.app.pools["test-pool"].mock_calls, [])
@@ -4273,7 +4328,10 @@ def test_731_vm_console_not_running(self):
42734328
"</domain>\n"
42744329
)
42754330
self.vm._libvirt_domain.configure_mock(
4276-
**{"XMLDesc.return_value": xml_desc, "isActive.return_value": False}
4331+
**{
4332+
"XMLDesc.return_value": xml_desc,
4333+
"isActive.return_value": False,
4334+
}
42774335
)
42784336
with self.assertRaises(qubes.exc.QubesVMNotRunningError):
42794337
self.call_mgmt_func(b"admin.vm.Console", b"test-vm1")
@@ -4353,7 +4411,8 @@ def test_901_current_state_changed(self):
43534411
self.vm.get_power_state = lambda: "Running"
43544412
value = self.call_mgmt_func(b"admin.vm.CurrentState", b"test-vm1")
43554413
self.assertEqual(
4356-
value, "mem=512 mem_static_max=1024 cputime=100 power_state=Running"
4414+
value,
4415+
"mem=512 mem_static_max=1024 cputime=100 power_state=Running",
43574416
)
43584417

43594418
def test_990_vm_unexpected_payload(self):

0 commit comments

Comments
 (0)