dstack 0.19.10__py3-none-any.whl → 0.19.11rc1__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.
Potentially problematic release.
This version of dstack might be problematic. Click here for more details.
- dstack/_internal/cli/commands/metrics.py +25 -10
- dstack/_internal/core/backends/azure/compute.py +7 -5
- dstack/_internal/core/backends/base/compute.py +2 -1
- dstack/_internal/core/models/configurations.py +2 -1
- dstack/_internal/core/models/runs.py +2 -1
- dstack/_internal/proxy/gateway/resources/nginx/00-log-format.conf +11 -1
- dstack/_internal/proxy/gateway/resources/nginx/service.jinja2 +12 -6
- dstack/_internal/proxy/gateway/services/stats.py +17 -3
- dstack/_internal/server/services/jobs/configurators/base.py +15 -1
- dstack/_internal/server/services/jobs/configurators/extensions/cursor.py +3 -1
- dstack/_internal/server/services/jobs/configurators/extensions/vscode.py +3 -1
- dstack/version.py +2 -2
- {dstack-0.19.10.dist-info → dstack-0.19.11rc1.dist-info}/METADATA +1 -1
- {dstack-0.19.10.dist-info → dstack-0.19.11rc1.dist-info}/RECORD +17 -17
- {dstack-0.19.10.dist-info → dstack-0.19.11rc1.dist-info}/WHEEL +0 -0
- {dstack-0.19.10.dist-info → dstack-0.19.11rc1.dist-info}/entry_points.txt +0 -0
- {dstack-0.19.10.dist-info → dstack-0.19.11rc1.dist-info}/licenses/LICENSE.md +0 -0
|
@@ -39,8 +39,6 @@ class MetricsCommand(APIBaseCommand):
|
|
|
39
39
|
run = self.api.runs.get(run_name=args.run_name)
|
|
40
40
|
if run is None:
|
|
41
41
|
raise CLIError(f"Run {args.run_name} not found")
|
|
42
|
-
if run.status.is_finished():
|
|
43
|
-
raise CLIError(f"Run {args.run_name} is finished")
|
|
44
42
|
metrics = _get_run_jobs_metrics(api=self.api, run=run)
|
|
45
43
|
|
|
46
44
|
if not args.watch:
|
|
@@ -55,8 +53,6 @@ class MetricsCommand(APIBaseCommand):
|
|
|
55
53
|
run = self.api.runs.get(run_name=args.run_name)
|
|
56
54
|
if run is None:
|
|
57
55
|
raise CLIError(f"Run {args.run_name} not found")
|
|
58
|
-
if run.status.is_finished():
|
|
59
|
-
raise CLIError(f"Run {args.run_name} is finished")
|
|
60
56
|
metrics = _get_run_jobs_metrics(api=self.api, run=run)
|
|
61
57
|
except KeyboardInterrupt:
|
|
62
58
|
pass
|
|
@@ -78,11 +74,12 @@ def _get_run_jobs_metrics(api: Client, run: Run) -> List[JobMetrics]:
|
|
|
78
74
|
def _get_metrics_table(run: Run, metrics: List[JobMetrics]) -> Table:
|
|
79
75
|
table = Table(box=None)
|
|
80
76
|
table.add_column("NAME", style="bold", no_wrap=True)
|
|
77
|
+
table.add_column("STATUS")
|
|
81
78
|
table.add_column("CPU")
|
|
82
79
|
table.add_column("MEMORY")
|
|
83
80
|
table.add_column("GPU")
|
|
84
81
|
|
|
85
|
-
run_row: Dict[Union[str, int], Any] = {"NAME": run.name}
|
|
82
|
+
run_row: Dict[Union[str, int], Any] = {"NAME": run.name, "STATUS": run.status.value}
|
|
86
83
|
if len(run._run.jobs) != 1:
|
|
87
84
|
add_row_from_dict(table, run_row)
|
|
88
85
|
|
|
@@ -101,9 +98,9 @@ def _get_metrics_table(run: Run, metrics: List[JobMetrics]) -> Table:
|
|
|
101
98
|
cpu_usage = f"{cpu_usage:.0f}%"
|
|
102
99
|
memory_usage = _get_metric_value(job_metrics, "memory_working_set_bytes")
|
|
103
100
|
if memory_usage is not None:
|
|
104
|
-
memory_usage =
|
|
101
|
+
memory_usage = _format_memory(memory_usage, 2)
|
|
105
102
|
if resources is not None:
|
|
106
|
-
memory_usage += f"/{resources.memory_mib}
|
|
103
|
+
memory_usage += f"/{_format_memory(resources.memory_mib * 1024 * 1024, 2)}"
|
|
107
104
|
gpu_metrics = ""
|
|
108
105
|
gpus_detected_num = _get_metric_value(job_metrics, "gpus_detected_num")
|
|
109
106
|
if gpus_detected_num is not None:
|
|
@@ -113,13 +110,16 @@ def _get_metrics_table(run: Run, metrics: List[JobMetrics]) -> Table:
|
|
|
113
110
|
if gpu_memory_usage is not None:
|
|
114
111
|
if i != 0:
|
|
115
112
|
gpu_metrics += "\n"
|
|
116
|
-
gpu_metrics += f"
|
|
113
|
+
gpu_metrics += f"gpu={i} mem={_format_memory(gpu_memory_usage, 2)}"
|
|
117
114
|
if resources is not None:
|
|
118
|
-
gpu_metrics +=
|
|
119
|
-
|
|
115
|
+
gpu_metrics += (
|
|
116
|
+
f"/{_format_memory(resources.gpus[i].memory_mib * 1024 * 1024, 2)}"
|
|
117
|
+
)
|
|
118
|
+
gpu_metrics += f" util={gpu_util_percent}%"
|
|
120
119
|
|
|
121
120
|
job_row: Dict[Union[str, int], Any] = {
|
|
122
121
|
"NAME": f" replica={job.job_spec.replica_num} job={job.job_spec.job_num}",
|
|
122
|
+
"STATUS": job.job_submissions[-1].status.value,
|
|
123
123
|
"CPU": cpu_usage or "-",
|
|
124
124
|
"MEMORY": memory_usage or "-",
|
|
125
125
|
"GPU": gpu_metrics or "-",
|
|
@@ -136,3 +136,18 @@ def _get_metric_value(job_metrics: JobMetrics, name: str) -> Optional[Any]:
|
|
|
136
136
|
if metric.name == name:
|
|
137
137
|
return metric.values[-1]
|
|
138
138
|
return None
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def _format_memory(memory_bytes: int, decimal_places: int) -> str:
|
|
142
|
+
"""See test_format_memory in tests/_internal/cli/commands/test_metrics.py for examples."""
|
|
143
|
+
memory_mb = memory_bytes / 1024 / 1024
|
|
144
|
+
if memory_mb >= 1024:
|
|
145
|
+
value = memory_mb / 1024
|
|
146
|
+
unit = "GB"
|
|
147
|
+
else:
|
|
148
|
+
value = memory_mb
|
|
149
|
+
unit = "MB"
|
|
150
|
+
|
|
151
|
+
if decimal_places == 0:
|
|
152
|
+
return f"{round(value)}{unit}"
|
|
153
|
+
return f"{value:.{decimal_places}f}".rstrip("0").rstrip(".") + unit
|
|
@@ -391,11 +391,8 @@ class VMImageVariant(enum.Enum):
|
|
|
391
391
|
|
|
392
392
|
|
|
393
393
|
_SUPPORTED_VM_SERIES_PATTERNS = [
|
|
394
|
-
#
|
|
395
|
-
#
|
|
396
|
-
r"D(\d+)s_v3", # Dsv3-series (general purpose)
|
|
397
|
-
r"E(\d+)i?s_v4", # Esv4-series (memory optimized)
|
|
398
|
-
r"E(\d+)-(\d+)s_v4", # Esv4-series (constrained vCPU)
|
|
394
|
+
r"D(\d+)s_v6", # Dsv6-series (general purpose)
|
|
395
|
+
r"E(\d+)i?s_v6", # Esv6-series (memory optimized)
|
|
399
396
|
r"F(\d+)s_v2", # Fsv2-series (compute optimized)
|
|
400
397
|
r"NC(\d+)s_v3", # NCv3-series [V100 16GB]
|
|
401
398
|
r"NC(\d+)as_T4_v3", # NCasT4_v3-series [T4]
|
|
@@ -404,6 +401,11 @@ _SUPPORTED_VM_SERIES_PATTERNS = [
|
|
|
404
401
|
r"NC(\d+)ads_A100_v4", # NC A100 v4-series [A100 80GB]
|
|
405
402
|
r"ND(\d+)asr_v4", # ND A100 v4-series [8xA100 40GB]
|
|
406
403
|
r"ND(\d+)amsr_A100_v4", # NDm A100 v4-series [8xA100 80GB]
|
|
404
|
+
# Deprecated series
|
|
405
|
+
# TODO: Remove after several releases
|
|
406
|
+
r"D(\d+)s_v3", # Dsv3-series (general purpose)
|
|
407
|
+
r"E(\d+)i?s_v4", # Esv4-series (memory optimized)
|
|
408
|
+
r"E(\d+)-(\d+)s_v4", # Esv4-series (constrained vCPU)
|
|
407
409
|
]
|
|
408
410
|
_SUPPORTED_VM_SERIES_PATTERN = (
|
|
409
411
|
"^Standard_(" + "|".join(f"({s})" for s in _SUPPORTED_VM_SERIES_PATTERNS) + ")$"
|
|
@@ -19,6 +19,7 @@ from dstack._internal.core.consts import (
|
|
|
19
19
|
DSTACK_RUNNER_SSH_PORT,
|
|
20
20
|
DSTACK_SHIM_HTTP_PORT,
|
|
21
21
|
)
|
|
22
|
+
from dstack._internal.core.models.configurations import DEFAULT_REPO_DIR
|
|
22
23
|
from dstack._internal.core.models.gateways import (
|
|
23
24
|
GatewayComputeConfiguration,
|
|
24
25
|
GatewayProvisioningData,
|
|
@@ -754,7 +755,7 @@ def get_docker_commands(
|
|
|
754
755
|
f" --ssh-port {DSTACK_RUNNER_SSH_PORT}"
|
|
755
756
|
" --temp-dir /tmp/runner"
|
|
756
757
|
" --home-dir /root"
|
|
757
|
-
" --working-dir
|
|
758
|
+
f" --working-dir {DEFAULT_REPO_DIR}"
|
|
758
759
|
),
|
|
759
760
|
]
|
|
760
761
|
|
|
@@ -26,6 +26,7 @@ STRIP_PREFIX_DEFAULT = True
|
|
|
26
26
|
RUN_PRIOTIRY_MIN = 0
|
|
27
27
|
RUN_PRIOTIRY_MAX = 100
|
|
28
28
|
RUN_PRIORITY_DEFAULT = 0
|
|
29
|
+
DEFAULT_REPO_DIR = "/workflow"
|
|
29
30
|
|
|
30
31
|
|
|
31
32
|
class RunConfigurationType(str, Enum):
|
|
@@ -181,7 +182,7 @@ class BaseRunConfiguration(CoreModel):
|
|
|
181
182
|
Field(
|
|
182
183
|
description=(
|
|
183
184
|
"The path to the working directory inside the container."
|
|
184
|
-
" It's specified relative to the repository directory (
|
|
185
|
+
f" It's specified relative to the repository directory (`{DEFAULT_REPO_DIR}`) and should be inside it."
|
|
185
186
|
' Defaults to `"."` '
|
|
186
187
|
)
|
|
187
188
|
),
|
|
@@ -8,6 +8,7 @@ from typing_extensions import Annotated
|
|
|
8
8
|
from dstack._internal.core.models.backends.base import BackendType
|
|
9
9
|
from dstack._internal.core.models.common import ApplyAction, CoreModel, NetworkMode, RegistryAuth
|
|
10
10
|
from dstack._internal.core.models.configurations import (
|
|
11
|
+
DEFAULT_REPO_DIR,
|
|
11
12
|
AnyRunConfiguration,
|
|
12
13
|
RunConfiguration,
|
|
13
14
|
)
|
|
@@ -338,7 +339,7 @@ class RunSpec(CoreModel):
|
|
|
338
339
|
Field(
|
|
339
340
|
description=(
|
|
340
341
|
"The path to the working directory inside the container."
|
|
341
|
-
" It's specified relative to the repository directory (
|
|
342
|
+
f" It's specified relative to the repository directory (`{DEFAULT_REPO_DIR}`) and should be inside it."
|
|
342
343
|
' Defaults to `"."`.'
|
|
343
344
|
)
|
|
344
345
|
),
|
|
@@ -1 +1,11 @@
|
|
|
1
|
-
log_format dstack_stat '$time_iso8601 $host $status $request_time';
|
|
1
|
+
log_format dstack_stat '$time_iso8601 $host $status $request_time $dstack_replica_hit';
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
# A hack to avoid this Nginx reload error when no services are registered:
|
|
5
|
+
# nginx: [emerg] unknown "dstack_replica_hit" variable
|
|
6
|
+
server {
|
|
7
|
+
listen unix:/tmp/dstack-dummy-nginx.sock;
|
|
8
|
+
server_name placeholder.local;
|
|
9
|
+
deny all;
|
|
10
|
+
set $dstack_replica_hit 0;
|
|
11
|
+
}
|
|
@@ -14,6 +14,7 @@ upstream {{ domain }}.upstream {
|
|
|
14
14
|
server {
|
|
15
15
|
server_name {{ domain }};
|
|
16
16
|
limit_req_status 429;
|
|
17
|
+
set $dstack_replica_hit 0;
|
|
17
18
|
access_log {{ access_log_path }} dstack_stat;
|
|
18
19
|
client_max_body_size {{ client_max_body_size }};
|
|
19
20
|
|
|
@@ -23,11 +24,7 @@ server {
|
|
|
23
24
|
auth_request /_dstack_auth;
|
|
24
25
|
{% endif %}
|
|
25
26
|
|
|
26
|
-
{% if replicas %}
|
|
27
27
|
try_files /nonexistent @$http_upgrade;
|
|
28
|
-
{% else %}
|
|
29
|
-
return 503;
|
|
30
|
-
{% endif %}
|
|
31
28
|
|
|
32
29
|
{% if location.limit_req %}
|
|
33
30
|
limit_req zone={{ location.limit_req.zone }}{% if location.limit_req.burst %} burst={{ location.limit_req.burst }} nodelay{% endif %};
|
|
@@ -35,8 +32,9 @@ server {
|
|
|
35
32
|
}
|
|
36
33
|
{% endfor %}
|
|
37
34
|
|
|
38
|
-
{% if replicas %}
|
|
39
35
|
location @websocket {
|
|
36
|
+
set $dstack_replica_hit 1;
|
|
37
|
+
{% if replicas %}
|
|
40
38
|
proxy_pass http://{{ domain }}.upstream;
|
|
41
39
|
proxy_set_header X-Real-IP $remote_addr;
|
|
42
40
|
proxy_set_header Host $host;
|
|
@@ -44,19 +42,27 @@ server {
|
|
|
44
42
|
proxy_set_header Upgrade $http_upgrade;
|
|
45
43
|
proxy_set_header Connection "Upgrade";
|
|
46
44
|
proxy_read_timeout 300s;
|
|
45
|
+
{% else %}
|
|
46
|
+
return 503;
|
|
47
|
+
{% endif %}
|
|
47
48
|
}
|
|
48
49
|
location @ {
|
|
50
|
+
set $dstack_replica_hit 1;
|
|
51
|
+
{% if replicas %}
|
|
49
52
|
proxy_pass http://{{ domain }}.upstream;
|
|
50
53
|
proxy_set_header X-Real-IP $remote_addr;
|
|
51
54
|
proxy_set_header Host $host;
|
|
52
55
|
proxy_read_timeout 300s;
|
|
56
|
+
{% else %}
|
|
57
|
+
return 503;
|
|
58
|
+
{% endif %}
|
|
53
59
|
}
|
|
54
|
-
{% endif %}
|
|
55
60
|
|
|
56
61
|
{% if auth %}
|
|
57
62
|
location = /_dstack_auth {
|
|
58
63
|
internal;
|
|
59
64
|
if ($remote_addr = 127.0.0.1) {
|
|
65
|
+
# for requests from the gateway app, e.g. from the OpenAI-compatible API
|
|
60
66
|
return 200;
|
|
61
67
|
}
|
|
62
68
|
proxy_pass http://localhost:{{ proxy_port }}/api/auth/{{ project_name }};
|
|
@@ -11,10 +11,10 @@ from pydantic import BaseModel
|
|
|
11
11
|
|
|
12
12
|
from dstack._internal.proxy.gateway.repo.repo import GatewayProxyRepo
|
|
13
13
|
from dstack._internal.proxy.gateway.schemas.stats import PerWindowStats, ServiceStats, Stat
|
|
14
|
+
from dstack._internal.proxy.lib.errors import UnexpectedProxyError
|
|
14
15
|
from dstack._internal.utils.common import run_async
|
|
15
16
|
|
|
16
17
|
logger = logging.getLogger(__name__)
|
|
17
|
-
IGNORE_STATUSES = {403, 404}
|
|
18
18
|
WINDOWS = (30, 60, 300)
|
|
19
19
|
TTL = WINDOWS[-1]
|
|
20
20
|
EMPTY_STATS = {window: Stat(requests=0, request_time=0.0) for window in WINDOWS}
|
|
@@ -35,6 +35,7 @@ class LogEntry(BaseModel):
|
|
|
35
35
|
host: str
|
|
36
36
|
status: int
|
|
37
37
|
request_time: float
|
|
38
|
+
is_replica_hit: bool
|
|
38
39
|
|
|
39
40
|
|
|
40
41
|
class StatsCollector:
|
|
@@ -87,7 +88,8 @@ class StatsCollector:
|
|
|
87
88
|
now = datetime.datetime.now(tz=datetime.timezone.utc)
|
|
88
89
|
|
|
89
90
|
for entry in self._read_access_log(now - datetime.timedelta(seconds=TTL)):
|
|
90
|
-
|
|
91
|
+
# only include requests that hit or should hit a service replica
|
|
92
|
+
if not entry.is_replica_hit:
|
|
91
93
|
continue
|
|
92
94
|
|
|
93
95
|
frame_timestamp = int(entry.timestamp.timestamp())
|
|
@@ -119,7 +121,10 @@ class StatsCollector:
|
|
|
119
121
|
line = self._file.readline()
|
|
120
122
|
if not line:
|
|
121
123
|
break
|
|
122
|
-
|
|
124
|
+
cells = line.split()
|
|
125
|
+
if len(cells) == 4: # compatibility with pre-0.19.11 logs
|
|
126
|
+
cells.append("0" if cells[2] in ["403", "404"] else "1")
|
|
127
|
+
timestamp_str, host, status, request_time, dstack_replica_hit = cells
|
|
123
128
|
timestamp = datetime.datetime.fromisoformat(timestamp_str)
|
|
124
129
|
if timestamp < after:
|
|
125
130
|
continue
|
|
@@ -128,6 +133,7 @@ class StatsCollector:
|
|
|
128
133
|
host=host,
|
|
129
134
|
status=int(status),
|
|
130
135
|
request_time=float(request_time),
|
|
136
|
+
is_replica_hit=_parse_nginx_bool(dstack_replica_hit),
|
|
131
137
|
)
|
|
132
138
|
if os.fstat(self._file.fileno()).st_ino != st_ino:
|
|
133
139
|
# file was rotated
|
|
@@ -154,3 +160,11 @@ async def get_service_stats(
|
|
|
154
160
|
)
|
|
155
161
|
for service in services
|
|
156
162
|
]
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def _parse_nginx_bool(v: str) -> bool:
|
|
166
|
+
if v == "0":
|
|
167
|
+
return False
|
|
168
|
+
if v == "1":
|
|
169
|
+
return True
|
|
170
|
+
raise UnexpectedProxyError(f"Cannot parse boolean value: expected '0' or '1', got {v!r}")
|
|
@@ -10,6 +10,7 @@ from dstack._internal import settings
|
|
|
10
10
|
from dstack._internal.core.errors import DockerRegistryError, ServerClientError
|
|
11
11
|
from dstack._internal.core.models.common import RegistryAuth
|
|
12
12
|
from dstack._internal.core.models.configurations import (
|
|
13
|
+
DEFAULT_REPO_DIR,
|
|
13
14
|
PortMapping,
|
|
14
15
|
PythonVersion,
|
|
15
16
|
RunConfigurationType,
|
|
@@ -149,7 +150,8 @@ class JobConfigurator(ABC):
|
|
|
149
150
|
commands = self.run_spec.configuration.commands
|
|
150
151
|
elif shell_commands := self._shell_commands():
|
|
151
152
|
entrypoint = [self._shell(), "-i", "-c"]
|
|
152
|
-
|
|
153
|
+
dstack_image_commands = self._dstack_image_commands()
|
|
154
|
+
commands = [_join_shell_commands(dstack_image_commands + shell_commands)]
|
|
153
155
|
else: # custom docker image without commands
|
|
154
156
|
image_config = await self._get_image_config()
|
|
155
157
|
entrypoint = image_config.entrypoint or []
|
|
@@ -164,6 +166,18 @@ class JobConfigurator(ABC):
|
|
|
164
166
|
|
|
165
167
|
return result
|
|
166
168
|
|
|
169
|
+
def _dstack_image_commands(self) -> List[str]:
|
|
170
|
+
if (
|
|
171
|
+
self.run_spec.configuration.image is not None
|
|
172
|
+
or self.run_spec.configuration.entrypoint is not None
|
|
173
|
+
):
|
|
174
|
+
return []
|
|
175
|
+
return [
|
|
176
|
+
f"uv venv --prompt workflow --seed {DEFAULT_REPO_DIR}/.venv > /dev/null 2>&1",
|
|
177
|
+
f"echo 'source {DEFAULT_REPO_DIR}/.venv/bin/activate' >> ~/.bashrc",
|
|
178
|
+
f"source {DEFAULT_REPO_DIR}/.venv/bin/activate",
|
|
179
|
+
]
|
|
180
|
+
|
|
167
181
|
def _app_specs(self) -> List[AppSpec]:
|
|
168
182
|
specs = []
|
|
169
183
|
for i, pm in enumerate(filter_reserved_ports(self._ports())):
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
from typing import List
|
|
2
2
|
|
|
3
|
+
from dstack._internal.core.models.configurations import DEFAULT_REPO_DIR
|
|
4
|
+
|
|
3
5
|
|
|
4
6
|
class CursorDesktop:
|
|
5
7
|
def __init__(
|
|
@@ -37,6 +39,6 @@ class CursorDesktop:
|
|
|
37
39
|
return [
|
|
38
40
|
"echo To open in Cursor, use link below:",
|
|
39
41
|
"echo ''",
|
|
40
|
-
f"echo ' cursor://vscode-remote/ssh-remote+{self.run_name}
|
|
42
|
+
f"echo ' cursor://vscode-remote/ssh-remote+{self.run_name}{DEFAULT_REPO_DIR}'", # TODO use $REPO_DIR
|
|
41
43
|
"echo ''",
|
|
42
44
|
]
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
from typing import List
|
|
2
2
|
|
|
3
|
+
from dstack._internal.core.models.configurations import DEFAULT_REPO_DIR
|
|
4
|
+
|
|
3
5
|
|
|
4
6
|
class VSCodeDesktop:
|
|
5
7
|
def __init__(
|
|
@@ -37,6 +39,6 @@ class VSCodeDesktop:
|
|
|
37
39
|
return [
|
|
38
40
|
"echo To open in VS Code Desktop, use link below:",
|
|
39
41
|
"echo ''",
|
|
40
|
-
f"echo ' vscode://vscode-remote/ssh-remote+{self.run_name}
|
|
42
|
+
f"echo ' vscode://vscode-remote/ssh-remote+{self.run_name}{DEFAULT_REPO_DIR}'", # TODO use $REPO_DIR
|
|
41
43
|
"echo ''",
|
|
42
44
|
]
|
dstack/version.py
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
__version__ = "0.19.
|
|
1
|
+
__version__ = "0.19.11rc1"
|
|
2
2
|
__is_release__ = True
|
|
3
|
-
base_image = "0.
|
|
3
|
+
base_image = "0.8"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dstack
|
|
3
|
-
Version: 0.19.
|
|
3
|
+
Version: 0.19.11rc1
|
|
4
4
|
Summary: dstack is an open-source orchestration engine for running AI workloads on any cloud or on-premises.
|
|
5
5
|
Project-URL: Homepage, https://dstack.ai
|
|
6
6
|
Project-URL: Source, https://github.com/dstackai/dstack
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
dstack/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
-
dstack/version.py,sha256=
|
|
2
|
+
dstack/version.py,sha256=GxG1ziHLEcRXoddW7khMHK2u0fShzLeWrp1qMzeZKMQ,68
|
|
3
3
|
dstack/_internal/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
4
|
dstack/_internal/compat.py,sha256=bF9U9fTMfL8UVhCouedoUSTYFl7UAOiU0WXrnRoByxw,40
|
|
5
5
|
dstack/_internal/settings.py,sha256=GOqfcLEONWC1hGU36IYPuOhJXP_qC3Y6d2SQge_NdpY,953
|
|
@@ -15,7 +15,7 @@ dstack/_internal/cli/commands/fleet.py,sha256=J0Yi5CAYvIQF_NC4ZBsDYGc3grTOtvaF7s
|
|
|
15
15
|
dstack/_internal/cli/commands/gateway.py,sha256=DcD6P_MvXbSL9aXkLX9hgGYSAzARjgY6RSbrCMzdNcg,6075
|
|
16
16
|
dstack/_internal/cli/commands/init.py,sha256=bLhSlViNWtjflB6xNq_PuCR2o2A06h222luh1NeUgVA,1169
|
|
17
17
|
dstack/_internal/cli/commands/logs.py,sha256=o8ehPAKM12Xn9thg2jjnYdr7_wKqF-00ziVry8IVVwE,1528
|
|
18
|
-
dstack/_internal/cli/commands/metrics.py,sha256=
|
|
18
|
+
dstack/_internal/cli/commands/metrics.py,sha256=ZS_dHD4_YK135J09xKpVTY_3CXzhj8QhDo18Ail9Pas,5862
|
|
19
19
|
dstack/_internal/cli/commands/offer.py,sha256=rf10T9ohEC77GmZexdqF_RBCQkLYzVSAwTzZlxukNYM,4085
|
|
20
20
|
dstack/_internal/cli/commands/project.py,sha256=V8gJwQWQGvGKQJPUyce_M7Ij_B7bOxYzo2IQgkLLHFE,6151
|
|
21
21
|
dstack/_internal/cli/commands/ps.py,sha256=5RU4mcL4-FT4PcXktfKb4htCOPqia7mIuVGgfK7x9lY,1894
|
|
@@ -58,14 +58,14 @@ dstack/_internal/core/backends/aws/resources.py,sha256=Wht_USG8ps9HQBhAYfxDxjaob
|
|
|
58
58
|
dstack/_internal/core/backends/azure/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
59
59
|
dstack/_internal/core/backends/azure/auth.py,sha256=CHp3QRNx3tIwkhyOY_l8WU-ElY4Pxhavoy9JSdwr15g,1259
|
|
60
60
|
dstack/_internal/core/backends/azure/backend.py,sha256=XySTor8v_tLkZctDBryrFHrbVzQgNf_RUPkXQYplvwM,746
|
|
61
|
-
dstack/_internal/core/backends/azure/compute.py,sha256=
|
|
61
|
+
dstack/_internal/core/backends/azure/compute.py,sha256=waunprBzpiJBMtVDJMjFCxEdmtO52E7ckzcc6OcZLf4,24488
|
|
62
62
|
dstack/_internal/core/backends/azure/configurator.py,sha256=cC0YhiayPtrOEEr8Lr-9nDDq6v2-sbxK-1QhixpM1YY,18228
|
|
63
63
|
dstack/_internal/core/backends/azure/models.py,sha256=ap0WsYBSFdDCxY0G3W1sg2DBN2k0xknz6bp8Ypf6phs,3356
|
|
64
64
|
dstack/_internal/core/backends/azure/resources.py,sha256=cJWS2Yjxdg-XtjpdBxfVDZaX_gTbuoEpmdjTxdA9uIw,3431
|
|
65
65
|
dstack/_internal/core/backends/azure/utils.py,sha256=taHMJq6UHRzUXLUcO2P5VCKy3wJaye2bG-6QdkEPNdY,1741
|
|
66
66
|
dstack/_internal/core/backends/base/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
67
67
|
dstack/_internal/core/backends/base/backend.py,sha256=hdFMHED1RMV9GVfLSU0yGhGE-cXlbLvt1coDA885PMM,505
|
|
68
|
-
dstack/_internal/core/backends/base/compute.py,sha256=
|
|
68
|
+
dstack/_internal/core/backends/base/compute.py,sha256=XblmmEz4muUjcnlIudKEwoPSaqMBVZtbOcwgGs47Xvc,28625
|
|
69
69
|
dstack/_internal/core/backends/base/configurator.py,sha256=OCv8N2oxcxy3In2zS1PKiCJ0a-COZwxGjBz2FYkQnfg,3807
|
|
70
70
|
dstack/_internal/core/backends/base/models.py,sha256=Ij0osOl-T-ABsKLoVg2eY81DMkwdWkevAnjXj2QnLXI,532
|
|
71
71
|
dstack/_internal/core/backends/base/offers.py,sha256=AzAAx5eSTaHv8CbWuGERTHS151x4oJuQn3tr_Bz9HKQ,6282
|
|
@@ -156,7 +156,7 @@ dstack/_internal/core/backends/vultr/models.py,sha256=TkqK_lW6w5k_7wsoFiKDb6NXuT
|
|
|
156
156
|
dstack/_internal/core/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
157
157
|
dstack/_internal/core/models/common.py,sha256=XWd79dmFGMrdpTcStH5fVmNXCKE0s7FsIorPL0saQ8w,2138
|
|
158
158
|
dstack/_internal/core/models/config.py,sha256=JJ7rT7dztzTWCY5TkoyxXxTvG5D4IFYhGe7EzwkLOWQ,581
|
|
159
|
-
dstack/_internal/core/models/configurations.py,sha256=
|
|
159
|
+
dstack/_internal/core/models/configurations.py,sha256=yG5GaCbTK4QhSh0UMYrYpFSeFvD0f-Uhi3TT_XviGhQ,19068
|
|
160
160
|
dstack/_internal/core/models/envs.py,sha256=yq84YRFBILOy4x3XnGcTgYpbZ69eFTCQPgBCr9Ndov4,4969
|
|
161
161
|
dstack/_internal/core/models/fleets.py,sha256=gbP2rj1ODDuy4IfTbPNB-ae050thvzTtA8uDb5iTmdY,12059
|
|
162
162
|
dstack/_internal/core/models/gateways.py,sha256=_O8EWwHWLdgNoWY4P4u71KM-uEr5DDp42LXfyv1qMDI,4054
|
|
@@ -167,7 +167,7 @@ dstack/_internal/core/models/placement.py,sha256=WJVq5ENJykyRarQzL2EeYQag_9_jV7V
|
|
|
167
167
|
dstack/_internal/core/models/profiles.py,sha256=seeysTuMv1vVUmpHAZgrMUGcbMtH7hSMFIvfx0Qk__0,10406
|
|
168
168
|
dstack/_internal/core/models/projects.py,sha256=H5ZZRiyUEKifpTFAhl45KBi5ly7ooE0WmI329myK360,643
|
|
169
169
|
dstack/_internal/core/models/resources.py,sha256=rsf6hAhi5bfSb_Z9VcS3UoEG0G8Ohl6ekyrOStLOAqw,14114
|
|
170
|
-
dstack/_internal/core/models/runs.py,sha256=
|
|
170
|
+
dstack/_internal/core/models/runs.py,sha256=6egFnxV0qGs-XCr22RvJc-rSpc3zsNIk2UF3cRdWlX4,19017
|
|
171
171
|
dstack/_internal/core/models/secrets.py,sha256=IQyemsNpSzqOCB-VlVTuc4gyPFmXXO4mhko0Ur0ey3I,221
|
|
172
172
|
dstack/_internal/core/models/server.py,sha256=Hkc1v2s3KOiwslsWVmhUOAzcSeREoG-HD1SzSX9WUGg,152
|
|
173
173
|
dstack/_internal/core/models/services.py,sha256=2Hpi7j0Q1shaf_0wd0C0044AJAmuYi-D3qx3PH849oI,3076
|
|
@@ -204,9 +204,9 @@ dstack/_internal/proxy/gateway/models.py,sha256=OLarOKJj-6teeg9dvxp3ueRv2_7yDJJf
|
|
|
204
204
|
dstack/_internal/proxy/gateway/repo/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
205
205
|
dstack/_internal/proxy/gateway/repo/repo.py,sha256=0i9FaLwDLnf8hijtRjT8hBooWj7EJ6L0_WJMbFaIBmo,4629
|
|
206
206
|
dstack/_internal/proxy/gateway/repo/state_v1.py,sha256=fngXqJWONuoJZEQcKHgiOGvs-ZQ3NATMzUFn67w4xxY,5943
|
|
207
|
-
dstack/_internal/proxy/gateway/resources/nginx/00-log-format.conf,sha256
|
|
207
|
+
dstack/_internal/proxy/gateway/resources/nginx/00-log-format.conf,sha256=-nVcJRFb4qbxy-t9BOq03dvdBtZ-P-Fi81gOzS0GnPc,361
|
|
208
208
|
dstack/_internal/proxy/gateway/resources/nginx/entrypoint.jinja2,sha256=umnUlm34wfoLNik3GFr1Gn2jtZMAx1-kgjBYcY3sLAU,817
|
|
209
|
-
dstack/_internal/proxy/gateway/resources/nginx/service.jinja2,sha256=
|
|
209
|
+
dstack/_internal/proxy/gateway/resources/nginx/service.jinja2,sha256=sccX4pIfdErti7VPhvN_9ObEJgbvsZc-COTJk1dUe8U,2780
|
|
210
210
|
dstack/_internal/proxy/gateway/routers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
211
211
|
dstack/_internal/proxy/gateway/routers/auth.py,sha256=PCMYEy2HLbiSZgqrtMUH90hbMAMXHp1nSZ0j13Nlrhs,253
|
|
212
212
|
dstack/_internal/proxy/gateway/routers/config.py,sha256=1UKHAPSYkeG8ULl9X3Eu6nPg94Xp-fecTObRa5Yw294,908
|
|
@@ -221,7 +221,7 @@ dstack/_internal/proxy/gateway/services/__init__.py,sha256=47DEQpj8HBSa-_TImW-5J
|
|
|
221
221
|
dstack/_internal/proxy/gateway/services/nginx.py,sha256=tGvs0Ci1X0aO8HjaflCgkxEXop0Z7o6euw7ADfCUOro,6149
|
|
222
222
|
dstack/_internal/proxy/gateway/services/registry.py,sha256=Gqyri5PaJW79iRYufawS09XHO_q7a1Re3tx2dGjBTfQ,13580
|
|
223
223
|
dstack/_internal/proxy/gateway/services/server_client.py,sha256=KSnpO8iPm5wxQPU0DcW7kqUzwliaQrb3b0K8Jmk8iA0,3630
|
|
224
|
-
dstack/_internal/proxy/gateway/services/stats.py,sha256=
|
|
224
|
+
dstack/_internal/proxy/gateway/services/stats.py,sha256=F1LI34oXk_vF3VkWqpRnf_aO2ykECv6_WmBlZVa2jU8,5945
|
|
225
225
|
dstack/_internal/proxy/gateway/testing/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
226
226
|
dstack/_internal/proxy/gateway/testing/common.py,sha256=K50IHpdxM9NpojVPrFFEaZyMwTAHvDU76VLB3qlZBn8,269
|
|
227
227
|
dstack/_internal/proxy/lib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -402,14 +402,14 @@ dstack/_internal/server/services/gateways/connection.py,sha256=ot3lV85XdmCT45vBW
|
|
|
402
402
|
dstack/_internal/server/services/gateways/pool.py,sha256=0LclTl1tyx-doS78LeaAKjr-SMp98zuwh5f9s06JSd0,1914
|
|
403
403
|
dstack/_internal/server/services/jobs/__init__.py,sha256=GU3vMC0SZKyvL564A7t_QRoDjf83-8GsUkguDWK5x6c,25578
|
|
404
404
|
dstack/_internal/server/services/jobs/configurators/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
405
|
-
dstack/_internal/server/services/jobs/configurators/base.py,sha256=
|
|
405
|
+
dstack/_internal/server/services/jobs/configurators/base.py,sha256=WLRIBM50P8mfvpotzYjK3Gtf5ScQsuijGieH_zaYqCg,11984
|
|
406
406
|
dstack/_internal/server/services/jobs/configurators/dev.py,sha256=ufN6Sd8TwIsjQYNZE32fkAqJI7o2zjgoZThbrP-bd7U,2378
|
|
407
407
|
dstack/_internal/server/services/jobs/configurators/service.py,sha256=FOWrLE-6YFSMuGqjOwYTLMV4FuIM5lCMDFjS0l0CoLI,929
|
|
408
408
|
dstack/_internal/server/services/jobs/configurators/task.py,sha256=0-B3oO-61Eq4-mmlLmqJPliFKHhvvIV0tqc12slcQuA,1436
|
|
409
409
|
dstack/_internal/server/services/jobs/configurators/extensions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
410
410
|
dstack/_internal/server/services/jobs/configurators/extensions/base.py,sha256=xJbHxaaSJ1zjn8zuuApP1Xt2uBaedPhhc-IY0NtDDJQ,418
|
|
411
|
-
dstack/_internal/server/services/jobs/configurators/extensions/cursor.py,sha256=
|
|
412
|
-
dstack/_internal/server/services/jobs/configurators/extensions/vscode.py,sha256=
|
|
411
|
+
dstack/_internal/server/services/jobs/configurators/extensions/cursor.py,sha256=r6Cgdd-P5C63xXyrqC6E0yNKIeTX6KabRLO92VEpJRY,1719
|
|
412
|
+
dstack/_internal/server/services/jobs/configurators/extensions/vscode.py,sha256=WRg_jqi4eSqbs3XRVASMFF7OQHYRDtVBNn6NCroJY1I,1694
|
|
413
413
|
dstack/_internal/server/services/logs/__init__.py,sha256=NAjO1KeYvuDznN2EkfAaJt9S6Y00fo_dl3ob3WmsdGQ,3088
|
|
414
414
|
dstack/_internal/server/services/logs/aws.py,sha256=MuRVGgYwkh0TA11Y2H0upSj56-k_Bs-vT_oa2X-5yZE,13834
|
|
415
415
|
dstack/_internal/server/services/logs/base.py,sha256=7eCB6SPF9iWviv4vZ_34SvfM_Bvi9DeVj1t7TxmrXKs,1273
|
|
@@ -584,8 +584,8 @@ dstack/plugins/__init__.py,sha256=buT1pcyORLgVbl89ATkRWJPhvejriVz7sNBjvuZRCRE,40
|
|
|
584
584
|
dstack/plugins/_base.py,sha256=-etiB-EozaJCg2wtmONfj8ic-K03qXvXyl_TIDp-kNE,2662
|
|
585
585
|
dstack/plugins/_models.py,sha256=1Gw--mDQ1_0FFr9Zur9LE8UbMoWESUpTdHHt12AyIZo,341
|
|
586
586
|
dstack/plugins/_utils.py,sha256=FqeWYb7zOrgZkO9Bd8caL5I81_TUEsysIzvxsULrmzk,392
|
|
587
|
-
dstack-0.19.
|
|
588
|
-
dstack-0.19.
|
|
589
|
-
dstack-0.19.
|
|
590
|
-
dstack-0.19.
|
|
591
|
-
dstack-0.19.
|
|
587
|
+
dstack-0.19.11rc1.dist-info/METADATA,sha256=ZU6h89CiVMvwc_lXF_Cv4LI2DPdA6_zvPr7rZF1iTJY,20512
|
|
588
|
+
dstack-0.19.11rc1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
589
|
+
dstack-0.19.11rc1.dist-info/entry_points.txt,sha256=GnLrMS8hx3rWAySQjA7tPNhtixV6a-brRkmal1PKoHc,58
|
|
590
|
+
dstack-0.19.11rc1.dist-info/licenses/LICENSE.md,sha256=qDABaRGjSKVOib1U8viw2P_96sIK7Puo426784oD9f8,15976
|
|
591
|
+
dstack-0.19.11rc1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|