dstack 0.18.43__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 (278) 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 -20
  7. dstack/_internal/cli/services/profile.py +34 -83
  8. dstack/_internal/cli/utils/gateway.py +1 -1
  9. dstack/_internal/cli/utils/run.py +11 -0
  10. dstack/_internal/core/backends/__init__.py +56 -39
  11. dstack/_internal/core/backends/aws/__init__.py +0 -25
  12. dstack/_internal/core/backends/aws/auth.py +1 -10
  13. dstack/_internal/core/backends/aws/backend.py +26 -0
  14. dstack/_internal/core/backends/aws/compute.py +21 -45
  15. dstack/_internal/{server/services/backends/configurators/aws.py → core/backends/aws/configurator.py} +46 -85
  16. dstack/_internal/core/backends/aws/models.py +135 -0
  17. dstack/_internal/core/backends/aws/resources.py +1 -1
  18. dstack/_internal/core/backends/azure/__init__.py +0 -20
  19. dstack/_internal/core/backends/azure/auth.py +2 -11
  20. dstack/_internal/core/backends/azure/backend.py +21 -0
  21. dstack/_internal/core/backends/azure/compute.py +14 -28
  22. dstack/_internal/{server/services/backends/configurators/azure.py → core/backends/azure/configurator.py} +141 -210
  23. dstack/_internal/core/backends/azure/models.py +89 -0
  24. dstack/_internal/core/backends/base/__init__.py +0 -12
  25. dstack/_internal/core/backends/base/backend.py +18 -0
  26. dstack/_internal/core/backends/base/compute.py +153 -33
  27. dstack/_internal/core/backends/base/configurator.py +105 -0
  28. dstack/_internal/core/backends/base/models.py +14 -0
  29. dstack/_internal/core/backends/configurators.py +138 -0
  30. dstack/_internal/core/backends/cudo/__init__.py +0 -15
  31. dstack/_internal/core/backends/cudo/backend.py +16 -0
  32. dstack/_internal/core/backends/cudo/compute.py +8 -26
  33. dstack/_internal/core/backends/cudo/configurator.py +72 -0
  34. dstack/_internal/core/backends/cudo/models.py +37 -0
  35. dstack/_internal/core/backends/datacrunch/__init__.py +0 -15
  36. dstack/_internal/core/backends/datacrunch/backend.py +16 -0
  37. dstack/_internal/core/backends/datacrunch/compute.py +8 -25
  38. dstack/_internal/core/backends/datacrunch/configurator.py +66 -0
  39. dstack/_internal/core/backends/datacrunch/models.py +38 -0
  40. dstack/_internal/core/{models/backends/dstack.py → backends/dstack/models.py} +7 -7
  41. dstack/_internal/core/backends/gcp/__init__.py +0 -16
  42. dstack/_internal/core/backends/gcp/auth.py +2 -11
  43. dstack/_internal/core/backends/gcp/backend.py +17 -0
  44. dstack/_internal/core/backends/gcp/compute.py +14 -44
  45. dstack/_internal/{server/services/backends/configurators/gcp.py → core/backends/gcp/configurator.py} +46 -103
  46. dstack/_internal/core/backends/gcp/models.py +125 -0
  47. dstack/_internal/core/backends/kubernetes/__init__.py +0 -15
  48. dstack/_internal/core/backends/kubernetes/backend.py +16 -0
  49. dstack/_internal/core/backends/kubernetes/compute.py +16 -5
  50. dstack/_internal/core/backends/kubernetes/configurator.py +55 -0
  51. dstack/_internal/core/backends/kubernetes/models.py +72 -0
  52. dstack/_internal/core/backends/lambdalabs/__init__.py +0 -16
  53. dstack/_internal/core/backends/lambdalabs/backend.py +17 -0
  54. dstack/_internal/core/backends/lambdalabs/compute.py +7 -28
  55. dstack/_internal/core/backends/lambdalabs/configurator.py +82 -0
  56. dstack/_internal/core/backends/lambdalabs/models.py +37 -0
  57. dstack/_internal/core/backends/local/__init__.py +0 -13
  58. dstack/_internal/core/backends/local/backend.py +14 -0
  59. dstack/_internal/core/backends/local/compute.py +16 -2
  60. dstack/_internal/core/backends/models.py +128 -0
  61. dstack/_internal/core/backends/oci/__init__.py +0 -15
  62. dstack/_internal/core/backends/oci/auth.py +1 -5
  63. dstack/_internal/core/backends/oci/backend.py +16 -0
  64. dstack/_internal/core/backends/oci/compute.py +9 -23
  65. dstack/_internal/{server/services/backends/configurators/oci.py → core/backends/oci/configurator.py} +40 -85
  66. dstack/_internal/core/{models/backends/oci.py → backends/oci/models.py} +24 -25
  67. dstack/_internal/core/backends/oci/region.py +1 -1
  68. dstack/_internal/core/backends/runpod/__init__.py +0 -15
  69. dstack/_internal/core/backends/runpod/backend.py +16 -0
  70. dstack/_internal/core/backends/runpod/compute.py +28 -6
  71. dstack/_internal/core/backends/runpod/configurator.py +59 -0
  72. dstack/_internal/core/backends/runpod/models.py +54 -0
  73. dstack/_internal/core/backends/template/__init__.py +0 -0
  74. dstack/_internal/core/backends/tensordock/__init__.py +0 -15
  75. dstack/_internal/core/backends/tensordock/backend.py +16 -0
  76. dstack/_internal/core/backends/tensordock/compute.py +8 -27
  77. dstack/_internal/core/backends/tensordock/configurator.py +68 -0
  78. dstack/_internal/core/backends/tensordock/models.py +38 -0
  79. dstack/_internal/core/backends/vastai/__init__.py +0 -15
  80. dstack/_internal/core/backends/vastai/backend.py +16 -0
  81. dstack/_internal/core/backends/vastai/compute.py +2 -2
  82. dstack/_internal/core/backends/vastai/configurator.py +66 -0
  83. dstack/_internal/core/backends/vastai/models.py +37 -0
  84. dstack/_internal/core/backends/vultr/__init__.py +0 -15
  85. dstack/_internal/core/backends/vultr/backend.py +16 -0
  86. dstack/_internal/core/backends/vultr/compute.py +10 -24
  87. dstack/_internal/core/backends/vultr/configurator.py +64 -0
  88. dstack/_internal/core/backends/vultr/models.py +34 -0
  89. dstack/_internal/core/models/backends/__init__.py +0 -184
  90. dstack/_internal/core/models/backends/base.py +0 -19
  91. dstack/_internal/core/models/configurations.py +22 -16
  92. dstack/_internal/core/models/envs.py +4 -3
  93. dstack/_internal/core/models/fleets.py +17 -22
  94. dstack/_internal/core/models/gateways.py +3 -3
  95. dstack/_internal/core/models/instances.py +24 -0
  96. dstack/_internal/core/models/profiles.py +85 -45
  97. dstack/_internal/core/models/projects.py +1 -1
  98. dstack/_internal/core/models/repos/base.py +0 -5
  99. dstack/_internal/core/models/repos/local.py +3 -3
  100. dstack/_internal/core/models/repos/remote.py +26 -12
  101. dstack/_internal/core/models/repos/virtual.py +1 -1
  102. dstack/_internal/core/models/resources.py +45 -76
  103. dstack/_internal/core/models/runs.py +21 -19
  104. dstack/_internal/core/models/volumes.py +1 -3
  105. dstack/_internal/core/services/profiles.py +7 -16
  106. dstack/_internal/core/services/repos.py +0 -4
  107. dstack/_internal/server/app.py +11 -4
  108. dstack/_internal/server/background/__init__.py +10 -0
  109. dstack/_internal/server/background/tasks/process_gateways.py +4 -8
  110. dstack/_internal/server/background/tasks/process_instances.py +14 -9
  111. dstack/_internal/server/background/tasks/process_metrics.py +1 -1
  112. dstack/_internal/server/background/tasks/process_placement_groups.py +5 -1
  113. dstack/_internal/server/background/tasks/process_prometheus_metrics.py +135 -0
  114. dstack/_internal/server/background/tasks/process_running_jobs.py +80 -24
  115. dstack/_internal/server/background/tasks/process_runs.py +1 -0
  116. dstack/_internal/server/background/tasks/process_submitted_jobs.py +20 -38
  117. dstack/_internal/server/background/tasks/process_volumes.py +5 -2
  118. dstack/_internal/server/migrations/versions/60e444118b6d_add_jobprometheusmetrics.py +40 -0
  119. dstack/_internal/server/migrations/versions/7bc2586e8b9e_make_instancemodel_pool_id_optional.py +36 -0
  120. dstack/_internal/server/migrations/versions/98d1b92988bc_add_jobterminationreason_terminated_due_.py +140 -0
  121. dstack/_internal/server/migrations/versions/bc8ca4a505c6_store_backendtype_as_string.py +171 -0
  122. dstack/_internal/server/models.py +59 -9
  123. dstack/_internal/server/routers/backends.py +14 -23
  124. dstack/_internal/server/routers/instances.py +3 -4
  125. dstack/_internal/server/routers/metrics.py +31 -10
  126. dstack/_internal/server/routers/prometheus.py +36 -0
  127. dstack/_internal/server/routers/repos.py +1 -2
  128. dstack/_internal/server/routers/runs.py +13 -59
  129. dstack/_internal/server/schemas/gateways.py +14 -23
  130. dstack/_internal/server/schemas/projects.py +7 -2
  131. dstack/_internal/server/schemas/repos.py +2 -38
  132. dstack/_internal/server/schemas/runner.py +1 -0
  133. dstack/_internal/server/schemas/runs.py +1 -24
  134. dstack/_internal/server/security/permissions.py +1 -1
  135. dstack/_internal/server/services/backends/__init__.py +85 -158
  136. dstack/_internal/server/services/config.py +53 -567
  137. dstack/_internal/server/services/fleets.py +9 -103
  138. dstack/_internal/server/services/gateways/__init__.py +13 -4
  139. dstack/_internal/server/services/{pools.py → instances.py} +22 -329
  140. dstack/_internal/server/services/jobs/__init__.py +9 -6
  141. dstack/_internal/server/services/jobs/configurators/base.py +25 -1
  142. dstack/_internal/server/services/jobs/configurators/dev.py +9 -1
  143. dstack/_internal/server/services/jobs/configurators/extensions/cursor.py +42 -0
  144. dstack/_internal/server/services/metrics.py +131 -72
  145. dstack/_internal/server/services/offers.py +1 -1
  146. dstack/_internal/server/services/projects.py +23 -14
  147. dstack/_internal/server/services/prometheus.py +245 -0
  148. dstack/_internal/server/services/runner/client.py +14 -3
  149. dstack/_internal/server/services/runs.py +67 -31
  150. dstack/_internal/server/services/volumes.py +9 -4
  151. dstack/_internal/server/settings.py +3 -0
  152. dstack/_internal/server/statics/index.html +1 -1
  153. dstack/_internal/server/statics/{main-fe8fd9db55df8d10e648.js → main-4fd5a4770eff59325ee3.js} +68 -15
  154. dstack/_internal/server/statics/{main-fe8fd9db55df8d10e648.js.map → main-4fd5a4770eff59325ee3.js.map} +1 -1
  155. dstack/_internal/server/statics/{main-7510e71dfa9749a4e70e.css → main-da9f8c06a69c20dac23e.css} +1 -1
  156. dstack/_internal/server/statics/static/media/entraID.d65d1f3e9486a8e56d24fc07b3230885.svg +9 -0
  157. dstack/_internal/server/testing/common.py +75 -32
  158. dstack/_internal/utils/json_schema.py +6 -0
  159. dstack/_internal/utils/ssh.py +2 -1
  160. dstack/api/__init__.py +4 -0
  161. dstack/api/_public/__init__.py +16 -20
  162. dstack/api/_public/backends.py +1 -1
  163. dstack/api/_public/repos.py +36 -36
  164. dstack/api/_public/runs.py +170 -83
  165. dstack/api/server/__init__.py +11 -13
  166. dstack/api/server/_backends.py +12 -16
  167. dstack/api/server/_fleets.py +15 -55
  168. dstack/api/server/_gateways.py +3 -14
  169. dstack/api/server/_repos.py +1 -4
  170. dstack/api/server/_runs.py +21 -96
  171. dstack/api/server/_volumes.py +10 -5
  172. dstack/api/utils.py +3 -0
  173. dstack/version.py +1 -1
  174. {dstack-0.18.43.dist-info → dstack-0.19.0rc1.dist-info}/METADATA +10 -1
  175. {dstack-0.18.43.dist-info → dstack-0.19.0rc1.dist-info}/RECORD +229 -206
  176. tests/_internal/cli/services/configurators/test_profile.py +6 -6
  177. tests/_internal/core/backends/aws/test_configurator.py +35 -0
  178. tests/_internal/core/backends/aws/test_resources.py +1 -1
  179. tests/_internal/core/backends/azure/test_configurator.py +61 -0
  180. tests/_internal/core/backends/cudo/__init__.py +0 -0
  181. tests/_internal/core/backends/cudo/test_configurator.py +37 -0
  182. tests/_internal/core/backends/datacrunch/__init__.py +0 -0
  183. tests/_internal/core/backends/datacrunch/test_configurator.py +17 -0
  184. tests/_internal/core/backends/gcp/test_configurator.py +42 -0
  185. tests/_internal/core/backends/kubernetes/test_configurator.py +43 -0
  186. tests/_internal/core/backends/lambdalabs/__init__.py +0 -0
  187. tests/_internal/core/backends/lambdalabs/test_configurator.py +38 -0
  188. tests/_internal/core/backends/oci/test_configurator.py +55 -0
  189. tests/_internal/core/backends/runpod/__init__.py +0 -0
  190. tests/_internal/core/backends/runpod/test_configurator.py +33 -0
  191. tests/_internal/core/backends/tensordock/__init__.py +0 -0
  192. tests/_internal/core/backends/tensordock/test_configurator.py +38 -0
  193. tests/_internal/core/backends/vastai/__init__.py +0 -0
  194. tests/_internal/core/backends/vastai/test_configurator.py +33 -0
  195. tests/_internal/core/backends/vultr/__init__.py +0 -0
  196. tests/_internal/core/backends/vultr/test_configurator.py +33 -0
  197. tests/_internal/server/background/tasks/test_process_gateways.py +4 -0
  198. tests/_internal/server/background/tasks/test_process_instances.py +49 -48
  199. tests/_internal/server/background/tasks/test_process_metrics.py +0 -3
  200. tests/_internal/server/background/tasks/test_process_placement_groups.py +2 -0
  201. tests/_internal/server/background/tasks/test_process_prometheus_metrics.py +186 -0
  202. tests/_internal/server/background/tasks/test_process_running_jobs.py +123 -19
  203. tests/_internal/server/background/tasks/test_process_runs.py +8 -22
  204. tests/_internal/server/background/tasks/test_process_submitted_jobs.py +3 -40
  205. tests/_internal/server/background/tasks/test_process_submitted_volumes.py +2 -0
  206. tests/_internal/server/background/tasks/test_process_terminating_jobs.py +10 -15
  207. tests/_internal/server/routers/test_backends.py +6 -764
  208. tests/_internal/server/routers/test_fleets.py +2 -26
  209. tests/_internal/server/routers/test_gateways.py +27 -3
  210. tests/_internal/server/routers/test_instances.py +0 -10
  211. tests/_internal/server/routers/test_metrics.py +42 -0
  212. tests/_internal/server/routers/test_projects.py +56 -0
  213. tests/_internal/server/routers/test_prometheus.py +333 -0
  214. tests/_internal/server/routers/test_repos.py +0 -15
  215. tests/_internal/server/routers/test_runs.py +83 -275
  216. tests/_internal/server/routers/test_volumes.py +2 -3
  217. tests/_internal/server/services/backends/__init__.py +0 -0
  218. tests/_internal/server/services/jobs/configurators/test_task.py +35 -0
  219. tests/_internal/server/services/test_config.py +7 -4
  220. tests/_internal/server/services/test_fleets.py +1 -4
  221. tests/_internal/server/services/{test_pools.py → test_instances.py} +11 -49
  222. tests/_internal/server/services/test_metrics.py +167 -0
  223. tests/_internal/server/services/test_repos.py +1 -14
  224. tests/_internal/server/services/test_runs.py +0 -4
  225. dstack/_internal/cli/commands/pool.py +0 -581
  226. dstack/_internal/cli/commands/run.py +0 -75
  227. dstack/_internal/core/backends/aws/config.py +0 -18
  228. dstack/_internal/core/backends/azure/config.py +0 -12
  229. dstack/_internal/core/backends/base/config.py +0 -5
  230. dstack/_internal/core/backends/cudo/config.py +0 -9
  231. dstack/_internal/core/backends/datacrunch/config.py +0 -9
  232. dstack/_internal/core/backends/gcp/config.py +0 -22
  233. dstack/_internal/core/backends/kubernetes/config.py +0 -6
  234. dstack/_internal/core/backends/lambdalabs/config.py +0 -9
  235. dstack/_internal/core/backends/nebius/__init__.py +0 -15
  236. dstack/_internal/core/backends/nebius/api_client.py +0 -319
  237. dstack/_internal/core/backends/nebius/compute.py +0 -220
  238. dstack/_internal/core/backends/nebius/config.py +0 -6
  239. dstack/_internal/core/backends/nebius/types.py +0 -37
  240. dstack/_internal/core/backends/oci/config.py +0 -6
  241. dstack/_internal/core/backends/runpod/config.py +0 -9
  242. dstack/_internal/core/backends/tensordock/config.py +0 -9
  243. dstack/_internal/core/backends/vastai/config.py +0 -6
  244. dstack/_internal/core/backends/vultr/config.py +0 -9
  245. dstack/_internal/core/models/backends/aws.py +0 -86
  246. dstack/_internal/core/models/backends/azure.py +0 -68
  247. dstack/_internal/core/models/backends/cudo.py +0 -43
  248. dstack/_internal/core/models/backends/datacrunch.py +0 -44
  249. dstack/_internal/core/models/backends/gcp.py +0 -67
  250. dstack/_internal/core/models/backends/kubernetes.py +0 -40
  251. dstack/_internal/core/models/backends/lambdalabs.py +0 -43
  252. dstack/_internal/core/models/backends/nebius.py +0 -54
  253. dstack/_internal/core/models/backends/runpod.py +0 -40
  254. dstack/_internal/core/models/backends/tensordock.py +0 -44
  255. dstack/_internal/core/models/backends/vastai.py +0 -43
  256. dstack/_internal/core/models/backends/vultr.py +0 -40
  257. dstack/_internal/core/models/pools.py +0 -43
  258. dstack/_internal/server/routers/pools.py +0 -142
  259. dstack/_internal/server/schemas/pools.py +0 -38
  260. dstack/_internal/server/services/backends/configurators/base.py +0 -72
  261. dstack/_internal/server/services/backends/configurators/cudo.py +0 -87
  262. dstack/_internal/server/services/backends/configurators/datacrunch.py +0 -79
  263. dstack/_internal/server/services/backends/configurators/kubernetes.py +0 -63
  264. dstack/_internal/server/services/backends/configurators/lambdalabs.py +0 -98
  265. dstack/_internal/server/services/backends/configurators/nebius.py +0 -85
  266. dstack/_internal/server/services/backends/configurators/runpod.py +0 -97
  267. dstack/_internal/server/services/backends/configurators/tensordock.py +0 -82
  268. dstack/_internal/server/services/backends/configurators/vastai.py +0 -80
  269. dstack/_internal/server/services/backends/configurators/vultr.py +0 -80
  270. dstack/api/_public/pools.py +0 -41
  271. dstack/api/_public/resources.py +0 -105
  272. dstack/api/server/_pools.py +0 -63
  273. tests/_internal/server/routers/test_pools.py +0 -612
  274. /dstack/_internal/{server/services/backends/configurators → core/backends/dstack}/__init__.py +0 -0
  275. {dstack-0.18.43.dist-info → dstack-0.19.0rc1.dist-info}/LICENSE.md +0 -0
  276. {dstack-0.18.43.dist-info → dstack-0.19.0rc1.dist-info}/WHEEL +0 -0
  277. {dstack-0.18.43.dist-info → dstack-0.19.0rc1.dist-info}/entry_points.txt +0 -0
  278. {dstack-0.18.43.dist-info → dstack-0.19.0rc1.dist-info}/top_level.txt +0 -0
