parsl 2024.11.25__py3-none-any.whl → 2024.12.9__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/configs/ASPIRE1.py +0 -1
- parsl/configs/cc_in2p3.py +0 -2
- parsl/configs/frontera.py +0 -2
- parsl/configs/htex_local.py +0 -2
- parsl/dataflow/dflow.py +0 -2
- parsl/executors/base.py +1 -1
- parsl/executors/high_throughput/executor.py +15 -2
- parsl/executors/high_throughput/interchange.py +2 -1
- parsl/executors/high_throughput/zmq_pipes.py +13 -4
- parsl/monitoring/monitoring.py +1 -1
- parsl/monitoring/radios/base.py +13 -0
- parsl/monitoring/radios/filesystem.py +52 -0
- parsl/monitoring/radios/htex.py +57 -0
- parsl/monitoring/radios/multiprocessing.py +17 -0
- parsl/monitoring/radios/udp.py +56 -0
- parsl/monitoring/radios/zmq.py +17 -0
- parsl/monitoring/remote.py +4 -6
- parsl/monitoring/router.py +1 -1
- parsl/providers/cluster_provider.py +2 -5
- parsl/providers/condor/condor.py +4 -13
- parsl/providers/grid_engine/grid_engine.py +3 -9
- parsl/providers/local/local.py +6 -23
- parsl/providers/lsf/lsf.py +3 -18
- parsl/providers/pbspro/pbspro.py +3 -10
- parsl/providers/slurm/slurm.py +4 -20
- parsl/providers/torque/torque.py +2 -10
- parsl/tests/configs/cc_in2p3.py +0 -2
- parsl/tests/configs/frontera.py +0 -2
- parsl/tests/configs/htex_local.py +0 -2
- parsl/tests/configs/htex_local_alternate.py +0 -3
- parsl/tests/configs/htex_local_intask_staging.py +0 -2
- parsl/tests/configs/htex_local_rsync_staging.py +0 -2
- parsl/tests/configs/local_threads_monitoring.py +0 -1
- parsl/tests/configs/slurm_local.py +0 -2
- parsl/tests/manual_tests/htex_local.py +0 -2
- parsl/tests/manual_tests/test_memory_limits.py +0 -2
- parsl/tests/manual_tests/test_udp_simple.py +0 -1
- parsl/tests/scaling_tests/htex_local.py +0 -2
- parsl/tests/sites/test_affinity.py +0 -2
- parsl/tests/sites/test_worker_info.py +0 -2
- parsl/tests/test_htex/test_drain.py +0 -2
- parsl/tests/test_htex/test_manager_selector_by_block.py +0 -2
- parsl/tests/test_monitoring/test_htex_init_blocks_vs_monitoring.py +0 -3
- parsl/tests/test_monitoring/test_stdouterr.py +0 -1
- parsl/tests/test_providers/test_local_provider.py +1 -2
- parsl/tests/test_providers/test_pbspro_template.py +1 -3
- parsl/tests/test_providers/test_slurm_template.py +1 -3
- parsl/tests/test_scaling/test_regression_1621.py +0 -2
- parsl/tests/test_scaling/test_regression_3568_scaledown_vs_MISSING.py +0 -1
- parsl/tests/test_scaling/test_scale_down.py +0 -2
- parsl/tests/test_scaling/test_scale_down_htex_auto_scale.py +0 -2
- parsl/tests/test_scaling/test_scale_down_htex_unregistered.py +0 -2
- parsl/tests/test_scaling/test_shutdown_scalein.py +0 -2
- parsl/tests/test_scaling/test_worker_interchange_bad_messages_3262.py +0 -2
- parsl/tests/test_staging/test_zip_in.py +0 -1
- parsl/tests/test_staging/test_zip_out.py +0 -1
- parsl/tests/test_staging/test_zip_to_zip.py +0 -1
- parsl/tests/test_utils/test_execute_wait.py +35 -0
- parsl/utils.py +35 -0
- parsl/version.py +1 -1
- {parsl-2024.11.25.data → parsl-2024.12.9.data}/scripts/interchange.py +2 -1
- {parsl-2024.11.25.dist-info → parsl-2024.12.9.dist-info}/METADATA +2 -2
- {parsl-2024.11.25.dist-info → parsl-2024.12.9.dist-info}/RECORD +71 -73
- parsl/channels/__init__.py +0 -4
- parsl/channels/base.py +0 -82
- parsl/channels/errors.py +0 -30
- parsl/channels/local/local.py +0 -102
- parsl/monitoring/radios.py +0 -191
- parsl/tests/integration/test_channels/__init__.py +0 -0
- parsl/tests/test_channels/__init__.py +0 -0
- parsl/tests/test_channels/test_large_output.py +0 -22
- parsl/tests/test_channels/test_local_channel.py +0 -19
- /parsl/{channels/local → monitoring/radios}/__init__.py +0 -0
- {parsl-2024.11.25.data → parsl-2024.12.9.data}/scripts/exec_parsl_function.py +0 -0
- {parsl-2024.11.25.data → parsl-2024.12.9.data}/scripts/parsl_coprocess.py +0 -0
- {parsl-2024.11.25.data → parsl-2024.12.9.data}/scripts/process_worker_pool.py +0 -0
- {parsl-2024.11.25.dist-info → parsl-2024.12.9.dist-info}/LICENSE +0 -0
- {parsl-2024.11.25.dist-info → parsl-2024.12.9.dist-info}/WHEEL +0 -0
- {parsl-2024.11.25.dist-info → parsl-2024.12.9.dist-info}/entry_points.txt +0 -0
- {parsl-2024.11.25.dist-info → parsl-2024.12.9.dist-info}/top_level.txt +0 -0
parsl/monitoring/radios.py
DELETED
@@ -1,191 +0,0 @@
|
|
1
|
-
import logging
|
2
|
-
import os
|
3
|
-
import pickle
|
4
|
-
import socket
|
5
|
-
import uuid
|
6
|
-
from abc import ABCMeta, abstractmethod
|
7
|
-
from multiprocessing.queues import Queue
|
8
|
-
|
9
|
-
import zmq
|
10
|
-
|
11
|
-
logger = logging.getLogger(__name__)
|
12
|
-
|
13
|
-
|
14
|
-
class MonitoringRadioSender(metaclass=ABCMeta):
|
15
|
-
@abstractmethod
|
16
|
-
def send(self, message: object) -> None:
|
17
|
-
pass
|
18
|
-
|
19
|
-
|
20
|
-
class FilesystemRadioSender(MonitoringRadioSender):
|
21
|
-
"""A MonitoringRadioSender that sends messages over a shared filesystem.
|
22
|
-
|
23
|
-
The messsage directory structure is based on maildir,
|
24
|
-
https://en.wikipedia.org/wiki/Maildir
|
25
|
-
|
26
|
-
The writer creates a message in tmp/ and then when it is fully
|
27
|
-
written, moves it atomically into new/
|
28
|
-
|
29
|
-
The reader ignores tmp/ and only reads and deletes messages from
|
30
|
-
new/
|
31
|
-
|
32
|
-
This avoids a race condition of reading partially written messages.
|
33
|
-
|
34
|
-
This radio is likely to give higher shared filesystem load compared to
|
35
|
-
the UDP radio, but should be much more reliable.
|
36
|
-
"""
|
37
|
-
|
38
|
-
def __init__(self, *, monitoring_url: str, timeout: int = 10, run_dir: str):
|
39
|
-
logger.info("filesystem based monitoring channel initializing")
|
40
|
-
self.base_path = f"{run_dir}/monitor-fs-radio/"
|
41
|
-
self.tmp_path = f"{self.base_path}/tmp"
|
42
|
-
self.new_path = f"{self.base_path}/new"
|
43
|
-
|
44
|
-
os.makedirs(self.tmp_path, exist_ok=True)
|
45
|
-
os.makedirs(self.new_path, exist_ok=True)
|
46
|
-
|
47
|
-
def send(self, message: object) -> None:
|
48
|
-
logger.info("Sending a monitoring message via filesystem")
|
49
|
-
|
50
|
-
unique_id = str(uuid.uuid4())
|
51
|
-
|
52
|
-
tmp_filename = f"{self.tmp_path}/{unique_id}"
|
53
|
-
new_filename = f"{self.new_path}/{unique_id}"
|
54
|
-
buffer = message
|
55
|
-
|
56
|
-
# this will write the message out then atomically
|
57
|
-
# move it into new/, so that a partially written
|
58
|
-
# file will never be observed in new/
|
59
|
-
with open(tmp_filename, "wb") as f:
|
60
|
-
pickle.dump(buffer, f)
|
61
|
-
os.rename(tmp_filename, new_filename)
|
62
|
-
|
63
|
-
|
64
|
-
class HTEXRadioSender(MonitoringRadioSender):
|
65
|
-
|
66
|
-
def __init__(self, monitoring_url: str, timeout: int = 10):
|
67
|
-
"""
|
68
|
-
Parameters
|
69
|
-
----------
|
70
|
-
|
71
|
-
monitoring_url : str
|
72
|
-
URL of the form <scheme>://<IP>:<PORT>
|
73
|
-
timeout : int
|
74
|
-
timeout, default=10s
|
75
|
-
"""
|
76
|
-
logger.info("htex-based monitoring channel initialising")
|
77
|
-
|
78
|
-
def send(self, message: object) -> None:
|
79
|
-
""" Sends a message to the UDP receiver
|
80
|
-
|
81
|
-
Parameter
|
82
|
-
---------
|
83
|
-
|
84
|
-
message: object
|
85
|
-
Arbitrary pickle-able object that is to be sent
|
86
|
-
|
87
|
-
Returns:
|
88
|
-
None
|
89
|
-
"""
|
90
|
-
|
91
|
-
import parsl.executors.high_throughput.monitoring_info
|
92
|
-
|
93
|
-
result_queue = parsl.executors.high_throughput.monitoring_info.result_queue
|
94
|
-
|
95
|
-
# this message needs to go in the result queue tagged so that it is treated
|
96
|
-
# i) as a monitoring message by the interchange, and then further more treated
|
97
|
-
# as a RESOURCE_INFO message when received by monitoring (rather than a NODE_INFO
|
98
|
-
# which is the implicit default for messages from the interchange)
|
99
|
-
|
100
|
-
# for the interchange, the outer wrapper, this needs to be a dict:
|
101
|
-
|
102
|
-
interchange_msg = {
|
103
|
-
'type': 'monitoring',
|
104
|
-
'payload': message
|
105
|
-
}
|
106
|
-
|
107
|
-
if result_queue:
|
108
|
-
result_queue.put(pickle.dumps(interchange_msg))
|
109
|
-
else:
|
110
|
-
logger.error("result_queue is uninitialized - cannot put monitoring message")
|
111
|
-
|
112
|
-
return
|
113
|
-
|
114
|
-
|
115
|
-
class UDPRadioSender(MonitoringRadioSender):
|
116
|
-
|
117
|
-
def __init__(self, monitoring_url: str, timeout: int = 10):
|
118
|
-
"""
|
119
|
-
Parameters
|
120
|
-
----------
|
121
|
-
|
122
|
-
monitoring_url : str
|
123
|
-
URL of the form <scheme>://<IP>:<PORT>
|
124
|
-
timeout : int
|
125
|
-
timeout, default=10s
|
126
|
-
"""
|
127
|
-
self.monitoring_url = monitoring_url
|
128
|
-
self.sock_timeout = timeout
|
129
|
-
try:
|
130
|
-
self.scheme, self.ip, port = (x.strip('/') for x in monitoring_url.split(':'))
|
131
|
-
self.port = int(port)
|
132
|
-
except Exception:
|
133
|
-
raise Exception("Failed to parse monitoring url: {}".format(monitoring_url))
|
134
|
-
|
135
|
-
self.sock = socket.socket(socket.AF_INET,
|
136
|
-
socket.SOCK_DGRAM,
|
137
|
-
socket.IPPROTO_UDP) # UDP
|
138
|
-
self.sock.settimeout(self.sock_timeout)
|
139
|
-
|
140
|
-
def send(self, message: object) -> None:
|
141
|
-
""" Sends a message to the UDP receiver
|
142
|
-
|
143
|
-
Parameter
|
144
|
-
---------
|
145
|
-
|
146
|
-
message: object
|
147
|
-
Arbitrary pickle-able object that is to be sent
|
148
|
-
|
149
|
-
Returns:
|
150
|
-
None
|
151
|
-
"""
|
152
|
-
try:
|
153
|
-
buffer = pickle.dumps(message)
|
154
|
-
except Exception:
|
155
|
-
logging.exception("Exception during pickling", exc_info=True)
|
156
|
-
return
|
157
|
-
|
158
|
-
try:
|
159
|
-
self.sock.sendto(buffer, (self.ip, self.port))
|
160
|
-
except socket.timeout:
|
161
|
-
logging.error("Could not send message within timeout limit")
|
162
|
-
return
|
163
|
-
return
|
164
|
-
|
165
|
-
|
166
|
-
class MultiprocessingQueueRadioSender(MonitoringRadioSender):
|
167
|
-
"""A monitoring radio which connects over a multiprocessing Queue.
|
168
|
-
This radio is intended to be used on the submit side, where components
|
169
|
-
in the submit process, or processes launched by multiprocessing, will have
|
170
|
-
access to a Queue shared with the monitoring database code (bypassing the
|
171
|
-
monitoring router).
|
172
|
-
"""
|
173
|
-
def __init__(self, queue: Queue) -> None:
|
174
|
-
self.queue = queue
|
175
|
-
|
176
|
-
def send(self, message: object) -> None:
|
177
|
-
self.queue.put(message)
|
178
|
-
|
179
|
-
|
180
|
-
class ZMQRadioSender(MonitoringRadioSender):
|
181
|
-
"""A monitoring radio which connects over ZMQ. This radio is not
|
182
|
-
thread-safe, because its use of ZMQ is not thread-safe.
|
183
|
-
"""
|
184
|
-
|
185
|
-
def __init__(self, hub_address: str, hub_zmq_port: int) -> None:
|
186
|
-
self._hub_channel = zmq.Context().socket(zmq.DEALER)
|
187
|
-
self._hub_channel.set_hwm(0)
|
188
|
-
self._hub_channel.connect(f"tcp://{hub_address}:{hub_zmq_port}")
|
189
|
-
|
190
|
-
def send(self, message: object) -> None:
|
191
|
-
self._hub_channel.send_pyobj(message)
|
File without changes
|
File without changes
|
@@ -1,22 +0,0 @@
|
|
1
|
-
import pytest
|
2
|
-
|
3
|
-
from parsl.channels.local.local import LocalChannel
|
4
|
-
|
5
|
-
|
6
|
-
@pytest.mark.local
|
7
|
-
def test_local_large_output_2210():
|
8
|
-
"""Regression test for #2210.
|
9
|
-
The local channel was hanging if the specified command gave too
|
10
|
-
much output, due to a race condition between process exiting and
|
11
|
-
pipes filling up.
|
12
|
-
"""
|
13
|
-
|
14
|
-
c = LocalChannel()
|
15
|
-
|
16
|
-
# this will output 128kb of stdout
|
17
|
-
c.execute_wait("yes | dd count=128 bs=1024", walltime=60)
|
18
|
-
|
19
|
-
# if this test fails, execute_wait should raise a timeout
|
20
|
-
# exception.
|
21
|
-
|
22
|
-
# The contents out the output is not verified by this test
|
@@ -1,19 +0,0 @@
|
|
1
|
-
import pytest
|
2
|
-
|
3
|
-
from parsl.channels.local.local import LocalChannel
|
4
|
-
|
5
|
-
|
6
|
-
@pytest.mark.local
|
7
|
-
def test_env():
|
8
|
-
''' Regression testing for issue #27
|
9
|
-
'''
|
10
|
-
|
11
|
-
lc = LocalChannel()
|
12
|
-
rc, stdout, stderr = lc.execute_wait("env", 1)
|
13
|
-
|
14
|
-
stdout = stdout.split('\n')
|
15
|
-
x = [s for s in stdout if s.startswith("PATH=")]
|
16
|
-
assert x, "PATH not found"
|
17
|
-
|
18
|
-
x = [s for s in stdout if s.startswith("HOME=")]
|
19
|
-
assert x, "HOME not found"
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|