Merge pull request #2255 from GNS3/fix/2243

Only add speed/duplex params when using Qemu >= v2.12
This commit is contained in:
Jeremy Grossmann 2023-07-06 16:43:54 +10:00 committed by GitHub
commit c5c4e1ad56
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 16 additions and 32 deletions

View File

@ -86,6 +86,7 @@ class QemuVM(BaseNode):
self._local_udp_tunnels = {}
self._guest_cid = None
self._command_line_changed = False
self._qemu_version = None
# QEMU VM settings
if qemu_path:
@ -1871,8 +1872,7 @@ class QemuVM(BaseNode):
# special case, sata controller doesn't exist in Qemu
options.extend(["-device", 'ahci,id=ahci{}'.format(disk_index)])
options.extend(["-drive", 'file={},if=none,id=drive{},index={},media=disk{}'.format(disk, disk_index, disk_index, extra_drive_options)])
qemu_version = await self.manager.get_qemu_version(self.qemu_path)
if qemu_version and parse_version(qemu_version) >= parse_version("4.2.0"):
if self._qemu_version and parse_version(self._qemu_version) >= parse_version("4.2.0"):
# The ide-drive device is deprecated since version 4.2.0
# https://qemu.readthedocs.io/en/latest/system/deprecated.html#ide-drive-since-4-2
options.extend(["-device", 'ide-hd,drive=drive{},bus=ahci{}.0,id=drive{}'.format(disk_index, disk_index, disk_index)])
@ -2131,11 +2131,10 @@ class QemuVM(BaseNode):
patched_qemu = False
if self._legacy_networking:
qemu_version = await self.manager.get_qemu_version(self.qemu_path)
if qemu_version:
if parse_version(qemu_version) >= parse_version("2.9.0"):
if self._qemu_version:
if parse_version(self._qemu_version) >= parse_version("2.9.0"):
raise QemuError("Qemu version 2.9.0 and later doesn't support legacy networking mode")
if parse_version(qemu_version) < parse_version("1.1.0"):
if parse_version(self._qemu_version) < parse_version("1.1.0"):
# this is a patched Qemu if version is below 1.1.0
patched_qemu = True
@ -2144,8 +2143,7 @@ class QemuVM(BaseNode):
pci_bridges = math.floor(pci_devices / 32)
pci_bridges_created = 0
if pci_bridges >= 1:
qemu_version = await self.manager.get_qemu_version(self.qemu_path)
if qemu_version and parse_version(qemu_version) < parse_version("2.4.0"):
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 = 4 + pci_bridges # Bridge consume PCI ports
@ -2191,7 +2189,9 @@ class QemuVM(BaseNode):
else:
# newer QEMU networking syntax
device_string = "{},mac={}".format(adapter_type, mac)
if adapter_type == "virtio-net-pci":
if adapter_type == "virtio-net-pci" and \
self._qemu_version and parse_version(self._qemu_version) >= parse_version("2.12"):
# speed and duplex support was added in Qemu 2.12
device_string = "{},speed=10000,duplex=full".format(device_string)
bridge_id = math.floor(pci_device_id / 32)
if bridge_id > 0:
@ -2224,8 +2224,7 @@ class QemuVM(BaseNode):
if any(opt in self._options for opt in ["-display", "-nographic", "-curses", "-sdl" "-spice", "-vnc"]):
return []
version = await self.manager.get_qemu_version(self.qemu_path)
if version and parse_version(version) >= parse_version("3.0"):
if self._qemu_version and parse_version(self._qemu_version) >= parse_version("3.0"):
return ["-display", "none"]
else:
return ["-nographic"]
@ -2270,9 +2269,8 @@ class QemuVM(BaseNode):
elif sys.platform.startswith("win"):
if require_hardware_accel:
# HAXM is only available starting with Qemu version 2.9.0
version = await self.manager.get_qemu_version(self.qemu_path)
if version and parse_version(version) < parse_version("2.9.0"):
raise QemuError("HAXM acceleration can only be enable for Qemu version 2.9.0 and above (current version: {})".format(version))
if self._qemu_version and parse_version(self._qemu_version) < parse_version("2.9.0"):
raise QemuError("HAXM acceleration can only be enable for Qemu version 2.9.0 and above (current version: {})".format(self._qemu_version))
# check if HAXM is installed
version = self.manager.get_haxm_windows_version()
@ -2372,6 +2370,7 @@ class QemuVM(BaseNode):
(to be passed to subprocess.Popen())
"""
self._qemu_version = await self.manager.get_qemu_version(self.qemu_path)
vm_name = self._name.replace(",", ",,")
project_path = self.project.path.replace(",", ",,")
additional_options = self._options.strip()
@ -2389,10 +2388,9 @@ class QemuVM(BaseNode):
if await self._run_with_hardware_acceleration(self.qemu_path, self._options):
if sys.platform.startswith("linux"):
command.extend(["-enable-kvm"])
version = await self.manager.get_qemu_version(self.qemu_path)
# Issue on some combo Intel CPU + KVM + Qemu 2.4.0
# https://github.com/GNS3/gns3-server/issues/685
if version and parse_version(version) >= parse_version("2.4.0") and self.platform == "x86_64":
if self._qemu_version and parse_version(self._qemu_version) >= parse_version("2.4.0") and self.platform == "x86_64":
command.extend(["-machine", "smm=off"])
elif sys.platform.startswith("win") or sys.platform.startswith("darwin"):
command.extend(["-enable-hax"])

View File

@ -78,6 +78,7 @@ async def vm(compute_project, manager, fake_qemu_binary, fake_qemu_img_binary):
vm._start_ubridge = AsyncioMagicMock()
vm._ubridge_hypervisor = MagicMock()
vm._ubridge_hypervisor.is_running.return_value = True
vm.manager.get_qemu_version = AsyncioMagicMock(return_value="6.2.0")
vm.manager.config.set("Qemu", "enable_hardware_acceleration", False)
return vm
@ -141,7 +142,6 @@ async def test_is_running(vm, running_subprocess_mock):
async def test_start(vm, running_subprocess_mock):
vm.manager.get_qemu_version = AsyncioMagicMock(return_value="3.1.0")
with asyncio_patch("gns3server.compute.qemu.QemuVM.start_wrap_console"):
with asyncio_patch("asyncio.create_subprocess_exec", return_value=running_subprocess_mock) as mock:
await vm.start()
@ -156,7 +156,6 @@ async def test_stop(vm, running_subprocess_mock):
future = asyncio.Future()
future.set_result(True)
process.wait.return_value = future
vm.manager.get_qemu_version = AsyncioMagicMock(return_value="3.1.0")
with asyncio_patch("gns3server.compute.qemu.QemuVM.start_wrap_console"):
with asyncio_patch("asyncio.create_subprocess_exec", return_value=process):
@ -241,7 +240,6 @@ async def test_port_remove_nio_binding(vm):
async def test_close(vm, port_manager):
vm.manager.get_qemu_version = AsyncioMagicMock(return_value="3.1.0")
with asyncio_patch("gns3server.compute.qemu.QemuVM.start_wrap_console"):
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()):
await vm.start()
@ -369,7 +367,6 @@ async def test_disk_options(vm, tmpdir, fake_qemu_img_binary):
async def test_cdrom_option(vm, tmpdir, fake_qemu_img_binary):
vm.manager.get_qemu_version = AsyncioMagicMock(return_value="3.1.0")
vm._cdrom_image = str(tmpdir / "test.iso")
open(vm._cdrom_image, "w+").close()
@ -380,7 +377,6 @@ async def test_cdrom_option(vm, tmpdir, fake_qemu_img_binary):
async def test_bios_option(vm, tmpdir, fake_qemu_img_binary):
vm.manager.get_qemu_version = AsyncioMagicMock(return_value="3.1.0")
vm._bios_image = str(tmpdir / "test.img")
open(vm._bios_image, "w+").close()
options = await vm._build_command()
@ -390,7 +386,6 @@ async def test_bios_option(vm, tmpdir, fake_qemu_img_binary):
@pytest.mark.skipif(sys.platform.startswith("win"), reason="Test not working on Windows")
async def test_uefi_boot_mode_option(vm, tmpdir, images_dir, fake_qemu_img_binary):
vm.manager.get_qemu_version = AsyncioMagicMock(return_value="3.1.0")
vm._uefi = True
# create fake OVMF files
@ -408,7 +403,6 @@ async def test_uefi_boot_mode_option(vm, tmpdir, images_dir, fake_qemu_img_binar
async def test_uefi_with_bios_image_already_configured(vm, tmpdir, fake_qemu_img_binary):
vm.manager.get_qemu_version = AsyncioMagicMock(return_value="3.1.0")
vm._bios_image = str(tmpdir / "test.img")
vm._uefi = True
with pytest.raises(QemuError):
@ -434,7 +428,6 @@ async def test_spice_option(vm, fake_qemu_img_binary):
async def test_tpm_option(vm, tmpdir, fake_qemu_img_binary):
vm.manager.get_qemu_version = AsyncioMagicMock(return_value="3.1.0")
vm._tpm = True
tpm_sock = os.path.join(vm.temporary_directory, "swtpm.sock")
with patch("os.path.exists", return_value=True) as os_path:
@ -528,7 +521,6 @@ async def test_control_vm_expect_text(vm, running_subprocess_mock):
async def test_build_command(vm, fake_qemu_binary):
vm.manager.get_qemu_version = AsyncioMagicMock(return_value="3.1.0")
os.environ["DISPLAY"] = "0:0"
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()):
cmd = await vm._build_command()
@ -563,7 +555,6 @@ async def test_build_command_manual_uuid(vm):
If user has set a uuid we keep it
"""
vm.manager.get_qemu_version = AsyncioMagicMock(return_value="3.1.0")
vm.options = "-uuid e1c307a4-896f-11e6-81a5-3c07547807cc"
os.environ["DISPLAY"] = "0:0"
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()):
@ -698,7 +689,6 @@ async def test_build_command_two_adapters_mac_address(vm):
Should support multiple base vmac address
"""
vm.manager.get_qemu_version = AsyncioMagicMock(return_value="2.5.0")
vm.adapters = 2
vm.mac_address = "00:00:ab:0e:0f:09"
mac_0 = vm._mac_address
@ -723,12 +713,9 @@ async def test_build_command_two_adapters_mac_address(vm):
async def test_build_command_large_number_of_adapters(vm):
"""
When we have more than 28 interface we need to add a pci bridge for
additional interfaces
additional interfaces (supported only with Qemu 2.4 and later)
"""
# It's supported only with Qemu 2.4 and later
vm.manager.get_qemu_version = AsyncioMagicMock(return_value="2.4.0")
vm.adapters = 100
vm.mac_address = "00:00:ab:0e:0f:09"
mac_0 = vm._mac_address
@ -770,7 +757,6 @@ async def test_build_command_with_virtio_net_pci_adapter(vm):
Test virtio-net-pci adapter which has parameters speed=1000 & duplex=full hard-coded
"""
vm.manager.get_qemu_version = AsyncioMagicMock(return_value="2.4.0")
vm.adapters = 1
vm.mac_address = "00:00:ab:0e:0f:09"
vm._adapter_type = "virtio-net-pci"