toil 6.1.0a1__py3-none-any.whl → 7.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 +1 -232
- toil/batchSystems/abstractBatchSystem.py +41 -17
- toil/batchSystems/abstractGridEngineBatchSystem.py +79 -65
- toil/batchSystems/awsBatch.py +8 -8
- toil/batchSystems/cleanup_support.py +7 -3
- toil/batchSystems/contained_executor.py +4 -5
- toil/batchSystems/gridengine.py +1 -1
- toil/batchSystems/htcondor.py +5 -5
- toil/batchSystems/kubernetes.py +25 -11
- toil/batchSystems/local_support.py +3 -3
- toil/batchSystems/lsf.py +9 -9
- toil/batchSystems/mesos/batchSystem.py +4 -4
- toil/batchSystems/mesos/executor.py +3 -2
- toil/batchSystems/options.py +9 -0
- toil/batchSystems/singleMachine.py +11 -10
- toil/batchSystems/slurm.py +129 -16
- toil/batchSystems/torque.py +1 -1
- toil/bus.py +45 -3
- toil/common.py +56 -31
- toil/cwl/cwltoil.py +442 -371
- toil/deferred.py +1 -1
- toil/exceptions.py +1 -1
- toil/fileStores/abstractFileStore.py +69 -20
- toil/fileStores/cachingFileStore.py +6 -22
- toil/fileStores/nonCachingFileStore.py +6 -15
- toil/job.py +270 -86
- toil/jobStores/abstractJobStore.py +37 -31
- toil/jobStores/aws/jobStore.py +280 -218
- toil/jobStores/aws/utils.py +60 -31
- toil/jobStores/conftest.py +2 -2
- toil/jobStores/fileJobStore.py +3 -3
- toil/jobStores/googleJobStore.py +3 -4
- toil/leader.py +89 -38
- toil/lib/aws/__init__.py +26 -10
- toil/lib/aws/iam.py +2 -2
- toil/lib/aws/session.py +62 -22
- toil/lib/aws/utils.py +73 -37
- toil/lib/conversions.py +24 -1
- toil/lib/ec2.py +118 -69
- toil/lib/expando.py +1 -1
- toil/lib/generatedEC2Lists.py +8 -8
- toil/lib/io.py +42 -4
- toil/lib/misc.py +1 -3
- toil/lib/resources.py +57 -16
- toil/lib/retry.py +12 -5
- toil/lib/threading.py +29 -14
- toil/lib/throttle.py +1 -1
- toil/options/common.py +31 -30
- toil/options/wdl.py +5 -0
- toil/provisioners/__init__.py +9 -3
- toil/provisioners/abstractProvisioner.py +12 -2
- toil/provisioners/aws/__init__.py +20 -15
- toil/provisioners/aws/awsProvisioner.py +406 -329
- toil/provisioners/gceProvisioner.py +2 -2
- toil/provisioners/node.py +13 -5
- toil/server/app.py +1 -1
- toil/statsAndLogging.py +93 -23
- toil/test/__init__.py +27 -12
- toil/test/batchSystems/batchSystemTest.py +40 -33
- toil/test/batchSystems/batch_system_plugin_test.py +79 -0
- toil/test/batchSystems/test_slurm.py +22 -7
- toil/test/cactus/__init__.py +0 -0
- toil/test/cactus/test_cactus_integration.py +58 -0
- toil/test/cwl/cwlTest.py +245 -236
- toil/test/cwl/seqtk_seq.cwl +1 -1
- toil/test/docs/scriptsTest.py +11 -14
- toil/test/jobStores/jobStoreTest.py +40 -54
- toil/test/lib/aws/test_iam.py +2 -2
- toil/test/lib/test_ec2.py +1 -1
- toil/test/options/__init__.py +13 -0
- toil/test/options/options.py +37 -0
- toil/test/provisioners/aws/awsProvisionerTest.py +51 -34
- toil/test/provisioners/clusterTest.py +99 -16
- toil/test/server/serverTest.py +2 -2
- toil/test/src/autoDeploymentTest.py +1 -1
- toil/test/src/dockerCheckTest.py +2 -1
- toil/test/src/environmentTest.py +125 -0
- toil/test/src/fileStoreTest.py +1 -1
- toil/test/src/jobDescriptionTest.py +18 -8
- toil/test/src/jobTest.py +1 -1
- toil/test/src/realtimeLoggerTest.py +4 -0
- toil/test/src/workerTest.py +52 -19
- toil/test/utils/toilDebugTest.py +62 -4
- toil/test/utils/utilsTest.py +23 -21
- toil/test/wdl/wdltoil_test.py +49 -21
- toil/test/wdl/wdltoil_test_kubernetes.py +77 -0
- toil/toilState.py +68 -9
- toil/utils/toilDebugFile.py +1 -1
- toil/utils/toilDebugJob.py +153 -26
- toil/utils/toilLaunchCluster.py +12 -2
- toil/utils/toilRsyncCluster.py +7 -2
- toil/utils/toilSshCluster.py +7 -3
- toil/utils/toilStats.py +310 -266
- toil/utils/toilStatus.py +98 -52
- toil/version.py +11 -11
- toil/wdl/wdltoil.py +644 -225
- toil/worker.py +125 -83
- {toil-6.1.0a1.dist-info → toil-7.0.0.dist-info}/LICENSE +25 -0
- toil-7.0.0.dist-info/METADATA +158 -0
- {toil-6.1.0a1.dist-info → toil-7.0.0.dist-info}/RECORD +103 -96
- {toil-6.1.0a1.dist-info → toil-7.0.0.dist-info}/WHEEL +1 -1
- toil-6.1.0a1.dist-info/METADATA +0 -125
- {toil-6.1.0a1.dist-info → toil-7.0.0.dist-info}/entry_points.txt +0 -0
- {toil-6.1.0a1.dist-info → toil-7.0.0.dist-info}/top_level.txt +0 -0
|
@@ -18,6 +18,8 @@ from operator import attrgetter
|
|
|
18
18
|
from statistics import mean, stdev
|
|
19
19
|
from typing import List, Optional
|
|
20
20
|
|
|
21
|
+
from botocore.client import BaseClient
|
|
22
|
+
|
|
21
23
|
from toil.lib.aws import (get_aws_zone_from_boto,
|
|
22
24
|
get_aws_zone_from_environment,
|
|
23
25
|
get_aws_zone_from_environment_region,
|
|
@@ -27,8 +29,10 @@ logger = logging.getLogger(__name__)
|
|
|
27
29
|
|
|
28
30
|
ZoneTuple = namedtuple('ZoneTuple', ['name', 'price_deviation'])
|
|
29
31
|
|
|
32
|
+
|
|
30
33
|
def get_aws_zone_from_spot_market(spotBid: Optional[float], nodeType: Optional[str],
|
|
31
|
-
|
|
34
|
+
boto3_ec2: Optional[BaseClient], zone_options: Optional[List[str]]) -> \
|
|
35
|
+
Optional[str]:
|
|
32
36
|
"""
|
|
33
37
|
If a spot bid, node type, and Boto2 EC2 connection are specified, picks a
|
|
34
38
|
zone where instances are easy to buy from the zones in the region of the
|
|
@@ -40,21 +44,22 @@ def get_aws_zone_from_spot_market(spotBid: Optional[float], nodeType: Optional[s
|
|
|
40
44
|
"""
|
|
41
45
|
if spotBid:
|
|
42
46
|
# if spot bid is present, all the other parameters must be as well
|
|
43
|
-
assert bool(spotBid) == bool(nodeType) == bool(
|
|
47
|
+
assert bool(spotBid) == bool(nodeType) == bool(boto3_ec2)
|
|
44
48
|
# if the zone is unset and we are using the spot market, optimize our
|
|
45
49
|
# choice based on the spot history
|
|
46
50
|
|
|
47
51
|
if zone_options is None:
|
|
48
52
|
# We can use all the zones in the region
|
|
49
|
-
zone_options = [z.name for z in
|
|
53
|
+
zone_options = [z.name for z in boto3_ec2.describe_availability_zones()]
|
|
50
54
|
|
|
51
|
-
return optimize_spot_bid(
|
|
55
|
+
return optimize_spot_bid(boto3_ec2, instance_type=nodeType, spot_bid=float(spotBid), zone_options=zone_options)
|
|
52
56
|
else:
|
|
53
57
|
return None
|
|
54
58
|
|
|
55
59
|
|
|
56
60
|
def get_best_aws_zone(spotBid: Optional[float] = None, nodeType: Optional[str] = None,
|
|
57
|
-
|
|
61
|
+
boto3_ec2: Optional[BaseClient] = None,
|
|
62
|
+
zone_options: Optional[List[str]] = None) -> Optional[str]:
|
|
58
63
|
"""
|
|
59
64
|
Get the right AWS zone to use.
|
|
60
65
|
|
|
@@ -81,12 +86,13 @@ def get_best_aws_zone(spotBid: Optional[float] = None, nodeType: Optional[str] =
|
|
|
81
86
|
"""
|
|
82
87
|
return get_aws_zone_from_environment() or \
|
|
83
88
|
get_aws_zone_from_metadata() or \
|
|
84
|
-
get_aws_zone_from_spot_market(spotBid, nodeType,
|
|
89
|
+
get_aws_zone_from_spot_market(spotBid, nodeType, boto3_ec2, zone_options) or \
|
|
85
90
|
get_aws_zone_from_environment_region() or \
|
|
86
91
|
get_aws_zone_from_boto()
|
|
87
92
|
|
|
88
93
|
|
|
89
|
-
def choose_spot_zone(zones: List[str], bid: float,
|
|
94
|
+
def choose_spot_zone(zones: List[str], bid: float,
|
|
95
|
+
spot_history: List['boto.ec2.spotpricehistory.SpotPriceHistory']) -> str:
|
|
90
96
|
"""
|
|
91
97
|
Returns the zone to put the spot request based on, in order of priority:
|
|
92
98
|
|
|
@@ -137,7 +143,7 @@ def choose_spot_zone(zones: List[str], bid: float, spot_history: List['boto.ec2.
|
|
|
137
143
|
return min(markets_under_bid or markets_over_bid, key=attrgetter('price_deviation')).name
|
|
138
144
|
|
|
139
145
|
|
|
140
|
-
def optimize_spot_bid(
|
|
146
|
+
def optimize_spot_bid(boto3_ec2: BaseClient, instance_type: str, spot_bid: float, zone_options: List[str]):
|
|
141
147
|
"""
|
|
142
148
|
Check whether the bid is in line with history and makes an effort to place
|
|
143
149
|
the instance in a sensible zone.
|
|
@@ -145,7 +151,7 @@ def optimize_spot_bid(boto2_ec2, instance_type, spot_bid, zone_options: List[str
|
|
|
145
151
|
:param zone_options: The collection of allowed zones to consider, within
|
|
146
152
|
the region associated with the Boto2 connection.
|
|
147
153
|
"""
|
|
148
|
-
spot_history = _get_spot_history(
|
|
154
|
+
spot_history = _get_spot_history(boto3_ec2, instance_type)
|
|
149
155
|
if spot_history:
|
|
150
156
|
_check_spot_bid(spot_bid, spot_history)
|
|
151
157
|
most_stable_zone = choose_spot_zone(zone_options, spot_bid, spot_history)
|
|
@@ -183,20 +189,19 @@ def _check_spot_bid(spot_bid, spot_history):
|
|
|
183
189
|
average = mean([datum.price for datum in spot_history])
|
|
184
190
|
if spot_bid > average * 2:
|
|
185
191
|
logger.warning("Your bid $ %f is more than double this instance type's average "
|
|
186
|
-
|
|
192
|
+
"spot price ($ %f) over the last week", spot_bid, average)
|
|
187
193
|
|
|
188
194
|
|
|
189
|
-
def _get_spot_history(
|
|
195
|
+
def _get_spot_history(boto3_ec2: BaseClient, instance_type: str):
|
|
190
196
|
"""
|
|
191
197
|
Returns list of 1,000 most recent spot market data points represented as SpotPriceHistory
|
|
192
198
|
objects. Note: The most recent object/data point will be first in the list.
|
|
193
199
|
|
|
194
200
|
:rtype: list[SpotPriceHistory]
|
|
195
201
|
"""
|
|
196
|
-
|
|
197
202
|
one_week_ago = datetime.datetime.now() - datetime.timedelta(days=7)
|
|
198
|
-
spot_data =
|
|
199
|
-
|
|
200
|
-
|
|
203
|
+
spot_data = boto3_ec2.describe_spot_price_history(StartTime=one_week_ago.isoformat(),
|
|
204
|
+
InstanceTypes=[instance_type],
|
|
205
|
+
ProductDescriptions=["Linux/UNIX"])
|
|
201
206
|
spot_data.sort(key=attrgetter("timestamp"), reverse=True)
|
|
202
207
|
return spot_data
|