mirror of
https://github.com/GNS3/gns3-server.git
synced 2026-11-03 14:01:15 +02:00
fix: dedupe and report automatic template creation from images
install_appliances_from_image relied on the name+version pair check in TemplatesService, so the same appliance reached through a second image (the CSR1000v case) created a second template sharing the name. The auto path now skips when any template with the same name exists, whatever the version, and returns a manifest of created and skipped candidates; POST /images/install replies 200 with that manifest instead of an empty 204, and the image_install MCP tool surfaces it.
This commit is contained in:
7 files changed
+154
-11
No files matched your search
@@ -206,19 +206,24 @@ async def prune_images(
|
||||
|
||||
@router.post(
|
||||
"/install",
|
||||
status_code=status.HTTP_204_NO_CONTENT,
|
||||
status_code=status.HTTP_200_OK,
|
||||
dependencies=[Depends(has_privilege("Image.Allocate"))]
|
||||
)
|
||||
async def install_images(
|
||||
images_repo: ImagesRepository = Depends(get_repository(ImagesRepository)),
|
||||
templates_repo: TemplatesRepository = Depends(get_repository(TemplatesRepository))
|
||||
) -> None:
|
||||
) -> dict:
|
||||
"""
|
||||
Attempt to automatically create templates based on image checksums.
|
||||
|
||||
Returns the list of created templates and the list of skipped
|
||||
candidates (with the reason why they were skipped).
|
||||
|
||||
Required privilege: Image.Allocate
|
||||
"""
|
||||
|
||||
created = []
|
||||
skipped = []
|
||||
skip_images = get_builtin_disks()
|
||||
images = await images_repo.get_images()
|
||||
for image in images:
|
||||
@@ -229,8 +234,12 @@ async def install_images(
|
||||
if templates:
|
||||
# the image is already used by a template
|
||||
log.warning(f"Image '{image.path}' is used by one or more templates")
|
||||
skipped.append({
|
||||
"name": image.filename,
|
||||
"reason": "image is already used by one or more templates",
|
||||
})
|
||||
continue
|
||||
await Controller.instance().appliance_manager.install_appliances_from_image(
|
||||
results = await Controller.instance().appliance_manager.install_appliances_from_image(
|
||||
image.path,
|
||||
image.checksum,
|
||||
images_repo,
|
||||
@@ -239,6 +248,12 @@ async def install_images(
|
||||
None,
|
||||
os.path.dirname(image.path)
|
||||
)
|
||||
for result in results:
|
||||
if result.get("status") == "created":
|
||||
created.append({k: v for k, v in result.items() if k != "status"})
|
||||
else:
|
||||
skipped.append({k: v for k, v in result.items() if k != "status"})
|
||||
return {"created": created, "skipped": skipped}
|
||||
|
||||
|
||||
@router.get(
|
||||
|
||||
Reference in new issue
Block a user