Compare commits

...
39 Commits
Author SHA1 Message Date
grossmj fbd8f6ce28 Release v2.2.45 2024-01-12 21:38:26 +11:00
grossmj 195da24910 Bundle web-ui v2.2.45 2024-01-12 21:34:11 +11:00
grossmj b4c7609aeb Remove old web-ui files 2024-01-12 21:29:04 +11:00
grossmj cd9c4c84b6 Bundle web-ui v2.2.45 2024-01-12 21:21:18 +11:00
grossmj 2566de0f5a Sync appliances 2024-01-12 21:13:52 +11:00
grossmj 6a069d0af6 Fix mouse offset issues with VNC in Qemu. Fixes #2335 2024-01-12 16:18:32 +11:00
grossmj 2789b3802a Fix issues when generating docs 2024-01-12 16:14:01 +11:00
grossmj 9e1a1337d4 Update readthedocs.yml to use Python 3.12 2024-01-12 15:27:41 +11:00
Jeremy Grossmann 466eb8128e Merge pull request #2336 from GNS3/fix/2319
Refactor project notifications
2024-01-12 13:38:51 +11:00
grossmj e41227b5bd Update readthedocs.yml 2024-01-12 13:32:15 +11:00
grossmj 78a3b8e824 Update documentation 2024-01-12 13:21:34 +11:00
grossmj 4c149e1614 Add project.created, project.opened and project.deleted controller notification stream.
Move project.updated and project.closed from project notification to controller notification stream.
2024-01-12 13:16:55 +11:00
grossmj 473fa98eda Do not stop searching for Qemu binaries if one binary cannot be executed. Ref #2306 2024-01-11 23:11:56 +11:00
grossmj 13d9afd8bc Fix Ethernet switch and Ethernet hub port validations. Fixes #2334 2024-01-11 22:40:38 +11:00
grossmj b4edbbbaa7 Bundle dev version of the web-ui 2023-12-07 12:34:52 +10:00
grossmj 02e19800fb Update CORS policy 2023-12-06 22:33:55 +10:00
grossmj 24bb0ca419 Add custom executable paths on Windows 2023-12-05 21:24:40 +10:00
grossmj 6c5f75bf43 Upgrade sentry-sdk and aiohttp 2023-11-22 10:32:50 +10:00
grossmj 7afdcbb3d3 Development in 2.2.45.dev3 2023-11-07 19:11:57 +10:00
grossmj c88f76b740 Release v2.2.44.1 2023-11-07 14:59:28 +10:00
grossmj b81cc14cef Do not compute checksums on macOS 2023-11-07 14:30:39 +10:00
grossmj aa133c3b8a Add multiprocessing.set_start_method() 2023-11-07 13:33:43 +10:00
grossmj 7449064ea2 Bump version to v2.2.45.dev2 2023-11-07 12:21:39 +10:00
grossmj db315e3c3c Have freeze support for macOS as well 2023-11-07 11:17:48 +10:00
grossmj c437482e85 Catch exceptions when computing image checksums. Ref https://github.com/GNS3/gns3-server/issues/2228 2023-11-07 11:08:47 +10:00
grossmj aac6fbfc31 Add freeze_support() for multiprocessing 2023-11-07 10:42:53 +10:00
grossmj 3c4b5db1ca Development on 2.2.45.dev1 2023-11-06 17:00:17 +10:00
grossmj 5c8abdc6fd Release v2.2.44 2023-11-06 16:02:23 +10:00
grossmj f80f41b5b3 Sync appliances 2023-11-06 15:58:21 +10:00
grossmj 503373a6e9 Bundle web-ui v2.2.44 2023-11-06 15:53:51 +10:00
grossmj 8236c85b5f Upgrade sentry-sdk 2023-11-06 15:44:30 +10:00
grossmj ae825b0080 Non-blocking checksums computation when server starts. Fixes #2228 2023-11-06 12:32:23 +10:00
grossmj 191feed669 Fix timeout issue when creating Qemu disk image. Fixes https://github.com/GNS3/gns3-server/issues/2313 2023-11-05 15:41:46 +10:00
grossmj 3b22bcfe96 Support for web socket console over HTTPS 2023-11-03 14:40:40 +10:00
grossmj 0f07b9e019 Add back script create_cert.sh 2023-11-03 12:31:34 +10:00
grossmj 8676a3dccf Bundle web-ui 2023-11-02 17:40:47 +10:00
grossmj b0dbf59ac4 Use Python 3.8 in appveyor.yml 2023-10-31 14:48:08 +10:00
Jeremy Grossmann 14fd165f2a Merge pull request #2307 from GNS3/fix/3521
Allow disabling hardware virtualization check
2023-10-30 15:03:50 +10:00
grossmj 7c49a9160c Allow disabling hardware virtualization check 2023-10-30 14:57:11 +10:00
68 changed files with 780 additions and 322 deletions

No files matched your search

