Compare commits

...
279 Commits
Author SHA1 Message Date
grossmj 469bd692a0 Release v3.0.2 2025-01-03 21:44:00 +07:00
grossmj d34c3a0ac7 Bundle web-ui v3.0.2 2025-01-03 21:40:11 +07:00
Jeremy Grossmann fb3409c1a1 Merge pull request #2474 from GNS3/install-all-images
Support to create templates based on image checksums
2025-01-03 21:38:59 +07:00
grossmj 08693871ae Support to create templates based on image checksums. 2025-01-03 21:35:14 +07:00
Jeremy Grossmann f5ea20347e Merge pull request #2472 from GNS3/builtin-disks-improvements
Improvements for built-in disks
2025-01-03 20:01:06 +07:00
grossmj ac4c5f5985 Improve tests for pruning images 2025-01-03 19:56:41 +07:00
grossmj e17a79e261 Fix tests 2025-01-02 23:17:55 +07:00
grossmj 4758431c76 Improvements for built-in disks
* Checksum is updated in the database for updated disks.
* It is not possible to prune them.
2025-01-02 23:10:51 +07:00
Jeremy Grossmann b472f6dbf8 Merge pull request #2471 from GNS3/watchdog-migration
Watchdog migration
2024-12-31 17:30:24 +07:00
grossmj b39c7541fb Add timeout for waiting watchdog observer thread to complete 2024-12-31 17:24:19 +07:00
grossmj 82779d816f Use watchdog instead of watchfiles to monitor for new images on the file system 2024-12-31 17:19:32 +07:00
Jeremy Grossmann 96c6805ace Merge pull request #2469 from GNS3/joserfc-migration
Replace python-jose library by joserfc
2024-12-30 16:02:17 +07:00
grossmj efb84b3063 Add back ValidationError 2024-12-30 15:59:01 +07:00
Jeremy Grossmann 0be45c7da2 Merge branch '3.0' into joserfc-migration 2024-12-30 15:52:54 +07:00
Jeremy Grossmann a4222b4d03 Merge pull request #2470 from GNS3/drop-python3.8
Drop Python 3.8
2024-12-30 15:51:23 +07:00
grossmj 5f75fc7573 Add greenlet dependency 2024-12-30 15:45:17 +07:00
grossmj 5269d4386c Drop Python 3.8 2024-12-30 15:36:40 +07:00
grossmj 9d6cea665a Replace python-jose library by joserfc 2024-12-30 15:25:24 +07:00
grossmj 8b57fbaa0a Downgrade uvicorn to v0.33.0 2024-12-28 18:23:46 +07:00
grossmj d4a9a21af9 Upgrade dependencies 2024-12-28 18:21:18 +07:00
grossmj 8a900588ca Merge branch '2.2' into 3.0 2024-12-28 18:04:25 +07:00
grossmj 8ed1fa6ad5 Merge branch 'master' into 2.2 2024-12-28 18:03:39 +07:00
Jeremy Grossmann a689a55937 Merge pull request #2467 from GNS3/update-remote-install-script
Use iptables to block IOU home call
2024-12-28 18:01:25 +07:00
grossmj 1c0b0ae423 Remove blocking IOU phone home call. 2024-12-28 18:00:22 +07:00
grossmj ad7813d04b Use iptables to block IOU home call 2024-12-28 17:50:59 +07:00
grossmj 654b84cb7b Release v3.0.1 2024-12-27 21:05:24 +07:00
grossmj fc1acc58de Sync appliances 2024-12-27 21:01:23 +07:00
grossmj 07ac4f5834 Bundle web-ui v3.0.1 2024-12-27 21:00:58 +07:00
grossmj 249bf89b7e Allow for upgrading built-in disks 2024-12-26 23:04:47 +07:00
grossmj efc3ff62b5 Fix config parsing when configuring server protocol. Fixes https://github.com/GNS3/gns3-gui/issues/3681 2024-12-26 16:36:52 +07:00
grossmj a521e61efc Update empty Qemu disks with correct MD5 checksums 2024-12-23 22:45:36 +07:00
grossmj 9492fd0671 Fix tests 2024-12-22 22:34:23 +07:00
grossmj 512407939d Increase timeout to run compute HTTP queries. Fixes #3453 2024-12-22 22:29:56 +07:00
Jeremy Grossmann 685bf88005 Merge pull request #2457 from GNS3/update-remote-install-script
Update remote install script
2024-12-22 22:07:33 +07:00
grossmj a1090a3da8 Fallback when cannot use deb822 format 2024-12-22 21:52:18 +07:00
grossmj c8e5b41f39 Add compatibility for earlier Ubuntu versions 2024-12-22 21:29:05 +07:00
grossmj 94b5d3e636 Update remote-install.sh to support a custom repository and the deb822 source format 2024-12-22 20:26:24 +07:00
grossmj d54e6babe2 Release v3.0.0 2024-12-20 18:20:42 +07:00
grossmj a9b7869e04 Bundle web-ui v3.0.0 2024-12-19 19:49:40 +07:00
grossmj 72838a8108 Sync appliances 2024-12-19 19:04:19 +07:00
grossmj 7229707746 Use static favicon for API docs. Ref #3674 2024-12-19 17:25:42 +07:00
Jeremy Grossmann c9694a4e1d Merge pull request #2456 from GNS3/feature/self-hosted-static-files
Configure self-hosting JavaScript and CSS for docs
2024-12-19 17:10:48 +07:00
grossmj a792792128 Remove debug message 2024-12-19 17:09:00 +07:00
grossmj eca502c49c Do not test authentication on docs endpoints 2024-12-19 17:04:00 +07:00
grossmj 0ee73605c0 Configure self-hosting JavaScript and CSS for docs 2024-12-19 16:54:11 +07:00
grossmj 648ae231ef Fix project auto open feature. Fixes #2455 2024-12-18 18:40:31 +07:00
grossmj 0dd53d3178 Bump version to 3.0.0.dev14 2024-12-17 16:51:09 +07:00
grossmj 09d67ec1a8 Bump version to 3.0.0.dev13 2024-12-17 16:32:30 +07:00
grossmj c820a807ad Fix IOU node start 2024-12-17 16:24:42 +07:00
grossmj 014d3f2ad9 Store IOU licence in the secrets directory and disable the check by default 2024-12-17 16:12:17 +07:00
grossmj 5e1b8814b6 Merge branch '2.2' into 3.0
# Conflicts:
#	gns3server/compute/iou/iou_vm.py
2024-12-17 15:08:45 +07:00
grossmj df56955bf0 Use license instead of licence 2024-12-17 15:01:01 +07:00
grossmj b84bedffec Merge branch '2.2' into 3.0
# Conflicts:
#	tests/utils/test_images.py
2024-12-16 18:31:57 +07:00
grossmj 423d3fd82b Fix tests 2024-12-16 18:30:30 +07:00
grossmj e1b4d74f1e Merge branch '2.2' into 3.0 2024-12-16 18:17:01 +07:00
grossmj 86fbae00e1 Fix issue with iourc_path 2024-12-16 18:16:42 +07:00
grossmj f38efd311a Merge branch '2.2' into 3.0 2024-12-16 18:14:16 +07:00
grossmj 91e9fa1cbc Fix tests 2024-12-16 18:13:51 +07:00
grossmj db067579db Merge branch '2.2' into 3.0
# Conflicts:
#	gns3server/compute/iou/iou_vm.py
2024-12-16 18:08:51 +07:00
grossmj 6314dd3c35 Fix: do not use the iourc file if IOU licence check is not enabled 2024-12-16 18:07:02 +07:00
grossmj 4e41aefbdb Require "Project.Audit" permission to duplicate a project and check if "Project.Allocate" permission for the destination. 2024-12-06 14:09:08 +10:00
grossmj bbff6974e6 Fix undefined name 'default_directory' 2024-12-02 14:36:58 +10:00
grossmj c05dcef54f Fix formatting issue 2024-12-02 13:18:12 +10:00
grossmj b7d43b29cd Fix tests after merging 2024-12-02 13:02:08 +10:00
grossmj cbaa563996 Merge branch '2.2' into 3.0
# Conflicts:
#	CHANGELOG
#	gns3server/crash_report.py
#	gns3server/static/web-ui/index.html
#	gns3server/static/web-ui/main.9297104511b6616fc55c.js
#	gns3server/utils/images.py
#	gns3server/version.py
#	tests/api/routes/compute/test_dynamips_nodes.py
#	tests/handlers/api/compute/test_qemu.py
#	tests/utils/test_images.py
2024-12-02 12:16:34 +10:00
Jeremy Grossmann e94b55e3bf Merge pull request #2452 from GNS3/release/v2.2.52
release/v2.2.52
2024-12-02 11:36:09 +10:00
grossmj 6c521b5f7a Development on 2.2.53.dev1 2024-12-02 11:33:59 +10:00
grossmj a8014da10b Release v2.2.52 2024-12-02 11:14:23 +10:00
grossmj f6080013e3 Bundle web-ui v2.2.52 2024-12-02 11:09:30 +10:00
grossmj fc54c6e496 Sync appliances 2024-12-02 11:02:47 +10:00
Jeremy Grossmann 04cd107651 Merge pull request #2448 from GNS3/bugfix/3664
Fix listing images
2024-11-28 12:45:37 +10:00
grossmj 19cabdfde6 Use log.debug for some messages in images.py 2024-11-28 12:42:50 +10:00
grossmj af7fbe6bb4 Fix tests 2024-11-27 15:18:49 +10:00
grossmj 3d58b437b4 Remove restrictions based on file extension when listing images and fix ELF header checks 2024-11-27 14:51:34 +10:00
grossmj 83921a45df Fix use project name instead of ID for fast duplication when running local server. Fixes #2446 2024-11-26 12:07:06 +10:00
grossmj b2db8896ea Release v3.0.0rc2 2024-11-20 14:00:49 +10:00
grossmj a22f7ac3d2 Bundle web-ui v3.0.0rc2 2024-11-20 13:51:15 +10:00
grossmj e19af851c1 Sync appliances 2024-11-20 12:39:39 +10:00
grossmj a00f53fbaa Fix error 500 on PUT for cloud, nat, vmware and vpcs nodes. Fixes #2426 2024-11-19 12:21:35 +10:00
Jeremy Grossmann 8db81de153 Merge pull request #2445 from GNS3/bugfix/2426
Fix issue with asyncio.Queue
2024-11-18 14:00:20 +10:00
Jeremy Grossmann fa0d7d7529 Use call_soon_threadsafe() in notification manager 2024-11-18 12:13:41 +10:00
grossmj bd813b0a53 Merge branch '2.2' into 3.0
# Conflicts:
#	requirements.txt
#	setup.py
2024-11-18 11:46:42 +10:00
grossmj b37db57bb9 Fix tests 2024-11-17 15:00:13 +10:00
grossmj 31a2cb998d Fix issue with asyncio.Queue which is not thread safe. 2024-11-17 14:39:22 +10:00
grossmj e83e12b51a Add a duplicated project in the same resource pools as the original project if it is in any 2024-11-17 14:03:47 +10:00
grossmj a7da814b85 Upgrade FastAPI to v0.115.5 2024-11-13 12:10:04 +10:00
Jeremy Grossmann 11c9802268 Merge pull request #2443 from GNS3/feature/upgrade-resource-files
Overwrite user resources when the originals have changed
2024-11-10 18:30:13 +10:00
grossmj a60e0d424d Overwrite user resources when the originals have changed.
Excepting configs and disks which can be customized.
2024-11-09 12:17:06 +10:00
grossmj db1fb29c63 Relax setuptools requirement to allow for easier Debian packaging on Ubuntu Focal & Jammy 2024-11-08 12:46:55 +10:00
Jeremy Grossmann 1a6a729736 Merge pull request #2442 from Xatrekak/master
Fixed issues with installing on Ubuntu 24.04 via remote-install.sh
2024-11-08 10:02:43 +10:00
Dustin 77c356c82c Update remote-install.sh
Fixes for Ubuntu 24.04
2024-11-07 18:15:52 -05:00
Dustin b4819b5500 Update remote-install.sh
Fixing changes for Ubuntu 24.04
2024-11-07 17:44:42 -05:00
grossmj ec9dbd20b8 Merge branch '2.2' into 3.0
# Conflicts:
#	gns3server/compute/base_node.py
#	gns3server/compute/docker/docker_vm.py
#	gns3server/compute/qemu/qemu_vm.py
#	gns3server/crash_report.py
#	gns3server/version.py
2024-11-07 23:18:42 +10:00
grossmj a5f0dba5cf Development on 2.2.52.dev1 2024-11-07 23:13:31 +10:00
Jeremy Grossmann 11a9451098 Merge pull request #2440 from GNS3/release/v2.2.51
release/v2.2.51
2024-11-07 23:13:03 +10:00
grossmj 754680d8e9 Release v2.2.51 2024-11-07 15:08:27 +10:00
grossmj 05773ce189 Sync appliances 2024-11-07 15:06:06 +10:00
grossmj aeae9deb01 Merge remote-tracking branch 'origin/2.2' into 2.2 2024-11-07 14:53:23 +10:00
grossmj f3749e83ec Catch error when cannot resize Docker container TTY. 2024-11-07 14:52:59 +10:00
Jeremy Grossmann c2db4e8542 Merge pull request #2439 from GNS3/bugfix/2438
Fix disk interface is being overriden when set to none
2024-11-07 14:52:08 +10:00
grossmj 52a7696618 Fix tests 2024-11-07 14:48:57 +10:00
grossmj 7bf17392dd Do not use "ide" if there is a disk image and no interface type has been explicitly configured. 2024-11-07 14:37:26 +10:00
grossmj 2718224dde Increase SQLite timeout. Ref #2422 2024-10-31 21:31:03 +10:00
Jeremy Grossmann 0122070b29 Merge pull request #2435 from GNS3/upgrade-dependencies
Upgrade dependencies
2024-10-31 20:56:30 +10:00
grossmj 345ecb7630 Upgrade dev dependencies 2024-10-31 20:49:12 +10:00
grossmj ae538dd11d Fix test user with wrong creds 2024-10-31 19:31:17 +10:00
grossmj ce4dd17409 Upgrade fastapi and fix tests 2024-10-31 19:23:28 +10:00
grossmj 8c7c17b889 Upgrade dependencies and fix Pydantic warnings 2024-10-31 17:09:52 +10:00
grossmj 1530bdfc2b Disable Python 3.13 testing 2024-10-31 13:53:25 +10:00
grossmj 74d07173c1 Upgrade aiohttp to v3.10.10. Fixes #2411 2024-10-31 13:48:22 +10:00
grossmj ec300d19d4 Replace aiohttp.web.HTTPConflict() 2024-10-31 13:11:01 +10:00
grossmj fb06eb3c0c Remove old debug message 2024-10-31 13:07:09 +10:00
grossmj 7e902726bf Fix issues after merge 2024-10-31 13:06:17 +10:00
grossmj c4fcb43e78 Merge branch '2.2' into 3.0
# Conflicts:
#	.github/workflows/testing.yml
#	CHANGELOG
#	README.md
#	dev-requirements.txt
#	gns3server/compute/docker/docker_vm.py
#	gns3server/controller/export_project.py
#	gns3server/controller/import_project.py
#	gns3server/controller/project.py
#	gns3server/crash_report.py
#	gns3server/static/web-ui/index.html
#	gns3server/static/web-ui/main.df8c319a3da6fb0e3629.js
#	gns3server/version.py
#	requirements.txt
#	setup.py
#	tests/compute/docker/test_docker_vm.py
#	tests/controller/test_import_project.py
2024-10-31 12:54:35 +10:00
grossmj 753135a80d Merge branch 'master' into 2.2 2024-10-28 17:32:34 +10:00
grossmj c05e1cb8e7 Use @locking when sending uBridge commands. Ref https://github.com/GNS3/gns3-gui/issues/3651 2024-10-28 13:02:04 +10:00
grossmj 48b7e6ca50 Fix run Docker containers with user namespaces enabled. Fixes #2414 2024-10-26 19:03:05 +10:00
grossmj dbe2b8a5fb Python 3.13 support 2024-10-26 18:38:07 +10:00
grossmj 80487eb62d Upgrade dependencies 2024-10-26 18:22:40 +10:00
grossmj 6e66b26b88 Fix errors in init.sh. Fixes #2431 2024-10-22 12:18:28 +10:00
grossmj 9990666076 Development on 2.2.51.dev1 2024-10-21 13:24:14 +10:00
Jeremy Grossmann 97e5a5edc3 Merge pull request #2430 from GNS3/2.2
Release v2.2.50
2024-10-21 13:21:24 +10:00
grossmj 2b5c6ce8fb Release v2.2.50 2024-10-21 12:14:18 +10:00
grossmj 0aac62d03a Bundle web-ui v2.2.50 2024-10-21 12:08:42 +10:00
grossmj 4058abf16e Sync appliances 2024-10-21 11:54:02 +10:00
grossmj 4357410b10 Do not run tests on Windows (temporarily) 2024-10-19 17:13:13 +10:00
grossmj 734365b216 Fix win10pcap installation in tests 2024-10-19 17:04:10 +10:00
grossmj abb7cc2075 Install win10pcap in tests 2024-10-19 17:00:32 +10:00
grossmj c273a78560 Upgrade pytest to v8.3.3 2024-10-19 16:33:54 +10:00
grossmj 718269e5b3 Fix syntax error in testing.yml 2024-10-19 16:23:46 +10:00
grossmj 19fd7d2193 Install Windows dependencies in GH Actions 2024-10-19 16:22:29 +10:00
grossmj e62ffb1b87 Fix testing on Windows with GH Actions 2024-10-19 16:12:06 +10:00
grossmj 42808161bf Replace AppVeyor testing with GH Actions 2024-10-19 16:07:53 +10:00
Jeremy Grossmann 45ee662c56 Merge pull request #2428 from GNS3/bugfix/2427
Symbolic links support for project export/import
2024-10-19 15:54:41 +10:00
grossmj 24bfc205db Symbolic links support for project export/import 2024-10-19 15:49:23 +10:00
grossmj cb46c0fbcc Merge remote-tracking branch 'origin/2.2' into 2.2 2024-10-14 17:48:42 +10:00
grossmj 35256901b5 Add comment to indicate sentry-sdk is optional. Ref https://github.com/GNS3/gns3-server/issues/2423 2024-10-14 17:46:53 +10:00
Jeremy Grossmann 6933c3d938 Merge pull request #2420 from GNS3/bugfix/2419
Fix issues with recent busybox versions
2024-10-01 17:37:44 +07:00
grossmj 8af71ee291 Formatting 2024-10-01 17:35:11 +07:00
grossmj c0be6875c2 Fix issues with recent busybox versions
* `busybox --install` does not exist
* `sleep` does not take float values (e.g. 0.5).
2024-10-01 17:31:29 +07:00
Jeremy Grossmann a1922ef067 Merge pull request #2413 from z5241248/master
Duplicate faster
2024-09-29 19:44:49 +07:00
grossmj cafdb2522b Add / update docstrings 2024-09-29 19:42:06 +07:00
grossmj f7996d5e98 Fix tests 2024-09-27 20:05:06 +07:00
grossmj 996dad2f5c Support to reset MAC addresses for Docker nodes and some adjustments for fast duplication. 2024-09-26 18:41:23 +07:00
Jeremy Grossmann 1332e940fd Merge branch '2.2' into master 2024-09-26 16:26:56 +07:00
grossmj 19bd953d31 Update README.md to change the minimum required Python version. 2024-09-26 16:25:26 +07:00
赵昕彧 3a896b6964 Duplicate faster - 2 2024-09-26 08:26:08 +08:00
grossmj 441f0fb1b5 Merge remote-tracking branch 'z5241248/master' into fork/z5241248/master 2024-09-25 19:45:44 +07:00
grossmj a02b57698a Add missing imports 2024-09-25 19:45:14 +07:00
Jeremy Grossmann 7582107ae5 Merge branch '2.2' into master 2024-09-25 19:41:40 +07:00
赵昕彧 2dbde5df22 Copying project files directly, rather than copying them in an import-export fashion, can make copying projects many times faster 2024-09-25 20:27:46 +08:00
grossmj a7b56739a9 Fixes after merging 2024-09-23 14:08:24 +07:00
grossmj 8ce0cbf7f7 Merge branch '2.2' into 3.0
# Conflicts:
#	gns3server/compute/base_node.py
#	gns3server/compute/docker/docker_vm.py
#	gns3server/compute/dynamips/nodes/c1700.py
#	gns3server/compute/dynamips/nodes/c2600.py
#	gns3server/compute/dynamips/nodes/c2691.py
#	gns3server/compute/dynamips/nodes/c3600.py
#	gns3server/compute/dynamips/nodes/c3725.py
#	gns3server/compute/dynamips/nodes/c3745.py
#	gns3server/compute/dynamips/nodes/c7200.py
#	gns3server/compute/dynamips/nodes/router.py
#	gns3server/compute/qemu/qemu_vm.py
#	gns3server/controller/node.py
#	gns3server/controller/topology.py
#	gns3server/handlers/api/compute/docker_handler.py
#	gns3server/handlers/api/compute/dynamips_vm_handler.py
#	gns3server/handlers/api/compute/qemu_handler.py
#	gns3server/schemas/docker.py
#	gns3server/schemas/docker_template.py
#	gns3server/schemas/dynamips_template.py
#	gns3server/schemas/dynamips_vm.py
#	gns3server/schemas/node.py
#	gns3server/schemas/qemu.py
#	gns3server/schemas/qemu_template.py
2024-09-23 13:28:56 +07:00
grossmj 7b5d123ad8 Improve error message when a project cannot be parsed. 2024-09-23 13:23:03 +07:00
Jeremy Grossmann d1a7474ef6 Merge pull request #2418 from GNS3/revert-2417-backport-aux-console-support
Revert "Backport auxiliary console support for Qemu, Docker and Dynamips nodes"
2024-09-23 13:15:34 +07:00
Jeremy Grossmann af6f34b2ca Revert "Backport auxiliary console support for Qemu, Docker and Dynamips nodes" 2024-09-23 13:10:58 +07:00
grossmj d3138daa23 Fix Docker tests 2024-09-22 22:12:40 +07:00
grossmj 967c7d066d Delete old code after merging 2024-09-22 22:02:14 +07:00
grossmj 7619080a50 Merge branch '2.2' into 3.0
# Conflicts:
#	gns3server/compute/base_node.py
#	gns3server/compute/docker/docker_vm.py
#	gns3server/compute/dynamips/nodes/c1700.py
#	gns3server/compute/dynamips/nodes/c2600.py
#	gns3server/compute/dynamips/nodes/c2691.py
#	gns3server/compute/dynamips/nodes/c3600.py
#	gns3server/compute/dynamips/nodes/c3725.py
#	gns3server/compute/dynamips/nodes/c3745.py
#	gns3server/compute/dynamips/nodes/c7200.py
#	gns3server/compute/dynamips/nodes/router.py
#	gns3server/compute/qemu/qemu_vm.py
#	gns3server/controller/node.py
#	gns3server/handlers/api/compute/docker_handler.py
#	gns3server/handlers/api/compute/dynamips_vm_handler.py
#	gns3server/handlers/api/compute/qemu_handler.py
#	gns3server/schemas/docker.py
#	gns3server/schemas/docker_template.py
#	gns3server/schemas/dynamips_template.py
#	gns3server/schemas/dynamips_vm.py
#	gns3server/schemas/node.py
#	gns3server/schemas/qemu.py
#	gns3server/schemas/qemu_template.py
2024-09-22 22:01:06 +07:00
Jeremy Grossmann f1294cf267 Merge pull request #2417 from GNS3/backport-aux-console-support
Backport auxiliary console support for Qemu, Docker and Dynamips nodes
2024-09-22 21:44:31 +07:00
grossmj 74782d413f Change method to allocate AUX console for existing Dynamips nodes 2024-09-22 21:41:10 +07:00
grossmj c41c11eb34 Backport auxiliary console support for Qemu, Docker and Dynamips nodes 2024-09-22 18:29:04 +07:00
Jeremy Grossmann 1f09a3e6bc Merge pull request #2416 from GNS3/bugfix/2414
Run Docker containers with user namespaces enabled
2024-09-19 11:01:11 +07:00
grossmj 22f022cc22 Fix for running Docker containers with user namespaces enabled 2024-09-19 10:40:22 +07:00
grossmj 8429494280 Test base MAC address for Docker VMs 2024-09-19 10:19:07 +07:00
grossmj a1666dd247 Fix MAC address support for Docker containers 2024-09-18 18:02:35 +07:00
grossmj 3214f52e9e Merge branch '2.2' into 3.0
# Conflicts:
#	gns3server/compute/docker/docker_vm.py
#	gns3server/handlers/api/compute/docker_handler.py
#	gns3server/schemas/docker.py
#	gns3server/schemas/docker_template.py
#	tests/compute/docker/test_docker_vm.py
2024-09-18 17:29:06 +07:00
grossmj ddd6235acd Merge branch 'master' into 2.2 2024-09-18 17:14:21 +07:00
Jeremy Grossmann bcc148bbd2 Merge pull request #2415 from GNS3/docker-mac-address
Support for custom MAC addresses in Docker containers
2024-09-18 04:05:18 -06:00
grossmj 3792901dc7 Support for configuring MAC address in Docker containers 2024-09-18 16:30:22 +07:00
赵昕彧 5ffe5fd9b3 Copying project files directly, rather than copying them in an import-export fashion, can make copying projects many times faster 2024-08-23 14:31:21 +08:00
grossmj 9bcf26b943 Release v3.0.0rc1 2024-08-11 11:35:19 -06:00
grossmj b80e1f3a22 Downgrade aiohttp to v3.9.5 2024-08-11 11:22:20 -06:00
grossmj ba13b0b078 Bundle web-ui v3.0.0rc1 2024-08-11 11:09:27 -06:00
grossmj 90c69d95ad Merge branch '2.2' into 3.0
# Conflicts:
#	gns3server/crash_report.py
#	gns3server/static/web-ui/index.html
#	gns3server/static/web-ui/main.99a70a8d013fc974361c.js
#	gns3server/version.py
#	requirements.txt
2024-08-10 18:58:43 -06:00
grossmj 69a5b16bad Upgrade aiohttp to v3.10.3 2024-08-11 01:34:30 +02:00
grossmj 21a5c5d3f2 Development on 2.2.50.dev1 2024-08-06 20:33:54 +02:00
Jeremy Grossmann 225779bc11 Merge pull request #2409 from GNS3/2.2
Release v2.2.49
2024-08-06 20:32:41 +02:00
grossmj b1209155f5 Release v2.2.49 2024-08-06 12:55:15 +02:00
grossmj 7cebb9472a Bundle web-ui v2.2.49 2024-08-06 12:41:06 +02:00
grossmj 00c3b1abc1 Merge remote-tracking branch 'origin/master' into 2.2 2024-08-06 12:37:55 +02:00
grossmj b1c1c0520c Sync appliances 2024-08-06 12:34:07 +02:00
grossmj 2bb26075f0 Forbid -nic and -nicdev in Qemu additional options. Fixes https://github.com/GNS3/gns3-server/issues/2397 2024-08-05 17:51:46 +02:00
grossmj 54e436394f Upgrade packages in requirements.txt 2024-08-03 16:35:17 +02:00
grossmj 9046c60811 Fix tests by downgrading pytest-asyncio 2024-08-03 13:15:36 +02:00
grossmj 24cace8122 Merge remote-tracking branch 'origin/2.2' into 3.0
# Conflicts:
#	dev-requirements.txt
#	requirements.txt
#	setup.py
2024-08-03 12:58:19 +02:00
grossmj 6746ef39be Upgrade development packages 2024-08-03 12:32:43 +02:00
grossmj 8889eaa439 Upgrade jsonschema and sentry-sdk packages 2024-08-03 12:32:06 +02:00
grossmj 95a4c284bc Update IOU base configs to use "no ip domain lookup". Fixes #2404 2024-07-22 19:07:17 +02:00
Jeremy Grossmann 9a3bd2ee0c Merge pull request #2406 from GNS3/feature/convert-invalid-node-names
Convert node hostnames for topologies
2024-07-20 18:01:50 +02:00
grossmj 2416069a6e Update _convert_2.2.0() with correct comments 2024-07-20 17:55:38 +02:00
grossmj eefb3d87b2 Fix tests and add conversion test 2024-07-20 17:47:25 +02:00
grossmj 999f41b03e Convert topologies < 3.0 to have valid node hostnames 2024-07-20 17:22:24 +02:00
grossmj ea339af1e9 Merge branch '2.2' into 3.0
# Conflicts:
#	gns3server/crash_report.py
#	gns3server/static/web-ui/index.html
#	gns3server/static/web-ui/main.a1204c9aa64b1cc15d28.js
2024-07-13 17:19:03 +02:00
grossmj 6951137a25 Development on 2.2.49.dev1 2024-07-13 16:32:13 +02:00
Jeremy Grossmann cccbca3d5e Merge pull request #2401 from GNS3/release/v2.2.48.1
Release v2.2.48.1
2024-07-13 14:43:53 +02:00
grossmj 8659439829 Release v2.2.48.1 2024-07-12 18:26:16 +02:00
grossmj 677bc389a5 Bundle web-ui v2.2.48.1 2024-07-11 23:44:24 +02:00
grossmj 3f7f5a3cda Fix to access resources_path and install_builtin_appliances settings 2024-07-09 12:28:39 +02:00
grossmj 59ad5c55ec Merge branch '2.2' into 3.0
# Conflicts:
#	CHANGELOG
#	gns3server/config_samples/gns3_server.conf
#	gns3server/controller/__init__.py
#	gns3server/crash_report.py
#	gns3server/static/web-ui/index.html
#	gns3server/static/web-ui/main.b65e52314df938ebe652.js
#	gns3server/version.py
2024-07-09 12:14:44 +02:00
grossmj 4a58ede550 Development on 2.2.49.dev1 2024-07-09 00:32:44 +02:00
Jeremy Grossmann 3f5b0bb514 Merge pull request #2395 from GNS3/2.2
Release v2.2.48
2024-07-09 00:30:55 +02:00
grossmj 6e8e0764c1 Release v2.2.48 2024-07-08 18:44:09 +02:00
grossmj eaa18ad624 Bundle web-ui v2.2.48 2024-07-08 18:24:02 +02:00
grossmj 0a32be276e Sync appliances 2024-07-08 18:18:25 +02:00
Jeremy Grossmann 271c958381 Merge pull request #2394 from GNS3/bugfix/2226
New path settings for the server config
2024-07-08 18:16:27 +02:00
grossmj ca1d99b112 Add 'install_builtin_appliances' and 'resources_path' settings in the server config 2024-07-08 18:06:33 +02:00
grossmj 6b14abc06f Add allow_unsafe_options for Qemu settings 2024-07-07 19:08:12 +02:00
grossmj 6ed18c561f Merge branch '2.2' into 3.0
# Conflicts:
#	gns3server/compute/qemu/qemu_vm.py
#	gns3server/config_samples/gns3_server.conf
#	gns3server/controller/export_project.py
#	gns3server/controller/project.py
#	gns3server/controller/snapshot.py
#	gns3server/handlers/api/controller/project_handler.py
#	tests/controller/test_export_project.py
#	tests/controller/test_import_project.py
#	tests/controller/test_snapshot.py
2024-07-07 19:04:50 +02:00
Jeremy Grossmann 90dce03da2 Merge pull request #2392 from GNS3/bugfix/2385
Forbid unsafe Qemu additional options
2024-07-06 17:18:59 +02:00
Jeremy Grossmann b48bd92da3 Merge pull request #2393 from GNS3/feature/keep-compute-ids
Option to keep the compute IDs unchanged when exporting a project
2024-07-06 17:12:38 +02:00
grossmj d54c9db8c3 Option to keep the compute IDs unchanged when exporting a project 2024-07-06 17:08:16 +02:00
grossmj b194e48649 Forbid unsafe Qemu additional options 2024-07-06 12:24:22 +02:00
Jeremy Grossmann 29f848d833 Merge pull request #2391 from GNS3/bugfix/2388
Fix issues with invalid snapshot filenames
2024-07-05 12:49:59 +02:00
grossmj 08154e43aa Fix error when snapshot exists with an underscore in the name 2024-07-05 12:04:53 +02:00
grossmj 45a0644371 Upgrade request and sqlalchemy packages 2024-07-03 19:05:05 +02:00
grossmj 3a4ffb8786 Merge branch '2.2' into 3.0
# Conflicts:
#	gns3server/compute/qemu/qemu_vm.py
#	gns3server/utils/__init__.py
#	requirements.txt
2024-07-03 19:00:44 +02:00
grossmj 84efc55d02 Upgrade sentry-sdk, psutil and aiofiles packages 2024-07-03 18:53:14 +02:00
grossmj fec0220b55 Merge branch '2.2' into 3.0
# Conflicts:
#	gns3server/version.py
2024-07-01 18:53:21 +02:00
Jeremy Grossmann a58fb320ac Merge pull request #2387 from GNS3/bugfix/3588
Fix check to test if IPv6 is enabled on host
2024-06-17 16:54:20 +02:00
grossmj 39057bd781 Fix check for IPv6 enabled on host 2024-06-17 16:41:40 +02:00
grossmj 0f3b96f134 Development on 2.2.48.dev1 2024-05-23 12:19:15 +07:00
grossmj df210386dd Development on 3.0.0.dev14 2024-05-19 20:57:11 +07:00
grossmj 3e512e650a Release v3.0.0b3 2024-05-19 17:23:16 +07:00
grossmj e50e2c90bd Bundle web-ui v3.0.0b3 2024-05-19 17:16:52 +07:00
grossmj c1f9f1111d Sync appliances 2024-05-19 17:13:07 +07:00
grossmj 8c1dbf0084 Fix to allow duplicating IOS routers 2024-05-19 00:33:55 +07:00
grossmj 6f2b12c218 Fix to allow changing the auxiliary console for IOS router nodes. 2024-05-18 23:43:50 +07:00
grossmj 4b1068e02f Replace deprecated method datetime.utcnow() 2024-05-18 23:33:26 +07:00
grossmj d56acc5844 Upgrade FastAPI to v0.111.0 2024-05-18 23:31:22 +07:00
grossmj d477eb8366 Fix reset console for non running IOU devices 2024-05-18 23:30:58 +07:00
Jeremy Grossmann 35f94b0c73 Merge pull request #2382 from GNS3/update-ga-workflows
Update GitHub Action workflows
2024-05-17 12:22:43 +07:00
grossmj b82b9a64e6 Rename codeql.yml back to codeql-analysis.yml 2024-05-17 12:19:38 +07:00
grossmj 901652aaeb Update GitHub Action workflows 2024-05-17 12:14:47 +07:00
grossmj 990dabb7e4 Do not allow to create a builtin template using the API. 2024-05-17 00:05:25 +07:00
grossmj 3ab74b8094 Development on 3.0.0.dev13 2024-05-16 19:18:53 +07:00
grossmj 5cd540d94d Remove old files 2024-05-16 17:57:51 +07:00
grossmj d3860ba84b Merge branch '2.2' into 3.0
# Conflicts:
#	CHANGELOG
#	dev-requirements.txt
#	gns3server/compute/qemu/__init__.py
#	gns3server/compute/vmware/__init__.py
#	gns3server/controller/snapshot.py
#	gns3server/crash_report.py
#	gns3server/handlers/api/compute/atm_switch_handler.py
#	gns3server/run.py
#	gns3server/static/web-ui/26.77d4bfd104f37c42e028.js
#	gns3server/static/web-ui/index.html
#	gns3server/static/web-ui/runtime.415291667f70565cd8ef.js
#	gns3server/utils/__init__.py
#	gns3server/utils/images.py
#	gns3server/utils/interfaces.py
#	gns3server/version.py
#	gns3server/web/web_server.py
#	pytest.ini
#	requirements.txt
#	scripts/update-bundled-web-ui.sh
#	setup.py
#	tests/api/routes/compute/test_dynamips_nodes.py
#	tests/compute/builtin/nodes/test_cloud.py
#	tests/compute/docker/test_docker.py
#	tests/compute/docker/test_docker_vm.py
#	tests/compute/dynamips/test_dynamips_manager.py
#	tests/compute/dynamips/test_dynamips_router.py
#	tests/compute/iou/test_iou_vm.py
#	tests/compute/qemu/test_qcow2.py
#	tests/compute/qemu/test_qemu_manager.py
#	tests/compute/qemu/test_qemu_vm.py
#	tests/compute/test_base_node.py
#	tests/compute/test_manager.py
#	tests/compute/test_project.py
#	tests/compute/traceng/test_traceng_vm.py
#	tests/compute/virtualbox/test_virtualbox_manager.py
#	tests/compute/virtualbox/test_virtualbox_vm.py
#	tests/compute/vmware/test_vmware_manager.py
#	tests/compute/vmware/test_vmware_vm.py
#	tests/compute/vpcs/test_vpcs_vm.py
#	tests/conftest.py
#	tests/controller/gns3vm/test_remote_gns3_vm.py
#	tests/controller/gns3vm/test_virtualbox_gns3_vm.py
#	tests/controller/gns3vm/test_vmware_gns3_vm.py
#	tests/controller/test_export_project.py
#	tests/controller/test_gns3vm.py
#	tests/controller/test_import_project.py
#	tests/test_config.py
#	tests/utils/test_asyncio.py
#	tests/utils/test_images.py
#	tests/web/test_response.py
2024-05-16 17:53:39 +07:00
grossmj 3e133eda44 Bundle web-ui v3.0.0b3 2024-05-16 17:30:12 +07:00
grossmj e01256980c Sync appliances 2024-05-16 17:27:38 +07:00
grossmj aabfe9eadc Use cryptography backend for python-jose. Ref #2372 2024-05-16 15:01:05 +07:00
Jeremy Grossmann 6c9a3b634b Merge pull request #2381 from GNS3/release/v2.2.47
Release v2.2.47
2024-05-15 17:06:53 +07:00
grossmj 0561aba927 Release v2.2.47 2024-05-15 12:14:48 +07:00
grossmj 86a78f53cb Fix update-bundled-web-ui.sh script 2024-05-15 12:05:43 +07:00
grossmj f0bc74ff6e Bundle web-ui v2.2.47 2024-05-15 12:04:34 +07:00
grossmj f81128f717 Bundle web-ui v2.2.47 2024-05-15 11:55:47 +07:00
grossmj 9ce505cad3 Sync appliances 2024-05-15 11:43:04 +07:00
grossmj 314e01d2b4 Ensure Python >= 3.8 is used in pyproject.toml 2024-05-12 16:44:09 +07:00
Jeremy Grossmann 6b8635f7d5 Merge pull request #2380 from GNS3/drop-python3.7
Drop Python 3.7
2024-05-09 19:10:04 +07:00
grossmj 388ffe9f00 Change sentry-sdk version 2024-05-09 19:03:08 +07:00
grossmj d01129a3cf Upgrade aiohttp, sentry-sdk and truststore 2024-05-09 18:58:37 +07:00
grossmj 535ea0ad9f Upgrade jsonschema and aiohttp 2024-05-09 18:37:40 +07:00
grossmj ccb5de6df1 Drop Python 3.7 2024-05-09 18:23:58 +07:00
Jeremy Grossmann cdcfc652db Merge pull request #2379 from GNS3/fix-warnings-in-tests
Fix warnings in tests
2024-05-09 18:13:13 +07:00
grossmj 7030dadbcb Remove dev requirements for Python 3.6 2024-05-09 18:04:19 +07:00
grossmj 46a9fdb61d Remove event_loop 2024-05-09 17:53:02 +07:00
grossmj 9958b876cf Do not run Docker VM tests on Windows 2024-05-09 17:36:58 +07:00
grossmj 259d3a0155 Fix cannot import UTC 2024-05-09 17:23:32 +07:00
grossmj 33499be425 Fix warnings in tests 2024-05-09 17:11:12 +07:00
grossmj 3fd44f5260 Do not wait for the server to close when shutting down. 2024-05-09 16:37:45 +07:00
grossmj c076275bd0 Fix test create image with not supported characters by filesystem. Fixes #2375 2024-05-09 16:01:55 +07:00
grossmj 081447ba2e Fix tests. Ref #2376 2024-05-09 15:37:42 +07:00
grossmj 3df7af12e1 Allow listing x86_64 IOU images. Fixes #2376 2024-05-09 15:21:05 +07:00
grossmj d9e4ce5639 Upgrade Jinja2 to version 3.1.4. Fixes #2378 2024-05-08 18:08:00 +07:00
grossmj 689d476b71 Fix tests 2024-04-28 18:03:06 +07:00
grossmj f1701e3f09 Upgrade fastapi and platformdirs 2024-04-27 23:21:58 +07:00
grossmj 38df4bea2e Do not return an error if an image has already been uploaded 2024-04-26 19:02:50 +07:00
grossmj 35b75f0f7f Fix link capture for ATM switch. Fixes https://github.com/GNS3/gns3-gui/issues/3570 2024-04-23 18:35:36 +07:00
grossmj 2609849507 Fix tests after updating error message when busybox is not installed. 2024-04-23 18:00:37 +07:00
grossmj 448b94f701 Add more details to error message when busybox is not installed. Fixes https://github.com/GNS3/gns3-gui/issues/3569 2024-04-23 17:54:06 +07:00
grossmj 18002a7580 Fix invalid escape sequences 2024-04-23 16:52:28 +07:00
grossmj 644e659729 Use NAT symbol for builtin NAT template 2024-04-22 19:11:58 +07:00
grossmj 1c37e8bd32 Merge branch '2.2' into 3.0
# Conflicts:
#	gns3server/controller/symbol_themes.py
#	gns3server/controller/template_manager.py
2024-04-22 19:08:45 +07:00
Jeremy Grossmann 1414bdcadf Merge pull request #2369 from GNS3/feature/nat-symbols
NAT symbols
2024-04-22 19:00:19 +07:00
grossmj b6e68ba1a8 Add NAT symbols 2024-04-22 18:51:29 +07:00
Jeremy Grossmann 19142d97bb Merge pull request #2366 from GNS3/bugfix/block-iou-call
Block IOU phone home call using IPtable
2024-04-20 15:53:39 +07:00
grossmj faf7e09ebb Only use iptable to block xml.cisco.com on Ubuntu Focal. 2024-04-20 15:45:28 +07:00
grossmj 4959a51ce7 Block IOU phone home call using IPtable 2024-04-06 13:04:20 +07:00
Jeremy Grossmann 5bab4131e1 Merge pull request #2361 from GNS3/release/v2.2.46
Release v2.2.46
2024-02-26 17:51:46 +08:00
177 changed files with 6552 additions and 1389 deletions

