diff --git a/doc/changelog.d/4503.fixed.md b/doc/changelog.d/4503.fixed.md new file mode 100644 index 000000000000..2223b10105d6 --- /dev/null +++ b/doc/changelog.d/4503.fixed.md @@ -0,0 +1 @@ +Ansys Lab authentication diff --git a/src/ansys/fluent/core/launcher/pim_launcher.py b/src/ansys/fluent/core/launcher/pim_launcher.py index dd3788d7a7c4..47765c3363a6 100644 --- a/src/ansys/fluent/core/launcher/pim_launcher.py +++ b/src/ansys/fluent/core/launcher/pim_launcher.py @@ -38,6 +38,8 @@ import inspect import logging import os +import tempfile +import time from typing import Any, Dict from ansys.fluent.core.fluent_connection import FluentConnection, _get_max_c_int_limit @@ -50,6 +52,7 @@ UIMode, _get_argvals_and_session, ) +from ansys.fluent.core.session import _parse_server_info_file from ansys.fluent.core.session_meshing import Meshing from ansys.fluent.core.session_pure_meshing import PureMeshing from ansys.fluent.core.session_solver import Solver @@ -193,6 +196,54 @@ def __call__(self): ) +def get_ip_port_password( + file_service, + filename="sifile.txt", + max_retries=20, + wait_time_between_retries=1, # seconds +): + """ + Downloads the file with retries and parses server info. + + Parameters + ---------- + file_service: PimFileTransferService + Service object with method download_file(filename, target_dir). + filename: str + Name of the file to download. + max_retries: int + Maximum number of attempts. + wait_time_between_retries: float + Seconds to wait between retries (can be fractional, e.g., 0.5 for half a second). + + Returns + ------- + Tuple (ip, port, password) parsed from the downloaded file. + + Raises + ------ + TimeoutError + If unable to download the server info file after multiple retries. + """ + with tempfile.TemporaryDirectory(prefix="fluent_sifile_") as tmpdir: + for attempt in range(1, max_retries + 1): + try: + file_service.download_file(filename, tmpdir) + break + except Exception as ex: + logger.warning( + f"Attempt {attempt} of {max_retries} failed to download {filename}: {ex}" + ) + if attempt == max_retries: + raise TimeoutError( + f"Failed to download file '{filename}' after {max_retries} attempts " + f"with {wait_time_between_retries}s between retries." + ) from ex + time.sleep(wait_time_between_retries) + + return _parse_server_info_file(os.path.join(tmpdir, filename)) + + def launch_remote_fluent( session_cls, start_transcript: bool, @@ -232,6 +283,11 @@ def launch_remote_fluent( ------- Meshing | PureMeshing | Solver | SolverIcing Session object. + + Raises + ------ + TimeoutError + If unable to download the server info file after multiple retries. """ pim = pypim.connect() @@ -245,6 +301,10 @@ def launch_remote_fluent( instance.wait_for_ready() + ip, port, password = get_ip_port_password( + file_service=PimFileTransferService(pim_instance=instance) + ) + channel = instance.build_grpc_channel( options=[ ("grpc.max_send_message_length", _get_max_c_int_limit()), @@ -253,6 +313,9 @@ def launch_remote_fluent( ) fluent_connection = create_fluent_connection( + ip=ip, + port=port, + password=password, channel=channel, cleanup_on_exit=cleanup_on_exit, instance=instance, @@ -288,11 +351,20 @@ def create_fluent_instance( def create_fluent_connection( - channel, cleanup_on_exit: bool, instance, launcher_args: Dict[str, Any] | None + ip: str, + port: int, + password: str, + channel, + cleanup_on_exit: bool, + instance, + launcher_args: Dict[str, Any] | None, ): """Create a Fluent connection.""" return FluentConnection( + ip=ip, + port=port, + password=password, channel=channel, cleanup_on_exit=cleanup_on_exit, remote_instance=instance,