+30
View File
@@ -1,5 +1,35 @@
# Change Log
## 2.2.45 12/01/2024
* Bundle web-ui v2.2.45
* Fix mouse offset issues with VNC in Qemu. Fixes #2335
* Add project.created, project.opened and project.deleted controller notification stream. Move project.updated and project.closed from project notification to controller notification stream.
* Do not stop searching for Qemu binaries if one binary cannot be executed. Ref #2306
* Fix Ethernet switch and Ethernet hub port validations. Fixes #2334
* Update CORS policy
* Add custom executable paths on Windows
* Upgrade sentry-sdk and aiohttp
## 2.2.44.1 07/11/2023
* Catch exceptions when computing image checksums. Ref https://github.com/GNS3/gns3-server/issues/2228
* Add freeze_support() for multiprocessing
## 2.2.44 06/11/2023
* Bundle web-ui v2.2.44
* Non-blocking checksums computation when server starts. Fixes #2228
* Fix timeout issue when creating Qemu disk image. Fixes https://github.com/GNS3/gns3-server/issues/2313
* Support for web socket console over HTTPS
* Add back script create_cert.sh
* Allow disabling hardware virtualization check
* Fix L2IOU "failed code signing checks" when IOU base file name is >= 63 characters
* Change "ip cef" to "no ip cef" in IOU default configs. Fixes #2298
* Add Qemu IGB network device
* Add Python 3.12 support.
* Fix issue with importlib.resources.files() and Python 3.9
## 2.2.43 19/09/2023
* Force English output for VBoxManage. Fixes #2266
+1 -1
View File
@@ -5,7 +5,7 @@ image: Visual Studio 2022
platform: x64
environment:
PYTHON: "C:\\Python37-x64"
PYTHON: "C:\\Python38-x64"
DISTUTILS_USE_SDK: "1"
API_TOKEN:
secure: VEKn4bYH3QO0ixtQW5ni4Enmn8cS1NlZV246ludBDgQ=
+3
View File
@@ -62,6 +62,9 @@ default_nat_interface = vmnet10
; Enable the built-in templates
enable_builtin_templates = True
; check if hardware virtualization is used by other emulators (KVM, VMware or VirtualBox)
hardware_virtualization_check = True
[VPCS]
; VPCS executable location, default: search in PATH
;vpcs_path = vpcs
+5 -4
View File
@@ -11,7 +11,8 @@
10
]
},
"link_id": "b76bd8b1-2171-4361-9228-801713d23079",
"link_id": "c3f1b38a-160d-4a67-baa0-34fc3d9759ed",
"link_style": {},
"link_type": "ethernet",
"nodes": [
{
@@ -21,7 +22,7 @@
"x": 64,
"y": 0
},
"node_id": "8b77b480-361e-488b-96b1-a769890e11ec",
"node_id": "481e5898-cd97-4351-8b1e-0c9e77fc7c58",
"port_number": 3
},
{
@@ -30,10 +31,10 @@
"style": "font-family: TypeWriter;font-size: 10.0;font-weight: bold;fill: #000000;fill-opacity: 1.0;",
"text": "2/4"
},
"node_id": "b4688a3d-0af8-4ddc-b85f-e26dc1031c4c",
"node_id": "63f7b8ab-146d-4142-b8c5-cf387ac1d963",
"port_number": 4
}
],
"project_id": "85333131-b83a-4112-9a51-184ba0c536a8",
"project_id": "292936d2-9f54-4e29-959f-b59ed9ac5e6f",
"suspend": false
}
+1 -1
View File
@@ -1,3 +1,3 @@
{
"message": "Warning ASA 8 is not officialy supported by GNS3"
"message": "Warning ASA 8 is not officially supported by GNS3"
}
+3
View File
@@ -0,0 +1,3 @@
{
"a": "b"
}
+3
View File
@@ -0,0 +1,3 @@
{
"a": "b"
}
@@ -0,0 +1,21 @@
{
"auto_close": true,
"auto_open": false,
"auto_start": false,
"drawing_grid_size": 25,
"filename": "Test.gns3",
"grid_size": 75,
"name": "Test",
"path": "/tmp/tmprusds8mt/projects/87d4b692-52b4-4b4c-8828-13666306a68a",
"project_id": "87d4b692-52b4-4b4c-8828-13666306a68a",
"scene_height": 1000,
"scene_width": 2000,
"show_grid": false,
"show_interface_labels": false,
"show_layers": false,
"snap_to_grid": false,
"status": "opened",
"supplier": null,
"variables": null,
"zoom": 100
}
@@ -0,0 +1,21 @@
{
"auto_close": true,
"auto_open": false,
"auto_start": false,
"drawing_grid_size": 25,
"filename": "Test.gns3",
"grid_size": 75,
"name": "Test",
"path": "/tmp/tmpvqf8d5mx/projects/6f01ee8c-5fe7-47a2-95ab-a0f4c0a355f9",
"project_id": "6f01ee8c-5fe7-47a2-95ab-a0f4c0a355f9",
"scene_height": 1000,
"scene_width": 2000,
"show_grid": false,
"show_interface_labels": false,
"show_layers": false,
"snap_to_grid": false,
"status": "closed",
"supplier": null,
"variables": null,
"zoom": 100
}
@@ -0,0 +1,21 @@
{
"auto_close": true,
"auto_open": false,
"auto_start": false,
"drawing_grid_size": 25,
"filename": "test.gns3",
"grid_size": 75,
"name": "test",
"path": "/tmp/tmp7swwxptj/projects/e5b0b37a-a74e-40a2-9adb-42908f146fba",
"project_id": "e5b0b37a-a74e-40a2-9adb-42908f146fba",
"scene_height": 1000,
"scene_width": 2000,
"show_grid": false,
"show_interface_labels": false,
"show_layers": false,
"snap_to_grid": false,
"status": "opened",
"supplier": null,
"variables": null,
"zoom": 100
}
@@ -23,7 +23,7 @@ Types
+++++++++
EthernetSwitchPort
^^^^^^^^^^^^^^^^^^^^^^
Ethernet port
Ethernet switch port
.. raw:: html
@@ -56,7 +56,7 @@ Types
+++++++++
EthernetSwitchPort
^^^^^^^^^^^^^^^^^^^^^^
Ethernet port
Ethernet switch port
.. raw:: html
@@ -23,7 +23,7 @@ Input
<table>
<tr> <th>Name</th> <th>Mandatory</th> <th>Type</th> <th>Description</th> </tr>
<tr><td>application_id</td> <td> </td> <td>['integer', 'null']</td> <td>Application ID for running IOU image</td> </tr>
<tr><td>application_id</td> <td>&#10004;</td> <td>['integer', 'null']</td> <td>Application ID for running IOU image</td> </tr>
<tr><td>console</td> <td> </td> <td>['integer', 'null']</td> <td>Console TCP port</td> </tr>
<tr><td>console_type</td> <td> </td> <td>enum</td> <td>Possible values: telnet, none</td> </tr>
<tr><td>ethernet_adapters</td> <td> </td> <td>integer</td> <td>How many ethernet adapters are connected to the IOU</td> </tr>
+2
View File
@@ -35,6 +35,8 @@ Input
<table>
<tr> <th>Name</th> <th>Mandatory</th> <th>Type</th> <th>Description</th> </tr>
<tr><td>auto_close</td> <td> </td> <td>boolean</td> <td>Project auto close</td> </tr>
<tr><td>auto_open</td> <td> </td> <td>boolean</td> <td>Project open when GNS3 start</td> </tr>
<tr><td>auto_start</td> <td> </td> <td>boolean</td> <td>Project start when opened</td> </tr>
<tr><td>drawing_grid_size</td> <td> </td> <td>integer</td> <td>Grid size for the drawing area for drawings</td> </tr>
<tr><td>grid_size</td> <td> </td> <td>integer</td> <td>Grid size for the drawing area for nodes</td> </tr>
<tr><td>name</td> <td>&#10004;</td> <td>['string', 'null']</td> <td>Project name</td> </tr>
@@ -34,6 +34,7 @@ Input
<tr><td>console_type</td> <td> </td> <td>enum</td> <td>Possible values: telnet, vnc, spice, spice+agent, none</td> </tr>
<tr><td>cpu_throttling</td> <td> </td> <td>['integer', 'null']</td> <td>Percentage of CPU allowed for QEMU</td> </tr>
<tr><td>cpus</td> <td> </td> <td>['integer', 'null']</td> <td>Number of vCPUs</td> </tr>
<tr><td>create_config_disk</td> <td> </td> <td>['boolean', 'null']</td> <td>Automatically create a config disk on HDD disk interface (secondary slave)</td> </tr>
<tr><td>custom_adapters</td> <td> </td> <td>array</td> <td></td> </tr>
<tr><td>hda_disk_image</td> <td> </td> <td>string</td> <td>QEMU hda disk image path</td> </tr>
<tr><td>hda_disk_image_md5sum</td> <td> </td> <td>['string', 'null']</td> <td>QEMU hda disk image checksum</td> </tr>
@@ -63,6 +64,9 @@ Input
<tr><td>process_priority</td> <td> </td> <td>enum</td> <td>Possible values: realtime, very high, high, normal, low, very low, null</td> </tr>
<tr><td>qemu_path</td> <td> </td> <td>['string', 'null']</td> <td>Path to QEMU</td> </tr>
<tr><td>ram</td> <td> </td> <td>['integer', 'null']</td> <td>Amount of RAM in MB</td> </tr>
<tr><td>replicate_network_connection_state</td> <td> </td> <td>['boolean', 'null']</td> <td>Replicate the network connection state for links in Qemu</td> </tr>
<tr><td>tpm</td> <td> </td> <td>['boolean', 'null']</td> <td>Enable the Trusted Platform Module (TPM) in Qemu</td> </tr>
<tr><td>uefi</td> <td> </td> <td>['boolean', 'null']</td> <td>Enable the UEFI boot mode in Qemu</td> </tr>
<tr><td>usage</td> <td> </td> <td>string</td> <td>How to use the Qemu VM</td> </tr>
</table>
@@ -84,6 +88,7 @@ Output
<tr><td>console_type</td> <td>&#10004;</td> <td>enum</td> <td>Possible values: telnet, vnc, spice, spice+agent, none</td> </tr>
<tr><td>cpu_throttling</td> <td>&#10004;</td> <td>integer</td> <td>Percentage of CPU allowed for QEMU</td> </tr>
<tr><td>cpus</td> <td>&#10004;</td> <td>['integer', 'null']</td> <td>Number of vCPUs</td> </tr>
<tr><td>create_config_disk</td> <td>&#10004;</td> <td>['boolean', 'null']</td> <td>Automatically create a config disk on HDD disk interface (secondary slave)</td> </tr>
<tr><td>hda_disk_image</td> <td>&#10004;</td> <td>string</td> <td>QEMU hda disk image path</td> </tr>
<tr><td>hda_disk_image_md5sum</td> <td>&#10004;</td> <td>['string', 'null']</td> <td>QEMU hda disk image checksum</td> </tr>
<tr><td>hda_disk_interface</td> <td>&#10004;</td> <td>string</td> <td>QEMU hda interface</td> </tr>
@@ -113,8 +118,11 @@ Output
<tr><td>project_id</td> <td>&#10004;</td> <td>string</td> <td>Project UUID</td> </tr>
<tr><td>qemu_path</td> <td>&#10004;</td> <td>string</td> <td>Path to QEMU</td> </tr>
<tr><td>ram</td> <td>&#10004;</td> <td>integer</td> <td>Amount of RAM in MB</td> </tr>
<tr><td>replicate_network_connection_state</td> <td>&#10004;</td> <td>boolean</td> <td>Replicate the network connection state for links in Qemu</td> </tr>
<tr><td>save_vm_state</td> <td> </td> <td>['boolean', 'null']</td> <td>Save VM state support</td> </tr>
<tr><td>status</td> <td>&#10004;</td> <td>enum</td> <td>Possible values: started, stopped, suspended</td> </tr>
<tr><td>tpm</td> <td>&#10004;</td> <td>boolean</td> <td>Enable the Trusted Platform Module (TPM) in Qemu</td> </tr>
<tr><td>uefi</td> <td>&#10004;</td> <td>boolean</td> <td>Enable the UEFI boot mode in Qemu</td> </tr>
<tr><td>usage</td> <td>&#10004;</td> <td>string</td> <td>How to use the QEMU VM</td> </tr>
</table>
@@ -36,6 +36,7 @@ Output
<tr><td>console_type</td> <td>&#10004;</td> <td>enum</td> <td>Possible values: telnet, vnc, spice, spice+agent, none</td> </tr>
<tr><td>cpu_throttling</td> <td>&#10004;</td> <td>integer</td> <td>Percentage of CPU allowed for QEMU</td> </tr>
<tr><td>cpus</td> <td>&#10004;</td> <td>['integer', 'null']</td> <td>Number of vCPUs</td> </tr>
<tr><td>create_config_disk</td> <td>&#10004;</td> <td>['boolean', 'null']</td> <td>Automatically create a config disk on HDD disk interface (secondary slave)</td> </tr>
<tr><td>hda_disk_image</td> <td>&#10004;</td> <td>string</td> <td>QEMU hda disk image path</td> </tr>
<tr><td>hda_disk_image_md5sum</td> <td>&#10004;</td> <td>['string', 'null']</td> <td>QEMU hda disk image checksum</td> </tr>
<tr><td>hda_disk_interface</td> <td>&#10004;</td> <td>string</td> <td>QEMU hda interface</td> </tr>
@@ -65,8 +66,11 @@ Output
<tr><td>project_id</td> <td>&#10004;</td> <td>string</td> <td>Project UUID</td> </tr>
<tr><td>qemu_path</td> <td>&#10004;</td> <td>string</td> <td>Path to QEMU</td> </tr>
<tr><td>ram</td> <td>&#10004;</td> <td>integer</td> <td>Amount of RAM in MB</td> </tr>
<tr><td>replicate_network_connection_state</td> <td>&#10004;</td> <td>boolean</td> <td>Replicate the network connection state for links in Qemu</td> </tr>
<tr><td>save_vm_state</td> <td> </td> <td>['boolean', 'null']</td> <td>Save VM state support</td> </tr>
<tr><td>status</td> <td>&#10004;</td> <td>enum</td> <td>Possible values: started, stopped, suspended</td> </tr>
<tr><td>tpm</td> <td>&#10004;</td> <td>boolean</td> <td>Enable the Trusted Platform Module (TPM) in Qemu</td> </tr>
<tr><td>uefi</td> <td>&#10004;</td> <td>boolean</td> <td>Enable the UEFI boot mode in Qemu</td> </tr>
<tr><td>usage</td> <td>&#10004;</td> <td>string</td> <td>How to use the QEMU VM</td> </tr>
</table>
@@ -110,6 +114,7 @@ Input
<tr><td>console_type</td> <td> </td> <td>enum</td> <td>Possible values: telnet, vnc, spice, spice+agent, none</td> </tr>
<tr><td>cpu_throttling</td> <td> </td> <td>['integer', 'null']</td> <td>Percentage of CPU allowed for QEMU</td> </tr>
<tr><td>cpus</td> <td> </td> <td>['integer', 'null']</td> <td>Number of vCPUs</td> </tr>
<tr><td>create_config_disk</td> <td> </td> <td>['boolean', 'null']</td> <td>Automatically create a config disk on HDD disk interface (secondary slave)</td> </tr>
<tr><td>custom_adapters</td> <td> </td> <td>array</td> <td></td> </tr>
<tr><td>hda_disk_image</td> <td> </td> <td>string</td> <td>QEMU hda disk image path</td> </tr>
<tr><td>hda_disk_image_md5sum</td> <td> </td> <td>['string', 'null']</td> <td>QEMU hda disk image checksum</td> </tr>
@@ -138,6 +143,9 @@ Input
<tr><td>process_priority</td> <td> </td> <td>enum</td> <td>Possible values: realtime, very high, high, normal, low, very low, null</td> </tr>
<tr><td>qemu_path</td> <td> </td> <td>['string', 'null']</td> <td>Path to QEMU</td> </tr>
<tr><td>ram</td> <td> </td> <td>['integer', 'null']</td> <td>Amount of RAM in MB</td> </tr>
<tr><td>replicate_network_connection_state</td> <td> </td> <td>['boolean', 'null']</td> <td>Replicate the network connection state for links in Qemu</td> </tr>
<tr><td>tpm</td> <td> </td> <td>['boolean', 'null']</td> <td>Enable the Trusted Platform Module (TPM) in Qemu</td> </tr>
<tr><td>uefi</td> <td> </td> <td>['boolean', 'null']</td> <td>Enable the UEFI boot mode in Qemu</td> </tr>
<tr><td>usage</td> <td> </td> <td>string</td> <td>How to use the QEMU VM</td> </tr>
</table>
@@ -159,6 +167,7 @@ Output
<tr><td>console_type</td> <td>&#10004;</td> <td>enum</td> <td>Possible values: telnet, vnc, spice, spice+agent, none</td> </tr>
<tr><td>cpu_throttling</td> <td>&#10004;</td> <td>integer</td> <td>Percentage of CPU allowed for QEMU</td> </tr>
<tr><td>cpus</td> <td>&#10004;</td> <td>['integer', 'null']</td> <td>Number of vCPUs</td> </tr>
<tr><td>create_config_disk</td> <td>&#10004;</td> <td>['boolean', 'null']</td> <td>Automatically create a config disk on HDD disk interface (secondary slave)</td> </tr>
<tr><td>hda_disk_image</td> <td>&#10004;</td> <td>string</td> <td>QEMU hda disk image path</td> </tr>
<tr><td>hda_disk_image_md5sum</td> <td>&#10004;</td> <td>['string', 'null']</td> <td>QEMU hda disk image checksum</td> </tr>
<tr><td>hda_disk_interface</td> <td>&#10004;</td> <td>string</td> <td>QEMU hda interface</td> </tr>
@@ -188,8 +197,11 @@ Output
<tr><td>project_id</td> <td>&#10004;</td> <td>string</td> <td>Project UUID</td> </tr>
<tr><td>qemu_path</td> <td>&#10004;</td> <td>string</td> <td>Path to QEMU</td> </tr>
<tr><td>ram</td> <td>&#10004;</td> <td>integer</td> <td>Amount of RAM in MB</td> </tr>
<tr><td>replicate_network_connection_state</td> <td>&#10004;</td> <td>boolean</td> <td>Replicate the network connection state for links in Qemu</td> </tr>
<tr><td>save_vm_state</td> <td> </td> <td>['boolean', 'null']</td> <td>Save VM state support</td> </tr>
<tr><td>status</td> <td>&#10004;</td> <td>enum</td> <td>Possible values: started, stopped, suspended</td> </tr>
<tr><td>tpm</td> <td>&#10004;</td> <td>boolean</td> <td>Enable the Trusted Platform Module (TPM) in Qemu</td> </tr>
<tr><td>uefi</td> <td>&#10004;</td> <td>boolean</td> <td>Enable the UEFI boot mode in Qemu</td> </tr>
<tr><td>usage</td> <td>&#10004;</td> <td>string</td> <td>How to use the QEMU VM</td> </tr>
</table>
@@ -36,6 +36,7 @@ Output
<tr><td>console_type</td> <td>&#10004;</td> <td>enum</td> <td>Possible values: telnet, vnc, spice, spice+agent, none</td> </tr>
<tr><td>cpu_throttling</td> <td>&#10004;</td> <td>integer</td> <td>Percentage of CPU allowed for QEMU</td> </tr>
<tr><td>cpus</td> <td>&#10004;</td> <td>['integer', 'null']</td> <td>Number of vCPUs</td> </tr>
<tr><td>create_config_disk</td> <td>&#10004;</td> <td>['boolean', 'null']</td> <td>Automatically create a config disk on HDD disk interface (secondary slave)</td> </tr>
<tr><td>hda_disk_image</td> <td>&#10004;</td> <td>string</td> <td>QEMU hda disk image path</td> </tr>
<tr><td>hda_disk_image_md5sum</td> <td>&#10004;</td> <td>['string', 'null']</td> <td>QEMU hda disk image checksum</td> </tr>
<tr><td>hda_disk_interface</td> <td>&#10004;</td> <td>string</td> <td>QEMU hda interface</td> </tr>
@@ -65,8 +66,11 @@ Output
<tr><td>project_id</td> <td>&#10004;</td> <td>string</td> <td>Project UUID</td> </tr>
<tr><td>qemu_path</td> <td>&#10004;</td> <td>string</td> <td>Path to QEMU</td> </tr>
<tr><td>ram</td> <td>&#10004;</td> <td>integer</td> <td>Amount of RAM in MB</td> </tr>
<tr><td>replicate_network_connection_state</td> <td>&#10004;</td> <td>boolean</td> <td>Replicate the network connection state for links in Qemu</td> </tr>
<tr><td>save_vm_state</td> <td> </td> <td>['boolean', 'null']</td> <td>Save VM state support</td> </tr>
<tr><td>status</td> <td>&#10004;</td> <td>enum</td> <td>Possible values: started, stopped, suspended</td> </tr>
<tr><td>tpm</td> <td>&#10004;</td> <td>boolean</td> <td>Enable the Trusted Platform Module (TPM) in Qemu</td> </tr>
<tr><td>uefi</td> <td>&#10004;</td> <td>boolean</td> <td>Enable the UEFI boot mode in Qemu</td> </tr>
<tr><td>usage</td> <td>&#10004;</td> <td>string</td> <td>How to use the QEMU VM</td> </tr>
</table>
@@ -47,6 +47,7 @@ Input
<tr><td>capturing</td> <td> </td> <td>boolean</td> <td>Read only property. True if a capture running on the link</td> </tr>
<tr><td>filters</td> <td> </td> <td>object</td> <td>Packet filter. This allow to simulate latency and errors</td> </tr>
<tr><td>link_id</td> <td> </td> <td>string</td> <td>Link UUID</td> </tr>
<tr><td>link_style</td> <td> </td> <td>object</td> <td>Link line style</td> </tr>
<tr><td>link_type</td> <td> </td> <td>enum</td> <td>Possible values: ethernet, serial</td> </tr>
<tr><td>nodes</td> <td> </td> <td>array</td> <td>List of the VMS</td> </tr>
<tr><td>project_id</td> <td> </td> <td>string</td> <td>Project UUID</td> </tr>
@@ -65,6 +66,7 @@ Output
<tr><td>capturing</td> <td> </td> <td>boolean</td> <td>Read only property. True if a capture running on the link</td> </tr>
<tr><td>filters</td> <td> </td> <td>object</td> <td>Packet filter. This allow to simulate latency and errors</td> </tr>
<tr><td>link_id</td> <td> </td> <td>string</td> <td>Link UUID</td> </tr>
<tr><td>link_style</td> <td> </td> <td>object</td> <td>Link line style</td> </tr>
<tr><td>link_type</td> <td> </td> <td>enum</td> <td>Possible values: ethernet, serial</td> </tr>
<tr><td>nodes</td> <td> </td> <td>array</td> <td>List of the VMS</td> </tr>
<tr><td>project_id</td> <td> </td> <td>string</td> <td>Project UUID</td> </tr>
@@ -30,6 +30,7 @@ Output
<tr><td>capturing</td> <td> </td> <td>boolean</td> <td>Read only property. True if a capture running on the link</td> </tr>
<tr><td>filters</td> <td> </td> <td>object</td> <td>Packet filter. This allow to simulate latency and errors</td> </tr>
<tr><td>link_id</td> <td> </td> <td>string</td> <td>Link UUID</td> </tr>
<tr><td>link_style</td> <td> </td> <td>object</td> <td>Link line style</td> </tr>
<tr><td>link_type</td> <td> </td> <td>enum</td> <td>Possible values: ethernet, serial</td> </tr>
<tr><td>nodes</td> <td> </td> <td>array</td> <td>List of the VMS</td> </tr>
<tr><td>project_id</td> <td> </td> <td>string</td> <td>Project UUID</td> </tr>
@@ -69,6 +70,7 @@ Input
<tr><td>capturing</td> <td> </td> <td>boolean</td> <td>Read only property. True if a capture running on the link</td> </tr>
<tr><td>filters</td> <td> </td> <td>object</td> <td>Packet filter. This allow to simulate latency and errors</td> </tr>
<tr><td>link_id</td> <td> </td> <td>string</td> <td>Link UUID</td> </tr>
<tr><td>link_style</td> <td> </td> <td>object</td> <td>Link line style</td> </tr>
<tr><td>link_type</td> <td> </td> <td>enum</td> <td>Possible values: ethernet, serial</td> </tr>
<tr><td>nodes</td> <td> </td> <td>array</td> <td>List of the VMS</td> </tr>
<tr><td>project_id</td> <td> </td> <td>string</td> <td>Project UUID</td> </tr>
@@ -87,6 +89,7 @@ Output
<tr><td>capturing</td> <td> </td> <td>boolean</td> <td>Read only property. True if a capture running on the link</td> </tr>
<tr><td>filters</td> <td> </td> <td>object</td> <td>Packet filter. This allow to simulate latency and errors</td> </tr>
<tr><td>link_id</td> <td> </td> <td>string</td> <td>Link UUID</td> </tr>
<tr><td>link_style</td> <td> </td> <td>object</td> <td>Link line style</td> </tr>
<tr><td>link_type</td> <td> </td> <td>enum</td> <td>Possible values: ethernet, serial</td> </tr>
<tr><td>nodes</td> <td> </td> <td>array</td> <td>List of the VMS</td> </tr>
<tr><td>project_id</td> <td> </td> <td>string</td> <td>Project UUID</td> </tr>
@@ -39,6 +39,7 @@ Output
<tr><td>capturing</td> <td> </td> <td>boolean</td> <td>Read only property. True if a capture running on the link</td> </tr>
<tr><td>filters</td> <td> </td> <td>object</td> <td>Packet filter. This allow to simulate latency and errors</td> </tr>
<tr><td>link_id</td> <td> </td> <td>string</td> <td>Link UUID</td> </tr>
<tr><td>link_style</td> <td> </td> <td>object</td> <td>Link line style</td> </tr>
<tr><td>link_type</td> <td> </td> <td>enum</td> <td>Possible values: ethernet, serial</td> </tr>
<tr><td>nodes</td> <td> </td> <td>array</td> <td>List of the VMS</td> </tr>
<tr><td>project_id</td> <td> </td> <td>string</td> <td>Project UUID</td> </tr>
@@ -19,6 +19,8 @@ Input
<table>
<tr> <th>Name</th> <th>Mandatory</th> <th>Type</th> <th>Description</th> </tr>
<tr><td>auto_close</td> <td> </td> <td>boolean</td> <td>Project auto close</td> </tr>
<tr><td>auto_open</td> <td> </td> <td>boolean</td> <td>Project open when GNS3 start</td> </tr>
<tr><td>auto_start</td> <td> </td> <td>boolean</td> <td>Project start when opened</td> </tr>
<tr><td>drawing_grid_size</td> <td> </td> <td>integer</td> <td>Grid size for the drawing area for drawings</td> </tr>
<tr><td>grid_size</td> <td> </td> <td>integer</td> <td>Grid size for the drawing area for nodes</td> </tr>
<tr><td>name</td> <td>&#10004;</td> <td>['string', 'null']</td> <td>Project name</td> </tr>
@@ -24,11 +24,14 @@ Input
<table>
<tr> <th>Name</th> <th>Mandatory</th> <th>Type</th> <th>Description</th> </tr>
<tr><td>auto_close</td> <td> </td> <td>boolean</td> <td>Project auto close</td> </tr>
<tr><td>auto_open</td> <td> </td> <td>boolean</td> <td>Project open when GNS3 start</td> </tr>
<tr><td>auto_start</td> <td> </td> <td>boolean</td> <td>Project start when opened</td> </tr>
<tr><td>drawing_grid_size</td> <td> </td> <td>integer</td> <td>Grid size for the drawing area for drawings</td> </tr>
<tr><td>grid_size</td> <td> </td> <td>integer</td> <td>Grid size for the drawing area for nodes</td> </tr>
<tr><td>name</td> <td>&#10004;</td> <td>['string', 'null']</td> <td>Project name</td> </tr>
<tr><td>path</td> <td> </td> <td>['string', 'null']</td> <td>Project directory</td> </tr>
<tr><td>project_id</td> <td> </td> <td>['string', 'null']</td> <td>Project UUID</td> </tr>
<tr><td>reset_mac_addresses</td> <td> </td> <td>boolean</td> <td>Reset MAC addresses for this project</td> </tr>
<tr><td>scene_height</td> <td> </td> <td>integer</td> <td>Height of the drawing area</td> </tr>
<tr><td>scene_width</td> <td> </td> <td>integer</td> <td>Width of the drawing area</td> </tr>
<tr><td>show_grid</td> <td> </td> <td>boolean</td> <td>Show the grid on the drawing area</td> </tr>
+32
View File
@@ -50,6 +50,38 @@ A compute has been deleted.
.. literalinclude:: api/notifications/compute.deleted.json
project.created
---------------
A project has been created.
.. literalinclude:: api/notifications/project.created.json
project.updated
---------------
A project has been updated.
.. literalinclude:: api/notifications/project.updated.json
project.closed
---------------
A project has been closed.
.. literalinclude:: api/notifications/project.closed.json
project.deleted
---------------
A project has been deleted.
.. literalinclude:: api/notifications/project.deleted.json
template.created
-----------------
+1 -1
View File
@@ -576,7 +576,7 @@ Read :doc:`project_notifications` for more information.
Where to find the endpoints?
###########################
############################
A list of all endpoints is available: :doc:`endpoints`
+23 -1
View File
@@ -103,7 +103,8 @@
"properties": {
"name": {
"type": "string",
"description": "Variable name"
"description": "Variable name",
"minLength": 1
},
"value": {
"type": "string",
@@ -387,6 +388,27 @@
"type": "boolean",
"description": "Suspend the link"
},
"link_style": {
"type": "object",
"description": "Link line style",
"items": {
"type": "object",
"properties": {
"color": {
"description": "Link line color",
"type": "string"
},
"width": {
"description": "Link line width",
"type": "integer"
},
"type": {
"description": "Link line type",
"type": "integer"
}
}
}
},
"filters": {
"$schema": "http://json-schema.org/draft-04/schema#",
"description": "Packet filter. This allow to simulate latency and errors",
+1 -17
View File
@@ -100,28 +100,12 @@ A drawing has been deleted.
.. literalinclude:: api/notifications/drawing.deleted.json
project.updated
---------------
A project has been updated.
.. literalinclude:: api/notifications/project.updated.json
project.closed
---------------
A project has been closed.
.. literalinclude:: api/notifications/project.closed.json
snapshot.restored
--------------------------
A snapshot has been restored
.. literalinclude:: api/notifications/project.snapshot_restored.json
.. literalinclude:: api/notifications/snapshot.restored.json
log.error
---------
+1 -1
View File
@@ -11,7 +11,7 @@
"status": "stable",
"maintainer": "GNS3 Team",
"maintainer_email": "developers@gns3.net",
"usage": "Configure interfaces in /opt/bootlocal.sh, BIRD configuration is done in /usr/local/etc/bird",
"usage": "\n*** BIRD v1 is end-of-life ***\nPlease use the BIRD2 appliance.\n\nConfigure interfaces in /opt/bootlocal.sh, BIRD configuration is done in /usr/local/etc/bird",
"qemu": {
"adapter_type": "e1000",
"adapters": 4,
+13
View File
@@ -26,6 +26,13 @@
"kvm": "require"
},
"images": [
{
"filename": "asav9-18-2.qcow2",
"version": "9.18.2 CML",
"md5sum": "6f10fe106edfad9163625770a47a6b73",
"filesize": 340262912,
"download_url": "https://learningnetworkstore.cisco.com/cisco-modeling-labs-personal/cisco-modeling-labs-personal/CML-PERSONAL.html"
},
{
"filename": "asav9-16-2.qcow2",
"version": "9.16.2 CML",
@@ -119,6 +126,12 @@
}
],
"versions": [
{
"name": "9.18.2 CML",
"images": {
"hda_disk_image": "asav9-18-2.qcow2"
}
},
{
"name": "9.16.2 CML",
"images": {
+13
View File
@@ -24,6 +24,13 @@
"kvm": "require"
},
"images": [
{
"filename": "c8000v-universalk9_8G_serial.17.09.01a.qcow2",
"version": "17.09.01a 8G",
"md5sum": "a10ae2c4d71f4eb611bc4d83ad7709f0",
"filesize": 1856634880,
"download_url": "https://software.cisco.com/download/home/286327102/type/282046477/release/Bengaluru-17.6.5"
},
{
"filename": "c8000v-universalk9_8G_serial.17.06.05.qcow2",
"version": "17.06.05 8G",
@@ -54,6 +61,12 @@
}
],
"versions": [
{
"name": "17.09.01a 8G",
"images": {
"hda_disk_image": "c8000v-universalk9_8G_serial.17.09.01a.qcow2"
}
},
{
"name": "17.06.05 8G",
"images": {
@@ -24,6 +24,13 @@
"kvm": "require"
},
"images": [
{
"filename": "csr1000v-universalk9.17.03.06-serial.qcow2",
"version": "17.03.06",
"md5sum": "086ab9bef6e66de847af0da3910c60e8",
"filesize": 1422000128,
"download_url": "https://software.cisco.com/download/home/284364978/type/282046477/release/Gibraltar-16.12.3"
},
{
"filename": "csr1000v-universalk9.16.12.03-serial.qcow2",
"version": "16.12.3",
@@ -159,6 +166,12 @@
}
],
"versions": [
{
"name": "17.03.06",
"images": {
"hda_disk_image": "csr1000v-universalk9.17.03.06-serial.qcow2"
}
},
{
"name": "16.12.3",
"images": {
@@ -26,6 +26,13 @@
"options": "-smp 4 -cpu host"
},
"images": [
{
"filename": "xrv9k-fullk9-x-7.7.1.qcow2",
"version": "7.7.1",
"md5sum": "682fff40d2ff373d8da3342906553b54",
"filesize": 1643905024,
"download_url": "https://software.cisco.com/download/home/286288939/type/280805694/release/7.1.1"
},
{
"filename": "xrv9k-fullk9-x-7.1.1.qcow2",
"version": "7.1.1",
@@ -105,6 +112,12 @@
}
],
"versions": [
{
"name": "7.7.1",
"images": {
"hda_disk_image": "xrv9k-fullk9-x-7.7.1.qcow2"
}
},
{
"name": "7.1.1",
"images": {
+14
View File
@@ -26,6 +26,13 @@
"kvm": "require"
},
"images": [
{
"filename": "nexus9300v64.10.3.1.F.qcow2",
"version": "9300v 10.3.1.F",
"md5sum": "a6ffd2501a5791c11cee319943b912da",
"filesize": 2097086464,
"download_url": "https://software.cisco.com/download/home/286312239/type/282088129/release/10.1(1)"
},
{
"filename": "nexus9500v64.10.1.1.qcow2",
"version": "9500v 10.1.1",
@@ -198,6 +205,13 @@
}
],
"versions": [
{
"name": "9300v 10.3.1.F",
"images": {
"bios_image": "OVMF-edk2-stable202305.fd",
"hda_disk_image": "nexus9300v64.10.3.1.F.qcow2"
}
},
{
"name": "9500v 10.1.1",
"images": {
+7 -7
View File
@@ -24,12 +24,12 @@
},
"images": [
{
"filename": "debian-12.2.qcow2",
"version": "12.2",
"md5sum": "adf7716ec4a4e4e9e5ccfc7a1d7bd103",
"filesize": 286654464,
"filename": "debian-12.4.qcow2",
"version": "12.4",
"md5sum": "adcf7fdc25e10b3d2d9e2ef91168bffd",
"filesize": 286179840,
"download_url": "https://sourceforge.net/projects/gns-3/files/Qemu%20Appliances/",
"direct_download_url": "https://downloads.sourceforge.net/project/gns-3/Qemu%20Appliances/debian-12.2.qcow2"
"direct_download_url": "https://downloads.sourceforge.net/project/gns-3/Qemu%20Appliances/debian-12.4.qcow2"
},
{
"filename": "debian-11.8.qcow2",
@@ -42,9 +42,9 @@
],
"versions": [
{
"name": "12.2",
"name": "12.4",
"images": {
"hda_disk_image": "debian-12.2.qcow2"
"hda_disk_image": "debian-12.4.qcow2"
}
},
{
+21 -4
View File
@@ -11,26 +11,36 @@
"status": "experimental",
"maintainer": "GNS3 Team",
"maintainer_email": "developers@gns3.net",
"usage": "Make sure the Boot priority of the configuration template is HDD or CD.\n\nAbort the BCM process and format the flash after first boot by entering these commands:\nen\nformat flash:\n\nSometimes the flash device is not available after boot.",
"usage": "Make sure the Boot priority of the configuration template is HDD or CD.\n\nFor FTOS 9.8, switch to vnc console, start the device, abort the BMP process and format the flash after first boot by entering these commands:\nen\nformat flash:\n\nSometimes the flash device is not available after boot.",
"first_port_name": "Management0/0",
"port_name_format": "fortyGigE0/{0}",
"qemu": {
"adapter_type": "e1000",
"adapters": 6,
"ram": 512,
"ram": 1024,
"hda_disk_interface": "ide",
"arch": "i386",
"console_type": "vnc",
"console_type": "telnet",
"boot_priority": "cd",
"kvm": "require"
},
"images": [
{
"filename": "FTOS-SI-9.13.0.0.iso",
"version": "9.13.0",
"md5sum": "8418049e451c76e7b85e36eca0a0a730",
"filesize": 131278848,
"download_url": "https://www.dell.com/support/kbdoc/en-us/000184062/ftos-for-s-series-os-emulator-current-release-evaluation-version",
"direct_download_url": "https://downloads.dell.com/translatedpdf/force10/os9/FTOS-SI-9.13.0.0.zip",
"compression": "zip"
},
{
"filename": "FTOS-SI-9.8.0.0.iso",
"version": "9.8.0",
"md5sum": "b9b50eda0a73407dc381792ff7975e24",
"filesize": 108115968,
"download_url": "https://www.force10networks.com/CSPortal20/Software/SSeriesDownloads.aspx",
"download_url": "https://www.dell.com/support/kbdoc/en-us/000184062/ftos-for-s-series-os-emulator-current-release-evaluation-version",
"direct_download_url": "https://downloads.dell.com/translatedpdf/force10/os9/FTOS-SI-9.8.0.0.zip",
"compression": "zip"
},
{
@@ -43,6 +53,13 @@
}
],
"versions": [
{
"name": "9.13.0",
"images": {
"hda_disk_image": "empty30G.qcow2",
"cdrom_image": "FTOS-SI-9.13.0.0.iso"
}
},
{
"name": "9.8.0",
"images": {
+15 -45
View File
@@ -26,6 +26,14 @@
"options": "-nographic"
},
"images": [
{
"filename": "Fedora-Cloud-Base-39-1.5.x86_64.qcow2",
"version": "39-1.5",
"md5sum": "800a10df2d369891ed65900bcacacd47",
"filesize": 544604160,
"download_url": "https://download.fedoraproject.org/pub/fedora/linux/releases/39/Cloud/x86_64/images",
"direct_download_url": "https://download.fedoraproject.org/pub/fedora/linux/releases/39/Cloud/x86_64/images/Fedora-Cloud-Base-39-1.5.x86_64.qcow2"
},
{
"filename": "Fedora-Cloud-Base-38-1.6.x86_64.qcow2",
"version": "38-1.6",
@@ -34,30 +42,6 @@
"download_url": "https://download.fedoraproject.org/pub/fedora/linux/releases/38/Cloud/x86_64/images",
"direct_download_url": "https://download.fedoraproject.org/pub/fedora/linux/releases/38/Cloud/x86_64/images/Fedora-Cloud-Base-38-1.6.x86_64.qcow2"
},
{
"filename": "Fedora-Cloud-Base-37-1.7.x86_64.qcow2",
"version": "37-1.7",
"md5sum": "36f7b464b6ab46ad97c001b539495e90",
"filesize": 492830720,
"download_url": "https://download.fedoraproject.org/pub/fedora/linux/releases/37/Cloud/x86_64/images",
"direct_download_url": "https://download.fedoraproject.org/pub/fedora/linux/releases/37/Cloud/x86_64/images/Fedora-Cloud-Base-37-1.7.x86_64.qcow2"
},
{
"filename": "Fedora-Cloud-Base-36-1.5.x86_64.qcow2",
"version": "36-1.5",
"md5sum": "7f7cdad25b77f232078bf454c39529d3",
"filesize": 448266240,
"download_url": "https://download.fedoraproject.org/pub/fedora/linux/releases/36/Cloud/x86_64/images",
"direct_download_url": "https://download.fedoraproject.org/pub/fedora/linux/releases/36/Cloud/x86_64/images/Fedora-Cloud-Base-36-1.5.x86_64.qcow2"
},
{
"filename": "Fedora-Cloud-Base-35-1.2.x86_64.qcow2",
"version": "35-1.2",
"md5sum": "cfa9cdcfb946e5f4cf9dd4d7906008d0",
"filesize": 376897536,
"download_url": "https://download.fedoraproject.org/pub/fedora/linux/releases/35/Cloud/x86_64/images",
"direct_download_url": "https://download.fedoraproject.org/pub/fedora/linux/releases/35/Cloud/x86_64/images/Fedora-Cloud-Base-35-1.2.x86_64.qcow2"
},
{
"filename": "fedora-cloud-init-data.iso",
"version": "1.0",
@@ -68,33 +52,19 @@
}
],
"versions": [
{
"name": "39-1.5",
"images": {
"hda_disk_image": "Fedora-Cloud-Base-39-1.5.x86_64.qcow2",
"cdrom_image": "fedora-cloud-init-data.iso"
}
},
{
"name": "38-1.6",
"images": {
"hda_disk_image": "Fedora-Cloud-Base-38-1.6.x86_64.qcow2",
"cdrom_image": "fedora-cloud-init-data.iso"
}
},
{
"name": "37-1.7",
"images": {
"hda_disk_image": "Fedora-Cloud-Base-37-1.7.x86_64.qcow2",
"cdrom_image": "fedora-cloud-init-data.iso"
}
},
{
"name": "36-1.5",
"images": {
"hda_disk_image": "Fedora-Cloud-Base-36-1.5.x86_64.qcow2",
"cdrom_image": "fedora-cloud-init-data.iso"
}
},
{
"name": "35-1.2",
"images": {
"hda_disk_image": "Fedora-Cloud-Base-35-1.2.x86_64.qcow2",
"cdrom_image": "fedora-cloud-init-data.iso"
}
}
]
}
+14
View File
@@ -63,6 +63,13 @@
"filesize": 86704128,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FGT_VM64_KVM-v7.0.13.M-build0566-FORTINET.out.kvm.qcow2",
"version": "7.0.13",
"md5sum": "47a4bab29407153a635c54b64d6a226e",
"filesize": 89325568,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FGT_VM64_KVM-v7.0.12.M-build0523-FORTINET.out.kvm.qcow2",
"version": "7.0.12",
@@ -367,6 +374,13 @@
"hdb_disk_image": "empty30G.qcow2"
}
},
{
"name": "7.0.13",
"images": {
"hda_disk_image": "FGT_VM64_KVM-v7.0.13.M-build0566-FORTINET.out.kvm.qcow2",
"hdb_disk_image": "empty30G.qcow2"
}
},
{
"name": "7.0.12",
"images": {
+51 -2
View File
@@ -7,16 +7,65 @@
"vendor_url": "https://www.huawei.com",
"product_name": "HuaWei NE40E",
"product_url": "https://e.huawei.com/en/products/enterprise-networking/routers/ne/ne40e",
"registry_version": 4,
"registry_version": 6,
"status": "experimental",
"availability": "service-contract",
"maintainer": "none",
"maintainer_email": "",
"first_port_name": "eth0",
"port_name_format": "Ethernet1/0/{0}",
"qemu": {
"adapter_type": "e1000",
"adapters": 12,
"custom_adapters": [
{
"adapter_number": 0,
"port_name": "Gi0/0/0"
},
{
"adapter_number": 1,
"port_name": "Mgmt0/0"
},
{
"adapter_number": 2,
"port_name": "Ethernet1/0/0"
},
{
"adapter_number": 3,
"port_name": "Ethernet1/0/1"
},
{
"adapter_number": 4,
"port_name": "Ethernet1/0/2"
},
{
"adapter_number": 5,
"port_name": "Ethernet1/0/3"
},
{
"adapter_number": 6,
"port_name": "Ethernet1/0/4"
},
{
"adapter_number": 7,
"port_name": "Ethernet1/0/5"
},
{
"adapter_number": 8,
"port_name": "Ethernet1/0/6"
},
{
"adapter_number": 9,
"port_name": "Ethernet1/0/7"
},
{
"adapter_number": 10,
"port_name": "Ethernet1/0/8"
},
{
"adapter_number": 11,
"port_name": "Ethernet1/0/9"
}
],
"ram": 2048,
"cpus": 2,
"hda_disk_interface": "ide",
+13
View File
@@ -30,6 +30,13 @@
"options": "-vga std -usbdevice tablet"
},
"images": [
{
"version": "1.3.0",
"filename": "ostinatostd-1.3.0-1.qcow2",
"filesize": 173735936,
"md5sum": "ff25fed989c43aeac84bf0d542ad43ba",
"download_url": "https://ostinato.org/pricing/gns3"
},
{
"filename": "ostinatostd-1.2.0-1.qcow2",
"version": "1.2.0",
@@ -46,6 +53,12 @@
}
],
"versions": [
{
"name": "1.3.0",
"images": {
"hda_disk_image": "ostinatostd-1.3.0-1.qcow2"
}
},
{
"name": "1.2.0",
"images": {
+17 -3
View File
@@ -11,9 +11,9 @@
"registry_version": 4,
"status": "stable",
"availability": "service-contract",
"maintainer": "Neyder Achahuanco",
"maintainer_email": "neyder@neyder.net",
"usage": "You should download Red Hat Enterprise Linux KVM Guest Image from https://access.redhat.com/downloads/content/479/ver=/rhel---9/9.2/x86_64/product-software attach/customize cloud-init.iso and start.\nusername: cloud-user\npassword: redhat",
"maintainer": "Da-Geek",
"maintainer_email": "dageek@dageeks-geeks.gg",
"usage": "You should download Red Hat Enterprise Linux KVM Guest Image from https://access.redhat.com/downloads/content/479/ver=/rhel---9/9.3/x86_64/product-software attach/customize rhel-cloud-init.iso and start.\nusername: cloud-user\npassword: redhat",
"qemu": {
"adapter_type": "virtio-net-pci",
"adapters": 1,
@@ -26,6 +26,13 @@
"options": "-cpu host -nographic"
},
"images": [
{
"filename": "rhel-9.3-x86_64-kvm.qcow2",
"version": "9.3",
"md5sum": "409d8d15f5177db2617b0e3e02139b5c",
"filesize": 858193920,
"download_url": "https://access.redhat.com/downloads/content/479/ver=/rhel---9/9.3/x86_64/product-software"
},
{
"filename": "rhel-9.2-x86_64-kvm.qcow2",
"version": "9.2",
@@ -112,6 +119,13 @@
}
],
"versions": [
{
"name": "9.3",
"images": {
"hda_disk_image": "rhel-9.3-x86_64-kvm.qcow2",
"cdrom_image": "rhel-cloud-init.iso"
}
},
{
"name": "9.2",
"images": {
+30
View File
@@ -26,6 +26,14 @@
"options": "-nographic -cpu host"
},
"images": [
{
"filename": "Rocky-9-GenericCloud-Base-9.3-20231113.0.x86_64.qcow2",
"version": "9.3",
"md5sum": "48cdeb033364af5909e15ee48d0e144d",
"filesize": 1083965440,
"download_url": "https://download.rockylinux.org/pub/rocky/9/images/x86_64/",
"direct_download_url": "https://download.rockylinux.org/pub/rocky/9/images/x86_64/Rocky-9-GenericCloud-Base-9.3-20231113.0.x86_64.qcow2"
},
{
"filename": "Rocky-9-GenericCloud-Base-9.2-20230513.0.x86_64.qcow2",
"version": "9.2",
@@ -34,6 +42,14 @@
"download_url": "https://download.rockylinux.org/pub/rocky/9/images/x86_64/",
"direct_download_url": "https://download.rockylinux.org/pub/rocky/9/images/x86_64/Rocky-9-GenericCloud-Base-9.2-20230513.0.x86_64.qcow2"
},
{
"filename": "Rocky-8-GenericCloud-Base-8.9-20231119.0.x86_64.qcow2",
"version": "8.9",
"md5sum": "50c44d8d9c4df43694372c13768f114c",
"filesize": 1971978240,
"download_url": "https://download.rockylinux.org/pub/rocky/8/images/x86_64/",
"direct_download_url": "https://download.rockylinux.org/pub/rocky/8/images/x86_64/Rocky-8-GenericCloud-Base-8.9-20231119.0.x86_64.qcow2"
},
{
"filename": "Rocky-8-GenericCloud-Base-8.8-20230518.0.x86_64.qcow2",
"version": "8.8",
@@ -52,6 +68,13 @@
}
],
"versions": [
{
"name": "9.3",
"images": {
"hda_disk_image": "Rocky-9-GenericCloud-Base-9.3-20231113.0.x86_64.qcow2",
"cdrom_image": "rocky-cloud-init-data.iso"
}
},
{
"name": "9.2",
"images": {
@@ -59,6 +82,13 @@
"cdrom_image": "rocky-cloud-init-data.iso"
}
},
{
"name": "8.9",
"images": {
"hda_disk_image": "Rocky-8-GenericCloud-Base-8.9-20231119.0.x86_64.qcow2",
"cdrom_image": "rocky-cloud-init-data.iso"
}
},
{
"name": "8.8",
"images": {
+5 -5
View File
@@ -28,12 +28,12 @@
},
"images": [
{
"filename": "ubuntu-23.04-server-cloudimg-arm64.img",
"filename": "ubuntu-23.04-server-cloudimg-amd64.img",
"version": "Ubuntu 23.04 (Lunar Lobster)",
"md5sum": "35fa3b31b65717af6f0520a769aac8c0",
"filesize": 786432000,
"md5sum": "369e3b1f68416c39245a8014172406dd",
"filesize": 756678656,
"download_url": "https://cloud-images.ubuntu.com/releases/23.04/release/",
"direct_download_url": "https://cloud-images.ubuntu.com/releases/23.04/release/ubuntu-23.04-server-cloudimg-arm64.img"
"direct_download_url": "https://cloud-images.ubuntu.com/releases/23.04/release/ubuntu-23.04-server-cloudimg-amd64.img"
},
{
"filename": "ubuntu-22.04-server-cloudimg-amd64.img",
@@ -72,7 +72,7 @@
{
"name": "Ubuntu 23.04 (Lunar Lobster)",
"images": {
"hda_disk_image": "ubuntu-23.04-server-cloudimg-arm64.img",
"hda_disk_image": "ubuntu-23.04-server-cloudimg-amd64.img",
"cdrom_image": "ubuntu-cloud-init-data.iso"
}
},
+3
View File
@@ -656,6 +656,9 @@ class BaseNode:
"""
path = self._manager.config.get_section_config("Server").get("ubridge_path", "ubridge")
if sys.platform.startswith("win") and hasattr(sys, "frozen"):
ubridge_dir = os.path.normpath(os.path.join(os.path.dirname(os.path.abspath(sys.executable)), "ubridge"))
os.environ["PATH"] = os.pathsep.join(ubridge_dir) + os.pathsep + os.environ.get("PATH", "")
path = shutil.which(path)
return path
+3
View File
@@ -252,6 +252,9 @@ class Dynamips(BaseManager):
# look for Dynamips
dynamips_path = self.config.get_section_config("Dynamips").get("dynamips_path", "dynamips")
if not os.path.isabs(dynamips_path):
if sys.platform.startswith("win") and hasattr(sys, "frozen"):
dynamips_dir = os.path.normpath(os.path.join(os.path.dirname(os.path.abspath(sys.executable)), "dynamips"))
os.environ["PATH"] = os.pathsep.join(dynamips_dir) + os.pathsep + os.environ.get("PATH", "")
dynamips_path = shutil.which(dynamips_path)
if not dynamips_path:
+10 -7
View File
@@ -16,12 +16,14 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import aiohttp
import asyncio
import psutil
import platform
from .project import Project
from ..config import Config
from uuid import UUID
import logging
log = logging.getLogger(__name__)
@@ -128,10 +130,11 @@ class ProjectManager:
:returns: boolean
"""
for project in self._projects.values():
for node in project.nodes:
if node == source_node:
continue
if node.hw_virtualization and node.__class__.__name__ != source_node.__class__.__name__:
return False
if Config.instance().get_section_config("Server").getboolean("hardware_virtualization_check", True):
for project in self._projects.values():
for node in project.nodes:
if node == source_node:
continue
if node.hw_virtualization and node.__class__.__name__ != source_node.__class__.__name__:
return False
return True
+13 -3
View File
@@ -26,6 +26,7 @@ import sys
import re
import subprocess
from ...utils import shlex_quote
from ...utils.asyncio import subprocess_check_output
from ...utils.get_resource import get_resource
from ..base_manager import BaseManager
@@ -159,13 +160,20 @@ class Qemu(BaseManager):
for arch in archs:
if f.endswith(arch) or f.endswith("{}.exe".format(arch)) or f.endswith("{}w.exe".format(arch)):
qemu_path = os.path.join(path, f)
version = await Qemu.get_qemu_version(qemu_path)
try:
version = await Qemu.get_qemu_version(qemu_path)
except QemuError as e:
log.warning(str(e))
continue
qemus.append({"path": qemu_path, "version": version})
else:
qemu_path = os.path.join(path, f)
version = await Qemu.get_qemu_version(qemu_path)
try:
version = await Qemu.get_qemu_version(qemu_path)
except QemuError as e:
log.warning(str(e))
continue
qemus.append({"path": qemu_path, "version": version})
except OSError:
continue
@@ -337,6 +345,8 @@ class Qemu(BaseManager):
command.append(path)
command.append("{}M".format(img_size))
command_string = " ".join(shlex_quote(s) for s in command)
log.info("Creating disk image with {}".format(command_string))
process = await asyncio.create_subprocess_exec(*command)
await process.wait()
except (OSError, subprocess.SubprocessError) as e:
+3
View File
@@ -2426,6 +2426,9 @@ class QemuVM(BaseNode):
command.extend(shlex.split(additional_options))
except ValueError as e:
raise QemuError("Invalid additional options: {} error {}".format(additional_options, e))
# avoiding mouse offset (see https://github.com/GNS3/gns3-server/issues/2335)
if self._console_type == "vnc":
command.extend(['-machine', 'usb=on', '-device', 'usb-tablet'])
return command
def __json__(self):
+3
View File
@@ -140,6 +140,9 @@ class VPCSVM(BaseNode):
vpcs_path = self._manager.config.get_section_config("VPCS").get("vpcs_path", "vpcs")
if not os.path.isabs(vpcs_path):
if sys.platform.startswith("win") and hasattr(sys, "frozen"):
vpcs_dir = os.path.normpath(os.path.join(os.path.dirname(os.path.abspath(sys.executable)), "vpcs"))
os.environ["PATH"] = os.pathsep.join(vpcs_dir) + os.pathsep + os.environ.get("PATH", "")
vpcs_path = shutil.which(vpcs_path)
return vpcs_path
+19 -5
View File
@@ -130,16 +130,27 @@ class Project:
self._iou_id_lock = asyncio.Lock()
log.debug('Project "{name}" [{id}] loaded'.format(name=self.name, id=self._id))
self.emit_controller_notification("project.created", self.__json__())
def emit_notification(self, action, event):
"""
Emit a notification to all clients using this project.
Emit a project notification to all clients using this project.
:param action: Action name
:param event: Event to send
"""
self.controller.notification.project_emit(action, event, project_id=self.id)
self._controller.notification.project_emit(action, event, project_id=self.id)
def emit_controller_notification(self, action, event):
"""
Emit a controller notification, all clients will see it.
:param action: Action name
:param event: Event to send
"""
self._controller.notification.controller_emit(action, event)
async def update(self, **kwargs):
"""
@@ -154,7 +165,7 @@ class Project:
# We send notif only if object has changed
if old_json != self.__json__():
self.emit_notification("project.updated", self.__json__())
self.emit_controller_notification("project.updated", self.__json__())
self.dump()
# update on computes
@@ -803,7 +814,8 @@ class Project:
self._clean_pictures()
self._status = "closed"
if not ignore_notification:
self.emit_notification("project.closed", self.__json__())
self.emit_controller_notification("project.closed", self.__json__())
self.reset()
self._closing = False
@@ -857,6 +869,7 @@ class Project:
shutil.rmtree(self.path)
except OSError as e:
raise aiohttp.web.HTTPConflict(text="Cannot delete project directory {}: {}".format(self.path, str(e)))
self.emit_controller_notification("project.deleted", self.__json__())
async def delete_on_computes(self):
"""
@@ -976,7 +989,7 @@ class Project:
await self.add_drawing(dump=False, **drawing_data)
self.dump()
# We catch all error to be able to rollback the .gns3 to the previous state
# We catch all error to be able to roll back the .gns3 to the previous state
except Exception as e:
for compute in list(self._project_created_on_compute):
try:
@@ -1001,6 +1014,7 @@ class Project:
pass
self._loading = False
self.emit_controller_notification("project.opened", self.__json__())
# Should we start the nodes when project is open
if self._auto_start:
# Start all in the background without waiting for completion
+1 -1
View File
@@ -57,7 +57,7 @@ class CrashReport:
Report crash to a third party service
"""
DSN = "https://8dcaf668c2f31af6028fb4130bf2f58e@o19455.ingest.sentry.io/38482"
DSN = "https://ffea69bec1b4f934d815234ea0046382@o19455.ingest.sentry.io/38482"
_instance = None
def __init__(self):
@@ -487,11 +487,18 @@ class NodeHandler:
except ValueError:
pass
ws_console_compute_url = "ws://{compute_host}:{compute_port}/v2/compute/projects/{project_id}/{node_type}/nodes/{node_id}/console/ws".format(compute_host=compute_host,
compute_port=compute.port,
project_id=project.id,
node_type=node.node_type,
node_id=node.id)
ws_protocol = "ws"
if request.scheme == "https":
ws_protocol = "wss"
ws_console_compute_url = "{protocol}://{compute_host}:{compute_port}/v2/compute/projects/{project_id}/{node_type}/nodes/{node_id}/console/ws".format(
protocol=ws_protocol,
compute_host=compute_host,
compute_port=compute.port,
project_id=project.id,
node_type=node.node_type,
node_id=node.id
)
async def ws_forward(ws_client):
async for msg in ws:
@@ -504,7 +511,7 @@ class NodeHandler:
try:
async with aiohttp.ClientSession(connector=aiohttp.TCPConnector(limit=None, force_close=True)) as session:
async with session.ws_connect(ws_console_compute_url) as ws_client:
async with session.ws_connect(ws_console_compute_url, ssl=False) as ws_client:
asyncio.ensure_future(ws_forward(ws_client))
async for msg in ws_client:
if msg.type == aiohttp.WSMsgType.TEXT:
@@ -515,6 +522,8 @@ class NodeHandler:
break
except ConnectionResetError:
log.info("Websocket console connection with compute disconnected")
except aiohttp.ClientError as e:
log.error("Websocket console connection with compute failed: {}".format(e))
finally:
if not ws.closed:
await ws.close()
+4
View File
@@ -31,6 +31,7 @@ import gns3server.utils.get_resource
import os
import sys
import types
import multiprocessing
# To avoid strange bug later we switch the event loop before any other operation
if sys.platform.startswith("win"):
@@ -79,6 +80,9 @@ def main():
if not sys.platform.startswith("win"):
if "--daemon" in sys.argv:
daemonize()
else:
multiprocessing.freeze_support()
from gns3server.run import run
run()
+26 -46
View File
@@ -17,28 +17,30 @@
import copy
ETHERNET_HUB_PORT_SCHEMA = {
"description": "Ethernet port",
"properties": {
"name": {
"description": "Port name",
"type": "string",
"minLength": 1,
},
"port_number": {
"description": "Port number",
"type": "integer",
"minimum": 0
},
},
"required": ["name", "port_number"],
"additionalProperties": False
}
ETHERNET_HUB_CREATE_SCHEMA = {
"$schema": "http://json-schema.org/draft-04/schema#",
"description": "Request validation to create a new Ethernet hub instance",
"type": "object",
"definitions": {
"EthernetHubPort": {
"description": "Ethernet port",
"properties": {
"name": {
"description": "Port name",
"type": "string",
"minLength": 1,
},
"port_number": {
"description": "Port number",
"type": "integer",
"minimum": 0
},
},
"required": ["name", "port_number"],
"additionalProperties": False
},
"EthernetHubPort": ETHERNET_HUB_PORT_SCHEMA
},
"properties": {
"name": {
@@ -57,12 +59,9 @@ ETHERNET_HUB_CREATE_SCHEMA = {
},
"ports_mapping": {
"type": "array",
"items": [
{"type": "object",
"oneOf": [
{"$ref": "#/definitions/EthernetHubPort"}
]},
]
"items": {
"$ref": "#/definitions/EthernetHubPort"
}
},
},
"additionalProperties": False,
@@ -74,23 +73,7 @@ ETHERNET_HUB_OBJECT_SCHEMA = {
"description": "Ethernet hub instance",
"type": "object",
"definitions": {
"EthernetHubPort": {
"description": "Ethernet port",
"properties": {
"name": {
"description": "Port name",
"type": "string",
"minLength": 1,
},
"port_number": {
"description": "Port number",
"type": "integer",
"minimum": 0
},
},
"required": ["name", "port_number"],
"additionalProperties": False
},
"EthernetHubPort": ETHERNET_HUB_PORT_SCHEMA
},
"properties": {
"name": {
@@ -114,12 +97,9 @@ ETHERNET_HUB_OBJECT_SCHEMA = {
},
"ports_mapping": {
"type": "array",
"items": [
{"type": "object",
"oneOf": [
{"$ref": "#/definitions/EthernetHubPort"}
]},
]
"items": {
"$ref": "#/definitions/EthernetHubPort"
}
},
"status": {
"description": "Node status",
+38 -70
View File
@@ -17,40 +17,42 @@
import copy
ETHERNET_SWITCH_PORT_SCHEMA = {
"description": "Ethernet switch port",
"properties": {
"name": {
"description": "Port name",
"type": "string",
"minLength": 1,
},
"port_number": {
"description": "Port number",
"type": "integer",
"minimum": 0
},
"type": {
"description": "Port type",
"enum": ["access", "dot1q", "qinq"],
},
"vlan": {"description": "VLAN number",
"type": "integer",
"minimum": 1
},
"ethertype": {
"description": "QinQ Ethertype",
"enum": ["", "0x8100", "0x88A8", "0x9100", "0x9200"],
},
},
"required": ["name", "port_number", "type"],
"additionalProperties": False
}
ETHERNET_SWITCH_CREATE_SCHEMA = {
"$schema": "http://json-schema.org/draft-04/schema#",
"description": "Request validation to create a new Ethernet switch instance",
"type": "object",
"definitions": {
"EthernetSwitchPort": {
"description": "Ethernet port",
"properties": {
"name": {
"description": "Port name",
"type": "string",
"minLength": 1,
},
"port_number": {
"description": "Port number",
"type": "integer",
"minimum": 0
},
"type": {
"description": "Port type",
"enum": ["access", "dot1q", "qinq"],
},
"vlan": {"description": "VLAN number",
"type": "integer",
"minimum": 1
},
"ethertype": {
"description": "QinQ Ethertype",
"enum": ["", "0x8100", "0x88A8", "0x9100", "0x9200"],
},
},
"required": ["name", "port_number", "type"],
"additionalProperties": False
},
"EthernetSwitchPort": ETHERNET_SWITCH_PORT_SCHEMA
},
"properties": {
"name": {
@@ -79,12 +81,9 @@ ETHERNET_SWITCH_CREATE_SCHEMA = {
},
"ports_mapping": {
"type": "array",
"items": [
{"type": "object",
"oneOf": [
{"$ref": "#/definitions/EthernetSwitchPort"}
]},
]
"items": {
"$ref": "#/definitions/EthernetSwitchPort"
}
},
},
"additionalProperties": False,
@@ -96,35 +95,7 @@ ETHERNET_SWITCH_OBJECT_SCHEMA = {
"description": "Ethernet switch instance",
"type": "object",
"definitions": {
"EthernetSwitchPort": {
"description": "Ethernet port",
"properties": {
"name": {
"description": "Port name",
"type": "string",
"minLength": 1,
},
"port_number": {
"description": "Port number",
"type": "integer",
"minimum": 0
},
"type": {
"description": "Port type",
"enum": ["access", "dot1q", "qinq"],
},
"vlan": {"description": "VLAN number",
"type": "integer",
"minimum": 1
},
"ethertype": {
"description": "QinQ Ethertype",
"enum": ["", "0x8100", "0x88A8", "0x9100", "0x9200"],
},
},
"required": ["name", "port_number", "type"],
"additionalProperties": False
},
"EthernetSwitchPort": ETHERNET_SWITCH_PORT_SCHEMA
},
"properties": {
"name": {
@@ -148,12 +119,9 @@ ETHERNET_SWITCH_OBJECT_SCHEMA = {
},
"ports_mapping": {
"type": "array",
"items": [
{"type": "object",
"oneOf": [
{"$ref": "#/definitions/EthernetSwitchPort"}
]},
]
"items": {
"$ref": "#/definitions/EthernetSwitchPort"
}
},
"status": {
"description": "Node status",
@@ -1542,6 +1542,29 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
ipaddr.js
MIT
Copyright (C) 2011-2017 whitequark <whitequark@whitequark.org>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
mdn-data
CC0-1.0
CC0 1.0 Universal
+1 -1
View File
@@ -46,6 +46,6 @@
gtag('config', 'G-5D6FZL9923');
</script>
<script src="runtime.baa1121a4737aeb68bb7.js" defer></script><script src="polyfills-es5.865074f5cd9a121111a2.js" nomodule defer></script><script src="polyfills.2f91a039d848e57ff02e.js" defer></script><script src="main.6b11a28a9dc4ce54a2ab.js" defer></script>
<script src="runtime.ecefb4ce510d1c218e7d.js" defer></script><script src="polyfills-es5.865074f5cd9a121111a2.js" nomodule defer></script><script src="polyfills.2f91a039d848e57ff02e.js" defer></script><script src="main.054d2e56a89c0b6f1b49.js" defer></script>
</body></html>
@@ -0,0 +1 @@
(self.webpackChunkgns3_web_ui=self.webpackChunkgns3_web_ui||[]).push([[179],{98255:function(ue){function q(f){return Promise.resolve().then(function(){var B=new Error("Cannot find module '"+f+"'");throw B.code="MODULE_NOT_FOUND",B})}q.keys=function(){return[]},q.resolve=q,q.id=98255,ue.exports=q},82908:function(ue){ue.exports=function(f,B){(null==B||B>f.length)&&(B=f.length);for(var U=0,V=new Array(B);U<B;U++)V[U]=f[U];return V},ue.exports.default=ue.exports,ue.exports.__esModule=!0},36457:function(ue){ue.exports=function(f){if(Array.isArray(f))return f},ue.exports.default=ue.exports,ue.exports.__esModule=!0},35036:function(ue){ue.exports=function(f,B){var U=null==f?null:"undefined"!=typeof Symbol&&f[Symbol.iterator]||f["@@iterator"];if(null!=U){var N,b,V=[],Z=!0,w=!1;try{for(U=U.call(f);!(Z=(N=U.next()).done)&&(V.push(N.value),!B||V.length!==B);Z=!0);}catch(_){w=!0,b=_}finally{try{!Z&&null!=U.return&&U.return()}finally{if(w)throw b}}return V}},ue.exports.default=ue.exports,ue.exports.__esModule=!0},13969:function(ue){ue.exports=function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")},ue.exports.default=ue.exports,ue.exports.__esModule=!0},6326:function(ue,q,f){var B=f(36457),U=f(35036),V=f(54850),Z=f(13969);ue.exports=function(N,b){return B(N)||U(N,b)||V(N,b)||Z()},ue.exports.default=ue.exports,ue.exports.__esModule=!0},54850:function(ue,q,f){var B=f(82908);ue.exports=function(V,Z){if(V){if("string"==typeof V)return B(V,Z);var w=Object.prototype.toString.call(V).slice(8,-1);if("Object"===w&&V.constructor&&(w=V.constructor.name),"Map"===w||"Set"===w)return Array.from(V);if("Arguments"===w||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(w))return B(V,Z)}},ue.exports.default=ue.exports,ue.exports.__esModule=!0},26552:function(ue,q,f){ue.exports=f(55590)},61855:function(ue,q,f){"use strict";f.d(q,{ZT:function(){return U},mG:function(){return _},Jh:function(){return I},ev:function(){return R}});var B=function($,ae){return(B=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(se,ce){se.__proto__=ce}||function(se,ce){for(var le in ce)Object.prototype.hasOwnProperty.call(ce,le)&&(se[le]=ce[le])})($,ae)};function U($,ae){if("function"!=typeof ae&&null!==ae)throw new TypeError("Class extends value "+String(ae)+" is not a constructor or null");function se(){this.constructor=$}B($,ae),$.prototype=null===ae?Object.create(ae):(se.prototype=ae.prototype,new se)}function _($,ae,se,ce){return new(se||(se=Promise))(function(oe,Ae){function be(_t){try{qe(ce.next(_t))}catch(yt){Ae(yt)}}function it(_t){try{qe(ce.throw(_t))}catch(yt){Ae(yt)}}function qe(_t){_t.done?oe(_t.value):function(oe){return oe instanceof se?oe:new se(function(Ae){Ae(oe)})}(_t.value).then(be,it)}qe((ce=ce.apply($,ae||[])).next())})}function I($,ae){var ce,le,oe,Ae,se={label:0,sent:function(){if(1&oe[0])throw oe[1];return oe[1]},trys:[],ops:[]};return Ae={next:be(0),throw:be(1),return:be(2)},"function"==typeof Symbol&&(Ae[Symbol.iterator]=function(){return this}),Ae;function be(qe){return function(_t){return function(qe){if(ce)throw new TypeError("Generator is already executing.");for(;se;)try{if(ce=1,le&&(oe=2&qe[0]?le.return:qe[0]?le.throw||((oe=le.return)&&oe.call(le),0):le.next)&&!(oe=oe.call(le,qe[1])).done)return oe;switch(le=0,oe&&(qe=[2&qe[0],oe.value]),qe[0]){case 0:case 1:oe=qe;break;case 4:return se.label++,{value:qe[1],done:!1};case 5:se.label++,le=qe[1],qe=[0];continue;case 7:qe=se.ops.pop(),se.trys.pop();continue;default:if(!(oe=(oe=se.trys).length>0&&oe[oe.length-1])&&(6===qe[0]||2===qe[0])){se=0;continue}if(3===qe[0]&&(!oe||qe[1]>oe[0]&&qe[1]<oe[3])){se.label=qe[1];break}if(6===qe[0]&&se.label<oe[1]){se.label=oe[1],oe=qe;break}if(oe&&se.label<oe[2]){se.label=oe[2],se.ops.push(qe);break}oe[2]&&se.ops.pop(),se.trys.pop();continue}qe=ae.call($,se)}catch(_t){qe=[6,_t],le=0}finally{ce=oe=0}if(5&qe[0])throw qe[1];return{value:qe[0]?qe[1]:void 0,done:!0}}([qe,_t])}}}function R($,ae,se){if(se||2===arguments.length)for(var oe,ce=0,le=ae.length;ce<le;ce++)(oe||!(ce in ae))&&(oe||(oe=Array.prototype.slice.call(ae,0,ce)),oe[ce]=ae[ce]);return $.concat(oe||Array.prototype.slice.call(ae))}},739:function(ue,q,f){"use strict";f.d(q,{l3:function(){return w},_j:function(){return V},LC:function(){return Z},ZN:function(){return O},jt:function(){return b},pV:function(){return T},F4:function(){return S},IO:function(){return k},vP:function(){return I},SB:function(){return A},oB:function(){return D},eR:function(){return v},X$:function(){return N},ZE:function(){return F},k1:function(){return z}});var B=f(14105),U=f(18967),V=function K(){(0,U.Z)(this,K)},Z=function K(){(0,U.Z)(this,K)},w="*";function N(K,j){return{type:7,name:K,definitions:j,options:{}}}function b(K){var j=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;return{type:4,styles:j,timings:K}}function I(K){var j=arguments.length>1&&void 0!==arguments[1]?arguments[1]Line truncated
@@ -1 +0,0 @@
(self.webpackChunkgns3_web_ui=self.webpackChunkgns3_web_ui||[]).push([[179],{98255:function(ue){function q(f){return Promise.resolve().then(function(){var U=new Error("Cannot find module '"+f+"'");throw U.code="MODULE_NOT_FOUND",U})}q.keys=function(){return[]},q.resolve=q,q.id=98255,ue.exports=q},82908:function(ue){ue.exports=function(f,U){(null==U||U>f.length)&&(U=f.length);for(var B=0,V=new Array(U);B<U;B++)V[B]=f[B];return V},ue.exports.default=ue.exports,ue.exports.__esModule=!0},36457:function(ue){ue.exports=function(f){if(Array.isArray(f))return f},ue.exports.default=ue.exports,ue.exports.__esModule=!0},35036:function(ue){ue.exports=function(f,U){var B=null==f?null:"undefined"!=typeof Symbol&&f[Symbol.iterator]||f["@@iterator"];if(null!=B){var R,b,V=[],Z=!0,T=!1;try{for(B=B.call(f);!(Z=(R=B.next()).done)&&(V.push(R.value),!U||V.length!==U);Z=!0);}catch(v){T=!0,b=v}finally{try{!Z&&null!=B.return&&B.return()}finally{if(T)throw b}}return V}},ue.exports.default=ue.exports,ue.exports.__esModule=!0},13969:function(ue){ue.exports=function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")},ue.exports.default=ue.exports,ue.exports.__esModule=!0},6326:function(ue,q,f){var U=f(36457),B=f(35036),V=f(54850),Z=f(13969);ue.exports=function(R,b){return U(R)||B(R,b)||V(R,b)||Z()},ue.exports.default=ue.exports,ue.exports.__esModule=!0},54850:function(ue,q,f){var U=f(82908);ue.exports=function(V,Z){if(V){if("string"==typeof V)return U(V,Z);var T=Object.prototype.toString.call(V).slice(8,-1);if("Object"===T&&V.constructor&&(T=V.constructor.name),"Map"===T||"Set"===T)return Array.from(V);if("Arguments"===T||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(T))return U(V,Z)}},ue.exports.default=ue.exports,ue.exports.__esModule=!0},26552:function(ue,q,f){ue.exports=f(55590)},61855:function(ue,q,f){"use strict";f.d(q,{ZT:function(){return B},mG:function(){return v},Jh:function(){return I},ev:function(){return N}});var U=function($,ae){return(U=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(se,ce){se.__proto__=ce}||function(se,ce){for(var le in ce)Object.prototype.hasOwnProperty.call(ce,le)&&(se[le]=ce[le])})($,ae)};function B($,ae){if("function"!=typeof ae&&null!==ae)throw new TypeError("Class extends value "+String(ae)+" is not a constructor or null");function se(){this.constructor=$}U($,ae),$.prototype=null===ae?Object.create(ae):(se.prototype=ae.prototype,new se)}function v($,ae,se,ce){return new(se||(se=Promise))(function(oe,Ae){function be(_t){try{qe(ce.next(_t))}catch(yt){Ae(yt)}}function it(_t){try{qe(ce.throw(_t))}catch(yt){Ae(yt)}}function qe(_t){_t.done?oe(_t.value):function(oe){return oe instanceof se?oe:new se(function(Ae){Ae(oe)})}(_t.value).then(be,it)}qe((ce=ce.apply($,ae||[])).next())})}function I($,ae){var ce,le,oe,Ae,se={label:0,sent:function(){if(1&oe[0])throw oe[1];return oe[1]},trys:[],ops:[]};return Ae={next:be(0),throw:be(1),return:be(2)},"function"==typeof Symbol&&(Ae[Symbol.iterator]=function(){return this}),Ae;function be(qe){return function(_t){return function(qe){if(ce)throw new TypeError("Generator is already executing.");for(;se;)try{if(ce=1,le&&(oe=2&qe[0]?le.return:qe[0]?le.throw||((oe=le.return)&&oe.call(le),0):le.next)&&!(oe=oe.call(le,qe[1])).done)return oe;switch(le=0,oe&&(qe=[2&qe[0],oe.value]),qe[0]){case 0:case 1:oe=qe;break;case 4:return se.label++,{value:qe[1],done:!1};case 5:se.label++,le=qe[1],qe=[0];continue;case 7:qe=se.ops.pop(),se.trys.pop();continue;default:if(!(oe=(oe=se.trys).length>0&&oe[oe.length-1])&&(6===qe[0]||2===qe[0])){se=0;continue}if(3===qe[0]&&(!oe||qe[1]>oe[0]&&qe[1]<oe[3])){se.label=qe[1];break}if(6===qe[0]&&se.label<oe[1]){se.label=oe[1],oe=qe;break}if(oe&&se.label<oe[2]){se.label=oe[2],se.ops.push(qe);break}oe[2]&&se.ops.pop(),se.trys.pop();continue}qe=ae.call($,se)}catch(_t){qe=[6,_t],le=0}finally{ce=oe=0}if(5&qe[0])throw qe[1];return{value:qe[0]?qe[1]:void 0,done:!0}}([qe,_t])}}}function N($,ae,se){if(se||2===arguments.length)for(var oe,ce=0,le=ae.length;ce<le;ce++)(oe||!(ce in ae))&&(oe||(oe=Array.prototype.slice.call(ae,0,ce)),oe[ce]=ae[ce]);return $.concat(oe||Array.prototype.slice.call(ae))}},739:function(ue,q,f){"use strict";f.d(q,{l3:function(){return T},_j:function(){return V},LC:function(){return Z},ZN:function(){return O},jt:function(){return b},pV:function(){return E},F4:function(){return M},IO:function(){return A},vP:function(){return I},SB:function(){return k},oB:function(){return D},eR:function(){return _},X$:function(){return R},ZE:function(){return F},k1:function(){return z}});var U=f(14105),B=f(18967),V=function K(){(0,B.Z)(this,K)},Z=function K(){(0,B.Z)(this,K)},T="*";function R(K,j){return{type:7,name:K,definitions:j,options:{}}}function b(K){var j=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;return{type:4,styles:j,timings:K}}function I(K){var j=arguments.length>1&&void 0!==arguments[1]?arguments[1]Line truncated
@@ -1 +0,0 @@
!function(){"use strict";var e,v={},g={};function n(e){var a=g[e];if(void 0!==a)return a.exports;var t=g[e]={id:e,loaded:!1,exports:{}};return v[e](t,t.exports,n),t.loaded=!0,t.exports}n.m=v,e=[],n.O=function(a,t,u,o){if(!t){var r=1/0;for(i=0;i<e.length;i++){t=e[i][0],u=e[i][1],o=e[i][2];for(var l=!0,f=0;f<t.length;f++)(!1&o||r>=o)&&Object.keys(n.O).every(function(b){return n.O[b](t[f])})?t.splice(f--,1):(l=!1,o<r&&(r=o));if(l){e.splice(i--,1);var s=u();void 0!==s&&(a=s)}}return a}o=o||0;for(var i=e.length;i>0&&e[i-1][2]>o;i--)e[i]=e[i-1];e[i]=[t,u,o]},n.n=function(e){var a=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(a,{a:a}),a},n.d=function(e,a){for(var t in a)n.o(a,t)&&!n.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:a[t]})},n.f={},n.e=function(e){return Promise.all(Object.keys(n.f).reduce(function(a,t){return n.f[t](e,a),a},[]))},n.u=function(e){return e+".49028ab13de5de406c90.js"},n.miniCssF=function(e){return"styles.f8555f2eecf8cf87f666.css"},n.hmd=function(e){return(e=Object.create(e)).children||(e.children=[]),Object.defineProperty(e,"exports",{enumerable:!0,set:function(){throw new Error("ES Modules may not assign module.exports or exports.*, Use ESM export syntax, instead: "+e.id)}}),e},n.o=function(e,a){return Object.prototype.hasOwnProperty.call(e,a)},function(){var e={},a="gns3-web-ui:";n.l=function(t,u,o,i){if(e[t])e[t].push(u);else{var r,l;if(void 0!==o)for(var f=document.getElementsByTagName("script"),s=0;s<f.length;s++){var c=f[s];if(c.getAttribute("src")==t||c.getAttribute("data-webpack")==a+o){r=c;break}}r||(l=!0,(r=document.createElement("script")).charset="utf-8",r.timeout=120,n.nc&&r.setAttribute("nonce",n.nc),r.setAttribute("data-webpack",a+o),r.src=n.tu(t)),e[t]=[u];var d=function(h,b){r.onerror=r.onload=null,clearTimeout(p);var _=e[t];if(delete e[t],r.parentNode&&r.parentNode.removeChild(r),_&&_.forEach(function(m){return m(b)}),h)return h(b)},p=setTimeout(d.bind(null,void 0,{type:"timeout",target:r}),12e4);r.onerror=d.bind(null,r.onerror),r.onload=d.bind(null,r.onload),l&&document.head.appendChild(r)}}}(),n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},function(){var e;n.tu=function(a){return void 0===e&&(e={createScriptURL:function(t){return t}},"undefined"!=typeof trustedTypes&&trustedTypes.createPolicy&&(e=trustedTypes.createPolicy("angular#bundler",e))),e.createScriptURL(a)}}(),n.p="",function(){var e={666:0};n.f.j=function(u,o){var i=n.o(e,u)?e[u]:void 0;if(0!==i)if(i)o.push(i[2]);else if(666!=u){var r=new Promise(function(c,d){i=e[u]=[c,d]});o.push(i[2]=r);var l=n.p+n.u(u),f=new Error;n.l(l,function(c){if(n.o(e,u)&&(0!==(i=e[u])&&(e[u]=void 0),i)){var d=c&&("load"===c.type?"missing":c.type),p=c&&c.target&&c.target.src;f.message="Loading chunk "+u+" failed.\n("+d+": "+p+")",f.name="ChunkLoadError",f.type=d,f.request=p,i[1](f)}},"chunk-"+u,u)}else e[u]=0},n.O.j=function(u){return 0===e[u]};var a=function(u,o){var f,s,i=o[0],r=o[1],l=o[2],c=0;for(f in r)n.o(r,f)&&(n.m[f]=r[f]);if(l)var d=l(n);for(u&&u(o);c<i.length;c++)n.o(e,s=i[c])&&e[s]&&e[s][0](),e[i[c]]=0;return n.O(d)},t=self.webpackChunkgns3_web_ui=self.webpackChunkgns3_web_ui||[];t.forEach(a.bind(null,0)),t.push=a.bind(null,t.push.bind(t))}()}();
@@ -0,0 +1 @@
!function(){"use strict";var e,v={},g={};function n(e){var a=g[e];if(void 0!==a)return a.exports;var t=g[e]={id:e,loaded:!1,exports:{}};return v[e].call(t.exports,t,t.exports,n),t.loaded=!0,t.exports}n.m=v,e=[],n.O=function(a,t,u,o){if(!t){var r=1/0;for(i=0;i<e.length;i++){t=e[i][0],u=e[i][1],o=e[i][2];for(var l=!0,f=0;f<t.length;f++)(!1&o||r>=o)&&Object.keys(n.O).every(function(b){return n.O[b](t[f])})?t.splice(f--,1):(l=!1,o<r&&(r=o));if(l){e.splice(i--,1);var s=u();void 0!==s&&(a=s)}}return a}o=o||0;for(var i=e.length;i>0&&e[i-1][2]>o;i--)e[i]=e[i-1];e[i]=[t,u,o]},n.n=function(e){var a=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(a,{a:a}),a},n.d=function(e,a){for(var t in a)n.o(a,t)&&!n.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:a[t]})},n.f={},n.e=function(e){return Promise.all(Object.keys(n.f).reduce(function(a,t){return n.f[t](e,a),a},[]))},n.u=function(e){return e+".49028ab13de5de406c90.js"},n.miniCssF=function(e){return"styles.f8555f2eecf8cf87f666.css"},n.hmd=function(e){return(e=Object.create(e)).children||(e.children=[]),Object.defineProperty(e,"exports",{enumerable:!0,set:function(){throw new Error("ES Modules may not assign module.exports or exports.*, Use ESM export syntax, instead: "+e.id)}}),e},n.o=function(e,a){return Object.prototype.hasOwnProperty.call(e,a)},function(){var e={},a="gns3-web-ui:";n.l=function(t,u,o,i){if(e[t])e[t].push(u);else{var r,l;if(void 0!==o)for(var f=document.getElementsByTagName("script"),s=0;s<f.length;s++){var c=f[s];if(c.getAttribute("src")==t||c.getAttribute("data-webpack")==a+o){r=c;break}}r||(l=!0,(r=document.createElement("script")).charset="utf-8",r.timeout=120,n.nc&&r.setAttribute("nonce",n.nc),r.setAttribute("data-webpack",a+o),r.src=n.tu(t)),e[t]=[u];var d=function(h,b){r.onerror=r.onload=null,clearTimeout(p);var _=e[t];if(delete e[t],r.parentNode&&r.parentNode.removeChild(r),_&&_.forEach(function(m){return m(b)}),h)return h(b)},p=setTimeout(d.bind(null,void 0,{type:"timeout",target:r}),12e4);r.onerror=d.bind(null,r.onerror),r.onload=d.bind(null,r.onload),l&&document.head.appendChild(r)}}}(),n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},function(){var e;n.tu=function(a){return void 0===e&&(e={createScriptURL:function(t){return t}},"undefined"!=typeof trustedTypes&&trustedTypes.createPolicy&&(e=trustedTypes.createPolicy("angular#bundler",e))),e.createScriptURL(a)}}(),n.p="",function(){var e={666:0};n.f.j=function(u,o){var i=n.o(e,u)?e[u]:void 0;if(0!==i)if(i)o.push(i[2]);else if(666!=u){var r=new Promise(function(c,d){i=e[u]=[c,d]});o.push(i[2]=r);var l=n.p+n.u(u),f=new Error;n.l(l,function(c){if(n.o(e,u)&&(0!==(i=e[u])&&(e[u]=void 0),i)){var d=c&&("load"===c.type?"missing":c.type),p=c&&c.target&&c.target.src;f.message="Loading chunk "+u+" failed.\n("+d+": "+p+")",f.name="ChunkLoadError",f.type=d,f.request=p,i[1](f)}},"chunk-"+u,u)}else e[u]=0},n.O.j=function(u){return 0===e[u]};var a=function(u,o){var f,s,i=o[0],r=o[1],l=o[2],c=0;for(f in r)n.o(r,f)&&(n.m[f]=r[f]);if(l)var d=l(n);for(u&&u(o);c<i.length;c++)n.o(e,s=i[c])&&e[s]&&e[s][0](),e[i[c]]=0;return n.O(d)},t=self.webpackChunkgns3_web_ui=self.webpackChunkgns3_web_ui||[];t.forEach(a.bind(null,0)),t.push=a.bind(null,t.push.bind(t))}()}();
+2 -2
View File
@@ -23,8 +23,8 @@
# or negative for a release candidate or beta (after the base version
# number has been incremented)
__version__ = "2.2.44.dev1"
__version_info__ = (2, 2, 44, 99)
__version__ = "2.2.45"
__version_info__ = (2, 2, 45, 0)
if "dev" in __version__:
try:
+30 -8
View File
@@ -38,7 +38,7 @@ from .route import Route
from ..config import Config
from ..compute import MODULES
from ..compute.port_manager import PortManager
from ..compute.qemu import Qemu
from ..utils.images import list_images
from ..controller import Controller
# do not delete this import
@@ -87,6 +87,8 @@ class WebServer:
except (RuntimeError, OSError, asyncio.CancelledError) as e:
log.critical("Could not start the server: {}".format(e))
return False
except KeyboardInterrupt:
return False
return True
async def reload_server(self):
@@ -230,16 +232,34 @@ class WebServer:
atexit.register(close_asyncio_loop)
async def _compute_image_checksums(self):
"""
Compute image checksums.
"""
if sys.platform.startswith("darwin") and hasattr(sys, "frozen"):
# do not compute on macOS because errors
return
loop = asyncio.get_event_loop()
import concurrent.futures
with concurrent.futures.ProcessPoolExecutor(max_workers=1) as pool:
try:
log.info("Computing image checksums...")
await loop.run_in_executor(pool, list_images, "qemu")
log.info("Finished computing image checksums")
except OSError as e:
log.warning("Could not compute image checksums: {}".format(e))
async def _on_startup(self, *args):
"""
Called when the HTTP server start
"""
await Controller.instance().start()
# Because with a large image collection
# without md5sum already computed we start the
# computing with server start
asyncio.ensure_future(Qemu.instance().list_images())
# Start computing checksums now because it can take a long time
# for a large image collection
await self._compute_image_checksums()
def run(self):
"""
@@ -291,13 +311,13 @@ class WebServer:
# Background task started with the server
self._app.on_startup.append(self._on_startup)
resource_options = aiohttp_cors.ResourceOptions(expose_headers="*", allow_headers="*", max_age=0)
resource_options = aiohttp_cors.ResourceOptions(allow_credentials=True, expose_headers="*", allow_headers="*", max_age=0)
# Allow CORS for this domains
cors = aiohttp_cors.setup(self._app, defaults={
# Default web server for web gui dev
"http://127.0.0.1:8080": resource_options,
"http://localhost:8080": resource_options,
"http://127.0.0.1:3080": resource_options,
"http://localhost:3080": resource_options,
"http://127.0.0.1:4200": resource_options,
"http://localhost:4200": resource_options,
"http://gns3.github.io": resource_options,
@@ -330,6 +350,8 @@ class WebServer:
try:
self._loop.run_forever()
except ConnectionResetError:
log.warning("Connection reset by peer")
except TypeError as e:
# This is to ignore an asyncio.windows_events exception
# on Windows when the process gets the SIGBREAK signal
+8 -4
View File
@@ -1,5 +1,9 @@
build:
image: latest
version: 2
python:
version: 3.6
build:
os: "ubuntu-22.04"
tools:
python: "3.12"
sphinx:
configuration: docs/conf.py
+3 -3
View File
@@ -1,13 +1,13 @@
jsonschema>=4.17.3,<4.18; python_version >= '3.7' # v4.17.3 is the last version to support Python 3.7
jsonschema==3.2.0; python_version < '3.7' # v3.2.0 is the last version to support Python 3.6
aiohttp>=3.8.5,<3.9; python_version < '3.12'
aiohttp==3.9.0b0; python_version == '3.12'
aiohttp>=3.8.5,<3.9; python_version <= '3.7'
aiohttp>=3.9.0,<3.10; python_version > '3.7'
aiohttp-cors>=0.7.0,<0.8
aiofiles>=23.2.1,<23.3; python_version >= '3.7'
aiofiles==0.8.0; python_version < '3.7' # v0.8.0 is the last version to support Python 3.6
Jinja2>=3.1.2,<3.2; python_version >= '3.7'
Jinja2==3.0.3; python_version < '3.7' # v3.0.3 is the last version to support Python 3.6
sentry-sdk==1.32.0,<1.33
sentry-sdk==1.36.0,<1.37
psutil==5.9.6
async-timeout>=4.0.2,<4.1
distro>=1.8.0
+40
View File
@@ -0,0 +1,40 @@
#!/bin/bash
# -*- coding: utf-8 -*-
#
# Copyright (C) 2020 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/>.
# Bash shell script for generating self-signed certs.
# The certificate is automatically put in your GNS3 config
DST_DIR="$HOME/.config/GNS3/ssl"
OLD_DIR=`pwd`
fail_if_error() {
[ $1 != 0 ] && {
unset PASSPHRASE
cd $OLD_DIR
exit 10
}
}
mkdir -p $DST_DIR
fail_if_error $?
cd $DST_DIR
SUBJ="/C=US/ST=Texas/O=GNS3SELF/localityName=Austin/commonName=localhost/organizationalUnitName=GNS3Server/emailAddress=gns3cert@gns3.com"
openssl req -nodes -new -x509 -keyout server.key -out server.cert -subj "$SUBJ"
+3 -1
View File
@@ -213,7 +213,9 @@ async def test_compute_httpQuery_project(compute):
response = MagicMock()
with asyncio_patch("aiohttp.ClientSession.request", return_value=response) as mock:
response.status = 200
project = Project(name="Test")
with patch('gns3server.controller.project.Project.emit_controller_notification') as mock_notification:
project = Project(name="Test")
mock_notification.assert_called()
await compute.post("/projects", project)
mock.assert_called_with("POST", "https://example.com:84/v2/compute/projects", data=json.dumps(project.__json__()), headers={'content-type': 'application/json'}, auth=None, chunked=None, timeout=20)
await compute.close()
+50 -37
View File
@@ -47,15 +47,19 @@ async def node(controller, project):
async def test_affect_uuid():
p = Project(name="Test")
assert len(p.id) == 36
p = Project(project_id='00010203-0405-0607-0809-0a0b0c0d0e0f', name="Test 2")
assert p.id == '00010203-0405-0607-0809-0a0b0c0d0e0f'
with patch('gns3server.controller.project.Project.emit_controller_notification') as mock_notification:
p = Project(name="Test")
mock_notification.assert_called()
assert len(p.id) == 36
p = Project(project_id='00010203-0405-0607-0809-0a0b0c0d0e0f', name="Test 2")
assert p.id == '00010203-0405-0607-0809-0a0b0c0d0e0f'
async def test_json():
p = Project(name="Test")
with patch('gns3server.controller.project.Project.emit_controller_notification') as mock_notification:
p = Project(name="Test")
mock_notification.assert_called()
assert p.__json__() == {
"name": "Test",
@@ -83,11 +87,11 @@ async def test_json():
async def test_update(controller):
project = Project(controller=controller, name="Hello")
project.emit_notification = MagicMock()
project.emit_controller_notification = MagicMock()
assert project.name == "Hello"
await project.update(name="World")
assert project.name == "World"
project.emit_notification.assert_any_call("project.updated", project.__json__())
project.emit_controller_notification.assert_any_call("project.updated", project.__json__())
async def test_update_on_compute(controller):
@@ -106,7 +110,9 @@ async def test_path(projects_dir):
directory = projects_dir
with patch("gns3server.utils.path.get_default_project_directory", return_value=directory):
p = Project(project_id=str(uuid4()), name="Test")
with patch('gns3server.controller.project.Project.emit_controller_notification') as mock_notification:
p = Project(project_id=str(uuid4()), name="Test")
mock_notification.assert_called()
assert p.path == os.path.join(directory, p.id)
assert os.path.exists(os.path.join(directory, p.id))
@@ -124,23 +130,27 @@ def test_path_exist(tmpdir):
async def test_init_path(tmpdir):
p = Project(path=str(tmpdir), project_id=str(uuid4()), name="Test")
assert p.path == str(tmpdir)
with patch('gns3server.controller.project.Project.emit_controller_notification') as mock_notification:
p = Project(path=str(tmpdir), project_id=str(uuid4()), name="Test")
mock_notification.assert_called()
assert p.path == str(tmpdir)
@pytest.mark.skipif(sys.platform.startswith("win"), reason="Not supported on Windows")
async def test_changing_path_with_quote_not_allowed(tmpdir):
with pytest.raises(aiohttp.web.HTTPForbidden):
p = Project(project_id=str(uuid4()), name="Test")
p.path = str(tmpdir / "project\"53")
with patch('gns3server.controller.project.Project.emit_controller_notification'):
p = Project(project_id=str(uuid4()), name="Test")
p.path = str(tmpdir / "project\"53")
async def test_captures_directory(tmpdir):
p = Project(path=str(tmpdir / "capturestest"), name="Test")
assert p.captures_directory == str(tmpdir / "capturestest" / "project-files" / "captures")
assert os.path.exists(p.captures_directory)
with patch('gns3server.controller.project.Project.emit_controller_notification'):
p = Project(path=str(tmpdir / "capturestest"), name="Test")
assert p.captures_directory == str(tmpdir / "capturestest" / "project-files" / "captures")
assert os.path.exists(p.captures_directory)
async def test_add_node_local(controller):
@@ -649,36 +659,39 @@ async def test_dump(projects_dir):
directory = projects_dir
with patch("gns3server.utils.path.get_default_project_directory", return_value=directory):
p = Project(project_id='00010203-0405-0607-0809-0a0b0c0d0e0f', name="Test")
p.dump()
with open(os.path.join(directory, p.id, "Test.gns3")) as f:
content = f.read()
assert "00010203-0405-0607-0809-0a0b0c0d0e0f" in content
with patch('gns3server.controller.project.Project.emit_controller_notification'):
p = Project(project_id='00010203-0405-0607-0809-0a0b0c0d0e0f', name="Test")
p.dump()
with open(os.path.join(directory, p.id, "Test.gns3")) as f:
content = f.read()
assert "00010203-0405-0607-0809-0a0b0c0d0e0f" in content
async def test_open_close(controller):
project = Project(controller=controller, name="Test")
assert project.status == "opened"
await project.close()
project.start_all = AsyncioMagicMock()
await project.open()
assert not project.start_all.called
assert project.status == "opened"
project.emit_notification = MagicMock()
await project.close()
assert project.status == "closed"
project.emit_notification.assert_any_call("project.closed", project.__json__())
with patch('gns3server.controller.project.Project.emit_controller_notification'):
project = Project(controller=controller, name="Test")
assert project.status == "opened"
await project.close()
project.start_all = AsyncioMagicMock()
await project.open()
assert not project.start_all.called
assert project.status == "opened"
project.emit_controller_notification = MagicMock()
await project.close()
assert project.status == "closed"
project.emit_controller_notification.assert_any_call("project.closed", project.__json__())
async def test_open_auto_start(controller):
project = Project(controller=controller, name="Test", auto_start=True)
assert project.status == "opened"
await project.close()
project.start_all = AsyncioMagicMock()
await project.open()
assert project.start_all.called
with patch('gns3server.controller.project.Project.emit_controller_notification'):
project = Project(controller=controller, name="Test", auto_start=True)
assert project.status == "opened"
await project.close()
project.start_all = AsyncioMagicMock()
await project.open()
assert project.start_all.called
def test_is_running(project, node):
+31 -30
View File
@@ -19,7 +19,7 @@ import json
import uuid
import pytest
import aiohttp
from unittest.mock import MagicMock
from unittest.mock import MagicMock, patch
from tests.utils import asyncio_patch
from gns3server.controller.project import Project
@@ -30,35 +30,36 @@ from gns3server.version import __version__
async def test_project_to_topology_empty(tmpdir):
project = Project(name="Test")
topo = project_to_topology(project)
assert topo == {
"project_id": project.id,
"name": "Test",
"auto_start": False,
"auto_close": True,
"auto_open": False,
"scene_width": 2000,
"scene_height": 1000,
"revision": GNS3_FILE_FORMAT_REVISION,
"zoom": 100,
"show_grid": False,
"show_interface_labels": False,
"show_layers": False,
"snap_to_grid": False,
"grid_size": 75,
"drawing_grid_size": 25,
"topology": {
"nodes": [],
"links": [],
"computes": [],
"drawings": []
},
"type": "topology",
"supplier": None,
"variables": None,
"version": __version__
}
with patch('gns3server.controller.project.Project.emit_controller_notification'):
project = Project(name="Test")
topo = project_to_topology(project)
assert topo == {
"project_id": project.id,
"name": "Test",
"auto_start": False,
"auto_close": True,
"auto_open": False,
"scene_width": 2000,
"scene_height": 1000,
"revision": GNS3_FILE_FORMAT_REVISION,
"zoom": 100,
"show_grid": False,
"show_interface_labels": False,
"show_layers": False,
"snap_to_grid": False,
"grid_size": 75,
"drawing_grid_size": 25,
"topology": {
"nodes": [],
"links": [],
"computes": [],
"drawings": []
},
"type": "topology",
"supplier": None,
"variables": None,
"version": __version__
}
async def test_basic_topology(controller):
@@ -186,7 +186,9 @@ async def test_notification(controller_api, http_client, project, controller):
assert b'"cpu_usage_percent"' in response.body
assert b'{"action": "node.created", "event": {"a": "b"}}\n' in response.body
assert project.status == "opened"
controller.notification.project_emit("node.updated", {"a": "b"})
controller.notification.project_emit("node.deleted", {"a": "b"})
controller.notification.project_emit("snapshot.restored", {"a": "b"})
async def test_notification_invalid_id(controller_api):