sl-shared-assets 2.0.0__py3-none-any.whl → 3.0.0rc1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of sl-shared-assets might be problematic. Click here for more details.
- sl_shared_assets/__init__.py +9 -5
- sl_shared_assets/__init__.pyi +4 -4
- sl_shared_assets/cli.py +270 -20
- sl_shared_assets/cli.pyi +50 -5
- sl_shared_assets/data_classes/configuration_data.py +20 -0
- sl_shared_assets/data_classes/configuration_data.pyi +14 -0
- sl_shared_assets/data_classes/session_data.py +7 -11
- sl_shared_assets/data_classes/session_data.pyi +1 -2
- sl_shared_assets/server/__init__.py +2 -2
- sl_shared_assets/server/__init__.pyi +5 -2
- sl_shared_assets/server/job.py +229 -1
- sl_shared_assets/server/job.pyi +111 -0
- sl_shared_assets/server/server.py +365 -31
- sl_shared_assets/server/server.pyi +144 -15
- sl_shared_assets/tools/__init__.py +2 -1
- sl_shared_assets/tools/__init__.pyi +2 -0
- sl_shared_assets/tools/packaging_tools.py +1 -2
- sl_shared_assets/tools/project_management_tools.py +150 -34
- sl_shared_assets/tools/project_management_tools.pyi +46 -3
- {sl_shared_assets-2.0.0.dist-info → sl_shared_assets-3.0.0rc1.dist-info}/METADATA +5 -6
- sl_shared_assets-3.0.0rc1.dist-info/RECORD +36 -0
- {sl_shared_assets-2.0.0.dist-info → sl_shared_assets-3.0.0rc1.dist-info}/entry_points.txt +2 -0
- sl_shared_assets-2.0.0.dist-info/RECORD +0 -36
- {sl_shared_assets-2.0.0.dist-info → sl_shared_assets-3.0.0rc1.dist-info}/WHEEL +0 -0
- {sl_shared_assets-2.0.0.dist-info → sl_shared_assets-3.0.0rc1.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
from .job import
|
|
1
|
+
from .job import (
|
|
2
|
+
Job as Job,
|
|
3
|
+
JupyterJob as JupyterJob,
|
|
4
|
+
)
|
|
2
5
|
from .server import (
|
|
3
6
|
Server as Server,
|
|
4
7
|
ServerCredentials as ServerCredentials,
|
|
5
8
|
generate_server_credentials as generate_server_credentials,
|
|
6
9
|
)
|
|
7
10
|
|
|
8
|
-
__all__ = ["Server", "ServerCredentials", "generate_server_credentials", "Job"]
|
|
11
|
+
__all__ = ["Server", "ServerCredentials", "generate_server_credentials", "Job", "JupyterJob"]
|
sl_shared_assets/server/job.py
CHANGED
|
@@ -1,13 +1,51 @@
|
|
|
1
1
|
"""This module provides the core Job class, used as the starting point for all SLURM-managed job executed on lab compute
|
|
2
2
|
server(s). Specifically, the Job class acts as a wrapper around the SLURM configuration and specific logic of each
|
|
3
3
|
job. During runtime, Server class interacts with input job objects to manage their transfer and execution on the
|
|
4
|
-
remote servers.
|
|
4
|
+
remote servers.
|
|
5
|
+
|
|
6
|
+
Since version 3.0.0, this module also provides the specialized JupyterJob class used to launch remote Jupyter
|
|
7
|
+
notebook servers.
|
|
8
|
+
"""
|
|
5
9
|
|
|
6
10
|
# noinspection PyProtectedMember
|
|
11
|
+
import re
|
|
7
12
|
from pathlib import Path
|
|
8
13
|
import datetime
|
|
14
|
+
from dataclasses import dataclass
|
|
9
15
|
|
|
16
|
+
# noinspection PyProtectedMember
|
|
10
17
|
from simple_slurm import Slurm # type: ignore
|
|
18
|
+
from ataraxis_base_utilities import LogLevel, console
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@dataclass
|
|
22
|
+
class _JupyterConnectionInfo:
|
|
23
|
+
"""Stores the data used to establish the connection with a Jupyter notebook server running under SLURM control on a
|
|
24
|
+
remote Sun lab server.
|
|
25
|
+
|
|
26
|
+
More specifically, this class is used to transfer the connection metadata collected on the remote server back to
|
|
27
|
+
the local machine that requested the server to be established.
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
compute_node: str
|
|
31
|
+
"""The hostname of the compute node where Jupyter is running."""
|
|
32
|
+
|
|
33
|
+
port: int
|
|
34
|
+
"""The port number on which Jupyter is listening for communication. Usually, this is the default port 8888 or 9999.
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
token: str
|
|
38
|
+
"""The authentication token for the Jupyter server. This token is used to authenticate the user when establishing
|
|
39
|
+
communication with the Jupyter server."""
|
|
40
|
+
|
|
41
|
+
@property
|
|
42
|
+
def localhost_url(self) -> str:
|
|
43
|
+
"""Returns the localhost URL for connecting to the server.
|
|
44
|
+
|
|
45
|
+
To use this URL, first set up an SSH tunnel to the server via the specific Jupyter communication port and the
|
|
46
|
+
remote server access credentials.
|
|
47
|
+
"""
|
|
48
|
+
return f"http://localhost:{self.port}/?token={self.token}"
|
|
11
49
|
|
|
12
50
|
|
|
13
51
|
class Job:
|
|
@@ -138,3 +176,193 @@ class Job:
|
|
|
138
176
|
|
|
139
177
|
# Returns the script content to caller as a string
|
|
140
178
|
return fixed_script_content
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
class JupyterJob(Job):
|
|
182
|
+
"""Specialized Job instance designed to launch a Jupyter notebook server on SLURM.
|
|
183
|
+
|
|
184
|
+
This class extends the base Job class to include Jupyter-specific configuration and commands for starting a
|
|
185
|
+
notebook server in a SLURM environment. Using this specialized job allows users to set up remote Jupyter servers
|
|
186
|
+
while still benefitting from SLURM's job management and fair airtime policies.
|
|
187
|
+
|
|
188
|
+
Notes:
|
|
189
|
+
Jupyter servers directly compete for resources with headless data processing jobs. Therefore, it is important
|
|
190
|
+
to minimize the resource footprint and the runtime of each Jupyter server, if possible.
|
|
191
|
+
|
|
192
|
+
Args:
|
|
193
|
+
job_name: The descriptive name of the Jupyter SLURM job to be created. Primarily, this name is used in terminal
|
|
194
|
+
printouts to identify the job to human operators.
|
|
195
|
+
output_log: The absolute path to the .txt file on the processing server, where to store the standard output
|
|
196
|
+
data of the job.
|
|
197
|
+
error_log: The absolute path to the .txt file on the processing server, where to store the standard error
|
|
198
|
+
data of the job.
|
|
199
|
+
working_directory: The absolute path to the directory where temporary job files will be stored. During runtime,
|
|
200
|
+
classes from this library use that directory to store files such as the job's shell script. All such files
|
|
201
|
+
are automatically removed from the directory at the end of a non-errors runtime.
|
|
202
|
+
conda_environment: The name of the conda environment to activate on the server before running the job logic. The
|
|
203
|
+
environment should contain the necessary Python packages and CLIs to support running the job's logic. For
|
|
204
|
+
Jupyter jobs, this necessarily includes the Jupyter notebook and jupyterlab packages.
|
|
205
|
+
port: The connection port number for Jupyter server. Do not change the default value unless you know what you
|
|
206
|
+
are doing, as the server has most common communication ports closed for security reasons.
|
|
207
|
+
notebook_directory: The directory to use as Jupyter's root. During runtime, Jupyter will only have access to
|
|
208
|
+
items stored in or under this directory. For most runtimes, this should be set to the user's root data or
|
|
209
|
+
working directory.
|
|
210
|
+
cpus_to_use: The number of CPUs to allocate to the Jupyter server. Keep this value as small as possible to avoid
|
|
211
|
+
interfering with headless data processing jobs.
|
|
212
|
+
ram_gb: The amount of RAM, in GB, to allocate to the Jupyter server. Keep this value as small as possible to
|
|
213
|
+
avoid interfering with headless data processing jobs.
|
|
214
|
+
time_limit: The maximum Jupyter server uptime, in minutes. Set this to the expected duration of your jupyter
|
|
215
|
+
session.
|
|
216
|
+
jupyter_args: Stores additional arguments to pass to jupyter notebook initialization command.
|
|
217
|
+
|
|
218
|
+
Attributes:
|
|
219
|
+
port: Stores the connection port of the managed Jupyter server.
|
|
220
|
+
notebook_dir: Stores the absolute path to the directory used as Jupyter's root, relative to the remote server
|
|
221
|
+
root.
|
|
222
|
+
connection_info: Stores the JupyterConnectionInfo instance after the Jupyter server is instantiated.
|
|
223
|
+
host: Stores the hostname of the remote server.
|
|
224
|
+
user: Stores the username used to connect with the remote server.
|
|
225
|
+
connection_info_file: The absolute path to the file that stores connection information, relative to the remote
|
|
226
|
+
server root.
|
|
227
|
+
_command: Stores the shell command for launching the Jupyter server.
|
|
228
|
+
"""
|
|
229
|
+
|
|
230
|
+
def __init__(
|
|
231
|
+
self,
|
|
232
|
+
job_name: str,
|
|
233
|
+
output_log: Path,
|
|
234
|
+
error_log: Path,
|
|
235
|
+
working_directory: Path,
|
|
236
|
+
conda_environment: str,
|
|
237
|
+
notebook_directory: Path,
|
|
238
|
+
port: int = 9999, # Defaults to using port 9999
|
|
239
|
+
cpus_to_use: int = 2, # Defaults to 2 CPU cores
|
|
240
|
+
ram_gb: int = 32, # Defaults to 32 GB of RAM
|
|
241
|
+
time_limit: int = 120, # Defaults to 2 hours of runtime (120 minutes)
|
|
242
|
+
jupyter_args: str = "",
|
|
243
|
+
) -> None:
|
|
244
|
+
# Initializes parent Job class
|
|
245
|
+
super().__init__(
|
|
246
|
+
job_name=job_name,
|
|
247
|
+
output_log=output_log,
|
|
248
|
+
error_log=error_log,
|
|
249
|
+
working_directory=working_directory,
|
|
250
|
+
conda_environment=conda_environment,
|
|
251
|
+
cpus_to_use=cpus_to_use,
|
|
252
|
+
ram_gb=ram_gb,
|
|
253
|
+
time_limit=time_limit,
|
|
254
|
+
)
|
|
255
|
+
|
|
256
|
+
# Saves important jupyter configuration parameters to class attributes
|
|
257
|
+
self.port = port
|
|
258
|
+
self.notebook_dir = notebook_directory
|
|
259
|
+
|
|
260
|
+
# Similar to job ID, these attributes initialize to None and are reconfigured as part of the job submission
|
|
261
|
+
# process.
|
|
262
|
+
self.connection_info: _JupyterConnectionInfo | None = None
|
|
263
|
+
self.host: str | None = None
|
|
264
|
+
self.user: str | None = None
|
|
265
|
+
|
|
266
|
+
# Resolves the server-side path to the jupyter server connection info file.
|
|
267
|
+
self.connection_info_file = working_directory.joinpath(f"{job_name}_connection.txt")
|
|
268
|
+
|
|
269
|
+
# Builds Jupyter launch command.
|
|
270
|
+
self._build_jupyter_command(jupyter_args)
|
|
271
|
+
|
|
272
|
+
def _build_jupyter_command(self, jupyter_args: str) -> None:
|
|
273
|
+
"""Builds the command to launch Jupyter notebook server on the remote Sun lab server."""
|
|
274
|
+
|
|
275
|
+
# Gets the hostname of the compute node and caches it in the connection data file. Also caches the port name.
|
|
276
|
+
self.add_command('echo "COMPUTE_NODE: $(hostname)" > {}'.format(self.connection_info_file))
|
|
277
|
+
self.add_command('echo "PORT: {}" >> {}'.format(self.port, self.connection_info_file))
|
|
278
|
+
|
|
279
|
+
# Generates a random access token for security and caches it in the connection data file.
|
|
280
|
+
self.add_command("TOKEN=$(openssl rand -hex 24)")
|
|
281
|
+
self.add_command('echo "TOKEN: $TOKEN" >> {}'.format(self.connection_info_file))
|
|
282
|
+
|
|
283
|
+
# Builds Jupyter startup command.
|
|
284
|
+
jupyter_cmd = [
|
|
285
|
+
"jupyter lab",
|
|
286
|
+
"--no-browser",
|
|
287
|
+
f"--port={self.port}",
|
|
288
|
+
"--ip=0.0.0.0", # Listen on all interfaces
|
|
289
|
+
"--ServerApp.allow_origin='*'", # Allow connections from SSH tunnel
|
|
290
|
+
"--ServerApp.allow_remote_access=True", # Enable remote access
|
|
291
|
+
"--ServerApp.disable_check_xsrf=True", # Helps with proxy connections
|
|
292
|
+
f"--ServerApp.root_dir={self.notebook_dir}", # Root directory (not notebook-dir)
|
|
293
|
+
"--IdentityProvider.token=$TOKEN", # Token authentication
|
|
294
|
+
]
|
|
295
|
+
|
|
296
|
+
# Adds any additional arguments.
|
|
297
|
+
if jupyter_args:
|
|
298
|
+
jupyter_cmd.append(jupyter_args)
|
|
299
|
+
|
|
300
|
+
# Adds resolved jupyter command to the list of job commands.
|
|
301
|
+
jupyter_cmd_str = " ".join(jupyter_cmd)
|
|
302
|
+
self.add_command(jupyter_cmd_str)
|
|
303
|
+
|
|
304
|
+
def parse_connection_info(self, info_file: Path) -> None:
|
|
305
|
+
"""Parses the connection information file created by the Jupyter job on the server.
|
|
306
|
+
|
|
307
|
+
Use this method to parse the connection file fetched from the server to finalize setting up the Jupyter
|
|
308
|
+
server job.
|
|
309
|
+
|
|
310
|
+
Args:
|
|
311
|
+
info_file: The path to the .txt file generated by the remote server that stores the Jupyter connection
|
|
312
|
+
information to be parsed.
|
|
313
|
+
"""
|
|
314
|
+
|
|
315
|
+
with open(info_file, "r") as f:
|
|
316
|
+
content = f.read()
|
|
317
|
+
|
|
318
|
+
# Extracts information using regex
|
|
319
|
+
compute_node_match = re.search(r"COMPUTE_NODE: (.+)", content)
|
|
320
|
+
port_match = re.search(r"PORT: (\d+)", content)
|
|
321
|
+
token_match = re.search(r"TOKEN: (.+)", content)
|
|
322
|
+
|
|
323
|
+
if not all([compute_node_match, port_match, token_match]):
|
|
324
|
+
message = f"Could not parse connection information file for the Jupyter server job with id {self.job_id}."
|
|
325
|
+
console.error(message, ValueError)
|
|
326
|
+
|
|
327
|
+
# Stores extracted data inside connection_info attribute as a JupyterConnectionInfo instance.
|
|
328
|
+
self.connection_info = _JupyterConnectionInfo(
|
|
329
|
+
compute_node=compute_node_match.group(1).strip(), # type: ignore
|
|
330
|
+
port=int(port_match.group(1)), # type: ignore
|
|
331
|
+
token=token_match.group(1).strip(), # type: ignore
|
|
332
|
+
)
|
|
333
|
+
|
|
334
|
+
def print_connection_info(self) -> None:
|
|
335
|
+
"""Constructs and displays the command to set up the SSH tunnel to the server and the link to the localhost
|
|
336
|
+
server view in the terminal.
|
|
337
|
+
|
|
338
|
+
The SSH command should be used via a separate terminal or subprocess call to establish the secure SSH tunnel to
|
|
339
|
+
the Jupyter server. Once the SSH tunnel is established, the printed localhost url can be used to view the
|
|
340
|
+
server from the local machine.
|
|
341
|
+
"""
|
|
342
|
+
|
|
343
|
+
# If connection information is not available, there is nothing to print
|
|
344
|
+
if self.connection_info is None:
|
|
345
|
+
console.echo(
|
|
346
|
+
message=(
|
|
347
|
+
f"No connection information is available for the job {self.job_name}, which indicates that the job "
|
|
348
|
+
f"has not been submitted to the server. Submit the job for execution to the remote Sun lab server "
|
|
349
|
+
f"to generate the connection information"
|
|
350
|
+
),
|
|
351
|
+
level=LogLevel.WARNING,
|
|
352
|
+
)
|
|
353
|
+
return # No connection information available, so does not proceed with printing.
|
|
354
|
+
|
|
355
|
+
# Prints generic connection details to terminal
|
|
356
|
+
console.echo(f"Jupyter is running on: {self.connection_info.compute_node}")
|
|
357
|
+
console.echo(f"Port: {self.connection_info.port}")
|
|
358
|
+
console.echo(f"Token: {self.connection_info.token}")
|
|
359
|
+
|
|
360
|
+
# Constructs and displays the SSH tunnel command and the localhost url for connecting to the server
|
|
361
|
+
tunnel_cmd = (
|
|
362
|
+
f"ssh -N -L {self.connection_info.port}:{self.connection_info.compute_node}:{self.connection_info.port} "
|
|
363
|
+
f"{self.user}@{self.host}"
|
|
364
|
+
)
|
|
365
|
+
localhost_url = f"http://localhost:{self.connection_info.port}/?token={self.connection_info.token}"
|
|
366
|
+
print(f"\nTo access locally, run this in a terminal:")
|
|
367
|
+
print(tunnel_cmd)
|
|
368
|
+
print(f"\nThen open: {localhost_url}")
|
sl_shared_assets/server/job.pyi
CHANGED
|
@@ -1,8 +1,29 @@
|
|
|
1
1
|
from pathlib import Path
|
|
2
|
+
from dataclasses import dataclass
|
|
2
3
|
|
|
3
4
|
from _typeshed import Incomplete
|
|
4
5
|
from simple_slurm import Slurm
|
|
5
6
|
|
|
7
|
+
@dataclass
|
|
8
|
+
class _JupyterConnectionInfo:
|
|
9
|
+
"""Stores the data used to establish the connection with a Jupyter notebook server running under SLURM control on a
|
|
10
|
+
remote Sun lab server.
|
|
11
|
+
|
|
12
|
+
More specifically, this class is used to transfer the connection metadata collected on the remote server back to
|
|
13
|
+
the local machine that requested the server to be established.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
compute_node: str
|
|
17
|
+
port: int
|
|
18
|
+
token: str
|
|
19
|
+
@property
|
|
20
|
+
def localhost_url(self) -> str:
|
|
21
|
+
"""Returns the localhost URL for connecting to the server.
|
|
22
|
+
|
|
23
|
+
To use this URL, first set up an SSH tunnel to the server via the specific Jupyter communication port and the
|
|
24
|
+
remote server access credentials.
|
|
25
|
+
"""
|
|
26
|
+
|
|
6
27
|
class Job:
|
|
7
28
|
"""Aggregates the data of a single SLURM-managed job to be executed on the Sun lab BioHPC cluster.
|
|
8
29
|
|
|
@@ -92,3 +113,93 @@ class Job:
|
|
|
92
113
|
executed on the remote compute server. Do not call this method manually unless you know what you are doing.
|
|
93
114
|
The returned string is safe to dump into a .sh (shell script) file and move to the BioHPC server for execution.
|
|
94
115
|
"""
|
|
116
|
+
|
|
117
|
+
class JupyterJob(Job):
|
|
118
|
+
"""Specialized Job instance designed to launch a Jupyter notebook server on SLURM.
|
|
119
|
+
|
|
120
|
+
This class extends the base Job class to include Jupyter-specific configuration and commands for starting a
|
|
121
|
+
notebook server in a SLURM environment. Using this specialized job allows users to set up remote Jupyter servers
|
|
122
|
+
while still benefitting from SLURM's job management and fair airtime policies.
|
|
123
|
+
|
|
124
|
+
Notes:
|
|
125
|
+
Jupyter servers directly compete for resources with headless data processing jobs. Therefore, it is important
|
|
126
|
+
to minimize the resource footprint and the runtime of each Jupyter server, if possible.
|
|
127
|
+
|
|
128
|
+
Args:
|
|
129
|
+
job_name: The descriptive name of the Jupyter SLURM job to be created. Primarily, this name is used in terminal
|
|
130
|
+
printouts to identify the job to human operators.
|
|
131
|
+
output_log: The absolute path to the .txt file on the processing server, where to store the standard output
|
|
132
|
+
data of the job.
|
|
133
|
+
error_log: The absolute path to the .txt file on the processing server, where to store the standard error
|
|
134
|
+
data of the job.
|
|
135
|
+
working_directory: The absolute path to the directory where temporary job files will be stored. During runtime,
|
|
136
|
+
classes from this library use that directory to store files such as the job's shell script. All such files
|
|
137
|
+
are automatically removed from the directory at the end of a non-errors runtime.
|
|
138
|
+
conda_environment: The name of the conda environment to activate on the server before running the job logic. The
|
|
139
|
+
environment should contain the necessary Python packages and CLIs to support running the job's logic. For
|
|
140
|
+
Jupyter jobs, this necessarily includes the Jupyter notebook and jupyterlab packages.
|
|
141
|
+
port: The connection port number for Jupyter server. Do not change the default value unless you know what you
|
|
142
|
+
are doing, as the server has most common communication ports closed for security reasons.
|
|
143
|
+
notebook_directory: The directory to use as Jupyter's root. During runtime, Jupyter will only have access to
|
|
144
|
+
items stored in or under this directory. For most runtimes, this should be set to the user's root data or
|
|
145
|
+
working directory.
|
|
146
|
+
cpus_to_use: The number of CPUs to allocate to the Jupyter server. Keep this value as small as possible to avoid
|
|
147
|
+
interfering with headless data processing jobs.
|
|
148
|
+
ram_gb: The amount of RAM, in GB, to allocate to the Jupyter server. Keep this value as small as possible to
|
|
149
|
+
avoid interfering with headless data processing jobs.
|
|
150
|
+
time_limit: The maximum Jupyter server uptime, in minutes. Set this to the expected duration of your jupyter
|
|
151
|
+
session.
|
|
152
|
+
jupyter_args: Stores additional arguments to pass to jupyter notebook initialization command.
|
|
153
|
+
|
|
154
|
+
Attributes:
|
|
155
|
+
port: Stores the connection port of the managed Jupyter server.
|
|
156
|
+
notebook_dir: Stores the absolute path to the directory used as Jupyter's root, relative to the remote server
|
|
157
|
+
root.
|
|
158
|
+
connection_info: Stores the JupyterConnectionInfo instance after the Jupyter server is instantiated.
|
|
159
|
+
host: Stores the hostname of the remote server.
|
|
160
|
+
user: Stores the username used to connect with the remote server.
|
|
161
|
+
connection_info_file: The absolute path to the file that stores connection information, relative to the remote
|
|
162
|
+
server root.
|
|
163
|
+
_command: Stores the shell command for launching the Jupyter server.
|
|
164
|
+
"""
|
|
165
|
+
|
|
166
|
+
port: Incomplete
|
|
167
|
+
notebook_dir: Incomplete
|
|
168
|
+
connection_info: _JupyterConnectionInfo | None
|
|
169
|
+
host: str | None
|
|
170
|
+
user: str | None
|
|
171
|
+
connection_info_file: Incomplete
|
|
172
|
+
def __init__(
|
|
173
|
+
self,
|
|
174
|
+
job_name: str,
|
|
175
|
+
output_log: Path,
|
|
176
|
+
error_log: Path,
|
|
177
|
+
working_directory: Path,
|
|
178
|
+
conda_environment: str,
|
|
179
|
+
notebook_directory: Path,
|
|
180
|
+
port: int = 9999,
|
|
181
|
+
cpus_to_use: int = 2,
|
|
182
|
+
ram_gb: int = 32,
|
|
183
|
+
time_limit: int = 120,
|
|
184
|
+
jupyter_args: str = "",
|
|
185
|
+
) -> None: ...
|
|
186
|
+
def _build_jupyter_command(self, jupyter_args: str) -> None:
|
|
187
|
+
"""Builds the command to launch Jupyter notebook server on the remote Sun lab server."""
|
|
188
|
+
def parse_connection_info(self, info_file: Path) -> None:
|
|
189
|
+
"""Parses the connection information file created by the Jupyter job on the server.
|
|
190
|
+
|
|
191
|
+
Use this method to parse the connection file fetched from the server to finalize setting up the Jupyter
|
|
192
|
+
server job.
|
|
193
|
+
|
|
194
|
+
Args:
|
|
195
|
+
info_file: The path to the .txt file generated by the remote server that stores the Jupyter connection
|
|
196
|
+
information to be parsed.
|
|
197
|
+
"""
|
|
198
|
+
def print_connection_info(self) -> None:
|
|
199
|
+
"""Constructs and displays the command to set up the SSH tunnel to the server and the link to the localhost
|
|
200
|
+
server view in the terminal.
|
|
201
|
+
|
|
202
|
+
The SSH command should be used via a separate terminal or subprocess call to establish the secure SSH tunnel to
|
|
203
|
+
the Jupyter server. Once the SSH tunnel is established, the printed localhost url can be used to view the
|
|
204
|
+
server from the local machine.
|
|
205
|
+
"""
|