Skip to content
Merged
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
63 changes: 46 additions & 17 deletions uit/gui_tools/submit.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@
import param
import panel as pn

from .file_browser import HpcFileBrowser, create_file_browser, get_js_loading_code, FileSelector
from .file_browser import HpcFileBrowser, create_file_browser, get_js_loading_code
from .utils import HpcBase, HpcConfigurable
from ..uit import QUEUES
from .file_browser import AsyncHpcPath
from ..pbs_script import NODE_TYPES, factors, PbsScript
from ..job import PbsJob

Expand Down Expand Up @@ -74,21 +75,50 @@ class PbsScriptInputs(HpcBase):
wall_time_maxes = None
node_maxes = None

base_dir = param.Selector(
label="Base Directory",
doc="Base directory that the job's working directory path will be created in.\n\n"
"**Note:** by default the job's working directory is: "
f"`<BASE_DIRECTORY>/{PbsJob.DEFAULT_JOB_LABEL}/<JOB_NAME>.<TIMESTAMP>/`",
)
use_namespace = param.Boolean(label="Use Namespace Path", default=True)
namespace_path = param.String(label="Namespace Path", doc="Path created within the Base Directory")
execution_dir = param.String(label="Execution Directory", doc="Full Directory path in which job(s) will be run.")

def __init__(self, **params):
super().__init__(**params)
self.workdir = FileSelector(
title="Base Directory",
show_browser=False,
help_text=(
"Base directory that the job's working directory path will be created in.\n\n"
"**Note:** by default the job's working directory is: "
f"`<BASE_DIRECTORY>/{PbsJob.DEFAULT_JOB_LABEL}/<JOB_NAME>.<TIMESTAMP>/`"
),
options = pn.widgets.Button(icon="menu-2", align="center", margin=(15, 0, 0, 0))
options.on_click(self.toggle_exec_dir_widgets)
self.exec_dir_wg_box = pn.layout.WidgetBox(
self.param.base_dir, self.param.use_namespace, self.param.namespace_path, visible=False
)

@param.depends("uit_client", watch=True)
def set_file_browser(self):
self.workdir.file_browser = create_file_browser(self.uit_client, patterns=[])
self.execution_dir_col = pn.Column(
pn.Row(pn.widgets.TextInput.from_param(self.param.execution_dir, disabled=True, width=500), options),
self.exec_dir_wg_box,
)

async def populate_base_dir_selector(self):
options = {}
if AsyncHpcPath(self.uit_client.WORKDIR, uit_client=self.uit_client).exists():
options["WORKDIR"] = self.uit_client.WORKDIR
workdir2 = await self.uit_client.env.get_environmental_variable("WORKDIR2")
if workdir2 and AsyncHpcPath(self.uit_client.WORKDIR2, uit_client=self.uit_client).exists():
options["WORKDIR2"] = self.uit_client.WORKDIR2
self.param.base_dir.objects = options
self.base_dir = options["WORKDIR"]

def default_namespace_path(self):
return f"{self.workflow_group}/{self.workflow_name}"

@param.depends("use_namespace", "base_dir", "namespace_path", watch=True)
def update_job_dir(self):
namespace = self.namespace_path + "/" if self.use_namespace else ""
self.exec_dir_wg_box[-1] = self.param.namespace_path if self.use_namespace else None
self.execution_dir = f"{self.base_dir}/{namespace}<JOB_NAME>.<TIMESTAMP>/"

def toggle_exec_dir_widgets(self, _):
self.exec_dir_wg_box.visible = not self.exec_dir_wg_box.visible

@staticmethod
def get_default(value, objects):
Expand All @@ -98,14 +128,13 @@ def get_default(value, objects):
async def update_hpc_connection_dependent_defaults(self):
if not self.uit_client.connected:
return

queues_stats = await self.await_if_async(self.uit_client.get_raw_queue_stats())

self.subproject_usage = await self.await_if_async(self.uit_client.show_usage(as_df=True))
subprojects = self.subproject_usage["Subproject"].to_list()
self.param.hpc_subproject.objects = subprojects
self.hpc_subproject = self.get_default(self.hpc_subproject, subprojects)
self.workdir.file_path = self.uit_client.WORKDIR.as_posix()
await self.populate_base_dir_selector()
self.param.node_type.objects = list(NODE_TYPES[self.uit_client.system].keys())
self.node_type = self.get_default(self.node_type, self.param.node_type.objects)
self.param.queue.objects = await self.await_if_async(self.uit_client.get_queues())
Expand All @@ -119,6 +148,7 @@ async def update_hpc_connection_dependent_defaults(self):
)
self.max_wall_time = self.wall_time_maxes[self.queue]
self.nodes = round(self.DEFAULT_PROCESSES_PER_JOB / self.processes_per_node)
self.namespace_path = self.default_namespace_path()

@param.depends("queue", watch=True)
def update_queue_depended_bounds(self):
Expand Down Expand Up @@ -220,8 +250,7 @@ def pbs_options_view(self):
),
pn.Column(
self.param.hpc_subproject,
self.workdir,
self.param.node_type,
self.execution_dir_col,
pn.widgets.Spinner.from_param(self.param.nodes),
self.param.processes_per_node,
self.param.wall_time,
Expand Down Expand Up @@ -522,7 +551,7 @@ def job(self):
script=self.pbs_script,
client=self.uit_client,
workspace=self.user_workspace,
base_dir=self.workdir.file_path,
base_dir=self.base_dir,
)
return self._job

Expand Down
9 changes: 8 additions & 1 deletion uit/job.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,11 @@ def __init__(
home_input_files=None,
archive_input_files=None,
base_dir=None,
namespace_path=None,
description=None,
metadata=None,
post_processing_script=None,
use_namespace=True,
):
self.script = script
self.post_processing_script = post_processing_script
Expand All @@ -52,6 +54,8 @@ def __init__(
self._post_processing_job_id = None
self._remote_workspace_id = None
self._remote_workspace = None
self.use_namespace = use_namespace
self.namespace_path = namespace_path

def __repr__(self):
return f"<{self.__class__.__name__} name={self.name} id={self.job_id}>"
Expand Down Expand Up @@ -116,7 +120,10 @@ def remote_workspace_suffix(self):
str: Suffix
"""
if not self._remote_workspace:
self._remote_workspace = PurePosixPath(self.label, f"{self.name}.{self.remote_workspace_id}")
if self.use_namespace:
self._remote_workspace = PurePosixPath(self.namespace_path, f"{self.name}.{self.remote_workspace_id}")
else:
self._remote_workspace = PurePosixPath(f"{self.name}.{self.remote_workspace_id}")
return self._remote_workspace

@property
Expand Down