No files matched your search

@@ -10,7 +10,7 @@ jobs:
name: Add issue to project
runs-on: ubuntu-latest
steps:
- uses: actions/add-to-project@v0.4.0
- uses: actions/add-to-project@v1.0.1
with:
project-url: https://github.com/orgs/GNS3/projects/3
github-token: ${{ secrets.ADD_NEW_ISSUES_TO_PROJECT }}
+51 -28
View File
@@ -13,58 +13,81 @@ name: "CodeQL"
on:
push:
branches: [ master ]
branches: [ "master" ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ master ]
branches: [ "master" ]
schedule:
- cron: '44 1 * * 3'
- cron: '21 12 * * 4'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
name: Analyze (${{ matrix.language }})
# Runner size impacts CodeQL analysis time. To learn more, please see:
# - https://gh.io/recommended-hardware-resources-for-running-codeql
# - https://gh.io/supported-runners-and-hardware-resources
# - https://gh.io/using-larger-runners (GitHub.com only)
# Consider using larger runners or machines with greater resources for possible analysis time improvements.
runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }}
permissions:
# required for all workflows
security-events: write
# required to fetch internal or private CodeQL packs
packages: read
# only required for workflows in private repositories
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'python' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://git.io/codeql-language-support
include:
- language: python
build-mode: none
# CodeQL supports the following values keywords for 'language': 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift'
# Use `c-cpp` to analyze code written in C, C++ or both
# Use 'java-kotlin' to analyze code written in Java, Kotlin or both
# Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both
# To learn more about changing the languages that are analyzed or customizing the build mode for your analysis,
# see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning.
# If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how
# your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
steps:
- name: Checkout repository
uses: actions/checkout@v2
uses: actions/checkout@v4
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
build-mode: ${{ matrix.build-mode }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality
# If the analyze step fails for one of the languages you are analyzing with
# "We were unable to automatically build your code", modify the matrix above
# to set the build mode to "manual" for that language. Then modify this step
# to build your code.
# ℹ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
- if: matrix.build-mode == 'manual'
shell: bash
run: |
echo 'If you are using a "manual" build mode for one or more of the' \
'languages you are analyzing, replace this with the commands to build' \
'your code, for example:'
echo ' make bootstrap'
echo ' make release'
exit 1
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
uses: github/codeql-action/analyze@v3
with:
category: "/language:${{matrix.language}}"
@@ -12,11 +12,11 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
fetch-depth: 0
ref: "gh-pages"
- uses: actions/setup-python@v3
- uses: actions/setup-python@v5
with:
python-version: 3.8
- name: Merge changes from 3.0 branch
+17 -4
View File
@@ -13,16 +13,21 @@ on:
jobs:
build:
runs-on: ubuntu-latest
runs-on: ${{ matrix.os }}
strategy:
matrix:
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
os: ["ubuntu-latest"]
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
#include:
# only test with Python 3.10 on Windows
# - os: windows-latest
# python-version: "3.10"
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v3
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Display Python version
@@ -31,6 +36,14 @@ jobs:
run: |
python -m pip install --upgrade pip
python -m pip install .[dev]
- name: Install Windows specific dependencies
if: runner.os == 'Windows'
run: |
python -m pip install -r win-requirements.txt
curl -O "http://www.win10pcap.org/download/Win10Pcap-v10.2-5002.msi"
msiexec /i "Win10Pcap-v10.2-5002.msi" /qn /norestart
- name: Lint with flake8
run: |
# stop the build if there are Python syntax errors or undefined names
+136
View File
@@ -1,5 +1,141 @@
# Change Log
## 3.0.2 03/01/2025
* Bundle web-ui v3.0.2
* Support to create templates based on image checksums.
* Improvements for installing built-in disks.
* Use watchdog instead of watchfiles to monitor for new images on the file system
* Drop Python 3.8
* Replace python-jose library by joserfc
* Upgrade dependencies
* Remove blocking IOU phone home call.
## 3.0.1 27/12/2024
* Bundle web-ui v3.0.1
* Allow for upgrading built-in disks
* Fix config parsing when configuring server protocol. Fixes https://github.com/GNS3/gns3-gui/issues/3681
* Update empty Qemu disks with correct MD5 checksums
* Increase timeout to run compute HTTP queries. Fixes #3453
## 3.0.0 20/12/2024
* Bundle web-ui v3.0.0
* Use static favicon for API docs. Ref #3674
* Configure self-hosting JavaScript and CSS for docs
* Fix project auto open feature. Fixes #2455
* Store IOU licence in the secrets directory and disable the check by default
* Require "Project.Audit" permission to duplicate a project and check if "Project.Allocate" permission for the destination.
## 2.2.52 02/12/2024
* Bundle web-ui v2.2.52
* Sync appliances
* Remove restrictions based on file extension when listing images and fix ELF header checks
* Fix use project name instead of ID for fast duplication when running local server. Fixes #2446
* Overwrite user resources when the originals have changed.
* Relax setuptools requirement to allow for easier Debian packaging on Ubuntu Focal & Jammy
## 3.0.0rc2 20/11/2024
* Bundle web-ui v3.0.0rc2
* Fix error 500 on PUT for cloud, nat, vmware and vpcs nodes. Fixes #2426
* Add a duplicated project in the same resource pools as the original project if it is in any
* Upgrade FastAPI to v0.115.5
* Overwrite user resources when the originals have changed.
* Relax setuptools requirement to allow for easier Debian packaging on Ubuntu Focal & Jammy
* Increase SQLite timeout. Ref #2422
* Fix test user with wrong creds
* Upgrade dependencies and fix Pydantic warnings
* Upgrade aiohttp to v3.10.10. Fixes #2411
* Replace aiohttp.web.HTTPConflict()
* Python 3.13 support
## 2.2.51 07/11/2024
* Catch error when cannot resize Docker container TTY.
* Do not use "ide" if there is a disk image and no interface type has been explicitly configured.
* Use @locking when sending uBridge commands. Ref https://github.com/GNS3/gns3-gui/issues/3651
* Fix run Docker containers with user namespaces enabled. Fixes #2414
* Python 3.13 support
* Upgrade dependencies
* Fix errors in init.sh. Fixes #2431
## 2.2.50 21/10/2024
* Bundle web-ui v2.2.50
* Symbolic links support for project export/import
* Add comment to indicate sentry-sdk is optional. Ref https://github.com/GNS3/gns3-server/issues/2423
* Fix issues with recent busybox versions
* Support to reset MAC addresses for Docker nodes and some adjustments for fast duplication.
* Update README.md to change the minimum required Python version.
* Faster project duplication for local projects (no remote compute)
* Improve error message when a project cannot be parsed.
* Fix for running Docker containers with user namespaces enabled
* Support for configuring MAC address in Docker containers
* Upgrade aiohttp to v3.10.3
## 3.0.0rc1 11/08/2024
* Bundle web-ui v3.0.0rc1
* Convert topologies < 3.0 to have valid node hostnames
* Fix to access resources_path and install_builtin_appliances settings
## 2.2.49 06/08/2024
* Bundle web-ui v2.2.49
* Forbid -nic and -nicdev in Qemu additional options. Fixes https://github.com/GNS3/gns3-server/issues/2397
* Upgrade jsonschema and sentry-sdk packages
* Update IOU base configs to use "no ip domain lookup". Fixes #2404
## 2.2.48.1 12/07/2024
* Bundle web-ui v2.2.48.1
## 2.2.48 08/07/2024
* Bundle web-ui v2.2.48
* Add 'install_builtin_appliances' and 'resources_path' settings in the server config
* Option to keep the compute IDs unchanged when exporting a project
* Forbid unsafe Qemu additional options
* Fix error when snapshot exists with an underscore in the name
* Upgrade sentry-sdk, psutil and aiofiles packages
* Fix check for IPv6 enabled on host
## 3.0.0b3 19/05/2024
* Bundle web-ui v3.0.0b3
* Fix to allow duplicating IOS routers
* Fix to allow changing the auxiliary console for IOS router nodes.
* Replace deprecated method datetime.utcnow()
* Upgrade FastAPI to v0.111.0
* Fix reset console for non running IOU devices
* Do not allow to create a builtin template using the API.
* Use cryptography backend for python-jose. Ref #2372
## 2.2.47 15/05/2024
* Fix update-bundled-web-ui.sh script
* Bundle web-ui v2.2.47
* Change sentry-sdk version
* Upgrade aiohttp, sentry-sdk and truststore
* Upgrade jsonschema and aiohttp
* Drop Python 3.7
* Remove dev requirements for Python 3.6
* Do not run Docker VM tests on Windows
* Do not wait for the server to close when shutting down.
* Fix test create image with not supported characters by filesystem. Fixes #2375
* Allow listing x86_64 IOU images. Fixes #2376
* Upgrade Jinja2 to version 3.1.4. Fixes #2378
* Fix link capture for ATM switch. Fixes https://github.com/GNS3/gns3-gui/issues/3570
* Fix tests after updating error message when busybox is not installed.
* Add more details to error message when busybox is not installed. Fixes https://github.com/GNS3/gns3-gui/issues/3569
* Fix invalid escape sequences
* Add NAT symbols
* Fix cannot stop Docker VM while console connection is still active.
* Upgrade sentry-sdk to version 1.40.6
## 3.0.0b2 07/04/2024
* Bundle web-ui v3.0.0b2
+6 -6
View File
@@ -1,7 +1,7 @@
pytest==8.1.1
flake8==7.0.0
pytest==8.3.3
flake8==7.1.1
pytest-timeout==2.3.1
pytest-asyncio==0.21.1
requests==2.31.0
httpx==0.24.1 # version 0.24.1 is required by httpx_ws
httpx_ws==0.4.2
pytest-asyncio==0.21.2
requests==2.32.3
httpx==0.27.2 # version 0.24.1 is required by httpx_ws
httpx_ws==0.6.2
+1 -1
View File
@@ -85,7 +85,7 @@ def get_cloud(node: Cloud = Depends(dep_node)) -> schemas.Cloud:
@router.put("/{node_id}", response_model=schemas.Cloud)
def update_cloud(node_data: schemas.CloudUpdate, node: Cloud = Depends(dep_node)) -> schemas.Cloud:
async def update_cloud(node_data: schemas.CloudUpdate, node: Cloud = Depends(dep_node)) -> schemas.Cloud:
"""
Update a cloud node.
"""
@@ -69,6 +69,7 @@ async def create_docker_node(project_id: UUID, node_data: schemas.DockerCreate)
start_command=node_data.get("start_command"),
environment=node_data.get("environment"),
adapters=node_data.get("adapters"),
mac_address=node_data.get("mac_address"),
console=node_data.get("console"),
console_type=node_data.get("console_type"),
console_resolution=node_data.get("console_resolution", "1024x768"),
@@ -124,6 +125,8 @@ async def update_docker_node(node_data: schemas.DockerUpdate, node: DockerVM = D
"start_command",
"environment",
"adapters",
"mac_address",
"custom_adapters",
"extra_hosts",
"extra_volumes",
"memory",
@@ -20,7 +20,7 @@ API routes for Dynamips nodes.
import os
from fastapi import APIRouter, WebSocket, Depends, status
from fastapi import APIRouter, WebSocket, Body, Depends, status
from fastapi.encoders import jsonable_encoder
from fastapi.responses import StreamingResponse
from typing import List, Union
@@ -334,7 +334,7 @@ async def get_auto_idlepc(node: Router = Depends(dep_node)) -> dict:
status_code=status.HTTP_201_CREATED,
dependencies=[Depends(compute_authentication)]
)
async def duplicate_router(destination_node_id: UUID, node: Router = Depends(dep_node)) -> schemas.Dynamips:
async def duplicate_router(destination_node_id: UUID = Body(..., embed=True), node: Router = Depends(dep_node)) -> schemas.Dynamips:
"""
Duplicate a router.
"""
+1 -1
View File
@@ -80,7 +80,7 @@ def get_nat_node(node: Nat = Depends(dep_node)) -> schemas.NAT:
@router.put("/{node_id}", response_model=schemas.NAT)
def update_nat_node(node_data: schemas.NATUpdate, node: Nat = Depends(dep_node)) -> schemas.NAT:
async def update_nat_node(node_data: schemas.NATUpdate, node: Nat = Depends(dep_node)) -> schemas.NAT:
"""
Update a NAT node.
"""
@@ -97,7 +97,7 @@ def get_vmware_node(node: VMwareVM = Depends(dep_node)) -> schemas.VMware:
response_model=schemas.VMware,
dependencies=[Depends(compute_authentication)]
)
def update_vmware_node(node_data: schemas.VMwareUpdate, node: VMwareVM = Depends(dep_node)) -> schemas.VMware:
async def update_vmware_node(node_data: schemas.VMwareUpdate, node: VMwareVM = Depends(dep_node)) -> schemas.VMware:
"""
Update a VMware node.
"""
+10 -4
View File
@@ -91,15 +91,21 @@ def get_vpcs_node(node: VPCSVM = Depends(dep_node)) -> schemas.VPCS:
response_model=schemas.VPCS,
dependencies=[Depends(compute_authentication)]
)
def update_vpcs_node(node_data: schemas.VPCSUpdate, node: VPCSVM = Depends(dep_node)) -> schemas.VPCS:
async def update_vpcs_node(node_data: schemas.VPCSUpdate, node: VPCSVM = Depends(dep_node)) -> schemas.VPCS:
"""
Update a VPCS node.
"""
node_data = jsonable_encoder(node_data, exclude_unset=True)
node.name = node_data.get("name", node.name)
node.console = node_data.get("console", node.console)
node.console_type = node_data.get("console_type", node.console_type)
name = node_data.get("name", node.name)
if node.name != name:
node.name = name
console = node_data.get("console", node.console)
if node.console != console:
node.console = console
console_type = node_data.get("console_type", node.console_type)
if node.console_type != console_type:
node.console_type = console_type
node.updated()
return node.asdict()
+62 -23
View File
@@ -27,11 +27,11 @@ from fastapi.encoders import jsonable_encoder
from starlette.requests import ClientDisconnect
from sqlalchemy.orm.exc import MultipleResultsFound
from typing import List, Optional
from gns3server import schemas
from gns3server import schemas
from gns3server.config import Config
from gns3server.compute.qemu import Qemu
from gns3server.utils.images import InvalidImageError, write_image, read_image_info, default_images_directory
from gns3server.utils.images import InvalidImageError, write_image, read_image_info, default_images_directory, get_builtin_disks
from gns3server.db.repositories.images import ImagesRepository
from gns3server.db.repositories.templates import TemplatesRepository
from gns3server.db.repositories.rbac import RbacRepository
@@ -51,7 +51,6 @@ log = logging.getLogger(__name__)
router = APIRouter()
@router.post(
"/qemu/{image_path:path}",
response_model=schemas.Image,
@@ -149,8 +148,10 @@ async def upload_image(
if os.path.commonprefix([base_images_directory, full_path]) != base_images_directory:
raise ControllerForbiddenError(f"Cannot write image, '{image_path}' is forbidden")
if await images_repo.get_image(image_path):
raise ControllerBadRequestError(f"Image '{image_path}' already exists")
image = await images_repo.get_image(image_path)
if image:
log.warning(f"Image '{image_path}' already exists")
return image
try:
allow_raw_image = Config.instance().settings.Server.allow_raw_images
@@ -173,6 +174,61 @@ async def upload_image(
return image
@router.delete(
"/prune",
status_code=status.HTTP_204_NO_CONTENT,
dependencies=[Depends(has_privilege("Image.Allocate"))]
)
async def prune_images(
images_repo: ImagesRepository = Depends(get_repository(ImagesRepository)),
) -> None:
"""
Prune images not attached to any template.
Required privilege: Image.Allocate
"""
skip_images = get_builtin_disks()
await images_repo.prune_images(skip_images)
@router.post(
"/install",
status_code=status.HTTP_204_NO_CONTENT,
dependencies=[Depends(has_privilege("Image.Allocate"))]
)
async def install_images(
images_repo: ImagesRepository = Depends(get_repository(ImagesRepository)),
templates_repo: TemplatesRepository = Depends(get_repository(TemplatesRepository))
) -> None:
"""
Attempt to automatically create templates based on image checksums.
Required privilege: Image.Allocate
"""
skip_images = get_builtin_disks()
images = await images_repo.get_images()
for image in images:
if skip_images and image.filename in skip_images:
log.debug(f"Skipping image '{image.path}' for image installation")
continue
templates = await images_repo.get_image_templates(image.image_id)
if templates:
# the image is already used by a template
log.warning(f"Image '{image.path}' is used by one or more templates")
continue
await Controller.instance().appliance_manager.install_appliances_from_image(
image.path,
image.checksum,
images_repo,
templates_repo,
None,
None,
os.path.dirname(image.path)
)
@router.get(
"/{image_path:path}",
response_model=schemas.Image,
@@ -216,7 +272,7 @@ async def delete_image(
image = await images_repo.get_image(image_path)
except MultipleResultsFound:
raise ControllerBadRequestError(f"Image '{image_path}' matches multiple images. "
f"Please include the relative path of the image")
f"Please include the absolute path of the image")
if not image:
raise ControllerNotFoundError(f"Image '{image_path}' not found")
@@ -234,20 +290,3 @@ async def delete_image(
success = await images_repo.delete_image(image_path)
if not success:
raise ControllerError(f"Image '{image_path}' could not be deleted")
@router.post(
"/prune",
status_code=status.HTTP_204_NO_CONTENT,
dependencies=[Depends(has_privilege("Image.Allocate"))]
)
async def prune_images(
images_repo: ImagesRepository = Depends(get_repository(ImagesRepository)),
) -> None:
"""
Prune images not attached to any template.
Required privilege: Image.Allocate
"""
await images_repo.prune_images()
+31 -3
View File
@@ -320,6 +320,7 @@ async def export_project(
include_snapshots: bool = False,
include_images: bool = False,
reset_mac_addresses: bool = False,
keep_compute_ids: bool = False,
compression: schemas.ProjectCompression = "zstd",
compression_level: int = None,
) -> StreamingResponse:
@@ -366,6 +367,7 @@ async def export_project(
tmpdir,
include_snapshots=include_snapshots,
include_images=include_images,
keep_compute_ids=keep_compute_ids,
reset_mac_addresses=reset_mac_addresses,
)
async for chunk in zstream:
@@ -424,22 +426,48 @@ async def import_project(
status_code=status.HTTP_201_CREATED,
response_model=schemas.Project,
responses={**responses, 409: {"model": schemas.ErrorMessage, "description": "Could not duplicate project"}},
dependencies=[Depends(has_privilege("Project.Allocate"))]
dependencies=[Depends(has_privilege("Project.Audit"))]
)
async def duplicate_project(
project_data: schemas.ProjectDuplicate,
project: Project = Depends(dep_project)
project: Project = Depends(dep_project),
current_user: schemas.User = Depends(get_current_active_user),
rbac_repo: RbacRepository = Depends(get_repository(RbacRepository)),
pools_repo: ResourcePoolsRepository = Depends(get_repository(ResourcePoolsRepository))
) -> schemas.Project:
"""
Duplicate a project.
Required privilege: Project.Allocate
Required privilege: Project.Audit
"""
pool_memberships = await pools_repo.get_resource_memberships(project.id)
# check if the project can be duplicated somewhere (either in a pool or in the root)
if not current_user.is_superadmin:
can_be_duplicated_somewhere = False
if pool_memberships:
for pool in pool_memberships:
if await rbac_repo.check_user_has_privilege(current_user.user_id, f"/pools/{pool.resource_pool_id}", "Project.Allocate"):
can_be_duplicated_somewhere = True
break
if not can_be_duplicated_somewhere and not await rbac_repo.check_user_has_privilege(current_user.user_id, "/projects", "Project.Allocate"):
log.warning(f"Project {project.name} cannot be duplicated anywhere")
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN)
reset_mac_addresses = project_data.reset_mac_addresses
new_project = await project.duplicate(
name=project_data.name, reset_mac_addresses=reset_mac_addresses
)
# Add the new project in the same resource pools if the duplicated project belongs to any
if pool_memberships:
resource_create = schemas.ResourceCreate(resource_id=new_project.id, resource_type="project", name=new_project.name)
resource = await pools_repo.create_resource(resource_create)
for pool in pool_memberships:
await pools_repo.add_resource_to_pool(pool.resource_pool_id, resource)
return new_project.asdict()
+23 -2
View File
@@ -18,6 +18,7 @@
API routes for templates.
"""
import os
import hashlib
import json
@@ -34,6 +35,8 @@ from gns3server.db.repositories.templates import TemplatesRepository
from gns3server.services.templates import TemplatesService
from gns3server.db.repositories.rbac import RbacRepository
from gns3server.db.repositories.images import ImagesRepository
from gns3server.controller.controller_error import ControllerError
from gns3server.utils.images import get_builtin_disks
from .dependencies.authentication import get_current_active_user
from .dependencies.rbac import has_privilege
@@ -132,10 +135,28 @@ async def delete_template(
Required privilege: Template.Allocate
"""
images = await templates_repo.get_template_images(template_id)
await TemplatesService(templates_repo).delete_template(template_id)
await rbac_repo.delete_all_ace_starting_with_path(f"/templates/{template_id}")
if prune_images:
await images_repo.prune_images()
if prune_images and images:
skip_images = get_builtin_disks()
for image in images:
if image.filename in skip_images:
continue
templates = await images_repo.get_image_templates(image.image_id)
if templates:
template_names = ", ".join([template.name for template in templates])
raise ControllerError(f"Image '{image.path}' is used by one or more templates: {template_names}")
try:
os.remove(image.path)
except OSError:
log.warning(f"Could not delete image file {image.path}")
print(f"Deleting image '{image.path}'")
success = await images_repo.delete_image(image.path)
if not success:
raise ControllerError(f"Image '{image.path}' could not removed from the database")
@router.get(
+2 -2
View File
@@ -54,7 +54,7 @@ async def login(
) -> schemas.Token:
"""
Default user login method using forms (x-www-form-urlencoded).
Example: curl http://host:port/v3/users/login -H "Content-Type: application/x-www-form-urlencoded" -d "username=admin&password=admin"
Example: curl -X POST http://host:port/v3/access/users/login -H "Content-Type: application/x-www-form-urlencoded" -d "username=admin&password=admin"
"""
user = await users_repo.authenticate_user(username=form_data.username, password=form_data.password)
@@ -76,7 +76,7 @@ async def authenticate(
) -> schemas.Token:
"""
Alternative authentication method using json.
Example: curl http://host:port/v3/users/authenticate -d '{"username": "admin", "password": "admin"}' -H "Content-Type: application/json"
Example: curl -X POST http://host:port/v3/access/users/authenticate -d '{"username": "admin", "password": "admin"}' -H "Content-Type: application/json"
"""
user = await users_repo.authenticate_user(username=user_credentials.username, password=user_credentials.password)
+3 -3
View File
@@ -27,20 +27,20 @@ router = APIRouter()
templates = Jinja2Templates(directory=os.path.join("gns3server", "templates"))
@router.get("/")
@router.get("/", include_in_schema=False)
async def root():
return RedirectResponse("/static/web-ui/bundled", status_code=308) # permanent redirect
@router.get("/debug", response_class=HTMLResponse, deprecated=True)
@router.get("/debug", response_class=HTMLResponse, deprecated=True, include_in_schema=False)
def debug(request: Request):
kwargs = {"request": request, "gns3_version": __version__, "gns3_host": request.client.host}
return templates.TemplateResponse("index.html", kwargs)
@router.get("/static/web-ui/{file_path:path}", description="Web user interface")
@router.get("/static/web-ui/{file_path:path}", description="Web user interface", include_in_schema=False)
async def web_ui(file_path: str):
file_path = os.path.normpath(file_path).strip("/")
+38 -3
View File
@@ -19,15 +19,20 @@
FastAPI app
"""
import time
from fastapi import FastAPI, Request, HTTPException, status
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
from fastapi.exceptions import RequestValidationError
from fastapi.staticfiles import StaticFiles
from sqlalchemy.exc import SQLAlchemyError
from uvicorn.main import Server as UvicornServer
from fastapi.openapi.docs import (
get_redoc_html,
get_swagger_ui_html,
get_swagger_ui_oauth2_redirect_html,
)
from gns3server.controller.controller_error import (
ControllerError,
ControllerNotFoundError,
@@ -51,7 +56,11 @@ log = logging.getLogger(__name__)
def get_application() -> FastAPI:
application = FastAPI(
title="GNS3 controller API", description="This page describes the public controller API for GNS3", version="v3"
title="GNS3 controller API",
description="This page describes the public controller API for GNS3",
version="v3",
docs_url=None,
redoc_url=None
)
application.add_middleware(
@@ -66,6 +75,7 @@ def get_application() -> FastAPI:
application.add_event_handler("shutdown", tasks.create_shutdown_handler(application))
application.include_router(index.router, tags=["Index"])
application.include_router(controller.router, prefix="/v3")
application.mount("/static", StaticFiles(packages=[('gns3server', 'static')]), name="static")
application.mount("/v3/compute", compute_api, name="compute")
return application
@@ -85,6 +95,31 @@ def handle_exit(*args, **kwargs):
UvicornServer.handle_exit = handle_exit
# Configure self-hosting JavaScript and CSS for docs
@app.get("/docs", include_in_schema=False)
async def custom_swagger_ui_html():
return get_swagger_ui_html(
openapi_url=app.openapi_url,
title=app.title + " - Swagger UI",
oauth2_redirect_url=app.swagger_ui_oauth2_redirect_url,
swagger_js_url="/static/swagger-ui-bundle.js",
swagger_css_url="/static/swagger-ui.css",
swagger_favicon_url="/static/favicon.ico"
)
@app.get(app.swagger_ui_oauth2_redirect_url, include_in_schema=False)
async def swagger_ui_redirect():
return get_swagger_ui_oauth2_redirect_html()
@app.get("/redoc", include_in_schema=False)
async def redoc_html():
return get_redoc_html(
openapi_url=app.openapi_url,
title=app.title + " - ReDoc",
redoc_js_url="/static/redoc.standalone.js",
redoc_favicon_url="/static/favicon.ico"
)
@app.exception_handler(ControllerError)
async def controller_error_handler(request: Request, exc: ControllerError):
+6 -6
View File
@@ -30,24 +30,24 @@
"version": "9.2",
"md5sum": "c5bc76e8c95ac9f810a3482c80a54cc7",
"filesize": 563347456,
"download_url": "https://repo.almalinux.org/almalinux/9/cloud/x86_64/images/",
"direct_download_url": "https://repo.almalinux.org/almalinux/9/cloud/x86_64/images/AlmaLinux-9-GenericCloud-9.2-20230513.x86_64.qcow2"
"download_url": "https://vault.almalinux.org/9.2/cloud/x86_64/images/",
"direct_download_url": "https://vault.almalinux.org/9.2/cloud/x86_64/images/AlmaLinux-9-GenericCloud-9.2-20230513.x86_64.qcow2"
},
{
"filename": "AlmaLinux-8-GenericCloud-8.8-20230524.x86_64.qcow2",
"version": "8.8",
"md5sum": "3958c5fc25770ef63cf97aa5d93f0a0b",
"filesize": 565444608,
"download_url": "https://repo.almalinux.org/almalinux/8/cloud/x86_64/images/",
"direct_download_url": "https://repo.almalinux.org/almalinux/8/cloud/x86_64/images/AlmaLinux-8-GenericCloud-8.8-20230524.x86_64.qcow2"
"download_url": "https://vault.almalinux.org/8.8/cloud/x86_64/images/",
"direct_download_url": "https://vault.almalinux.org/8.8/cloud/x86_64/images/AlmaLinux-8-GenericCloud-8.8-20230524.x86_64.qcow2"
},
{
"filename": "AlmaLinux-8-GenericCloud-8.7-20221111.x86_64.qcow2",
"version": "8.7",
"md5sum": "b2b8c7fd3b6869362f3f8ed47549c804",
"filesize": 566231040,
"download_url": "https://repo.almalinux.org/almalinux/8/cloud/x86_64/images/",
"direct_download_url": "https://repo.almalinux.org/almalinux/8/cloud/x86_64/images/AlmaLinux-8-GenericCloud-8.7-20221111.x86_64.qcow2"
"download_url": "https://vault.almalinux.org/8.7/cloud/x86_64/images/",
"direct_download_url": "https://vault.almalinux.org/8.7/cloud/x86_64/images/AlmaLinux-8-GenericCloud-8.7-20221111.x86_64.qcow2"
},
{
"filename": "almalinux-cloud-init-data.iso",
+30 -348
View File
@@ -2,14 +2,14 @@
"appliance_id": "c90f3ff3-4ed2-4437-9afb-21232fa92015",
"name": "Arista vEOS",
"category": "multilayer_switch",
"description": "Arista EOS\u00ae is the core of Arista cloud networking solutions for next-generation data centers and cloud networks. Cloud architectures built with Arista EOS scale to tens of thousands of compute and storage nodes with management and provisioning capabilities that work at scale. Through its programmability, EOS enables a set of software applications that deliver workflow automation, high availability, unprecedented network visibility and analytics and rapid integration with a wide range of third-party applications for virtualization, management, automation and orchestration services.\n\nArista Extensible Operating System (EOS) is a fully programmable and highly modular, Linux-based network operation system, using familiar industry standard CLI and runs a single binary software image across the Arista switching family. Architected for resiliency and programmability, EOS has a unique multi-process state sharing architecture that separates state information and packet forwarding from protocol processing and application logic.",
"description": "Arista EOS is the core of Arista cloud networking solutions for next-generation data centers and cloud networks. Cloud architectures built with Arista EOS scale to tens of thousands of compute and storage nodes with management and provisioning capabilities that work at scale. Through its programmability, EOS enables a set of software applications that deliver workflow automation, high availability, unprecedented network visibility and analytics and rapid integration with a wide range of third-party applications for virtualization, management, automation and orchestration services.\n\nArista Extensible Operating System (EOS) is a fully programmable and highly modular, Linux-based network operation system, using familiar industry standard CLI and runs a single binary software image across the Arista switching family. Architected for resiliency and programmability, EOS has a unique multi-process state sharing architecture that separates state information and packet forwarding from protocol processing and application logic.",
"vendor_name": "Arista",
"vendor_url": "http://www.arista.com/",
"documentation_url": "https://www.arista.com/assets/data/docs/Manuals/EOS-4.17.2F-Manual.pdf",
"product_name": "vEOS",
"product_url": "https://eos.arista.com/",
"registry_version": 4,
"status": "experimental",
"status": "stable",
"maintainer": "GNS3 Team",
"maintainer_email": "developers@gns3.net",
"usage": "The login is admin, with no password by default",
@@ -24,378 +24,60 @@
"hdb_disk_interface": "ide",
"arch": "x86_64",
"console_type": "telnet",
"kvm": "require"
"kvm": "require",
"options": "-cpu host"
},
"images": [
{
"filename": "vEOS-lab-4.26.2F.vmdk",
"version": "4.26.2F",
"md5sum": "de8ce9750fddb63bd3f71bccfcd7651e",
"filesize": 475332608,
"filename": "vEOS-lab-4.33.1F.qcow2",
"version": "4.33.1F",
"md5sum": "8f662409c0732ed9f682edce63601e8a",
"filesize": 611909632,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS-lab-4.25.3M.vmdk",
"version": "4.25.3M",
"md5sum": "2f196969036b4d283e86f15118d59c26",
"filesize": 451543040,
"filename": "vEOS-lab-4.32.3M.qcow2",
"version": "4.32.3M",
"md5sum": "46fc46f5ed1da8752eed8396f08862f8",
"filesize": 605683712,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS-lab-4.24.3M.vmdk",
"version": "4.24.3M",
"md5sum": "0a28e44c7ce4a8965f24a4a463a89b7d",
"filesize": 455213056,
"filename": "vEOS-lab-4.31.6M.qcow2",
"version": "4.31.6M",
"md5sum": "7410110b77472f058322ec4681f8a356",
"filesize": 590479360,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS-lab-4.24.2.1F.vmdk",
"version": "4.24.2.1F",
"md5sum": "6bab8b59ce5230e243e56f4127448fc8",
"filesize": 455213056,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS-lab-4.23.4.2M.vmdk",
"version": "4.23.4.2M",
"md5sum": "d21cbef4e39f1e783b13a926cb54a242",
"filesize": 454295552,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS-lab-4.23.0.1F.vmdk",
"version": "4.23.0.1F",
"md5sum": "08d52154aa11a834aef9f42bbf29f977",
"filesize": 439484416,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS-lab-4.22.2.1F.vmdk",
"version": "4.22.2.1F",
"md5sum": "2a425bf8efe569a2bdf0e328f240cd16",
"filesize": 426377216,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS-lab-4.22.0F.vmdk",
"version": "4.22.0F",
"md5sum": "cfcc75c2b8176cfd819afcfd6799b74c",
"filesize": 414121984,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS-lab-4.21.1.1F.vmdk",
"version": "4.21.1F",
"md5sum": "02bfb7e53781fd44ff02357f201586d9",
"filesize": 358809600,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS-lab-4.20.10M-combined.vmdk",
"version": "4.20.10M-combined",
"md5sum": "d1f2d650f93dbf24e04fdd2c9d62bd62",
"filesize": 334626816,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS-lab-4.20.1F.vmdk",
"version": "4.20.1F",
"md5sum": "aadb6f3dbff28317f68cb4c4502d0db8",
"filesize": 662044672,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS-lab-4.19.10M-combined.vmdk",
"version": "4.19.10M-combined",
"md5sum": "103daa45c33be4584cbe6adc60de46a3",
"filesize": 324141056,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS-lab-4.19.10M.vmdk",
"version": "4.19.10M",
"md5sum": "665ed14389411ae5f16ba0a2ff84240a",
"filesize": 637337600,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS-lab-4.18.10M-combined.vmdk",
"version": "4.18.10M-combined",
"md5sum": "e33e0ef5b8cecc84c5bb57569b36b9c6",
"filesize": 317652992,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS-lab-4.18.10M.vmdk",
"version": "4.18.10M",
"md5sum": "1d87e9ace37fe3706dbf3e49c8d4d231",
"filesize": 624427008,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS-lab-4.18.5M.vmdk",
"version": "4.18.5M",
"md5sum": "b1ee6268dbaf2b2276fd7a5286c7ce2b",
"filesize": 623116288,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS-lab-4.18.1F.vmdk",
"version": "4.18.1F",
"md5sum": "9648c63185f3b793b47528a858ca4364",
"filesize": 620625920,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS-lab-4.17.8M.vmdk",
"version": "4.17.8M",
"md5sum": "afc79a06f930ea2cc0ae3e03cbfd3f23",
"filesize": 608829440,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS-lab-4.17.2F.vmdk",
"version": "4.17.2F",
"md5sum": "3b4845edfa77cf9aaeb9c0a005d3e277",
"filesize": 609615872,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS-lab-4.16.13M.vmdk",
"version": "4.16.13M",
"md5sum": "4d0facf90140fc3aab031f0f8f88a32f",
"filesize": 521404416,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS-lab-4.16.6M.vmdk",
"version": "4.16.6M",
"md5sum": "b3f7b7cee17f2e66bb38b453a4939fef",
"filesize": 519962624,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS-lab-4.15.10M.vmdk",
"version": "4.15.10M",
"md5sum": "98e08281a9c48ddf6f3c5d62a124a20f",
"filesize": 517079040,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS-lab-4.15.5M.vmdk",
"version": "4.15.5M",
"md5sum": "cd74bb69c7ee905ac3d33c4d109f3ab7",
"filesize": 516030464,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS-lab-4.14.14M.vmdk",
"version": "4.14.14M",
"md5sum": "d81ba0522f4d7838d96f7985e41cdc47",
"filesize": 422641664,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS-lab-4.13.16M.vmdk",
"version": "4.13.16M",
"md5sum": "5763b2c043830c341c8b1009f4ea9a49",
"filesize": 404684800,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS-lab-4.13.8M.vmdk",
"version": "4.13.8M",
"md5sum": "a47145b9e6e7a24171c0850f8755535e",
"filesize": 409010176,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "Aboot-veos-serial-8.0.0.iso",
"version": "8.0.0",
"md5sum": "488ad1c435d18c69bb8d69c7806457c9",
"filesize": 5242880,
"filename": "Aboot-veos-serial-8.0.2.iso",
"version": "8.0.2",
"md5sum": "8d7e754efebca1930a93a2587ff7606c",
"filesize": 6291456,
"download_url": "https://www.arista.com/en/support/software-download"
}
],
"versions": [
{
"name": "4.26.2F",
"name": "4.33.1F",
"images": {
"hda_disk_image": "Aboot-veos-serial-8.0.0.iso",
"hdb_disk_image": "vEOS-lab-4.26.2F.vmdk"
"hda_disk_image": "Aboot-veos-serial-8.0.2.iso",
"hdb_disk_image": "vEOS-lab-4.33.1F.qcow2"
}
},
{
"name": "4.25.3M",
"name": "4.32.3M",
"images": {
"hda_disk_image": "Aboot-veos-serial-8.0.0.iso",
"hdb_disk_image": "vEOS-lab-4.25.3M.vmdk"
"hda_disk_image": "Aboot-veos-serial-8.0.2.iso",
"hdb_disk_image": "vEOS-lab-4.32.3M.qcow2"
}
},
{
"name": "4.24.3M",
"name": "4.31.6M",
"images": {
"hda_disk_image": "Aboot-veos-serial-8.0.0.iso",
"hdb_disk_image": "vEOS-lab-4.24.3M.vmdk"
}
},
{
"name": "4.24.2.1F",
"images": {
"hda_disk_image": "Aboot-veos-serial-8.0.0.iso",
"hdb_disk_image": "vEOS-lab-4.24.2.1F.vmdk"
}
},
{
"name": "4.23.4.2M",
"images": {
"hda_disk_image": "Aboot-veos-serial-8.0.0.iso",
"hdb_disk_image": "vEOS-lab-4.23.4.2M.vmdk"
}
},
{
"name": "4.23.0.1F",
"images": {
"hda_disk_image": "Aboot-veos-serial-8.0.0.iso",
"hdb_disk_image": "vEOS-lab-4.23.0.1F.vmdk"
}
},
{
"name": "4.22.2.1F",
"images": {
"hda_disk_image": "Aboot-veos-serial-8.0.0.iso",
"hdb_disk_image": "vEOS-lab-4.22.2.1F.vmdk"
}
},
{
"name": "4.22.0F",
"images": {
"hda_disk_image": "Aboot-veos-serial-8.0.0.iso",
"hdb_disk_image": "vEOS-lab-4.22.0F.vmdk"
}
},
{
"name": "4.21.1F",
"images": {
"hda_disk_image": "Aboot-veos-serial-8.0.0.iso",
"hdb_disk_image": "vEOS-lab-4.21.1.1F.vmdk"
}
},
{
"name": "4.20.10M-combined",
"images": {
"hda_disk_image": "vEOS-lab-4.20.10M-combined.vmdk"
}
},
{
"name": "4.20.1F",
"images": {
"hda_disk_image": "Aboot-veos-serial-8.0.0.iso",
"hdb_disk_image": "vEOS-lab-4.20.1F.vmdk"
}
},
{
"name": "4.19.10M-combined",
"images": {
"hda_disk_image": "vEOS-lab-4.19.10M-combined.vmdk"
}
},
{
"name": "4.19.10M",
"images": {
"hda_disk_image": "Aboot-veos-serial-8.0.0.iso",
"hdb_disk_image": "vEOS-lab-4.19.10M.vmdk"
}
},
{
"name": "4.18.10M-combined",
"images": {
"hda_disk_image": "vEOS-lab-4.18.10M-combined.vmdk"
}
},
{
"name": "4.18.10M",
"images": {
"hda_disk_image": "Aboot-veos-serial-8.0.0.iso",
"hdb_disk_image": "vEOS-lab-4.18.10M.vmdk"
}
},
{
"name": "4.18.5M",
"images": {
"hda_disk_image": "Aboot-veos-serial-8.0.0.iso",
"hdb_disk_image": "vEOS-lab-4.18.5M.vmdk"
}
},
{
"name": "4.18.1F",
"images": {
"hda_disk_image": "Aboot-veos-serial-8.0.0.iso",
"hdb_disk_image": "vEOS-lab-4.18.1F.vmdk"
}
},
{
"name": "4.17.8M",
"images": {
"hda_disk_image": "Aboot-veos-serial-8.0.0.iso",
"hdb_disk_image": "vEOS-lab-4.17.8M.vmdk"
}
},
{
"name": "4.17.2F",
"images": {
"hda_disk_image": "Aboot-veos-serial-8.0.0.iso",
"hdb_disk_image": "vEOS-lab-4.17.2F.vmdk"
}
},
{
"name": "4.16.13M",
"images": {
"hda_disk_image": "Aboot-veos-serial-8.0.0.iso",
"hdb_disk_image": "vEOS-lab-4.16.13M.vmdk"
}
},
{
"name": "4.16.6M",
"images": {
"hda_disk_image": "Aboot-veos-serial-8.0.0.iso",
"hdb_disk_image": "vEOS-lab-4.16.6M.vmdk"
}
},
{
"name": "4.15.10M",
"images": {
"hda_disk_image": "Aboot-veos-serial-8.0.0.iso",
"hdb_disk_image": "vEOS-lab-4.15.10M.vmdk"
}
},
{
"name": "4.15.5M",
"images": {
"hda_disk_image": "Aboot-veos-serial-8.0.0.iso",
"hdb_disk_image": "vEOS-lab-4.15.5M.vmdk"
}
},
{
"name": "4.14.14M",
"images": {
"hda_disk_image": "Aboot-veos-serial-8.0.0.iso",
"hdb_disk_image": "vEOS-lab-4.14.14M.vmdk"
}
},
{
"name": "4.13.16M",
"images": {
"hda_disk_image": "Aboot-veos-serial-8.0.0.iso",
"hdb_disk_image": "vEOS-lab-4.13.16M.vmdk"
}
},
{
"name": "4.13.8M",
"images": {
"hda_disk_image": "Aboot-veos-serial-8.0.0.iso",
"hdb_disk_image": "vEOS-lab-4.13.8M.vmdk"
"hda_disk_image": "Aboot-veos-serial-8.0.2.iso",
"hdb_disk_image": "vEOS-lab-4.31.6M.qcow2"
}
}
]
}
}
@@ -32,6 +32,27 @@
"process_priority": "normal"
},
"images": [
{
"filename": "arubaoscx-disk-image-genericx86-p4-20240129204649.vmdk",
"version": "10.13.1000",
"md5sum": "a1a24b15e3b8a09b0c0f14bdfacc4a75",
"filesize": 395342848,
"download_url": "https://networkingsupport.hpe.com"
},
{
"filename": "arubaoscx-disk-image-genericx86-p4-20231110145644.vmdk",
"version": "10.13.0005",
"md5sum": "427fd4580e2ee3eac55a9e7d629d1375",
"filesize": 394995200,
"download_url": "https://networkingsupport.hpe.com"
},
{
"filename": "arubaoscx-disk-image-genericx86-p4-20230810165021.vmdk",
"version": "10.12.1000",
"md5sum": "ea89f94dda9d28bf583dc35e0299b106",
"filesize": 384622080,
"download_url": "https://networkingsupport.hpe.com"
},
{
"filename": "arubaoscx-disk-image-genericx86-p4-20230531220439.vmdk",
"version": "10.12.0006",
@@ -118,6 +139,24 @@
}
],
"versions": [
{
"name": "10.13.1000",
"images": {
"hda_disk_image": "arubaoscx-disk-image-genericx86-p4-20240129204649.vmdk"
}
},
{
"name": "10.13.0005",
"images": {
"hda_disk_image": "arubaoscx-disk-image-genericx86-p4-20231110145644.vmdk"
}
},
{
"name": "10.12.1000",
"images": {
"hda_disk_image": "arubaoscx-disk-image-genericx86-p4-20230810165021.vmdk"
}
},
{
"name": "10.12.0006",
"images": {
@@ -6,7 +6,7 @@
"vendor_name": "Asterfusion",
"vendor_url": "https://cloudswit.ch/",
"vendor_logo_url": "https://raw.githubusercontent.com/GNS3/gns3-registry/master/vendor-logos/asterfusion.png",
"documentation_url": "https://help.cloudswit.ch/portal/en/home",
"documentation_url": "https://help.cloudswit.ch/portal/en/kb/articles/vasternos",
"product_name": "vAsterNOS",
"product_url": "https://cloudswit.ch/product/sonic-enterprise-distribution",
"registry_version": 4,
@@ -34,7 +34,7 @@
"version": "V3.1",
"md5sum": "c323c9c3f60e1a93eca2acdc5034b85c",
"filesize": 2724659200,
"download_url": "https://cloudswit.ch/product/sonic-enterprise-distribution/#vAsterNOS"
"download_url": "https://drive.cloudswitch.io/external/8ae2e3932ad8bb2ec30dd25be415d288ff3e4a949c557c6bd48ac6e6265bcfc1"
}
],
"versions": [
+26
View File
@@ -33,11 +33,23 @@
"md5sum": "cbbbea66a253f1dac0fcf81274dc778d",
"filesize": 87756936
},
{
"filename": "c7200-adventerprisek9-mz.152-4.M11.image",
"version": "152-4.M11",
"md5sum": "9a2005ad09ce1ec6fe7cf9af1e9b099e",
"filesize": 128487680
},
{
"filename": "c7200-adventerprisek9-mz.124-24.T5.image",
"version": "124-24.T5",
"md5sum": "6b89d0d804e1f2bb5b8bda66b5692047",
"filesize": 102345240
},
{
"filename": "c7200-a3jk9s-mz.124-25g.image",
"version": "124-25G",
"md5sum": "9c7cc9b3f3b3571411a7f62faaa2c036",
"filesize": 71528984
}
],
"versions": [
@@ -55,12 +67,26 @@
"image": "c7200-advipservicesk9-mz.152-4.S5.image"
}
},
{
"name": "152-4.M11",
"idlepc": "0x6062e5c0",
"images": {
"image": "c7200-adventerprisek9-mz.152-4.M11.image"
}
},
{
"name": "124-24.T5",
"idlepc": "0x606df838",
"images": {
"image": "c7200-adventerprisek9-mz.124-24.T5.image"
}
},
{
"name": "124-25G",
"idlepc": "0x6066a998",
"images": {
"image": "c7200-a3jk9s-mz.124-25g.image"
}
}
]
}
+14 -1
View File
@@ -12,7 +12,7 @@
"status": "stable",
"maintainer": "GNS3 Team",
"maintainer_email": "developers@gns3.net",
"usage": "There is no default password and enable password. A default configuration is present. ASAv goes through a double-boot before becoming active. This is normal and expected.",
"usage": "There is no default password and enable password. A default configuration is present. ASAv goes through a double-boot before becoming active. This is normal and expected. Switch to the Telnet console type after the first boot.",
"symbol": ":/symbols/asa.svg",
"first_port_name": "Management0/0",
"port_name_format": "Gi0/{0}",
@@ -26,6 +26,13 @@
"kvm": "require"
},
"images": [
{
"filename": "asav9-22-1-1.qcow2",
"version": "9.22.1.1 CML",
"md5sum": "250a924cdc2370208eaac9d1dc8dc9e3",
"filesize": 379518976,
"download_url": "https://learningnetworkstore.cisco.com/cisco-modeling-labs-personal/cisco-modeling-labs-personal/CML-PERSONAL.html"
},
{
"filename": "asav9-18-2.qcow2",
"version": "9.18.2 CML",
@@ -126,6 +133,12 @@
}
],
"versions": [
{
"name": "9.22.1.1 CML",
"images": {
"hda_disk_image": "asav9-22-1-1.qcow2"
}
},
{
"name": "9.18.2 CML",
"images": {
+14 -1
View File
@@ -25,11 +25,18 @@
},
"images": [
{
"filename": "c8000v-universalk9_8G_serial.17.09.04a.qcow2",
"version": "17.09.04a 8G",
"md5sum": "d5dcba52b522f41648538737af80cdf9",
"filesize": 1858142208,
"download_url": "https://software.cisco.com/download/home/286327102/type/282046477/release/Cupertino-17.9.4a"
},
{
"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"
"download_url": "https://software.cisco.com/download/home/286327102/type/282046477/release/Cupertino-17.9.1a"
},
{
"filename": "c8000v-universalk9_8G_serial.17.06.05.qcow2",
@@ -62,6 +69,12 @@
],
"versions": [
{
"name": "17.09.04a 8G",
"images": {
"hda_disk_image": "c8000v-universalk9_8G_serial.17.09.04a.qcow2"
}
},
{
"name": "17.09.01a 8G",
"images": {
"hda_disk_image": "c8000v-universalk9_8G_serial.17.09.01a.qcow2"
+28 -2
View File
@@ -24,12 +24,26 @@
"kvm": "require"
},
"images": [
{
"filename": "csr1000v-universalk9.17.03.08a-serial.qcow2",
"version": "17.03.08a",
"md5sum": "6abece87d6db99d9fd6917203e253f91",
"filesize": 1421410304,
"download_url": "https://software.cisco.com/download/home/286323714/type/282046477/release/Amsterdam-17.3.8a"
},
{
"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"
"download_url": "https://software.cisco.com/download/home/286323714/type/282046477/release/Amsterdam-17.3.6"
},
{
"filename": "csr1000v-ucmk9.16.12.5-serial.qcow2",
"version": "16.12.05",
"md5sum": "5c0cc217f0f0648407b34b11a1dd5b8e",
"filesize": 844103680,
"download_url": "https://software.cisco.com/download/home/286323714/type/286321980/release/16.12.5"
},
{
"filename": "csr1000v-universalk9.16.12.03-serial.qcow2",
@@ -166,13 +180,25 @@
}
],
"versions": [
{
"name": "17.03.08a",
"images": {
"hda_disk_image": "csr1000v-universalk9.17.03.08a-serial.qcow2"
}
},
{
"name": "17.03.06",
"images": {
"hda_disk_image": "csr1000v-universalk9.17.03.06-serial.qcow2"
}
},
{
{
"name": "16.12.05",
"images": {
"hda_disk_image": "csr1000v-ucmk9.16.12.5-serial.qcow2"
}
},
{
"name": "16.12.3",
"images": {
"hda_disk_image": "csr1000v-universalk9.16.12.03-serial.qcow2"
+14 -2
View File
@@ -13,11 +13,17 @@
"iou": {
"ethernet_adapters": 4,
"serial_adapters": 0,
"nvram": 128,
"ram": 256,
"nvram": 512,
"ram": 512,
"startup_config": "iou_l2_base_startup-config.txt"
},
"images": [
{
"filename": "x86_64_crb_linux_l2-adventerprisek9-ms.iol",
"version": "17.15.1",
"md5sum": "6c587cdfd5056078e70b3f6c26800d66",
"filesize": 243251976
},
{
"filename": "x86_64_crb_linux_l2-adventerprisek9-ms",
"version": "17.12.1",
@@ -44,6 +50,12 @@
}
],
"versions": [
{
"name": "17.15.1",
"images": {
"image": "x86_64_crb_linux_l2-adventerprisek9-ms.iol"
}
},
{
"name": "17.12.1",
"images": {
+14 -2
View File
@@ -13,11 +13,17 @@
"iou": {
"ethernet_adapters": 2,
"serial_adapters": 2,
"nvram": 128,
"ram": 256,
"nvram": 512,
"ram": 512,
"startup_config": "iou_l3_base_startup-config.txt"
},
"images": [
{
"filename": "x86_64_crb_linux-adventerprisek9-ms.iol",
"version": "17.15.1",
"md5sum": "5d584f6cfbeaadc87d55f613da1049ed",
"filesize": 292001512
},
{
"filename": "x86_64_crb_linux-adventerprisek9-ms",
"version": "17.12.1",
@@ -44,6 +50,12 @@
}
],
"versions": [
{
"name": "17.15.1",
"images": {
"image": "x86_64_crb_linux-adventerprisek9-ms.iol"
}
},
{
"name": "17.12.1",
"images": {
+29 -1
View File
@@ -28,7 +28,21 @@
"options": ""
},
"images": [
{
{
"filename": "MFG_CTVM_8_10_196_0.iso",
"version": "8.10.196.0",
"md5sum": "6093aca44dcf45c999f83e62dc9aeea2",
"filesize": 650809344,
"download_url": "https://software.cisco.com/download/release.html?mdfid=284464214&flowid=&softwareid=280926587&release=8.10.196.0"
},
{
"filename": "MFG_CTVM_8_5_182_0.iso",
"version": "8.5.182.0",
"md5sum": "1cf3c57c2b123e739ab4662ea0abbc34",
"filesize": 388579328,
"download_url": "https://software.cisco.com/download/home/284464214/type/280926587/release/8.5.182.0"
},
{
"filename": "MFG_CTVM_8_3_102_0.iso",
"version": "8.3.102.0",
"md5sum": "7f6b7968b5bed04b5ecc119b6ba4e41c",
@@ -73,6 +87,20 @@
}
],
"versions": [
{
"name": "8.10.196.0",
"images": {
"hda_disk_image": "empty8G.qcow2",
"cdrom_image": "MFG_CTVM_8_10_196_0.iso"
}
},
{
"name": "8.5.182.0",
"images": {
"hda_disk_image": "empty8G.qcow2",
"cdrom_image": "MFG_CTVM_8_5_182_0.iso"
}
},
{
"name": "8.3.102.0",
"images": {
+28
View File
@@ -23,6 +23,14 @@
"kvm": "allow"
},
"images": [
{
"filename": "debian-12.6.qcow2",
"version": "12.6",
"md5sum": "04753ba14295c6414d49bffe27b676ae",
"filesize": 280907776,
"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.6.qcow2"
},
{
"filename": "debian-12.4.qcow2",
"version": "12.4",
@@ -31,6 +39,14 @@
"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.4.qcow2"
},
{
"filename": "debian-11.10.qcow2",
"version": "11.10",
"md5sum": "99a1dc8e110d641309674e69b630e732",
"filesize": 263520256,
"download_url": "https://sourceforge.net/projects/gns-3/files/Qemu%20Appliances/",
"direct_download_url": "https://downloads.sourceforge.net/project/gns-3/Qemu%20Appliances/debian-11.10.qcow2"
},
{
"filename": "debian-11.8.qcow2",
"version": "11.8",
@@ -41,12 +57,24 @@
}
],
"versions": [
{
"name": "12.6",
"images": {
"hda_disk_image": "debian-12.6.qcow2"
}
},
{
"name": "12.4",
"images": {
"hda_disk_image": "debian-12.4.qcow2"
}
},
{
"name": "11.10",
"images": {
"hda_disk_image": "debian-11.10.qcow2"
}
},
{
"name": "11.8",
"images": {
+46 -4
View File
@@ -28,10 +28,17 @@
},
"images": [
{
"filename": "FAD_KVM-FORTINET.out.kvm-data.qcow2",
"version": "ALL",
"md5sum": "b7500835594e62d8acb1c6ec43d597c1",
"filesize": 30998528,
"filename": "FAD_KVM-V7.4.4-build0347-FORTINET.out.kvm_boot.qcow2",
"version": "7.4.4",
"md5sum": "52fa343fd423a1a560473b8cf02f4c9c",
"filesize": 180617216,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FAD_KVM-V7.2.6-build0257-FORTINET.out.kvm_boot.qcow2",
"version": "7.2.6",
"md5sum": "ed8c3622b12212786c310aa94c928f06",
"filesize": 146341888,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
@@ -41,6 +48,13 @@
"filesize": 145817600,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FAD_KVM-v7.1.4-build0138-FORTINET.out.kvm_boot.qcow2",
"version": "7.1.4",
"md5sum": "d4b3ff27fc9d0461199d6066174744ca",
"filesize": 134152192,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FAD_KVM-V7.1.1-build0117-FORTINET.out.kvm-boot.qcow2",
"version": "7.1.1",
@@ -243,9 +257,30 @@
"md5sum": "7a71f52bde93c0000b047626731b7aef",
"filesize": 68026368,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FAD_KVM-FORTINET.out.kvm-data.qcow2",
"version": "ALL",
"md5sum": "b7500835594e62d8acb1c6ec43d597c1",
"filesize": 30998528,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
}
],
"versions": [
{
"name": "7.4.4",
"images": {
"hda_disk_image": "FAD_KVM-V7.4.4-build0347-FORTINET.out.kvm_boot.qcow2",
"hdb_disk_image": "FAD_KVM-FORTINET.out.kvm-data.qcow2"
}
},
{
"name": "7.2.6",
"images": {
"hda_disk_image": "FAD_KVM-V7.2.6-build0257-FORTINET.out.kvm_boot.qcow2",
"hdb_disk_image": "FAD_KVM-FORTINET.out.kvm-data.qcow2"
}
},
{
"name": "7.2.0",
"images": {
@@ -253,6 +288,13 @@
"hdb_disk_image": "FAD_KVM-FORTINET.out.kvm-data.qcow2"
}
},
{
"name": "7.1.4",
"images": {
"hda_disk_image": "FAD_KVM-v7.1.4-build0138-FORTINET.out.kvm_boot.qcow2",
"hdb_disk_image": "FAD_KVM-FORTINET.out.kvm-data.qcow2"
}
},
{
"name": "7.1.1",
"images": {
+42
View File
@@ -29,6 +29,13 @@
"kvm": "allow"
},
"images": [
{
"filename": "FAZ_VM64_KVM-v7.4.3-build2487-FORTINET.out.kvm.qcow2",
"version": "7.4.3",
"md5sum": "c58709af18516763ed88f58621447bf6",
"filesize": 504463360,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FAZ_VM64_KVM-v7.4.2-build2397-FORTINET.out.kvm.qcow2",
"version": "7.4.2",
@@ -43,6 +50,13 @@
"filesize": 435310592,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FAZ_VM64_KVM-v7.2.5-build1574-FORTINET.out.kvm.qcow2",
"version": "7.2.5",
"md5sum": "225d7405f35f78a482cffa34ef90080d",
"filesize": 379973632,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FAZ_VM64_KVM-v7.2.4-build1460-FORTINET.out.kvm.qcow2",
"version": "7.2.4",
@@ -64,6 +78,13 @@
"filesize": 340631552,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FAZ_VM64_KVM-v7.0.12-build0623-FORTINET.out.kvm.qcow2",
"version": "7.0.12",
"md5sum": "a45f8987ea13da836c684b5d9850c1c2",
"filesize": 349560832,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FAZ_VM64_KVM-v7.0.11-build0595-FORTINET.out.kvm.qcow2",
"version": "7.0.11",
@@ -256,6 +277,13 @@
}
],
"versions": [
{
"name": "7.4.3",
"images": {
"hda_disk_image": "FAZ_VM64_KVM-v7.4.3-build2487-FORTINET.out.kvm.qcow2",
"hdb_disk_image": "empty30G.qcow2"
}
},
{
"name": "7.4.2",
"images": {
@@ -270,6 +298,13 @@
"hdb_disk_image": "empty30G.qcow2"
}
},
{
"name": "7.2.5",
"images": {
"hda_disk_image": "FAZ_VM64_KVM-v7.2.5-build1574-FORTINET.out.kvm.qcow2",
"hdb_disk_image": "empty30G.qcow2"
}
},
{
"name": "7.2.4",
"images": {
@@ -291,6 +326,13 @@
"hdb_disk_image": "empty30G.qcow2"
}
},
{
"name": "7.0.12",
"images": {
"hda_disk_image": "FAZ_VM64_KVM-v7.0.12-build0623-FORTINET.out.kvm.qcow2",
"hdb_disk_image": "empty30G.qcow2"
}
},
{
"name": "7.0.11",
"images": {
+58 -2
View File
@@ -13,13 +13,13 @@
"status": "stable",
"maintainer": "GNS3 Team",
"maintainer_email": "developers@gns3.net",
"usage": "Default username is admin, no password is set. First book takes longer.",
"usage": "Default username is admin, no password is set. First boot takes longer.",
"symbol": "fortinet.svg",
"port_name_format": "Port{port1}",
"qemu": {
"adapter_type": "e1000",
"adapters": 4,
"ram": 1024,
"ram": 4096,
"hda_disk_interface": "virtio",
"hdb_disk_interface": "virtio",
"arch": "x86_64",
@@ -28,6 +28,27 @@
"kvm": "allow"
},
"images": [
{
"filename": "FAC_VM_KVM-v6.6.1-build1660-FORTINET.out.kvm_fackvm.qcow2",
"version": "6.6.1",
"md5sum": "4b2b475ac8b6f88b5033dca367d53cbb",
"filesize": 138477584,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FAC_VM_KVM-v6.5.5-build1385-FORTINET.out.kvm_fackvm.qcow2",
"version": "6.5.5",
"md5sum": "6850128ac51cee2577114ecd487786ff",
"filesize": 112918544,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FAC_VM_KVM-v6.4.9-build1067-FORTINET.out.kvm_fackvm.qcow2",
"version": "6.4.9",
"md5sum": "aee068a16fb2ca332d41e6add499b7d3",
"filesize": 112197648,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FAC_VM_KVM-v6-build0058-FORTINET.out.kvm.qcow2",
"version": "6.0.3",
@@ -105,6 +126,20 @@
"filesize": 62771200,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FAC_VM_KVM-v6.6.1-build1660-FORTINET.out.kvm_datadrive.qcow2",
"version": "6.6.1",
"md5sum": "9bbaa1ce1508b4af1f43ba00879269f9",
"filesize": 197568,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FAC_VM_KVM-v6.5.5-build1385-FORTINET.out.kvm_datadrive.qcow2",
"version": "6.4.x, 6.5.x",
"md5sum": "3f7173307047cf562f55ed2f99450c10",
"filesize": 197568,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FAC_VM_KVM-ALL-DATADRIVE.qcow2",
"version": "All",
@@ -114,6 +149,27 @@
}
],
"versions": [
{
"name": "6.6.1",
"images": {
"hda_disk_image": "FAC_VM_KVM-v6.6.1-build1660-FORTINET.out.kvm_fackvm.qcow2",
"hdb_disk_image": "FAC_VM_KVM-v6.6.1-build1660-FORTINET.out.kvm_datadrive.qcow2"
}
},
{
"name": "6.5.5",
"images": {
"hda_disk_image": "FAC_VM_KVM-v6.5.5-build1385-FORTINET.out.kvm_fackvm.qcow2",
"hdb_disk_image": "FAC_VM_KVM-v6.5.5-build1385-FORTINET.out.kvm_datadrive.qcow2"
}
},
{
"name": "6.4.9",
"images": {
"hda_disk_image": "FAC_VM_KVM-v6.4.9-build1067-FORTINET.out.kvm_fackvm.qcow2",
"hdb_disk_image": "FAC_VM_KVM-v6.5.5-build1385-FORTINET.out.kvm_datadrive.qcow2"
}
},
{
"name": "6.0.3",
"images": {
+42
View File
@@ -28,6 +28,13 @@
"kvm": "allow"
},
"images": [
{
"filename": "FGT_VM64_KVM-v7.4.4.F-build2662-FORTINET.out.kvm.qcow2",
"version": "7.4.4",
"md5sum": "dfe0e78827ec728631539669001bb23f",
"filesize": 102170624,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FGT_VM64_KVM-v7.4.3.F-build2573-FORTINET.out.kvm.qcow2",
"version": "7.4.3",
@@ -42,6 +49,13 @@
"filesize": 116064256,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FGT_VM64_KVM-v7.2.8.M-build1639-FORTINET.out.kvm_fortios.qcow2",
"version": "7.2.8",
"md5sum": "5c8fd4baf80aeb2999d4be5a9c49eb3d",
"filesize": 89980928,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FGT_VM64_KVM-v7.2.7.M-build1577-FORTINET.out.kvm.qcow2",
"version": "7.2.7",
@@ -77,6 +91,13 @@
"filesize": 86704128,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FGT_VM64_KVM-v7.0.15.M-build0601-FORTINET.out.kvm.qcow2",
"version": "7.0.15",
"md5sum": "423f50378b7e93098ab765c3dd3a788f",
"filesize": 77398016,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FGT_VM64_KVM-v7.0.14.M-build0601-FORTINET.out.kvm.qcow2",
"version": "7.0.14",
@@ -367,6 +388,13 @@
}
],
"versions": [
{
"name": "7.4.4",
"images": {
"hda_disk_image": "FGT_VM64_KVM-v7.4.4.F-build2662-FORTINET.out.kvm.qcow2",
"hdb_disk_image": "empty30G.qcow2"
}
},
{
"name": "7.4.3",
"images": {
@@ -381,6 +409,13 @@
"hdb_disk_image": "empty30G.qcow2"
}
},
{
"name": "7.2.8",
"images": {
"hda_disk_image": "FGT_VM64_KVM-v7.2.8.M-build1639-FORTINET.out.kvm_fortios.qcow2",
"hdb_disk_image": "empty30G.qcow2"
}
},
{
"name": "7.2.7",
"images": {
@@ -416,6 +451,13 @@
"hdb_disk_image": "empty30G.qcow2"
}
},
{
"name": "7.0.15",
"images": {
"hda_disk_image": "FGT_VM64_KVM-v7.0.15.M-build0601-FORTINET.out.kvm.qcow2",
"hdb_disk_image": "empty30G.qcow2"
}
},
{
"name": "7.0.14",
"images": {
+42
View File
@@ -29,6 +29,13 @@
"kvm": "allow"
},
"images": [
{
"filename": "FMG_VM64_KVM-v7.4.3-build2487-FORTINET.out.kvm.qcow2",
"version": "7.4.23",
"md5sum": "b01d9f86aa27c538407d518df1326863",
"filesize": 346107904,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FMG_VM64_KVM-v7.4.2-build2397-FORTINET.out.kvm.qcow2",
"version": "7.4.2",
@@ -43,6 +50,13 @@
"filesize": 309387264,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FMG_VM64_KVM-v7.2.5-build1574-FORTINET.out.kvm.qcow2",
"version": "7.2.5",
"md5sum": "754326845096afd909ec45d98f8d5a83",
"filesize": 278401024,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FMG_VM64_KVM-v7.2.4-build1460-FORTINET.out.kvm.qcow2",
"version": "7.2.4",
@@ -64,6 +78,13 @@
"filesize": 242814976,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FMG_VM64_KVM-v7.0.12-build0623-FORTINET.out.kvm.qcow2",
"version": "7.0.12",
"md5sum": "5b6f6a2b8bc00e56337aa7023a9025cf",
"filesize": 249520128,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FMG_VM64_KVM-v7.0.11-build0595-FORTINET.out.kvm.qcow2",
"version": "7.0.11",
@@ -256,6 +277,13 @@
}
],
"versions": [
{
"name": "7.4.3",
"images": {
"hda_disk_image": "FMG_VM64_KVM-v7.4.3-build2487-FORTINET.out.kvm.qcow2",
"hdb_disk_image": "empty30G.qcow2"
}
},
{
"name": "7.4.2",
"images": {
@@ -270,6 +298,13 @@
"hdb_disk_image": "empty30G.qcow2"
}
},
{
"name": "7.2.5",
"images": {
"hda_disk_image": "FMG_VM64_KVM-v7.2.5-build1574-FORTINET.out.kvm.qcow2",
"hdb_disk_image": "empty30G.qcow2"
}
},
{
"name": "7.2.4",
"images": {
@@ -291,6 +326,13 @@
"hdb_disk_image": "empty30G.qcow2"
}
},
{
"name": "7.0.12",
"images": {
"hda_disk_image": "FMG_VM64_KVM-v7.0.12-build0623-FORTINET.out.kvm.qcow2",
"hdb_disk_image": "empty30G.qcow2"
}
},
{
"name": "7.0.11",
"images": {
+56
View File
@@ -28,6 +28,27 @@
"kvm": "allow"
},
"images": [
{
"filename": "FWB_KVM-v7.6.0.F-build0962-FORTINET.out.kvm_boot.qcow2",
"version": "7.6.0",
"md5sum": "e94aa4af7ed0a12bd6084f0d74a2a96e",
"filesize": 329187840,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FWB_KVM-v7.4.3-build0638-FORTINET.out.kvm_boot.qcow2",
"version": "7.4.3",
"md5sum": "3c0ac11a6d80a319a4fe460aff5bc66c",
"filesize": 303497728,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FWB_KVM-v7.2.8-build0400-FORTINET.out.kvm_boot.qcow2",
"version": "7.2.8",
"md5sum": "367307242e6855dc190df089d196e712",
"filesize": 257950208,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FWB_KVM-v7.2.1-build0330-FORTINET.out.kvm.boot.qcow2",
"version": "7.2.1",
@@ -35,6 +56,13 @@
"filesize": 260506112,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FWB_KVM-v7.0.10-build0166-FORTINET.out.kvm_boot.qcow2",
"version": "7.0.10",
"md5sum": "ff9d4b827c4e41c1b38e59359ba05487",
"filesize": 257556992,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FWB_KVM-v7.0.6-build0140-FORTINET.out.kvm.boot.qcow2",
"version": "7.0.6",
@@ -150,6 +178,27 @@
}
],
"versions": [
{
"name": "7.6.0",
"images": {
"hda_disk_image": "FWB_KVM-v7.6.0.F-build0962-FORTINET.out.kvm_boot.qcow2",
"hdb_disk_image": "empty30G.qcow2"
}
},
{
"name": "7.4.3",
"images": {
"hda_disk_image": "FWB_KVM-v7.4.3-build0638-FORTINET.out.kvm_boot.qcow2",
"hdb_disk_image": "empty30G.qcow2"
}
},
{
"name": "7.2.8",
"images": {
"hda_disk_image": "FWB_KVM-v7.2.8-build0400-FORTINET.out.kvm_boot.qcow2",
"hdb_disk_image": "empty30G.qcow2"
}
},
{
"name": "7.2.1",
"images": {
@@ -157,6 +206,13 @@
"hdb_disk_image": "empty30G.qcow2"
}
},
{
"name": "7.0.10",
"images": {
"hda_disk_image": "FWB_KVM-v7.0.10-build0166-FORTINET.out.kvm_boot.qcow2",
"hdb_disk_image": "empty30G.qcow2"
}
},
{
"name": "7.0.6",
"images": {
+62
View File
@@ -0,0 +1,62 @@
{
"appliance_id": "ac98ab6f-7966-444b-842f-9507c965b8b7",
"name": "HBCD-PE",
"category": "guest",
"description": "Hiren’s BootCD PE (Preinstallation Environment) is a restored edition of Hiren’s BootCD based on Windows 11 PE x64. ",
"vendor_name": "hirensbootcd.org",
"vendor_url": "https://www.hirensbootcd.org/",
"documentation_url": "https://www.hirensbootcd.org/howtos/",
"product_name": "Hiren’s BootCD PE",
"product_url": "https://www.hirensbootcd.org/",
"registry_version": 4,
"status": "stable",
"maintainer": "GNS3 Team",
"maintainer_email": "developers@gns3.net",
"qemu": {
"adapter_type": "e1000",
"adapters": 1,
"ram": 4096,
"hda_disk_interface": "sata",
"arch": "x86_64",
"console_type": "vnc",
"boot_priority": "c",
"kvm": "require"
},
"images": [
{
"filename": "HBCD_PE_x64.iso",
"version": "1.0.8",
"md5sum": "45baab64b088431bdf3370292e9a74b0",
"filesize": 3291686912,
"download_url": "https://www.hirensbootcd.org/download/",
"direct_download_url": "https://www.hirensbootcd.org/files/HBCD_PE_x64.iso"
},
{
"filename": "empty30G.qcow2",
"version": "1.0",
"md5sum": "3411a599e822f2ac6be560a26405821a",
"filesize": 197120,
"download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/",
"direct_download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty30G.qcow2/download"
},
{
"filename": "OVMF-edk2-stable202305.fd",
"version": "stable202305",
"md5sum": "6c4cf1519fec4a4b95525d9ae562963a",
"filesize": 4194304,
"download_url": "https://sourceforge.net/projects/gns-3/files/Qemu%20Appliances/",
"direct_download_url": "https://sourceforge.net/projects/gns-3/files/Qemu%20Appliances/OVMF-edk2-stable202305.fd.zip/download",
"compression": "zip"
}
],
"versions": [
{
"name": "1.0.8",
"images": {
"bios_image": "OVMF-edk2-stable202305.fd",
"hda_disk_image": "empty30G.qcow2",
"cdrom_image": "HBCD_PE_x64.iso"
}
}
]
}
@@ -0,0 +1,50 @@
{
"appliance_id": "92dbd0e9-144e-4c59-a4a8-97b6a1661818",
"name": "Innovaphone App-Platform",
"category": "guest",
"description": "In addition to telephony, apps for Video Telephony, Chat, Conferencing, Application Sharing and many other functions have become indispensable UCC tools in the area of business communication. Based on the myApps platform and its various components, innovaphone provides a collaborative work and communication platform for enhanced corporate communications \u2013 regardless of the location and the device being used. The innovaphone platform myApps consists of many independent components that work well individually, yet unfold their remarkable performance when combined.",
"vendor_name": "Innovaphone",
"vendor_url": "https://www.innovaphone.com",
"vendor_logo_url": "https://www.innovaphone.com/content/downloads/innovaphone-myapps-logo-short-without-background-screen.png",
"documentation_url": "https://wiki.innovaphone.com/index.php?title=Reference14r2:Concept_App_Platform",
"product_name": "App-Platform",
"product_url": "https://www.innovaphone.com/en/products/myapps/myapps-platform.html",
"registry_version": 4,
"status": "experimental",
"availability": "free-to-try",
"maintainer": "Thomas Marchsteiner",
"maintainer_email": "thomas.marchsteiner@acp.at",
"usage": "Default users console:root/iplinux , ssh:admin/ipapps , Webinterface:pwd \nAfter first boot wait for automatic reboot.\nA static ip can be set via the setip utility. \nLoading another keymap can be done via the loadkeys command. \nThe app-platform-disk1.vmdk file is contained within an ova file. \nIt can be extraced with the tar utility, 7Zip or any other tool which can handle tar files.",
"symbol": "innovaphone-ap-icon.jpg",
"first_port_name": "eth0",
"qemu": {
"adapter_type": "vmxnet3",
"adapters": 1,
"ram": 512,
"cpus": 1,
"hda_disk_interface": "scsi",
"arch": "x86_64",
"console_type": "vnc",
"boot_priority": "d",
"kvm": "allow",
"on_close": "power_off",
"process_priority": "normal"
},
"images": [
{
"filename": "app-platform-disk1_120010.vmdk",
"version": "12.0010",
"md5sum": "d5a5a77f682c2c988b0810935d79a787",
"filesize": 129474560,
"download_url": "https://store.innovaphone.com/"
}
],
"versions": [
{
"images": {
"hda_disk_image": "app-platform-disk1_120010.vmdk"
},
"name": "12.0010"
}
]
}
@@ -0,0 +1,78 @@
{
"appliance_id": "ddf8f7a4-60c0-4c9d-849c-ffc3c9d1d082",
"name": "Innovaphone IPVA",
"category": "guest",
"description": "The innovaphone PBX is a professional IP telephone system. The IPVA is a software-only solution. It appears as and performs as an innovaphone 'hard-box' excluding DSP-, ISDN-/AB-resources.",
"vendor_name": "Innovaphone",
"vendor_url": "https://www.innovaphone.com/",
"vendor_logo_url": "https://www.innovaphone.com/content/downloads/innovaphone-myapps-logo-short-without-background-screen.png",
"documentation_url": "https://wiki.innovaphone.com/index.php?title=Reference15r1:Concept_Innovaphone_Virtual_Appliance_(IPVA)",
"product_name": "IPVA",
"product_url": "https://www.innovaphone.com/en/products/innovaphone-pbx.html",
"registry_version": 4,
"status": "experimental",
"availability": "free-to-try",
"maintainer": "Thomas Marchsteiner",
"maintainer_email": "thomas.marchsteiner@acp.at",
"usage": "Default user admin/ipva \nDefault network configuration: DHCP client on eth0 with fallback to static address 192.168.0.1/24 after timeout. Static address 192.168.1.1/24 on eth1\n The ova in the zip file contains the disk images to run this appliance. Disableing the dhcp client and setting a static IP is possible with the following commands:\n> config change IP0 ETH0 /addr 192.168.0.1 /mask 255.255.255.0 \n> config change DHCP0 /mode off \n> config write \n> config activate \n> reset",
"symbol": "innovaphone-pbx-green.png",
"first_port_name": "eth0",
"port_name_format": "eth{port1}",
"qemu": {
"adapter_type": "vmxnet3",
"adapters": 2,
"ram": 256,
"cpus": 1,
"hda_disk_interface": "ide",
"hdb_disk_interface": "ide",
"hdc_disk_interface": "ide",
"hdd_disk_interface": "ide",
"arch": "x86_64",
"console_type": "vnc",
"boot_priority": "d",
"kvm": "allow",
"on_close": "power_off",
"process_priority": "normal"
},
"images": [
{
"filename": "ipva-qemu-disk1-14r2.vmdk",
"version": "14r2",
"md5sum": "aaa1c3885eee30ca6ffa3827619e8643",
"filesize": 6269952,
"download_url": "https://store.innovaphone.com/"
},
{
"filename": "ipva-qemu-disk2-14r2.vmdk",
"version": "14r2",
"md5sum": "008a8fc6b0b1e5f11a3e7fd6f22ba349",
"filesize": 72192,
"download_url": "https://store.innovaphone.com/"
},
{
"filename": "ipva-qemu-disk3-14r2.vmdk",
"version": "14r2",
"md5sum": "20516731c480e2112b3fb4a4d7f514f2",
"filesize": 68096,
"download_url": "https://store.innovaphone.com/"
},
{
"filename": "ipva-qemu-disk4-14r2.vmdk",
"version": "14r2",
"md5sum": "15d7d79ef8c28bd29b2eceac8405f964",
"filesize": 68096,
"download_url": "https://store.innovaphone.com/"
}
],
"versions": [
{
"images": {
"hda_disk_image": "ipva-qemu-disk1-14r2.vmdk",
"hdb_disk_image": "ipva-qemu-disk2-14r2.vmdk",
"hdc_disk_image": "ipva-qemu-disk3-14r2.vmdk",
"hdd_disk_image": "ipva-qemu-disk4-14r2.vmdk"
},
"name": "14r2"
}
]
}
@@ -12,18 +12,19 @@
"status": "stable",
"maintainer": "GNS3 Team",
"maintainer_email": "developers@gns3.net",
"usage": "16 GB RAM is the bare minimum; you should use 32/64 GB in production deplyments.\nDefault credentials:\n- CLI: admin / abc123\n- WebUI: super / juniper123",
"usage": "16 GB RAM is the bare minimum; you should use 32/64 GB in production deployments.\nDefault credentials:\n- CLI: admin / abc123\n- WebUI: super / juniper123",
"symbol": "juniper-vqfx.svg",
"port_name_format": "em{0}",
"qemu": {
"adapter_type": "e1000",
"adapters": 4,
"ram": 16384,
"cpus": 4,
"hda_disk_interface": "ide",
"arch": "x86_64",
"console_type": "telnet",
"kvm": "require",
"options": "-smp 4 -nographic"
"options": "-nographic -machine q35,smbios-entry-point-type=32"
},
"images": [
{
@@ -34,7 +34,7 @@
"arch": "x86_64",
"console_type": "telnet",
"kvm": "require",
"options": "-nographic"
"options": "-nographic -machine q35,smbios-entry-point-type=32"
},
"images": [
{
+1 -1
View File
@@ -26,7 +26,7 @@
"arch": "x86_64",
"console_type": "telnet",
"kvm": "require",
"options": "-nographic -enable-kvm"
"options": "-nographic -enable-kvm -machine q35,smbios-entry-point-type=32"
},
"images": [
{
+2 -1
View File
@@ -20,11 +20,12 @@
"adapter_type": "virtio-net-pci",
"adapters": 13,
"ram": 4096,
"cpus": 4,
"hda_disk_interface": "ide",
"arch": "x86_64",
"console_type": "telnet",
"kvm": "require",
"options": "-nographic -enable-kvm -smp cpus=3"
"options": "-nographic -enable-kvm -machine q35,smbios-entry-point-type=32"
},
"images": [
{
+1 -1
View File
@@ -23,7 +23,7 @@
"arch": "x86_64",
"console_type": "vnc",
"kvm": "require",
"options": "-nographic"
"options": "-nographic -machine q35,smbios-entry-point-type=32"
},
"images": [
{
+2 -1
View File
@@ -19,11 +19,12 @@
"adapter_type": "virtio-net-pci",
"adapters": 12,
"ram": 1024,
"cpus": 2,
"hda_disk_interface": "ide",
"arch": "x86_64",
"console_type": "telnet",
"kvm": "require",
"options": "-nographic -smp 2"
"options": "-nographic -machine q35,smbios-entry-point-type=32"
},
"images": [
{
+1 -1
View File
@@ -25,7 +25,7 @@
"arch": "x86_64",
"console_type": "telnet",
"kvm": "require",
"options": "-nographic -enable-kvm"
"options": "-nographic -enable-kvm -machine q35,smbios-entry-point-type=32"
},
"images": [
{
+2 -1
View File
@@ -19,11 +19,12 @@
"adapter_type": "vmxnet3",
"adapters": 6,
"ram": 4096,
"cpus": 2,
"hda_disk_interface": "ide",
"arch": "x86_64",
"console_type": "telnet",
"kvm": "require",
"options": "-smp 2"
"options": "-machine q35,smbios-entry-point-type=32"
},
"images": [
{
+30 -99
View File
@@ -28,149 +28,80 @@
},
"images": [
{
"filename": "chr-7.14.2.img",
"version": "7.14.2",
"md5sum": "531901dac85b67b23011e946a62abc7b",
"filename": "chr-7.16.img",
"version": "7.16",
"md5sum": "a4c2d00a87e73b3129cd66a4e0743c9a",
"filesize": 134217728,
"download_url": "http://www.mikrotik.com/download",
"direct_download_url": "https://download.mikrotik.com/routeros/7.14.2/chr-7.14.2.img.zip",
"direct_download_url": "https://download.mikrotik.com/routeros/7.16/chr-7.16.img.zip",
"compression": "zip"
},
{
"filename": "chr-7.11.2.img",
"version": "7.11.2",
"md5sum": "fbffd097d2c5df41fc3335c3977f782c",
"filename": "chr-7.15.3.img",
"version": "7.15.3",
"md5sum": "5af8c748a0de4e8e8b303180738721a9",
"filesize": 134217728,
"download_url": "http://www.mikrotik.com/download",
"direct_download_url": "https://download.mikrotik.com/routeros/7.11.2/chr-7.11.2.img.zip",
"direct_download_url": "https://download.mikrotik.com/routeros/7.15.3/chr-7.15.3.img.zip",
"compression": "zip"
},
{
"filename": "chr-7.10.1.img",
"version": "7.10.1",
"md5sum": "917729e79b9992562f4160d461b21cac",
"filename": "chr-7.14.3.img",
"version": "7.14.3",
"md5sum": "73f527efef81b529b267a0683cb87617",
"filesize": 134217728,
"download_url": "http://www.mikrotik.com/download",
"direct_download_url": "https://download.mikrotik.com/routeros/7.10.1/chr-7.10.1.img.zip",
"direct_download_url": "https://download.mikrotik.com/routeros/7.14.3/chr-7.14.3.img.zip",
"compression": "zip"
},
{
"filename": "chr-7.7.img",
"version": "7.7",
"md5sum": "efc4fdeb1cc06dc240a14f1215fd59b3",
"filesize": 134217728,
"download_url": "http://www.mikrotik.com/download",
"direct_download_url": "https://download.mikrotik.com/routeros/7.7/chr-7.7.img.zip",
"compression": "zip"
},
{
"filename": "chr-7.6.img",
"version": "7.6",
"md5sum": "864482f9efaea9d40910c050318f65b9",
"filesize": 134217728,
"download_url": "http://www.mikrotik.com/download",
"direct_download_url": "https://download.mikrotik.com/routeros/7.6/chr-7.6.img.zip",
"compression": "zip"
},
{
"filename": "chr-7.3.1.img",
"version": "7.3.1",
"md5sum": "99f8ea75f8b745a8bf5ca3cc1bd325e3",
"filesize": 134217728,
"download_url": "http://www.mikrotik.com/download",
"direct_download_url": "https://download.mikrotik.com/routeros/7.3.1/chr-7.3.1.img.zip",
"compression": "zip"
},
{
"filename": "chr-7.1.5.img",
"version": "7.1.5",
"md5sum": "9c0be05f891df2b1400bdae5e719898e",
"filesize": 134217728,
"download_url": "http://www.mikrotik.com/download",
"direct_download_url": "https://download.mikrotik.com/routeros/7.1.5/chr-7.1.5.img.zip",
"compression": "zip"
},
{
"filename": "chr-6.49.10.img",
"version": "6.49.10",
"md5sum": "49ae1ecfe310aea1df37b824aa13cf84",
"filename": "chr-6.49.17.img",
"version": "6.49.17",
"md5sum": "ad9f4bd8cd4965a403350deeb5d35b96",
"filesize": 67108864,
"download_url": "http://www.mikrotik.com/download",
"direct_download_url": "https://download.mikrotik.com/routeros/6.49.10/chr-6.49.10.img.zip",
"direct_download_url": "https://download.mikrotik.com/routeros/6.49.17/chr-6.49.17.img.zip",
"compression": "zip"
},
{
"filename": "chr-6.49.6.img",
"version": "6.49.6",
"md5sum": "ae27d38acc9c4dcd875e0f97bcae8d97",
"filename": "chr-6.49.13.img",
"version": "6.49.13",
"md5sum": "18349e1c3209495e571bcbee8a7e3259",
"filesize": 67108864,
"download_url": "http://www.mikrotik.com/download",
"direct_download_url": "https://download.mikrotik.com/routeros/6.49.6/chr-6.49.6.img.zip",
"compression": "zip"
},
{
"filename": "chr-6.48.6.img",
"version": "6.48.6",
"md5sum": "875574a561570227ff8f395aabe478c6",
"filesize": 67108864,
"download_url": "http://www.mikrotik.com/download",
"direct_download_url": "https://download.mikrotik.com/routeros/6.48.6/chr-6.48.6.img.zip",
"direct_download_url": "https://download.mikrotik.com/routeros/6.49.13/chr-6.49.13.img.zip",
"compression": "zip"
}
],
"versions": [
{
"name": "7.11.2",
"name": "7.16",
"images": {
"hda_disk_image": "chr-7.11.2.img"
"hda_disk_image": "chr-7.16.img"
}
},
{
"name": "7.10.1",
"name": "7.15.3",
"images": {
"hda_disk_image": "chr-7.10.1.img"
"hda_disk_image": "chr-7.15.3.img"
}
},
{
"name": "7.7",
"name": "7.14.3",
"images": {
"hda_disk_image": "chr-7.7.img"
"hda_disk_image": "chr-7.14.3.img"
}
},
{
"name": "7.6",
"name": "6.49.17",
"images": {
"hda_disk_image": "chr-7.6.img"
"hda_disk_image": "chr-6.49.17.img"
}
},
{
"name": "7.3.1",
"name": "6.49.13",
"images": {
"hda_disk_image": "chr-7.3.1.img"
}
},
{
"name": "7.1.5",
"images": {
"hda_disk_image": "chr-7.1.5.img"
}
},
{
"name": "6.49.10",
"images": {
"hda_disk_image": "chr-6.49.10.img"
}
},
{
"name": "6.49.6",
"images": {
"hda_disk_image": "chr-6.49.6.img"
}
},
{
"name": "6.48.6",
"images": {
"hda_disk_image": "chr-6.48.6.img"
"hda_disk_image": "chr-6.49.13.img"
}
}
]
+52
View File
@@ -0,0 +1,52 @@
{
"appliance_id": "00714342-14b2-4281-aa20-9043ca8dc26e",
"name": "NixOS",
"category": "guest",
"description": "NixOS QEMU Appliance for images created with nixos-generator. Automatically sets hostname based on vmname.",
"vendor_name": "NixOS",
"vendor_url": "https://nixos.org/",
"vendor_logo_url": "https://avatars.githubusercontent.com/u/487568",
"documentation_url": "https://github.com/ob7/gns3-nixos-appliance",
"product_name": "NixOS",
"product_url": "https://github.com/NixOS/nixpkgs",
"registry_version": 4,
"status": "experimental",
"availability": "free",
"maintainer": "ob7dev",
"maintainer_email": "dev@ob7.us",
"usage": "For custom NixOS images, create qcow2 VM with: nixos-generate -f qcow -c ./server.nix Import it into GNS3 as image. VM name is passed into QEMU guest with Advanced Options field entry: -fw_cfg name=opt/vm_hostname,string=%vm-name%",
"symbol": ":/symbols/affinity/circle/gray/template.svg",
"first_port_name": "eth0",
"port_name_format": "eth{0}",
"qemu": {
"adapter_type": "e1000",
"adapters": 4,
"ram": 256,
"cpus": 1,
"hda_disk_interface": "ide",
"arch": "x86_64",
"console_type": "telnet",
"kvm": "allow",
"options": "-fw_cfg name=opt/vm_hostname,string=%vm-name%",
"on_close": "power_off"
},
"images": [
{
"filename": "nixos-24-11.qcow2",
"version": "24.11",
"md5sum": "2459f05136836dd430402d75cba0f205",
"download_url": "https://github.com/nix-community/nixos-generators",
"filesize": 1749483520,
"download_url": "https://f.ob7.us/gns3/",
"direct_download_url": "http://ob7.us/nixos-24-11.qcow2"
}
],
"versions": [
{
"name": "24.11",
"images": {
"hda_disk_image": "nixos-24-11.qcow2"
}
}
]
}
@@ -16,6 +16,6 @@
"docker": {
"adapters": 16,
"image": "gns3/openvswitch:latest",
"environment": "MANAGEMENT_INTERFACE=1"
"environment": "MANAGEMENT_INTERFACE=eth0"
}
}
+15 -2
View File
@@ -26,7 +26,14 @@
},
"images": [
{
"filename": "OPNsense-24.1-OpenSSL-nano-amd64.img",
"filename": "OPNsense-24.7-nano-amd64.img",
"version": "24.7",
"md5sum": "4f75dc2c948b907cbf73763b1539677c",
"filesize": 3221225472,
"download_url": "https://opnsense.c0urier.net/releases/24.7/"
},
{
"filename": "OPNsense-24.1-nano-amd64.img",
"version": "24.1",
"md5sum": "ea8472df2c272419b7834cddaf68048d",
"filesize": 3221225472,
@@ -69,10 +76,16 @@
}
],
"versions": [
{
"name": "24.7",
"images": {
"hda_disk_image": "OPNsense-24.7-nano-amd64.img"
}
},
{
"name": "24.1",
"images": {
"hda_disk_image": "OPNsense-24.1-OpenSSL-nano-amd64.img"
"hda_disk_image": "OPNsense-24.1-nano-amd64.img"
}
},
{
+26
View File
@@ -28,6 +28,20 @@
},
"images": [
{
"filename": "PA-VM-KVM-11.0.0.qcow2",
"version": "11.0.0",
"md5sum": "fc54b0e680ca2bcecb5522430e420f06",
"filesize": 4130865152,
"download_url": "https://support.paloaltonetworks.com/Updates/SoftwareUpdates/"
},
{
"filename": "PA-VM-KVM-10.2.3.qcow2",
"version": "10.2.3",
"md5sum": "0e7b2a52d1447186d335ef9a1a197c6c",
"filesize": 5298585600,
"download_url": "https://support.paloaltonetworks.com/Updates/SoftwareUpdates/"
},
{
"filename": "PA-VM-KVM-10.1.0.qcow2",
"version": "10.1.0",
"md5sum": "8266fd412a22694749f2cd4afcd5fa33",
@@ -128,6 +142,18 @@
],
"versions": [
{
"name": "11.0.0",
"images": {
"hda_disk_image": "PA-VM-KVM-11.0.0.qcow2"
}
},
{
"name": "10.2.3",
"images": {
"hda_disk_image": "PA-VM-KVM-10.2.3.qcow2"
}
},
{
"name": "10.1.0",
"images": {
"hda_disk_image": "PA-VM-KVM-10.1.0.qcow2"
+14
View File
@@ -24,6 +24,13 @@
"process_priority": "normal"
},
"images": [
{
"filename": "pfSense-CE-2.7.2-RELEASE-amd64.iso",
"version": "2.7.2",
"md5sum": "50c3e723d68ec74d038041a34fa846f8",
"filesize": 874672128,
"download_url": "https://www.pfsense.org/download/mirror.php?section=downloads"
},
{
"filename": "pfSense-CE-2.7.0-RELEASE-amd64.iso",
"version": "2.7.0",
@@ -76,6 +83,13 @@
}
],
"versions": [
{
"name": "2.7.2",
"images": {
"hda_disk_image": "empty100G.qcow2",
"cdrom_image": "pfSense-CE-2.7.2-RELEASE-amd64.iso"
}
},
{
"name": "2.7.0",
"images": {
+10 -10
View File
@@ -24,17 +24,17 @@
},
"images": [
{
"filename": "ReactOS-0.4.14-release-15-gb6088a6.iso",
"version": "Installer-0.4.14-release-15",
"md5sum": "af4be6b27463446905f155f14232d2b4",
"filename": "ReactOS-0.4.14-release-21-g1302c1b.iso",
"version": "Installer-0.4.14-release-21",
"md5sum": "a30bc9143788c76ed584ffd5d25fddfe",
"filesize": 140509184,
"download_url": "https://reactos.org/download",
"direct_download_url": "https://sourceforge.net/projects/reactos/files/ReactOS/0.4.14/ReactOS-0.4.14-release-21-g1302c1b-iso.zip/download"
},
{
"filename": "ReactOS-0.4.14-release-15-gb6088a6-Live.iso",
"version": "Live-0.4.14-release-15",
"md5sum": "73c1a0169a9a3b8a4feb91f4d00f5e97",
"filename": "ReactOS-0.4.14-release-21-g1302c1b-Live.iso",
"version": "Live-0.4.14-release-21",
"md5sum": "fc362820069adeea088b3a48dcfa3f9e",
"filesize": 267386880,
"download_url": "https://reactos.org/download",
"direct_download_url": "https://sourceforge.net/projects/reactos/files/ReactOS/0.4.14/ReactOS-0.4.14-release-21-g1302c1b-live.zip/download"
@@ -50,17 +50,17 @@
],
"versions": [
{
"name": "Installer-0.4.14-release-15",
"name": "Installer-0.4.14-release-21",
"images": {
"hda_disk_image": "empty30G.qcow2",
"cdrom_image": "ReactOS-0.4.14-release-15-gb6088a6.iso"
"cdrom_image": "ReactOS-0.4.14-release-21-g1302c1b.iso"
}
},
{
"name": "Live-0.4.14-release-15",
"name": "Live-0.4.14-release-21",
"images": {
"hda_disk_image": "empty30G.qcow2",
"cdrom_image": "ReactOS-0.4.14-release-15-gb6088a6-Live.iso"
"cdrom_image": "ReactOS-0.4.14-release-21-g1302c1b-Live.iso"
}
}
]
+27 -3
View File
@@ -13,18 +13,27 @@
"status": "stable",
"maintainer": "Brent Stewart",
"maintainer_email": "brent@stewart.tc",
"usage": "Your default account will have sudo priviledges. Squil and Squert username and password are configured in the Setup wizard. MySQL root is set to null. For more info see https://github.com/Security-Onion-Solutions/security-onion/wiki/Passwords.",
"usage": "Your default account will have sudo privileges. Squil and Squert username and password are configured in the Setup wizard. MySQL root is set to null. For more info see https://github.com/Security-Onion-Solutions/security-onion/wiki/Passwords.",
"symbol": "securityonion-logo.png",
"qemu": {
"adapter_type": "e1000",
"adapters": 2,
"ram": 3072,
"ram": 4096,
"hda_disk_interface": "ide",
"arch": "x86_64",
"console_type": "vnc",
"kvm": "allow"
"kvm": "allow",
"options": "-cpu host"
},
"images": [
{
"filename": "securityonion-2.4.80-20240624.iso",
"version": "2.4.80-20240624",
"md5sum": "139f9762e926f9cb3c4a9528a3752c31",
"filesize": 12391022592,
"download_url": "https://github.com/Security-Onion-Solutions/securityonion/blob/2.4/main/DOWNLOAD_AND_VERIFY_ISO.md",
"direct_download_url": "https://download.securityonion.net/file/securityonion/securityonion-2.4.80-20240624.iso"
},
{
"filename": "securityonion-16.04.7.1.iso",
"version": "16.04.7.1",
@@ -49,6 +58,14 @@
"download_url": "https://github.com/Security-Onion-Solutions/security-onion/releases/",
"direct_download_url": "https://github.com/Security-Onion-Solutions/security-onion/releases/download/v14.04.5.4_20171031/securityonion-14.04.5.4.iso"
},
{
"filename": "empty100G.qcow2",
"version": "1.0",
"md5sum": "5d9fec18a980f13002028491259f158d",
"filesize": 198656,
"download_url": "https://github.com/riverbed/Riverbed-Community-Toolkit/raw/master/SteelHead/GNS3",
"direct_download_url": "https://github.com/riverbed/Riverbed-Community-Toolkit/raw/master/SteelHead/GNS3/empty100G.qcow2"
},
{
"filename": "empty30G.qcow2",
"version": "1.0",
@@ -59,6 +76,13 @@
}
],
"versions": [
{
"name": "2.4.80-20240624",
"images": {
"hda_disk_image": "empty100G.qcow2",
"cdrom_image": "securityonion-2.4.80-20240624.iso"
}
},
{
"name": "16.04.7.1",
"images": {
+104
View File
@@ -0,0 +1,104 @@
{
"appliance_id": "8c19ccaa-a1d0-4473-94a2-a93b64924d88",
"name": "TrueNAS",
"category": "guest",
"description": "TrueNAS is a family of network-attached storage (NAS) products produced by iXsystems, incorporating both FOSS, as well as commercial offerings. Based on the OpenZFS file system, TrueNAS runs on FreeBSD as well as Linux and is available under the BSD License It is compatible with x86-64 hardware and is also available as turnkey appliances from iXsystems.",
"vendor_name": "iXsystems",
"vendor_url": "https://www.truenas.com/",
"documentation_url": "https://www.truenas.com/docs/",
"product_name": "TrueNAS",
"product_url": "https://www.truenas.com/",
"registry_version": 4,
"status": "stable",
"maintainer": "GNS3 Team",
"maintainer_email": "developers@gns3.net",
"usage": "To install TrueNAS SCALE you may have to select the Legacy BIOS option.",
"port_name_format": "eth{0}",
"qemu": {
"adapter_type": "e1000",
"adapters": 1,
"ram": 8192,
"hda_disk_interface": "ide",
"hdb_disk_interface": "ide",
"arch": "x86_64",
"console_type": "vnc",
"boot_priority": "cd",
"kvm": "require"
},
"images": [
{
"filename": "TrueNAS-13.0-U6.2.iso",
"version": "CORE 13.0 U6.2",
"md5sum": "8b2882b53af5e9f3ca905c6acdee1690",
"filesize": 1049112576,
"download_url": "https://www.truenas.com/download-truenas-core/",
"direct_download_url": "https://download-core.sys.truenas.net/13.0/STABLE/U6.2/x64/TrueNAS-13.0-U6.2.iso"
},
{
"filename": "TrueNAS-13.3-RELEASE.iso",
"version": "CORE 13.3 RELEASE",
"md5sum": "8bb16cfb06f3f1374a27cf6aebb14ed3",
"filesize": 995567616,
"download_url": "https://www.truenas.com/download-truenas-core/",
"direct_download_url": "https://download-core.sys.truenas.net/13.3/STABLE/RELEASE/x64/TrueNAS-13.3-RELEASE.iso"
},
{
"filename": "TrueNAS-SCALE-24.04.2.2.iso",
"version": "SCALE 24.04.2.2",
"md5sum": "47d9026254a0775800bb2b8ab6d874fd",
"filesize": 1630355456,
"download_url": "https://www.truenas.com/download-truenas-scale/",
"direct_download_url": "https://download.sys.truenas.net/TrueNAS-SCALE-Dragonfish/24.04.2.2/TrueNAS-SCALE-24.04.2.2.iso"
},
{
"filename": "TrueNAS-SCALE-24.10-BETA.1.iso",
"version": "SCALE 24.10-BETA.1",
"md5sum": "cc3d5758d1db3d55ae9c8716f5d43b88",
"filesize": 1491378176,
"download_url": "https://www.truenas.com/download-truenas-scale/",
"direct_download_url": "https://download.sys.truenas.net/TrueNAS-SCALE-ElectricEel-BETA/24.10-BETA.1/TrueNAS-SCALE-24.10-BETA.1.iso"
},
{
"filename": "empty30G.qcow2",
"version": "1.0",
"md5sum": "3411a599e822f2ac6be560a26405821a",
"filesize": 197120,
"download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/",
"direct_download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty30G.qcow2/download"
}
],
"versions": [
{
"name": "CORE 13.0 U6.2",
"images": {
"hda_disk_image": "empty30G.qcow2",
"hdb_disk_image": "empty30G.qcow2",
"cdrom_image": "TrueNAS-13.0-U6.2.iso"
}
},
{
"name": "CORE 13.3 RELEASE",
"images": {
"hda_disk_image": "empty30G.qcow2",
"hdb_disk_image": "empty30G.qcow2",
"cdrom_image": "TrueNAS-13.3-RELEASE.iso"
}
},
{
"name": "SCALE 24.04.2.2",
"images": {
"hda_disk_image": "empty30G.qcow2",
"hdb_disk_image": "empty30G.qcow2",
"cdrom_image": "TrueNAS-SCALE-24.04.2.2.iso"
}
},
{
"name": "SCALE 24.10-BETA.1",
"images": {
"hda_disk_image": "empty30G.qcow2",
"hdb_disk_image": "empty30G.qcow2",
"cdrom_image": "TrueNAS-SCALE-24.10-BETA.1.iso"
}
}
]
}
+35 -20
View File
@@ -28,36 +28,44 @@
},
"images": [
{
"filename": "ubuntu-23.04-server-cloudimg-amd64.img",
"version": "Ubuntu 23.04 (Lunar Lobster)",
"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-amd64.img"
"filename": "ubuntu-24.10-server-cloudimg-amd64.img",
"version": "Ubuntu 24.10 (Oracular Oriole)",
"md5sum": "f2960f8743efedd0a4968bfcd9451782",
"filesize": 627360256,
"download_url": "https://cloud-images.ubuntu.com/releases/oracular/release-20241009/",
"direct_download_url": "https://cloud-images.ubuntu.com/releases/oracular/release-20241009/ubuntu-24.10-server-cloudimg-amd64.img"
},
{
"filename": "ubuntu-24.04-server-cloudimg-amd64.img",
"version": "Ubuntu 24.04 LTS (Noble Numbat)",
"md5sum": "a1c8a01953578ad432cbef03db2f3161",
"filesize": 587241984,
"download_url": "https://cloud-images.ubuntu.com/releases/noble/release-20241004/",
"direct_download_url": "https://cloud-images.ubuntu.com/releases/noble/release-20241004/ubuntu-24.04-server-cloudimg-amd64.img"
},
{
"filename": "ubuntu-22.04-server-cloudimg-amd64.img",
"version": "Ubuntu 22.04 LTS (Jammy Jellyfish)",
"md5sum": "3ce0b84f9592482fb645e8253b979827",
"filesize": 686096384,
"download_url": "https://cloud-images.ubuntu.com/releases/jammy/release",
"direct_download_url": "https://cloud-images.ubuntu.com/releases/jammy/release/ubuntu-22.04-server-cloudimg-amd64.img"
"md5sum": "8f9a70435dc5b0b86cf5d0d4716b6091",
"filesize": 653668352,
"download_url": "https://cloud-images.ubuntu.com/releases/jammy/release-20241002/",
"direct_download_url": "https://cloud-images.ubuntu.com/releases/jammy/release-20241002/ubuntu-22.04-server-cloudimg-amd64.img"
},
{
"filename": "ubuntu-20.04-server-cloudimg-amd64.img",
"version": "Ubuntu 20.04 LTS (Focal Fossa)",
"md5sum": "044bc979b2238192ee3edb44e2bb6405",
"filesize": 552337408,
"download_url": "https://cloud-images.ubuntu.com/releases/focal/release-20210119.1/",
"direct_download_url": "https://cloud-images.ubuntu.com/releases/focal/release-20210119.1/ubuntu-20.04-server-cloudimg-amd64.img"
"md5sum": "1dff90e16acb0167c27ff82e4ac1813a",
"filesize": 627310592,
"download_url": "https://cloud-images.ubuntu.com/releases/focal/release-20240821/",
"direct_download_url": "https://cloud-images.ubuntu.com/releases/focal/release-20240821/ubuntu-20.04-server-cloudimg-amd64.img"
},
{
"filename": "ubuntu-18.04-server-cloudimg-amd64.img",
"version": "Ubuntu 18.04 LTS (Bionic Beaver)",
"md5sum": "f4134e7fa16d7fa766c7467cbe25c949",
"filesize": 336134144,
"download_url": "https://cloud-images.ubuntu.com/releases/18.04/release-20180426.2/",
"direct_download_url": "https://cloud-images.ubuntu.com/releases/18.04/release-20180426.2/ubuntu-18.04-server-cloudimg-amd64.img"
"md5sum": "62fa110eeb0459c1ff166f897aeb9f78",
"filesize": 405667840,
"download_url": "https://cloud-images.ubuntu.com/releases/bionic/release-20230607/",
"direct_download_url": "https://cloud-images.ubuntu.com/releases/bionic/release-20230607/ubuntu-18.04-server-cloudimg-amd64.img"
},
{
"filename": "ubuntu-cloud-init-data.iso",
@@ -70,9 +78,16 @@
],
"versions": [
{
"name": "Ubuntu 23.04 (Lunar Lobster)",
"name": "Ubuntu 24.10 (Oracular Oriole)",
"images": {
"hda_disk_image": "ubuntu-23.04-server-cloudimg-amd64.img",
"hda_disk_image": "ubuntu-24.10-server-cloudimg-amd64.img",
"cdrom_image": "ubuntu-cloud-init-data.iso"
}
},
{
"name": "Ubuntu 24.04 LTS (Noble Numbat)",
"images": {
"hda_disk_image": "ubuntu-24.04-server-cloudimg-amd64.img",
"cdrom_image": "ubuntu-cloud-init-data.iso"
}
},
+1 -1
View File
@@ -14,7 +14,7 @@
"symbol": "linux_guest.svg",
"docker": {
"adapters": 1,
"image": "gns3/ubuntu:focal",
"image": "gns3/ubuntu:noble",
"console_type": "telnet"
}
}
+13
View File
@@ -27,6 +27,13 @@
"options": "-vga qxl"
},
"images": [
{
"filename": "Ubuntu 24.04 (64bit).vmdk",
"version": "24.04",
"md5sum": "7709a5a1cf888c7644d245c42d217918",
"filesize": 6432555008,
"download_url": "https://www.osboxes.org/ubuntu/"
},
{
"filename": "Ubuntu 22.04 (64bit).vmdk",
"version": "22.04",
@@ -57,6 +64,12 @@
}
],
"versions": [
{
"name": "24.04",
"images": {
"hda_disk_image": "Ubuntu 24.04 (64bit).vmdk"
}
},
{
"name": "22.04",
"images": {
@@ -10,8 +10,8 @@
"product_url": "http://www.cisco.com/",
"registry_version": 4,
"status": "experimental",
"maintainer": "Laurent LEVIER",
"maintainer_email": "laurent.levier@orange.com",
"maintainer": "Christopher Uhrig",
"maintainer_email": "christopher.uhrig@telekom.de",
"usage": "Initial username is admin, password is admin as well.",
"first_port_name": "Management0/0",
"port_name_format": "Ge0/{0}",
@@ -39,6 +39,20 @@
"md5sum": "4aa487101d4cdc390f53a6e8b6f45ca7",
"filesize": 328400896,
"download_url": "http://www.cisco.com/"
},
{
"filename": "viptela-edge-20.9.5.1-genericx86-64.qcow2",
"version": "20.9.5.1",
"md5sum": "41d9e981908fd83695de78d6ca5794bd",
"filesize": 409468928,
"download_url": "https://software.cisco.com/download/home/286320995/type/286321047/release/20.9.5.1"
},
{
"filename": "viptela-edge-20.12.4-genericx86-64.qcow2",
"version": "20.12.4",
"md5sum": "9f1aedada5e632c7bc29a51c004f4486",
"filesize": 411762688,
"download_url": "https://software.cisco.com/download/home/286320995/type/286321047/release/20.12.4"
}
],
"versions": [
@@ -53,6 +67,18 @@
"images": {
"hda_disk_image": "viptela-edge-genericx86-64.qcow2"
}
},
{
"name": "20.9.5.1",
"images": {
"hda_disk_image": "viptela-edge-20.9.5.1-genericx86-64.qcow2"
}
},
{
"name": "20.12.4",
"images": {
"hda_disk_image": "viptela-edge-20.12.4-genericx86-64.qcow2"
}
}
]
}
@@ -24,6 +24,20 @@
"options": "-smp 2,maxcpus=2 -cpu host"
},
"images": [
{
"filename": "viptela-smart-20.12.4-genericx86-64.qcow2",
"version": "20.12.4",
"md5sum": "0e7b6468498a89195ab815260bc4cfb6",
"filesize": 411762688,
"download_url": "https://software.cisco.com/download/home/286320995/type/286321043/release/20.12.4"
},
{
"filename": "viptela-smart-20.9.5.1-genericx86-64.qcow2",
"version": "20.9.5.1",
"md5sum": "08e105778bb68f8f24f323dfd263a91a",
"filesize": 409468928,
"download_url": "https://software.cisco.com/download/home/286320995/type/286321043/release/20.9.5.1"
},
{
"filename": "viptela-smart-19.2.0-genericx86-64.qcow2",
"version": "19.2.0",
@@ -31,7 +45,7 @@
"filesize": 328400896,
"download_url": "http://www.cisco.com/"
},
{
{
"filename": "viptela-smart-genericx86-64-disk1.vmdk",
"version": "18.3.7",
"md5sum": "ab9b06c212319336810a4b336ec3dd96",
@@ -51,6 +65,18 @@
"images": {
"hda_disk_image": "viptela-smart-19.2.0-genericx86-64.qcow2"
}
},
{
"name": "20.9.5.1",
"images": {
"hda_disk_image": "viptela-smart-20.9.5.1-genericx86-64.qcow2"
}
},
{
"name": "20.12.4",
"images": {
"hda_disk_image": "viptela-smart-20.12.4-genericx86-64.qcow2"
}
}
]
}
@@ -10,8 +10,8 @@
"product_url": "http://www.cisco.com/",
"registry_version": 4,
"status": "experimental",
"maintainer": "Laurent LEVIER",
"maintainer_email": "laurent.levier@orange.com",
"maintainer": "Christopher Uhrig",
"maintainer_email": "christopher.uhrig@telekom.de",
"usage": "Initial username is admin, password is admin as well.",
"qemu": {
"adapter_type": "vmxnet3",
@@ -25,14 +25,28 @@
"options": "-cpu host -smp 2,maxcpus=2"
},
"images": [
{
{
"filename": "viptela-vmanage-20.12.4-genericx86-64.qcow2",
"version": "20.12.4",
"md5sum": "4e0d4c379623c495a0bb671a76a12f9f",
"filesize": 4951375872,
"download_url": "https://software.cisco.com/download/home/286320995/type/286321039/release/20.12.4"
},
{
"filename": "viptela-vmanage-20.9.5.2-genericx86-64.qcow2",
"version": "20.9.5.2",
"md5sum": "a8a4ebee0274541200f4fe94a739d454",
"filesize": 3133865984,
"download_url": "https://software.cisco.com/download/home/286320995/type/286321039/release/20.9.5.2"
},
{
"filename": "viptela-vmanage-19.2.0-genericx86-64.qcow2",
"version": "19.2.0",
"md5sum": "27ef126f178c6c929a36ad2cf6ed8db7",
"filesize": 1185349632,
"download_url": "http://www.cisco.com/"
},
{
{
"filename": "viptela-vmanage-genericx86-64-disk1.vmdk",
"version": "18.3.7",
"md5sum": "2290c6467c907d9ca9c65793fe898716",
@@ -55,6 +69,20 @@
"hda_disk_image": "viptela-vmanage-19.2.0-genericx86-64.qcow2",
"hdb_disk_image": "empty30G.qcow2"
}
},
{
"name": "20.12.4",
"images": {
"hda_disk_image": "viptela-vmanage-20.12.4-genericx86-64.qcow2",
"hdb_disk_image": "empty30G.qcow2"
}
},
{
"name": "20.9.5.2",
"images": {
"hda_disk_image": "viptela-vmanage-20.9.5.2-genericx86-64.qcow2",
"hdb_disk_image": "empty30G.qcow2"
}
},
{
"name": "18.3.7",
+103 -106
View File
@@ -1,181 +1,178 @@
{
"appliance_id": "f82b74c4-0f30-456f-a582-63daca528502",
"name": "VyOS",
"name": "VyOS Universal Router",
"category": "router",
"description": "VyOS is a community fork of Vyatta, a Linux-based network operating system that provides software-based network routing, firewall, and VPN functionality.",
"vendor_name": "Linux",
"vendor_url": "https://vyos.net/",
"description": "VyOS is an open-source network operating system that provides a comprehensive suite of features for routing, firewalling, and VPN functionality. VyOS offers a robust and flexible solution for both small-scale and large-scale network environments. It is designed to support enterprise-grade networking with the added benefits of community-driven development and continuous updates.\n\nThe VyOS Universal Router, when used in GNS3, brings the power and versatility of VyOS to network simulation and emulation. GNS3 users can deploy the VyOS Universal Router to create and test complex network topologies in a virtual environment. This appliance provides a rich set of features, including dynamic routing protocols, stateful firewall capabilities, various VPNs, as well as high availability configurations.\n\nThe seamless integration with GNS3 allows network engineers and architects to validate network designs, perform testing and troubleshooting, and enhance their skill sets in a controlled, risk-free environment.",
"vendor_name": "VyOS Inc.",
"vendor_url": "https://vyos.io/",
"vendor_logo_url": "https://raw.githubusercontent.com/GNS3/gns3-registry/master/vendor-logos/VyOS.png",
"documentation_url": "https://docs.vyos.io/",
"product_name": "VyOS",
"product_url": "https://vyos.net/",
"product_name": "VyOS Universal Router",
"product_url": "https://vyos.io/vyos-universal-router",
"registry_version": 4,
"status": "stable",
"maintainer": "GNS3 Team",
"maintainer_email": "developers@gns3.net",
"usage": "Default username/password is vyos/vyos.\n\nThe -KVM versions are ready to use, no installation is required.\nThe other images will start the router from the CDROM on initial boot. Login and then type \"install image\" and follow the instructions.",
"availability": "service-contract",
"maintainer": "VyOS Inc.",
"maintainer_email": "support@vyos.io",
"usage": "\nDefault credentials:\nUser: vyos\nPassword: vyos",
"symbol": "vyos.svg",
"port_name_format": "eth{0}",
"qemu": {
"adapter_type": "e1000",
"adapters": 3,
"ram": 512,
"hda_disk_interface": "scsi",
"adapter_type": "virtio-net-pci",
"adapters": 10,
"ram": 2048,
"cpus": 4,
"hda_disk_interface": "virtio",
"arch": "x86_64",
"console_type": "telnet",
"boot_priority": "cd",
"kvm": "allow"
"boot_priority": "c",
"kvm": "require",
"on_close": "shutdown_signal"
},
"images": [
{
"filename": "vyos-1.3.2-amd64.iso",
"filename": "vyos-1.4.0-kvm-amd64.qcow2",
"version": "1.4.0",
"md5sum": "a130e446bc5bf87391981f183ee3694b",
"filesize": 468320256,
"download_url": "https://support.vyos.io/"
},
{
"filename": "vyos-1.3.7-qemu-amd64.qcow2",
"version": "1.3.7",
"md5sum": "f4663b1e2df115bfa5c7ec17584514d6",
"filesize": 359792640,
"download_url": "https://support.vyos.io/"
},
{
"filename": "vyos-1.3.2-10G-qemu.qcow2",
"version": "1.3.2",
"md5sum": "070743faac800f9e5197058a8b6b3ba1",
"filesize": 334495744,
"download_url": "https://support.vyos.io/en/downloads/files/vyos-1-3-2-generic-iso-image"
"md5sum": "68ad3fb530213189ac9ed496d5fe7897",
"filesize": 326893568,
"download_url": "https://support.vyos.io/"
},
{
"filename": "vyos-1.3.1-S1-amd64.iso",
"filename": "vyos-1.3.1-S1-10G-qemu.qcow2",
"version": "1.3.1-S1",
"md5sum": "781f345e8a4ab9eb9e075ce5c87c8817",
"filesize": 351272960,
"download_url": "https://support.vyos.io/en/downloads/files/vyos-1-3-1-s1-generic-iso-image"
"md5sum": "d8ed9f82a983295b94b07f8e37c48ed0",
"filesize": 343801856,
"download_url": "https://support.vyos.io/"
},
{
"filename": "vyos-1.3.1-amd64.iso",
"filename": "vyos-1.3.1-10G-qemu.qcow2",
"version": "1.3.1",
"md5sum": "b6f57bd0cf9b60cdafa337b08ba4f2bc",
"filesize": 350224384,
"download_url": "https://support.vyos.io/en/downloads/files/vyos-1-3-1-generic-iso-image"
"md5sum": "482367c833990fb2b9350e3708d33dc9",
"filesize": 342556672,
"download_url": "https://support.vyos.io/"
},
{
"filename": "vyos-1.3.0-amd64.iso",
"filename": "vyos-1.3.0-10G-qemu.qcow2",
"version": "1.3.0",
"md5sum": "2019bd9c5efa6194e2761de678d0073f",
"filesize": 338690048,
"download_url": "https://support.vyos.io/en/downloads/files/vyos-1-3-0-generic-iso-image"
},
{
"filename": "vyos-1.2.9-S1-amd64.iso",
"version": "1.2.9-S1",
"md5sum": "3fece6363f9766f862e26d292d0ed5a3",
"filesize": 430964736,
"download_url": "https://support.vyos.io/en/downloads/files/vyos-1-2-9-s1-generic-iso-image",
"direct_download_url": "https://legacy-lts-images.vyos.io/1.2.9-S1/vyos-1.2.9-S1-amd64.iso"
"md5sum": "086e95e992e9b4d014c5f154cd01a6e6",
"filesize": 330956800,
"download_url": "https://support.vyos.io/"
},
{
"filename": "vyos-1.2.9-S1-10G-qemu.qcow2",
"version": "1.2.9-S1-KVM",
"version": "1.2.9-S1",
"md5sum": "0a70d78b80a3716d42487c02ef44f41f",
"filesize": 426967040,
"download_url": "https://support.vyos.io/en/downloads/files/vyos-1-2-9-s1-for-kvm",
"direct_download_url": "https://legacy-lts-images.vyos.io/1.2.9-S1/vyos-1.2.9-S1-10G-qemu.qcow2"
"download_url": "https://support.vyos.io/"
},
{
"filename": "vyos-1.2.9-amd64.iso",
"version": "1.2.9",
"md5sum": "586be23b6256173e174c82d8f1f699a1",
"filesize": 430964736,
"download_url": "https://support.vyos.io/en/downloads/files/vyos-1-2-9-generic-iso-image",
"direct_download_url": "https://legacy-lts-images.vyos.io/1.2.9/vyos-1.2.9-amd64.iso"
},
{
"filename": "vyos-1.2.9-10G-qemu.qcow2",
"version": "1.2.9-KVM",
"md5sum": "76871c7b248c32f75177c419128257ac",
"filesize": 427360256,
"download_url": "https://support.vyos.io/en/downloads/files/vyos-1-2-9-10g-qemu-qcow2",
"direct_download_url": "https://legacy-lts-images.vyos.io/1.2.9/vyos-1.2.9-10G-qemu.qcow2"
},
{
"filename": "vyos-1.2.8-amd64.iso",
"filename": "vyos-1.2.8-10G-qemu.qcow2",
"version": "1.2.8",
"md5sum": "0ad879db903efdbf1c39dc945e165931",
"filesize": 429916160,
"download_url": "https://support.vyos.io/en/downloads/files/vyos-1-2-8-generic-iso-image"
"md5sum": "96c76f619d0f8ea11dc8a3a18ed67b98",
"filesize": 425852928,
"download_url": "https://support.vyos.io/"
},
{
"filename": "vyos-1.1.8-amd64.iso",
"version": "1.1.8",
"md5sum": "95a141d4b592b81c803cdf7e9b11d8ea",
"filesize": 241172480,
"direct_download_url": "https://legacy-lts-images.vyos.io/vyos-1.1.8-amd64.iso"
"filename": "vyos-1.2.7-qemu.qcow2",
"version": "1.2.7",
"md5sum": "1be4674c970fcdd65067e504baea5d74",
"filesize": 424607744,
"download_url": "https://support.vyos.io/"
},
{
"filename": "empty8G.qcow2",
"version": "1.0",
"md5sum": "f1d2c25b6990f99bd05b433ab603bdb4",
"filesize": 197120,
"download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/",
"direct_download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty8G.qcow2/download"
"filename": "vyos-1.2.6-qemu.qcow2",
"version": "1.2.6",
"md5sum": "d8010d79889ca0ba5cb2634665e548e3",
"filesize": 424607744,
"download_url": "https://support.vyos.io/"
},
{
"filename": "vyos-1.2.5-amd64.qcow2",
"version": "1.2.5",
"md5sum": "110c22309ec480600446fd2fb4f27a0d",
"filesize": 411500544 ,
"download_url": "https://support.vyos.io/"
}
],
"versions": [
{
"name": "1.4.0",
"images": {
"hda_disk_image": "vyos-1.4.0-kvm-amd64.qcow2"
}
},
{
"name": "1.3.7",
"images": {
"hda_disk_image": "vyos-1.3.7-qemu-amd64.qcow2"
}
},
{
"name": "1.3.2",
"images": {
"hda_disk_image": "empty8G.qcow2",
"cdrom_image": "vyos-1.3.2-amd64.iso"
"hda_disk_image": "vyos-1.3.2-10G-qemu.qcow2"
}
},
{
"name": "1.3.1-S1",
"images": {
"hda_disk_image": "empty8G.qcow2",
"cdrom_image": "vyos-1.3.1-S1-amd64.iso"
"hda_disk_image": "vyos-1.3.1-S1-10G-qemu.qcow2"
}
},
{
"name": "1.3.1",
"images": {
"hda_disk_image": "empty8G.qcow2",
"cdrom_image": "vyos-1.3.1-amd64.iso"
"hda_disk_image": "vyos-1.3.1-10G-qemu.qcow2"
}
},
{
"name": "1.3.0",
"images": {
"hda_disk_image": "empty8G.qcow2",
"cdrom_image": "vyos-1.3.0-amd64.iso"
"hda_disk_image": "vyos-1.3.0-10G-qemu.qcow2"
}
},
{
"name": "1.2.9-S1",
"images": {
"hda_disk_image": "empty8G.qcow2",
"cdrom_image": "vyos-1.2.9-S1-amd64.iso"
}
},
{
"name": "1.2.9-S1-KVM",
"images": {
"hda_disk_image": "vyos-1.2.9-S1-10G-qemu.qcow2"
}
},
{
"name": "1.2.9",
"images": {
"hda_disk_image": "empty8G.qcow2",
"cdrom_image": "vyos-1.2.9-amd64.iso"
}
},
{
"name": "1.2.9-KVM",
"images": {
"hda_disk_image": "vyos-1.2.9-10G-qemu.qcow2"
}
},
{
"name": "1.2.8",
"images": {
"hda_disk_image": "empty8G.qcow2",
"cdrom_image": "vyos-1.2.8-amd64.iso"
"hda_disk_image": "vyos-1.2.8-10G-qemu.qcow2"
}
},
{
"name": "1.1.8",
"name": "1.2.7",
"images": {
"hda_disk_image": "empty8G.qcow2",
"cdrom_image": "vyos-1.1.8-amd64.iso"
"hda_disk_image": "vyos-1.2.7-qemu.qcow2"
}
},
{
"name": "1.2.6",
"images": {
"hda_disk_image": "vyos-1.2.6-qemu.qcow2"
}
},
{
"name": "1.2.5",
"images": {
"hda_disk_image": "vyos-1.2.5-amd64.qcow2"
}
}
]
+1
View File
@@ -742,6 +742,7 @@ class BaseNode:
path = shutil.which(self._manager.config.settings.Server.ubridge_path)
return path
@locking
async def _ubridge_send(self, command):
"""
Sends a command to uBridge hypervisor.
+10 -4
View File
@@ -28,6 +28,7 @@ import shutil
import platformdirs
from gns3server.utils import parse_version
from gns3server.config import Config
from gns3server.utils.asyncio import locking
from gns3server.compute.base_manager import BaseManager
from gns3server.compute.docker.docker_vm import DockerVM
@@ -87,7 +88,7 @@ class Docker(BaseManager):
f"{stdout.decode('utf-8', errors='ignore').strip()}")
except OSError as e:
raise DockerError(f"Could not install busybox: {e}")
raise DockerError("No busybox executable could be found")
raise DockerError("No busybox executable could be found, please install busybox (apt install busybox-static on Debian/Ubuntu) and make sure it is in your PATH")
@staticmethod
def resources_path():
@@ -95,8 +96,13 @@ class Docker(BaseManager):
Get the Docker resources storage directory
"""
appname = vendor = "GNS3"
docker_resources_dir = os.path.join(platformdirs.user_data_dir(appname, vendor, roaming=True), "docker", "resources")
resources_path = Config.instance().settings.Server.resources_path
if not resources_path:
appname = vendor = "GNS3"
resources_path = platformdirs.user_data_dir(appname, vendor, roaming=True)
else:
resources_path = os.path.expanduser(resources_path)
docker_resources_dir = os.path.join(resources_path, "docker")
os.makedirs(docker_resources_dir, exist_ok=True)
return docker_resources_dir
@@ -109,7 +115,7 @@ class Docker(BaseManager):
dst_path = self.resources_path()
log.info(f"Installing Docker resources in '{dst_path}'")
from gns3server.controller import Controller
Controller.instance().install_resource_files(dst_path, "compute/docker/resources")
await Controller.instance().install_resource_files(dst_path, "compute/docker/resources")
await self.install_busybox(dst_path)
except OSError as e:
raise DockerError(f"Could not install Docker resources to {dst_path}: {e}")
+56 -2
View File
@@ -34,6 +34,7 @@ from gns3server.utils.asyncio import wait_for_file_creation
from gns3server.utils.asyncio import monitor_process
from gns3server.utils.get_resource import get_resource
from gns3server.utils.hostname import is_rfc1123_hostname_valid
from gns3server.utils import macaddress_to_int, int_to_macaddress
from gns3server.compute.ubridge.ubridge_error import UbridgeError, UbridgeNamespaceError
from ..base_node import BaseNode
@@ -78,6 +79,7 @@ class DockerVM(BaseNode):
aux=None,
start_command=None,
adapters=None,
mac_address="",
environment=None,
console_type="telnet",
aux_type="none",
@@ -130,6 +132,8 @@ class DockerVM(BaseNode):
else:
self.adapters = adapters
self.mac_address = mac_address
log.debug(
"{module}: {name} [{image}] initialized.".format(
module=self.manager.module_name, name=self.name, image=self._image
@@ -145,6 +149,7 @@ class DockerVM(BaseNode):
"project_id": self._project.id,
"image": self._image,
"adapters": self.adapters,
"mac_address": self.mac_address,
"console": self.console,
"console_type": self.console_type,
"console_resolution": self.console_resolution,
@@ -190,6 +195,36 @@ class DockerVM(BaseNode):
def ethernet_adapters(self):
return self._ethernet_adapters
@property
def mac_address(self):
"""
Returns the MAC address for this Docker container.
:returns: adapter type (string)
"""
return self._mac_address
@mac_address.setter
def mac_address(self, mac_address):
"""
Sets the MAC address for this Docker container.
:param mac_address: MAC address
"""
if not mac_address:
# use the node UUID to generate a random MAC address
self._mac_address = "02:42:%s:%s:%s:00" % (self.id[2:4], self.id[4:6], self.id[6:8])
else:
self._mac_address = mac_address
log.info('Docker container "{name}" [{id}]: MAC address changed to {mac_addr}'.format(
name=self._name,
id=self._id,
mac_addr=self._mac_address)
)
@property
def start_command(self):
return self._start_command
@@ -429,6 +464,7 @@ class DockerVM(BaseNode):
"Mounts": self._mount_binds(image_infos),
"Memory": self._memory * (1024 * 1024), # convert memory to bytes
"NanoCpus": int(self._cpus * 1e9), # convert cpus to nano cpus
"UsernsMode": "host"
},
"Volumes": {},
"Env": ["container=docker"], # Systemd compliant: https://github.com/GNS3/gns3-server/issues/573
@@ -799,7 +835,10 @@ class DockerVM(BaseNode):
"""
# resize the container TTY.
await self._manager.query("POST", f"containers/{self._cid}/resize?h={rows}&w={columns}")
try:
await self._manager.query("POST", f"containers/{self._cid}/resize?h={rows}&w={columns}")
except DockerError as e:
log.warning(f"Could not resize the container TTY: {e}")
async def _start_console(self):
"""
@@ -1058,7 +1097,20 @@ class DockerVM(BaseNode):
adapter_number=adapter_number, hostif=adapter.host_ifc
)
)
log.debug("Move container %s adapter %s to namespace %s", self.name, adapter.host_ifc, self._namespace)
mac_address = int_to_macaddress(macaddress_to_int(self._mac_address) + adapter_number)
custom_adapter = self._get_custom_adapter_settings(adapter_number)
custom_mac_address = custom_adapter.get("mac_address")
if custom_mac_address:
mac_address = custom_mac_address
try:
await self._ubridge_send('docker set_mac_addr {ifc} {mac}'.format(ifc=adapter.host_ifc, mac=mac_address))
except UbridgeError:
log.warning(f"Could not set MAC address {mac_address} on interface {adapter.host_ifc}")
log.debug(f"Move container {self.name} adapter {adapter.host_ifc} to namespace {self._namespace}")
try:
await self._ubridge_send(
"docker move_to_ns {ifc} {ns} eth{adapter}".format(
@@ -1067,6 +1119,8 @@ class DockerVM(BaseNode):
)
except UbridgeError as e:
raise UbridgeNamespaceError(e)
else:
log.info(f"Created adapter {adapter_number} with MAC address {mac_address} in namespace {self._namespace}")
if nio:
await self._connect_nio(adapter_number, nio)
+5 -2
View File
@@ -25,7 +25,10 @@ PATH=/gns3/bin:/tmp/gns3/bin:/sbin:$PATH
# bootstrap busybox commands
if [ ! -d /tmp/gns3/bin ]; then
busybox mkdir -p /tmp/gns3/bin
/gns3/bin/busybox --install -s /tmp/gns3/bin
for applet in `busybox --list`
do
ln -s /gns3/bin/busybox "/tmp/gns3/bin/$applet"
done
fi
# Restore file permission and mount volumes
@@ -75,7 +78,7 @@ ip link set dev lo up
while true
do
grep $GNS3_MAX_ETHERNET /proc/net/dev > /dev/null && break
sleep 0.5
usleep 500000 # wait 0.5 seconds
done
# activate eth interfaces
@@ -1030,6 +1030,26 @@ class Router(BaseNode):
self.aux = aux
await self._hypervisor.send(f'vm set_aux_tcp_port "{self._name}" {aux}')
async def set_aux_type(self, aux_type):
"""
Sets the aux type.
:param aux_type: auxiliary console type
"""
if self.aux_type != aux_type:
status = await self.get_status()
if status == "running":
raise DynamipsError('"{name}" must be stopped to change the auxiliary console type to {aux_type}'.format(
name=self._name,
aux_type=aux_type)
)
self.aux_type = aux_type
if self._aux and aux_type == "telnet":
await self._hypervisor.send(f'vm set_aux_tcp_port "{self._name}" {self._aux}')
async def reset_console(self):
"""
Reset console
+24 -13
View File
@@ -436,14 +436,16 @@ class IOUVM(BaseNode):
)
)
async def _check_iou_licence(self):
def _is_iou_license_check_enabled(self):
"""
Checks for a valid IOU key in the iourc file (paranoid mode).
Returns if IOU license check is enabled.
:return: boolean
"""
# license check is sent by the controller
if self.license_check is False:
return
return False
try:
# we allow license check to be disabled server wide
@@ -453,7 +455,14 @@ class IOUVM(BaseNode):
if server_wide_license_check is False:
log.warning("License check is explicitly disabled on this server")
return
return False
return True
async def _check_iou_license(self):
"""
Checks for a valid IOU key in the iourc file (paranoid mode).
"""
config = configparser.ConfigParser()
try:
@@ -559,15 +568,16 @@ class IOUVM(BaseNode):
except OSError as e:
raise IOUError(f"Could not rename nvram files: {e}")
iourc_path = self.iourc_path
if not iourc_path:
raise IOUError("Could not find an iourc file (IOU license), please configure an IOU license")
if not os.path.isfile(iourc_path):
raise IOUError(f"The iourc path '{iourc_path}' is not a regular file")
iourc_path = None
if self._is_iou_license_check_enabled():
iourc_path = self.iourc_path
if not iourc_path:
raise IOUError("Could not find an iourc file (IOU license), please configure an IOU license")
if not os.path.isfile(iourc_path):
raise IOUError(f"The iourc path '{iourc_path}' is not a regular file")
await self._check_iou_license()
await self._check_iou_licence()
await self._start_ubridge()
self._create_netmap_config()
if self.use_default_iou_values:
# make sure we have the default nvram amount to correctly push the configs
@@ -579,7 +589,7 @@ class IOUVM(BaseNode):
self._nvram_watcher = FileWatcher(self._nvram_file(), self._nvram_changed, delay=2)
# created a environment variable pointing to the iourc file.
# created an environment variable pointing to the iourc file.
env = os.environ.copy()
if "IOURC" not in os.environ and iourc_path:
env["IOURC"] = iourc_path
@@ -661,7 +671,8 @@ class IOUVM(BaseNode):
self._telnet_server.close()
await self._telnet_server.wait_closed()
self._telnet_server = None
await self.start_console()
if self.is_running():
await self.start_console()
@locking
async def _networking(self):
+2 -2
View File
@@ -15,7 +15,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import asyncio
from contextlib import contextmanager
from gns3server.utils.notification_queue import NotificationQueue
@@ -54,7 +54,7 @@ class NotificationManager:
"""
for listener in self._listeners:
listener.put_nowait((action, event, kwargs))
asyncio.get_running_loop().call_soon_threadsafe(listener.put_nowait, (action, event, kwargs))
@staticmethod
def reset():
+26 -15
View File
@@ -45,7 +45,7 @@ from ..nios.nio_tap import NIOTAP
from ..base_node import BaseNode
from ...utils.asyncio import monitor_process
from ...utils.images import md5sum
from ...utils import macaddress_to_int, int_to_macaddress
from ...utils import macaddress_to_int, int_to_macaddress, is_ipv6_enabled
from ...utils.hostname import is_rfc1123_hostname_valid
from gns3server.schemas.compute.qemu_nodes import Qemu, QemuPlatform
@@ -54,6 +54,12 @@ import logging
log = logging.getLogger(__name__)
# forbidden additional options
FORBIDDEN_OPTIONS = {"-blockdev", "-drive", "-hda", "-hdb", "-hdc", "-hdd",
"-fsdev", "-virtfs", "-nic", "-netdev"}
FORBIDDEN_OPTIONS |= {"-" + opt for opt in FORBIDDEN_OPTIONS
if opt.startswith("-") and not opt.startswith("--")}
class QemuVM(BaseNode):
module_name = "qemu"
@@ -1855,14 +1861,17 @@ class QemuVM(BaseNode):
if port:
console_host = self._manager.port_manager.console_host
if console_host == "0.0.0.0":
if socket.has_ipv6:
# to fix an issue with Qemu when IPv4 is not enabled
# see https://github.com/GNS3/gns3-gui/issues/2352
# FIXME: consider making this more global (not just for Qemu + SPICE)
console_host = "::"
else:
raise QemuError("IPv6 must be enabled in order to use the SPICE console")
return ["-spice", f"addr={console_host},port={port},disable-ticketing", "-vga", "qxl"]
try:
if is_ipv6_enabled():
# to fix an issue with Qemu when IPv4 is not enabled
# see https://github.com/GNS3/gns3-gui/issues/2352
# FIXME: consider making this more global (not just for Qemu + SPICE)
console_host = "::"
except OSError as e:
raise QemuError("Could not check if IPv6 is enabled: {}".format(e))
return ["-spice",
f"addr={console_host},port={port},disable-ticketing",
"-vga", "qxl"]
else:
return []
@@ -2148,11 +2157,6 @@ class QemuVM(BaseNode):
continue
interface = getattr(self, f"hd{drive}_disk_interface")
# fail-safe: use "ide" if there is a disk image and no interface type has been explicitly configured
if interface == "none":
interface = "ide"
setattr(self, f"hd{drive}_disk_interface", interface)
disk_name = f"hd{drive}"
if not os.path.isfile(disk_image) or not os.path.exists(disk_image):
if os.path.islink(disk_image):
@@ -2640,9 +2644,16 @@ class QemuVM(BaseNode):
command.extend(self._tpm_options())
if additional_options:
try:
command.extend(shlex.split(additional_options))
additional_opt_list = shlex.split(additional_options)
except ValueError as e:
raise QemuError(f"Invalid additional options: {additional_options} error {e}")
allow_unsafe_options = self.manager.config.settings.Qemu.allow_unsafe_options
if allow_unsafe_options is False:
for opt in additional_opt_list:
if opt in FORBIDDEN_OPTIONS:
raise QemuError("Forbidden additional option: {}".format(opt))
command.extend(additional_opt_list)
# 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'])
+13 -3
View File
@@ -34,7 +34,7 @@ enable_ssl = False
certfile = /home/gns3/.config/GNS3/ssl/server.cert
certkey = /home/gns3/.config/GNS3/ssl/server.key
; Path where devices images are stored
; Path where binary images are stored
images_path = /home/gns3/GNS3/images
; Additional paths to look for images
@@ -43,15 +43,20 @@ additional_images_paths = /opt/images;/mnt/disk1/images
; Path where user projects are stored
projects_path = /home/gns3/GNS3/projects
; Path where user appliances are stored
; Path where custom user appliances are stored
appliances_path = /home/gns3/GNS3/appliances
; Path where custom device symbols are stored
; Path where custom user symbols are stored
symbols_path = /home/gns3/GNS3/symbols
; Path where custom configs are stored
configs_path = /home/gns3/GNS3/configs
; Path where files like built-in appliances and Docker resources are stored
; The default path is the local user data directory
; (Linux: "~/.local/share/GNS3", macOS: "~/Library/Application Support/GNS3", Windows: "%APPDATA%\GNS3")
; resources_path = /home/gns3/GNS3/resources
; Default symbol theme
; Currently available themes are "Classic", Affinity-square-blue", "Affinity-square-red"
; "Affinity-square-gray", "Affinity-circle-blue", "Affinity-circle-red" and "Affinity-circle-gray"
@@ -102,6 +107,9 @@ default_nat_interface = vmnet10
; Enable the built-in templates
enable_builtin_templates = True
; Install built-in appliances
install_builtin_appliances = True
; check if hardware virtualization is used by other emulators (KVM, VMware or VirtualBox)
hardware_virtualization_check = True
@@ -148,3 +156,5 @@ monitor_host = 127.0.0.1
enable_hardware_acceleration = True
; Require hardware acceleration in order to start VMs
require_hardware_acceleration = False
; Allow unsafe additional command line options
allow_unsafe_options = False
@@ -15,7 +15,7 @@ no ip icmp rate-limit unreachable
!
! due to some bugs with IOU, try to change the following line to 'ip cef' if your routing does not work
no ip cef
no ip domain-lookup
no ip domain lookup
!
!
!
@@ -14,7 +14,7 @@ no ip icmp rate-limit unreachable
!
! due to some bugs with IOU, try to change the following line to 'ip cef' if your routing does not work
no ip cef
no ip domain-lookup
no ip domain lookup
!
!
ip tcp synwait-time 5
+67 -43
View File
@@ -28,10 +28,10 @@ try:
except ImportError:
from importlib import resources as importlib_resources
from ..config import Config
from ..utils import parse_version
from ..utils import parse_version, md5sum
from ..utils.images import default_images_directory
from ..utils.asyncio import wait_run_in_executor
from .project import Project
from .appliance import Appliance
@@ -43,6 +43,7 @@ from .topology import load_topology
from .gns3vm import GNS3VM
from .gns3vm.gns3_vm_error import GNS3VMError
from .controller_error import ControllerError, ControllerNotFoundError
from ..db.tasks import update_disk_checksums
from ..version import __version__
import logging
@@ -64,7 +65,7 @@ class Controller:
self.gns3vm = GNS3VM(self)
self.symbols = Symbols()
self._appliance_manager = ApplianceManager()
self._iou_license_settings = {"iourc_content": "", "license_check": True}
self._iou_license_settings = {"iourc_content": "", "license_check": False}
self._vars_loaded = False
self._vars_file = Config.instance().controller_vars
log.info(f'Loading controller vars file "{self._vars_file}"')
@@ -72,8 +73,11 @@ class Controller:
async def start(self, computes=None):
log.info("Controller is starting")
self._install_base_configs()
self._install_builtin_disks()
await self._install_base_configs()
installed_disks = await self._install_builtin_disks()
if installed_disks:
await update_disk_checksums(installed_disks)
server_config = Config.instance().settings.Server
Config.instance().listen_for_config_changes(self._update_config)
name = server_config.name
@@ -86,12 +90,12 @@ class Controller:
if host == "0.0.0.0":
host = "127.0.0.1"
self._load_controller_vars()
await self._load_controller_vars()
if server_config.enable_ssl:
self._ssl_context = self._create_ssl_context(server_config)
protocol = server_config.protocol
protocol = server_config.protocol.value
if self._ssl_context and protocol != "https":
log.warning(f"Protocol changed to 'https' for local compute because SSL is enabled")
protocol = "https"
@@ -134,7 +138,9 @@ class Controller:
log.warning(str(e))
await self.load_projects()
await self._project_auto_open()
# start to auto open projects (if configured) 5 seconds after the controller has started
asyncio.get_event_loop().call_later(5, asyncio.create_task, self._project_auto_open())
def _create_ssl_context(self, server_config):
@@ -188,7 +194,7 @@ class Controller:
async def reload(self):
log.info("Controller is reloading")
self._load_controller_vars()
await self._load_controller_vars()
# remove all projects deleted from disk.
for project in self._projects.copy().values():
@@ -208,19 +214,15 @@ class Controller:
if self._vars_loaded:
controller_vars = {
"appliances_etag": self._appliance_manager.appliances_etag,
"iou_license_check": self._iou_license_settings["license_check"],
"version": __version__
}
if self._iou_license_settings["iourc_content"]:
iou_config = Config.instance().settings.IOU
server_config = Config.instance().settings.Server
if iou_config.iourc_path:
iourc_path = iou_config.iourc_path
else:
os.makedirs(server_config.secrets_dir, exist_ok=True)
iourc_path = os.path.join(server_config.secrets_dir, "gns3_iourc_license")
os.makedirs(server_config.secrets_dir, exist_ok=True)
iourc_path = os.path.join(server_config.secrets_dir, "iou_license")
try:
with open(iourc_path, "w+") as f:
@@ -236,7 +238,7 @@ class Controller:
except OSError as e:
log.error(f"Cannot write controller vars file '{self._vars_file}': {e}")
def _load_controller_vars(self):
async def _load_controller_vars(self):
"""
Reload the controller vars from disk
"""
@@ -251,15 +253,11 @@ class Controller:
return []
# load the IOU license settings
iou_config = Config.instance().settings.IOU
server_config = Config.instance().settings.Server
if iou_config.iourc_path:
iourc_path = iou_config.iourc_path
else:
if not server_config.secrets_dir:
server_config.secrets_dir = os.path.dirname(Config.instance().server_config)
iourc_path = os.path.join(server_config.secrets_dir, "gns3_iourc_license")
if not server_config.secrets_dir:
server_config.secrets_dir = os.path.dirname(Config.instance().server_config)
iourc_path = os.path.join(server_config.secrets_dir, "iou_license")
if os.path.exists(iourc_path):
try:
@@ -268,15 +266,23 @@ class Controller:
log.info(f"iourc file '{iourc_path}' loaded")
except OSError as e:
log.error(f"Cannot read IOU license file '{iourc_path}': {e}")
self._iou_license_settings["license_check"] = iou_config.license_check
previous_version = controller_vars.get("version")
log.info("Comparing controller version {} with config version {}".format(__version__, previous_version))
if not previous_version or \
parse_version(__version__.split("+")[0]) > parse_version(previous_version.split("+")[0]):
self._appliance_manager.install_builtin_appliances()
elif not os.listdir(self._appliance_manager.builtin_appliances_path()):
self._appliance_manager.install_builtin_appliances()
# IOU license check is disabled by default
self._iou_license_settings["license_check"] = controller_vars.get("iou_license_check", False)
log.info("IOU license check is {} on the controller".format("enabled" if self._iou_license_settings["license_check"] else "disabled"))
# install the built-in appliances if needed
if Config.instance().settings.Server.install_builtin_appliances:
previous_version = controller_vars.get("version")
log.info("Comparing controller version {} with config version {}".format(__version__, previous_version))
builtin_appliances_path = self._appliance_manager.builtin_appliances_path()
if not previous_version or \
parse_version(__version__.split("+")[0]) > parse_version(previous_version.split("+")[0]):
await self._appliance_manager.install_builtin_appliances()
elif not os.listdir(builtin_appliances_path):
await self._appliance_manager.install_builtin_appliances()
else:
log.info(f"Built-in appliances are installed in '{builtin_appliances_path}'")
self._appliance_manager.appliances_etag = controller_vars.get("appliances_etag")
self._appliance_manager.load_appliances()
@@ -303,12 +309,24 @@ class Controller:
except OSError as e:
log.error(str(e))
@staticmethod
def install_resource_files(dst_path, resource_name):
async def install_resource_files(dst_path, resource_name, upgrade_resources=True):
"""
Install files from resources to user's file system
"""
installed_resources = []
async def should_copy(src, dst, upgrade_resources):
if not os.path.exists(dst):
return True
if upgrade_resources is False:
return False
# copy the resource if it is different
src_md5 = await wait_run_in_executor(md5sum, src)
dst_md5 = await wait_run_in_executor(md5sum, dst)
return src_md5 != dst_md5
if hasattr(sys, "frozen") and sys.platform.startswith("win"):
resource_path = os.path.normpath(os.path.join(os.path.dirname(sys.executable), resource_name))
for filename in os.listdir(resource_path):
@@ -317,14 +335,16 @@ class Controller:
else:
for entry in importlib_resources.files('gns3server').joinpath(resource_name).iterdir():
full_path = os.path.join(dst_path, entry.name)
if entry.is_file() and not os.path.exists(full_path):
if entry.is_file() and await should_copy(str(entry), full_path, upgrade_resources):
log.debug(f'Installing {resource_name} resource file "{entry.name}" to "{full_path}"')
shutil.copy(str(entry), os.path.join(dst_path, entry.name))
shutil.copy(str(entry), os.path.join(full_path))
installed_resources.append(full_path)
elif entry.is_dir():
os.makedirs(full_path, exist_ok=True)
Controller.install_resource_files(full_path, os.path.join(resource_name, entry.name))
await Controller.install_resource_files(full_path, os.path.join(resource_name, entry.name))
return installed_resources
def _install_base_configs(self):
async def _install_base_configs(self):
"""
At startup we copy base configs to the user location to allow
them to customize it
@@ -333,11 +353,12 @@ class Controller:
dst_path = self.configs_path()
log.info(f"Installing base configs in '{dst_path}'")
try:
Controller.install_resource_files(dst_path, "configs")
# do not overwrite base configs because they may have been customized by the user
await Controller.install_resource_files(dst_path, "configs", upgrade_resources=False)
except OSError as e:
log.error(f"Could not install base config files to {dst_path}: {e}")
def _install_builtin_disks(self):
async def _install_builtin_disks(self):
"""
At startup we copy built-in Qemu disks to the user location to allow
them to use with appliances
@@ -346,7 +367,7 @@ class Controller:
dst_path = self.disks_path()
log.info(f"Installing built-in disks in '{dst_path}'")
try:
Controller.install_resource_files(dst_path, "disks")
return await Controller.install_resource_files(dst_path, "disks")
except OSError as e:
log.error(f"Could not install disk files to {dst_path}: {e}")
@@ -586,9 +607,12 @@ class Controller:
Auto open the project with auto open enable
"""
for project in self._projects.values():
if project.auto_open:
await project.open()
try:
for project in self._projects.values():
if project.auto_open:
await project.open()
except ControllerError as e:
log.error(f"Could not auto open projects: {e}")
def get_free_project_name(self, base_name):
"""
+11 -8
View File
@@ -95,28 +95,31 @@ class ApplianceManager:
os.makedirs(appliances_path, exist_ok=True)
return appliances_path
def builtin_appliances_path(self, delete_first=False):
def builtin_appliances_path(self):
"""
Get the built-in appliance storage directory
"""
appname = vendor = "GNS3"
appliances_dir = os.path.join(platformdirs.user_data_dir(appname, vendor, roaming=True), "appliances")
if delete_first:
shutil.rmtree(appliances_dir, ignore_errors=True)
resources_path = Config.instance().settings.Server.resources_path
if not resources_path:
appname = vendor = "GNS3"
resources_path = platformdirs.user_data_dir(appname, vendor, roaming=True)
else:
resources_path = os.path.expanduser(resources_path)
appliances_dir = os.path.join(resources_path, "appliances")
os.makedirs(appliances_dir, exist_ok=True)
return appliances_dir
def install_builtin_appliances(self):
async def install_builtin_appliances(self):
"""
At startup we copy the built-in appliances files.
"""
dst_path = self.builtin_appliances_path(delete_first=True)
dst_path = self.builtin_appliances_path()
log.info(f"Installing built-in appliances in '{dst_path}'")
from . import Controller
try:
Controller.instance().install_resource_files(dst_path, "appliances")
await Controller.instance().install_resource_files(dst_path, "appliances")
except OSError as e:
log.error(f"Could not install built-in appliance files to {dst_path}: {e}")
+8 -3
View File
@@ -18,14 +18,19 @@
import ipaddress
import aiohttp
import asyncio
import async_timeout
import socket
import json
import sys
import io
from fastapi import HTTPException
from aiohttp import web
if sys.version_info >= (3, 11):
from asyncio import timeout as asynctimeout
else:
from async_timeout import timeout as asynctimeout
from ..utils import parse_version
from ..utils.asyncio import locking
from ..controller.controller_error import (
@@ -502,8 +507,8 @@ class Compute:
""" Returns URL for specific path at Compute"""
return self._getUrl(path)
async def _run_http_query(self, method, path, data=None, timeout=20, raw=False):
async with async_timeout.timeout(delay=timeout):
async def _run_http_query(self, method, path, data=None, timeout=120, raw=False):
async with asynctimeout(delay=timeout):
url = self._getUrl(path)
headers = {"content-type": "application/json"}
chunked = None
+27 -23
View File
@@ -16,6 +16,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import os
import sys
import json
import asyncio
import aiofiles
@@ -39,7 +40,7 @@ async def export_project(
temporary_dir,
include_images=False,
include_snapshots=False,
keep_compute_id=False,
keep_compute_ids=False,
allow_all_nodes=False,
reset_mac_addresses=False,
):
@@ -54,9 +55,9 @@ async def export_project(
:param temporary_dir: A temporary dir where to store intermediate data
:param include_images: save OS images to the zip file
:param include_snapshots: save snapshots to the zip file
:param keep_compute_id: If false replace all compute id by local (standard behavior for .gns3project to make it portable)
:param allow_all_nodes: Allow all nodes type to be include in the zip even if not portable
:param reset_mac_addresses: Reset MAC addresses for every nodes.
:param keep_compute_ids: If false replace all compute IDs by local (standard behavior for .gns3project to make it portable)
:param allow_all_nodes: Allow all nodes type to be included in the zip even if not portable
:param reset_mac_addresses: Reset MAC addresses for each node.
"""
# To avoid issue with data not saved we disallow the export of a running project
@@ -77,7 +78,7 @@ async def export_project(
os.path.join(project._path, file),
zstream,
include_images,
keep_compute_id,
keep_compute_ids,
allow_all_nodes,
temporary_dir,
reset_mac_addresses,
@@ -89,14 +90,15 @@ async def export_project(
files = [f for f in files if _is_exportable(os.path.join(root, f), include_snapshots)]
for file in files:
path = os.path.join(root, file)
# check if we can export the file
try:
open(path).close()
except OSError as e:
msg = f"Could not export file {path}: {e}"
log.warning(msg)
project.emit_notification("log.warning", {"message": msg})
continue
if not os.path.islink(path):
try:
# check if we can export the file
open(path).close()
except OSError as e:
msg = f"Could not export file {path}: {e}"
log.warning(msg)
project.emit_notification("log.warning", {"message": msg})
continue
# ignore the .gns3 file
if file.endswith(".gns3"):
continue
@@ -150,7 +152,10 @@ def _patch_mtime(path):
:param path: file path
"""
st = os.stat(path)
if sys.platform.startswith("win"):
# only UNIX type platforms
return
st = os.stat(path, follow_symlinks=False)
file_date = datetime.fromtimestamp(st.st_mtime)
if file_date.year < 1980:
new_mtime = file_date.replace(year=1980).timestamp()
@@ -166,10 +171,6 @@ def _is_exportable(path, include_snapshots=False):
if include_snapshots is False and path.endswith("snapshots"):
return False
# do not export symlinks
if os.path.islink(path):
return False
# do not export directories of snapshots
if include_snapshots is False and "{sep}snapshots{sep}".format(sep=os.path.sep) in path:
return False
@@ -193,7 +194,7 @@ def _is_exportable(path, include_snapshots=False):
async def _patch_project_file(
project, path, zstream, include_images, keep_compute_id, allow_all_nodes, temporary_dir, reset_mac_addresses
project, path, zstream, include_images, keep_compute_ids, allow_all_nodes, temporary_dir, reset_mac_addresses
):
"""
Patch a project file (.gns3) to export a project.
@@ -225,16 +226,19 @@ async def _patch_project_file(
if not allow_all_nodes and node["node_type"] in ["virtualbox", "vmware"]:
raise ControllerError("Projects with a {} node cannot be exported".format(node["node_type"]))
if not keep_compute_id:
if not keep_compute_ids:
node["compute_id"] = "local" # To make project portable all node by default run on local
if "properties" in node and node["node_type"] != "docker":
if "properties" in node:
for prop, value in node["properties"].items():
# reset the MAC address
if reset_mac_addresses and prop in ("mac_addr", "mac_address"):
node["properties"][prop] = None
if node["node_type"] == "docker":
continue
if node["node_type"] == "iou":
if not prop == "path":
continue
@@ -243,13 +247,13 @@ async def _patch_project_file(
if value is None or value.strip() == "":
continue
if not keep_compute_id: # If we keep the original compute we can keep the image path
if not keep_compute_ids: # If we keep the original compute we can keep the image path
node["properties"][prop] = os.path.basename(value)
if include_images is True:
images.append({"compute_id": compute_id, "image": value, "image_type": node["node_type"]})
if not keep_compute_id:
if not keep_compute_ids:
topology["topology"][
"computes"
] = [] # Strip compute information because could contain secret info like password
+24 -3
View File
@@ -17,6 +17,7 @@
import os
import sys
import stat
import json
import uuid
import shutil
@@ -40,7 +41,7 @@ Handle the import of project from a .gns3project
"""
async def import_project(controller, project_id, stream, location=None, name=None, keep_compute_id=False,
async def import_project(controller, project_id, stream, location=None, name=None, keep_compute_ids=False,
auto_start=False, auto_open=False, auto_close=True):
"""
Import a project contain in a zip file
@@ -52,7 +53,7 @@ async def import_project(controller, project_id, stream, location=None, name=Non
:param stream: A io.BytesIO of the zipfile
:param location: Directory for the project if None put in the default directory
:param name: Wanted project name, generate one from the .gns3 if None
:param keep_compute_id: If true do not touch the compute id
:param keep_compute_ids: keep compute IDs unchanged
:returns: Project
"""
@@ -95,6 +96,7 @@ async def import_project(controller, project_id, stream, location=None, name=Non
try:
with zipfile_zstd.ZipFile(stream) as zip_file:
await wait_run_in_executor(zip_file.extractall, path)
_create_symbolic_links(zip_file, path)
except zipfile_zstd.BadZipFile:
raise ControllerError("Cannot extract files from GNS3 project (invalid zip)")
@@ -126,7 +128,7 @@ async def import_project(controller, project_id, stream, location=None, name=Non
drawing["drawing_id"] = str(uuid.uuid4())
# Modify the compute id of the node depending of compute capacity
if not keep_compute_id:
if not keep_compute_ids:
# For some VM type we move them to the GNS3 VM if possible
# unless it's a linux host without GNS3 VM
if not sys.platform.startswith("linux") or controller.has_compute("vm"):
@@ -184,6 +186,24 @@ async def import_project(controller, project_id, stream, location=None, name=Non
project = await controller.load_project(dot_gns3_path, load=False)
return project
def _create_symbolic_links(zip_file, path):
"""
Manually create symbolic links (if any) because ZipFile does not support it.
:param zip_file: ZipFile instance
:param path: project location
"""
for zip_info in zip_file.infolist():
if stat.S_ISLNK(zip_info.external_attr >> 16):
symlink_target = zip_file.read(zip_info.filename).decode()
symlink_path = os.path.join(path, zip_info.filename)
try:
# remove the regular file and replace it by a symbolic link
os.remove(symlink_path)
os.symlink(symlink_target, symlink_path)
except OSError as e:
raise ControllerError(f"Cannot create symbolic link: {e}")
def _move_node_file(path, old_id, new_id):
"""
@@ -269,6 +289,7 @@ async def _import_snapshots(snapshots_path, project_name, project_id):
with open(snapshot_path, "rb") as f:
with zipfile_zstd.ZipFile(f) as zip_file:
await wait_run_in_executor(zip_file.extractall, tmpdir)
_create_symbolic_links(zip_file, tmpdir)
except OSError as e:
raise ControllerError(f"Cannot open snapshot '{os.path.basename(snapshot)}': {e}")
except zipfile_zstd.BadZipFile:
+10 -8
View File
@@ -29,8 +29,8 @@ from .controller_error import (
)
from .ports.port_factory import PortFactory, StandardPortFactory, DynamipsPortFactory
from ..utils.images import images_directories
from ..utils import macaddress_to_int, int_to_macaddress
from ..config import Config
from ..utils.qt import qt_font_to_style
import logging
@@ -572,15 +572,11 @@ class Node:
Start a node
"""
try:
# For IOU we need to send the licence everytime
# For IOU: we need to send the licence everytime we start a node
if self.node_type == "iou":
license_check = self._project.controller.iou_license.get("license_check", True)
iourc_content = self._project.controller.iou_license.get("iourc_content", None)
# if license_check and not iourc_content:
# raise aiohttp.web.HTTPConflict(text="IOU licence is not configured")
await self.post(
"/start", timeout=240, data={"license_check": license_check, "iourc_content": iourc_content}
)
await self.post("/start", timeout=240, data={"license_check": license_check, "iourc_content": iourc_content})
else:
await self.post("/start", data=data, timeout=240)
except asyncio.TimeoutError:
@@ -758,7 +754,13 @@ class Node:
break
port_name = f"eth{adapter_number}"
port_name = custom_adapter_settings.get("port_name", port_name)
self._ports.append(PortFactory(port_name, 0, adapter_number, 0, "ethernet", short_name=port_name))
mac_address = custom_adapter_settings.get("mac_address")
if not mac_address and "mac_address" in self._properties:
mac_address = int_to_macaddress(macaddress_to_int(self._properties["mac_address"]) + adapter_number)
port = PortFactory(port_name, 0, adapter_number, 0, "ethernet", short_name=port_name)
port.mac_address = mac_address
self._ports.append(port)
elif self._node_type in ("ethernet_switch", "ethernet_hub"):
# Basic node we don't want to have adapter number
port_number = 0
+4 -4
View File
@@ -15,7 +15,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import os
import asyncio
from contextlib import contextmanager
from gns3server.utils.notification_queue import NotificationQueue
@@ -73,7 +73,7 @@ class Notification:
"""
for controller_listener in self._controller_listeners:
controller_listener.put_nowait((action, event, {}))
asyncio.get_running_loop().call_soon_threadsafe(controller_listener.put_nowait, (action, event, {}))
def project_has_listeners(self, project_id):
"""
@@ -134,7 +134,7 @@ class Notification:
except KeyError:
return
for listener in project_listeners:
listener.put_nowait((action, event, {}))
asyncio.get_running_loop().call_soon_threadsafe(listener.put_nowait, (action, event, {}))
def _send_event_to_all_projects(self, action, event):
"""
@@ -146,4 +146,4 @@ class Notification:
"""
for project_listeners in self._project_listeners.values():
for listener in project_listeners:
listener.put_nowait((action, event, {}))
asyncio.get_running_loop().call_soon_threadsafe(listener.put_nowait, (action, event, {}))
+96 -9
View File
@@ -15,6 +15,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import sys
import re
import os
import json
@@ -26,6 +27,7 @@ import asyncio
import aiofiles
import tempfile
import zipfile
import pathlib
from uuid import UUID, uuid4
@@ -41,8 +43,9 @@ from ..utils.application_id import get_next_application_id
from ..utils.asyncio.pool import Pool
from ..utils.asyncio import locking
from ..utils.asyncio import aiozipstream
from ..utils.asyncio import wait_run_in_executor
from .export_project import export_project
from .import_project import import_project
from .import_project import import_project, _move_node_file
from .controller_error import ControllerError, ControllerForbiddenError, ControllerNotFoundError
import logging
@@ -210,7 +213,11 @@ class Project:
if os.path.exists(snapshot_dir):
for snap in os.listdir(snapshot_dir):
if snap.endswith(".gns3project"):
snapshot = Snapshot(self, filename=snap)
try:
snapshot = Snapshot(self, filename=snap)
except ValueError:
log.error("Invalid snapshot file: {}".format(snap))
continue
self._snapshots[snapshot.id] = snapshot
# Create the project on demand on the compute node
@@ -491,7 +498,7 @@ class Project:
if base_name is None:
return None
base_name = re.sub(r"[ ]", "", base_name)
base_name = re.sub(r"[ ]", "", base_name) # remove spaces in node name
if base_name in self._allocated_node_names:
base_name = re.sub(r"[0-9]+$", "{0}", base_name)
@@ -588,7 +595,7 @@ class Project:
if node_type == "iou":
async with self._iou_id_lock:
# wait for a IOU node to be completely created before adding a new one
# wait for an IOU node to be completely created before adding a new one
# this is important otherwise we allocate the same application ID (used
# to generate MAC addresses) when creating multiple IOU node at the same time
if "properties" in kwargs.keys():
@@ -1058,13 +1065,15 @@ class Project:
"""
Duplicate a project
It's the save as feature of the 1.X. It's implemented on top of the
export / import features. It will generate a gns3p and reimport it.
It's a little slower but we have only one implementation to maintain.
Implemented on top of the export / import features. It will generate a gns3p and reimport it.
NEW: fast duplication is used if possible (when there are no remote computes).
If not, the project is exported and reimported as explained above.
:param name: Name of the new project. A new one will be generated in case of conflicts
:param reset_mac_addresses: Reset MAC addresses for the new project
"""
# If the project was not open we open it temporary
previous_status = self._status
if self._status == "closed":
@@ -1072,6 +1081,18 @@ class Project:
self.dump()
assert self._status != "closed"
try:
proj = await self._fast_duplication(name, reset_mac_addresses)
if proj:
if previous_status == "closed":
await self.close()
return proj
else:
log.info("Fast duplication failed, fallback to normal duplication")
except Exception as e:
raise ControllerError(f"Cannot duplicate project: {str(e)}")
try:
begin = time.time()
@@ -1087,7 +1108,7 @@ class Project:
zstream,
self,
tmpdir,
keep_compute_id=True,
keep_compute_ids=True,
allow_all_nodes=True,
reset_mac_addresses=reset_mac_addresses,
)
@@ -1106,7 +1127,7 @@ class Project:
str(uuid.uuid4()),
f,
name=name,
keep_compute_id=True
keep_compute_ids=True
)
log.info(f"Project '{project.name}' duplicated in {time.time() - begin:.4f} seconds")
@@ -1310,3 +1331,69 @@ class Project:
def __repr__(self):
return f"<gns3server.controller.Project {self._name} {self._id}>"
async def _fast_duplication(self, name=None, reset_mac_addresses=True):
"""
Fast duplication of a project.
Copy the project files directly rather than in an import-export fashion.
:param name: Name of the new project. A new one will be generated in case of conflicts
:param reset_mac_addresses: Reset MAC addresses for the new project
"""
# remote replication is not supported with remote computes
for compute in self.computes:
if compute.id != "local":
log.warning("Fast duplication is not supported with remote compute: '{}'".format(compute.id))
return None
# work dir
p_work = pathlib.Path(self.path).parent.absolute()
t0 = time.time()
new_project_id = str(uuid.uuid4())
new_project_path = p_work.joinpath(new_project_id)
# copy dir
await wait_run_in_executor(shutil.copytree, self.path, new_project_path.as_posix(), symlinks=True, ignore_dangling_symlinks=True)
log.info("Project content copied from '{}' to '{}' in {}s".format(self.path, new_project_path, time.time() - t0))
topology = json.loads(new_project_path.joinpath('{}.gns3'.format(self.name)).read_bytes())
project_name = name or topology["name"]
# If the project name is already used we generate a new one
project_name = self.controller.get_free_project_name(project_name)
topology["name"] = project_name
# To avoid unexpected behavior (project start without manual operations just after import)
topology["auto_start"] = False
topology["auto_open"] = False
topology["auto_close"] = False
# change node ID
node_old_to_new = {}
for node in topology["topology"]["nodes"]:
new_node_id = str(uuid.uuid4())
if "node_id" in node:
node_old_to_new[node["node_id"]] = new_node_id
_move_node_file(new_project_path, node["node_id"], new_node_id)
node["node_id"] = new_node_id
if reset_mac_addresses:
if "properties" in node:
for prop, value in node["properties"].items():
# reset the MAC address
if prop in ("mac_addr", "mac_address"):
node["properties"][prop] = None
# change link ID
for link in topology["topology"]["links"]:
link["link_id"] = str(uuid.uuid4())
for node in link["nodes"]:
node["node_id"] = node_old_to_new[node["node_id"]]
# Generate new drawings id
for drawing in topology["topology"]["drawings"]:
drawing["drawing_id"] = str(uuid.uuid4())
# And we dump the updated.gns3
dot_gns3_path = new_project_path.joinpath('{}.gns3'.format(project_name))
topology["project_id"] = new_project_id
with open(dot_gns3_path, "w+") as f:
json.dump(topology, f, indent=4)
os.remove(new_project_path.joinpath('{}.gns3'.format(self.name)))
project = await self.controller.load_project(dot_gns3_path, load=False)
log.info("Project '{}' fast duplicated in {:.4f} seconds".format(project.name, time.time() - t0))
return project
+5 -10
View File
@@ -51,22 +51,17 @@ class Snapshot:
self._project = project
if name:
self._name = name
self._created_at = datetime.now().timestamp()
self._created_at = datetime.now(timezone.utc).timestamp()
filename = (
self._name
+ "_"
+ datetime.utcfromtimestamp(self._created_at).replace(tzinfo=None).strftime("%d%m%y_%H%M%S")
+ datetime.fromtimestamp(self._created_at, tz=timezone.utc).replace(tzinfo=None).strftime("%d%m%y_%H%M%S")
+ ".gns3project"
)
else:
self._name = filename.split("_")[0]
self._name = filename.rsplit("_", 2)[0]
datestring = filename.replace(self._name + "_", "").split(".")[0]
try:
self._created_at = (
datetime.strptime(datestring, "%d%m%y_%H%M%S").replace(tzinfo=timezone.utc).timestamp()
)
except ValueError:
self._created_at = datetime.utcnow().timestamp()
self._created_at = (datetime.strptime(datestring, "%d%m%y_%H%M%S").replace(tzinfo=timezone.utc).timestamp())
self._path = os.path.join(project.path, "snapshots", filename)
@property
@@ -104,7 +99,7 @@ class Snapshot:
with tempfile.TemporaryDirectory(dir=snapshot_directory) as tmpdir:
# Do not compress the snapshots
with aiozipstream.ZipFile(compression=zipfile.ZIP_STORED) as zstream:
await export_project(zstream, self._project, tmpdir, keep_compute_id=True, allow_all_nodes=True)
await export_project(zstream, self._project, tmpdir, keep_compute_ids=True, allow_all_nodes=True)
async with aiofiles.open(self.path, "wb") as f:
async for chunk in zstream:
await f.write(chunk)
+7
View File
@@ -18,6 +18,7 @@
CLASSIC_SYMBOL_THEME = {
"cloud": ":/symbols/classic/cloud.svg",
"nat": ":/symbols/classic/nat.svg",
"ethernet_switch": ":/symbols/classic/ethernet_switch.svg",
"hub": ":/symbols/classic/hub.svg",
"frame_relay_switch": ":/symbols/classic/frame_relay_switch.svg",
@@ -35,6 +36,7 @@ CLASSIC_SYMBOL_THEME = {
AFFINITY_SQUARE_BLUE_SYMBOL_THEME = {
"cloud": ":/symbols/affinity/square/blue/cloud.svg",
"nat": ":/symbols/affinity/square/blue/nat.svg",
"ethernet_switch": ":/symbols/affinity/square/blue/switch.svg",
"hub": ":/symbols/affinity/square/blue/hub.svg",
"frame_relay_switch": ":/symbols/affinity/square/blue/isdn.svg",
@@ -52,6 +54,7 @@ AFFINITY_SQUARE_BLUE_SYMBOL_THEME = {
AFFINITY_SQUARE_RED_SYMBOL_THEME = {
"cloud": ":/symbols/affinity/square/red/cloud.svg",
"nat": ":/symbols/affinity/square/red/nat.svg",
"ethernet_switch": ":/symbols/affinity/square/red/switch.svg",
"hub": ":/symbols/affinity/square/red/hub.svg",
"frame_relay_switch": ":/symbols/affinity/square/red/isdn.svg",
@@ -69,6 +72,7 @@ AFFINITY_SQUARE_RED_SYMBOL_THEME = {
AFFINITY_SQUARE_GRAY_SYMBOL_THEME = {
"cloud": ":/symbols/affinity/square/gray/cloud.svg",
"nat": ":/symbols/affinity/square/gray/nat.svg",
"ethernet_switch": ":/symbols/affinity/square/gray/switch.svg",
"hub": ":/symbols/affinity/square/gray/hub.svg",
"frame_relay_switch": ":/symbols/affinity/square/gray/isdn.svg",
@@ -86,6 +90,7 @@ AFFINITY_SQUARE_GRAY_SYMBOL_THEME = {
AFFINITY_CIRCLE_BLUE_SYMBOL_THEME = {
"cloud": ":/symbols/affinity/circle/blue/cloud.svg",
"nat": ":/symbols/affinity/circle/blue/nat.svg",
"ethernet_switch": ":/symbols/affinity/circle/blue/switch.svg",
"hub": ":/symbols/affinity/circle/blue/hub.svg",
"frame_relay_switch": ":/symbols/affinity/circle/blue/isdn.svg",
@@ -103,6 +108,7 @@ AFFINITY_CIRCLE_BLUE_SYMBOL_THEME = {
AFFINITY_CIRCLE_RED_SYMBOL_THEME = {
"cloud": ":/symbols/affinity/circle/red/cloud.svg",
"nat": ":/symbols/affinity/circle/red/nat.svg",
"ethernet_switch": ":/symbols/affinity/circle/red/switch.svg",
"hub": ":/symbols/affinity/circle/red/hub.svg",
"frame_relay_switch": ":/symbols/affinity/circle/red/isdn.svg",
@@ -120,6 +126,7 @@ AFFINITY_CIRCLE_RED_SYMBOL_THEME = {
AFFINITY_CIRCLE_GRAY_SYMBOL_THEME = {
"cloud": ":/symbols/affinity/circle/gray/cloud.svg",
"nat": ":/symbols/affinity/circle/gray/nat.svg",
"ethernet_switch": ":/symbols/affinity/circle/gray/switch.svg",
"hub": ":/symbols/affinity/circle/gray/hub.svg",
"frame_relay_switch": ":/symbols/affinity/circle/gray/isdn.svg",
+1 -1
View File
@@ -45,7 +45,7 @@ class Symbols:
self._symbol_size_cache = {}
self._server_config = Config.instance().settings.Server
self._current_theme = self._server_config.default_symbol_theme
self._current_theme = self._server_config.default_symbol_theme.value
self._themes = BUILTIN_SYMBOL_THEMES
@property
+31 -2
View File
@@ -35,6 +35,7 @@ from .drawing import Drawing
from .node import Node
from .link import Link
from gns3server.utils.hostname import is_ios_hostname_valid, is_rfc1123_hostname_valid, to_rfc1123_hostname, to_ios_hostname
from gns3server.schemas.controller.topology import Topology
from gns3server.schemas.compute.dynamips_nodes import DynamipsCreate
@@ -43,7 +44,7 @@ import logging
log = logging.getLogger(__name__)
GNS3_FILE_FORMAT_REVISION = 9
GNS3_FILE_FORMAT_REVISION = 10
class DynamipsNodeValidation(DynamipsCreate):
@@ -186,10 +187,14 @@ def load_topology(path):
if variables:
topo["variables"] = [var for var in variables if var.get("name")]
# Version before GNS3 3.0
if topo["revision"] < 10:
topo = _convert_2_2_0(topo, path)
try:
_check_topology_schema(topo, path)
except ControllerError as e:
log.error("Can't load the topology %s", path)
log.error("Can't load the topology %s, please check using the debug mode...", path)
raise e
if changed:
@@ -201,6 +206,30 @@ def load_topology(path):
return topo
def _convert_2_2_0(topo, topo_path):
"""
Convert topologies from GNS3 2.2.x to 3.0
Changes:
* Convert Qemu and Docker node names to be a valid RFC1123 hostnames.
* Convert Dynamips and IOU node names to be a valid IOS hostnames.
"""
topo["revision"] = 10
for node in topo.get("topology", {}).get("nodes", []):
if "properties" in node:
if node["node_type"] in ("qemu", "docker") and not is_rfc1123_hostname_valid(node["name"]):
new_name = to_rfc1123_hostname(node["name"])
log.info(f"Convert node name {node['name']} to {new_name} (RFC1123)")
node["name"] = new_name
if node["node_type"] in ("dynamips", "iou") and not is_ios_hostname_valid(node["name"] ):
new_name = to_ios_hostname(node["name"])
log.info(f"Convert node name {node['name']} to {new_name} (IOS)")
node["name"] = new_name
return topo
def _convert_2_1_0(topo, topo_path):
"""
Convert topologies from GNS3 2.1.x to 2.2
+1 -1
View File
@@ -213,7 +213,7 @@ class UDPLink(Link):
:returns: Node where the capture should run
"""
ALWAYS_RUNNING_NODES_TYPE = ("cloud", "nat", "ethernet_switch", "ethernet_hub")
ALWAYS_RUNNING_NODES_TYPE = ("cloud", "nat", "ethernet_switch", "ethernet_hub", "frame_relay_switch", "atm_switch")
for node in self._nodes:
if (
+1 -1
View File
@@ -58,7 +58,7 @@ class CrashReport:
Report crash to a third party service
"""
DSN = "https://395af26fb5b2245d4c9810095aa11da9@o19455.ingest.us.sentry.io/38482"
DSN = "https://9cf53e6b9adfe49b867f1847b7cc4d72@o19455.ingest.us.sentry.io/38482"
_instance = None
def __init__(self):
+1
View File
@@ -66,6 +66,7 @@ class DockerTemplate(Template):
template_id = Column(GUID, ForeignKey("templates.template_id", ondelete="CASCADE"), primary_key=True)
image = Column(String)
adapters = Column(Integer)
mac_address = Column(String)
start_command = Column(String)
environment = Column(String)
console_type = Column(String)
+22 -3
View File
@@ -18,7 +18,7 @@
import os
from typing import Optional, List
from sqlalchemy import select, delete
from sqlalchemy import select, delete, update
from sqlalchemy.ext.asyncio import AsyncSession
from .base import BaseRepository
@@ -103,6 +103,22 @@ class ImagesRepository(BaseRepository):
await self._db_session.refresh(db_image)
return db_image
async def update_image(self, image_path: str, checksum: str, checksum_algorithm: str) -> models.Image:
"""
Update an image.
"""
query = update(models.Image).\
where(models.Image.path == image_path).\
values(checksum=checksum, checksum_algorithm=checksum_algorithm)
await self._db_session.execute(query)
await self._db_session.commit()
image_db = await self.get_image_by_checksum(checksum)
if image_db:
await self._db_session.refresh(image_db) # force refresh of updated_at value
return image_db
async def delete_image(self, image_path: str) -> bool:
"""
Delete an image.
@@ -119,7 +135,7 @@ class ImagesRepository(BaseRepository):
await self._db_session.commit()
return result.rowcount > 0
async def prune_images(self) -> int:
async def prune_images(self, skip_images: list[str] = None) -> int:
"""
Prune images not attached to any template.
"""
@@ -130,12 +146,15 @@ class ImagesRepository(BaseRepository):
images = result.scalars().all()
images_deleted = 0
for image in images:
if skip_images and image.filename in skip_images:
log.debug(f"Skipping image '{image.path}' for pruning")
continue
try:
log.debug(f"Deleting image '{image.path}'")
os.remove(image.path)
except OSError:
log.warning(f"Could not delete image file {image.path}")
if await self.delete_image(image.filename):
if await self.delete_image(image.path):
images_deleted += 1
log.info(f"{images_deleted} image(s) have been deleted")
return images_deleted
+1 -1
View File
@@ -80,7 +80,7 @@ class ResourcePoolsRepository(BaseRepository):
await self._db_session.commit()
return result.rowcount > 0
async def get_resource_memberships(self, resource_id: UUID) -> List[models.UserGroup]:
async def get_resource_memberships(self, resource_id: UUID) -> List[models.ResourcePool]:
"""
Get all resource memberships in resource pools.
"""
+11
View File
@@ -170,3 +170,14 @@ class TemplatesRepository(BaseRepository):
await self._db_session.commit()
await self._db_session.refresh(template_in_db)
return template_in_db
async def get_template_images(self, template_id: UUID) -> List[models.Image]:
"""
Return all images attached to a template.
"""
query = select(models.Image).\
join(models.Image.templates).\
filter(models.Template.template_id == template_id)
result = await self._db_session.execute(query)
return result.scalars().all()
+121 -80
View File
@@ -16,13 +16,11 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import asyncio
import signal
import time
import os
from fastapi import FastAPI
from pydantic import ValidationError
from watchfiles import awatch, Change
from typing import List
from sqlalchemy import event
from sqlalchemy.engine import Engine
@@ -32,10 +30,13 @@ from alembic import command, config
from alembic.script import ScriptDirectory
from alembic.runtime.migration import MigrationContext
from alembic.util.exc import CommandError
from watchdog.observers import Observer
from watchdog.events import FileSystemEvent, PatternMatchingEventHandler
from gns3server.db.repositories.computes import ComputesRepository
from gns3server.db.repositories.images import ImagesRepository
from gns3server.utils.images import discover_images, check_valid_image_header, read_image_info, default_images_directory, InvalidImageError
from gns3server.utils.images import md5sum, discover_images, read_image_info, InvalidImageError
from gns3server.utils.asyncio import wait_run_in_executor
from gns3server import schemas
from .models import Base
@@ -77,7 +78,7 @@ async def connect_to_db(app: FastAPI) -> None:
db_path = os.path.join(Config.instance().config_dir, "gns3_controller.db")
db_url = os.environ.get("GNS3_DATABASE_URI", f"sqlite+aiosqlite:///{db_path}")
engine = create_async_engine(db_url, connect_args={"check_same_thread": False}, future=True)
engine = create_async_engine(db_url, connect_args={"check_same_thread": False, "timeout": 20}, future=True)
alembic_cfg = config.Config()
alembic_cfg.set_main_option("script_location", "gns3server:db_migrations")
#alembic_cfg.set_main_option('sqlalchemy.url', db_url)
@@ -130,81 +131,7 @@ async def get_computes(app: FastAPI) -> List[dict]:
return computes
def image_filter(change: Change, path: str) -> bool:
if change == Change.added and os.path.isfile(path):
if path.endswith(".tmp") or path.endswith(".md5sum") or path.startswith("."):
return False
if "/lib/" in path or "/lib64/" in path:
# ignore custom IOU libraries
return False
header_magic_len = 7
with open(path, "rb") as f:
image_header = f.read(header_magic_len) # read the first 7 bytes of the file
if len(image_header) >= header_magic_len:
try:
check_valid_image_header(image_header)
except InvalidImageError as e:
log.debug(f"New image '{path}': {e}")
return False
else:
log.debug(f"New image '{path}': size is too small to be valid")
return False
return True
# FIXME: should we support image deletion?
# elif change == Change.deleted:
# return True
return False
async def monitor_images_on_filesystem(app: FastAPI):
directories_to_monitor = []
for image_type in ("qemu", "ios", "iou"):
image_dir = default_images_directory(image_type)
if os.path.isdir(image_dir):
log.debug(f"Monitoring for new images in '{image_dir}'")
directories_to_monitor.append(image_dir)
try:
async for changes in awatch(
*directories_to_monitor,
watch_filter=image_filter,
raise_interrupt=True
):
async with AsyncSession(app.state._db_engine) as db_session:
images_repository = ImagesRepository(db_session)
for change in changes:
change_type, image_path = change
if change_type == Change.added:
try:
image = await read_image_info(image_path)
except InvalidImageError as e:
log.warning(str(e))
continue
try:
if await images_repository.get_image(image_path):
continue
await images_repository.add_image(**image)
log.info(f"Discovered image '{image_path}' has been added to the database")
except SQLAlchemyError as e:
log.warning(f"Error while adding image '{image_path}' to the database: {e}")
# if change_type == Change.deleted:
# try:
# if await images_repository.get_image(image_path):
# success = await images_repository.delete_image(image_path)
# if not success:
# log.warning(f"Could not delete image '{image_path}' from the database")
# else:
# log.info(f"Image '{image_path}' has been deleted from the database")
# except SQLAlchemyError as e:
# log.warning(f"Error while deleting image '{image_path}' from the database: {e}")
except KeyboardInterrupt:
# send SIGTERM to the server PID so uvicorn can shutdown the process
os.kill(os.getpid(), signal.SIGTERM)
async def discover_images_on_filesystem(app: FastAPI):
async def discover_images_on_filesystem(app: FastAPI) -> None:
async with AsyncSession(app.state._db_engine) as db_session:
images_repository = ImagesRepository(db_session)
@@ -228,3 +155,117 @@ async def discover_images_on_filesystem(app: FastAPI):
# monitor if images have been manually added
asyncio.create_task(monitor_images_on_filesystem(app))
async def update_disk_checksums(updated_disks: List[str]) -> None:
"""
Update the checksum of a list of disks in the database.
:param updated_disks: list of updated disks
"""
from gns3server.api.server import app
async with AsyncSession(app.state._db_engine) as db_session:
images_repository = ImagesRepository(db_session)
for path in updated_disks:
image = await images_repository.get_image(path)
if image:
log.info(f"Updating image '{path}' in the database")
checksum = await wait_run_in_executor(md5sum, path, cache_to_md5file=False)
if image.checksum != checksum:
await images_repository.update_image(path, checksum, "md5")
class EventHandler(PatternMatchingEventHandler):
"""
Watchdog event handler.
"""
def __init__(self, queue: asyncio.Queue, loop: asyncio.BaseEventLoop, **kwargs):
self._loop = loop
self._queue = queue
# ignore temporary files, md5sum files, hidden files and directories
super().__init__(ignore_patterns=["*.tmp", "*.md5sum", ".*"], ignore_directories = True, **kwargs)
def on_closed(self, event: FileSystemEvent) -> None:
# monitor for closed files (e.g. when a file has finished to be copied)
if "/lib/" in event.src_path or "/lib64/" in event.src_path:
return # ignore custom IOU libraries
self._loop.call_soon_threadsafe(self._queue.put_nowait, event)
class EventIterator(object):
"""
Watchdog Event iterator.
"""
def __init__(self, queue: asyncio.Queue):
self.queue = queue
def __aiter__(self):
return self
async def __anext__(self):
item = await self.queue.get()
if item is None:
raise StopAsyncIteration
return item
async def monitor_images_on_filesystem(app: FastAPI):
def watchdog(
path: str,
queue: asyncio.Queue,
loop: asyncio.BaseEventLoop,
app: FastAPI, recursive: bool = False
) -> None:
"""
Thread to monitor a directory for new images.
"""
handler = EventHandler(queue, loop)
observer = Observer()
observer.schedule(handler, str(path), recursive=recursive)
observer.start()
log.info(f"Monitoring for new images in '{path}'")
while True:
time.sleep(1)
# stop when the app is exiting
if app.state.exiting:
observer.stop()
observer.join(10)
log.info(f"Stopping monitoring for new images in '{path}'")
loop.call_soon_threadsafe(queue.put_nowait, None)
break
queue = asyncio.Queue()
loop = asyncio.get_event_loop()
server_config = Config.instance().settings.Server
image_dir = os.path.expanduser(server_config.images_path)
asyncio.get_event_loop().run_in_executor(None, watchdog,image_dir, queue, loop, app, True)
async for filesystem_event in EventIterator(queue):
# read the file system event from the queue
image_path = filesystem_event.src_path
expected_image_type = None
if "IOU" in image_path:
expected_image_type = "iou"
elif "QEMU" in image_path:
expected_image_type = "qemu"
elif "IOS" in image_path:
expected_image_type = "ios"
async with AsyncSession(app.state._db_engine) as db_session:
images_repository = ImagesRepository(db_session)
try:
image = await read_image_info(image_path, expected_image_type)
except InvalidImageError as e:
log.warning(str(e))
continue
try:
if await images_repository.get_image(image_path):
continue
await images_repository.add_image(**image)
log.info(f"Discovered image '{image_path}' has been added to the database")
except SQLAlchemyError as e:
log.warning(f"Error while adding image '{image_path}' to the database: {e}")
@@ -0,0 +1,27 @@
"""add mac_address field in Docker templates table
Revision ID: 9a5292aa4389
Revises: 7ceeddd9c9a8
Create Date: 2024-09-18 17:52:53.429522
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '9a5292aa4389'
down_revision = '7ceeddd9c9a8'
branch_labels = None
depends_on = None
def upgrade() -> None:
op.add_column('docker_templates', sa.Column('mac_address', sa.String()))
def downgrade() -> None:
op.drop_column('docker_templates', 'mac_address')
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -39,6 +39,7 @@ class DockerBase(BaseModel):
usage: Optional[str] = Field(None, description="How to use the Docker container")
start_command: Optional[str] = Field(None, description="Docker CMD entry")
adapters: Optional[int] = Field(None, ge=0, le=99, description="Number of adapters")
mac_address: Optional[str] = Field(None, description="Base MAC address", pattern="^([0-9a-fA-F]{2}[:]){5}([0-9a-fA-F]{2})$")
environment: Optional[str] = Field(None, description="Docker environment variables")
extra_hosts: Optional[str] = Field(None, description="Docker extra hosts (added to /etc/hosts)")
extra_volumes: Optional[List[str]] = Field(None, description="Additional directories to make persistent")
@@ -43,7 +43,7 @@ class EthernetSwitchPort(BaseModel):
port_number: int
type: EthernetSwitchPortType = Field(..., description="Port type")
vlan: int = Field(..., ge=1, le=4094, description="VLAN number")
ethertype: Optional[EthernetSwitchEtherType] = Field("0x8100", description="QinQ Ethertype")
ethertype: Optional[EthernetSwitchEtherType] = Field(EthernetSwitchEtherType.ethertype_8021q, description="QinQ Ethertype")
@model_validator(mode="after")
def check_ethertype(self) -> "EthernetSwitchPort":
Loaded 100 of 177 files, more files were not shown because too many files have changed in this diff. Show more