dstack 0.18.44__py3-none-any.whl → 0.19.0rc1__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.
Files changed (267) hide show
  1. dstack/_internal/cli/commands/gateway.py +15 -3
  2. dstack/_internal/cli/commands/logs.py +0 -22
  3. dstack/_internal/cli/commands/stats.py +8 -17
  4. dstack/_internal/cli/main.py +1 -5
  5. dstack/_internal/cli/services/configurators/fleet.py +4 -39
  6. dstack/_internal/cli/services/configurators/run.py +22 -21
  7. dstack/_internal/cli/services/profile.py +34 -83
  8. dstack/_internal/cli/utils/gateway.py +1 -1
  9. dstack/_internal/core/backends/__init__.py +56 -39
  10. dstack/_internal/core/backends/aws/__init__.py +0 -25
  11. dstack/_internal/core/backends/aws/auth.py +1 -10
  12. dstack/_internal/core/backends/aws/backend.py +26 -0
  13. dstack/_internal/core/backends/aws/compute.py +20 -45
  14. dstack/_internal/{server/services/backends/configurators/aws.py → core/backends/aws/configurator.py} +46 -85
  15. dstack/_internal/core/backends/aws/models.py +135 -0
  16. dstack/_internal/core/backends/aws/resources.py +1 -1
  17. dstack/_internal/core/backends/azure/__init__.py +0 -20
  18. dstack/_internal/core/backends/azure/auth.py +2 -11
  19. dstack/_internal/core/backends/azure/backend.py +21 -0
  20. dstack/_internal/core/backends/azure/compute.py +13 -27
  21. dstack/_internal/{server/services/backends/configurators/azure.py → core/backends/azure/configurator.py} +141 -210
  22. dstack/_internal/core/backends/azure/models.py +89 -0
  23. dstack/_internal/core/backends/base/__init__.py +0 -12
  24. dstack/_internal/core/backends/base/backend.py +18 -0
  25. dstack/_internal/core/backends/base/compute.py +153 -33
  26. dstack/_internal/core/backends/base/configurator.py +105 -0
  27. dstack/_internal/core/backends/base/models.py +14 -0
  28. dstack/_internal/core/backends/configurators.py +138 -0
  29. dstack/_internal/core/backends/cudo/__init__.py +0 -15
  30. dstack/_internal/core/backends/cudo/backend.py +16 -0
  31. dstack/_internal/core/backends/cudo/compute.py +8 -26
  32. dstack/_internal/core/backends/cudo/configurator.py +72 -0
  33. dstack/_internal/core/backends/cudo/models.py +37 -0
  34. dstack/_internal/core/backends/datacrunch/__init__.py +0 -15
  35. dstack/_internal/core/backends/datacrunch/backend.py +16 -0
  36. dstack/_internal/core/backends/datacrunch/compute.py +8 -25
  37. dstack/_internal/core/backends/datacrunch/configurator.py +66 -0
  38. dstack/_internal/core/backends/datacrunch/models.py +38 -0
  39. dstack/_internal/core/{models/backends/dstack.py → backends/dstack/models.py} +7 -7
  40. dstack/_internal/core/backends/gcp/__init__.py +0 -16
  41. dstack/_internal/core/backends/gcp/auth.py +2 -11
  42. dstack/_internal/core/backends/gcp/backend.py +17 -0
  43. dstack/_internal/core/backends/gcp/compute.py +13 -43
  44. dstack/_internal/{server/services/backends/configurators/gcp.py → core/backends/gcp/configurator.py} +46 -103
  45. dstack/_internal/core/backends/gcp/models.py +125 -0
  46. dstack/_internal/core/backends/kubernetes/__init__.py +0 -15
  47. dstack/_internal/core/backends/kubernetes/backend.py +16 -0
  48. dstack/_internal/core/backends/kubernetes/compute.py +16 -5
  49. dstack/_internal/core/backends/kubernetes/configurator.py +55 -0
  50. dstack/_internal/core/backends/kubernetes/models.py +72 -0
  51. dstack/_internal/core/backends/lambdalabs/__init__.py +0 -16
  52. dstack/_internal/core/backends/lambdalabs/backend.py +17 -0
  53. dstack/_internal/core/backends/lambdalabs/compute.py +7 -28
  54. dstack/_internal/core/backends/lambdalabs/configurator.py +82 -0
  55. dstack/_internal/core/backends/lambdalabs/models.py +37 -0
  56. dstack/_internal/core/backends/local/__init__.py +0 -13
  57. dstack/_internal/core/backends/local/backend.py +14 -0
  58. dstack/_internal/core/backends/local/compute.py +16 -2
  59. dstack/_internal/core/backends/models.py +128 -0
  60. dstack/_internal/core/backends/oci/__init__.py +0 -15
  61. dstack/_internal/core/backends/oci/auth.py +1 -5
  62. dstack/_internal/core/backends/oci/backend.py +16 -0
  63. dstack/_internal/core/backends/oci/compute.py +9 -23
  64. dstack/_internal/{server/services/backends/configurators/oci.py → core/backends/oci/configurator.py} +40 -85
  65. dstack/_internal/core/{models/backends/oci.py → backends/oci/models.py} +24 -25
  66. dstack/_internal/core/backends/oci/region.py +1 -1
  67. dstack/_internal/core/backends/runpod/__init__.py +0 -15
  68. dstack/_internal/core/backends/runpod/backend.py +16 -0
  69. dstack/_internal/core/backends/runpod/compute.py +7 -3
  70. dstack/_internal/core/backends/runpod/configurator.py +59 -0
  71. dstack/_internal/core/backends/runpod/models.py +54 -0
  72. dstack/_internal/core/backends/template/__init__.py +0 -0
  73. dstack/_internal/core/backends/tensordock/__init__.py +0 -15
  74. dstack/_internal/core/backends/tensordock/backend.py +16 -0
  75. dstack/_internal/core/backends/tensordock/compute.py +8 -27
  76. dstack/_internal/core/backends/tensordock/configurator.py +68 -0
  77. dstack/_internal/core/backends/tensordock/models.py +38 -0
  78. dstack/_internal/core/backends/vastai/__init__.py +0 -15
  79. dstack/_internal/core/backends/vastai/backend.py +16 -0
  80. dstack/_internal/core/backends/vastai/compute.py +2 -2
  81. dstack/_internal/core/backends/vastai/configurator.py +66 -0
  82. dstack/_internal/core/backends/vastai/models.py +37 -0
  83. dstack/_internal/core/backends/vultr/__init__.py +0 -15
  84. dstack/_internal/core/backends/vultr/backend.py +16 -0
  85. dstack/_internal/core/backends/vultr/compute.py +10 -24
  86. dstack/_internal/core/backends/vultr/configurator.py +64 -0
  87. dstack/_internal/core/backends/vultr/models.py +34 -0
  88. dstack/_internal/core/models/backends/__init__.py +0 -184
  89. dstack/_internal/core/models/backends/base.py +0 -19
  90. dstack/_internal/core/models/configurations.py +20 -15
  91. dstack/_internal/core/models/envs.py +4 -3
  92. dstack/_internal/core/models/fleets.py +17 -22
  93. dstack/_internal/core/models/gateways.py +3 -3
  94. dstack/_internal/core/models/instances.py +24 -0
  95. dstack/_internal/core/models/profiles.py +41 -46
  96. dstack/_internal/core/models/projects.py +1 -1
  97. dstack/_internal/core/models/repos/base.py +0 -5
  98. dstack/_internal/core/models/repos/local.py +3 -3
  99. dstack/_internal/core/models/repos/remote.py +26 -12
  100. dstack/_internal/core/models/repos/virtual.py +1 -1
  101. dstack/_internal/core/models/resources.py +45 -76
  102. dstack/_internal/core/models/runs.py +17 -19
  103. dstack/_internal/core/models/volumes.py +1 -3
  104. dstack/_internal/core/services/profiles.py +7 -16
  105. dstack/_internal/core/services/repos.py +0 -4
  106. dstack/_internal/server/app.py +0 -3
  107. dstack/_internal/server/background/tasks/process_gateways.py +4 -8
  108. dstack/_internal/server/background/tasks/process_instances.py +14 -9
  109. dstack/_internal/server/background/tasks/process_metrics.py +1 -1
  110. dstack/_internal/server/background/tasks/process_placement_groups.py +4 -1
  111. dstack/_internal/server/background/tasks/process_prometheus_metrics.py +1 -1
  112. dstack/_internal/server/background/tasks/process_running_jobs.py +14 -5
  113. dstack/_internal/server/background/tasks/process_submitted_jobs.py +16 -37
  114. dstack/_internal/server/background/tasks/process_volumes.py +5 -2
  115. dstack/_internal/server/migrations/versions/7bc2586e8b9e_make_instancemodel_pool_id_optional.py +36 -0
  116. dstack/_internal/server/migrations/versions/bc8ca4a505c6_store_backendtype_as_string.py +171 -0
  117. dstack/_internal/server/models.py +48 -9
  118. dstack/_internal/server/routers/backends.py +14 -23
  119. dstack/_internal/server/routers/instances.py +3 -4
  120. dstack/_internal/server/routers/metrics.py +10 -8
  121. dstack/_internal/server/routers/prometheus.py +1 -1
  122. dstack/_internal/server/routers/repos.py +1 -2
  123. dstack/_internal/server/routers/runs.py +13 -59
  124. dstack/_internal/server/schemas/gateways.py +14 -23
  125. dstack/_internal/server/schemas/projects.py +7 -2
  126. dstack/_internal/server/schemas/repos.py +2 -38
  127. dstack/_internal/server/schemas/runner.py +1 -0
  128. dstack/_internal/server/schemas/runs.py +1 -24
  129. dstack/_internal/server/services/backends/__init__.py +85 -158
  130. dstack/_internal/server/services/config.py +52 -576
  131. dstack/_internal/server/services/fleets.py +8 -103
  132. dstack/_internal/server/services/gateways/__init__.py +12 -4
  133. dstack/_internal/server/services/{pools.py → instances.py} +22 -329
  134. dstack/_internal/server/services/jobs/__init__.py +9 -6
  135. dstack/_internal/server/services/jobs/configurators/base.py +16 -0
  136. dstack/_internal/server/services/jobs/configurators/dev.py +9 -1
  137. dstack/_internal/server/services/jobs/configurators/extensions/cursor.py +42 -0
  138. dstack/_internal/server/services/metrics.py +39 -13
  139. dstack/_internal/server/services/offers.py +1 -1
  140. dstack/_internal/server/services/projects.py +23 -14
  141. dstack/_internal/server/services/prometheus.py +176 -18
  142. dstack/_internal/server/services/runs.py +24 -16
  143. dstack/_internal/server/services/volumes.py +8 -4
  144. dstack/_internal/server/statics/index.html +1 -1
  145. dstack/_internal/server/statics/{main-4eb116b97819badd1e2c.js → main-4fd5a4770eff59325ee3.js} +7 -7
  146. dstack/_internal/server/statics/{main-4eb116b97819badd1e2c.js.map → main-4fd5a4770eff59325ee3.js.map} +1 -1
  147. dstack/_internal/server/testing/common.py +58 -32
  148. dstack/_internal/utils/json_schema.py +6 -0
  149. dstack/_internal/utils/ssh.py +2 -1
  150. dstack/api/__init__.py +4 -0
  151. dstack/api/_public/__init__.py +16 -20
  152. dstack/api/_public/backends.py +1 -1
  153. dstack/api/_public/repos.py +36 -36
  154. dstack/api/_public/runs.py +167 -83
  155. dstack/api/server/__init__.py +11 -13
  156. dstack/api/server/_backends.py +12 -16
  157. dstack/api/server/_fleets.py +15 -57
  158. dstack/api/server/_gateways.py +3 -14
  159. dstack/api/server/_repos.py +1 -4
  160. dstack/api/server/_runs.py +21 -100
  161. dstack/api/server/_volumes.py +10 -5
  162. dstack/version.py +1 -1
  163. {dstack-0.18.44.dist-info → dstack-0.19.0rc1.dist-info}/METADATA +1 -1
  164. {dstack-0.18.44.dist-info → dstack-0.19.0rc1.dist-info}/RECORD +218 -204
  165. tests/_internal/cli/services/configurators/test_profile.py +6 -6
  166. tests/_internal/core/backends/aws/test_configurator.py +35 -0
  167. tests/_internal/core/backends/aws/test_resources.py +1 -1
  168. tests/_internal/core/backends/azure/test_configurator.py +61 -0
  169. tests/_internal/core/backends/cudo/__init__.py +0 -0
  170. tests/_internal/core/backends/cudo/test_configurator.py +37 -0
  171. tests/_internal/core/backends/datacrunch/__init__.py +0 -0
  172. tests/_internal/core/backends/datacrunch/test_configurator.py +17 -0
  173. tests/_internal/core/backends/gcp/test_configurator.py +42 -0
  174. tests/_internal/core/backends/kubernetes/test_configurator.py +43 -0
  175. tests/_internal/core/backends/lambdalabs/__init__.py +0 -0
  176. tests/_internal/core/backends/lambdalabs/test_configurator.py +38 -0
  177. tests/_internal/core/backends/oci/test_configurator.py +55 -0
  178. tests/_internal/core/backends/runpod/__init__.py +0 -0
  179. tests/_internal/core/backends/runpod/test_configurator.py +33 -0
  180. tests/_internal/core/backends/tensordock/__init__.py +0 -0
  181. tests/_internal/core/backends/tensordock/test_configurator.py +38 -0
  182. tests/_internal/core/backends/vastai/__init__.py +0 -0
  183. tests/_internal/core/backends/vastai/test_configurator.py +33 -0
  184. tests/_internal/core/backends/vultr/__init__.py +0 -0
  185. tests/_internal/core/backends/vultr/test_configurator.py +33 -0
  186. tests/_internal/server/background/tasks/test_process_gateways.py +4 -0
  187. tests/_internal/server/background/tasks/test_process_instances.py +49 -48
  188. tests/_internal/server/background/tasks/test_process_metrics.py +0 -3
  189. tests/_internal/server/background/tasks/test_process_placement_groups.py +2 -0
  190. tests/_internal/server/background/tasks/test_process_prometheus_metrics.py +0 -3
  191. tests/_internal/server/background/tasks/test_process_running_jobs.py +0 -21
  192. tests/_internal/server/background/tasks/test_process_runs.py +8 -22
  193. tests/_internal/server/background/tasks/test_process_submitted_jobs.py +3 -40
  194. tests/_internal/server/background/tasks/test_process_submitted_volumes.py +2 -0
  195. tests/_internal/server/background/tasks/test_process_terminating_jobs.py +10 -15
  196. tests/_internal/server/routers/test_backends.py +6 -764
  197. tests/_internal/server/routers/test_fleets.py +0 -26
  198. tests/_internal/server/routers/test_gateways.py +27 -3
  199. tests/_internal/server/routers/test_instances.py +0 -10
  200. tests/_internal/server/routers/test_metrics.py +27 -0
  201. tests/_internal/server/routers/test_projects.py +56 -0
  202. tests/_internal/server/routers/test_prometheus.py +116 -27
  203. tests/_internal/server/routers/test_repos.py +0 -15
  204. tests/_internal/server/routers/test_runs.py +4 -219
  205. tests/_internal/server/routers/test_volumes.py +2 -3
  206. tests/_internal/server/services/backends/__init__.py +0 -0
  207. tests/_internal/server/services/jobs/configurators/test_task.py +35 -0
  208. tests/_internal/server/services/test_config.py +7 -4
  209. tests/_internal/server/services/test_fleets.py +1 -4
  210. tests/_internal/server/services/{test_pools.py → test_instances.py} +11 -49
  211. tests/_internal/server/services/test_metrics.py +9 -5
  212. tests/_internal/server/services/test_repos.py +1 -14
  213. tests/_internal/server/services/test_runs.py +0 -4
  214. dstack/_internal/cli/commands/pool.py +0 -581
  215. dstack/_internal/cli/commands/run.py +0 -75
  216. dstack/_internal/core/backends/aws/config.py +0 -18
  217. dstack/_internal/core/backends/azure/config.py +0 -12
  218. dstack/_internal/core/backends/base/config.py +0 -5
  219. dstack/_internal/core/backends/cudo/config.py +0 -9
  220. dstack/_internal/core/backends/datacrunch/config.py +0 -9
  221. dstack/_internal/core/backends/gcp/config.py +0 -22
  222. dstack/_internal/core/backends/kubernetes/config.py +0 -6
  223. dstack/_internal/core/backends/lambdalabs/config.py +0 -9
  224. dstack/_internal/core/backends/nebius/__init__.py +0 -15
  225. dstack/_internal/core/backends/nebius/api_client.py +0 -319
  226. dstack/_internal/core/backends/nebius/compute.py +0 -220
  227. dstack/_internal/core/backends/nebius/config.py +0 -6
  228. dstack/_internal/core/backends/nebius/types.py +0 -37
  229. dstack/_internal/core/backends/oci/config.py +0 -6
  230. dstack/_internal/core/backends/runpod/config.py +0 -17
  231. dstack/_internal/core/backends/tensordock/config.py +0 -9
  232. dstack/_internal/core/backends/vastai/config.py +0 -6
  233. dstack/_internal/core/backends/vultr/config.py +0 -9
  234. dstack/_internal/core/models/backends/aws.py +0 -86
  235. dstack/_internal/core/models/backends/azure.py +0 -68
  236. dstack/_internal/core/models/backends/cudo.py +0 -43
  237. dstack/_internal/core/models/backends/datacrunch.py +0 -44
  238. dstack/_internal/core/models/backends/gcp.py +0 -67
  239. dstack/_internal/core/models/backends/kubernetes.py +0 -40
  240. dstack/_internal/core/models/backends/lambdalabs.py +0 -43
  241. dstack/_internal/core/models/backends/nebius.py +0 -54
  242. dstack/_internal/core/models/backends/runpod.py +0 -42
  243. dstack/_internal/core/models/backends/tensordock.py +0 -44
  244. dstack/_internal/core/models/backends/vastai.py +0 -43
  245. dstack/_internal/core/models/backends/vultr.py +0 -40
  246. dstack/_internal/core/models/pools.py +0 -43
  247. dstack/_internal/server/routers/pools.py +0 -142
  248. dstack/_internal/server/schemas/pools.py +0 -38
  249. dstack/_internal/server/services/backends/configurators/base.py +0 -72
  250. dstack/_internal/server/services/backends/configurators/cudo.py +0 -87
  251. dstack/_internal/server/services/backends/configurators/datacrunch.py +0 -79
  252. dstack/_internal/server/services/backends/configurators/kubernetes.py +0 -63
  253. dstack/_internal/server/services/backends/configurators/lambdalabs.py +0 -98
  254. dstack/_internal/server/services/backends/configurators/nebius.py +0 -85
  255. dstack/_internal/server/services/backends/configurators/runpod.py +0 -67
  256. dstack/_internal/server/services/backends/configurators/tensordock.py +0 -82
  257. dstack/_internal/server/services/backends/configurators/vastai.py +0 -80
  258. dstack/_internal/server/services/backends/configurators/vultr.py +0 -80
  259. dstack/api/_public/pools.py +0 -41
  260. dstack/api/_public/resources.py +0 -105
  261. dstack/api/server/_pools.py +0 -63
  262. tests/_internal/server/routers/test_pools.py +0 -612
  263. /dstack/_internal/{server/services/backends/configurators → core/backends/dstack}/__init__.py +0 -0
  264. {dstack-0.18.44.dist-info → dstack-0.19.0rc1.dist-info}/LICENSE.md +0 -0
  265. {dstack-0.18.44.dist-info → dstack-0.19.0rc1.dist-info}/WHEEL +0 -0
  266. {dstack-0.18.44.dist-info → dstack-0.19.0rc1.dist-info}/entry_points.txt +0 -0
  267. {dstack-0.18.44.dist-info → dstack-0.19.0rc1.dist-info}/top_level.txt +0 -0
