Skip to content
Draft
Show file tree
Hide file tree
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
1 change: 1 addition & 0 deletions docs/developer/hyperion/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ Documentation specific for the Hyperion module within MX-Bluesky
.. toctree::
:caption: How-to Guides
:maxdepth: 1

how-to/debug-k8s
how-to/update-panda-ioc

Expand Down
3 changes: 2 additions & 1 deletion helm/hyperion/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ spec:
. /app/mx-bluesky/.venv/bin/activate
hyperion --mode supervisor \
--client-config /etc/hyperion/client_config.yaml \
--supervisor-config /etc/hyperion/supervisor_config.yaml
--supervisor-config /etc/hyperion/supervisor_config.yaml \
--baton-name HyperionK8s \
{{- if .Values.supervisor.enableDebugging }} \
--debug-port {{ .Values.supervisor.debugPort }}
{{- end }}
Expand Down
4 changes: 3 additions & 1 deletion src/mx_bluesky/hyperion/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
LOGGER,
do_default_logging_setup,
)
from mx_bluesky.hyperion.baton_handler import run_forever
from mx_bluesky.hyperion.baton_handler import run_forever, set_hyperion_baton_user
from mx_bluesky.hyperion.in_process_runner import InProcessRunner
from mx_bluesky.hyperion.parameters.cli import (
HyperionArgs,
Expand All @@ -40,6 +40,8 @@ def initialise_globals(args: HyperionArgs):
LOGGER.info(f"Hyperion launched with args:{argv}")
if args.debug_port:
enable_debugging(args.wait_for_debug_attach, args.debug_port)
# Apply a different name for our baton
set_hyperion_baton_user(args.baton_name)
alerting.set_alerting_service(LoggingAlertService(CONST.GRAYLOG_STREAM_ID))


Expand Down
15 changes: 10 additions & 5 deletions src/mx_bluesky/hyperion/baton_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,16 @@
setup_devices,
)

HYPERION_USER = "Hyperion"
_hyperion_baton_user = "Hyperion"
NO_USER = "None"
COUNTDOWN_THRESHOLD_SECONDS = 600


def set_hyperion_baton_user(new_user: str):
global _hyperion_baton_user
_hyperion_baton_user = new_user


def run_forever(runner: PlanRunner):
try:
while True:
Expand Down Expand Up @@ -77,7 +82,7 @@ def run_udc_when_requested(context: BlueskyContext, runner: PlanRunner):
def acquire_baton() -> MsgGenerator:
yield from _wait_for_hyperion_requested(baton)
LOGGER.debug("Hyperion is now current baton holder.")
yield from bps.abs_set(baton.current_user, HYPERION_USER)
yield from bps.abs_set(baton.current_user, _hyperion_baton_user)

def collect() -> MsgGenerator:
"""
Expand Down Expand Up @@ -161,7 +166,7 @@ def _wait_for_hyperion_requested(baton: Baton):
sleep_per_check = 0.1
while True:
requested_user = yield from bps.rd(baton.requested_user)
if requested_user == HYPERION_USER:
if requested_user == _hyperion_baton_user:
LOGGER.debug("Baton requested for Hyperion")
break
yield from bps.sleep(sleep_per_check)
Expand Down Expand Up @@ -205,7 +210,7 @@ def _raise_udc_completed_alert(alert_service: AlertService):

def _is_requesting_baton(baton: Baton) -> MsgGenerator:
requested_user = yield from bps.rd(baton.requested_user)
return requested_user == HYPERION_USER
return requested_user == _hyperion_baton_user


def _get_baton(context: BlueskyContext) -> Baton:
Expand All @@ -224,7 +229,7 @@ def _unrequest_baton(baton: Baton) -> MsgGenerator[str]:
The previously requested user, or NO_USER if no user was already requested.
"""
requested_user = yield from bps.rd(baton.requested_user)
if requested_user == HYPERION_USER:
if requested_user == _hyperion_baton_user:
LOGGER.debug("Hyperion no longer requesting baton")
yield from bps.abs_set(baton.requested_user, NO_USER)
return NO_USER
Expand Down
7 changes: 7 additions & 0 deletions src/mx_bluesky/hyperion/parameters/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class HyperionArgs(CommonArgs):
mode: HyperionMode = HyperionMode.UDC
client_config: str | None = None
supervisor_config: str | None = None
baton_name: str = "Hyperion"


