1
0
mirror of https://github.com/GNS3/gns3-server synced 2025-05-22 08:48:52 +00:00

Fix tests and require Qemu version >= 2.4

This commit is contained in:
grossmj 2025-04-30 13:38:52 +07:00
parent cdf819f820
commit 2b96e54629
No known key found for this signature in database
GPG Key ID: 1E7DD6DBB53FF3D7
2 changed files with 33 additions and 58 deletions

View File

@ -2450,15 +2450,7 @@ class QemuVM(BaseNode):
# and pci_bridges also consume IDs. # and pci_bridges also consume IDs.
# Move network devices to their own bridge # Move network devices to their own bridge
pci_devices_reserved = 32 pci_devices_reserved = 32
pci_devices = pci_devices_reserved + len(self._ethernet_adapters)
pci_bridges = math.floor(pci_devices / 32)
pci_bridges_created = 0 pci_bridges_created = 0
if pci_bridges >= 1:
if self._qemu_version and parse_version(self._qemu_version) < parse_version("2.4.0"):
raise QemuError(
"Qemu version 2.4 or later is required to run this VM with a large number of network adapters"
)
pci_device_id = pci_devices_reserved pci_device_id = pci_devices_reserved
for adapter_number, adapter in enumerate(self._ethernet_adapters): for adapter_number, adapter in enumerate(self._ethernet_adapters):
mac = int_to_macaddress(macaddress_to_int(self._mac_address) + adapter_number) mac = int_to_macaddress(macaddress_to_int(self._mac_address) + adapter_number)
@ -2650,6 +2642,8 @@ class QemuVM(BaseNode):
""" """
self._qemu_version = await self.manager.get_qemu_version(self.qemu_path) self._qemu_version = await self.manager.get_qemu_version(self.qemu_path)
if self._qemu_version and parse_version(self._qemu_version) < parse_version("2.4.0"):
raise QemuError("Qemu version 2.4 or later is required to run Qemu VMs")
vm_name = self._name.replace(",", ",,") vm_name = self._name.replace(",", ",,")
project_path = self.project.path.replace(",", ",,") project_path = self.project.path.replace(",", ",,")
additional_options = self._options.strip() additional_options = self._options.strip()

View File

