parsl 2024.8.5__py3-none-any.whl → 2024.8.19__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.
- parsl/channels/__init__.py +1 -4
- parsl/channels/oauth_ssh/oauth_ssh.py +12 -4
- parsl/channels/ssh/ssh.py +17 -7
- parsl/channels/ssh_il/ssh_il.py +13 -3
- parsl/dataflow/dflow.py +1 -1
- parsl/executors/high_throughput/executor.py +18 -27
- parsl/executors/high_throughput/interchange.py +4 -0
- parsl/executors/high_throughput/mpi_executor.py +23 -2
- parsl/executors/high_throughput/mpi_prefix_composer.py +5 -4
- parsl/executors/taskvine/executor.py +2 -0
- parsl/executors/workqueue/executor.py +2 -0
- parsl/monitoring/db_manager.py +36 -49
- parsl/monitoring/monitoring.py +9 -5
- parsl/monitoring/remote.py +4 -4
- parsl/monitoring/router.py +16 -18
- parsl/providers/__init__.py +0 -4
- parsl/providers/ad_hoc/ad_hoc.py +6 -2
- parsl/tests/configs/local_adhoc.py +2 -2
- parsl/tests/test_htex/test_resource_spec_validation.py +40 -0
- parsl/tests/test_htex/test_zmq_binding.py +2 -1
- parsl/tests/test_mpi_apps/test_bad_mpi_config.py +29 -14
- parsl/tests/test_mpi_apps/test_mpi_mode_enabled.py +16 -8
- parsl/tests/test_mpi_apps/test_mpiex.py +2 -3
- parsl/tests/test_mpi_apps/test_resource_spec.py +39 -41
- parsl/tests/test_providers/test_local_provider.py +6 -5
- parsl/version.py +1 -1
- {parsl-2024.8.5.data → parsl-2024.8.19.data}/scripts/interchange.py +4 -0
- {parsl-2024.8.5.dist-info → parsl-2024.8.19.dist-info}/METADATA +5 -3
- {parsl-2024.8.5.dist-info → parsl-2024.8.19.dist-info}/RECORD +36 -47
- parsl/configs/ad_hoc.py +0 -38
- parsl/tests/configs/ad_hoc_cluster_htex.py +0 -35
- parsl/tests/configs/htex_ad_hoc_cluster.py +0 -26
- parsl/tests/configs/swan_htex.py +0 -43
- parsl/tests/integration/test_channels/test_scp_1.py +0 -45
- parsl/tests/integration/test_channels/test_ssh_1.py +0 -40
- parsl/tests/integration/test_channels/test_ssh_errors.py +0 -46
- parsl/tests/integration/test_channels/test_ssh_file_transport.py +0 -41
- parsl/tests/integration/test_channels/test_ssh_interactive.py +0 -24
- parsl/tests/manual_tests/test_ad_hoc_htex.py +0 -49
- parsl/tests/manual_tests/test_oauth_ssh.py +0 -13
- parsl/tests/test_mpi_apps/test_mpi_mode_disabled.py +0 -47
- {parsl-2024.8.5.data → parsl-2024.8.19.data}/scripts/exec_parsl_function.py +0 -0
- {parsl-2024.8.5.data → parsl-2024.8.19.data}/scripts/parsl_coprocess.py +0 -0
- {parsl-2024.8.5.data → parsl-2024.8.19.data}/scripts/process_worker_pool.py +0 -0
- {parsl-2024.8.5.dist-info → parsl-2024.8.19.dist-info}/LICENSE +0 -0
- {parsl-2024.8.5.dist-info → parsl-2024.8.19.dist-info}/WHEEL +0 -0
- {parsl-2024.8.5.dist-info → parsl-2024.8.19.dist-info}/entry_points.txt +0 -0
- {parsl-2024.8.5.dist-info → parsl-2024.8.19.dist-info}/top_level.txt +0 -0
parsl/monitoring/router.py
CHANGED
@@ -1,15 +1,16 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
3
|
import logging
|
4
|
+
import multiprocessing.queues as mpq
|
4
5
|
import os
|
5
6
|
import pickle
|
6
|
-
import queue
|
7
7
|
import socket
|
8
8
|
import threading
|
9
9
|
import time
|
10
10
|
from multiprocessing.synchronize import Event
|
11
|
-
from typing import Optional, Tuple
|
11
|
+
from typing import Optional, Tuple
|
12
12
|
|
13
|
+
import typeguard
|
13
14
|
import zmq
|
14
15
|
|
15
16
|
from parsl.log_utils import set_file_logger
|
@@ -31,13 +32,12 @@ class MonitoringRouter:
|
|
31
32
|
|
32
33
|
monitoring_hub_address: str = "127.0.0.1",
|
33
34
|
logdir: str = ".",
|
34
|
-
run_id: str,
|
35
35
|
logging_level: int = logging.INFO,
|
36
36
|
atexit_timeout: int = 3, # in seconds
|
37
|
-
priority_msgs:
|
38
|
-
node_msgs:
|
39
|
-
block_msgs:
|
40
|
-
resource_msgs:
|
37
|
+
priority_msgs: mpq.Queue,
|
38
|
+
node_msgs: mpq.Queue,
|
39
|
+
block_msgs: mpq.Queue,
|
40
|
+
resource_msgs: mpq.Queue,
|
41
41
|
exit_event: Event,
|
42
42
|
):
|
43
43
|
""" Initializes a monitoring configuration class.
|
@@ -71,7 +71,6 @@ class MonitoringRouter:
|
|
71
71
|
|
72
72
|
self.hub_address = hub_address
|
73
73
|
self.atexit_timeout = atexit_timeout
|
74
|
-
self.run_id = run_id
|
75
74
|
|
76
75
|
self.loop_freq = 10.0 # milliseconds
|
77
76
|
|
@@ -172,7 +171,6 @@ class MonitoringRouter:
|
|
172
171
|
msg_0 = (msg, 0)
|
173
172
|
|
174
173
|
if msg[0] == MessageType.NODE_INFO:
|
175
|
-
msg[1]['run_id'] = self.run_id
|
176
174
|
self.node_msgs.put(msg_0)
|
177
175
|
elif msg[0] == MessageType.RESOURCE_INFO:
|
178
176
|
self.resource_msgs.put(msg_0)
|
@@ -205,12 +203,14 @@ class MonitoringRouter:
|
|
205
203
|
|
206
204
|
|
207
205
|
@wrap_with_logs
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
206
|
+
@typeguard.typechecked
|
207
|
+
def router_starter(*,
|
208
|
+
comm_q: mpq.Queue,
|
209
|
+
exception_q: mpq.Queue,
|
210
|
+
priority_msgs: mpq.Queue,
|
211
|
+
node_msgs: mpq.Queue,
|
212
|
+
block_msgs: mpq.Queue,
|
213
|
+
resource_msgs: mpq.Queue,
|
214
214
|
exit_event: Event,
|
215
215
|
|
216
216
|
hub_address: str,
|
@@ -218,8 +218,7 @@ def router_starter(comm_q: "queue.Queue[Union[Tuple[int, int], str]]",
|
|
218
218
|
zmq_port_range: Tuple[int, int],
|
219
219
|
|
220
220
|
logdir: str,
|
221
|
-
logging_level: int
|
222
|
-
run_id: str) -> None:
|
221
|
+
logging_level: int) -> None:
|
223
222
|
setproctitle("parsl: monitoring router")
|
224
223
|
try:
|
225
224
|
router = MonitoringRouter(hub_address=hub_address,
|
@@ -227,7 +226,6 @@ def router_starter(comm_q: "queue.Queue[Union[Tuple[int, int], str]]",
|
|
227
226
|
zmq_port_range=zmq_port_range,
|
228
227
|
logdir=logdir,
|
229
228
|
logging_level=logging_level,
|
230
|
-
run_id=run_id,
|
231
229
|
priority_msgs=priority_msgs,
|
232
230
|
node_msgs=node_msgs,
|
233
231
|
block_msgs=block_msgs,
|
parsl/providers/__init__.py
CHANGED
@@ -1,6 +1,3 @@
|
|
1
|
-
# Workstation Provider
|
2
|
-
from parsl.providers.ad_hoc.ad_hoc import AdHocProvider
|
3
|
-
|
4
1
|
# Cloud Providers
|
5
2
|
from parsl.providers.aws.aws import AWSProvider
|
6
3
|
from parsl.providers.azure.azure import AzureProvider
|
@@ -24,7 +21,6 @@ __all__ = ['LocalProvider',
|
|
24
21
|
'SlurmProvider',
|
25
22
|
'TorqueProvider',
|
26
23
|
'LSFProvider',
|
27
|
-
'AdHocProvider',
|
28
24
|
'PBSProProvider',
|
29
25
|
'AWSProvider',
|
30
26
|
'GoogleCloudProvider',
|
parsl/providers/ad_hoc/ad_hoc.py
CHANGED
@@ -12,8 +12,12 @@ from parsl.utils import RepresentationMixin
|
|
12
12
|
logger = logging.getLogger(__name__)
|
13
13
|
|
14
14
|
|
15
|
-
class
|
16
|
-
"""
|
15
|
+
class DeprecatedAdHocProvider(ExecutionProvider, RepresentationMixin):
|
16
|
+
""" Deprecated ad-hoc execution provider
|
17
|
+
|
18
|
+
The (former) AdHocProvider is deprecated. See
|
19
|
+
`issue #3515 <https://github.com/Parsl/parsl/issues/3515>`_
|
20
|
+
for further discussion.
|
17
21
|
|
18
22
|
This provider is used to provision execution resources over one or more ad hoc nodes
|
19
23
|
that are each accessible over a Channel (say, ssh) but otherwise lack a cluster scheduler.
|
@@ -1,7 +1,7 @@
|
|
1
1
|
from parsl.channels import LocalChannel
|
2
2
|
from parsl.config import Config
|
3
3
|
from parsl.executors import HighThroughputExecutor
|
4
|
-
from parsl.providers import
|
4
|
+
from parsl.providers.ad_hoc.ad_hoc import DeprecatedAdHocProvider
|
5
5
|
|
6
6
|
|
7
7
|
def fresh_config():
|
@@ -10,7 +10,7 @@ def fresh_config():
|
|
10
10
|
HighThroughputExecutor(
|
11
11
|
label='AdHoc',
|
12
12
|
encrypted=True,
|
13
|
-
provider=
|
13
|
+
provider=DeprecatedAdHocProvider(
|
14
14
|
channels=[LocalChannel(), LocalChannel()]
|
15
15
|
)
|
16
16
|
)
|
@@ -0,0 +1,40 @@
|
|
1
|
+
import queue
|
2
|
+
from unittest import mock
|
3
|
+
|
4
|
+
import pytest
|
5
|
+
|
6
|
+
from parsl.executors import HighThroughputExecutor
|
7
|
+
from parsl.executors.high_throughput.mpi_prefix_composer import (
|
8
|
+
InvalidResourceSpecification,
|
9
|
+
)
|
10
|
+
|
11
|
+
|
12
|
+
def double(x):
|
13
|
+
return x * 2
|
14
|
+
|
15
|
+
|
16
|
+
@pytest.mark.local
|
17
|
+
def test_submit_calls_validate():
|
18
|
+
|
19
|
+
htex = HighThroughputExecutor()
|
20
|
+
htex.outgoing_q = mock.Mock(spec=queue.Queue)
|
21
|
+
htex.validate_resource_spec = mock.Mock(spec=htex.validate_resource_spec)
|
22
|
+
|
23
|
+
res_spec = {}
|
24
|
+
htex.submit(double, res_spec, (5,), {})
|
25
|
+
htex.validate_resource_spec.assert_called()
|
26
|
+
|
27
|
+
|
28
|
+
@pytest.mark.local
|
29
|
+
def test_resource_spec_validation():
|
30
|
+
htex = HighThroughputExecutor()
|
31
|
+
ret_val = htex.validate_resource_spec({})
|
32
|
+
assert ret_val is None
|
33
|
+
|
34
|
+
|
35
|
+
@pytest.mark.local
|
36
|
+
def test_resource_spec_validation_bad_keys():
|
37
|
+
htex = HighThroughputExecutor()
|
38
|
+
|
39
|
+
with pytest.raises(InvalidResourceSpecification):
|
40
|
+
htex.validate_resource_spec({"num_nodes": 2})
|
@@ -25,7 +25,8 @@ def make_interchange(*, interchange_address: Optional[str], cert_dir: Optional[s
|
|
25
25
|
logdir=".",
|
26
26
|
logging_level=logging.INFO,
|
27
27
|
manager_selector=RandomManagerSelector(),
|
28
|
-
poll_period=10
|
28
|
+
poll_period=10,
|
29
|
+
run_id="test_run_id")
|
29
30
|
|
30
31
|
|
31
32
|
@pytest.fixture
|
@@ -1,33 +1,48 @@
|
|
1
1
|
import pytest
|
2
2
|
|
3
3
|
from parsl import Config
|
4
|
-
from parsl.executors import
|
4
|
+
from parsl.executors import MPIExecutor
|
5
5
|
from parsl.launchers import AprunLauncher, SimpleLauncher, SrunLauncher
|
6
6
|
from parsl.providers import SlurmProvider
|
7
7
|
|
8
8
|
|
9
9
|
@pytest.mark.local
|
10
|
-
def
|
11
|
-
"""
|
10
|
+
def test_bad_launcher():
|
11
|
+
"""TypeError if a launcher other than SimpleLauncher is supplied"""
|
12
12
|
|
13
13
|
for launcher in [SrunLauncher(), AprunLauncher()]:
|
14
|
-
with pytest.raises(
|
14
|
+
with pytest.raises(TypeError):
|
15
15
|
Config(executors=[
|
16
|
-
|
17
|
-
enable_mpi_mode=True,
|
16
|
+
MPIExecutor(
|
18
17
|
provider=SlurmProvider(launcher=launcher),
|
19
18
|
)
|
20
19
|
])
|
21
20
|
|
22
21
|
|
23
22
|
@pytest.mark.local
|
24
|
-
def
|
23
|
+
def test_bad_mpi_launcher():
|
24
|
+
"""ValueError if an unsupported mpi_launcher is specified"""
|
25
|
+
|
26
|
+
with pytest.raises(ValueError):
|
27
|
+
Config(executors=[
|
28
|
+
MPIExecutor(
|
29
|
+
mpi_launcher="bad_launcher",
|
30
|
+
provider=SlurmProvider(launcher=SimpleLauncher()),
|
31
|
+
)
|
32
|
+
])
|
33
|
+
|
34
|
+
|
35
|
+
@pytest.mark.local
|
36
|
+
@pytest.mark.parametrize(
|
37
|
+
"mpi_launcher",
|
38
|
+
["srun", "aprun", "mpiexec"]
|
39
|
+
)
|
40
|
+
def test_correct_launcher_with_mpi_mode(mpi_launcher: str):
|
25
41
|
"""Confirm that SimpleLauncher works with mpi_mode"""
|
26
42
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
assert isinstance(config.executors[0].provider.launcher, SimpleLauncher)
|
43
|
+
executor = MPIExecutor(
|
44
|
+
mpi_launcher=mpi_launcher,
|
45
|
+
provider=SlurmProvider(launcher=SimpleLauncher()),
|
46
|
+
)
|
47
|
+
|
48
|
+
assert isinstance(executor.provider.launcher, SimpleLauncher)
|
@@ -6,26 +6,34 @@ from typing import Dict
|
|
6
6
|
import pytest
|
7
7
|
|
8
8
|
import parsl
|
9
|
-
from parsl import bash_app, python_app
|
9
|
+
from parsl import Config, bash_app, python_app
|
10
|
+
from parsl.executors import MPIExecutor
|
10
11
|
from parsl.executors.high_throughput.mpi_prefix_composer import (
|
11
12
|
MissingResourceSpecification,
|
12
13
|
)
|
13
|
-
from parsl.
|
14
|
+
from parsl.launchers import SimpleLauncher
|
15
|
+
from parsl.providers import LocalProvider
|
14
16
|
|
15
17
|
EXECUTOR_LABEL = "MPI_TEST"
|
16
18
|
|
17
19
|
|
18
20
|
def local_setup():
|
19
|
-
config = fresh_config()
|
20
|
-
config.executors[0].label = EXECUTOR_LABEL
|
21
|
-
config.executors[0].max_workers_per_node = 2
|
22
|
-
config.executors[0].enable_mpi_mode = True
|
23
|
-
config.executors[0].mpi_launcher = "mpiexec"
|
24
21
|
|
25
22
|
cwd = os.path.abspath(os.path.dirname(__file__))
|
26
23
|
pbs_nodefile = os.path.join(cwd, "mocks", "pbs_nodefile")
|
27
24
|
|
28
|
-
config
|
25
|
+
config = Config(
|
26
|
+
executors=[
|
27
|
+
MPIExecutor(
|
28
|
+
label=EXECUTOR_LABEL,
|
29
|
+
max_workers_per_block=2,
|
30
|
+
mpi_launcher="mpiexec",
|
31
|
+
provider=LocalProvider(
|
32
|
+
worker_init=f"export PBS_NODEFILE={pbs_nodefile}",
|
33
|
+
launcher=SimpleLauncher()
|
34
|
+
)
|
35
|
+
)
|
36
|
+
])
|
29
37
|
|
30
38
|
parsl.load(config)
|
31
39
|
|
@@ -4,7 +4,6 @@ from pathlib import Path
|
|
4
4
|
|
5
5
|
import pytest
|
6
6
|
|
7
|
-
import parsl
|
8
7
|
from parsl import Config, HighThroughputExecutor
|
9
8
|
from parsl.executors.high_throughput.mpi_executor import MPIExecutor
|
10
9
|
from parsl.launchers import SimpleLauncher
|
@@ -42,8 +41,8 @@ def test_docstring():
|
|
42
41
|
def test_init():
|
43
42
|
"""Ensure all relevant kwargs are copied over from HTEx"""
|
44
43
|
|
45
|
-
new_kwargs = {'max_workers_per_block'}
|
46
|
-
excluded_kwargs = {'available_accelerators', '
|
44
|
+
new_kwargs = {'max_workers_per_block', 'mpi_launcher'}
|
45
|
+
excluded_kwargs = {'available_accelerators', 'cores_per_worker', 'max_workers_per_node',
|
47
46
|
'mem_per_worker', 'cpu_affinity', 'max_workers', 'manager_selector'}
|
48
47
|
|
49
48
|
# Get the kwargs from both HTEx and MPIEx
|
@@ -1,18 +1,20 @@
|
|
1
1
|
import contextlib
|
2
2
|
import logging
|
3
3
|
import os
|
4
|
+
import queue
|
4
5
|
import typing
|
5
6
|
import unittest
|
6
7
|
from typing import Dict
|
8
|
+
from unittest import mock
|
7
9
|
|
8
10
|
import pytest
|
9
11
|
|
10
|
-
import parsl
|
11
12
|
from parsl.app.app import python_app
|
13
|
+
from parsl.executors.high_throughput.executor import HighThroughputExecutor
|
14
|
+
from parsl.executors.high_throughput.mpi_executor import MPIExecutor
|
12
15
|
from parsl.executors.high_throughput.mpi_prefix_composer import (
|
13
16
|
InvalidResourceSpecification,
|
14
17
|
MissingResourceSpecification,
|
15
|
-
validate_resource_spec,
|
16
18
|
)
|
17
19
|
from parsl.executors.high_throughput.mpi_resource_management import (
|
18
20
|
get_nodes_in_batchjob,
|
@@ -20,6 +22,8 @@ from parsl.executors.high_throughput.mpi_resource_management import (
|
|
20
22
|
get_slurm_hosts_list,
|
21
23
|
identify_scheduler,
|
22
24
|
)
|
25
|
+
from parsl.launchers import SimpleLauncher
|
26
|
+
from parsl.providers import LocalProvider
|
23
27
|
from parsl.tests.configs.htex_local import fresh_config
|
24
28
|
|
25
29
|
EXECUTOR_LABEL = "MPI_TEST"
|
@@ -48,23 +52,6 @@ def get_env_vars(parsl_resource_specification: Dict = {}) -> Dict:
|
|
48
52
|
return parsl_vars
|
49
53
|
|
50
54
|
|
51
|
-
@pytest.mark.local
|
52
|
-
def test_resource_spec_env_vars():
|
53
|
-
resource_spec = {
|
54
|
-
"num_nodes": 4,
|
55
|
-
"ranks_per_node": 2,
|
56
|
-
}
|
57
|
-
|
58
|
-
assert double(5).result() == 10
|
59
|
-
|
60
|
-
future = get_env_vars(parsl_resource_specification=resource_spec)
|
61
|
-
|
62
|
-
result = future.result()
|
63
|
-
assert isinstance(result, Dict)
|
64
|
-
assert result["PARSL_NUM_NODES"] == str(resource_spec["num_nodes"])
|
65
|
-
assert result["PARSL_RANKS_PER_NODE"] == str(resource_spec["ranks_per_node"])
|
66
|
-
|
67
|
-
|
68
55
|
@pytest.mark.local
|
69
56
|
@unittest.mock.patch("subprocess.check_output", return_value=b"c203-031\nc203-032\n")
|
70
57
|
def test_slurm_mocked_mpi_fetch(subprocess_check):
|
@@ -83,16 +70,6 @@ def add_to_path(path: os.PathLike) -> typing.Generator[None, None, None]:
|
|
83
70
|
os.environ["PATH"] = old_path
|
84
71
|
|
85
72
|
|
86
|
-
@pytest.mark.local
|
87
|
-
@pytest.mark.skip
|
88
|
-
def test_slurm_mpi_fetch():
|
89
|
-
logging.warning(f"Current pwd : {os.path.dirname(__file__)}")
|
90
|
-
with add_to_path(os.path.dirname(__file__)):
|
91
|
-
logging.warning(f"PATH: {os.environ['PATH']}")
|
92
|
-
nodeinfo = get_slurm_hosts_list()
|
93
|
-
logging.warning(f"Got : {nodeinfo}")
|
94
|
-
|
95
|
-
|
96
73
|
@contextlib.contextmanager
|
97
74
|
def mock_pbs_nodefile(nodefile: str = "pbs_nodefile") -> typing.Generator[None, None, None]:
|
98
75
|
cwd = os.path.abspath(os.path.dirname(__file__))
|
@@ -122,22 +99,43 @@ def test_top_level():
|
|
122
99
|
|
123
100
|
@pytest.mark.local
|
124
101
|
@pytest.mark.parametrize(
|
125
|
-
"resource_spec,
|
102
|
+
"resource_spec, exception",
|
126
103
|
(
|
127
|
-
|
128
|
-
({"
|
129
|
-
({"
|
130
|
-
({
|
131
|
-
({
|
132
|
-
({"launcher_options": "--debug_foo"}, True, None),
|
133
|
-
({"num_nodes": 2, "BAD_OPT": 1}, True, InvalidResourceSpecification),
|
134
|
-
({}, True, MissingResourceSpecification),
|
104
|
+
|
105
|
+
({"num_nodes": 2, "ranks_per_node": 1}, None),
|
106
|
+
({"launcher_options": "--debug_foo"}, None),
|
107
|
+
({"num_nodes": 2, "BAD_OPT": 1}, InvalidResourceSpecification),
|
108
|
+
({}, MissingResourceSpecification),
|
135
109
|
)
|
136
110
|
)
|
137
|
-
def
|
111
|
+
def test_mpi_resource_spec(resource_spec: Dict, exception):
|
112
|
+
"""Test validation of resource_specification in MPIExecutor"""
|
113
|
+
|
114
|
+
mpi_ex = MPIExecutor(provider=LocalProvider(launcher=SimpleLauncher()))
|
115
|
+
mpi_ex.outgoing_q = mock.Mock(spec=queue.Queue)
|
116
|
+
|
138
117
|
if exception:
|
139
118
|
with pytest.raises(exception):
|
140
|
-
validate_resource_spec(resource_spec
|
119
|
+
mpi_ex.validate_resource_spec(resource_spec)
|
141
120
|
else:
|
142
|
-
result = validate_resource_spec(resource_spec
|
121
|
+
result = mpi_ex.validate_resource_spec(resource_spec)
|
143
122
|
assert result is None
|
123
|
+
|
124
|
+
|
125
|
+
@pytest.mark.local
|
126
|
+
@pytest.mark.parametrize(
|
127
|
+
"resource_spec",
|
128
|
+
(
|
129
|
+
{"num_nodes": 2, "ranks_per_node": 1},
|
130
|
+
{"launcher_options": "--debug_foo"},
|
131
|
+
{"BAD_OPT": 1},
|
132
|
+
)
|
133
|
+
)
|
134
|
+
def test_mpi_resource_spec_passed_to_htex(resource_spec: dict):
|
135
|
+
"""HTEX should reject every resource_spec"""
|
136
|
+
|
137
|
+
htex = HighThroughputExecutor()
|
138
|
+
htex.outgoing_q = mock.Mock(spec=queue.Queue)
|
139
|
+
|
140
|
+
with pytest.raises(InvalidResourceSpecification):
|
141
|
+
htex.validate_resource_spec(resource_spec)
|
@@ -11,7 +11,8 @@ import time
|
|
11
11
|
|
12
12
|
import pytest
|
13
13
|
|
14
|
-
from parsl.channels import LocalChannel
|
14
|
+
from parsl.channels import LocalChannel
|
15
|
+
from parsl.channels.ssh.ssh import DeprecatedSSHChannel
|
15
16
|
from parsl.jobs.states import JobState
|
16
17
|
from parsl.launchers import SingleNodeLauncher
|
17
18
|
from parsl.providers import LocalProvider
|
@@ -92,10 +93,10 @@ def test_ssh_channel():
|
|
92
93
|
# already exist, so create it here.
|
93
94
|
pathlib.Path('{}/known.hosts'.format(config_dir)).touch(mode=0o600)
|
94
95
|
script_dir = tempfile.mkdtemp()
|
95
|
-
channel =
|
96
|
-
|
97
|
-
|
98
|
-
|
96
|
+
channel = DeprecatedSSHChannel('127.0.0.1', port=server_port,
|
97
|
+
script_dir=remote_script_dir,
|
98
|
+
host_keys_filename='{}/known.hosts'.format(config_dir),
|
99
|
+
key_filename=priv_key)
|
99
100
|
try:
|
100
101
|
p = LocalProvider(channel=channel,
|
101
102
|
launcher=SingleNodeLauncher(debug=False))
|
parsl/version.py
CHANGED
@@ -55,6 +55,7 @@ class Interchange:
|
|
55
55
|
poll_period: int,
|
56
56
|
cert_dir: Optional[str],
|
57
57
|
manager_selector: ManagerSelector,
|
58
|
+
run_id: str,
|
58
59
|
) -> None:
|
59
60
|
"""
|
60
61
|
Parameters
|
@@ -125,6 +126,8 @@ class Interchange:
|
|
125
126
|
self.command_channel.connect("tcp://{}:{}".format(client_address, client_ports[2]))
|
126
127
|
logger.info("Connected to client")
|
127
128
|
|
129
|
+
self.run_id = run_id
|
130
|
+
|
128
131
|
self.hub_address = hub_address
|
129
132
|
self.hub_zmq_port = hub_zmq_port
|
130
133
|
|
@@ -227,6 +230,7 @@ class Interchange:
|
|
227
230
|
d: Dict = cast(Dict, manager.copy())
|
228
231
|
d['timestamp'] = datetime.datetime.now()
|
229
232
|
d['last_heartbeat'] = datetime.datetime.fromtimestamp(d['last_heartbeat'])
|
233
|
+
d['run_id'] = self.run_id
|
230
234
|
|
231
235
|
monitoring_radio.send((MessageType.NODE_INFO, d))
|
232
236
|
|
@@ -1,9 +1,9 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: parsl
|
3
|
-
Version: 2024.8.
|
3
|
+
Version: 2024.8.19
|
4
4
|
Summary: Simple data dependent workflows in Python
|
5
5
|
Home-page: https://github.com/Parsl/parsl
|
6
|
-
Download-URL: https://github.com/Parsl/parsl/archive/2024.08.
|
6
|
+
Download-URL: https://github.com/Parsl/parsl/archive/2024.08.19.tar.gz
|
7
7
|
Author: The Parsl Team
|
8
8
|
Author-email: parsl@googlegroups.com
|
9
9
|
License: Apache 2.0
|
@@ -25,7 +25,6 @@ Requires-Dist: globus-sdk
|
|
25
25
|
Requires-Dist: dill
|
26
26
|
Requires-Dist: tblib
|
27
27
|
Requires-Dist: requests
|
28
|
-
Requires-Dist: paramiko
|
29
28
|
Requires-Dist: psutil>=5.5.1
|
30
29
|
Requires-Dist: setproctitle
|
31
30
|
Requires-Dist: filelock<4,>=3.13
|
@@ -57,6 +56,7 @@ Requires-Dist: jsonschema; extra == "all"
|
|
57
56
|
Requires-Dist: proxystore; extra == "all"
|
58
57
|
Requires-Dist: radical.pilot==1.60; extra == "all"
|
59
58
|
Requires-Dist: radical.utils==1.60; extra == "all"
|
59
|
+
Requires-Dist: paramiko; extra == "all"
|
60
60
|
Provides-Extra: aws
|
61
61
|
Requires-Dist: boto3; extra == "aws"
|
62
62
|
Provides-Extra: azure
|
@@ -87,6 +87,8 @@ Requires-Dist: proxystore; extra == "proxystore"
|
|
87
87
|
Provides-Extra: radical-pilot
|
88
88
|
Requires-Dist: radical.pilot==1.60; extra == "radical-pilot"
|
89
89
|
Requires-Dist: radical.utils==1.60; extra == "radical-pilot"
|
90
|
+
Provides-Extra: ssh
|
91
|
+
Requires-Dist: paramiko; extra == "ssh"
|
90
92
|
Provides-Extra: visualization
|
91
93
|
Requires-Dist: pydot; extra == "visualization"
|
92
94
|
Requires-Dist: networkx<2.6,>=2.5; extra == "visualization"
|