1
0
mirror of https://github.com/GNS3/gns3-server synced 2025-05-06 17:19:01 +00:00

Merge pull request #2395 from GNS3/2.2

Release v2.2.48
This commit is contained in:
Jeremy Grossmann 2024-07-09 00:30:55 +02:00 committed by GitHub
commit 3f5b0bb514
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
34 changed files with 721 additions and 86 deletions

View File

@ -1,5 +1,15 @@
# Change Log # Change Log
## 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
## 2.2.47 15/05/2024 ## 2.2.47 15/05/2024
* Fix update-bundled-web-ui.sh script * Fix update-bundled-web-ui.sh script

View File

@ -9,18 +9,23 @@ ssl = False
certfile=/home/gns3/.config/GNS3/ssl/server.cert certfile=/home/gns3/.config/GNS3/ssl/server.cert
certkey=/home/gns3/.config/GNS3/ssl/server.key 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 images_path = /home/gns3/GNS3/images
; Path where user projects are stored ; Path where user projects are stored
projects_path = /home/gns3/GNS3/projects 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 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 symbols_path = /home/gns3/GNS3/symbols
; 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
; Option to automatically send crash reports to the GNS3 team ; Option to automatically send crash reports to the GNS3 team
report_errors = True report_errors = True
@ -62,6 +67,9 @@ default_nat_interface = vmnet10
; Enable the built-in templates ; Enable the built-in templates
enable_builtin_templates = True 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) ; check if hardware virtualization is used by other emulators (KVM, VMware or VirtualBox)
hardware_virtualization_check = True hardware_virtualization_check = True
@ -93,6 +101,8 @@ require_kvm = True
enable_hardware_acceleration = True enable_hardware_acceleration = True
; Require hardware acceleration in order to start VMs (all platforms) ; Require hardware acceleration in order to start VMs (all platforms)
require_hardware_acceleration = False require_hardware_acceleration = False
; Allow unsafe additional command line options
allow_unsafe_options = False
[VMware] [VMware]
; First vmnet interface of the range that can be managed by the GNS3 server ; First vmnet interface of the range that can be managed by the GNS3 server

View File

@ -24,9 +24,101 @@
"hdb_disk_interface": "ide", "hdb_disk_interface": "ide",
"arch": "x86_64", "arch": "x86_64",
"console_type": "telnet", "console_type": "telnet",
"kvm": "require" "kvm": "require",
"options": "-cpu host"
}, },
"images": [ "images": [
{
"filename": "vEOS64-lab-4.32.0F.vmdk",
"version": "4.32.0F",
"md5sum": "851771260bb18ad3e90fa6956f0c6161",
"filesize": 591724544,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS64-lab-4.31.3M.vmdk",
"version": "4.31.3M",
"md5sum": "7df107da137f4a4e752014d4f0e94cd3",
"filesize": 577961984,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS64-lab-4.30.6M.vmdk",
"version": "4.30.6M",
"md5sum": "19721aace820b9ebf6d7ae6524803cf5",
"filesize": 553123840,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS64-lab-4.29.8M.vmdk",
"version": "4.29.8M",
"md5sum": "131888f74cd63a93894521d40eb4d0b6",
"filesize": 548405248,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS64-lab-4.28.11M.vmdk",
"version": "4.28.11M",
"md5sum": "6cac0e7b04a74ee0dc358327a00accfd",
"filesize": 513343488,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS64-lab-4.27.12M.vmdk",
"version": "4.27.12M",
"md5sum": "34c4f785c7fc054cda8754dd13c0d7c7",
"filesize": 496697344,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS-lab-4.32.0F.vmdk",
"version": "4.32.0F",
"md5sum": "584b901a1249717504050e48f74fb8dd",
"filesize": 591396864,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS-lab-4.31.3M.vmdk",
"version": "4.31.3M",
"md5sum": "a2e130697cdf8547006eebebde6eefca",
"filesize": 590086144,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS-lab-4.30.6M.vmdk",
"version": "4.30.6M",
"md5sum": "a4467648bcfa7b19640af8a4ad3153c6",
"filesize": 565968896,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS-lab-4.29.8M.vmdk",
"version": "4.29.8M",
"md5sum": "1952f6114a4376212c525db9ec8efd5f",
"filesize": 558039040,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS-lab-4.28.11M.vmdk",
"version": "4.28.11M",
"md5sum": "5502df24dfc231c45afb33d6018c16d0",
"filesize": 521338880,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS-lab-4.27.12M.vmdk",
"version": "4.27.12M",
"md5sum": "e08a97e7c1977993f947fedeb4c6ddd5",
"filesize": 504299520,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"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"
},
{ {
"filename": "vEOS-lab-4.26.2F.vmdk", "filename": "vEOS-lab-4.26.2F.vmdk",
"version": "4.26.2F", "version": "4.26.2F",
@ -218,6 +310,90 @@
} }
], ],
"versions": [ "versions": [
{
"name": "4.32.0F",
"images": {
"hda_disk_image": "Aboot-veos-serial-8.0.2.iso",
"hdb_disk_image": "vEOS64-lab-4.32.0F.vmdk"
}
},
{
"name": "4.31.3M",
"images": {
"hda_disk_image": "Aboot-veos-serial-8.0.2.iso",
"hdb_disk_image": "vEOS64-lab-4.31.3M.vmdk"
}
},
{
"name": "4.30.6M",
"images": {
"hda_disk_image": "Aboot-veos-serial-8.0.2.iso",
"hdb_disk_image": "vEOS64-lab-4.30.6M.vmdk"
}
},
{
"name": "4.29.8M",
"images": {
"hda_disk_image": "Aboot-veos-serial-8.0.2.iso",
"hdb_disk_image": "vEOS64-lab-4.29.8M.vmdk"
}
},
{
"name": "4.28.11M",
"images": {
"hda_disk_image": "Aboot-veos-serial-8.0.2.iso",
"hdb_disk_image": "vEOS64-lab-4.28.11M.vmdk"
}
},
{
"name": "4.27.12M",
"images": {
"hda_disk_image": "Aboot-veos-serial-8.0.2.iso",
"hdb_disk_image": "vEOS64-lab-4.27.12M.vmdk"
}
},
{
"name": "4.32.0F",
"images": {
"hda_disk_image": "Aboot-veos-serial-8.0.2.iso",
"hdb_disk_image": "vEOS-lab-4.32.0F.vmdk"
}
},
{
"name": "4.31.3M",
"images": {
"hda_disk_image": "Aboot-veos-serial-8.0.2.iso",
"hdb_disk_image": "vEOS-lab-4.31.3M.vmdk"
}
},
{
"name": "4.30.6M",
"images": {
"hda_disk_image": "Aboot-veos-serial-8.0.2.iso",
"hdb_disk_image": "vEOS-lab-4.30.6M.vmdk"
}
},
{
"name": "4.29.8M",
"images": {
"hda_disk_image": "Aboot-veos-serial-8.0.2.iso",
"hdb_disk_image": "vEOS-lab-4.29.8M.vmdk"
}
},
{
"name": "4.28.11M",
"images": {
"hda_disk_image": "Aboot-veos-serial-8.0.2.iso",
"hdb_disk_image": "vEOS-lab-4.28.11M.vmdk"
}
},
{
"name": "4.27.12M",
"images": {
"hda_disk_image": "Aboot-veos-serial-8.0.2.iso",
"hdb_disk_image": "vEOS-lab-4.27.12M.vmdk"
}
},
{ {
"name": "4.26.2F", "name": "4.26.2F",
"images": { "images": {
@ -398,4 +574,4 @@
} }
} }
] ]
} }

