-
-
Notifications
You must be signed in to change notification settings - Fork 223
Expand file tree
/
Copy pathprofile.py
More file actions
182 lines (167 loc) · 5.69 KB
/
profile.py
File metadata and controls
182 lines (167 loc) · 5.69 KB
1
2
3
4
5
6
7
8
9
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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
import argparse
import os
from typing import Union
from dstack._internal.core.models.configurations import AnyRunConfiguration
from dstack._internal.core.models.profiles import (
CreationPolicy,
Profile,
ProfileRetry,
SpotPolicy,
parse_duration,
parse_max_duration,
)
def register_profile_args(parser: argparse.ArgumentParser):
"""
Registers `parser` with `dstack apply` run configuration
CLI arguments that override `profiles.yml` settings.
"""
profile_group = parser.add_argument_group("Profile")
profile_group.add_argument(
"--profile",
metavar="NAME",
help="The name of the profile. Defaults to [code]$DSTACK_PROFILE[/]",
default=os.getenv("DSTACK_PROFILE"),
dest="profile",
)
profile_group.add_argument(
"--max-price",
metavar="PRICE",
type=float,
help="The maximum price per hour, in dollars",
dest="max_price",
)
profile_group.add_argument(
"--max-duration",
type=max_duration,
dest="max_duration",
help="The maximum duration of the run",
metavar="DURATION",
)
profile_group.add_argument(
"-b",
"--backend",
action="append",
metavar="NAME",
dest="backends",
help="The backends that will be tried for provisioning",
)
profile_group.add_argument(
"-r",
"--region",
action="append",
metavar="NAME",
dest="regions",
help="The regions that will be tried for provisioning",
)
profile_group.add_argument(
"--instance-type",
action="append",
metavar="NAME",
dest="instance_types",
help="The cloud-specific instance types that will be tried for provisioning",
)
fleets_group = parser.add_argument_group("Fleets")
fleets_group.add_argument(
"--fleet",
action="append",
metavar="NAME",
dest="fleets",
help="Consider only the specified fleet(s)",
)
fleets_group_exc = fleets_group.add_mutually_exclusive_group()
fleets_group_exc.add_argument(
"-R",
"--reuse",
dest="creation_policy_reuse",
action="store_true",
help="Reuse an existing instance from fleet (do not provision a new one)",
)
fleets_group_exc.add_argument(
"--dont-destroy",
dest="dont_destroy",
action="store_true",
help="Do not destroy instance after the run is finished (if the run provisions a new instance)",
)
fleets_group_exc.add_argument(
"--idle-duration",
dest="idle_duration",
type=str,
help="Time to wait before destroying the idle instance (if the run provisions a new instance)",
)
spot_group = parser.add_argument_group("Spot policy")
spot_group_exc = spot_group.add_mutually_exclusive_group()
spot_group_exc.add_argument(
"--spot",
action="store_const",
dest="spot_policy",
const=SpotPolicy.SPOT,
help="Consider only spot instances",
)
spot_group_exc.add_argument(
"--on-demand",
action="store_const",
dest="spot_policy",
const=SpotPolicy.ONDEMAND,
help="Consider only on-demand instances",
)
spot_group_exc.add_argument(
"--spot-auto",
action="store_const",
dest="spot_policy",
const=SpotPolicy.AUTO,
help="Consider both spot and on-demand instances",
)
spot_group_exc.add_argument(
"--spot-policy",
type=SpotPolicy,
dest="spot_policy",
metavar="POLICY",
help="One of %s" % ", ".join([f"[code]{i.value}[/]" for i in SpotPolicy]),
)
retry_group = parser.add_argument_group("Retry policy")
retry_group_exc = retry_group.add_mutually_exclusive_group()
retry_group_exc.add_argument("--retry", action="store_const", dest="retry", const=True)
retry_group_exc.add_argument("--no-retry", action="store_const", dest="retry", const=False)
retry_group_exc.add_argument(
"--retry-duration", type=retry_duration, dest="retry_duration", metavar="DURATION"
)
def apply_profile_args(
args: argparse.Namespace,
profile_settings: Union[Profile, AnyRunConfiguration],
):
"""
Overrides `profile_settings` settings with arguments registered by `register_profile_args()`.
"""
# TODO: Re-assigned profile attributes are not validated by pydantic.
# So the validation will only be done by the server.
# Consider setting validate_assignment=True for modified pydantic models.
if args.backends:
profile_settings.backends = args.backends
if args.regions:
profile_settings.regions = args.regions
if args.instance_types:
profile_settings.instance_types = args.instance_types
if args.max_price is not None:
profile_settings.max_price = args.max_price
if args.max_duration is not None:
profile_settings.max_duration = args.max_duration
if args.fleets:
profile_settings.fleets = args.fleets
if args.idle_duration is not None:
profile_settings.idle_duration = args.idle_duration
elif args.dont_destroy:
profile_settings.idle_duration = -1
if args.creation_policy_reuse:
profile_settings.creation_policy = CreationPolicy.REUSE
if args.spot_policy is not None:
profile_settings.spot_policy = args.spot_policy
if args.retry is not None:
profile_settings.retry = args.retry
elif args.retry_duration is not None:
profile_settings.retry = ProfileRetry(
duration=args.retry_duration,
)
def max_duration(v: str) -> int:
return parse_max_duration(v)
def retry_duration(v: str) -> int:
return parse_duration(v)