@dataclass(kw_only=True)
Expand Down Expand Up @@ -99,6 +100,11 @@ def parse_cli_args() -> HyperionArgs:
"--supervisor-config",
help="Specify the supervisor bluesky context configuration file.",
)
parser.add_argument(
"--baton-name",
default="Hyperion",
help="Specify the baton string that identifies this instance of hyperion",
)
args = parser.parse_args()
return HyperionArgs(
dev_mode=args.dev or False,
Expand All @@ -107,4 +113,5 @@ def parse_cli_args() -> HyperionArgs:
client_config=args.client_config,
debug_port=args.debug_port,
wait_for_debug_attach=args.wait_for_attach,
baton_name=args.baton_name,
)
6 changes: 3 additions & 3 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@
_get_logging_dirs,
do_default_logging_setup,
)
from mx_bluesky.hyperion.baton_handler import HYPERION_USER
from mx_bluesky.hyperion.baton_handler import _hyperion_baton_user
from mx_bluesky.hyperion.parameters.device_composites import (
HyperionFlyScanXRayCentreComposite,
)
Expand Down Expand Up @@ -411,8 +411,8 @@ def backlight():
@pytest.fixture
def baton():
baton = i03.baton.build(connect_immediately=True, mock=True)
set_mock_value(baton.requested_user, HYPERION_USER)
set_mock_value(baton.current_user, HYPERION_USER)
set_mock_value(baton.requested_user, _hyperion_baton_user)
set_mock_value(baton.current_user, _hyperion_baton_user)
return baton


Expand Down
6 changes: 3 additions & 3 deletions tests/system_tests/hyperion/test_main_udc.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

from mx_bluesky.common.utils.context import find_device_in_context
from mx_bluesky.hyperion.__main__ import main
from mx_bluesky.hyperion.baton_handler import HYPERION_USER
from mx_bluesky.hyperion.baton_handler import _hyperion_baton_user


@pytest.fixture(autouse=True)
Expand All @@ -17,7 +17,7 @@ def patch_setup_devices():
def patched_setup_devices(context: BlueskyContext, dev_mode: bool):
setup_devices(context, True)
# reapply requested user to the newly created fake baton
baton_with_requested_user(context, HYPERION_USER)
baton_with_requested_user(context, _hyperion_baton_user)

