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
|
@@ -16,19 +16,28 @@ import logging
|
|
|
16
16
|
from collections import namedtuple
|
|
17
17
|
from operator import attrgetter
|
|
18
18
|
from statistics import mean, stdev
|
|
19
|
-
from typing import
|
|
19
|
+
from typing import Optional
|
|
20
20
|
|
|
21
|
-
from
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
from botocore.client import BaseClient
|
|
22
|
+
|
|
23
|
+
from toil.lib.aws import (
|
|
24
|
+
get_aws_zone_from_boto,
|
|
25
|
+
get_aws_zone_from_environment,
|
|
26
|
+
get_aws_zone_from_environment_region,
|
|
27
|
+
get_aws_zone_from_metadata,
|
|
28
|
+
)
|
|
25
29
|
|
|
26
30
|
logger = logging.getLogger(__name__)
|
|
27
31
|
|
|
28
|
-
ZoneTuple = namedtuple(
|
|
32
|
+
ZoneTuple = namedtuple("ZoneTuple", ["name", "price_deviation"])
|
|
33
|
+
|
|
29
34
|
|
|
30
|
-
def get_aws_zone_from_spot_market(
|
|
31
|
-
|
|
35
|
+
def get_aws_zone_from_spot_market(
|
|
36
|
+
spotBid: Optional[float],
|
|
37
|
+
nodeType: Optional[str],
|
|
38
|
+
boto3_ec2: Optional[BaseClient],
|
|
39
|
+
zone_options: Optional[list[str]],
|
|
40
|
+
) -> Optional[str]:
|
|
32
41
|
"""
|
|
33
42
|
If a spot bid, node type, and Boto2 EC2 connection are specified, picks a
|
|
34
43
|
zone where instances are easy to buy from the zones in the region of the
|
|
@@ -40,21 +49,30 @@ def get_aws_zone_from_spot_market(spotBid: Optional[float], nodeType: Optional[s
|
|
|
40
49
|
"""
|
|
41
50
|
if spotBid:
|
|
42
51
|
# if spot bid is present, all the other parameters must be as well
|
|
43
|
-
assert bool(spotBid) == bool(nodeType) == bool(
|
|
52
|
+
assert bool(spotBid) == bool(nodeType) == bool(boto3_ec2)
|
|
44
53
|
# if the zone is unset and we are using the spot market, optimize our
|
|
45
54
|
# choice based on the spot history
|
|
46
55
|
|
|
47
56
|
if zone_options is None:
|
|
48
57
|
# We can use all the zones in the region
|
|
49
|
-
zone_options = [z.name for z in
|
|
50
|
-
|
|
51
|
-
return optimize_spot_bid(
|
|
58
|
+
zone_options = [z.name for z in boto3_ec2.describe_availability_zones()]
|
|
59
|
+
|
|
60
|
+
return optimize_spot_bid(
|
|
61
|
+
boto3_ec2,
|
|
62
|
+
instance_type=nodeType,
|
|
63
|
+
spot_bid=float(spotBid),
|
|
64
|
+
zone_options=zone_options,
|
|
65
|
+
)
|
|
52
66
|
else:
|
|
53
67
|
return None
|
|
54
68
|
|
|
55
69
|
|
|
56
|
-
def get_best_aws_zone(
|
|
57
|
-
|
|
70
|
+
def get_best_aws_zone(
|
|
71
|
+
spotBid: Optional[float] = None,
|
|
72
|
+
nodeType: Optional[str] = None,
|
|
73
|
+
boto3_ec2: Optional[BaseClient] = None,
|
|
74
|
+
zone_options: Optional[list[str]] = None,
|
|
75
|
+
) -> Optional[str]:
|
|
58
76
|
"""
|
|
59
77
|
Get the right AWS zone to use.
|
|
60
78
|
|
|
@@ -79,14 +97,20 @@ def get_best_aws_zone(spotBid: Optional[float] = None, nodeType: Optional[str] =
|
|
|
79
97
|
|
|
80
98
|
Returns None if no method can produce a zone to use.
|
|
81
99
|
"""
|
|
82
|
-
return
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
100
|
+
return (
|
|
101
|
+
get_aws_zone_from_environment()
|
|
102
|
+
or get_aws_zone_from_metadata()
|
|
103
|
+
or get_aws_zone_from_spot_market(spotBid, nodeType, boto3_ec2, zone_options)
|
|
104
|
+
or get_aws_zone_from_environment_region()
|
|
105
|
+
or get_aws_zone_from_boto()
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def choose_spot_zone(
|
|
110
|
+
zones: list[str],
|
|
111
|
+
bid: float,
|
|
112
|
+
spot_history: list["boto.ec2.spotpricehistory.SpotPriceHistory"],
|
|
113
|
+
) -> str:
|
|
90
114
|
"""
|
|
91
115
|
Returns the zone to put the spot request based on, in order of priority:
|
|
92
116
|
|
|
@@ -125,7 +149,11 @@ def choose_spot_zone(zones: List[str], bid: float, spot_history: List['boto.ec2.
|
|
|
125
149
|
# standard deviation values.
|
|
126
150
|
markets_under_bid, markets_over_bid = [], []
|
|
127
151
|
for zone in zones:
|
|
128
|
-
zone_histories = [
|
|
152
|
+
zone_histories = [
|
|
153
|
+
zone_history
|
|
154
|
+
for zone_history in spot_history
|
|
155
|
+
if zone_history.availability_zone == zone
|
|
156
|
+
]
|
|
129
157
|
if zone_histories:
|
|
130
158
|
price_deviation = stdev([history.price for history in zone_histories])
|
|
131
159
|
recent_price = zone_histories[0].price
|
|
@@ -134,10 +162,14 @@ def choose_spot_zone(zones: List[str], bid: float, spot_history: List['boto.ec2.
|
|
|
134
162
|
zone_tuple = ZoneTuple(name=zone, price_deviation=price_deviation)
|
|
135
163
|
(markets_over_bid, markets_under_bid)[recent_price < bid].append(zone_tuple)
|
|
136
164
|
|
|
137
|
-
return min(
|
|
165
|
+
return min(
|
|
166
|
+
markets_under_bid or markets_over_bid, key=attrgetter("price_deviation")
|
|
167
|
+
).name
|
|
138
168
|
|
|
139
169
|
|
|
140
|
-
def optimize_spot_bid(
|
|
170
|
+
def optimize_spot_bid(
|
|
171
|
+
boto3_ec2: BaseClient, instance_type: str, spot_bid: float, zone_options: list[str]
|
|
172
|
+
):
|
|
141
173
|
"""
|
|
142
174
|
Check whether the bid is in line with history and makes an effort to place
|
|
143
175
|
the instance in a sensible zone.
|
|
@@ -145,7 +177,7 @@ def optimize_spot_bid(boto2_ec2, instance_type, spot_bid, zone_options: List[str
|
|
|
145
177
|
:param zone_options: The collection of allowed zones to consider, within
|
|
146
178
|
the region associated with the Boto2 connection.
|
|
147
179
|
"""
|
|
148
|
-
spot_history = _get_spot_history(
|
|
180
|
+
spot_history = _get_spot_history(boto3_ec2, instance_type)
|
|
149
181
|
if spot_history:
|
|
150
182
|
_check_spot_bid(spot_bid, spot_history)
|
|
151
183
|
most_stable_zone = choose_spot_zone(zone_options, spot_bid, spot_history)
|
|
@@ -182,21 +214,26 @@ def _check_spot_bid(spot_bid, spot_history):
|
|
|
182
214
|
"""
|
|
183
215
|
average = mean([datum.price for datum in spot_history])
|
|
184
216
|
if spot_bid > average * 2:
|
|
185
|
-
logger.warning(
|
|
186
|
-
|
|
217
|
+
logger.warning(
|
|
218
|
+
"Your bid $ %f is more than double this instance type's average "
|
|
219
|
+
"spot price ($ %f) over the last week",
|
|
220
|
+
spot_bid,
|
|
221
|
+
average,
|
|
222
|
+
)
|
|
187
223
|
|
|
188
224
|
|
|
189
|
-
def _get_spot_history(
|
|
225
|
+
def _get_spot_history(boto3_ec2: BaseClient, instance_type: str):
|
|
190
226
|
"""
|
|
191
227
|
Returns list of 1,000 most recent spot market data points represented as SpotPriceHistory
|
|
192
228
|
objects. Note: The most recent object/data point will be first in the list.
|
|
193
229
|
|
|
194
230
|
:rtype: list[SpotPriceHistory]
|
|
195
231
|
"""
|
|
196
|
-
|
|
197
232
|
one_week_ago = datetime.datetime.now() - datetime.timedelta(days=7)
|
|
198
|
-
spot_data =
|
|
199
|
-
|
|
200
|
-
|
|
233
|
+
spot_data = boto3_ec2.describe_spot_price_history(
|
|
234
|
+
StartTime=one_week_ago.isoformat(),
|
|
235
|
+
InstanceTypes=[instance_type],
|
|
236
|
+
ProductDescriptions=["Linux/UNIX"],
|
|
237
|
+
)
|
|
201
238
|
spot_data.sort(key=attrgetter("timestamp"), reverse=True)
|
|
202
239
|
return spot_data
|