@@ -1,67 +0,0 @@
1
- import json
2
- from typing import List
3
-
4
- from dstack._internal.core.backends.base import Backend
5
- from dstack._internal.core.backends.runpod import RunpodBackend, RunpodConfig, api_client
6
- from dstack._internal.core.models.backends.base import BackendType, ConfigMultiElement
7
- from dstack._internal.core.models.backends.runpod import (
8
- RunpodConfigInfo,
9
- RunpodConfigInfoWithCreds,
10
- RunpodConfigInfoWithCredsPartial,
11
- RunpodConfigValues,
12
- RunpodCreds,
13
- RunpodStoredConfig,
14
- )
15
- from dstack._internal.server.models import BackendModel, DecryptedString, ProjectModel
16
- from dstack._internal.server.services.backends import Configurator
17
- from dstack._internal.server.services.backends.configurators.base import (
18
- raise_invalid_credentials_error,
19
- )
20
-
21
-
22
- class RunpodConfigurator(Configurator):
23
- TYPE: BackendType = BackendType.RUNPOD
24
-
25
- def get_config_values(self, config: RunpodConfigInfoWithCredsPartial) -> RunpodConfigValues:
26
- config_values = RunpodConfigValues()
27
- if config.creds is None:
28
- return config_values
29
- self._validate_runpod_api_key(config.creds.api_key)
30
- config_values.regions = self._get_regions_element(selected=config.regions or [])
31
- return config_values
32
-
33
- def create_backend(
34
- self, project: ProjectModel, config: RunpodConfigInfoWithCreds
35
- ) -> BackendModel:
36
- return BackendModel(
37
- project_id=project.id,
38
- type=self.TYPE.value,
39
- config=RunpodStoredConfig(
40
- **RunpodConfigInfo.__response__.parse_obj(config).dict()
41
- ).json(),
42
- auth=DecryptedString(plaintext=RunpodCreds.parse_obj(config.creds).json()),
43
- )
44
-
45
- def get_config_info(self, model: BackendModel, include_creds: bool) -> RunpodConfigInfo:
46
- config = self._get_backend_config(model)
47
- if include_creds:
48
- return RunpodConfigInfoWithCreds.__response__.parse_obj(config)
49
- return RunpodConfigInfo.__response__.parse_obj(config)
50
-
51
- def get_backend(self, model: BackendModel) -> Backend:
52
- config = self._get_backend_config(model)
53
- return RunpodBackend(config=config)
54
-
55
- def _get_regions_element(self, selected: List[str]) -> ConfigMultiElement:
56
- return ConfigMultiElement(selected=selected)
57
-
58
- def _get_backend_config(self, model: BackendModel) -> RunpodConfig:
59
- return RunpodConfig(
60
- **json.loads(model.config),
61
- creds=RunpodCreds.parse_raw(model.auth.get_plaintext_or_error()),
62
- )
63
-
64
- def _validate_runpod_api_key(self, api_key: str):
65
- client = api_client.RunpodApiClient(api_key=api_key)
66
- if not client.validate_api_key():
67
- raise_invalid_credentials_error(fields=[["creds", "api_key"]])
@@ -1,82 +0,0 @@
1
- import json
2
- from typing import List
3
-
4
- from dstack._internal.core.backends.tensordock import TensorDockBackend, api_client
5
- from dstack._internal.core.backends.tensordock.config import TensorDockConfig
6
- from dstack._internal.core.models.backends.base import (
7
- BackendType,
8
- ConfigElementValue,
9
- ConfigMultiElement,
10
- )
11
- from dstack._internal.core.models.backends.tensordock import (
12
- AnyTensorDockConfigInfo,
13
- TensorDockConfigInfo,
14
- TensorDockConfigInfoWithCreds,
15
- TensorDockConfigInfoWithCredsPartial,
16
- TensorDockConfigValues,
17
- TensorDockCreds,
18
- TensorDockStoredConfig,
19
- )
20
- from dstack._internal.server.models import BackendModel, DecryptedString, ProjectModel
21
- from dstack._internal.server.services.backends.configurators.base import (
22
- Configurator,
23
- raise_invalid_credentials_error,
24
- )
25
-
26
- # TensorDock regions are dynamic, currently we don't offer any filtering
27
- REGIONS = []
28
-
29
-
30
- class TensorDockConfigurator(Configurator):
31
- TYPE: BackendType = BackendType.TENSORDOCK
32
-
33
- def get_config_values(
34
- self, config: TensorDockConfigInfoWithCredsPartial
35
- ) -> TensorDockConfigValues:
36
- config_values = TensorDockConfigValues()
37
- if config.creds is None:
38
- return config_values
39
- self._validate_tensordock_creds(config.creds.api_key, config.creds.api_token)
40
- config_values.regions = self._get_regions_element(selected=config.regions or [])
41
- return config_values
42
-
43
- def create_backend(
44
- self, project: ProjectModel, config: TensorDockConfigInfoWithCreds
45
- ) -> BackendModel:
46
- if config.regions is None:
47
- config.regions = REGIONS
48
- return BackendModel(
49
- project_id=project.id,
50
- type=self.TYPE.value,
51
- config=TensorDockStoredConfig(
52
- **TensorDockConfigInfo.__response__.parse_obj(config).dict()
53
- ).json(),
54
- auth=DecryptedString(plaintext=TensorDockCreds.parse_obj(config.creds).json()),
55
- )
56
-
57
- def get_config_info(self, model: BackendModel, include_creds: bool) -> AnyTensorDockConfigInfo:
58
- config = self._get_backend_config(model)
59
- if include_creds:
60
- return TensorDockConfigInfoWithCreds.__response__.parse_obj(config)
61
- return TensorDockConfigInfo.__response__.parse_obj(config)
62
-
63
- def get_backend(self, model: BackendModel) -> TensorDockBackend:
64
- config = self._get_backend_config(model)
65
- return TensorDockBackend(config=config)
66
-
67
- def _get_backend_config(self, model: BackendModel) -> TensorDockConfig:
68
- return TensorDockConfig.__response__(
69
- **json.loads(model.config),
70
- creds=TensorDockCreds.parse_raw(model.auth.get_plaintext_or_error()),
71
- )
72
-
73
- def _validate_tensordock_creds(self, api_key: str, api_token: str):
74
- client = api_client.TensorDockAPIClient(api_key=api_key, api_token=api_token)
75
- if not client.auth_test():
76
- raise_invalid_credentials_error(fields=[["creds", "api_key"], ["creds", "api_token"]])
77
-
78
- def _get_regions_element(self, selected: List[str]) -> ConfigMultiElement:
79
- element = ConfigMultiElement(selected=selected)
80
- for r in REGIONS:
81
- element.values.append(ConfigElementValue(value=r, label=r))
82
- return element
@@ -1,80 +0,0 @@
1
- import json
2
- from typing import List
3
-
4
- from dstack._internal.core.backends.vastai import VastAIBackend, api_client
5
- from dstack._internal.core.backends.vastai.config import VastAIConfig
6
- from dstack._internal.core.models.backends.base import (
7
- BackendType,
8
- ConfigElementValue,
9
- ConfigMultiElement,
10
- )
11
- from dstack._internal.core.models.backends.vastai import (
12
- AnyVastAIConfigInfo,
13
- VastAIConfigInfo,
14
- VastAIConfigInfoWithCreds,
15
- VastAIConfigInfoWithCredsPartial,
16
- VastAIConfigValues,
17
- VastAICreds,
18
- VastAIStoredConfig,
19
- )
20
- from dstack._internal.server.models import BackendModel, DecryptedString, ProjectModel
21
- from dstack._internal.server.services.backends.configurators.base import (
22
- Configurator,
23
- raise_invalid_credentials_error,
24
- )
25
-
26
- # VastAI regions are dynamic, currently we don't offer any filtering
27
- REGIONS = []
28
-
29
-
30
- class VastAIConfigurator(Configurator):
31
- TYPE: BackendType = BackendType.VASTAI
32
-
33
- def get_config_values(self, config: VastAIConfigInfoWithCredsPartial) -> VastAIConfigValues:
34
- config_values = VastAIConfigValues()
35
- if config.creds is None:
36
- return config_values
37
- self._validate_vastai_creds(config.creds.api_key)
38
- config_values.regions = self._get_regions_element(selected=config.regions or [])
39
- return config_values
40
-
41
- def create_backend(
42
- self, project: ProjectModel, config: VastAIConfigInfoWithCreds
43
- ) -> BackendModel:
44
- if config.regions is None:
45
- config.regions = REGIONS
46
- return BackendModel(
47
- project_id=project.id,
48
- type=self.TYPE.value,
49
- config=VastAIStoredConfig(
50
- **VastAIConfigInfo.__response__.parse_obj(config).dict()
51
- ).json(),
52
- auth=DecryptedString(plaintext=VastAICreds.parse_obj(config.creds).json()),
53
- )
54
-
55
- def get_config_info(self, model: BackendModel, include_creds: bool) -> AnyVastAIConfigInfo:
56
- config = self._get_backend_config(model)
57
- if include_creds:
58
- return VastAIConfigInfoWithCreds.__response__.parse_obj(config)
59
- return VastAIConfigInfo.__response__.parse_obj(config)
60
-
61
- def get_backend(self, model: BackendModel) -> VastAIBackend:
62
- config = self._get_backend_config(model)
63
- return VastAIBackend(config=config)
64
-
65
- def _get_backend_config(self, model: BackendModel) -> VastAIConfig:
66
- return VastAIConfig.__response__(
67
- **json.loads(model.config),
68
- creds=VastAICreds.parse_raw(model.auth.get_plaintext_or_error()),
69
- )
70
-
71
- def _validate_vastai_creds(self, api_key: str):
72
- client = api_client.VastAIAPIClient(api_key=api_key)
73
- if not client.auth_test():
74
- raise_invalid_credentials_error(fields=[["creds", "api_key"]])
75
-
76
- def _get_regions_element(self, selected: List[str]) -> ConfigMultiElement:
77
- element = ConfigMultiElement(selected=selected)
78
- for r in REGIONS:
79
- element.values.append(ConfigElementValue(value=r, label=r))
80
- return element
@@ -1,80 +0,0 @@
1
- import json
2
- from typing import List
3
-
4
- from dstack._internal.core.backends.base import Backend
5
- from dstack._internal.core.backends.vultr import VultrBackend, VultrConfig, api_client
6
- from dstack._internal.core.models.backends import (
7
- VultrConfigInfoWithCreds,
8
- VultrConfigInfoWithCredsPartial,
9
- VultrConfigValues,
10
- )
11
- from dstack._internal.core.models.backends.base import (
12
- BackendType,
13
- ConfigElementValue,
14
- ConfigMultiElement,
15
- )
16
- from dstack._internal.core.models.backends.vultr import (
17
- VultrConfigInfo,
18
- VultrCreds,
19
- VultrStoredConfig,
20
- )
21
- from dstack._internal.server.models import BackendModel, DecryptedString, ProjectModel
22
- from dstack._internal.server.services.backends import Configurator
23
- from dstack._internal.server.services.backends.configurators.base import (
24
- raise_invalid_credentials_error,
25
- )
26
-
27
- REGIONS = []
28
-
29
-
30
- class VultrConfigurator(Configurator):
31
- TYPE: BackendType = BackendType.VULTR
32
-
33
- def get_config_values(self, config: VultrConfigInfoWithCredsPartial) -> VultrConfigValues:
34
- config_values = VultrConfigValues()
35
- if config.creds is None:
36
- return config_values
37
- self._validate_vultr_api_key(config.creds.api_key)
38
- config_values.regions = self._get_regions_element(selected=config.regions or [])
39
- return config_values
40
-
41
- def create_backend(
42
- self, project: ProjectModel, config: VultrConfigInfoWithCreds
43
- ) -> BackendModel:
44
- if config.regions is None:
45
- config.regions = REGIONS
46
- return BackendModel(
47
- project_id=project.id,
48
- type=self.TYPE.value,
49
- config=VultrStoredConfig(
50
- **VultrConfigInfo.__response__.parse_obj(config).dict()
51
- ).json(),
52
- auth=DecryptedString(plaintext=VultrCreds.parse_obj(config.creds).json()),
53
- )
54
-
55
- def get_config_info(self, model: BackendModel, include_creds: bool) -> VultrConfigInfo:
56
- config = self._get_backend_config(model)
57
- if include_creds:
58
- return VultrConfigInfoWithCreds.__response__.parse_obj(config)
59
- return VultrConfigInfo.__response__.parse_obj(config)
60
-
61
- def get_backend(self, model: BackendModel) -> Backend:
62
- config = self._get_backend_config(model)
63
- return VultrBackend(config=config)
64
-
65
- def _get_regions_element(self, selected: List[str]) -> ConfigMultiElement:
66
- element = ConfigMultiElement(selected=selected)
67
- for r in REGIONS:
68
- element.values.append(ConfigElementValue(value=r, label=r))
69
- return element
70
-
71
- def _get_backend_config(self, model: BackendModel) -> VultrConfig:
72
- return VultrConfig.__response__(
73
- **json.loads(model.config),
74
- creds=VultrCreds.parse_raw(model.auth.get_plaintext_or_error()),
75
- )
76
-
77
- def _validate_vultr_api_key(self, api_key: str):
78
- client = api_client.VultrApiClient(api_key=api_key)
79
- if not client.validate_api_key():
80
- raise_invalid_credentials_error(fields=[["creds", "api_key"]])
@@ -1,41 +0,0 @@
1
- from typing import List
2
-
3
- from dstack._internal.core.models.pools import Pool
4
- from dstack.api.server import APIClient
5
-
6
-
7
- class PoolInstance:
8
- def __init__(self, api_client: APIClient, pool: Pool):
9
- self._api_client = api_client
10
- self._pool = pool
11
-
12
- @property
13
- def name(self) -> str:
14
- return self._pool.name
15
-
16
- def __str__(self) -> str:
17
- return f"<PoolInstance '{self.name}'>"
18
-
19
- def __repr__(self) -> str:
20
- return f"<PoolInstance '{self.name}'>"
21
-
22
-
23
- class PoolCollection:
24
- """
25
- Operations with pools
26
- """
27
-
28
- def __init__(self, api_client: APIClient, project: str):
29
- self._api_client = api_client
30
- self._project = project
31
-
32
- def list(self) -> List[PoolInstance]:
33
- """
34
- List available pool in the project
35
-
36
- Returns:
37
- pools
38
- """
39
- list_raw_pool = self._api_client.pool.list(project_name=self._project)
40
- list_pool = [PoolInstance(self._api_client, instance) for instance in list_raw_pool]
41
- return list_pool
@@ -1,105 +0,0 @@
1
- from typing import List, Optional, Union
2
-
3
- from dstack._internal.core.models.resources import (
4
- DEFAULT_CPU_COUNT,
5
- DEFAULT_GPU_COUNT,
6
- DEFAULT_MEMORY_SIZE,
7
- ComputeCapabilityLike,
8
- DiskLike,
9
- DiskSpec,
10
- DiskSpecSchema,
11
- GPULike,
12
- GPUSpec,
13
- GPUSpecSchema,
14
- IntRangeLike,
15
- MemoryLike,
16
- MemoryRangeLike,
17
- ResourcesSpec,
18
- ResourcesSpecSchema,
19
- )
20
-
21
-
22
- # TODO(andrey): This method looks like a workaround and possibly must be reworked (replaced with something else).
23
- # Currently it's only used by the `dstack pool add` command.
24
- def Resources(
25
- *,
26
- cpu: IntRangeLike = DEFAULT_CPU_COUNT,
27
- memory: MemoryRangeLike = DEFAULT_MEMORY_SIZE,
28
- gpu: Optional[GPULike] = None,
29
- shm_size: Optional[MemoryLike] = None,
30
- disk: Optional[DiskLike] = None,
31
- ) -> ResourcesSpec:
32
- """
33
- Creates required resources specification.
34
-
35
- Args:
36
- cpu (Optional[Range[int]]): The number of CPUs
37
- memory (Optional[Range[Memory]]): The size of RAM memory (e.g., `"16GB"`)
38
- gpu (Optional[GPUSpec]): The GPU spec
39
- shm_size (Optional[Range[Memory]]): The of shared memory (e.g., `"8GB"`). If you are using parallel communicating processes (e.g., dataloaders in PyTorch), you may need to configure this.
40
- disk (Optional[DiskSpec]): The disk spec
41
-
42
- Returns:
43
- resources specification
44
- """
45
- return ResourcesSpec.parse_obj(
46
- ResourcesSpecSchema(
47
- cpu=cpu,
48
- memory=memory,
49
- gpu=gpu,
50
- shm_size=shm_size,
51
- disk=disk,
52
- )
53
- )
54
-
55
-
56
- def GPU(
57
- *,
58
- name: Optional[Union[List[str], str]] = None,
59
- count: IntRangeLike = DEFAULT_GPU_COUNT,
60
- memory: Optional[MemoryRangeLike] = None,
61
- total_memory: Optional[MemoryRangeLike] = None,
62
- compute_capability: Optional[ComputeCapabilityLike] = None,
63
- ) -> GPUSpec:
64
- """
65
- Creates GPU specification.
66
-
67
- Args:
68
- name (Optional[List[str]]): The name of the GPU (e.g., `"A100"` or `"H100"`)
69
- count (Optional[Range[int]]): The number of GPUs
70
- memory (Optional[Range[Memory]]): The size of a single GPU memory (e.g., `"16GB"`)
71
- total_memory (Optional[Range[Memory]]): The total size of all GPUs memory (e.g., `"32GB"`)
72
- compute_capability (Optional[float]): The minimum compute capability of the GPU (e.g., `7.5`)
73
-
74
- Returns:
75
- GPU specification
76
- """
77
- return GPUSpec.parse_obj(
78
- GPUSpecSchema(
79
- name=name,
80
- count=count,
81
- memory=memory,
82
- total_memory=total_memory,
83
- compute_capability=compute_capability,
84
- )
85
- )
86
-
87
-
88
- def Disk(
89
- *,
90
- size: MemoryRangeLike,
91
- ) -> DiskSpec:
92
- """
93
- Creates disk specification.
94
-
95
- Args:
96
- size (Range[Memory]): The size of the disk (e.g., `"100GB"`)
97
-
98
- Returns:
99
- disk specification
100
- """
101
- return DiskSpec.parse_obj(
102
- DiskSpecSchema(
103
- size=size,
104
- )
105
- )
@@ -1,63 +0,0 @@
1
- from typing import List, Optional
2
-
3
- from pydantic import parse_obj_as
4
-
5
- import dstack._internal.server.schemas.pools as schemas_pools
6
- from dstack._internal.core.models.instances import SSHKey
7
- from dstack._internal.core.models.pools import Instance, Pool, PoolInstances
8
- from dstack._internal.server.schemas.runs import AddRemoteInstanceRequest
9
- from dstack.api.server._group import APIClientGroup
10
-
11
-
12
- class PoolAPIClient(APIClientGroup):
13
- def list(self, project_name: str) -> List[Pool]:
14
- resp = self._request(f"/api/project/{project_name}/pool/list")
15
- return parse_obj_as(List[Pool.__response__], resp.json())
16
-
17
- def delete(self, project_name: str, pool_name: str, force: bool) -> None:
18
- body = schemas_pools.DeletePoolRequest(name=pool_name, force=force)
19
- self._request(f"/api/project/{project_name}/pool/delete", body=body.json())
20
-
21
- def create(self, project_name: str, pool_name: str) -> None:
22
- body = schemas_pools.CreatePoolRequest(name=pool_name)
23
- self._request(f"/api/project/{project_name}/pool/create", body=body.json())
24
-
25
- def show(self, project_name: str, pool_name: Optional[str]) -> PoolInstances:
26
- body = schemas_pools.ShowPoolRequest(name=pool_name)
27
- resp = self._request(f"/api/project/{project_name}/pool/show", body=body.json())
28
- return parse_obj_as(PoolInstances.__response__, resp.json())
29
-
30
- def remove(self, project_name: str, pool_name: str, instance_name: str, force: bool) -> None:
31
- body = schemas_pools.RemoveInstanceRequest(
32
- pool_name=pool_name, instance_name=instance_name, force=force
33
- )
34
- self._request(f"/api/project/{project_name}/pool/remove", body=body.json())
35
-
36
- def set_default(self, project_name: str, pool_name: str) -> None:
37
- body = schemas_pools.SetDefaultPoolRequest(pool_name=pool_name)
38
- self._request(f"/api/project/{project_name}/pool/set_default", body=body.json())
39
-
40
- def add_remote(
41
- self,
42
- project_name: str,
43
- pool_name: Optional[str],
44
- instance_name: Optional[str],
45
- instance_network: Optional[str],
46
- region: Optional[str],
47
- host: str,
48
- port: int,
49
- ssh_user: str,
50
- ssh_keys: List[SSHKey],
51
- ) -> Instance:
52
- body = AddRemoteInstanceRequest(
53
- pool_name=pool_name,
54
- instance_name=instance_name,
55
- instance_network=instance_network,
56
- region=region,
57
- host=host,
58
- port=port,
59
- ssh_user=ssh_user,
60
- ssh_keys=ssh_keys,
61
- )
62
- result = self._request(f"/api/project/{project_name}/pool/add_remote", body=body.json())
63
- return parse_obj_as(Instance.__response__, result.json())