dstack 0.18.44__py3-none-any.whl → 0.19.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.

Potentially problematic release.


This version of dstack might be problematic. Click here for more details.

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-4a0fe83e84574654e397.js} +18 -14
  146. dstack/_internal/server/statics/{main-4eb116b97819badd1e2c.js.map → main-4a0fe83e84574654e397.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.0.dist-info}/METADATA +1 -1
  164. {dstack-0.18.44.dist-info → dstack-0.19.0.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.0.dist-info}/LICENSE.md +0 -0
  265. {dstack-0.18.44.dist-info → dstack-0.19.0.dist-info}/WHEEL +0 -0
  266. {dstack-0.18.44.dist-info → dstack-0.19.0.dist-info}/entry_points.txt +0 -0
  267. {dstack-0.18.44.dist-info → dstack-0.19.0.dist-info}/top_level.txt +0 -0
@@ -1,187 +1,61 @@
1
1
  import asyncio
2
2
  import heapq
3
- from typing import Callable, Coroutine, Dict, List, Optional, Tuple, Type, Union
3
+ from typing import Callable, Coroutine, Dict, List, Optional, Tuple
4
4
  from uuid import UUID
5
5
 
6
6
  from sqlalchemy import delete, update
7
7
  from sqlalchemy.ext.asyncio import AsyncSession
8
8
 
9
- from dstack._internal.core.backends.base import Backend
10
- from dstack._internal.core.backends.local import LocalBackend
9
+ from dstack._internal.core.backends.base.backend import Backend
10
+ from dstack._internal.core.backends.base.configurator import (
11
+ Configurator,
12
+ StoredBackendRecord,
13
+ )
14
+ from dstack._internal.core.backends.configurators import (
15
+ get_configurator,
16
+ list_available_backend_types,
17
+ )
18
+ from dstack._internal.core.backends.local.backend import LocalBackend
19
+ from dstack._internal.core.backends.models import (
20
+ AnyBackendConfig,
21
+ AnyBackendConfigWithCreds,
22
+ )
11
23
  from dstack._internal.core.errors import (
12
24
  BackendError,
13
25
  BackendInvalidCredentialsError,
14
26
  BackendNotAvailable,
15
27
  ResourceExistsError,
28
+ ResourceNotExistsError,
16
29
  ServerClientError,
17
30
  )
18
- from dstack._internal.core.models.backends import (
19
- AnyConfigInfoWithCreds,
20
- AnyConfigInfoWithCredsPartial,
21
- AnyConfigValues,
22
- )
23
31
  from dstack._internal.core.models.backends.base import BackendType
24
32
  from dstack._internal.core.models.instances import (
25
33
  InstanceOfferWithAvailability,
26
34
  )
27
35
  from dstack._internal.core.models.runs import Requirements
28
- from dstack._internal.server.models import BackendModel, ProjectModel
29
- from dstack._internal.server.services.backends.configurators.base import Configurator
36
+ from dstack._internal.server import settings
37
+ from dstack._internal.server.models import BackendModel, DecryptedString, ProjectModel
30
38
  from dstack._internal.server.settings import LOCAL_BACKEND_ENABLED
31
39
  from dstack._internal.utils.common import run_async
32
40
  from dstack._internal.utils.logging import get_logger
33
41
 
34
42
  logger = get_logger(__name__)
35
43
 
