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
@@ -14,7 +14,7 @@ from dstack._internal.core.models.instances import (
14
14
  InstanceType,
15
15
  Resources,
16
16
  )
17
- from dstack._internal.core.models.profiles import Profile, ProfileRetryPolicy
17
+ from dstack._internal.core.models.profiles import Profile
18
18
  from dstack._internal.core.models.runs import (
19
19
  JobProvisioningData,
20
20
  JobStatus,
@@ -29,10 +29,10 @@ from dstack._internal.core.models.volumes import (
29
29
  from dstack._internal.server.background.tasks.process_submitted_jobs import process_submitted_jobs
30
30
  from dstack._internal.server.models import InstanceModel, JobModel, VolumeAttachmentModel
31
31
  from dstack._internal.server.testing.common import (
32
+ ComputeMockSpec,
32
33
  create_fleet,
33
34
  create_instance,
34
35
  create_job,
35
- create_pool,
36
36
  create_project,
37
37
  create_repo,
38
38
  create_run,
@@ -52,7 +52,6 @@ class TestProcessSubmittedJobs:
52
52
  async def test_fails_job_when_no_backends(self, test_db, session: AsyncSession):
53
53
  project = await create_project(session=session)
54
54
  user = await create_user(session=session)
55
- await create_pool(session=session, project=project)
56
55
  repo = await create_repo(
57
56
  session=session,
58
57
  project_id=project.id,
@@ -93,7 +92,6 @@ class TestProcessSubmittedJobs:
93
92
  ):
94
93
  project = await create_project(session=session)
95
94
  user = await create_user(session=session)
96
- pool = await create_pool(session=session, project=project)
97
95
  repo = await create_repo(
98
96
  session=session,
99
97
  project_id=project.id,
@@ -151,12 +149,6 @@ class TestProcessSubmittedJobs:
151
149
  assert job is not None
152
150
  assert job.status == JobStatus.PROVISIONING
153
151
 
154
- await session.refresh(pool)
155
- instance_offer = InstanceOfferWithAvailability.parse_raw(pool.instances[0].offer)
156
- assert offer == instance_offer
157
- pool_job_provisioning_data = pool.instances[0].job_provisioning_data
158
- assert pool_job_provisioning_data == job.job_provisioning_data
159
-
160
152
  @pytest.mark.asyncio
161
153
  @pytest.mark.parametrize("test_db", ["sqlite", "postgres"], indirect=True)
162
154
  async def test_fails_job_when_privileged_true_and_no_offers_with_create_instance_support(
@@ -166,7 +158,6 @@ class TestProcessSubmittedJobs:
166
158
  ):
167
159
  project = await create_project(session=session)
168
160
  user = await create_user(session=session)
169
- pool = await create_pool(session=session, project=project)
170
161
  repo = await create_repo(
171
162
  session=session,
172
163
  project_id=project.id,
@@ -227,9 +218,6 @@ class TestProcessSubmittedJobs:
227
218
  assert job.status == JobStatus.TERMINATING
228
219
  assert job.termination_reason == JobTerminationReason.FAILED_TO_START_DUE_TO_NO_CAPACITY
229
220
 
230
- await session.refresh(pool)
231
- assert not pool.instances
232
-
233
221
  @pytest.mark.asyncio
234
222
  @pytest.mark.parametrize("test_db", ["sqlite", "postgres"], indirect=True)
235
223
  async def test_fails_job_when_instance_mounts_and_no_offers_with_create_instance_support(
@@ -239,7 +227,6 @@ class TestProcessSubmittedJobs:
239
227
  ):
240
228
  project = await create_project(session=session)
241
229
  user = await create_user(session=session)
242
- pool = await create_pool(session=session, project=project)
243
230
  repo = await create_repo(
244
231
  session=session,
245
232
  project_id=project.id,
@@ -300,9 +287,6 @@ class TestProcessSubmittedJobs:
300
287
  assert job.status == JobStatus.TERMINATING
301
288
  assert job.termination_reason == JobTerminationReason.FAILED_TO_START_DUE_TO_NO_CAPACITY
302
289
 
303
- await session.refresh(pool)
304
- assert not pool.instances
305
-
306
290
  @pytest.mark.asyncio
307
291
  @pytest.mark.parametrize("test_db", ["sqlite", "postgres"], indirect=True)
308
292
  async def test_provisions_job_with_optional_instance_volume_not_attached(
@@ -312,7 +296,6 @@ class TestProcessSubmittedJobs:
312
296
  ):
313
297
  project = await create_project(session=session)
314
298
  user = await create_user(session=session)
315
- pool = await create_pool(session=session, project=project)
316
299
  repo = await create_repo(
317
300
  session=session,
318
301
  project_id=project.id,
@@ -369,18 +352,11 @@ class TestProcessSubmittedJobs:
369
352
  assert job is not None
370
353
  assert job.status == JobStatus.PROVISIONING
371
354
 
372
- await session.refresh(pool)
373
- instance_offer = InstanceOfferWithAvailability.parse_raw(pool.instances[0].offer)
374
- assert offer == instance_offer
375
- pool_job_provisioning_data = pool.instances[0].job_provisioning_data
376
- assert pool_job_provisioning_data == job.job_provisioning_data
377
-
378
355
  @pytest.mark.asyncio
379
356
  @pytest.mark.parametrize("test_db", ["sqlite", "postgres"], indirect=True)
380
357
  async def test_fails_job_when_no_capacity(self, test_db, session: AsyncSession):
381
358
  project = await create_project(session=session)
382
359
  user = await create_user(session=session)
383
- pool = await create_pool(session=session, project=project)
384
360
  repo = await create_repo(
385
361
  session=session,
386
362
  project_id=project.id,
@@ -396,7 +372,6 @@ class TestProcessSubmittedJobs:
396
372
  repo_id=repo.name,
397
373
  profile=Profile(
398
374
  name="default",
399
- retry_policy=ProfileRetryPolicy(retry=True, duration=3600),
400
375
  ),
401
376
  ),
402
377
  )
@@ -414,15 +389,12 @@ class TestProcessSubmittedJobs:
414
389
  assert job is not None
415
390
  assert job.status == JobStatus.TERMINATING
416
391
  assert job.termination_reason == JobTerminationReason.FAILED_TO_START_DUE_TO_NO_CAPACITY
417
- await session.refresh(pool)
418
- assert not pool.instances
419
392
 
420
393
  @pytest.mark.asyncio
421
394
  @pytest.mark.parametrize("test_db", ["sqlite", "postgres"], indirect=True)
422
395
  async def test_assignes_job_to_instance(self, test_db, session: AsyncSession):
423
396
  project = await create_project(session)
424
397
  user = await create_user(session)
425
- pool = await create_pool(session=session, project=project)
426
398
  repo = await create_repo(
427
399
  session=session,
428
400
  project_id=project.id,
@@ -430,10 +402,8 @@ class TestProcessSubmittedJobs:
430
402
  instance = await create_instance(
431
403
  session=session,
432
404
  project=project,
433
- pool=pool,
434
405
  status=InstanceStatus.IDLE,
435
406
  )
436
- await session.refresh(pool)
437
407
  run = await create_run(
438
408
  session=session,
439
409
  project=project,
@@ -459,7 +429,6 @@ class TestProcessSubmittedJobs:
459
429
  async def test_assigns_job_to_instance_with_volumes(self, test_db, session: AsyncSession):
460
430
  project = await create_project(session)
461
431
  user = await create_user(session)
462
- pool = await create_pool(session=session, project=project)
463
432
  repo = await create_repo(
464
433
  session=session,
465
434
  project_id=project.id,
@@ -476,12 +445,10 @@ class TestProcessSubmittedJobs:
476
445
  instance = await create_instance(
477
446
  session=session,
478
447
  project=project,
479
- pool=pool,
480
448
  status=InstanceStatus.IDLE,
481
449
  backend=BackendType.AWS,
482
450
  region="us-east-1",
483
451
  )
484
- await session.refresh(pool)
485
452
  run_spec = get_run_spec(run_name="test-run", repo_id=repo.name)
486
453
  run_spec.configuration.volumes = [
487
454
  VolumeMountPoint(name=volume.name, path="/volume"),
@@ -506,6 +473,7 @@ class TestProcessSubmittedJobs:
506
473
  backend_mock = Mock()
507
474
  m.return_value = backend_mock
508
475
  backend_mock.TYPE = BackendType.AWS
476
+ backend_mock.compute.return_value = Mock(spec=ComputeMockSpec)
509
477
  backend_mock.compute.return_value.attach_volume.return_value = VolumeAttachmentData()
510
478
  # Submitted jobs processing happens in two steps
511
479
  await process_submitted_jobs()
@@ -532,7 +500,6 @@ class TestProcessSubmittedJobs:
532
500
  async def test_assigns_job_to_shared_instance(self, test_db, session: AsyncSession):
533
501
  project = await create_project(session)
534
502
  user = await create_user(session)
535
- pool = await create_pool(session=session, project=project)
536
503
  repo = await create_repo(
537
504
  session=session,
538
505
  project_id=project.id,
@@ -541,13 +508,11 @@ class TestProcessSubmittedJobs:
541
508
  instance = await create_instance(
542
509
  session=session,
543
510
  project=project,
544
- pool=pool,
545
511
  status=InstanceStatus.IDLE,
546
512
  offer=offer,
547
513
  total_blocks=4,
548
514
  busy_blocks=1,
549
515
  )
550
- await session.refresh(pool)
551
516
  run = await create_run(
552
517
  session=session,
553
518
  project=project,
@@ -577,12 +542,10 @@ class TestProcessSubmittedJobs:
577
542
  project = await create_project(session)
578
543
  user = await create_user(session)
579
544
  repo = await create_repo(session=session, project_id=project.id)
580
- pool = await create_pool(session=session, project=project)
581
545
  fleet = await create_fleet(session=session, project=project)
582
546
  instance = await create_instance(
583
547
  session=session,
584
548
  project=project,
585
- pool=pool,
586
549
  instance_num=0,
587
550
  status=InstanceStatus.BUSY,
588
551
  )
@@ -7,6 +7,7 @@ from dstack._internal.core.models.backends.base import BackendType
7
7
  from dstack._internal.core.models.volumes import VolumeProvisioningData, VolumeStatus
8
8
  from dstack._internal.server.background.tasks.process_volumes import process_submitted_volumes
9
9
  from dstack._internal.server.testing.common import (
10
+ ComputeMockSpec,
10
11
  create_project,
11
12
  create_user,
12
13
  create_volume,
@@ -40,6 +41,7 @@ class TestProcessSubmittedVolumes:
40
41
  ) as m:
41
42
  aws_mock = Mock()
42
43
  m.return_value = aws_mock
44
+ aws_mock.compute.return_value = Mock(spec=ComputeMockSpec)
43
45
  aws_mock.compute.return_value.create_volume.return_value = VolumeProvisioningData(
44
46
  backend=BackendType.AWS,
45
47
  volume_id="1234",
@@ -16,9 +16,9 @@ from dstack._internal.server.background.tasks.process_terminating_jobs import (
16
16
  from dstack._internal.server.models import InstanceModel, JobModel, VolumeAttachmentModel
17
17
  from dstack._internal.server.services.volumes import volume_model_to_volume
18
18
  from dstack._internal.server.testing.common import (
19
+ ComputeMockSpec,
19
20
  create_instance,
20
21
  create_job,
21
- create_pool,
22
22
  create_project,
23
23
  create_repo,
24
24
  create_run,
@@ -39,11 +39,9 @@ class TestProcessTerminatingJobs:
39
39
  async def test_terminates_job(self, session: AsyncSession):
40
40
  project = await create_project(session=session)
41
41
  user = await create_user(session=session)
42
- pool = await create_pool(session=session, project=project)
43
42
  instance = await create_instance(
44
43
  session=session,
45
44
  project=project,
46
- pool=pool,
47
45
  status=InstanceStatus.BUSY,
48
46
  )
49
47
  repo = await create_repo(session=session, project_id=project.id)
@@ -78,7 +76,6 @@ class TestProcessTerminatingJobs:
78
76
  async def test_detaches_job_volumes(self, session: AsyncSession):
79
77
  project = await create_project(session=session)
80
78
  user = await create_user(session=session)
81
- pool = await create_pool(session=session, project=project)
82
79
  volume = await create_volume(
83
80
  session=session,
84
81
  project=project,
@@ -90,7 +87,6 @@ class TestProcessTerminatingJobs:
90
87
  instance = await create_instance(
91
88
  session=session,
92
89
  project=project,
93
- pool=pool,
94
90
  status=InstanceStatus.BUSY,
95
91
  volumes=[volume],
96
92
  )
@@ -114,6 +110,7 @@ class TestProcessTerminatingJobs:
114
110
  with patch("dstack._internal.server.services.backends.get_project_backend_by_type") as m:
115
111
  backend_mock = Mock()
116
112
  m.return_value = backend_mock
113
+ backend_mock.compute.return_value = Mock(spec=ComputeMockSpec)
117
114
  backend_mock.compute.return_value.is_volume_detached.return_value = True
118
115
  await process_terminating_jobs()
119
116
  m.assert_awaited_once()
@@ -125,7 +122,6 @@ class TestProcessTerminatingJobs:
125
122
  async def test_force_detaches_job_volumes(self, session: AsyncSession):
126
123
  project = await create_project(session=session)
127
124
  user = await create_user(session=session)
128
- pool = await create_pool(session=session, project=project)
129
125
  volume = await create_volume(
130
126
  session=session,
131
127
  project=project,
@@ -137,7 +133,6 @@ class TestProcessTerminatingJobs:
137
133
  instance = await create_instance(
138
134
  session=session,
139
135
  project=project,
140
- pool=pool,
141
136
  status=InstanceStatus.BUSY,
142
137
  volumes=[volume],
143
138
  )
@@ -163,6 +158,7 @@ class TestProcessTerminatingJobs:
163
158
  with patch("dstack._internal.server.services.backends.get_project_backend_by_type") as m:
164
159
  backend_mock = Mock()
165
160
  m.return_value = backend_mock
161
+ backend_mock.compute.return_value = Mock(spec=ComputeMockSpec)
166
162
  backend_mock.compute.return_value.is_volume_detached.return_value = False
167
163
  await process_terminating_jobs()
168
164
  m.assert_awaited_once()
@@ -188,6 +184,7 @@ class TestProcessTerminatingJobs:
188
184
  ) + timedelta(minutes=30)
189
185
  backend_mock = Mock()
190
186
  m.return_value = backend_mock
187
+ backend_mock.compute.return_value = Mock(spec=ComputeMockSpec)
191
188
  backend_mock.compute.return_value.is_volume_detached.return_value = False
192
189
  await process_terminating_jobs()
193
190
  m.assert_awaited_once()
@@ -205,6 +202,7 @@ class TestProcessTerminatingJobs:
205
202
  with patch("dstack._internal.server.services.backends.get_project_backend_by_type") as m:
206
203
  backend_mock = Mock()
207
204
  m.return_value = backend_mock
205
+ backend_mock.compute.return_value = Mock(spec=ComputeMockSpec)
208
206
  backend_mock.compute.return_value.is_volume_detached.return_value = True
209
207
  await process_terminating_jobs()
210
208
  m.assert_awaited_once()
@@ -223,7 +221,6 @@ class TestProcessTerminatingJobs:
223
221
  async def test_terminates_job_on_shared_instance(self, session: AsyncSession):
224
222
  project = await create_project(session)
225
223
  user = await create_user(session)
226
- pool = await create_pool(session=session, project=project)
227
224
  repo = await create_repo(
228
225
  session=session,
229
226
  project_id=project.id,
@@ -231,12 +228,10 @@ class TestProcessTerminatingJobs:
231
228
  instance = await create_instance(
232
229
  session=session,
233
230
  project=project,
234
- pool=pool,
235
231
  status=InstanceStatus.BUSY,
236
232
  total_blocks=4,
237
233
  busy_blocks=3,
238
234
  )
239
- await session.refresh(pool)
240
235
  run = await create_run(
241
236
  session=session,
242
237
  project=project,
@@ -270,7 +265,6 @@ class TestProcessTerminatingJobs:
270
265
  async def test_detaches_job_volumes_on_shared_instance(self, session: AsyncSession):
271
266
  project = await create_project(session=session)
272
267
  user = await create_user(session=session)
273
- pool = await create_pool(session=session, project=project)
274
268
  volume_conf_1 = get_volume_configuration(name="vol-1")
275
269
  volume_1 = await create_volume(
276
270
  session=session,
@@ -294,7 +288,6 @@ class TestProcessTerminatingJobs:
294
288
  instance = await create_instance(
295
289
  session=session,
296
290
  project=project,
297
- pool=pool,
298
291
  status=InstanceStatus.BUSY,
299
292
  volumes=[volume_1, volume_2],
300
293
  )
@@ -319,13 +312,15 @@ class TestProcessTerminatingJobs:
319
312
  with patch("dstack._internal.server.services.backends.get_project_backend_by_type") as m:
320
313
  backend_mock = Mock()
321
314
  m.return_value = backend_mock
315
+ backend_mock.compute.return_value = Mock(spec=ComputeMockSpec)
322
316
  backend_mock.compute.return_value.is_volume_detached.return_value = True
323
317
 
324
318
  await process_terminating_jobs()
325
319
 
326
- m.assert_awaited_once()
327
- backend_mock.compute.return_value.detach_volume.assert_called_once()
328
- backend_mock.compute.return_value.is_volume_detached.assert_called_once()
320
+ m.assert_awaited_once()
321
+ backend_mock.compute.return_value.detach_volume.assert_called_once()
322
+ backend_mock.compute.return_value.is_volume_detached.assert_called_once()
323
+
329
324
  await session.refresh(job)
330
325
  await session.refresh(instance)
331
326
  assert job.status == JobStatus.TERMINATED