1
0
mirror of https://github.com/GNS3/gns3-server synced 2024-12-26 16:58:28 +00:00

Merge pull request #2336 from GNS3/fix/2319

Refactor project notifications
This commit is contained in:
Jeremy Grossmann 2024-01-12 13:38:51 +11:00 committed by GitHub
commit 466eb8128e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 271 additions and 102 deletions

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
}

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"
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -23,7 +23,7 @@ Types
+++++++++
EthernetSwitchPort
^^^^^^^^^^^^^^^^^^^^^^
Ethernet port
Ethernet switch port
.. raw:: html

View File

@ -56,7 +56,7 @@ Types
+++++++++
EthernetSwitchPort
^^^^^^^^^^^^^^^^^^^^^^
Ethernet port
Ethernet switch port
.. raw:: html

View File

@ -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>

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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

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
-----------------

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",

View File

@ -100,22 +100,6 @@ 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
--------------------------

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

View File

@ -1,5 +1,5 @@
version: 2
build:
image: latest
python:
version: 3.6
os: "ubuntu-22.04"
tools:
python: "3.11"

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()

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):

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):