mirror of
https://github.com/GNS3/gns3-server.git
synced 2026-11-10 17:05:53 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
08139ebdd1 | ||
|
|
cd87ac4474 | ||
|
|
77744cc31d | ||
|
|
df9d642a56 | ||
|
|
fad28c766a | ||
|
|
21d9d968c4 | ||
|
|
945a2c98cd | ||
|
|
5e1792ff4d | ||
|
|
a2628042e8 | ||
|
|
e616b09028 | ||
|
|
958865e919 | ||
|
|
7f595b089b | ||
|
|
a76d7576c6 | ||
|
|
533c4544ea | ||
|
|
04a302a389 | ||
|
|
5da742394e | ||
|
|
962c5eed8e | ||
|
|
f4dab1482f | ||
|
|
7ef9b7600c | ||
|
|
c51d71a4fa | ||
|
|
af83adfdf6 | ||
|
|
658bfb7624 | ||
|
|
88a1cef21f | ||
|
|
1ced862c08 | ||
|
|
6097166055 | ||
|
|
38ee79c15f | ||
|
|
a6ca7c4e36 | ||
|
|
b76d2c2150 | ||
|
|
d2a0632ec4 | ||
|
|
fde5f5cbe2 | ||
|
|
7dc5628845 | ||
|
|
723b519e8f | ||
|
|
9c653f7dbf | ||
|
|
c226b2a9ef | ||
|
|
c5c4e1ad56 | ||
|
|
8e2989d747 | ||
|
|
c181df6935 | ||
|
|
24c03406e7 | ||
|
|
6c8c5c1787 | ||
|
|
f541c03b94 | ||
|
|
0a14a08d54 | ||
|
|
29b4e89d21 | ||
|
|
bbb68cb148 | ||
|
|
6f132a2e09 | ||
|
|
d5cfb85de5 | ||
|
|
3dbc714f37 | ||
|
|
682af449f8 | ||
|
|
60f1d76eab | ||
|
|
16b619066a | ||
|
|
d44038305f | ||
|
|
3641742930 | ||
|
|
4bf7838543 | ||
|
|
998fe6d8a4 | ||
|
|
aa79f4cb25 | ||
|
|
2602602193 | ||
|
|
8d969349c8 | ||
|
|
bf67fec242 | ||
|
|
a070a72f66 | ||
|
|
71d1aefb65 | ||
|
|
0b6436d2cb | ||
|
|
77f5044aec | ||
|
|
088ae699de | ||
|
|
21dc2a8dbc | ||
|
|
aae7bf9865 | ||
|
|
4338afab7f | ||
|
|
ef62eba4e8 | ||
|
|
cc4ead40e2 | ||
|
|
67943c4727 | ||
|
|
045c0c4c14 | ||
|
|
a0943b0b5a | ||
|
|
84c886b058 | ||
|
|
e59b5fb95b | ||
|
|
cc4d6759e3 | ||
|
|
e45467af57 | ||
|
|
c6d6fcfe66 | ||
|
|
73bcd019cc | ||
|
|
2361e138ec | ||
|
|
0f02cff5f2 | ||
|
|
72af145a23 | ||
|
|
d03e7ac9c5 | ||
|
|
af2fc8c111 | ||
|
|
25c03b7823 | ||
|
|
b4bfb24a80 | ||
|
|
ce220e5ae4 | ||
|
|
791ce6a56e | ||
|
|
0406083991 | ||
|
|
be557abba9 | ||
|
|
4bdd405bc5 | ||
|
|
229168367b | ||
|
|
e257fb425e | ||
|
|
fac224ac48 | ||
|
|
62c2ca9be1 | ||
|
|
f98a60fc74 | ||
|
|
42a5f1956e | ||
|
|
13df828ca7 | ||
|
|
19a8d1caed | ||
|
|
290df5290a | ||
|
|
fbe10360c2 | ||
|
|
ac042b02c4 | ||
|
|
e44999f588 | ||
|
|
952b4e7249 | ||
|
|
3b0336bd7e | ||
|
|
7689b7841f | ||
|
|
bf5970b904 | ||
|
|
2eca92e34d | ||
|
|
70d3f991ed |
No files matched your search
@@ -1,5 +1,40 @@
|
||||
# Change Log
|
||||
|
||||
## 2.2.42 09/08/2023
|
||||
|
||||
* Bundle web-ui v2.2.42
|
||||
* Handle API version key in VirtualBox 7. Fixes #2266
|
||||
* Enable system certificate store for SSL connections
|
||||
* Use DEFAULT_BUFFER_SIZE for md5sum
|
||||
* Fix version check when installing appliances. Ref https://github.com/GNS3/gns3-gui/issues/3486
|
||||
* Allow connection to ws console over IPv6. Fixes https://github.com/GNS3/gns3-web-ui/issues/1400
|
||||
* Support for Python 3.12
|
||||
* Remove import urllib3 and let sentry_sdk import and patch it. Fixes https://github.com/GNS3/gns3-gui/issues/3498
|
||||
|
||||
## 2.2.41 12/07/2023
|
||||
|
||||
* Bundle web-ui v2.2.41
|
||||
* Catch urllib3 exceptions when sending crash report. Ref https://github.com/GNS3/gns3-gui/issues/3483
|
||||
* Only fetch Qemu version once when starting Qemu + only add speed/duplex for virtio-net-pci with Qemu version >= 2.12
|
||||
* Use recent OVMF firmware (stable-202305) and use flash drives to configure Qemu command line
|
||||
* Remove the useless executable permissions to the file gns3server/disks/empty8G.qcow2
|
||||
* Backport UEFI boot mode support for Qemu VMs
|
||||
|
||||
## 2.2.40.1 10/06/2023
|
||||
|
||||
* Re-bundle Web-Ui v2.2.40. Fixes #2239
|
||||
|
||||
## 2.2.40 06/06/2023
|
||||
|
||||
* qemu : with network adapter_type equal to "virtio-net-pci", fix the speed to 10000 and duplex to full. The values are actually fake. (https://github.com/GNS3/gns3-gui/issues/3476)
|
||||
* Parse name for request to node creation from template
|
||||
* Remove Xvfb + x11vnc support
|
||||
* Require a Host-Only Network to start the VirtualBox GNS3 VM on macOS with VirtualBox 7
|
||||
* Properly catch aiohttp client exception. Ref #2228
|
||||
* Catch ConnectionResetError when waiting for the wrap console
|
||||
* Fix open IPv6 address for HTTP consoles on controller. Fixes https://github.com/GNS3/gns3-gui/issues/3448
|
||||
* Use proc.communicate() when checking for subprocess output As recommended in https://docs.python.org/3/library/asyncio-subprocess.html#asyncio.subprocess.Process.stderr
|
||||
|
||||
## 2.2.39 08/05/2023
|
||||
|
||||
* Install web-ui v2.2.39
|
||||
|
||||
@@ -24,6 +24,22 @@
|
||||
"kvm": "allow"
|
||||
},
|
||||
"images": [
|
||||
{
|
||||
"filename": "AlmaLinux-9-GenericCloud-9.2-20230513.x86_64.qcow2",
|
||||
"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"
|
||||
},
|
||||
{
|
||||
"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"
|
||||
},
|
||||
{
|
||||
"filename": "AlmaLinux-8-GenericCloud-8.7-20221111.x86_64.qcow2",
|
||||
"version": "8.7",
|
||||
@@ -37,10 +53,25 @@
|
||||
"version": "1.0",
|
||||
"md5sum": "72fb52af76e9561d125dd99224e2c1d1",
|
||||
"filesize": 374784,
|
||||
"download_url": "https://github.com/GNS3/gns3-registry/raw/master/cloud-init/AlmaLinux/almalinux-cloud-init-data.iso"
|
||||
"download_url": "https://github.com/GNS3/gns3-registry/tree/master/cloud-init/AlmaLinux",
|
||||
"direct_download_url": "https://github.com/GNS3/gns3-registry/raw/master/cloud-init/AlmaLinux/almalinux-cloud-init-data.iso"
|
||||
}
|
||||
],
|
||||
"versions": [
|
||||
{
|
||||
"name": "9.2",
|
||||
"images": {
|
||||
"hda_disk_image": "AlmaLinux-9-GenericCloud-9.2-20230513.x86_64.qcow2",
|
||||
"cdrom_image": "almalinux-cloud-init-data.iso"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "8.8",
|
||||
"images": {
|
||||
"hda_disk_image": "AlmaLinux-8-GenericCloud-8.8-20230524.x86_64.qcow2",
|
||||
"cdrom_image": "almalinux-cloud-init-data.iso"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "8.7",
|
||||
"images": {
|
||||
|
||||
@@ -32,6 +32,13 @@
|
||||
"process_priority": "normal"
|
||||
},
|
||||
"images": [
|
||||
{
|
||||
"filename": "arubaoscx-disk-image-genericx86-p4-20230531220439.vmdk",
|
||||
"version": "10.12.0006",
|
||||
"md5sum": "c4f80fecd02ef93b431b75dd610e0063",
|
||||
"filesize": 384638464,
|
||||
"download_url": "https://asp.arubanetworks.com/"
|
||||
},
|
||||
{
|
||||
"filename": "arubaoscx-disk-image-genericx86-p4-20221130174651.vmdk",
|
||||
"version": "10.11.0001",
|
||||
@@ -111,6 +118,12 @@
|
||||
}
|
||||
],
|
||||
"versions": [
|
||||
{
|
||||
"name": "10.12.0006",
|
||||
"images": {
|
||||
"hda_disk_image": "arubaoscx-disk-image-genericx86-p4-20230531220439.vmdk"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "10.11.0001",
|
||||
"images": {
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
{
|
||||
"appliance_id": "8fecbf89-5cd1-4aea-b735-5f36cf0efbb7",
|
||||
"name": "BIRD2",
|
||||
"category": "router",
|
||||
"description": "The BIRD project aims to develop a fully functional dynamic IP routing daemon primarily targeted on (but not limited to) Linux, FreeBSD and other UNIX-like systems and distributed under the GNU General Public License.",
|
||||
"vendor_name": "CZ.NIC Labs",
|
||||
"vendor_url": "https://bird.network.cz",
|
||||
"documentation_url": "https://bird.network.cz/?get_doc&f=bird.html&v=20",
|
||||
"product_name": "BIRD internet routing daemon",
|
||||
"registry_version": 4,
|
||||
"status": "stable",
|
||||
"maintainer": "Bernhard Ehlers",
|
||||
"maintainer_email": "dev-ehlers@mailbox.org",
|
||||
"usage": "Username:\tgns3\nPassword:\tgns3\nTo become root, use \"sudo -s\".\n\nNetwork configuration:\nsudo nano /etc/network/interfaces\nsudo systemctl restart networking\n\nBIRD:\nRestart: sudo systemctl restart bird\nReconfigure: birdc configure",
|
||||
"port_name_format": "eth{0}",
|
||||
"qemu": {
|
||||
"adapter_type": "virtio-net-pci",
|
||||
"adapters": 4,
|
||||
"ram": 512,
|
||||
"hda_disk_interface": "scsi",
|
||||
"arch": "x86_64",
|
||||
"console_type": "telnet",
|
||||
"kvm": "allow"
|
||||
},
|
||||
"images": [
|
||||
{
|
||||
"filename": "bird2-debian-2.0.12.qcow2",
|
||||
"version": "2.0.12",
|
||||
"md5sum": "435218a2e90cba921cc7fde1d64a9419",
|
||||
"filesize": 287965184,
|
||||
"download_url": "https://sourceforge.net/projects/gns-3/files/Qemu%20Appliances/",
|
||||
"direct_download_url": "http://downloads.sourceforge.net/project/gns-3/Qemu%20Appliances/bird2-debian-2.0.12.qcow2"
|
||||
}
|
||||
],
|
||||
"versions": [
|
||||
{
|
||||
"name": "2.0.12",
|
||||
"images": {
|
||||
"hda_disk_image": "bird2-debian-2.0.12.qcow2"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -27,35 +27,69 @@
|
||||
},
|
||||
"images": [
|
||||
{
|
||||
"filename": "CentOS-7-x86_64-GenericCloud-2111.qcow2",
|
||||
"version": "7 (2111)",
|
||||
"md5sum": "730b8662695831670721c8245be61dac",
|
||||
"filesize": 897384448,
|
||||
"download_url": "https://cloud.centos.org/centos/7/images/CentOS-7-x86_64-GenericCloud-2111.qcow2"
|
||||
"filename": "CentOS-Stream-GenericCloud-9-20230727.1.x86_64.qcow2",
|
||||
"version": "Stream-9 (20230727.1)",
|
||||
"md5sum": "b66b7e4951cb5491ae44d5616d56b7cf",
|
||||
"filesize": 1128764416,
|
||||
"download_url": "https://cloud.centos.org/centos/9-stream/x86_64/images",
|
||||
"direct_download_url": "https://cloud.centos.org/centos/9-stream/x86_64/images/CentOS-Stream-GenericCloud-9-20230727.1.x86_64.qcow2"
|
||||
},
|
||||
{
|
||||
"filename": "CentOS-7-x86_64-GenericCloud-1809.qcow2",
|
||||
"version": "7 (1809)",
|
||||
"md5sum": "da79108d1324b27bd1759362b82fbe40",
|
||||
"filesize": 914948096,
|
||||
"download_url": "https://cloud.centos.org/centos/7/images/CentOS-7-x86_64-GenericCloud-1809.qcow2"
|
||||
"filename": "CentOS-Stream-GenericCloud-8-20230710.0.x86_64.qcow2",
|
||||
"version": "Stream-8 (20230710.0)",
|
||||
"md5sum": "83e02ce98c29753c86fb7be7d802aa75",
|
||||
"filesize": 1676164096,
|
||||
"download_url": "https://cloud.centos.org/centos/8-stream/x86_64/images",
|
||||
"direct_download_url": "https://cloud.centos.org/centos/8-stream/x86_64/images/CentOS-Stream-GenericCloud-8-20230710.0.x86_64.qcow2"
|
||||
},
|
||||
{
|
||||
"filename": "CentOS-8-GenericCloud-8.4.2105-20210603.0.x86_64.qcow2",
|
||||
"version": "8.4 (2105)",
|
||||
"md5sum": "032eed270415526546eac07628905a62",
|
||||
"filesize": 1309652992,
|
||||
"download_url": "https://cloud.centos.org/centos/8/x86_64/images/CentOS-8-GenericCloud-8.4.2105-20210603.0.x86_64.qcow2"
|
||||
"download_url": "https://cloud.centos.org/centos/8/x86_64/images",
|
||||
"direct_download_url": "https://cloud.centos.org/centos/8/x86_64/images/CentOS-8-GenericCloud-8.4.2105-20210603.0.x86_64.qcow2"
|
||||
},
|
||||
{
|
||||
"filename": "CentOS-7-x86_64-GenericCloud-2111.qcow2",
|
||||
"version": "7 (2111)",
|
||||
"md5sum": "730b8662695831670721c8245be61dac",
|
||||
"filesize": 897384448,
|
||||
"download_url": "https://cloud.centos.org/centos/7/images",
|
||||
"direct_download_url": "https://cloud.centos.org/centos/7/images/CentOS-7-x86_64-GenericCloud-2111.qcow2"
|
||||
},
|
||||
{
|
||||
"filename": "CentOS-7-x86_64-GenericCloud-1809.qcow2",
|
||||
"version": "7 (1809)",
|
||||
"md5sum": "da79108d1324b27bd1759362b82fbe40",
|
||||
"filesize": 914948096,
|
||||
"download_url": "https://cloud.centos.org/centos/7/images",
|
||||
"direct_download_url": "https://cloud.centos.org/centos/7/images/CentOS-7-x86_64-GenericCloud-1809.qcow2"
|
||||
},
|
||||
{
|
||||
"filename": "centos-cloud-init-data.iso",
|
||||
"version": "1.0",
|
||||
"md5sum": "15ca60c12db6d13b8eeae1a19613fd6e",
|
||||
"filesize": 378880,
|
||||
"download_url": "https://github.com/asenci/gns3-centos-cloud-init-data/raw/master/centos-cloud-init-data.iso"
|
||||
"version": "1.1",
|
||||
"md5sum": "59ea8223fd659d8bce9081ff175912e9",
|
||||
"filesize": 374784,
|
||||
"download_url": "https://github.com/GNS3/gns3-registry/tree/master/cloud-init/centos-cloud",
|
||||
"direct_download_url": "https://github.com/GNS3/gns3-registry/raw/master/cloud-init/centos-cloud/centos-cloud-init-data.iso"
|
||||
}
|
||||
],
|
||||
"versions": [
|
||||
{
|
||||
"name": "Stream-9 (20230727.1)",
|
||||
"images": {
|
||||
"hda_disk_image": "CentOS-Stream-GenericCloud-9-20230727.1.x86_64.qcow2",
|
||||
"cdrom_image": "centos-cloud-init-data.iso"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Stream-8 (20230710.0)",
|
||||
"images": {
|
||||
"hda_disk_image": "CentOS-Stream-GenericCloud-8-20230710.0.x86_64.qcow2",
|
||||
"cdrom_image": "centos-cloud-init-data.iso"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "8.4 (2105)",
|
||||
"images": {
|
||||
|
||||
@@ -24,10 +24,17 @@
|
||||
"kvm": "require"
|
||||
},
|
||||
"images": [
|
||||
{
|
||||
"filename": "c8000v-universalk9_8G_serial.17.06.05.qcow2",
|
||||
"version": "17.06.05 8G",
|
||||
"md5sum": "aeb15ab8e1cbd0cd76f7260a81442f98",
|
||||
"filesize": 1777795072,
|
||||
"download_url": "https://software.cisco.com/download/home/286327102/type/282046477/release/Bengaluru-17.6.5"
|
||||
},
|
||||
{
|
||||
"filename": "c8000v-universalk9_8G_serial.17.06.01a.qcow2",
|
||||
"version": "17.06.01a 8G",
|
||||
"md5sum": "d8b8ae633d953ec1b6d8f18a09a4f4e7",
|
||||
"md5sum": "e278fa644295c703976a86f7f1c1cd65",
|
||||
"filesize": 1595277312,
|
||||
"download_url": "https://software.cisco.com/download/home/286327102/type/282046477/release/Bengaluru-17.6.1a"
|
||||
},
|
||||
@@ -47,6 +54,12 @@
|
||||
}
|
||||
],
|
||||
"versions": [
|
||||
{
|
||||
"name": "17.06.05 8G",
|
||||
"images": {
|
||||
"hda_disk_image": "c8000v-universalk9_8G_serial.17.06.05.qcow2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "17.06.01a 8G",
|
||||
"images": {
|
||||
|
||||
@@ -188,12 +188,12 @@
|
||||
"download_url": "https://software.cisco.com/download/"
|
||||
},
|
||||
{
|
||||
"filename": "OVMF-20160813.fd",
|
||||
"version": "16.08.13",
|
||||
"md5sum": "8ff0ef1ec56345db5b6bda1a8630e3c6",
|
||||
"filesize": 2097152,
|
||||
"download_url": "",
|
||||
"direct_download_url": "https://sourceforge.net/projects/gns-3/files/Qemu%20Appliances/OVMF-20160813.fd.zip/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"
|
||||
}
|
||||
],
|
||||
@@ -201,161 +201,161 @@
|
||||
{
|
||||
"name": "9500v 10.1.1",
|
||||
"images": {
|
||||
"bios_image": "OVMF-20160813.fd",
|
||||
"bios_image": "OVMF-edk2-stable202305.fd",
|
||||
"hda_disk_image": "nexus9500v64.10.1.1.qcow2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "9300v 10.1.1",
|
||||
"images": {
|
||||
"bios_image": "OVMF-20160813.fd",
|
||||
"bios_image": "OVMF-edk2-stable202305.fd",
|
||||
"hda_disk_image": "nexus9300v.10.1.1.qcow2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "9500v 9.3.9",
|
||||
"images": {
|
||||
"bios_image": "OVMF-20160813.fd",
|
||||
"bios_image": "OVMF-edk2-stable202305.fd",
|
||||
"hda_disk_image": "nexus9500v.9.3.9.qcow2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "9300v 9.3.9",
|
||||
"images": {
|
||||
"bios_image": "OVMF-20160813.fd",
|
||||
"bios_image": "OVMF-edk2-stable202305.fd",
|
||||
"hda_disk_image": "nexus9300v.9.3.9.qcow2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "9300v 9.3.8",
|
||||
"images": {
|
||||
"bios_image": "OVMF-20160813.fd",
|
||||
"bios_image": "OVMF-edk2-stable202305.fd",
|
||||
"hda_disk_image": "nexus9300v.9.3.8.qcow2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "9500v 9.3.7",
|
||||
"images": {
|
||||
"bios_image": "OVMF-20160813.fd",
|
||||
"bios_image": "OVMF-edk2-stable202305.fd",
|
||||
"hda_disk_image": "nexus9500v.9.3.7.qcow2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "9500v 9.3.3",
|
||||
"images": {
|
||||
"bios_image": "OVMF-20160813.fd",
|
||||
"bios_image": "OVMF-edk2-stable202305.fd",
|
||||
"hda_disk_image": "nexus9500v.9.3.3.qcow2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "9300v 9.3.3",
|
||||
"images": {
|
||||
"bios_image": "OVMF-20160813.fd",
|
||||
"bios_image": "OVMF-edk2-stable202305.fd",
|
||||
"hda_disk_image": "nexus9300v.9.3.3.qcow2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "9.3.1",
|
||||
"images": {
|
||||
"bios_image": "OVMF-20160813.fd",
|
||||
"bios_image": "OVMF-edk2-stable202305.fd",
|
||||
"hda_disk_image": "nxosv.9.3.1.qcow2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "9.2.3",
|
||||
"images": {
|
||||
"bios_image": "OVMF-20160813.fd",
|
||||
"bios_image": "OVMF-edk2-stable202305.fd",
|
||||
"hda_disk_image": "nxosv-final.9.2.3.qcow2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "9.2.2",
|
||||
"images": {
|
||||
"bios_image": "OVMF-20160813.fd",
|
||||
"bios_image": "OVMF-edk2-stable202305.fd",
|
||||
"hda_disk_image": "nxosv-final.9.2.2.qcow2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "9.2.1",
|
||||
"images": {
|
||||
"bios_image": "OVMF-20160813.fd",
|
||||
"bios_image": "OVMF-edk2-stable202305.fd",
|
||||
"hda_disk_image": "nxosv-final.9.2.1.qcow2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "7.0.3.I7.9",
|
||||
"images": {
|
||||
"bios_image": "OVMF-20160813.fd",
|
||||
"bios_image": "OVMF-edk2-stable202305.fd",
|
||||
"hda_disk_image": "nxosv-final.7.0.3.I7.9.qcow2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "7.0.3.I7.7",
|
||||
"images": {
|
||||
"bios_image": "OVMF-20160813.fd",
|
||||
"bios_image": "OVMF-edk2-stable202305.fd",
|
||||
"hda_disk_image": "nxosv-final.7.0.3.I7.7.qcow2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "7.0.3.I7.6",
|
||||
"images": {
|
||||
"bios_image": "OVMF-20160813.fd",
|
||||
"bios_image": "OVMF-edk2-stable202305.fd",
|
||||
"hda_disk_image": "nxosv-final.7.0.3.I7.6.qcow2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "7.0.3.I7.5",
|
||||
"images": {
|
||||
"bios_image": "OVMF-20160813.fd",
|
||||
"bios_image": "OVMF-edk2-stable202305.fd",
|
||||
"hda_disk_image": "nxosv-final.7.0.3.I7.5.qcow2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "7.0.3.I7.4",
|
||||
"images": {
|
||||
"bios_image": "OVMF-20160813.fd",
|
||||
"bios_image": "OVMF-edk2-stable202305.fd",
|
||||
"hda_disk_image": "nxosv-final.7.0.3.I7.4.qcow2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "7.0.3.I7.3",
|
||||
"images": {
|
||||
"bios_image": "OVMF-20160813.fd",
|
||||
"bios_image": "OVMF-edk2-stable202305.fd",
|
||||
"hda_disk_image": "nxosv-final.7.0.3.I7.3.qcow2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "7.0.3.I7.2",
|
||||
"images": {
|
||||
"bios_image": "OVMF-20160813.fd",
|
||||
"bios_image": "OVMF-edk2-stable202305.fd",
|
||||
"hda_disk_image": "nxosv-final.7.0.3.I7.2.qcow2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "7.0.3.I7.1",
|
||||
"images": {
|
||||
"bios_image": "OVMF-20160813.fd",
|
||||
"bios_image": "OVMF-edk2-stable202305.fd",
|
||||
"hda_disk_image": "nxosv-final.7.0.3.I7.1.qcow2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "7.0.3.I6.1",
|
||||
"images": {
|
||||
"bios_image": "OVMF-20160813.fd",
|
||||
"bios_image": "OVMF-edk2-stable202305.fd",
|
||||
"hda_disk_image": "nxosv-final.7.0.3.I6.1.qcow2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "7.0.3.I5.2",
|
||||
"images": {
|
||||
"bios_image": "OVMF-20160813.fd",
|
||||
"bios_image": "OVMF-edk2-stable202305.fd",
|
||||
"hda_disk_image": "nxosv-final.7.0.3.I5.2.qcow2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "7.0.3.I5.1",
|
||||
"images": {
|
||||
"bios_image": "OVMF-20160813.fd",
|
||||
"bios_image": "OVMF-edk2-stable202305.fd",
|
||||
"hda_disk_image": "nxosv-final.7.0.3.I5.1.qcow2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
"product_name": "Debian",
|
||||
"registry_version": 4,
|
||||
"status": "experimental",
|
||||
"maintainer": "GNS3 Team",
|
||||
"maintainer_email": "developers@gns3.net",
|
||||
"maintainer": "Bernhard Ehlers",
|
||||
"maintainer_email": "dev-ehlers@mailbox.org",
|
||||
"usage": "Username:\tdebian\nPassword:\tdebian\nTo become root, use \"sudo -s\".\n\nNetwork configuration:\n- In \"/etc/network/interfaces\" comment out \"source-directory /run/network/interfaces.d\"\n- Remove \"/etc/network/interfaces.d/50-cloud-init\"\n- Create \"/etc/network/interfaces.d/10-ens4\", for example:\n\nauto ens4\n#iface ens4 inet dhcp\niface ens4 inet static\n address 10.1.1.100/24\n gateway 10.1.1.1\n dns-nameservers 10.1.1.1\n",
|
||||
"symbol": "linux_guest.svg",
|
||||
"port_name_format": "ens{port4}",
|
||||
@@ -24,41 +24,57 @@
|
||||
},
|
||||
"images": [
|
||||
{
|
||||
"filename": "debian-11-genericcloud-amd64-20221219-1234.qcow2",
|
||||
"version": "11.6",
|
||||
"md5sum": "bd6ddbccc89e40deb7716b812958238d",
|
||||
"filesize": 258801664,
|
||||
"download_url": "https://cloud.debian.org/images/cloud/bullseye/",
|
||||
"direct_download_url": "https://cloud.debian.org/images/cloud/bullseye/20221219-1234/debian-11-genericcloud-amd64-20221219-1234.qcow2"
|
||||
"filename": "debian-12-genericcloud-amd64-20230723-1450.qcow2",
|
||||
"version": "12.1",
|
||||
"md5sum": "6d1efcaa206de01eeeb590d773421c5c",
|
||||
"filesize": 280166400,
|
||||
"download_url": "https://cloud.debian.org/images/cloud/bookworm/",
|
||||
"direct_download_url": "https://cloud.debian.org/images/cloud/bookworm/20230723-1450/debian-12-genericcloud-amd64-20230723-1450.qcow2"
|
||||
},
|
||||
{
|
||||
"filename": "debian-10-genericcloud-amd64-20220911-1135.qcow2",
|
||||
"filename": "debian-11-genericcloud-amd64-20230601-1398.qcow2",
|
||||
"version": "11.7",
|
||||
"md5sum": "1b24a841dc5ca9bcf40b94ad4b4775d4",
|
||||
"filesize": 259063808,
|
||||
"download_url": "https://cloud.debian.org/images/cloud/bullseye/",
|
||||
"direct_download_url": "https://cloud.debian.org/images/cloud/bullseye/20230601-1398/debian-11-genericcloud-amd64-20230601-1398.qcow2"
|
||||
},
|
||||
{
|
||||
"filename": "debian-10-genericcloud-amd64-20230601-1398.qcow2",
|
||||
"version": "10.13",
|
||||
"md5sum": "9d4d1175bef974caba79dd6ca33d500c",
|
||||
"filesize": 234749952,
|
||||
"md5sum": "ca799fb4011712f4686c422c1a9731cf",
|
||||
"filesize": 228130816,
|
||||
"download_url": "https://cloud.debian.org/images/cloud/buster/",
|
||||
"direct_download_url": "https://cloud.debian.org/images/cloud/buster/20220911-1135/debian-10-genericcloud-amd64-20220911-1135.qcow2"
|
||||
"direct_download_url": "https://cloud.debian.org/images/cloud/buster/20230601-1398/debian-10-genericcloud-amd64-20230601-1398.qcow2"
|
||||
},
|
||||
{
|
||||
"filename": "debian-cloud-init-data.iso",
|
||||
"version": "1.0",
|
||||
"md5sum": "43f6bf70c178a9d3c270b5c24971e578",
|
||||
"filesize": 374784,
|
||||
"download_url": "https://github.com/GNS3/gns3-registry/raw/master/cloud-init/Debian/debian-cloud-init-data.iso"
|
||||
"download_url": "https://github.com/GNS3/gns3-registry/tree/master/cloud-init/Debian",
|
||||
"direct_download_url": "https://github.com/GNS3/gns3-registry/raw/master/cloud-init/Debian/debian-cloud-init-data.iso"
|
||||
}
|
||||
],
|
||||
"versions": [
|
||||
{
|
||||
"name": "11.6",
|
||||
"name": "12.1",
|
||||
"images": {
|
||||
"hda_disk_image": "debian-11-genericcloud-amd64-20221219-1234.qcow2",
|
||||
"hda_disk_image": "debian-12-genericcloud-amd64-20230723-1450.qcow2",
|
||||
"cdrom_image": "debian-cloud-init-data.iso"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "11.7",
|
||||
"images": {
|
||||
"hda_disk_image": "debian-11-genericcloud-amd64-20230601-1398.qcow2",
|
||||
"cdrom_image": "debian-cloud-init-data.iso"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "10.13",
|
||||
"images": {
|
||||
"hda_disk_image": "debian-10-genericcloud-amd64-20220911-1135.qcow2",
|
||||
"hda_disk_image": "debian-10-genericcloud-amd64-20230601-1398.qcow2",
|
||||
"cdrom_image": "debian-cloud-init-data.iso"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"appliance_id": "f59a5cf6-baaa-45a6-9685-989a2c3f3f4a",
|
||||
"name": "endhost",
|
||||
"category": "guest",
|
||||
"description": "General purpose alpine-based endhost",
|
||||
"vendor_name": "endhost",
|
||||
"vendor_url": "https://www.alpinelinux.org",
|
||||
"product_name": "endhost",
|
||||
"registry_version": 4,
|
||||
"status": "experimental",
|
||||
"maintainer": "GNS3 Team",
|
||||
"maintainer_email": "developers@gns3.net",
|
||||
"docker": {
|
||||
"adapters": 1,
|
||||
"image": "gns3/endhost:latest"
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,13 @@
|
||||
"options": "-nographic"
|
||||
},
|
||||
"images": [
|
||||
{
|
||||
"filename": "VOSSGNS3.8.10.1.0.qcow2",
|
||||
"version": "v8.10.1.0",
|
||||
"md5sum": "d8f09f5a9759882be84ad7e4be575ed3",
|
||||
"filesize": 433258496,
|
||||
"direct_download_url": "https://akamai-ep.extremenetworks.com/Extreme_P/github-en/Virtual_VOSS/VOSSGNS3.8.10.1.0.qcow2"
|
||||
},
|
||||
{
|
||||
"filename": "VOSSGNS3.8.8.0.0.qcow2",
|
||||
"version": "v8.8.0.0",
|
||||
@@ -85,6 +92,13 @@
|
||||
}
|
||||
],
|
||||
"versions": [
|
||||
{
|
||||
"name": "v8.10.1.0",
|
||||
"images":
|
||||
{
|
||||
"hda_disk_image": "VOSSGNS3.8.10.1.0.qcow2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v8.8.0.0",
|
||||
"images": {
|
||||
|
||||
@@ -26,22 +26,69 @@
|
||||
"options": "-nographic"
|
||||
},
|
||||
"images": [
|
||||
{
|
||||
"filename": "Fedora-Cloud-Base-38-1.6.x86_64.qcow2",
|
||||
"version": "38-1.6",
|
||||
"md5sum": "53ddfe7b28666d5ddc55e93ff06abad2",
|
||||
"filesize": 497287168,
|
||||
"download_url": "https://download.fedoraproject.org/pub/fedora/linux/releases/38/Cloud/x86_64/images",
|
||||
"direct_download_url": "https://download.fedoraproject.org/pub/fedora/linux/releases/38/Cloud/x86_64/images/Fedora-Cloud-Base-38-1.6.x86_64.qcow2"
|
||||
},
|
||||
{
|
||||
"filename": "Fedora-Cloud-Base-37-1.7.x86_64.qcow2",
|
||||
"version": "37-1.7",
|
||||
"md5sum": "36f7b464b6ab46ad97c001b539495e90",
|
||||
"filesize": 492830720,
|
||||
"download_url": "https://download.fedoraproject.org/pub/fedora/linux/releases/37/Cloud/x86_64/images",
|
||||
"direct_download_url": "https://download.fedoraproject.org/pub/fedora/linux/releases/37/Cloud/x86_64/images/Fedora-Cloud-Base-37-1.7.x86_64.qcow2"
|
||||
},
|
||||
{
|
||||
"filename": "Fedora-Cloud-Base-36-1.5.x86_64.qcow2",
|
||||
"version": "36-1.5",
|
||||
"md5sum": "7f7cdad25b77f232078bf454c39529d3",
|
||||
"filesize": 448266240,
|
||||
"download_url": "https://download.fedoraproject.org/pub/fedora/linux/releases/36/Cloud/x86_64/images",
|
||||
"direct_download_url": "https://download.fedoraproject.org/pub/fedora/linux/releases/36/Cloud/x86_64/images/Fedora-Cloud-Base-36-1.5.x86_64.qcow2"
|
||||
},
|
||||
{
|
||||
"filename": "Fedora-Cloud-Base-35-1.2.x86_64.qcow2",
|
||||
"version": "35-1.2",
|
||||
"md5sum": "cfa9cdcfb946e5f4cf9dd4d7906008d0",
|
||||
"filesize": 376897536,
|
||||
"download_url": "https://download.fedoraproject.org/pub/fedora/linux/releases/35/Cloud/x86_64/images/Fedora-Cloud-Base-35-1.2.x86_64.qcow2"
|
||||
"download_url": "https://download.fedoraproject.org/pub/fedora/linux/releases/35/Cloud/x86_64/images",
|
||||
"direct_download_url": "https://download.fedoraproject.org/pub/fedora/linux/releases/35/Cloud/x86_64/images/Fedora-Cloud-Base-35-1.2.x86_64.qcow2"
|
||||
},
|
||||
{
|
||||
"filename": "fedora-cloud-init-data.iso",
|
||||
"version": "1.0",
|
||||
"md5sum": "3d0d6391d3f5ece1180c70b9667c4dca",
|
||||
"filesize": 374784,
|
||||
"download_url": "https://github.com/GNS3/gns3-registry/raw/master/cloud-init/fedora-cloud/fedora-cloud-init-data.iso"
|
||||
"download_url": "https://github.com/GNS3/gns3-registry/tree/master/cloud-init/fedora-cloud",
|
||||
"direct_download_url": "https://github.com/GNS3/gns3-registry/raw/master/cloud-init/fedora-cloud/fedora-cloud-init-data.iso"
|
||||
}
|
||||
],
|
||||
"versions": [
|
||||
{
|
||||
"name": "38-1.6",
|
||||
"images": {
|
||||
"hda_disk_image": "Fedora-Cloud-Base-38-1.6.x86_64.qcow2",
|
||||
"cdrom_image": "fedora-cloud-init-data.iso"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "37-1.7",
|
||||
"images": {
|
||||
"hda_disk_image": "Fedora-Cloud-Base-37-1.7.x86_64.qcow2",
|
||||
"cdrom_image": "fedora-cloud-init-data.iso"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "36-1.5",
|
||||
"images": {
|
||||
"hda_disk_image": "Fedora-Cloud-Base-36-1.5.x86_64.qcow2",
|
||||
"cdrom_image": "fedora-cloud-init-data.iso"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "35-1.2",
|
||||
"images": {
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"appliance_id": "79df483d-8cc9-48de-85ea-e6cb45b93e2a",
|
||||
"name": "haproxy",
|
||||
"category": "guest",
|
||||
"description": "haproxy alpine container",
|
||||
"vendor_name": "haproxy",
|
||||
"vendor_url": "https://www.haproxy.org",
|
||||
"product_name": "haproxy",
|
||||
"registry_version": 4,
|
||||
"status": "experimental",
|
||||
"maintainer": "GNS3 Team",
|
||||
"maintainer_email": "developers@gns3.net",
|
||||
"usage": "Modify /etc/haproxy/haproxy.cfg to suit your needs.",
|
||||
"docker": {
|
||||
"adapters": 1,
|
||||
"image": "gns3/haproxy:latest"
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,7 @@
|
||||
"arch": "x86_64",
|
||||
"console_type": "telnet",
|
||||
"kvm": "require",
|
||||
"options": "-machine type=pc-1.0,accel=kvm -serial mon:stdio -nographic -nodefaults -rtc base=utc -cpu host"
|
||||
"options": "-machine type=pc,accel=kvm -serial mon:stdio -nographic -nodefaults -rtc base=utc -cpu host"
|
||||
},
|
||||
"images": [
|
||||
{
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
"arch": "x86_64",
|
||||
"console_type": "telnet",
|
||||
"kvm": "require",
|
||||
"options": "-machine type=pc-1.0,accel=kvm -serial mon:stdio -nographic -nodefaults -rtc base=utc -cpu host"
|
||||
"options": "-machine type=pc,accel=kvm -serial mon:stdio -nographic -nodefaults -rtc base=utc -cpu host"
|
||||
},
|
||||
"images": [
|
||||
{
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
"product_name": "ipterm",
|
||||
"registry_version": 4,
|
||||
"status": "stable",
|
||||
"maintainer": "GNS3 Team",
|
||||
"maintainer_email": "developers@gns3.net",
|
||||
"maintainer": "Bernhard Ehlers",
|
||||
"maintainer_email": "dev-ehlers@mailbox.org",
|
||||
"usage": "The /root directory is persistent.",
|
||||
"symbol": "linux_guest.svg",
|
||||
"docker": {
|
||||
|
||||
@@ -27,6 +27,15 @@
|
||||
"options": "-nographic"
|
||||
},
|
||||
"images": [
|
||||
{
|
||||
"filename": "chr-7.10.1.img",
|
||||
"version": "7.10.1",
|
||||
"md5sum": "917729e79b9992562f4160d461b21cac",
|
||||
"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",
|
||||
"compression": "zip"
|
||||
},
|
||||
{
|
||||
"filename": "chr-7.7.img",
|
||||
"version": "7.7",
|
||||
@@ -83,6 +92,12 @@
|
||||
}
|
||||
],
|
||||
"versions": [
|
||||
{
|
||||
"name": "7.10.1",
|
||||
"images": {
|
||||
"hda_disk_image": "chr-7.10.1.img"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "7.7",
|
||||
"images": {
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"appliance_id": "b770027f-1822-4ab6-b2f9-73336ca0983d",
|
||||
"name": "Mikrotik WinBox",
|
||||
"category": "guest",
|
||||
"description": "Mikrotik's WinBox router management software for GNS3",
|
||||
"vendor_name": "Mikrotik",
|
||||
"vendor_url": "https://mikrotik.com",
|
||||
"product_name": "Mikrotik WinBox",
|
||||
"registry_version": 4,
|
||||
"status": "stable",
|
||||
"availability": "free",
|
||||
"maintainer": "Alexander Horner",
|
||||
"maintainer_email": "contact@alexhorner.cc",
|
||||
"docker": {
|
||||
"adapters": 1,
|
||||
"image": "gns3/mikrotik-winbox",
|
||||
"console_type": "vnc"
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@
|
||||
"usage": "In the web interface login as admin/admin\n\nPersistent configuration:\n- Add \"/var/lib/redis\" as an additional persistent directory.\n- Use \"redis-cli save\" in an auxiliary console to save the configuration.",
|
||||
"docker": {
|
||||
"adapters": 1,
|
||||
"image": "ntop/ntopng:latest",
|
||||
"image": "ntop/ntopng:stable",
|
||||
"start_command": "--dns-mode 2 --interface eth0",
|
||||
"console_type": "http",
|
||||
"console_http_port": 3000,
|
||||
|
||||
@@ -25,6 +25,13 @@
|
||||
"kvm": "require"
|
||||
},
|
||||
"images": [
|
||||
{
|
||||
"filename": "OPNsense-23.1-OpenSSL-nano-amd64.img",
|
||||
"version": "23.1",
|
||||
"md5sum": "db7d3b9fd3b94894623368db1041ff11",
|
||||
"filesize": 3221225472,
|
||||
"download_url": "https://opnsense.c0urier.net/releases/23.1/"
|
||||
},
|
||||
{
|
||||
"filename": "OPNsense-22.1.2-OpenSSL-nano-amd64.img",
|
||||
"version": "22.1.2",
|
||||
@@ -55,6 +62,12 @@
|
||||
}
|
||||
],
|
||||
"versions": [
|
||||
{
|
||||
"name": "23.1",
|
||||
"images": {
|
||||
"hda_disk_image": "OPNsense-23.1-OpenSSL-nano-amd64.img"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "22.1.2",
|
||||
"images": {
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
{
|
||||
"appliance_id": "88e67f45-e0de-4e5e-9f36-2dc83e4a6c60",
|
||||
"name": "Oracle Linux Cloud Guest",
|
||||
"category": "guest",
|
||||
"description": "A highly performant and secure operating environment, Oracle Linux delivers virtualization, management, automation, and cloud native computing tools, along with the operating system, in a single, easy-to-manage support offering. Oracle Linux provides a 100% application binary compatible alternative to Red Hat Enterprise Linux and CentOS Linux and is supported across both hybrid and multicloud environments.",
|
||||
"vendor_name": "Oracle Corporation",
|
||||
"vendor_url": "https://www.oracle.com",
|
||||
"documentation_url": "https://docs.oracle.com/en-us/iaas/images/",
|
||||
"product_name": "Oracle Linux Cloud Guest",
|
||||
"product_url": "https://www.oracle.com/au/linux/",
|
||||
"registry_version": 4,
|
||||
"status": "stable",
|
||||
"maintainer": "GNS3 Team",
|
||||
"maintainer_email": "developers@gns3.net",
|
||||
"usage": "Username: oracle\nPassword: oracle",
|
||||
"port_name_format": "Ethernet{0}",
|
||||
"qemu": {
|
||||
"adapter_type": "virtio-net-pci",
|
||||
"adapters": 1,
|
||||
"ram": 1024,
|
||||
"hda_disk_interface": "virtio",
|
||||
"arch": "x86_64",
|
||||
"console_type": "telnet",
|
||||
"boot_priority": "c",
|
||||
"kvm": "require",
|
||||
"options": "-cpu host -nographic"
|
||||
},
|
||||
"images": [
|
||||
{
|
||||
"filename": "OL9U1_x86_64-kvm-b158.qcow",
|
||||
"version": "9.1",
|
||||
"md5sum": "9f32851b96fc38191892197fa11f7435",
|
||||
"filesize": 539033600,
|
||||
"download_url": "https://yum.oracle.com/oracle-linux-templates.html",
|
||||
"direct_download_url": "https://yum.oracle.com/templates/OracleLinux/OL9/u1/x86_64/OL9U1_x86_64-kvm-b158.qcow"
|
||||
},
|
||||
{
|
||||
"filename": "OL8U7_x86_64-kvm-b148.qcow",
|
||||
"version": "8.7",
|
||||
"md5sum": "962cdde7e810888b9914e937222f687f",
|
||||
"filesize": 913965056,
|
||||
"download_url": "https://yum.oracle.com/oracle-linux-templates.html",
|
||||
"direct_download_url": "https://yum.oracle.com/templates/OracleLinux/OL8/u7/x86_64/OL8U7_x86_64-kvm-b148.qcow"
|
||||
},
|
||||
{
|
||||
"filename": "oracle-cloud-init-data.iso",
|
||||
"version": "1.1",
|
||||
"md5sum": "cb51bc42ae9dfb7345bfa7362a313baf",
|
||||
"filesize": 374784,
|
||||
"download_url": "https://github.com/GNS3/gns3-registry/tree/master/cloud-init/oracle-cloud",
|
||||
"direct_download_url": "https://github.com/GNS3/gns3-registry/raw/master/cloud-init/oracle-cloud/oracle-cloud-init-data.iso"
|
||||
}
|
||||
],
|
||||
"versions": [
|
||||
{
|
||||
"name": "9.1",
|
||||
"images": {
|
||||
"hda_disk_image": "OL9U1_x86_64-kvm-b158.qcow",
|
||||
"cdrom_image": "oracle-cloud-init-data.iso"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "8.7",
|
||||
"images": {
|
||||
"hda_disk_image": "OL8U7_x86_64-kvm-b148.qcow",
|
||||
"cdrom_image": "oracle-cloud-init-data.iso"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -24,6 +24,13 @@
|
||||
"process_priority": "normal"
|
||||
},
|
||||
"images": [
|
||||
{
|
||||
"filename": "pfSense-CE-2.7.0-RELEASE-amd64.iso",
|
||||
"version": "2.7.0",
|
||||
"md5sum": "cb0b72ca864d06682265de5e5a72a1fb",
|
||||
"filesize": 765218816,
|
||||
"download_url": "https://www.pfsense.org/download/mirror.php?section=downloads"
|
||||
},
|
||||
{
|
||||
"filename": "pfSense-CE-2.6.0-RELEASE-amd64.iso",
|
||||
"version": "2.6.0",
|
||||
@@ -69,6 +76,13 @@
|
||||
}
|
||||
],
|
||||
"versions": [
|
||||
{
|
||||
"name": "2.7.0",
|
||||
"images": {
|
||||
"hda_disk_image": "empty100G.qcow2",
|
||||
"cdrom_image": "pfSense-CE-2.7.0-RELEASE-amd64.iso"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "2.6.0",
|
||||
"images": {
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
"availability": "service-contract",
|
||||
"maintainer": "Neyder Achahuanco",
|
||||
"maintainer_email": "neyder@neyder.net",
|
||||
"usage": "You should download Red Hat Enterprise Linux KVM Guest Image from https://access.redhat.com/downloads/content/479/ver=/rhel---8/8.5/x86_64/product-software attach/customize cloud-init.iso and start.\nusername: cloud-user\npassword: redhat",
|
||||
"usage": "You should download Red Hat Enterprise Linux KVM Guest Image from https://access.redhat.com/downloads/content/479/ver=/rhel---9/9.2/x86_64/product-software attach/customize cloud-init.iso and start.\nusername: cloud-user\npassword: redhat",
|
||||
"qemu": {
|
||||
"adapter_type": "virtio-net-pci",
|
||||
"adapters": 1,
|
||||
@@ -26,6 +26,48 @@
|
||||
"options": "-nographic"
|
||||
},
|
||||
"images": [
|
||||
{
|
||||
"filename": "rhel-9.2-x86_64-kvm.qcow2",
|
||||
"version": "9.2",
|
||||
"md5sum": "f33845298b387dbcfbf162c6b4e3f8c8",
|
||||
"filesize": 819265536,
|
||||
"download_url": "https://access.redhat.com/downloads/content/479/ver=/rhel---8/9.2/x86_64/product-software"
|
||||
},
|
||||
{
|
||||
"filename": "rhel-baseos-9.1-x86_64-kvm.qcow2",
|
||||
"version": "9.1",
|
||||
"md5sum": "622de743da83bcec1ad2959ecaedb8f4",
|
||||
"filesize": 753401856,
|
||||
"download_url": "https://access.redhat.com/downloads/content/479/ver=/rhel---8/9.1/x86_64/product-software"
|
||||
},
|
||||
{
|
||||
"filename": "rhel-baseos-9.0-x86_64-kvm.qcow2",
|
||||
"version": "9.0",
|
||||
"md5sum": "4a41497d354fe99a4abf55f1ed73edcb",
|
||||
"filesize": 696582144,
|
||||
"download_url": "https://access.redhat.com/downloads/content/479/ver=/rhel---8/9.0/x86_64/product-software"
|
||||
},
|
||||
{
|
||||
"filename": "rhel-8.8-x86_64-kvm.qcow2",
|
||||
"version": "8.8",
|
||||
"md5sum": "bf22af816ba6abd846bbb0c9ecf7bce1",
|
||||
"filesize": 926810112,
|
||||
"download_url": "https://access.redhat.com/downloads/content/479/ver=/rhel---8/8.8/x86_64/product-software"
|
||||
},
|
||||
{
|
||||
"filename": "rhel-8.7-x86_64-kvm.qcow2",
|
||||
"version": "8.7",
|
||||
"md5sum": "ab71a2c4cc276441bf999f531e064507",
|
||||
"filesize": 858128384,
|
||||
"download_url": "https://access.redhat.com/downloads/content/479/ver=/rhel---8/8.7/x86_64/product-software"
|
||||
},
|
||||
{
|
||||
"filename": "rhel-8.6-x86_64-kvm.qcow2",
|
||||
"version": "8.6",
|
||||
"md5sum": "19501666f46df6b5472db1254e86a339",
|
||||
"filesize": 832438272,
|
||||
"download_url": "https://access.redhat.com/downloads/content/479/ver=/rhel---8/8.6/x86_64/product-software"
|
||||
},
|
||||
{
|
||||
"filename": "rhel-8.5-x86_64-kvm.qcow2",
|
||||
"version": "8.5",
|
||||
@@ -70,6 +112,48 @@
|
||||
}
|
||||
],
|
||||
"versions": [
|
||||
{
|
||||
"name": "9.2",
|
||||
"images": {
|
||||
"hda_disk_image": "rhel-9.2-x86_64-kvm.qcow2",
|
||||
"cdrom_image": "rhel-cloud-init.iso"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "9.1",
|
||||
"images": {
|
||||
"hda_disk_image": "rhel-baseos-9.1-x86_64-kvm.qcow2",
|
||||
"cdrom_image": "rhel-cloud-init.iso"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "9.0",
|
||||
"images": {
|
||||
"hda_disk_image": "rhel-baseos-9.0-x86_64-kvm.qcow2",
|
||||
"cdrom_image": "rhel-cloud-init.iso"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "8.8",
|
||||
"images": {
|
||||
"hda_disk_image": "rhel-8.8-x86_64-kvm.qcow2",
|
||||
"cdrom_image": "rhel-cloud-init.iso"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "8.7",
|
||||
"images": {
|
||||
"hda_disk_image": "rhel-8.7-x86_64-kvm.qcow2",
|
||||
"cdrom_image": "rhel-cloud-init.iso"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "8.6",
|
||||
"images": {
|
||||
"hda_disk_image": "rhel-8.6-x86_64-kvm.qcow2",
|
||||
"cdrom_image": "rhel-cloud-init.iso"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "8.5",
|
||||
"images": {
|
||||
|
||||
@@ -39,7 +39,8 @@
|
||||
"version": "1.0",
|
||||
"md5sum": "33ffda3a81436e305f37fb913edd6d43",
|
||||
"filesize": 374784,
|
||||
"download_url": "https://github.com/GNS3/gns3-registry/raw/master/cloud-init/rocky-cloud/rocky-cloud-init-data.iso"
|
||||
"download_url": "https://github.com/GNS3/gns3-registry/tree/master/cloud-init/rocky-cloud",
|
||||
"direct_download_url": "https://github.com/GNS3/gns3-registry/raw/master/cloud-init/rocky-cloud/rocky-cloud-init-data.iso"
|
||||
}
|
||||
],
|
||||
"versions": [
|
||||
|
||||
@@ -26,98 +26,75 @@
|
||||
"options": "-nographic"
|
||||
},
|
||||
"images": [
|
||||
{
|
||||
"filename": "ubuntu-23.04-server-cloudimg-arm64.img",
|
||||
"version": "Ubuntu 23.04 (Lunar Lobster)",
|
||||
"md5sum": "35fa3b31b65717af6f0520a769aac8c0",
|
||||
"filesize": 786432000,
|
||||
"download_url": "https://cloud-images.ubuntu.com/releases/23.04/release/",
|
||||
"direct_download_url": "https://cloud-images.ubuntu.com/releases/23.04/release/ubuntu-23.04-server-cloudimg-arm64.img"
|
||||
},
|
||||
{
|
||||
"filename": "ubuntu-22.04-server-cloudimg-amd64.img",
|
||||
"version": "22.04 (LTS)",
|
||||
"md5sum": "ac2351289daa173fa1ed6b2b81d81d7c",
|
||||
"filesize": 624295936,
|
||||
"download_url": "https://cloud-images.ubuntu.com/releases/jammy/release/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"
|
||||
},
|
||||
{
|
||||
"filename": "ubuntu-20.04-server-cloudimg-amd64.img",
|
||||
"version": "20.04 (LTS)",
|
||||
"version": "Ubuntu 20.04 LTS (Focal Fossa)",
|
||||
"md5sum": "044bc979b2238192ee3edb44e2bb6405",
|
||||
"filesize": 552337408,
|
||||
"download_url": "https://cloud-images.ubuntu.com/releases/focal/release-20210119.1/ubuntu-20.04-server-cloudimg-amd64.img"
|
||||
"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"
|
||||
},
|
||||
{
|
||||
"filename": "ubuntu-18.04-server-cloudimg-amd64.img",
|
||||
"version": "18.04 (LTS)",
|
||||
"version": "Ubuntu 18.04 LTS (Bionic Beaver)",
|
||||
"md5sum": "f4134e7fa16d7fa766c7467cbe25c949",
|
||||
"filesize": 336134144,
|
||||
"download_url": "https://cloud-images.ubuntu.com/releases/18.04/release-20180426.2/ubuntu-18.04-server-cloudimg-amd64.img"
|
||||
},
|
||||
{
|
||||
"filename": "ubuntu-17.10-server-cloudimg-amd64.img",
|
||||
"version": "17.10",
|
||||
"md5sum": "331b44f2b05858c251b3ea92c8b65152",
|
||||
"filesize": 320405504,
|
||||
"download_url": "https://cloud-images.ubuntu.com/releases/17.10/release-20180404/ubuntu-17.10-server-cloudimg-amd64.img"
|
||||
},
|
||||
{
|
||||
"filename": "ubuntu-16.04-server-cloudimg-amd64-disk1.img",
|
||||
"version": "16.04 (LTS)",
|
||||
"md5sum": "22c124ba65ea096cdef8b0a197dd613a",
|
||||
"filesize": 290193408,
|
||||
"download_url": "https://cloud-images.ubuntu.com/releases/16.04/release-20180405/ubuntu-16.04-server-cloudimg-amd64-disk1.img"
|
||||
},
|
||||
{
|
||||
"filename": "ubuntu-14.04-server-cloudimg-amd64-disk1.img",
|
||||
"version": "14.04 (LTS)",
|
||||
"md5sum": "d11b89321d41d0eeddcacf73bf0d2262",
|
||||
"filesize": 262668800,
|
||||
"download_url": "https://cloud-images.ubuntu.com/releases/14.04/release-20180404/ubuntu-14.04-server-cloudimg-amd64-disk1.img"
|
||||
"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"
|
||||
},
|
||||
{
|
||||
"filename": "ubuntu-cloud-init-data.iso",
|
||||
"version": "1.0",
|
||||
"md5sum": "328469100156ae8dbf262daa319c27ff",
|
||||
"filesize": 131072,
|
||||
"download_url": "https://github.com/asenci/gns3-ubuntu-cloud-init-data/raw/master/ubuntu-cloud-init-data.iso"
|
||||
"version": "1.1",
|
||||
"md5sum": "9a90ee8f88736204c756015b3cd86500",
|
||||
"filesize": 374784,
|
||||
"download_url": "https://github.com/GNS3/gns3-registry/tree/master/cloud-init/ubuntu-cloud",
|
||||
"direct_download_url": "https://github.com/GNS3/gns3-registry/raw/master/cloud-init/ubuntu-cloud/ubuntu-cloud-init-data.iso"
|
||||
}
|
||||
],
|
||||
"versions": [
|
||||
{
|
||||
"name": "22.04 (LTS)",
|
||||
"name": "Ubuntu 23.04 (Lunar Lobster)",
|
||||
"images": {
|
||||
"hda_disk_image": "ubuntu-23.04-server-cloudimg-arm64.img",
|
||||
"cdrom_image": "ubuntu-cloud-init-data.iso"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Ubuntu 22.04 LTS (Jammy Jellyfish)",
|
||||
"images": {
|
||||
"hda_disk_image": "ubuntu-22.04-server-cloudimg-amd64.img",
|
||||
"cdrom_image": "ubuntu-cloud-init-data.iso"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "20.04 (LTS)",
|
||||
"name": "Ubuntu 20.04 LTS (Focal Fossa)",
|
||||
"images": {
|
||||
"hda_disk_image": "ubuntu-20.04-server-cloudimg-amd64.img",
|
||||
"cdrom_image": "ubuntu-cloud-init-data.iso"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "18.04 (LTS)",
|
||||
"name": "Ubuntu 18.04 LTS (Bionic Beaver)",
|
||||
"images": {
|
||||
"hda_disk_image": "ubuntu-18.04-server-cloudimg-amd64.img",
|
||||
"cdrom_image": "ubuntu-cloud-init-data.iso"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "17.10",
|
||||
"images": {
|
||||
"hda_disk_image": "ubuntu-17.10-server-cloudimg-amd64.img",
|
||||
"cdrom_image": "ubuntu-cloud-init-data.iso"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "16.04 (LTS)",
|
||||
"images": {
|
||||
"hda_disk_image": "ubuntu-16.04-server-cloudimg-amd64-disk1.img",
|
||||
"cdrom_image": "ubuntu-cloud-init-data.iso"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "14.04 (LTS)",
|
||||
"images": {
|
||||
"hda_disk_image": "ubuntu-14.04-server-cloudimg-amd64-disk1.img",
|
||||
"cdrom_image": "ubuntu-cloud-init-data.iso"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -8,8 +8,8 @@
|
||||
"product_name": "webterm",
|
||||
"registry_version": 4,
|
||||
"status": "stable",
|
||||
"maintainer": "GNS3 Team",
|
||||
"maintainer_email": "developers@gns3.net",
|
||||
"maintainer": "Bernhard Ehlers",
|
||||
"maintainer_email": "dev-ehlers@mailbox.org",
|
||||
"usage": "The /root directory is persistent.",
|
||||
"symbol": "firefox.svg",
|
||||
"docker": {
|
||||
|
||||
@@ -38,12 +38,12 @@
|
||||
"compression": "zip"
|
||||
},
|
||||
{
|
||||
"filename": "OVMF-20160813.fd",
|
||||
"version": "16.08.13",
|
||||
"md5sum": "8ff0ef1ec56345db5b6bda1a8630e3c6",
|
||||
"filesize": 2097152,
|
||||
"download_url": "",
|
||||
"direct_download_url": "https://sourceforge.net/projects/gns-3/files/Qemu%20Appliances/OVMF-20160813.fd.zip/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"
|
||||
}
|
||||
],
|
||||
@@ -51,7 +51,7 @@
|
||||
{
|
||||
"name": "2212",
|
||||
"images": {
|
||||
"bios_image": "OVMF-20160813.fd",
|
||||
"bios_image": "OVMF-edk2-stable202305.fd",
|
||||
"hda_disk_image": "WinDev2212Eval-disk1.vmdk"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,13 @@
|
||||
"options": "-usbdevice tablet"
|
||||
},
|
||||
"images": [
|
||||
{
|
||||
"filename": "SERVER_EVAL_x64FRE_en-us.iso",
|
||||
"version": "2022",
|
||||
"md5sum": "e7908933449613edc97e1b11180429d1",
|
||||
"filesize": 5044094976,
|
||||
"download_url": "https://www.microsoft.com/en-gb/evalcenter/evaluate-windows-server-2022"
|
||||
},
|
||||
{
|
||||
"filename": "Win2k16_14393.0.161119-1705.RS1_REFRESH_SERVER_EVAL_X64FRE_EN-US.ISO",
|
||||
"version": "2016",
|
||||
@@ -51,6 +58,13 @@
|
||||
}
|
||||
],
|
||||
"versions": [
|
||||
{
|
||||
"name": "2022",
|
||||
"images": {
|
||||
"hda_disk_image": "empty100G.qcow2",
|
||||
"cdrom_image": "SERVER_EVAL_x64FRE_en-us.iso"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "2016",
|
||||
"images": {
|
||||
|
||||
@@ -409,7 +409,10 @@ class BaseNode:
|
||||
if self._wrapper_telnet_server:
|
||||
self._wrap_console_writer.close()
|
||||
if sys.version_info >= (3, 7, 0):
|
||||
await self._wrap_console_writer.wait_closed()
|
||||
try:
|
||||
await self._wrap_console_writer.wait_closed()
|
||||
except ConnectionResetError:
|
||||
pass
|
||||
self._wrapper_telnet_server.close()
|
||||
await self._wrapper_telnet_server.wait_closed()
|
||||
self._wrapper_telnet_server = None
|
||||
|
||||
@@ -150,9 +150,9 @@ class Docker(BaseManager):
|
||||
data=data,
|
||||
headers={"content-type": "application/json", },
|
||||
timeout=timeout)
|
||||
except (aiohttp.ClientResponseError, aiohttp.ClientOSError) as e:
|
||||
except aiohttp.ClientError as e:
|
||||
raise DockerError("Docker has returned an error: {}".format(str(e)))
|
||||
except (asyncio.TimeoutError):
|
||||
except asyncio.TimeoutError:
|
||||
raise DockerError("Docker timeout " + method + " " + path)
|
||||
if response.status >= 300:
|
||||
body = await response.read()
|
||||
|
||||
@@ -85,7 +85,6 @@ class DockerVM(BaseNode):
|
||||
self._ethernet_adapters = []
|
||||
self._temporary_directory = None
|
||||
self._telnet_servers = []
|
||||
self._xvfb_process = None
|
||||
self._vnc_process = None
|
||||
self._vncconfig_process = None
|
||||
self._console_resolution = console_resolution
|
||||
@@ -585,8 +584,8 @@ class DockerVM(BaseNode):
|
||||
self._display = self._get_free_display_port()
|
||||
tigervnc_path = shutil.which("Xtigervnc") or shutil.which("Xvnc")
|
||||
|
||||
if not (tigervnc_path or shutil.which("Xvfb") and shutil.which("x11vnc")):
|
||||
raise DockerError("Please install TigerVNC (recommended) or Xvfb + x11vnc before using VNC support")
|
||||
if not tigervnc_path:
|
||||
raise DockerError("Please install TigerVNC server before using VNC support")
|
||||
|
||||
if tigervnc_path:
|
||||
with open(os.path.join(self.working_dir, "vnc.log"), "w") as fd:
|
||||
@@ -600,29 +599,6 @@ class DockerVM(BaseNode):
|
||||
"-SecurityTypes", "None",
|
||||
":{}".format(self._display),
|
||||
stdout=fd, stderr=subprocess.STDOUT)
|
||||
else:
|
||||
if restart is False:
|
||||
self._xvfb_process = await asyncio.create_subprocess_exec("Xvfb",
|
||||
"-nolisten", "tcp",
|
||||
"-extension", "MIT-SHM",
|
||||
":{}".format(self._display),
|
||||
"-screen", "0",
|
||||
self._console_resolution + "x16")
|
||||
|
||||
# We pass a port for TCPV6 due to a crash in X11VNC if not here: https://github.com/GNS3/gns3-server/issues/569
|
||||
with open(os.path.join(self.working_dir, "vnc.log"), "w") as fd:
|
||||
self._vnc_process = await asyncio.create_subprocess_exec("x11vnc",
|
||||
"-forever",
|
||||
"-nopw",
|
||||
"-shared",
|
||||
"-noshm",
|
||||
"-geometry", self._console_resolution,
|
||||
"-display", "WAIT:{}".format(self._display),
|
||||
"-rfbport", str(self.console),
|
||||
"-rfbportv6", str(self.console),
|
||||
"-noncache",
|
||||
"-listen", self._manager.port_manager.console_host,
|
||||
stdout=fd, stderr=subprocess.STDOUT)
|
||||
|
||||
async def _start_vnc(self):
|
||||
"""
|
||||
@@ -631,8 +607,8 @@ class DockerVM(BaseNode):
|
||||
|
||||
self._display = self._get_free_display_port()
|
||||
tigervnc_path = shutil.which("Xtigervnc") or shutil.which("Xvnc")
|
||||
if not (tigervnc_path or shutil.which("Xvfb") and shutil.which("x11vnc")):
|
||||
raise DockerError("Please install TigerVNC server (recommended) or Xvfb + x11vnc before using VNC support")
|
||||
if not tigervnc_path:
|
||||
raise DockerError("Please install TigerVNC server before using VNC support")
|
||||
await self._start_vnc_process()
|
||||
x11_socket = os.path.join("/tmp/.X11-unix/", "X{}".format(self._display))
|
||||
try:
|
||||
@@ -875,12 +851,6 @@ class DockerVM(BaseNode):
|
||||
await self._vnc_process.wait()
|
||||
except ProcessLookupError:
|
||||
pass
|
||||
if self._xvfb_process:
|
||||
try:
|
||||
self._xvfb_process.terminate()
|
||||
await self._xvfb_process.wait()
|
||||
except ProcessLookupError:
|
||||
pass
|
||||
|
||||
if self._display:
|
||||
display = "/tmp/.X11-unix/X{}".format(self._display)
|
||||
|
||||
@@ -86,6 +86,7 @@ class QemuVM(BaseNode):
|
||||
self._local_udp_tunnels = {}
|
||||
self._guest_cid = None
|
||||
self._command_line_changed = False
|
||||
self._qemu_version = None
|
||||
|
||||
# QEMU VM settings
|
||||
if qemu_path:
|
||||
@@ -122,6 +123,7 @@ class QemuVM(BaseNode):
|
||||
self._kernel_image = ""
|
||||
self._kernel_command_line = ""
|
||||
self._tpm = False
|
||||
self._uefi = False
|
||||
self._legacy_networking = False
|
||||
self._replicate_network_connection_state = True
|
||||
self._create_config_disk = False
|
||||
@@ -833,6 +835,30 @@ class QemuVM(BaseNode):
|
||||
log.info('QEMU VM "{name}" [{id}] has disabled the Trusted Platform Module (TPM)'.format(name=self._name, id=self._id))
|
||||
self._tpm = tpm
|
||||
|
||||
@property
|
||||
def uefi(self):
|
||||
"""
|
||||
Returns whether UEFI boot mode is activated for this QEMU VM.
|
||||
|
||||
:returns: boolean
|
||||
"""
|
||||
|
||||
return self._uefi
|
||||
|
||||
@uefi.setter
|
||||
def uefi(self, uefi):
|
||||
"""
|
||||
Sets whether UEFI boot mode is activated for this QEMU VM.
|
||||
|
||||
:param uefi: boolean
|
||||
"""
|
||||
|
||||
if uefi:
|
||||
log.info(f'QEMU VM "{self._name}" [{self._id}] has enabled the UEFI boot mode')
|
||||
else:
|
||||
log.info(f'QEMU VM "{self._name}" [{self._id}] has disabled the UEFI boot mode')
|
||||
self._uefi = uefi
|
||||
|
||||
@property
|
||||
def options(self):
|
||||
"""
|
||||
@@ -1846,8 +1872,7 @@ class QemuVM(BaseNode):
|
||||
# special case, sata controller doesn't exist in Qemu
|
||||
options.extend(["-device", 'ahci,id=ahci{}'.format(disk_index)])
|
||||
options.extend(["-drive", 'file={},if=none,id=drive{},index={},media=disk{}'.format(disk, disk_index, disk_index, extra_drive_options)])
|
||||
qemu_version = await self.manager.get_qemu_version(self.qemu_path)
|
||||
if qemu_version and parse_version(qemu_version) >= parse_version("4.2.0"):
|
||||
if self._qemu_version and parse_version(self._qemu_version) >= parse_version("4.2.0"):
|
||||
# The ‘ide-drive’ device is deprecated since version 4.2.0
|
||||
# https://qemu.readthedocs.io/en/latest/system/deprecated.html#ide-drive-since-4-2
|
||||
options.extend(["-device", 'ide-hd,drive=drive{},bus=ahci{}.0,id=drive{}'.format(disk_index, disk_index, disk_index)])
|
||||
@@ -1994,12 +2019,28 @@ class QemuVM(BaseNode):
|
||||
|
||||
options = []
|
||||
if self._bios_image:
|
||||
if self._uefi:
|
||||
raise QemuError("Cannot use a bios image and the UEFI boot mode at the same time")
|
||||
if not os.path.isfile(self._bios_image) or not os.path.exists(self._bios_image):
|
||||
if os.path.islink(self._bios_image):
|
||||
raise QemuError("bios image '{}' linked to '{}' is not accessible".format(self._bios_image, os.path.realpath(self._bios_image)))
|
||||
else:
|
||||
raise QemuError("bios image '{}' is not accessible".format(self._bios_image))
|
||||
options.extend(["-bios", self._bios_image.replace(",", ",,")])
|
||||
elif self._uefi:
|
||||
# get the OVMF firmware from the images directory
|
||||
ovmf_firmware_path = self.manager.get_abs_image_path("OVMF_CODE.fd")
|
||||
log.info("Configuring UEFI boot mode using OVMF file: '{}'".format(ovmf_firmware_path))
|
||||
options.extend(["-drive", "if=pflash,format=raw,readonly,file={}".format(ovmf_firmware_path)])
|
||||
|
||||
# the node should have its own copy of OVMF_VARS.fd (the UEFI variables store)
|
||||
ovmf_vars_node_path = os.path.join(self.working_dir, "OVMF_VARS.fd")
|
||||
if not os.path.exists(ovmf_vars_node_path):
|
||||
try:
|
||||
shutil.copyfile(self.manager.get_abs_image_path("OVMF_VARS.fd"), ovmf_vars_node_path)
|
||||
except OSError as e:
|
||||
raise QemuError("Cannot copy OVMF_VARS.fd file to the node working directory: {}".format(e))
|
||||
options.extend(["-drive", "if=pflash,format=raw,file={}".format(ovmf_vars_node_path)])
|
||||
return options
|
||||
|
||||
def _linux_boot_options(self):
|
||||
@@ -2090,11 +2131,10 @@ class QemuVM(BaseNode):
|
||||
|
||||
patched_qemu = False
|
||||
if self._legacy_networking:
|
||||
qemu_version = await self.manager.get_qemu_version(self.qemu_path)
|
||||
if qemu_version:
|
||||
if parse_version(qemu_version) >= parse_version("2.9.0"):
|
||||
if self._qemu_version:
|
||||
if parse_version(self._qemu_version) >= parse_version("2.9.0"):
|
||||
raise QemuError("Qemu version 2.9.0 and later doesn't support legacy networking mode")
|
||||
if parse_version(qemu_version) < parse_version("1.1.0"):
|
||||
if parse_version(self._qemu_version) < parse_version("1.1.0"):
|
||||
# this is a patched Qemu if version is below 1.1.0
|
||||
patched_qemu = True
|
||||
|
||||
@@ -2103,8 +2143,7 @@ class QemuVM(BaseNode):
|
||||
pci_bridges = math.floor(pci_devices / 32)
|
||||
pci_bridges_created = 0
|
||||
if pci_bridges >= 1:
|
||||
qemu_version = await self.manager.get_qemu_version(self.qemu_path)
|
||||
if qemu_version and parse_version(qemu_version) < parse_version("2.4.0"):
|
||||
if self._qemu_version and parse_version(self._qemu_version) < parse_version("2.4.0"):
|
||||
raise QemuError("Qemu version 2.4 or later is required to run this VM with a large number of network adapters")
|
||||
|
||||
pci_device_id = 4 + pci_bridges # Bridge consume PCI ports
|
||||
@@ -2150,6 +2189,10 @@ class QemuVM(BaseNode):
|
||||
else:
|
||||
# newer QEMU networking syntax
|
||||
device_string = "{},mac={}".format(adapter_type, mac)
|
||||
if adapter_type == "virtio-net-pci" and \
|
||||
self._qemu_version and parse_version(self._qemu_version) >= parse_version("2.12"):
|
||||
# speed and duplex support was added in Qemu 2.12
|
||||
device_string = "{},speed=10000,duplex=full".format(device_string)
|
||||
bridge_id = math.floor(pci_device_id / 32)
|
||||
if bridge_id > 0:
|
||||
if pci_bridges_created < bridge_id:
|
||||
@@ -2181,8 +2224,7 @@ class QemuVM(BaseNode):
|
||||
|
||||
if any(opt in self._options for opt in ["-display", "-nographic", "-curses", "-sdl" "-spice", "-vnc"]):
|
||||
return []
|
||||
version = await self.manager.get_qemu_version(self.qemu_path)
|
||||
if version and parse_version(version) >= parse_version("3.0"):
|
||||
if self._qemu_version and parse_version(self._qemu_version) >= parse_version("3.0"):
|
||||
return ["-display", "none"]
|
||||
else:
|
||||
return ["-nographic"]
|
||||
@@ -2227,9 +2269,8 @@ class QemuVM(BaseNode):
|
||||
elif sys.platform.startswith("win"):
|
||||
if require_hardware_accel:
|
||||
# HAXM is only available starting with Qemu version 2.9.0
|
||||
version = await self.manager.get_qemu_version(self.qemu_path)
|
||||
if version and parse_version(version) < parse_version("2.9.0"):
|
||||
raise QemuError("HAXM acceleration can only be enable for Qemu version 2.9.0 and above (current version: {})".format(version))
|
||||
if self._qemu_version and parse_version(self._qemu_version) < parse_version("2.9.0"):
|
||||
raise QemuError("HAXM acceleration can only be enable for Qemu version 2.9.0 and above (current version: {})".format(self._qemu_version))
|
||||
|
||||
# check if HAXM is installed
|
||||
version = self.manager.get_haxm_windows_version()
|
||||
@@ -2329,6 +2370,7 @@ class QemuVM(BaseNode):
|
||||
(to be passed to subprocess.Popen())
|
||||
"""
|
||||
|
||||
self._qemu_version = await self.manager.get_qemu_version(self.qemu_path)
|
||||
vm_name = self._name.replace(",", ",,")
|
||||
project_path = self.project.path.replace(",", ",,")
|
||||
additional_options = self._options.strip()
|
||||
@@ -2346,10 +2388,9 @@ class QemuVM(BaseNode):
|
||||
if await self._run_with_hardware_acceleration(self.qemu_path, self._options):
|
||||
if sys.platform.startswith("linux"):
|
||||
command.extend(["-enable-kvm"])
|
||||
version = await self.manager.get_qemu_version(self.qemu_path)
|
||||
# Issue on some combo Intel CPU + KVM + Qemu 2.4.0
|
||||
# https://github.com/GNS3/gns3-server/issues/685
|
||||
if version and parse_version(version) >= parse_version("2.4.0") and self.platform == "x86_64":
|
||||
if self._qemu_version and parse_version(self._qemu_version) >= parse_version("2.4.0") and self.platform == "x86_64":
|
||||
command.extend(["-machine", "smm=off"])
|
||||
elif sys.platform.startswith("win") or sys.platform.startswith("darwin"):
|
||||
command.extend(["-enable-hax"])
|
||||
|
||||
@@ -251,7 +251,9 @@ class Controller:
|
||||
self._iou_license_settings = controller_settings["iou_license"]
|
||||
|
||||
previous_version = controller_settings.get("version")
|
||||
if not previous_version or parse_version(__version__) > parse_version(previous_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()
|
||||
|
||||
self._appliance_manager.appliances_etag = controller_settings.get("appliances_etag")
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
# 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 os
|
||||
import json
|
||||
import uuid
|
||||
@@ -23,6 +22,7 @@ import asyncio
|
||||
import aiohttp
|
||||
import shutil
|
||||
|
||||
|
||||
try:
|
||||
import importlib_resources
|
||||
except ImportError:
|
||||
@@ -200,7 +200,10 @@ class ApplianceManager:
|
||||
log.info("Checking if appliances are up-to-date (ETag {})".format(self._appliances_etag))
|
||||
headers["If-None-Match"] = self._appliances_etag
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.get('https://api.github.com/repos/GNS3/gns3-registry/contents/appliances', headers=headers) as response:
|
||||
async with session.get(
|
||||
'https://api.github.com/repos/GNS3/gns3-registry/contents/appliances',
|
||||
headers=headers
|
||||
) as response:
|
||||
if response.status == 304:
|
||||
log.info("Appliances are already up-to-date (ETag {})".format(self._appliances_etag))
|
||||
return
|
||||
|
||||
@@ -450,7 +450,7 @@ class Compute:
|
||||
elif response.type == aiohttp.WSMsgType.CLOSED:
|
||||
pass
|
||||
break
|
||||
except aiohttp.client_exceptions.ClientResponseError as e:
|
||||
except aiohttp.ClientError as e:
|
||||
log.error("Client response error received on compute '{}' WebSocket '{}': {}".format(self._id, ws_url,e))
|
||||
finally:
|
||||
self._connected = False
|
||||
|
||||
@@ -80,6 +80,9 @@ class VirtualBoxGNS3VM(BaseGNS3VM):
|
||||
except ValueError:
|
||||
continue
|
||||
self._system_properties[name.strip()] = value.strip()
|
||||
if "API Version" in self._system_properties:
|
||||
# API version is not consistent between VirtualBox versions, the key is named "API Version" in VirtualBox 7
|
||||
self._system_properties["API version"] = self._system_properties.pop("API Version")
|
||||
|
||||
async def _check_requirements(self):
|
||||
"""
|
||||
@@ -122,9 +125,9 @@ class VirtualBoxGNS3VM(BaseGNS3VM):
|
||||
continue
|
||||
return interface
|
||||
|
||||
async def _look_for_vboxnet(self, interface_number):
|
||||
async def _look_for_vboxnet(self, backend_type, interface_number):
|
||||
"""
|
||||
Look for the VirtualBox network name associated with a host only interface.
|
||||
Look for the VirtualBox network name associated with an interface.
|
||||
|
||||
:returns: None or vboxnet name
|
||||
"""
|
||||
@@ -133,7 +136,7 @@ class VirtualBoxGNS3VM(BaseGNS3VM):
|
||||
for info in result.splitlines():
|
||||
if '=' in info:
|
||||
name, value = info.split('=', 1)
|
||||
if name == "hostonlyadapter{}".format(interface_number):
|
||||
if name == "{}{}".format(backend_type, interface_number):
|
||||
return value.strip('"')
|
||||
return None
|
||||
|
||||
@@ -159,7 +162,7 @@ class VirtualBoxGNS3VM(BaseGNS3VM):
|
||||
return True
|
||||
return False
|
||||
|
||||
async def _check_vboxnet_exists(self, vboxnet):
|
||||
async def _check_vboxnet_exists(self, vboxnet, vboxnet_type):
|
||||
"""
|
||||
Check if the vboxnet interface exists
|
||||
|
||||
@@ -167,7 +170,7 @@ class VirtualBoxGNS3VM(BaseGNS3VM):
|
||||
:returns: boolean
|
||||
"""
|
||||
|
||||
properties = await self._execute("list", ["hostonlyifs"])
|
||||
properties = await self._execute("list", ["{}".format(vboxnet_type)])
|
||||
for prop in properties.splitlines():
|
||||
try:
|
||||
name, value = prop.split(':', 1)
|
||||
@@ -230,29 +233,42 @@ class VirtualBoxGNS3VM(BaseGNS3VM):
|
||||
if nat_interface_number < 0:
|
||||
raise GNS3VMError('VM "{}" must have a NAT interface configured in order to start'.format(self.vmname))
|
||||
|
||||
hostonly_interface_number = await self._look_for_interface("hostonly")
|
||||
if hostonly_interface_number < 0:
|
||||
raise GNS3VMError('VM "{}" must have a host-only interface configured in order to start'.format(self.vmname))
|
||||
if sys.platform.startswith("darwin") and parse_version(self._system_properties["API version"]) >= parse_version("7_0"):
|
||||
# VirtualBox 7.0+ on macOS requires a host-only network interface
|
||||
backend_type = "hostonly-network"
|
||||
backend_description = "host-only network"
|
||||
vboxnet_type = "hostonlynets"
|
||||
interface_number = await self._look_for_interface("hostonlynetwork")
|
||||
if interface_number < 0:
|
||||
raise GNS3VMError('VM "{}" must have a network adapter attached to a host-only network in order to start'.format(self.vmname))
|
||||
else:
|
||||
backend_type = "hostonlyadapter"
|
||||
backend_description = "host-only adapter"
|
||||
vboxnet_type = "hostonlyifs"
|
||||
interface_number = await self._look_for_interface("hostonly")
|
||||
|
||||
vboxnet = await self._look_for_vboxnet(hostonly_interface_number)
|
||||
if interface_number < 0:
|
||||
raise GNS3VMError('VM "{}" must have a network adapter attached to a {} in order to start'.format(self.vmname, backend_description))
|
||||
|
||||
vboxnet = await self._look_for_vboxnet(backend_type, interface_number)
|
||||
if vboxnet is None:
|
||||
raise GNS3VMError('A VirtualBox host-only network could not be found on network adapter {} for "{}"'.format(hostonly_interface_number, self._vmname))
|
||||
raise GNS3VMError('A VirtualBox host-only network could not be found on network adapter {} for "{}"'.format(interface_number, self._vmname))
|
||||
|
||||
if not (await self._check_vboxnet_exists(vboxnet)):
|
||||
if not (await self._check_vboxnet_exists(vboxnet, vboxnet_type)):
|
||||
if sys.platform.startswith("win") and vboxnet == "vboxnet0":
|
||||
# The GNS3 VM is configured with vboxnet0 by default which is not available
|
||||
# on Windows. Try to patch this with the first available vboxnet we find.
|
||||
first_available_vboxnet = await self._find_first_available_vboxnet()
|
||||
if first_available_vboxnet is None:
|
||||
raise GNS3VMError('Please add a VirtualBox host-only network with DHCP enabled and attached it to network adapter {} for "{}"'.format(hostonly_interface_number, self._vmname))
|
||||
await self.set_hostonly_network(hostonly_interface_number, first_available_vboxnet)
|
||||
raise GNS3VMError('Please add a VirtualBox host-only network with DHCP enabled and attached it to network adapter {} for "{}"'.format(interface_number, self._vmname))
|
||||
await self.set_hostonly_network(interface_number, first_available_vboxnet)
|
||||
vboxnet = first_available_vboxnet
|
||||
else:
|
||||
raise GNS3VMError('VirtualBox host-only network "{}" does not exist, please make the sure the network adapter {} configuration is valid for "{}"'.format(vboxnet,
|
||||
hostonly_interface_number,
|
||||
interface_number,
|
||||
self._vmname))
|
||||
|
||||
if not (await self._check_dhcp_server(vboxnet)):
|
||||
if backend_type == "hostonlyadapter" and not (await self._check_dhcp_server(vboxnet)):
|
||||
raise GNS3VMError('DHCP must be enabled on VirtualBox host-only network "{}"'.format(vboxnet))
|
||||
|
||||
vm_state = await self._get_state()
|
||||
@@ -296,7 +312,7 @@ class VirtualBoxGNS3VM(BaseGNS3VM):
|
||||
await self._execute("controlvm", [self._vmname, "natpf{}".format(nat_interface_number),
|
||||
"GNS3VM,tcp,{},{},,{}".format(ip_address, api_port, self.port)])
|
||||
|
||||
self.ip_address = await self._get_ip(hostonly_interface_number, api_port)
|
||||
self.ip_address = await self._get_ip(interface_number, api_port)
|
||||
log.info("GNS3 VM has been started with IP {}".format(self.ip_address))
|
||||
self.running = True
|
||||
|
||||
|
||||
@@ -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 ipaddress
|
||||
import aiohttp
|
||||
import asyncio
|
||||
import html
|
||||
@@ -716,6 +717,17 @@ class Node:
|
||||
"first_port_name": self._first_port_name,
|
||||
"custom_adapters": self._custom_adapters
|
||||
}
|
||||
|
||||
# add brackets around console host for http/https console type
|
||||
console_host = str(self._compute.console_host)
|
||||
if self._console_type == "http" or self._console_type == "https":
|
||||
try:
|
||||
ip = ipaddress.ip_address(console_host)
|
||||
if isinstance(ip, ipaddress.IPv6Address):
|
||||
console_host = '[' + console_host + ']'
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
return {
|
||||
"compute_id": str(self._compute.id),
|
||||
"project_id": self._project.id,
|
||||
@@ -725,7 +737,7 @@ class Node:
|
||||
"node_directory": self._node_directory,
|
||||
"name": self._name,
|
||||
"console": self._console,
|
||||
"console_host": str(self._compute.console_host),
|
||||
"console_host": console_host,
|
||||
"console_type": self._console_type,
|
||||
"console_auto_start": self._console_auto_start,
|
||||
"command_line": self._command_line,
|
||||
|
||||
@@ -798,7 +798,7 @@ class Project:
|
||||
try:
|
||||
await compute.post("/projects/{}/close".format(self._id), dont_connect=True)
|
||||
# We don't care if a compute is down at this step
|
||||
except (ComputeError, aiohttp.web.HTTPError, aiohttp.ClientResponseError, TimeoutError):
|
||||
except (ComputeError, aiohttp.web.HTTPError, aiohttp.ClientError, TimeoutError):
|
||||
pass
|
||||
self._clean_pictures()
|
||||
self._status = "closed"
|
||||
|
||||
@@ -32,7 +32,6 @@ import distro
|
||||
|
||||
from .version import __version__, __version_info__
|
||||
from .config import Config
|
||||
from .utils.get_resource import get_resource
|
||||
|
||||
import logging
|
||||
log = logging.getLogger(__name__)
|
||||
@@ -58,7 +57,7 @@ class CrashReport:
|
||||
Report crash to a third party service
|
||||
"""
|
||||
|
||||
DSN = "https://75db396c4c294ad7a05ff7e8804ae5b8@o19455.ingest.sentry.io/38482"
|
||||
DSN = "https://226eee142b22cc399d1566b3dd4cbc86@o19455.ingest.sentry.io/38482"
|
||||
_instance = None
|
||||
|
||||
def __init__(self):
|
||||
@@ -71,22 +70,16 @@ class CrashReport:
|
||||
sentry_uncaught.disabled = True
|
||||
|
||||
if SENTRY_SDK_AVAILABLE:
|
||||
cacert = None
|
||||
if hasattr(sys, "frozen"):
|
||||
cacert_resource = get_resource("cacert.pem")
|
||||
if cacert_resource is not None and os.path.isfile(cacert_resource):
|
||||
cacert = cacert_resource
|
||||
else:
|
||||
log.error("The SSL certificate bundle file '{}' could not be found".format(cacert_resource))
|
||||
|
||||
# Don't send log records as events.
|
||||
sentry_logging = LoggingIntegration(level=logging.INFO, event_level=None)
|
||||
|
||||
sentry_sdk.init(dsn=CrashReport.DSN,
|
||||
release=__version__,
|
||||
ca_certs=cacert,
|
||||
default_integrations=False,
|
||||
integrations=[sentry_logging])
|
||||
try:
|
||||
sentry_sdk.init(dsn=CrashReport.DSN,
|
||||
release=__version__,
|
||||
default_integrations=False,
|
||||
integrations=[sentry_logging])
|
||||
except Exception as e:
|
||||
log.error("Crash report could not be sent: {}".format(e))
|
||||
return
|
||||
|
||||
tags = {
|
||||
"os:name": platform.system(),
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Executable → Regular
File mode changed.
@@ -17,6 +17,7 @@
|
||||
|
||||
import aiohttp
|
||||
import asyncio
|
||||
import ipaddress
|
||||
|
||||
from gns3server.web.route import Route
|
||||
from gns3server.controller import Controller
|
||||
@@ -477,7 +478,16 @@ class NodeHandler:
|
||||
await ws.prepare(request)
|
||||
request.app['websockets'].add(ws)
|
||||
|
||||
ws_console_compute_url = "ws://{compute_host}:{compute_port}/v2/compute/projects/{project_id}/{node_type}/nodes/{node_id}/console/ws".format(compute_host=compute.host,
|
||||
compute_host = compute.host
|
||||
try:
|
||||
# handle IPv6 address
|
||||
ip = ipaddress.ip_address(compute_host)
|
||||
if isinstance(ip, ipaddress.IPv6Address):
|
||||
compute_host = '[' + compute_host + ']'
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
ws_console_compute_url = "ws://{compute_host}:{compute_port}/v2/compute/projects/{project_id}/{node_type}/nodes/{node_id}/console/ws".format(compute_host=compute_host,
|
||||
compute_port=compute.port,
|
||||
project_id=project.id,
|
||||
node_type=node.node_type,
|
||||
|
||||
@@ -169,6 +169,7 @@ class TemplateHandler:
|
||||
node = await project.add_node_from_template(request.match_info["template_id"],
|
||||
x=request.json["x"],
|
||||
y=request.json["y"],
|
||||
name=request.json.get("name"),
|
||||
compute_id=request.json.get("compute_id"))
|
||||
response.set_status(201)
|
||||
response.json(node)
|
||||
+7
-1
@@ -35,7 +35,6 @@ from gns3server.version import __version__
|
||||
from gns3server.config import Config
|
||||
from gns3server.crash_report import CrashReport
|
||||
|
||||
|
||||
import logging
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@@ -243,6 +242,13 @@ def run():
|
||||
user_log.info("Running with Python {major}.{minor}.{micro} and has PID {pid}".format(major=sys.version_info[0], minor=sys.version_info[1],
|
||||
micro=sys.version_info[2], pid=os.getpid()))
|
||||
|
||||
try:
|
||||
import truststore
|
||||
truststore.inject_into_ssl()
|
||||
log.info("Using system certificate store for SSL connections")
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
# check for the correct locale (UNIX/Linux only)
|
||||
locale_check()
|
||||
|
||||
|
||||
@@ -194,6 +194,10 @@ QEMU_CREATE_SCHEMA = {
|
||||
"description": "Enable the Trusted Platform Module (TPM) in Qemu",
|
||||
"type": ["boolean", "null"],
|
||||
},
|
||||
"uefi": {
|
||||
"description": "Enable the UEFI boot mode in Qemu",
|
||||
"type": ["boolean", "null"],
|
||||
},
|
||||
"create_config_disk": {
|
||||
"description": "Automatically create a config disk on HDD disk interface (secondary slave)",
|
||||
"type": ["boolean", "null"],
|
||||
@@ -392,6 +396,10 @@ QEMU_UPDATE_SCHEMA = {
|
||||
"description": "Enable the Trusted Platform Module (TPM) in Qemu",
|
||||
"type": ["boolean", "null"],
|
||||
},
|
||||
"uefi": {
|
||||
"description": "Enable the UEFI boot mode in Qemu",
|
||||
"type": ["boolean", "null"],
|
||||
},
|
||||
"create_config_disk": {
|
||||
"description": "Automatically create a config disk on HDD disk interface (secondary slave)",
|
||||
"type": ["boolean", "null"],
|
||||
@@ -603,6 +611,10 @@ QEMU_OBJECT_SCHEMA = {
|
||||
"description": "Enable the Trusted Platform Module (TPM) in Qemu",
|
||||
"type": "boolean",
|
||||
},
|
||||
"uefi": {
|
||||
"description": "Enable the UEFI boot mode in Qemu",
|
||||
"type": "boolean",
|
||||
},
|
||||
"create_config_disk": {
|
||||
"description": "Automatically create a config disk on HDD disk interface (secondary slave)",
|
||||
"type": ["boolean", "null"],
|
||||
@@ -678,6 +690,7 @@ QEMU_OBJECT_SCHEMA = {
|
||||
"legacy_networking",
|
||||
"replicate_network_connection_state",
|
||||
"tpm",
|
||||
"uefi",
|
||||
"create_config_disk",
|
||||
"on_close",
|
||||
"cpu_throttling",
|
||||
|
||||
@@ -188,6 +188,11 @@ QEMU_TEMPLATE_PROPERTIES = {
|
||||
"type": "boolean",
|
||||
"default": False
|
||||
},
|
||||
"uefi": {
|
||||
"description": "Enable the UEFI boot mode in Qemu",
|
||||
"type": "boolean",
|
||||
"default": False
|
||||
},
|
||||
"create_config_disk": {
|
||||
"description": "Automatically create a config disk on HDD disk interface (secondary slave)",
|
||||
"type": "boolean",
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
"use strict";(self.webpackChunkgns3_web_ui=self.webpackChunkgns3_web_ui||[]).push([[26],{91026:function(W,g,a){a.r(g),a.d(g,{TopologySummaryComponent:function(){return U}});var t=a(38999),_=a(96852),h=a(14200),f=a(36889),v=a(3941),y=a(15132),p=a(40098),x=a(39095),c=a(88802),S=a(73044),d=a(59412),T=a(93386);function C(i,e){if(1&i){var o=t.EpF();t.TgZ(0,"div",2),t.NdJ("mousemove",function(r){return t.CHM(o),t.oxw().dragWidget(r)},!1,t.evT)("mouseup",function(){return t.CHM(o),t.oxw().toggleDragging(!1)},!1,t.evT),t.qZA()}}function b(i,e){1&i&&(t.O4$(),t.TgZ(0,"svg",28),t._UZ(1,"rect",29),t.qZA())}function E(i,e){1&i&&(t.O4$(),t.TgZ(0,"svg",28),t._UZ(1,"rect",30),t.qZA())}function Z(i,e){1&i&&(t.O4$(),t.TgZ(0,"svg",28),t._UZ(1,"rect",31),t.qZA())}function O(i,e){if(1&i&&(t.TgZ(0,"div"),t._uU(1),t.qZA()),2&i){var o=t.oxw().$implicit;t.xp6(1),t.lnq(" ",o.console_type,"://",o.console_host,":",o.console," ")}}function P(i,e){1&i&&(t.TgZ(0,"div"),t._uU(1," none "),t.qZA())}function M(i,e){if(1&i&&(t.TgZ(0,"div",25),t.TgZ(1,"div"),t.YNc(2,b,2,0,"svg",26),t.YNc(3,E,2,0,"svg",26),t.YNc(4,Z,2,0,"svg",26),t._uU(5),t.qZA(),t.YNc(6,O,2,3,"div",27),t.YNc(7,P,2,0,"div",27),t.qZA()),2&i){var o=e.$implicit;t.xp6(2),t.Q6J("ngIf","started"===o.status),t.xp6(1),t.Q6J("ngIf","suspended"===o.status),t.xp6(1),t.Q6J("ngIf","stopped"===o.status),t.xp6(1),t.hij(" ",o.name," "),t.xp6(1),t.Q6J("ngIf",null!=o.console&&null!=o.console&&"none"!=o.console_type),t.xp6(1),t.Q6J("ngIf",null==o.console||"none"===o.console_type)}}function w(i,e){1&i&&(t.O4$(),t.TgZ(0,"svg",28),t._UZ(1,"rect",29),t.qZA())}function A(i,e){1&i&&(t.O4$(),t.TgZ(0,"svg",28),t._UZ(1,"rect",31),t.qZA())}function F(i,e){if(1&i&&(t.TgZ(0,"div",25),t.TgZ(1,"div"),t.YNc(2,w,2,0,"svg",26),t.YNc(3,A,2,0,"svg",26),t._uU(4),t.qZA(),t.TgZ(5,"div"),t._uU(6),t.qZA(),t.TgZ(7,"div"),t._uU(8),t.qZA(),t.qZA()),2&i){var o=e.$implicit,s=t.oxw(2);t.xp6(2),t.Q6J("ngIf",o.connected),t.xp6(1),t.Q6J("ngIf",!o.connected),t.xp6(1),t.hij(" ",o.name," "),t.xp6(2),t.hij(" ",o.host," "),t.xp6(2),t.hij(" ",s.server.location," ")}}var I=function(i){return{lightTheme:i}},D=function(){return{right:!0,left:!0,bottom:!0,top:!0}};function N(i,e){if(1&i){var o=t.EpF();t.TgZ(0,"div",3),t.NdJ("mousedown",function(){return t.CHM(o),t.oxw().toggleDragging(!0)})("resizeStart",function(){return t.CHM(o),t.oxw().toggleDragging(!1)})("resizeEnd",function(n){return t.CHM(o),t.oxw().onResizeEnd(n)}),t.TgZ(1,"div",4),t.TgZ(2,"mat-tab-group"),t.TgZ(3,"mat-tab",5),t.NdJ("click",function(){return t.CHM(o),t.oxw().toggleTopologyVisibility(!0)}),t.TgZ(4,"div",6),t.TgZ(5,"div",7),t.TgZ(6,"mat-select",8),t.TgZ(7,"mat-optgroup",9),t.TgZ(8,"mat-option",10),t.NdJ("onSelectionChange",function(){return t.CHM(o),t.oxw().applyStatusFilter("started")}),t._uU(9,"started"),t.qZA(),t.TgZ(10,"mat-option",11),t.NdJ("onSelectionChange",function(){return t.CHM(o),t.oxw().applyStatusFilter("suspended")}),t._uU(11,"suspended"),t.qZA(),t.TgZ(12,"mat-option",12),t.NdJ("onSelectionChange",function(){return t.CHM(o),t.oxw().applyStatusFilter("stopped")}),t._uU(13,"stopped"),t.qZA(),t.qZA(),t.TgZ(14,"mat-optgroup",13),t.TgZ(15,"mat-option",14),t.NdJ("onSelectionChange",function(){return t.CHM(o),t.oxw().applyCaptureFilter("capture")}),t._uU(16,"active capture(s)"),t.qZA(),t.TgZ(17,"mat-option",15),t.NdJ("onSelectionChange",function(){return t.CHM(o),t.oxw().applyCaptureFilter("packet")}),t._uU(18,"active packet captures"),t.qZA(),t.qZA(),t.qZA(),t.qZA(),t.TgZ(19,"div",16),t.TgZ(20,"mat-select",17),t.NdJ("selectionChange",function(){return t.CHM(o),t.oxw().setSortingOrder()})("valueChange",function(n){return t.CHM(o),t.oxw().sortingOrder=n}),t.TgZ(21,"mat-option",18),t._uU(22,"sort by name ascending"),t.qZA(),t.TgZ(23,"mat-option",19),t._uU(24,"sort by name descending"),t.qZA(),t.qZA(),t.qZA(),t._UZ(25,"mat-divider",20),t.TgZ(26,"div",21),t.YNc(27,M,8,6,"div",22),t.qZA(),t.qZA(),t.qZA(),t.TgZ(28,"mat-tab",23),t.NdJ("click",function(){return t.CHM(o),t.oxw().toggleTopologyVisibility(!1)}),t.TgZ(29,"div",6),t.TgZ(30,"div",24),t.YNc(31,F,9,5,"div",22),t.qZA(),t.qZA(),t.qZA(),t.qZA(),t.qZA(),t.qZA()}if(2&i){var s=t.oxw();t.Q6J("ngStyle",s.style)("ngClass",t.VKq(9,I,s.isLightThemeEnabled))("validateResize",s.validate)("resizeEdges",t.DdM(11,D))("enableGhostResize",!0),t.xp6(20),t.Q6J("value",s.sortingOrder),t.xp6(6),t.Q6J("ngStyle",s.styleInside),t.xp6(1),t.Q6J("ngForOf",s.filteredNodes),t.xp6(4),t.Q6J("ngForOf",s.computes)}}var U=function(){function i(e,o,s,r,n){this.nodesDataSource=e,this.projectService=o,this.computeService=s,this.linksDataSource=r,this.themeService=n,this.closeTopologySummary=new t.vpe,this.style={},this.styleInside={height:"280px"},this.subscriptions=[],this.nodes=[],this.filteredNodes=[],this.sortingOrder="asc",this.startedStatusFilterEnabled=!1,this.suspendedStatusFilterEnabled=!1,this.stoppedStatusFilterEnabled=!1,this.captureFilterEnabled=!1,this.packetFilterEnabled=!1,this.computes=[],this.isTopologyVisible=!0,this.isDraggLine truncated
|
||||
@@ -1 +0,0 @@
|
||||
"use strict";(self.webpackChunkgns3_web_ui=self.webpackChunkgns3_web_ui||[]).push([[26],{91026:function(W,g,a){a.r(g),a.d(g,{TopologySummaryComponent:function(){return U}});var t=a(38999),_=a(96852),h=a(14200),f=a(36889),v=a(3941),y=a(15132),p=a(40098),x=a(39095),c=a(88802),S=a(73044),d=a(59412),T=a(93386);function C(i,e){if(1&i){var o=t.EpF();t.TgZ(0,"div",2),t.NdJ("mousemove",function(r){return t.CHM(o),t.oxw().dragWidget(r)},!1,t.evT)("mouseup",function(){return t.CHM(o),t.oxw().toggleDragging(!1)},!1,t.evT),t.qZA()}}function b(i,e){1&i&&(t.O4$(),t.TgZ(0,"svg",28),t._UZ(1,"rect",29),t.qZA())}function E(i,e){1&i&&(t.O4$(),t.TgZ(0,"svg",28),t._UZ(1,"rect",30),t.qZA())}function Z(i,e){1&i&&(t.O4$(),t.TgZ(0,"svg",28),t._UZ(1,"rect",31),t.qZA())}function O(i,e){if(1&i&&(t.TgZ(0,"div"),t._uU(1),t.qZA()),2&i){var o=t.oxw().$implicit;t.xp6(1),t.lnq(" ",o.console_type," ",o.console_host,":",o.console," ")}}function P(i,e){1&i&&(t.TgZ(0,"div"),t._uU(1," none "),t.qZA())}function M(i,e){if(1&i&&(t.TgZ(0,"div",25),t.TgZ(1,"div"),t.YNc(2,b,2,0,"svg",26),t.YNc(3,E,2,0,"svg",26),t.YNc(4,Z,2,0,"svg",26),t._uU(5),t.qZA(),t.YNc(6,O,2,3,"div",27),t.YNc(7,P,2,0,"div",27),t.qZA()),2&i){var o=e.$implicit;t.xp6(2),t.Q6J("ngIf","started"===o.status),t.xp6(1),t.Q6J("ngIf","suspended"===o.status),t.xp6(1),t.Q6J("ngIf","stopped"===o.status),t.xp6(1),t.hij(" ",o.name," "),t.xp6(1),t.Q6J("ngIf",null!=o.console&&null!=o.console&&"none"!=o.console_type),t.xp6(1),t.Q6J("ngIf",null==o.console||"none"===o.console_type)}}function w(i,e){1&i&&(t.O4$(),t.TgZ(0,"svg",28),t._UZ(1,"rect",29),t.qZA())}function A(i,e){1&i&&(t.O4$(),t.TgZ(0,"svg",28),t._UZ(1,"rect",31),t.qZA())}function F(i,e){if(1&i&&(t.TgZ(0,"div",25),t.TgZ(1,"div"),t.YNc(2,w,2,0,"svg",26),t.YNc(3,A,2,0,"svg",26),t._uU(4),t.qZA(),t.TgZ(5,"div"),t._uU(6),t.qZA(),t.TgZ(7,"div"),t._uU(8),t.qZA(),t.qZA()),2&i){var o=e.$implicit,s=t.oxw(2);t.xp6(2),t.Q6J("ngIf",o.connected),t.xp6(1),t.Q6J("ngIf",!o.connected),t.xp6(1),t.hij(" ",o.name," "),t.xp6(2),t.hij(" ",o.host," "),t.xp6(2),t.hij(" ",s.server.location," ")}}var I=function(i){return{lightTheme:i}},D=function(){return{right:!0,left:!0,bottom:!0,top:!0}};function N(i,e){if(1&i){var o=t.EpF();t.TgZ(0,"div",3),t.NdJ("mousedown",function(){return t.CHM(o),t.oxw().toggleDragging(!0)})("resizeStart",function(){return t.CHM(o),t.oxw().toggleDragging(!1)})("resizeEnd",function(n){return t.CHM(o),t.oxw().onResizeEnd(n)}),t.TgZ(1,"div",4),t.TgZ(2,"mat-tab-group"),t.TgZ(3,"mat-tab",5),t.NdJ("click",function(){return t.CHM(o),t.oxw().toggleTopologyVisibility(!0)}),t.TgZ(4,"div",6),t.TgZ(5,"div",7),t.TgZ(6,"mat-select",8),t.TgZ(7,"mat-optgroup",9),t.TgZ(8,"mat-option",10),t.NdJ("onSelectionChange",function(){return t.CHM(o),t.oxw().applyStatusFilter("started")}),t._uU(9,"started"),t.qZA(),t.TgZ(10,"mat-option",11),t.NdJ("onSelectionChange",function(){return t.CHM(o),t.oxw().applyStatusFilter("suspended")}),t._uU(11,"suspended"),t.qZA(),t.TgZ(12,"mat-option",12),t.NdJ("onSelectionChange",function(){return t.CHM(o),t.oxw().applyStatusFilter("stopped")}),t._uU(13,"stopped"),t.qZA(),t.qZA(),t.TgZ(14,"mat-optgroup",13),t.TgZ(15,"mat-option",14),t.NdJ("onSelectionChange",function(){return t.CHM(o),t.oxw().applyCaptureFilter("capture")}),t._uU(16,"active capture(s)"),t.qZA(),t.TgZ(17,"mat-option",15),t.NdJ("onSelectionChange",function(){return t.CHM(o),t.oxw().applyCaptureFilter("packet")}),t._uU(18,"active packet captures"),t.qZA(),t.qZA(),t.qZA(),t.qZA(),t.TgZ(19,"div",16),t.TgZ(20,"mat-select",17),t.NdJ("selectionChange",function(){return t.CHM(o),t.oxw().setSortingOrder()})("valueChange",function(n){return t.CHM(o),t.oxw().sortingOrder=n}),t.TgZ(21,"mat-option",18),t._uU(22,"sort by name ascending"),t.qZA(),t.TgZ(23,"mat-option",19),t._uU(24,"sort by name descending"),t.qZA(),t.qZA(),t.qZA(),t._UZ(25,"mat-divider",20),t.TgZ(26,"div",21),t.YNc(27,M,8,6,"div",22),t.qZA(),t.qZA(),t.qZA(),t.TgZ(28,"mat-tab",23),t.NdJ("click",function(){return t.CHM(o),t.oxw().toggleTopologyVisibility(!1)}),t.TgZ(29,"div",6),t.TgZ(30,"div",24),t.YNc(31,F,9,5,"div",22),t.qZA(),t.qZA(),t.qZA(),t.qZA(),t.qZA(),t.qZA()}if(2&i){var s=t.oxw();t.Q6J("ngStyle",s.style)("ngClass",t.VKq(9,I,s.isLightThemeEnabled))("validateResize",s.validate)("resizeEdges",t.DdM(11,D))("enableGhostResize",!0),t.xp6(20),t.Q6J("value",s.sortingOrder),t.xp6(6),t.Q6J("ngStyle",s.styleInside),t.xp6(1),t.Q6J("ngForOf",s.filteredNodes),t.xp6(4),t.Q6J("ngForOf",s.computes)}}var U=function(){function i(e,o,s,r,n){this.nodesDataSource=e,this.projectService=o,this.computeService=s,this.linksDataSource=r,this.themeService=n,this.closeTopologySummary=new t.vpe,this.style={},this.styleInside={height:"280px"},this.subscriptions=[],this.nodes=[],this.filteredNodes=[],this.sortingOrder="asc",this.startedStatusFilterEnabled=!1,this.suspendedStatusFilterEnabled=!1,this.stoppedStatusFilterEnabled=!1,this.captureFilterEnabled=!1,this.packetFilterEnabled=!1,this.computes=[],this.isTopologyVisible=!0,this.isDragginLine truncated
|
||||
@@ -46,6 +46,6 @@
|
||||
|
||||
gtag('config', 'G-5D6FZL9923');
|
||||
</script>
|
||||
<script src="runtime.91a209cf21f6fb848205.js" defer></script><script src="polyfills-es5.865074f5cd9a121111a2.js" nomodule defer></script><script src="polyfills.2f91a039d848e57ff02e.js" defer></script><script src="main.96be36058f5df0ca7e7f.js" defer></script>
|
||||
<script src="runtime.baa1121a4737aeb68bb7.js" defer></script><script src="polyfills-es5.865074f5cd9a121111a2.js" nomodule defer></script><script src="polyfills.2f91a039d848e57ff02e.js" defer></script><script src="main.6b11a28a9dc4ce54a2ab.js" defer></script>
|
||||
|
||||
</body></html>
|
||||
@@ -0,0 +1 @@
|
||||
(self.webpackChunkgns3_web_ui=self.webpackChunkgns3_web_ui||[]).push([[179],{98255:function(ue){function q(f){return Promise.resolve().then(function(){var U=new Error("Cannot find module '"+f+"'");throw U.code="MODULE_NOT_FOUND",U})}q.keys=function(){return[]},q.resolve=q,q.id=98255,ue.exports=q},82908:function(ue){ue.exports=function(f,U){(null==U||U>f.length)&&(U=f.length);for(var B=0,V=new Array(U);B<U;B++)V[B]=f[B];return V},ue.exports.default=ue.exports,ue.exports.__esModule=!0},36457:function(ue){ue.exports=function(f){if(Array.isArray(f))return f},ue.exports.default=ue.exports,ue.exports.__esModule=!0},35036:function(ue){ue.exports=function(f,U){var B=null==f?null:"undefined"!=typeof Symbol&&f[Symbol.iterator]||f["@@iterator"];if(null!=B){var R,b,V=[],Z=!0,T=!1;try{for(B=B.call(f);!(Z=(R=B.next()).done)&&(V.push(R.value),!U||V.length!==U);Z=!0);}catch(v){T=!0,b=v}finally{try{!Z&&null!=B.return&&B.return()}finally{if(T)throw b}}return V}},ue.exports.default=ue.exports,ue.exports.__esModule=!0},13969:function(ue){ue.exports=function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")},ue.exports.default=ue.exports,ue.exports.__esModule=!0},6326:function(ue,q,f){var U=f(36457),B=f(35036),V=f(54850),Z=f(13969);ue.exports=function(R,b){return U(R)||B(R,b)||V(R,b)||Z()},ue.exports.default=ue.exports,ue.exports.__esModule=!0},54850:function(ue,q,f){var U=f(82908);ue.exports=function(V,Z){if(V){if("string"==typeof V)return U(V,Z);var T=Object.prototype.toString.call(V).slice(8,-1);if("Object"===T&&V.constructor&&(T=V.constructor.name),"Map"===T||"Set"===T)return Array.from(V);if("Arguments"===T||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(T))return U(V,Z)}},ue.exports.default=ue.exports,ue.exports.__esModule=!0},26552:function(ue,q,f){ue.exports=f(55590)},61855:function(ue,q,f){"use strict";f.d(q,{ZT:function(){return B},mG:function(){return v},Jh:function(){return I},ev:function(){return N}});var U=function($,ae){return(U=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(se,ce){se.__proto__=ce}||function(se,ce){for(var le in ce)Object.prototype.hasOwnProperty.call(ce,le)&&(se[le]=ce[le])})($,ae)};function B($,ae){if("function"!=typeof ae&&null!==ae)throw new TypeError("Class extends value "+String(ae)+" is not a constructor or null");function se(){this.constructor=$}U($,ae),$.prototype=null===ae?Object.create(ae):(se.prototype=ae.prototype,new se)}function v($,ae,se,ce){return new(se||(se=Promise))(function(oe,Ae){function be(_t){try{qe(ce.next(_t))}catch(yt){Ae(yt)}}function it(_t){try{qe(ce.throw(_t))}catch(yt){Ae(yt)}}function qe(_t){_t.done?oe(_t.value):function(oe){return oe instanceof se?oe:new se(function(Ae){Ae(oe)})}(_t.value).then(be,it)}qe((ce=ce.apply($,ae||[])).next())})}function I($,ae){var ce,le,oe,Ae,se={label:0,sent:function(){if(1&oe[0])throw oe[1];return oe[1]},trys:[],ops:[]};return Ae={next:be(0),throw:be(1),return:be(2)},"function"==typeof Symbol&&(Ae[Symbol.iterator]=function(){return this}),Ae;function be(qe){return function(_t){return function(qe){if(ce)throw new TypeError("Generator is already executing.");for(;se;)try{if(ce=1,le&&(oe=2&qe[0]?le.return:qe[0]?le.throw||((oe=le.return)&&oe.call(le),0):le.next)&&!(oe=oe.call(le,qe[1])).done)return oe;switch(le=0,oe&&(qe=[2&qe[0],oe.value]),qe[0]){case 0:case 1:oe=qe;break;case 4:return se.label++,{value:qe[1],done:!1};case 5:se.label++,le=qe[1],qe=[0];continue;case 7:qe=se.ops.pop(),se.trys.pop();continue;default:if(!(oe=(oe=se.trys).length>0&&oe[oe.length-1])&&(6===qe[0]||2===qe[0])){se=0;continue}if(3===qe[0]&&(!oe||qe[1]>oe[0]&&qe[1]<oe[3])){se.label=qe[1];break}if(6===qe[0]&&se.label<oe[1]){se.label=oe[1],oe=qe;break}if(oe&&se.label<oe[2]){se.label=oe[2],se.ops.push(qe);break}oe[2]&&se.ops.pop(),se.trys.pop();continue}qe=ae.call($,se)}catch(_t){qe=[6,_t],le=0}finally{ce=oe=0}if(5&qe[0])throw qe[1];return{value:qe[0]?qe[1]:void 0,done:!0}}([qe,_t])}}}function N($,ae,se){if(se||2===arguments.length)for(var oe,ce=0,le=ae.length;ce<le;ce++)(oe||!(ce in ae))&&(oe||(oe=Array.prototype.slice.call(ae,0,ce)),oe[ce]=ae[ce]);return $.concat(oe||Array.prototype.slice.call(ae))}},739:function(ue,q,f){"use strict";f.d(q,{l3:function(){return T},_j:function(){return V},LC:function(){return Z},ZN:function(){return O},jt:function(){return b},pV:function(){return E},F4:function(){return M},IO:function(){return A},vP:function(){return I},SB:function(){return k},oB:function(){return D},eR:function(){return _},X$:function(){return R},ZE:function(){return F},k1:function(){return z}});var U=f(14105),B=f(18967),V=function K(){(0,B.Z)(this,K)},Z=function K(){(0,B.Z)(this,K)},T="*";function R(K,j){return{type:7,name:K,definitions:j,options:{}}}function b(K){var j=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;return{type:4,styles:j,timings:K}}function I(K){var j=arguments.length>1&&void 0!==arguments[1]?arguments[1]Line truncated
|
||||
@@ -1 +0,0 @@
|
||||
(self.webpackChunkgns3_web_ui=self.webpackChunkgns3_web_ui||[]).push([[179],{98255:function(ue){function q(f){return Promise.resolve().then(function(){var U=new Error("Cannot find module '"+f+"'");throw U.code="MODULE_NOT_FOUND",U})}q.keys=function(){return[]},q.resolve=q,q.id=98255,ue.exports=q},82908:function(ue){ue.exports=function(f,U){(null==U||U>f.length)&&(U=f.length);for(var B=0,V=new Array(U);B<U;B++)V[B]=f[B];return V},ue.exports.default=ue.exports,ue.exports.__esModule=!0},36457:function(ue){ue.exports=function(f){if(Array.isArray(f))return f},ue.exports.default=ue.exports,ue.exports.__esModule=!0},35036:function(ue){ue.exports=function(f,U){var B=null==f?null:"undefined"!=typeof Symbol&&f[Symbol.iterator]||f["@@iterator"];if(null!=B){var R,b,V=[],Z=!0,T=!1;try{for(B=B.call(f);!(Z=(R=B.next()).done)&&(V.push(R.value),!U||V.length!==U);Z=!0);}catch(v){T=!0,b=v}finally{try{!Z&&null!=B.return&&B.return()}finally{if(T)throw b}}return V}},ue.exports.default=ue.exports,ue.exports.__esModule=!0},13969:function(ue){ue.exports=function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")},ue.exports.default=ue.exports,ue.exports.__esModule=!0},6326:function(ue,q,f){var U=f(36457),B=f(35036),V=f(54850),Z=f(13969);ue.exports=function(R,b){return U(R)||B(R,b)||V(R,b)||Z()},ue.exports.default=ue.exports,ue.exports.__esModule=!0},54850:function(ue,q,f){var U=f(82908);ue.exports=function(V,Z){if(V){if("string"==typeof V)return U(V,Z);var T=Object.prototype.toString.call(V).slice(8,-1);if("Object"===T&&V.constructor&&(T=V.constructor.name),"Map"===T||"Set"===T)return Array.from(V);if("Arguments"===T||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(T))return U(V,Z)}},ue.exports.default=ue.exports,ue.exports.__esModule=!0},26552:function(ue,q,f){ue.exports=f(55590)},61855:function(ue,q,f){"use strict";f.d(q,{ZT:function(){return B},mG:function(){return v},Jh:function(){return I},ev:function(){return N}});var U=function($,ae){return(U=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(se,ce){se.__proto__=ce}||function(se,ce){for(var le in ce)Object.prototype.hasOwnProperty.call(ce,le)&&(se[le]=ce[le])})($,ae)};function B($,ae){if("function"!=typeof ae&&null!==ae)throw new TypeError("Class extends value "+String(ae)+" is not a constructor or null");function se(){this.constructor=$}U($,ae),$.prototype=null===ae?Object.create(ae):(se.prototype=ae.prototype,new se)}function v($,ae,se,ce){return new(se||(se=Promise))(function(oe,Ae){function be(_t){try{qe(ce.next(_t))}catch(yt){Ae(yt)}}function it(_t){try{qe(ce.throw(_t))}catch(yt){Ae(yt)}}function qe(_t){_t.done?oe(_t.value):function(oe){return oe instanceof se?oe:new se(function(Ae){Ae(oe)})}(_t.value).then(be,it)}qe((ce=ce.apply($,ae||[])).next())})}function I($,ae){var ce,le,oe,Ae,se={label:0,sent:function(){if(1&oe[0])throw oe[1];return oe[1]},trys:[],ops:[]};return Ae={next:be(0),throw:be(1),return:be(2)},"function"==typeof Symbol&&(Ae[Symbol.iterator]=function(){return this}),Ae;function be(qe){return function(_t){return function(qe){if(ce)throw new TypeError("Generator is already executing.");for(;se;)try{if(ce=1,le&&(oe=2&qe[0]?le.return:qe[0]?le.throw||((oe=le.return)&&oe.call(le),0):le.next)&&!(oe=oe.call(le,qe[1])).done)return oe;switch(le=0,oe&&(qe=[2&qe[0],oe.value]),qe[0]){case 0:case 1:oe=qe;break;case 4:return se.label++,{value:qe[1],done:!1};case 5:se.label++,le=qe[1],qe=[0];continue;case 7:qe=se.ops.pop(),se.trys.pop();continue;default:if(!(oe=(oe=se.trys).length>0&&oe[oe.length-1])&&(6===qe[0]||2===qe[0])){se=0;continue}if(3===qe[0]&&(!oe||qe[1]>oe[0]&&qe[1]<oe[3])){se.label=qe[1];break}if(6===qe[0]&&se.label<oe[1]){se.label=oe[1],oe=qe;break}if(oe&&se.label<oe[2]){se.label=oe[2],se.ops.push(qe);break}oe[2]&&se.ops.pop(),se.trys.pop();continue}qe=ae.call($,se)}catch(_t){qe=[6,_t],le=0}finally{ce=oe=0}if(5&qe[0])throw qe[1];return{value:qe[0]?qe[1]:void 0,done:!0}}([qe,_t])}}}function N($,ae,se){if(se||2===arguments.length)for(var oe,ce=0,le=ae.length;ce<le;ce++)(oe||!(ce in ae))&&(oe||(oe=Array.prototype.slice.call(ae,0,ce)),oe[ce]=ae[ce]);return $.concat(oe||Array.prototype.slice.call(ae))}},739:function(ue,q,f){"use strict";f.d(q,{l3:function(){return T},_j:function(){return V},LC:function(){return Z},ZN:function(){return O},jt:function(){return b},pV:function(){return E},F4:function(){return M},IO:function(){return A},vP:function(){return I},SB:function(){return k},oB:function(){return D},eR:function(){return _},X$:function(){return R},ZE:function(){return F},k1:function(){return z}});var U=f(14105),B=f(18967),V=function K(){(0,B.Z)(this,K)},Z=function K(){(0,B.Z)(this,K)},T="*";function R(K,j){return{type:7,name:K,definitions:j,options:{}}}function b(K){var j=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;return{type:4,styles:j,timings:K}}function I(K){var j=arguments.length>1&&void 0!==arguments[1]?arguments[1]Line truncated
|
||||
@@ -1 +0,0 @@
|
||||
!function(){"use strict";var e,v={},g={};function n(e){var u=g[e];if(void 0!==u)return u.exports;var t=g[e]={id:e,loaded:!1,exports:{}};return v[e](t,t.exports,n),t.loaded=!0,t.exports}n.m=v,e=[],n.O=function(u,t,a,o){if(!t){var r=1/0;for(i=0;i<e.length;i++){t=e[i][0],a=e[i][1],o=e[i][2];for(var l=!0,f=0;f<t.length;f++)(!1&o||r>=o)&&Object.keys(n.O).every(function(b){return n.O[b](t[f])})?t.splice(f--,1):(l=!1,o<r&&(r=o));if(l){e.splice(i--,1);var s=a();void 0!==s&&(u=s)}}return u}o=o||0;for(var i=e.length;i>0&&e[i-1][2]>o;i--)e[i]=e[i-1];e[i]=[t,a,o]},n.n=function(e){var u=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(u,{a:u}),u},n.d=function(e,u){for(var t in u)n.o(u,t)&&!n.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:u[t]})},n.f={},n.e=function(e){return Promise.all(Object.keys(n.f).reduce(function(u,t){return n.f[t](e,u),u},[]))},n.u=function(e){return e+".52bf50eec59e1bcb0895.js"},n.miniCssF=function(e){return"styles.f8555f2eecf8cf87f666.css"},n.hmd=function(e){return(e=Object.create(e)).children||(e.children=[]),Object.defineProperty(e,"exports",{enumerable:!0,set:function(){throw new Error("ES Modules may not assign module.exports or exports.*, Use ESM export syntax, instead: "+e.id)}}),e},n.o=function(e,u){return Object.prototype.hasOwnProperty.call(e,u)},function(){var e={},u="gns3-web-ui:";n.l=function(t,a,o,i){if(e[t])e[t].push(a);else{var r,l;if(void 0!==o)for(var f=document.getElementsByTagName("script"),s=0;s<f.length;s++){var c=f[s];if(c.getAttribute("src")==t||c.getAttribute("data-webpack")==u+o){r=c;break}}r||(l=!0,(r=document.createElement("script")).charset="utf-8",r.timeout=120,n.nc&&r.setAttribute("nonce",n.nc),r.setAttribute("data-webpack",u+o),r.src=n.tu(t)),e[t]=[a];var d=function(h,b){r.onerror=r.onload=null,clearTimeout(p);var _=e[t];if(delete e[t],r.parentNode&&r.parentNode.removeChild(r),_&&_.forEach(function(m){return m(b)}),h)return h(b)},p=setTimeout(d.bind(null,void 0,{type:"timeout",target:r}),12e4);r.onerror=d.bind(null,r.onerror),r.onload=d.bind(null,r.onload),l&&document.head.appendChild(r)}}}(),n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},function(){var e;n.tu=function(u){return void 0===e&&(e={createScriptURL:function(t){return t}},"undefined"!=typeof trustedTypes&&trustedTypes.createPolicy&&(e=trustedTypes.createPolicy("angular#bundler",e))),e.createScriptURL(u)}}(),n.p="",function(){var e={666:0};n.f.j=function(a,o){var i=n.o(e,a)?e[a]:void 0;if(0!==i)if(i)o.push(i[2]);else if(666!=a){var r=new Promise(function(c,d){i=e[a]=[c,d]});o.push(i[2]=r);var l=n.p+n.u(a),f=new Error;n.l(l,function(c){if(n.o(e,a)&&(0!==(i=e[a])&&(e[a]=void 0),i)){var d=c&&("load"===c.type?"missing":c.type),p=c&&c.target&&c.target.src;f.message="Loading chunk "+a+" failed.\n("+d+": "+p+")",f.name="ChunkLoadError",f.type=d,f.request=p,i[1](f)}},"chunk-"+a,a)}else e[a]=0},n.O.j=function(a){return 0===e[a]};var u=function(a,o){var f,s,i=o[0],r=o[1],l=o[2],c=0;for(f in r)n.o(r,f)&&(n.m[f]=r[f]);if(l)var d=l(n);for(a&&a(o);c<i.length;c++)n.o(e,s=i[c])&&e[s]&&e[s][0](),e[i[c]]=0;return n.O(d)},t=self.webpackChunkgns3_web_ui=self.webpackChunkgns3_web_ui||[];t.forEach(u.bind(null,0)),t.push=u.bind(null,t.push.bind(t))}()}();
|
||||
@@ -0,0 +1 @@
|
||||
!function(){"use strict";var e,v={},g={};function n(e){var a=g[e];if(void 0!==a)return a.exports;var t=g[e]={id:e,loaded:!1,exports:{}};return v[e](t,t.exports,n),t.loaded=!0,t.exports}n.m=v,e=[],n.O=function(a,t,u,o){if(!t){var r=1/0;for(i=0;i<e.length;i++){t=e[i][0],u=e[i][1],o=e[i][2];for(var l=!0,f=0;f<t.length;f++)(!1&o||r>=o)&&Object.keys(n.O).every(function(b){return n.O[b](t[f])})?t.splice(f--,1):(l=!1,o<r&&(r=o));if(l){e.splice(i--,1);var s=u();void 0!==s&&(a=s)}}return a}o=o||0;for(var i=e.length;i>0&&e[i-1][2]>o;i--)e[i]=e[i-1];e[i]=[t,u,o]},n.n=function(e){var a=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(a,{a:a}),a},n.d=function(e,a){for(var t in a)n.o(a,t)&&!n.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:a[t]})},n.f={},n.e=function(e){return Promise.all(Object.keys(n.f).reduce(function(a,t){return n.f[t](e,a),a},[]))},n.u=function(e){return e+".49028ab13de5de406c90.js"},n.miniCssF=function(e){return"styles.f8555f2eecf8cf87f666.css"},n.hmd=function(e){return(e=Object.create(e)).children||(e.children=[]),Object.defineProperty(e,"exports",{enumerable:!0,set:function(){throw new Error("ES Modules may not assign module.exports or exports.*, Use ESM export syntax, instead: "+e.id)}}),e},n.o=function(e,a){return Object.prototype.hasOwnProperty.call(e,a)},function(){var e={},a="gns3-web-ui:";n.l=function(t,u,o,i){if(e[t])e[t].push(u);else{var r,l;if(void 0!==o)for(var f=document.getElementsByTagName("script"),s=0;s<f.length;s++){var c=f[s];if(c.getAttribute("src")==t||c.getAttribute("data-webpack")==a+o){r=c;break}}r||(l=!0,(r=document.createElement("script")).charset="utf-8",r.timeout=120,n.nc&&r.setAttribute("nonce",n.nc),r.setAttribute("data-webpack",a+o),r.src=n.tu(t)),e[t]=[u];var d=function(h,b){r.onerror=r.onload=null,clearTimeout(p);var _=e[t];if(delete e[t],r.parentNode&&r.parentNode.removeChild(r),_&&_.forEach(function(m){return m(b)}),h)return h(b)},p=setTimeout(d.bind(null,void 0,{type:"timeout",target:r}),12e4);r.onerror=d.bind(null,r.onerror),r.onload=d.bind(null,r.onload),l&&document.head.appendChild(r)}}}(),n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},function(){var e;n.tu=function(a){return void 0===e&&(e={createScriptURL:function(t){return t}},"undefined"!=typeof trustedTypes&&trustedTypes.createPolicy&&(e=trustedTypes.createPolicy("angular#bundler",e))),e.createScriptURL(a)}}(),n.p="",function(){var e={666:0};n.f.j=function(u,o){var i=n.o(e,u)?e[u]:void 0;if(0!==i)if(i)o.push(i[2]);else if(666!=u){var r=new Promise(function(c,d){i=e[u]=[c,d]});o.push(i[2]=r);var l=n.p+n.u(u),f=new Error;n.l(l,function(c){if(n.o(e,u)&&(0!==(i=e[u])&&(e[u]=void 0),i)){var d=c&&("load"===c.type?"missing":c.type),p=c&&c.target&&c.target.src;f.message="Loading chunk "+u+" failed.\n("+d+": "+p+")",f.name="ChunkLoadError",f.type=d,f.request=p,i[1](f)}},"chunk-"+u,u)}else e[u]=0},n.O.j=function(u){return 0===e[u]};var a=function(u,o){var f,s,i=o[0],r=o[1],l=o[2],c=0;for(f in r)n.o(r,f)&&(n.m[f]=r[f]);if(l)var d=l(n);for(u&&u(o);c<i.length;c++)n.o(e,s=i[c])&&e[s]&&e[s][0](),e[i[c]]=0;return n.O(d)},t=self.webpackChunkgns3_web_ui=self.webpackChunkgns3_web_ui||[];t.forEach(a.bind(null,0)),t.push=a.bind(null,t.push.bind(t))}()}();
|
||||
@@ -71,10 +71,10 @@ async def subprocess_check_output(*args, cwd=None, env=None, stderr=False):
|
||||
|
||||
if stderr:
|
||||
proc = await asyncio.create_subprocess_exec(*args, stderr=asyncio.subprocess.PIPE, cwd=cwd, env=env)
|
||||
output = await proc.stderr.read()
|
||||
_, output = await proc.communicate()
|
||||
else:
|
||||
proc = await asyncio.create_subprocess_exec(*args, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.DEVNULL, cwd=cwd, env=env)
|
||||
output = await proc.stdout.read()
|
||||
output, _ = await proc.communicate()
|
||||
if output is None:
|
||||
return ""
|
||||
# If we received garbage we ignore invalid characters
|
||||
|
||||
@@ -20,7 +20,7 @@ import hashlib
|
||||
|
||||
from ..config import Config
|
||||
from . import force_unix_path
|
||||
|
||||
from io import DEFAULT_BUFFER_SIZE
|
||||
|
||||
import logging
|
||||
log = logging.getLogger(__name__)
|
||||
@@ -167,12 +167,13 @@ def md5sum(path, stopped_event=None):
|
||||
|
||||
try:
|
||||
m = hashlib.md5()
|
||||
log.debug("Calculating MD5 sum of `{}`".format(path))
|
||||
with open(path, 'rb') as f:
|
||||
while True:
|
||||
if stopped_event is not None and stopped_event.is_set():
|
||||
log.error("MD5 sum calculation of `{}` has stopped due to cancellation".format(path))
|
||||
return
|
||||
buf = f.read(128)
|
||||
buf = f.read(DEFAULT_BUFFER_SIZE)
|
||||
if not buf:
|
||||
break
|
||||
m.update(buf)
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
# or negative for a release candidate or beta (after the base version
|
||||
# number has been incremented)
|
||||
|
||||
__version__ = "2.2.39"
|
||||
__version_info__ = (2, 2, 39, 0)
|
||||
__version__ = "2.2.42"
|
||||
__version_info__ = (2, 2, 42, 0)
|
||||
|
||||
if "dev" in __version__:
|
||||
try:
|
||||
|
||||
+4
-3
@@ -2,15 +2,16 @@ jsonschema>=4.17.3,<4.18; python_version >= '3.7'
|
||||
jsonschema==3.2.0; python_version < '3.7' # v3.2.0 is the last version to support Python 3.6
|
||||
aiohttp>=3.8.4,<3.9
|
||||
aiohttp-cors>=0.7.0,<0.8
|
||||
aiofiles>=22.1.0,<22.2; python_version >= '3.7'
|
||||
aiofiles>=23.1.0,<23.2; python_version >= '3.7'
|
||||
aiofiles==0.8.0; python_version < '3.7' # v0.8.0 is the last version to support Python 3.6
|
||||
Jinja2>=3.1.2,<3.2; python_version >= '3.7'
|
||||
Jinja2==3.0.3; python_version < '3.7' # v3.0.3 is the last version to support Python 3.6
|
||||
sentry-sdk==1.17.0,<1.18
|
||||
psutil==5.9.4
|
||||
sentry-sdk==1.29.2,<1.30
|
||||
psutil==5.9.5
|
||||
async-timeout>=4.0.2,<4.1
|
||||
distro>=1.8.0
|
||||
py-cpuinfo>=9.0.0,<10.0
|
||||
importlib-resources>=1.3; python_version <= '3.9'
|
||||
truststore>=0.7.0; python_version >= '3.10'
|
||||
setuptools>=60.8.1; python_version >= '3.7'
|
||||
setuptools==59.6.0; python_version < '3.7' # v59.6.0 is the last version to support Python 3.6
|
||||
@@ -26,6 +26,7 @@ function help {
|
||||
echo "--with-openvpn: Install OpenVPN" >&2
|
||||
echo "--with-iou: Install IOU" >&2
|
||||
echo "--with-i386-repository: Add the i386 repositories required by IOU if they are not already available on the system. Warning: this will replace your source.list in order to use the official Ubuntu mirror" >&2
|
||||
echo "--with-welcome: Install GNS3-VM welcome.py script" >&2
|
||||
echo "--without-kvm: Disable KVM, required if system do not support it (limitation in some hypervisors and cloud providers). Warning: only disable KVM if strictly necessary as this will degrade performance" >&2
|
||||
echo "--unstable: Use the GNS3 unstable repository"
|
||||
echo "--help: This help" >&2
|
||||
@@ -48,8 +49,9 @@ USE_IOU=0
|
||||
I386_REPO=0
|
||||
DISABLE_KVM=0
|
||||
UNSTABLE=0
|
||||
WELCOME_SETUP=0
|
||||
|
||||
TEMP=`getopt -o h --long with-openvpn,with-iou,with-i386-repository,without-kvm,unstable,help -n 'gns3-remote-install.sh' -- "$@"`
|
||||
TEMP=`getopt -o h --long with-openvpn,with-iou,with-i386-repository,with-welcome,without-kvm,unstable,help -n 'gns3-remote-install.sh' -- "$@"`
|
||||
if [ $? != 0 ]
|
||||
then
|
||||
help
|
||||
@@ -72,6 +74,10 @@ while true ; do
|
||||
I386_REPO=1
|
||||
shift
|
||||
;;
|
||||
--with-welcome)
|
||||
WELCOME_SETUP=1
|
||||
shift
|
||||
;;
|
||||
--without-kvm)
|
||||
DISABLE_KVM=1
|
||||
shift
|
||||
@@ -159,7 +165,7 @@ apt-get install -y gns3-server
|
||||
log "Create user GNS3 with /opt/gns3 as home directory"
|
||||
if [ ! -d "/opt/gns3/" ]
|
||||
then
|
||||
useradd -d /opt/gns3/ -m gns3
|
||||
useradd -m -d /opt/gns3/ gns3
|
||||
fi
|
||||
|
||||
|
||||
@@ -296,6 +302,37 @@ fi
|
||||
|
||||
log "GNS3 installed with success"
|
||||
|
||||
if [ $WELCOME_SETUP == 1 ]
|
||||
then
|
||||
NEEDRESTART_MODE=a apt-get install -y net-tools
|
||||
NEEDRESTART_MODE=a apt-get install -y python3-pip
|
||||
NEEDRESTART_MODE=a apt-get install -y dialog
|
||||
pip install --no-input --upgrade pip
|
||||
pip install --no-input pythondialog
|
||||
|
||||
#Pull down welcome script from repo
|
||||
curl https://raw.githubusercontent.com/GNS3/gns3-server/master/scripts/welcome.py > /usr/local/bin/welcome.py
|
||||
|
||||
chmod 755 /usr/local/bin/welcome.py
|
||||
chown gns3:gns3 /usr/local/bin/welcome.py
|
||||
|
||||
mkdir /etc/systemd/system/getty@tty1.service.d
|
||||
cat <<EOFI > /etc/systemd/system/getty@tty1.service.d/override.conf
|
||||
[Service]
|
||||
ExecStart=
|
||||
ExecStart=-/sbin/agetty -a gns3 --noclear %I \$TERM
|
||||
EOFI
|
||||
|
||||
chmod 755 /etc/systemd/system/getty@tty1.service.d/override.conf
|
||||
chown root:root /etc/systemd/system/getty@tty1.service.d/override.conf
|
||||
|
||||
echo "python3 /usr/local/bin/welcome.py" >> /opt/gns3/.bashrc
|
||||
echo "gns3:gns3" | chpasswd
|
||||
usermod --shell /bin/bash gns3
|
||||
usermod -aG sudo gns3
|
||||
|
||||
fi
|
||||
|
||||
if [ $USE_VPN == 1 ]
|
||||
then
|
||||
log "Setup VPN"
|
||||
@@ -417,3 +454,12 @@ service gns3 start
|
||||
log "Download http://$MY_IP_ADDR:8003/$UUID/$HOSTNAME.ovpn to setup your OpenVPN client after rebooting the server"
|
||||
|
||||
fi
|
||||
|
||||
if [ $WELCOME_SETUP == 1 ]
|
||||
then
|
||||
NEEDRESTART_MODE=a apt-get update
|
||||
NEEDRESTART_MODE=a apt-get upgrade
|
||||
python3 -c 'import sys; sys.path.append("/usr/local/bin/"); import welcome; ws = welcome.Welcome_dialog(); ws.repair_remote_install()'
|
||||
cd /opt/gns3
|
||||
su gns3
|
||||
fi
|
||||
@@ -72,7 +72,7 @@ if [ "$CUSTOM_REPO" = false ] ; then
|
||||
else
|
||||
cd "$REPO_DIR"
|
||||
|
||||
git checkout master
|
||||
git checkout 2.2
|
||||
git fetch --tags
|
||||
git pull
|
||||
|
||||
@@ -96,3 +96,8 @@ yarn ng build --source-map=false --configuration=production --base-href /static/
|
||||
cp -R $REPO_DIR/dist/* "$GNS3SERVER_DIR/gns3server/static/web-ui/"
|
||||
|
||||
cd "$GNS3SERVER_DIR"
|
||||
git add gns3server/static/web-ui/*
|
||||
if [[ -n "$TAG" ]]
|
||||
then
|
||||
git commit -m "Bundle web-ui ${TAG}"
|
||||
fi
|
||||
@@ -0,0 +1,479 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2015 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import locale
|
||||
import re
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import subprocess
|
||||
import configparser
|
||||
from json import loads as convert
|
||||
import urllib.request
|
||||
from dialog import Dialog, PythonDialogBug
|
||||
|
||||
|
||||
class Welcome_dialog:
|
||||
def __init__(self):
|
||||
try:
|
||||
locale.setlocale(locale.LC_ALL, '')
|
||||
except locale.Error:
|
||||
# Not supported via SSH
|
||||
pass
|
||||
self.display = Dialog(dialog="dialog", autowidgetsize=True)
|
||||
if self.gns3_version() is None:
|
||||
self.display.set_background_title("GNS3")
|
||||
else:
|
||||
self.display.set_background_title("GNS3 {}".format(self.gns3_version()))
|
||||
|
||||
def get_ip(self):
|
||||
"""
|
||||
Return the active IP
|
||||
"""
|
||||
#request 'ip addr' data in JSON format from shell
|
||||
ip_addr_response = subprocess.run(['ip', '--json', 'addr'],capture_output=True)
|
||||
|
||||
#process response, decode and use json.loads to convert the string to a dict
|
||||
ip_addr_data = convert(ip_addr_response.stdout.decode("utf-8"))
|
||||
|
||||
#search ip_addr_data for the first ip adress that is not under a virtual bridge or loopback interface
|
||||
for i in ip_addr_data:
|
||||
if ('virbr' in i['ifname']) or ('lo' in i['ifname']):
|
||||
continue
|
||||
try:
|
||||
if 'UP' in i['flags']:
|
||||
ip_addr = i['addr_info'][0]['local']
|
||||
break
|
||||
except:
|
||||
continue
|
||||
ip_addr = None
|
||||
|
||||
return ip_addr
|
||||
|
||||
def repair_remote_install(self):
|
||||
"""
|
||||
This method is only called by remote-install.sh during setup to ensure it is setting the same IP as shown by Dialog
|
||||
"""
|
||||
ip_addr = self.get_ip()
|
||||
subprocess.run(["sed", "-i", f"s/host = 0.0.0.0/host = {ip_addr}/", "/etc/gns3/gns3_server.conf"],capture_output=False)
|
||||
subprocess.run(["service", "gns3", "stop"],capture_output=False)
|
||||
subprocess.run(["service", "gns3", "start"],capture_output=False)
|
||||
|
||||
|
||||
def get_config(self):
|
||||
"""
|
||||
Read the config
|
||||
"""
|
||||
config = configparser.RawConfigParser()
|
||||
path = os.path.expanduser("~/.config/GNS3/gns3_server.conf")
|
||||
config.read([path], encoding="utf-8")
|
||||
return config
|
||||
|
||||
|
||||
def write_config(self, config):
|
||||
"""
|
||||
Write the config file
|
||||
"""
|
||||
|
||||
with open(os.path.expanduser("~/.config/GNS3/gns3_server.conf"), 'w') as f:
|
||||
config.write(f)
|
||||
|
||||
|
||||
def gns3_major_version(self):
|
||||
"""
|
||||
Returns the GNS3 major server version
|
||||
"""
|
||||
|
||||
version = self.gns3_version()
|
||||
if version:
|
||||
match = re.search(r"\d+.\d+", version)
|
||||
return match.group(0)
|
||||
return ""
|
||||
|
||||
|
||||
def gns3_version(self):
|
||||
"""
|
||||
Return the GNS3 server version
|
||||
"""
|
||||
try:
|
||||
return subprocess.check_output(["gns3server", "--version"]).strip().decode()
|
||||
except (subprocess.CalledProcessError, FileNotFoundError):
|
||||
return None
|
||||
|
||||
|
||||
def gns3vm_version(self):
|
||||
"""
|
||||
Return the GNS3 VM version
|
||||
"""
|
||||
try:
|
||||
with open('/home/gns3/.config/GNS3/gns3vm_version') as f:
|
||||
return f.read().strip()
|
||||
except FileNotFoundError:
|
||||
return "Remote Install"
|
||||
|
||||
|
||||
def mode(self):
|
||||
if self.display.yesno("This feature is for testers only. You may break your GNS3 installation. Are you REALLY sure you want to continue?", yes_label="Exit (Safe option)", no_label="Continue") == self.display.OK:
|
||||
return
|
||||
code, tag = self.display.menu("Select the GNS3 version",
|
||||
choices=[("2.1", "Stable release for this GNS3 VM (RECOMMENDED)"),
|
||||
("2.1dev", "Development version for stable release"),
|
||||
("2.2", "Latest stable release")])
|
||||
self.display.clear()
|
||||
if code == Dialog.OK:
|
||||
os.makedirs(os.path.expanduser("~/.config/GNS3"), exist_ok=True)
|
||||
with open(os.path.expanduser("~/.config/GNS3/gns3_release"), "w+") as f:
|
||||
f.write(tag)
|
||||
|
||||
self.update(force=True)
|
||||
|
||||
|
||||
def get_release(self):
|
||||
try:
|
||||
with open(os.path.expanduser("~/.config/GNS3/gns3_release")) as f:
|
||||
content = f.read()
|
||||
|
||||
# Support old VM versions
|
||||
if content == "stable":
|
||||
content = "1.5"
|
||||
elif content == "testing":
|
||||
content = "1.5"
|
||||
elif content == "unstable":
|
||||
content = "1.5dev"
|
||||
|
||||
return content
|
||||
except OSError:
|
||||
return "1.5"
|
||||
|
||||
|
||||
def update(self, force=False):
|
||||
if not force:
|
||||
if self.display.yesno("PLEASE SNAPSHOT THE VM BEFORE RUNNING THE UPGRADE IN CASE OF FAILURE. The server will reboot at the end of the upgrade process. Continue?") != self.display.OK:
|
||||
return
|
||||
release = self.get_release()
|
||||
if release == "2.2":
|
||||
if self.display.yesno("It is recommended to run GNS3 version 2.2 with lastest GNS3 VM based on Ubuntu 18.04 LTS, please download this VM from our website or continue at your own risk!") != self.display.OK:
|
||||
return
|
||||
if release.endswith("dev"):
|
||||
ret = os.system("curl -Lk https://raw.githubusercontent.com/GNS3/gns3-vm/unstable/scripts/update_{}.sh > /tmp/update.sh && bash -x /tmp/update.sh".format(release))
|
||||
else:
|
||||
ret = os.system("curl -Lk https://raw.githubusercontent.com/GNS3/gns3-vm/master/scripts/update_{}.sh > /tmp/update.sh && bash -x /tmp/update.sh".format(release))
|
||||
if ret != 0:
|
||||
print("ERROR DURING UPGRADE PROCESS PLEASE TAKE A SCREENSHOT IF YOU NEED SUPPORT")
|
||||
time.sleep(15)
|
||||
|
||||
|
||||
def migrate(self):
|
||||
"""
|
||||
Migrate GNS3 VM data.
|
||||
"""
|
||||
|
||||
code, option = self.display.menu("Select an option",
|
||||
choices=[("Setup", "Configure this VM to send data to another GNS3 VM"),
|
||||
("Send", "Send images and projects to another GNS3 VM")])
|
||||
self.display.clear()
|
||||
if code == Dialog.OK:
|
||||
(answer, destination) = self.display.inputbox("What is IP address or hostname of the other GNS3 VM?", init="172.16.1.128")
|
||||
if answer != self.display.OK:
|
||||
return
|
||||
if destination == self.get_ip():
|
||||
self.display.msgbox("The destination cannot be the same as this VM IP address ({})".format(destination))
|
||||
return
|
||||
if option == "Send":
|
||||
# first make sure they are no files belonging to root
|
||||
os.system("sudo chown -R gns3:gns3 /opt/gns3")
|
||||
# then rsync the data
|
||||
command = r"rsync -az --progress -e 'ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /home/gns3/.ssh/gns3-vm-key' /opt/gns3 gns3@{}:/opt".format(destination)
|
||||
ret = os.system('bash -c "{}"'.format(command))
|
||||
time.sleep(10)
|
||||
if ret != 0:
|
||||
self.display.msgbox("Could not send data to the other GNS3 VM located at {}".format(destination))
|
||||
else:
|
||||
self.display.msgbox("Images and projects have been successfully sent to the other GNS3 VM located at {}".format(destination))
|
||||
elif option == "Setup":
|
||||
script = """
|
||||
if [ ! -f ~/.ssh/gns3-vm-key ]
|
||||
then
|
||||
ssh-keygen -f ~/.ssh/gns3-vm-key -N '' -C gns3@{}
|
||||
fi
|
||||
ssh-copy-id -i ~/.ssh/gns3-vm-key gns3@{}
|
||||
""".format(self.get_ip(), destination)
|
||||
ret = os.system('bash -c "{}"'.format(script))
|
||||
time.sleep(10)
|
||||
if ret != 0:
|
||||
self.display.msgbox("Error while setting up the migrate feature")
|
||||
else:
|
||||
self.display.msgbox("Configuration successful, you can now send data to the GNS3 VM located at {} without password".format(destination))
|
||||
|
||||
|
||||
def shrink_disk(self):
|
||||
|
||||
ret = os.system("lspci | grep -i vmware")
|
||||
if ret != 0:
|
||||
self.display.msgbox("Shrinking the disk is only supported when running inside VMware")
|
||||
return
|
||||
|
||||
if self.display.yesno("Would you like to shrink the VM disk? The VM will reboot at the end of the process. Continue?") != self.display.OK:
|
||||
return
|
||||
|
||||
os.system("sudo service gns3 stop")
|
||||
os.system("sudo service docker stop")
|
||||
os.system("sudo vmware-toolbox-cmd disk shrink /opt")
|
||||
os.system("sudo vmware-toolbox-cmd disk shrink /")
|
||||
|
||||
self.display.msgbox("The GNS3 VM will reboot")
|
||||
os.execvp("sudo", ['/usr/bin/sudo', "reboot"])
|
||||
|
||||
def vm_information(self):
|
||||
"""
|
||||
Show IP, SSH settings....
|
||||
"""
|
||||
|
||||
content = "Welcome to GNS3 appliance\n\n"
|
||||
|
||||
version = self.gns3_version()
|
||||
if version is None:
|
||||
content += "GNS3 is not installed please install it with sudo pip3 install gns3-server. Or download a preinstalled VM.\n\n"
|
||||
else:
|
||||
content = "GNS3 version: {gns3_version}\nVM version: {gns3vm_version}\nKVM support available: {kvm}\n\n".format(
|
||||
gns3vm_version=self.gns3vm_version(),
|
||||
gns3_version=version,
|
||||
kvm=self.kvm_support())
|
||||
|
||||
ip = self.get_ip()
|
||||
|
||||
if ip:
|
||||
content += f"""
|
||||
IP: {ip}
|
||||
Web UI: http://{ip}:3080
|
||||
|
||||
To log in using SSH:
|
||||
ssh gns3@{ip}
|
||||
Password: gns3
|
||||
|
||||
Images and projects are located in /opt/gns3
|
||||
""".strip()
|
||||
|
||||
else:
|
||||
content += "eth0 is not configured. Please manually configure it via the Networking menu."
|
||||
|
||||
content += "\n\nRelease channel: " + self.get_release()
|
||||
|
||||
try:
|
||||
self.display.msgbox(content)
|
||||
# If it's an scp command or any bugs
|
||||
except:
|
||||
os.execvp("bash", ['/bin/bash'])
|
||||
|
||||
|
||||
def check_internet_connectivity(self):
|
||||
self.display.pause("Please wait...\n\n")
|
||||
try:
|
||||
response = urllib.request.urlopen('http://pypi.python.org/', timeout=5)
|
||||
except urllib.request.URLError as err:
|
||||
self.display.infobox("Can't connect to Internet (pypi.python.org): {}".format(str(err)))
|
||||
time.sleep(15)
|
||||
return
|
||||
self.display.infobox("Connection to Internet: OK")
|
||||
time.sleep(2)
|
||||
|
||||
|
||||
def keyboard_configuration():
|
||||
"""
|
||||
Allow user to change the keyboard layout
|
||||
"""
|
||||
os.system("/usr/bin/sudo dpkg-reconfigure keyboard-configuration")
|
||||
|
||||
|
||||
def set_security(self):
|
||||
config = self.get_config()
|
||||
if self.display.yesno("Enable server authentication?") == self.display.OK:
|
||||
if not config.has_section("Server"):
|
||||
config.add_section("Server")
|
||||
config.set("Server", "auth", True)
|
||||
(answer, text) = self.display.inputbox("Login?")
|
||||
if answer != self.display.OK:
|
||||
return
|
||||
config.set("Server", "user", text)
|
||||
(answer, text) = self.display.passwordbox("Password?")
|
||||
if answer != self.display.OK:
|
||||
return
|
||||
config.set("Server", "password", text)
|
||||
else:
|
||||
config.set("Server", "auth", False)
|
||||
|
||||
self.write_config(config)
|
||||
|
||||
|
||||
def log(self):
|
||||
os.system("/usr/bin/sudo chmod 755 /var/log/upstart/gns3.log")
|
||||
with open("/var/log/upstart/gns3.log") as f:
|
||||
try:
|
||||
while True:
|
||||
line = f.readline()
|
||||
sys.stdout.write(line)
|
||||
except (KeyboardInterrupt, MemoryError):
|
||||
return
|
||||
|
||||
|
||||
def edit_config(self):
|
||||
"""
|
||||
Edit GNS3 configuration file
|
||||
"""
|
||||
|
||||
major_version = self.gns3_major_version()
|
||||
if major_version == "2.2":
|
||||
os.system("nano ~/.config/GNS3/{}/gns3_server.conf".format(major_version))
|
||||
else:
|
||||
os.system("nano ~/.config/GNS3/gns3_server.conf")
|
||||
|
||||
|
||||
def edit_network(self):
|
||||
"""
|
||||
Edit network configuration file
|
||||
"""
|
||||
if self.display.yesno("The server will reboot at the end of the process. Continue?") != self.display.OK:
|
||||
return
|
||||
os.system("sudo nano /etc/network/interfaces")
|
||||
os.execvp("sudo", ['/usr/bin/sudo', "reboot"])
|
||||
|
||||
|
||||
def edit_proxy(self):
|
||||
"""
|
||||
Configure proxy settings
|
||||
"""
|
||||
res, http_proxy = self.display.inputbox(text="HTTP proxy string, for example http://<user>:<password>@<proxy>:<port>. Leave empty for no proxy.")
|
||||
if res != self.display.OK:
|
||||
return
|
||||
res, https_proxy = self.display.inputbox(text="HTTPS proxy string, for example http://<user>:<password>@<proxy>:<port>. Leave empty for no proxy.")
|
||||
if res != self.display.OK:
|
||||
return
|
||||
|
||||
with open('/tmp/00proxy', 'w+') as f:
|
||||
f.write('Acquire::http::Proxy "' + http_proxy + '";')
|
||||
os.system("sudo mv /tmp/00proxy /etc/apt/apt.conf.d/00proxy")
|
||||
os.system("sudo chown root /etc/apt/apt.conf.d/00proxy")
|
||||
os.system("sudo chmod 744 /etc/apt/apt.conf.d/00proxy")
|
||||
|
||||
with open('/tmp/proxy.sh', 'w+') as f:
|
||||
f.write('export http_proxy="' + http_proxy + '"\n')
|
||||
f.write('export https_proxy="' + https_proxy + '"\n')
|
||||
f.write('export HTTP_PROXY="' + http_proxy + '"\n')
|
||||
f.write('export HTTPS_PROXY="' + https_proxy + '"\n')
|
||||
os.system("sudo mv /tmp/proxy.sh /etc/profile.d/proxy.sh")
|
||||
os.system("sudo chown root /etc/profile.d/proxy.sh")
|
||||
os.system("sudo chmod 744 /etc/profile.d/proxy.sh")
|
||||
os.system("sudo cp /etc/profile.d/proxy.sh /etc/default/docker")
|
||||
|
||||
self.display.msgbox("The GNS3 VM will reboot")
|
||||
os.execvp("sudo", ['/usr/bin/sudo', "reboot"])
|
||||
|
||||
|
||||
def kvm_support(self):
|
||||
"""
|
||||
Returns true if KVM is available
|
||||
"""
|
||||
return subprocess.call("kvm-ok") == 0
|
||||
|
||||
|
||||
def kvm_control(self):
|
||||
"""
|
||||
Check if KVM is correctly configured
|
||||
"""
|
||||
|
||||
kvm_ok = self.kvm_support()
|
||||
config = self.get_config()
|
||||
try:
|
||||
if config.getboolean("Qemu", "enable_kvm") is True:
|
||||
if kvm_ok is False:
|
||||
if self.display.yesno("KVM is not available!\n\nQemu VM will crash!!\n\nThe reason could be unsupported hardware or another virtualization solution is already running.\n\nDisable KVM and get lower performances?") == self.display.OK:
|
||||
config.set("Qemu", "enable_kvm", False)
|
||||
self.write_config(config)
|
||||
os.execvp("sudo", ['/usr/bin/sudo', "reboot"])
|
||||
else:
|
||||
if kvm_ok is True:
|
||||
if self.display.yesno("KVM is available on your computer.\n\nEnable KVM and get better performances?") == self.display.OK:
|
||||
config.set("Qemu", "enable_kvm", True)
|
||||
self.write_config(config)
|
||||
os.execvp("sudo", ['/usr/bin/sudo', "reboot"])
|
||||
except configparser.NoSectionError:
|
||||
return
|
||||
|
||||
|
||||
def display_loop(self):
|
||||
try:
|
||||
while True:
|
||||
code, tag = self.display.menu("GNS3 {}".format(self.gns3_version()),
|
||||
choices=[("Information", "Display VM information"),
|
||||
("Upgrade", "Upgrade GNS3"),
|
||||
("Migrate", "Migrate data to another GNS3 VM"),
|
||||
("Shell", "Open a console"),
|
||||
("Security", "Configure authentication"),
|
||||
("Keyboard", "Change keyboard layout"),
|
||||
("Configure", "Edit server configuration (advanced users ONLY)"),
|
||||
("Proxy", "Configure proxy settings"),
|
||||
("Networking", "Configure networking settings"),
|
||||
("Log", "Show server log"),
|
||||
("Test", "Check internet connection"),
|
||||
("Shrink", "Shrink the VM disk"),
|
||||
("Version", "Select the GNS3 version"),
|
||||
("Restore", "Restore the VM (if you have trouble for upgrade)"),
|
||||
("Reboot", "Reboot the VM"),
|
||||
("Shutdown", "Shutdown the VM")])
|
||||
self.display.clear()
|
||||
if code == Dialog.OK:
|
||||
if tag == "Shell":
|
||||
os.execvp("bash", ['/bin/bash'])
|
||||
elif tag == "Version":
|
||||
self.mode()
|
||||
elif tag == "Restore":
|
||||
os.execvp("sudo", ['/usr/bin/sudo', "/usr/local/bin/gns3restore"])
|
||||
elif tag == "Reboot":
|
||||
os.execvp("sudo", ['/usr/bin/sudo', "reboot"])
|
||||
elif tag == "Shutdown":
|
||||
os.execvp("sudo", ['/usr/bin/sudo', "poweroff"])
|
||||
elif tag == "Upgrade":
|
||||
self.update()
|
||||
elif tag == "Information":
|
||||
self.vm_information()
|
||||
elif tag == "Log":
|
||||
self.log()
|
||||
elif tag == "Migrate":
|
||||
self.migrate()
|
||||
elif tag == "Configure":
|
||||
self.edit_config()
|
||||
elif tag == "Networking":
|
||||
self.edit_network()
|
||||
elif tag == "Security":
|
||||
self.set_security()
|
||||
elif tag == "Keyboard":
|
||||
self.keyboard_configuration()
|
||||
elif tag == "Test":
|
||||
self.check_internet_connectivity()
|
||||
elif tag == "Proxy":
|
||||
self.edit_proxy()
|
||||
elif tag == "Shrink":
|
||||
self.shrink_disk()
|
||||
except KeyboardInterrupt:
|
||||
sys.exit(0)
|
||||
|
||||
if __name__ == "__main__":
|
||||
ws = Welcome_dialog()
|
||||
ws.vm_information()
|
||||
ws.kvm_control()
|
||||
ws.display_loop()
|
||||
@@ -1115,8 +1115,7 @@ async def test_close(vm, port_manager):
|
||||
async def test_close_vnc(vm):
|
||||
|
||||
vm._console_type = "vnc"
|
||||
vm._x11vnc_process = MagicMock()
|
||||
vm._xvfb_process = MagicMock()
|
||||
vm._vnc_process = MagicMock()
|
||||
|
||||
with asyncio_patch("gns3server.compute.docker.DockerVM._get_container_state", return_value="stopped"):
|
||||
with asyncio_patch("gns3server.compute.docker.Docker.query") as mock_query:
|
||||
@@ -1124,7 +1123,7 @@ async def test_close_vnc(vm):
|
||||
mock_query.assert_called_with("DELETE", "containers/e90e34656842", params={"force": 1, "v": 1})
|
||||
|
||||
assert vm._closed is True
|
||||
assert vm._xvfb_process.terminate.called
|
||||
assert vm._vnc_process.terminate.called
|
||||
|
||||
|
||||
async def test_get_namespace(vm):
|
||||
|
||||
@@ -102,6 +102,7 @@ async def test_start(vm):
|
||||
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=mock_process) as mock_exec:
|
||||
mock_process.returncode = None
|
||||
mock_process.communicate = AsyncioMagicMock(return_value=(None, None))
|
||||
await vm.start()
|
||||
assert vm.is_running()
|
||||
assert vm.command_line == ' '.join(mock_exec.call_args[0])
|
||||
@@ -130,6 +131,7 @@ async def test_start_with_iourc(vm, tmpdir):
|
||||
with patch("gns3server.config.Config.get_section_config", return_value={"iourc_path": fake_file}):
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=mock_process) as exec_mock:
|
||||
mock_process.returncode = None
|
||||
mock_process.communicate = AsyncioMagicMock(return_value=(None, None))
|
||||
await vm.start()
|
||||
assert vm.is_running()
|
||||
arsgs, kwargs = exec_mock.call_args
|
||||
@@ -165,11 +167,12 @@ async def test_stop(vm):
|
||||
future = asyncio.Future()
|
||||
future.set_result(True)
|
||||
process.wait.return_value = future
|
||||
process.returncode = None
|
||||
process.communicate = AsyncioMagicMock(return_value=(None, None))
|
||||
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=process):
|
||||
with asyncio_patch("gns3server.utils.asyncio.wait_for_process_termination"):
|
||||
await vm.start()
|
||||
process.returncode = None
|
||||
assert vm.is_running()
|
||||
await vm.stop()
|
||||
assert vm.is_running() is False
|
||||
@@ -190,6 +193,7 @@ async def test_reload(vm, fake_iou_bin):
|
||||
future.set_result(True)
|
||||
process.wait.return_value = future
|
||||
process.returncode = None
|
||||
process.communicate = AsyncioMagicMock(return_value=(None, None))
|
||||
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=process):
|
||||
with asyncio_patch("gns3server.utils.asyncio.wait_for_process_termination"):
|
||||
@@ -202,10 +206,13 @@ async def test_reload(vm, fake_iou_bin):
|
||||
|
||||
async def test_close(vm, port_manager):
|
||||
|
||||
process = MagicMock()
|
||||
process.returncode = None
|
||||
process.communicate = AsyncioMagicMock(return_value=(None, None))
|
||||
vm._start_ubridge = AsyncioMagicMock(return_value=True)
|
||||
vm._ubridge_send = AsyncioMagicMock()
|
||||
with asyncio_patch("gns3server.compute.iou.iou_vm.IOUVM._check_requirements", return_value=True):
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()):
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=process):
|
||||
await vm.start()
|
||||
port = vm.console
|
||||
await vm.close()
|
||||
|
||||
@@ -78,6 +78,7 @@ async def vm(compute_project, manager, fake_qemu_binary, fake_qemu_img_binary):
|
||||
vm._start_ubridge = AsyncioMagicMock()
|
||||
vm._ubridge_hypervisor = MagicMock()
|
||||
vm._ubridge_hypervisor.is_running.return_value = True
|
||||
vm.manager.get_qemu_version = AsyncioMagicMock(return_value="6.2.0")
|
||||
vm.manager.config.set("Qemu", "enable_hardware_acceleration", False)
|
||||
return vm
|
||||
|
||||
@@ -141,7 +142,6 @@ async def test_is_running(vm, running_subprocess_mock):
|
||||
|
||||
async def test_start(vm, running_subprocess_mock):
|
||||
|
||||
vm.manager.get_qemu_version = AsyncioMagicMock(return_value="3.1.0")
|
||||
with asyncio_patch("gns3server.compute.qemu.QemuVM.start_wrap_console"):
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=running_subprocess_mock) as mock:
|
||||
await vm.start()
|
||||
@@ -156,7 +156,6 @@ async def test_stop(vm, running_subprocess_mock):
|
||||
future = asyncio.Future()
|
||||
future.set_result(True)
|
||||
process.wait.return_value = future
|
||||
vm.manager.get_qemu_version = AsyncioMagicMock(return_value="3.1.0")
|
||||
|
||||
with asyncio_patch("gns3server.compute.qemu.QemuVM.start_wrap_console"):
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=process):
|
||||
@@ -241,7 +240,6 @@ async def test_port_remove_nio_binding(vm):
|
||||
|
||||
async def test_close(vm, port_manager):
|
||||
|
||||
vm.manager.get_qemu_version = AsyncioMagicMock(return_value="3.1.0")
|
||||
with asyncio_patch("gns3server.compute.qemu.QemuVM.start_wrap_console"):
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()):
|
||||
await vm.start()
|
||||
@@ -369,7 +367,6 @@ async def test_disk_options(vm, tmpdir, fake_qemu_img_binary):
|
||||
|
||||
async def test_cdrom_option(vm, tmpdir, fake_qemu_img_binary):
|
||||
|
||||
vm.manager.get_qemu_version = AsyncioMagicMock(return_value="3.1.0")
|
||||
vm._cdrom_image = str(tmpdir / "test.iso")
|
||||
open(vm._cdrom_image, "w+").close()
|
||||
|
||||
@@ -380,13 +377,38 @@ async def test_cdrom_option(vm, tmpdir, fake_qemu_img_binary):
|
||||
|
||||
async def test_bios_option(vm, tmpdir, fake_qemu_img_binary):
|
||||
|
||||
vm.manager.get_qemu_version = AsyncioMagicMock(return_value="3.1.0")
|
||||
vm._bios_image = str(tmpdir / "test.img")
|
||||
open(vm._bios_image, "w+").close()
|
||||
options = await vm._build_command()
|
||||
assert ' '.join(['-bios', str(tmpdir / "test.img")]) in ' '.join(options)
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.platform.startswith("win"), reason="Test not working on Windows")
|
||||
async def test_uefi_boot_mode_option(vm, tmpdir, images_dir, fake_qemu_img_binary):
|
||||
|
||||
vm._uefi = True
|
||||
|
||||
# create fake OVMF files
|
||||
ovmf_code_path = os.path.join(images_dir, "OVMF_CODE.fd")
|
||||
with open(ovmf_code_path, "w+") as f:
|
||||
f.write('1')
|
||||
ovmf_vars_path = os.path.join(images_dir, "OVMF_VARS.fd")
|
||||
with open(ovmf_vars_path, "w+") as f:
|
||||
f.write('1')
|
||||
|
||||
options = await vm._build_command()
|
||||
assert ' '.join(["-drive", "if=pflash,format=raw,readonly,file={}".format(ovmf_code_path)]) in ' '.join(options)
|
||||
assert ' '.join(["-drive", "if=pflash,format=raw,file={}".format(os.path.join(vm.working_dir, "OVMF_VARS.fd"))]) in ' '.join(options)
|
||||
|
||||
|
||||
async def test_uefi_with_bios_image_already_configured(vm, tmpdir, fake_qemu_img_binary):
|
||||
|
||||
vm._bios_image = str(tmpdir / "test.img")
|
||||
vm._uefi = True
|
||||
with pytest.raises(QemuError):
|
||||
await vm._build_command()
|
||||
|
||||
|
||||
async def test_vnc_option(vm, fake_qemu_img_binary):
|
||||
|
||||
vm._console_type = 'vnc'
|
||||
@@ -406,7 +428,6 @@ async def test_spice_option(vm, fake_qemu_img_binary):
|
||||
|
||||
async def test_tpm_option(vm, tmpdir, fake_qemu_img_binary):
|
||||
|
||||
vm.manager.get_qemu_version = AsyncioMagicMock(return_value="3.1.0")
|
||||
vm._tpm = True
|
||||
tpm_sock = os.path.join(vm.temporary_directory, "swtpm.sock")
|
||||
with patch("os.path.exists", return_value=True) as os_path:
|
||||
@@ -500,7 +521,6 @@ async def test_control_vm_expect_text(vm, running_subprocess_mock):
|
||||
|
||||
async def test_build_command(vm, fake_qemu_binary):
|
||||
|
||||
vm.manager.get_qemu_version = AsyncioMagicMock(return_value="3.1.0")
|
||||
os.environ["DISPLAY"] = "0:0"
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()):
|
||||
cmd = await vm._build_command()
|
||||
@@ -535,7 +555,6 @@ async def test_build_command_manual_uuid(vm):
|
||||
If user has set a uuid we keep it
|
||||
"""
|
||||
|
||||
vm.manager.get_qemu_version = AsyncioMagicMock(return_value="3.1.0")
|
||||
vm.options = "-uuid e1c307a4-896f-11e6-81a5-3c07547807cc"
|
||||
os.environ["DISPLAY"] = "0:0"
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()):
|
||||
@@ -670,7 +689,6 @@ async def test_build_command_two_adapters_mac_address(vm):
|
||||
Should support multiple base vmac address
|
||||
"""
|
||||
|
||||
vm.manager.get_qemu_version = AsyncioMagicMock(return_value="2.5.0")
|
||||
vm.adapters = 2
|
||||
vm.mac_address = "00:00:ab:0e:0f:09"
|
||||
mac_0 = vm._mac_address
|
||||
@@ -695,12 +713,9 @@ async def test_build_command_two_adapters_mac_address(vm):
|
||||
async def test_build_command_large_number_of_adapters(vm):
|
||||
"""
|
||||
When we have more than 28 interface we need to add a pci bridge for
|
||||
additional interfaces
|
||||
additional interfaces (supported only with Qemu 2.4 and later)
|
||||
"""
|
||||
|
||||
# It's supported only with Qemu 2.4 and later
|
||||
vm.manager.get_qemu_version = AsyncioMagicMock(return_value="2.4.0")
|
||||
|
||||
vm.adapters = 100
|
||||
vm.mac_address = "00:00:ab:0e:0f:09"
|
||||
mac_0 = vm._mac_address
|
||||
@@ -737,6 +752,19 @@ async def test_build_command_large_number_of_adapters(vm):
|
||||
await vm._build_command()
|
||||
|
||||
|
||||
async def test_build_command_with_virtio_net_pci_adapter(vm):
|
||||
"""
|
||||
Test virtio-net-pci adapter which has parameters speed=1000 & duplex=full hard-coded
|
||||
"""
|
||||
|
||||
vm.adapters = 1
|
||||
vm.mac_address = "00:00:ab:0e:0f:09"
|
||||
vm._adapter_type = "virtio-net-pci"
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()):
|
||||
cmd = await vm._build_command()
|
||||
assert "virtio-net-pci,mac=00:00:ab:0e:0f:09,speed=10000,duplex=full,netdev=gns3-0" in cmd
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.platform.startswith("win"), reason="Not supported on Windows")
|
||||
async def test_build_command_with_invalid_options(vm):
|
||||
|
||||
|
||||
@@ -952,6 +952,6 @@ async def test_create_node_from_template(controller_api, controller, project):
|
||||
"x": 42,
|
||||
"y": 12
|
||||
})
|
||||
mock.assert_called_with(id, x=42, y=12, compute_id=None)
|
||||
mock.assert_called_with(id, x=42, y=12, name=None, compute_id=None)
|
||||
assert response.route == "/projects/{project_id}/templates/{template_id}"
|
||||
assert response.status == 201
|
||||
Reference in new issue
Block a user