mirror of
https://github.com/GNS3/gns3-server.git
synced 2026-11-03 05:51:15 +02:00
Merge branch '3.0' into feature/ai-copilot-bridge
This commit is contained in:
12 files changed
+108
-69
No files matched your search
@@ -154,6 +154,17 @@ async def upload_image(
|
||||
if os.path.commonprefix([base_images_directory, full_path]) != base_images_directory:
|
||||
raise ControllerForbiddenError(f"Cannot write image, '{image_path}' is forbidden")
|
||||
|
||||
# If the client sends X-MD5-Checksum, check for a duplicate before consuming the upload stream
|
||||
checksum_header = request.headers.get("X-MD5-Checksum")
|
||||
if checksum_header:
|
||||
check_dir = os.path.dirname(full_path) if image_dir else None
|
||||
duplicate = await images_repo.get_image_by_checksum(checksum_header, check_dir)
|
||||
if duplicate:
|
||||
location = f" in '{check_dir}'" if check_dir else ""
|
||||
raise ControllerError(
|
||||
f"Image '{duplicate.filename}' with the same checksum already exists{location}"
|
||||
)
|
||||
|
||||
try:
|
||||
allow_raw_image = Config.instance().settings.Server.allow_raw_images
|
||||
image = await write_image(image_path, full_path, request.stream(), images_repo, allow_raw_image=allow_raw_image)
|
||||
|
||||
@@ -105,6 +105,16 @@ async def dep_node(node_id: UUID, project: Project = Depends(dep_project)) -> No
|
||||
return node
|
||||
|
||||
|
||||
def _check_node_type(node: Node, *required_types: str) -> None:
|
||||
"""
|
||||
Raise ControllerBadRequestError if node is not one of the required types.
|
||||
"""
|
||||
|
||||
if node.node_type not in required_types:
|
||||
type_str = "/".join(required_types)
|
||||
raise ControllerBadRequestError(f"This endpoint is only supported on a {type_str} node")
|
||||
|
||||
|
||||
@router.post(
|
||||
"",
|
||||
status_code=status.HTTP_201_CREATED,
|
||||
@@ -407,8 +417,7 @@ async def auto_idlepc(node: Node = Depends(dep_node)) -> dict:
|
||||
Required privilege: Node.Audit
|
||||
"""
|
||||
|
||||
if node.node_type != "dynamips":
|
||||
raise ControllerBadRequestError("Auto Idle-PC is only supported on a Dynamips node")
|
||||
_check_node_type(node, "dynamips")
|
||||
return await node.dynamips_auto_idlepc()
|
||||
|
||||
|
||||
@@ -420,8 +429,7 @@ async def idlepc_proposals(node: Node = Depends(dep_node)) -> List[str]:
|
||||
Required privilege: Node.Audit
|
||||
"""
|
||||
|
||||
if node.node_type != "dynamips":
|
||||
raise ControllerBadRequestError("Idle-PC proposals is only supported on a Dynamips node")
|
||||
_check_node_type(node, "dynamips")
|
||||
return await node.dynamips_idlepc_proposals()
|
||||
|
||||
|
||||
@@ -441,8 +449,7 @@ async def create_disk_image(
|
||||
Required privilege: Node.Allocate
|
||||
"""
|
||||
|
||||
if node.node_type != "qemu":
|
||||
raise ControllerBadRequestError("Creating a disk image is only supported on a Qemu node")
|
||||
_check_node_type(node, "qemu")
|
||||
await node.post(f"/disk_image/{disk_name}", data=disk_data.model_dump(exclude_unset=True))
|
||||
|
||||
|
||||
@@ -462,8 +469,7 @@ async def update_disk_image(
|
||||
Required privilege: Node.Allocate
|
||||
"""
|
||||
|
||||
if node.node_type != "qemu":
|
||||
raise ControllerBadRequestError("Updating a disk image is only supported on a Qemu node")
|
||||
_check_node_type(node, "qemu")
|
||||
await node.put(f"/disk_image/{disk_name}", data=disk_data.model_dump(exclude_unset=True))
|
||||
|
||||
|
||||
@@ -482,8 +488,7 @@ async def delete_disk_image(
|
||||
Required privilege: Node.Allocate
|
||||
"""
|
||||
|
||||
if node.node_type != "qemu":
|
||||
raise ControllerBadRequestError("Deleting a disk image is only supported on a Qemu node")
|
||||
_check_node_type(node, "qemu")
|
||||
await node.delete(f"/disk_image/{disk_name}")
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user