2015-02-19 18:43:45 +00:00
# -*- coding: utf-8 -*-
#
# Copyright (C) 2015 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/>.
2015-07-22 04:58:28 +00:00
import sys
2015-07-28 14:05:48 +00:00
import os . path
2017-11-13 21:12:39 +00:00
import aiohttp . web
2016-05-14 00:00:07 +00:00
from gns3server . web . route import Route
from gns3server . compute . project_manager import ProjectManager
from gns3server . schemas . nio import NIO_SCHEMA
from gns3server . compute . qemu import Qemu
from gns3server . config import Config
2016-06-23 22:56:06 +00:00
from gns3server . schemas . node import (
NODE_LIST_IMAGES_SCHEMA ,
NODE_CAPTURE_SCHEMA
)
2016-05-14 00:00:07 +00:00
from gns3server . schemas . qemu import (
QEMU_CREATE_SCHEMA ,
QEMU_UPDATE_SCHEMA ,
QEMU_OBJECT_SCHEMA ,
2018-03-26 11:05:49 +00:00
QEMU_RESIZE_SCHEMA ,
2016-05-14 00:00:07 +00:00
QEMU_BINARY_LIST_SCHEMA ,
QEMU_BINARY_FILTER_SCHEMA ,
QEMU_CAPABILITY_LIST_SCHEMA ,
2018-03-26 11:05:49 +00:00
QEMU_IMAGE_CREATE_SCHEMA ,
QEMU_IMAGE_UPDATE_SCHEMA
2016-05-14 00:00:07 +00:00
)
2015-02-19 18:43:45 +00:00
class QEMUHandler :
"""
API entry points for QEMU .
"""
@Route.post (
2016-05-11 17:35:36 +00:00
r " /projects/ {project_id} /qemu/nodes " ,
2015-02-19 18:43:45 +00:00
parameters = {
2016-05-14 00:00:07 +00:00
" project_id " : " Project UUID "
2015-02-19 18:43:45 +00:00
} ,
status_codes = {
201 : " Instance created " ,
400 : " Invalid request " ,
409 : " Conflict "
} ,
2015-04-12 21:09:37 +00:00
description = " Create a new Qemu VM instance " ,
2015-02-19 18:43:45 +00:00
input = QEMU_CREATE_SCHEMA ,
output = QEMU_OBJECT_SCHEMA )
2018-10-15 10:05:49 +00:00
async def create ( request , response ) :
2015-02-19 18:43:45 +00:00
qemu = Qemu . instance ( )
2018-10-15 10:05:49 +00:00
vm = await qemu . create_node ( request . json . pop ( " name " ) ,
2016-05-11 17:35:36 +00:00
request . match_info [ " project_id " ] ,
request . json . pop ( " node_id " , None ) ,
linked_clone = request . json . get ( " linked_clone " , True ) ,
qemu_path = request . json . pop ( " qemu_path " , None ) ,
console = request . json . pop ( " console " , None ) ,
console_type = request . json . pop ( " console_type " , " telnet " ) ,
platform = request . json . pop ( " platform " , None ) )
2015-03-16 18:45:21 +00:00
2015-04-12 21:09:37 +00:00
for name , value in request . json . items ( ) :
if hasattr ( vm , name ) and getattr ( vm , name ) != value :
setattr ( vm , name , value )
2015-02-19 19:22:30 +00:00
2015-02-19 18:43:45 +00:00
response . set_status ( 201 )
response . json ( vm )
@Route.get (
2016-05-11 17:35:36 +00:00
r " /projects/ {project_id} /qemu/nodes/ {node_id} " ,
2015-02-19 18:43:45 +00:00
parameters = {
2016-05-14 00:00:07 +00:00
" project_id " : " Project UUID " ,
" node_id " : " Node UUID "
2015-02-19 18:43:45 +00:00
} ,
status_codes = {
200 : " Success " ,
400 : " Invalid request " ,
404 : " Instance doesn ' t exist "
} ,
2015-04-12 21:09:37 +00:00
description = " Get a Qemu VM instance " ,
2015-02-19 18:43:45 +00:00
output = QEMU_OBJECT_SCHEMA )
def show ( request , response ) :
qemu_manager = Qemu . instance ( )
2016-05-11 17:35:36 +00:00
vm = qemu_manager . get_node ( request . match_info [ " node_id " ] , project_id = request . match_info [ " project_id " ] )
2015-02-19 18:43:45 +00:00
response . json ( vm )
@Route.put (
2016-05-11 17:35:36 +00:00
r " /projects/ {project_id} /qemu/nodes/ {node_id} " ,
2015-02-19 18:43:45 +00:00
parameters = {
2016-05-14 00:00:07 +00:00
" project_id " : " Project UUID " ,
" node_id " : " Node UUID "
2015-02-19 18:43:45 +00:00
} ,
status_codes = {
200 : " Instance updated " ,
400 : " Invalid request " ,
404 : " Instance doesn ' t exist " ,
409 : " Conflict "
} ,
2015-04-12 21:09:37 +00:00
description = " Update a Qemu VM instance " ,
2015-02-19 18:43:45 +00:00
input = QEMU_UPDATE_SCHEMA ,
output = QEMU_OBJECT_SCHEMA )
2019-06-12 12:23:03 +00:00
async def update ( request , response ) :
2015-02-19 18:43:45 +00:00
qemu_manager = Qemu . instance ( )
2016-05-11 17:35:36 +00:00
vm = qemu_manager . get_node ( request . match_info [ " node_id " ] , project_id = request . match_info [ " project_id " ] )
2018-06-09 14:47:36 +00:00
# update the console first to avoid issue if updating console type
vm . console = request . json . pop ( " console " , vm . console )
2015-04-12 21:09:37 +00:00
for name , value in request . json . items ( ) :
if hasattr ( vm , name ) and getattr ( vm , name ) != value :
2020-10-06 06:38:51 +00:00
await vm . update_property ( name , value )
2016-05-18 09:00:35 +00:00
vm . updated ( )
2015-02-19 18:43:45 +00:00
response . json ( vm )
@Route.delete (
2016-05-11 17:35:36 +00:00
r " /projects/ {project_id} /qemu/nodes/ {node_id} " ,
2015-02-19 18:43:45 +00:00
parameters = {
2016-05-14 00:00:07 +00:00
" project_id " : " Project UUID " ,
" node_id " : " Node UUID "
2015-02-19 18:43:45 +00:00
} ,
status_codes = {
204 : " Instance deleted " ,
400 : " Invalid request " ,
404 : " Instance doesn ' t exist "
} ,
2015-04-12 21:09:37 +00:00
description = " Delete a Qemu VM instance " )
2018-10-15 10:05:49 +00:00
async def delete ( request , response ) :
2015-02-19 18:43:45 +00:00
2018-10-15 10:05:49 +00:00
await Qemu . instance ( ) . delete_node ( request . match_info [ " node_id " ] )
2015-02-19 18:43:45 +00:00
response . set_status ( 204 )
2017-07-25 08:01:03 +00:00
@Route.post (
r " /projects/ {project_id} /qemu/nodes/ {node_id} /duplicate " ,
parameters = {
" project_id " : " Project UUID " ,
" node_id " : " Node UUID "
} ,
status_codes = {
201 : " Instance duplicated " ,
404 : " Instance doesn ' t exist "
} ,
description = " Duplicate a Qemu instance " )
2018-10-15 10:05:49 +00:00
async def duplicate ( request , response ) :
2017-07-25 08:01:03 +00:00
2018-10-15 10:05:49 +00:00
new_node = await Qemu . instance ( ) . duplicate_node (
2017-07-25 08:01:03 +00:00
request . match_info [ " node_id " ] ,
request . json [ " destination_node_id " ]
)
response . set_status ( 201 )
response . json ( new_node )
2018-03-26 11:05:49 +00:00
@Route.post (
r " /projects/ {project_id} /qemu/nodes/ {node_id} /resize_disk " ,
parameters = {
" project_id " : " Project UUID " ,
" node_id " : " Node UUID "
} ,
status_codes = {
201 : " Instance updated " ,
404 : " Instance doesn ' t exist "
} ,
description = " Resize a Qemu VM disk image " ,
input = QEMU_RESIZE_SCHEMA )
2018-10-15 10:05:49 +00:00
async def resize_disk ( request , response ) :
2018-03-26 11:05:49 +00:00
qemu_manager = Qemu . instance ( )
vm = qemu_manager . get_node ( request . match_info [ " node_id " ] , project_id = request . match_info [ " project_id " ] )
2018-10-15 10:05:49 +00:00
await vm . resize_disk ( request . json [ " drive_name " ] , request . json [ " extend " ] )
2018-03-26 11:05:49 +00:00
response . set_status ( 201 )
2015-02-19 18:43:45 +00:00
@Route.post (
2016-05-11 17:35:36 +00:00
r " /projects/ {project_id} /qemu/nodes/ {node_id} /start " ,
2015-02-19 18:43:45 +00:00
parameters = {
2016-05-14 00:00:07 +00:00
" project_id " : " Project UUID " ,
" node_id " : " Node UUID "
2015-02-19 18:43:45 +00:00
} ,
status_codes = {
2016-02-02 17:25:17 +00:00
200 : " Instance started " ,
2015-02-19 18:43:45 +00:00
400 : " Invalid request " ,
404 : " Instance doesn ' t exist "
} ,
2016-02-02 17:25:17 +00:00
description = " Start a Qemu VM instance " ,
output = QEMU_OBJECT_SCHEMA )
2018-10-15 10:05:49 +00:00
async def start ( request , response ) :
2015-02-19 18:43:45 +00:00
qemu_manager = Qemu . instance ( )
2016-05-11 17:35:36 +00:00
vm = qemu_manager . get_node ( request . match_info [ " node_id " ] , project_id = request . match_info [ " project_id " ] )
2018-03-21 09:41:25 +00:00
hardware_accel = qemu_manager . config . get_section_config ( " Qemu " ) . getboolean ( " enable_hardware_acceleration " , True )
if sys . platform . startswith ( " linux " ) :
# the enable_kvm option was used before version 2.0 and has priority
enable_kvm = qemu_manager . config . get_section_config ( " Qemu " ) . getboolean ( " enable_kvm " )
if enable_kvm is not None :
hardware_accel = enable_kvm
2021-07-27 07:04:51 +00:00
if hardware_accel and " -machine accel=tcg " not in vm . options :
2015-07-22 04:58:28 +00:00
pm = ProjectManager . instance ( )
if pm . check_hardware_virtualization ( vm ) is False :
2018-03-21 09:41:25 +00:00
raise aiohttp . web . HTTPConflict ( text = " Cannot start VM with hardware acceleration (KVM/HAX) enabled because hardware virtualization (VT-x/AMD-V) is already used by another software like VMware or VirtualBox " )
2018-10-15 10:05:49 +00:00
await vm . start ( )
2016-02-02 17:25:17 +00:00
response . json ( vm )
2015-02-19 18:43:45 +00:00
@Route.post (
2016-05-11 17:35:36 +00:00
r " /projects/ {project_id} /qemu/nodes/ {node_id} /stop " ,
2015-02-19 18:43:45 +00:00
parameters = {
2016-05-14 00:00:07 +00:00
" project_id " : " Project UUID " ,
" node_id " : " Node UUID "
2015-02-19 18:43:45 +00:00
} ,
status_codes = {
204 : " Instance stopped " ,
400 : " Invalid request " ,
404 : " Instance doesn ' t exist "
} ,
2015-04-12 21:09:37 +00:00
description = " Stop a Qemu VM instance " )
2018-10-15 10:05:49 +00:00
async def stop ( request , response ) :
2015-02-19 18:43:45 +00:00
qemu_manager = Qemu . instance ( )
2016-05-11 17:35:36 +00:00
vm = qemu_manager . get_node ( request . match_info [ " node_id " ] , project_id = request . match_info [ " project_id " ] )
2018-10-15 10:05:49 +00:00
await vm . stop ( )
2015-02-19 18:43:45 +00:00
response . set_status ( 204 )
@Route.post (
2016-05-11 17:35:36 +00:00
r " /projects/ {project_id} /qemu/nodes/ {node_id} /reload " ,
2015-02-19 18:43:45 +00:00
parameters = {
2016-05-14 00:00:07 +00:00
" project_id " : " Project UUID " ,
" node_id " : " Node UUID " ,
2015-02-19 18:43:45 +00:00
} ,
status_codes = {
204 : " Instance reloaded " ,
400 : " Invalid request " ,
404 : " Instance doesn ' t exist "
} ,
2015-04-12 21:09:37 +00:00
description = " Reload a Qemu VM instance " )
2018-10-15 10:05:49 +00:00
async def reload ( request , response ) :
2015-02-19 18:43:45 +00:00
qemu_manager = Qemu . instance ( )
2016-05-11 17:35:36 +00:00
vm = qemu_manager . get_node ( request . match_info [ " node_id " ] , project_id = request . match_info [ " project_id " ] )
2018-10-15 10:05:49 +00:00
await vm . reload ( )
2015-02-19 18:43:45 +00:00
response . set_status ( 204 )
@Route.post (
2016-05-11 17:35:36 +00:00
r " /projects/ {project_id} /qemu/nodes/ {node_id} /suspend " ,
2015-02-19 18:43:45 +00:00
parameters = {
2016-05-14 00:00:07 +00:00
" project_id " : " Project UUID " ,
" node_id " : " Node UUID " ,
2015-02-19 18:43:45 +00:00
} ,
status_codes = {
204 : " Instance suspended " ,
400 : " Invalid request " ,
404 : " Instance doesn ' t exist "
} ,
2015-04-12 21:09:37 +00:00
description = " Suspend a Qemu VM instance " )
2018-10-15 10:05:49 +00:00
async def suspend ( request , response ) :
2015-02-19 18:43:45 +00:00
qemu_manager = Qemu . instance ( )
2016-05-11 17:35:36 +00:00
vm = qemu_manager . get_node ( request . match_info [ " node_id " ] , project_id = request . match_info [ " project_id " ] )
2018-10-15 10:05:49 +00:00
await vm . suspend ( )
2015-02-19 18:43:45 +00:00
response . set_status ( 204 )
2015-02-20 23:15:56 +00:00
@Route.post (
2016-05-11 17:35:36 +00:00
r " /projects/ {project_id} /qemu/nodes/ {node_id} /resume " ,
2015-02-20 23:15:56 +00:00
parameters = {
2016-05-14 00:00:07 +00:00
" project_id " : " Project UUID " ,
" node_id " : " Node UUID " ,
2015-02-20 23:15:56 +00:00
} ,
status_codes = {
204 : " Instance resumed " ,
400 : " Invalid request " ,
404 : " Instance doesn ' t exist "
} ,
2015-04-12 21:09:37 +00:00
description = " Resume a Qemu VM instance " )
2018-10-15 10:05:49 +00:00
async def resume ( request , response ) :
2015-02-20 23:15:56 +00:00
qemu_manager = Qemu . instance ( )
2016-05-11 17:35:36 +00:00
vm = qemu_manager . get_node ( request . match_info [ " node_id " ] , project_id = request . match_info [ " project_id " ] )
2018-10-15 10:05:49 +00:00
await vm . resume ( )
2015-02-20 23:15:56 +00:00
response . set_status ( 204 )
2015-02-19 18:43:45 +00:00
@Route.post (
2016-05-11 17:35:36 +00:00
r " /projects/ {project_id} /qemu/nodes/ {node_id} /adapters/ { adapter_number: \ d+}/ports/ { port_number: \ d+}/nio " ,
2015-02-19 18:43:45 +00:00
parameters = {
2016-05-14 00:00:07 +00:00
" project_id " : " Project UUID " ,
" node_id " : " Node UUID " ,
2015-02-19 18:43:45 +00:00
" adapter_number " : " Network adapter where the nio is located " ,
2015-03-07 03:08:00 +00:00
" port_number " : " Port on the adapter (always 0) "
2015-02-19 18:43:45 +00:00
} ,
status_codes = {
201 : " NIO created " ,
400 : " Invalid request " ,
404 : " Instance doesn ' t exist "
} ,
2015-04-12 21:09:37 +00:00
description = " Add a NIO to a Qemu VM instance " ,
2015-04-27 20:19:17 +00:00
input = NIO_SCHEMA ,
output = NIO_SCHEMA )
2018-10-15 10:05:49 +00:00
async def create_nio ( request , response ) :
2015-02-19 18:43:45 +00:00
qemu_manager = Qemu . instance ( )
2016-05-11 17:35:36 +00:00
vm = qemu_manager . get_node ( request . match_info [ " node_id " ] , project_id = request . match_info [ " project_id " ] )
2015-04-27 20:19:17 +00:00
nio_type = request . json [ " type " ]
2018-03-19 09:26:12 +00:00
if nio_type not in ( " nio_udp " ) :
2017-11-13 21:12:39 +00:00
raise aiohttp . web . HTTPConflict ( text = " NIO of type {} is not supported " . format ( nio_type ) )
2016-06-25 00:35:39 +00:00
nio = qemu_manager . create_nio ( request . json )
2018-10-15 10:05:49 +00:00
await vm . adapter_add_nio_binding ( int ( request . match_info [ " adapter_number " ] ) , nio )
2015-02-19 18:43:45 +00:00
response . set_status ( 201 )
response . json ( nio )
2017-07-12 12:50:33 +00:00
@Route.put (
r " /projects/ {project_id} /qemu/nodes/ {node_id} /adapters/ { adapter_number: \ d+}/ports/ { port_number: \ d+}/nio " ,
parameters = {
" project_id " : " Project UUID " ,
" node_id " : " Node UUID " ,
" adapter_number " : " Network adapter where the nio is located " ,
" port_number " : " Port from where the nio should be updated "
} ,
status_codes = {
201 : " NIO updated " ,
400 : " Invalid request " ,
404 : " Instance doesn ' t exist "
} ,
input = NIO_SCHEMA ,
output = NIO_SCHEMA ,
2018-10-27 07:47:17 +00:00
description = " Update a NIO on a Qemu instance " )
2018-10-15 10:05:49 +00:00
async def update_nio ( request , response ) :
2017-07-12 12:50:33 +00:00
qemu_manager = Qemu . instance ( )
vm = qemu_manager . get_node ( request . match_info [ " node_id " ] , project_id = request . match_info [ " project_id " ] )
2018-10-27 07:47:17 +00:00
adapter_number = int ( request . match_info [ " adapter_number " ] )
nio = vm . get_nio ( adapter_number )
if " filters " in request . json :
2017-07-12 12:50:33 +00:00
nio . filters = request . json [ " filters " ]
2018-10-27 07:47:17 +00:00
if " suspend " in request . json :
2018-03-19 09:26:12 +00:00
nio . suspend = request . json [ " suspend " ]
2018-10-27 07:47:17 +00:00
await vm . adapter_update_nio_binding ( adapter_number , nio )
2017-07-12 12:50:33 +00:00
response . set_status ( 201 )
response . json ( request . json )
2015-02-19 18:43:45 +00:00
@Route.delete (
2016-05-11 17:35:36 +00:00
r " /projects/ {project_id} /qemu/nodes/ {node_id} /adapters/ { adapter_number: \ d+}/ports/ { port_number: \ d+}/nio " ,
2015-02-19 18:43:45 +00:00
parameters = {
2016-05-14 00:00:07 +00:00
" project_id " : " Project UUID " ,
" node_id " : " Node UUID " ,
2015-02-19 18:43:45 +00:00
" adapter_number " : " Network adapter where the nio is located " ,
2015-03-07 03:08:00 +00:00
" port_number " : " Port on the adapter (always 0) "
2015-02-19 18:43:45 +00:00
} ,
status_codes = {
204 : " NIO deleted " ,
400 : " Invalid request " ,
404 : " Instance doesn ' t exist "
} ,
2015-04-12 21:09:37 +00:00
description = " Remove a NIO from a Qemu VM instance " )
2018-10-15 10:05:49 +00:00
async def delete_nio ( request , response ) :
2015-02-19 18:43:45 +00:00
qemu_manager = Qemu . instance ( )
2016-05-11 17:35:36 +00:00
vm = qemu_manager . get_node ( request . match_info [ " node_id " ] , project_id = request . match_info [ " project_id " ] )
2018-10-27 07:47:17 +00:00
adapter_number = int ( request . match_info [ " adapter_number " ] )
await vm . adapter_remove_nio_binding ( adapter_number )
2015-02-19 18:43:45 +00:00
response . set_status ( 204 )
2015-02-20 13:39:13 +00:00
2016-06-23 22:56:06 +00:00
@Route.post (
r " /projects/ {project_id} /qemu/nodes/ {node_id} /adapters/ { adapter_number: \ d+}/ports/ { port_number: \ d+}/start_capture " ,
parameters = {
" project_id " : " Project UUID " ,
" node_id " : " Node UUID " ,
" adapter_number " : " Adapter to start a packet capture " ,
" port_number " : " Port on the adapter (always 0) "
} ,
status_codes = {
200 : " Capture started " ,
400 : " Invalid request " ,
404 : " Instance doesn ' t exist " ,
} ,
description = " Start a packet capture on a Qemu VM instance " ,
input = NODE_CAPTURE_SCHEMA )
2018-10-15 10:05:49 +00:00
async def start_capture ( request , response ) :
2016-06-23 22:56:06 +00:00
qemu_manager = Qemu . instance ( )
vm = qemu_manager . get_node ( request . match_info [ " node_id " ] , project_id = request . match_info [ " project_id " ] )
adapter_number = int ( request . match_info [ " adapter_number " ] )
pcap_file_path = os . path . join ( vm . project . capture_working_directory ( ) , request . json [ " capture_file_name " ] )
2018-10-15 10:05:49 +00:00
await vm . start_capture ( adapter_number , pcap_file_path )
2016-06-23 22:56:06 +00:00
response . json ( { " pcap_file_path " : pcap_file_path } )
@Route.post (
r " /projects/ {project_id} /qemu/nodes/ {node_id} /adapters/ { adapter_number: \ d+}/ports/ { port_number: \ d+}/stop_capture " ,
parameters = {
" project_id " : " Project UUID " ,
" node_id " : " Node UUID " ,
" adapter_number " : " Adapter to stop a packet capture " ,
" port_number " : " Port on the adapter (always 0) "
} ,
status_codes = {
204 : " Capture stopped " ,
400 : " Invalid request " ,
404 : " Instance doesn ' t exist " ,
} ,
description = " Stop a packet capture on a Qemu VM instance " )
2018-10-15 10:05:49 +00:00
async def stop_capture ( request , response ) :
2016-06-23 22:56:06 +00:00
qemu_manager = Qemu . instance ( )
vm = qemu_manager . get_node ( request . match_info [ " node_id " ] , project_id = request . match_info [ " project_id " ] )
adapter_number = int ( request . match_info [ " adapter_number " ] )
2018-10-15 10:05:49 +00:00
await vm . stop_capture ( adapter_number )
2016-06-23 22:56:06 +00:00
response . set_status ( 204 )
2018-10-27 07:47:17 +00:00
@Route.get (
r " /projects/ {project_id} /qemu/nodes/ {node_id} /adapters/ { adapter_number: \ d+}/ports/ { port_number: \ d+}/pcap " ,
description = " Stream the pcap capture file " ,
parameters = {
" project_id " : " Project UUID " ,
" node_id " : " Node UUID " ,
" adapter_number " : " Adapter to steam a packet capture " ,
" port_number " : " Port on the adapter (always 0) "
} ,
status_codes = {
200 : " File returned " ,
403 : " Permission denied " ,
404 : " The file doesn ' t exist "
} )
async def stream_pcap_file ( request , response ) :
qemu_manager = Qemu . instance ( )
vm = qemu_manager . get_node ( request . match_info [ " node_id " ] , project_id = request . match_info [ " project_id " ] )
adapter_number = int ( request . match_info [ " adapter_number " ] )
nio = vm . get_nio ( adapter_number )
await qemu_manager . stream_pcap_file ( nio , vm . project . id , request , response )
2015-02-20 13:39:13 +00:00
@Route.get (
2015-02-20 15:54:23 +00:00
r " /qemu/binaries " ,
2015-02-20 13:39:13 +00:00
status_codes = {
200 : " Success " ,
400 : " Invalid request " ,
404 : " Instance doesn ' t exist "
} ,
description = " Get a list of available Qemu binaries " ,
2016-01-01 00:40:12 +00:00
input = QEMU_BINARY_FILTER_SCHEMA ,
2015-02-20 13:39:13 +00:00
output = QEMU_BINARY_LIST_SCHEMA )
2018-10-15 10:05:49 +00:00
async def list_binaries ( request , response ) :
2015-02-20 13:39:13 +00:00
2018-10-15 10:05:49 +00:00
binaries = await Qemu . binary_list ( request . json . get ( " archs " , None ) )
2015-02-20 13:39:13 +00:00
response . json ( binaries )
2015-04-13 12:33:13 +00:00
2015-05-10 17:46:51 +00:00
@Route.get (
r " /qemu/img-binaries " ,
status_codes = {
200 : " Success " ,
400 : " Invalid request " ,
404 : " Instance doesn ' t exist "
} ,
description = " Get a list of available Qemu-img binaries " ,
output = QEMU_BINARY_LIST_SCHEMA )
2018-10-15 10:05:49 +00:00
async def list_img_binaries ( request , response ) :
2015-05-10 17:46:51 +00:00
2018-10-15 10:05:49 +00:00
binaries = await Qemu . img_binary_list ( )
2015-05-10 17:46:51 +00:00
response . json ( binaries )
2016-01-01 00:40:12 +00:00
@Route.get (
r " /qemu/capabilities " ,
status_codes = {
200 : " Success "
} ,
description = " Get a list of Qemu capabilities on this server " ,
output = QEMU_CAPABILITY_LIST_SCHEMA
)
2018-10-15 10:05:49 +00:00
async def get_capabilities ( request , response ) :
2016-01-04 15:30:06 +00:00
capabilities = { " kvm " : [ ] }
2018-10-15 10:05:49 +00:00
kvms = await Qemu . get_kvm_archs ( )
2016-01-01 00:40:12 +00:00
if kvms :
capabilities [ " kvm " ] = kvms
response . json ( capabilities )
2015-07-27 17:18:36 +00:00
@Route.post (
r " /qemu/img " ,
status_codes = {
201 : " Image created " ,
} ,
2015-07-28 15:50:57 +00:00
description = " Create a Qemu image " ,
input = QEMU_IMAGE_CREATE_SCHEMA
2015-07-27 17:18:36 +00:00
)
2018-10-15 10:05:49 +00:00
async def create_img ( request , response ) :
2015-07-27 17:18:36 +00:00
qemu_img = request . json . pop ( " qemu_img " )
path = request . json . pop ( " path " )
2015-07-28 14:05:48 +00:00
if os . path . isabs ( path ) :
config = Config . instance ( )
if config . get_section_config ( " Server " ) . getboolean ( " local " , False ) is False :
response . set_status ( 403 )
return
2018-10-15 10:05:49 +00:00
await Qemu . instance ( ) . create_disk ( qemu_img , path , request . json )
2015-07-27 17:18:36 +00:00
response . set_status ( 201 )
2018-03-26 11:05:49 +00:00
@Route.put (
r " /qemu/img " ,
status_codes = {
201 : " Image Updated " ,
} ,
description = " Update a Qemu image " ,
input = QEMU_IMAGE_UPDATE_SCHEMA
)
2018-10-15 10:05:49 +00:00
async def update_img ( request , response ) :
2018-03-26 11:05:49 +00:00
qemu_img = request . json . pop ( " qemu_img " )
path = request . json . pop ( " path " )
if os . path . isabs ( path ) :
config = Config . instance ( )
if config . get_section_config ( " Server " ) . getboolean ( " local " , False ) is False :
response . set_status ( 403 )
return
if " extend " in request . json :
2018-10-15 10:05:49 +00:00
await Qemu . instance ( ) . resize_disk ( qemu_img , path , request . json . pop ( " extend " ) )
2018-03-26 11:05:49 +00:00
response . set_status ( 201 )
2015-04-13 12:33:13 +00:00
@Route.get (
2016-05-14 00:00:07 +00:00
r " /qemu/images " ,
2015-04-13 12:33:13 +00:00
status_codes = {
2016-05-14 00:00:07 +00:00
200 : " List of Qemu images " ,
2015-04-13 12:33:13 +00:00
} ,
description = " Retrieve the list of Qemu images " ,
2016-05-11 17:35:36 +00:00
output = NODE_LIST_IMAGES_SCHEMA )
2018-10-15 10:05:49 +00:00
async def list_qemu_images ( request , response ) :
2015-04-13 12:33:13 +00:00
qemu_manager = Qemu . instance ( )
2018-10-15 10:05:49 +00:00
images = await qemu_manager . list_images ( )
2015-04-13 12:33:13 +00:00
response . set_status ( 200 )
2016-05-14 00:00:07 +00:00
response . json ( images )
2015-04-24 08:15:23 +00:00
@Route.post (
2016-05-14 00:00:07 +00:00
r " /qemu/images/ { filename:.+} " ,
parameters = {
" filename " : " Image filename "
} ,
2015-04-24 08:15:23 +00:00
status_codes = {
204 : " Image uploaded " ,
} ,
raw = True ,
2016-05-14 00:00:07 +00:00
description = " Upload Qemu image " )
2018-10-15 10:05:49 +00:00
async def upload_image ( request , response ) :
2015-04-24 08:15:23 +00:00
qemu_manager = Qemu . instance ( )
2021-05-16 05:14:38 +00:00
filename = os . path . normpath ( request . match_info [ " filename " ] )
await qemu_manager . write_image ( filename , request . content )
2015-04-24 08:15:23 +00:00
response . set_status ( 204 )
2017-11-13 21:12:39 +00:00
@Route.get (
r " /qemu/images/ { filename:.+} " ,
parameters = {
" filename " : " Image filename "
} ,
status_codes = {
200 : " Image returned " ,
} ,
raw = True ,
description = " Download Qemu image " )
2018-10-15 10:05:49 +00:00
async def download_image ( request , response ) :
2017-11-13 21:12:39 +00:00
2021-05-16 05:14:38 +00:00
filename = os . path . normpath ( request . match_info [ " filename " ] )
2017-11-13 21:12:39 +00:00
# Raise error if user try to escape
2021-05-15 08:05:32 +00:00
if filename [ 0 ] == " . " or os . path . sep in filename :
2017-11-23 15:28:10 +00:00
raise aiohttp . web . HTTPForbidden ( )
2017-11-13 21:12:39 +00:00
2021-05-15 08:05:32 +00:00
qemu_manager = Qemu . instance ( )
image_path = qemu_manager . get_abs_image_path ( filename )
2019-03-06 16:00:01 +00:00
await response . stream_file ( image_path )
2020-01-31 09:31:27 +00:00
@Route.get (
r " /projects/ {project_id} /qemu/nodes/ {node_id} /console/ws " ,
description = " WebSocket for console " ,
parameters = {
" project_id " : " Project UUID " ,
" node_id " : " Node UUID " ,
} )
async def console_ws ( request , response ) :
qemu_manager = Qemu . instance ( )
vm = qemu_manager . get_node ( request . match_info [ " node_id " ] , project_id = request . match_info [ " project_id " ] )
return await vm . start_websocket_console ( request )