From c528d2cd950b5eac072f5b499d145ab40c645db9 Mon Sep 17 00:00:00 2001 From: grossmj Date: Mon, 13 Jul 2026 18:19:52 +0200 Subject: [PATCH 1/2] fix(import): project import does not move images symlinks into place --- gns3server/controller/import_project.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/gns3server/controller/import_project.py b/gns3server/controller/import_project.py index a0f95bf00..56d4bb4f5 100644 --- a/gns3server/controller/import_project.py +++ b/gns3server/controller/import_project.py @@ -271,7 +271,7 @@ async def _upload_file(compute, project_id, file_path, path): async def _import_images(controller, images_path): """ - Copy images to the images directory or delete them if they already exists. + Copy images to the images directory or delete them if they already exist. """ image_dir = controller.images_path() @@ -279,11 +279,12 @@ async def _import_images(controller, images_path): for (dirpath, dirnames, filenames) in os.walk(root, followlinks=False): for filename in filenames: path = os.path.join(dirpath, filename) - if os.path.islink(path): - continue dst = os.path.join(image_dir, os.path.relpath(path, root)) os.makedirs(os.path.dirname(dst), exist_ok=True) - await wait_run_in_executor(shutil.move, path, dst) + if not os.path.exists(dst): + await wait_run_in_executor(shutil.move, path, dst) + if not os.path.islink(dst): + os.chmod(dst, stat.S_IWRITE | stat.S_IREAD | stat.S_IEXEC) async def update_snapshots(snapshots_dir, project_path, project_name, project_id, reset_mac_addresses=True): From 1986bce538f4e12f43d8665ccb97dd10564035c0 Mon Sep 17 00:00:00 2001 From: grossmj Date: Wed, 15 Jul 2026 09:43:34 +0200 Subject: [PATCH 2/2] Only set IOU images to be executable when importing images --- gns3server/controller/import_project.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/gns3server/controller/import_project.py b/gns3server/controller/import_project.py index 56d4bb4f5..a1912208f 100644 --- a/gns3server/controller/import_project.py +++ b/gns3server/controller/import_project.py @@ -283,9 +283,15 @@ async def _import_images(controller, images_path): os.makedirs(os.path.dirname(dst), exist_ok=True) if not os.path.exists(dst): await wait_run_in_executor(shutil.move, path, dst) - if not os.path.islink(dst): - os.chmod(dst, stat.S_IWRITE | stat.S_IREAD | stat.S_IEXEC) - + try: + with open(dst, "rb") as f: + # read the first 7 bytes of the file. + elf_header_start = f.read(7) + # IOU images must start with the ELF magic number, be 32-bit or 64-bit, little endian and have an ELF version of 1 + if elf_header_start == b'\x7fELF\x01\x01\x01' or elf_header_start == b'\x7fELF\x02\x01\x01': + os.chmod(dst, stat.S_IWRITE | stat.S_IREAD | stat.S_IEXEC) + except OSError as e: + continue async def update_snapshots(snapshots_dir, project_path, project_name, project_id, reset_mac_addresses=True): """