View File

@ -32,6 +32,27 @@
"process_priority": "normal" "process_priority": "normal"
}, },
"images": [ "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", "filename": "arubaoscx-disk-image-genericx86-p4-20230531220439.vmdk",
"version": "10.12.0006", "version": "10.12.0006",
@ -118,6 +139,24 @@
} }
], ],
"versions": [ "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", "name": "10.12.0006",
"images": { "images": {

View File

@ -19,7 +19,7 @@
}, },
"images": [ "images": [
{ {
"filename": "x86_64_crb_linux_l2-adventerprisek9-ms", "filename": "x86_64_crb_linux_l2-adventerprisek9-ms.bin",
"version": "17.12.1", "version": "17.12.1",
"md5sum": "2b5055e4cef8fd257416d74a94adb626", "md5sum": "2b5055e4cef8fd257416d74a94adb626",
"filesize": 240355720 "filesize": 240355720
@ -47,7 +47,7 @@
{ {
"name": "17.12.1", "name": "17.12.1",
"images": { "images": {
"image": "x86_64_crb_linux_l2-adventerprisek9-ms" "image": "x86_64_crb_linux_l2-adventerprisek9-ms.bin"
} }
}, },
{ {

View File

@ -19,7 +19,7 @@
}, },
"images": [ "images": [
{ {
"filename": "x86_64_crb_linux-adventerprisek9-ms", "filename": "x86_64_crb_linux-adventerprisek9-ms.bin",
"version": "17.12.1", "version": "17.12.1",
"md5sum": "4a2fce8de21d1831fbceffd155e41ae7", "md5sum": "4a2fce8de21d1831fbceffd155e41ae7",
"filesize": 288947184 "filesize": 288947184
@ -47,7 +47,7 @@
{ {
"name": "17.12.1", "name": "17.12.1",
"images": { "images": {
"image": "x86_64_crb_linux-adventerprisek9-ms" "image": "x86_64_crb_linux-adventerprisek9-ms.bin"
} }
}, },
{ {

View File

@ -23,6 +23,14 @@
"kvm": "allow" "kvm": "allow"
}, },
"images": [ "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", "filename": "debian-12.4.qcow2",
"version": "12.4", "version": "12.4",
@ -31,6 +39,14 @@
"download_url": "https://sourceforge.net/projects/gns-3/files/Qemu%20Appliances/", "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" "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", "filename": "debian-11.8.qcow2",
"version": "11.8", "version": "11.8",
@ -41,12 +57,24 @@
} }
], ],
"versions": [ "versions": [
{
"name": "12.6",
"images": {
"hda_disk_image": "debian-12.6.qcow2"
}
},
{ {
"name": "12.4", "name": "12.4",
"images": { "images": {
"hda_disk_image": "debian-12.4.qcow2" "hda_disk_image": "debian-12.4.qcow2"
} }
}, },
{
"name": "11.10",
"images": {
"hda_disk_image": "debian-11.10.qcow2"
}
},
{ {
"name": "11.8", "name": "11.8",
"images": { "images": {

View File

@ -28,10 +28,17 @@
}, },
"images": [ "images": [
{ {
"filename": "FAD_KVM-FORTINET.out.kvm-data.qcow2", "filename": "FAD_KVM-V7.4.4-build0347-FORTINET.out.kvm_boot.qcow2",
"version": "ALL", "version": "7.4.4",
"md5sum": "b7500835594e62d8acb1c6ec43d597c1", "md5sum": "52fa343fd423a1a560473b8cf02f4c9c",
"filesize": 30998528, "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" "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
}, },
{ {
@ -41,6 +48,13 @@
"filesize": 145817600, "filesize": 145817600,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" "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", "filename": "FAD_KVM-V7.1.1-build0117-FORTINET.out.kvm-boot.qcow2",
"version": "7.1.1", "version": "7.1.1",
@ -243,9 +257,30 @@
"md5sum": "7a71f52bde93c0000b047626731b7aef", "md5sum": "7a71f52bde93c0000b047626731b7aef",
"filesize": 68026368, "filesize": 68026368,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" "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": [ "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", "name": "7.2.0",
"images": { "images": {
@ -253,6 +288,13 @@
"hdb_disk_image": "FAD_KVM-FORTINET.out.kvm-data.qcow2" "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", "name": "7.1.1",
"images": { "images": {

View File

@ -29,6 +29,13 @@
"kvm": "allow" "kvm": "allow"
}, },
"images": [ "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", "filename": "FAZ_VM64_KVM-v7.4.2-build2397-FORTINET.out.kvm.qcow2",
"version": "7.4.2", "version": "7.4.2",
@ -43,6 +50,13 @@
"filesize": 435310592, "filesize": 435310592,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" "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", "filename": "FAZ_VM64_KVM-v7.2.4-build1460-FORTINET.out.kvm.qcow2",
"version": "7.2.4", "version": "7.2.4",
@ -64,6 +78,13 @@
"filesize": 340631552, "filesize": 340631552,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" "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", "filename": "FAZ_VM64_KVM-v7.0.11-build0595-FORTINET.out.kvm.qcow2",
"version": "7.0.11", "version": "7.0.11",
@ -256,6 +277,13 @@
} }
], ],
"versions": [ "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", "name": "7.4.2",
"images": { "images": {
@ -270,6 +298,13 @@
"hdb_disk_image": "empty30G.qcow2" "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", "name": "7.2.4",
"images": { "images": {
@ -291,6 +326,13 @@
"hdb_disk_image": "empty30G.qcow2" "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", "name": "7.0.11",
"images": { "images": {

View File

@ -13,13 +13,13 @@
"status": "stable", "status": "stable",
"maintainer": "GNS3 Team", "maintainer": "GNS3 Team",
"maintainer_email": "developers@gns3.net", "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", "symbol": "fortinet.svg",
"port_name_format": "Port{port1}", "port_name_format": "Port{port1}",
"qemu": { "qemu": {
"adapter_type": "e1000", "adapter_type": "e1000",
"adapters": 4, "adapters": 4,
"ram": 1024, "ram": 4096,
"hda_disk_interface": "virtio", "hda_disk_interface": "virtio",
"hdb_disk_interface": "virtio", "hdb_disk_interface": "virtio",
"arch": "x86_64", "arch": "x86_64",
@ -28,6 +28,27 @@
"kvm": "allow" "kvm": "allow"
}, },
"images": [ "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", "filename": "FAC_VM_KVM-v6-build0058-FORTINET.out.kvm.qcow2",
"version": "6.0.3", "version": "6.0.3",
@ -105,6 +126,20 @@
"filesize": 62771200, "filesize": 62771200,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" "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", "filename": "FAC_VM_KVM-ALL-DATADRIVE.qcow2",
"version": "All", "version": "All",
@ -114,6 +149,27 @@
} }
], ],
"versions": [ "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", "name": "6.0.3",
"images": { "images": {

View File

@ -28,6 +28,13 @@
"kvm": "allow" "kvm": "allow"
}, },
"images": [ "images": [
{
"filename": "FGT_VM64_KVM-v7.4.4.F-build2573-FORTINET.out.kvm.qcow2",
"version": "7.4.4",
"md5sum": "dfe0e78827ec728631539669001bb23f",
"filesize": 100728832,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{ {
"filename": "FGT_VM64_KVM-v7.4.3.F-build2573-FORTINET.out.kvm.qcow2", "filename": "FGT_VM64_KVM-v7.4.3.F-build2573-FORTINET.out.kvm.qcow2",
"version": "7.4.3", "version": "7.4.3",
@ -42,6 +49,13 @@
"filesize": 116064256, "filesize": 116064256,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" "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", "filename": "FGT_VM64_KVM-v7.2.7.M-build1577-FORTINET.out.kvm.qcow2",
"version": "7.2.7", "version": "7.2.7",
@ -77,6 +91,13 @@
"filesize": 86704128, "filesize": 86704128,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" "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", "filename": "FGT_VM64_KVM-v7.0.14.M-build0601-FORTINET.out.kvm.qcow2",
"version": "7.0.14", "version": "7.0.14",
@ -367,6 +388,13 @@
} }
], ],
"versions": [ "versions": [
{
"name": "7.4.4",
"images": {
"hda_disk_image": "FGT_VM64_KVM-v7.4.4.F-build2573-FORTINET.out.kvm.qcow2",
"hdb_disk_image": "empty30G.qcow2"
}
},
{ {
"name": "7.4.3", "name": "7.4.3",
"images": { "images": {
@ -381,6 +409,13 @@
"hdb_disk_image": "empty30G.qcow2" "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", "name": "7.2.7",
"images": { "images": {
@ -416,6 +451,13 @@
"hdb_disk_image": "empty30G.qcow2" "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", "name": "7.0.14",
"images": { "images": {

View File

@ -29,6 +29,13 @@
"kvm": "allow" "kvm": "allow"
}, },
"images": [ "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", "filename": "FMG_VM64_KVM-v7.4.2-build2397-FORTINET.out.kvm.qcow2",
"version": "7.4.2", "version": "7.4.2",
@ -43,6 +50,13 @@
"filesize": 309387264, "filesize": 309387264,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" "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", "filename": "FMG_VM64_KVM-v7.2.4-build1460-FORTINET.out.kvm.qcow2",
"version": "7.2.4", "version": "7.2.4",
@ -64,6 +78,13 @@
"filesize": 242814976, "filesize": 242814976,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" "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", "filename": "FMG_VM64_KVM-v7.0.11-build0595-FORTINET.out.kvm.qcow2",
"version": "7.0.11", "version": "7.0.11",
@ -256,6 +277,13 @@
} }
], ],
"versions": [ "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", "name": "7.4.2",
"images": { "images": {
@ -270,6 +298,13 @@
"hdb_disk_image": "empty30G.qcow2" "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", "name": "7.2.4",
"images": { "images": {
@ -291,6 +326,13 @@
"hdb_disk_image": "empty30G.qcow2" "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", "name": "7.0.11",
"images": { "images": {

View File

@ -28,6 +28,27 @@
"kvm": "allow" "kvm": "allow"
}, },
"images": [ "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", "filename": "FWB_KVM-v7.2.1-build0330-FORTINET.out.kvm.boot.qcow2",
"version": "7.2.1", "version": "7.2.1",
@ -35,6 +56,13 @@
"filesize": 260506112, "filesize": 260506112,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" "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", "filename": "FWB_KVM-v7.0.6-build0140-FORTINET.out.kvm.boot.qcow2",
"version": "7.0.6", "version": "7.0.6",
@ -150,6 +178,27 @@
} }
], ],
"versions": [ "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", "name": "7.2.1",
"images": { "images": {
@ -157,6 +206,13 @@
"hdb_disk_image": "empty30G.qcow2" "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", "name": "7.0.6",
"images": { "images": {

View File

@ -28,6 +28,20 @@
}, },
"images": [ "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", "filename": "PA-VM-KVM-10.1.0.qcow2",
"version": "10.1.0", "version": "10.1.0",
"md5sum": "8266fd412a22694749f2cd4afcd5fa33", "md5sum": "8266fd412a22694749f2cd4afcd5fa33",
@ -128,6 +142,18 @@
], ],
"versions": [ "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", "name": "10.1.0",
"images": { "images": {
"hda_disk_image": "PA-VM-KVM-10.1.0.qcow2" "hda_disk_image": "PA-VM-KVM-10.1.0.qcow2"

View File

@ -29,6 +29,7 @@ import shutil
import platformdirs import platformdirs
from gns3server.utils import parse_version from gns3server.utils import parse_version
from gns3server.config import Config
from gns3server.utils.asyncio import locking from gns3server.utils.asyncio import locking
from gns3server.compute.base_manager import BaseManager from gns3server.compute.base_manager import BaseManager
from gns3server.compute.docker.docker_vm import DockerVM from gns3server.compute.docker.docker_vm import DockerVM
@ -96,8 +97,10 @@ class Docker(BaseManager):
Get the Docker resources storage directory Get the Docker resources storage directory
""" """
server_config = Config.instance().get_section_config("Server")
appname = vendor = "GNS3" appname = vendor = "GNS3"
docker_resources_dir = os.path.join(platformdirs.user_data_dir(appname, vendor, roaming=True), "docker", "resources") resources_path = os.path.expanduser(server_config.get("resources_path", platformdirs.user_data_dir(appname, vendor, roaming=True)))
docker_resources_dir = os.path.join(resources_path, "docker")
os.makedirs(docker_resources_dir, exist_ok=True) os.makedirs(docker_resources_dir, exist_ok=True)
return docker_resources_dir return docker_resources_dir

View File

@ -47,12 +47,18 @@ from ..base_node import BaseNode
from ...schemas.qemu import QEMU_OBJECT_SCHEMA, QEMU_PLATFORMS from ...schemas.qemu import QEMU_OBJECT_SCHEMA, QEMU_PLATFORMS
from ...utils.asyncio import monitor_process from ...utils.asyncio import monitor_process
from ...utils.images import md5sum 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
import logging import logging
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
# forbidden additional options
FORBIDDEN_OPTIONS = {"-blockdev", "-drive", "-hda", "-hdb", "-hdc", "-hdd",
"-fsdev", "-virtfs"}
FORBIDDEN_OPTIONS |= {"-" + opt for opt in FORBIDDEN_OPTIONS
if opt.startswith("-") and not opt.startswith("--")}
class QemuVM(BaseNode): class QemuVM(BaseNode):
module_name = 'qemu' module_name = 'qemu'
@ -1672,13 +1678,14 @@ class QemuVM(BaseNode):
if self._console: if self._console:
console_host = self._manager.port_manager.console_host console_host = self._manager.port_manager.console_host
if console_host == "0.0.0.0": if console_host == "0.0.0.0":
if socket.has_ipv6: try:
# to fix an issue with Qemu when IPv4 is not enabled if is_ipv6_enabled():
# see https://github.com/GNS3/gns3-gui/issues/2352 # to fix an issue with Qemu when IPv4 is not enabled
# FIXME: consider making this more global (not just for Qemu + SPICE) # see https://github.com/GNS3/gns3-gui/issues/2352
console_host = "::" # FIXME: consider making this more global (not just for Qemu + SPICE)
else: console_host = "::"
raise QemuError("IPv6 must be enabled in order to use the SPICE console") except OSError as e:
raise QemuError("Could not check if IPv6 is enabled: {}".format(e))
return ["-spice", return ["-spice",
"addr={},port={},disable-ticketing".format(console_host, self._console), "addr={},port={},disable-ticketing".format(console_host, self._console),
"-vga", "qxl"] "-vga", "qxl"]
@ -2423,9 +2430,19 @@ class QemuVM(BaseNode):
command.extend(self._tpm_options()) command.extend(self._tpm_options())
if additional_options: if additional_options:
try: try:
command.extend(shlex.split(additional_options)) additional_opt_list = shlex.split(additional_options)
except ValueError as e: except ValueError as e:
raise QemuError("Invalid additional options: {} error {}".format(additional_options, e)) raise QemuError("Invalid additional options: {} error {}".format(additional_options, e))
allow_unsafe_options = self.manager.config.get_section_config("Qemu").getboolean(
"allow_unsafe_options",
False
)
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) # avoiding mouse offset (see https://github.com/GNS3/gns3-server/issues/2335)
if self._console_type == "vnc": if self._console_type == "vnc":
command.extend(['-machine', 'usb=on', '-device', 'usb-tablet']) command.extend(['-machine', 'usb=on', '-device', 'usb-tablet'])

View File

@ -248,13 +248,19 @@ class Controller:
if "iou_license" in controller_settings: if "iou_license" in controller_settings:
self._iou_license_settings = controller_settings["iou_license"] self._iou_license_settings = controller_settings["iou_license"]
previous_version = controller_settings.get("version") # install the built-in appliances if needed
log.info("Comparing controller version {} with config version {}".format(__version__, previous_version)) server_config = Config.instance().get_section_config("Server")
if not previous_version or \ if server_config.getboolean("install_builtin_appliances", True):
parse_version(__version__.split("+")[0]) > parse_version(previous_version.split("+")[0]): previous_version = controller_settings.get("version")
self._appliance_manager.install_builtin_appliances() log.info("Comparing controller version {} with config version {}".format(__version__, previous_version))
elif not os.listdir(self._appliance_manager.builtin_appliances_path()): builtin_appliances_path = self._appliance_manager.builtin_appliances_path()
self._appliance_manager.install_builtin_appliances() 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(builtin_appliances_path):
self._appliance_manager.install_builtin_appliances()
else:
log.info("Built-in appliances are installed in '{}'".format(builtin_appliances_path))
self._appliance_manager.appliances_etag = controller_settings.get("appliances_etag") self._appliance_manager.appliances_etag = controller_settings.get("appliances_etag")
self._appliance_manager.load_appliances() self._appliance_manager.load_appliances()

View File

@ -87,8 +87,10 @@ class ApplianceManager:
Get the built-in appliance storage directory Get the built-in appliance storage directory
""" """
server_config = Config.instance().get_section_config("Server")
appname = vendor = "GNS3" appname = vendor = "GNS3"
appliances_dir = os.path.join(platformdirs.user_data_dir(appname, vendor, roaming=True), "appliances") resources_path = os.path.expanduser(server_config.get("resources_path", platformdirs.user_data_dir(appname, vendor, roaming=True)))
appliances_dir = os.path.join(resources_path, "appliances")
if delete_first: if delete_first:
shutil.rmtree(appliances_dir, ignore_errors=True) shutil.rmtree(appliances_dir, ignore_errors=True)
os.makedirs(appliances_dir, exist_ok=True) os.makedirs(appliances_dir, exist_ok=True)

View File

@ -32,7 +32,7 @@ log = logging.getLogger(__name__)
CHUNK_SIZE = 1024 * 8 # 8KB CHUNK_SIZE = 1024 * 8 # 8KB
async def export_project(zstream, project, temporary_dir, include_images=False, include_snapshots=False, keep_compute_id=False, allow_all_nodes=False, reset_mac_addresses=False): async def export_project(zstream, project, temporary_dir, include_images=False, include_snapshots=False, keep_compute_ids=False, allow_all_nodes=False, reset_mac_addresses=False):
""" """
Export a project to a zip file. Export a project to a zip file.
@ -44,9 +44,9 @@ async def export_project(zstream, project, temporary_dir, include_images=False,
:param temporary_dir: A temporary dir where to store intermediate data :param temporary_dir: A temporary dir where to store intermediate data
:param include_images: save OS images to the zip file :param include_images: save OS images to the zip file
:param include_snapshots: save snapshots 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 keep_compute_ids: If false replace all compute IDs y 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 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 every nodes. :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 # To avoid issue with data not saved we disallow the export of a running project
@ -62,7 +62,7 @@ async def export_project(zstream, project, temporary_dir, include_images=False,
# First we process the .gns3 in order to be sure we don't have an error # First we process the .gns3 in order to be sure we don't have an error
for file in os.listdir(project._path): for file in os.listdir(project._path):
if file.endswith(".gns3"): if file.endswith(".gns3"):
await _patch_project_file(project, os.path.join(project._path, file), zstream, include_images, keep_compute_id, allow_all_nodes, temporary_dir, reset_mac_addresses) await _patch_project_file(project, os.path.join(project._path, file), zstream, include_images, keep_compute_ids, allow_all_nodes, temporary_dir, reset_mac_addresses)
# Export the local files # Export the local files
for root, dirs, files in os.walk(project._path, topdown=True, followlinks=False): for root, dirs, files in os.walk(project._path, topdown=True, followlinks=False):
@ -170,7 +170,7 @@ def _is_exportable(path, include_snapshots=False):
return True return True
async def _patch_project_file(project, path, zstream, include_images, keep_compute_id, allow_all_nodes, temporary_dir, reset_mac_addresses): async def _patch_project_file(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. Patch a project file (.gns3) to export a project.
The .gns3 file is renamed to project.gns3 The .gns3 file is renamed to project.gns3
@ -197,7 +197,7 @@ async def _patch_project_file(project, path, zstream, include_images, keep_compu
if not allow_all_nodes and node["node_type"] in ["virtualbox", "vmware"]: if not allow_all_nodes and node["node_type"] in ["virtualbox", "vmware"]:
raise aiohttp.web.HTTPConflict(text="Projects with a {} node cannot be exported".format(node["node_type"])) raise aiohttp.web.HTTPConflict(text="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 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 and node["node_type"] != "docker":
@ -215,7 +215,7 @@ async def _patch_project_file(project, path, zstream, include_images, keep_compu
if value is None or value.strip() == '': if value is None or value.strip() == '':
continue 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) node["properties"][prop] = os.path.basename(value)
if include_images is True: if include_images is True:
@ -225,7 +225,7 @@ async def _patch_project_file(project, path, zstream, include_images, keep_compu
'image_type': node['node_type'] '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 topology["topology"]["computes"] = [] # Strip compute information because could contain secret info like password
local_images = set([i['image'] for i in images if i['compute_id'] == 'local']) local_images = set([i['image'] for i in images if i['compute_id'] == 'local'])

View File

@ -38,7 +38,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): auto_start=False, auto_open=False, auto_close=True):
""" """
Import a project contain in a zip file Import a project contain in a zip file
@ -50,7 +50,7 @@ async def import_project(controller, project_id, stream, location=None, name=Non
:param stream: A io.BytesIO of the zipfile :param stream: A io.BytesIO of the zipfile
:param location: Directory for the project if None put in the default directory :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 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 :returns: Project
""" """
@ -124,7 +124,7 @@ async def import_project(controller, project_id, stream, location=None, name=Non
drawing["drawing_id"] = str(uuid.uuid4()) drawing["drawing_id"] = str(uuid.uuid4())
# Modify the compute id of the node depending of compute capacity # 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 # For some VM type we move them to the GNS3 VM if possible
# unless it's a linux host without GNS3 VM # unless it's a linux host without GNS3 VM
if not sys.platform.startswith("linux") or controller.has_compute("vm"): if not sys.platform.startswith("linux") or controller.has_compute("vm"):

View File

@ -192,7 +192,11 @@ class Project:
if os.path.exists(snapshot_dir): if os.path.exists(snapshot_dir):
for snap in os.listdir(snapshot_dir): for snap in os.listdir(snapshot_dir):
if snap.endswith(".gns3project"): 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 self._snapshots[snapshot.id] = snapshot
# Create the project on demand on the compute node # Create the project on demand on the compute node
@ -1062,7 +1066,7 @@ class Project:
with tempfile.TemporaryDirectory(dir=working_dir) as tmpdir: with tempfile.TemporaryDirectory(dir=working_dir) as tmpdir:
# Do not compress the exported project when duplicating # Do not compress the exported project when duplicating
with aiozipstream.ZipFile(compression=zipfile.ZIP_STORED) as zstream: with aiozipstream.ZipFile(compression=zipfile.ZIP_STORED) as zstream:
await export_project(zstream, self, tmpdir, keep_compute_id=True, allow_all_nodes=True, reset_mac_addresses=reset_mac_addresses) await export_project(zstream, self, tmpdir, keep_compute_ids=True, allow_all_nodes=True, reset_mac_addresses=reset_mac_addresses)
# export the project to a temporary location # export the project to a temporary location
project_path = os.path.join(tmpdir, "project.gns3p") project_path = os.path.join(tmpdir, "project.gns3p")
@ -1073,7 +1077,7 @@ class Project:
# import the temporary project # import the temporary project
with open(project_path, "rb") as f: with open(project_path, "rb") as f:
project = await import_project(self._controller, str(uuid.uuid4()), f, location=location, name=name, keep_compute_id=True) project = await import_project(self._controller, str(uuid.uuid4()), f, location=location, name=name, keep_compute_ids=True)
log.info("Project '{}' duplicated in {:.4f} seconds".format(project.name, time.time() - begin)) log.info("Project '{}' duplicated in {:.4f} seconds".format(project.name, time.time() - begin))
except (ValueError, OSError, UnicodeEncodeError) as e: except (ValueError, OSError, UnicodeEncodeError) as e:

View File

@ -55,12 +55,10 @@ class Snapshot:
self._created_at = datetime.now(timezone.utc).timestamp() self._created_at = datetime.now(timezone.utc).timestamp()
filename = self._name + "_" + datetime.fromtimestamp(self._created_at, tz=timezone.utc).replace(tzinfo=None).strftime(FILENAME_TIME_FORMAT) + ".gns3project" filename = self._name + "_" + datetime.fromtimestamp(self._created_at, tz=timezone.utc).replace(tzinfo=None).strftime(FILENAME_TIME_FORMAT) + ".gns3project"
else: else:
self._name = filename.split("_")[0] self._name = filename.rsplit("_", 2)[0]
datestring = filename.replace(self._name + "_", "").split(".")[0] datestring = filename.replace(self._name + "_", "").split(".")[0]
try: self._created_at = datetime.strptime(datestring, FILENAME_TIME_FORMAT).replace(tzinfo=timezone.utc).timestamp()
self._created_at = datetime.strptime(datestring, FILENAME_TIME_FORMAT).replace(tzinfo=timezone.utc).timestamp()
except ValueError:
self._created_at = datetime.now(timezone.utc)
self._path = os.path.join(project.path, "snapshots", filename) self._path = os.path.join(project.path, "snapshots", filename)
@property @property
@ -98,7 +96,7 @@ class Snapshot:
with tempfile.TemporaryDirectory(dir=snapshot_directory) as tmpdir: with tempfile.TemporaryDirectory(dir=snapshot_directory) as tmpdir:
# Do not compress the snapshots # Do not compress the snapshots
with aiozipstream.ZipFile(compression=zipfile.ZIP_STORED) as zstream: 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 with aiofiles.open(self.path, 'wb') as f:
async for chunk in zstream: async for chunk in zstream:
await f.write(chunk) await f.write(chunk)

View File

@ -57,7 +57,7 @@ class CrashReport:
Report crash to a third party service Report crash to a third party service
""" """
DSN = "https://ec32b24c329df619c8b9b1c58cfedcdb@o19455.ingest.us.sentry.io/38482" DSN = "https://3fb84d1ee07fa46b3638825e30cb8f05@o19455.ingest.us.sentry.io/38482"
_instance = None _instance = None
def __init__(self): def __init__(self):

View File

@ -319,6 +319,10 @@ class ProjectHandler:
reset_mac_addresses = True reset_mac_addresses = True
else: else:
reset_mac_addresses = False reset_mac_addresses = False
if request.query.get("keep_compute_ids", "no").lower() == "yes":
keep_compute_ids = True
else:
keep_compute_ids = False
compression_query = request.query.get("compression", "zip").lower() compression_query = request.query.get("compression", "zip").lower()
if compression_query == "zip": if compression_query == "zip":
@ -336,9 +340,17 @@ class ProjectHandler:
working_dir = os.path.abspath(os.path.join(project.path, os.pardir)) working_dir = os.path.abspath(os.path.join(project.path, os.pardir))
with tempfile.TemporaryDirectory(dir=working_dir) as tmpdir: with tempfile.TemporaryDirectory(dir=working_dir) as tmpdir:
with aiozipstream.ZipFile(compression=compression) as zstream: with aiozipstream.ZipFile(compression=compression) as zstream:
await export_project(zstream, project, tmpdir, include_snapshots=include_snapshots, include_images=include_images, reset_mac_addresses=reset_mac_addresses) await export_project(
zstream,
project,
tmpdir,
include_snapshots=include_snapshots,
include_images=include_images,
reset_mac_addresses=reset_mac_addresses,
keep_compute_ids=keep_compute_ids
)
# We need to do that now because export could failed and raise an HTTP error # We need to do that now because export could fail and raise an HTTP error
# that why response start need to be the later possible # that why response start need to be the later possible
response.content_type = 'application/gns3project' response.content_type = 'application/gns3project'
response.headers['CONTENT-DISPOSITION'] = 'attachment; filename="{}.gns3project"'.format(project.name) response.headers['CONTENT-DISPOSITION'] = 'attachment; filename="{}.gns3project"'.format(project.name)
@ -350,7 +362,7 @@ class ProjectHandler:
log.info("Project '{}' exported in {:.4f} seconds".format(project.name, time.time() - begin)) log.info("Project '{}' exported in {:.4f} seconds".format(project.name, time.time() - begin))
# Will be raise if you have no space left or permission issue on your temporary directory # Will be raised if you have no space left or permission issue on your temporary directory
# RuntimeError: something was wrong during the zip process # RuntimeError: something was wrong during the zip process
except (ValueError, OSError, RuntimeError) as e: except (ValueError, OSError, RuntimeError) as e:
raise aiohttp.web.HTTPNotFound(text="Cannot export project: {}".format(str(e))) raise aiohttp.web.HTTPNotFound(text="Cannot export project: {}".format(str(e)))

View File

@ -1,4 +1,6 @@
<!DOCTYPE html><html lang="en"><head> <html lang="en"><head><script src="runtime.415291667f70565cd8ef.js" defer></script><script src="polyfills-es5.865074f5cd9a121111a2.js" nomodule defer></script><script src="polyfills.2f91a039d848e57ff02e.js" defer></script><script src="main.b65e52314df938ebe652.js" defer></script>
<meta charset="utf-8"> <meta charset="utf-8">
<title>GNS3 Web UI</title> <title>GNS3 Web UI</title>
<!-- It's important to have base here because of the script below //--> <!-- It's important to have base here because of the script below //-->
@ -36,16 +38,4 @@
<body class="mat-app-background" oncontextmenu="return false;"> <body class="mat-app-background" oncontextmenu="return false;">
<app-root></app-root> <app-root></app-root>
<!-- Global site tag (gtag.js) - Google Analytics --> <!-- Global site tag (gtag.js) - Google Analytics -->
<script async="" src="https://www.googletagmanager.com/gtag/js?id=G-5D6FZL9923"></script> </body></html>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() {
dataLayer.push(arguments);
}
gtag('js', new Date());
gtag('config', 'G-5D6FZL9923');
</script>
<script src="runtime.415291667f70565cd8ef.js" defer></script><script src="polyfills-es5.865074f5cd9a121111a2.js" nomodule defer></script><script src="polyfills.2f91a039d848e57ff02e.js" defer></script><script src="main.0e7dc9152b2aa567227c.js" defer></script>
</body></html>

View File

@ -21,6 +21,8 @@ import re
import shlex import shlex
import textwrap import textwrap
import posixpath import posixpath
import socket
import errno
def force_unix_path(path): def force_unix_path(path):
@ -100,3 +102,21 @@ def shlex_quote(s):
return s if re.match(r'^[-_\w./]+$', s) else '"%s"' % s.replace('"', '\\"') return s if re.match(r'^[-_\w./]+$', s) else '"%s"' % s.replace('"', '\\"')
else: else:
return shlex.quote(s) return shlex.quote(s)
def is_ipv6_enabled() -> bool:
if not socket.has_ipv6:
return False # the socket library has no support for IPv6
try:
with socket.socket(socket.AF_INET6, socket.SOCK_STREAM) as sock:
sock.bind(("::1", 0))
return True
except OSError as e:
if e.errno in (errno.EADDRNOTAVAIL, errno.EAFNOSUPPORT):
# EADDRNOTAVAIL is the errno if IPv6 modules/drivers are loaded but disabled.
# EAFNOSUPPORT is the errno if IPv6 modules/drivers are not loaded at all.
return False
if e.errno == errno.EADDRINUSE:
return True
raise

View File

@ -23,8 +23,8 @@
# or negative for a release candidate or beta (after the base version # or negative for a release candidate or beta (after the base version
# number has been incremented) # number has been incremented)
__version__ = "2.2.47" __version__ = "2.2.48"
__version_info__ = (2, 2, 47, 0) __version_info__ = (2, 2, 48, 0)
if "dev" in __version__: if "dev" in __version__:
try: try:

View File

@ -1,10 +1,10 @@
jsonschema>=4.22.0,<4.23 jsonschema>=4.22.0,<4.23
aiohttp>=3.9.5,<3.10 aiohttp>=3.9.5,<3.10
aiohttp-cors>=0.7.0,<0.8 aiohttp-cors>=0.7.0,<0.8
aiofiles>=23.2.1,<23.3 aiofiles>=24.1.0,<25.0
Jinja2>=3.1.4,<3.2 Jinja2>=3.1.4,<3.2
sentry-sdk==2.1.1,<2.2 sentry-sdk==2.7.1,<2.8
psutil==5.9.8 psutil==6.0.0
async-timeout>=4.0.3,<4.1 async-timeout>=4.0.3,<4.1
distro>=1.9.0 distro>=1.9.0
py-cpuinfo>=9.0.0,<10.0 py-cpuinfo>=9.0.0,<10.0

View File

@ -774,6 +774,14 @@ async def test_build_command_with_invalid_options(vm):
await vm._build_command() await vm._build_command()
@pytest.mark.skipif(sys.platform.startswith("win"), reason="Not supported on Windows")
async def test_build_command_with_forbidden_options(vm):
vm.options = "-blockdev"
with pytest.raises(QemuError):
await vm._build_command()
def test_hda_disk_image(vm, images_dir): def test_hda_disk_image(vm, images_dir):
open(os.path.join(images_dir, "test1"), "w+").close() open(os.path.join(images_dir, "test1"), "w+").close()

View File

@ -325,7 +325,7 @@ async def test_export_with_images(tmpdir, project):
myzip.getinfo("images/IOS/test.image") myzip.getinfo("images/IOS/test.image")
async def test_export_keep_compute_id(tmpdir, project): async def test_export_keep_compute_ids(tmpdir, project):
""" """
If we want to restore the same computes we could ask to keep them If we want to restore the same computes we could ask to keep them
in the file in the file
@ -354,7 +354,7 @@ async def test_export_keep_compute_id(tmpdir, project):
json.dump(data, f) json.dump(data, f)
with aiozipstream.ZipFile() as z: with aiozipstream.ZipFile() as z:
await export_project(z, project, str(tmpdir), keep_compute_id=True) await export_project(z, project, str(tmpdir), keep_compute_ids=True)
await write_file(str(tmpdir / 'zipfile.zip'), z) await write_file(str(tmpdir / 'zipfile.zip'), z)
with zipfile.ZipFile(str(tmpdir / 'zipfile.zip')) as myzip: with zipfile.ZipFile(str(tmpdir / 'zipfile.zip')) as myzip:
@ -458,7 +458,7 @@ async def test_export_with_ignoring_snapshots(tmpdir, project):
Path(os.path.join(snapshots_dir, 'snap.gns3project')).touch() Path(os.path.join(snapshots_dir, 'snap.gns3project')).touch()
with aiozipstream.ZipFile() as z: with aiozipstream.ZipFile() as z:
await export_project(z, project, str(tmpdir), keep_compute_id=True) await export_project(z, project, str(tmpdir), keep_compute_ids=True)
await write_file(str(tmpdir / 'zipfile.zip'), z) await write_file(str(tmpdir / 'zipfile.zip'), z)
with zipfile.ZipFile(str(tmpdir / 'zipfile.zip')) as myzip: with zipfile.ZipFile(str(tmpdir / 'zipfile.zip')) as myzip:

View File

@ -449,7 +449,7 @@ async def test_import_node_id(linux_platform, tmpdir, controller):
assert os.path.exists(os.path.join(project.path, "project-files", "iou", topo["topology"]["nodes"][0]["node_id"], "startup.cfg")) assert os.path.exists(os.path.join(project.path, "project-files", "iou", topo["topology"]["nodes"][0]["node_id"], "startup.cfg"))
async def test_import_keep_compute_id(windows_platform, tmpdir, controller): async def test_import_keep_compute_ids(windows_platform, tmpdir, controller):
""" """
On linux host IOU should be moved to the GNS3 VM On linux host IOU should be moved to the GNS3 VM
""" """
@ -487,7 +487,7 @@ async def test_import_keep_compute_id(windows_platform, tmpdir, controller):
myzip.write(str(tmpdir / "project.gns3"), "project.gns3") myzip.write(str(tmpdir / "project.gns3"), "project.gns3")
with open(zip_path, "rb") as f: with open(zip_path, "rb") as f:
project = await import_project(controller, project_id, f, keep_compute_id=True) project = await import_project(controller, project_id, f, keep_compute_ids=True)
with open(os.path.join(project.path, "test.gns3")) as f: with open(os.path.join(project.path, "test.gns3")) as f:
topo = json.load(f) topo = json.load(f)

View File

@ -750,7 +750,7 @@ def test_snapshots(project):
def test_get_snapshot(project): def test_get_snapshot(project):
os.makedirs(os.path.join(project.path, "snapshots")) os.makedirs(os.path.join(project.path, "snapshots"))
open(os.path.join(project.path, "snapshots", "test1.gns3project"), "w+").close() open(os.path.join(project.path, "snapshots", "test1_260716_103713.gns3project"), "w+").close()
project.reset() project.reset()
snapshot = list(project.snapshots.values())[0] snapshot = list(project.snapshots.values())[0]

View File

@ -61,15 +61,21 @@ def test_snapshot_filename(project):
def test_json(project): def test_json(project):
snapshot = Snapshot(project, filename="test1_260716_100439.gns3project") snapshot = Snapshot(project, filename="snapshot_test_260716_100439.gns3project")
assert snapshot.__json__() == { assert snapshot.__json__() == {
"snapshot_id": snapshot._id, "snapshot_id": snapshot._id,
"name": "test1", "name": "snapshot_test",
"project_id": project.id, "project_id": project.id,
"created_at": 1469527479 "created_at": 1469527479
} }
def test_invalid_snapshot_filename(project):
with pytest.raises(ValueError):
Snapshot(project, filename="snapshot_test_invalid_file.gns3project")
async def test_restore(project, controller): async def test_restore(project, controller):
compute = AsyncioMagicMock() compute = AsyncioMagicMock()