Skip to content

Commit 124b629

Browse files
committed
Merge remote-tracking branch 'origin/pr/716'
* origin/pr/716: Add tests for changing netvm Fix formatting in tests Reuse property-pre-set:netvm event for processing default_netvm change Fix comments Rename NetVMMixin.on_domain_shutdown function Include network-providing qubes in default_netvm change check
2 parents bf9c3bf + 0d341f7 commit 124b629

File tree

6 files changed

+108
-42
lines changed

6 files changed

+108
-42
lines changed

qubes/app.py

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1700,31 +1700,26 @@ def on_property_pre_set_default_netvm(
17001700
self, event, name, newvalue, oldvalue=None
17011701
):
17021702
# pylint: disable=unused-argument,invalid-name
1703-
if (
1704-
newvalue is not None
1705-
and oldvalue is not None
1706-
and oldvalue.is_running()
1707-
and not newvalue.is_running()
1708-
and self.domains.get_vms_connected_to(oldvalue)
1709-
):
1710-
raise qubes.exc.QubesVMNotRunningError(
1711-
newvalue,
1712-
"Cannot change {!r} to domain that "
1713-
"is not running ({!r}).".format(name, newvalue.name),
1714-
)
1703+
for vm in self.domains:
1704+
if hasattr(vm, "netvm") and vm.property_is_default("netvm"):
1705+
# Use pre-set event instead of pre-reset, so it can get both
1706+
# old and new values, and perform necessary actions.
1707+
# Especially, it needs to detach old netvm.
1708+
vm.fire_event(
1709+
"property-pre-set:netvm",
1710+
pre_event=True,
1711+
name="netvm",
1712+
newvalue=newvalue,
1713+
oldvalue=oldvalue,
1714+
)
17151715

