diff --git a/docs/api/notifications/link.updated.json b/docs/api/notifications/link.updated.json index 02d45efa..6fb0157e 100644 --- a/docs/api/notifications/link.updated.json +++ b/docs/api/notifications/link.updated.json @@ -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 } \ No newline at end of file diff --git a/docs/api/notifications/log.warning.json b/docs/api/notifications/log.warning.json index 5d630354..dd724322 100644 --- a/docs/api/notifications/log.warning.json +++ b/docs/api/notifications/log.warning.json @@ -1,3 +1,3 @@ { - "message": "Warning ASA 8 is not officialy supported by GNS3" + "message": "Warning ASA 8 is not officially supported by GNS3" } \ No newline at end of file diff --git a/docs/api/notifications/project.created.json b/docs/api/notifications/project.created.json new file mode 100644 index 00000000..54428224 --- /dev/null +++ b/docs/api/notifications/project.created.json @@ -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 +} \ No newline at end of file diff --git a/docs/api/notifications/project.deleted.json b/docs/api/notifications/project.deleted.json new file mode 100644 index 00000000..0c93406f --- /dev/null +++ b/docs/api/notifications/project.deleted.json @@ -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 +} \ No newline at end of file diff --git a/docs/api/notifications/project.opened.json b/docs/api/notifications/project.opened.json new file mode 100644 index 00000000..e7c9cc8e --- /dev/null +++ b/docs/api/notifications/project.opened.json @@ -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 +} \ No newline at end of file diff --git a/docs/api/v2/compute/ethernet_switch/projectsprojectidethernetswitchnodes.rst b/docs/api/v2/compute/ethernet_switch/projectsprojectidethernetswitchnodes.rst index dcbfcb5d..e855f049 100644 --- a/docs/api/v2/compute/ethernet_switch/projectsprojectidethernetswitchnodes.rst +++ b/docs/api/v2/compute/ethernet_switch/projectsprojectidethernetswitchnodes.rst @@ -23,7 +23,7 @@ Types +++++++++ EthernetSwitchPort ^^^^^^^^^^^^^^^^^^^^^^ -Ethernet port +Ethernet switch port .. raw:: html diff --git a/docs/api/v2/compute/ethernet_switch/projectsprojectidethernetswitchnodesnodeid.rst b/docs/api/v2/compute/ethernet_switch/projectsprojectidethernetswitchnodesnodeid.rst index 8a56fe64..efa5d250 100644 --- a/docs/api/v2/compute/ethernet_switch/projectsprojectidethernetswitchnodesnodeid.rst +++ b/docs/api/v2/compute/ethernet_switch/projectsprojectidethernetswitchnodesnodeid.rst @@ -56,7 +56,7 @@ Types +++++++++ EthernetSwitchPort ^^^^^^^^^^^^^^^^^^^^^^ -Ethernet port +Ethernet switch port .. raw:: html diff --git a/docs/api/v2/compute/iou/projectsprojectidiounodes.rst b/docs/api/v2/compute/iou/projectsprojectidiounodes.rst index 4eee67da..5ef4495c 100644 --- a/docs/api/v2/compute/iou/projectsprojectidiounodes.rst +++ b/docs/api/v2/compute/iou/projectsprojectidiounodes.rst @@ -23,7 +23,7 @@ Input - + diff --git a/docs/api/v2/compute/project/projects.rst b/docs/api/v2/compute/project/projects.rst index ed7b6a5e..3d1abea5 100644 --- a/docs/api/v2/compute/project/projects.rst +++ b/docs/api/v2/compute/project/projects.rst @@ -35,6 +35,8 @@ Input
Name Mandatory Type Description
application_id ['integer', 'null'] Application ID for running IOU image
application_id ['integer', 'null'] Application ID for running IOU image
console ['integer', 'null'] Console TCP port
console_type enum Possible values: telnet, none
ethernet_adapters integer How many ethernet adapters are connected to the IOU
+ + diff --git a/docs/api/v2/compute/qemu/projectsprojectidqemunodes.rst b/docs/api/v2/compute/qemu/projectsprojectidqemunodes.rst index d39588a5..7ef0486d 100644 --- a/docs/api/v2/compute/qemu/projectsprojectidqemunodes.rst +++ b/docs/api/v2/compute/qemu/projectsprojectidqemunodes.rst @@ -34,6 +34,7 @@ Input + @@ -63,6 +64,9 @@ Input + + +
Name Mandatory Type Description
auto_close boolean Project auto close
auto_open boolean Project open when GNS3 start
auto_start boolean Project start when opened
drawing_grid_size integer Grid size for the drawing area for drawings
grid_size integer Grid size for the drawing area for nodes
name ['string', 'null'] Project name
console_type enum Possible values: telnet, vnc, spice, spice+agent, none
cpu_throttling ['integer', 'null'] Percentage of CPU allowed for QEMU
cpus ['integer', 'null'] Number of vCPUs
create_config_disk ['boolean', 'null'] Automatically create a config disk on HDD disk interface (secondary slave)
custom_adapters array
hda_disk_image string QEMU hda disk image path
hda_disk_image_md5sum ['string', 'null'] QEMU hda disk image checksum
process_priority enum Possible values: realtime, very high, high, normal, low, very low, null
qemu_path ['string', 'null'] Path to QEMU
ram ['integer', 'null'] Amount of RAM in MB
replicate_network_connection_state ['boolean', 'null'] Replicate the network connection state for links in Qemu
tpm ['boolean', 'null'] Enable the Trusted Platform Module (TPM) in Qemu
uefi ['boolean', 'null'] Enable the UEFI boot mode in Qemu
usage string How to use the Qemu VM
@@ -84,6 +88,7 @@ Output console_type ✔ enum Possible values: telnet, vnc, spice, spice+agent, none cpu_throttling ✔ integer Percentage of CPU allowed for QEMU cpus ✔ ['integer', 'null'] Number of vCPUs + create_config_disk ✔ ['boolean', 'null'] Automatically create a config disk on HDD disk interface (secondary slave) hda_disk_image ✔ string QEMU hda disk image path hda_disk_image_md5sum ✔ ['string', 'null'] QEMU hda disk image checksum hda_disk_interface ✔ string QEMU hda interface @@ -113,8 +118,11 @@ Output project_id ✔ string Project UUID qemu_path ✔ string Path to QEMU ram ✔ integer Amount of RAM in MB + replicate_network_connection_state ✔ boolean Replicate the network connection state for links in Qemu save_vm_state ['boolean', 'null'] Save VM state support status ✔ enum Possible values: started, stopped, suspended + tpm ✔ boolean Enable the Trusted Platform Module (TPM) in Qemu + uefi ✔ boolean Enable the UEFI boot mode in Qemu usage ✔ string How to use the QEMU VM diff --git a/docs/api/v2/compute/qemu/projectsprojectidqemunodesnodeid.rst b/docs/api/v2/compute/qemu/projectsprojectidqemunodesnodeid.rst index fa458038..3a4073f2 100644 --- a/docs/api/v2/compute/qemu/projectsprojectidqemunodesnodeid.rst +++ b/docs/api/v2/compute/qemu/projectsprojectidqemunodesnodeid.rst @@ -36,6 +36,7 @@ Output console_type ✔ enum Possible values: telnet, vnc, spice, spice+agent, none cpu_throttling ✔ integer Percentage of CPU allowed for QEMU cpus ✔ ['integer', 'null'] Number of vCPUs + create_config_disk ✔ ['boolean', 'null'] Automatically create a config disk on HDD disk interface (secondary slave) hda_disk_image ✔ string QEMU hda disk image path hda_disk_image_md5sum ✔ ['string', 'null'] QEMU hda disk image checksum hda_disk_interface ✔ string QEMU hda interface @@ -65,8 +66,11 @@ Output project_id ✔ string Project UUID qemu_path ✔ string Path to QEMU ram ✔ integer Amount of RAM in MB + replicate_network_connection_state ✔ boolean Replicate the network connection state for links in Qemu save_vm_state ['boolean', 'null'] Save VM state support status ✔ enum Possible values: started, stopped, suspended + tpm ✔ boolean Enable the Trusted Platform Module (TPM) in Qemu + uefi ✔ boolean Enable the UEFI boot mode in Qemu usage ✔ string How to use the QEMU VM @@ -110,6 +114,7 @@ Input console_type enum Possible values: telnet, vnc, spice, spice+agent, none cpu_throttling ['integer', 'null'] Percentage of CPU allowed for QEMU cpus ['integer', 'null'] Number of vCPUs + create_config_disk ['boolean', 'null'] Automatically create a config disk on HDD disk interface (secondary slave) custom_adapters array hda_disk_image string QEMU hda disk image path hda_disk_image_md5sum ['string', 'null'] QEMU hda disk image checksum @@ -138,6 +143,9 @@ Input process_priority enum Possible values: realtime, very high, high, normal, low, very low, null qemu_path ['string', 'null'] Path to QEMU ram ['integer', 'null'] Amount of RAM in MB + replicate_network_connection_state ['boolean', 'null'] Replicate the network connection state for links in Qemu + tpm ['boolean', 'null'] Enable the Trusted Platform Module (TPM) in Qemu + uefi ['boolean', 'null'] Enable the UEFI boot mode in Qemu usage string How to use the QEMU VM @@ -159,6 +167,7 @@ Output console_type ✔ enum Possible values: telnet, vnc, spice, spice+agent, none cpu_throttling ✔ integer Percentage of CPU allowed for QEMU cpus ✔ ['integer', 'null'] Number of vCPUs + create_config_disk ✔ ['boolean', 'null'] Automatically create a config disk on HDD disk interface (secondary slave) hda_disk_image ✔ string QEMU hda disk image path hda_disk_image_md5sum ✔ ['string', 'null'] QEMU hda disk image checksum hda_disk_interface ✔ string QEMU hda interface @@ -188,8 +197,11 @@ Output project_id ✔ string Project UUID qemu_path ✔ string Path to QEMU ram ✔ integer Amount of RAM in MB + replicate_network_connection_state ✔ boolean Replicate the network connection state for links in Qemu save_vm_state ['boolean', 'null'] Save VM state support status ✔ enum Possible values: started, stopped, suspended + tpm ✔ boolean Enable the Trusted Platform Module (TPM) in Qemu + uefi ✔ boolean Enable the UEFI boot mode in Qemu usage ✔ string How to use the QEMU VM diff --git a/docs/api/v2/compute/qemu/projectsprojectidqemunodesnodeidstart.rst b/docs/api/v2/compute/qemu/projectsprojectidqemunodesnodeidstart.rst index 5df86864..1f9b05a4 100644 --- a/docs/api/v2/compute/qemu/projectsprojectidqemunodesnodeidstart.rst +++ b/docs/api/v2/compute/qemu/projectsprojectidqemunodesnodeidstart.rst @@ -36,6 +36,7 @@ Output console_type ✔ enum Possible values: telnet, vnc, spice, spice+agent, none cpu_throttling ✔ integer Percentage of CPU allowed for QEMU cpus ✔ ['integer', 'null'] Number of vCPUs + create_config_disk ✔ ['boolean', 'null'] Automatically create a config disk on HDD disk interface (secondary slave) hda_disk_image ✔ string QEMU hda disk image path hda_disk_image_md5sum ✔ ['string', 'null'] QEMU hda disk image checksum hda_disk_interface ✔ string QEMU hda interface @@ -65,8 +66,11 @@ Output project_id ✔ string Project UUID qemu_path ✔ string Path to QEMU ram ✔ integer Amount of RAM in MB + replicate_network_connection_state ✔ boolean Replicate the network connection state for links in Qemu save_vm_state ['boolean', 'null'] Save VM state support status ✔ enum Possible values: started, stopped, suspended + tpm ✔ boolean Enable the Trusted Platform Module (TPM) in Qemu + uefi ✔ boolean Enable the UEFI boot mode in Qemu usage ✔ string How to use the QEMU VM diff --git a/docs/api/v2/controller/link/projectsprojectidlinks.rst b/docs/api/v2/controller/link/projectsprojectidlinks.rst index 8022478f..f5e5ff7d 100644 --- a/docs/api/v2/controller/link/projectsprojectidlinks.rst +++ b/docs/api/v2/controller/link/projectsprojectidlinks.rst @@ -47,6 +47,7 @@ Input capturing boolean Read only property. True if a capture running on the link filters object Packet filter. This allow to simulate latency and errors link_id string Link UUID + link_style object Link line style link_type enum Possible values: ethernet, serial nodes array List of the VMS project_id string Project UUID @@ -65,6 +66,7 @@ Output capturing boolean Read only property. True if a capture running on the link filters object Packet filter. This allow to simulate latency and errors link_id string Link UUID + link_style object Link line style link_type enum Possible values: ethernet, serial nodes array List of the VMS project_id string Project UUID diff --git a/docs/api/v2/controller/link/projectsprojectidlinkslinkid.rst b/docs/api/v2/controller/link/projectsprojectidlinkslinkid.rst index 14e82bd2..3da82ff1 100644 --- a/docs/api/v2/controller/link/projectsprojectidlinkslinkid.rst +++ b/docs/api/v2/controller/link/projectsprojectidlinkslinkid.rst @@ -30,6 +30,7 @@ Output capturing boolean Read only property. True if a capture running on the link filters object Packet filter. This allow to simulate latency and errors link_id string Link UUID + link_style object Link line style link_type enum Possible values: ethernet, serial nodes array List of the VMS project_id string Project UUID @@ -69,6 +70,7 @@ Input capturing boolean Read only property. True if a capture running on the link filters object Packet filter. This allow to simulate latency and errors link_id string Link UUID + link_style object Link line style link_type enum Possible values: ethernet, serial nodes array List of the VMS project_id string Project UUID @@ -87,6 +89,7 @@ Output capturing boolean Read only property. True if a capture running on the link filters object Packet filter. This allow to simulate latency and errors link_id string Link UUID + link_style object Link line style link_type enum Possible values: ethernet, serial nodes array List of the VMS project_id string Project UUID diff --git a/docs/api/v2/controller/link/projectsprojectidlinkslinkidstartcapture.rst b/docs/api/v2/controller/link/projectsprojectidlinkslinkidstartcapture.rst index 7db0a05a..bc8f6c42 100644 --- a/docs/api/v2/controller/link/projectsprojectidlinkslinkidstartcapture.rst +++ b/docs/api/v2/controller/link/projectsprojectidlinkslinkidstartcapture.rst @@ -39,6 +39,7 @@ Output capturing boolean Read only property. True if a capture running on the link filters object Packet filter. This allow to simulate latency and errors link_id string Link UUID + link_style object Link line style link_type enum Possible values: ethernet, serial nodes array List of the VMS project_id string Project UUID diff --git a/docs/api/v2/controller/project/projects.rst b/docs/api/v2/controller/project/projects.rst index fc6c8bd2..9b954366 100644 --- a/docs/api/v2/controller/project/projects.rst +++ b/docs/api/v2/controller/project/projects.rst @@ -19,6 +19,8 @@ Input + + diff --git a/docs/api/v2/controller/project/projectsprojectidduplicate.rst b/docs/api/v2/controller/project/projectsprojectidduplicate.rst index 13e63c0f..ddfca566 100644 --- a/docs/api/v2/controller/project/projectsprojectidduplicate.rst +++ b/docs/api/v2/controller/project/projectsprojectidduplicate.rst @@ -24,11 +24,14 @@ Input
Name Mandatory Type Description
auto_close boolean Project auto close
auto_open boolean Project open when GNS3 start
auto_start boolean Project start when opened
drawing_grid_size integer Grid size for the drawing area for drawings
grid_size integer Grid size for the drawing area for nodes
name ['string', 'null'] Project name
+ + + diff --git a/docs/controller_notifications.rst b/docs/controller_notifications.rst index e21caa54..5d7765e0 100644 --- a/docs/controller_notifications.rst +++ b/docs/controller_notifications.rst @@ -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 ----------------- diff --git a/docs/gns3_file.json b/docs/gns3_file.json index 825a9e87..a90d89b8 100644 --- a/docs/gns3_file.json +++ b/docs/gns3_file.json @@ -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", diff --git a/docs/project_notifications.rst b/docs/project_notifications.rst index f37dd07e..58ab1861 100644 --- a/docs/project_notifications.rst +++ b/docs/project_notifications.rst @@ -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 -------------------------- diff --git a/gns3server/controller/project.py b/gns3server/controller/project.py index c4dc3b95..eed15198 100644 --- a/gns3server/controller/project.py +++ b/gns3server/controller/project.py @@ -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 diff --git a/readthedocs.yml b/readthedocs.yml index 87fa516b..754f9590 100644 --- a/readthedocs.yml +++ b/readthedocs.yml @@ -1,5 +1,5 @@ +version: 2 build: - image: latest - -python: - version: 3.6 + os: "ubuntu-22.04" + tools: + python: "3.11" diff --git a/tests/controller/test_compute.py b/tests/controller/test_compute.py index d7f5329c..b9b911b3 100644 --- a/tests/controller/test_compute.py +++ b/tests/controller/test_compute.py @@ -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() diff --git a/tests/controller/test_project.py b/tests/controller/test_project.py index bc729fee..fb8bcfeb 100644 --- a/tests/controller/test_project.py +++ b/tests/controller/test_project.py @@ -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): diff --git a/tests/controller/test_topology.py b/tests/controller/test_topology.py index 4ac24259..4499ddce 100644 --- a/tests/controller/test_topology.py +++ b/tests/controller/test_topology.py @@ -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):
Name Mandatory Type Description
auto_close boolean Project auto close
auto_open boolean Project open when GNS3 start
auto_start boolean Project start when opened
drawing_grid_size integer Grid size for the drawing area for drawings
grid_size integer Grid size for the drawing area for nodes
name ['string', 'null'] Project name
path ['string', 'null'] Project directory
project_id ['string', 'null'] Project UUID
reset_mac_addresses boolean Reset MAC addresses for this project
scene_height integer Height of the drawing area
scene_width integer Width of the drawing area
show_grid boolean Show the grid on the drawing area