mirror of
https://github.com/GNS3/gns3-server.git
synced 2025-06-21 00:22:56 +00:00
Handle creating Qemu disk images and resizing
This commit is contained in:
@ -51,6 +51,11 @@ from . import virtualbox_nodes
|
||||
from . import vmware_nodes
|
||||
from . import vpcs_nodes
|
||||
|
||||
import logging
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
compute_api = FastAPI(
|
||||
title="GNS3 compute API",
|
||||
dependencies=[Depends(compute_authentication)],
|
||||
@ -63,6 +68,7 @@ compute_api.state.controller_host = None
|
||||
|
||||
@compute_api.exception_handler(ComputeError)
|
||||
async def controller_error_handler(request: Request, exc: ComputeError):
|
||||
log.error(f"Compute error: {exc}")
|
||||
return JSONResponse(
|
||||
status_code=409,
|
||||
content={"message": str(exc)},
|
||||
@ -71,6 +77,7 @@ async def controller_error_handler(request: Request, exc: ComputeError):
|
||||
|
||||
@compute_api.exception_handler(ComputeTimeoutError)
|
||||
async def controller_timeout_error_handler(request: Request, exc: ComputeTimeoutError):
|
||||
log.error(f"Compute timeout error: {exc}")
|
||||
return JSONResponse(
|
||||
status_code=408,
|
||||
content={"message": str(exc)},
|
||||
@ -79,6 +86,7 @@ async def controller_timeout_error_handler(request: Request, exc: ComputeTimeout
|
||||
|
||||
@compute_api.exception_handler(ComputeUnauthorizedError)
|
||||
async def controller_unauthorized_error_handler(request: Request, exc: ComputeUnauthorizedError):
|
||||
log.error(f"Compute unauthorized error: {exc}")
|
||||
return JSONResponse(
|
||||
status_code=401,
|
||||
content={"message": str(exc)},
|
||||
@ -87,6 +95,7 @@ async def controller_unauthorized_error_handler(request: Request, exc: ComputeUn
|
||||
|
||||
@compute_api.exception_handler(ComputeForbiddenError)
|
||||
async def controller_forbidden_error_handler(request: Request, exc: ComputeForbiddenError):
|
||||
log.error(f"Compute forbidden error: {exc}")
|
||||
return JSONResponse(
|
||||
status_code=403,
|
||||
content={"message": str(exc)},
|
||||
@ -95,6 +104,7 @@ async def controller_forbidden_error_handler(request: Request, exc: ComputeForbi
|
||||
|
||||
@compute_api.exception_handler(ComputeNotFoundError)
|
||||
async def controller_not_found_error_handler(request: Request, exc: ComputeNotFoundError):
|
||||
log.error(f"Compute not found error: {exc}")
|
||||
return JSONResponse(
|
||||
status_code=404,
|
||||
content={"message": str(exc)},
|
||||
@ -103,6 +113,7 @@ async def controller_not_found_error_handler(request: Request, exc: ComputeNotFo
|
||||
|
||||
@compute_api.exception_handler(GNS3VMError)
|
||||
async def controller_error_handler(request: Request, exc: GNS3VMError):
|
||||
log.error(f"Compute GNS3 VM error: {exc}")
|
||||
return JSONResponse(
|
||||
status_code=409,
|
||||
content={"message": str(exc)},
|
||||
@ -111,6 +122,7 @@ async def controller_error_handler(request: Request, exc: GNS3VMError):
|
||||
|
||||
@compute_api.exception_handler(ImageMissingError)
|
||||
async def image_missing_error_handler(request: Request, exc: ImageMissingError):
|
||||
log.error(f"Compute image missing error: {exc}")
|
||||
return JSONResponse(
|
||||
status_code=409,
|
||||
content={"message": str(exc), "image": exc.image, "exception": exc.__class__.__name__},
|
||||
@ -119,6 +131,7 @@ async def image_missing_error_handler(request: Request, exc: ImageMissingError):
|
||||
|
||||
@compute_api.exception_handler(NodeError)
|
||||
async def node_error_handler(request: Request, exc: NodeError):
|
||||
log.error(f"Compute node error: {exc}")
|
||||
return JSONResponse(
|
||||
status_code=409,
|
||||
content={"message": str(exc), "exception": exc.__class__.__name__},
|
||||
@ -127,6 +140,7 @@ async def node_error_handler(request: Request, exc: NodeError):
|
||||
|
||||
@compute_api.exception_handler(UbridgeError)
|
||||
async def ubridge_error_handler(request: Request, exc: UbridgeError):
|
||||
log.error(f"Compute uBridge error: {exc}")
|
||||
return JSONResponse(
|
||||
status_code=409,
|
||||
content={"message": str(exc), "exception": exc.__class__.__name__},
|
||||
|
@ -144,55 +144,6 @@ async def get_qemu_capabilities() -> dict:
|
||||
return capabilities
|
||||
|
||||
|
||||
@router.post(
|
||||
"/qemu/img",
|
||||
status_code=status.HTTP_204_NO_CONTENT,
|
||||
responses={403: {"model": schemas.ErrorMessage, "description": "Forbidden to create Qemu image"}},
|
||||
)
|
||||
async def create_qemu_image(image_data: schemas.QemuImageCreate) -> Response:
|
||||
"""
|
||||
Create a Qemu image.
|
||||
"""
|
||||
|
||||
#FIXME: move to controller
|
||||
raise NotImplementedError()
|
||||
|
||||
# Raise error if user try to escape
|
||||
#if not is_safe_path(image_data.path, project.path):
|
||||
# raise HTTPException(status_code=status.HTTP_403_FORBIDDEN)
|
||||
|
||||
await Qemu.instance().create_disk(
|
||||
image_data.qemu_img,
|
||||
image_data.path,
|
||||
jsonable_encoder(image_data, exclude_unset=True, exclude={"qemu_img", "path"})
|
||||
)
|
||||
|
||||
return Response(status_code=status.HTTP_204_NO_CONTENT)
|
||||
|
||||
|
||||
@router.put(
|
||||
"/qemu/img",
|
||||
status_code=status.HTTP_204_NO_CONTENT,
|
||||
responses={403: {"model": schemas.ErrorMessage, "description": "Forbidden to update Qemu image"}},
|
||||
)
|
||||
async def update_qemu_image(image_data: schemas.QemuImageUpdate) -> Response:
|
||||
"""
|
||||
Update a Qemu image.
|
||||
"""
|
||||
|
||||
#FIXME: move to controller
|
||||
raise NotImplementedError()
|
||||
|
||||
# Raise error if user try to escape
|
||||
#if not is_safe_path(image_data.path, project.path):
|
||||
# raise HTTPException(status_code=status.HTTP_403_FORBIDDEN)
|
||||
|
||||
if image_data.extend:
|
||||
await Qemu.instance().resize_disk(image_data.qemu_img, image_data.path, image_data.extend)
|
||||
|
||||
return Response(status_code=status.HTTP_204_NO_CONTENT)
|
||||
|
||||
|
||||
@router.get("/virtualbox/vms", response_model=List[dict])
|
||||
async def get_virtualbox_vms() -> List[dict]:
|
||||
|
||||
|
@ -26,10 +26,10 @@ from fastapi.responses import StreamingResponse
|
||||
from uuid import UUID
|
||||
|
||||
from gns3server import schemas
|
||||
from gns3server.compute.project_manager import ProjectManager
|
||||
from gns3server.compute.qemu import Qemu
|
||||
from gns3server.compute.qemu.qemu_vm import QemuVM
|
||||
|
||||
|
||||
responses = {404: {"model": schemas.ErrorMessage, "description": "Could not find project or Qemu node"}}
|
||||
|
||||
router = APIRouter(responses=responses)
|
||||
@ -126,10 +126,39 @@ async def duplicate_qemu_node(
|
||||
return new_node.asdict()
|
||||
|
||||
|
||||
@router.post("/{node_id}/resize_disk", status_code=status.HTTP_204_NO_CONTENT)
|
||||
async def resize_qemu_node_disk(node_data: schemas.QemuDiskResize, node: QemuVM = Depends(dep_node)) -> Response:
|
||||
@router.post(
|
||||
"/{node_id}/disk_image/{disk_name}",
|
||||
status_code=status.HTTP_204_NO_CONTENT
|
||||
)
|
||||
async def create_qemu_disk_image(
|
||||
disk_name: str,
|
||||
disk_data: schemas.QemuDiskImageCreate,
|
||||
node: QemuVM = Depends(dep_node)
|
||||
) -> Response:
|
||||
"""
|
||||
Create a Qemu disk image.
|
||||
"""
|
||||
|
||||
await node.resize_disk(node_data.drive_name, node_data.extend)
|
||||
options = jsonable_encoder(disk_data, exclude_unset=True)
|
||||
await node.create_disk_image(disk_name, options)
|
||||
return Response(status_code=status.HTTP_204_NO_CONTENT)
|
||||
|
||||
|
||||
@router.put(
|
||||
"/{node_id}/disk_image/{disk_name}",
|
||||
status_code=status.HTTP_204_NO_CONTENT
|
||||
)
|
||||
async def update_qemu_disk_image(
|
||||
disk_name: str,
|
||||
disk_data: schemas.QemuDiskImageUpdate,
|
||||
node: QemuVM = Depends(dep_node)
|
||||
) -> Response:
|
||||
"""
|
||||
Update a Qemu disk image.
|
||||
"""
|
||||
|
||||
if disk_data.extend:
|
||||
await node.resize_disk_image(disk_name, disk_data.extend)
|
||||
return Response(status_code=status.HTTP_204_NO_CONTENT)
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user