toil 6.1.0a1__py3-none-any.whl → 8.0.0__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.
- toil/__init__.py +122 -315
- toil/batchSystems/__init__.py +1 -0
- toil/batchSystems/abstractBatchSystem.py +173 -89
- toil/batchSystems/abstractGridEngineBatchSystem.py +272 -148
- toil/batchSystems/awsBatch.py +244 -135
- toil/batchSystems/cleanup_support.py +26 -16
- toil/batchSystems/contained_executor.py +31 -28
- toil/batchSystems/gridengine.py +86 -50
- toil/batchSystems/htcondor.py +166 -89
- toil/batchSystems/kubernetes.py +632 -382
- toil/batchSystems/local_support.py +20 -15
- toil/batchSystems/lsf.py +134 -81
- toil/batchSystems/lsfHelper.py +13 -11
- toil/batchSystems/mesos/__init__.py +41 -29
- toil/batchSystems/mesos/batchSystem.py +290 -151
- toil/batchSystems/mesos/executor.py +79 -50
- toil/batchSystems/mesos/test/__init__.py +31 -23
- toil/batchSystems/options.py +46 -28
- toil/batchSystems/registry.py +53 -19
- toil/batchSystems/singleMachine.py +296 -125
- toil/batchSystems/slurm.py +603 -138
- toil/batchSystems/torque.py +47 -33
- toil/bus.py +186 -76
- toil/common.py +664 -368
- toil/cwl/__init__.py +1 -1
- toil/cwl/cwltoil.py +1136 -483
- toil/cwl/utils.py +17 -22
- toil/deferred.py +63 -42
- toil/exceptions.py +5 -3
- toil/fileStores/__init__.py +5 -5
- toil/fileStores/abstractFileStore.py +140 -60
- toil/fileStores/cachingFileStore.py +717 -269
- toil/fileStores/nonCachingFileStore.py +116 -87
- toil/job.py +1225 -368
- toil/jobStores/abstractJobStore.py +416 -266
- toil/jobStores/aws/jobStore.py +863 -477
- toil/jobStores/aws/utils.py +201 -120
- toil/jobStores/conftest.py +3 -2
- toil/jobStores/fileJobStore.py +292 -154
- toil/jobStores/googleJobStore.py +140 -74
- toil/jobStores/utils.py +36 -15
- toil/leader.py +668 -272
- toil/lib/accelerators.py +115 -18
- toil/lib/aws/__init__.py +74 -31
- toil/lib/aws/ami.py +122 -87
- toil/lib/aws/iam.py +284 -108
- toil/lib/aws/s3.py +31 -0
- toil/lib/aws/session.py +214 -39
- toil/lib/aws/utils.py +287 -231
- toil/lib/bioio.py +13 -5
- toil/lib/compatibility.py +11 -6
- toil/lib/conversions.py +104 -47
- toil/lib/docker.py +131 -103
- toil/lib/ec2.py +361 -199
- toil/lib/ec2nodes.py +174 -106
- toil/lib/encryption/_dummy.py +5 -3
- toil/lib/encryption/_nacl.py +10 -6
- toil/lib/encryption/conftest.py +1 -0
- toil/lib/exceptions.py +26 -7
- toil/lib/expando.py +5 -3
- toil/lib/ftp_utils.py +217 -0
- toil/lib/generatedEC2Lists.py +127 -19
- toil/lib/humanize.py +6 -2
- toil/lib/integration.py +341 -0
- toil/lib/io.py +141 -15
- toil/lib/iterables.py +4 -2
- toil/lib/memoize.py +12 -8
- toil/lib/misc.py +66 -21
- toil/lib/objects.py +2 -2
- toil/lib/resources.py +68 -15
- toil/lib/retry.py +126 -81
- toil/lib/threading.py +299 -82
- toil/lib/throttle.py +16 -15
- toil/options/common.py +843 -409
- toil/options/cwl.py +175 -90
- toil/options/runner.py +50 -0
- toil/options/wdl.py +73 -17
- toil/provisioners/__init__.py +117 -46
- toil/provisioners/abstractProvisioner.py +332 -157
- toil/provisioners/aws/__init__.py +70 -33
- toil/provisioners/aws/awsProvisioner.py +1145 -715
- toil/provisioners/clusterScaler.py +541 -279
- toil/provisioners/gceProvisioner.py +282 -179
- toil/provisioners/node.py +155 -79
- toil/realtimeLogger.py +34 -22
- toil/resource.py +137 -75
- toil/server/app.py +128 -62
- toil/server/celery_app.py +3 -1
- toil/server/cli/wes_cwl_runner.py +82 -53
- toil/server/utils.py +54 -28
- toil/server/wes/abstract_backend.py +64 -26
- toil/server/wes/amazon_wes_utils.py +21 -15
- toil/server/wes/tasks.py +121 -63
- toil/server/wes/toil_backend.py +142 -107
- toil/server/wsgi_app.py +4 -3
- toil/serviceManager.py +58 -22
- toil/statsAndLogging.py +224 -70
- toil/test/__init__.py +282 -183
- toil/test/batchSystems/batchSystemTest.py +460 -210
- toil/test/batchSystems/batch_system_plugin_test.py +90 -0
- toil/test/batchSystems/test_gridengine.py +173 -0
- toil/test/batchSystems/test_lsf_helper.py +67 -58
- toil/test/batchSystems/test_slurm.py +110 -49
- toil/test/cactus/__init__.py +0 -0
- toil/test/cactus/test_cactus_integration.py +56 -0
- toil/test/cwl/cwlTest.py +496 -287
- toil/test/cwl/measure_default_memory.cwl +12 -0
- toil/test/cwl/not_run_required_input.cwl +29 -0
- toil/test/cwl/scatter_duplicate_outputs.cwl +40 -0
- toil/test/cwl/seqtk_seq.cwl +1 -1
- toil/test/docs/scriptsTest.py +69 -46
- toil/test/jobStores/jobStoreTest.py +427 -264
- toil/test/lib/aws/test_iam.py +118 -50
- toil/test/lib/aws/test_s3.py +16 -9
- toil/test/lib/aws/test_utils.py +5 -6
- toil/test/lib/dockerTest.py +118 -141
- toil/test/lib/test_conversions.py +113 -115
- toil/test/lib/test_ec2.py +58 -50
- toil/test/lib/test_integration.py +104 -0
- toil/test/lib/test_misc.py +12 -5
- toil/test/mesos/MesosDataStructuresTest.py +23 -10
- toil/test/mesos/helloWorld.py +7 -6
- toil/test/mesos/stress.py +25 -20
- toil/test/options/__init__.py +13 -0
- toil/test/options/options.py +42 -0
- toil/test/provisioners/aws/awsProvisionerTest.py +320 -150
- toil/test/provisioners/clusterScalerTest.py +440 -250
- toil/test/provisioners/clusterTest.py +166 -44
- toil/test/provisioners/gceProvisionerTest.py +174 -100
- toil/test/provisioners/provisionerTest.py +25 -13
- toil/test/provisioners/restartScript.py +5 -4
- toil/test/server/serverTest.py +188 -141
- toil/test/sort/restart_sort.py +137 -68
- toil/test/sort/sort.py +134 -66
- toil/test/sort/sortTest.py +91 -49
- toil/test/src/autoDeploymentTest.py +141 -101
- toil/test/src/busTest.py +20 -18
- toil/test/src/checkpointTest.py +8 -2
- toil/test/src/deferredFunctionTest.py +49 -35
- toil/test/src/dockerCheckTest.py +32 -24
- toil/test/src/environmentTest.py +135 -0
- toil/test/src/fileStoreTest.py +539 -272
- toil/test/src/helloWorldTest.py +7 -4
- toil/test/src/importExportFileTest.py +61 -31
- toil/test/src/jobDescriptionTest.py +46 -21
- toil/test/src/jobEncapsulationTest.py +2 -0
- toil/test/src/jobFileStoreTest.py +74 -50
- toil/test/src/jobServiceTest.py +187 -73
- toil/test/src/jobTest.py +121 -71
- toil/test/src/miscTests.py +19 -18
- toil/test/src/promisedRequirementTest.py +82 -36
- toil/test/src/promisesTest.py +7 -6
- toil/test/src/realtimeLoggerTest.py +10 -6
- toil/test/src/regularLogTest.py +71 -37
- toil/test/src/resourceTest.py +80 -49
- toil/test/src/restartDAGTest.py +36 -22
- toil/test/src/resumabilityTest.py +9 -2
- toil/test/src/retainTempDirTest.py +45 -14
- toil/test/src/systemTest.py +12 -8
- toil/test/src/threadingTest.py +44 -25
- toil/test/src/toilContextManagerTest.py +10 -7
- toil/test/src/userDefinedJobArgTypeTest.py +8 -5
- toil/test/src/workerTest.py +73 -23
- toil/test/utils/toilDebugTest.py +103 -33
- toil/test/utils/toilKillTest.py +4 -5
- toil/test/utils/utilsTest.py +245 -106
- toil/test/wdl/wdltoil_test.py +818 -149
- toil/test/wdl/wdltoil_test_kubernetes.py +91 -0
- toil/toilState.py +120 -35
- toil/utils/toilConfig.py +13 -4
- toil/utils/toilDebugFile.py +44 -27
- toil/utils/toilDebugJob.py +214 -27
- toil/utils/toilDestroyCluster.py +11 -6
- toil/utils/toilKill.py +8 -3
- toil/utils/toilLaunchCluster.py +256 -140
- toil/utils/toilMain.py +37 -16
- toil/utils/toilRsyncCluster.py +32 -14
- toil/utils/toilSshCluster.py +49 -22
- toil/utils/toilStats.py +356 -273
- toil/utils/toilStatus.py +292 -139
- toil/utils/toilUpdateEC2Instances.py +3 -1
- toil/version.py +12 -12
- toil/wdl/utils.py +5 -5
- toil/wdl/wdltoil.py +3913 -1033
- toil/worker.py +367 -184
- {toil-6.1.0a1.dist-info → toil-8.0.0.dist-info}/LICENSE +25 -0
- toil-8.0.0.dist-info/METADATA +173 -0
- toil-8.0.0.dist-info/RECORD +253 -0
- {toil-6.1.0a1.dist-info → toil-8.0.0.dist-info}/WHEEL +1 -1
- toil-6.1.0a1.dist-info/METADATA +0 -125
- toil-6.1.0a1.dist-info/RECORD +0 -237
- {toil-6.1.0a1.dist-info → toil-8.0.0.dist-info}/entry_points.txt +0 -0
- {toil-6.1.0a1.dist-info → toil-8.0.0.dist-info}/top_level.txt +0 -0
toil/test/sort/sortTest.py
CHANGED
|
@@ -25,29 +25,35 @@ from toil.batchSystems.mesos.test import MesosTestSupport
|
|
|
25
25
|
from toil.common import Toil
|
|
26
26
|
from toil.exceptions import FailedJobsException
|
|
27
27
|
from toil.job import Job
|
|
28
|
-
from toil.jobStores.abstractJobStore import (
|
|
29
|
-
|
|
28
|
+
from toil.jobStores.abstractJobStore import (
|
|
29
|
+
JobStoreExistsException,
|
|
30
|
+
NoSuchJobStoreException,
|
|
31
|
+
)
|
|
30
32
|
from toil.lib.bioio import root_logger
|
|
31
|
-
from toil.test import (
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
33
|
+
from toil.test import (
|
|
34
|
+
ToilTest,
|
|
35
|
+
needs_aws_ec2,
|
|
36
|
+
needs_google_project,
|
|
37
|
+
needs_google_storage,
|
|
38
|
+
needs_gridengine,
|
|
39
|
+
needs_mesos,
|
|
40
|
+
needs_torque,
|
|
41
|
+
slow,
|
|
42
|
+
)
|
|
43
|
+
from toil.test.sort.sort import (
|
|
44
|
+
copySubRangeOfFile,
|
|
45
|
+
getMidPoint,
|
|
46
|
+
main,
|
|
47
|
+
makeFileToSort,
|
|
48
|
+
merge,
|
|
49
|
+
sort,
|
|
50
|
+
)
|
|
45
51
|
|
|
46
52
|
logger = logging.getLogger(__name__)
|
|
47
53
|
|
|
48
|
-
defaultLineLen = int(os.environ.get(
|
|
49
|
-
defaultLines = int(os.environ.get(
|
|
50
|
-
defaultN = int(os.environ.get(
|
|
54
|
+
defaultLineLen = int(os.environ.get("TOIL_TEST_SORT_LINE_LEN", 10))
|
|
55
|
+
defaultLines = int(os.environ.get("TOIL_TEST_SORT_LINES", 10))
|
|
56
|
+
defaultN = int(os.environ.get("TOIL_TEST_SORT_N", defaultLineLen * defaultLines / 5))
|
|
51
57
|
|
|
52
58
|
|
|
53
59
|
@contextmanager
|
|
@@ -67,10 +73,11 @@ class SortTest(ToilTest, MesosTestSupport):
|
|
|
67
73
|
Tests Toil by sorting a file in parallel on various combinations of job stores and batch
|
|
68
74
|
systems.
|
|
69
75
|
"""
|
|
76
|
+
|
|
70
77
|
def setUp(self):
|
|
71
78
|
super().setUp()
|
|
72
|
-
self.tempDir = self._createTempDir(purpose=
|
|
73
|
-
self.outputFile = os.path.join(self.tempDir,
|
|
79
|
+
self.tempDir = self._createTempDir(purpose="tempDir")
|
|
80
|
+
self.outputFile = os.path.join(self.tempDir, "sortedFile.txt")
|
|
74
81
|
self.inputFile = os.path.join(self.tempDir, "fileToSort.txt")
|
|
75
82
|
|
|
76
83
|
def tearDown(self):
|
|
@@ -78,9 +85,19 @@ class SortTest(ToilTest, MesosTestSupport):
|
|
|
78
85
|
shutil.rmtree(self.tempDir)
|
|
79
86
|
ToilTest.tearDown(self)
|
|
80
87
|
|
|
81
|
-
def _toilSort(
|
|
82
|
-
|
|
83
|
-
|
|
88
|
+
def _toilSort(
|
|
89
|
+
self,
|
|
90
|
+
jobStoreLocator,
|
|
91
|
+
batchSystem,
|
|
92
|
+
lines=defaultLines,
|
|
93
|
+
N=defaultN,
|
|
94
|
+
testNo=1,
|
|
95
|
+
lineLen=defaultLineLen,
|
|
96
|
+
retryCount=2,
|
|
97
|
+
badWorker=0.5,
|
|
98
|
+
downCheckpoints=False,
|
|
99
|
+
caching=True,
|
|
100
|
+
):
|
|
84
101
|
"""
|
|
85
102
|
Generate a file consisting of the given number of random lines, each line of the given
|
|
86
103
|
length. Sort the file with Toil by splitting the file recursively until each part is less
|
|
@@ -112,8 +129,8 @@ class SortTest(ToilTest, MesosTestSupport):
|
|
|
112
129
|
options.caching = caching
|
|
113
130
|
# This is required because mesos_endpoint now defaults to the IP of the machine
|
|
114
131
|
# that is starting the workflow while the mesos *tests* run locally.
|
|
115
|
-
if batchSystem ==
|
|
116
|
-
options.mesos_endpoint =
|
|
132
|
+
if batchSystem == "mesos":
|
|
133
|
+
options.mesos_endpoint = "localhost:5050"
|
|
117
134
|
options.downCheckpoints = downCheckpoints
|
|
118
135
|
options.N = N
|
|
119
136
|
options.outputFile = self.outputFile
|
|
@@ -166,18 +183,22 @@ class SortTest(ToilTest, MesosTestSupport):
|
|
|
166
183
|
except FailedJobsException as e:
|
|
167
184
|
i = e.numberOfFailedJobs
|
|
168
185
|
if totalTrys > 32: # p(fail after this many restarts) = 0.5**32
|
|
169
|
-
self.fail(
|
|
186
|
+
self.fail("Exceeded a reasonable number of restarts")
|
|
170
187
|
totalTrys += 1
|
|
171
188
|
finally:
|
|
172
|
-
subprocess.check_call(
|
|
189
|
+
subprocess.check_call(
|
|
190
|
+
[resolveEntryPoint("toil"), "clean", jobStoreLocator]
|
|
191
|
+
)
|
|
173
192
|
# final test to make sure the jobStore was actually deleted
|
|
174
|
-
self.assertRaises(
|
|
175
|
-
|
|
176
|
-
|
|
193
|
+
self.assertRaises(
|
|
194
|
+
NoSuchJobStoreException, Toil.resumeJobStore, jobStoreLocator
|
|
195
|
+
)
|
|
177
196
|
|
|
178
197
|
@needs_aws_ec2
|
|
179
198
|
def testAwsSingle(self):
|
|
180
|
-
self._toilSort(
|
|
199
|
+
self._toilSort(
|
|
200
|
+
jobStoreLocator=self._awsJobStore(), batchSystem="single_machine"
|
|
201
|
+
)
|
|
181
202
|
|
|
182
203
|
@needs_aws_ec2
|
|
183
204
|
@needs_mesos
|
|
@@ -192,14 +213,18 @@ class SortTest(ToilTest, MesosTestSupport):
|
|
|
192
213
|
def testFileMesos(self):
|
|
193
214
|
self._startMesos()
|
|
194
215
|
try:
|
|
195
|
-
self._toilSort(
|
|
216
|
+
self._toilSort(
|
|
217
|
+
jobStoreLocator=self._getTestJobStorePath(), batchSystem="mesos"
|
|
218
|
+
)
|
|
196
219
|
finally:
|
|
197
220
|
self._stopMesos()
|
|
198
221
|
|
|
199
222
|
@needs_google_project
|
|
200
223
|
@needs_google_storage
|
|
201
224
|
def testGoogleSingle(self):
|
|
202
|
-
self._toilSort(
|
|
225
|
+
self._toilSort(
|
|
226
|
+
jobStoreLocator=self._googleJobStore(), batchSystem="single_machine"
|
|
227
|
+
)
|
|
203
228
|
|
|
204
229
|
@needs_google_project
|
|
205
230
|
@needs_google_storage
|
|
@@ -212,29 +237,46 @@ class SortTest(ToilTest, MesosTestSupport):
|
|
|
212
237
|
self._stopMesos()
|
|
213
238
|
|
|
214
239
|
def testFileSingle(self):
|
|
215
|
-
self._toilSort(
|
|
240
|
+
self._toilSort(
|
|
241
|
+
jobStoreLocator=self._getTestJobStorePath(), batchSystem="single_machine"
|
|
242
|
+
)
|
|
216
243
|
|
|
217
244
|
def testFileSingleNonCaching(self):
|
|
218
|
-
self._toilSort(
|
|
219
|
-
|
|
245
|
+
self._toilSort(
|
|
246
|
+
jobStoreLocator=self._getTestJobStorePath(),
|
|
247
|
+
batchSystem="single_machine",
|
|
248
|
+
caching=False,
|
|
249
|
+
)
|
|
220
250
|
|
|
221
251
|
def testFileSingleCheckpoints(self):
|
|
222
|
-
self._toilSort(
|
|
223
|
-
|
|
252
|
+
self._toilSort(
|
|
253
|
+
jobStoreLocator=self._getTestJobStorePath(),
|
|
254
|
+
batchSystem="single_machine",
|
|
255
|
+
retryCount=2,
|
|
256
|
+
downCheckpoints=True,
|
|
257
|
+
)
|
|
224
258
|
|
|
225
259
|
def testFileSingle10000(self):
|
|
226
|
-
self._toilSort(
|
|
227
|
-
|
|
260
|
+
self._toilSort(
|
|
261
|
+
jobStoreLocator=self._getTestJobStorePath(),
|
|
262
|
+
batchSystem="single_machine",
|
|
263
|
+
lines=10000,
|
|
264
|
+
N=10000,
|
|
265
|
+
)
|
|
228
266
|
|
|
229
267
|
@needs_gridengine
|
|
230
|
-
@unittest.skip(
|
|
268
|
+
@unittest.skip("GridEngine does not support shared caching")
|
|
231
269
|
def testFileGridEngine(self):
|
|
232
|
-
self._toilSort(
|
|
270
|
+
self._toilSort(
|
|
271
|
+
jobStoreLocator=self._getTestJobStorePath(), batchSystem="gridengine"
|
|
272
|
+
)
|
|
233
273
|
|
|
234
274
|
@needs_torque
|
|
235
|
-
@unittest.skip(
|
|
275
|
+
@unittest.skip("PBS/Torque does not support shared caching")
|
|
236
276
|
def testFileTorqueEngine(self):
|
|
237
|
-
self._toilSort(
|
|
277
|
+
self._toilSort(
|
|
278
|
+
jobStoreLocator=self._getTestJobStorePath(), batchSystem="torque"
|
|
279
|
+
)
|
|
238
280
|
|
|
239
281
|
testNo = 5
|
|
240
282
|
|
|
@@ -258,7 +300,7 @@ class SortTest(ToilTest, MesosTestSupport):
|
|
|
258
300
|
makeFileToSort(tempFile2)
|
|
259
301
|
sort(tempFile1)
|
|
260
302
|
sort(tempFile2)
|
|
261
|
-
with open(tempFile3,
|
|
303
|
+
with open(tempFile3, "w") as fileHandle:
|
|
262
304
|
with open(tempFile1) as tempFileHandle1:
|
|
263
305
|
with open(tempFile2) as tempFileHandle2:
|
|
264
306
|
merge(tempFileHandle1, tempFileHandle2, fileHandle)
|
|
@@ -277,7 +319,7 @@ class SortTest(ToilTest, MesosTestSupport):
|
|
|
277
319
|
assert fileSize > 0
|
|
278
320
|
fileStart = random.choice(range(0, fileSize))
|
|
279
321
|
fileEnd = random.choice(range(fileStart, fileSize))
|
|
280
|
-
with open(outputFile,
|
|
322
|
+
with open(outputFile, "w") as f:
|
|
281
323
|
f.write(copySubRangeOfFile(tempFile, fileStart, fileEnd))
|
|
282
324
|
with open(outputFile) as f:
|
|
283
325
|
l = f.read()
|
|
@@ -294,11 +336,11 @@ class SortTest(ToilTest, MesosTestSupport):
|
|
|
294
336
|
midPoint = getMidPoint(self.inputFile, 0, fileSize)
|
|
295
337
|
print(f"The mid point is {midPoint} of a file of {fileSize} bytes.")
|
|
296
338
|
assert midPoint < fileSize
|
|
297
|
-
assert sorted_contents[midPoint] ==
|
|
339
|
+
assert sorted_contents[midPoint] == "\n"
|
|
298
340
|
assert midPoint >= 0
|
|
299
341
|
|
|
300
342
|
def _awsJobStore(self):
|
|
301
|
-
return f
|
|
343
|
+
return f"aws:{self.awsRegion()}:sort-test-{uuid4()}"
|
|
302
344
|
|
|
303
345
|
def _googleJobStore(self):
|
|
304
346
|
return f'google:{os.getenv("TOIL_GOOGLE_PROJECTID")}:sort-test-{uuid4()}'
|
|
@@ -5,10 +5,7 @@ from contextlib import contextmanager
|
|
|
5
5
|
|
|
6
6
|
from toil.exceptions import FailedJobsException
|
|
7
7
|
from toil.lib.iterables import concat
|
|
8
|
-
from toil.test import
|
|
9
|
-
needs_local_appliance,
|
|
10
|
-
needs_mesos,
|
|
11
|
-
slow)
|
|
8
|
+
from toil.test import ApplianceTestSupport, needs_local_appliance, needs_mesos, slow
|
|
12
9
|
from toil.version import exactPython
|
|
13
10
|
|
|
14
11
|
logger = logging.getLogger(__name__)
|
|
@@ -35,34 +32,38 @@ class AutoDeploymentTest(ApplianceTestSupport):
|
|
|
35
32
|
Creates an appliance cluster with a virtualenv at './venv' on the leader and a temporary
|
|
36
33
|
directory on the host mounted at /data in the leader and worker containers.
|
|
37
34
|
"""
|
|
38
|
-
dataDirPath = self._createTempDir(purpose=
|
|
39
|
-
with self._applianceCluster(mounts={dataDirPath:
|
|
40
|
-
leader.runOnAppliance(
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
35
|
+
dataDirPath = self._createTempDir(purpose="data")
|
|
36
|
+
with self._applianceCluster(mounts={dataDirPath: "/data"}) as (leader, worker):
|
|
37
|
+
leader.runOnAppliance(
|
|
38
|
+
"virtualenv",
|
|
39
|
+
"--system-site-packages",
|
|
40
|
+
"--never-download", # prevent silent upgrades to pip etc
|
|
41
|
+
"--python",
|
|
42
|
+
exactPython,
|
|
43
|
+
"venv",
|
|
44
|
+
)
|
|
45
|
+
leader.runOnAppliance("venv/bin/pip", "list") # For diagnostic purposes
|
|
46
46
|
yield leader, worker
|
|
47
47
|
|
|
48
48
|
# TODO: Are we sure the python in the appliance we are testing is the same
|
|
49
49
|
# as the one we are testing from? If not, how can we get the version it is?
|
|
50
|
-
sitePackages = f
|
|
50
|
+
sitePackages = f"venv/lib/{exactPython}/site-packages"
|
|
51
51
|
|
|
52
52
|
def testRestart(self):
|
|
53
53
|
"""
|
|
54
54
|
Test whether auto-deployment works on restart.
|
|
55
55
|
"""
|
|
56
56
|
with self._venvApplianceCluster() as (leader, worker):
|
|
57
|
+
|
|
57
58
|
def userScript():
|
|
58
59
|
from toil.common import Toil
|
|
59
60
|
from toil.job import Job
|
|
60
61
|
|
|
61
62
|
# noinspection PyUnusedLocal
|
|
62
|
-
def job(job, disk=
|
|
63
|
+
def job(job, disk="10M", cores=1, memory="10M"):
|
|
63
64
|
assert False
|
|
64
65
|
|
|
65
|
-
if __name__ ==
|
|
66
|
+
if __name__ == "__main__":
|
|
66
67
|
options = Job.Runner.getDefaultArgumentParser().parse_args()
|
|
67
68
|
with Toil(options) as toil:
|
|
68
69
|
if toil.config.restart:
|
|
@@ -72,26 +73,30 @@ class AutoDeploymentTest(ApplianceTestSupport):
|
|
|
72
73
|
|
|
73
74
|
userScript = self._getScriptSource(userScript)
|
|
74
75
|
|
|
75
|
-
leader.deployScript(
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
pythonArgs = [
|
|
80
|
-
toilArgs = [
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
76
|
+
leader.deployScript(
|
|
77
|
+
path=self.sitePackages, packagePath="foo.bar", script=userScript
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
pythonArgs = ["venv/bin/python", "-m", "foo.bar"]
|
|
81
|
+
toilArgs = [
|
|
82
|
+
"--logDebug",
|
|
83
|
+
"--batchSystem=mesos",
|
|
84
|
+
"--mesosEndpoint=localhost:5050",
|
|
85
|
+
"--defaultMemory=10M",
|
|
86
|
+
"/data/jobstore",
|
|
87
|
+
]
|
|
85
88
|
command = concat(pythonArgs, toilArgs)
|
|
86
|
-
self.assertRaises(
|
|
89
|
+
self.assertRaises(
|
|
90
|
+
subprocess.CalledProcessError, leader.runOnAppliance, *command
|
|
91
|
+
)
|
|
87
92
|
|
|
88
93
|
# Deploy an updated version of the script ...
|
|
89
|
-
userScript = userScript.replace(
|
|
90
|
-
leader.deployScript(
|
|
91
|
-
|
|
92
|
-
|
|
94
|
+
userScript = userScript.replace("assert False", "assert True")
|
|
95
|
+
leader.deployScript(
|
|
96
|
+
path=self.sitePackages, packagePath="foo.bar", script=userScript
|
|
97
|
+
)
|
|
93
98
|
# ... and restart Toil.
|
|
94
|
-
command = concat(pythonArgs,
|
|
99
|
+
command = concat(pythonArgs, "--restart", toilArgs)
|
|
95
100
|
leader.runOnAppliance(*command)
|
|
96
101
|
|
|
97
102
|
def testSplitRootPackages(self):
|
|
@@ -109,11 +114,11 @@ class AutoDeploymentTest(ApplianceTestSupport):
|
|
|
109
114
|
def libraryModule():
|
|
110
115
|
# noinspection PyUnusedLocal
|
|
111
116
|
def libraryJob(job):
|
|
112
|
-
open(
|
|
117
|
+
open("/data/foo.txt", "w").close()
|
|
113
118
|
|
|
114
|
-
leader.deployScript(
|
|
115
|
-
|
|
116
|
-
|
|
119
|
+
leader.deployScript(
|
|
120
|
+
path=self.sitePackages, packagePath="toil_lib.foo", script=libraryModule
|
|
121
|
+
)
|
|
117
122
|
|
|
118
123
|
# Deploy the user script
|
|
119
124
|
def userScript():
|
|
@@ -124,12 +129,14 @@ class AutoDeploymentTest(ApplianceTestSupport):
|
|
|
124
129
|
from toil.job import Job
|
|
125
130
|
|
|
126
131
|
# noinspection PyUnusedLocal
|
|
127
|
-
def job(job, disk=
|
|
132
|
+
def job(job, disk="10M", cores=1, memory="10M"):
|
|
128
133
|
# Double the requirements to prevent chaining as chaining might hide problems
|
|
129
134
|
# in auto-deployment code.
|
|
130
|
-
job.addChildJobFn(
|
|
135
|
+
job.addChildJobFn(
|
|
136
|
+
libraryJob, disk="20M", cores=cores, memory=memory
|
|
137
|
+
)
|
|
131
138
|
|
|
132
|
-
if __name__ ==
|
|
139
|
+
if __name__ == "__main__":
|
|
133
140
|
options = Job.Runner.getDefaultArgumentParser().parse_args()
|
|
134
141
|
with Toil(options) as toil:
|
|
135
142
|
if toil.config.restart:
|
|
@@ -137,24 +144,32 @@ class AutoDeploymentTest(ApplianceTestSupport):
|
|
|
137
144
|
else:
|
|
138
145
|
toil.start(Job.wrapJobFn(job))
|
|
139
146
|
|
|
140
|
-
leader.deployScript(
|
|
141
|
-
|
|
142
|
-
|
|
147
|
+
leader.deployScript(
|
|
148
|
+
path=self.sitePackages, packagePath="toil_script.bar", script=userScript
|
|
149
|
+
)
|
|
143
150
|
|
|
144
151
|
# Assert that output file isn't there
|
|
145
|
-
worker.runOnAppliance(
|
|
152
|
+
worker.runOnAppliance("test", "!", "-f", "/data/foo.txt")
|
|
146
153
|
# Just being paranoid
|
|
147
|
-
self.assertRaises(
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
154
|
+
self.assertRaises(
|
|
155
|
+
subprocess.CalledProcessError,
|
|
156
|
+
worker.runOnAppliance,
|
|
157
|
+
"test",
|
|
158
|
+
"-f",
|
|
159
|
+
"/data/foo.txt",
|
|
160
|
+
)
|
|
161
|
+
leader.runOnAppliance(
|
|
162
|
+
"venv/bin/python",
|
|
163
|
+
"-m",
|
|
164
|
+
"toil_script.bar",
|
|
165
|
+
"--logDebug",
|
|
166
|
+
"--batchSystem=mesos",
|
|
167
|
+
"--mesosEndpoint=localhost:5050",
|
|
168
|
+
"--defaultMemory=10M",
|
|
169
|
+
"/data/jobstore",
|
|
170
|
+
)
|
|
156
171
|
# Assert that out output file is there
|
|
157
|
-
worker.runOnAppliance(
|
|
172
|
+
worker.runOnAppliance("test", "-f", "/data/foo.txt")
|
|
158
173
|
|
|
159
174
|
def testUserTypesInJobFunctionArgs(self):
|
|
160
175
|
"""
|
|
@@ -165,6 +180,7 @@ class AutoDeploymentTest(ApplianceTestSupport):
|
|
|
165
180
|
revealed https://github.com/BD2KGenomics/toil/issues/1278.
|
|
166
181
|
"""
|
|
167
182
|
with self._venvApplianceCluster() as (leader, worker):
|
|
183
|
+
|
|
168
184
|
def userScript():
|
|
169
185
|
from toil.common import Toil
|
|
170
186
|
from toil.job import Job
|
|
@@ -174,10 +190,10 @@ class AutoDeploymentTest(ApplianceTestSupport):
|
|
|
174
190
|
pass
|
|
175
191
|
|
|
176
192
|
# noinspection PyUnusedLocal
|
|
177
|
-
def job(job, x, disk=
|
|
193
|
+
def job(job, x, disk="10M", cores=1, memory="10M"):
|
|
178
194
|
return x
|
|
179
195
|
|
|
180
|
-
if __name__ ==
|
|
196
|
+
if __name__ == "__main__":
|
|
181
197
|
options = Job.Runner.getDefaultArgumentParser().parse_args()
|
|
182
198
|
x = X()
|
|
183
199
|
with Toil(options) as toil:
|
|
@@ -187,23 +203,28 @@ class AutoDeploymentTest(ApplianceTestSupport):
|
|
|
187
203
|
# translation from __main__ to foo.bar is a side effect of auto-deployment.
|
|
188
204
|
assert r.__class__ is not X
|
|
189
205
|
import foo.bar
|
|
206
|
+
|
|
190
207
|
assert r.__class__ is foo.bar.X
|
|
191
208
|
# Assert that a copy was made. This is a side effect of pickling/unpickling.
|
|
192
209
|
assert x is not r
|
|
193
210
|
|
|
194
211
|
userScript = self._getScriptSource(userScript)
|
|
195
212
|
|
|
196
|
-
leader.deployScript(
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
leader.runOnAppliance(
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
213
|
+
leader.deployScript(
|
|
214
|
+
path=self.sitePackages, packagePath="foo.bar", script=userScript
|
|
215
|
+
)
|
|
216
|
+
|
|
217
|
+
leader.runOnAppliance(
|
|
218
|
+
"venv/bin/python",
|
|
219
|
+
"-m",
|
|
220
|
+
"foo.bar",
|
|
221
|
+
"--logDebug",
|
|
222
|
+
"--batchSystem=mesos",
|
|
223
|
+
"--mesosEndpoint=localhost:5050",
|
|
224
|
+
"--defaultMemory=10M",
|
|
225
|
+
"--defaultDisk=10M",
|
|
226
|
+
"/data/jobstore",
|
|
227
|
+
)
|
|
207
228
|
|
|
208
229
|
def testDeferralWithConcurrentEncapsulation(self):
|
|
209
230
|
"""
|
|
@@ -243,18 +264,21 @@ class AutoDeploymentTest(ApplianceTestSupport):
|
|
|
243
264
|
|
|
244
265
|
3) it is an instance of Job (and so does not introduce the user script to sys.path itself),
|
|
245
266
|
|
|
246
|
-
… it might cause problems with deserializing a
|
|
267
|
+
… it might cause problems with deserializing a deferred function defined in the user script.
|
|
247
268
|
|
|
248
269
|
`Encapsulated` has two children to ensure that `Follow-on` is run in a separate worker.
|
|
249
270
|
"""
|
|
250
271
|
with self._venvApplianceCluster() as (leader, worker):
|
|
272
|
+
|
|
251
273
|
def userScript():
|
|
252
274
|
from toil.common import Toil
|
|
253
275
|
from toil.job import Job
|
|
254
276
|
|
|
255
277
|
def root(rootJob):
|
|
256
278
|
def nullFile():
|
|
257
|
-
return rootJob.fileStore.jobStore.import_file(
|
|
279
|
+
return rootJob.fileStore.jobStore.import_file(
|
|
280
|
+
"file:///dev/null"
|
|
281
|
+
)
|
|
258
282
|
|
|
259
283
|
startFile = nullFile()
|
|
260
284
|
endFile = nullFile()
|
|
@@ -290,7 +314,7 @@ class AutoDeploymentTest(ApplianceTestSupport):
|
|
|
290
314
|
def last(job, endFile):
|
|
291
315
|
job.fileStore.jobStore.delete_file(endFile)
|
|
292
316
|
|
|
293
|
-
if __name__ ==
|
|
317
|
+
if __name__ == "__main__":
|
|
294
318
|
options = Job.Runner.getDefaultArgumentParser().parse_args()
|
|
295
319
|
with Toil(options) as toil:
|
|
296
320
|
rootJob = Job.wrapJobFn(root)
|
|
@@ -298,18 +322,22 @@ class AutoDeploymentTest(ApplianceTestSupport):
|
|
|
298
322
|
|
|
299
323
|
userScript = self._getScriptSource(userScript)
|
|
300
324
|
|
|
301
|
-
leader.deployScript(
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
leader.runOnAppliance(
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
325
|
+
leader.deployScript(
|
|
326
|
+
path=self.sitePackages, packagePath="foo.bar", script=userScript
|
|
327
|
+
)
|
|
328
|
+
|
|
329
|
+
leader.runOnAppliance(
|
|
330
|
+
"venv/bin/python",
|
|
331
|
+
"-m",
|
|
332
|
+
"foo.bar",
|
|
333
|
+
"--logDebug",
|
|
334
|
+
"--batchSystem=mesos",
|
|
335
|
+
"--mesosEndpoint=localhost:5050",
|
|
336
|
+
"--retryCount=0",
|
|
337
|
+
"--defaultMemory=10M",
|
|
338
|
+
"--defaultDisk=10M",
|
|
339
|
+
"/data/jobstore",
|
|
340
|
+
)
|
|
313
341
|
|
|
314
342
|
def testDeferralWithFailureAndEncapsulation(self):
|
|
315
343
|
"""
|
|
@@ -348,6 +376,7 @@ class AutoDeploymentTest(ApplianceTestSupport):
|
|
|
348
376
|
jobs have been executed by that worker.
|
|
349
377
|
"""
|
|
350
378
|
with self._venvApplianceCluster() as (leader, worker):
|
|
379
|
+
|
|
351
380
|
def userScript():
|
|
352
381
|
import os
|
|
353
382
|
import time
|
|
@@ -359,7 +388,9 @@ class AutoDeploymentTest(ApplianceTestSupport):
|
|
|
359
388
|
|
|
360
389
|
def root(rootJob):
|
|
361
390
|
def nullFile():
|
|
362
|
-
return rootJob.fileStore.jobStore.import_file(
|
|
391
|
+
return rootJob.fileStore.jobStore.import_file(
|
|
392
|
+
"file:///dev/null"
|
|
393
|
+
)
|
|
363
394
|
|
|
364
395
|
startFile = nullFile()
|
|
365
396
|
endFile = nullFile()
|
|
@@ -380,10 +411,10 @@ class AutoDeploymentTest(ApplianceTestSupport):
|
|
|
380
411
|
Return path to a file at the root of the job store, exploiting the fact that
|
|
381
412
|
the job store is shared between leader and worker container.
|
|
382
413
|
"""
|
|
383
|
-
prefix =
|
|
414
|
+
prefix = "file:"
|
|
384
415
|
locator = config.jobStore
|
|
385
416
|
assert locator.startswith(prefix)
|
|
386
|
-
return os.path.join(locator[len(prefix):],
|
|
417
|
+
return os.path.join(locator[len(prefix) :], "testDeferredFile")
|
|
387
418
|
|
|
388
419
|
def deferred(deferredFilePath):
|
|
389
420
|
"""
|
|
@@ -425,6 +456,7 @@ class AutoDeploymentTest(ApplianceTestSupport):
|
|
|
425
456
|
finds the left-overs of the `deferring` job.
|
|
426
457
|
"""
|
|
427
458
|
import errno
|
|
459
|
+
|
|
428
460
|
jobStore = job.fileStore.jobStore
|
|
429
461
|
with jobStore.read_file_stream(endFile) as fH:
|
|
430
462
|
pid = int(fH.read())
|
|
@@ -452,36 +484,44 @@ class AutoDeploymentTest(ApplianceTestSupport):
|
|
|
452
484
|
else:
|
|
453
485
|
raise
|
|
454
486
|
|
|
455
|
-
if __name__ ==
|
|
487
|
+
if __name__ == "__main__":
|
|
456
488
|
import errno
|
|
489
|
+
|
|
457
490
|
options = Job.Runner.getDefaultArgumentParser().parse_args()
|
|
458
491
|
with Toil(options) as toil:
|
|
459
492
|
deferredFilePath = deferredFile(toil.config)
|
|
460
|
-
open(deferredFilePath,
|
|
493
|
+
open(deferredFilePath, "w").close()
|
|
461
494
|
try:
|
|
462
495
|
assert os.path.exists(deferredFilePath)
|
|
463
496
|
try:
|
|
464
497
|
toil.start(Job.wrapJobFn(root))
|
|
465
498
|
except FailedJobsException as e:
|
|
466
|
-
assert
|
|
467
|
-
|
|
468
|
-
|
|
499
|
+
assert (
|
|
500
|
+
e.numberOfFailedJobs == 2
|
|
501
|
+
) # `root` and `deferring`
|
|
502
|
+
assert not os.path.exists(
|
|
503
|
+
deferredFilePath
|
|
504
|
+
), "Apparently, the deferred function did not run."
|
|
469
505
|
else:
|
|
470
|
-
assert False,
|
|
506
|
+
assert False, "Workflow should not have succeeded."
|
|
471
507
|
finally:
|
|
472
508
|
tryUnlink(deferredFilePath)
|
|
473
509
|
|
|
474
510
|
userScript = self._getScriptSource(userScript)
|
|
475
511
|
|
|
476
|
-
leader.deployScript(
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
leader.runOnAppliance(
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
512
|
+
leader.deployScript(
|
|
513
|
+
path=self.sitePackages, packagePath="foo.bar", script=userScript
|
|
514
|
+
)
|
|
515
|
+
|
|
516
|
+
leader.runOnAppliance(
|
|
517
|
+
"venv/bin/python",
|
|
518
|
+
"-m",
|
|
519
|
+
"foo.bar",
|
|
520
|
+
"--logDebug",
|
|
521
|
+
"--batchSystem=mesos",
|
|
522
|
+
"--mesosEndpoint=localhost:5050",
|
|
523
|
+
"--retryCount=0",
|
|
524
|
+
"--defaultMemory=10M",
|
|
525
|
+
"--defaultDisk=10M",
|
|
526
|
+
"/data/jobstore",
|
|
527
|
+
)
|