Add project_id in all VM calls.

pull/100/head
Jeremy 9 years ago
parent b680138073
commit 291fac7084

@ -5,9 +5,9 @@ DELETE /projects/{project_id} HTTP/1.1
HTTP/1.1 204
CONNECTION: keep-alive
CONNECTION: close
CONTENT-LENGTH: 0
DATE: Thu, 08 Jan 2015 16:09:15 GMT
SERVER: Python/3.4 GNS3/1.3.dev1
SERVER: Python/3.4 aiohttp/0.13.1
X-ROUTE: /v1/projects/{project_id}

@ -1,13 +0,0 @@
curl -i -X DELETE 'http://localhost:8000/virtualbox/{uuid}/adapters/{adapter_id:\d+}/nio'
DELETE /virtualbox/{uuid}/adapters/{adapter_id:\d+}/nio HTTP/1.1
HTTP/1.1 204
CONNECTION: keep-alive
CONTENT-LENGTH: 0
DATE: Thu, 08 Jan 2015 16:09:15 GMT
SERVER: Python/3.4 GNS3/1.3.dev1
X-ROUTE: /v1/virtualbox/{uuid}/adapters/{adapter_id:\d+}/nio

@ -1,13 +0,0 @@
curl -i -X DELETE 'http://localhost:8000/vpcs/{uuid}/ports/{port_number:\d+}/nio'
DELETE /vpcs/{uuid}/ports/{port_number:\d+}/nio HTTP/1.1
HTTP/1.1 204
CONNECTION: keep-alive
CONTENT-LENGTH: 0
DATE: Thu, 08 Jan 2015 16:09:15 GMT
SERVER: Python/3.4 GNS3/1.3.dev1
X-ROUTE: /v1/vpcs/{uuid}/ports/{port_number:\d+}/nio

@ -5,56 +5,32 @@ GET /interfaces HTTP/1.1
HTTP/1.1 200
CONNECTION: keep-alive
CONTENT-LENGTH: 652
CONNECTION: close
CONTENT-LENGTH: 298
CONTENT-TYPE: application/json
DATE: Thu, 08 Jan 2015 16:09:15 GMT
SERVER: Python/3.4 GNS3/1.3.dev1
SERVER: Python/3.4 aiohttp/0.13.1
X-ROUTE: /v1/interfaces
[
{
"id": "lo0",
"name": "lo0"
"id": "lo",
"name": "lo"
},
{
"id": "gif0",
"name": "gif0"
"id": "eth0",
"name": "eth0"
},
{
"id": "stf0",
"name": "stf0"
"id": "wlan0",
"name": "wlan0"
},
{
"id": "en0",
"name": "en0"
"id": "vmnet1",
"name": "vmnet1"
},
{
"id": "en1",
"name": "en1"
},
{
"id": "fw0",
"name": "fw0"
},
{
"id": "en2",
"name": "en2"
},
{
"id": "p2p0",
"name": "p2p0"
},
{
"id": "bridge0",
"name": "bridge0"
},
{
"id": "vboxnet0",
"name": "vboxnet0"
},
{
"id": "vboxnet1",
"name": "vboxnet1"
"id": "vmnet8",
"name": "vmnet8"
}
]

@ -5,15 +5,16 @@ GET /projects/{project_id} HTTP/1.1
HTTP/1.1 200
CONNECTION: keep-alive
CONTENT-LENGTH: 108
CONNECTION: close
CONTENT-LENGTH: 165
CONTENT-TYPE: application/json
DATE: Thu, 08 Jan 2015 16:09:15 GMT
SERVER: Python/3.4 GNS3/1.3.dev1
SERVER: Python/3.4 aiohttp/0.13.1
X-ROUTE: /v1/projects/{project_id}
{
"location": "/tmp",
"path": "/tmp/00010203-0405-0607-0809-0a0b0c0d0e0f",
"project_id": "00010203-0405-0607-0809-0a0b0c0d0e0f",
"temporary": false
}