@ -570,7 +570,11 @@ async def test_build_command(vm, fake_qemu_binary):
"-net", "-net",
"none", "none",
"-device", "-device",
"e1000,mac={},netdev=gns3-0".format(vm._mac_address), "i82801b11-bridge,id=dmi_pci_bridge1",
"-device",
"pci-bridge,id=pci-bridge1,bus=dmi_pci_bridge1,chassis_nr=0x1,addr=0x1,shpc=off",
"-device",
"e1000,mac={},bus=pci-bridge1,addr=0x00,netdev=gns3-0".format(vm._mac_address),
"-netdev", "-netdev",
"socket,id=gns3-0,udp=127.0.0.1:{},localaddr=127.0.0.1:{}".format(nio.rport, nio.lport), "socket,id=gns3-0,udp=127.0.0.1:{},localaddr=127.0.0.1:{}".format(nio.rport, nio.lport),
"-display", "-display",
@ -593,40 +597,16 @@ async def test_build_command_manual_uuid(vm):
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_build_command_kvm(linux_platform, vm, fake_qemu_binary): async def test_build_command_kvm_below_2_4(linux_platform, vm, fake_qemu_binary):
""" """
Qemu 2.4 introduce an issue with KVM Qemu 2.4 introduce an issue with KVM
""" """
vm.manager.get_qemu_version = AsyncioMagicMock(return_value="2.3.2") vm.manager.get_qemu_version = AsyncioMagicMock(return_value="2.3.2")
os.environ["DISPLAY"] = "0:0"
with asyncio_patch("gns3server.compute.qemu.qemu_vm.QemuVM._run_with_hardware_acceleration", return_value=True): with asyncio_patch("gns3server.compute.qemu.qemu_vm.QemuVM._run_with_hardware_acceleration", return_value=True):
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()) as process: with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()):
cmd = await vm._build_command() with pytest.raises(QemuError):
nio = vm._local_udp_tunnels[0][0] await vm._build_command()
assert cmd == [
fake_qemu_binary,
"-name",
"test",
"-m",
"256M",
"-smp",
"cpus=1,maxcpus=1,sockets=1",
"-enable-kvm",
"-boot",
"order=c",
"-uuid",
vm.id,
"-serial",
"telnet:127.0.0.1:{},server,nowait".format(vm._internal_console_port),
"-net",
"none",
"-device",
"e1000,mac={},netdev=gns3-0".format(vm._mac_address),
"-netdev",
"socket,id=gns3-0,udp=127.0.0.1:{},localaddr=127.0.0.1:{}".format(nio.rport, nio.lport),
"-nographic"
]
@pytest.mark.asyncio @pytest.mark.asyncio
@ -661,7 +641,11 @@ async def test_build_command_kvm_2_4(linux_platform, vm, fake_qemu_binary):
"-net", "-net",
"none", "none",
"-device", "-device",
"e1000,mac={},netdev=gns3-0".format(vm._mac_address), "i82801b11-bridge,id=dmi_pci_bridge1",
"-device",
"pci-bridge,id=pci-bridge1,bus=dmi_pci_bridge1,chassis_nr=0x1,addr=0x1,shpc=off",
"-device",
"e1000,mac={},bus=pci-bridge1,addr=0x00,netdev=gns3-0".format(vm._mac_address),
"-netdev", "-netdev",
"socket,id=gns3-0,udp=127.0.0.1:{},localaddr=127.0.0.1:{}".format(nio.rport, nio.lport), "socket,id=gns3-0,udp=127.0.0.1:{},localaddr=127.0.0.1:{}".format(nio.rport, nio.lport),
"-nographic" "-nographic"
@ -705,11 +689,15 @@ async def test_build_command_two_adapters(vm, fake_qemu_binary):
"-net", "-net",
"none", "none",
"-device", "-device",
"e1000,mac={},netdev=gns3-0".format(vm._mac_address), "i82801b11-bridge,id=dmi_pci_bridge1",
"-device",
"pci-bridge,id=pci-bridge1,bus=dmi_pci_bridge1,chassis_nr=0x1,addr=0x1,shpc=off",
"-device",
"e1000,mac={},bus=pci-bridge1,addr=0x00,netdev=gns3-0".format(vm._mac_address),
"-netdev", "-netdev",
"socket,id=gns3-0,udp=127.0.0.1:{},localaddr=127.0.0.1:{}".format(nio1.rport, nio1.lport), "socket,id=gns3-0,udp=127.0.0.1:{},localaddr=127.0.0.1:{}".format(nio1.rport, nio1.lport),
"-device", "-device",
"e1000,mac={},netdev=gns3-1".format(int_to_macaddress(macaddress_to_int(vm._mac_address) + 1)), "e1000,mac={},bus=pci-bridge1,addr=0x01,netdev=gns3-1".format(int_to_macaddress(macaddress_to_int(vm._mac_address) + 1)),
"-netdev", "-netdev",
"socket,id=gns3-1,udp=127.0.0.1:{},localaddr=127.0.0.1:{}".format(nio2.rport, nio2.lport), "socket,id=gns3-1,udp=127.0.0.1:{},localaddr=127.0.0.1:{}".format(nio2.rport, nio2.lport),
"-nographic" "-nographic"
@ -729,8 +717,8 @@ async def test_build_command_two_adapters_mac_address(vm):
assert mac_0[:8] == "00:00:ab" assert mac_0[:8] == "00:00:ab"
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()): with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()):
cmd = await vm._build_command() cmd = await vm._build_command()
assert "e1000,mac={},netdev=gns3-0".format(mac_0) in cmd assert "e1000,mac={},bus=pci-bridge1,addr=0x00,netdev=gns3-0".format(mac_0) in cmd
assert "e1000,mac={},netdev=gns3-1".format(mac_1) in cmd assert "e1000,mac={},bus=pci-bridge1,addr=0x01,netdev=gns3-1".format(mac_1) in cmd
vm.mac_address = "00:42:ab:0e:0f:0a" vm.mac_address = "00:42:ab:0e:0f:0a"
mac_0 = vm._mac_address mac_0 = vm._mac_address
@ -739,8 +727,8 @@ async def test_build_command_two_adapters_mac_address(vm):
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()): with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()):
cmd = await vm._build_command() cmd = await vm._build_command()
assert "e1000,mac={},netdev=gns3-0".format(mac_0) in cmd assert "e1000,mac={},bus=pci-bridge1,addr=0x00,netdev=gns3-0".format(mac_0) in cmd
assert "e1000,mac={},netdev=gns3-1".format(mac_1) in cmd assert "e1000,mac={},bus=pci-bridge1,addr=0x01,netdev=gns3-1".format(mac_1) in cmd
@pytest.mark.asyncio @pytest.mark.asyncio
@ -762,28 +750,20 @@ async def test_build_command_large_number_of_adapters(vm):
assert len([l for l in cmd if "e1000" in l ]) == 100 assert len([l for l in cmd if "e1000" in l ]) == 100
assert len(vm._ethernet_adapters) == 100 assert len(vm._ethernet_adapters) == 100
assert "e1000,mac={},netdev=gns3-0".format(mac_0) in cmd assert "e1000,mac={},bus=pci-bridge1,addr=0x00,netdev=gns3-0".format(mac_0) in cmd
assert "e1000,mac={},netdev=gns3-1".format(mac_1) in cmd assert "e1000,mac={},bus=pci-bridge1,addr=0x01,netdev=gns3-1".format(mac_1) in cmd
assert "pci-bridge,id=pci-bridge0,bus=dmi_pci_bridge0,chassis_nr=0x1,addr=0x0,shpc=off" not in cmd assert "pci-bridge,id=pci-bridge0,bus=dmi_pci_bridge0,chassis_nr=0x1,addr=0x0,shpc=off" not in cmd
assert "pci-bridge,id=pci-bridge1,bus=dmi_pci_bridge1,chassis_nr=0x1,addr=0x1,shpc=off" in cmd assert "pci-bridge,id=pci-bridge1,bus=dmi_pci_bridge1,chassis_nr=0x1,addr=0x1,shpc=off" in cmd
assert "pci-bridge,id=pci-bridge2,bus=dmi_pci_bridge2,chassis_nr=0x1,addr=0x2,shpc=off" in cmd assert "pci-bridge,id=pci-bridge2,bus=dmi_pci_bridge2,chassis_nr=0x1,addr=0x2,shpc=off" in cmd
assert "i82801b11-bridge,id=dmi_pci_bridge1" in cmd assert "i82801b11-bridge,id=dmi_pci_bridge1" in cmd
mac_29 = int_to_macaddress(macaddress_to_int(vm._mac_address) + 29) mac_29 = int_to_macaddress(macaddress_to_int(vm._mac_address) + 29)
assert "e1000,mac={},bus=pci-bridge1,addr=0x04,netdev=gns3-29".format(mac_29) in cmd assert "e1000,mac={},bus=pci-bridge1,addr=0x1d,netdev=gns3-29".format(mac_29) in cmd
mac_30 = int_to_macaddress(macaddress_to_int(vm._mac_address) + 30) mac_30 = int_to_macaddress(macaddress_to_int(vm._mac_address) + 30)
assert "e1000,mac={},bus=pci-bridge1,addr=0x05,netdev=gns3-30".format(mac_30) in cmd assert "e1000,mac={},bus=pci-bridge1,addr=0x1e,netdev=gns3-30".format(mac_30) in cmd
mac_74 = int_to_macaddress(macaddress_to_int(vm._mac_address) + 74) mac_74 = int_to_macaddress(macaddress_to_int(vm._mac_address) + 74)
assert "e1000,mac={},bus=pci-bridge2,addr=0x11,netdev=gns3-74".format(mac_74) in cmd assert "e1000,mac={},bus=pci-bridge3,addr=0x0a,netdev=gns3-74".format(mac_74) in cmd
# Qemu < 2.4 doesn't support large number of adapters
vm.manager.get_qemu_version = AsyncioMagicMock(return_value="2.0.0")
with pytest.raises(QemuError):
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()):
await vm._build_command()
vm.adapters = 5
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()):
await vm._build_command()
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_build_command_with_virtio_net_pci_adapter(vm): async def test_build_command_with_virtio_net_pci_adapter(vm):
@ -796,7 +776,8 @@ async def test_build_command_with_virtio_net_pci_adapter(vm):
vm._adapter_type = "virtio-net-pci" vm._adapter_type = "virtio-net-pci"
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()): with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()):
cmd = await vm._build_command() cmd = await vm._build_command()
assert "virtio-net-pci,mac=00:00:ab:0e:0f:09,speed=10000,duplex=full,netdev=gns3-0" in cmd print(cmd)
assert "virtio-net-pci,mac=00:00:ab:0e:0f:09,speed=10000,duplex=full,bus=pci-bridge1,addr=0x00,netdev=gns3-0" in cmd
@pytest.mark.asyncio @pytest.mark.asyncio