diff --git a/gns3server/compute/qemu/qemu_vm.py b/gns3server/compute/qemu/qemu_vm.py index 63eac753..08d55955 100644 --- a/gns3server/compute/qemu/qemu_vm.py +++ b/gns3server/compute/qemu/qemu_vm.py @@ -47,7 +47,7 @@ from ..base_node import BaseNode from ...schemas.qemu import QEMU_OBJECT_SCHEMA, QEMU_PLATFORMS from ...utils.asyncio import monitor_process from ...utils.images import md5sum -from ...utils import macaddress_to_int, int_to_macaddress +from ...utils import macaddress_to_int, int_to_macaddress, is_ipv6_enabled import logging @@ -1672,13 +1672,14 @@ class QemuVM(BaseNode): if self._console: console_host = self._manager.port_manager.console_host if console_host == "0.0.0.0": - if socket.has_ipv6: - # to fix an issue with Qemu when IPv4 is not enabled - # see https://github.com/GNS3/gns3-gui/issues/2352 - # FIXME: consider making this more global (not just for Qemu + SPICE) - console_host = "::" - else: - raise QemuError("IPv6 must be enabled in order to use the SPICE console") + try: + if is_ipv6_enabled(): + # to fix an issue with Qemu when IPv4 is not enabled + # see https://github.com/GNS3/gns3-gui/issues/2352 + # FIXME: consider making this more global (not just for Qemu + SPICE) + console_host = "::" + except OSError as e: + raise QemuError("Could not check if IPv6 is enabled: {}".format(e)) return ["-spice", "addr={},port={},disable-ticketing".format(console_host, self._console), "-vga", "qxl"] diff --git a/gns3server/utils/__init__.py b/gns3server/utils/__init__.py index c571582d..3740066b 100644 --- a/gns3server/utils/__init__.py +++ b/gns3server/utils/__init__.py @@ -21,6 +21,8 @@ import re import shlex import textwrap import posixpath +import socket +import errno def force_unix_path(path): @@ -100,3 +102,21 @@ def shlex_quote(s): return s if re.match(r'^[-_\w./]+$', s) else '"%s"' % s.replace('"', '\\"') else: return shlex.quote(s) + + +def is_ipv6_enabled() -> bool: + + if not socket.has_ipv6: + return False # the socket library has no support for IPv6 + try: + with socket.socket(socket.AF_INET6, socket.SOCK_STREAM) as sock: + sock.bind(("::1", 0)) + return True + except OSError as e: + if e.errno in (errno.EADDRNOTAVAIL, errno.EAFNOSUPPORT): + # EADDRNOTAVAIL is the errno if IPv6 modules/drivers are loaded but disabled. + # EAFNOSUPPORT is the errno if IPv6 modules/drivers are not loaded at all. + return False + if e.errno == errno.EADDRINUSE: + return True + raise