@@ -9,7 +9,7 @@ from sqlalchemy.ext.asyncio import AsyncSession
9
9
  from sqlalchemy.orm import joinedload, selectinload
10
10
 
11
11
  from dstack._internal.core.backends import BACKENDS_WITH_CREATE_INSTANCE_SUPPORT
12
- from dstack._internal.core.backends.base import Backend
12
+ from dstack._internal.core.backends.base.backend import Backend
13
13
  from dstack._internal.core.errors import (
14
14
  ForbiddenError,
15
15
  ResourceExistsError,
@@ -27,16 +27,13 @@ from dstack._internal.core.models.fleets import (
27
27
  SSHParams,
28
28
  )
29
29
  from dstack._internal.core.models.instances import (
30
- InstanceConfiguration,
31
30
  InstanceOfferWithAvailability,
32
31
  InstanceStatus,
33
32
  RemoteConnectionInfo,
34
33
  SSHConnectionParams,
35
34
  SSHKey,
36
35
  )
37
- from dstack._internal.core.models.pools import Instance
38
36
  from dstack._internal.core.models.profiles import (
39
- DEFAULT_POOL_TERMINATION_IDLE_TIME,
40
37
  Profile,
41
38
  SpotPolicy,
42
39
  )
@@ -44,29 +41,26 @@ from dstack._internal.core.models.resources import ResourcesSpec
44
41
  from dstack._internal.core.models.runs import Requirements, get_policy_map
45
42
  from dstack._internal.core.models.users import GlobalRole
46
43
  from dstack._internal.core.services import validate_dstack_resource_name
47
- from dstack._internal.core.services.profiles import get_termination
48
44
  from dstack._internal.server.db import get_db
49
45
  from dstack._internal.server.models import (
50
46
  FleetModel,
51
47
  InstanceModel,
52
- PoolModel,
53
48
  ProjectModel,
54
49
  UserModel,
55
50
  )
51
+ from dstack._internal.server.services import instances as instances_services
56
52
  from dstack._internal.server.services import offers as offers_services
57
- from dstack._internal.server.services import pools as pools_services
53
+ from dstack._internal.server.services.instances import list_active_remote_instances
58
54
  from dstack._internal.server.services.locking import (
59
55
  get_locker,
60
56
  string_to_lock_id,
61
57
  )
62
- from dstack._internal.server.services.pools import list_active_remote_instances
63
58
  from dstack._internal.server.services.projects import (
64
59
  get_member,
65
60
  get_member_permissions,
66
61
  list_project_models,
67
62
  list_user_project_models,
68
63
  )
69
- from dstack._internal.utils import common as common_utils
70
64
  from dstack._internal.utils import random_names
71
65
  from dstack._internal.utils.logging import get_logger
72
66
  from dstack._internal.utils.ssh import pkey_from_str
@@ -291,7 +285,7 @@ async def get_create_instance_offers(
291
285
  fleet = fleet_model_to_fleet(fleet_model)
292
286
  multinode = fleet.spec.configuration.placement == InstanceGroupPlacement.CLUSTER
293
287
  for instance in fleet_model.instances:
294
- jpd = pools_services.get_instance_provisioning_data(instance)
288
+ jpd = instances_services.get_instance_provisioning_data(instance)
295
289
  if jpd is not None:
296
290
  master_job_provisioning_data = jpd
297
291
  break
@@ -308,7 +302,7 @@ async def get_create_instance_offers(
308
302
  offers = [
309
303
  (backend, offer)
310
304
  for backend, offer in offers
311
- if backend.TYPE in BACKENDS_WITH_CREATE_INSTANCE_SUPPORT
305
+ if offer.backend in BACKENDS_WITH_CREATE_INSTANCE_SUPPORT
312
306
  ]
313
307
  return offers
314
308
 
@@ -346,9 +340,6 @@ async def create_fleet(
346
340
  else:
347
341
  spec.configuration.name = await generate_fleet_name(session=session, project=project)
348
342
 
349
- pool = await pools_services.get_or_create_pool_by_name(
350
- session=session, project=project, pool_name=None
351
- )
352
343
  fleet_model = FleetModel(
353
344
  id=uuid.uuid4(),
354
345
  name=spec.configuration.name,
@@ -362,7 +353,6 @@ async def create_fleet(
362
353
  for i, host in enumerate(spec.configuration.ssh_config.hosts):
363
354
  instances_model = await create_fleet_ssh_instance_model(
364
355
  project=project,
365
- pool=pool,
366
356
  spec=spec,
367
357
  ssh_params=spec.configuration.ssh_config,
368
358
  env=spec.configuration.env,
@@ -380,7 +370,6 @@ async def create_fleet(
380
370
  session=session,
381
371
  project=project,
382
372
  user=user,
383
- pool=pool,
384
373
  spec=spec,
385
374
  placement_group_name=placement_group_name,
386
375
  reservation=spec.configuration.reservation,
@@ -395,7 +384,6 @@ async def create_fleet_instance_model(
395
384
  session: AsyncSession,
396
385
  project: ProjectModel,
397
386
  user: UserModel,
398
- pool: PoolModel,
399
387
  spec: FleetSpec,
400
388
  placement_group_name: Optional[str],
401
389
  reservation: Optional[str],
@@ -403,11 +391,10 @@ async def create_fleet_instance_model(
403
391
  ) -> InstanceModel:
404
392
  profile = spec.merged_profile
405
393
  requirements = _get_fleet_requirements(spec)
406
- instance_model = await pools_services.create_instance_model(
394
+ instance_model = await instances_services.create_instance_model(
407
395
  session=session,
408
396
  project=project,
409
397
  user=user,
410
- pool=pool,
411
398
  profile=profile,
412
399
  requirements=requirements,
413
400
  instance_name=f"{spec.configuration.name}-{instance_num}",
@@ -421,7 +408,6 @@ async def create_fleet_instance_model(
421
408
 
422
409
  async def create_fleet_ssh_instance_model(
423
410
  project: ProjectModel,
424
- pool: PoolModel,
425
411
  spec: FleetSpec,
426
412
  ssh_params: SSHParams,
427
413
  env: Env,
@@ -460,9 +446,8 @@ async def create_fleet_ssh_instance_model(
460
446
  ssh_proxy = None
461
447
  ssh_proxy_keys = None
462
448
 
463
- instance_model = await pools_services.create_ssh_instance_model(
449
+ instance_model = await instances_services.create_ssh_instance_model(
464
450
  project=project,
465
- pool=pool,
466
451
  instance_name=f"{spec.configuration.name}-{instance_num}",
467
452
  instance_num=instance_num,
468
453
  region="remote",
@@ -517,6 +502,7 @@ async def delete_fleets(
517
502
  .options(selectinload(FleetModel.instances))
518
503
  .options(selectinload(FleetModel.runs))
519
504
  .execution_options(populate_existing=True)
505
+ .order_by(FleetModel.id) # take locks in order
520
506
  .with_for_update()
521
507
  )
522
508
  fleet_models = res.scalars().unique().all()
@@ -540,7 +526,7 @@ def fleet_model_to_fleet(
540
526
  instance_models = fleet_model.instances
541
527
  if not include_deleted_instances:
542
528
  instance_models = [i for i in instance_models if not i.deleted]
543
- instances = [pools_services.instance_model_to_instance(i) for i in instance_models]
529
+ instances = [instances_services.instance_model_to_instance(i) for i in instance_models]
544
530
  instances = sorted(instances, key=lambda i: i.instance_num)
545
531
  spec = get_fleet_spec(fleet_model)
546
532
  if not include_sensitive:
@@ -584,86 +570,6 @@ def is_fleet_empty(fleet_model: FleetModel) -> bool:
584
570
  return len(active_instances) == 0
585
571
 
586
572
 
587
- async def create_instance(
588
- session: AsyncSession,
589
- project: ProjectModel,
590
- user: UserModel,
591
- profile: Profile,
592
- requirements: Requirements,
593
- ) -> Instance:
594
- offers = await get_create_instance_offers(
595
- project=project,
596
- profile=profile,
597
- requirements=requirements,
598
- exclude_not_available=True,
599
- )
600
-
601
- # Raise error if no backends suppport create_instance
602
- backend_types = set((backend.TYPE for backend, _ in offers))
603
- if all(
604
- (backend_type not in BACKENDS_WITH_CREATE_INSTANCE_SUPPORT)
605
- for backend_type in backend_types
606
- ):
607
- backends = ", ".join(sorted(backend_types))
608
- raise ServerClientError(
609
- f"Backends {backends} do not support create_instance. Try to select other backends."
610
- )
611
-
612
- pool = await pools_services.get_or_create_pool_by_name(session, project, profile.pool_name)
613
- instance_name = await pools_services.generate_instance_name(
614
- session=session,
615
- project=project,
616
- pool_name=pool.name,
617
- )
618
-
619
- termination_policy, termination_idle_time = get_termination(
620
- profile, DEFAULT_POOL_TERMINATION_IDLE_TIME
621
- )
622
- instance = InstanceModel(
623
- id=uuid.uuid4(),
624
- name=instance_name,
625
- instance_num=0,
626
- project=project,
627
- pool=pool,
628
- created_at=common_utils.get_current_datetime(),
629
- status=InstanceStatus.PENDING,
630
- unreachable=False,
631
- profile=profile.json(),
632
- requirements=requirements.json(),
633
- instance_configuration=None,
634
- termination_policy=termination_policy,
635
- termination_idle_time=termination_idle_time,
636
- total_blocks=1,
637
- busy_blocks=0,
638
- )
639
- logger.info(
640
- "Added a new instance %s",
641
- instance.name,
642
- extra={
643
- "instance_name": instance.name,
644
- "instance_status": InstanceStatus.PENDING.value,
645
- },
646
- )
647
- session.add(instance)
648
- await session.commit()
649
-
650
- project_ssh_key = SSHKey(
651
- public=project.ssh_public_key.strip(),
652
- private=project.ssh_private_key.strip(),
653
- )
654
- instance_config = InstanceConfiguration(
655
- project_name=project.name,
656
- instance_name=instance_name,
657
- instance_id=str(instance.id),
658
- ssh_keys=[project_ssh_key],
659
- user=user.name,
660
- )
661
- instance.instance_configuration = instance_config.json()
662
- await session.commit()
663
-
664
- return pools_services.instance_model_to_instance(instance)
665
-
666
-
667
573
  def _check_can_manage_ssh_fleets(user: UserModel, project: ProjectModel):
668
574
  if user.global_role == GlobalRole.ADMIN:
669
575
  return
@@ -16,6 +16,7 @@ from dstack._internal.core.backends import (
16
16
  )
17
17
  from dstack._internal.core.backends.base.compute import (
18
18
  Compute,
19
+ ComputeWithGatewaySupport,
19
20
  get_dstack_gateway_wheel,
20
21
  get_dstack_runner_version,
21
22
  )
@@ -38,6 +39,7 @@ from dstack._internal.server import settings
38
39
  from dstack._internal.server.db import get_db
39
40
  from dstack._internal.server.models import GatewayComputeModel, GatewayModel, ProjectModel
40
41
  from dstack._internal.server.services.backends import (
42
+ check_backend_type_available,
41
43
  get_project_backend_by_type_or_error,
42
44
  get_project_backend_with_model_by_type_or_error,
43
45
  )
@@ -91,6 +93,7 @@ async def create_gateway_compute(
91
93
  configuration: GatewayConfiguration,
92
94
  backend_id: Optional[uuid.UUID] = None,
93
95
  ) -> GatewayComputeModel:
96
+ assert isinstance(backend_compute, ComputeWithGatewaySupport)
94
97
  private_bytes, public_bytes = generate_rsa_key_pair_bytes()
95
98
  gateway_ssh_private_key = private_bytes.decode()
96
99
  gateway_ssh_public_key = public_bytes.decode()
@@ -220,6 +223,7 @@ async def delete_gateways(
220
223
  )
221
224
  .options(selectinload(GatewayModel.gateway_compute))
222
225
  .execution_options(populate_existing=True)
226
+ .order_by(GatewayModel.id) # take locks in order
223
227
  .with_for_update()
224
228
  )
225
229
  gateway_models = res.scalars().all()
@@ -227,6 +231,8 @@ async def delete_gateways(
227
231
  backend = await get_project_backend_by_type_or_error(
228
232
  project=project, backend_type=gateway_model.backend.type
229
233
  )
234
+ compute = backend.compute()
235
+ assert isinstance(compute, ComputeWithGatewaySupport)
230
236
  gateway_compute_configuration = get_gateway_compute_configuration(gateway_model)
231
237
  if (
232
238
  gateway_model.gateway_compute is not None
@@ -235,7 +241,7 @@ async def delete_gateways(
235
241
  logger.info("Deleting gateway compute for %s...", gateway_model.name)
236
242
  try:
237
243
  await run_async(
238
- backend.compute().terminate_gateway,
244
+ compute.terminate_gateway,
239
245
  gateway_model.gateway_compute.instance_id,
240
246
  gateway_compute_configuration,
241
247
  gateway_model.gateway_compute.backend_data,
@@ -532,10 +538,12 @@ def gateway_model_to_gateway(gateway_model: GatewayModel) -> Gateway:
532
538
 
533
539
 
534
540
  def _validate_gateway_configuration(configuration: GatewayConfiguration):
541
+ check_backend_type_available(configuration.backend)
535
542
  if configuration.backend not in BACKENDS_WITH_GATEWAY_SUPPORT:
536
543
  raise ServerClientError(
537
- f"Gateways are not supported for {configuration.backend.value} backend. "
538
- f"Supported backends: {[b.value for b in BACKENDS_WITH_GATEWAY_SUPPORT]}."
544
+ f"Gateways are not supported for {configuration.backend.value} backend."
545
+ " Available backends with gateway support:"
546
+ f" {[b.value for b in BACKENDS_WITH_GATEWAY_SUPPORT]}."
539
547
  )
540
548
 
541
549
  if configuration.name is not None:
@@ -547,7 +555,8 @@ def _validate_gateway_configuration(configuration: GatewayConfiguration):
547
555
  ):
548
556
  raise ServerClientError(
549
557
  f"Private gateways are not supported for {configuration.backend.value} backend. "
550
- f"Supported backends: {[b.value for b in BACKENDS_WITH_PRIVATE_GATEWAY_SUPPORT]}."
558
+ " Available backends with private gateway support:"
559
+ f" {[b.value for b in BACKENDS_WITH_PRIVATE_GATEWAY_SUPPORT]}."
551
560
  )
552
561
 
553
562
  if configuration.certificate is not None: