@ -18,40 +18,26 @@
import os
from aiohttp . web import HTTPConflict
from . . . . web . route import Route
from . . . . compute . docker import Docker
from gns3server . web . route import Route
from gns3server . compute . docker import Docker
from gns3server . schemas . node import NODE_CAPTURE_SCHEMA
from gns3server . schemas . nio import NIO_SCHEMA
from . . . . schemas . docker import (
from gns3server . schemas . docker import (
DOCKER_CREATE_SCHEMA ,
DOCKER_OBJECT_SCHEMA ,
DOCKER_UPDATE_SCHEMA ,
DOCKER_LIST_IMAGES_SCHEMA
)
from . . . . schemas . node import NODE_CAPTURE_SCHEMA
from . . . . schemas . nio import NIO_SCHEMA
class DockerHandler :
""" API entry points for Docker ."""
""" API entry points for Docker containers ."""
@classmethod
@Route.get (
r " /docker/images " ,
status_codes = {
200 : " Success " ,
} ,
output = DOCKER_LIST_IMAGES_SCHEMA ,
description = " Get all available Docker images " )
def show ( request , response ) :
docker_manager = Docker . instance ( )
images = yield from docker_manager . list_images ( )
response . json ( images )
@classmethod
@Route.post (
r " /projects/ {project_id} /docker/nodes " ,
parameters = {
" project_id " : " UUID for the project "
" project_id " : " Project UUID "
} ,
status_codes = {
201 : " Instance created " ,
@ -63,33 +49,32 @@ class DockerHandler:
output = DOCKER_OBJECT_SCHEMA )
def create ( request , response ) :
docker_manager = Docker . instance ( )
vm = yield from docker_manager . create_node ( request . json . pop ( " name " ) ,
request . match_info [ " project_id " ] ,
request . json . get ( " node_id " ) ,
image = request . json . pop ( " image " ) ,
start_command = request . json . get ( " start_command " ) ,
environment = request . json . get ( " environment " ) ,
adapters = request . json . get ( " adapters " ) ,
console = request . json . get ( " console " ) ,
console_type = request . json . get ( " console_type " ) ,
console_resolution = request . json . get ( " console_resolution " , " 1024x768 " ) ,
console_http_port = request . json . get ( " console_http_port " , 80 ) ,
console_http_path = request . json . get ( " console_http_path " , " / " ) ,
aux = request . json . get ( " aux " ) )
container = yield from docker_manager . create_node ( request . json . pop ( " name " ) ,
request . match_info [ " project_id " ] ,
request . json . get ( " node_id " ) ,
image = request . json . pop ( " image " ) ,
start_command = request . json . get ( " start_command " ) ,
environment = request . json . get ( " environment " ) ,
adapters = request . json . get ( " adapters " ) ,
console = request . json . get ( " console " ) ,
console_type = request . json . get ( " console_type " ) ,
console_resolution = request . json . get ( " console_resolution " , " 1024x768 " ) ,
console_http_port = request . json . get ( " console_http_port " , 80 ) ,
console_http_path = request . json . get ( " console_http_path " , " / " ) ,
aux = request . json . get ( " aux " ) )
for name , value in request . json . items ( ) :
if name != " _ node_id" :
if hasattr ( vm, name ) and getattr ( vm , name ) != value :
setattr ( vm , name , value )
if name != " node_id" :
if hasattr ( container, name ) and getattr ( container , name ) != value :
setattr ( container , name , value )
response . set_status ( 201 )
response . json ( vm )
response . json ( container )
@classmethod
@Route.post (
r " /projects/ {project_id} /docker/nodes/ {node_id} /start " ,
parameters = {
" project_id " : " UUID of the project " ,
" node_id " : " ID of the container "
" project_id " : " Project UUID " ,
" node_id " : " Node UUID "
} ,
status_codes = {
204 : " Instance started " ,
@ -101,16 +86,15 @@ class DockerHandler:
output = DOCKER_OBJECT_SCHEMA )
def start ( request , response ) :
docker_manager = Docker . instance ( )
vm = docker_manager . get_node ( request . match_info [ " node_id " ] , project_id = request . match_info [ " project_id " ] )
yield from vm . start ( )
container = docker_manager . get_node ( request . match_info [ " node_id " ] , project_id = request . match_info [ " project_id " ] )
yield from container . start ( )
response . set_status ( 204 )
@classmethod
@Route.post (
r " /projects/ {project_id} /docker/nodes/ {node_id} /stop " ,
parameters = {
" project_id " : " UUID of the project " ,
" node_id " : " ID of the container "
" project_id " : " Project UUID " ,
" node_id " : " Node UUID "
} ,
status_codes = {
204 : " Instance stopped " ,
@ -122,16 +106,15 @@ class DockerHandler:
output = DOCKER_OBJECT_SCHEMA )
def stop ( request , response ) :
docker_manager = Docker . instance ( )
vm = docker_manager . get_node ( request . match_info [ " node_id " ] , project_id = request . match_info [ " project_id " ] )
yield from vm . stop ( )
container = docker_manager . get_node ( request . match_info [ " node_id " ] , project_id = request . match_info [ " project_id " ] )
yield from container . stop ( )
response . set_status ( 204 )
@classmethod
@Route.post (
r " /projects/ {project_id} /docker/nodes/ {node_id} /reload " ,
parameters = {
" project_id " : " UUID of the project " ,
" node_id " : " ID of the container "
" project_id " : " Project UUID " ,
" node_id " : " Node UUID "
} ,
status_codes = {
204 : " Instance restarted " ,
@ -143,16 +126,15 @@ class DockerHandler:
output = DOCKER_OBJECT_SCHEMA )
def reload ( request , response ) :
docker_manager = Docker . instance ( )
vm = docker_manager . get_node ( request . match_info [ " node_id " ] , project_id = request . match_info [ " project_id " ] )
yield from vm . restart ( )
container = docker_manager . get_node ( request . match_info [ " node_id " ] , project_id = request . match_info [ " project_id " ] )
yield from container . restart ( )
response . set_status ( 204 )
@classmethod
@Route.delete (
r " /projects/ {project_id} /docker/nodes/ {node_id} " ,
parameters = {
" project_id " : " UUID for the project " ,
" node_id " : " ID for the container " ,
" project_id " : " Project UUID " ,
" node_id " : " Node UUID " ,
} ,
status_codes = {
204 : " Instance deleted " ,
@ -162,16 +144,15 @@ class DockerHandler:
description = " Delete a Docker container " )
def delete ( request , response ) :
docker_manager = Docker . instance ( )
vm = docker_manager . get_node ( request . match_info [ " node_id " ] , project_id = request . match_info [ " project_id " ] )
yield from vm . delete ( )
container = docker_manager . get_node ( request . match_info [ " node_id " ] , project_id = request . match_info [ " project_id " ] )
yield from container . delete ( )
response . set_status ( 204 )
@classmethod
@Route.post (
r " /projects/ {project_id} /docker/nodes/ {node_id} / suspend " ,
r " /projects/ {project_id} /docker/nodes/ {node_id} / pause " ,
parameters = {
" project_id " : " UUID of the project " ,
" node_id " : " ID of the container "
" project_id " : " Project UUID " ,
" node_id " : " Node UUID "
} ,
status_codes = {
204 : " Instance paused " ,
@ -181,17 +162,37 @@ class DockerHandler:
description = " Pause a Docker container " ,
input = DOCKER_CREATE_SCHEMA ,
output = DOCKER_OBJECT_SCHEMA )
def suspend ( request , response ) :
def pause ( request , response ) :
docker_manager = Docker . instance ( )
container = docker_manager . get_node ( request . match_info [ " node_id " ] , project_id = request . match_info [ " project_id " ] )
yield from container . pause ( )
response . set_status ( 204 )
@Route.post (
r " /projects/ {project_id} /docker/nodes/ {node_id} /unpause " ,
parameters = {
" project_id " : " Project UUID " ,
" node_id " : " Node UUID "
} ,
status_codes = {
204 : " Instance unpaused " ,
400 : " Invalid request " ,
404 : " Instance doesn ' t exist "
} ,
description = " Unpause a Docker container " ,
input = DOCKER_CREATE_SCHEMA ,
output = DOCKER_OBJECT_SCHEMA )
def unpause ( request , response ) :
docker_manager = Docker . instance ( )
vm = docker_manager . get_node ( request . match_info [ " node_id " ] , project_id = request . match_info [ " project_id " ] )
yield from vm . pause ( )
container = docker_manager . get_node ( request . match_info [ " node_id " ] , project_id = request . match_info [ " project_id " ] )
yield from container. un pause( )
response . set_status ( 204 )
@Route.post (
r " /projects/ {project_id} /docker/nodes/ {node_id} /adapters/ { adapter_number: \ d+}/ports/ { port_number: \ d+}/nio " ,
parameters = {
" project_id " : " UUID for the project " ,
" node_id " : " ID of the container " ,
" project_id " : " Project UUID " ,
" node_id " : " Node UUID " ,
" adapter_number " : " Adapter where the nio should be added " ,
" port_number " : " Port on the adapter "
} ,
@ -205,21 +206,20 @@ class DockerHandler:
output = NIO_SCHEMA )
def create_nio ( request , response ) :
docker_manager = Docker . instance ( )
vm = docker_manager . get_node ( request . match_info [ " node_id " ] , project_id = request . match_info [ " project_id " ] )
container = docker_manager . get_node ( request . match_info [ " node_id " ] , project_id = request . match_info [ " project_id " ] )
nio_type = request . json [ " type " ]
if nio_type not in ( " nio_udp " ) :
if nio_type != " nio_udp " :
raise HTTPConflict ( text = " NIO of type {} is not supported " . format ( nio_type ) )
nio = docker_manager . create_nio ( int ( request . match_info [ " adapter_number " ] ) , request . json )
yield from vm . adapter_add_nio_binding ( int ( request . match_info [ " adapter_number " ] ) , nio )
yield from container . adapter_add_nio_binding ( int ( request . match_info [ " adapter_number " ] ) , nio )
response . set_status ( 201 )
response . json ( nio )
@classmethod
@Route.delete (
r " /projects/ {project_id} /docker/nodes/ {node_id} /adapters/ { adapter_number: \ d+}/ports/ { port_number: \ d+}/nio " ,
parameters = {
" project_id " : " UUID for the project " ,
" node_id " : " ID of the container " ,
" project_id " : " Project UUID " ,
" node_id " : " Node UUID " ,
" adapter_number " : " Adapter where the nio should be added " ,
" port_number " : " Port on the adapter "
} ,
@ -231,16 +231,15 @@ class DockerHandler:
description = " Remove a NIO from a Docker container " )
def delete_nio ( request , response ) :
docker_manager = Docker . instance ( )
vm = docker_manager . get_node ( request . match_info [ " node_id " ] , project_id = request . match_info [ " project_id " ] )
yield from vm . adapter_remove_nio_binding ( int ( request . match_info [ " adapter_number " ] ) )
container = docker_manager . get_node ( request . match_info [ " node_id " ] , project_id = request . match_info [ " project_id " ] )
yield from container . adapter_remove_nio_binding ( int ( request . match_info [ " adapter_number " ] ) )
response . set_status ( 204 )
@classmethod
@Route.put (
r " /projects/ {project_id} /docker/nodes/ {node_id} " ,
parameters = {
" project_id " : " UUID for the project " ,
" node_id " : " UUID for the instance "
" project_id " : " Project UUID " ,
" node_id " : " Node UUID"
} ,
status_codes = {
200 : " Instance updated " ,
@ -254,25 +253,25 @@ class DockerHandler:
def update ( request , response ) :
docker_manager = Docker . instance ( )
vm = docker_manager . get_node ( request . match_info [ " node_id " ] , project_id = request . match_info [ " project_id " ] )
vm . name = request . json . get ( " name " , vm . name )
vm . console = request . json . get ( " console " , vm . console )
vm . aux = request . json . get ( " aux " , vm . aux )
vm . console_type = request . json . get ( " console_type " , vm . console_type )
vm . console_resolution = request . json . get ( " console_resolution " , vm . console_resolution )
vm . console_http_port = request . json . get ( " console_http_port " , vm . console_http_port )
vm . console_http_path = request . json . get ( " console_http_path " , vm . console_http_path )
vm . start_command = request . json . get ( " start_command " , vm . start_command )
vm . environment = request . json . get ( " environment " , vm . environment )
vm . adapters = request . json . get ( " adapters " , vm . adapters )
yield from vm . update ( )
response . json ( vm )
container = docker_manager . get_node ( request . match_info [ " node_id " ] , project_id = request . match_info [ " project_id " ] )
container . name = request . json . get ( " name " , container . name )
container . console = request . json . get ( " console " , container . console )
container . aux = request . json . get ( " aux " , container . aux )
container . console_type = request . json . get ( " console_type " , container . console_type )
container . console_resolution = request . json . get ( " console_resolution " , container . console_resolution )
container . console_http_port = request . json . get ( " console_http_port " , container . console_http_port )
container . console_http_path = request . json . get ( " console_http_path " , container . console_http_path )
container . start_command = request . json . get ( " start_command " , container . start_command )
container . environment = request . json . get ( " environment " , container . environment )
container . adapters = request . json . get ( " adapters " , container . adapters )
yield from container . update ( )
response . json ( container )
@Route.post (
r " /projects/ {project_id} /docker/nodes/ {node_id} /adapters/ { adapter_number: \ d+}/ports/ { port_number: \ d+}/start_capture " ,
parameters = {
" project_id " : " UUID for the project " ,
" node_id " : " UUID for the instance " ,
" project_id " : " Project UUID " ,
" node_id " : " Node UUID" ,
" adapter_number " : " Adapter to start a packet capture " ,
" port_number " : " Port on the adapter "
} ,
@ -282,25 +281,25 @@ class DockerHandler:
404 : " Instance doesn ' t exist " ,
409 : " Node not started "
} ,
description = " Start a packet capture on a Docker VM instance" ,
description = " Start a packet capture on a Docker container instance" ,
input = NODE_CAPTURE_SCHEMA )
def start_capture ( request , response ) :
docker_manager = Docker . instance ( )
vm = docker_manager . get_node ( request . match_info [ " node_id " ] , project_id = request . match_info [ " project_id " ] )
container = docker_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 " ] )
pcap_file_path = os . path . join ( container . project . capture_working_directory ( ) , request . json [ " capture_file_name " ] )
if not vm . is_running ( ) :
raise HTTPConflict ( text = " Cannot capture traffic on a non started VM " )
yield from vm . start_capture ( adapter_number , pcap_file_path )
if not container . is_running ( ) :
raise HTTPConflict ( text = " Cannot capture traffic on a non started Docker container " )
yield from container . start_capture ( adapter_number , pcap_file_path )
response . json ( { " pcap_file_path " : str ( pcap_file_path ) } )
@Route.post (
r " /projects/ {project_id} /docker/nodes/ {node_id} /adapters/ { adapter_number: \ d+}/ports/ { port_number: \ d+}/stop_capture " ,
parameters = {
" project_id " : " UUID for the project " ,
" node_id " : " UUID for the instance " ,
" project_id " : " Project UUID " ,
" node_id " : " Node UUID" ,
" adapter_number " : " Adapter to stop a packet capture " ,
" port_number " : " Port on the adapter (always 0) "
} ,
@ -308,17 +307,29 @@ class DockerHandler:
204 : " Capture stopped " ,
400 : " Invalid request " ,
404 : " Instance doesn ' t exist " ,
409 : " VM not started"
409 : " Container not started"
} ,
description = " Stop a packet capture on a IOU VM instance" )
description = " Stop a packet capture on a Docker container instance" )
def stop_capture ( request , response ) :
docker_manager = Docker . instance ( )
vm = docker_manager . get_node ( request . match_info [ " node_id " ] , project_id = request . match_info [ " project_id " ] )
container = docker_manager . get_node ( request . match_info [ " node_id " ] , project_id = request . match_info [ " project_id " ] )
if not vm . is_running ( ) :
raise HTTPConflict ( text = " Cannot capture traffic on a non started VM " )
if not container . is_running ( ) :
raise HTTPConflict ( text = " Cannot capture traffic on a non started Docker container " )
adapter_number = int ( request . match_info [ " adapter_number " ] )
yield from vm . stop_capture ( adapter_number )
yield from container . stop_capture ( adapter_number )
response . set_status ( 204 )
@Route.get (
r " /docker/images " ,
status_codes = {
200 : " Success " ,
} ,
output = DOCKER_LIST_IMAGES_SCHEMA ,
description = " Get all available Docker images " )
def show ( request , response ) :
docker_manager = Docker . instance ( )
images = yield from docker_manager . list_images ( )
response . json ( images )