toil 7.0.0__py3-none-any.whl → 8.1.0b1__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 +124 -86
- toil/batchSystems/__init__.py +1 -0
- toil/batchSystems/abstractBatchSystem.py +137 -77
- toil/batchSystems/abstractGridEngineBatchSystem.py +211 -101
- toil/batchSystems/awsBatch.py +237 -128
- toil/batchSystems/cleanup_support.py +22 -16
- toil/batchSystems/contained_executor.py +30 -26
- toil/batchSystems/gridengine.py +85 -49
- toil/batchSystems/htcondor.py +164 -87
- toil/batchSystems/kubernetes.py +622 -386
- toil/batchSystems/local_support.py +17 -12
- toil/batchSystems/lsf.py +132 -79
- toil/batchSystems/lsfHelper.py +13 -11
- toil/batchSystems/mesos/__init__.py +41 -29
- toil/batchSystems/mesos/batchSystem.py +288 -149
- toil/batchSystems/mesos/executor.py +77 -49
- toil/batchSystems/mesos/test/__init__.py +31 -23
- toil/batchSystems/options.py +39 -29
- toil/batchSystems/registry.py +53 -19
- toil/batchSystems/singleMachine.py +293 -123
- toil/batchSystems/slurm.py +651 -155
- toil/batchSystems/torque.py +46 -32
- toil/bus.py +141 -73
- toil/common.py +784 -397
- toil/cwl/__init__.py +1 -1
- toil/cwl/cwltoil.py +1137 -534
- toil/cwl/utils.py +17 -22
- toil/deferred.py +62 -41
- toil/exceptions.py +5 -3
- toil/fileStores/__init__.py +5 -5
- toil/fileStores/abstractFileStore.py +88 -57
- toil/fileStores/cachingFileStore.py +711 -247
- toil/fileStores/nonCachingFileStore.py +113 -75
- toil/job.py +1031 -349
- toil/jobStores/abstractJobStore.py +387 -243
- toil/jobStores/aws/jobStore.py +772 -412
- toil/jobStores/aws/utils.py +161 -109
- toil/jobStores/conftest.py +1 -0
- toil/jobStores/fileJobStore.py +289 -151
- toil/jobStores/googleJobStore.py +137 -70
- toil/jobStores/utils.py +36 -15
- toil/leader.py +614 -269
- toil/lib/accelerators.py +115 -18
- toil/lib/aws/__init__.py +55 -28
- 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 +204 -58
- toil/lib/aws/utils.py +290 -213
- toil/lib/bioio.py +13 -5
- toil/lib/compatibility.py +11 -6
- toil/lib/conversions.py +83 -49
- toil/lib/docker.py +131 -103
- toil/lib/dockstore.py +379 -0
- toil/lib/ec2.py +322 -209
- toil/lib/ec2nodes.py +174 -105
- 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 +4 -2
- toil/lib/ftp_utils.py +217 -0
- toil/lib/generatedEC2Lists.py +127 -19
- toil/lib/history.py +1271 -0
- toil/lib/history_submission.py +681 -0
- toil/lib/humanize.py +6 -2
- toil/lib/io.py +121 -12
- toil/lib/iterables.py +4 -2
- toil/lib/memoize.py +12 -8
- toil/lib/misc.py +83 -18
- toil/lib/objects.py +2 -2
- toil/lib/resources.py +19 -7
- toil/lib/retry.py +125 -87
- toil/lib/threading.py +282 -80
- toil/lib/throttle.py +15 -14
- toil/lib/trs.py +390 -0
- toil/lib/web.py +38 -0
- toil/options/common.py +850 -402
- toil/options/cwl.py +185 -90
- toil/options/runner.py +50 -0
- toil/options/wdl.py +70 -19
- toil/provisioners/__init__.py +111 -46
- toil/provisioners/abstractProvisioner.py +322 -157
- toil/provisioners/aws/__init__.py +62 -30
- toil/provisioners/aws/awsProvisioner.py +980 -627
- toil/provisioners/clusterScaler.py +541 -279
- toil/provisioners/gceProvisioner.py +283 -180
- toil/provisioners/node.py +147 -79
- toil/realtimeLogger.py +34 -22
- toil/resource.py +137 -75
- toil/server/app.py +127 -61
- toil/server/celery_app.py +3 -1
- toil/server/cli/wes_cwl_runner.py +84 -55
- toil/server/utils.py +56 -31
- 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 +183 -65
- toil/test/__init__.py +263 -179
- toil/test/batchSystems/batchSystemTest.py +438 -195
- toil/test/batchSystems/batch_system_plugin_test.py +18 -7
- toil/test/batchSystems/test_gridengine.py +173 -0
- toil/test/batchSystems/test_lsf_helper.py +67 -58
- toil/test/batchSystems/test_slurm.py +265 -49
- toil/test/cactus/test_cactus_integration.py +20 -22
- toil/test/cwl/conftest.py +39 -0
- toil/test/cwl/cwlTest.py +375 -72
- toil/test/cwl/measure_default_memory.cwl +12 -0
- toil/test/cwl/not_run_required_input.cwl +29 -0
- toil/test/cwl/optional-file.cwl +18 -0
- toil/test/cwl/scatter_duplicate_outputs.cwl +40 -0
- toil/test/docs/scriptsTest.py +60 -34
- toil/test/jobStores/jobStoreTest.py +412 -235
- toil/test/lib/aws/test_iam.py +116 -48
- 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 +57 -49
- toil/test/lib/test_history.py +212 -0
- toil/test/lib/test_misc.py +12 -5
- toil/test/lib/test_trs.py +161 -0
- toil/test/mesos/MesosDataStructuresTest.py +23 -10
- toil/test/mesos/helloWorld.py +7 -6
- toil/test/mesos/stress.py +25 -20
- toil/test/options/options.py +7 -2
- toil/test/provisioners/aws/awsProvisionerTest.py +293 -140
- toil/test/provisioners/clusterScalerTest.py +440 -250
- toil/test/provisioners/clusterTest.py +81 -42
- 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 +140 -100
- 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 +33 -26
- toil/test/src/environmentTest.py +20 -10
- toil/test/src/fileStoreTest.py +538 -271
- toil/test/src/helloWorldTest.py +7 -4
- toil/test/src/importExportFileTest.py +61 -31
- toil/test/src/jobDescriptionTest.py +32 -17
- 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 +120 -70
- 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 +6 -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 +33 -16
- toil/test/utils/toilDebugTest.py +70 -58
- toil/test/utils/toilKillTest.py +4 -5
- toil/test/utils/utilsTest.py +239 -102
- toil/test/wdl/wdltoil_test.py +789 -148
- toil/test/wdl/wdltoil_test_kubernetes.py +37 -23
- toil/toilState.py +52 -26
- toil/utils/toilConfig.py +13 -4
- toil/utils/toilDebugFile.py +44 -27
- toil/utils/toilDebugJob.py +85 -25
- toil/utils/toilDestroyCluster.py +11 -6
- toil/utils/toilKill.py +8 -3
- toil/utils/toilLaunchCluster.py +251 -145
- toil/utils/toilMain.py +37 -16
- toil/utils/toilRsyncCluster.py +27 -14
- toil/utils/toilSshCluster.py +45 -22
- toil/utils/toilStats.py +75 -36
- toil/utils/toilStatus.py +226 -119
- toil/utils/toilUpdateEC2Instances.py +3 -1
- toil/version.py +6 -6
- toil/wdl/utils.py +5 -5
- toil/wdl/wdltoil.py +3528 -1053
- toil/worker.py +370 -149
- toil-8.1.0b1.dist-info/METADATA +178 -0
- toil-8.1.0b1.dist-info/RECORD +259 -0
- {toil-7.0.0.dist-info → toil-8.1.0b1.dist-info}/WHEEL +1 -1
- toil-7.0.0.dist-info/METADATA +0 -158
- toil-7.0.0.dist-info/RECORD +0 -244
- {toil-7.0.0.dist-info → toil-8.1.0b1.dist-info}/LICENSE +0 -0
- {toil-7.0.0.dist-info → toil-8.1.0b1.dist-info}/entry_points.txt +0 -0
- {toil-7.0.0.dist-info → toil-8.1.0b1.dist-info}/top_level.txt +0 -0
toil/test/lib/test_misc.py
CHANGED
|
@@ -32,6 +32,7 @@ class UserNameAvailableTest(ToilTest):
|
|
|
32
32
|
apparent_user_name = get_user_name()
|
|
33
33
|
self.assertEqual(apparent_user_name, real_user_name)
|
|
34
34
|
|
|
35
|
+
|
|
35
36
|
class UserNameUnvailableTest(ToilTest):
|
|
36
37
|
"""
|
|
37
38
|
Make sure we can get something for a user name when user names are not
|
|
@@ -42,9 +43,12 @@ class UserNameUnvailableTest(ToilTest):
|
|
|
42
43
|
super().setUp()
|
|
43
44
|
# Monkey patch getpass.getuser to fail
|
|
44
45
|
self.original_getuser = getpass.getuser
|
|
46
|
+
|
|
45
47
|
def fake_getuser():
|
|
46
|
-
raise KeyError(
|
|
48
|
+
raise KeyError("Fake key error")
|
|
49
|
+
|
|
47
50
|
getpass.getuser = fake_getuser
|
|
51
|
+
|
|
48
52
|
def tearDown(self):
|
|
49
53
|
# Fix the module we hacked up
|
|
50
54
|
getpass.getuser = self.original_getuser
|
|
@@ -54,7 +58,8 @@ class UserNameUnvailableTest(ToilTest):
|
|
|
54
58
|
apparent_user_name = get_user_name()
|
|
55
59
|
# Make sure we got something
|
|
56
60
|
self.assertTrue(isinstance(apparent_user_name, str))
|
|
57
|
-
self.assertNotEqual(apparent_user_name,
|
|
61
|
+
self.assertNotEqual(apparent_user_name, "")
|
|
62
|
+
|
|
58
63
|
|
|
59
64
|
class UserNameVeryBrokenTest(ToilTest):
|
|
60
65
|
"""
|
|
@@ -66,9 +71,12 @@ class UserNameVeryBrokenTest(ToilTest):
|
|
|
66
71
|
super().setUp()
|
|
67
72
|
# Monkey patch getpass.getuser to fail
|
|
68
73
|
self.original_getuser = getpass.getuser
|
|
74
|
+
|
|
69
75
|
def fake_getuser():
|
|
70
|
-
raise RuntimeError(
|
|
76
|
+
raise RuntimeError("Fake error that we did not anticipate")
|
|
77
|
+
|
|
71
78
|
getpass.getuser = fake_getuser
|
|
79
|
+
|
|
72
80
|
def tearDown(self):
|
|
73
81
|
# Fix the module we hacked up
|
|
74
82
|
getpass.getuser = self.original_getuser
|
|
@@ -78,5 +86,4 @@ class UserNameVeryBrokenTest(ToilTest):
|
|
|
78
86
|
apparent_user_name = get_user_name()
|
|
79
87
|
# Make sure we got something
|
|
80
88
|
self.assertTrue(isinstance(apparent_user_name, str))
|
|
81
|
-
self.assertNotEqual(apparent_user_name,
|
|
82
|
-
|
|
89
|
+
self.assertNotEqual(apparent_user_name, "")
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
# Copyright (C) 2015-2024 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
|
+
|
|
15
|
+
import io
|
|
16
|
+
import logging
|
|
17
|
+
import pytest
|
|
18
|
+
from typing import IO
|
|
19
|
+
import urllib.request
|
|
20
|
+
from urllib.error import URLError
|
|
21
|
+
|
|
22
|
+
from toil.lib.retry import retry
|
|
23
|
+
from toil.lib.trs import find_workflow, fetch_workflow
|
|
24
|
+
from toil.test import ToilTest, needs_online
|
|
25
|
+
|
|
26
|
+
logger = logging.getLogger(__name__)
|
|
27
|
+
logging.basicConfig(level=logging.DEBUG)
|
|
28
|
+
|
|
29
|
+
@pytest.mark.integrative
|
|
30
|
+
@needs_online
|
|
31
|
+
class DockstoreLookupTest(ToilTest):
|
|
32
|
+
"""
|
|
33
|
+
Make sure we can look up workflows on Dockstore.
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
@retry(errors=[URLError, RuntimeError])
|
|
37
|
+
def read_result(self, url_or_path: str) -> IO[bytes]:
|
|
38
|
+
"""
|
|
39
|
+
Read a file or URL.
|
|
40
|
+
|
|
41
|
+
Binary mode to allow testing for binary file support.
|
|
42
|
+
|
|
43
|
+
This lets us test that we have the right workflow contents and not care
|
|
44
|
+
how we are being shown them.
|
|
45
|
+
"""
|
|
46
|
+
if url_or_path.startswith("http://") or url_or_path.startswith("https://"):
|
|
47
|
+
response = urllib.request.urlopen(url_or_path)
|
|
48
|
+
if response.status != 200:
|
|
49
|
+
raise RuntimeError(f"HTTP error response: {response}")
|
|
50
|
+
return response
|
|
51
|
+
else:
|
|
52
|
+
return open(url_or_path, "rb")
|
|
53
|
+
|
|
54
|
+
# TODO: Tests that definitely test a clear cache
|
|
55
|
+
|
|
56
|
+
def test_lookup_from_page_url(self) -> None:
|
|
57
|
+
PAGE_URL = "https://dockstore.org/workflows/github.com/dockstore/bcc2020-training/HelloWorld:master?tab=info"
|
|
58
|
+
trs_id, trs_version, language = find_workflow(PAGE_URL)
|
|
59
|
+
|
|
60
|
+
self.assertEqual(trs_id, "#workflow/github.com/dockstore/bcc2020-training/HelloWorld")
|
|
61
|
+
self.assertEqual(trs_version, "master")
|
|
62
|
+
self.assertEqual(language, "WDL")
|
|
63
|
+
|
|
64
|
+
def test_lookup_from_trs_with_version(self) -> None:
|
|
65
|
+
TRS_ID = "#workflow/github.com/dockstore-testing/md5sum-checker"
|
|
66
|
+
TRS_VERSION = "master"
|
|
67
|
+
trs_id, trs_version, language = find_workflow(f"{TRS_ID}:{TRS_VERSION}")
|
|
68
|
+
|
|
69
|
+
self.assertEqual(trs_id, TRS_ID)
|
|
70
|
+
self.assertEqual(trs_version, TRS_VERSION)
|
|
71
|
+
self.assertEqual(language, "CWL")
|
|
72
|
+
|
|
73
|
+
def test_lookup_from_trs_no_version(self) -> None:
|
|
74
|
+
TRS_ID = "#workflow/github.com/dockstore-testing/md5sum-checker"
|
|
75
|
+
with pytest.raises(ValueError):
|
|
76
|
+
# We don't yet have a way to read Dockstore's default version info,
|
|
77
|
+
# so it's not safe to apply any default version when multiple
|
|
78
|
+
# versions exist.
|
|
79
|
+
trs_id, trs_version, language = find_workflow(TRS_ID)
|
|
80
|
+
|
|
81
|
+
# TODO: Add a test with a workflow that we know has and will only ever
|
|
82
|
+
# have one version, to test version auto-detection in that case.
|
|
83
|
+
|
|
84
|
+
def test_get(self) -> None:
|
|
85
|
+
TRS_ID = "#workflow/github.com/dockstore-testing/md5sum-checker"
|
|
86
|
+
TRS_VERSION = "master"
|
|
87
|
+
LANGUAGE = "CWL"
|
|
88
|
+
# Despite "-checker" in the ID, this actually refers to the base md5sum
|
|
89
|
+
# workflow that just happens to have a checker *available*, not to the
|
|
90
|
+
# checker workflow itself.
|
|
91
|
+
WORKFLOW_URL = "https://raw.githubusercontent.com/dockstore-testing/md5sum-checker/master/md5sum/md5sum-workflow.cwl"
|
|
92
|
+
looked_up = fetch_workflow(TRS_ID, TRS_VERSION, LANGUAGE)
|
|
93
|
+
|
|
94
|
+
data_from_lookup = self.read_result(looked_up).read()
|
|
95
|
+
data_from_source = self.read_result(WORKFLOW_URL).read()
|
|
96
|
+
self.assertEqual(data_from_lookup, data_from_source)
|
|
97
|
+
|
|
98
|
+
def test_get_from_trs_cached(self) -> None:
|
|
99
|
+
TRS_ID = "#workflow/github.com/dockstore-testing/md5sum-checker"
|
|
100
|
+
TRS_VERSION = "master"
|
|
101
|
+
LANGUAGE = "CWL"
|
|
102
|
+
WORKFLOW_URL = "https://raw.githubusercontent.com/dockstore-testing/md5sum-checker/master/md5sum/md5sum-workflow.cwl"
|
|
103
|
+
# This lookup may or may not be cached
|
|
104
|
+
fetch_workflow(TRS_ID, TRS_VERSION, LANGUAGE)
|
|
105
|
+
# This lookup is definitely cached
|
|
106
|
+
looked_up = fetch_workflow(TRS_ID, TRS_VERSION, LANGUAGE)
|
|
107
|
+
|
|
108
|
+
data_from_lookup = self.read_result(looked_up).read()
|
|
109
|
+
data_from_source = self.read_result(WORKFLOW_URL).read()
|
|
110
|
+
self.assertEqual(data_from_lookup, data_from_source)
|
|
111
|
+
|
|
112
|
+
def test_lookup_from_trs_with_version(self) -> None:
|
|
113
|
+
TRS_VERSIONED_ID = "#workflow/github.com/dockstore-testing/md5sum-checker:workflowWithHTTPImport"
|
|
114
|
+
trs_id, trs_version, language = find_workflow(TRS_VERSIONED_ID)
|
|
115
|
+
|
|
116
|
+
parts = TRS_VERSIONED_ID.split(":")
|
|
117
|
+
|
|
118
|
+
self.assertEqual(trs_id, parts[0])
|
|
119
|
+
self.assertEqual(trs_version, parts[1])
|
|
120
|
+
self.assertEqual(language, "CWL")
|
|
121
|
+
|
|
122
|
+
def test_lookup_from_trs_nonexistent_workflow(self) -> None:
|
|
123
|
+
TRS_VERSIONED_ID = "#workflow/github.com/adamnovak/veryfakerepo:notARealVersion"
|
|
124
|
+
with self.assertRaises(FileNotFoundError):
|
|
125
|
+
looked_up = find_workflow(TRS_VERSIONED_ID)
|
|
126
|
+
|
|
127
|
+
def test_lookup_from_trs_nonexistent_workflow_bad_format(self) -> None:
|
|
128
|
+
TRS_VERSIONED_ID = "#workflow/AbsoluteGarbage:notARealVersion"
|
|
129
|
+
with self.assertRaises(FileNotFoundError):
|
|
130
|
+
looked_up = find_workflow(TRS_VERSIONED_ID)
|
|
131
|
+
|
|
132
|
+
def test_lookup_from_trs_nonexistent_version(self) -> None:
|
|
133
|
+
TRS_VERSIONED_ID = "#workflow/github.com/dockstore-testing/md5sum-checker:notARealVersion"
|
|
134
|
+
with self.assertRaises(FileNotFoundError):
|
|
135
|
+
looked_up = find_workflow(TRS_VERSIONED_ID)
|
|
136
|
+
|
|
137
|
+
def test_get_nonexistent_workflow(self) -> None:
|
|
138
|
+
TRS_ID = "#workflow/github.com/adamnovak/veryfakerepo"
|
|
139
|
+
TRS_VERSION = "notARealVersion"
|
|
140
|
+
LANGUAGE = "CWL"
|
|
141
|
+
with self.assertRaises(FileNotFoundError):
|
|
142
|
+
looked_up = fetch_workflow(TRS_ID, TRS_VERSION, LANGUAGE)
|
|
143
|
+
|
|
144
|
+
def test_get_nonexistent_version(self) -> None:
|
|
145
|
+
TRS_ID = "#workflow/github.com/dockstore-testing/md5sum-checker"
|
|
146
|
+
TRS_VERSION = "notARealVersion"
|
|
147
|
+
LANGUAGE = "CWL"
|
|
148
|
+
with self.assertRaises(FileNotFoundError):
|
|
149
|
+
looked_up = fetch_workflow(TRS_ID, TRS_VERSION, LANGUAGE)
|
|
150
|
+
|
|
151
|
+
def test_get_nonexistent_workflow_bad_format(self) -> None:
|
|
152
|
+
# Dockstore enforces an ID pattern and blames your request if you ask
|
|
153
|
+
# about something that doesn't follow it. So don't follow it.
|
|
154
|
+
TRS_ID = "#workflow/AbsoluteGarbage"
|
|
155
|
+
TRS_VERSION = "notARealVersion"
|
|
156
|
+
LANGUAGE = "CWL"
|
|
157
|
+
with self.assertRaises(FileNotFoundError):
|
|
158
|
+
looked_up = fetch_workflow(TRS_ID, TRS_VERSION, LANGUAGE)
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
|
|
@@ -21,15 +21,19 @@ class DataStructuresTest(ToilTest):
|
|
|
21
21
|
def _getJob(self, cores=1, memory=1000, disk=5000, preemptible=True):
|
|
22
22
|
from toil.batchSystems.mesos import MesosShape, ToilJob
|
|
23
23
|
|
|
24
|
-
resources = MesosShape(
|
|
24
|
+
resources = MesosShape(
|
|
25
|
+
wallTime=0, cores=cores, memory=memory, disk=disk, preemptible=preemptible
|
|
26
|
+
)
|
|
25
27
|
|
|
26
|
-
job = ToilJob(
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
28
|
+
job = ToilJob(
|
|
29
|
+
jobID=str(uuid.uuid4()),
|
|
30
|
+
name=str(uuid.uuid4()),
|
|
31
|
+
resources=resources,
|
|
32
|
+
command="do nothing",
|
|
33
|
+
userScript=None,
|
|
34
|
+
environment=None,
|
|
35
|
+
workerCleanupInfo=None,
|
|
36
|
+
)
|
|
33
37
|
return job
|
|
34
38
|
|
|
35
39
|
def testJobQueue(self, testJobs=1000):
|
|
@@ -39,15 +43,24 @@ class DataStructuresTest(ToilTest):
|
|
|
39
43
|
non-preemptible jobs groups first, with priority given to large jobs.
|
|
40
44
|
"""
|
|
41
45
|
from toil.batchSystems.mesos import JobQueue
|
|
46
|
+
|
|
42
47
|
jobQueue = JobQueue()
|
|
43
48
|
|
|
44
49
|
for jobNum in range(0, testJobs):
|
|
45
|
-
testJob = self._getJob(
|
|
50
|
+
testJob = self._getJob(
|
|
51
|
+
cores=random.choice(list(range(10))),
|
|
52
|
+
preemptible=random.choice([True, False]),
|
|
53
|
+
)
|
|
46
54
|
jobQueue.insertJob(testJob, testJob.resources)
|
|
47
55
|
|
|
48
56
|
sortedTypes = jobQueue.sortedTypes
|
|
49
57
|
self.assertGreaterEqual(20, len(sortedTypes))
|
|
50
|
-
self.assertTrue(
|
|
58
|
+
self.assertTrue(
|
|
59
|
+
all(
|
|
60
|
+
sortedTypes[i] <= sortedTypes[i + 1]
|
|
61
|
+
for i in range(len(sortedTypes) - 1)
|
|
62
|
+
)
|
|
63
|
+
)
|
|
51
64
|
|
|
52
65
|
preemptible = sortedTypes.pop(0).preemptible
|
|
53
66
|
for jtype in sortedTypes:
|
toil/test/mesos/helloWorld.py
CHANGED
|
@@ -23,14 +23,15 @@ from toil.job import Job
|
|
|
23
23
|
childMessage = "The child job is now running!"
|
|
24
24
|
parentMessage = "The parent job is now running!"
|
|
25
25
|
|
|
26
|
+
|
|
26
27
|
def hello_world(job):
|
|
27
28
|
|
|
28
29
|
job.fileStore.log_to_leader(parentMessage)
|
|
29
|
-
with open(
|
|
30
|
-
handle.write(
|
|
30
|
+
with open("foo_bam.txt", "w") as handle:
|
|
31
|
+
handle.write("\nThis is a triumph...\n")
|
|
31
32
|
|
|
32
33
|
# Assign FileStoreID to a given file
|
|
33
|
-
foo_bam = job.fileStore.writeGlobalFile(
|
|
34
|
+
foo_bam = job.fileStore.writeGlobalFile("foo_bam.txt")
|
|
34
35
|
|
|
35
36
|
# Spawn child
|
|
36
37
|
job.addChildJobFn(hello_world_child, foo_bam, memory=100, cores=0.5, disk="3G")
|
|
@@ -43,13 +44,13 @@ def hello_world_child(job, hw):
|
|
|
43
44
|
# NOTE: path and the udpated file are stored to /tmp
|
|
44
45
|
# If we want to SAVE our changes to this tmp file, we must write it out.
|
|
45
46
|
with open(path) as r:
|
|
46
|
-
with open(
|
|
47
|
+
with open("bar_bam.txt", "w") as handle:
|
|
47
48
|
for line in r.readlines():
|
|
48
49
|
handle.write(line)
|
|
49
50
|
|
|
50
51
|
# Assign FileStoreID to a given file
|
|
51
52
|
# can also use: job.updateGlobalFile() given the FileStoreID instantiation.
|
|
52
|
-
job.fileStore.writeGlobalFile(
|
|
53
|
+
job.fileStore.writeGlobalFile("bar_bam.txt")
|
|
53
54
|
|
|
54
55
|
|
|
55
56
|
def main():
|
|
@@ -67,5 +68,5 @@ def main():
|
|
|
67
68
|
toil.start(i)
|
|
68
69
|
|
|
69
70
|
|
|
70
|
-
if __name__ ==
|
|
71
|
+
if __name__ == "__main__":
|
|
71
72
|
main()
|
toil/test/mesos/stress.py
CHANGED
|
@@ -17,58 +17,63 @@ from configargparse import ArgumentParser
|
|
|
17
17
|
from toil.job import Job
|
|
18
18
|
|
|
19
19
|
|
|
20
|
-
def touchFile(
|
|
20
|
+
def touchFile(fileStore):
|
|
21
21
|
with fileStore.writeGlobalFileStream() as (f, id):
|
|
22
|
-
f.write(
|
|
22
|
+
f.write("This is a triumph")
|
|
23
|
+
|
|
23
24
|
|
|
24
25
|
class LongTestJob(Job):
|
|
25
26
|
def __init__(self, numJobs):
|
|
26
|
-
Job.__init__(self,
|
|
27
|
+
Job.__init__(self, memory=100000, cores=0.01)
|
|
27
28
|
self.numJobs = numJobs
|
|
28
29
|
|
|
29
30
|
def run(self, fileStore):
|
|
30
|
-
for i in range(0,self.numJobs):
|
|
31
|
+
for i in range(0, self.numJobs):
|
|
31
32
|
self.addChild(HelloWorldJob(i))
|
|
32
33
|
self.addFollowOn(LongTestFollowOn())
|
|
33
34
|
|
|
35
|
+
|
|
34
36
|
class LongTestFollowOn(Job):
|
|
35
37
|
|
|
36
38
|
def __init__(self):
|
|
37
|
-
Job.__init__(self,
|
|
39
|
+
Job.__init__(self, memory=1000000, cores=0.01)
|
|
38
40
|
|
|
39
41
|
def run(self, fileStore):
|
|
40
|
-
touchFile(
|
|
42
|
+
touchFile(fileStore)
|
|
41
43
|
|
|
42
|
-
class HelloWorldJob(Job):
|
|
43
44
|
|
|
44
|
-
|
|
45
|
-
Job.__init__(self, memory=100000, cores=0.01)
|
|
46
|
-
self.i=i
|
|
45
|
+
class HelloWorldJob(Job):
|
|
47
46
|
|
|
47
|
+
def __init__(self, i):
|
|
48
|
+
Job.__init__(self, memory=100000, cores=0.01)
|
|
49
|
+
self.i = i
|
|
48
50
|
|
|
49
51
|
def run(self, fileStore):
|
|
50
|
-
touchFile(
|
|
52
|
+
touchFile(fileStore)
|
|
51
53
|
self.addFollowOn(HelloWorldFollowOn(self.i))
|
|
52
54
|
|
|
55
|
+
|
|
53
56
|
class HelloWorldFollowOn(Job):
|
|
54
57
|
|
|
55
|
-
def __init__(self,i):
|
|
56
|
-
Job.__init__(self,
|
|
58
|
+
def __init__(self, i):
|
|
59
|
+
Job.__init__(self, memory=200000, cores=0.01)
|
|
57
60
|
self.i = i
|
|
58
61
|
|
|
59
62
|
def run(self, fileStore):
|
|
60
|
-
touchFile(
|
|
63
|
+
touchFile(fileStore)
|
|
64
|
+
|
|
61
65
|
|
|
62
66
|
def main(numJobs):
|
|
63
67
|
# Boilerplate -- startToil requires options
|
|
64
68
|
parser = ArgumentParser()
|
|
65
69
|
Job.Runner.addToilOptions(parser)
|
|
66
|
-
options = parser.parse_args(
|
|
67
|
-
options.batchSystem="mesos"
|
|
68
|
-
options.mesos_endpoint="localhost:5050"
|
|
70
|
+
options = parser.parse_args(args=["./toilTest"])
|
|
71
|
+
options.batchSystem = "mesos"
|
|
72
|
+
options.mesos_endpoint = "localhost:5050"
|
|
69
73
|
# Launch first toil Job
|
|
70
|
-
i = LongTestJob(
|
|
71
|
-
Job.Runner.startToil(i,
|
|
74
|
+
i = LongTestJob(numJobs)
|
|
75
|
+
Job.Runner.startToil(i, options)
|
|
76
|
+
|
|
72
77
|
|
|
73
|
-
if __name__=="__main__":
|
|
78
|
+
if __name__ == "__main__":
|
|
74
79
|
main(numJobs=5)
|
toil/test/options/options.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from configargparse import ArgParser
|
|
2
2
|
|
|
3
|
-
from toil.common import
|
|
3
|
+
from toil.common import Toil, addOptions
|
|
4
4
|
from toil.test import ToilTest
|
|
5
5
|
|
|
6
6
|
|
|
@@ -8,6 +8,7 @@ class OptionsTest(ToilTest):
|
|
|
8
8
|
"""
|
|
9
9
|
Class to test functionality of all Toil options
|
|
10
10
|
"""
|
|
11
|
+
|
|
11
12
|
def test_default_caching_slurm(self):
|
|
12
13
|
"""
|
|
13
14
|
Test to ensure that caching will be set to false when running on Slurm
|
|
@@ -30,7 +31,11 @@ class OptionsTest(ToilTest):
|
|
|
30
31
|
addOptions(parser, jobstore_as_flag=True, wdl=False, cwl=False)
|
|
31
32
|
# the kubernetes batchsystem (and I think all batchsystems including singlemachine) return False
|
|
32
33
|
# for default_caching
|
|
33
|
-
test_args = [
|
|
34
|
+
test_args = [
|
|
35
|
+
"--jobstore=example-jobstore",
|
|
36
|
+
"--batchSystem=kubernetes",
|
|
37
|
+
"--caching=True",
|
|
38
|
+
]
|
|
34
39
|
options = parser.parse_args(test_args)
|
|
35
40
|
with Toil(options) as toil:
|
|
36
41
|
caching_value = toil.config.caching
|