mirror of
https://github.com/GNS3/gns3-server
synced 2025-01-12 09:00:57 +00:00
Merge pull request #2255 from GNS3/fix/2243
Only add speed/duplex params when using Qemu >= v2.12
This commit is contained in:
commit
c5c4e1ad56
@ -86,6 +86,7 @@ class QemuVM(BaseNode):
|
|||||||
self._local_udp_tunnels = {}
|
self._local_udp_tunnels = {}
|
||||||
self._guest_cid = None
|
self._guest_cid = None
|
||||||
self._command_line_changed = False
|
self._command_line_changed = False
|
||||||
|
self._qemu_version = None
|
||||||
|
|
||||||
# QEMU VM settings
|
# QEMU VM settings
|
||||||
if qemu_path:
|
if qemu_path:
|
||||||
@ -1871,8 +1872,7 @@ class QemuVM(BaseNode):
|
|||||||
# special case, sata controller doesn't exist in Qemu
|
# special case, sata controller doesn't exist in Qemu
|
||||||
options.extend(["-device", 'ahci,id=ahci{}'.format(disk_index)])
|
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)])
|
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 self._qemu_version and parse_version(self._qemu_version) >= parse_version("4.2.0"):
|
||||||
if qemu_version and parse_version(qemu_version) >= parse_version("4.2.0"):
|
|
||||||
# The ‘ide-drive’ device is deprecated since 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
|
# 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)])
|
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
|
patched_qemu = False
|
||||||
if self._legacy_networking:
|
if self._legacy_networking:
|
||||||
qemu_version = await self.manager.get_qemu_version(self.qemu_path)
|
if self._qemu_version:
|
||||||
if qemu_version:
|
if parse_version(self._qemu_version) >= parse_version("2.9.0"):
|
||||||
if parse_version(qemu_version) >= parse_version("2.9.0"):
|
|
||||||
raise QemuError("Qemu version 2.9.0 and later doesn't support legacy networking mode")
|
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
|
# this is a patched Qemu if version is below 1.1.0
|
||||||
patched_qemu = True
|
patched_qemu = True
|
||||||
|
|
||||||
@ -2144,8 +2143,7 @@ class QemuVM(BaseNode):
|
|||||||
pci_bridges = math.floor(pci_devices / 32)
|
pci_bridges = math.floor(pci_devices / 32)
|
||||||
pci_bridges_created = 0
|
pci_bridges_created = 0
|
||||||
if pci_bridges >= 1:
|
if pci_bridges >= 1:
|
||||||
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"):
|
||||||
if qemu_version and parse_version(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")
|
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
|
pci_device_id = 4 + pci_bridges # Bridge consume PCI ports
|
||||||
@ -2191,7 +2189,9 @@ class QemuVM(BaseNode):
|
|||||||
else:
|
else:
|
||||||
# newer QEMU networking syntax
|
# newer QEMU networking syntax
|
||||||
device_string = "{},mac={}".format(adapter_type, mac)
|
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)
|
device_string = "{},speed=10000,duplex=full".format(device_string)
|
||||||
bridge_id = math.floor(pci_device_id / 32)
|
bridge_id = math.floor(pci_device_id / 32)
|
||||||
if bridge_id > 0:
|
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"]):
|
if any(opt in self._options for opt in ["-display", "-nographic", "-curses", "-sdl" "-spice", "-vnc"]):
|
||||||
return []
|
return []
|
||||||
version = await self.manager.get_qemu_version(self.qemu_path)
|
if self._qemu_version and parse_version(self._qemu_version) >= parse_version("3.0"):
|
||||||
if version and parse_version(version) >= parse_version("3.0"):
|
|
||||||
return ["-display", "none"]
|
return ["-display", "none"]
|
||||||
else:
|
else:
|
||||||
return ["-nographic"]
|
return ["-nographic"]
|
||||||
@ -2270,9 +2269,8 @@ class QemuVM(BaseNode):
|
|||||||
elif sys.platform.startswith("win"):
|
elif sys.platform.startswith("win"):
|
||||||
if require_hardware_accel:
|
if require_hardware_accel:
|
||||||
# HAXM is only available starting with Qemu version 2.9.0
|
# HAXM is only available starting with Qemu version 2.9.0
|
||||||
version = await self.manager.get_qemu_version(self.qemu_path)
|
if self._qemu_version and parse_version(self._qemu_version) < parse_version("2.9.0"):
|
||||||
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(self._qemu_version))
|
||||||
raise QemuError("HAXM acceleration can only be enable for Qemu version 2.9.0 and above (current version: {})".format(version))
|
|
||||||
|
|
||||||
# check if HAXM is installed
|
# check if HAXM is installed
|
||||||
version = self.manager.get_haxm_windows_version()
|
version = self.manager.get_haxm_windows_version()
|
||||||
@ -2372,6 +2370,7 @@ class QemuVM(BaseNode):
|
|||||||
(to be passed to subprocess.Popen())
|
(to be passed to subprocess.Popen())
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
self._qemu_version = await self.manager.get_qemu_version(self.qemu_path)
|
||||||
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()
|
||||||
@ -2389,10 +2388,9 @@ class QemuVM(BaseNode):
|
|||||||
if await self._run_with_hardware_acceleration(self.qemu_path, self._options):
|
if await self._run_with_hardware_acceleration(self.qemu_path, self._options):
|
||||||
if sys.platform.startswith("linux"):
|
if sys.platform.startswith("linux"):
|
||||||
command.extend(["-enable-kvm"])
|
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
|
# Issue on some combo Intel CPU + KVM + Qemu 2.4.0
|
||||||
# https://github.com/GNS3/gns3-server/issues/685
|
# 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"])
|
command.extend(["-machine", "smm=off"])
|
||||||
elif sys.platform.startswith("win") or sys.platform.startswith("darwin"):
|
elif sys.platform.startswith("win") or sys.platform.startswith("darwin"):
|
||||||
command.extend(["-enable-hax"])
|
command.extend(["-enable-hax"])
|
||||||
|
@ -78,6 +78,7 @@ async def vm(compute_project, manager, fake_qemu_binary, fake_qemu_img_binary):
|
|||||||
vm._start_ubridge = AsyncioMagicMock()
|
vm._start_ubridge = AsyncioMagicMock()
|
||||||
vm._ubridge_hypervisor = MagicMock()
|
vm._ubridge_hypervisor = MagicMock()
|
||||||
vm._ubridge_hypervisor.is_running.return_value = True
|
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)
|
vm.manager.config.set("Qemu", "enable_hardware_acceleration", False)
|
||||||
return vm
|
return vm
|
||||||
|
|
||||||
@ -141,7 +142,6 @@ async def test_is_running(vm, running_subprocess_mock):
|
|||||||
|
|
||||||
async def test_start(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("gns3server.compute.qemu.QemuVM.start_wrap_console"):
|
||||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=running_subprocess_mock) as mock:
|
with asyncio_patch("asyncio.create_subprocess_exec", return_value=running_subprocess_mock) as mock:
|
||||||
await vm.start()
|
await vm.start()
|
||||||
@ -156,7 +156,6 @@ async def test_stop(vm, running_subprocess_mock):
|
|||||||
future = asyncio.Future()
|
future = asyncio.Future()
|
||||||
future.set_result(True)
|
future.set_result(True)
|
||||||
process.wait.return_value = future
|
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("gns3server.compute.qemu.QemuVM.start_wrap_console"):
|
||||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=process):
|
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):
|
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("gns3server.compute.qemu.QemuVM.start_wrap_console"):
|
||||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()):
|
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()):
|
||||||
await vm.start()
|
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):
|
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")
|
vm._cdrom_image = str(tmpdir / "test.iso")
|
||||||
open(vm._cdrom_image, "w+").close()
|
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):
|
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")
|
vm._bios_image = str(tmpdir / "test.img")
|
||||||
open(vm._bios_image, "w+").close()
|
open(vm._bios_image, "w+").close()
|
||||||
options = await vm._build_command()
|
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")
|
@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):
|
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
|
vm._uefi = True
|
||||||
|
|
||||||
# create fake OVMF files
|
# 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):
|
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._bios_image = str(tmpdir / "test.img")
|
||||||
vm._uefi = True
|
vm._uefi = True
|
||||||
with pytest.raises(QemuError):
|
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):
|
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
|
vm._tpm = True
|
||||||
tpm_sock = os.path.join(vm.temporary_directory, "swtpm.sock")
|
tpm_sock = os.path.join(vm.temporary_directory, "swtpm.sock")
|
||||||
with patch("os.path.exists", return_value=True) as os_path:
|
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):
|
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"
|
os.environ["DISPLAY"] = "0:0"
|
||||||
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()
|
||||||
@ -563,7 +555,6 @@ async def test_build_command_manual_uuid(vm):
|
|||||||
If user has set a uuid we keep it
|
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"
|
vm.options = "-uuid e1c307a4-896f-11e6-81a5-3c07547807cc"
|
||||||
os.environ["DISPLAY"] = "0:0"
|
os.environ["DISPLAY"] = "0:0"
|
||||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()):
|
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
|
Should support multiple base vmac address
|
||||||
"""
|
"""
|
||||||
|
|
||||||
vm.manager.get_qemu_version = AsyncioMagicMock(return_value="2.5.0")
|
|
||||||
vm.adapters = 2
|
vm.adapters = 2
|
||||||
vm.mac_address = "00:00:ab:0e:0f:09"
|
vm.mac_address = "00:00:ab:0e:0f:09"
|
||||||
mac_0 = vm._mac_address
|
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):
|
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
|
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.adapters = 100
|
||||||
vm.mac_address = "00:00:ab:0e:0f:09"
|
vm.mac_address = "00:00:ab:0e:0f:09"
|
||||||
mac_0 = vm._mac_address
|
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
|
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.adapters = 1
|
||||||
vm.mac_address = "00:00:ab:0e:0f:09"
|
vm.mac_address = "00:00:ab:0e:0f:09"
|
||||||
vm._adapter_type = "virtio-net-pci"
|
vm._adapter_type = "virtio-net-pci"
|
||||||
|
Loading…
Reference in New Issue
Block a user