17161716
@qubes.events.handler("property-set:default_netvm")
17171717
def on_property_set_default_netvm(
17181718
self, event, name, newvalue, oldvalue=None
17191719
):
17201720
# pylint: disable=unused-argument
17211721
for vm in self.domains:
1722-
if (
1723-
hasattr(vm, "provides_network")
1724-
and not vm.provides_network
1725-
and hasattr(vm, "netvm")
1726-
and vm.property_is_default("netvm")
1727-
):
1722+
if hasattr(vm, "netvm") and vm.property_is_default("netvm"):
17281723
# fire property-reset:netvm as it is responsible for resetting
17291724
# netvm to its default value
17301725
vm.fire_event(

qubes/tests/app.py

Lines changed: 51 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1116,6 +1116,41 @@ def test_207_default_kernel(self):
11161116
existence.side_effect = [True, False]
11171117
self.app.default_kernel = "unittest_GNU_Hurd_1.0.0"
11181118

1119+
def test_208_default_netvm_change(self):
1120+
netvm1 = self.app.add_new_vm(
1121+
"AppVM",
1122+
name="netvm1",
1123+
template=self.template,
1124+
label="red",
1125+
provides_network=True,
1126+
netvm=None,
1127+
)
1128+
netvm2 = self.app.add_new_vm(
1129+
"AppVM",
1130+
name="netvm2",
1131+
template=self.template,
1132+
label="red",
1133+
provides_network=True,
1134+
netvm=None,
1135+
)
1136+
self.app.default_netvm = netvm1
1137+
with (
1138+
mock.patch("qubes.vm.qubesvm.QubesVM.is_running", lambda x: True),
1139+
mock.patch(
1140+
"qubes.vm.mix.net.NetVMMixin.attach_network"
1141+
) as mock_attach,
1142+
mock.patch(
1143+
"qubes.vm.mix.net.NetVMMixin.detach_network"
1144+
) as mock_detach,
1145+
mock.patch("qubes.vm.qubesvm.QubesVM.create_qdb_entries"),
1146+
):
1147+
1148+
self.app.default_netvm = netvm2
1149+
mock_detach.assert_called()
1150+
mock_attach.assert_called()
1151+
1152+
self.app.default_netvm = None
1153+
11191154
def test_300_preload_default_dispvm(self):
11201155
"""Fire event for new setting from no previous one."""
11211156
self.appvm.features["preload-dispvm-max"] = "1"
@@ -1138,11 +1173,10 @@ def test_301_preload_default_dispvm_change(self):
11381173
self.app.default_dispvm = self.appvm
11391174
self.appvm_alt.features["preload-dispvm-max"] = "1"
11401175
# Global is not set and thus there are no events.
1141-
with mock.patch.object(
1142-
self.appvm, "fire_event_async"
1143-
) as mock_old, mock.patch.object(
1144-
self.appvm_alt, "fire_event_async"
1145-
) as mock_new:
1176+
with (
1177+
mock.patch.object(self.appvm, "fire_event_async") as mock_old,
1178+
mock.patch.object(self.appvm_alt, "fire_event_async") as mock_new,
1179+
):
11461180
self.app.default_dispvm = self.appvm_alt
11471181
mock_old.assert_not_called()
11481182
mock_new.assert_not_called()
@@ -1151,11 +1185,10 @@ def test_301_preload_default_dispvm_change(self):
11511185
self.app.default_dispvm = self.appvm
11521186
self.appvm.features["preload-dispvm-max"] = "2"
11531187
self.appvm_alt.features["preload-dispvm-max"] = "2"
1154-
with mock.patch.object(
1155-
self.appvm, "fire_event_async"
1156-
) as mock_old, mock.patch.object(
1157-
self.appvm_alt, "fire_event_async"
1158-
) as mock_new:
1188+
with (
1189+
mock.patch.object(self.appvm, "fire_event_async") as mock_old,
1190+
mock.patch.object(self.appvm_alt, "fire_event_async") as mock_new,
1191+
):
11591192
self.app.default_dispvm = self.appvm_alt
11601193
mock_old.assert_called_once_with(
11611194
"domain-preload-dispvm-start", reason=mock.ANY
@@ -1172,11 +1205,10 @@ def test_302_preload_default_dispvm_change_noop(self):
11721205
self.appvm_alt.features["preload-dispvm-max"] = "1"
11731206
self.app.domains["dom0"].features["preload-dispvm-max"] = "1"
11741207
self.app.default_dispvm = self.appvm
1175-
with mock.patch.object(
1176-
self.appvm, "fire_event_async"
1177-
) as mock_old, mock.patch.object(
1178-
self.appvm_alt, "fire_event_async"
1179-
) as mock_new:
1208+
with (
1209+
mock.patch.object(self.appvm, "fire_event_async") as mock_old,
1210+
mock.patch.object(self.appvm_alt, "fire_event_async") as mock_new,
1211+
):
11801212
self.app.default_dispvm = self.appvm_alt
11811213
mock_old.assert_not_called()
11821214
mock_new.assert_not_called()
@@ -1189,11 +1221,10 @@ def test_303_preload_default_dispvm_change_partial_noop(self):
11891221
self.appvm_alt.features["preload-dispvm-max"] = "1"
11901222
self.app.domains["dom0"].features["preload-dispvm-max"] = "2"
11911223
self.app.default_dispvm = self.appvm
1192-
with mock.patch.object(
1193-
self.appvm, "fire_event_async"
1194-
) as mock_old, mock.patch.object(
1195-
self.appvm_alt, "fire_event_async"
1196-
) as mock_new:
1224+
with (
1225+
mock.patch.object(self.appvm, "fire_event_async") as mock_old,
1226+
mock.patch.object(self.appvm_alt, "fire_event_async") as mock_new,
1227+
):
11971228
self.app.default_dispvm = self.appvm_alt
11981229
mock_old.assert_not_called()
11991230
mock_new.assert_called_once_with(

qubes/tests/vm/mix/net.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#
2222
import ipaddress
2323
import unittest
24+
from unittest.mock import patch
2425

2526
import qubes
2627
import qubes.vm.qubesvm
@@ -122,6 +123,42 @@ def test_144_netvm_loopback2(self):
122123
self.netvm1.netvm = vm
123124
self.assertPropertyInvalidValue(vm, "netvm", self.netvm2)
124125

126+
def test_145_netvm_change(self):
127+
vm = self.get_vm()
128+
self.setup_netvms(vm)
129+
with (
130+
patch("qubes.vm.qubesvm.QubesVM.is_running", lambda x: True),
131+
patch("qubes.vm.mix.net.NetVMMixin.attach_network") as mock_attach,
132+
patch("qubes.vm.mix.net.NetVMMixin.detach_network") as mock_detach,
133+
patch("qubes.vm.qubesvm.QubesVM.create_qdb_entries"),
134+
):
135+
136+
with self.subTest("setting netvm to none"):
137+
vm.netvm = None
138+
mock_detach.assert_called_once()
139+
mock_attach.assert_not_called()
140+
mock_detach.reset_mock()
141+
142+
with self.subTest("connecting netvm again"):
143+
vm.netvm = self.netvm1
144+
mock_detach.assert_not_called()
145+
mock_attach.assert_called_once()
146+
mock_attach.reset_mock()
147+
148+
with self.subTest("changing netvm"):
149+
vm.netvm = self.netvm2
150+
mock_detach.assert_called_once()
151+
mock_attach.assert_called_once()
152+
mock_detach.reset_mock()
153+
mock_attach.reset_mock()
154+
155+
with self.subTest("resetting netvm to default"):
156+
del vm.netvm
157+
mock_detach.assert_called_once()
158+
mock_attach.assert_called_once()
159+
mock_detach.reset_mock()
160+
mock_attach.reset_mock()
161+
125162
def test_150_ip(self):
126163
vm = self.get_vm()
127164
self.setup_netvms(vm)

qubes/tests/vm/qubesvm.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1230,7 +1230,7 @@ def test_600_libvirt_xml_hvm_with_qemu_args(self):
12301230
vm.netvm = None
12311231
vm.virt_mode = "hvm"
12321232
vm.debug = True
1233-
vm.features['qemu-extra-args'] = '-some-option'
1233+
vm.features["qemu-extra-args"] = "-some-option"
12341234
libvirt_xml = vm.create_config_file()
12351235
self.assertXMLEqual(
12361236
lxml.etree.XML(libvirt_xml), lxml.etree.XML(expected)

qubes/vm/mix/net.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@ def on_domain_shutdown_net(self, event, **kwargs):
322322
pass
323323

324324
@qubes.events.handler("domain-start")
325-
def on_domain_started(self, event, **kwargs):
325+
def on_domain_started_net(self, event, **kwargs):
326326
"""Connect this domain to its downstream domains. Also reload firewall
327327
in its netvm.
328328
@@ -467,7 +467,7 @@ def reload_connected_ips(self):
467467

468468
@qubes.events.handler("property-pre-reset:netvm")
469469
def on_property_pre_reset_netvm(self, event, name, oldvalue=None):
470-
"""Sets the the NetVM to default NetVM"""
470+
"""Sets the NetVM to default NetVM"""
471471
# pylint: disable=unused-argument
472472
# we are changing to default netvm
473473
newvalue = type(self).netvm.get_default(self)
@@ -485,7 +485,7 @@ def on_property_pre_reset_netvm(self, event, name, oldvalue=None):
485485

486486
@qubes.events.handler("property-reset:netvm")
487487
def on_property_reset_netvm(self, event, name, oldvalue=None):
488-
"""Sets the the NetVM to default NetVM"""
488+
"""Sets the NetVM to default NetVM"""
489489
# pylint: disable=unused-argument
490490
# we are changing to default netvm
491491
newvalue = self.netvm

test-packages/qubesdb.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
class QubesDB:
2+
def __init__(self, name):
3+
pass
4+
25
def read(self, key):
36
return b'testvm'
47

0 commit comments

Comments
 (0)