diff --git a/CHANGELOG b/CHANGELOG
index 2c16955d..fa41bc21 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,5 +1,14 @@
# Change Log
+## 2.2.38 28/02/2023
+
+* Bundle web-ui v2.2.38
+* Fix c7200_i0_log.txt is created in the current directory. Fixes #2191
+* Check swtpm version and start swtpm before qemu
+* Fix broken websocket console with Python 3.11
+* Fix "cannot reopen console". Ref #2182
+* Fix Qemu binary not set when adding appliance from template
+
## 2.2.37 25/01/2023
* Fix link communication issues on Windows with uBridge
diff --git a/gns3server/appliances/cisco-nxosv9k.gns3a b/gns3server/appliances/cisco-nxosv9k.gns3a
index 19bc1d79..4005961a 100644
--- a/gns3server/appliances/cisco-nxosv9k.gns3a
+++ b/gns3server/appliances/cisco-nxosv9k.gns3a
@@ -33,6 +33,27 @@
"filesize": 1592000512,
"download_url": "https://software.cisco.com/download/home/286312239/type/282088129/release/10.1(1)"
},
+ {
+ "filename": "nexus9300v.10.1.1.qcow2",
+ "version": "9300v 10.1.1",
+ "md5sum": "4051bdb96aff6e54b72b7e3b06c9d6eb",
+ "filesize": 1990983680,
+ "download_url": "https://software.cisco.com/download/home/286312239/type/282088129/release/10.1(1)"
+ },
+ {
+ "filename": "nexus9500v.9.3.9.qcow2",
+ "version": "9500v 9.3.9",
+ "md5sum": "30c25039927f89aebe73ea20d15abd6d",
+ "filesize": 1980760064,
+ "download_url": "https://software.cisco.com/download/home/286312239/type/282088129/release/9.3(9)"
+ },
+ {
+ "filename": "nexus9300v.9.3.9.qcow2",
+ "version": "9300v 9.3.9",
+ "md5sum": "e807005cb7d2d2957b4af0e59f368b36",
+ "filesize": 1980563456,
+ "download_url": "https://software.cisco.com/download/home/286312239/type/282088129/release/9.3(9)"
+ },
{
"filename": "nexus9300v.9.3.8.qcow2",
"version": "9300v 9.3.8",
@@ -184,6 +205,27 @@
"hda_disk_image": "nexus9500v64.10.1.1.qcow2"
}
},
+ {
+ "name": "9300v 10.1.1",
+ "images": {
+ "bios_image": "OVMF-20160813.fd",
+ "hda_disk_image": "nexus9300v.10.1.1.qcow2"
+ }
+ },
+ {
+ "name": "9500v 9.3.9",
+ "images": {
+ "bios_image": "OVMF-20160813.fd",
+ "hda_disk_image": "nexus9500v.9.3.9.qcow2"
+ }
+ },
+ {
+ "name": "9300v 9.3.9",
+ "images": {
+ "bios_image": "OVMF-20160813.fd",
+ "hda_disk_image": "nexus9300v.9.3.9.qcow2"
+ }
+ },
{
"name": "9300v 9.3.8",
"images": {
diff --git a/gns3server/appliances/fortiweb.gns3a b/gns3server/appliances/fortiweb.gns3a
index 63eb984f..0464b8e5 100644
--- a/gns3server/appliances/fortiweb.gns3a
+++ b/gns3server/appliances/fortiweb.gns3a
@@ -27,6 +27,13 @@
"kvm": "allow"
},
"images": [
+ {
+ "filename": "FWB_KVM-v700-build0129-FORTINET.out.kvm.qcow2",
+ "version": "7.0.5",
+ "md5sum": "dc14114c68cf42df322e5b89bffd9bf7",
+ "filesize": 258146816,
+ "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
+ },
{
"filename": "FWB_KVM-v700-build0097-FORTINET.out.kvm.qcow2",
"version": "7.0.1",
@@ -128,6 +135,13 @@
}
],
"versions": [
+ {
+ "name": "7.0.5",
+ "images": {
+ "hda_disk_image": "FWB_KVM-v700-build0129-FORTINET.out.kvm.qcow2",
+ "hdb_disk_image": "empty30G.qcow2"
+ }
+ },
{
"name": "7.0.1",
"images": {
diff --git a/gns3server/appliances/pan-vm-fw.gns3a b/gns3server/appliances/pan-vm-fw.gns3a
index eb34c763..1406aed8 100644
--- a/gns3server/appliances/pan-vm-fw.gns3a
+++ b/gns3server/appliances/pan-vm-fw.gns3a
@@ -27,6 +27,13 @@
"options": "-smp 2"
},
"images": [
+ {
+ "filename": "PA-VM-KVM-10.1.0.qcow2",
+ "version": "10.1.0",
+ "md5sum": "8266fd412a22694749f2cd4afcd5fa33",
+ "filesize": 3597467648,
+ "download_url": "https://support.paloaltonetworks.com/Updates/SoftwareUpdates/"
+ },
{
"filename": "PA-VM-KVM-10.0.0.qcow2",
"version": "10.0.0",
@@ -120,6 +127,12 @@
}
],
"versions": [
+ {
+ "name": "10.1.0",
+ "images": {
+ "hda_disk_image": "PA-VM-KVM-10.1.0.qcow2"
+ }
+ },
{
"name": "10.0.0",
"images": {
diff --git a/gns3server/appliances/tinycore-linux.gns3a b/gns3server/appliances/tinycore-linux.gns3a
index 86638b46..7fa60832 100644
--- a/gns3server/appliances/tinycore-linux.gns3a
+++ b/gns3server/appliances/tinycore-linux.gns3a
@@ -17,7 +17,7 @@
"qemu": {
"adapter_type": "e1000",
"adapters": 1,
- "ram": 96,
+ "ram": 128,
"hda_disk_interface": "virtio",
"arch": "i386",
"console_type": "vnc",
@@ -28,7 +28,7 @@
{
"filename": "linux-tinycore-11.1.qcow2",
"version": "11.1",
- "md5sum": "993d1ce9b86cb131c90e8263891d51b8",
+ "md5sum": "00a65300a1dcc956e4e677c638bf4445",
"filesize": 33816576,
"download_url": "https://sourceforge.net/projects/gns-3/files/Qemu%20Appliances/",
"direct_download_url": "http://downloads.sourceforge.net/project/gns-3/Qemu%20Appliances/linux-tinycore-11.1.qcow2"
diff --git a/gns3server/appliances/ubuntu-server.gns3a b/gns3server/appliances/ubuntu-server.gns3a
deleted file mode 100644
index ff6bc214..00000000
--- a/gns3server/appliances/ubuntu-server.gns3a
+++ /dev/null
@@ -1,45 +0,0 @@
-{
- "appliance_id": "d2a23e69-9e92-4c3f-83c8-8caa1aa58ece",
- "name": "Ubuntu Server",
- "category": "guest",
- "description": "This is a custom Ubuntu server which comes with Canonical security updates, Xorg and Telnetd",
- "vendor_name": "Canonical Inc.",
- "vendor_url": "https://www.ubuntu.com",
- "documentation_url": "https://help.ubuntu.com",
- "product_name": "Ubuntu",
- "product_url": "https://ubuntu.com/server",
- "registry_version": 4,
- "status": "stable",
- "maintainer": "Mohamad Siblini",
- "maintainer_email": "info@ictkin.com",
- "usage": "Username: gns3\nPassword: gns3 | MD5: 435f15a54f7f673e302ad26f05226e0e",
- "port_name_format": "ens{0}",
- "qemu": {
- "adapter_type": "virtio-net-pci",
- "adapters": 1,
- "ram": 2048,
- "hda_disk_interface": "virtio",
- "arch": "x86_64",
- "console_type": "vnc",
- "boot_priority": "c",
- "kvm": "require",
- "options": "-vga virtio"
- },
- "images": [
- {
- "filename": "Ubuntu Server 18.04.3 LTS (64bit).vmdk",
- "version": "18.04.3 LTS Server",
- "md5sum": "435f15a54f7f673e302ad26f05226e0e",
- "filesize": 2707814912,
- "download_url": "https://www.ictkin.com/gns3-appliance/"
- }
- ],
- "versions": [
- {
- "name": "18.04.3 LTS Server",
- "images": {
- "hda_disk_image": "Ubuntu Server 18.04.3 LTS (64bit).vmdk"
- }
- }
- ]
-}
diff --git a/gns3server/compute/base_node.py b/gns3server/compute/base_node.py
index 9a522d6e..54dea0d6 100644
--- a/gns3server/compute/base_node.py
+++ b/gns3server/compute/base_node.py
@@ -469,7 +469,18 @@ class BaseNode:
try:
# keep forwarding websocket data in both direction
- await asyncio.wait([ws_forward(telnet_writer), telnet_forward(telnet_reader)], return_when=asyncio.FIRST_COMPLETED)
+ if sys.version_info >= (3, 11, 0):
+ # Starting with Python 3.11, passing coroutine objects to wait() directly is forbidden.
+ aws = [asyncio.create_task(ws_forward(telnet_writer)), asyncio.create_task(telnet_forward(telnet_reader))]
+ else:
+ aws = [ws_forward(telnet_writer), telnet_forward(telnet_reader)]
+
+ done, pending = await asyncio.wait(aws, return_when=asyncio.FIRST_COMPLETED)
+ for task in done:
+ if task.exception():
+ log.warning(f"Exception while forwarding WebSocket data to Telnet server {task.exception()}")
+ for task in pending:
+ task.cancel()
finally:
log.info("Client has disconnected from console WebSocket")
if not ws.closed:
diff --git a/gns3server/compute/dynamips/__init__.py b/gns3server/compute/dynamips/__init__.py
index 73e896e7..c7287638 100644
--- a/gns3server/compute/dynamips/__init__.py
+++ b/gns3server/compute/dynamips/__init__.py
@@ -273,7 +273,7 @@ class Dynamips(BaseManager):
"""
try:
- output = await subprocess_check_output(dynamips_path)
+ output = await subprocess_check_output(dynamips_path, "-P", "none")
match = re.search(r"Cisco Router Simulation Platform \(version\s+([\d.]+)", output)
if match:
version = match.group(1)
diff --git a/gns3server/compute/qemu/__init__.py b/gns3server/compute/qemu/__init__.py
index be834425..d377fd6e 100644
--- a/gns3server/compute/qemu/__init__.py
+++ b/gns3server/compute/qemu/__init__.py
@@ -223,7 +223,7 @@ class Qemu(BaseManager):
version = match.group(1)
return version
else:
- raise QemuError("Could not determine the Qemu version for {}".format(qemu_path))
+ raise QemuError("Could not determine the Qemu version for '{}'".format(qemu_path))
except (OSError, subprocess.SubprocessError) as e:
raise QemuError("Error while looking for the Qemu version: {}".format(e))
@@ -242,10 +242,29 @@ class Qemu(BaseManager):
version = match.group(1)
return version
else:
- raise QemuError("Could not determine the Qemu-img version for {}".format(qemu_img_path))
+ raise QemuError("Could not determine the Qemu-img version for '{}'".format(qemu_img_path))
except (OSError, subprocess.SubprocessError) as e:
raise QemuError("Error while looking for the Qemu-img version: {}".format(e))
+ @staticmethod
+ async def get_swtpm_version(swtpm_path):
+ """
+ Gets the swtpm version.
+
+ :param swtpm_path: path to swtpm executable.
+ """
+
+ try:
+ output = await subprocess_check_output(swtpm_path, "--version")
+ match = re.search(r"version\s+([\d.]+)", output)
+ if match:
+ version = match.group(1)
+ return version
+ else:
+ raise QemuError("Could not determine the swtpm version for '{}'".format(swtpm_path))
+ except (OSError, subprocess.SubprocessError) as e:
+ raise QemuError("Error while looking for the swtpm version: {}".format(e))
+
@staticmethod
def get_haxm_windows_version():
"""
diff --git a/gns3server/compute/qemu/qemu_vm.py b/gns3server/compute/qemu/qemu_vm.py
index 9db5d32a..6a8ef00b 100644
--- a/gns3server/compute/qemu/qemu_vm.py
+++ b/gns3server/compute/qemu/qemu_vm.py
@@ -216,7 +216,7 @@ class QemuVM(BaseNode):
if qemu_bin == "qemu":
self._platform = "i386"
else:
- self._platform = re.sub(r'^qemu-system-(.*)$', r'\1', qemu_bin, re.IGNORECASE)
+ self._platform = re.sub(r'^qemu-system-(\w+).*$', r'\1', qemu_bin, re.IGNORECASE)
if self._platform.split(".")[0] not in QEMU_PLATFORMS:
raise QemuError("Platform {} is unknown".format(self._platform))
log.info('QEMU VM "{name}" [{id}] has set the QEMU path to {qemu_path}'.format(name=self._name,
@@ -1079,6 +1079,10 @@ class QemuVM(BaseNode):
# check if there is enough RAM to run
self.check_available_ram(self.ram)
+ # start swtpm (TPM emulator) first if TPM is enabled
+ if self._tpm:
+ await self._start_swtpm()
+
command = await self._build_command()
command_string = " ".join(shlex_quote(s) for s in command)
try:
@@ -1104,8 +1108,6 @@ class QemuVM(BaseNode):
await self._set_process_priority()
if self._cpu_throttling:
self._set_cpu_throttling()
- if self._tpm:
- self._start_swtpm()
if "-enable-kvm" in command_string or "-enable-hax" in command_string:
self._hw_virtualization = True
@@ -2019,10 +2021,9 @@ class QemuVM(BaseNode):
options.extend(["-kernel", self._kernel_image.replace(",", ",,")])
if self._kernel_command_line:
options.extend(["-append", self._kernel_command_line])
-
return options
- def _start_swtpm(self):
+ async def _start_swtpm(self):
"""
Start swtpm (TPM emulator)
"""
@@ -2035,6 +2036,10 @@ class QemuVM(BaseNode):
swtpm = shutil.which("swtpm")
if not swtpm:
raise QemuError("Could not find swtpm (TPM emulator)")
+ swtpm_version = await self.manager.get_swtpm_version(swtpm)
+ if swtpm_version and parse_version(swtpm_version) < parse_version("0.8.0"):
+ # swtpm >= version 0.8.0 is required
+ raise QemuError("swtpm version 0.8.0 or above must be installed (detected version is {})".format(swtpm_version))
try:
command = [
swtpm,
@@ -2066,6 +2071,8 @@ class QemuVM(BaseNode):
"""
tpm_sock = os.path.join(self.temporary_directory, "swtpm.sock")
+ if not os.path.exists(tpm_sock):
+ raise QemuError("swtpm socket file '{}' does not exist".format(tpm_sock))
options = [
"-chardev",
"socket,id=chrtpm,path={}".format(tpm_sock),
diff --git a/gns3server/crash_report.py b/gns3server/crash_report.py
index e1bcef33..09ae4c4f 100644
--- a/gns3server/crash_report.py
+++ b/gns3server/crash_report.py
@@ -58,7 +58,7 @@ class CrashReport:
Report crash to a third party service
"""
- DSN = "https://5eb3c88b4e4949d985a6c4c71157b9c3@o19455.ingest.sentry.io/38482"
+ DSN = "https://4f6a87fd456f468ab0a87ecbc97ed8fb@o19455.ingest.sentry.io/38482"
_instance = None
def __init__(self):
diff --git a/gns3server/handlers/api/controller/node_handler.py b/gns3server/handlers/api/controller/node_handler.py
index c2d23e80..c9e7c057 100644
--- a/gns3server/handlers/api/controller/node_handler.py
+++ b/gns3server/handlers/api/controller/node_handler.py
@@ -29,6 +29,9 @@ from gns3server.schemas.node import (
NODE_DUPLICATE_SCHEMA
)
+import logging
+log = logging.getLogger(__name__)
+
class NodeHandler:
"""
@@ -500,6 +503,8 @@ class NodeHandler:
await ws.send_bytes(msg.data)
elif msg.type == aiohttp.WSMsgType.ERROR:
break
+ except ConnectionResetError:
+ log.info("Websocket console connection with compute disconnected")
finally:
if not ws.closed:
await ws.close()
diff --git a/gns3server/schemas/qemu_template.py b/gns3server/schemas/qemu_template.py
index f6b93a9b..a84a3da9 100644
--- a/gns3server/schemas/qemu_template.py
+++ b/gns3server/schemas/qemu_template.py
@@ -35,7 +35,7 @@ QEMU_TEMPLATE_PROPERTIES = {
"platform": {
"description": "Platform to emulate",
"enum": QEMU_PLATFORMS,
- "default": "i386"
+ "default": ""
},
"linked_clone": {
"description": "Whether the VM is a linked clone or not",
diff --git a/gns3server/static/web-ui/index.html b/gns3server/static/web-ui/index.html
index 5dc9f1f9..773d1415 100644
--- a/gns3server/static/web-ui/index.html
+++ b/gns3server/static/web-ui/index.html
@@ -46,6 +46,6 @@
gtag('config', 'G-5D6FZL9923');
-
+