@ -5,11 +5,11 @@ GET /version HTTP/1.1
HTTP/1.1 200
CONNECTION: keep-alive
CONNECTION: close
CONTENT-LENGTH: 29
CONTENT-TYPE: application/json
DATE: Thu, 08 Jan 2015 16:09:15 GMT
SERVER: Python/3.4 GNS3/1.3.dev1
SERVER: Python/3.4 aiohttp/0.13.1
X-ROUTE: /v1/version
{

@ -1,26 +0,0 @@
curl -i -X GET 'http://localhost:8000/virtualbox/{uuid}'
GET /virtualbox/{uuid} HTTP/1.1
HTTP/1.1 200
CONNECTION: keep-alive
CONTENT-LENGTH: 346
CONTENT-TYPE: application/json
DATE: Thu, 08 Jan 2015 16:09:15 GMT
SERVER: Python/3.4 GNS3/1.3.dev1
X-ROUTE: /v1/virtualbox/{uuid}
{
"adapter_start_index": 0,
"adapter_type": "Intel PRO/1000 MT Desktop (82540EM)",
"adapters": 0,
"console": 2001,
"enable_remote_console": false,
"headless": false,
"name": "VMTEST",
"project_id": "a1e920ca-338a-4e9f-b363-aa607b09dd80",
"uuid": "aa7a7c1e-6fc2-43b8-b53b-60e605565625",
"vmname": "VMTEST"
}

@ -1,22 +0,0 @@
curl -i -X GET 'http://localhost:8000/vpcs/{uuid}'
GET /vpcs/{uuid} HTTP/1.1
HTTP/1.1 200
CONNECTION: keep-alive
CONTENT-LENGTH: 211
CONTENT-TYPE: application/json
DATE: Thu, 08 Jan 2015 16:09:15 GMT
SERVER: Python/3.4 GNS3/1.3.dev1
X-ROUTE: /v1/vpcs/{uuid}
{
"console": 2003,
"name": "PC TEST 1",
"project_id": "a1e920ca-338a-4e9f-b363-aa607b09dd80",
"script_file": null,
"startup_script": null,
"uuid": "c505f88b-7fe1-4985-9aca-a3798f6659ab"
}

@ -5,11 +5,11 @@ POST /ports/udp HTTP/1.1
HTTP/1.1 201
CONNECTION: keep-alive
CONNECTION: close
CONTENT-LENGTH: 25
CONTENT-TYPE: application/json
DATE: Thu, 08 Jan 2015 16:09:15 GMT
SERVER: Python/3.4 GNS3/1.3.dev1
SERVER: Python/3.4 aiohttp/0.13.1
X-ROUTE: /v1/ports/udp
{

@ -5,9 +5,9 @@ POST /projects/{project_id}/close HTTP/1.1
HTTP/1.1 204
CONNECTION: keep-alive
CONNECTION: close
CONTENT-LENGTH: 0
DATE: Thu, 08 Jan 2015 16:09:15 GMT
SERVER: Python/3.4 GNS3/1.3.dev1
SERVER: Python/3.4 aiohttp/0.13.1
X-ROUTE: /v1/projects/{project_id}/close

@ -5,9 +5,9 @@ POST /projects/{project_id}/commit HTTP/1.1
HTTP/1.1 204
CONNECTION: keep-alive
CONNECTION: close
CONTENT-LENGTH: 0
DATE: Thu, 08 Jan 2015 16:09:15 GMT
SERVER: Python/3.4 GNS3/1.3.dev1
SERVER: Python/3.4 aiohttp/0.13.1
X-ROUTE: /v1/projects/{project_id}/commit

@ -7,11 +7,11 @@ POST /version HTTP/1.1
HTTP/1.1 200
CONNECTION: keep-alive
CONNECTION: close
CONTENT-LENGTH: 29
CONTENT-TYPE: application/json
DATE: Thu, 08 Jan 2015 16:09:15 GMT
SERVER: Python/3.4 GNS3/1.3.dev1
SERVER: Python/3.4 aiohttp/0.13.1
X-ROUTE: /v1/version
{

@ -1,31 +0,0 @@
curl -i -X POST 'http://localhost:8000/virtualbox' -d '{"linked_clone": false, "name": "VM1", "project_id": "a1e920ca-338a-4e9f-b363-aa607b09dd80", "vmname": "VM1"}'
POST /virtualbox HTTP/1.1
{
"linked_clone": false,
"name": "VM1",
"project_id": "a1e920ca-338a-4e9f-b363-aa607b09dd80",
"vmname": "VM1"
}
HTTP/1.1 201
CONNECTION: keep-alive
CONTENT-LENGTH: 340
CONTENT-TYPE: application/json
DATE: Thu, 08 Jan 2015 16:09:15 GMT
SERVER: Python/3.4 GNS3/1.3.dev1
X-ROUTE: /v1/virtualbox
{
"adapter_start_index": 0,
"adapter_type": "Intel PRO/1000 MT Desktop (82540EM)",
"adapters": 0,
"console": 2000,
"enable_remote_console": false,
"headless": false,
"name": "VM1",
"project_id": "a1e920ca-338a-4e9f-b363-aa607b09dd80",
"uuid": "267f3908-f3dd-4cac-bca3-2e31a1018493",
"vmname": "VM1"
}

@ -1,25 +0,0 @@
curl -i -X POST 'http://localhost:8000/virtualbox/{uuid}/adapters/{adapter_id:\d+}/nio' -d '{"lport": 4242, "rhost": "127.0.0.1", "rport": 4343, "type": "nio_udp"}'
POST /virtualbox/{uuid}/adapters/{adapter_id:\d+}/nio HTTP/1.1
{
"lport": 4242,
"rhost": "127.0.0.1",
"rport": 4343,
"type": "nio_udp"
}
HTTP/1.1 201
CONNECTION: keep-alive
CONTENT-LENGTH: 89
CONTENT-TYPE: application/json
DATE: Thu, 08 Jan 2015 16:09:15 GMT
SERVER: Python/3.4 GNS3/1.3.dev1
X-ROUTE: /v1/virtualbox/{uuid}/adapters/{adapter_id:\d+}/nio
{
"lport": 4242,
"rhost": "127.0.0.1",
"rport": 4343,
"type": "nio_udp"
}

@ -1,25 +0,0 @@
curl -i -X POST 'http://localhost:8000/vpcs' -d '{"name": "PC TEST 1", "project_id": "a1e920ca-338a-4e9f-b363-aa607b09dd80"}'
POST /vpcs HTTP/1.1
{
"name": "PC TEST 1",
"project_id": "a1e920ca-338a-4e9f-b363-aa607b09dd80"
}
HTTP/1.1 201
CONNECTION: keep-alive
CONTENT-LENGTH: 211
CONTENT-TYPE: application/json
DATE: Thu, 08 Jan 2015 16:09:15 GMT
SERVER: Python/3.4 GNS3/1.3.dev1
X-ROUTE: /v1/vpcs
{
"console": 2001,
"name": "PC TEST 1",
"project_id": "a1e920ca-338a-4e9f-b363-aa607b09dd80",
"script_file": null,
"startup_script": null,
"uuid": "d7a9ef38-2863-4cf2-97ce-dcf8416a93ae"
}

@ -1,25 +0,0 @@
curl -i -X POST 'http://localhost:8000/vpcs/{uuid}/ports/{port_number:\d+}/nio' -d '{"lport": 4242, "rhost": "127.0.0.1", "rport": 4343, "type": "nio_udp"}'
POST /vpcs/{uuid}/ports/{port_number:\d+}/nio HTTP/1.1
{
"lport": 4242,
"rhost": "127.0.0.1",
"rport": 4343,
"type": "nio_udp"
}
HTTP/1.1 201
CONNECTION: keep-alive
CONTENT-LENGTH: 89
CONTENT-TYPE: application/json
DATE: Thu, 08 Jan 2015 16:09:15 GMT
SERVER: Python/3.4 GNS3/1.3.dev1
X-ROUTE: /v1/vpcs/{uuid}/ports/{port_number:\d+}/nio
{
"lport": 4242,
"rhost": "127.0.0.1",
"rport": 4343,
"type": "nio_udp"
}

@ -1,21 +1,20 @@
curl -i -X PUT 'http://localhost:8000/projects/{project_id}' -d '{"temporary": false}'
curl -i -X PUT 'http://localhost:8000/projects/{project_id}' -d '{"path": "/tmp/pytest-42/test_update_path_project_non_l0"}'
PUT /projects/{project_id} HTTP/1.1
{
"temporary": false
"path": "/tmp/pytest-42/test_update_path_project_non_l0"
}
HTTP/1.1 200
CONNECTION: keep-alive
CONTENT-LENGTH: 164
HTTP/1.1 403
CONNECTION: close
CONTENT-LENGTH: 101
CONTENT-TYPE: application/json
DATE: Thu, 08 Jan 2015 16:09:15 GMT
SERVER: Python/3.4 GNS3/1.3.dev1
SERVER: Python/3.4 aiohttp/0.13.1
X-ROUTE: /v1/projects/{project_id}
{
"location": "/var/folders/3s/r2wbv07n7wg4vrsn874lmxxh0000gn/T/tmptf8_s67s",
"project_id": "12d03846-c355-4da9-b708-cd45e5d30a50",
"temporary": false
"message": "You are not allowed to modifiy the project directory location",
"status": 403
}

@ -29,6 +29,7 @@ Output
<table>
<tr> <th>Name</th> <th>Mandatory</th> <th>Type</th> <th>Description</th> </tr>
<tr><td>location</td> <td>&#10004;</td> <td>string</td> <td>Base directory where the project should be created on remote server</td> </tr>
<tr><td>path</td> <td> </td> <td>string</td> <td>Directory of the project on the server</td> </tr>
<tr><td>project_id</td> <td>&#10004;</td> <td>string</td> <td>Project UUID</td> </tr>
<tr><td>temporary</td> <td>&#10004;</td> <td>boolean</td> <td>If project is a temporary project</td> </tr>
</table>

@ -23,6 +23,7 @@ Output
<table>
<tr> <th>Name</th> <th>Mandatory</th> <th>Type</th> <th>Description</th> </tr>
<tr><td>location</td> <td>&#10004;</td> <td>string</td> <td>Base directory where the project should be created on remote server</td> </tr>
<tr><td>path</td> <td> </td> <td>string</td> <td>Directory of the project on the server</td> </tr>
<tr><td>project_id</td> <td>&#10004;</td> <td>string</td> <td>Project UUID</td> </tr>
<tr><td>temporary</td> <td>&#10004;</td> <td>boolean</td> <td>If project is a temporary project</td> </tr>
</table>
@ -39,6 +40,7 @@ Parameters
Response status codes
**********************
- **200**: The project has been updated
- **403**: You are not allowed to modify this property
- **404**: The project doesn't exist
Input
@ -47,6 +49,7 @@ Input
<table>
<tr> <th>Name</th> <th>Mandatory</th> <th>Type</th> <th>Description</th> </tr>
<tr><td>path</td> <td> </td> <td>['string', 'null']</td> <td>Path of the project on the server (work only with --local)</td> </tr>
<tr><td>temporary</td> <td> </td> <td>boolean</td> <td>If project is a temporary project</td> </tr>
</table>
@ -57,6 +60,7 @@ Output
<table>
<tr> <th>Name</th> <th>Mandatory</th> <th>Type</th> <th>Description</th> </tr>
<tr><td>location</td> <td>&#10004;</td> <td>string</td> <td>Base directory where the project should be created on remote server</td> </tr>
<tr><td>path</td> <td> </td> <td>string</td> <td>Directory of the project on the server</td> </tr>
<tr><td>project_id</td> <td>&#10004;</td> <td>string</td> <td>Project UUID</td> </tr>
<tr><td>temporary</td> <td>&#10004;</td> <td>boolean</td> <td>If project is a temporary project</td> </tr>
</table>

@ -1,53 +0,0 @@
/v1/virtualbox
-----------------------------------------------------------
.. contents::
POST /v1/virtualbox
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Create a new VirtualBox VM instance
Response status codes
**********************
- **400**: Invalid project UUID
- **201**: Instance created
- **409**: Conflict
Input
*******
.. raw:: html
<table>
<tr> <th>Name</th> <th>Mandatory</th> <th>Type</th> <th>Description</th> </tr>
<tr><td>adapter_start_index</td> <td> </td> <td>integer</td> <td>adapter index from which to start using adapters</td> </tr>
<tr><td>adapter_type</td> <td> </td> <td>string</td> <td>VirtualBox adapter type</td> </tr>
<tr><td>adapters</td> <td> </td> <td>integer</td> <td>number of adapters</td> </tr>
<tr><td>console</td> <td> </td> <td>integer</td> <td>console TCP port</td> </tr>
<tr><td>enable_remote_console</td> <td> </td> <td>boolean</td> <td>enable the remote console</td> </tr>
<tr><td>headless</td> <td> </td> <td>boolean</td> <td>headless mode</td> </tr>
<tr><td>linked_clone</td> <td>&#10004;</td> <td>boolean</td> <td>either the VM is a linked clone or not</td> </tr>
<tr><td>name</td> <td>&#10004;</td> <td>string</td> <td>VirtualBox VM instance name</td> </tr>
<tr><td>project_id</td> <td>&#10004;</td> <td>string</td> <td>Project UUID</td> </tr>
<tr><td>uuid</td> <td> </td> <td>string</td> <td>VirtualBox VM instance UUID</td> </tr>
<tr><td>vbox_id</td> <td> </td> <td>integer</td> <td>VirtualBox VM instance ID (for project created before GNS3 1.3)</td> </tr>
<tr><td>vmname</td> <td>&#10004;</td> <td>string</td> <td>VirtualBox VM name (in VirtualBox itself)</td> </tr>
</table>
Output
*******
.. raw:: html
<table>
<tr> <th>Name</th> <th>Mandatory</th> <th>Type</th> <th>Description</th> </tr>
<tr><td>adapter_start_index</td> <td> </td> <td>integer</td> <td>adapter index from which to start using adapters</td> </tr>
<tr><td>adapter_type</td> <td> </td> <td>string</td> <td>VirtualBox adapter type</td> </tr>
<tr><td>adapters</td> <td> </td> <td>integer</td> <td>number of adapters</td> </tr>
<tr><td>console</td> <td> </td> <td>integer</td> <td>console TCP port</td> </tr>
<tr><td>enable_remote_console</td> <td> </td> <td>boolean</td> <td>enable the remote console</td> </tr>
<tr><td>headless</td> <td> </td> <td>boolean</td> <td>headless mode</td> </tr>
<tr><td>name</td> <td>&#10004;</td> <td>string</td> <td>VirtualBox VM instance name</td> </tr>
<tr><td>project_id</td> <td>&#10004;</td> <td>string</td> <td>Project UUID</td> </tr>
<tr><td>uuid</td> <td>&#10004;</td> <td>string</td> <td>VirtualBox VM instance UUID</td> </tr>
<tr><td>vmname</td> <td> </td> <td>string</td> <td>VirtualBox VM name (in VirtualBox itself)</td> </tr>
</table>

@ -1,99 +0,0 @@
/v1/virtualbox/{uuid}
-----------------------------------------------------------
.. contents::
GET /v1/virtualbox/**{uuid}**
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Get a VirtualBox VM instance
Parameters
**********
- **uuid**: Instance UUID
Response status codes
**********************
- **200**: Success
- **404**: Instance doesn't exist
Output
*******
.. raw:: html
<table>
<tr> <th>Name</th> <th>Mandatory</th> <th>Type</th> <th>Description</th> </tr>
<tr><td>adapter_start_index</td> <td> </td> <td>integer</td> <td>adapter index from which to start using adapters</td> </tr>
<tr><td>adapter_type</td> <td> </td> <td>string</td> <td>VirtualBox adapter type</td> </tr>
<tr><td>adapters</td> <td> </td> <td>integer</td> <td>number of adapters</td> </tr>
<tr><td>console</td> <td> </td> <td>integer</td> <td>console TCP port</td> </tr>
<tr><td>enable_remote_console</td> <td> </td> <td>boolean</td> <td>enable the remote console</td> </tr>
<tr><td>headless</td> <td> </td> <td>boolean</td> <td>headless mode</td> </tr>
<tr><td>name</td> <td>&#10004;</td> <td>string</td> <td>VirtualBox VM instance name</td> </tr>
<tr><td>project_id</td> <td>&#10004;</td> <td>string</td> <td>Project UUID</td> </tr>
<tr><td>uuid</td> <td>&#10004;</td> <td>string</td> <td>VirtualBox VM instance UUID</td> </tr>
<tr><td>vmname</td> <td> </td> <td>string</td> <td>VirtualBox VM name (in VirtualBox itself)</td> </tr>
</table>
PUT /v1/virtualbox/**{uuid}**
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Update a VirtualBox VM instance
Parameters
**********
- **uuid**: Instance UUID
Response status codes
**********************
- **200**: Instance updated
- **409**: Conflict
- **404**: Instance doesn't exist
Input
*******
.. raw:: html
<table>
<tr> <th>Name</th> <th>Mandatory</th> <th>Type</th> <th>Description</th> </tr>
<tr><td>adapter_start_index</td> <td> </td> <td>integer</td> <td>adapter index from which to start using adapters</td> </tr>
<tr><td>adapter_type</td> <td> </td> <td>string</td> <td>VirtualBox adapter type</td> </tr>
<tr><td>adapters</td> <td> </td> <td>integer</td> <td>number of adapters</td> </tr>
<tr><td>console</td> <td> </td> <td>integer</td> <td>console TCP port</td> </tr>
<tr><td>enable_remote_console</td> <td> </td> <td>boolean</td> <td>enable the remote console</td> </tr>
<tr><td>headless</td> <td> </td> <td>boolean</td> <td>headless mode</td> </tr>
<tr><td>name</td> <td> </td> <td>string</td> <td>VirtualBox VM instance name</td> </tr>
<tr><td>vmname</td> <td> </td> <td>string</td> <td>VirtualBox VM name (in VirtualBox itself)</td> </tr>
</table>
Output
*******
.. raw:: html
<table>
<tr> <th>Name</th> <th>Mandatory</th> <th>Type</th> <th>Description</th> </tr>
<tr><td>adapter_start_index</td> <td> </td> <td>integer</td> <td>adapter index from which to start using adapters</td> </tr>
<tr><td>adapter_type</td> <td> </td> <td>string</td> <td>VirtualBox adapter type</td> </tr>
<tr><td>adapters</td> <td> </td> <td>integer</td> <td>number of adapters</td> </tr>
<tr><td>console</td> <td> </td> <td>integer</td> <td>console TCP port</td> </tr>
<tr><td>enable_remote_console</td> <td> </td> <td>boolean</td> <td>enable the remote console</td> </tr>
<tr><td>headless</td> <td> </td> <td>boolean</td> <td>headless mode</td> </tr>
<tr><td>name</td> <td>&#10004;</td> <td>string</td> <td>VirtualBox VM instance name</td> </tr>
<tr><td>project_id</td> <td>&#10004;</td> <td>string</td> <td>Project UUID</td> </tr>
<tr><td>uuid</td> <td>&#10004;</td> <td>string</td> <td>VirtualBox VM instance UUID</td> </tr>
<tr><td>vmname</td> <td> </td> <td>string</td> <td>VirtualBox VM name (in VirtualBox itself)</td> </tr>
</table>
DELETE /v1/virtualbox/**{uuid}**
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Delete a VirtualBox VM instance
Parameters
**********
- **uuid**: Instance UUID
Response status codes
**********************
- **404**: Instance doesn't exist
- **204**: Instance deleted

@ -1,36 +0,0 @@
/v1/virtualbox/{uuid}/adapters/{adapter_id:\d+}/nio
-----------------------------------------------------------
.. contents::
POST /v1/virtualbox/**{uuid}**/adapters/**{adapter_id:\d+}**/nio
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Add a NIO to a VirtualBox VM instance
Parameters
**********
- **uuid**: Instance UUID
- **adapter_id**: Adapter where the nio should be added
Response status codes
**********************
- **400**: Invalid instance UUID
- **201**: NIO created
- **404**: Instance doesn't exist
DELETE /v1/virtualbox/**{uuid}**/adapters/**{adapter_id:\d+}**/nio
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Remove a NIO from a VirtualBox VM instance
Parameters
**********
- **uuid**: Instance UUID
- **adapter_id**: Adapter from where the nio should be removed
Response status codes
**********************
- **400**: Invalid instance UUID
- **404**: Instance doesn't exist
- **204**: NIO deleted

@ -1,29 +0,0 @@
/v1/virtualbox/{uuid}/capture/{adapter_id:\d+}/start
-----------------------------------------------------------
.. contents::
POST /v1/virtualbox/**{uuid}**/capture/**{adapter_id:\d+}**/start
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Start a packet capture on a VirtualBox VM instance
Parameters
**********
- **uuid**: Instance UUID
- **adapter_id**: Adapter to start a packet capture
Response status codes
**********************
- **200**: Capture started
- **400**: Invalid instance UUID
- **404**: Instance doesn't exist
Input
*******
.. raw:: html
<table>
<tr> <th>Name</th> <th>Mandatory</th> <th>Type</th> <th>Description</th> </tr>
<tr><td>capture_filename</td> <td>&#10004;</td> <td>string</td> <td>Capture file name</td> </tr>
</table>

@ -1,20 +0,0 @@
/v1/virtualbox/{uuid}/capture/{adapter_id:\d+}/stop
-----------------------------------------------------------
.. contents::
POST /v1/virtualbox/**{uuid}**/capture/**{adapter_id:\d+}**/stop
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Stop a packet capture on a VirtualBox VM instance
Parameters
**********
- **uuid**: Instance UUID
- **adapter_id**: Adapter to stop a packet capture
Response status codes
**********************
- **400**: Invalid instance UUID
- **404**: Instance doesn't exist
- **204**: Capture stopped

@ -1,19 +0,0 @@
/v1/virtualbox/{uuid}/reload
-----------------------------------------------------------
.. contents::
POST /v1/virtualbox/**{uuid}**/reload
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Reload a VirtualBox VM instance
Parameters
**********
- **uuid**: Instance UUID
Response status codes
**********************
- **400**: Invalid instance UUID
- **404**: Instance doesn't exist
- **204**: Instance reloaded

@ -1,19 +0,0 @@
/v1/virtualbox/{uuid}/resume
-----------------------------------------------------------
.. contents::
POST /v1/virtualbox/**{uuid}**/resume
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Resume a suspended VirtualBox VM instance
Parameters
**********
- **uuid**: Instance UUID
Response status codes
**********************
- **400**: Invalid instance UUID
- **404**: Instance doesn't exist
- **204**: Instance resumed

@ -1,19 +0,0 @@
/v1/virtualbox/{uuid}/start
-----------------------------------------------------------
.. contents::
POST /v1/virtualbox/**{uuid}**/start
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Start a VirtualBox VM instance
Parameters
**********
- **uuid**: Instance UUID
Response status codes
**********************
- **400**: Invalid instance UUID
- **404**: Instance doesn't exist
- **204**: Instance started

@ -1,19 +0,0 @@
/v1/virtualbox/{uuid}/stop
-----------------------------------------------------------
.. contents::
POST /v1/virtualbox/**{uuid}**/stop
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Stop a VirtualBox VM instance
Parameters
**********
- **uuid**: Instance UUID
Response status codes
**********************
- **400**: Invalid instance UUID
- **404**: Instance doesn't exist
- **204**: Instance stopped

@ -1,19 +0,0 @@
/v1/virtualbox/{uuid}/suspend
-----------------------------------------------------------
.. contents::
POST /v1/virtualbox/**{uuid}**/suspend
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Suspend a VirtualBox VM instance
Parameters
**********
- **uuid**: Instance UUID
Response status codes
**********************
- **400**: Invalid instance UUID
- **404**: Instance doesn't exist
- **204**: Instance suspended

@ -1,43 +0,0 @@
/v1/vpcs
-----------------------------------------------------------
.. contents::
POST /v1/vpcs
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Create a new VPCS instance
Response status codes
**********************
- **400**: Invalid project UUID
- **201**: Instance created
- **409**: Conflict
Input
*******
.. raw:: html
<table>
<tr> <th>Name</th> <th>Mandatory</th> <th>Type</th> <th>Description</th> </tr>
<tr><td>console</td> <td> </td> <td>['integer', 'null']</td> <td>console TCP port</td> </tr>
<tr><td>name</td> <td>&#10004;</td> <td>string</td> <td>VPCS device name</td> </tr>
<tr><td>project_id</td> <td>&#10004;</td> <td>string</td> <td>Project UUID</td> </tr>
<tr><td>startup_script</td> <td> </td> <td>['string', 'null']</td> <td>Content of the VPCS startup script</td> </tr>
<tr><td>uuid</td> <td> </td> <td>string</td> <td>VPCS device UUID</td> </tr>
<tr><td>vpcs_id</td> <td> </td> <td>integer</td> <td>VPCS device instance ID (for project created before GNS3 1.3)</td> </tr>
</table>
Output
*******
.. raw:: html
<table>
<tr> <th>Name</th> <th>Mandatory</th> <th>Type</th> <th>Description</th> </tr>
<tr><td>console</td> <td>&#10004;</td> <td>integer</td> <td>console TCP port</td> </tr>
<tr><td>name</td> <td>&#10004;</td> <td>string</td> <td>VPCS device name</td> </tr>
<tr><td>project_id</td> <td>&#10004;</td> <td>string</td> <td>Project UUID</td> </tr>
<tr><td>script_file</td> <td> </td> <td>['string', 'null']</td> <td>VPCS startup script</td> </tr>
<tr><td>startup_script</td> <td> </td> <td>['string', 'null']</td> <td>Content of the VPCS startup script</td> </tr>
<tr><td>uuid</td> <td>&#10004;</td> <td>string</td> <td>VPCS device UUID</td> </tr>
</table>

@ -1,86 +0,0 @@
/v1/vpcs/{uuid}
-----------------------------------------------------------
.. contents::
GET /v1/vpcs/**{uuid}**
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Get a VPCS instance
Parameters
**********
- **uuid**: Instance UUID
Response status codes
**********************
- **200**: Success
- **404**: Instance doesn't exist
Output
*******
.. raw:: html
<table>
<tr> <th>Name</th> <th>Mandatory</th> <th>Type</th> <th>Description</th> </tr>
<tr><td>console</td> <td>&#10004;</td> <td>integer</td> <td>console TCP port</td> </tr>
<tr><td>name</td> <td>&#10004;</td> <td>string</td> <td>VPCS device name</td> </tr>
<tr><td>project_id</td> <td>&#10004;</td> <td>string</td> <td>Project UUID</td> </tr>
<tr><td>script_file</td> <td> </td> <td>['string', 'null']</td> <td>VPCS startup script</td> </tr>
<tr><td>startup_script</td> <td> </td> <td>['string', 'null']</td> <td>Content of the VPCS startup script</td> </tr>
<tr><td>uuid</td> <td>&#10004;</td> <td>string</td> <td>VPCS device UUID</td> </tr>
</table>
PUT /v1/vpcs/**{uuid}**
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Update a VPCS instance
Parameters
**********
- **uuid**: Instance UUID
Response status codes
**********************
- **200**: Instance updated
- **409**: Conflict
- **404**: Instance doesn't exist
Input
*******
.. raw:: html
<table>
<tr> <th>Name</th> <th>Mandatory</th> <th>Type</th> <th>Description</th> </tr>
<tr><td>console</td> <td> </td> <td>['integer', 'null']</td> <td>console TCP port</td> </tr>
<tr><td>name</td> <td> </td> <td>['string', 'null']</td> <td>VPCS device name</td> </tr>
<tr><td>startup_script</td> <td> </td> <td>['string', 'null']</td> <td>Content of the VPCS startup script</td> </tr>
</table>
Output
*******
.. raw:: html
<table>
<tr> <th>Name</th> <th>Mandatory</th> <th>Type</th> <th>Description</th> </tr>
<tr><td>console</td> <td>&#10004;</td> <td>integer</td> <td>console TCP port</td> </tr>
<tr><td>name</td> <td>&#10004;</td> <td>string</td> <td>VPCS device name</td> </tr>
<tr><td>project_id</td> <td>&#10004;</td> <td>string</td> <td>Project UUID</td> </tr>
<tr><td>script_file</td> <td> </td> <td>['string', 'null']</td> <td>VPCS startup script</td> </tr>
<tr><td>startup_script</td> <td> </td> <td>['string', 'null']</td> <td>Content of the VPCS startup script</td> </tr>
<tr><td>uuid</td> <td>&#10004;</td> <td>string</td> <td>VPCS device UUID</td> </tr>
</table>
DELETE /v1/vpcs/**{uuid}**
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Delete a VPCS instance
Parameters
**********
- **uuid**: Instance UUID
Response status codes
**********************
- **404**: Instance doesn't exist
- **204**: Instance deleted

@ -1,36 +0,0 @@
/v1/vpcs/{uuid}/ports/{port_number:\d+}/nio
-----------------------------------------------------------
.. contents::
POST /v1/vpcs/**{uuid}**/ports/**{port_number:\d+}**/nio
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Add a NIO to a VPCS instance
Parameters
**********
- **uuid**: Instance UUID
- **port_number**: Port where the nio should be added
Response status codes
**********************
- **400**: Invalid instance UUID
- **201**: NIO created
- **404**: Instance doesn't exist
DELETE /v1/vpcs/**{uuid}**/ports/**{port_number:\d+}**/nio
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Remove a NIO from a VPCS instance
Parameters
**********
- **uuid**: Instance UUID
- **port_number**: Port from where the nio should be removed
Response status codes
**********************
- **400**: Invalid instance UUID
- **404**: Instance doesn't exist
- **204**: NIO deleted

@ -1,19 +0,0 @@
/v1/vpcs/{uuid}/reload
-----------------------------------------------------------
.. contents::
POST /v1/vpcs/**{uuid}**/reload
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Reload a VPCS instance
Parameters
**********
- **uuid**: Instance UUID
Response status codes
**********************
- **400**: Invalid instance UUID
- **404**: Instance doesn't exist
- **204**: Instance reloaded

@ -1,19 +0,0 @@
/v1/vpcs/{uuid}/start
-----------------------------------------------------------
.. contents::
POST /v1/vpcs/**{uuid}**/start
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Start a VPCS instance
Parameters
**********
- **uuid**: Instance UUID
Response status codes
**********************
- **400**: Invalid VPCS instance UUID
- **404**: Instance doesn't exist
- **204**: Instance started

@ -1,19 +0,0 @@
/v1/vpcs/{uuid}/stop
-----------------------------------------------------------
.. contents::
POST /v1/vpcs/**{uuid}**/stop
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Stop a VPCS instance
Parameters
**********
- **uuid**: Instance UUID
Response status codes
**********************
- **400**: Invalid VPCS instance UUID
- **404**: Instance doesn't exist
- **204**: Instance stopped

@ -23,6 +23,7 @@ from ..schemas.virtualbox import VBOX_NIO_SCHEMA
from ..schemas.virtualbox import VBOX_CAPTURE_SCHEMA
from ..schemas.virtualbox import VBOX_OBJECT_SCHEMA
from ..modules.virtualbox import VirtualBox
from ..modules.project_manager import ProjectManager
class VirtualBoxHandler:
@ -33,7 +34,7 @@ class VirtualBoxHandler:
@classmethod
@Route.get(
r"/virtualbox/vms_tmp",
r"/virtualbox/vms",
status_codes={
200: "Success",
},
@ -46,10 +47,13 @@ class VirtualBoxHandler:
@classmethod
@Route.post(
r"/virtualbox/vms",
r"/{project_id}/virtualbox/vms",
parameters={
"project_id": "UUID for the project"
},
status_codes={
201: "Instance created",
400: "Invalid project ID",
400: "Invalid request",
409: "Conflict"
},
description="Create a new VirtualBox VM instance",
@ -59,7 +63,7 @@ class VirtualBoxHandler:
vbox_manager = VirtualBox.instance()
vm = yield from vbox_manager.create_vm(request.json.pop("name"),
request.json.pop("project_id"),
request.match_info["project_id"],
request.json.get("vm_id"),
request.json.pop("vmname"),
request.json.pop("linked_clone"),
@ -74,12 +78,14 @@ class VirtualBoxHandler:
@classmethod
@Route.get(
r"/virtualbox/vms/{vm_id}",
r"/{project_id}/virtualbox/vms/{vm_id}",
parameters={
"project_id": "UUID for the project",
"vm_id": "UUID for the instance"
},
status_codes={
200: "Success",
400: "Invalid request",
404: "Instance doesn't exist"
},
description="Get a VirtualBox VM instance",
@ -87,17 +93,19 @@ class VirtualBoxHandler:
def show(request, response):
vbox_manager = VirtualBox.instance()
vm = vbox_manager.get_vm(request.match_info["vm_id"])
vm = vbox_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"])
response.json(vm)
@classmethod
@Route.put(
r"/virtualbox/vms/{vm_id}",
r"/{project_id}/virtualbox/vms/{vm_id}",
parameters={
"project_id": "UUID for the project",
"vm_id": "UUID for the instance"
},
status_codes={
200: "Instance updated",
400: "Invalid request",
404: "Instance doesn't exist",
409: "Conflict"
},
@ -107,7 +115,7 @@ class VirtualBoxHandler:
def update(request, response):
vbox_manager = VirtualBox.instance()
vm = vbox_manager.get_vm(request.match_info["vm_id"])
vm = vbox_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"])
for name, value in request.json.items():
if hasattr(vm, name) and getattr(vm, name) != value:
@ -118,124 +126,135 @@ class VirtualBoxHandler:
@classmethod
@Route.delete(
r"/virtualbox/vms/{vm_id}",
r"/{project_id}/virtualbox/vms/{vm_id}",
parameters={
"project_id": "UUID for the project",
"vm_id": "UUID for the instance"
},
status_codes={
204: "Instance deleted",
400: "Invalid request",
404: "Instance doesn't exist"
},
description="Delete a VirtualBox VM instance")
def delete(request, response):
# check the project_id exists
ProjectManager.instance().get_project(request.match_info["project_id"])
yield from VirtualBox.instance().delete_vm(request.match_info["vm_id"])
response.set_status(204)
@classmethod
@Route.post(
r"/virtualbox/vms/{vm_id}/start",
r"/{project_id}/virtualbox/vms/{vm_id}/start",
parameters={
"project_id": "UUID for the project",
"vm_id": "UUID for the instance"
},
status_codes={
204: "Instance started",
400: "Invalid instance UUID",
400: "Invalid request",
404: "Instance doesn't exist"
},
description="Start a VirtualBox VM instance")
def start(request, response):
vbox_manager = VirtualBox.instance()
vm = vbox_manager.get_vm(request.match_info["vm_id"])
vm = vbox_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"])
yield from vm.start()
response.set_status(204)
@classmethod
@Route.post(
r"/virtualbox/vms/{vm_id}/stop",
r"/{project_id}/virtualbox/vms/{vm_id}/stop",
parameters={
"project_id": "UUID for the project",
"vm_id": "UUID for the instance"
},
status_codes={
204: "Instance stopped",
400: "Invalid instance UUID",
400: "Invalid request",
404: "Instance doesn't exist"
},
description="Stop a VirtualBox VM instance")
def stop(request, response):
vbox_manager = VirtualBox.instance()
vm = vbox_manager.get_vm(request.match_info["vm_id"])
vm = vbox_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"])
yield from vm.stop()
response.set_status(204)
@classmethod
@Route.post(
r"/virtualbox/vms/{vm_id}/suspend",
r"/{project_id}/virtualbox/vms/{vm_id}/suspend",
parameters={
"project_id": "UUID for the project",
"vm_id": "UUID for the instance"
},
status_codes={
204: "Instance suspended",
400: "Invalid instance UUID",
400: "Invalid request",
404: "Instance doesn't exist"
},
description="Suspend a VirtualBox VM instance")
def suspend(request, response):
vbox_manager = VirtualBox.instance()
vm = vbox_manager.get_vm(request.match_info["vm_id"])
vm = vbox_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"])
yield from vm.suspend()
response.set_status(204)
@classmethod
@Route.post(
r"/virtualbox/vms/{vm_id}/resume",
r"/{project_id}/virtualbox/vms/{vm_id}/resume",
parameters={
"project_id": "UUID for the project",
"vm_id": "UUID for the instance"
},
status_codes={
204: "Instance resumed",
400: "Invalid instance UUID",
400: "Invalid request",
404: "Instance doesn't exist"
},
description="Resume a suspended VirtualBox VM instance")
def suspend(request, response):
vbox_manager = VirtualBox.instance()
vm = vbox_manager.get_vm(request.match_info["vm_id"])
vm = vbox_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"])
yield from vm.resume()
response.set_status(204)
@classmethod
@Route.post(
r"/virtualbox/vms/{vm_id}/reload",
r"/{project_id}/virtualbox/vms/{vm_id}/reload",
parameters={
"project_id": "UUID for the project",
"vm_id": "UUID for the instance"
},
status_codes={
204: "Instance reloaded",
400: "Invalid instance UUID",
400: "Invalid request",
404: "Instance doesn't exist"
},
description="Reload a VirtualBox VM instance")
def suspend(request, response):
def reload(request, response):
vbox_manager = VirtualBox.instance()
vm = vbox_manager.get_vm(request.match_info["vm_id"])
vm = vbox_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"])
yield from vm.reload()
response.set_status(204)
@Route.post(
r"/virtualbox/vms/{vm_id}/adapters/{adapter_id:\d+}/nio",
r"/{project_id}/virtualbox/vms/{vm_id}/adapters/{adapter_id:\d+}/nio",
parameters={
"project_id": "UUID for the project",
"vm_id": "UUID for the instance",
"adapter_id": "Adapter where the nio should be added"
},
status_codes={
201: "NIO created",
400: "Invalid instance UUID",
400: "Invalid request",
404: "Instance doesn't exist"
},
description="Add a NIO to a VirtualBox VM instance",
@ -244,7 +263,7 @@ class VirtualBoxHandler:
def create_nio(request, response):
vbox_manager = VirtualBox.instance()
vm = vbox_manager.get_vm(request.match_info["vm_id"])
vm = vbox_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"])
nio = vbox_manager.create_nio(vbox_manager.vboxmanage_path, request.json)
vm.port_add_nio_binding(int(request.match_info["adapter_id"]), nio)
response.set_status(201)
@ -252,33 +271,35 @@ class VirtualBoxHandler:
@classmethod
@Route.delete(
r"/virtualbox/vms/{vm_id}/adapters/{adapter_id:\d+}/nio",
r"/{project_id}/virtualbox/vms/{vm_id}/adapters/{adapter_id:\d+}/nio",
parameters={
"project_id": "UUID for the project",
"vm_id": "UUID for the instance",
"adapter_id": "Adapter from where the nio should be removed"
},
status_codes={
204: "NIO deleted",
400: "Invalid instance UUID",
400: "Invalid request",
404: "Instance doesn't exist"
},
description="Remove a NIO from a VirtualBox VM instance")
def delete_nio(request, response):
vbox_manager = VirtualBox.instance()
vm = vbox_manager.get_vm(request.match_info["vm_id"])
vm = vbox_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"])
vm.port_remove_nio_binding(int(request.match_info["adapter_id"]))
response.set_status(204)
@Route.post(
r"/virtualbox/{vm_id}/capture/{adapter_id:\d+}/start",
r"/{project_id}/virtualbox/{vm_id}/capture/{adapter_id:\d+}/start",
parameters={
"project_id": "UUID for the project",
"vm_id": "UUID for the instance",
"adapter_id": "Adapter to start a packet capture"
},
status_codes={
200: "Capture started",
400: "Invalid instance UUID",
400: "Invalid request",
404: "Instance doesn't exist"
},
description="Start a packet capture on a VirtualBox VM instance",
@ -286,27 +307,28 @@ class VirtualBoxHandler:
def start_capture(request, response):
vbox_manager = VirtualBox.instance()
vm = vbox_manager.get_vm(request.match_info["vm_id"])
vm = vbox_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"])
adapter_id = int(request.match_info["adapter_id"])
pcap_file_path = os.path.join(vm.project.capture_working_directory(), request.json["filename"])
vm.start_capture(adapter_id, pcap_file_path)
response.json({"pcap_file_path": pcap_file_path})
@Route.post(
r"/virtualbox/{vm_id}/capture/{adapter_id:\d+}/stop",
r"/{project_id}/virtualbox/{vm_id}/capture/{adapter_id:\d+}/stop",
parameters={
"project_id": "UUID for the project",
"vm_id": "UUID for the instance",
"adapter_id": "Adapter to stop a packet capture"
},
status_codes={
204: "Capture stopped",
400: "Invalid instance UUID",
400: "Invalid request",
404: "Instance doesn't exist"
},
description="Stop a packet capture on a VirtualBox VM instance")
def start_capture(request, response):
vbox_manager = VirtualBox.instance()
vm = vbox_manager.get_vm(request.match_info["vm_id"])
vm = vbox_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"])
vm.stop_capture(int(request.match_info["adapter_id"]))
response.set_status(204)

@ -31,10 +31,13 @@ class VPCSHandler:
@classmethod
@Route.post(
r"/vpcs/vms",
r"/{project_id}/vpcs/vms",
parameters={
"project_id": "UUID for the project"
},
status_codes={
201: "Instance created",
400: "Invalid project UUID",
400: "Invalid request",
409: "Conflict"
},
description="Create a new VPCS instance",
@ -44,7 +47,7 @@ class VPCSHandler:
vpcs = VPCS.instance()
vm = yield from vpcs.create_vm(request.json["name"],
request.json["project_id"],
request.match_info["project_id"],
request.json.get("vm_id"),
console=request.json.get("console"),
startup_script=request.json.get("startup_script"))
@ -53,12 +56,14 @@ class VPCSHandler:
@classmethod
@Route.get(
r"/vpcs/vms/{vm_id}",
r"/{project_id}/vpcs/vms/{vm_id}",
parameters={
"project_id": "UUID for the project",
"vm_id": "UUID for the instance"
},
status_codes={
200: "Success",
400: "Invalid request",
404: "Instance doesn't exist"
},
description="Get a VPCS instance",
@ -66,17 +71,19 @@ class VPCSHandler:
def show(request, response):
vpcs_manager = VPCS.instance()
vm = vpcs_manager.get_vm(request.match_info["vm_id"])
vm = vpcs_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"])
response.json(vm)
@classmethod
@Route.put(
r"/vpcs/vms/{vm_id}",
r"/{project_id}/vpcs/vms/{vm_id}",
parameters={
"project_id": "UUID for the project",
"vm_id": "UUID for the instance"
},
status_codes={
200: "Instance updated",
400: "Invalid request",
404: "Instance doesn't exist",
409: "Conflict"
},
@ -86,7 +93,7 @@ class VPCSHandler:
def update(request, response):
vpcs_manager = VPCS.instance()
vm = vpcs_manager.get_vm(request.match_info["vm_id"])
vm = vpcs_manager.get_vm(request.match_info["vm_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.startup_script = request.json.get("startup_script", vm.startup_script)
@ -94,12 +101,14 @@ class VPCSHandler:
@classmethod
@Route.delete(
r"/vpcs/vms/{vm_id}",
r"/{project_id}/vpcs/vms/{vm_id}",
parameters={
"project_id": "UUID for the project",
"vm_id": "UUID for the instance"
},
status_codes={
204: "Instance deleted",
400: "Invalid request",
404: "Instance doesn't exist"
},
description="Delete a VPCS instance")
@ -110,70 +119,74 @@ class VPCSHandler:
@classmethod
@Route.post(
r"/vpcs/vms/{vm_id}/start",
r"/{project_id}/vpcs/vms/{vm_id}/start",
parameters={
"project_id": "UUID for the project",
"vm_id": "UUID for the instance"
},
status_codes={
204: "Instance started",
400: "Invalid VPCS instance UUID",
400: "Invalid request",
404: "Instance doesn't exist"
},
description="Start a VPCS instance")
def start(request, response):
vpcs_manager = VPCS.instance()
vm = vpcs_manager.get_vm(request.match_info["vm_id"])
vm = vpcs_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"])
yield from vm.start()
response.set_status(204)
@classmethod
@Route.post(
r"/vpcs/vms/{vm_id}/stop",
r"/{project_id}/vpcs/vms/{vm_id}/stop",
parameters={
"project_id": "UUID for the project",
"vm_id": "UUID for the instance"
},
status_codes={
204: "Instance stopped",
400: "Invalid VPCS instance UUID",
400: "Invalid request",
404: "Instance doesn't exist"
},
description="Stop a VPCS instance")
def stop(request, response):
vpcs_manager = VPCS.instance()
vm = vpcs_manager.get_vm(request.match_info["vm_id"])
vm = vpcs_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"])
yield from vm.stop()
response.set_status(204)
@classmethod
@Route.post(
r"/vpcs/vms/{vm_id}/reload",
r"/{project_id}/vpcs/vms/{vm_id}/reload",
parameters={
"project_id": "UUID for the project",
"vm_id": "UUID for the instance",
},
status_codes={
204: "Instance reloaded",
400: "Invalid instance UUID",
400: "Invalid request",
404: "Instance doesn't exist"
},
description="Reload a VPCS instance")
def reload(request, response):
vpcs_manager = VPCS.instance()
vm = vpcs_manager.get_vm(request.match_info["vm_id"])
vm = vpcs_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"])
yield from vm.reload()
response.set_status(204)
@Route.post(
r"/vpcs/vms/{vm_id}/ports/{port_number:\d+}/nio",
r"/{project_id}/vpcs/vms/{vm_id}/ports/{port_number:\d+}/nio",
parameters={
"project_id": "UUID for the project",
"vm_id": "UUID for the instance",
"port_number": "Port where the nio should be added"
},
status_codes={
201: "NIO created",
400: "Invalid instance UUID",
400: "Invalid request",
404: "Instance doesn't exist"
},
description="Add a NIO to a VPCS instance",
@ -182,7 +195,7 @@ class VPCSHandler:
def create_nio(request, response):
vpcs_manager = VPCS.instance()
vm = vpcs_manager.get_vm(request.match_info["vm_id"])
vm = vpcs_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"])
nio = vpcs_manager.create_nio(vm.vpcs_path, request.json)
vm.port_add_nio_binding(int(request.match_info["port_number"]), nio)
response.set_status(201)
@ -190,20 +203,21 @@ class VPCSHandler:
@classmethod
@Route.delete(
r"/vpcs/vms/{vm_id}/ports/{port_number:\d+}/nio",
r"/{project_id}/vpcs/vms/{vm_id}/ports/{port_number:\d+}/nio",
parameters={
"project_id": "UUID for the project",
"vm_id": "UUID for the instance",
"port_number": "Port from where the nio should be removed"
},
status_codes={
204: "NIO deleted",
400: "Invalid instance UUID",
400: "Invalid request",
404: "Instance doesn't exist"
},
description="Remove a NIO from a VPCS instance")
def delete_nio(request, response):
vpcs_manager = VPCS.instance()
vm = vpcs_manager.get_vm(request.match_info["vm_id"])
vm = vpcs_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"])
vm.port_remove_nio_binding(int(request.match_info["port_number"]))
response.set_status(204)

@ -108,22 +108,34 @@ class BaseManager:
BaseManager._instance = None
log.debug("Module {} unloaded".format(self.module_name))
def get_vm(self, vm_id):
def get_vm(self, vm_id, project_id=None):
"""
Returns a VM instance.
:param vm_id: VM identifier
:param project_id: Project identifier
:returns: VM instance
"""
if project_id:
# check the project_id exists
project = ProjectManager.instance().get_project(project_id)
try:
UUID(vm_id, version=4)
except ValueError:
raise aiohttp.web.HTTPBadRequest(text="{} is not a valid UUID".format(vm_id))
raise aiohttp.web.HTTPBadRequest(text="VM ID {} is not a valid UUID".format(vm_id))
if vm_id not in self._vms:
raise aiohttp.web.HTTPNotFound(text="ID {} doesn't exist".format(vm_id))
raise aiohttp.web.HTTPNotFound(text="VM ID {} doesn't exist".format(vm_id))
vm = self._vms[vm_id]
if project_id:
if vm.project.id != project.id:
raise aiohttp.web.HTTPNotFound(text="Project ID {} doesn't belong to VM {}".format(project_id, vm.name))
return self._vms[vm_id]
@asyncio.coroutine

@ -54,7 +54,7 @@ class ProjectManager:
try:
UUID(project_id, version=4)
except ValueError:
raise aiohttp.web.HTTPBadRequest(text="{} is not a valid UUID".format(project_id))
raise aiohttp.web.HTTPBadRequest(text="Project ID {} is not a valid UUID".format(project_id))
if project_id not in self._projects:
raise aiohttp.web.HTTPNotFound(text="Project ID {} doesn't exist".format(project_id))

@ -28,13 +28,6 @@ VBOX_CREATE_SCHEMA = {
"maxLength": 36,
"pattern": "(^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}|\d+)$"
},
"project_id": {
"description": "Project UUID",
"type": "string",
"minLength": 36,
"maxLength": 36,
"pattern": "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$"
},
"linked_clone": {
"description": "either the VM is a linked clone or not",
"type": "boolean"
@ -82,7 +75,7 @@ VBOX_CREATE_SCHEMA = {
},
},
"additionalProperties": False,
"required": ["name", "vmname", "linked_clone", "project_id"],
"required": ["name", "vmname", "linked_clone"],
}
VBOX_UPDATE_SCHEMA = {

@ -33,13 +33,6 @@ VPCS_CREATE_SCHEMA = {
"maxLength": 36,
"pattern": "^([a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}|\d+)$"
},
"project_id": {
"description": "Project UUID",
"type": "string",
"minLength": 36,
"maxLength": 36,
"pattern": "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$"
},
"console": {
"description": "console TCP port",
"minimum": 1,
@ -52,7 +45,7 @@ VPCS_CREATE_SCHEMA = {
},
},
"additionalProperties": False,
"required": ["name", "project_id"]
"required": ["name"]
}
VPCS_UPDATE_SCHEMA = {

@ -22,10 +22,9 @@ from tests.utils import asyncio_patch
@pytest.fixture(scope="module")
def vm(server, project):
with asyncio_patch("gns3server.modules.virtualbox.virtualbox_vm.VirtualBoxVM.create", return_value=True) as mock:
response = server.post("/virtualbox/vms", {"name": "VMTEST",
"vmname": "VMTEST",
"linked_clone": False,
"project_id": project.id})
response = server.post("/{project_id}/virtualbox/vms".format(project_id=project.id), {"name": "VMTEST",
"vmname": "VMTEST",
"linked_clone": False})
assert mock.called
assert response.status == 201
return response.json
@ -34,10 +33,9 @@ def vm(server, project):
def test_vbox_create(server, project):
with asyncio_patch("gns3server.modules.virtualbox.virtualbox_vm.VirtualBoxVM.create", return_value=True):
response = server.post("/virtualbox/vms", {"name": "VM1",
"vmname": "VM1",
"linked_clone": False,
"project_id": project.id},
response = server.post("/{project_id}/virtualbox/vms".format(project_id=project.id), {"name": "VM1",
"vmname": "VM1",
"linked_clone": False},
example=True)
assert response.status == 201
assert response.json["name"] == "VM1"
@ -45,72 +43,74 @@ def test_vbox_create(server, project):
def test_vbox_get(server, project, vm):
response = server.get("/virtualbox/vms/{}".format(vm["vm_id"]), example=True)
response = server.get("/{project_id}/virtualbox/vms/{vm_id}".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True)
assert response.status == 200
assert response.route == "/virtualbox/vms/{vm_id}"
assert response.route == "/{project_id}/virtualbox/vms/{vm_id}"
assert response.json["name"] == "VMTEST"
assert response.json["project_id"] == project.id
def test_vbox_start(server, vm):
with asyncio_patch("gns3server.modules.virtualbox.virtualbox_vm.VirtualBoxVM.start", return_value=True) as mock:
response = server.post("/virtualbox/vms/{}/start".format(vm["vm_id"]))
response = server.post("/{project_id}/virtualbox/vms/{vm_id}/start".format(project_id=vm["project_id"], vm_id=vm["vm_id"]))
assert mock.called
assert response.status == 204
def test_vbox_stop(server, vm):
with asyncio_patch("gns3server.modules.virtualbox.virtualbox_vm.VirtualBoxVM.stop", return_value=True) as mock:
response = server.post("/virtualbox/vms/{}/stop".format(vm["vm_id"]))
response = server.post("/{project_id}/virtualbox/vms/{vm_id}/stop".format(project_id=vm["project_id"], vm_id=vm["vm_id"]))
assert mock.called
assert response.status == 204
def test_vbox_suspend(server, vm):
with asyncio_patch("gns3server.modules.virtualbox.virtualbox_vm.VirtualBoxVM.suspend", return_value=True) as mock:
response = server.post("/virtualbox/vms/{}/suspend".format(vm["vm_id"]))
response = server.post("/{project_id}/virtualbox/vms/{vm_id}/suspend".format(project_id=vm["project_id"], vm_id=vm["vm_id"]))
assert mock.called
assert response.status == 204
def test_vbox_resume(server, vm):
with asyncio_patch("gns3server.modules.virtualbox.virtualbox_vm.VirtualBoxVM.resume", return_value=True) as mock:
response = server.post("/virtualbox/vms/{}/resume".format(vm["vm_id"]))
response = server.post("/{project_id}/virtualbox/vms/{vm_id}/resume".format(project_id=vm["project_id"], vm_id=vm["vm_id"]))
assert mock.called
assert response.status == 204
def test_vbox_reload(server, vm):
with asyncio_patch("gns3server.modules.virtualbox.virtualbox_vm.VirtualBoxVM.reload", return_value=True) as mock:
response = server.post("/virtualbox/vms/{}/reload".format(vm["vm_id"]))
response = server.post("/{project_id}/virtualbox/vms/{vm_id}/reload".format(project_id=vm["project_id"], vm_id=vm["vm_id"]))
assert mock.called
assert response.status == 204
def test_vbox_nio_create_udp(server, vm):
response = server.post("/virtualbox/vms/{}/adapters/0/nio".format(vm["vm_id"]), {"type": "nio_udp",
"lport": 4242,
"rport": 4343,
"rhost": "127.0.0.1"},
response = server.post("/{project_id}/virtualbox/vms/{vm_id}/adapters/0/nio".format(project_id=vm["project_id"],
vm_id=vm["vm_id"]), {"type": "nio_udp",
"lport": 4242,
"rport": 4343,
"rhost": "127.0.0.1"},
example=True)
assert response.status == 201
assert response.route == "/virtualbox/vms/{vm_id}/adapters/{adapter_id:\d+}/nio"
assert response.route == "/{project_id}/virtualbox/vms/{vm_id}/adapters/{adapter_id:\d+}/nio"
assert response.json["type"] == "nio_udp"
def test_vbox_delete_nio(server, vm):
server.post("/virtualbox/vms/{}/adapters/0/nio".format(vm["vm_id"]), {"type": "nio_udp",
"lport": 4242,
"rport": 4343,
"rhost": "127.0.0.1"})
response = server.delete("/virtualbox/vms/{}/adapters/0/nio".format(vm["vm_id"]), example=True)
server.post("/{project_id}/virtualbox/vms/{vm_id}/adapters/0/nio".format(project_id=vm["project_id"],
vm_id=vm["vm_id"]), {"type": "nio_udp",
"lport": 4242,
"rport": 4343,
"rhost": "127.0.0.1"})
response = server.delete("/{project_id}/virtualbox/vms/{vm_id}/adapters/0/nio".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True)
assert response.status == 204
assert response.route == "/virtualbox/vms/{vm_id}/adapters/{adapter_id:\d+}/nio"
assert response.route == "/{project_id}/virtualbox/vms/{vm_id}/adapters/{adapter_id:\d+}/nio"
def test_vpcs_update(server, vm, free_console_port):
response = server.put("/virtualbox/vms/{}".format(vm["vm_id"]), {"name": "test",
"console": free_console_port})
def test_vbox_update(server, vm, free_console_port):
response = server.put("/{project_id}/virtualbox/vms/{vm_id}".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), {"name": "test",
"console": free_console_port})
assert response.status == 200
assert response.json["name"] == "test"
assert response.json["console"] == free_console_port

@ -23,108 +23,108 @@ from unittest.mock import patch
@pytest.fixture(scope="module")
def vm(server, project):
response = server.post("/vpcs/vms", {"name": "PC TEST 1", "project_id": project.id})
response = server.post("/{project_id}/vpcs/vms".format(project_id=project.id), {"name": "PC TEST 1"})
assert response.status == 201
return response.json
def test_vpcs_create(server, project):
response = server.post("/vpcs/vms", {"name": "PC TEST 1", "project_id": project.id}, example=True)
response = server.post("/{project_id}/vpcs/vms".format(project_id=project.id), {"name": "PC TEST 1"}, example=True)
assert response.status == 201
assert response.route == "/vpcs/vms"
assert response.route == "/{project_id}/vpcs/vms"
assert response.json["name"] == "PC TEST 1"
assert response.json["project_id"] == project.id
assert response.json["script_file"] is None
def test_vpcs_get(server, project, vm):
response = server.get("/vpcs/vms/{}".format(vm["vm_id"]), example=True)
response = server.get("/{project_id}/vpcs/vms/{vm_id}".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True)
assert response.status == 200
assert response.route == "/vpcs/vms/{vm_id}"
assert response.route == "/{project_id}/vpcs/vms/{vm_id}"
assert response.json["name"] == "PC TEST 1"
assert response.json["project_id"] == project.id
def test_vpcs_create_startup_script(server, project):
response = server.post("/vpcs/vms", {"name": "PC TEST 1", "project_id": project.id, "startup_script": "ip 192.168.1.2\necho TEST"})
response = server.post("/{project_id}/vpcs/vms".format(project_id=project.id), {"name": "PC TEST 1", "startup_script": "ip 192.168.1.2\necho TEST"})
assert response.status == 201
assert response.route == "/vpcs/vms"
assert response.route == "/{project_id}/vpcs/vms"
assert response.json["name"] == "PC TEST 1"
assert response.json["project_id"] == project.id
assert response.json["startup_script"] == "ip 192.168.1.2\necho TEST"
def test_vpcs_create_port(server, project, free_console_port):
response = server.post("/vpcs/vms", {"name": "PC TEST 1", "project_id": project.id, "console": free_console_port})
response = server.post("/{project_id}/vpcs/vms".format(project_id=project.id), {"name": "PC TEST 1", "console": free_console_port})
assert response.status == 201
assert response.route == "/vpcs/vms"
assert response.route == "/{project_id}/vpcs/vms"
assert response.json["name"] == "PC TEST 1"
assert response.json["project_id"] == project.id
assert response.json["console"] == free_console_port
def test_vpcs_nio_create_udp(server, vm):
response = server.post("/vpcs/vms/{}/ports/0/nio".format(vm["vm_id"]), {"type": "nio_udp",
"lport": 4242,
"rport": 4343,
"rhost": "127.0.0.1"},
response = server.post("/{project_id}/vpcs/vms/{vm_id}/ports/0/nio".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), {"type": "nio_udp",
"lport": 4242,
"rport": 4343,
"rhost": "127.0.0.1"},
example=True)
assert response.status == 201
assert response.route == "/vpcs/vms/{vm_id}/ports/{port_number:\d+}/nio"
assert response.route == "/{project_id}/vpcs/vms/{vm_id}/ports/{port_number:\d+}/nio"
assert response.json["type"] == "nio_udp"
def test_vpcs_nio_create_tap(server, vm):
with patch("gns3server.modules.base_manager.BaseManager._has_privileged_access", return_value=True):
response = server.post("/vpcs/vms/{}/ports/0/nio".format(vm["vm_id"]), {"type": "nio_tap",
"tap_device": "test"})
response = server.post("/{project_id}/vpcs/vms/{vm_id}/ports/0/nio".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), {"type": "nio_tap",
"tap_device": "test"})
assert response.status == 201
assert response.route == "/vpcs/vms/{vm_id}/ports/{port_number:\d+}/nio"
assert response.route == "/{project_id}/vpcs/vms/{vm_id}/ports/{port_number:\d+}/nio"
assert response.json["type"] == "nio_tap"
def test_vpcs_delete_nio(server, vm):
server.post("/vpcs/vms/{}/ports/0/nio".format(vm["vm_id"]), {"type": "nio_udp",
"lport": 4242,
"rport": 4343,
"rhost": "127.0.0.1"})
response = server.delete("/vpcs/vms/{}/ports/0/nio".format(vm["vm_id"]), example=True)
server.post("/{project_id}/vpcs/vms/{vm_id}/ports/0/nio".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), {"type": "nio_udp",
"lport": 4242,
"rport": 4343,
"rhost": "127.0.0.1"})
response = server.delete("/{project_id}/vpcs/vms/{vm_id}/ports/0/nio".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True)
assert response.status == 204
assert response.route == "/vpcs/vms/{vm_id}/ports/{port_number:\d+}/nio"
assert response.route == "/{project_id}/vpcs/vms/{vm_id}/ports/{port_number:\d+}/nio"
def test_vpcs_start(server, vm):
with asyncio_patch("gns3server.modules.vpcs.vpcs_vm.VPCSVM.start", return_value=True) as mock:
response = server.post("/vpcs/vms/{}/start".format(vm["vm_id"]))
response = server.post("/{project_id}/vpcs/vms/{vm_id}/start".format(project_id=vm["project_id"], vm_id=vm["vm_id"]))
assert mock.called
assert response.status == 204
def test_vpcs_stop(server, vm):
with asyncio_patch("gns3server.modules.vpcs.vpcs_vm.VPCSVM.stop", return_value=True) as mock:
response = server.post("/vpcs/vms/{}/stop".format(vm["vm_id"]))
response = server.post("/{project_id}/vpcs/vms/{vm_id}/stop".format(project_id=vm["project_id"], vm_id=vm["vm_id"]))
assert mock.called
assert response.status == 204
def test_vpcs_reload(server, vm):
with asyncio_patch("gns3server.modules.vpcs.vpcs_vm.VPCSVM.reload", return_value=True) as mock:
response = server.post("/vpcs/vms/{}/reload".format(vm["vm_id"]))
response = server.post("/{project_id}/vpcs/vms/{vm_id}/reload".format(project_id=vm["project_id"], vm_id=vm["vm_id"]))
assert mock.called
assert response.status == 204
def test_vpcs_delete(server, vm):
with asyncio_patch("gns3server.modules.vpcs.VPCS.delete_vm", return_value=True) as mock:
response = server.delete("/vpcs/vms/{}".format(vm["vm_id"]))
response = server.delete("/{project_id}/vpcs/vms/{vm_id}".format(project_id=vm["project_id"], vm_id=vm["vm_id"]))
assert mock.called
assert response.status == 204
def test_vpcs_update(server, vm, tmpdir, free_console_port):
response = server.put("/vpcs/vms/{}".format(vm["vm_id"]), {"name": "test",
"console": free_console_port,
"startup_script": "ip 192.168.1.1"})
response = server.put("/{project_id}/vpcs/vms/{vm_id}".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), {"name": "test",
"console": free_console_port,
"startup_script": "ip 192.168.1.1"})
assert response.status == 200
assert response.json["name"] == "test"
assert response.json["console"] == free_console_port

Loading…
Cancel
Save