36
- _CONFIGURATOR_CLASSES: List[Type[Configurator]] = []
37
-
38
- try:
39
- from dstack._internal.server.services.backends.configurators.aws import AWSConfigurator
40
-
41
- _CONFIGURATOR_CLASSES.append(AWSConfigurator)
42
- except ImportError:
43
- pass
44
-
45
- try:
46
- from dstack._internal.server.services.backends.configurators.azure import AzureConfigurator
47
-
48
- _CONFIGURATOR_CLASSES.append(AzureConfigurator)
49
- except ImportError:
50
- pass
51
-
52
- try:
53
- from dstack._internal.server.services.backends.configurators.cudo import (
54
- CudoConfigurator,
55
- )
56
-
57
- _CONFIGURATOR_CLASSES.append(CudoConfigurator)
58
- except ImportError:
59
- pass
60
-
61
- try:
62
- from dstack._internal.server.services.backends.configurators.datacrunch import (
63
- DataCrunchConfigurator,
64
- )
65
-
66
- _CONFIGURATOR_CLASSES.append(DataCrunchConfigurator)
67
- except ImportError:
68
- pass
69
-
70
- try:
71
- from dstack._internal.server.services.backends.configurators.gcp import GCPConfigurator
72
-
73
- _CONFIGURATOR_CLASSES.append(GCPConfigurator)
74
- except ImportError:
75
- pass
76
-
77
- try:
78
- from dstack._internal.server.services.backends.configurators.kubernetes import (
79
- KubernetesConfigurator,
80
- )
81
-
82
- _CONFIGURATOR_CLASSES.append(KubernetesConfigurator)
83
- except ImportError:
84
- pass
85
-
86
- try:
87
- from dstack._internal.server.services.backends.configurators.lambdalabs import (
88
- LambdaConfigurator,
89
- )
90
-
91
- _CONFIGURATOR_CLASSES.append(LambdaConfigurator)
92
- except ImportError:
93
- pass
94
-
95
- try:
96
- from dstack._internal.server.services.backends.configurators.nebius import NebiusConfigurator
97
-
98
- _CONFIGURATOR_CLASSES.append(NebiusConfigurator)
99
- except ImportError:
100
- pass
101
-
102
- try:
103
- from dstack._internal.server.services.backends.configurators.oci import OCIConfigurator
104
-
105
- _CONFIGURATOR_CLASSES.append(OCIConfigurator)
106
- except ImportError:
107
- pass
108
-
109
- try:
110
- from dstack._internal.server.services.backends.configurators.runpod import RunpodConfigurator
111
-
112
- _CONFIGURATOR_CLASSES.append(RunpodConfigurator)
113
- except ImportError:
114
- pass
115
-
116
- try:
117
- from dstack._internal.server.services.backends.configurators.tensordock import (
118
- TensorDockConfigurator,
119
- )
120
-
121
- _CONFIGURATOR_CLASSES.append(TensorDockConfigurator)
122
- except ImportError:
123
- pass
124
-
125
- try:
126
- from dstack._internal.server.services.backends.configurators.vastai import VastAIConfigurator
127
-
128
- _CONFIGURATOR_CLASSES.append(VastAIConfigurator)
129
- except ImportError:
130
- pass
131
-
132
- try:
133
- from dstack._internal.server.services.backends.configurators.vultr import VultrConfigurator
134
-
135
- _CONFIGURATOR_CLASSES.append(VultrConfigurator)
136
- except ImportError:
137
- pass
138
-
139
-
140
- _BACKEND_TYPE_TO_CONFIGURATOR_CLASS_MAP = {c.TYPE: c for c in _CONFIGURATOR_CLASSES}
141
-
142
-
143
- def register_configurator(configurator: Type[Configurator]):
144
- _BACKEND_TYPE_TO_CONFIGURATOR_CLASS_MAP[configurator.TYPE] = configurator
145
-
146
-
147
- def get_configurator(backend_type: Union[BackendType, str]) -> Optional[Configurator]:
148
- backend_type = BackendType(backend_type)
149
- configurator_class = _BACKEND_TYPE_TO_CONFIGURATOR_CLASS_MAP.get(backend_type)
150
- if configurator_class is None:
151
- return None
152
- return configurator_class()
153
-
154
-
155
- def list_available_backend_types() -> List[BackendType]:
156
- available_backend_types = []
157
- for configurator_class in _BACKEND_TYPE_TO_CONFIGURATOR_CLASS_MAP.values():
158
- available_backend_types.append(configurator_class.TYPE)
159
- return available_backend_types
160
-
161
-
162
- async def get_backend_config_values(
163
- config: AnyConfigInfoWithCredsPartial,
164
- ) -> AnyConfigValues:
165
- configurator = get_configurator(config.type)
166
- if configurator is None:
167
- raise BackendNotAvailable()
168
- config_values = await run_async(configurator.get_config_values, config)
169
- return config_values
170
-
171
44
 
172
45
  async def create_backend(
173
46
  session: AsyncSession,
174
47
  project: ProjectModel,
175
- config: AnyConfigInfoWithCreds,
176
- ) -> AnyConfigInfoWithCreds:
48
+ config: AnyBackendConfigWithCreds,
49
+ ) -> AnyBackendConfigWithCreds:
177
50
  configurator = get_configurator(config.type)
178
51
  if configurator is None:
179
52
  raise BackendNotAvailable()
180
53
  backend = await get_project_backend_by_type(project=project, backend_type=configurator.TYPE)
181
54
  if backend is not None:
182
55
  raise ResourceExistsError()
183
- await run_async(configurator.get_config_values, config)
184
- backend = await run_async(configurator.create_backend, project=project, config=config)
56
+ backend = await validate_and_create_backend_model(
57
+ project=project, configurator=configurator, config=config
58
+ )
185
59
  session.add(backend)
186
60
  await session.commit()
187
61
  return config