# Patch setup_devices to patch the baton again when it is re-created
with (
Expand All @@ -40,7 +40,7 @@ def patch_udc_default_state():


def baton_with_requested_user(
bluesky_context: BlueskyContext, user: str = HYPERION_USER
bluesky_context: BlueskyContext, user: str = _hyperion_baton_user
) -> Baton:
baton = find_device_in_context(bluesky_context, "baton", Baton)
set_mock_value(baton.requested_user, user)
Expand Down
24 changes: 12 additions & 12 deletions tests/unit_tests/hyperion/test_baton_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@
from mx_bluesky.common.utils.log import LOGGER
from mx_bluesky.hyperion._plan_runner_params import RobotUnload, UDCCleanup, Wait
from mx_bluesky.hyperion.baton_handler import (
HYPERION_USER,
NO_USER,
_hyperion_baton_user,
_initialise_udc,
run_forever,
run_udc_when_requested,
Expand Down Expand Up @@ -84,7 +84,7 @@ def patched_setup_devices(context: BlueskyContext, dev_mode: bool):
except ValueError:
# No baton, setup devices and configure it
setup_devices(context, True)
baton_with_requested_user(context, HYPERION_USER)
baton_with_requested_user(context, _hyperion_baton_user)

with (
patch(
Expand Down Expand Up @@ -140,13 +140,13 @@ def mock_load_module(module, **kwargs):
mock=True,
)
synchrotron_with_countdown(context)
baton_with_requested_user(context, HYPERION_USER)
baton_with_requested_user(context, _hyperion_baton_user)
yield context


@pytest.fixture
def bluesky_context_with_sim_run_engine(sim_run_engine: RunEngineSimulator):
baton_requested_user = HYPERION_USER
baton_requested_user = _hyperion_baton_user
countdown = 1200

# Baton for sim run engine
Expand Down Expand Up @@ -224,7 +224,7 @@ def single_collection_agamemnon_request_then_wait_forever(


def baton_with_requested_user(
bluesky_context: BlueskyContext, user: str = HYPERION_USER
bluesky_context: BlueskyContext, user: str = _hyperion_baton_user
) -> Baton:
baton = find_device_in_context(bluesky_context, "baton", Baton)
set_mock_value(baton.requested_user, user)
Expand Down Expand Up @@ -280,7 +280,7 @@ def test_loop_until_hyperion_requested(

def set_hyperion_requested(*args):
yield from bps.null()
set_mock_value(baton.requested_user, HYPERION_USER)
set_mock_value(baton.requested_user, _hyperion_baton_user)

mock_calls: list[Any] = [MagicMock()] * (number_of_sleep_calls - 1)
mock_calls.append(set_hyperion_requested())
Expand All @@ -303,7 +303,7 @@ def test_when_hyperion_requested_then_hyperion_set_to_current_user(

run_udc_when_requested(bluesky_context, udc_runner)

assert get_mock_put(baton.current_user).mock_calls[0] == call(HYPERION_USER)
assert get_mock_put(baton.current_user).mock_calls[0] == call(_hyperion_baton_user)


@patch("mx_bluesky.hyperion.in_process_runner.move_to_udc_default_state")
Expand All @@ -325,7 +325,7 @@ def test_when_hyperion_requested_then_default_state_and_collection_run(


async def _assert_baton_released(baton: Baton):
assert await baton.requested_user.get_value() != HYPERION_USER
assert await baton.requested_user.get_value() != _hyperion_baton_user
assert get_mock_put(baton.current_user).mock_calls[-1] == call(NO_USER)


Expand Down Expand Up @@ -608,7 +608,7 @@ async def take_requested_baton_away_then_wait_for_release_then_re_request():
await sleep(SLEEP_FAST_SPIN_WAIT_S)
assert len(mock_create_parameters_from_agamemnon.mock_calls) == 1
# Re-request baton, wait until hyperion picks up baton
await baton.requested_user.set(HYPERION_USER)
await baton.requested_user.set(_hyperion_baton_user)
while udc_runner.current_status != Status.BUSY:
await sleep(SLEEP_FAST_SPIN_WAIT_S)
finally:
Expand Down Expand Up @@ -651,7 +651,7 @@ async def wait_for_baton_release_then_re_request():
while await baton.current_user.get_value() != NO_USER:
await sleep(SLEEP_FAST_SPIN_WAIT_S)
assert len(mock_create_parameters_from_agamemnon.mock_calls) == 2
await baton.requested_user.set(HYPERION_USER)
await baton.requested_user.set(_hyperion_baton_user)
while udc_runner.current_status != Status.BUSY:
await sleep(SLEEP_FAST_SPIN_WAIT_S)
finally:
Expand Down Expand Up @@ -727,7 +727,7 @@ async def error_with_command_then_resume():
baton = find_device_in_context(udc_runner.context, "baton", Baton)
while await baton.current_user.get_value() != NO_USER:
await sleep(SLEEP_FAST_SPIN_WAIT_S)
await baton.requested_user.set(HYPERION_USER)
await baton.requested_user.set(_hyperion_baton_user)
while udc_runner.current_status != Status.BUSY: # type: ignore
await sleep(SLEEP_FAST_SPIN_WAIT_S)
finally:
Expand Down Expand Up @@ -773,7 +773,7 @@ async def release_baton_and_check_commissioning_signal_set():
try:
mock_set_commissioning_signal.assert_not_called()
LOGGER.debug("Set requested user")
set_mock_value(baton.requested_user, HYPERION_USER)
set_mock_value(baton.requested_user, _hyperion_baton_user)
LOGGER.debug("Wait for create_parameters call")
while len(parent.create_parameters_from_agamemnon.mock_calls) == 0:
await sleep(SLEEP_FAST_SPIN_WAIT_S)
Expand Down
18 changes: 16 additions & 2 deletions tests/unit_tests/hyperion/test_main_system.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
initialise_globals,
main,
)
from mx_bluesky.hyperion.baton_handler import HYPERION_USER
from mx_bluesky.hyperion.baton_handler import _hyperion_baton_user
from mx_bluesky.hyperion.parameters.cli import (
HyperionArgs,
HyperionMode,
Expand Down Expand Up @@ -180,6 +180,20 @@ def test_hyperion_does_not_enable_debugging_if_not_specified(
mock_enable_debugging.assert_not_called()


@patch("sys.argv", new=["hyperion", "--mode", "udc", "--baton-name", "HyperionK8s"])
@patch("mx_bluesky.hyperion.__main__.do_default_logging_setup", MagicMock())
@patch("mx_bluesky.hyperion.__main__.create_server_for_udc", MagicMock())
@patch("mx_bluesky.hyperion.__main__.run_forever", MagicMock())
@patch("mx_bluesky.hyperion.__main__.set_hyperion_baton_user")
def test_hyperion_sets_hyperion_baton_user_if_specified(
mock_set_baton_user: MagicMock,
mock_setup_context: MagicMock,
):
main()

mock_set_baton_user.assert_called_once_with("HyperionK8s")


@patch("sys.argv", new=["hyperion", "--mode", "udc"])
@patch("mx_bluesky.hyperion.__main__.do_default_logging_setup", MagicMock())
@patch("mx_bluesky.hyperion.__main__.run_forever", MagicMock())
Expand Down Expand Up @@ -308,7 +322,7 @@ def wait_for_udc_to_start_then_send_sigterm():
context = plan_runner.context
baton = find_device_in_context(context, "baton", Baton)
synchrotron = find_device_in_context(context, "synchrotron", Synchrotron)
set_mock_value(baton.requested_user, HYPERION_USER)
set_mock_value(baton.requested_user, _hyperion_baton_user)
set_mock_value(synchrotron.machine_user_countdown, 1200)
while len(mock_create_parameters_from_agamemnon.mock_calls) == 0:
sleep(0.2)
Expand Down
Loading