diff --git a/CHANGELOG b/CHANGELOG index b9c0984ef..57e62df21 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,15 @@ # Change Log +## 2.2.51 07/11/2024 + +* Catch error when cannot resize Docker container TTY. +* Do not use "ide" if there is a disk image and no interface type has been explicitly configured. +* Use @locking when sending uBridge commands. Ref https://github.com/GNS3/gns3-gui/issues/3651 +* Fix run Docker containers with user namespaces enabled. Fixes #2414 +* Python 3.13 support +* Upgrade dependencies +* Fix errors in init.sh. Fixes #2431 + ## 2.2.50 21/10/2024 * Bundle web-ui v2.2.50 diff --git a/gns3server/appliances/nixos.gns3a b/gns3server/appliances/nixos.gns3a new file mode 100644 index 000000000..32d3b6096 --- /dev/null +++ b/gns3server/appliances/nixos.gns3a @@ -0,0 +1,52 @@ +{ + "appliance_id": "00714342-14b2-4281-aa20-9043ca8dc26e", + "name": "NixOS", + "category": "guest", + "description": "NixOS QEMU Appliance for images created with nixos-generator. Automatically sets hostname based on vmname.", + "vendor_name": "NixOS", + "vendor_url": "https://nixos.org/", + "vendor_logo_url": "https://avatars.githubusercontent.com/u/487568", + "documentation_url": "https://github.com/ob7/gns3-nixos-appliance", + "product_name": "NixOS", + "product_url": "https://github.com/NixOS/nixpkgs", + "registry_version": 4, + "status": "experimental", + "availability": "free", + "maintainer": "ob7dev", + "maintainer_email": "dev@ob7.us", + "usage": "For custom NixOS images, create qcow2 VM with: nixos-generate -f qcow -c ./server.nix Import it into GNS3 as image. VM name is passed into QEMU guest with Advanced Options field entry: -fw_cfg name=opt/vm_hostname,string=%vm-name%", + "symbol": ":/symbols/affinity/circle/gray/template.svg", + "first_port_name": "eth0", + "port_name_format": "eth{0}", + "qemu": { + "adapter_type": "e1000", + "adapters": 4, + "ram": 256, + "cpus": 1, + "hda_disk_interface": "ide", + "arch": "x86_64", + "console_type": "telnet", + "kvm": "allow", + "options": "-fw_cfg name=opt/vm_hostname,string=%vm-name%", + "on_close": "power_off" + }, + "images": [ + { + "filename": "nixos-24-11.qcow2", + "version": "24.11", + "md5sum": "2459f05136836dd430402d75cba0f205", + "download_url": "https://github.com/nix-community/nixos-generators", + "filesize": 1749483520, + "download_url": "https://f.ob7.us/gns3/", + "direct_download_url": "http://ob7.us/nixos-24-11.qcow2" + } + ], + "versions": [ + { + "name": "24.11", + "images": { + "hda_disk_image": "nixos-24-11.qcow2" + } + } + ] +} diff --git a/gns3server/compute/docker/docker_vm.py b/gns3server/compute/docker/docker_vm.py index beb7adde1..4dbced0e1 100644 --- a/gns3server/compute/docker/docker_vm.py +++ b/gns3server/compute/docker/docker_vm.py @@ -835,7 +835,10 @@ async def _window_size_changed_callback(self, columns, rows): """ # resize the container TTY. - await self._manager.query("POST", f"containers/{self._cid}/resize?h={rows}&w={columns}") + try: + await self._manager.query("POST", f"containers/{self._cid}/resize?h={rows}&w={columns}") + except DockerError as e: + log.warning(f"Could not resize the container TTY: {e}") async def _start_console(self): """ diff --git a/gns3server/compute/qemu/qemu_vm.py b/gns3server/compute/qemu/qemu_vm.py index 35a1b89d6..100232338 100644 --- a/gns3server/compute/qemu/qemu_vm.py +++ b/gns3server/compute/qemu/qemu_vm.py @@ -2157,11 +2157,6 @@ async def _disk_options(self): continue interface = getattr(self, f"hd{drive}_disk_interface") - # fail-safe: use "ide" if there is a disk image and no interface type has been explicitly configured - if interface == "none": - interface = "ide" - setattr(self, f"hd{drive}_disk_interface", interface) - disk_name = f"hd{drive}" if not os.path.isfile(disk_image) or not os.path.exists(disk_image): if os.path.islink(disk_image): diff --git a/tests/compute/qemu/test_qemu_vm.py b/tests/compute/qemu/test_qemu_vm.py index d2348b236..c07e9051d 100644 --- a/tests/compute/qemu/test_qemu_vm.py +++ b/tests/compute/qemu/test_qemu_vm.py @@ -355,16 +355,23 @@ async def test_set_platform(compute_project, manager): async def test_disk_options(vm, tmpdir, fake_qemu_img_binary): vm._hda_disk_image = str(tmpdir / "test.qcow2") + vm._hda_disk_interface = "ide" + vm._hdb_disk_image = str(tmpdir / "test2.qcow2") open(vm._hda_disk_image, "w+").close() + open(vm._hdb_disk_image, "w+").close() - with asyncio_patch("gns3server.compute.qemu.qemu_vm.QemuVM._find_disk_file_format", return_value="qcow2"): + with (asyncio_patch("gns3server.compute.qemu.qemu_vm.QemuVM._find_disk_file_format", return_value="qcow2")): with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()) as process: options = await vm._disk_options() assert process.called args, kwargs = process.call_args - assert args == (fake_qemu_img_binary, "create", "-o", "backing_file={}".format(vm._hda_disk_image), "-F", "qcow2", "-f", "qcow2", os.path.join(vm.working_dir, "hda_disk.qcow2")) + assert args == (fake_qemu_img_binary, "create", "-o", "backing_file={}".format(vm._hda_disk_image), "-F", "qcow2", "-f", "qcow2", os.path.join(vm.working_dir, "hda_disk.qcow2")) or \ + args == (fake_qemu_img_binary, "create", "-o", "backing_file={}".format(vm._hdb_disk_image), "-F", "qcow2", "-f", "qcow2", os.path.join(vm.working_dir, "hdb_disk.qcow2")) - assert options == ['-drive', 'file=' + os.path.join(vm.working_dir, "hda_disk.qcow2") + ',if=ide,index=0,media=disk,id=drive0'] + assert options == [ + '-drive', 'file=' + os.path.join(vm.working_dir, "hda_disk.qcow2") + ',if=ide,index=0,media=disk,id=drive0', + '-drive', 'file=' + os.path.join(vm.working_dir, "hdb_disk.qcow2") + ',if=none,index=1,media=disk,id=drive1', + ] @pytest.mark.asyncio @@ -449,9 +456,13 @@ async def test_tpm_option(vm, tmpdir, fake_qemu_img_binary): async def test_disk_options_multiple_disk(vm, tmpdir, fake_qemu_img_binary): vm._hda_disk_image = str(tmpdir / "test0.qcow2") + vm._hda_disk_interface = "ide" vm._hdb_disk_image = str(tmpdir / "test1.qcow2") + vm._hdb_disk_interface = "ide" vm._hdc_disk_image = str(tmpdir / "test2.qcow2") + vm._hdc_disk_interface = "ide" vm._hdd_disk_image = str(tmpdir / "test3.qcow2") + vm._hdd_disk_interface = "ide" open(vm._hda_disk_image, "w+").close() open(vm._hdb_disk_image, "w+").close() open(vm._hdc_disk_image, "w+").close()