From 0e99a6a346b956c4bad5780bee4c2e7036b8b51b Mon Sep 17 00:00:00 2001 From: Emir Muhammad Date: Mon, 1 Jun 2026 11:46:29 +0200 Subject: [PATCH 01/14] [FIXUP] hardcode to 29 to test if boot works on different hosts --- src/drunc/connectivity_service/client.py | 10 ++++----- src/drunc/process_manager/configuration.py | 2 ++ src/drunc/process_manager/oks_parser.py | 5 +++++ .../process_manager/process_manager_driver.py | 21 ++++++++++++++++--- 4 files changed, 30 insertions(+), 8 deletions(-) diff --git a/src/drunc/connectivity_service/client.py b/src/drunc/connectivity_service/client.py index 5e7eb124f..87fa1406f 100644 --- a/src/drunc/connectivity_service/client.py +++ b/src/drunc/connectivity_service/client.py @@ -41,16 +41,16 @@ def is_ready(self, timeout: int = 10): attempt += 1 elapsed = time.time() - start - self.log.debug(f"Health check attempt {attempt} at {elapsed:.2f}s elapsed") - self.log.debug(f"Polling address: {self.address}") + self.log.info(f"Health check attempt {attempt} at {elapsed:.2f}s elapsed") + self.log.info(f"Polling address: {self.address}") try: r = get(self.address) except Exception as e: - self.log.debug(f"Polling failed with exception: {e}") + self.log.info(f"Polling failed with exception: {e}") r = None # Request failed - service is NOT ready. if r is None or not r.ok: - self.log.debug( + self.log.info( f"Connectivity service not ready, retrying in {delay:.2f}s" ) time.sleep(delay) @@ -58,7 +58,7 @@ def is_ready(self, timeout: int = 10): delay = min(delay * 2, max_delay) # Request succeeded - service is ready. else: - self.log.debug( + self.log.info( f"Connectivity service ready after {attempt} attempts ({elapsed:.2f}s)" ) return True diff --git a/src/drunc/process_manager/configuration.py b/src/drunc/process_manager/configuration.py index da9198722..21be97eb2 100644 --- a/src/drunc/process_manager/configuration.py +++ b/src/drunc/process_manager/configuration.py @@ -149,6 +149,8 @@ def get_commandline_parameters( Ordered list of command-line arguments for process launch. """ runs_on = obj.runs_on.runs_on.id + runs_on = "np04-srv-029.cern.ch" + control_service_port = -1 control_service_protocol = "" for svc in obj.exposes_service: diff --git a/src/drunc/process_manager/oks_parser.py b/src/drunc/process_manager/oks_parser.py index 5feb6ba50..dea72e64e 100644 --- a/src/drunc/process_manager/oks_parser.py +++ b/src/drunc/process_manager/oks_parser.py @@ -183,6 +183,7 @@ def collect_apps( collect_variables(controller.application_environment, rc_env) rc_env["DUNEDAQ_APPLICATION_NAME"] = controller.id host = controller.runs_on.runs_on.id + host = "np04-srv-029.cern.ch" tree_id_str = ".".join(map(str, tree_prefix)) apps.append( @@ -260,6 +261,10 @@ def collect_apps( ) log.debug(f"Collecting app {app.id} with args {args}") + host = "np04-srv-029.cern.ch" + + log.info(f"the host is {host}") + data_path = get_writer_directory_path(app, log) if not data_path: log.debug(f"No data path found for app {app.id}") diff --git a/src/drunc/process_manager/process_manager_driver.py b/src/drunc/process_manager/process_manager_driver.py index ea239f4d6..9b31305a3 100644 --- a/src/drunc/process_manager/process_manager_driver.py +++ b/src/drunc/process_manager/process_manager_driver.py @@ -141,15 +141,18 @@ def boot( # Step 3 - check for port conflicts and update configuration/DAL as needed db, session_dal = self.check_port_conflicts(db, session_dal) + self.log.info("step 4") # Step 4 - connect to the connection service csc, connection_server, connection_port = self._connect_to_service( session_dal, session_name ) + self.log.info("step 5") # Step 5 - track boot timings per host last_boot_on_host_at = {} previous_host = None + self.log.info("step 6") # Step 6: iterate over boot requests for request in self._convert_oks_to_boot_request( oks_conf=conf_file, @@ -159,6 +162,8 @@ def boot( override_logs=override_logs, **kwargs, ): + self.log.warning(request) + if not request: self.log.error("[red]No boot request was generated, ending boot.[/red]") return None @@ -169,10 +174,11 @@ def boot( f"Skipping connectivity service readiness check for application {request.process_description.metadata.name}" ) else: - self.log.debug( + self.log.info( f"Checking connectivity service readiness before booting application {request.process_description.metadata.name}" ) if csc and not csc.is_ready(timeout=10): + self.log.info("whoops its not ready?") raise DruncSetupException( "Connectivity service did not respond within timeout." ) @@ -205,6 +211,7 @@ def boot( ) handle_grpc_error(e) + self.log.info("step 7") # Step 7: discover segment root controller self._discover_controller( session_dal, session_name, csc, connection_server, connection_port @@ -239,7 +246,7 @@ def _collect_all_apps( apps = infra_apps + apps - self.log.debug(f"{json.dumps(apps, indent=4)}") + self.log.info(f"{json.dumps(apps, indent=4)}") return apps @@ -542,19 +549,27 @@ def _connect_to_service( self, session_dal: "conffwk.dal.Session", session_name: str ) -> ConnectivityServiceClient | None: if session_dal.connectivity_service: + self.log.info("we have connectivity service") + connection_server = session_dal.connectivity_service.host connection_port = session_dal.connectivity_service.service.port if connection_server == "localhost": + self.log.info("Apparently its localhost?") resolved_server = resolve_localhost_to_hostname(connection_server) - self.log.debug( + self.log.info( f"Resolved connection server 'localhost' to '{resolved_server}' to avoid K8s hairpinning." ) connection_server = resolved_server + connection_server = "np04-srv-029.cern.ch" client = ConnectivityServiceClient( session_name, f"{connection_server}:{connection_port}" ) + + self.log.info( + f"returning {client=}, {connection_server=}, {connection_port=}" + ) return client, connection_server, connection_port return None, None, None From 29f01727b10ab70914df03a1bb3e18d1d8d3f370 Mon Sep 17 00:00:00 2001 From: Emir Muhammad Date: Mon, 1 Jun 2026 12:27:29 +0200 Subject: [PATCH 02/14] minimum fix needed to fix the LCS issue --- src/drunc/process_manager/configuration.py | 2 +- src/drunc/process_manager/oks_parser.py | 4 ++-- .../process_manager/process_manager_driver.py | 16 ++++++++++++++-- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/drunc/process_manager/configuration.py b/src/drunc/process_manager/configuration.py index 21be97eb2..fa6e821cd 100644 --- a/src/drunc/process_manager/configuration.py +++ b/src/drunc/process_manager/configuration.py @@ -149,7 +149,7 @@ def get_commandline_parameters( Ordered list of command-line arguments for process launch. """ runs_on = obj.runs_on.runs_on.id - runs_on = "np04-srv-029.cern.ch" + # runs_on = "np04-srv-029.cern.ch" control_service_port = -1 control_service_protocol = "" diff --git a/src/drunc/process_manager/oks_parser.py b/src/drunc/process_manager/oks_parser.py index dea72e64e..e73a4cae4 100644 --- a/src/drunc/process_manager/oks_parser.py +++ b/src/drunc/process_manager/oks_parser.py @@ -183,7 +183,7 @@ def collect_apps( collect_variables(controller.application_environment, rc_env) rc_env["DUNEDAQ_APPLICATION_NAME"] = controller.id host = controller.runs_on.runs_on.id - host = "np04-srv-029.cern.ch" + # host = "np04-srv-029.cern.ch" tree_id_str = ".".join(map(str, tree_prefix)) apps.append( @@ -261,7 +261,7 @@ def collect_apps( ) log.debug(f"Collecting app {app.id} with args {args}") - host = "np04-srv-029.cern.ch" + # host = "np04-srv-029.cern.ch" log.info(f"the host is {host}") diff --git a/src/drunc/process_manager/process_manager_driver.py b/src/drunc/process_manager/process_manager_driver.py index 9b31305a3..5a29eadd4 100644 --- a/src/drunc/process_manager/process_manager_driver.py +++ b/src/drunc/process_manager/process_manager_driver.py @@ -7,6 +7,7 @@ from collections.abc import Iterator from time import sleep from typing import Dict, List +from urllib.parse import urlparse import conffwk import grpc @@ -129,6 +130,9 @@ def boot( ) -> Iterator[ProcessInstanceList] | None: self.log.info(f"Booting session [green]{session_name}[/green]") + self.log.warning( + f"parameters: {conf_file=}, {conf_id=}, {user=}, {self.address=}" + ) # Assume oksconflibs if no framework is defined conf_file = f"oksconflibs:{conf_file}" if ":" not in conf_file else conf_file @@ -556,13 +560,21 @@ def _connect_to_service( if connection_server == "localhost": self.log.info("Apparently its localhost?") - resolved_server = resolve_localhost_to_hostname(connection_server) + # resolved_server = resolve_localhost_to_hostname(connection_server) + + test_address = self.address + if "://" not in test_address: + test_address = "grpc://" + test_address + + resolved_server = urlparse(test_address).hostname self.log.info( f"Resolved connection server 'localhost' to '{resolved_server}' to avoid K8s hairpinning." ) connection_server = resolved_server - connection_server = "np04-srv-029.cern.ch" + # Funnily enough this is the minimum amount of change needed...s + # so basically instead of trying to resolve the localhost hostname, resolve to whatever we are connecting to? + # connection_server = "np04-srv-028" client = ConnectivityServiceClient( session_name, f"{connection_server}:{connection_port}" ) From 77280e1e035dd0b721901fa12d06d1c2397d9820 Mon Sep 17 00:00:00 2001 From: Emir Muhammad Date: Mon, 1 Jun 2026 12:47:33 +0200 Subject: [PATCH 03/14] Remove the confirmation? --- src/drunc/process_manager/interface/commands.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/drunc/process_manager/interface/commands.py b/src/drunc/process_manager/interface/commands.py index cbfde6250..05deb10de 100644 --- a/src/drunc/process_manager/interface/commands.py +++ b/src/drunc/process_manager/interface/commands.py @@ -48,11 +48,15 @@ def boot( processes = obj.get_driver("process_manager").ps(ProcessQuery(user=user)) if len(processes.values) > 0: - click.confirm( - f"You already have {len(processes.values)} processes running, are you sure you want to boot a session?", - abort=True, + log.info( + f"Note that there are already {len(processes.values)} processes running." ) + # click.confirm( + # f"You already have {len(processes.values)} processes running, are you sure you want to boot a session?", + # abort=True, + # ) + log.debug( f"Booting session {session_name} with boot configuration file {configuration_file} and id {configuration_id}, requested by user {user}" ) From 446f7747d8b313d2eb648e0b868456cdf47c761f Mon Sep 17 00:00:00 2001 From: Emir Muhammad Date: Mon, 1 Jun 2026 15:04:49 +0200 Subject: [PATCH 04/14] update controller advertising output --- src/drunc/process_manager/interface/commands.py | 3 ++- src/drunc/utils/utils.py | 12 ++++++++++++ tests/utils/test_utils.py | 7 +++++++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/drunc/process_manager/interface/commands.py b/src/drunc/process_manager/interface/commands.py index 05deb10de..eefbbb1d5 100644 --- a/src/drunc/process_manager/interface/commands.py +++ b/src/drunc/process_manager/interface/commands.py @@ -13,7 +13,7 @@ from drunc.process_manager.interface.context import ProcessManagerContext from drunc.process_manager.utils import tabulate_process_instance_list from drunc.utils.shell_utils import InterruptedCommand, log_pm_cmd -from drunc.utils.utils import get_logger +from drunc.utils.utils import get_logger, resolve_context_peer @click.command("boot") @@ -82,6 +82,7 @@ def boot( raise e controller_address = obj.get_driver("process_manager").controller_address + controller_address = resolve_context_peer(controller_address) if controller_address: obj.print( Panel( diff --git a/src/drunc/utils/utils.py b/src/drunc/utils/utils.py index 0109c00c4..2dc9456e3 100644 --- a/src/drunc/utils/utils.py +++ b/src/drunc/utils/utils.py @@ -524,6 +524,18 @@ def resolve_context_peer(peer: str) -> str: str: The original peer string, or a resolved ``host:port`` representation. """ + if not peer: + return peer + + # Some callers pass a plain host:port string without a transport prefix. + # Handle those directly instead of assuming the first token is always a transport. + if peer.startswith("[") or peer.count(":") == 1: + parsed = _parse_host_port(peer) + if parsed is not None: + host, port = parsed + resolved_host = _resolve_host(host) + return f"{resolved_host}:{port}" + match = re.match(r"^(?P[^:]+):(?P
.+)$", peer) if not match: return peer diff --git a/tests/utils/test_utils.py b/tests/utils/test_utils.py index 94b3573d6..5094824b0 100644 --- a/tests/utils/test_utils.py +++ b/tests/utils/test_utils.py @@ -20,6 +20,7 @@ now_str, parent_death_pact, regex_match, + resolve_context_peer, resolve_localhost_and_127_ip_to_network_ip, resolve_localhost_to_hostname, validate_command_facility, @@ -157,6 +158,12 @@ def test_resolve_localhost_and_127_ip_to_network_ip(): assert resolved == generate_address(this_ip) +def test_resolve_context_peer(): + assert resolve_context_peer("grpc:np04-srv-028:50000") == "np04-srv-028:50000" + assert resolve_context_peer("np04-srv-028:50000") == "np04-srv-028:50000" + assert resolve_context_peer("") == "" + + def test_host_is_local(): this_ip = socket.gethostbyname(socket.gethostname()) hostname = socket.gethostname() From 053c4db41080edccceb257d24e28f258da90a93b Mon Sep 17 00:00:00 2001 From: Emir Muhammad Date: Mon, 1 Jun 2026 15:36:59 +0200 Subject: [PATCH 05/14] [HACK] remoce shared context to enable controller shell to work --- src/drunc/apps/controller_shell.py | 1 + src/drunc/controller/controller_driver.py | 1 + src/drunc/controller/interface/shell.py | 6 ++++-- src/drunc/controller/interface/shell_utils.py | 16 +++++++++++++--- 4 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/drunc/apps/controller_shell.py b/src/drunc/apps/controller_shell.py index 5ff6ca7d0..79068740e 100644 --- a/src/drunc/apps/controller_shell.py +++ b/src/drunc/apps/controller_shell.py @@ -14,6 +14,7 @@ def main() -> None: log = get_logger("controller_shell", rich_handler=True) log.error("[red bold]:fire::fire: Exception thrown :fire::fire:") log.exception(e) + # raise e exit(1) diff --git a/src/drunc/controller/controller_driver.py b/src/drunc/controller/controller_driver.py index 376530660..6522058fb 100644 --- a/src/drunc/controller/controller_driver.py +++ b/src/drunc/controller/controller_driver.py @@ -126,6 +126,7 @@ def describe( execute_on_all_subsequent_children_in_path: bool = True, timeout: int | float = 60, ) -> DescribeResponse: + # self.log.("in describe") request = DescribeRequest( target=target, execute_along_path=execute_along_path, diff --git a/src/drunc/controller/interface/shell.py b/src/drunc/controller/interface/shell.py index 5c71bde1c..401dd9744 100644 --- a/src/drunc/controller/interface/shell.py +++ b/src/drunc/controller/interface/shell.py @@ -53,16 +53,18 @@ def controller_shell(ctx, controller_address: str, log_level: str) -> None: get_root_logger(log_level) controller_shell_log = get_logger("controller.iface.shell", rich_handler=True) - controller_shell_log.debug("Resetting the context instance address") + controller_shell_log.info("Resetting the context instance address") ctx.obj.reset(address=controller_address) ctx.call_on_close(controller_cleanup_wrapper(ctx.obj)) desc = None - controller_shell_log.debug( + controller_shell_log.info( f"[green]{getpass.getuser()}[/green] connecting to the [green]controller[/green] through a [green]controller-shell[/green] via address [green]{controller_address}[/green]" ) try: + controller_shell_log.info("test 1") desc = controller_setup(ctx.obj, controller_address) + controller_shell_log.info("test 2") except ServerUnreachable as e: controller_shell_log.critical("Could not connect to the controller") controller_shell_log.exception( diff --git a/src/drunc/controller/interface/shell_utils.py b/src/drunc/controller/interface/shell_utils.py index 3ffba7455..42e8a1572 100644 --- a/src/drunc/controller/interface/shell_utils.py +++ b/src/drunc/controller/interface/shell_utils.py @@ -46,7 +46,7 @@ pack_to_any, unpack_any, ) -from drunc.utils.utils import format_name_for_cli, get_logger, get_shared_rich_console +from drunc.utils.utils import format_name_for_cli, get_logger log = get_logger("controller.iface.shell_utils") @@ -188,7 +188,8 @@ def __init__(self, ctx, refresh_per_second=2, *args, **kwargs) -> None: # Get the instance of the console that the logger is using with the rich handler # so that the progress bar can be rendered in the same console, and not mess up # the logs - shared_console = get_shared_rich_console(self.ctx.log) + # shared_console = get_shared_rich_console(self.ctx.log) + shared_console = None if shared_console: kwargs["console"] = shared_console @@ -197,7 +198,7 @@ def __init__(self, ctx, refresh_per_second=2, *args, **kwargs) -> None: def update_table(self): # The following debug log line will be used in an integration test to validate # that issue 817 does not appear again (rich table overriding the log entries) - self.ctx.log.debug("Updating the status table...") + # self.ctx.log.debug("Updating the status table...") statuses = self.ctx.get_driver("controller").status() descriptions = self.ctx.get_driver("controller").describe() self.table = get_status_table(statuses, descriptions) @@ -251,6 +252,8 @@ def controller_setup(ctx, controller_address): timeout = 60 + log.warning("into progrss") + with Progress( SpinnerColumn(), TextColumn("[progress.description]{task.description}"), @@ -268,22 +271,29 @@ def controller_setup(ctx, controller_address): start_time = time.time() while time.time() - start_time < timeout: progress.update(waiting, completed=time.time() - start_time) + log.warning("trying this thingy") try: + log.warning("getting desc") desc = ctx.get_driver("controller").describe().description + log.warning("desc done") stored_exception = None break except ServerUnreachable as e: + log.warning("yee hawe") stored_exception = e time.sleep(1) except Exception as e: + log.warning("weewoo") ctx.critical("Could not get the controller's status") ctx.critical(e) ctx.critical("Exiting.") ctx.terminate() raise e + log.warning(start_time) + log.info("survived progress") if stored_exception is not None: raise stored_exception From 5ce8e03352fa556abff3d5505cf6a24773fee039 Mon Sep 17 00:00:00 2001 From: Emir Muhammad Date: Tue, 2 Jun 2026 14:39:35 +0200 Subject: [PATCH 06/14] add some notes and logging --- src/drunc/connectivity_service/client.py | 2 +- src/drunc/process_manager/oks_parser.py | 7 +- .../process_manager/process_manager_driver.py | 102 +++++++++++++++++- .../process_manager/ssh_process_manager.py | 2 +- 4 files changed, 109 insertions(+), 4 deletions(-) diff --git a/src/drunc/connectivity_service/client.py b/src/drunc/connectivity_service/client.py index 87fa1406f..111b349c5 100644 --- a/src/drunc/connectivity_service/client.py +++ b/src/drunc/connectivity_service/client.py @@ -17,7 +17,7 @@ def __init__(self, session: str, address: str): # assume the simplest case here self.address = f"http://{address}" - self.log.debug( + self.log.error( f"Connectivity service address: {self.address}, session: {self.session}" ) diff --git a/src/drunc/process_manager/oks_parser.py b/src/drunc/process_manager/oks_parser.py index e73a4cae4..bdb4d99d2 100644 --- a/src/drunc/process_manager/oks_parser.py +++ b/src/drunc/process_manager/oks_parser.py @@ -179,11 +179,16 @@ def collect_apps( # Add controller for this segment to list of apps controller = segment_obj.controller + rc_env = defenv.copy() collect_variables(controller.application_environment, rc_env) rc_env["DUNEDAQ_APPLICATION_NAME"] = controller.id + host = controller.runs_on.runs_on.id + # okay fine if we change this to 29 that works.. + # but we will need this to be clean # host = "np04-srv-029.cern.ch" + log.info(f"main host is {host}") tree_id_str = ".".join(map(str, tree_prefix)) apps.append( @@ -263,7 +268,7 @@ def collect_apps( # host = "np04-srv-029.cern.ch" - log.info(f"the host is {host}") + log.info(f"app host is {host}") data_path = get_writer_directory_path(app, log) if not data_path: diff --git a/src/drunc/process_manager/process_manager_driver.py b/src/drunc/process_manager/process_manager_driver.py index 5a29eadd4..3f2eed278 100644 --- a/src/drunc/process_manager/process_manager_driver.py +++ b/src/drunc/process_manager/process_manager_driver.py @@ -56,6 +56,88 @@ class ProcessManagerDriver: controller_address = "" + + def _dump_oks_value(self, value): + if value is None or isinstance(value, (str, int, float, bool)): + return value + + if isinstance(value, (list, tuple, set)): + return [self._dump_oks_value(item) for item in value] + + if hasattr(value, "className"): + class_name = value.className() + if class_name == "VariableSet": + return { + "class": class_name, + "contains": self._dump_oks_value(getattr(value, "contains", [])), + } + + if class_name == "Variable": + return { + "class": class_name, + "name": getattr(value, "name", None), + "value": getattr(value, "value", None), + } + + snapshot = { + "class": class_name, + "id": getattr(value, "id", None), + } + + field_map = { + "Session": [ + "log_path", + "rte_script", + "environment", + "segment", + "connectivity_service", + "infrastructure_applications", + "disabled", + ], + "Segment": ["controller", "segments", "applications", "disabled"], + "Application": [ + "application_name", + "application_environment", + "runs_on", + "log_path", + "data_path", + ], + "Controller": [ + "application_name", + "application_environment", + "runs_on", + "exposes_service", + "fsm", + "log_path", + ], + "ConnectivityService": ["host", "service"], + "Service": ["host", "port"], + "Resource": ["id"], + } + + for field_name in field_map.get(class_name, ["host", "service", "port", "name", "value"]): + try: + field_value = getattr(value, field_name) + except Exception: + continue + snapshot[field_name] = self._dump_oks_value(field_value) + + return snapshot + + if isinstance(value, dict): + return {key: self._dump_oks_value(item) for key, item in value.items()} + + return repr(value) + + def _dump_database(self, db: conffwk.Configuration) -> str: + configuration_file = db.active_database + full_db_path = get_full_db_path(configuration_file) + with open(full_db_path, encoding="utf-8") as config_file: + return config_file.read() + + def _dump_session_dal(self, session_dal: "conffwk.dal.Session") -> str: + return json.dumps(self._dump_oks_value(session_dal), indent=2, sort_keys=False) + def __init__(self, address: str, token: Token): self.log = get_logger("process_manager_driver", rich_handler=True) self.address = address @@ -145,13 +227,22 @@ def boot( # Step 3 - check for port conflicts and update configuration/DAL as needed db, session_dal = self.check_port_conflicts(db, session_dal) + # Step 3.5 - modify the host mapping (explicitly!!) + # self.log.warning("prechange session_dal:\n%s", self._dump_session_dal(session_dal)) + + # session_dal = self.update_dal_host(session_dal) + + + # self.log.warning("db dump:\n%s", self._dump_database(db)) + # self.log.warning("postchange session_dal:\n%s", self._dump_session_dal(session_dal)) + self.log.info("step 4") # Step 4 - connect to the connection service csc, connection_server, connection_port = self._connect_to_service( session_dal, session_name ) - self.log.info("step 5") + self.log.info(f"step 5 + {csc.address}") # Step 5 - track boot timings per host last_boot_on_host_at = {} previous_host = None @@ -250,6 +341,7 @@ def _collect_all_apps( apps = infra_apps + apps + self.log.warning("json jumps") self.log.info(f"{json.dumps(apps, indent=4)}") return apps @@ -428,6 +520,13 @@ def update_connectivity_port_dal( if item.name == "CONNECTION_PORT": item.value = new_port + + + def update_dal_host(self, session_dal): + session_dal.connectivity_service.host = "np04-srv-029" + return session_dal + + def check_port_conflicts( self, db: conffwk.Configuration, session_dal: "conffwk.dal.Session" ) -> tuple[conffwk.Configuration, "conffwk.dal.Session"]: @@ -572,6 +671,7 @@ def _connect_to_service( ) connection_server = resolved_server + self.log.info(f"connectivity service: {connection_server=}") # Funnily enough this is the minimum amount of change needed...s # so basically instead of trying to resolve the localhost hostname, resolve to whatever we are connecting to? # connection_server = "np04-srv-028" diff --git a/src/drunc/process_manager/ssh_process_manager.py b/src/drunc/process_manager/ssh_process_manager.py index 09a2f55cd..f4eef6679 100644 --- a/src/drunc/process_manager/ssh_process_manager.py +++ b/src/drunc/process_manager/ssh_process_manager.py @@ -394,7 +394,7 @@ def __boot(self, boot_request: BootRequest, uuid: str) -> ProcessInstance: self.log.info( f"Booted '{boot_request.process_description.metadata.name}' " f"from session '{boot_request.process_description.metadata.session}' " - f"with UUID {uuid}" + f"with UUID {uuid} in hosts '{boot_request.process_restriction.allowed_hosts}" ) # Query current process status From 33e0ae628de791dc694462b70c5775fcb58d2510 Mon Sep 17 00:00:00 2001 From: Emir Muhammad Date: Tue, 2 Jun 2026 14:40:06 +0200 Subject: [PATCH 07/14] new, add minimal working for it to run anywhere? --- .../process_manager/process_manager_driver.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/drunc/process_manager/process_manager_driver.py b/src/drunc/process_manager/process_manager_driver.py index 3f2eed278..478e400bb 100644 --- a/src/drunc/process_manager/process_manager_driver.py +++ b/src/drunc/process_manager/process_manager_driver.py @@ -56,7 +56,6 @@ class ProcessManagerDriver: controller_address = "" - def _dump_oks_value(self, value): if value is None or isinstance(value, (str, int, float, bool)): return value @@ -115,7 +114,9 @@ def _dump_oks_value(self, value): "Resource": ["id"], } - for field_name in field_map.get(class_name, ["host", "service", "port", "name", "value"]): + for field_name in field_map.get( + class_name, ["host", "service", "port", "name", "value"] + ): try: field_value = getattr(value, field_name) except Exception: @@ -232,7 +233,6 @@ def boot( # session_dal = self.update_dal_host(session_dal) - # self.log.warning("db dump:\n%s", self._dump_database(db)) # self.log.warning("postchange session_dal:\n%s", self._dump_session_dal(session_dal)) @@ -390,7 +390,9 @@ def _build_boot_request( override_logs: bool, pwd: str, ) -> BootRequest: - host = format_hostname(app["restriction"]) + # host = format_hostname(app["restriction"]) + host = "np04-srv-029" #! GOD BLESS THIS WORKSS + # this is one of the two minimal changes needed to get this working in general? name = app["name"] exe = app["type"] args = app["args"] @@ -520,13 +522,10 @@ def update_connectivity_port_dal( if item.name == "CONNECTION_PORT": item.value = new_port - - def update_dal_host(self, session_dal): session_dal.connectivity_service.host = "np04-srv-029" return session_dal - def check_port_conflicts( self, db: conffwk.Configuration, session_dal: "conffwk.dal.Session" ) -> tuple[conffwk.Configuration, "conffwk.dal.Session"]: @@ -661,7 +660,9 @@ def _connect_to_service( self.log.info("Apparently its localhost?") # resolved_server = resolve_localhost_to_hostname(connection_server) - test_address = self.address + # test_address = self.address + test_address = "np04-srv-029" + # this is one of the two minimal changes needed to get this working in general? if "://" not in test_address: test_address = "grpc://" + test_address From 0107676f7d9f55dce1b1c2572dae9f9f8775a187 Mon Sep 17 00:00:00 2001 From: Emir Muhammad Date: Tue, 2 Jun 2026 14:58:47 +0200 Subject: [PATCH 08/14] finally the multi host stuff works --- .../process_manager/process_manager_driver.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/drunc/process_manager/process_manager_driver.py b/src/drunc/process_manager/process_manager_driver.py index 478e400bb..4c6c33294 100644 --- a/src/drunc/process_manager/process_manager_driver.py +++ b/src/drunc/process_manager/process_manager_driver.py @@ -390,8 +390,14 @@ def _build_boot_request( override_logs: bool, pwd: str, ) -> BootRequest: - # host = format_hostname(app["restriction"]) - host = "np04-srv-029" #! GOD BLESS THIS WORKSS + host_test = format_hostname(app["restriction"]) + resolved_server_test = resolve_localhost_to_hostname(host_test) + self.log.info(f"boot resolve {resolved_server_test}") + + host = resolved_server_test + + # host = "np04-srv-029" #! GOD BLESS THIS WORKSS + # this is one of the two minimal changes needed to get this working in general? name = app["name"] exe = app["type"] @@ -658,10 +664,13 @@ def _connect_to_service( if connection_server == "localhost": self.log.info("Apparently its localhost?") - # resolved_server = resolve_localhost_to_hostname(connection_server) + resolved_server_test = resolve_localhost_to_hostname(connection_server) + self.log.info(resolved_server_test) # test_address = self.address - test_address = "np04-srv-029" + # test_address = "np04-srv-029" + test_address = resolved_server_test + # this is one of the two minimal changes needed to get this working in general? if "://" not in test_address: test_address = "grpc://" + test_address From 59944672a5f5c1b7620678d5a33db81e7d25de49 Mon Sep 17 00:00:00 2001 From: Emir Muhammad Date: Thu, 4 Jun 2026 11:39:37 +0200 Subject: [PATCH 09/14] pawel push --- src/drunc/process_manager/process_manager_driver.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/drunc/process_manager/process_manager_driver.py b/src/drunc/process_manager/process_manager_driver.py index 4c6c33294..4c3fb4ee6 100644 --- a/src/drunc/process_manager/process_manager_driver.py +++ b/src/drunc/process_manager/process_manager_driver.py @@ -599,6 +599,10 @@ def check_port_conflicts( if session_dal.infrastructure_applications: # Check if the own application needs to be spawned, or if an externally managed one is in use (e.g. if using ehn1 connectivity service or integration tests.) connectivity_service_host: str = session_dal.connectivity_service.host connectivity_service_port = session_dal.connectivity_service.service.port + self.log.critical( + f"{connectivity_service_host=}, {connectivity_service_port=}" + ) + if not is_port_available( connectivity_service_host, connectivity_service_port ): From df9c2a097701c97994f2d5550a9d3f8e5e833818 Mon Sep 17 00:00:00 2001 From: Emir Muhammad Date: Fri, 5 Jun 2026 17:49:56 +0200 Subject: [PATCH 10/14] clean up comments --- src/drunc/apps/controller_shell.py | 1 - src/drunc/connectivity_service/client.py | 12 ++--- src/drunc/controller/controller_driver.py | 1 - src/drunc/controller/interface/shell.py | 6 +-- src/drunc/controller/interface/shell_utils.py | 16 ++----- src/drunc/process_manager/configuration.py | 2 - src/drunc/process_manager/oks_parser.py | 10 ---- .../process_manager/process_manager_driver.py | 47 ++----------------- 8 files changed, 14 insertions(+), 81 deletions(-) diff --git a/src/drunc/apps/controller_shell.py b/src/drunc/apps/controller_shell.py index 79068740e..5ff6ca7d0 100644 --- a/src/drunc/apps/controller_shell.py +++ b/src/drunc/apps/controller_shell.py @@ -14,7 +14,6 @@ def main() -> None: log = get_logger("controller_shell", rich_handler=True) log.error("[red bold]:fire::fire: Exception thrown :fire::fire:") log.exception(e) - # raise e exit(1) diff --git a/src/drunc/connectivity_service/client.py b/src/drunc/connectivity_service/client.py index 111b349c5..5e7eb124f 100644 --- a/src/drunc/connectivity_service/client.py +++ b/src/drunc/connectivity_service/client.py @@ -17,7 +17,7 @@ def __init__(self, session: str, address: str): # assume the simplest case here self.address = f"http://{address}" - self.log.error( + self.log.debug( f"Connectivity service address: {self.address}, session: {self.session}" ) @@ -41,16 +41,16 @@ def is_ready(self, timeout: int = 10): attempt += 1 elapsed = time.time() - start - self.log.info(f"Health check attempt {attempt} at {elapsed:.2f}s elapsed") - self.log.info(f"Polling address: {self.address}") + self.log.debug(f"Health check attempt {attempt} at {elapsed:.2f}s elapsed") + self.log.debug(f"Polling address: {self.address}") try: r = get(self.address) except Exception as e: - self.log.info(f"Polling failed with exception: {e}") + self.log.debug(f"Polling failed with exception: {e}") r = None # Request failed - service is NOT ready. if r is None or not r.ok: - self.log.info( + self.log.debug( f"Connectivity service not ready, retrying in {delay:.2f}s" ) time.sleep(delay) @@ -58,7 +58,7 @@ def is_ready(self, timeout: int = 10): delay = min(delay * 2, max_delay) # Request succeeded - service is ready. else: - self.log.info( + self.log.debug( f"Connectivity service ready after {attempt} attempts ({elapsed:.2f}s)" ) return True diff --git a/src/drunc/controller/controller_driver.py b/src/drunc/controller/controller_driver.py index 6522058fb..376530660 100644 --- a/src/drunc/controller/controller_driver.py +++ b/src/drunc/controller/controller_driver.py @@ -126,7 +126,6 @@ def describe( execute_on_all_subsequent_children_in_path: bool = True, timeout: int | float = 60, ) -> DescribeResponse: - # self.log.("in describe") request = DescribeRequest( target=target, execute_along_path=execute_along_path, diff --git a/src/drunc/controller/interface/shell.py b/src/drunc/controller/interface/shell.py index 401dd9744..5c71bde1c 100644 --- a/src/drunc/controller/interface/shell.py +++ b/src/drunc/controller/interface/shell.py @@ -53,18 +53,16 @@ def controller_shell(ctx, controller_address: str, log_level: str) -> None: get_root_logger(log_level) controller_shell_log = get_logger("controller.iface.shell", rich_handler=True) - controller_shell_log.info("Resetting the context instance address") + controller_shell_log.debug("Resetting the context instance address") ctx.obj.reset(address=controller_address) ctx.call_on_close(controller_cleanup_wrapper(ctx.obj)) desc = None - controller_shell_log.info( + controller_shell_log.debug( f"[green]{getpass.getuser()}[/green] connecting to the [green]controller[/green] through a [green]controller-shell[/green] via address [green]{controller_address}[/green]" ) try: - controller_shell_log.info("test 1") desc = controller_setup(ctx.obj, controller_address) - controller_shell_log.info("test 2") except ServerUnreachable as e: controller_shell_log.critical("Could not connect to the controller") controller_shell_log.exception( diff --git a/src/drunc/controller/interface/shell_utils.py b/src/drunc/controller/interface/shell_utils.py index 42e8a1572..3ffba7455 100644 --- a/src/drunc/controller/interface/shell_utils.py +++ b/src/drunc/controller/interface/shell_utils.py @@ -46,7 +46,7 @@ pack_to_any, unpack_any, ) -from drunc.utils.utils import format_name_for_cli, get_logger +from drunc.utils.utils import format_name_for_cli, get_logger, get_shared_rich_console log = get_logger("controller.iface.shell_utils") @@ -188,8 +188,7 @@ def __init__(self, ctx, refresh_per_second=2, *args, **kwargs) -> None: # Get the instance of the console that the logger is using with the rich handler # so that the progress bar can be rendered in the same console, and not mess up # the logs - # shared_console = get_shared_rich_console(self.ctx.log) - shared_console = None + shared_console = get_shared_rich_console(self.ctx.log) if shared_console: kwargs["console"] = shared_console @@ -198,7 +197,7 @@ def __init__(self, ctx, refresh_per_second=2, *args, **kwargs) -> None: def update_table(self): # The following debug log line will be used in an integration test to validate # that issue 817 does not appear again (rich table overriding the log entries) - # self.ctx.log.debug("Updating the status table...") + self.ctx.log.debug("Updating the status table...") statuses = self.ctx.get_driver("controller").status() descriptions = self.ctx.get_driver("controller").describe() self.table = get_status_table(statuses, descriptions) @@ -252,8 +251,6 @@ def controller_setup(ctx, controller_address): timeout = 60 - log.warning("into progrss") - with Progress( SpinnerColumn(), TextColumn("[progress.description]{task.description}"), @@ -271,29 +268,22 @@ def controller_setup(ctx, controller_address): start_time = time.time() while time.time() - start_time < timeout: progress.update(waiting, completed=time.time() - start_time) - log.warning("trying this thingy") try: - log.warning("getting desc") desc = ctx.get_driver("controller").describe().description - log.warning("desc done") stored_exception = None break except ServerUnreachable as e: - log.warning("yee hawe") stored_exception = e time.sleep(1) except Exception as e: - log.warning("weewoo") ctx.critical("Could not get the controller's status") ctx.critical(e) ctx.critical("Exiting.") ctx.terminate() raise e - log.warning(start_time) - log.info("survived progress") if stored_exception is not None: raise stored_exception diff --git a/src/drunc/process_manager/configuration.py b/src/drunc/process_manager/configuration.py index fa6e821cd..da9198722 100644 --- a/src/drunc/process_manager/configuration.py +++ b/src/drunc/process_manager/configuration.py @@ -149,8 +149,6 @@ def get_commandline_parameters( Ordered list of command-line arguments for process launch. """ runs_on = obj.runs_on.runs_on.id - # runs_on = "np04-srv-029.cern.ch" - control_service_port = -1 control_service_protocol = "" for svc in obj.exposes_service: diff --git a/src/drunc/process_manager/oks_parser.py b/src/drunc/process_manager/oks_parser.py index bdb4d99d2..5feb6ba50 100644 --- a/src/drunc/process_manager/oks_parser.py +++ b/src/drunc/process_manager/oks_parser.py @@ -179,16 +179,10 @@ def collect_apps( # Add controller for this segment to list of apps controller = segment_obj.controller - rc_env = defenv.copy() collect_variables(controller.application_environment, rc_env) rc_env["DUNEDAQ_APPLICATION_NAME"] = controller.id - host = controller.runs_on.runs_on.id - # okay fine if we change this to 29 that works.. - # but we will need this to be clean - # host = "np04-srv-029.cern.ch" - log.info(f"main host is {host}") tree_id_str = ".".join(map(str, tree_prefix)) apps.append( @@ -266,10 +260,6 @@ def collect_apps( ) log.debug(f"Collecting app {app.id} with args {args}") - # host = "np04-srv-029.cern.ch" - - log.info(f"app host is {host}") - data_path = get_writer_directory_path(app, log) if not data_path: log.debug(f"No data path found for app {app.id}") diff --git a/src/drunc/process_manager/process_manager_driver.py b/src/drunc/process_manager/process_manager_driver.py index 4c3fb4ee6..8446fb218 100644 --- a/src/drunc/process_manager/process_manager_driver.py +++ b/src/drunc/process_manager/process_manager_driver.py @@ -213,9 +213,6 @@ def boot( ) -> Iterator[ProcessInstanceList] | None: self.log.info(f"Booting session [green]{session_name}[/green]") - self.log.warning( - f"parameters: {conf_file=}, {conf_id=}, {user=}, {self.address=}" - ) # Assume oksconflibs if no framework is defined conf_file = f"oksconflibs:{conf_file}" if ":" not in conf_file else conf_file @@ -228,26 +225,15 @@ def boot( # Step 3 - check for port conflicts and update configuration/DAL as needed db, session_dal = self.check_port_conflicts(db, session_dal) - # Step 3.5 - modify the host mapping (explicitly!!) - # self.log.warning("prechange session_dal:\n%s", self._dump_session_dal(session_dal)) - - # session_dal = self.update_dal_host(session_dal) - - # self.log.warning("db dump:\n%s", self._dump_database(db)) - # self.log.warning("postchange session_dal:\n%s", self._dump_session_dal(session_dal)) - - self.log.info("step 4") # Step 4 - connect to the connection service csc, connection_server, connection_port = self._connect_to_service( session_dal, session_name ) - self.log.info(f"step 5 + {csc.address}") # Step 5 - track boot timings per host last_boot_on_host_at = {} previous_host = None - self.log.info("step 6") # Step 6: iterate over boot requests for request in self._convert_oks_to_boot_request( oks_conf=conf_file, @@ -257,8 +243,6 @@ def boot( override_logs=override_logs, **kwargs, ): - self.log.warning(request) - if not request: self.log.error("[red]No boot request was generated, ending boot.[/red]") return None @@ -269,11 +253,10 @@ def boot( f"Skipping connectivity service readiness check for application {request.process_description.metadata.name}" ) else: - self.log.info( + self.log.debug( f"Checking connectivity service readiness before booting application {request.process_description.metadata.name}" ) if csc and not csc.is_ready(timeout=10): - self.log.info("whoops its not ready?") raise DruncSetupException( "Connectivity service did not respond within timeout." ) @@ -306,7 +289,6 @@ def boot( ) handle_grpc_error(e) - self.log.info("step 7") # Step 7: discover segment root controller self._discover_controller( session_dal, session_name, csc, connection_server, connection_port @@ -341,8 +323,7 @@ def _collect_all_apps( apps = infra_apps + apps - self.log.warning("json jumps") - self.log.info(f"{json.dumps(apps, indent=4)}") + self.log.debug(f"{json.dumps(apps, indent=4)}") return apps @@ -393,11 +374,7 @@ def _build_boot_request( host_test = format_hostname(app["restriction"]) resolved_server_test = resolve_localhost_to_hostname(host_test) self.log.info(f"boot resolve {resolved_server_test}") - host = resolved_server_test - - # host = "np04-srv-029" #! GOD BLESS THIS WORKSS - # this is one of the two minimal changes needed to get this working in general? name = app["name"] exe = app["type"] @@ -599,10 +576,6 @@ def check_port_conflicts( if session_dal.infrastructure_applications: # Check if the own application needs to be spawned, or if an externally managed one is in use (e.g. if using ehn1 connectivity service or integration tests.) connectivity_service_host: str = session_dal.connectivity_service.host connectivity_service_port = session_dal.connectivity_service.service.port - self.log.critical( - f"{connectivity_service_host=}, {connectivity_service_port=}" - ) - if not is_port_available( connectivity_service_host, connectivity_service_port ): @@ -661,18 +634,12 @@ def _connect_to_service( self, session_dal: "conffwk.dal.Session", session_name: str ) -> ConnectivityServiceClient | None: if session_dal.connectivity_service: - self.log.info("we have connectivity service") - connection_server = session_dal.connectivity_service.host connection_port = session_dal.connectivity_service.service.port if connection_server == "localhost": - self.log.info("Apparently its localhost?") resolved_server_test = resolve_localhost_to_hostname(connection_server) - self.log.info(resolved_server_test) - # test_address = self.address - # test_address = "np04-srv-029" test_address = resolved_server_test # this is one of the two minimal changes needed to get this working in general? @@ -680,22 +647,14 @@ def _connect_to_service( test_address = "grpc://" + test_address resolved_server = urlparse(test_address).hostname - self.log.info( + self.log.debug( f"Resolved connection server 'localhost' to '{resolved_server}' to avoid K8s hairpinning." ) connection_server = resolved_server - self.log.info(f"connectivity service: {connection_server=}") - # Funnily enough this is the minimum amount of change needed...s - # so basically instead of trying to resolve the localhost hostname, resolve to whatever we are connecting to? - # connection_server = "np04-srv-028" client = ConnectivityServiceClient( session_name, f"{connection_server}:{connection_port}" ) - - self.log.info( - f"returning {client=}, {connection_server=}, {connection_port=}" - ) return client, connection_server, connection_port return None, None, None From 926814e83fce1cf9b7745e3d2fb859a375838f2f Mon Sep 17 00:00:00 2001 From: Emir Muhammad Date: Fri, 5 Jun 2026 17:52:47 +0200 Subject: [PATCH 11/14] Clean up even more --- .../process_manager/process_manager_driver.py | 83 ------------------- 1 file changed, 83 deletions(-) diff --git a/src/drunc/process_manager/process_manager_driver.py b/src/drunc/process_manager/process_manager_driver.py index 8446fb218..155798263 100644 --- a/src/drunc/process_manager/process_manager_driver.py +++ b/src/drunc/process_manager/process_manager_driver.py @@ -56,89 +56,6 @@ class ProcessManagerDriver: controller_address = "" - def _dump_oks_value(self, value): - if value is None or isinstance(value, (str, int, float, bool)): - return value - - if isinstance(value, (list, tuple, set)): - return [self._dump_oks_value(item) for item in value] - - if hasattr(value, "className"): - class_name = value.className() - if class_name == "VariableSet": - return { - "class": class_name, - "contains": self._dump_oks_value(getattr(value, "contains", [])), - } - - if class_name == "Variable": - return { - "class": class_name, - "name": getattr(value, "name", None), - "value": getattr(value, "value", None), - } - - snapshot = { - "class": class_name, - "id": getattr(value, "id", None), - } - - field_map = { - "Session": [ - "log_path", - "rte_script", - "environment", - "segment", - "connectivity_service", - "infrastructure_applications", - "disabled", - ], - "Segment": ["controller", "segments", "applications", "disabled"], - "Application": [ - "application_name", - "application_environment", - "runs_on", - "log_path", - "data_path", - ], - "Controller": [ - "application_name", - "application_environment", - "runs_on", - "exposes_service", - "fsm", - "log_path", - ], - "ConnectivityService": ["host", "service"], - "Service": ["host", "port"], - "Resource": ["id"], - } - - for field_name in field_map.get( - class_name, ["host", "service", "port", "name", "value"] - ): - try: - field_value = getattr(value, field_name) - except Exception: - continue - snapshot[field_name] = self._dump_oks_value(field_value) - - return snapshot - - if isinstance(value, dict): - return {key: self._dump_oks_value(item) for key, item in value.items()} - - return repr(value) - - def _dump_database(self, db: conffwk.Configuration) -> str: - configuration_file = db.active_database - full_db_path = get_full_db_path(configuration_file) - with open(full_db_path, encoding="utf-8") as config_file: - return config_file.read() - - def _dump_session_dal(self, session_dal: "conffwk.dal.Session") -> str: - return json.dumps(self._dump_oks_value(session_dal), indent=2, sort_keys=False) - def __init__(self, address: str, token: Token): self.log = get_logger("process_manager_driver", rich_handler=True) self.address = address From b54a79c6faea552d87fb7b7a3dfa3b47305d3c01 Mon Sep 17 00:00:00 2001 From: Emir Muhammad Date: Mon, 8 Jun 2026 11:02:04 +0200 Subject: [PATCH 12/14] block boot on existing sessions --- src/drunc/process_manager/interface/commands.py | 14 ++++++-------- src/drunc/unified_shell/commands.py | 12 ++++++------ 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/src/drunc/process_manager/interface/commands.py b/src/drunc/process_manager/interface/commands.py index eefbbb1d5..b2644b288 100644 --- a/src/drunc/process_manager/interface/commands.py +++ b/src/drunc/process_manager/interface/commands.py @@ -45,18 +45,16 @@ def boot( ) -> None: log = get_logger("process_manager.shell") log_pm_cmd(obj) - processes = obj.get_driver("process_manager").ps(ProcessQuery(user=user)) + processes = obj.get_driver("process_manager").ps( + ProcessQuery(user=user, session=session_name) + ) if len(processes.values) > 0: - log.info( - f"Note that there are already {len(processes.values)} processes running." + click.confirm( + f"You already have {len(processes.values)} processes running for {session_name}, are you sure you want to boot a session?", + abort=True, ) - # click.confirm( - # f"You already have {len(processes.values)} processes running, are you sure you want to boot a session?", - # abort=True, - # ) - log.debug( f"Booting session {session_name} with boot configuration file {configuration_file} and id {configuration_id}, requested by user {user}" ) diff --git a/src/drunc/unified_shell/commands.py b/src/drunc/unified_shell/commands.py index be093c134..7dc1bc950 100644 --- a/src/drunc/unified_shell/commands.py +++ b/src/drunc/unified_shell/commands.py @@ -58,12 +58,12 @@ def boot( override_logs_boot = obj.override_logs else: override_logs_boot = override_logs - # if len(processes.values) > 0: - # log.error( - # f"Cannot boot: session {session_name} already has {len(processes.values)} processes running. " - # "Please terminate the existing session first." - # ) - # return + if len(processes.values) > 0: + log.error( + f"Cannot boot: session {session_name} already has {len(processes.values)} processes running. " + "Please terminate the existing session first." + ) + return try: results = obj.get_driver("process_manager").boot( From a26a9b2858c4016363908d3943d5a154473020aa Mon Sep 17 00:00:00 2001 From: Emir Muhammad Date: Mon, 8 Jun 2026 12:50:42 +0200 Subject: [PATCH 13/14] Cleanup --- .../process_manager/process_manager_driver.py | 25 +++++++------------ 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/src/drunc/process_manager/process_manager_driver.py b/src/drunc/process_manager/process_manager_driver.py index 155798263..aa38f314a 100644 --- a/src/drunc/process_manager/process_manager_driver.py +++ b/src/drunc/process_manager/process_manager_driver.py @@ -288,10 +288,10 @@ def _build_boot_request( override_logs: bool, pwd: str, ) -> BootRequest: - host_test = format_hostname(app["restriction"]) - resolved_server_test = resolve_localhost_to_hostname(host_test) - self.log.info(f"boot resolve {resolved_server_test}") - host = resolved_server_test + # Run mapping to physical hostname to enable multi host usage + host = resolve_localhost_to_hostname(format_hostname(app["restriction"])) + self.log.info(f"boot resolve {host}") # keep this until big PR gets merged + # this is one of the two minimal changes needed to get this working in general? name = app["name"] exe = app["type"] @@ -422,10 +422,6 @@ def update_connectivity_port_dal( if item.name == "CONNECTION_PORT": item.value = new_port - def update_dal_host(self, session_dal): - session_dal.connectivity_service.host = "np04-srv-029" - return session_dal - def check_port_conflicts( self, db: conffwk.Configuration, session_dal: "conffwk.dal.Session" ) -> tuple[conffwk.Configuration, "conffwk.dal.Session"]: @@ -555,15 +551,12 @@ def _connect_to_service( connection_port = session_dal.connectivity_service.service.port if connection_server == "localhost": - resolved_server_test = resolve_localhost_to_hostname(connection_server) - - test_address = resolved_server_test - - # this is one of the two minimal changes needed to get this working in general? - if "://" not in test_address: - test_address = "grpc://" + test_address + # resolve localhost to hostname to enable multi host + resolved_address = resolve_localhost_to_hostname(connection_server) + if "://" not in resolved_address: + resolved_address = "grpc://" + resolved_address - resolved_server = urlparse(test_address).hostname + resolved_server = urlparse(resolved_address).hostname self.log.debug( f"Resolved connection server 'localhost' to '{resolved_server}' to avoid K8s hairpinning." ) From e26bc6d98b427f53dfc781fd025429758f0a5763 Mon Sep 17 00:00:00 2001 From: Emir Muhammad Date: Mon, 8 Jun 2026 15:06:39 +0200 Subject: [PATCH 14/14] Fix pytest --- src/drunc/process_manager/interface/commands.py | 2 +- tests/process_manager/conftest.py | 6 ++++-- tests/process_manager/interface/test_commands.py | 5 +++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/drunc/process_manager/interface/commands.py b/src/drunc/process_manager/interface/commands.py index b2644b288..b5a479086 100644 --- a/src/drunc/process_manager/interface/commands.py +++ b/src/drunc/process_manager/interface/commands.py @@ -289,7 +289,7 @@ def logs_impl( log = get_logger("process_manager.shell") # TODO: MOVE BACK TO DEBUG BEFORE MERGE # THIS IS USEFUL FOR TESTING THOUGH - log.error(f"Running logs with query {query}") + log.debug(f"Running logs with query {query}") log_req = LogRequest( how_far=how_far, query=query, diff --git a/tests/process_manager/conftest.py b/tests/process_manager/conftest.py index 6a2ba4bfd..78aed2525 100644 --- a/tests/process_manager/conftest.py +++ b/tests/process_manager/conftest.py @@ -7,6 +7,8 @@ to be back in line with druncschema definitions. """ +import socket + import google.protobuf.any_pb2 import pytest from druncschema.description_pb2 import Description @@ -36,7 +38,7 @@ def app_data(): Provides a mock application dictionary with required keys. """ return { - "restriction": "localhost", + "restriction": socket.gethostname(), "name": "TestApp", "type": "binary", "args": ["--arg1"], @@ -55,7 +57,7 @@ def bootrequest(app_data): user="test_user", session="session1", name=app_data["name"], - hostname="localhost", + hostname=socket.gethostname(), tree_id=app_data["tree_id"], ), executable_and_arguments=[{"exec": "binary", "args": ["--arg1"]}], diff --git a/tests/process_manager/interface/test_commands.py b/tests/process_manager/interface/test_commands.py index 6ba1e10ad..f1a5c5e4b 100644 --- a/tests/process_manager/interface/test_commands.py +++ b/tests/process_manager/interface/test_commands.py @@ -237,8 +237,9 @@ def test_boot_exiting_processes_abort(boot_arguments): # check that 'boot' was never called mock_driver.boot.assert_not_called() + # conf-id-123 from session name in this file assert ( - "You already have 2 processes running, are you sure you want to boot a session?" + "You already have 2 processes running for conf-id-123, are you sure you want to boot a session?" in result.output ) @@ -267,7 +268,7 @@ def test_boot_exiting_processes_user_confirm(boot_arguments): mock_driver.boot.assert_called() assert ( - "You already have 2 processes running, are you sure you want to boot a session?" + "You already have 2 processes running for conf-id-123, are you sure you want to boot a session?" in result.output )