@ -20,15 +20,17 @@ API routes for Qemu nodes.
import os
from fastapi import APIRouter , WebSocket , Depends , Body , Path , Response, status
from fastapi import APIRouter , WebSocket , Depends , Body , Path , status
from fastapi . encoders import jsonable_encoder
from fastapi . responses import StreamingResponse
from typing import Union
from uuid import UUID
from gns3server import schemas
from gns3server . compute . qemu import Qemu
from gns3server . compute . qemu . qemu_vm import QemuVM
from . dependencies . authentication import compute_authentication , ws_compute_authentication
responses = { 404 : { " model " : schemas . ErrorMessage , " description " : " Could not find project or Qemu node " } }
@ -50,6 +52,7 @@ def dep_node(project_id: UUID, node_id: UUID) -> QemuVM:
response_model = schemas . Qemu ,
status_code = status . HTTP_201_CREATED ,
responses = { 409 : { " model " : schemas . ErrorMessage , " description " : " Could not create Qemu node " } } ,
dependencies = [ Depends ( compute_authentication ) ]
)
async def create_qemu_node ( project_id : UUID , node_data : schemas . QemuCreate ) - > schemas . Qemu :
"""
@ -78,7 +81,11 @@ async def create_qemu_node(project_id: UUID, node_data: schemas.QemuCreate) -> s
return vm . asdict ( )
@router.get ( " / {node_id} " , response_model = schemas . Qemu )
@router.get (
" / {node_id} " ,
response_model = schemas . Qemu ,
dependencies = [ Depends ( compute_authentication ) ]
)
def get_qemu_node ( node : QemuVM = Depends ( dep_node ) ) - > schemas . Qemu :
"""
Return a Qemu node .
@ -87,7 +94,11 @@ def get_qemu_node(node: QemuVM = Depends(dep_node)) -> schemas.Qemu:
return node . asdict ( )
@router.put ( " / {node_id} " , response_model = schemas . Qemu )
@router.put (
" / {node_id} " ,
response_model = schemas . Qemu ,
dependencies = [ Depends ( compute_authentication ) ]
)
async def update_qemu_node ( node_data : schemas . QemuUpdate , node : QemuVM = Depends ( dep_node ) ) - > schemas . Qemu :
"""
Update a Qemu node .
@ -103,7 +114,11 @@ async def update_qemu_node(node_data: schemas.QemuUpdate, node: QemuVM = Depends
return node . asdict ( )
@router.delete ( " / {node_id} " , status_code = status . HTTP_204_NO_CONTENT )
@router.delete (
" / {node_id} " ,
status_code = status . HTTP_204_NO_CONTENT ,
dependencies = [ Depends ( compute_authentication ) ]
)
async def delete_qemu_node ( node : QemuVM = Depends ( dep_node ) ) - > None :
"""
Delete a Qemu node .
@ -112,7 +127,12 @@ async def delete_qemu_node(node: QemuVM = Depends(dep_node)) -> None:
await Qemu . instance ( ) . delete_node ( node . id )
@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 ,
dependencies = [ Depends ( compute_authentication ) ]
)
async def duplicate_qemu_node (
destination_node_id : UUID = Body ( . . . , embed = True ) ,
node : QemuVM = Depends ( dep_node )
@ -127,7 +147,8 @@ async def duplicate_qemu_node(
@router.post (
" / {node_id} /disk_image/ {disk_name} " ,
status_code = status . HTTP_204_NO_CONTENT
status_code = status . HTTP_204_NO_CONTENT ,
dependencies = [ Depends ( compute_authentication ) ]
)
async def create_qemu_disk_image (
disk_name : str ,
@ -144,7 +165,8 @@ async def create_qemu_disk_image(
@router.put (
" / {node_id} /disk_image/ {disk_name} " ,
status_code = status . HTTP_204_NO_CONTENT
status_code = status . HTTP_204_NO_CONTENT ,
dependencies = [ Depends ( compute_authentication ) ]
)
async def update_qemu_disk_image (
disk_name : str ,
@ -161,7 +183,8 @@ async def update_qemu_disk_image(
@router.delete (
" / {node_id} /disk_image/ {disk_name} " ,
status_code = status . HTTP_204_NO_CONTENT
status_code = status . HTTP_204_NO_CONTENT ,
dependencies = [ Depends ( compute_authentication ) ]
)
async def delete_qemu_disk_image (
disk_name : str ,
@ -174,7 +197,11 @@ async def delete_qemu_disk_image(
node . delete_disk_image ( disk_name )
@router.post ( " / {node_id} /start " , status_code = status . HTTP_204_NO_CONTENT )
@router.post (
" / {node_id} /start " ,
status_code = status . HTTP_204_NO_CONTENT ,
dependencies = [ Depends ( compute_authentication ) ]
)
async def start_qemu_node ( node : QemuVM = Depends ( dep_node ) ) - > None :
"""
Start a Qemu node .
@ -183,7 +210,11 @@ async def start_qemu_node(node: QemuVM = Depends(dep_node)) -> None:
await node . start ( )
@router.post ( " / {node_id} /stop " , status_code = status . HTTP_204_NO_CONTENT )
@router.post (
" / {node_id} /stop " ,
status_code = status . HTTP_204_NO_CONTENT ,
dependencies = [ Depends ( compute_authentication ) ]
)
async def stop_qemu_node ( node : QemuVM = Depends ( dep_node ) ) - > None :
"""
Stop a Qemu node .
@ -192,7 +223,11 @@ async def stop_qemu_node(node: QemuVM = Depends(dep_node)) -> None:
await node . stop ( )
@router.post ( " / {node_id} /reload " , status_code = status . HTTP_204_NO_CONTENT )
@router.post (
" / {node_id} /reload " ,
status_code = status . HTTP_204_NO_CONTENT ,
dependencies = [ Depends ( compute_authentication ) ]
)
async def reload_qemu_node ( node : QemuVM = Depends ( dep_node ) ) - > None :
"""
Reload a Qemu node .
@ -201,7 +236,11 @@ async def reload_qemu_node(node: QemuVM = Depends(dep_node)) -> None:
await node . reload ( )
@router.post ( " / {node_id} /suspend " , status_code = status . HTTP_204_NO_CONTENT )
@router.post (
" / {node_id} /suspend " ,
status_code = status . HTTP_204_NO_CONTENT ,
dependencies = [ Depends ( compute_authentication ) ]
)
async def suspend_qemu_node ( node : QemuVM = Depends ( dep_node ) ) - > None :
"""
Suspend a Qemu node .
@ -210,7 +249,11 @@ async def suspend_qemu_node(node: QemuVM = Depends(dep_node)) -> None:
await node . suspend ( )
@router.post ( " / {node_id} /resume " , status_code = status . HTTP_204_NO_CONTENT )
@router.post (
" / {node_id} /resume " ,
status_code = status . HTTP_204_NO_CONTENT ,
dependencies = [ Depends ( compute_authentication ) ]
)
async def resume_qemu_node ( node : QemuVM = Depends ( dep_node ) ) - > None :
"""
Resume a Qemu node .
@ -223,6 +266,7 @@ async def resume_qemu_node(node: QemuVM = Depends(dep_node)) -> None:
" / {node_id} /adapters/ {adapter_number} /ports/ {port_number} /nio " ,
status_code = status . HTTP_201_CREATED ,
response_model = schemas . UDPNIO ,
dependencies = [ Depends ( compute_authentication ) ]
)
async def create_qemu_node_nio (
* ,
@ -245,6 +289,7 @@ async def create_qemu_node_nio(
" / {node_id} /adapters/ {adapter_number} /ports/ {port_number} /nio " ,
status_code = status . HTTP_201_CREATED ,
response_model = schemas . UDPNIO ,
dependencies = [ Depends ( compute_authentication ) ]
)
async def update_qemu_node_nio (
* ,
@ -267,7 +312,11 @@ async def update_qemu_node_nio(
return nio . asdict ( )
@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 ,
dependencies = [ Depends ( compute_authentication ) ]
)
async def delete_qemu_node_nio (
adapter_number : int ,
port_number : int = Path ( . . . , ge = 0 , le = 0 ) ,
@ -281,7 +330,10 @@ async def delete_qemu_node_nio(
await node . adapter_remove_nio_binding ( adapter_number )
@router.post ( " / {node_id} /adapters/ {adapter_number} /ports/ {port_number} /capture/start " )
@router.post (
" / {node_id} /adapters/ {adapter_number} /ports/ {port_number} /capture/start " ,
dependencies = [ Depends ( compute_authentication ) ]
)
async def start_qemu_node_capture (
* ,
adapter_number : int ,
@ -300,7 +352,9 @@ async def start_qemu_node_capture(
@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 ,
dependencies = [ Depends ( compute_authentication ) ]
)
async def stop_qemu_node_capture (
adapter_number : int ,
@ -315,7 +369,10 @@ async def stop_qemu_node_capture(
await node . stop_capture ( adapter_number )
@router.get ( " / {node_id} /adapters/ {adapter_number} /ports/ {port_number} /capture/stream " )
@router.get (
" / {node_id} /adapters/ {adapter_number} /ports/ {port_number} /capture/stream " ,
dependencies = [ Depends ( compute_authentication ) ]
)
async def stream_pcap_file (
adapter_number : int ,
port_number : int = Path ( . . . , ge = 0 , le = 0 ) ,
@ -330,16 +387,26 @@ async def stream_pcap_file(
return StreamingResponse ( stream , media_type = " application/vnd.tcpdump.pcap " )
@router.websocket ( " / {node_id} /console/ws " )
async def console_ws ( websocket : WebSocket , node : QemuVM = Depends ( dep_node ) ) - > None :
@router.websocket (
" / {node_id} /console/ws "
)
async def console_ws (
websocket : Union [ None , WebSocket ] = Depends ( ws_compute_authentication ) ,
node : QemuVM = Depends ( dep_node )
) - > None :
"""
Console WebSocket .
"""
await node . start_websocket_console ( websocket )
if websocket :
await node . start_websocket_console ( websocket )
@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 ,
dependencies = [ Depends ( compute_authentication ) ]
)
async def reset_console ( node : QemuVM = Depends ( dep_node ) ) - > None :
await node . reset_console ( )