-
Notifications
You must be signed in to change notification settings - Fork 70
feat: auto-select farm and queue when only one is available #1015
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
base: mainline
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -51,6 +51,10 @@ | |
| __config_file_path = None | ||
| __config_mtime = None | ||
|
|
||
| # Setting name constants | ||
| _SETTING_FARM_ID = "defaults.farm_id" | ||
|
Check failure on line 55 in src/deadline/client/config/config_file.py
|
||
| _SETTING_QUEUE_ID = "defaults.queue_id" | ||
|
Check failure on line 56 in src/deadline/client/config/config_file.py
|
||
Check noticeCode scanning / CodeQL Unused global variable Note
The global variable '_SETTING_QUEUE_ID' is not used.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed |
||
|
|
||
| # This value defines the AWS Deadline Cloud settings structure. For each named setting, | ||
| # it stores: | ||
| # "default" - The default value. | ||
|
|
@@ -76,21 +80,21 @@ | |
| "is_path": True, | ||
| "description": "The directory in which to place the job submission history for this AWS profile name.", | ||
| }, | ||
| "defaults.farm_id": { | ||
| _SETTING_FARM_ID: { | ||
| "default": "", | ||
| "depend": "defaults.aws_profile_name", | ||
| "section_format": "{}", | ||
| "description": "The Farm ID to use by default.", | ||
| }, | ||
| "settings.storage_profile_id": { | ||
| "default": "", | ||
| "depend": "defaults.farm_id", | ||
| "depend": _SETTING_FARM_ID, | ||
| "section_format": "{}", | ||
| "description": "The storage profile that this workstation conforms to. It specifies where shared file systems are mounted, and where named job attachments should go.", | ||
| }, | ||
| "defaults.queue_id": { | ||
| _SETTING_QUEUE_ID: { | ||
| "default": "", | ||
| "depend": "defaults.farm_id", | ||
| "depend": _SETTING_FARM_ID, | ||
| "section_format": "{}", | ||
| "description": "The Queue ID to use by default.", | ||
| }, | ||
|
|
@@ -121,7 +125,7 @@ | |
| }, | ||
| "defaults.job_attachments_file_system": { | ||
| "default": "COPIED", | ||
| "depend": "defaults.farm_id", | ||
| "depend": _SETTING_FARM_ID, | ||
| "description": "The file system mode to use for job attachments when running jobs. COPIED means to download a copy of the attachment data, VIRTUAL means to use a virtual file system for lazy loading.", | ||
| }, | ||
| "settings.s3_max_pool_connections": { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,10 +9,11 @@ | |
| import os | ||
| import sys | ||
| import json | ||
| import threading as _threading | ||
| from typing import Any, Dict, Optional, Protocol | ||
| import yaml | ||
|
|
||
| from qtpy.QtCore import QSize, Qt # pylint: disable=import-error | ||
| from qtpy.QtCore import QSize, Qt, Signal as _Signal # pylint: disable=import-error | ||
| from qtpy.QtGui import QKeyEvent # pylint: disable=import-error | ||
| from qtpy.QtWidgets import ( # pylint: disable=import-error; type: ignore | ||
| QApplication, | ||
|
|
@@ -36,6 +37,8 @@ | |
| from ..deadline_authentication_status import DeadlineAuthenticationStatus | ||
| from .._utils import block_signals, tr | ||
| from ...config import get_setting, set_setting, config_file | ||
| from ...config.config_file import _SETTING_FARM_ID | ||
| from ...config.config_file import _SETTING_QUEUE_ID | ||
| from ...exceptions import UserInitiatedCancel, NonValidInputError | ||
| from ...job_bundle import create_job_history_bundle_dir | ||
| from ...job_bundle.parameters import JobParameter | ||
|
|
@@ -104,6 +107,8 @@ class SubmitJobToDeadlineDialog(QDialog): | |
| submitter_info (SubmitterInfo): Information related to the submitter window and application it's running in | ||
| """ | ||
|
|
||
| _auto_select_complete = _Signal() | ||
|
|
||
| def __init__( | ||
| self, | ||
| *, | ||
|
|
@@ -229,6 +234,7 @@ def _build_ui( | |
| self.deadline_authentication_status.api_availability_changed.connect( | ||
| self.refresh_deadline_settings | ||
| ) | ||
| self._auto_select_complete.connect(self.refresh_deadline_settings) | ||
|
|
||
| # Refresh the submit button enable state once queue parameter status changes | ||
| self.shared_job_settings.valid_parameters.connect(self._set_submit_button_state) | ||
|
|
@@ -257,8 +263,8 @@ def _set_submit_button_state(self): | |
| # Enable/disable the Submit button based on whether the | ||
| # AWS Deadline Cloud API is accessible and the farm+queue are configured. | ||
| api_available = self.deadline_authentication_status.api_availability is True | ||
| farm_configured = get_setting("defaults.farm_id") != "" | ||
| queue_configured = get_setting("defaults.queue_id") != "" | ||
| farm_configured = get_setting(_SETTING_FARM_ID) != "" | ||
| queue_configured = get_setting(_SETTING_QUEUE_ID) != "" | ||
| queue_valid = self.shared_job_settings.is_queue_valid() | ||
|
|
||
| enable = api_available and farm_configured and queue_configured and queue_valid | ||
|
|
@@ -295,6 +301,7 @@ def _set_submit_button_state(self): | |
| self.submit_button.setToolTip("") | ||
|
|
||
| def refresh_deadline_settings(self): | ||
| self._auto_select_defaults() | ||
| self._set_submit_button_state() | ||
|
|
||
| self.shared_job_settings.deadline_cloud_settings_box.refresh_setting_controls( | ||
|
|
@@ -303,6 +310,51 @@ def refresh_deadline_settings(self): | |
| # If necessary, this reloads the queue parameters | ||
| self.shared_job_settings.refresh_queue_parameters() | ||
|
|
||
| def _auto_select_defaults(self): | ||
| """Auto-select farm/queue in a background thread if only one is available.""" | ||
| if self.deadline_authentication_status.api_availability is not True: | ||
| return | ||
| if get_setting(_SETTING_FARM_ID) and get_setting(_SETTING_QUEUE_ID): | ||
| return | ||
| if getattr(self, "_auto_select_in_progress", False): | ||
| return | ||
| self._auto_select_in_progress = True | ||
|
Comment on lines
+319
to
+321
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: There's a theoretical race window between the flag check and set, but given this is triggered by user actions with natural delays, it's unlikely to be hit in practice. No action needed unless you want to be |
||
|
|
||
| _threading.Thread(target=self._do_auto_select, daemon=True).start() | ||
|
rickrams marked this conversation as resolved.
|
||
|
|
||
| def _do_auto_select(self): | ||
| """Background worker that auto-selects farm/queue if only one exists.""" | ||
| try: | ||
| farm_changed = self._try_auto_select_farm() | ||
| queue_changed = self._try_auto_select_queue() | ||
| if farm_changed or queue_changed: | ||
| self._auto_select_complete.emit() | ||
| except Exception: | ||
| logger.debug("Auto-select defaults failed", exc_info=True) | ||
| finally: | ||
| self._auto_select_in_progress = False | ||
|
|
||
| def _try_auto_select_farm(self) -> bool: | ||
| if get_setting(_SETTING_FARM_ID): | ||
| return False | ||
| farms = api.list_farms().get("farms", []) | ||
| if len(farms) == 1: | ||
| set_setting(_SETTING_FARM_ID, farms[0]["farmId"]) | ||
| logger.info("Auto-selected farm: %s", farms[0]["farmId"]) | ||
| return True | ||
| return False | ||
|
|
||
| def _try_auto_select_queue(self) -> bool: | ||
| if not get_setting(_SETTING_FARM_ID) or get_setting(_SETTING_QUEUE_ID): | ||
| return False | ||
| farm_id = get_setting(_SETTING_FARM_ID) | ||
| queues = api.list_queues(farmId=farm_id).get("queues", []) | ||
| if len(queues) == 1: | ||
| set_setting(_SETTING_QUEUE_ID, queues[0]["queueId"]) | ||
| logger.info("Auto-selected queue: %s", queues[0]["queueId"]) | ||
| return True | ||
| return False | ||
|
|
||
| def keyPressEvent(self, event: QKeyEvent) -> None: | ||
| """ | ||
| Override to capture any enter/return key presses so that the Submit | ||
|
|
||
Check notice
Code scanning / CodeQL
Unused global variable Note
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed