Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Catching exception when interface missing for Desktop beta feature #184

Merged
merged 6 commits into from
Sep 28, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 34 additions & 13 deletions exegol/model/ContainerConfig.py
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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'
"""
Expand All @@ -508,16 +510,18 @@ def configureDesktop(self, desktop_config: str):
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:
elif i == 2: # port
logger.debug(f"Desktop port set: {data}")
try:
self.__desktop_port = int(data)
except ValueError:
Expand All @@ -526,7 +530,21 @@ 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()
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"""
Expand Down Expand Up @@ -744,11 +762,14 @@ def generateRandomPassword(length: int = 30) -> str:
@staticmethod
def __findAvailableRandomPort(interface: str = 'localhost') -> int:
"""Find an available random port. Using the socket system to """
import socket
sock = socket.socket()
sock.bind((interface, 0)) # Using port 0 let the system decide for a random port
random_port = sock.getsockname()[1]
sock.close()
logger.debug(f"Attempting to bind to interface {interface}")
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}")
return random_port

# ===== Apply config section =====
Expand Down