From fe8df5a17ab9b894667ab443cc101f697ba1f9fb Mon Sep 17 00:00:00 2001 From: Shutdown <40902872+ShutdownRepo@users.noreply.github.com> Date: Wed, 27 Sep 2023 22:10:37 +0200 Subject: [PATCH 1/6] catching exception and returning port -1 when cannot bind --- exegol/model/ContainerConfig.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/exegol/model/ContainerConfig.py b/exegol/model/ContainerConfig.py index 7b74d2b2..f924ac10 100644 --- a/exegol/model/ContainerConfig.py +++ b/exegol/model/ContainerConfig.py @@ -744,10 +744,16 @@ def generateRandomPassword(length: int = 30) -> str: @staticmethod def __findAvailableRandomPort(interface: str = 'localhost') -> int: """Find an available random port. Using the socket system to """ + logger.debug(f"Attempting to bind to interface {interface}") import socket sock = socket.socket() - sock.bind((interface, 0)) # Using port 0 let the system decide for a random port + try: + sock.bind((interface, 0)) # Using port 0 let the system decide for a random port + except OSError as e: + logger.error(f"Unable to bind to interface/port: {e}") + return -1 random_port = sock.getsockname()[1] + logger.debug(f"Found available port {random_port}") sock.close() return random_port From 3b9df15decbb087aa12bbe983db2c045b9a4f461 Mon Sep 17 00:00:00 2001 From: Shutdown <40902872+ShutdownRepo@users.noreply.github.com> Date: Wed, 27 Sep 2023 23:05:25 +0200 Subject: [PATCH 2/6] fixing port definition logic --- exegol/model/ContainerConfig.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/exegol/model/ContainerConfig.py b/exegol/model/ContainerConfig.py index f924ac10..13099dda 100644 --- a/exegol/model/ContainerConfig.py +++ b/exegol/model/ContainerConfig.py @@ -504,20 +504,24 @@ def configureDesktop(self, desktop_config: str): """ self.__desktop_proto = UserConfig().desktop_default_proto self.__desktop_host = "127.0.0.1" if UserConfig().desktop_default_localhost else "0.0.0.0" + _host_set_by_user = False for i, data in enumerate(desktop_config.split(":")): if not data: continue - if i == 0: + if i == 0: # protocol + logger.debug(f"Desktop proto set: {data}") data = data.lower() if data in UserConfig.desktop_available_proto: self.__desktop_proto = data else: logger.critical(f"The desktop mode '{data}' is not supported. Please choose a supported mode: [green]{', '.join(UserConfig.desktop_available_proto)}[/green].") - elif i == 1 and data: + elif i == 1 and data: # host + logger.debug(f"Desktop host set: {data}") self.__desktop_host = data - self.__desktop_port = self.__findAvailableRandomPort(self.__desktop_host) - elif i == 2: + _host_set_by_user = True + elif i == 2: # port + logger.debug(f"Desktop port set: {data}") try: self.__desktop_port = int(data) except ValueError: @@ -526,7 +530,9 @@ def configureDesktop(self, desktop_config: str): logger.critical(f"Your configuration is invalid, please use the following format:[green]mode:host:port[/green]") if self.__desktop_port is None: - self.__desktop_port = self.__findAvailableRandomPort() + _desktop_host = self.__desktop_host if _host_set_by_user else None + logger.debug(f"Desktop port automatically set for host {_desktop_host}") + self.__desktop_port = self.__findAvailableRandomPort(_desktop_host) def __disableDesktop(self): """Procedure to disable exegol desktop feature""" From 20df3f60455abb58b72bbacd49c5fff6a22be26d Mon Sep 17 00:00:00 2001 From: Shutdown <40902872+ShutdownRepo@users.noreply.github.com> Date: Wed, 27 Sep 2023 23:08:56 +0200 Subject: [PATCH 3/6] fixing automatic port definition statement structure --- exegol/model/ContainerConfig.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/exegol/model/ContainerConfig.py b/exegol/model/ContainerConfig.py index 13099dda..7530ee3d 100644 --- a/exegol/model/ContainerConfig.py +++ b/exegol/model/ContainerConfig.py @@ -530,9 +530,11 @@ def configureDesktop(self, desktop_config: str): logger.critical(f"Your configuration is invalid, please use the following format:[green]mode:host:port[/green]") if self.__desktop_port is None: - _desktop_host = self.__desktop_host if _host_set_by_user else None - logger.debug(f"Desktop port automatically set for host {_desktop_host}") - self.__desktop_port = self.__findAvailableRandomPort(_desktop_host) + logger.debug(f"Desktop port will be set automatically") + if _host_set_by_user: + self.__desktop_port = self.__findAvailableRandomPort(self.__desktop_host) + else: + self.__desktop_port = self.__findAvailableRandomPort() def __disableDesktop(self): """Procedure to disable exegol desktop feature""" From 44090f3cf58c07f0673baed2fb42d1ffbfe6f095 Mon Sep 17 00:00:00 2001 From: Dramelac Date: Thu, 28 Sep 2023 18:46:37 +0200 Subject: [PATCH 4/6] Simplify port finder logic --- exegol/model/ContainerConfig.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/exegol/model/ContainerConfig.py b/exegol/model/ContainerConfig.py index 7530ee3d..aa5fa346 100644 --- a/exegol/model/ContainerConfig.py +++ b/exegol/model/ContainerConfig.py @@ -504,7 +504,6 @@ def configureDesktop(self, desktop_config: str): """ self.__desktop_proto = UserConfig().desktop_default_proto self.__desktop_host = "127.0.0.1" if UserConfig().desktop_default_localhost else "0.0.0.0" - _host_set_by_user = False for i, data in enumerate(desktop_config.split(":")): if not data: @@ -519,7 +518,6 @@ def configureDesktop(self, desktop_config: str): elif i == 1 and data: # host logger.debug(f"Desktop host set: {data}") self.__desktop_host = data - _host_set_by_user = True elif i == 2: # port logger.debug(f"Desktop port set: {data}") try: @@ -531,10 +529,7 @@ def configureDesktop(self, desktop_config: str): if self.__desktop_port is None: logger.debug(f"Desktop port will be set automatically") - if _host_set_by_user: - self.__desktop_port = self.__findAvailableRandomPort(self.__desktop_host) - else: - self.__desktop_port = self.__findAvailableRandomPort() + self.__desktop_port = self.__findAvailableRandomPort(self.__desktop_host) def __disableDesktop(self): """Procedure to disable exegol desktop feature""" From c72e683da8aafa085b2b552f1dc700984485a2db Mon Sep 17 00:00:00 2001 From: Dramelac Date: Thu, 28 Sep 2023 19:20:01 +0200 Subject: [PATCH 5/6] Add a check on create mode if the network is available --- exegol/model/ContainerConfig.py | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/exegol/model/ContainerConfig.py b/exegol/model/ContainerConfig.py index aa5fa346..369ba40b 100644 --- a/exegol/model/ContainerConfig.py +++ b/exegol/model/ContainerConfig.py @@ -1,7 +1,9 @@ +import errno import logging import os import random import re +import socket import string from datetime import datetime from enum import Enum @@ -12,9 +14,9 @@ from docker.types import Mount from rich.prompt import Prompt +from exegol.config.ConstantConfig import ConstantConfig from exegol.config.EnvInfo import EnvInfo from exegol.config.UserConfig import UserConfig -from exegol.config.ConstantConfig import ConstantConfig from exegol.console.ConsoleFormat import boolFormatter, getColor from exegol.console.ExegolPrompt import Confirm from exegol.console.cli.ParametersManager import ParametersManager @@ -480,7 +482,7 @@ def enableDesktop(self, desktop_config: str = ""): """Procedure to enable exegol desktop feature""" if not self.isDesktopEnabled(): logger.verbose("Config: Enabling exegol desktop") - self.configureDesktop(desktop_config) + self.configureDesktop(desktop_config, create_mode=True) assert self.__desktop_proto is not None assert self.__desktop_host is not None assert self.__desktop_port is not None @@ -498,7 +500,7 @@ def enableDesktop(self, desktop_config: str = ""): # Exposing desktop service self.addPort(port_host=self.__desktop_port, port_container=self.__default_desktop_port[self.__desktop_proto], host_ip=self.__desktop_host) - def configureDesktop(self, desktop_config: str): + def configureDesktop(self, desktop_config: str, create_mode: bool = False): """Configure the exegol desktop feature from user parameters. Accepted format: 'mode:host:port' """ @@ -531,6 +533,19 @@ def configureDesktop(self, desktop_config: str): logger.debug(f"Desktop port will be set automatically") self.__desktop_port = self.__findAvailableRandomPort(self.__desktop_host) + if create_mode: + # Check if the port is available + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: + try: + s.bind((self.__desktop_host, self.__desktop_port)) + except socket.error as e: + if e.errno == errno.EADDRINUSE: + logger.critical(f"The port {self.__desktop_host}:{self.__desktop_port} is already in use !") + elif e.errno == errno.EADDRNOTAVAIL: + logger.critical(f"The network {self.__desktop_host}:{self.__desktop_port} is not available !") + else: + logger.critical(f"The supplied network configuration {self.__desktop_host}:{self.__desktop_port} is not available ! ([{e.errno}] {e})") + def __disableDesktop(self): """Procedure to disable exegol desktop feature""" if self.isDesktopEnabled(): @@ -748,13 +763,11 @@ def generateRandomPassword(length: int = 30) -> str: def __findAvailableRandomPort(interface: str = 'localhost') -> int: """Find an available random port. Using the socket system to """ logger.debug(f"Attempting to bind to interface {interface}") - import socket sock = socket.socket() try: sock.bind((interface, 0)) # Using port 0 let the system decide for a random port except OSError as e: - logger.error(f"Unable to bind to interface/port: {e}") - return -1 + logger.critical(f"Unable to bind a port to the interface {interface} ({e})") random_port = sock.getsockname()[1] logger.debug(f"Found available port {random_port}") sock.close() From c9866c2623baf269196935029fbb95b09699ff56 Mon Sep 17 00:00:00 2001 From: Dramelac Date: Thu, 28 Sep 2023 19:28:12 +0200 Subject: [PATCH 6/6] Use with format for socket --- exegol/model/ContainerConfig.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/exegol/model/ContainerConfig.py b/exegol/model/ContainerConfig.py index 369ba40b..0c7c26c7 100644 --- a/exegol/model/ContainerConfig.py +++ b/exegol/model/ContainerConfig.py @@ -763,14 +763,13 @@ def generateRandomPassword(length: int = 30) -> str: def __findAvailableRandomPort(interface: str = 'localhost') -> int: """Find an available random port. Using the socket system to """ logger.debug(f"Attempting to bind to interface {interface}") - sock = socket.socket() - try: - sock.bind((interface, 0)) # Using port 0 let the system decide for a random port - except OSError as e: - logger.critical(f"Unable to bind a port to the interface {interface} ({e})") - random_port = sock.getsockname()[1] + with socket.socket() as sock: + try: + sock.bind((interface, 0)) # Using port 0 let the system decide for a random port + except OSError as e: + logger.critical(f"Unable to bind a port to the interface {interface} ({e})") + random_port = sock.getsockname()[1] logger.debug(f"Found available port {random_port}") - sock.close() return random_port # ===== Apply config section =====