@@ -190,16 +64,17 @@ async def create_backend(
190
64
  async def update_backend(
191
65
  session: AsyncSession,
192
66
  project: ProjectModel,
193
- config: AnyConfigInfoWithCreds,
194
- ) -> AnyConfigInfoWithCreds:
67
+ config: AnyBackendConfigWithCreds,
68
+ ) -> AnyBackendConfigWithCreds:
195
69
  configurator = get_configurator(config.type)
196
70
  if configurator is None:
197
71
  raise BackendNotAvailable()
198
72
  backend_exists = any(configurator.TYPE == b.type for b in project.backends)
199
73
  if not backend_exists:
200
- raise ServerClientError("Backend does not exist")
201
- await run_async(configurator.get_config_values, config)
202
- backend = await run_async(configurator.create_backend, project=project, config=config)
74
+ raise ResourceNotExistsError()
75
+ backend = await validate_and_create_backend_model(
76
+ project=project, configurator=configurator, config=config
77
+ )
203
78
  # FIXME: potentially long write transaction
204
79
  await session.execute(
205
80
  update(BackendModel)
@@ -215,10 +90,31 @@ async def update_backend(
215
90
  return config
216
91
 
217
92
 
218
- async def get_config_info(
93
+ async def validate_and_create_backend_model(
94
+ project: ProjectModel,
95
+ configurator: Configurator,
96
+ config: AnyBackendConfigWithCreds,
97
+ ) -> BackendModel:
98
+ await run_async(
99
+ configurator.validate_config, config, default_creds_enabled=settings.DEFAULT_CREDS_ENABLED
100
+ )
101
+ backend_record = await run_async(
102
+ configurator.create_backend,
103
+ project_name=project.name,
104
+ config=config,
105
+ )
106
+ return BackendModel(
107
+ project_id=project.id,
108
+ type=configurator.TYPE,
109
+ config=backend_record.config,
110
+ auth=DecryptedString(plaintext=backend_record.auth),
111
+ )
112
+
113
+
114
+ async def get_backend_config(
219
115
  project: ProjectModel,
220
116
  backend_type: BackendType,
221
- ) -> Optional[AnyConfigInfoWithCreds]:
117
+ ) -> Optional[AnyBackendConfigWithCreds]:
222
118
  configurator = get_configurator(backend_type)
223
119
  if configurator is None:
224
120
  raise BackendNotAvailable()
@@ -230,10 +126,31 @@ async def get_config_info(
230
126
  )
231
127
  continue
232
128
  if backend_model.type == backend_type:
233
- return configurator.get_config_info(backend_model, include_creds=True)
129
+ return get_backend_config_from_backend_model(
130
+ configurator, backend_model, include_creds=True
131
+ )
234
132
  return None
235
133
 
236
134
 
135
+ def get_backend_config_from_backend_model(
136
+ configurator: Configurator,
137
+ backend_model: BackendModel,
138
+ include_creds: bool,
139
+ ) -> AnyBackendConfig:
140
+ backend_record = get_stored_backend_record(backend_model)
141
+ backend_config = configurator.get_backend_config(backend_record, include_creds=include_creds)
142
+ return backend_config
143
+
144
+
145
+ def get_stored_backend_record(backend_model: BackendModel) -> StoredBackendRecord:
146
+ return StoredBackendRecord(
147
+ config=backend_model.config,
148
+ auth=backend_model.auth.get_plaintext_or_error(),
149
+ project_id=backend_model.project_id,
150
+ backend_id=backend_model.id,
151
+ )
152
+
153
+
237
154
  async def delete_backends(
238
155
  session: AsyncSession,
239
156
  project: ProjectModel,
@@ -299,7 +216,8 @@ async def get_project_backends_with_models(project: ProjectModel) -> List[Backen
299
216
  )
300
217
  continue
301
218
  try:
302
- backend = await run_async(configurator.get_backend, backend_model)
219
+ backend_record = get_stored_backend_record(backend_model)
220
+ backend = await run_async(configurator.get_backend, backend_record)
303
221
  except BackendInvalidCredentialsError:
304
222
  logger.warning(
305
223
  "Credentials for %s backend are invalid. Backend will be ignored.",
@@ -449,3 +367,12 @@ async def get_instance_offers(
449
367
  offers = heapq.merge(*offers_by_backend, key=lambda i: i[1].price)
450
368
  # Put NOT_AVAILABLE, NO_QUOTA, and BUSY instances at the end, do not sort by price
451
369
  return sorted(offers, key=lambda i: not i[1].availability.is_available())
370
+
371
+
372
+ def check_backend_type_available(backend_type: BackendType):
373
+ if backend_type not in list_available_backend_types():
374
+ raise BackendNotAvailable(
375
+ f"Backend {backend_type.value} not available."
376
+ " Ensure that backend dependencies are installed."
377
+ f" Available backends: {[b.value for b in list_available_backend_types()]}."
378
+ )