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
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# Copyright (C) 2015-2021 Regents of the University of California
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
import logging
|
|
15
|
+
from typing import Optional
|
|
16
|
+
|
|
17
|
+
from configargparse import ArgParser, ArgumentParser
|
|
18
|
+
|
|
19
|
+
from toil.batchSystems.abstractBatchSystem import (
|
|
20
|
+
AbstractBatchSystem,
|
|
21
|
+
UpdatedBatchJobInfo,
|
|
22
|
+
)
|
|
23
|
+
from toil.batchSystems.cleanup_support import BatchSystemCleanupSupport
|
|
24
|
+
from toil.batchSystems.options import OptionSetter
|
|
25
|
+
from toil.batchSystems.registry import add_batch_system_factory
|
|
26
|
+
from toil.common import Toil, addOptions
|
|
27
|
+
from toil.job import JobDescription
|
|
28
|
+
from toil.test import ToilTest
|
|
29
|
+
|
|
30
|
+
logger = logging.getLogger(__name__)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class FakeBatchSystem(BatchSystemCleanupSupport):
|
|
34
|
+
@classmethod
|
|
35
|
+
def supportsAutoDeployment(cls) -> bool:
|
|
36
|
+
pass
|
|
37
|
+
|
|
38
|
+
def issueBatchJob(
|
|
39
|
+
self,
|
|
40
|
+
command: str,
|
|
41
|
+
job_desc: JobDescription,
|
|
42
|
+
job_environment: Optional[dict[str, str]] = None,
|
|
43
|
+
) -> int:
|
|
44
|
+
pass
|
|
45
|
+
|
|
46
|
+
def killBatchJobs(self, jobIDs: list[int]) -> None:
|
|
47
|
+
pass
|
|
48
|
+
|
|
49
|
+
def getIssuedBatchJobIDs(self) -> list[int]:
|
|
50
|
+
pass
|
|
51
|
+
|
|
52
|
+
def getRunningBatchJobIDs(self) -> dict[int, float]:
|
|
53
|
+
pass
|
|
54
|
+
|
|
55
|
+
def getUpdatedBatchJob(self, maxWait: int) -> Optional[UpdatedBatchJobInfo]:
|
|
56
|
+
pass
|
|
57
|
+
|
|
58
|
+
def shutdown(self) -> None:
|
|
59
|
+
pass
|
|
60
|
+
|
|
61
|
+
@classmethod
|
|
62
|
+
def add_options(cls, parser: ArgumentParser) -> None:
|
|
63
|
+
parser.add_argument("--fake_argument", default="exists")
|
|
64
|
+
|
|
65
|
+
@classmethod
|
|
66
|
+
def setOptions(cls, setOption: OptionSetter) -> None:
|
|
67
|
+
setOption("fake_argument")
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
class BatchSystemPluginTest(ToilTest):
|
|
71
|
+
def test_batchsystem_plugin_installable(self):
|
|
72
|
+
"""
|
|
73
|
+
Test that installing a batch system plugin works.
|
|
74
|
+
:return:
|
|
75
|
+
"""
|
|
76
|
+
|
|
77
|
+
def fake_batch_system_factory() -> type[AbstractBatchSystem]:
|
|
78
|
+
return FakeBatchSystem
|
|
79
|
+
|
|
80
|
+
add_batch_system_factory("fake", fake_batch_system_factory)
|
|
81
|
+
|
|
82
|
+
parser = ArgParser()
|
|
83
|
+
addOptions(parser)
|
|
84
|
+
|
|
85
|
+
options = parser.parse_args(["test-jobstore", "--clean=always"])
|
|
86
|
+
|
|
87
|
+
# try to install a batchsystem plugin with some arguments
|
|
88
|
+
# if the arguments exists, the values should also exist in the config
|
|
89
|
+
with Toil(options) as toil:
|
|
90
|
+
self.assertEqual(toil.config.fake_argument == "exists", True)
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import textwrap
|
|
2
|
+
from queue import Queue
|
|
3
|
+
|
|
4
|
+
import pytest
|
|
5
|
+
|
|
6
|
+
import toil.batchSystems.gridengine
|
|
7
|
+
from toil.batchSystems.abstractGridEngineBatchSystem import ExceededRetryAttempts
|
|
8
|
+
from toil.common import Config
|
|
9
|
+
from toil.lib.misc import CalledProcessErrorStderr
|
|
10
|
+
from toil.test import ToilTest
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class FakeBatchSystem:
|
|
14
|
+
"""
|
|
15
|
+
Class that implements a minimal Batch System, needed to create a Worker (see below).
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
def __init__(self):
|
|
19
|
+
self.config = self.__fake_config()
|
|
20
|
+
|
|
21
|
+
def getWaitDuration(self):
|
|
22
|
+
return 10
|
|
23
|
+
|
|
24
|
+
def __fake_config(self):
|
|
25
|
+
"""
|
|
26
|
+
Returns a dummy config for the batch system tests. We need a workflowID to be set up
|
|
27
|
+
since we are running tests without setting up a jobstore. This is the class version
|
|
28
|
+
to be used when an instance is not available.
|
|
29
|
+
|
|
30
|
+
:rtype: toil.common.Config
|
|
31
|
+
"""
|
|
32
|
+
config = Config()
|
|
33
|
+
from uuid import uuid4
|
|
34
|
+
|
|
35
|
+
config.workflowID = str(uuid4())
|
|
36
|
+
config.cleanWorkDir = "always"
|
|
37
|
+
return config
|
|
38
|
+
|
|
39
|
+
def with_retries(self, operation, *args, **kwargs):
|
|
40
|
+
"""
|
|
41
|
+
The grid engine batch system needs a with_retries function when running the GridEngineThread, so fake one
|
|
42
|
+
"""
|
|
43
|
+
return operation(*args, **kwargs)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def call_qstat_or_qacct(args, **_):
|
|
47
|
+
# example outputs taken from https://2021.help.altair.com/2021.1/AltairGridEngine/8.7.0/UsersGuideGE.pdf
|
|
48
|
+
qacct_info = {}
|
|
49
|
+
job_id_info = {
|
|
50
|
+
1: {"failed": True, "exit_code": 0, "completed": True},
|
|
51
|
+
2: {"failed": True, "exit_code": 2, "completed": True},
|
|
52
|
+
3: {"failed": False, "exit_code": 0, "completed": True},
|
|
53
|
+
4: {"failed": False, "exit_code": 10, "completed": True},
|
|
54
|
+
5: {"failed": False, "exit_code": 0, "completed": False},
|
|
55
|
+
}
|
|
56
|
+
for job_id, status_info in job_id_info.items():
|
|
57
|
+
failed = 1 if status_info["failed"] else 0
|
|
58
|
+
exit_status = status_info["exit_code"]
|
|
59
|
+
qacct_info[job_id] = textwrap.dedent(
|
|
60
|
+
f"""\
|
|
61
|
+
==============================================================
|
|
62
|
+
qname all.q
|
|
63
|
+
hostname kailua
|
|
64
|
+
group users
|
|
65
|
+
owner jondoe
|
|
66
|
+
project NONE
|
|
67
|
+
department defaultdepartment
|
|
68
|
+
jobname Sleeper
|
|
69
|
+
jobnumber 10
|
|
70
|
+
taskid undefined
|
|
71
|
+
account sge
|
|
72
|
+
priority 0
|
|
73
|
+
qsub_time Thu Mar 10 19:58:35 2011
|
|
74
|
+
start_time Thu Mar 10 19:58:42 2011
|
|
75
|
+
end_time Thu Mar 10 19:59:43 2011
|
|
76
|
+
granted_pe NONE
|
|
77
|
+
slots 1
|
|
78
|
+
failed {failed}
|
|
79
|
+
exit_status {exit_status}
|
|
80
|
+
ru_wallclock 61
|
|
81
|
+
ru_utime 0.070
|
|
82
|
+
ru_stime 0.050
|
|
83
|
+
ru_maxrss 1220
|
|
84
|
+
ru_ixrss 0
|
|
85
|
+
ru_ismrss 0
|
|
86
|
+
ru_idrss 0
|
|
87
|
+
"""
|
|
88
|
+
)
|
|
89
|
+
if args[0] == "qstat":
|
|
90
|
+
# This is guess for what qstat will return given a job. I'm unable to find an example for qstat.
|
|
91
|
+
# This also assumes the second argument args[1] is -j, as that is what we try to use
|
|
92
|
+
job_id = int(args[2])
|
|
93
|
+
if job_id not in job_id_info.keys() or job_id_info[job_id]["completed"]:
|
|
94
|
+
stderr = f"Following jobs do not exist {job_id}"
|
|
95
|
+
else:
|
|
96
|
+
# This is not the output of qstat when the job is running, and is just a guess
|
|
97
|
+
# We test on the existence of the string "Following jobs do not exist", so this should be okay for now
|
|
98
|
+
stderr = f"Job exists {job_id}"
|
|
99
|
+
raise CalledProcessErrorStderr(2, args, stderr=stderr)
|
|
100
|
+
elif args[0] == "qacct":
|
|
101
|
+
if args[1] != "-j":
|
|
102
|
+
# Documentation for qacct says if -j is not found then all jobs are listed
|
|
103
|
+
# https://gridscheduler.sourceforge.net/htmlman/htmlman1/qacct.html
|
|
104
|
+
# This is a guess for the output of qacct. We don't have a SGE cluster and I can't find a bare qacct example output online
|
|
105
|
+
qacct_response = "\n".join(qacct_info.values())
|
|
106
|
+
else:
|
|
107
|
+
job_id = int(args[2])
|
|
108
|
+
if job_id not in job_id_info.keys():
|
|
109
|
+
# This is a guess of the behavior when the job does not exist. Since the behavior is unknown, this is not currently tested
|
|
110
|
+
return ""
|
|
111
|
+
qacct_response = qacct_info[job_id]
|
|
112
|
+
|
|
113
|
+
return qacct_response
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
class GridEngineTest(ToilTest):
|
|
117
|
+
"""
|
|
118
|
+
Class for unit-testing GridEngineBatchSystem
|
|
119
|
+
"""
|
|
120
|
+
|
|
121
|
+
def setUp(self):
|
|
122
|
+
self.monkeypatch = pytest.MonkeyPatch()
|
|
123
|
+
self.worker = (
|
|
124
|
+
toil.batchSystems.gridengine.GridEngineBatchSystem.GridEngineThread(
|
|
125
|
+
newJobsQueue=Queue(),
|
|
126
|
+
updatedJobsQueue=Queue(),
|
|
127
|
+
killQueue=Queue(),
|
|
128
|
+
killedJobsQueue=Queue(),
|
|
129
|
+
boss=FakeBatchSystem(),
|
|
130
|
+
)
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
###
|
|
134
|
+
### Tests for coalesce_job_exit_codes for gridengine.
|
|
135
|
+
###
|
|
136
|
+
|
|
137
|
+
def test_coalesce_job_exit_codes_one_exists(self):
|
|
138
|
+
self.monkeypatch.setattr(
|
|
139
|
+
toil.batchSystems.gridengine, "call_command", call_qstat_or_qacct
|
|
140
|
+
)
|
|
141
|
+
job_ids = ["1"] # FAILED
|
|
142
|
+
expected_result = [1]
|
|
143
|
+
result = self.worker.coalesce_job_exit_codes(job_ids)
|
|
144
|
+
assert result == expected_result, f"{result} != {expected_result}"
|
|
145
|
+
|
|
146
|
+
def test_coalesce_job_exit_codes_one_still_running(self):
|
|
147
|
+
self.monkeypatch.setattr(
|
|
148
|
+
toil.batchSystems.gridengine, "call_command", call_qstat_or_qacct
|
|
149
|
+
)
|
|
150
|
+
job_ids = [
|
|
151
|
+
"5"
|
|
152
|
+
] # Still running. We currently raise an exception when this happens
|
|
153
|
+
try:
|
|
154
|
+
self.worker.coalesce_job_exit_codes(job_ids)
|
|
155
|
+
except ExceededRetryAttempts:
|
|
156
|
+
pass
|
|
157
|
+
else:
|
|
158
|
+
raise RuntimeError("Test did not raise an exception!")
|
|
159
|
+
|
|
160
|
+
def test_coalesce_job_exit_codes_many_all_exist(self):
|
|
161
|
+
self.monkeypatch.setattr(
|
|
162
|
+
toil.batchSystems.gridengine, "call_command", call_qstat_or_qacct
|
|
163
|
+
)
|
|
164
|
+
job_ids = [
|
|
165
|
+
"1", # FAILED,
|
|
166
|
+
"2", # FAILED (with exit code that we ignore),
|
|
167
|
+
"3", # SUCCEEDED,
|
|
168
|
+
"4",
|
|
169
|
+
] # EXIT CODE 10
|
|
170
|
+
# RUNNING and PENDING jobs should return None
|
|
171
|
+
expected_result = [1, 1, 0, 10]
|
|
172
|
+
result = self.worker.coalesce_job_exit_codes(job_ids)
|
|
173
|
+
assert result == expected_result, f"{result} != {expected_result}"
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"""lsfHelper.py shouldn't need a batch system and so the unit tests here should aim to run on any system."""
|
|
2
|
+
|
|
2
3
|
from toil.batchSystems.lsfHelper import parse_mem_and_cmd_from_output
|
|
3
4
|
from toil.test import ToilTest
|
|
4
5
|
|
|
@@ -6,69 +7,77 @@ from toil.test import ToilTest
|
|
|
6
7
|
class LSFHelperTest(ToilTest):
|
|
7
8
|
def test_parse_mem_and_cmd_from_output(self):
|
|
8
9
|
# https://github.com/DataBiosphere/toil/pull/3475
|
|
9
|
-
output = (
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
10
|
+
output = (
|
|
11
|
+
"\nJob <2924748>, Job Name <toil_job_64>, User <thiagogenez>, Project <default>, S"
|
|
12
|
+
"\n tatus <RUN>, Queue <research-rh74>, Job Priority <50>, Com"
|
|
13
|
+
"\n mand <_toil_worker CactusBarRecursion file:/hps/nobackup/p"
|
|
14
|
+
"\n roduction/ensembl/thiagogenez/pairwises/arabidopsis/run/jo"
|
|
15
|
+
"\n bstore/3 kind-CactusBarRecursion/instance-iu6wo56x --conte"
|
|
16
|
+
"\n xt gAShortenedh32xqlE51Yi4=>, Share group charged </thiago"
|
|
17
|
+
"\n genez>, Esub <esub>"
|
|
18
|
+
"\nThu Mar 18 02:06:32: Submitted from host <noah-login-01>, CWD </hps/nobackup/pr"
|
|
19
|
+
"\n oduction/ensembl/thiagogenez/pairwises/arabidopsis/run>, S"
|
|
20
|
+
"\n pecified CWD </hps/nobackup/production/ensembl/thiagogenez"
|
|
21
|
+
"\n /pairwises/arabidopsis/run/.>, Output File </tmp/toil_work"
|
|
22
|
+
"\n flow_10e83102-2e4b-4093-9128-2a52f4bbc65a_job_64_batch_lsf"
|
|
23
|
+
"\n _2924748_std_output.log>, Error File </tmp/toil_workflow_1"
|
|
24
|
+
"\n 0e83102-2e4b-4093-9128-2a52f4bbc65a_job_64_batch_lsf_29247"
|
|
25
|
+
"\n 48_std_error.log>, Requested Resources <select[(mem>4000)]"
|
|
26
|
+
"\n rusage[mem=4000:duration=480, numcpus=1:duration=480]>;"
|
|
27
|
+
"\nThu Mar 18 02:06:33: Started on <hx-noah-31-02>, Execution Home </homes/thiagog"
|
|
28
|
+
"\n enez>, Execution CWD </hps/nobackup/production/ensembl/thi"
|
|
29
|
+
"\n agogenez/pairwises/arabidopsis/run/.>;"
|
|
30
|
+
"\nThu Mar 18 17:07:47: Resource usage collected."
|
|
31
|
+
"\n The CPU time used is 53936 seconds."
|
|
32
|
+
"\n MEM: 344 Mbytes; SWAP: 1.3 Gbytes; NTHREAD: 5"
|
|
33
|
+
"\n PGID: 433168; PIDs: 433168 433177 433179 444026 "
|
|
34
|
+
"\n"
|
|
35
|
+
"\n RUNLIMIT "
|
|
36
|
+
"\n 10085.0 min"
|
|
37
|
+
"\n"
|
|
38
|
+
"\n CORELIMIT MEMLIMIT"
|
|
39
|
+
"\n 0 M 3.9 G "
|
|
40
|
+
"\n"
|
|
41
|
+
"\n MEMORY USAGE:"
|
|
42
|
+
"\n MAX MEM: 2.5 Gbytes; AVG MEM: 343 Mbytes"
|
|
43
|
+
"\n"
|
|
44
|
+
"\n SCHEDULING PARAMETERS:"
|
|
45
|
+
"\n r15s r1m r15m ut pg io ls it tmp swp mem"
|
|
46
|
+
"\n loadSched - - - - 10.0 - - - 500M - 1000M "
|
|
47
|
+
"\n loadStop - - - - - - - - - - - "
|
|
48
|
+
"\n"
|
|
49
|
+
"\n availcpus "
|
|
50
|
+
"\n loadSched 1.0 "
|
|
51
|
+
"\n loadStop - "
|
|
52
|
+
"\n"
|
|
53
|
+
"\n RESOURCE REQUIREMENT DETAILS:"
|
|
54
|
+
"\n Combined: select[((mem>4000)) && (type == local)] order[r15s:pg] rusage[mem=40"
|
|
55
|
+
"\n 00.00:duration=8h:decay=0,numcpus=1.00:duration=8h:decay=0"
|
|
56
|
+
"\n ] span[hosts=1]"
|
|
57
|
+
"\n Effective: select[(((mem>4000))) && (type == local)] order[r15s:pg] rusage[mem"
|
|
58
|
+
"\n =4000.00:duration=8h:decay=0,numcpus=1.00:duration=8h:deca"
|
|
59
|
+
"\n y=0] span[hosts=1] "
|
|
60
|
+
"\n"
|
|
61
|
+
"\n"
|
|
62
|
+
)
|
|
60
63
|
max_mem, command = parse_mem_and_cmd_from_output(output=output)
|
|
61
64
|
assert len(max_mem.groups()) == 1
|
|
62
|
-
expected_mem =
|
|
63
|
-
assert
|
|
65
|
+
expected_mem = "2.5 Gbytes"
|
|
66
|
+
assert (
|
|
67
|
+
max_mem.group(1) == expected_mem
|
|
68
|
+
), f'Actual: {max_mem.group(1)}, Expected: "{expected_mem}"'
|
|
64
69
|
|
|
65
70
|
assert len(command.groups()) == 1
|
|
66
|
-
expected_command = (
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
71
|
+
expected_command = (
|
|
72
|
+
"_toil_worker CactusBarRecursion file:/hps/nobackup/production/ensembl/thiagogenez/"
|
|
73
|
+
"pairwises/arabidopsis/run/jobstore/3 kind-CactusBarRecursion/instance-iu6wo56x "
|
|
74
|
+
"--context gAShortenedh32xqlE51Yi4="
|
|
75
|
+
)
|
|
76
|
+
assert (
|
|
77
|
+
command.group(1) == expected_command
|
|
78
|
+
), f'Actual: {command.group(1)}, Expected: "{expected_command}"'
|
|
70
79
|
print(command)
|
|
71
80
|
|
|
72
|
-
max_mem, command = parse_mem_and_cmd_from_output(output=
|
|
81
|
+
max_mem, command = parse_mem_and_cmd_from_output(output="")
|
|
73
82
|
assert max_mem == None
|
|
74
83
|
assert command == None
|