1
0
mirror of https://github.com/GNS3/gns3-server synced 2025-05-29 12:18:56 +00:00

Merge branch '3.0' into iou-user-loader-libraries

This commit is contained in:
Jeremy Grossmann 2022-07-20 16:44:48 +02:00 committed by GitHub
commit da626d334f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
59 changed files with 528 additions and 402 deletions

View File

@ -67,7 +67,7 @@ compute_api.state.controller_host = None
@compute_api.exception_handler(ComputeError) @compute_api.exception_handler(ComputeError)
async def controller_error_handler(request: Request, exc: ComputeError): async def compute_error_handler(request: Request, exc: ComputeError):
log.error(f"Compute error: {exc}") log.error(f"Compute error: {exc}")
return JSONResponse( return JSONResponse(
status_code=409, status_code=409,
@ -76,7 +76,7 @@ async def controller_error_handler(request: Request, exc: ComputeError):
@compute_api.exception_handler(ComputeTimeoutError) @compute_api.exception_handler(ComputeTimeoutError)
async def controller_timeout_error_handler(request: Request, exc: ComputeTimeoutError): async def compute_timeout_error_handler(request: Request, exc: ComputeTimeoutError):
log.error(f"Compute timeout error: {exc}") log.error(f"Compute timeout error: {exc}")
return JSONResponse( return JSONResponse(
status_code=408, status_code=408,
@ -85,7 +85,7 @@ async def controller_timeout_error_handler(request: Request, exc: ComputeTimeout
@compute_api.exception_handler(ComputeUnauthorizedError) @compute_api.exception_handler(ComputeUnauthorizedError)
async def controller_unauthorized_error_handler(request: Request, exc: ComputeUnauthorizedError): async def compute_unauthorized_error_handler(request: Request, exc: ComputeUnauthorizedError):
log.error(f"Compute unauthorized error: {exc}") log.error(f"Compute unauthorized error: {exc}")
return JSONResponse( return JSONResponse(
status_code=401, status_code=401,
@ -94,7 +94,7 @@ async def controller_unauthorized_error_handler(request: Request, exc: ComputeUn
@compute_api.exception_handler(ComputeForbiddenError) @compute_api.exception_handler(ComputeForbiddenError)
async def controller_forbidden_error_handler(request: Request, exc: ComputeForbiddenError): async def compute_forbidden_error_handler(request: Request, exc: ComputeForbiddenError):
log.error(f"Compute forbidden error: {exc}") log.error(f"Compute forbidden error: {exc}")
return JSONResponse( return JSONResponse(
status_code=403, status_code=403,
@ -103,7 +103,7 @@ async def controller_forbidden_error_handler(request: Request, exc: ComputeForbi
@compute_api.exception_handler(ComputeNotFoundError) @compute_api.exception_handler(ComputeNotFoundError)
async def controller_not_found_error_handler(request: Request, exc: ComputeNotFoundError): async def compute_not_found_error_handler(request: Request, exc: ComputeNotFoundError):
log.error(f"Compute not found error: {exc}") log.error(f"Compute not found error: {exc}")
return JSONResponse( return JSONResponse(
status_code=404, status_code=404,
@ -112,7 +112,7 @@ async def controller_not_found_error_handler(request: Request, exc: ComputeNotFo
@compute_api.exception_handler(GNS3VMError) @compute_api.exception_handler(GNS3VMError)
async def controller_error_handler(request: Request, exc: GNS3VMError): async def compute_gns3vm_error_handler(request: Request, exc: GNS3VMError):
log.error(f"Compute GNS3 VM error: {exc}") log.error(f"Compute GNS3 VM error: {exc}")
return JSONResponse( return JSONResponse(
status_code=409, status_code=409,

View File

@ -109,43 +109,42 @@ async def update_atm_switch(
@router.delete("/{node_id}", status_code=status.HTTP_204_NO_CONTENT) @router.delete("/{node_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_atm_switch_node(node: ATMSwitch = Depends(dep_node)) -> Response: async def delete_atm_switch_node(node: ATMSwitch = Depends(dep_node)) -> None:
""" """
Delete an ATM switch node. Delete an ATM switch node.
""" """
await Dynamips.instance().delete_node(node.id) await Dynamips.instance().delete_node(node.id)
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{node_id}/start", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/start", status_code=status.HTTP_204_NO_CONTENT)
def start_atm_switch(node: ATMSwitch = Depends(dep_node)) -> Response: def start_atm_switch(node: ATMSwitch = Depends(dep_node)) -> None:
""" """
Start an ATM switch node. Start an ATM switch node.
This endpoint results in no action since ATM switch nodes are always on. This endpoint results in no action since ATM switch nodes are always on.
""" """
return Response(status_code=status.HTTP_204_NO_CONTENT) pass
@router.post("/{node_id}/stop", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/stop", status_code=status.HTTP_204_NO_CONTENT)
def stop_atm_switch(node: ATMSwitch = Depends(dep_node)) -> Response: def stop_atm_switch(node: ATMSwitch = Depends(dep_node)) -> None:
""" """
Stop an ATM switch node. Stop an ATM switch node.
This endpoint results in no action since ATM switch nodes are always on. This endpoint results in no action since ATM switch nodes are always on.
""" """
return Response(status_code=status.HTTP_204_NO_CONTENT) pass
@router.post("/{node_id}/suspend", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/suspend", status_code=status.HTTP_204_NO_CONTENT)
def suspend_atm_switch(node: ATMSwitch = Depends(dep_node)) -> Response: def suspend_atm_switch(node: ATMSwitch = Depends(dep_node)) -> None:
""" """
Suspend an ATM switch node. Suspend an ATM switch node.
This endpoint results in no action since ATM switch nodes are always on. This endpoint results in no action since ATM switch nodes are always on.
""" """
return Response(status_code=status.HTTP_204_NO_CONTENT) pass
@router.post( @router.post(
@ -171,7 +170,7 @@ async def create_nio(
@router.delete("/{node_id}/adapters/{adapter_number}/ports/{port_number}/nio", status_code=status.HTTP_204_NO_CONTENT) @router.delete("/{node_id}/adapters/{adapter_number}/ports/{port_number}/nio", status_code=status.HTTP_204_NO_CONTENT)
async def delete_nio(adapter_number: int, port_number: int, node: ATMSwitch = Depends(dep_node)) -> Response: async def delete_nio(adapter_number: int, port_number: int, node: ATMSwitch = Depends(dep_node)) -> None:
""" """
Remove a NIO (Network Input/Output) from the node. Remove a NIO (Network Input/Output) from the node.
The adapter number on the switch is always 0. The adapter number on the switch is always 0.
@ -179,7 +178,6 @@ async def delete_nio(adapter_number: int, port_number: int, node: ATMSwitch = De
nio = await node.remove_nio(port_number) nio = await node.remove_nio(port_number)
await nio.delete() await nio.delete()
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/start") @router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/start")
@ -209,14 +207,13 @@ async def stop_capture(
adapter_number: int = Path(..., ge=0, le=0), adapter_number: int = Path(..., ge=0, le=0),
port_number: int, port_number: int,
node: ATMSwitch = Depends(dep_node) node: ATMSwitch = Depends(dep_node)
) -> Response: ) -> None:
""" """
Stop a packet capture on the node. Stop a packet capture on the node.
The adapter number on the switch is always 0. The adapter number on the switch is always 0.
""" """
await node.stop_capture(port_number) await node.stop_capture(port_number)
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.get("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stream") @router.get("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stream")

View File

@ -99,43 +99,41 @@ def update_cloud(node_data: schemas.CloudUpdate, node: Cloud = Depends(dep_node)
@router.delete("/{node_id}", status_code=status.HTTP_204_NO_CONTENT) @router.delete("/{node_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_cloud(node: Cloud = Depends(dep_node)) -> Response: async def delete_cloud(node: Cloud = Depends(dep_node)) -> None:
""" """
Delete a cloud node. Delete a cloud node.
""" """
await Builtin.instance().delete_node(node.id) await Builtin.instance().delete_node(node.id)
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{node_id}/start", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/start", status_code=status.HTTP_204_NO_CONTENT)
async def start_cloud(node: Cloud = Depends(dep_node)) -> Response: async def start_cloud(node: Cloud = Depends(dep_node)) -> None:
""" """
Start a cloud node. Start a cloud node.
""" """
await node.start() await node.start()
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{node_id}/stop", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/stop", status_code=status.HTTP_204_NO_CONTENT)
async def stop_cloud(node: Cloud = Depends(dep_node)) -> Response: async def stop_cloud(node: Cloud = Depends(dep_node)) -> None:
""" """
Stop a cloud node. Stop a cloud node.
This endpoint results in no action since cloud nodes cannot be stopped. This endpoint results in no action since cloud nodes cannot be stopped.
""" """
return Response(status_code=status.HTTP_204_NO_CONTENT) pass
@router.post("/{node_id}/suspend", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/suspend", status_code=status.HTTP_204_NO_CONTENT)
async def suspend_cloud(node: Cloud = Depends(dep_node)) -> Response: async def suspend_cloud(node: Cloud = Depends(dep_node)) -> None:
""" """
Suspend a cloud node. Suspend a cloud node.
This endpoint results in no action since cloud nodes cannot be suspended. This endpoint results in no action since cloud nodes cannot be suspended.
""" """
return Response(status_code=status.HTTP_204_NO_CONTENT) pass
@router.post( @router.post(
@ -190,14 +188,13 @@ async def delete_cloud_nio(
adapter_number: int = Path(..., ge=0, le=0), adapter_number: int = Path(..., ge=0, le=0),
port_number: int, port_number: int,
node: Cloud = Depends(dep_node) node: Cloud = Depends(dep_node)
) -> Response: ) -> None:
""" """
Remove a NIO (Network Input/Output) from the node. Remove a NIO (Network Input/Output) from the node.
The adapter number on the cloud is always 0. The adapter number on the cloud is always 0.
""" """
await node.remove_nio(port_number) await node.remove_nio(port_number)
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/start") @router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/start")
@ -226,14 +223,13 @@ async def stop_cloud_capture(
adapter_number: int = Path(..., ge=0, le=0), adapter_number: int = Path(..., ge=0, le=0),
port_number: int, port_number: int,
node: Cloud = Depends(dep_node) node: Cloud = Depends(dep_node)
) -> Response: ) -> None:
""" """
Stop a packet capture on the node. Stop a packet capture on the node.
The adapter number on the cloud is always 0. The adapter number on the cloud is always 0.
""" """
await node.stop_capture(port_number) await node.stop_capture(port_number)
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.get("/{node_id}/adapters/{adapter_number}/ports/{port_number}/pcap") @router.get("/{node_id}/adapters/{adapter_number}/ports/{port_number}/pcap")

View File

@ -132,73 +132,66 @@ async def update_docker_node(node_data: schemas.DockerUpdate, node: DockerVM = D
@router.post("/{node_id}/start", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/start", status_code=status.HTTP_204_NO_CONTENT)
async def start_docker_node(node: DockerVM = Depends(dep_node)) -> Response: async def start_docker_node(node: DockerVM = Depends(dep_node)) -> None:
""" """
Start a Docker node. Start a Docker node.
""" """
await node.start() await node.start()
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{node_id}/stop", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/stop", status_code=status.HTTP_204_NO_CONTENT)
async def stop_docker_node(node: DockerVM = Depends(dep_node)) -> Response: async def stop_docker_node(node: DockerVM = Depends(dep_node)) -> None:
""" """
Stop a Docker node. Stop a Docker node.
""" """
await node.stop() await node.stop()
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{node_id}/suspend", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/suspend", status_code=status.HTTP_204_NO_CONTENT)
async def suspend_docker_node(node: DockerVM = Depends(dep_node)) -> Response: async def suspend_docker_node(node: DockerVM = Depends(dep_node)) -> None:
""" """
Suspend a Docker node. Suspend a Docker node.
""" """
await node.pause() await node.pause()
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{node_id}/reload", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/reload", status_code=status.HTTP_204_NO_CONTENT)
async def reload_docker_node(node: DockerVM = Depends(dep_node)) -> Response: async def reload_docker_node(node: DockerVM = Depends(dep_node)) -> None:
""" """
Reload a Docker node. Reload a Docker node.
""" """
await node.restart() await node.restart()
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{node_id}/pause", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/pause", status_code=status.HTTP_204_NO_CONTENT)
async def pause_docker_node(node: DockerVM = Depends(dep_node)) -> Response: async def pause_docker_node(node: DockerVM = Depends(dep_node)) -> None:
""" """
Pause a Docker node. Pause a Docker node.
""" """
await node.pause() await node.pause()
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{node_id}/unpause", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/unpause", status_code=status.HTTP_204_NO_CONTENT)
async def unpause_docker_node(node: DockerVM = Depends(dep_node)) -> Response: async def unpause_docker_node(node: DockerVM = Depends(dep_node)) -> None:
""" """
Unpause a Docker node. Unpause a Docker node.
""" """
await node.unpause() await node.unpause()
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.delete("/{node_id}", status_code=status.HTTP_204_NO_CONTENT) @router.delete("/{node_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_docker_node(node: DockerVM = Depends(dep_node)) -> Response: async def delete_docker_node(node: DockerVM = Depends(dep_node)) -> None:
""" """
Delete a Docker node. Delete a Docker node.
""" """
await node.delete() await node.delete()
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{node_id}/duplicate", response_model=schemas.Docker, status_code=status.HTTP_201_CREATED) @router.post("/{node_id}/duplicate", response_model=schemas.Docker, status_code=status.HTTP_201_CREATED)
@ -257,14 +250,13 @@ async def delete_docker_node_nio(
adapter_number: int, adapter_number: int,
port_number: int, port_number: int,
node: DockerVM = Depends(dep_node) node: DockerVM = Depends(dep_node)
) -> Response: ) -> None:
""" """
Delete a NIO (Network Input/Output) from the node. Delete a NIO (Network Input/Output) from the node.
The port number on the Docker node is always 0. The port number on the Docker node is always 0.
""" """
await node.adapter_remove_nio_binding(adapter_number) await node.adapter_remove_nio_binding(adapter_number)
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/start") @router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/start")
@ -292,14 +284,13 @@ async def stop_docker_node_capture(
adapter_number: int, adapter_number: int,
port_number: int, port_number: int,
node: DockerVM = Depends(dep_node) node: DockerVM = Depends(dep_node)
) -> Response: ) -> None:
""" """
Stop a packet capture on the node. Stop a packet capture on the node.
The port number on the Docker node is always 0. The port number on the Docker node is always 0.
""" """
await node.stop_capture(adapter_number) await node.stop_capture(adapter_number)
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.get("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stream") @router.get("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stream")
@ -328,7 +319,6 @@ async def console_ws(websocket: WebSocket, node: DockerVM = Depends(dep_node)) -
@router.post("/{node_id}/console/reset", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/console/reset", status_code=status.HTTP_204_NO_CONTENT)
async def reset_console(node: DockerVM = Depends(dep_node)) -> Response: async def reset_console(node: DockerVM = Depends(dep_node)) -> None:
await node.reset_console() await node.reset_console()
return Response(status_code=status.HTTP_204_NO_CONTENT)

View File

@ -19,7 +19,6 @@ API routes for Dynamips nodes.
""" """
import os import os
import sys
from fastapi import APIRouter, WebSocket, Depends, Response, status from fastapi import APIRouter, WebSocket, Depends, Response, status
from fastapi.encoders import jsonable_encoder from fastapi.encoders import jsonable_encoder
@ -29,7 +28,6 @@ from uuid import UUID
from gns3server.compute.dynamips import Dynamips from gns3server.compute.dynamips import Dynamips
from gns3server.compute.dynamips.nodes.router import Router from gns3server.compute.dynamips.nodes.router import Router
from gns3server.compute.dynamips.dynamips_error import DynamipsError
from gns3server import schemas from gns3server import schemas
responses = {404: {"model": schemas.ErrorMessage, "description": "Could not find project or Dynamips node"}} responses = {404: {"model": schemas.ErrorMessage, "description": "Could not find project or Dynamips node"}}
@ -105,17 +103,16 @@ async def update_router(node_data: schemas.DynamipsUpdate, node: Router = Depend
@router.delete("/{node_id}", status_code=status.HTTP_204_NO_CONTENT) @router.delete("/{node_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_router(node: Router = Depends(dep_node)) -> Response: async def delete_router(node: Router = Depends(dep_node)) -> None:
""" """
Delete a Dynamips router. Delete a Dynamips router.
""" """
await Dynamips.instance().delete_node(node.id) await Dynamips.instance().delete_node(node.id)
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{node_id}/start", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/start", status_code=status.HTTP_204_NO_CONTENT)
async def start_router(node: Router = Depends(dep_node)) -> Response: async def start_router(node: Router = Depends(dep_node)) -> None:
""" """
Start a Dynamips router. Start a Dynamips router.
""" """
@ -125,44 +122,39 @@ async def start_router(node: Router = Depends(dep_node)) -> Response:
except GeneratorExit: except GeneratorExit:
pass pass
await node.start() await node.start()
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{node_id}/stop", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/stop", status_code=status.HTTP_204_NO_CONTENT)
async def stop_router(node: Router = Depends(dep_node)) -> Response: async def stop_router(node: Router = Depends(dep_node)) -> None:
""" """
Stop a Dynamips router. Stop a Dynamips router.
""" """
await node.stop() await node.stop()
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{node_id}/suspend", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/suspend", status_code=status.HTTP_204_NO_CONTENT)
async def suspend_router(node: Router = Depends(dep_node)) -> Response: async def suspend_router(node: Router = Depends(dep_node)) -> None:
await node.suspend() await node.suspend()
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{node_id}/resume", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/resume", status_code=status.HTTP_204_NO_CONTENT)
async def resume_router(node: Router = Depends(dep_node)) -> Response: async def resume_router(node: Router = Depends(dep_node)) -> None:
""" """
Resume a suspended Dynamips router. Resume a suspended Dynamips router.
""" """
await node.resume() await node.resume()
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{node_id}/reload", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/reload", status_code=status.HTTP_204_NO_CONTENT)
async def reload_router(node: Router = Depends(dep_node)) -> Response: async def reload_router(node: Router = Depends(dep_node)) -> None:
""" """
Reload a suspended Dynamips router. Reload a suspended Dynamips router.
""" """
await node.reload() await node.reload()
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post( @router.post(
@ -208,14 +200,13 @@ async def update_nio(
@router.delete("/{node_id}/adapters/{adapter_number}/ports/{port_number}/nio", status_code=status.HTTP_204_NO_CONTENT) @router.delete("/{node_id}/adapters/{adapter_number}/ports/{port_number}/nio", status_code=status.HTTP_204_NO_CONTENT)
async def delete_nio(adapter_number: int, port_number: int, node: Router = Depends(dep_node)) -> Response: async def delete_nio(adapter_number: int, port_number: int, node: Router = Depends(dep_node)) -> None:
""" """
Delete a NIO (Network Input/Output) from the node. Delete a NIO (Network Input/Output) from the node.
""" """
nio = await node.slot_remove_nio_binding(adapter_number, port_number) nio = await node.slot_remove_nio_binding(adapter_number, port_number)
await nio.delete() await nio.delete()
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/start") @router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/start")
@ -237,13 +228,12 @@ async def start_capture(
@router.post( @router.post(
"/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stop", status_code=status.HTTP_204_NO_CONTENT "/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stop", status_code=status.HTTP_204_NO_CONTENT
) )
async def stop_capture(adapter_number: int, port_number: int, node: Router = Depends(dep_node)) -> Response: async def stop_capture(adapter_number: int, port_number: int, node: Router = Depends(dep_node)) -> None:
""" """
Stop a packet capture on the node. Stop a packet capture on the node.
""" """
await node.stop_capture(adapter_number, port_number) await node.stop_capture(adapter_number, port_number)
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.get("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stream") @router.get("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stream")
@ -301,7 +291,6 @@ async def console_ws(websocket: WebSocket, node: Router = Depends(dep_node)) ->
@router.post("/{node_id}/console/reset", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/console/reset", status_code=status.HTTP_204_NO_CONTENT)
async def reset_console(node: Router = Depends(dep_node)) -> Response: async def reset_console(node: Router = Depends(dep_node)) -> None:
await node.reset_console() await node.reset_console()
return Response(status_code=status.HTTP_204_NO_CONTENT)

View File

@ -108,43 +108,42 @@ async def update_ethernet_hub(
@router.delete("/{node_id}", status_code=status.HTTP_204_NO_CONTENT) @router.delete("/{node_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_ethernet_hub(node: EthernetHub = Depends(dep_node)) -> Response: async def delete_ethernet_hub(node: EthernetHub = Depends(dep_node)) -> None:
""" """
Delete an Ethernet hub. Delete an Ethernet hub.
""" """
await Dynamips.instance().delete_node(node.id) await Dynamips.instance().delete_node(node.id)
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{node_id}/start", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/start", status_code=status.HTTP_204_NO_CONTENT)
def start_ethernet_hub(node: EthernetHub = Depends(dep_node)) -> Response: def start_ethernet_hub(node: EthernetHub = Depends(dep_node)) -> None:
""" """
Start an Ethernet hub. Start an Ethernet hub.
This endpoint results in no action since Ethernet hub nodes are always on. This endpoint results in no action since Ethernet hub nodes are always on.
""" """
return Response(status_code=status.HTTP_204_NO_CONTENT) pass
@router.post("/{node_id}/stop", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/stop", status_code=status.HTTP_204_NO_CONTENT)
def stop_ethernet_hub(node: EthernetHub = Depends(dep_node)) -> Response: def stop_ethernet_hub(node: EthernetHub = Depends(dep_node)) -> None:
""" """
Stop an Ethernet hub. Stop an Ethernet hub.
This endpoint results in no action since Ethernet hub nodes are always on. This endpoint results in no action since Ethernet hub nodes are always on.
""" """
return Response(status_code=status.HTTP_204_NO_CONTENT) pass
@router.post("/{node_id}/suspend", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/suspend", status_code=status.HTTP_204_NO_CONTENT)
def suspend_ethernet_hub(node: EthernetHub = Depends(dep_node)) -> Response: def suspend_ethernet_hub(node: EthernetHub = Depends(dep_node)) -> None:
""" """
Suspend an Ethernet hub. Suspend an Ethernet hub.
This endpoint results in no action since Ethernet hub nodes are always on. This endpoint results in no action since Ethernet hub nodes are always on.
""" """
return Response(status_code=status.HTTP_204_NO_CONTENT) pass
@router.post( @router.post(
@ -175,7 +174,7 @@ async def delete_nio(
adapter_number: int = Path(..., ge=0, le=0), adapter_number: int = Path(..., ge=0, le=0),
port_number: int, port_number: int,
node: EthernetHub = Depends(dep_node) node: EthernetHub = Depends(dep_node)
) -> Response: ) -> None:
""" """
Delete a NIO (Network Input/Output) from the node. Delete a NIO (Network Input/Output) from the node.
The adapter number on the hub is always 0. The adapter number on the hub is always 0.
@ -183,7 +182,6 @@ async def delete_nio(
nio = await node.remove_nio(port_number) nio = await node.remove_nio(port_number)
await nio.delete() await nio.delete()
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/start") @router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/start")
@ -212,14 +210,13 @@ async def stop_capture(
adapter_number: int = Path(..., ge=0, le=0), adapter_number: int = Path(..., ge=0, le=0),
port_number: int, port_number: int,
node: EthernetHub = Depends(dep_node) node: EthernetHub = Depends(dep_node)
) -> Response: ) -> None:
""" """
Stop a packet capture on the node. Stop a packet capture on the node.
The adapter number on the hub is always 0. The adapter number on the hub is always 0.
""" """
await node.stop_capture(port_number) await node.stop_capture(port_number)
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.get("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stream") @router.get("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stream")

View File

@ -112,43 +112,42 @@ async def update_ethernet_switch(
@router.delete("/{node_id}", status_code=status.HTTP_204_NO_CONTENT) @router.delete("/{node_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_ethernet_switch(node: EthernetSwitch = Depends(dep_node)) -> Response: async def delete_ethernet_switch(node: EthernetSwitch = Depends(dep_node)) -> None:
""" """
Delete an Ethernet switch. Delete an Ethernet switch.
""" """
await Dynamips.instance().delete_node(node.id) await Dynamips.instance().delete_node(node.id)
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{node_id}/start", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/start", status_code=status.HTTP_204_NO_CONTENT)
def start_ethernet_switch(node: EthernetSwitch = Depends(dep_node)) -> Response: def start_ethernet_switch(node: EthernetSwitch = Depends(dep_node)) -> None:
""" """
Start an Ethernet switch. Start an Ethernet switch.
This endpoint results in no action since Ethernet switch nodes are always on. This endpoint results in no action since Ethernet switch nodes are always on.
""" """
return Response(status_code=status.HTTP_204_NO_CONTENT) pass
@router.post("/{node_id}/stop", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/stop", status_code=status.HTTP_204_NO_CONTENT)
def stop_ethernet_switch(node: EthernetSwitch = Depends(dep_node)) -> Response: def stop_ethernet_switch(node: EthernetSwitch = Depends(dep_node)) -> None:
""" """
Stop an Ethernet switch. Stop an Ethernet switch.
This endpoint results in no action since Ethernet switch nodes are always on. This endpoint results in no action since Ethernet switch nodes are always on.
""" """
return Response(status_code=status.HTTP_204_NO_CONTENT) pass
@router.post("/{node_id}/suspend", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/suspend", status_code=status.HTTP_204_NO_CONTENT)
def suspend_ethernet_switch(node: EthernetSwitch = Depends(dep_node)) -> Response: def suspend_ethernet_switch(node: EthernetSwitch = Depends(dep_node)) -> None:
""" """
Suspend an Ethernet switch. Suspend an Ethernet switch.
This endpoint results in no action since Ethernet switch nodes are always on. This endpoint results in no action since Ethernet switch nodes are always on.
""" """
return Response(status_code=status.HTTP_204_NO_CONTENT) pass
@router.post( @router.post(
@ -175,7 +174,7 @@ async def delete_nio(
adapter_number: int = Path(..., ge=0, le=0), adapter_number: int = Path(..., ge=0, le=0),
port_number: int, port_number: int,
node: EthernetSwitch = Depends(dep_node) node: EthernetSwitch = Depends(dep_node)
) -> Response: ) -> None:
""" """
Delete a NIO (Network Input/Output) from the node. Delete a NIO (Network Input/Output) from the node.
The adapter number on the switch is always 0. The adapter number on the switch is always 0.
@ -183,7 +182,6 @@ async def delete_nio(
nio = await node.remove_nio(port_number) nio = await node.remove_nio(port_number)
await nio.delete() await nio.delete()
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/start") @router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/start")
@ -212,14 +210,13 @@ async def stop_capture(
adapter_number: int = Path(..., ge=0, le=0), adapter_number: int = Path(..., ge=0, le=0),
port_number: int, port_number: int,
node: EthernetSwitch = Depends(dep_node) node: EthernetSwitch = Depends(dep_node)
) -> Response: ) -> None:
""" """
Stop a packet capture on the node. Stop a packet capture on the node.
The adapter number on the switch is always 0. The adapter number on the switch is always 0.
""" """
await node.stop_capture(port_number) await node.stop_capture(port_number)
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.get("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stream") @router.get("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stream")

View File

@ -112,43 +112,42 @@ async def update_frame_relay_switch(
@router.delete("/{node_id}", status_code=status.HTTP_204_NO_CONTENT) @router.delete("/{node_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_frame_relay_switch(node: FrameRelaySwitch = Depends(dep_node)) -> Response: async def delete_frame_relay_switch(node: FrameRelaySwitch = Depends(dep_node)) -> None:
""" """
Delete a Frame Relay switch node. Delete a Frame Relay switch node.
""" """
await Dynamips.instance().delete_node(node.id) await Dynamips.instance().delete_node(node.id)
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{node_id}/start", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/start", status_code=status.HTTP_204_NO_CONTENT)
def start_frame_relay_switch(node: FrameRelaySwitch = Depends(dep_node)) -> Response: def start_frame_relay_switch(node: FrameRelaySwitch = Depends(dep_node)) -> None:
""" """
Start a Frame Relay switch node. Start a Frame Relay switch node.
This endpoint results in no action since Frame Relay switch nodes are always on. This endpoint results in no action since Frame Relay switch nodes are always on.
""" """
return Response(status_code=status.HTTP_204_NO_CONTENT) pass
@router.post("/{node_id}/stop", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/stop", status_code=status.HTTP_204_NO_CONTENT)
def stop_frame_relay_switch(node: FrameRelaySwitch = Depends(dep_node)) -> Response: def stop_frame_relay_switch(node: FrameRelaySwitch = Depends(dep_node)) -> None:
""" """
Stop a Frame Relay switch node. Stop a Frame Relay switch node.
This endpoint results in no action since Frame Relay switch nodes are always on. This endpoint results in no action since Frame Relay switch nodes are always on.
""" """
return Response(status_code=status.HTTP_204_NO_CONTENT) pass
@router.post("/{node_id}/suspend", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/suspend", status_code=status.HTTP_204_NO_CONTENT)
def suspend_frame_relay_switch(node: FrameRelaySwitch = Depends(dep_node)) -> Response: def suspend_frame_relay_switch(node: FrameRelaySwitch = Depends(dep_node)) -> None:
""" """
Suspend a Frame Relay switch node. Suspend a Frame Relay switch node.
This endpoint results in no action since Frame Relay switch nodes are always on. This endpoint results in no action since Frame Relay switch nodes are always on.
""" """
return Response(status_code=status.HTTP_204_NO_CONTENT) pass
@router.post( @router.post(
@ -179,7 +178,7 @@ async def delete_nio(
adapter_number: int = Path(..., ge=0, le=0), adapter_number: int = Path(..., ge=0, le=0),
port_number: int, port_number: int,
node: FrameRelaySwitch = Depends(dep_node) node: FrameRelaySwitch = Depends(dep_node)
) -> Response: ) -> None:
""" """
Remove a NIO (Network Input/Output) from the node. Remove a NIO (Network Input/Output) from the node.
The adapter number on the switch is always 0. The adapter number on the switch is always 0.
@ -187,7 +186,6 @@ async def delete_nio(
nio = await node.remove_nio(port_number) nio = await node.remove_nio(port_number)
await nio.delete() await nio.delete()
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/start") @router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/start")
@ -216,14 +214,13 @@ async def stop_capture(
adapter_number: int = Path(..., ge=0, le=0), adapter_number: int = Path(..., ge=0, le=0),
port_number: int, port_number: int,
node: FrameRelaySwitch = Depends(dep_node) node: FrameRelaySwitch = Depends(dep_node)
) -> Response: ) -> None:
""" """
Stop a packet capture on the node. Stop a packet capture on the node.
The adapter number on the switch is always 0. The adapter number on the switch is always 0.
""" """
await node.stop_capture(port_number) await node.stop_capture(port_number)
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.get("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stream") @router.get("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stream")

View File

@ -54,14 +54,13 @@ async def get_dynamips_images() -> List[str]:
@router.post("/dynamips/images/{filename:path}", status_code=status.HTTP_204_NO_CONTENT) @router.post("/dynamips/images/{filename:path}", status_code=status.HTTP_204_NO_CONTENT)
async def upload_dynamips_image(filename: str, request: Request) -> Response: async def upload_dynamips_image(filename: str, request: Request) -> None:
""" """
Upload a Dynamips IOS image. Upload a Dynamips IOS image.
""" """
dynamips_manager = Dynamips.instance() dynamips_manager = Dynamips.instance()
await dynamips_manager.write_image(urllib.parse.unquote(filename), request.stream()) await dynamips_manager.write_image(urllib.parse.unquote(filename), request.stream())
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.get("/dynamips/images/{filename:path}") @router.get("/dynamips/images/{filename:path}")
@ -96,14 +95,13 @@ async def get_iou_images() -> List[str]:
@router.post("/iou/images/{filename:path}", status_code=status.HTTP_204_NO_CONTENT) @router.post("/iou/images/{filename:path}", status_code=status.HTTP_204_NO_CONTENT)
async def upload_iou_image(filename: str, request: Request) -> Response: async def upload_iou_image(filename: str, request: Request) -> None:
""" """
Upload an IOU image. Upload an IOU image.
""" """
iou_manager = IOU.instance() iou_manager = IOU.instance()
await iou_manager.write_image(urllib.parse.unquote(filename), request.stream()) await iou_manager.write_image(urllib.parse.unquote(filename), request.stream())
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.get("/iou/images/{filename:path}") @router.get("/iou/images/{filename:path}")
@ -134,11 +132,10 @@ async def get_qemu_images() -> List[str]:
@router.post("/qemu/images/{filename:path}", status_code=status.HTTP_204_NO_CONTENT) @router.post("/qemu/images/{filename:path}", status_code=status.HTTP_204_NO_CONTENT)
async def upload_qemu_image(filename: str, request: Request) -> Response: async def upload_qemu_image(filename: str, request: Request) -> None:
qemu_manager = Qemu.instance() qemu_manager = Qemu.instance()
await qemu_manager.write_image(urllib.parse.unquote(filename), request.stream()) await qemu_manager.write_image(urllib.parse.unquote(filename), request.stream())
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.get("/qemu/images/{filename:path}") @router.get("/qemu/images/{filename:path}")

View File

@ -20,7 +20,7 @@ API routes for IOU nodes.
import os import os
from fastapi import APIRouter, WebSocket, Depends, Body, Response, status from fastapi import APIRouter, WebSocket, Depends, Body, status
from fastapi.encoders import jsonable_encoder from fastapi.encoders import jsonable_encoder
from fastapi.responses import StreamingResponse from fastapi.responses import StreamingResponse
from typing import Union from typing import Union
@ -113,13 +113,12 @@ async def update_iou_node(node_data: schemas.IOUUpdate, node: IOUVM = Depends(de
@router.delete("/{node_id}", status_code=status.HTTP_204_NO_CONTENT) @router.delete("/{node_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_iou_node(node: IOUVM = Depends(dep_node)) -> Response: async def delete_iou_node(node: IOUVM = Depends(dep_node)) -> None:
""" """
Delete an IOU node. Delete an IOU node.
""" """
await IOU.instance().delete_node(node.id) await IOU.instance().delete_node(node.id)
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{node_id}/duplicate", response_model=schemas.IOU, status_code=status.HTTP_201_CREATED) @router.post("/{node_id}/duplicate", response_model=schemas.IOU, status_code=status.HTTP_201_CREATED)
@ -136,7 +135,7 @@ async def duplicate_iou_node(
@router.post("/{node_id}/start", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/start", status_code=status.HTTP_204_NO_CONTENT)
async def start_iou_node(start_data: schemas.IOUStart, node: IOUVM = Depends(dep_node)) -> Response: async def start_iou_node(start_data: schemas.IOUStart, node: IOUVM = Depends(dep_node)) -> None:
""" """
Start an IOU node. Start an IOU node.
""" """
@ -147,37 +146,34 @@ async def start_iou_node(start_data: schemas.IOUStart, node: IOUVM = Depends(dep
setattr(node, name, value) setattr(node, name, value)
await node.start() await node.start()
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{node_id}/stop", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/stop", status_code=status.HTTP_204_NO_CONTENT)
async def stop_iou_node(node: IOUVM = Depends(dep_node)) -> Response: async def stop_iou_node(node: IOUVM = Depends(dep_node)) -> None:
""" """
Stop an IOU node. Stop an IOU node.
""" """
await node.stop() await node.stop()
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{node_id}/stop", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/stop", status_code=status.HTTP_204_NO_CONTENT)
def suspend_iou_node(node: IOUVM = Depends(dep_node)) -> Response: def suspend_iou_node(node: IOUVM = Depends(dep_node)) -> None:
""" """
Suspend an IOU node. Suspend an IOU node.
Does nothing since IOU doesn't support being suspended. Does nothing since IOU doesn't support being suspended.
""" """
return Response(status_code=status.HTTP_204_NO_CONTENT) pass
@router.post("/{node_id}/reload", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/reload", status_code=status.HTTP_204_NO_CONTENT)
async def reload_iou_node(node: IOUVM = Depends(dep_node)) -> Response: async def reload_iou_node(node: IOUVM = Depends(dep_node)) -> None:
""" """
Reload an IOU node. Reload an IOU node.
""" """
await node.reload() await node.reload()
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post( @router.post(
@ -223,13 +219,12 @@ async def update_iou_node_nio(
@router.delete("/{node_id}/adapters/{adapter_number}/ports/{port_number}/nio", status_code=status.HTTP_204_NO_CONTENT) @router.delete("/{node_id}/adapters/{adapter_number}/ports/{port_number}/nio", status_code=status.HTTP_204_NO_CONTENT)
async def delete_iou_node_nio(adapter_number: int, port_number: int, node: IOUVM = Depends(dep_node)) -> Response: async def delete_iou_node_nio(adapter_number: int, port_number: int, node: IOUVM = Depends(dep_node)) -> None:
""" """
Delete a NIO (Network Input/Output) from the node. Delete a NIO (Network Input/Output) from the node.
""" """
await node.adapter_remove_nio_binding(adapter_number, port_number) await node.adapter_remove_nio_binding(adapter_number, port_number)
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/start") @router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/start")
@ -251,13 +246,12 @@ async def start_iou_node_capture(
@router.post( @router.post(
"/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stop", status_code=status.HTTP_204_NO_CONTENT "/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stop", status_code=status.HTTP_204_NO_CONTENT
) )
async def stop_iou_node_capture(adapter_number: int, port_number: int, node: IOUVM = Depends(dep_node)) -> Response: async def stop_iou_node_capture(adapter_number: int, port_number: int, node: IOUVM = Depends(dep_node)) -> None:
""" """
Stop a packet capture on the node. Stop a packet capture on the node.
""" """
await node.stop_capture(adapter_number, port_number) await node.stop_capture(adapter_number, port_number)
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.get("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stream") @router.get("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stream")
@ -285,7 +279,6 @@ async def console_ws(websocket: WebSocket, node: IOUVM = Depends(dep_node)) -> N
@router.post("/{node_id}/console/reset", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/console/reset", status_code=status.HTTP_204_NO_CONTENT)
async def reset_console(node: IOUVM = Depends(dep_node)) -> Response: async def reset_console(node: IOUVM = Depends(dep_node)) -> None:
await node.reset_console() await node.reset_console()
return Response(status_code=status.HTTP_204_NO_CONTENT)

View File

@ -94,43 +94,41 @@ def update_nat_node(node_data: schemas.NATUpdate, node: Nat = Depends(dep_node))
@router.delete("/{node_id}", status_code=status.HTTP_204_NO_CONTENT) @router.delete("/{node_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_nat_node(node: Nat = Depends(dep_node)) -> Response: async def delete_nat_node(node: Nat = Depends(dep_node)) -> None:
""" """
Delete a cloud node. Delete a cloud node.
""" """
await Builtin.instance().delete_node(node.id) await Builtin.instance().delete_node(node.id)
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{node_id}/start", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/start", status_code=status.HTTP_204_NO_CONTENT)
async def start_nat_node(node: Nat = Depends(dep_node)) -> Response: async def start_nat_node(node: Nat = Depends(dep_node)) -> None:
""" """
Start a NAT node. Start a NAT node.
""" """
await node.start() await node.start()
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{node_id}/stop", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/stop", status_code=status.HTTP_204_NO_CONTENT)
async def stop_nat_node(node: Nat = Depends(dep_node)) -> Response: async def stop_nat_node(node: Nat = Depends(dep_node)) -> None:
""" """
Stop a NAT node. Stop a NAT node.
This endpoint results in no action since cloud nodes cannot be stopped. This endpoint results in no action since cloud nodes cannot be stopped.
""" """
return Response(status_code=status.HTTP_204_NO_CONTENT) pass
@router.post("/{node_id}/suspend", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/suspend", status_code=status.HTTP_204_NO_CONTENT)
async def suspend_nat_node(node: Nat = Depends(dep_node)) -> Response: async def suspend_nat_node(node: Nat = Depends(dep_node)) -> None:
""" """
Suspend a NAT node. Suspend a NAT node.
This endpoint results in no action since NAT nodes cannot be suspended. This endpoint results in no action since NAT nodes cannot be suspended.
""" """
return Response(status_code=status.HTTP_204_NO_CONTENT) pass
@router.post( @router.post(
@ -185,14 +183,13 @@ async def delete_nat_node_nio(
adapter_number: int = Path(..., ge=0, le=0), adapter_number: int = Path(..., ge=0, le=0),
port_number: int, port_number: int,
node: Nat = Depends(dep_node) node: Nat = Depends(dep_node)
) -> Response: ) -> None:
""" """
Remove a NIO (Network Input/Output) from the node. Remove a NIO (Network Input/Output) from the node.
The adapter number on the cloud is always 0. The adapter number on the cloud is always 0.
""" """
await node.remove_nio(port_number) await node.remove_nio(port_number)
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/start") @router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/start")
@ -221,14 +218,13 @@ async def stop_nat_node_capture(
adapter_number: int = Path(..., ge=0, le=0), adapter_number: int = Path(..., ge=0, le=0),
port_number: int, port_number: int,
node: Nat = Depends(dep_node) node: Nat = Depends(dep_node)
) -> Response: ) -> None:
""" """
Stop a packet capture on the node. Stop a packet capture on the node.
The adapter number on the cloud is always 0. The adapter number on the cloud is always 0.
""" """
await node.stop_capture(port_number) await node.stop_capture(port_number)
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.get("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stream") @router.get("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stream")

View File

@ -103,7 +103,7 @@ def get_compute_project(project: Project = Depends(dep_project)) -> schemas.Proj
@router.post("/projects/{project_id}/close", status_code=status.HTTP_204_NO_CONTENT) @router.post("/projects/{project_id}/close", status_code=status.HTTP_204_NO_CONTENT)
async def close_compute_project(project: Project = Depends(dep_project)) -> Response: async def close_compute_project(project: Project = Depends(dep_project)) -> None:
""" """
Close a project on the compute. Close a project on the compute.
""" """
@ -118,18 +118,16 @@ async def close_compute_project(project: Project = Depends(dep_project)) -> Resp
pass pass
else: else:
log.warning("Skip project closing, another client is listening for project notifications") log.warning("Skip project closing, another client is listening for project notifications")
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.delete("/projects/{project_id}", status_code=status.HTTP_204_NO_CONTENT) @router.delete("/projects/{project_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_compute_project(project: Project = Depends(dep_project)) -> Response: async def delete_compute_project(project: Project = Depends(dep_project)) -> None:
""" """
Delete project from the compute. Delete project from the compute.
""" """
await project.delete() await project.delete()
ProjectManager.instance().remove_project(project.id) ProjectManager.instance().remove_project(project.id)
return Response(status_code=status.HTTP_204_NO_CONTENT)
# @Route.get( # @Route.get(
# r"/projects/{project_id}/notifications", # r"/projects/{project_id}/notifications",
@ -219,7 +217,7 @@ async def write_compute_project_file(
file_path: str, file_path: str,
request: Request, request: Request,
project: Project = Depends(dep_project) project: Project = Depends(dep_project)
) -> Response: ) -> None:
file_path = urllib.parse.unquote(file_path) file_path = urllib.parse.unquote(file_path)
path = os.path.normpath(file_path) path = os.path.normpath(file_path)
@ -243,5 +241,3 @@ async def write_compute_project_file(
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND) raise HTTPException(status_code=status.HTTP_404_NOT_FOUND)
except PermissionError: except PermissionError:
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN) raise HTTPException(status_code=status.HTTP_403_FORBIDDEN)
return Response(status_code=status.HTTP_204_NO_CONTENT)

View File

@ -104,13 +104,12 @@ async def update_qemu_node(node_data: schemas.QemuUpdate, node: QemuVM = Depends
@router.delete("/{node_id}", status_code=status.HTTP_204_NO_CONTENT) @router.delete("/{node_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_qemu_node(node: QemuVM = Depends(dep_node)) -> Response: async def delete_qemu_node(node: QemuVM = Depends(dep_node)) -> None:
""" """
Delete a Qemu node. Delete a Qemu node.
""" """
await Qemu.instance().delete_node(node.id) await Qemu.instance().delete_node(node.id)
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{node_id}/duplicate", response_model=schemas.Qemu, status_code=status.HTTP_201_CREATED) @router.post("/{node_id}/duplicate", response_model=schemas.Qemu, status_code=status.HTTP_201_CREATED)
@ -134,14 +133,13 @@ async def create_qemu_disk_image(
disk_name: str, disk_name: str,
disk_data: schemas.QemuDiskImageCreate, disk_data: schemas.QemuDiskImageCreate,
node: QemuVM = Depends(dep_node) node: QemuVM = Depends(dep_node)
) -> Response: ) -> None:
""" """
Create a Qemu disk image. Create a Qemu disk image.
""" """
options = jsonable_encoder(disk_data, exclude_unset=True) options = jsonable_encoder(disk_data, exclude_unset=True)
await node.create_disk_image(disk_name, options) await node.create_disk_image(disk_name, options)
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.put( @router.put(
@ -152,14 +150,13 @@ async def update_qemu_disk_image(
disk_name: str, disk_name: str,
disk_data: schemas.QemuDiskImageUpdate, disk_data: schemas.QemuDiskImageUpdate,
node: QemuVM = Depends(dep_node) node: QemuVM = Depends(dep_node)
) -> Response: ) -> None:
""" """
Update a Qemu disk image. Update a Qemu disk image.
""" """
if disk_data.extend: if disk_data.extend:
await node.resize_disk_image(disk_name, disk_data.extend) await node.resize_disk_image(disk_name, disk_data.extend)
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.delete( @router.delete(
@ -169,63 +166,57 @@ async def update_qemu_disk_image(
async def delete_qemu_disk_image( async def delete_qemu_disk_image(
disk_name: str, disk_name: str,
node: QemuVM = Depends(dep_node) node: QemuVM = Depends(dep_node)
) -> Response: ) -> None:
""" """
Delete a Qemu disk image. Delete a Qemu disk image.
""" """
node.delete_disk_image(disk_name) node.delete_disk_image(disk_name)
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{node_id}/start", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/start", status_code=status.HTTP_204_NO_CONTENT)
async def start_qemu_node(node: QemuVM = Depends(dep_node)) -> Response: async def start_qemu_node(node: QemuVM = Depends(dep_node)) -> None:
""" """
Start a Qemu node. Start a Qemu node.
""" """
await node.start() await node.start()
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{node_id}/stop", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/stop", status_code=status.HTTP_204_NO_CONTENT)
async def stop_qemu_node(node: QemuVM = Depends(dep_node)) -> Response: async def stop_qemu_node(node: QemuVM = Depends(dep_node)) -> None:
""" """
Stop a Qemu node. Stop a Qemu node.
""" """
await node.stop() await node.stop()
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{node_id}/reload", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/reload", status_code=status.HTTP_204_NO_CONTENT)
async def reload_qemu_node(node: QemuVM = Depends(dep_node)) -> Response: async def reload_qemu_node(node: QemuVM = Depends(dep_node)) -> None:
""" """
Reload a Qemu node. Reload a Qemu node.
""" """
await node.reload() await node.reload()
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{node_id}/suspend", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/suspend", status_code=status.HTTP_204_NO_CONTENT)
async def suspend_qemu_node(node: QemuVM = Depends(dep_node)) -> Response: async def suspend_qemu_node(node: QemuVM = Depends(dep_node)) -> None:
""" """
Suspend a Qemu node. Suspend a Qemu node.
""" """
await node.suspend() await node.suspend()
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{node_id}/resume", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/resume", status_code=status.HTTP_204_NO_CONTENT)
async def resume_qemu_node(node: QemuVM = Depends(dep_node)) -> Response: async def resume_qemu_node(node: QemuVM = Depends(dep_node)) -> None:
""" """
Resume a Qemu node. Resume a Qemu node.
""" """
await node.resume() await node.resume()
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post( @router.post(
@ -281,14 +272,13 @@ async def delete_qemu_node_nio(
adapter_number: int, adapter_number: int,
port_number: int = Path(..., ge=0, le=0), port_number: int = Path(..., ge=0, le=0),
node: QemuVM = Depends(dep_node) node: QemuVM = Depends(dep_node)
) -> Response: ) -> None:
""" """
Delete a NIO (Network Input/Output) from the node. Delete a NIO (Network Input/Output) from the node.
The port number on the Qemu node is always 0. The port number on the Qemu node is always 0.
""" """
await node.adapter_remove_nio_binding(adapter_number) await node.adapter_remove_nio_binding(adapter_number)
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/start") @router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/start")
@ -316,14 +306,13 @@ async def stop_qemu_node_capture(
adapter_number: int, adapter_number: int,
port_number: int = Path(..., ge=0, le=0), port_number: int = Path(..., ge=0, le=0),
node: QemuVM = Depends(dep_node) node: QemuVM = Depends(dep_node)
) -> Response: ) -> None:
""" """
Stop a packet capture on the node. Stop a packet capture on the node.
The port number on the Qemu node is always 0. The port number on the Qemu node is always 0.
""" """
await node.stop_capture(adapter_number) await node.stop_capture(adapter_number)
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.get("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stream") @router.get("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stream")
@ -351,7 +340,6 @@ async def console_ws(websocket: WebSocket, node: QemuVM = Depends(dep_node)) ->
@router.post("/{node_id}/console/reset", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/console/reset", status_code=status.HTTP_204_NO_CONTENT)
async def reset_console(node: QemuVM = Depends(dep_node)) -> Response: async def reset_console(node: QemuVM = Depends(dep_node)) -> None:
await node.reset_console() await node.reset_console()
return Response(status_code=status.HTTP_204_NO_CONTENT)

View File

@ -137,63 +137,57 @@ async def update_virtualbox_node(
@router.delete("/{node_id}", status_code=status.HTTP_204_NO_CONTENT) @router.delete("/{node_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_virtualbox_node(node: VirtualBoxVM = Depends(dep_node)) -> Response: async def delete_virtualbox_node(node: VirtualBoxVM = Depends(dep_node)) -> None:
""" """
Delete a VirtualBox node. Delete a VirtualBox node.
""" """
await VirtualBox.instance().delete_node(node.id) await VirtualBox.instance().delete_node(node.id)
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{node_id}/start", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/start", status_code=status.HTTP_204_NO_CONTENT)
async def start_virtualbox_node(node: VirtualBoxVM = Depends(dep_node)) -> Response: async def start_virtualbox_node(node: VirtualBoxVM = Depends(dep_node)) -> None:
""" """
Start a VirtualBox node. Start a VirtualBox node.
""" """
await node.start() await node.start()
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{node_id}/stop", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/stop", status_code=status.HTTP_204_NO_CONTENT)
async def stop_virtualbox_node(node: VirtualBoxVM = Depends(dep_node)) -> Response: async def stop_virtualbox_node(node: VirtualBoxVM = Depends(dep_node)) -> None:
""" """
Stop a VirtualBox node. Stop a VirtualBox node.
""" """
await node.stop() await node.stop()
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{node_id}/suspend", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/suspend", status_code=status.HTTP_204_NO_CONTENT)
async def suspend_virtualbox_node(node: VirtualBoxVM = Depends(dep_node)) -> Response: async def suspend_virtualbox_node(node: VirtualBoxVM = Depends(dep_node)) -> None:
""" """
Suspend a VirtualBox node. Suspend a VirtualBox node.
""" """
await node.suspend() await node.suspend()
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{node_id}/resume", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/resume", status_code=status.HTTP_204_NO_CONTENT)
async def resume_virtualbox_node(node: VirtualBoxVM = Depends(dep_node)) -> Response: async def resume_virtualbox_node(node: VirtualBoxVM = Depends(dep_node)) -> None:
""" """
Resume a VirtualBox node. Resume a VirtualBox node.
""" """
await node.resume() await node.resume()
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{node_id}/reload", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/reload", status_code=status.HTTP_204_NO_CONTENT)
async def reload_virtualbox_node(node: VirtualBoxVM = Depends(dep_node)) -> Response: async def reload_virtualbox_node(node: VirtualBoxVM = Depends(dep_node)) -> None:
""" """
Reload a VirtualBox node. Reload a VirtualBox node.
""" """
await node.reload() await node.reload()
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post( @router.post(
@ -249,14 +243,13 @@ async def delete_virtualbox_node_nio(
adapter_number: int, adapter_number: int,
port_number: int = Path(..., ge=0, le=0), port_number: int = Path(..., ge=0, le=0),
node: VirtualBoxVM = Depends(dep_node) node: VirtualBoxVM = Depends(dep_node)
) -> Response: ) -> None:
""" """
Delete a NIO (Network Input/Output) from the node. Delete a NIO (Network Input/Output) from the node.
The port number on the VirtualBox node is always 0. The port number on the VirtualBox node is always 0.
""" """
await node.adapter_remove_nio_binding(adapter_number) await node.adapter_remove_nio_binding(adapter_number)
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/start") @router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/start")
@ -284,14 +277,13 @@ async def stop_virtualbox_node_capture(
adapter_number: int, adapter_number: int,
port_number: int = Path(..., ge=0, le=0), port_number: int = Path(..., ge=0, le=0),
node: VirtualBoxVM = Depends(dep_node) node: VirtualBoxVM = Depends(dep_node)
) -> Response: ) -> None:
""" """
Stop a packet capture on the node. Stop a packet capture on the node.
The port number on the VirtualBox node is always 0. The port number on the VirtualBox node is always 0.
""" """
await node.stop_capture(adapter_number) await node.stop_capture(adapter_number)
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.get("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stream") @router.get("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stream")
@ -320,7 +312,7 @@ async def console_ws(websocket: WebSocket, node: VirtualBoxVM = Depends(dep_node
@router.post("/{node_id}/console/reset", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/console/reset", status_code=status.HTTP_204_NO_CONTENT)
async def reset_console(node: VirtualBoxVM = Depends(dep_node)) -> Response: async def reset_console(node: VirtualBoxVM = Depends(dep_node)) -> None:
await node.reset_console() await node.reset_console()
return Response(status_code=status.HTTP_204_NO_CONTENT)

View File

@ -103,63 +103,57 @@ def update_vmware_node(node_data: schemas.VMwareUpdate, node: VMwareVM = Depends
@router.delete("/{node_id}", status_code=status.HTTP_204_NO_CONTENT) @router.delete("/{node_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_vmware_node(node: VMwareVM = Depends(dep_node)) -> Response: async def delete_vmware_node(node: VMwareVM = Depends(dep_node)) -> None:
""" """
Delete a VMware node. Delete a VMware node.
""" """
await VMware.instance().delete_node(node.id) await VMware.instance().delete_node(node.id)
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{node_id}/start", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/start", status_code=status.HTTP_204_NO_CONTENT)
async def start_vmware_node(node: VMwareVM = Depends(dep_node)) -> Response: async def start_vmware_node(node: VMwareVM = Depends(dep_node)) -> None:
""" """
Start a VMware node. Start a VMware node.
""" """
await node.start() await node.start()
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{node_id}/stop", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/stop", status_code=status.HTTP_204_NO_CONTENT)
async def stop_vmware_node(node: VMwareVM = Depends(dep_node)) -> Response: async def stop_vmware_node(node: VMwareVM = Depends(dep_node)) -> None:
""" """
Stop a VMware node. Stop a VMware node.
""" """
await node.stop() await node.stop()
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{node_id}/suspend", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/suspend", status_code=status.HTTP_204_NO_CONTENT)
async def suspend_vmware_node(node: VMwareVM = Depends(dep_node)) -> Response: async def suspend_vmware_node(node: VMwareVM = Depends(dep_node)) -> None:
""" """
Suspend a VMware node. Suspend a VMware node.
""" """
await node.suspend() await node.suspend()
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{node_id}/resume", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/resume", status_code=status.HTTP_204_NO_CONTENT)
async def resume_vmware_node(node: VMwareVM = Depends(dep_node)) -> Response: async def resume_vmware_node(node: VMwareVM = Depends(dep_node)) -> None:
""" """
Resume a VMware node. Resume a VMware node.
""" """
await node.resume() await node.resume()
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{node_id}/reload", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/reload", status_code=status.HTTP_204_NO_CONTENT)
async def reload_vmware_node(node: VMwareVM = Depends(dep_node)) -> Response: async def reload_vmware_node(node: VMwareVM = Depends(dep_node)) -> None:
""" """
Reload a VMware node. Reload a VMware node.
""" """
await node.reload() await node.reload()
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post( @router.post(
@ -213,14 +207,13 @@ async def delete_vmware_node_nio(
adapter_number: int, adapter_number: int,
port_number: int = Path(..., ge=0, le=0), port_number: int = Path(..., ge=0, le=0),
node: VMwareVM = Depends(dep_node) node: VMwareVM = Depends(dep_node)
) -> Response: ) -> None:
""" """
Delete a NIO (Network Input/Output) from the node. Delete a NIO (Network Input/Output) from the node.
The port number on the VMware node is always 0. The port number on the VMware node is always 0.
""" """
await node.adapter_remove_nio_binding(adapter_number) await node.adapter_remove_nio_binding(adapter_number)
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/start") @router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/start")
@ -248,14 +241,13 @@ async def stop_vmware_node_capture(
adapter_number: int, adapter_number: int,
port_number: int = Path(..., ge=0, le=0), port_number: int = Path(..., ge=0, le=0),
node: VMwareVM = Depends(dep_node) node: VMwareVM = Depends(dep_node)
) -> Response: ) -> None:
""" """
Stop a packet capture on the node. Stop a packet capture on the node.
The port number on the VMware node is always 0. The port number on the VMware node is always 0.
""" """
await node.stop_capture(adapter_number) await node.stop_capture(adapter_number)
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.get("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stream") @router.get("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stream")
@ -297,7 +289,7 @@ async def console_ws(websocket: WebSocket, node: VMwareVM = Depends(dep_node)) -
@router.post("/{node_id}/console/reset", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/console/reset", status_code=status.HTTP_204_NO_CONTENT)
async def reset_console(node: VMwareVM = Depends(dep_node)) -> Response: async def reset_console(node: VMwareVM = Depends(dep_node)) -> None:
await node.reset_console() await node.reset_console()
return Response(status_code=status.HTTP_204_NO_CONTENT)

View File

@ -93,13 +93,12 @@ def update_vpcs_node(node_data: schemas.VPCSUpdate, node: VPCSVM = Depends(dep_n
@router.delete("/{node_id}", status_code=status.HTTP_204_NO_CONTENT) @router.delete("/{node_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_vpcs_node(node: VPCSVM = Depends(dep_node)) -> Response: async def delete_vpcs_node(node: VPCSVM = Depends(dep_node)) -> None:
""" """
Delete a VPCS node. Delete a VPCS node.
""" """
await VPCS.instance().delete_node(node.id) await VPCS.instance().delete_node(node.id)
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{node_id}/duplicate", response_model=schemas.VPCS, status_code=status.HTTP_201_CREATED) @router.post("/{node_id}/duplicate", response_model=schemas.VPCS, status_code=status.HTTP_201_CREATED)
@ -115,43 +114,40 @@ async def duplicate_vpcs_node(
@router.post("/{node_id}/start", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/start", status_code=status.HTTP_204_NO_CONTENT)
async def start_vpcs_node(node: VPCSVM = Depends(dep_node)) -> Response: async def start_vpcs_node(node: VPCSVM = Depends(dep_node)) -> None:
""" """
Start a VPCS node. Start a VPCS node.
""" """
await node.start() await node.start()
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{node_id}/stop", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/stop", status_code=status.HTTP_204_NO_CONTENT)
async def stop_vpcs_node(node: VPCSVM = Depends(dep_node)) -> Response: async def stop_vpcs_node(node: VPCSVM = Depends(dep_node)) -> None:
""" """
Stop a VPCS node. Stop a VPCS node.
""" """
await node.stop() await node.stop()
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{node_id}/suspend", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/suspend", status_code=status.HTTP_204_NO_CONTENT)
async def suspend_vpcs_node(node: VPCSVM = Depends(dep_node)) -> Response: async def suspend_vpcs_node(node: VPCSVM = Depends(dep_node)) -> None:
""" """
Suspend a VPCS node. Suspend a VPCS node.
Does nothing, suspend is not supported by VPCS. Does nothing, suspend is not supported by VPCS.
""" """
return Response(status_code=status.HTTP_204_NO_CONTENT) pass
@router.post("/{node_id}/reload", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/reload", status_code=status.HTTP_204_NO_CONTENT)
async def reload_vpcs_node(node: VPCSVM = Depends(dep_node)) -> Response: async def reload_vpcs_node(node: VPCSVM = Depends(dep_node)) -> None:
""" """
Reload a VPCS node. Reload a VPCS node.
""" """
await node.reload() await node.reload()
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post( @router.post(
@ -206,14 +202,13 @@ async def delete_vpcs_node_nio(
adapter_number: int = Path(..., ge=0, le=0), adapter_number: int = Path(..., ge=0, le=0),
port_number: int, port_number: int,
node: VPCSVM = Depends(dep_node) node: VPCSVM = Depends(dep_node)
) -> Response: ) -> None:
""" """
Delete a NIO (Network Input/Output) from the node. Delete a NIO (Network Input/Output) from the node.
The adapter number on the VPCS node is always 0. The adapter number on the VPCS node is always 0.
""" """
await node.port_remove_nio_binding(port_number) await node.port_remove_nio_binding(port_number)
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/start") @router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/start")
@ -242,21 +237,19 @@ async def stop_vpcs_node_capture(
adapter_number: int = Path(..., ge=0, le=0), adapter_number: int = Path(..., ge=0, le=0),
port_number: int, port_number: int,
node: VPCSVM = Depends(dep_node) node: VPCSVM = Depends(dep_node)
) -> Response: ) -> None:
""" """
Stop a packet capture on the node. Stop a packet capture on the node.
The adapter number on the VPCS node is always 0. The adapter number on the VPCS node is always 0.
""" """
await node.stop_capture(port_number) await node.stop_capture(port_number)
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{node_id}/console/reset", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/console/reset", status_code=status.HTTP_204_NO_CONTENT)
async def reset_console(node: VPCSVM = Depends(dep_node)) -> Response: async def reset_console(node: VPCSVM = Depends(dep_node)) -> None:
await node.reset_console() await node.reset_console()
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.get("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stream") @router.get("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stream")

View File

@ -106,7 +106,7 @@ async def install_appliance(
templates_repo: TemplatesRepository = Depends(get_repository(TemplatesRepository)), templates_repo: TemplatesRepository = Depends(get_repository(TemplatesRepository)),
current_user: schemas.User = Depends(get_current_active_user), current_user: schemas.User = Depends(get_current_active_user),
rbac_repo: RbacRepository = Depends(get_repository(RbacRepository)) rbac_repo: RbacRepository = Depends(get_repository(RbacRepository))
) -> Response: ) -> None:
""" """
Install an appliance. Install an appliance.
""" """
@ -120,4 +120,3 @@ async def install_appliance(
rbac_repo, rbac_repo,
current_user current_user
) )
return Response(status_code=status.HTTP_204_NO_CONTENT)

View File

@ -57,7 +57,7 @@ async def create_compute(
@router.post("/{compute_id}/connect", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{compute_id}/connect", status_code=status.HTTP_204_NO_CONTENT)
async def connect_compute(compute_id: Union[str, UUID]) -> Response: async def connect_compute(compute_id: Union[str, UUID]) -> None:
""" """
Connect to compute on the controller. Connect to compute on the controller.
""" """
@ -65,7 +65,6 @@ async def connect_compute(compute_id: Union[str, UUID]) -> Response:
compute = Controller.instance().get_compute(str(compute_id)) compute = Controller.instance().get_compute(str(compute_id))
if not compute.connected: if not compute.connected:
await compute.connect(report_failed_connection=True) await compute.connect(report_failed_connection=True)
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.get("/{compute_id}", response_model=schemas.Compute, response_model_exclude_unset=True) @router.get("/{compute_id}", response_model=schemas.Compute, response_model_exclude_unset=True)
@ -106,13 +105,12 @@ async def update_compute(
@router.delete("/{compute_id}", status_code=status.HTTP_204_NO_CONTENT) @router.delete("/{compute_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_compute( async def delete_compute(
compute_id: Union[str, UUID], computes_repo: ComputesRepository = Depends(get_repository(ComputesRepository)) compute_id: Union[str, UUID], computes_repo: ComputesRepository = Depends(get_repository(ComputesRepository))
) -> Response: ) -> None:
""" """
Delete a compute from the controller. Delete a compute from the controller.
""" """
await ComputesService(computes_repo).delete_compute(compute_id) await ComputesService(computes_repo).delete_compute(compute_id)
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.get("/{compute_id}/docker/images", response_model=List[schemas.ComputeDockerImage]) @router.get("/{compute_id}/docker/images", response_model=List[schemas.ComputeDockerImage])

View File

@ -83,13 +83,12 @@ def check_version(version: schemas.Version) -> dict:
dependencies=[Depends(get_current_active_user)], dependencies=[Depends(get_current_active_user)],
status_code=status.HTTP_204_NO_CONTENT, status_code=status.HTTP_204_NO_CONTENT,
) )
async def reload() -> Response: async def reload() -> None:
""" """
Reload the controller Reload the controller
""" """
await Controller.instance().reload() await Controller.instance().reload()
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post( @router.post(
@ -98,7 +97,7 @@ async def reload() -> Response:
status_code=status.HTTP_204_NO_CONTENT, status_code=status.HTTP_204_NO_CONTENT,
responses={403: {"model": schemas.ErrorMessage, "description": "Server shutdown not allowed"}}, responses={403: {"model": schemas.ErrorMessage, "description": "Server shutdown not allowed"}},
) )
async def shutdown() -> Response: async def shutdown() -> None:
""" """
Shutdown the server Shutdown the server
""" """
@ -126,7 +125,6 @@ async def shutdown() -> Response:
# then shutdown the server itself # then shutdown the server itself
os.kill(os.getpid(), signal.SIGTERM) os.kill(os.getpid(), signal.SIGTERM)
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.get( @router.get(

View File

@ -32,7 +32,7 @@ oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/v3/users/login", auto_error=Fals
async def get_user_from_token( async def get_user_from_token(
bearer_token: str = Depends(oauth2_scheme), bearer_token: str = Depends(oauth2_scheme),
user_repo: UsersRepository = Depends(get_repository(UsersRepository)), user_repo: UsersRepository = Depends(get_repository(UsersRepository)),
token: Optional[str] = None, token: Optional[str] = Query(None, include_in_schema=False)
) -> schemas.User: ) -> schemas.User:
if bearer_token: if bearer_token:

View File

@ -76,11 +76,10 @@ async def update_drawing(project_id: UUID, drawing_id: UUID, drawing_data: schem
@router.delete("/{drawing_id}", status_code=status.HTTP_204_NO_CONTENT) @router.delete("/{drawing_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_drawing(project_id: UUID, drawing_id: UUID) -> Response: async def delete_drawing(project_id: UUID, drawing_id: UUID) -> None:
""" """
Delete a drawing. Delete a drawing.
""" """
project = await Controller.instance().get_loaded_project(str(project_id)) project = await Controller.instance().get_loaded_project(str(project_id))
await project.delete_drawing(str(drawing_id)) await project.delete_drawing(str(drawing_id))
return Response(status_code=status.HTTP_204_NO_CONTENT)

View File

@ -113,7 +113,7 @@ async def update_user_group(
async def delete_user_group( async def delete_user_group(
user_group_id: UUID, user_group_id: UUID,
users_repo: UsersRepository = Depends(get_repository(UsersRepository)), users_repo: UsersRepository = Depends(get_repository(UsersRepository)),
) -> Response: ) -> None:
""" """
Delete an user group Delete an user group
""" """
@ -129,8 +129,6 @@ async def delete_user_group(
if not success: if not success:
raise ControllerError(f"User group '{user_group_id}' could not be deleted") raise ControllerError(f"User group '{user_group_id}' could not be deleted")
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.get("/{user_group_id}/members", response_model=List[schemas.User]) @router.get("/{user_group_id}/members", response_model=List[schemas.User])
async def get_user_group_members( async def get_user_group_members(
@ -152,7 +150,7 @@ async def add_member_to_group(
user_group_id: UUID, user_group_id: UUID,
user_id: UUID, user_id: UUID,
users_repo: UsersRepository = Depends(get_repository(UsersRepository)) users_repo: UsersRepository = Depends(get_repository(UsersRepository))
) -> Response: ) -> None:
""" """
Add member to an user group. Add member to an user group.
""" """
@ -165,8 +163,6 @@ async def add_member_to_group(
if not user_group: if not user_group:
raise ControllerNotFoundError(f"User group '{user_group_id}' not found") raise ControllerNotFoundError(f"User group '{user_group_id}' not found")
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.delete( @router.delete(
"/{user_group_id}/members/{user_id}", "/{user_group_id}/members/{user_id}",
@ -176,7 +172,7 @@ async def remove_member_from_group(
user_group_id: UUID, user_group_id: UUID,
user_id: UUID, user_id: UUID,
users_repo: UsersRepository = Depends(get_repository(UsersRepository)), users_repo: UsersRepository = Depends(get_repository(UsersRepository)),
) -> Response: ) -> None:
""" """
Remove member from an user group. Remove member from an user group.
""" """
@ -189,8 +185,6 @@ async def remove_member_from_group(
if not user_group: if not user_group:
raise ControllerNotFoundError(f"User group '{user_group_id}' not found") raise ControllerNotFoundError(f"User group '{user_group_id}' not found")
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.get("/{user_group_id}/roles", response_model=List[schemas.Role]) @router.get("/{user_group_id}/roles", response_model=List[schemas.Role])
async def get_user_group_roles( async def get_user_group_roles(
@ -226,8 +220,6 @@ async def add_role_to_group(
if not user_group: if not user_group:
raise ControllerNotFoundError(f"User group '{user_group_id}' not found") raise ControllerNotFoundError(f"User group '{user_group_id}' not found")
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.delete( @router.delete(
"/{user_group_id}/roles/{role_id}", "/{user_group_id}/roles/{role_id}",
@ -238,7 +230,7 @@ async def remove_role_from_group(
role_id: UUID, role_id: UUID,
users_repo: UsersRepository = Depends(get_repository(UsersRepository)), users_repo: UsersRepository = Depends(get_repository(UsersRepository)),
rbac_repo: RbacRepository = Depends(get_repository(RbacRepository)) rbac_repo: RbacRepository = Depends(get_repository(RbacRepository))
) -> Response: ) -> None:
""" """
Remove role from an user group. Remove role from an user group.
""" """
@ -250,5 +242,3 @@ async def remove_role_from_group(
user_group = await users_repo.remove_role_from_user_group(user_group_id, role) user_group = await users_repo.remove_role_from_user_group(user_group_id, role)
if not user_group: if not user_group:
raise ControllerNotFoundError(f"User group '{user_group_id}' not found") raise ControllerNotFoundError(f"User group '{user_group_id}' not found")
return Response(status_code=status.HTTP_204_NO_CONTENT)

View File

@ -129,7 +129,7 @@ async def get_image(
async def delete_image( async def delete_image(
image_path: str, image_path: str,
images_repo: ImagesRepository = Depends(get_repository(ImagesRepository)), images_repo: ImagesRepository = Depends(get_repository(ImagesRepository)),
) -> Response: ) -> None:
""" """
Delete an image. Delete an image.
""" """
@ -159,16 +159,13 @@ async def delete_image(
if not success: if not success:
raise ControllerError(f"Image '{image_path}' could not be deleted") raise ControllerError(f"Image '{image_path}' could not be deleted")
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/prune", status_code=status.HTTP_204_NO_CONTENT) @router.post("/prune", status_code=status.HTTP_204_NO_CONTENT)
async def prune_images( async def prune_images(
images_repo: ImagesRepository = Depends(get_repository(ImagesRepository)), images_repo: ImagesRepository = Depends(get_repository(ImagesRepository)),
) -> Response: ) -> None:
""" """
Prune images not attached to any template. Prune images not attached to any template.
""" """
await images_repo.prune_images() await images_repo.prune_images()
return Response(status_code=status.HTTP_204_NO_CONTENT)

View File

@ -136,14 +136,13 @@ async def update_link(link_data: schemas.LinkUpdate, link: Link = Depends(dep_li
@router.delete("/{link_id}", status_code=status.HTTP_204_NO_CONTENT) @router.delete("/{link_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_link(project_id: UUID, link: Link = Depends(dep_link)) -> Response: async def delete_link(project_id: UUID, link: Link = Depends(dep_link)) -> None:
""" """
Delete a link. Delete a link.
""" """
project = await Controller.instance().get_loaded_project(str(project_id)) project = await Controller.instance().get_loaded_project(str(project_id))
await project.delete_link(link.id) await project.delete_link(link.id)
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{link_id}/reset", response_model=schemas.Link) @router.post("/{link_id}/reset", response_model=schemas.Link)
@ -170,13 +169,12 @@ async def start_capture(capture_data: dict, link: Link = Depends(dep_link)) -> s
@router.post("/{link_id}/capture/stop", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{link_id}/capture/stop", status_code=status.HTTP_204_NO_CONTENT)
async def stop_capture(link: Link = Depends(dep_link)) -> Response: async def stop_capture(link: Link = Depends(dep_link)) -> None:
""" """
Stop packet capture on the link. Stop packet capture on the link.
""" """
await link.stop_capture() await link.stop_capture()
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.get("/{link_id}/capture/stream") @router.get("/{link_id}/capture/stream")

View File

@ -130,44 +130,40 @@ async def get_nodes(project: Project = Depends(dep_project)) -> List[schemas.Nod
@router.post("/start", status_code=status.HTTP_204_NO_CONTENT) @router.post("/start", status_code=status.HTTP_204_NO_CONTENT)
async def start_all_nodes(project: Project = Depends(dep_project)) -> Response: async def start_all_nodes(project: Project = Depends(dep_project)) -> None:
""" """
Start all nodes belonging to a given project. Start all nodes belonging to a given project.
""" """
await project.start_all() await project.start_all()
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/stop", status_code=status.HTTP_204_NO_CONTENT) @router.post("/stop", status_code=status.HTTP_204_NO_CONTENT)
async def stop_all_nodes(project: Project = Depends(dep_project)) -> Response: async def stop_all_nodes(project: Project = Depends(dep_project)) -> None:
""" """
Stop all nodes belonging to a given project. Stop all nodes belonging to a given project.
""" """
await project.stop_all() await project.stop_all()
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/suspend", status_code=status.HTTP_204_NO_CONTENT) @router.post("/suspend", status_code=status.HTTP_204_NO_CONTENT)
async def suspend_all_nodes(project: Project = Depends(dep_project)) -> Response: async def suspend_all_nodes(project: Project = Depends(dep_project)) -> None:
""" """
Suspend all nodes belonging to a given project. Suspend all nodes belonging to a given project.
""" """
await project.suspend_all() await project.suspend_all()
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/reload", status_code=status.HTTP_204_NO_CONTENT) @router.post("/reload", status_code=status.HTTP_204_NO_CONTENT)
async def reload_all_nodes(project: Project = Depends(dep_project)) -> Response: async def reload_all_nodes(project: Project = Depends(dep_project)) -> None:
""" """
Reload all nodes belonging to a given project. Reload all nodes belonging to a given project.
""" """
await project.stop_all() await project.stop_all()
await project.start_all() await project.start_all()
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.get("/{node_id}", response_model=schemas.Node) @router.get("/{node_id}", response_model=schemas.Node)
@ -201,13 +197,12 @@ async def update_node(node_data: schemas.NodeUpdate, node: Node = Depends(dep_no
status_code=status.HTTP_204_NO_CONTENT, status_code=status.HTTP_204_NO_CONTENT,
responses={**responses, 409: {"model": schemas.ErrorMessage, "description": "Cannot delete node"}}, responses={**responses, 409: {"model": schemas.ErrorMessage, "description": "Cannot delete node"}},
) )
async def delete_node(node_id: UUID, project: Project = Depends(dep_project)) -> Response: async def delete_node(node_id: UUID, project: Project = Depends(dep_project)) -> None:
""" """
Delete a node from a project. Delete a node from a project.
""" """
await project.delete_node(str(node_id)) await project.delete_node(str(node_id))
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{node_id}/duplicate", response_model=schemas.Node, status_code=status.HTTP_201_CREATED) @router.post("/{node_id}/duplicate", response_model=schemas.Node, status_code=status.HTTP_201_CREATED)
@ -221,65 +216,59 @@ async def duplicate_node(duplicate_data: schemas.NodeDuplicate, node: Node = Dep
@router.post("/{node_id}/start", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/start", status_code=status.HTTP_204_NO_CONTENT)
async def start_node(start_data: dict, node: Node = Depends(dep_node)) -> Response: async def start_node(start_data: dict, node: Node = Depends(dep_node)) -> None:
""" """
Start a node. Start a node.
""" """
await node.start(data=start_data) await node.start(data=start_data)
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{node_id}/stop", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/stop", status_code=status.HTTP_204_NO_CONTENT)
async def stop_node(node: Node = Depends(dep_node)) -> Response: async def stop_node(node: Node = Depends(dep_node)) -> None:
""" """
Stop a node. Stop a node.
""" """
await node.stop() await node.stop()
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{node_id}/suspend", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/suspend", status_code=status.HTTP_204_NO_CONTENT)
async def suspend_node(node: Node = Depends(dep_node)) -> Response: async def suspend_node(node: Node = Depends(dep_node)) -> None:
""" """
Suspend a node. Suspend a node.
""" """
await node.suspend() await node.suspend()
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{node_id}/reload", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/reload", status_code=status.HTTP_204_NO_CONTENT)
async def reload_node(node: Node = Depends(dep_node)) -> Response: async def reload_node(node: Node = Depends(dep_node)) -> None:
""" """
Reload a node. Reload a node.
""" """
await node.reload() await node.reload()
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{node_id}/isolate", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/isolate", status_code=status.HTTP_204_NO_CONTENT)
async def isolate_node(node: Node = Depends(dep_node)) -> Response: async def isolate_node(node: Node = Depends(dep_node)) -> None:
""" """
Isolate a node (suspend all attached links). Isolate a node (suspend all attached links).
""" """
for link in node.links: for link in node.links:
await link.update_suspend(True) await link.update_suspend(True)
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{node_id}/unisolate", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/unisolate", status_code=status.HTTP_204_NO_CONTENT)
async def unisolate_node(node: Node = Depends(dep_node)) -> Response: async def unisolate_node(node: Node = Depends(dep_node)) -> None:
""" """
Un-isolate a node (resume all attached suspended links). Un-isolate a node (resume all attached suspended links).
""" """
for link in node.links: for link in node.links:
await link.update_suspend(False) await link.update_suspend(False)
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.get("/{node_id}/links", response_model=List[schemas.Link], response_model_exclude_unset=True) @router.get("/{node_id}/links", response_model=List[schemas.Link], response_model_exclude_unset=True)
@ -321,7 +310,7 @@ async def create_disk_image(
disk_name: str, disk_name: str,
disk_data: schemas.QemuDiskImageCreate, disk_data: schemas.QemuDiskImageCreate,
node: Node = Depends(dep_node) node: Node = Depends(dep_node)
) -> Response: ) -> None:
""" """
Create a Qemu disk image. Create a Qemu disk image.
""" """
@ -329,7 +318,6 @@ async def create_disk_image(
if node.node_type != "qemu": if node.node_type != "qemu":
raise ControllerBadRequestError("Creating a disk image is only supported on a Qemu node") raise ControllerBadRequestError("Creating a disk image is only supported on a Qemu node")
await node.post(f"/disk_image/{disk_name}", data=disk_data.dict(exclude_unset=True)) await node.post(f"/disk_image/{disk_name}", data=disk_data.dict(exclude_unset=True))
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.put("/{node_id}/qemu/disk_image/{disk_name}", status_code=status.HTTP_204_NO_CONTENT) @router.put("/{node_id}/qemu/disk_image/{disk_name}", status_code=status.HTTP_204_NO_CONTENT)
@ -337,7 +325,7 @@ async def update_disk_image(
disk_name: str, disk_name: str,
disk_data: schemas.QemuDiskImageUpdate, disk_data: schemas.QemuDiskImageUpdate,
node: Node = Depends(dep_node) node: Node = Depends(dep_node)
) -> Response: ) -> None:
""" """
Update a Qemu disk image. Update a Qemu disk image.
""" """
@ -345,14 +333,13 @@ async def update_disk_image(
if node.node_type != "qemu": if node.node_type != "qemu":
raise ControllerBadRequestError("Updating a disk image is only supported on a Qemu node") raise ControllerBadRequestError("Updating a disk image is only supported on a Qemu node")
await node.put(f"/disk_image/{disk_name}", data=disk_data.dict(exclude_unset=True)) await node.put(f"/disk_image/{disk_name}", data=disk_data.dict(exclude_unset=True))
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.delete("/{node_id}/qemu/disk_image/{disk_name}", status_code=status.HTTP_204_NO_CONTENT) @router.delete("/{node_id}/qemu/disk_image/{disk_name}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_disk_image( async def delete_disk_image(
disk_name: str, disk_name: str,
node: Node = Depends(dep_node) node: Node = Depends(dep_node)
) -> Response: ) -> None:
""" """
Delete a Qemu disk image. Delete a Qemu disk image.
""" """
@ -360,7 +347,6 @@ async def delete_disk_image(
if node.node_type != "qemu": if node.node_type != "qemu":
raise ControllerBadRequestError("Deleting a disk image is only supported on a Qemu node") raise ControllerBadRequestError("Deleting a disk image is only supported on a Qemu node")
await node.delete(f"/disk_image/{disk_name}") await node.delete(f"/disk_image/{disk_name}")
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.get("/{node_id}/files/{file_path:path}") @router.get("/{node_id}/files/{file_path:path}")
@ -451,17 +437,15 @@ async def ws_console(websocket: WebSocket, node: Node = Depends(dep_node)) -> No
@router.post("/console/reset", status_code=status.HTTP_204_NO_CONTENT) @router.post("/console/reset", status_code=status.HTTP_204_NO_CONTENT)
async def reset_console_all_nodes(project: Project = Depends(dep_project)) -> Response: async def reset_console_all_nodes(project: Project = Depends(dep_project)) -> None:
""" """
Reset console for all nodes belonging to the project. Reset console for all nodes belonging to the project.
""" """
await project.reset_console_all() await project.reset_console_all()
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{node_id}/console/reset", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{node_id}/console/reset", status_code=status.HTTP_204_NO_CONTENT)
async def console_reset(node: Node = Depends(dep_node)) -> Response: async def console_reset(node: Node = Depends(dep_node)) -> None:
await node.post("/console/reset") await node.post("/console/reset")
return Response(status_code=status.HTTP_204_NO_CONTENT)

View File

@ -136,7 +136,7 @@ async def update_permission(
async def delete_permission( async def delete_permission(
permission_id: UUID, permission_id: UUID,
rbac_repo: RbacRepository = Depends(get_repository(RbacRepository)), rbac_repo: RbacRepository = Depends(get_repository(RbacRepository)),
) -> Response: ) -> None:
""" """
Delete a permission. Delete a permission.
""" """
@ -149,16 +149,13 @@ async def delete_permission(
if not success: if not success:
raise ControllerNotFoundError(f"Permission '{permission_id}' could not be deleted") raise ControllerNotFoundError(f"Permission '{permission_id}' could not be deleted")
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/prune", status_code=status.HTTP_204_NO_CONTENT) @router.post("/prune", status_code=status.HTTP_204_NO_CONTENT)
async def prune_permissions( async def prune_permissions(
rbac_repo: RbacRepository = Depends(get_repository(RbacRepository)) rbac_repo: RbacRepository = Depends(get_repository(RbacRepository))
) -> Response: ) -> None:
""" """
Prune orphaned permissions. Prune orphaned permissions.
""" """
await rbac_repo.prune_permissions() await rbac_repo.prune_permissions()
return Response(status_code=status.HTTP_204_NO_CONTENT)

View File

@ -141,7 +141,7 @@ async def update_project(
async def delete_project( async def delete_project(
project: Project = Depends(dep_project), project: Project = Depends(dep_project),
rbac_repo: RbacRepository = Depends(get_repository(RbacRepository)) rbac_repo: RbacRepository = Depends(get_repository(RbacRepository))
) -> Response: ) -> None:
""" """
Delete a project. Delete a project.
""" """
@ -150,7 +150,6 @@ async def delete_project(
await project.delete() await project.delete()
controller.remove_project(project) controller.remove_project(project)
await rbac_repo.delete_all_permissions_with_path(f"/projects/{project.id}") await rbac_repo.delete_all_permissions_with_path(f"/projects/{project.id}")
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.get("/{project_id}/stats") @router.get("/{project_id}/stats")
@ -167,13 +166,12 @@ def get_project_stats(project: Project = Depends(dep_project)) -> dict:
status_code=status.HTTP_204_NO_CONTENT, status_code=status.HTTP_204_NO_CONTENT,
responses={**responses, 409: {"model": schemas.ErrorMessage, "description": "Could not close project"}}, responses={**responses, 409: {"model": schemas.ErrorMessage, "description": "Could not close project"}},
) )
async def close_project(project: Project = Depends(dep_project)) -> Response: async def close_project(project: Project = Depends(dep_project)) -> None:
""" """
Close a project. Close a project.
""" """
await project.close() await project.close()
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post( @router.post(
@ -420,7 +418,7 @@ async def get_file(file_path: str, project: Project = Depends(dep_project)) -> F
@router.post("/{project_id}/files/{file_path:path}", status_code=status.HTTP_204_NO_CONTENT) @router.post("/{project_id}/files/{file_path:path}", status_code=status.HTTP_204_NO_CONTENT)
async def write_file(file_path: str, request: Request, project: Project = Depends(dep_project)) -> Response: async def write_file(file_path: str, request: Request, project: Project = Depends(dep_project)) -> None:
""" """
Write a file to a project. Write a file to a project.
""" """
@ -445,8 +443,6 @@ async def write_file(file_path: str, request: Request, project: Project = Depend
except OSError as e: except OSError as e:
raise ControllerError(str(e)) raise ControllerError(str(e))
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post( @router.post(
"/{project_id}/templates/{template_id}", "/{project_id}/templates/{template_id}",

View File

@ -106,7 +106,7 @@ async def update_role(
async def delete_role( async def delete_role(
role_id: UUID, role_id: UUID,
rbac_repo: RbacRepository = Depends(get_repository(RbacRepository)), rbac_repo: RbacRepository = Depends(get_repository(RbacRepository)),
) -> Response: ) -> None:
""" """
Delete a role. Delete a role.
""" """
@ -122,8 +122,6 @@ async def delete_role(
if not success: if not success:
raise ControllerError(f"Role '{role_id}' could not be deleted") raise ControllerError(f"Role '{role_id}' could not be deleted")
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.get("/{role_id}/permissions", response_model=List[schemas.Permission]) @router.get("/{role_id}/permissions", response_model=List[schemas.Permission])
async def get_role_permissions( async def get_role_permissions(
@ -145,7 +143,7 @@ async def add_permission_to_role(
role_id: UUID, role_id: UUID,
permission_id: UUID, permission_id: UUID,
rbac_repo: RbacRepository = Depends(get_repository(RbacRepository)) rbac_repo: RbacRepository = Depends(get_repository(RbacRepository))
) -> Response: ) -> None:
""" """
Add a permission to a role. Add a permission to a role.
""" """
@ -158,8 +156,6 @@ async def add_permission_to_role(
if not role: if not role:
raise ControllerNotFoundError(f"Role '{role_id}' not found") raise ControllerNotFoundError(f"Role '{role_id}' not found")
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.delete( @router.delete(
"/{role_id}/permissions/{permission_id}", "/{role_id}/permissions/{permission_id}",
@ -169,7 +165,7 @@ async def remove_permission_from_role(
role_id: UUID, role_id: UUID,
permission_id: UUID, permission_id: UUID,
rbac_repo: RbacRepository = Depends(get_repository(RbacRepository)), rbac_repo: RbacRepository = Depends(get_repository(RbacRepository)),
) -> Response: ) -> None:
""" """
Remove member from an user group. Remove member from an user group.
""" """
@ -181,5 +177,3 @@ async def remove_permission_from_role(
role = await rbac_repo.remove_permission_from_role(role_id, permission) role = await rbac_repo.remove_permission_from_role(role_id, permission)
if not role: if not role:
raise ControllerNotFoundError(f"Role '{role_id}' not found") raise ControllerNotFoundError(f"Role '{role_id}' not found")
return Response(status_code=status.HTTP_204_NO_CONTENT)

View File

@ -69,13 +69,12 @@ def get_snapshots(project: Project = Depends(dep_project)) -> List[schemas.Snaps
@router.delete("/{snapshot_id}", status_code=status.HTTP_204_NO_CONTENT) @router.delete("/{snapshot_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_snapshot(snapshot_id: UUID, project: Project = Depends(dep_project)) -> Response: async def delete_snapshot(snapshot_id: UUID, project: Project = Depends(dep_project)) -> None:
""" """
Delete a snapshot. Delete a snapshot.
""" """
await project.delete_snapshot(str(snapshot_id)) await project.delete_snapshot(str(snapshot_id))
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.post("/{snapshot_id}/restore", status_code=status.HTTP_201_CREATED, response_model=schemas.Project) @router.post("/{snapshot_id}/restore", status_code=status.HTTP_201_CREATED, response_model=schemas.Project)

View File

@ -95,7 +95,7 @@ def get_default_symbols() -> dict:
dependencies=[Depends(get_current_active_user)], dependencies=[Depends(get_current_active_user)],
status_code=status.HTTP_204_NO_CONTENT status_code=status.HTTP_204_NO_CONTENT
) )
async def upload_symbol(symbol_id: str, request: Request) -> Response: async def upload_symbol(symbol_id: str, request: Request) -> None:
""" """
Upload a symbol file. Upload a symbol file.
""" """
@ -112,4 +112,3 @@ async def upload_symbol(symbol_id: str, request: Request) -> Response:
# Reset the symbol list # Reset the symbol list
controller.symbols.list() controller.symbols.list()
return Response(status_code=status.HTTP_204_NO_CONTENT)

View File

@ -102,7 +102,7 @@ async def delete_template(
templates_repo: TemplatesRepository = Depends(get_repository(TemplatesRepository)), templates_repo: TemplatesRepository = Depends(get_repository(TemplatesRepository)),
images_repo: RbacRepository = Depends(get_repository(ImagesRepository)), images_repo: RbacRepository = Depends(get_repository(ImagesRepository)),
rbac_repo: RbacRepository = Depends(get_repository(RbacRepository)) rbac_repo: RbacRepository = Depends(get_repository(RbacRepository))
) -> Response: ) -> None:
""" """
Delete a template. Delete a template.
""" """
@ -111,7 +111,6 @@ async def delete_template(
await rbac_repo.delete_all_permissions_with_path(f"/templates/{template_id}") await rbac_repo.delete_all_permissions_with_path(f"/templates/{template_id}")
if prune_images: if prune_images:
await images_repo.prune_images() await images_repo.prune_images()
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.get("", response_model=List[schemas.Template], response_model_exclude_unset=True) @router.get("", response_model=List[schemas.Template], response_model_exclude_unset=True)

View File

@ -194,7 +194,7 @@ async def update_user(
async def delete_user( async def delete_user(
user_id: UUID, user_id: UUID,
users_repo: UsersRepository = Depends(get_repository(UsersRepository)), users_repo: UsersRepository = Depends(get_repository(UsersRepository)),
) -> Response: ) -> None:
""" """
Delete an user. Delete an user.
""" """
@ -210,8 +210,6 @@ async def delete_user(
if not success: if not success:
raise ControllerError(f"User '{user_id}' could not be deleted") raise ControllerError(f"User '{user_id}' could not be deleted")
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.get( @router.get(
"/{user_id}/groups", "/{user_id}/groups",
@ -254,7 +252,7 @@ async def add_permission_to_user(
user_id: UUID, user_id: UUID,
permission_id: UUID, permission_id: UUID,
rbac_repo: RbacRepository = Depends(get_repository(RbacRepository)) rbac_repo: RbacRepository = Depends(get_repository(RbacRepository))
) -> Response: ) -> None:
""" """
Add a permission to an user. Add a permission to an user.
""" """
@ -267,8 +265,6 @@ async def add_permission_to_user(
if not user: if not user:
raise ControllerNotFoundError(f"User '{user_id}' not found") raise ControllerNotFoundError(f"User '{user_id}' not found")
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.delete( @router.delete(
"/{user_id}/permissions/{permission_id}", "/{user_id}/permissions/{permission_id}",
@ -279,7 +275,7 @@ async def remove_permission_from_user(
user_id: UUID, user_id: UUID,
permission_id: UUID, permission_id: UUID,
rbac_repo: RbacRepository = Depends(get_repository(RbacRepository)), rbac_repo: RbacRepository = Depends(get_repository(RbacRepository)),
) -> Response: ) -> None:
""" """
Remove permission from an user. Remove permission from an user.
""" """
@ -291,5 +287,3 @@ async def remove_permission_from_user(
user = await rbac_repo.remove_permission_from_user(user_id, permission) user = await rbac_repo.remove_permission_from_user(user_id, permission)
if not user: if not user:
raise ControllerNotFoundError(f"User '{user_id}' not found") raise ControllerNotFoundError(f"User '{user_id}' not found")
return Response(status_code=status.HTTP_204_NO_CONTENT)

View File

@ -4,7 +4,7 @@
"category": "multilayer_switch", "category": "multilayer_switch",
"description": "The ArubaOS-CX Simulation Software is a virtual platform to enable simulation of the ArubaOS-CX Network Operating System. Simulated networks can be created using many of the protocols in the ArubaOS-CX Operating system like OSPF, BGP (inc. EVPN). Key features like the Aruba Network Analytics Engine and the REST API can be simulated, providing a lightweight development platform to building the modern network.", "description": "The ArubaOS-CX Simulation Software is a virtual platform to enable simulation of the ArubaOS-CX Network Operating System. Simulated networks can be created using many of the protocols in the ArubaOS-CX Operating system like OSPF, BGP (inc. EVPN). Key features like the Aruba Network Analytics Engine and the REST API can be simulated, providing a lightweight development platform to building the modern network.",
"vendor_name": "HPE Aruba", "vendor_name": "HPE Aruba",
"vendor_url": "arubanetworks.com", "vendor_url": "https://www.arubanetworks.com",
"product_name": "ArubaOS-CX Simulation Software", "product_name": "ArubaOS-CX Simulation Software",
"registry_version": 4, "registry_version": 4,
"status": "stable", "status": "stable",
@ -30,6 +30,13 @@
"process_priority": "normal" "process_priority": "normal"
}, },
"images": [ "images": [
{
"filename": "arubaoscx-disk-image-genericx86-p4-20220616193419.vmdk",
"version": "10.10.0002",
"md5sum": "ed031aeb6caf92adb408c7603d294fd4",
"filesize": 355858944,
"download_url": "https://asp.arubanetworks.com/"
},
{ {
"filename": "arubaoscx-disk-image-genericx86-p4-20220223012712.vmdk", "filename": "arubaoscx-disk-image-genericx86-p4-20220223012712.vmdk",
"version": "10.09.1000", "version": "10.09.1000",
@ -88,6 +95,12 @@
} }
], ],
"versions": [ "versions": [
{
"name": "10.10.0002",
"images": {
"hda_disk_image": "arubaoscx-disk-image-genericx86-p4-20220616193419.vmdk"
}
},
{ {
"name": "10.09.1000", "name": "10.09.1000",
"images": { "images": {

View File

@ -4,7 +4,7 @@
"category": "firewall", "category": "firewall",
"description": "Aruba Virtual Gateways allow customers to bring their public cloud infrastructure to the SD-WAN fabric and facilitate connectivity between branches and the public cloud.", "description": "Aruba Virtual Gateways allow customers to bring their public cloud infrastructure to the SD-WAN fabric and facilitate connectivity between branches and the public cloud.",
"vendor_name": "HPE Aruba", "vendor_name": "HPE Aruba",
"vendor_url": "arubanetworks.com", "vendor_url": "https://www.arubanetworks.com",
"documentation_url": "https://asp.arubanetworks.com/downloads;products=Aruba%20SD-WAN", "documentation_url": "https://asp.arubanetworks.com/downloads;products=Aruba%20SD-WAN",
"product_name": "Aruba SD-WAN Virtual Gateway", "product_name": "Aruba SD-WAN Virtual Gateway",
"product_url": "https://www.arubanetworks.com/products/networking/gateways-and-controllers/", "product_url": "https://www.arubanetworks.com/products/networking/gateways-and-controllers/",

View File

@ -4,7 +4,7 @@
"category": "guest", "category": "guest",
"description": "Aruba Virtual Mobility Controller", "description": "Aruba Virtual Mobility Controller",
"vendor_name": "HPE Aruba", "vendor_name": "HPE Aruba",
"vendor_url": "arubanetworks.com", "vendor_url": "https://www.arubanetworks.com",
"product_name": "Aruba VMC", "product_name": "Aruba VMC",
"registry_version": 4, "registry_version": 4,
"status": "stable", "status": "stable",

View File

@ -24,6 +24,13 @@
"kvm": "require" "kvm": "require"
}, },
"images": [ "images": [
{
"filename": "c8000v-universalk9_8G_serial.17.06.01a.qcow2",
"version": "17.06.01a 8G",
"md5sum": "d8b8ae633d953ec1b6d8f18a09a4f4e7",
"filesize": 1595277312,
"download_url": "https://software.cisco.com/download/home/286327102/type/282046477/release/Bengaluru-17.6.1a"
},
{ {
"filename": "c8000v-universalk9_8G_serial.17.04.01a.qcow2", "filename": "c8000v-universalk9_8G_serial.17.04.01a.qcow2",
"version": "17.04.01a 8G", "version": "17.04.01a 8G",
@ -40,6 +47,12 @@
} }
], ],
"versions": [ "versions": [
{
"name": "17.06.01a 8G",
"images": {
"hda_disk_image": "c8000v-universalk9_8G_serial.17.06.01a.qcow2"
}
},
{ {
"name": "17.04.01a 8G", "name": "17.04.01a 8G",
"images": { "images": {

View File

@ -18,6 +18,12 @@
"startup_config": "iou_l3_base_startup-config.txt" "startup_config": "iou_l3_base_startup-config.txt"
}, },
"images": [ "images": [
{
"filename": "i86bi_LinuxL3-AdvEnterpriseK9-M2_157_3_May_2018.bin",
"version": "15.7(3)M2",
"md5sum": "d6874260c3daeeb96d10fc844ae0b93b",
"filesize": 184759244
},
{ {
"filename": "i86bi-linux-l3-adventerprisek9-ms.155-2.T.bin", "filename": "i86bi-linux-l3-adventerprisek9-ms.155-2.T.bin",
"version": "155-2T", "version": "155-2T",
@ -32,6 +38,12 @@
} }
], ],
"versions": [ "versions": [
{
"name": "15.7(3)M2",
"images": {
"image": "i86bi_LinuxL3-AdvEnterpriseK9-M2_157_3_May_2018.bin"
}
},
{ {
"name": "155-2T", "name": "155-2T",
"images": { "images": {

View File

@ -24,12 +24,12 @@
}, },
"images": [ "images": [
{ {
"filename": "debian-11-genericcloud-amd64-20220328-962.qcow2", "filename": "debian-11-genericcloud-amd64-20220711-1073.qcow2",
"version": "11.3", "version": "11.4",
"md5sum": "7cf51e23747898485971a656ac2eb96d", "md5sum": "e8fadf4bbf7324a2e2875a5ba00588e7",
"filesize": 253296640, "filesize": 253231104,
"download_url": "https://cloud.debian.org/images/cloud/bullseye/", "download_url": "https://cloud.debian.org/images/cloud/bullseye/",
"direct_download_url": "https://cloud.debian.org/images/cloud/bullseye/20220328-962/debian-11-genericcloud-amd64-20220328-962.qcow2" "direct_download_url": "https://cloud.debian.org/images/cloud/bullseye/20220711-1073/debian-11-genericcloud-amd64-20220711-1073.qcow2"
}, },
{ {
"filename": "debian-10-genericcloud-amd64-20220328-962.qcow2", "filename": "debian-10-genericcloud-amd64-20220328-962.qcow2",
@ -49,9 +49,9 @@
], ],
"versions": [ "versions": [
{ {
"name": "11.3", "name": "11.4",
"images": { "images": {
"hda_disk_image": "debian-11-genericcloud-amd64-20220328-962.qcow2", "hda_disk_image": "debian-11-genericcloud-amd64-20220711-1073.qcow2",
"cdrom_image": "debian-cloud-init-data.iso" "cdrom_image": "debian-cloud-init-data.iso"
} }
}, },

View File

@ -27,7 +27,14 @@
"options": "-cpu core2duo" "options": "-cpu core2duo"
}, },
"images": [ "images": [
{ {
"filename": "EXOS-VM_v32.1.1.6.qcow2",
"version": "32.1.1.6",
"md5sum": "48868bbcb4255d6365049b5941dd2af7",
"filesize": 231211008,
"direct_download_url": "https://akamai-ep.extremenetworks.com/Extreme_P/github-en/Virtual_EXOS/EXOS-VM_v32.1.1.6.qcow2"
},
{
"filename": "EXOS-VM_v31.7.1.4.qcow2", "filename": "EXOS-VM_v31.7.1.4.qcow2",
"version": "31.7.1.4", "version": "31.7.1.4",
"md5sum": "a70e4fa3bc361434237ad12937aaf0fb", "md5sum": "a70e4fa3bc361434237ad12937aaf0fb",
@ -106,6 +113,12 @@
} }
], ],
"versions": [ "versions": [
{
"name": "32.1.1.6",
"images": {
"hda_disk_image": "EXOS-VM_v32.1.1.6.qcow2"
}
},
{ {
"name": "31.7.1.4", "name": "31.7.1.4",
"images": { "images": {

View File

@ -11,7 +11,7 @@
"status": "experimental", "status": "experimental",
"availability": "service-contract", "availability": "service-contract",
"maintainer": "none", "maintainer": "none",
"maintainer_email": "none", "maintainer_email": "",
"usage": "Default user is super, default password is super.", "usage": "Default user is super, default password is super.",
"port_name_format": "GigabitEthernet0/0/{0}", "port_name_format": "GigabitEthernet0/0/{0}",
"qemu": { "qemu": {

View File

@ -10,7 +10,7 @@
"status": "experimental", "status": "experimental",
"availability": "service-contract", "availability": "service-contract",
"maintainer": "none", "maintainer": "none",
"maintainer_email": "none", "maintainer_email": "",
"port_name_format": "GE1/0/{0}", "port_name_format": "GE1/0/{0}",
"qemu": { "qemu": {
"adapter_type": "e1000", "adapter_type": "e1000",

View File

@ -11,7 +11,7 @@
"status": "experimental", "status": "experimental",
"availability": "service-contract", "availability": "service-contract",
"maintainer": "none", "maintainer": "none",
"maintainer_email": "none", "maintainer_email": "",
"first_port_name": "eth0", "first_port_name": "eth0",
"port_name_format": "Ethernet1/0/{0}", "port_name_format": "Ethernet1/0/{0}",
"qemu": { "qemu": {

View File

@ -11,7 +11,7 @@
"status": "experimental", "status": "experimental",
"availability": "service-contract", "availability": "service-contract",
"maintainer": "none", "maintainer": "none",
"maintainer_email": "none", "maintainer_email": "",
"usage": "Default password is admin. Default username and password for web is admin/Admin@123.", "usage": "Default password is admin. Default username and password for web is admin/Admin@123.",
"first_port_name": "GigabitEthernet0/0/0", "first_port_name": "GigabitEthernet0/0/0",
"port_name_format": "GigabitEthernet1/0/{0}", "port_name_format": "GigabitEthernet1/0/{0}",

View File

@ -12,13 +12,13 @@
"status": "experimental", "status": "experimental",
"maintainer": "none", "maintainer": "none",
"maintainer_email": "developers@gns3.net", "maintainer_email": "developers@gns3.net",
"usage": "Initial username is root, password is root.\n", "usage": "Connect VCP by port Eth1.\nData port ge/xe-x/0/0 to ge/xe-x/0/9 mapping to Eth3 to Eth12.\nInitial username is root, password is root.\n",
"symbol": "juniper-vmx.svg", "symbol": "juniper-vmx.svg",
"first_port_name": "Eth0", "first_port_name": "Eth0",
"port_name_format": "Eth{port1}", "port_name_format": "Eth{port1}",
"qemu": { "qemu": {
"adapter_type": "virtio-net-pci", "adapter_type": "virtio-net-pci",
"adapters": 12, "adapters": 13,
"ram": 4096, "ram": 4096,
"hda_disk_interface": "ide", "hda_disk_interface": "ide",
"arch": "x86_64", "arch": "x86_64",

View File

@ -28,6 +28,18 @@
"options": "-nographic -enable-kvm" "options": "-nographic -enable-kvm"
}, },
"images": [ "images": [
{
"filename": "junos-x86-64-20.4R3.8.img",
"version": "20.4R3.8-KVM",
"md5sum": "69638ba0ad83d7a99a28b658b1dd8def",
"filesize": 2773090304
},
{
"filename": "metadata.img",
"version": "20.4R3.8-KVM",
"md5sum": "ae4e3562aa389929476d82420c79d511",
"filesize": 393216
},
{ {
"filename": "junos-x86-64-20.3R1.8.img", "filename": "junos-x86-64-20.3R1.8.img",
"version": "20.3R1.8-KVM", "version": "20.3R1.8-KVM",
@ -42,6 +54,13 @@
} }
], ],
"versions": [ "versions": [
{
"name": "20.4R3.8-KVM",
"images": {
"hda_disk_image": "junos-x86-64-20.4R3.8.img",
"hdb_disk_image": "metadata.img"
}
},
{ {
"name": "20.3R1.8-KVM", "name": "20.3R1.8-KVM",
"images": { "images": {

View File

@ -28,81 +28,81 @@
}, },
"images": [ "images": [
{ {
"filename": "chr-7.1rc7.img", "filename": "chr-7.4rc2.img",
"version": "7.1rc7", "version": "7.4rc2",
"md5sum": "04bc0ae1e5fbbda1522135bc57cf6560", "md5sum": "ddb107c95cc7d231f8d8bbdb4eebdab6",
"filesize": 134217728, "filesize": 134217728,
"download_url": "http://www.mikrotik.com/download", "download_url": "http://www.mikrotik.com/download",
"direct_download_url": "https://download.mikrotik.com/routeros/7.1rc7/chr-7.1rc7.img.zip", "direct_download_url": "https://download.mikrotik.com/routeros/7.4rc2/chr-7.4rc2.img.zip",
"compression": "zip" "compression": "zip"
}, },
{ {
"filename": "chr-7.1.img", "filename": "chr-7.3.1.img",
"version": "7.1", "version": "7.3.1",
"md5sum": "41545bc7b55717fe5bb1e489ee39ca45", "md5sum": "99f8ea75f8b745a8bf5ca3cc1bd325e3",
"filesize": 134217728, "filesize": 134217728,
"download_url": "http://www.mikrotik.com/download", "download_url": "http://www.mikrotik.com/download",
"direct_download_url": "https://download.mikrotik.com/routeros/7.1/chr-7.1.img.zip", "direct_download_url": "https://download.mikrotik.com/routeros/7.3.1/chr-7.3.1.img.zip",
"compression": "zip" "compression": "zip"
}, },
{ {
"filename": "chr-6.49rc2.img", "filename": "chr-7.1.5.img",
"version": "6.49rc2", "version": "7.1.5",
"md5sum": "e1088f8f64ac3d6ecf2e56ac96261226", "md5sum": "9c0be05f891df2b1400bdae5e719898e",
"filesize": 67108864, "filesize": 134217728,
"download_url": "http://www.mikrotik.com/download", "download_url": "http://www.mikrotik.com/download",
"direct_download_url": "https://download.mikrotik.com/routeros/6.49rc2/chr-6.49rc2.img.zip", "direct_download_url": "https://download.mikrotik.com/routeros/7.1.5/chr-7.1.5.img.zip",
"compression": "zip" "compression": "zip"
}, },
{ {
"filename": "chr-6.49.1.img", "filename": "chr-6.49.6.img",
"version": "6.49.1", "version": "6.49.6",
"md5sum": "6c896c4c853de99f2ea77f0f4b102261", "md5sum": "ae27d38acc9c4dcd875e0f97bcae8d97",
"filesize": 67108864, "filesize": 67108864,
"download_url": "http://www.mikrotik.com/download", "download_url": "http://www.mikrotik.com/download",
"direct_download_url": "https://download.mikrotik.com/routeros/6.49.1/chr-6.49.1.img.zip", "direct_download_url": "https://download.mikrotik.com/routeros/6.49.6/chr-6.49.6.img.zip",
"compression": "zip" "compression": "zip"
}, },
{ {
"filename": "chr-6.48.5.img", "filename": "chr-6.48.6.img",
"version": "6.48.5", "version": "6.48.6",
"md5sum": "d14debd4cd989f16f695b5b075960703", "md5sum": "875574a561570227ff8f395aabe478c6",
"filesize": 67108864, "filesize": 67108864,
"download_url": "http://www.mikrotik.com/download", "download_url": "http://www.mikrotik.com/download",
"direct_download_url": "https://download.mikrotik.com/routeros/6.48.5/chr-6.48.5.img.zip", "direct_download_url": "https://download.mikrotik.com/routeros/6.48.6/chr-6.48.6.img.zip",
"compression": "zip" "compression": "zip"
} }
], ],
"versions": [ "versions": [
{ {
"name": "7.1rc7", "name": "7.4rc2",
"images": { "images": {
"hda_disk_image": "chr-7.1rc7.img" "hda_disk_image": "chr-7.4rc2.img"
} }
}, },
{ {
"name": "7.1", "name": "7.3.1",
"images": { "images": {
"hda_disk_image": "chr-7.1.img" "hda_disk_image": "chr-7.3.1.img"
} }
}, },
{ {
"name": "6.49rc2", "name": "7.1.5",
"images": { "images": {
"hda_disk_image": "chr-6.49rc2.img" "hda_disk_image": "chr-7.1.5.img"
} }
}, },
{ {
"name": "6.49.1", "name": "6.49.6",
"images": { "images": {
"hda_disk_image": "chr-6.49.1.img" "hda_disk_image": "chr-6.49.6.img"
} }
}, },
{ {
"name": "6.48.5", "name": "6.48.6",
"images": { "images": {
"hda_disk_image": "chr-6.48.5.img" "hda_disk_image": "chr-6.48.6.img"
} }
} }
] ]
} }

View File

@ -29,8 +29,8 @@
"version": "0.4", "version": "0.4",
"md5sum": "e678698c97804901c7a53f6b68c8b861", "md5sum": "e678698c97804901c7a53f6b68c8b861",
"filesize": 26476544, "filesize": 26476544,
"download_url": "https://www.b-ehlers.de/projects/netem/index.html", "download_url": "https://sourceforge.net/projects/gns-3/files/Qemu%20Appliances/",
"direct_download_url": "https://www.b-ehlers.de/projects/netem/NETem-v4.qcow2" "direct_download_url": "https://sourceforge.net/projects/gns-3/files/Qemu%20Appliances/NETem-v4.qcow2/download"
} }
], ],
"versions": [ "versions": [

View File

@ -11,7 +11,7 @@
"registry_version": 3, "registry_version": 3,
"status": "stable", "status": "stable",
"maintainer": "Mohamad Siblini", "maintainer": "Mohamad Siblini",
"maintainer_email": "https://www.ictkin.com/contact", "maintainer_email": "info@ictkin.com",
"usage": "Username: gns3\nPassword: gns3 | MD5: 435f15a54f7f673e302ad26f05226e0e", "usage": "Username: gns3\nPassword: gns3 | MD5: 435f15a54f7f673e302ad26f05226e0e",
"port_name_format": "ens{0}", "port_name_format": "ens{0}",
"qemu": { "qemu": {

View File

@ -33,6 +33,7 @@ from gns3server.utils.asyncio.raw_command_server import AsyncioRawCommandServer
from gns3server.utils.asyncio import wait_for_file_creation from gns3server.utils.asyncio import wait_for_file_creation
from gns3server.utils.asyncio import monitor_process from gns3server.utils.asyncio import monitor_process
from gns3server.utils.get_resource import get_resource from gns3server.utils.get_resource import get_resource
from gns3server.utils.hostname import is_rfc1123_hostname_valid
from gns3server.compute.ubridge.ubridge_error import UbridgeError, UbridgeNamespaceError from gns3server.compute.ubridge.ubridge_error import UbridgeError, UbridgeNamespaceError
from ..base_node import BaseNode from ..base_node import BaseNode
@ -89,6 +90,9 @@ class DockerVM(BaseNode):
cpus=0, cpus=0,
): ):
if not is_rfc1123_hostname_valid(name):
raise DockerError(f"'{name}' is an invalid name to create a Docker node")
super().__init__( super().__init__(
name, node_id, project, manager, console=console, console_type=console_type, aux=aux, aux_type=aux_type name, node_id, project, manager, console=console, console_type=console_type, aux=aux, aux_type=aux_type
) )
@ -171,6 +175,18 @@ class DockerVM(BaseNode):
return display return display
display += 1 display += 1
@BaseNode.name.setter
def name(self, new_name):
"""
Sets the name of this Qemu VM.
:param new_name: name
"""
if not is_rfc1123_hostname_valid(new_name):
raise DockerError(f"'{new_name}' is an invalid name to rename Docker container '{self._name}'")
super(DockerVM, DockerVM).name.__set__(self, new_name)
@property @property
def ethernet_adapters(self): def ethernet_adapters(self):
return self._ethernet_adapters return self._ethernet_adapters

View File

@ -37,6 +37,7 @@ from ..dynamips_error import DynamipsError
from gns3server.utils.file_watcher import FileWatcher from gns3server.utils.file_watcher import FileWatcher
from gns3server.utils.asyncio import wait_run_in_executor, monitor_process from gns3server.utils.asyncio import wait_run_in_executor, monitor_process
from gns3server.utils.hostname import is_ios_hostname_valid
from gns3server.utils.images import md5sum from gns3server.utils.images import md5sum
@ -75,6 +76,9 @@ class Router(BaseNode):
ghost_flag=False, ghost_flag=False,
): ):
if not is_ios_hostname_valid(name):
raise DynamipsError(f"{name} is an invalid name to create a Dynamips node")
super().__init__( super().__init__(
name, node_id, project, manager, console=console, console_type=console_type, aux=aux, aux_type=aux_type name, node_id, project, manager, console=console, console_type=console_type, aux=aux, aux_type=aux_type
) )
@ -1653,6 +1657,9 @@ class Router(BaseNode):
:param new_name: new name string :param new_name: new name string
""" """
if not is_ios_hostname_valid(new_name):
raise DynamipsError(f"{new_name} is an invalid name to rename router '{self._name}'")
await self._hypervisor.send(f'vm rename "{self._name}" "{new_name}"') await self._hypervisor.send(f'vm rename "{self._name}" "{new_name}"')
# change the hostname in the startup-config # change the hostname in the startup-config

View File

@ -42,6 +42,7 @@ from .utils.iou_export import nvram_export
from gns3server.compute.ubridge.ubridge_error import UbridgeError from gns3server.compute.ubridge.ubridge_error import UbridgeError
from gns3server.utils.file_watcher import FileWatcher from gns3server.utils.file_watcher import FileWatcher
from gns3server.utils.asyncio.telnet_server import AsyncioTelnetServer from gns3server.utils.asyncio.telnet_server import AsyncioTelnetServer
from gns3server.utils.hostname import is_ios_hostname_valid
from gns3server.utils.asyncio import locking from gns3server.utils.asyncio import locking
import gns3server.utils.asyncio import gns3server.utils.asyncio
import gns3server.utils.images import gns3server.utils.images
@ -70,6 +71,9 @@ class IOUVM(BaseNode):
self, name, node_id, project, manager, application_id=None, path=None, console=None, console_type="telnet" self, name, node_id, project, manager, application_id=None, path=None, console=None, console_type="telnet"
): ):
if not is_ios_hostname_valid(name):
raise IOUError(f"'{name}' is an invalid name to create an IOU node")
super().__init__(name, node_id, project, manager, console=console, console_type=console_type) super().__init__(name, node_id, project, manager, console=console, console_type=console_type)
log.info( log.info(
@ -362,6 +366,8 @@ class IOUVM(BaseNode):
:param new_name: name :param new_name: name
""" """
if not is_ios_hostname_valid(new_name):
raise IOUError(f"'{new_name}' is an invalid name to rename IOU node '{self._name}'")
if self.startup_config_file: if self.startup_config_file:
content = self.startup_config_content content = self.startup_config_content
content = re.sub(r"hostname .+$", "hostname " + new_name, content, flags=re.MULTILINE) content = re.sub(r"hostname .+$", "hostname " + new_name, content, flags=re.MULTILINE)

View File

@ -22,7 +22,6 @@ order to run a QEMU VM.
import sys import sys
import os import os
import re import re
import shlex
import math import math
import shutil import shutil
import struct import struct
@ -47,6 +46,7 @@ from ..base_node import BaseNode
from ...utils.asyncio import monitor_process from ...utils.asyncio import monitor_process
from ...utils.images import md5sum from ...utils.images import md5sum
from ...utils import macaddress_to_int, int_to_macaddress from ...utils import macaddress_to_int, int_to_macaddress
from ...utils.hostname import is_rfc1123_hostname_valid
from gns3server.schemas.compute.qemu_nodes import Qemu, QemuPlatform from gns3server.schemas.compute.qemu_nodes import Qemu, QemuPlatform
@ -86,6 +86,9 @@ class QemuVM(BaseNode):
platform=None, platform=None,
): ):
if not is_rfc1123_hostname_valid(name):
raise QemuError(f"'{name}' is an invalid name to create a Qemu node")
super().__init__( super().__init__(
name, name,
node_id, node_id,
@ -172,6 +175,18 @@ class QemuVM(BaseNode):
log.info(f'QEMU VM "{self._name}" [{self._id}] has been created') log.info(f'QEMU VM "{self._name}" [{self._id}] has been created')
@BaseNode.name.setter
def name(self, new_name):
"""
Sets the name of this Qemu VM.
:param new_name: name
"""
if not is_rfc1123_hostname_valid(new_name):
raise QemuError(f"'{new_name}' is an invalid name to rename Qemu node '{self._name}'")
super(QemuVM, QemuVM).name.__set__(self, new_name)
@property @property
def guest_cid(self): def guest_cid(self):
""" """

View File

@ -23,7 +23,7 @@ import socket
import json import json
import sys import sys
import io import io
from operator import itemgetter from fastapi import HTTPException
from aiohttp import web from aiohttp import web
from ..utils import parse_version from ..utils import parse_version
@ -576,12 +576,13 @@ class Compute:
# If the 409 doesn't come from a GNS3 server # If the 409 doesn't come from a GNS3 server
except ValueError: except ValueError:
raise ControllerError(msg) raise ControllerError(msg)
elif response.status == 500:
raise aiohttp.web.HTTPInternalServerError(text=f"Internal server error {url}")
elif response.status == 503:
raise aiohttp.web.HTTPServiceUnavailable(text=f"Service unavailable {url} {body}")
else: else:
raise NotImplementedError(f"{response.status} status code is not supported for {method} '{url}'\n{body}") raise HTTPException(
status_code=response.status,
detail=f"HTTP error {response.status} received from compute "
f"'{self.name}' for request {method} {path}: {msg}"
)
if body and len(body): if body and len(body):
if raw: if raw:
response.body = body response.body = body

View File

@ -427,6 +427,7 @@ class Node:
# When updating properties used only on controller we don't need to call the compute # When updating properties used only on controller we don't need to call the compute
update_compute = False update_compute = False
old_json = self.asdict() old_json = self.asdict()
old_name = self._name
compute_properties = None compute_properties = None
# Update node properties with additional elements # Update node properties with additional elements
@ -454,7 +455,13 @@ class Node:
self._list_ports() self._list_ports()
if update_compute: if update_compute:
data = self._node_data(properties=compute_properties) data = self._node_data(properties=compute_properties)
response = await self.put(None, data=data) try:
response = await self.put(None, data=data)
except ComputeConflictError:
if old_name != self.name:
# special case when the new name is already updated on controller but refused by the compute
self.name = old_name
raise
await self.parse_node_response(response.json) await self.parse_node_response(response.json)
elif old_json != self.asdict(): elif old_json != self.asdict():
# We send notif only if object has changed # We send notif only if object has changed

View File

@ -90,7 +90,7 @@ async def get_computes(app: FastAPI) -> List[dict]:
def image_filter(change: Change, path: str) -> bool: def image_filter(change: Change, path: str) -> bool:
if change == Change.added: if change == Change.added and os.path.isfile(path):
if path.endswith(".tmp") or path.endswith(".md5sum") or path.startswith(".") or \ if path.endswith(".tmp") or path.endswith(".md5sum") or path.startswith(".") or \
"/lib/" in path or "/lib64/" in path: "/lib/" in path or "/lib64/" in path:
return False return False

View File

@ -0,0 +1,59 @@
#!/usr/bin/env python
#
# Copyright (C) 2022 GNS3 Technologies Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import re
def is_ios_hostname_valid(hostname: str) -> bool:
"""
Check if an IOS hostname is valid
IOS hostname must start with a letter, end with a letter or digit, and
have as interior characters only letters, digits, and hyphens.
They must be 63 characters or fewer (ARPANET rules).
"""
if re.search(r"""^(?!-|[0-9])[a-zA-Z0-9-]{1,63}(?<!-)$""", hostname):
return True
return False
def is_rfc1123_hostname_valid(hostname: str) -> bool:
"""
Check if a hostname is valid according to RFC 1123
Each element of the hostname must be from 1 to 63 characters long
and the entire hostname, including the dots, can be at most 253
characters long. Valid characters for hostnames are ASCII
letters from a to z, the digits from 0 to 9, and the hyphen (-).
A hostname may not start with a hyphen.
"""
if hostname[-1] == ".":
hostname = hostname[:-1] # strip exactly one dot from the right, if present
if len(hostname) > 253:
return False
labels = hostname.split(".")
# the TLD must be not all-numeric
if re.match(r"[0-9]+$", labels[-1]):
return False
allowed = re.compile(r"(?!-)[a-zA-Z0-9-]{1,63}(?<!-)$")
return all(allowed.match(label) for label in labels)

View File

@ -33,7 +33,7 @@ def base_params() -> dict:
"""Return standard parameters""" """Return standard parameters"""
params = { params = {
"name": "PC TEST 1", "name": "DOCKER-TEST-1",
"image": "nginx", "image": "nginx",
"start_command": "nginx-daemon", "start_command": "nginx-daemon",
"adapters": 2, "adapters": 2,
@ -71,10 +71,11 @@ async def test_docker_create(app: FastAPI, compute_client: AsyncClient, compute_
with asyncio_patch("gns3server.compute.docker.Docker.list_images", return_value=[{"image": "nginx"}]): with asyncio_patch("gns3server.compute.docker.Docker.list_images", return_value=[{"image": "nginx"}]):
with asyncio_patch("gns3server.compute.docker.Docker.query", return_value={"Id": "8bd8153ea8f5"}): with asyncio_patch("gns3server.compute.docker.Docker.query", return_value={"Id": "8bd8153ea8f5"}):
response = await compute_client.post(app.url_path_for("compute:create_docker_node", project_id=compute_project.id), response = await compute_client.post(
json=base_params) app.url_path_for("compute:create_docker_node", project_id=compute_project.id), json=base_params
)
assert response.status_code == status.HTTP_201_CREATED assert response.status_code == status.HTTP_201_CREATED
assert response.json()["name"] == "PC TEST 1" assert response.json()["name"] == "DOCKER-TEST-1"
assert response.json()["project_id"] == compute_project.id assert response.json()["project_id"] == compute_project.id
assert response.json()["container_id"] == "8bd8153ea8f5" assert response.json()["container_id"] == "8bd8153ea8f5"
assert response.json()["image"] == "nginx:latest" assert response.json()["image"] == "nginx:latest"
@ -84,6 +85,40 @@ async def test_docker_create(app: FastAPI, compute_client: AsyncClient, compute_
assert response.json()["extra_hosts"] == "test:127.0.0.1" assert response.json()["extra_hosts"] == "test:127.0.0.1"
@pytest.mark.parametrize(
"name, status_code",
(
("valid-name.com", status.HTTP_201_CREATED),
("42name", status.HTTP_201_CREATED),
("424242", status.HTTP_409_CONFLICT),
("name42", status.HTTP_201_CREATED),
("name.424242", status.HTTP_409_CONFLICT),
("-name", status.HTTP_409_CONFLICT),
("name%-test", status.HTTP_409_CONFLICT),
("x" * 63, status.HTTP_201_CREATED),
("x" * 64, status.HTTP_409_CONFLICT),
(("x" * 62 + ".") * 4, status.HTTP_201_CREATED),
("xx" + ("x" * 62 + ".") * 4, status.HTTP_409_CONFLICT),
),
)
async def test_docker_create_with_invalid_name(
app: FastAPI,
compute_client: AsyncClient,
compute_project: Project,
base_params: dict,
name: str,
status_code: int
) -> None:
base_params["name"] = name
with asyncio_patch("gns3server.compute.docker.Docker.list_images", return_value=[{"image": "nginx"}]):
with asyncio_patch("gns3server.compute.docker.Docker.query", return_value={"Id": "8bd8153ea8f5"}):
response = await compute_client.post(
app.url_path_for("compute:create_docker_node", project_id=compute_project.id), json=base_params
)
assert response.status_code == status_code
async def test_docker_start(app: FastAPI, compute_client: AsyncClient, vm: dict) -> None: async def test_docker_start(app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
with asyncio_patch("gns3server.compute.docker.docker_vm.DockerVM.start", return_value=True) as mock: with asyncio_patch("gns3server.compute.docker.docker_vm.DockerVM.start", return_value=True) as mock:

View File

@ -46,7 +46,7 @@ def fake_iou_bin(images_dir) -> str:
def base_params(tmpdir, fake_iou_bin) -> dict: def base_params(tmpdir, fake_iou_bin) -> dict:
"""Return standard parameters""" """Return standard parameters"""
return {"application_id": 42, "name": "PC TEST 1", "path": "iou.bin"} return {"application_id": 42, "name": "IOU-TEST-1", "path": "iou.bin"}
@pytest.fixture @pytest.fixture
@ -68,7 +68,7 @@ async def test_iou_create(app: FastAPI, compute_client: AsyncClient, compute_pro
response = await compute_client.post(app.url_path_for("compute:create_iou_node", project_id=compute_project.id), json=base_params) response = await compute_client.post(app.url_path_for("compute:create_iou_node", project_id=compute_project.id), json=base_params)
assert response.status_code == status.HTTP_201_CREATED assert response.status_code == status.HTTP_201_CREATED
assert response.json()["name"] == "PC TEST 1" assert response.json()["name"] == "IOU-TEST-1"
assert response.json()["project_id"] == compute_project.id assert response.json()["project_id"] == compute_project.id
assert response.json()["serial_adapters"] == 2 assert response.json()["serial_adapters"] == 2
assert response.json()["ethernet_adapters"] == 2 assert response.json()["ethernet_adapters"] == 2
@ -93,7 +93,7 @@ async def test_iou_create_with_params(app: FastAPI,
response = await compute_client.post(app.url_path_for("compute:create_iou_node", project_id=compute_project.id), json=params) response = await compute_client.post(app.url_path_for("compute:create_iou_node", project_id=compute_project.id), json=params)
assert response.status_code == status.HTTP_201_CREATED assert response.status_code == status.HTTP_201_CREATED
assert response.json()["name"] == "PC TEST 1" assert response.json()["name"] == "IOU-TEST-1"
assert response.json()["project_id"] == compute_project.id assert response.json()["project_id"] == compute_project.id
assert response.json()["serial_adapters"] == 4 assert response.json()["serial_adapters"] == 4
assert response.json()["ethernet_adapters"] == 0 assert response.json()["ethernet_adapters"] == 0
@ -106,6 +106,34 @@ async def test_iou_create_with_params(app: FastAPI,
assert f.read() == "hostname test" assert f.read() == "hostname test"
@pytest.mark.parametrize(
"name, status_code",
(
("valid-name", status.HTTP_201_CREATED),
("42name", status.HTTP_409_CONFLICT),
("name42", status.HTTP_201_CREATED),
("-name", status.HTTP_409_CONFLICT),
("name%-test", status.HTTP_409_CONFLICT),
("x" * 63, status.HTTP_201_CREATED),
("x" * 64, status.HTTP_409_CONFLICT),
),
)
async def test_iou_create_with_invalid_name(
app: FastAPI,
compute_client: AsyncClient,
compute_project: Project,
base_params: dict,
name: str,
status_code: int
) -> None:
base_params["name"] = name
response = await compute_client.post(
app.url_path_for("compute:create_iou_node", project_id=compute_project.id), json=base_params
)
assert response.status_code == status_code
async def test_iou_create_startup_config_already_exist( async def test_iou_create_startup_config_already_exist(
app: FastAPI, app: FastAPI,
compute_client: AsyncClient, compute_client: AsyncClient,
@ -133,7 +161,7 @@ async def test_iou_get(app: FastAPI, compute_client: AsyncClient, compute_projec
response = await compute_client.get(app.url_path_for("compute:get_iou_node", project_id=vm["project_id"], node_id=vm["node_id"])) response = await compute_client.get(app.url_path_for("compute:get_iou_node", project_id=vm["project_id"], node_id=vm["node_id"]))
assert response.status_code == status.HTTP_200_OK assert response.status_code == status.HTTP_200_OK
assert response.json()["name"] == "PC TEST 1" assert response.json()["name"] == "IOU-TEST-1"
assert response.json()["project_id"] == compute_project.id assert response.json()["project_id"] == compute_project.id
assert response.json()["serial_adapters"] == 2 assert response.json()["serial_adapters"] == 2
assert response.json()["ethernet_adapters"] == 2 assert response.json()["ethernet_adapters"] == 2

View File

@ -66,7 +66,7 @@ def fake_qemu_img_binary(tmpdir):
def base_params(tmpdir, fake_qemu_bin) -> dict: def base_params(tmpdir, fake_qemu_bin) -> dict:
"""Return standard parameters""" """Return standard parameters"""
return {"name": "PC TEST 1", "qemu_path": fake_qemu_bin} return {"name": "QEMU-TEST-1", "qemu_path": fake_qemu_bin}
@pytest.fixture @pytest.fixture
@ -88,7 +88,7 @@ async def test_qemu_create(app: FastAPI,
response = await compute_client.post(app.url_path_for("compute:create_qemu_node", project_id=compute_project.id), json=base_params) response = await compute_client.post(app.url_path_for("compute:create_qemu_node", project_id=compute_project.id), json=base_params)
assert response.status_code == status.HTTP_201_CREATED assert response.status_code == status.HTTP_201_CREATED
assert response.json()["name"] == "PC TEST 1" assert response.json()["name"] == "QEMU-TEST-1"
assert response.json()["project_id"] == compute_project.id assert response.json()["project_id"] == compute_project.id
assert response.json()["qemu_path"] == fake_qemu_bin assert response.json()["qemu_path"] == fake_qemu_bin
assert response.json()["platform"] == "x86_64" assert response.json()["platform"] == "x86_64"
@ -104,7 +104,7 @@ async def test_qemu_create_platform(app: FastAPI,
base_params["platform"] = "x86_64" base_params["platform"] = "x86_64"
response = await compute_client.post(app.url_path_for("compute:create_qemu_node", project_id=compute_project.id), json=base_params) response = await compute_client.post(app.url_path_for("compute:create_qemu_node", project_id=compute_project.id), json=base_params)
assert response.status_code == status.HTTP_201_CREATED assert response.status_code == status.HTTP_201_CREATED
assert response.json()["name"] == "PC TEST 1" assert response.json()["name"] == "QEMU-TEST-1"
assert response.json()["project_id"] == compute_project.id assert response.json()["project_id"] == compute_project.id
assert response.json()["qemu_path"] == fake_qemu_bin assert response.json()["qemu_path"] == fake_qemu_bin
assert response.json()["platform"] == "x86_64" assert response.json()["platform"] == "x86_64"
@ -122,13 +122,44 @@ async def test_qemu_create_with_params(app: FastAPI,
params["hda_disk_image"] = "linux载.img" params["hda_disk_image"] = "linux载.img"
response = await compute_client.post(app.url_path_for("compute:create_qemu_node", project_id=compute_project.id), json=params) response = await compute_client.post(app.url_path_for("compute:create_qemu_node", project_id=compute_project.id), json=params)
assert response.status_code == status.HTTP_201_CREATED assert response.status_code == status.HTTP_201_CREATED
assert response.json()["name"] == "PC TEST 1" assert response.json()["name"] == "QEMU-TEST-1"
assert response.json()["project_id"] == compute_project.id assert response.json()["project_id"] == compute_project.id
assert response.json()["ram"] == 1024 assert response.json()["ram"] == 1024
assert response.json()["hda_disk_image"] == "linux载.img" assert response.json()["hda_disk_image"] == "linux载.img"
assert response.json()["hda_disk_image_md5sum"] == "c4ca4238a0b923820dcc509a6f75849b" assert response.json()["hda_disk_image_md5sum"] == "c4ca4238a0b923820dcc509a6f75849b"
@pytest.mark.parametrize(
"name, status_code",
(
("valid-name.com", status.HTTP_201_CREATED),
("42name", status.HTTP_201_CREATED),
("424242", status.HTTP_409_CONFLICT),
("name42", status.HTTP_201_CREATED),
("name.424242", status.HTTP_409_CONFLICT),
("-name", status.HTTP_409_CONFLICT),
("name%-test", status.HTTP_409_CONFLICT),
("x" * 63, status.HTTP_201_CREATED),
("x" * 64, status.HTTP_409_CONFLICT),
(("x" * 62 + ".") * 4, status.HTTP_201_CREATED),
("xx" + ("x" * 62 + ".") * 4, status.HTTP_409_CONFLICT),
),
)
async def test_qemu_create_with_invalid_name(
app: FastAPI,
compute_client: AsyncClient,
compute_project: Project,
base_params: dict,
name: str,
status_code: int
) -> None:
base_params["name"] = name
response = await compute_client.post(
app.url_path_for("compute:create_qemu_node", project_id=compute_project.id), json=base_params
)
assert response.status_code == status_code
# async def test_qemu_create_with_project_file(app: FastAPI, # async def test_qemu_create_with_project_file(app: FastAPI,
# compute_client: AsyncClient, # compute_client: AsyncClient,
# compute_project: Project, # compute_project: Project,
@ -157,7 +188,7 @@ async def test_qemu_get(app: FastAPI, compute_client: AsyncClient, compute_proje
app.url_path_for("compute:get_qemu_node", project_id=qemu_vm["project_id"], node_id=qemu_vm["node_id"]) app.url_path_for("compute:get_qemu_node", project_id=qemu_vm["project_id"], node_id=qemu_vm["node_id"])
) )
assert response.status_code == status.HTTP_200_OK assert response.status_code == status.HTTP_200_OK
assert response.json()["name"] == "PC TEST 1" assert response.json()["name"] == "QEMU-TEST-1"
assert response.json()["project_id"] == compute_project.id assert response.json()["project_id"] == compute_project.id
assert response.json()["node_directory"] == os.path.join( assert response.json()["node_directory"] == os.path.join(
compute_project.path, compute_project.path,