dstack 0.18.43__tar.gz → 0.18.44__tar.gz

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 (701) hide show
  1. {dstack-0.18.43 → dstack-0.18.44}/PKG-INFO +1 -1
  2. {dstack-0.18.43 → dstack-0.18.44}/setup.py +1 -0
  3. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/cli/services/configurators/run.py +1 -0
  4. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/cli/utils/run.py +11 -0
  5. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/aws/compute.py +1 -0
  6. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/azure/compute.py +1 -1
  7. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/gcp/compute.py +1 -1
  8. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/runpod/compute.py +21 -3
  9. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/runpod/config.py +8 -0
  10. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/models/backends/runpod.py +2 -0
  11. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/models/configurations.py +2 -1
  12. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/models/profiles.py +46 -1
  13. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/models/runs.py +4 -0
  14. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/app.py +11 -1
  15. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/background/__init__.py +10 -0
  16. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/background/tasks/process_placement_groups.py +1 -0
  17. dstack-0.18.44/src/dstack/_internal/server/background/tasks/process_prometheus_metrics.py +135 -0
  18. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/background/tasks/process_running_jobs.py +66 -19
  19. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/background/tasks/process_runs.py +1 -0
  20. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/background/tasks/process_submitted_jobs.py +4 -1
  21. dstack-0.18.44/src/dstack/_internal/server/migrations/versions/60e444118b6d_add_jobprometheusmetrics.py +40 -0
  22. dstack-0.18.44/src/dstack/_internal/server/migrations/versions/98d1b92988bc_add_jobterminationreason_terminated_due_.py +140 -0
  23. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/models.py +11 -0
  24. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/routers/metrics.py +21 -2
  25. dstack-0.18.44/src/dstack/_internal/server/routers/prometheus.py +36 -0
  26. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/security/permissions.py +1 -1
  27. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/backends/configurators/runpod.py +3 -33
  28. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/config.py +13 -3
  29. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/fleets.py +1 -0
  30. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/gateways/__init__.py +1 -0
  31. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/jobs/configurators/base.py +9 -1
  32. dstack-0.18.44/src/dstack/_internal/server/services/metrics.py +146 -0
  33. dstack-0.18.44/src/dstack/_internal/server/services/prometheus.py +87 -0
  34. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/runner/client.py +14 -3
  35. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/runs.py +43 -15
  36. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/volumes.py +1 -0
  37. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/settings.py +3 -0
  38. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/index.html +1 -1
  39. dstack-0.18.43/src/dstack/_internal/server/statics/main-fe8fd9db55df8d10e648.js → dstack-0.18.44/src/dstack/_internal/server/statics/main-4eb116b97819badd1e2c.js +66 -13
  40. dstack-0.18.43/src/dstack/_internal/server/statics/main-fe8fd9db55df8d10e648.js.map → dstack-0.18.44/src/dstack/_internal/server/statics/main-4eb116b97819badd1e2c.js.map +1 -1
  41. dstack-0.18.43/src/dstack/_internal/server/statics/main-7510e71dfa9749a4e70e.css → dstack-0.18.44/src/dstack/_internal/server/statics/main-da9f8c06a69c20dac23e.css +1 -1
  42. dstack-0.18.44/src/dstack/_internal/server/statics/static/media/entraID.d65d1f3e9486a8e56d24fc07b3230885.svg +9 -0
  43. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/testing/common.py +17 -0
  44. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/api/_public/runs.py +3 -0
  45. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/api/server/_fleets.py +2 -0
  46. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/api/server/_runs.py +4 -0
  47. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/api/utils.py +3 -0
  48. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/version.py +1 -1
  49. {dstack-0.18.43 → dstack-0.18.44}/src/dstack.egg-info/PKG-INFO +1 -1
  50. {dstack-0.18.43 → dstack-0.18.44}/src/dstack.egg-info/SOURCES.txt +12 -3
  51. {dstack-0.18.43 → dstack-0.18.44}/src/dstack.egg-info/requires.txt +9 -0
  52. dstack-0.18.44/src/tests/_internal/server/background/tasks/test_process_prometheus_metrics.py +189 -0
  53. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/server/background/tasks/test_process_running_jobs.py +125 -0
  54. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/server/routers/test_fleets.py +2 -0
  55. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/server/routers/test_metrics.py +15 -0
  56. dstack-0.18.44/src/tests/_internal/server/routers/test_prometheus.py +244 -0
  57. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/server/routers/test_runs.py +79 -56
  58. dstack-0.18.44/src/tests/_internal/server/services/test_metrics.py +163 -0
  59. dstack-0.18.43/src/dstack/_internal/server/services/metrics.py +0 -113
  60. {dstack-0.18.43 → dstack-0.18.44}/LICENSE.md +0 -0
  61. {dstack-0.18.43 → dstack-0.18.44}/README.md +0 -0
  62. {dstack-0.18.43 → dstack-0.18.44}/setup.cfg +0 -0
  63. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/__init__.py +0 -0
  64. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/__init__.py +0 -0
  65. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/cli/__init__.py +0 -0
  66. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/cli/commands/__init__.py +0 -0
  67. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/cli/commands/apply.py +0 -0
  68. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/cli/commands/attach.py +0 -0
  69. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/cli/commands/completion.py +0 -0
  70. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/cli/commands/config.py +0 -0
  71. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/cli/commands/delete.py +0 -0
  72. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/cli/commands/fleet.py +0 -0
  73. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/cli/commands/gateway.py +0 -0
  74. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/cli/commands/init.py +0 -0
  75. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/cli/commands/logs.py +0 -0
  76. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/cli/commands/pool.py +0 -0
  77. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/cli/commands/ps.py +0 -0
  78. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/cli/commands/run.py +0 -0
  79. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/cli/commands/server.py +0 -0
  80. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/cli/commands/stats.py +0 -0
  81. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/cli/commands/stop.py +0 -0
  82. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/cli/commands/volume.py +0 -0
  83. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/cli/main.py +0 -0
  84. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/cli/services/__init__.py +0 -0
  85. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/cli/services/args.py +0 -0
  86. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/cli/services/completion.py +0 -0
  87. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/cli/services/configurators/__init__.py +0 -0
  88. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/cli/services/configurators/base.py +0 -0
  89. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/cli/services/configurators/fleet.py +0 -0
  90. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/cli/services/configurators/gateway.py +0 -0
  91. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/cli/services/configurators/volume.py +0 -0
  92. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/cli/services/profile.py +0 -0
  93. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/cli/services/repos.py +0 -0
  94. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/cli/utils/__init__.py +0 -0
  95. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/cli/utils/common.py +0 -0
  96. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/cli/utils/fleet.py +0 -0
  97. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/cli/utils/gateway.py +0 -0
  98. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/cli/utils/rich.py +0 -0
  99. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/cli/utils/updates.py +0 -0
  100. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/cli/utils/volume.py +0 -0
  101. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/compat.py +0 -0
  102. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/__init__.py +0 -0
  103. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/__init__.py +0 -0
  104. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/aws/__init__.py +0 -0
  105. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/aws/auth.py +0 -0
  106. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/aws/config.py +0 -0
  107. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/aws/resources.py +0 -0
  108. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/azure/__init__.py +0 -0
  109. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/azure/auth.py +0 -0
  110. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/azure/config.py +0 -0
  111. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/azure/resources.py +0 -0
  112. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/azure/utils.py +0 -0
  113. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/base/__init__.py +0 -0
  114. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/base/compute.py +0 -0
  115. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/base/config.py +0 -0
  116. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/base/offers.py +0 -0
  117. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/cudo/__init__.py +0 -0
  118. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/cudo/api_client.py +0 -0
  119. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/cudo/compute.py +0 -0
  120. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/cudo/config.py +0 -0
  121. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/datacrunch/__init__.py +0 -0
  122. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/datacrunch/api_client.py +0 -0
  123. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/datacrunch/compute.py +0 -0
  124. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/datacrunch/config.py +0 -0
  125. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/gcp/__init__.py +0 -0
  126. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/gcp/auth.py +0 -0
  127. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/gcp/config.py +0 -0
  128. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/gcp/resources.py +0 -0
  129. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/kubernetes/__init__.py +0 -0
  130. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/kubernetes/compute.py +0 -0
  131. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/kubernetes/config.py +0 -0
  132. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/kubernetes/utils.py +0 -0
  133. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/lambdalabs/__init__.py +0 -0
  134. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/lambdalabs/api_client.py +0 -0
  135. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/lambdalabs/compute.py +0 -0
  136. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/lambdalabs/config.py +0 -0
  137. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/local/__init__.py +0 -0
  138. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/local/compute.py +0 -0
  139. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/nebius/__init__.py +0 -0
  140. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/nebius/api_client.py +0 -0
  141. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/nebius/compute.py +0 -0
  142. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/nebius/config.py +0 -0
  143. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/nebius/types.py +0 -0
  144. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/oci/__init__.py +0 -0
  145. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/oci/auth.py +0 -0
  146. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/oci/compute.py +0 -0
  147. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/oci/config.py +0 -0
  148. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/oci/exceptions.py +0 -0
  149. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/oci/region.py +0 -0
  150. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/oci/resources.py +0 -0
  151. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/remote/__init__.py +0 -0
  152. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/remote/provisioning.py +0 -0
  153. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/runpod/__init__.py +0 -0
  154. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/runpod/api_client.py +0 -0
  155. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/tensordock/__init__.py +0 -0
  156. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/tensordock/api_client.py +0 -0
  157. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/tensordock/compute.py +0 -0
  158. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/tensordock/config.py +0 -0
  159. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/vastai/__init__.py +0 -0
  160. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/vastai/api_client.py +0 -0
  161. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/vastai/compute.py +0 -0
  162. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/vastai/config.py +0 -0
  163. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/vultr/__init__.py +0 -0
  164. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/vultr/api_client.py +0 -0
  165. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/vultr/compute.py +0 -0
  166. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/backends/vultr/config.py +0 -0
  167. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/consts.py +0 -0
  168. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/errors.py +0 -0
  169. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/models/__init__.py +0 -0
  170. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/models/backends/__init__.py +0 -0
  171. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/models/backends/aws.py +0 -0
  172. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/models/backends/azure.py +0 -0
  173. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/models/backends/base.py +0 -0
  174. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/models/backends/cudo.py +0 -0
  175. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/models/backends/datacrunch.py +0 -0
  176. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/models/backends/dstack.py +0 -0
  177. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/models/backends/gcp.py +0 -0
  178. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/models/backends/kubernetes.py +0 -0
  179. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/models/backends/lambdalabs.py +0 -0
  180. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/models/backends/nebius.py +0 -0
  181. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/models/backends/oci.py +0 -0
  182. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/models/backends/tensordock.py +0 -0
  183. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/models/backends/vastai.py +0 -0
  184. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/models/backends/vultr.py +0 -0
  185. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/models/common.py +0 -0
  186. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/models/config.py +0 -0
  187. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/models/envs.py +0 -0
  188. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/models/fleets.py +0 -0
  189. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/models/gateways.py +0 -0
  190. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/models/instances.py +0 -0
  191. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/models/logs.py +0 -0
  192. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/models/metrics.py +0 -0
  193. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/models/placement.py +0 -0
  194. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/models/pools.py +0 -0
  195. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/models/projects.py +0 -0
  196. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/models/repos/__init__.py +0 -0
  197. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/models/repos/base.py +0 -0
  198. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/models/repos/local.py +0 -0
  199. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/models/repos/remote.py +0 -0
  200. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/models/repos/virtual.py +0 -0
  201. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/models/resources.py +0 -0
  202. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/models/secrets.py +0 -0
  203. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/models/server.py +0 -0
  204. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/models/services.py +0 -0
  205. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/models/unix.py +0 -0
  206. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/models/users.py +0 -0
  207. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/models/volumes.py +0 -0
  208. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/services/__init__.py +0 -0
  209. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/services/api_client.py +0 -0
  210. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/services/configs/__init__.py +0 -0
  211. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/services/diff.py +0 -0
  212. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/services/logs.py +0 -0
  213. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/services/profiles.py +0 -0
  214. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/services/repos.py +0 -0
  215. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/services/ssh/__init__.py +0 -0
  216. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/services/ssh/attach.py +0 -0
  217. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/services/ssh/client.py +0 -0
  218. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/services/ssh/ports.py +0 -0
  219. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/core/services/ssh/tunnel.py +0 -0
  220. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/proxy/__init__.py +0 -0
  221. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/proxy/gateway/__init__.py +0 -0
  222. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/proxy/gateway/app.py +0 -0
  223. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/proxy/gateway/auth.py +0 -0
  224. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/proxy/gateway/const.py +0 -0
  225. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/proxy/gateway/deps.py +0 -0
  226. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/proxy/gateway/main.py +0 -0
  227. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/proxy/gateway/models.py +0 -0
  228. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/proxy/gateway/repo/__init__.py +0 -0
  229. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/proxy/gateway/repo/repo.py +0 -0
  230. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/proxy/gateway/repo/state_v1.py +0 -0
  231. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/proxy/gateway/resources/nginx/00-log-format.conf +0 -0
  232. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/proxy/gateway/resources/nginx/entrypoint.jinja2 +0 -0
  233. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/proxy/gateway/resources/nginx/service.jinja2 +0 -0
  234. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/proxy/gateway/routers/__init__.py +0 -0
  235. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/proxy/gateway/routers/auth.py +0 -0
  236. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/proxy/gateway/routers/config.py +0 -0
  237. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/proxy/gateway/routers/registry.py +0 -0
  238. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/proxy/gateway/routers/stats.py +0 -0
  239. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/proxy/gateway/schemas/__init__.py +0 -0
  240. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/proxy/gateway/schemas/common.py +0 -0
  241. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/proxy/gateway/schemas/config.py +0 -0
  242. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/proxy/gateway/schemas/registry.py +0 -0
  243. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/proxy/gateway/schemas/stats.py +0 -0
  244. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/proxy/gateway/services/__init__.py +0 -0
  245. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/proxy/gateway/services/nginx.py +0 -0
  246. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/proxy/gateway/services/registry.py +0 -0
  247. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/proxy/gateway/services/server_client.py +0 -0
  248. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/proxy/gateway/services/stats.py +0 -0
  249. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/proxy/gateway/testing/__init__.py +0 -0
  250. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/proxy/gateway/testing/common.py +0 -0
  251. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/proxy/lib/__init__.py +0 -0
  252. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/proxy/lib/auth.py +0 -0
  253. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/proxy/lib/deps.py +0 -0
  254. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/proxy/lib/errors.py +0 -0
  255. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/proxy/lib/models.py +0 -0
  256. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/proxy/lib/repo.py +0 -0
  257. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/proxy/lib/routers/__init__.py +0 -0
  258. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/proxy/lib/routers/model_proxy.py +0 -0
  259. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/proxy/lib/schemas/__init__.py +0 -0
  260. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/proxy/lib/schemas/model_proxy.py +0 -0
  261. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/proxy/lib/services/__init__.py +0 -0
  262. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/proxy/lib/services/model_proxy/__init__.py +0 -0
  263. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/proxy/lib/services/model_proxy/clients/__init__.py +0 -0
  264. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/proxy/lib/services/model_proxy/clients/base.py +0 -0
  265. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/proxy/lib/services/model_proxy/clients/openai.py +0 -0
  266. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/proxy/lib/services/model_proxy/clients/tgi.py +0 -0
  267. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/proxy/lib/services/model_proxy/model_proxy.py +0 -0
  268. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/proxy/lib/services/service_connection.py +0 -0
  269. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/proxy/lib/testing/__init__.py +0 -0
  270. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/proxy/lib/testing/auth.py +0 -0
  271. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/proxy/lib/testing/common.py +0 -0
  272. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/__init__.py +0 -0
  273. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/background/tasks/__init__.py +0 -0
  274. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/background/tasks/common.py +0 -0
  275. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/background/tasks/process_fleets.py +0 -0
  276. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/background/tasks/process_gateways.py +0 -0
  277. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/background/tasks/process_instances.py +0 -0
  278. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/background/tasks/process_metrics.py +0 -0
  279. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/background/tasks/process_terminating_jobs.py +0 -0
  280. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/background/tasks/process_volumes.py +0 -0
  281. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/db.py +0 -0
  282. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/deps.py +0 -0
  283. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/main.py +0 -0
  284. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/migrations/__init__.py +0 -0
  285. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/migrations/env.py +0 -0
  286. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/migrations/versions/065588ec72b8_add_vultr_to_backendtype_enum.py +0 -0
  287. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/migrations/versions/0e33559e16ed_update_instancestatus.py +0 -0
  288. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/migrations/versions/112753bc17dd_remove_nullable_fields.py +0 -0
  289. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/migrations/versions/1338b788b612_reverse_job_instance_relationship.py +0 -0
  290. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/migrations/versions/14f2cb002fc2_add_jobmodel_removed_flag.py +0 -0
  291. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/migrations/versions/1a48dfe44a40_rework_termination_handling.py +0 -0
  292. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/migrations/versions/1e3fb39ef74b_add_remote_connection_details.py +0 -0
  293. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/migrations/versions/1e76fb0dde87_add_jobmodel_inactivity_secs.py +0 -0
  294. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/migrations/versions/23e01c56279a_make_blob_nullable.py +0 -0
  295. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/migrations/versions/252d3743b641_.py +0 -0
  296. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/migrations/versions/27d3e55759fa_add_pools.py +0 -0
  297. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/migrations/versions/29826f417010_remove_instancemodel_retry_policy.py +0 -0
  298. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/migrations/versions/29c08c6a8cb3_.py +0 -0
  299. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/migrations/versions/3cf77fb8bcf1_store_repo_clone_url.py +0 -0
  300. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/migrations/versions/3dbdce90d0e0_fix_code_uq_constraint.py +0 -0
  301. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/migrations/versions/48ad3ecbaea2_do_not_delete_projects_and_runs.py +0 -0
  302. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/migrations/versions/4ae1a5b0e7f1_add_run_list_index.py +0 -0
  303. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/migrations/versions/4b4319398164_introduce_runs_processing.py +0 -0
  304. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/migrations/versions/51d45659d574_add_instancemodel_blocks_fields.py +0 -0
  305. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/migrations/versions/54a77e19c64c_add_manager_project_role.py +0 -0
  306. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/migrations/versions/555138b1f77f_change_instancemodel_for_asynchronous_.py +0 -0
  307. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/migrations/versions/58aa5162dcc3_add_gatewaymodel_configuration.py +0 -0
  308. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/migrations/versions/5ad8debc8fe6_fixes_for_psql.py +0 -0
  309. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/migrations/versions/5ec538b70e71_replace_instansestatus.py +0 -0
  310. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/migrations/versions/63c3f19cb184_add_jobterminationreason_inactivity_.py +0 -0
  311. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/migrations/versions/686fb8341ea5_add_user_emails.py +0 -0
  312. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/migrations/versions/710e5b3fac8f_add_encryption.py +0 -0
  313. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/migrations/versions/7b24b1c8eba7_add_instancemodel_last_processed_at.py +0 -0
  314. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/migrations/versions/803c7e9ed85d_add_jobmodel_job_runtime_data.py +0 -0
  315. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/migrations/versions/82b32a135ea2_.py +0 -0
  316. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/migrations/versions/866ec1d67184_replace_retrypolicy_limit_with_.py +0 -0
  317. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/migrations/versions/91a12fff6c76_add_repocredsmodel.py +0 -0
  318. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/migrations/versions/91ac5e543037_extend_repos_creds_column.py +0 -0
  319. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/migrations/versions/98cd9c8b5927_add_volumemodel.py +0 -0
  320. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/migrations/versions/99b4c8c954ea_add_termination_reason_message.py +0 -0
  321. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/migrations/versions/9eea6af28e10_added_fail_reason_for_instancemodel.py +0 -0
  322. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/migrations/versions/__init__.py +0 -0
  323. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/migrations/versions/a060e2440936_.py +0 -0
  324. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/migrations/versions/a751ef183f27_move_attachment_data_to_volumes_.py +0 -0
  325. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/migrations/versions/a7b46c073fa1_add_placementgroupmodel.py +0 -0
  326. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/migrations/versions/afbc600ff2b2_add_created_at_to_usermodel_and_.py +0 -0
  327. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/migrations/versions/b4d6ad60db08_add_instancemodel_unreachable.py +0 -0
  328. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/migrations/versions/b88d55c2a07d_replace_instancestatus_ready.py +0 -0
  329. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/migrations/versions/bfba43f6def2_.py +0 -0
  330. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/migrations/versions/c00090eaef21_support_fleets.py +0 -0
  331. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/migrations/versions/c154eece89da_add_fields_for_async_gateway_creation.py +0 -0
  332. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/migrations/versions/c20626d03cfb_add_jobmetricspoint.py +0 -0
  333. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/migrations/versions/c48df7985d57_add_instance_termination_retries.py +0 -0
  334. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/migrations/versions/c83d45f9a971_replace_string_with_text.py +0 -0
  335. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/migrations/versions/d0bb68e48b9f_add_project_owners_and_quotas.py +0 -0
  336. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/migrations/versions/d3e8af4786fa_gateway_compute_flag_deleted.py +0 -0
  337. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/migrations/versions/d6b11105f659_add_usermodel_active.py +0 -0
  338. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/migrations/versions/da574e93fee0_add_jobmodel_volumes_detached_at.py +0 -0
  339. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/migrations/versions/dfffd6a1165c_add_fields_for_gateways_behind_alb.py +0 -0
  340. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/migrations/versions/e3b7db07727f_add_gatewaycomputemodel_app_updated_at.py +0 -0
  341. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/migrations/versions/e6391ca6a264_separate_gateways_from_compute.py +0 -0
  342. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/migrations/versions/ea60480f82bb_add_membermodel_member_num.py +0 -0
  343. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/migrations/versions/ed0ca30e13bb_migrate_instancestatus_provisioning.py +0 -0
  344. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/migrations/versions/fe72c4de8376_add_gateways.py +0 -0
  345. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/migrations/versions/ffa99edd1988_add_jobterminationreason_max_duration_.py +0 -0
  346. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/routers/__init__.py +0 -0
  347. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/routers/backends.py +0 -0
  348. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/routers/fleets.py +0 -0
  349. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/routers/gateways.py +0 -0
  350. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/routers/instances.py +0 -0
  351. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/routers/logs.py +0 -0
  352. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/routers/pools.py +0 -0
  353. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/routers/projects.py +0 -0
  354. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/routers/repos.py +0 -0
  355. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/routers/runs.py +0 -0
  356. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/routers/secrets.py +0 -0
  357. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/routers/server.py +0 -0
  358. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/routers/users.py +0 -0
  359. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/routers/volumes.py +0 -0
  360. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/schemas/__init__.py +0 -0
  361. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/schemas/backends.py +0 -0
  362. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/schemas/common.py +0 -0
  363. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/schemas/fleets.py +0 -0
  364. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/schemas/gateways.py +0 -0
  365. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/schemas/instances.py +0 -0
  366. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/schemas/logs.py +0 -0
  367. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/schemas/pools.py +0 -0
  368. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/schemas/projects.py +0 -0
  369. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/schemas/repos.py +0 -0
  370. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/schemas/runner.py +0 -0
  371. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/schemas/runs.py +0 -0
  372. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/schemas/secrets.py +0 -0
  373. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/schemas/users.py +0 -0
  374. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/schemas/volumes.py +0 -0
  375. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/security/__init__.py +0 -0
  376. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/__init__.py +0 -0
  377. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/backends/__init__.py +0 -0
  378. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/backends/configurators/__init__.py +0 -0
  379. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/backends/configurators/aws.py +0 -0
  380. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/backends/configurators/azure.py +0 -0
  381. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/backends/configurators/base.py +0 -0
  382. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/backends/configurators/cudo.py +0 -0
  383. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/backends/configurators/datacrunch.py +0 -0
  384. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/backends/configurators/gcp.py +0 -0
  385. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/backends/configurators/kubernetes.py +0 -0
  386. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/backends/configurators/lambdalabs.py +0 -0
  387. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/backends/configurators/nebius.py +0 -0
  388. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/backends/configurators/oci.py +0 -0
  389. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/backends/configurators/tensordock.py +0 -0
  390. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/backends/configurators/vastai.py +0 -0
  391. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/backends/configurators/vultr.py +0 -0
  392. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/backends/handlers.py +0 -0
  393. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/docker.py +0 -0
  394. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/encryption/__init__.py +0 -0
  395. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/encryption/keys/__init__.py +0 -0
  396. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/encryption/keys/aes.py +0 -0
  397. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/encryption/keys/base.py +0 -0
  398. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/encryption/keys/identity.py +0 -0
  399. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/gateways/client.py +0 -0
  400. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/gateways/connection.py +0 -0
  401. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/gateways/pool.py +0 -0
  402. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/jobs/__init__.py +0 -0
  403. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/jobs/configurators/__init__.py +0 -0
  404. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/jobs/configurators/dev.py +0 -0
  405. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/jobs/configurators/extensions/__init__.py +0 -0
  406. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/jobs/configurators/extensions/base.py +0 -0
  407. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/jobs/configurators/extensions/vscode.py +0 -0
  408. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/jobs/configurators/service.py +0 -0
  409. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/jobs/configurators/task.py +0 -0
  410. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/locking.py +0 -0
  411. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/logging.py +0 -0
  412. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/logs/__init__.py +0 -0
  413. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/logs/aws.py +0 -0
  414. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/logs/base.py +0 -0
  415. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/logs/filelog.py +0 -0
  416. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/logs/gcp.py +0 -0
  417. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/offers.py +0 -0
  418. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/permissions.py +0 -0
  419. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/placement.py +0 -0
  420. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/pools.py +0 -0
  421. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/projects.py +0 -0
  422. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/proxy/__init__.py +0 -0
  423. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/proxy/auth.py +0 -0
  424. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/proxy/deps.py +0 -0
  425. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/proxy/repo.py +0 -0
  426. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/proxy/routers/__init__.py +0 -0
  427. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/proxy/routers/service_proxy.py +0 -0
  428. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/proxy/services/__init__.py +0 -0
  429. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/proxy/services/service_proxy.py +0 -0
  430. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/repos.py +0 -0
  431. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/runner/__init__.py +0 -0
  432. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/runner/ssh.py +0 -0
  433. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/services/__init__.py +0 -0
  434. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/services/autoscalers.py +0 -0
  435. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/services/options.py +0 -0
  436. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/storage.py +0 -0
  437. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/services/users.py +0 -0
  438. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/00a6e1fb461ed2929fb9.png +0 -0
  439. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/0cae4d9f0a36034984a7.png +0 -0
  440. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/391de232cc0e30cae513.png +0 -0
  441. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/4e0eead8c1a73689ef9d.svg +0 -0
  442. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/544afa2f63428c2235b0.png +0 -0
  443. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/54a4f50f74c6b9381530.svg +0 -0
  444. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/68dd1360a7d2611e0132.svg +0 -0
  445. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/69544b4c81973b54a66f.png +0 -0
  446. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/77a8b02b17af19e39266.png +0 -0
  447. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/83a93a8871c219104367.svg +0 -0
  448. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/8f28bb8e9999e5e6a48b.svg +0 -0
  449. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/9124086961ab8c366bc4.svg +0 -0
  450. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/9a9ebaeb54b025dbac0a.svg +0 -0
  451. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/a3428392dc534f3b15c4.svg +0 -0
  452. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/ae22625574d69361f72c.png +0 -0
  453. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/android-chrome-144x144.png +0 -0
  454. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/android-chrome-192x192.png +0 -0
  455. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/android-chrome-256x256.png +0 -0
  456. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/android-chrome-36x36.png +0 -0
  457. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/android-chrome-384x384.png +0 -0
  458. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/android-chrome-48x48.png +0 -0
  459. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/android-chrome-512x512.png +0 -0
  460. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/android-chrome-72x72.png +0 -0
  461. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/android-chrome-96x96.png +0 -0
  462. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/apple-touch-icon-1024x1024.png +0 -0
  463. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/apple-touch-icon-114x114.png +0 -0
  464. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/apple-touch-icon-120x120.png +0 -0
  465. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/apple-touch-icon-144x144.png +0 -0
  466. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/apple-touch-icon-152x152.png +0 -0
  467. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/apple-touch-icon-167x167.png +0 -0
  468. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/apple-touch-icon-180x180.png +0 -0
  469. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/apple-touch-icon-57x57.png +0 -0
  470. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/apple-touch-icon-60x60.png +0 -0
  471. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/apple-touch-icon-72x72.png +0 -0
  472. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/apple-touch-icon-76x76.png +0 -0
  473. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/apple-touch-icon-precomposed.png +0 -0
  474. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/apple-touch-icon.png +0 -0
  475. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/apple-touch-startup-image-1125x2436.png +0 -0
  476. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/apple-touch-startup-image-1136x640.png +0 -0
  477. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/apple-touch-startup-image-1170x2532.png +0 -0
  478. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/apple-touch-startup-image-1179x2556.png +0 -0
  479. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/apple-touch-startup-image-1242x2208.png +0 -0
  480. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/apple-touch-startup-image-1242x2688.png +0 -0
  481. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/apple-touch-startup-image-1284x2778.png +0 -0
  482. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/apple-touch-startup-image-1290x2796.png +0 -0
  483. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/apple-touch-startup-image-1334x750.png +0 -0
  484. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/apple-touch-startup-image-1488x2266.png +0 -0
  485. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/apple-touch-startup-image-1536x2048.png +0 -0
  486. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/apple-touch-startup-image-1620x2160.png +0 -0
  487. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/apple-touch-startup-image-1640x2160.png +0 -0
  488. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/apple-touch-startup-image-1668x2224.png +0 -0
  489. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/apple-touch-startup-image-1668x2388.png +0 -0
  490. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/apple-touch-startup-image-1792x828.png +0 -0
  491. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/apple-touch-startup-image-2048x1536.png +0 -0
  492. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/apple-touch-startup-image-2048x2732.png +0 -0
  493. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/apple-touch-startup-image-2160x1620.png +0 -0
  494. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/apple-touch-startup-image-2160x1640.png +0 -0
  495. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/apple-touch-startup-image-2208x1242.png +0 -0
  496. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/apple-touch-startup-image-2224x1668.png +0 -0
  497. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/apple-touch-startup-image-2266x1488.png +0 -0
  498. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/apple-touch-startup-image-2388x1668.png +0 -0
  499. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/apple-touch-startup-image-2436x1125.png +0 -0
  500. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/apple-touch-startup-image-2532x1170.png +0 -0
  501. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/apple-touch-startup-image-2556x1179.png +0 -0
  502. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/apple-touch-startup-image-2688x1242.png +0 -0
  503. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/apple-touch-startup-image-2732x2048.png +0 -0
  504. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/apple-touch-startup-image-2778x1284.png +0 -0
  505. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/apple-touch-startup-image-2796x1290.png +0 -0
  506. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/apple-touch-startup-image-640x1136.png +0 -0
  507. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/apple-touch-startup-image-750x1334.png +0 -0
  508. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/apple-touch-startup-image-828x1792.png +0 -0
  509. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/browserconfig.xml +0 -0
  510. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/favicon-16x16.png +0 -0
  511. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/favicon-32x32.png +0 -0
  512. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/favicon-48x48.png +0 -0
  513. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/favicon.ico +0 -0
  514. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/manifest.webmanifest +0 -0
  515. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/mstile-144x144.png +0 -0
  516. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/mstile-150x150.png +0 -0
  517. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/mstile-310x150.png +0 -0
  518. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/mstile-310x310.png +0 -0
  519. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/mstile-70x70.png +0 -0
  520. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/yandex-browser-50x50.png +0 -0
  521. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/assets/yandex-browser-manifest.json +0 -0
  522. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/b7ae68f44193474fc578.png +0 -0
  523. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/d2f008c75b2b5b191f3f.png +0 -0
  524. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/d44c33e1b92e05c379fd.png +0 -0
  525. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/dd43ff0552815179d7ab.png +0 -0
  526. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/dd4e7166c0b9aac197d7.png +0 -0
  527. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/e30b27916930d43d2271.png +0 -0
  528. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/e467d7d60aae81ab198b.svg +0 -0
  529. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/eb9b344b73818fe2b71a.png +0 -0
  530. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/f517dd626eb964120de0.png +0 -0
  531. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/f958aecddee5d8e3222c.png +0 -0
  532. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/manifest.json +0 -0
  533. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/robots.txt +0 -0
  534. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/static/media/github.1f7102513534c83a9d8d735d2b8c12a2.svg +0 -0
  535. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/static/media/logo.f602feeb138844eda97c8cb641461448.svg +0 -0
  536. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/static/media/okta.12f178e6873a1100965f2a4dbd18fcec.svg +0 -0
  537. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/statics/static/media/theme.3994c817bb7dda191c1c9640dee0bf42.svg +0 -0
  538. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/testing/__init__.py +0 -0
  539. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/testing/conf.py +0 -0
  540. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/utils/__init__.py +0 -0
  541. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/utils/common.py +0 -0
  542. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/utils/logging.py +0 -0
  543. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/server/utils/routers.py +0 -0
  544. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/settings.py +0 -0
  545. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/utils/__init__.py +0 -0
  546. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/utils/common.py +0 -0
  547. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/utils/crypto.py +0 -0
  548. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/utils/dxf.py +0 -0
  549. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/utils/env.py +0 -0
  550. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/utils/gpu.py +0 -0
  551. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/utils/hash.py +0 -0
  552. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/utils/ignore.py +0 -0
  553. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/utils/interpolator.py +0 -0
  554. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/utils/logging.py +0 -0
  555. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/utils/network.py +0 -0
  556. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/utils/path.py +0 -0
  557. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/utils/random_names.py +0 -0
  558. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/_internal/utils/ssh.py +0 -0
  559. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/api/__init__.py +0 -0
  560. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/api/_public/__init__.py +0 -0
  561. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/api/_public/backends.py +0 -0
  562. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/api/_public/pools.py +0 -0
  563. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/api/_public/repos.py +0 -0
  564. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/api/_public/resources.py +0 -0
  565. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/api/huggingface/__init__.py +0 -0
  566. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/api/server/__init__.py +0 -0
  567. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/api/server/_backends.py +0 -0
  568. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/api/server/_gateways.py +0 -0
  569. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/api/server/_group.py +0 -0
  570. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/api/server/_logs.py +0 -0
  571. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/api/server/_metrics.py +0 -0
  572. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/api/server/_pools.py +0 -0
  573. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/api/server/_projects.py +0 -0
  574. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/api/server/_repos.py +0 -0
  575. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/api/server/_secrets.py +0 -0
  576. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/api/server/_users.py +0 -0
  577. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/api/server/_volumes.py +0 -0
  578. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/api/server/utils.py +0 -0
  579. {dstack-0.18.43 → dstack-0.18.44}/src/dstack/core/__init__.py +0 -0
  580. {dstack-0.18.43 → dstack-0.18.44}/src/dstack.egg-info/dependency_links.txt +0 -0
  581. {dstack-0.18.43 → dstack-0.18.44}/src/dstack.egg-info/entry_points.txt +0 -0
  582. {dstack-0.18.43 → dstack-0.18.44}/src/dstack.egg-info/top_level.txt +0 -0
  583. {dstack-0.18.43 → dstack-0.18.44}/src/tests/__init__.py +0 -0
  584. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/__init__.py +0 -0
  585. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/cli/__init__.py +0 -0
  586. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/cli/commands/__init__.py +0 -0
  587. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/cli/commands/test_config.py +0 -0
  588. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/cli/commands/test_dstack.py +0 -0
  589. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/cli/common.py +0 -0
  590. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/cli/services/__init__.py +0 -0
  591. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/cli/services/configurators/__init__.py +0 -0
  592. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/cli/services/configurators/test_fleet.py +0 -0
  593. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/cli/services/configurators/test_profile.py +0 -0
  594. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/cli/services/configurators/test_run.py +0 -0
  595. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/core/__init__.py +0 -0
  596. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/core/backends/__init__.py +0 -0
  597. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/core/backends/aws/__init__.py +0 -0
  598. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/core/backends/aws/test_resources.py +0 -0
  599. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/core/backends/azure/__init__.py +0 -0
  600. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/core/backends/azure/test_compute.py +0 -0
  601. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/core/backends/azure/test_resources.py +0 -0
  602. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/core/backends/base/__init__.py +0 -0
  603. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/core/backends/base/test_compute.py +0 -0
  604. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/core/backends/gcp/__init__.py +0 -0
  605. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/core/backends/gcp/test_resources.py +0 -0
  606. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/core/backends/kubernetes/__init__.py +0 -0
  607. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/core/backends/kubernetes/test_compute.py +0 -0
  608. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/core/backends/oci/__init__.py +0 -0
  609. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/core/backends/oci/test_resources.py +0 -0
  610. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/core/models/__init__.py +0 -0
  611. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/core/models/repos/__init__.py +0 -0
  612. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/core/models/repos/test_remote.py +0 -0
  613. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/core/models/test_configurations.py +0 -0
  614. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/core/models/test_instances.py +0 -0
  615. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/core/models/test_resources.py +0 -0
  616. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/core/models/test_runs.py +0 -0
  617. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/core/models/test_unix.py +0 -0
  618. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/core/models/test_volumes.py +0 -0
  619. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/core/services/__init__.py +0 -0
  620. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/core/services/ssh/__init__.py +0 -0
  621. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/core/services/ssh/test_client.py +0 -0
  622. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/core/services/ssh/test_tunnel.py +0 -0
  623. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/core/services/test_logs.py +0 -0
  624. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/proxy/__init__.py +0 -0
  625. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/proxy/gateway/__init__.py +0 -0
  626. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/proxy/gateway/conftest.py +0 -0
  627. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/proxy/gateway/repo/__init__.py +0 -0
  628. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/proxy/gateway/repo/test_repo.py +0 -0
  629. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/proxy/gateway/repo/test_state_v1.py +0 -0
  630. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/proxy/gateway/routers/__init__.py +0 -0
  631. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/proxy/gateway/routers/test_registry.py +0 -0
  632. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/proxy/gateway/routers/test_stats.py +0 -0
  633. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/proxy/gateway/services/__init__.py +0 -0
  634. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/proxy/gateway/services/test_stats.py +0 -0
  635. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/proxy/gateway/test_app.py +0 -0
  636. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/proxy/lib/__init__.py +0 -0
  637. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/proxy/lib/routers/__init__.py +0 -0
  638. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/proxy/lib/routers/test_model_proxy.py +0 -0
  639. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/server/__init__.py +0 -0
  640. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/server/background/__init__.py +0 -0
  641. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/server/background/tasks/__init__.py +0 -0
  642. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/server/background/tasks/test_process_fleets.py +0 -0
  643. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/server/background/tasks/test_process_gateways.py +0 -0
  644. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/server/background/tasks/test_process_instances.py +0 -0
  645. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/server/background/tasks/test_process_metrics.py +0 -0
  646. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/server/background/tasks/test_process_placement_groups.py +0 -0
  647. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/server/background/tasks/test_process_runs.py +0 -0
  648. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/server/background/tasks/test_process_submitted_jobs.py +0 -0
  649. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/server/background/tasks/test_process_submitted_volumes.py +0 -0
  650. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/server/background/tasks/test_process_terminating_jobs.py +0 -0
  651. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/server/conftest.py +0 -0
  652. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/server/routers/__init__.py +0 -0
  653. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/server/routers/test_backends.py +0 -0
  654. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/server/routers/test_gateways.py +0 -0
  655. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/server/routers/test_instances.py +0 -0
  656. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/server/routers/test_logs.py +0 -0
  657. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/server/routers/test_pools.py +0 -0
  658. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/server/routers/test_projects.py +0 -0
  659. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/server/routers/test_repos.py +0 -0
  660. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/server/routers/test_server.py +0 -0
  661. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/server/routers/test_users.py +0 -0
  662. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/server/routers/test_volumes.py +0 -0
  663. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/server/services/__init__.py +0 -0
  664. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/server/services/encryption/__init__.py +0 -0
  665. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/server/services/encryption/keys/__init__.py +0 -0
  666. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/server/services/encryption/keys/test_aes.py +0 -0
  667. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/server/services/encryption/test_encryption.py +0 -0
  668. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/server/services/jobs/__init__.py +0 -0
  669. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/server/services/jobs/configurators/__init__.py +0 -0
  670. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/server/services/jobs/configurators/test_base.py +0 -0
  671. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/server/services/proxy/__init__.py +0 -0
  672. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/server/services/proxy/routers/__init__.py +0 -0
  673. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/server/services/proxy/routers/test_service_proxy.py +0 -0
  674. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/server/services/runner/__init__.py +0 -0
  675. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/server/services/runner/test_client.py +0 -0
  676. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/server/services/services/__init__.py +0 -0
  677. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/server/services/services/test_autoscalers.py +0 -0
  678. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/server/services/test_config.py +0 -0
  679. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/server/services/test_docker.py +0 -0
  680. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/server/services/test_fleets.py +0 -0
  681. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/server/services/test_logs.py +0 -0
  682. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/server/services/test_offers.py +0 -0
  683. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/server/services/test_pools.py +0 -0
  684. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/server/services/test_repos.py +0 -0
  685. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/server/services/test_runs.py +0 -0
  686. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/server/test_app.py +0 -0
  687. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/server/test_migrations.py +0 -0
  688. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/server/utils/__init__.py +0 -0
  689. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/server/utils/test_common.py +0 -0
  690. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/server/utils/test_routers.py +0 -0
  691. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/utils/__init__.py +0 -0
  692. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/utils/test_common.py +0 -0
  693. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/utils/test_env.py +0 -0
  694. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/utils/test_gpu.py +0 -0
  695. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/utils/test_interpolator.py +0 -0
  696. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/utils/test_network.py +0 -0
  697. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/utils/test_path.py +0 -0
  698. {dstack-0.18.43 → dstack-0.18.44}/src/tests/_internal/utils/test_ssh.py +0 -0
  699. {dstack-0.18.43 → dstack-0.18.44}/src/tests/api/__init__.py +0 -0
  700. {dstack-0.18.43 → dstack-0.18.44}/src/tests/api/test_utils.py +0 -0
  701. {dstack-0.18.43 → dstack-0.18.44}/src/tests/conftest.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dstack
3
- Version: 0.18.43
3
+ Version: 0.18.44
4
4
  Summary: dstack is an open-source orchestration engine for running AI workloads on any cloud or on-premises.
5
5
  Home-page: https://dstack.ai
6
6
  Author: Andrey Cheptsov
@@ -76,6 +76,7 @@ SERVER_DEPS = GATEWAY_AND_SERVER_COMMON_DEPS + [
76
76
  "asyncpg",
77
77
  "cachetools",
78
78
  "python-json-logger>=3.1.0",
79
+ "prometheus-client",
79
80
  "grpcio>=1.50", # indirect
80
81
  ]
81
82
 
@@ -95,6 +95,7 @@ class BaseRunConfigurator(ApplyEnvVarsConfiguratorMixin, BaseApplyConfigurator):
95
95
  reservation=profile.reservation,
96
96
  spot_policy=profile.spot_policy,
97
97
  retry_policy=profile.retry_policy,
98
+ utilization_policy=profile.utilization_policy,
98
99
  max_duration=profile.max_duration,
99
100
  stop_duration=profile.stop_duration,
100
101
  max_price=profile.max_price,
@@ -4,6 +4,8 @@ from rich.markup import escape
4
4
  from rich.table import Table
5
5
 
6
6
  from dstack._internal.cli.utils.common import NO_OFFERS_WARNING, add_row_from_dict, console
7
+ from dstack._internal.core.models.common import is_core_model_instance
8
+ from dstack._internal.core.models.configurations import DevEnvironmentConfiguration
7
9
  from dstack._internal.core.models.instances import InstanceAvailability
8
10
  from dstack._internal.core.models.profiles import (
9
11
  DEFAULT_RUN_TERMINATION_IDLE_TIME,
@@ -38,6 +40,13 @@ def print_run_plan(run_plan: RunPlan, offers_limit: int = 3):
38
40
  if job_plan.job_spec.max_duration
39
41
  else "-"
40
42
  )
43
+ inactivity_duration = None
44
+ if is_core_model_instance(run_plan.run_spec.configuration, DevEnvironmentConfiguration):
45
+ inactivity_duration = "-"
46
+ if isinstance(run_plan.run_spec.configuration.inactivity_duration, int):
47
+ inactivity_duration = format_pretty_duration(
48
+ run_plan.run_spec.configuration.inactivity_duration
49
+ )
41
50
  if job_plan.job_spec.retry is None:
42
51
  retry = "-"
43
52
  else:
@@ -72,6 +81,8 @@ def print_run_plan(run_plan: RunPlan, offers_limit: int = 3):
72
81
  props.add_row(th("Resources"), pretty_req)
73
82
  props.add_row(th("Max price"), max_price)
74
83
  props.add_row(th("Max duration"), max_duration)
84
+ if inactivity_duration is not None: # None means n/a
85
+ props.add_row(th("Inactivity duration"), inactivity_duration)
75
86
  props.add_row(th("Spot policy"), spot_policy)
76
87
  props.add_row(th("Retry policy"), retry)
77
88
  props.add_row(th("Creation policy"), creation_policy)
@@ -506,6 +506,7 @@ class AWSCompute(Compute):
506
506
  "Failed to terminate all gateway %s resources. backend_data parsing error.",
507
507
  configuration.instance_name,
508
508
  )
509
+ return
509
510
 
510
511
  elb_client = self.session.client("elbv2", region_name=configuration.region)
511
512
 
@@ -312,7 +312,7 @@ def get_resource_group_network_subnet_or_error(
312
312
  except Exception:
313
313
  raise ComputeError(
314
314
  "Network specified in incorrect format."
315
- " Supported format for `vps_ids` values: 'networkResourceGroupName/networkName'"
315
+ " Supported format for `vpc_ids` values: 'networkResourceGroupName/networkName'"
316
316
  )
317
317
  elif resource_group is not None:
318
318
  network_name = azure_utils.get_default_network_name(resource_group, location)
@@ -580,7 +580,7 @@ class GCPCompute(Compute):
580
580
  operation = self.disk_client.delete(
581
581
  project=self.config.project_id,
582
582
  zone=get_or_error(volume.provisioning_data).availability_zone,
583
- disk=volume.name,
583
+ disk=volume.volume_id,
584
584
  )
585
585
  gcp_resources.wait_for_extended_operation(operation, "persistent disk deletion")
586
586
  except google.api_core.exceptions.NotFound:
@@ -52,8 +52,9 @@ class RunpodCompute(Compute):
52
52
  ) -> List[InstanceOfferWithAvailability]:
53
53
  offers = get_catalog_offers(
54
54
  backend=BackendType.RUNPOD,
55
- locations=self.config.regions,
55
+ locations=self.config.regions or None,
56
56
  requirements=requirements,
57
+ extra_filter=lambda o: _is_secure_cloud(o.region) or self.config.allow_community_cloud,
57
58
  )
58
59
  offers = [
59
60
  InstanceOfferWithAvailability(
@@ -102,13 +103,22 @@ class RunpodCompute(Compute):
102
103
  bid_per_gpu = None
103
104
  if instance_offer.instance.resources.spot and gpu_count:
104
105
  bid_per_gpu = instance_offer.price / gpu_count
106
+ if _is_secure_cloud(instance_offer.region):
107
+ cloud_type = "SECURE"
108
+ data_center_id = instance_offer.region
109
+ country_code = None
110
+ else:
111
+ cloud_type = "COMMUNITY"
112
+ data_center_id = None
113
+ country_code = instance_offer.region
105
114
 
106
115
  resp = self.api_client.create_pod(
107
116
  name=pod_name,
108
117
  image_name=job.job_spec.image_name,
109
118
  gpu_type_id=instance_offer.instance.name,
110
- cloud_type="SECURE", # ["ALL", "COMMUNITY", "SECURE"]:
111
- data_center_id=instance_offer.region,
119
+ cloud_type=cloud_type,
120
+ data_center_id=data_center_id,
121
+ country_code=country_code,
112
122
  gpu_count=gpu_count,
113
123
  container_disk_in_gb=disk_size,
114
124
  min_vcpu_count=instance_offer.instance.resources.cpus,
@@ -257,3 +267,11 @@ def _get_volume_price(size: int) -> float:
257
267
  if size < 1000:
258
268
  return 0.07 * size
259
269
  return 0.05 * size
270
+
271
+
272
+ def _is_secure_cloud(region: str) -> str:
273
+ """
274
+ Secure cloud regions are datacenter IDs: CA-MTL-1, EU-NL-1, etc.
275
+ Community cloud regions are country codes: CA, NL, etc.
276
+ """
277
+ return "-" in region
@@ -4,6 +4,14 @@ from dstack._internal.core.models.backends.runpod import (
4
4
  RunpodStoredConfig,
5
5
  )
6
6
 
7
+ RUNPOD_COMMUNITY_CLOUD_DEFAULT = True
8
+
7
9
 
8
10
  class RunpodConfig(RunpodStoredConfig, BackendConfig):
9
11
  creds: AnyRunpodCreds
12
+
13
+ @property
14
+ def allow_community_cloud(self) -> bool:
15
+ if self.community_cloud is not None:
16
+ return self.community_cloud
17
+ return RUNPOD_COMMUNITY_CLOUD_DEFAULT
@@ -10,6 +10,7 @@ from dstack._internal.core.models.common import CoreModel
10
10
  class RunpodConfigInfo(CoreModel):
11
11
  type: Literal["runpod"] = "runpod"
12
12
  regions: Optional[List[str]] = None
13
+ community_cloud: Optional[bool] = None
13
14
 
14
15
 
15
16
  class RunpodStoredConfig(RunpodConfigInfo):
@@ -33,6 +34,7 @@ class RunpodConfigInfoWithCredsPartial(CoreModel):
33
34
  type: Literal["runpod"] = "runpod"
34
35
  creds: Optional[AnyRunpodCreds]
35
36
  regions: Optional[List[str]]
37
+ community_cloud: Optional[bool]
36
38
 
37
39
 
38
40
  class RunpodConfigValues(CoreModel):
@@ -221,7 +221,8 @@ class DevEnvironmentConfigurationParams(CoreModel):
221
221
  " Inactivity is defined as the absence of SSH connections to the"
222
222
  " dev environment, including VS Code connections, `ssh <run name>`"
223
223
  " shells, and attached `dstack apply` or `dstack attach` commands."
224
- " Use `off` for unlimited duration. Defaults to `off`"
224
+ " Use `off` for unlimited duration. Can be updated in-place."
225
+ " Defaults to `off`"
225
226
  )
226
227
  ),
227
228
  ]
@@ -1,5 +1,5 @@
1
1
  from enum import Enum
2
- from typing import List, Optional, Union
2
+ from typing import List, Optional, Union, overload
3
3
 
4
4
  from pydantic import Field, root_validator, validator
5
5
  from typing_extensions import Annotated, Literal
@@ -34,6 +34,14 @@ class TerminationPolicy(str, Enum):
34
34
  DESTROY_AFTER_IDLE = "destroy-after-idle"
35
35
 
36
36
 
37
+ @overload
38
+ def parse_duration(v: None) -> None: ...
39
+
40
+
41
+ @overload
42
+ def parse_duration(v: Union[int, str]) -> int: ...
43
+
44
+
37
45
  def parse_duration(v: Optional[Union[int, str]]) -> Optional[int]:
38
46
  if v is None:
39
47
  return None
@@ -112,6 +120,39 @@ class ProfileRetry(CoreModel):
112
120
  return values
113
121
 
114
122
 
123
+ class UtilizationPolicy(CoreModel):
124
+ _min_time_window = "5m"
125
+
126
+ min_gpu_utilization: Annotated[
127
+ int,
128
+ Field(
129
+ description=(
130
+ "Minimum required GPU utilization, percent."
131
+ " If any GPU has utilization below specified value during the whole time window,"
132
+ " the run is terminated"
133
+ ),
134
+ ge=0,
135
+ le=100,
136
+ ),
137
+ ]
138
+ time_window: Annotated[
139
+ Union[int, str],
140
+ Field(
141
+ description=(
142
+ "The time window of metric samples taking into account to measure utilization"
143
+ f" (e.g., `30m`, `1h`). Minimum is `{_min_time_window}`"
144
+ )
145
+ ),
146
+ ]
147
+
148
+ @validator("time_window", pre=True)
149
+ def validate_time_window(cls, v: Union[int, str]) -> int:
150
+ v = parse_duration(v)
151
+ if v < parse_duration(cls._min_time_window):
152
+ raise ValueError(f"Minimum time_window is {cls._min_time_window}")
153
+ return v
154
+
155
+
115
156
  class ProfileParams(CoreModel):
116
157
  backends: Annotated[
117
158
  Optional[List[BackendType]],
@@ -194,6 +235,10 @@ class ProfileParams(CoreModel):
194
235
  )
195
236
  ),
196
237
  ]
238
+ utilization_policy: Annotated[
239
+ Optional[UtilizationPolicy],
240
+ Field(description="Run termination policy based on utilization"),
241
+ ]
197
242
  # Deprecated:
198
243
  termination_policy: Annotated[
199
244
  Optional[TerminationPolicy],
@@ -23,6 +23,7 @@ from dstack._internal.core.models.profiles import (
23
23
  ProfileRetryPolicy,
24
24
  RetryEvent,
25
25
  SpotPolicy,
26
+ UtilizationPolicy,
26
27
  )
27
28
  from dstack._internal.core.models.repos import AnyRunRepoData
28
29
  from dstack._internal.core.models.resources import Memory, ResourcesSpec
@@ -114,6 +115,7 @@ class JobTerminationReason(str, Enum):
114
115
  ABORTED_BY_USER = "aborted_by_user"
115
116
  TERMINATED_BY_SERVER = "terminated_by_server"
116
117
  INACTIVITY_DURATION_EXCEEDED = "inactivity_duration_exceeded"
118
+ TERMINATED_DUE_TO_UTILIZATION_POLICY = "terminated_due_to_utilization_policy"
117
119
  # Set by the runner
118
120
  CONTAINER_EXITED_WITH_ERROR = "container_exited_with_error"
119
121
  PORTS_BINDING_FAILED = "ports_binding_failed"
@@ -135,6 +137,7 @@ class JobTerminationReason(str, Enum):
135
137
  self.ABORTED_BY_USER: JobStatus.ABORTED,
136
138
  self.TERMINATED_BY_SERVER: JobStatus.TERMINATED,
137
139
  self.INACTIVITY_DURATION_EXCEEDED: JobStatus.TERMINATED,
140
+ self.TERMINATED_DUE_TO_UTILIZATION_POLICY: JobStatus.TERMINATED,
138
141
  self.CONTAINER_EXITED_WITH_ERROR: JobStatus.FAILED,
139
142
  self.PORTS_BINDING_FAILED: JobStatus.FAILED,
140
143
  self.CREATING_CONTAINER_ERROR: JobStatus.FAILED,
@@ -190,6 +193,7 @@ class JobSpec(CoreModel):
190
193
  single_branch: Optional[bool] = None
191
194
  max_duration: Optional[int]
192
195
  stop_duration: Optional[int] = None
196
+ utilization_policy: Optional[UtilizationPolicy] = None
193
197
  registry_auth: Optional[RegistryAuth]
194
198
  requirements: Requirements
195
199
  retry: Optional[Retry]
@@ -29,6 +29,7 @@ from dstack._internal.server.routers import (
29
29
  metrics,
30
30
  pools,
31
31
  projects,
32
+ prometheus,
32
33
  repos,
33
34
  runs,
34
35
  secrets,
@@ -185,6 +186,7 @@ def register_routes(app: FastAPI, ui: bool = True):
185
186
  app.include_router(model_proxy.router, prefix="/proxy/models", tags=["model-proxy"])
186
187
  app.include_router(pools.root_router)
187
188
  app.include_router(pools.router)
189
+ app.include_router(prometheus.router)
188
190
 
189
191
  @app.exception_handler(ForbiddenError)
190
192
  async def forbidden_error_handler(request: Request, exc: ForbiddenError):
@@ -252,7 +254,11 @@ def register_routes(app: FastAPI, ui: bool = True):
252
254
 
253
255
  @app.exception_handler(404)
254
256
  async def custom_http_exception_handler(request, exc):
255
- if request.url.path.startswith("/api") or _is_proxy_request(request):
257
+ if (
258
+ request.url.path.startswith("/api")
259
+ or _is_proxy_request(request)
260
+ or _is_prometheus_request(request)
261
+ ):
256
262
  return JSONResponse(
257
263
  {"detail": exc.detail},
258
264
  status_code=status.HTTP_404_NOT_FOUND,
@@ -283,6 +289,10 @@ def _is_proxy_request(request: Request) -> bool:
283
289
  ) and referrer.path.startswith("/proxy")
284
290
 
285
291
 
292
+ def _is_prometheus_request(request: Request) -> bool:
293
+ return request.url.path.startswith("/metrics")
294
+
295
+
286
296
  def _print_dstack_logo():
287
297
  console.print(
288
298
  """[purple]╱╱╭╮╱╱╭╮╱╱╱╱╱╱╭╮
@@ -1,6 +1,7 @@
1
1
  from apscheduler.schedulers.asyncio import AsyncIOScheduler
2
2
  from apscheduler.triggers.interval import IntervalTrigger
3
3
 
4
+ from dstack._internal.server import settings
4
5
  from dstack._internal.server.background.tasks.process_fleets import process_fleets
5
6
  from dstack._internal.server.background.tasks.process_gateways import (
6
7
  process_gateways_connections,
@@ -16,6 +17,10 @@ from dstack._internal.server.background.tasks.process_metrics import (
16
17
  from dstack._internal.server.background.tasks.process_placement_groups import (
17
18
  process_placement_groups,
18
19
  )
20
+ from dstack._internal.server.background.tasks.process_prometheus_metrics import (
21
+ collect_prometheus_metrics,
22
+ delete_prometheus_metrics,
23
+ )
19
24
  from dstack._internal.server.background.tasks.process_running_jobs import process_running_jobs
20
25
  from dstack._internal.server.background.tasks.process_runs import process_runs
21
26
  from dstack._internal.server.background.tasks.process_submitted_jobs import process_submitted_jobs
@@ -43,6 +48,11 @@ def start_background_tasks() -> AsyncIOScheduler:
43
48
  # * 150 active instances with up to 2 minutes processing latency
44
49
  _scheduler.add_job(collect_metrics, IntervalTrigger(seconds=10), max_instances=1)
45
50
  _scheduler.add_job(delete_metrics, IntervalTrigger(minutes=5), max_instances=1)
51
+ if settings.ENABLE_PROMETHEUS_METRICS:
52
+ _scheduler.add_job(
53
+ collect_prometheus_metrics, IntervalTrigger(seconds=10), max_instances=1
54
+ )
55
+ _scheduler.add_job(delete_prometheus_metrics, IntervalTrigger(minutes=5), max_instances=1)
46
56
  # process_submitted_jobs and process_instances max processing rate is 75 jobs(instances) per minute.
47
57
  _scheduler.add_job(
48
58
  process_submitted_jobs,
@@ -28,6 +28,7 @@ async def process_placement_groups():
28
28
  PlacementGroupModel.deleted == False,
29
29
  PlacementGroupModel.id.not_in(lockset),
30
30
  )
31
+ .order_by(PlacementGroupModel.id) # take locks in order
31
32
  .with_for_update(skip_locked=True)
32
33
  )
33
34
  placement_group_models = res.scalars().all()
@@ -0,0 +1,135 @@
1
+ import uuid
2
+ from datetime import datetime, timedelta
3
+ from typing import Optional
4
+
5
+ import sqlalchemy.exc
6
+ from sqlalchemy import delete, or_, select, update
7
+ from sqlalchemy.orm import joinedload
8
+
9
+ from dstack._internal.core.consts import DSTACK_SHIM_HTTP_PORT
10
+ from dstack._internal.core.models.runs import JobStatus
11
+ from dstack._internal.server.db import get_session_ctx
12
+ from dstack._internal.server.models import InstanceModel, JobModel, JobPrometheusMetrics
13
+ from dstack._internal.server.services.jobs import get_job_provisioning_data, get_job_runtime_data
14
+ from dstack._internal.server.services.pools import get_instance_ssh_private_keys
15
+ from dstack._internal.server.services.runner import client
16
+ from dstack._internal.server.services.runner.ssh import runner_ssh_tunnel
17
+ from dstack._internal.server.utils.common import gather_map_async
18
+ from dstack._internal.utils.common import batched, get_current_datetime, get_or_error, run_async
19
+ from dstack._internal.utils.logging import get_logger
20
+
21
+ logger = get_logger(__name__)
22
+
23
+
24
+ MAX_JOBS_FETCHED = 100
25
+ BATCH_SIZE = 10
26
+ MIN_COLLECT_INTERVAL_SECONDS = 9
27
+ # 10 minutes should be more than enough to scrape metrics, and, in any case,
28
+ # 10 minutes old metrics has little to no value
29
+ METRICS_TTL_SECONDS = 600
30
+
31
+
32
+ async def collect_prometheus_metrics():
33
+ now = get_current_datetime()
34
+ cutoff = now - timedelta(seconds=MIN_COLLECT_INTERVAL_SECONDS)
35
+ async with get_session_ctx() as session:
36
+ res = await session.execute(
37
+ select(JobModel)
38
+ .join(JobPrometheusMetrics, isouter=True)
39
+ .where(
40
+ JobModel.status.in_([JobStatus.RUNNING]),
41
+ or_(
42
+ JobPrometheusMetrics.job_id.is_(None),
43
+ JobPrometheusMetrics.collected_at < cutoff,
44
+ ),
45
+ )
46
+ .options(joinedload(JobModel.instance).joinedload(InstanceModel.project))
47
+ .order_by(JobModel.last_processed_at.asc())
48
+ .limit(MAX_JOBS_FETCHED)
49
+ )
50
+ job_models = res.unique().scalars().all()
51
+ for batch in batched(job_models, BATCH_SIZE):
52
+ await _collect_jobs_metrics(batch, now)
53
+
54
+
55
+ async def delete_prometheus_metrics():
56
+ now = get_current_datetime()
57
+ cutoff = now - timedelta(seconds=METRICS_TTL_SECONDS)
58
+ async with get_session_ctx() as session:
59
+ await session.execute(
60
+ delete(JobPrometheusMetrics).where(JobPrometheusMetrics.collected_at < cutoff)
61
+ )
62
+ await session.commit()
63
+
64
+
65
+ async def _collect_jobs_metrics(job_models: list[JobModel], collected_at: datetime):
66
+ results = await gather_map_async(job_models, _collect_job_metrics, return_exceptions=True)
67
+ async with get_session_ctx() as session:
68
+ for job_model, result in results:
69
+ if result is None:
70
+ continue
71
+ if isinstance(result, BaseException):
72
+ logger.error(
73
+ "Failed to collect job %s Prometheus metrics: %r", job_model.job_name, result
74
+ )
75
+ continue
76
+ res = await session.execute(
77
+ update(JobPrometheusMetrics)
78
+ .where(JobPrometheusMetrics.job_id == job_model.id)
79
+ .values(
80
+ collected_at=collected_at,
81
+ text=result,
82
+ )
83
+ .returning(JobPrometheusMetrics)
84
+ )
85
+ metrics = res.scalar()
86
+ if metrics is None:
87
+ metrics = JobPrometheusMetrics(
88
+ job_id=job_model.id,
89
+ collected_at=collected_at,
90
+ text=result,
91
+ )
92
+ try:
93
+ async with session.begin_nested():
94
+ session.add(metrics)
95
+ except sqlalchemy.exc.IntegrityError:
96
+ # Concurrent server replica already committed, ignoring
97
+ pass
98
+ await session.commit()
99
+
100
+
101
+ async def _collect_job_metrics(job_model: JobModel) -> Optional[str]:
102
+ ssh_private_keys = get_instance_ssh_private_keys(get_or_error(job_model.instance))
103
+ jpd = get_job_provisioning_data(job_model)
104
+ jrd = get_job_runtime_data(job_model)
105
+ if jpd is None:
106
+ return None
107
+ try:
108
+ res = await run_async(
109
+ _pull_job_metrics,
110
+ ssh_private_keys,
111
+ jpd,
112
+ jrd,
113
+ job_model.id,
114
+ )
115
+ except Exception:
116
+ logger.exception("Failed to collect job %s Prometheus metrics", job_model.job_name)
117
+ return None
118
+
119
+ if isinstance(res, bool):
120
+ logger.warning(
121
+ "Failed to connect to job %s to collect Prometheus metrics", job_model.job_name
122
+ )
123
+ return None
124
+
125
+ if res is None:
126
+ # Either not supported by shim or exporter is not available
127
+ return None
128
+
129
+ return res
130
+
131
+
132
+ @runner_ssh_tunnel(ports=[DSTACK_SHIM_HTTP_PORT], retries=1)
133
+ def _pull_job_metrics(ports: dict[int, int], task_id: uuid.UUID) -> Optional[str]:
134
+ shim_client = client.ShimClient(port=ports[DSTACK_SHIM_HTTP_PORT])
135
+ return shim_client.get_task_metrics(task_id)
@@ -1,4 +1,6 @@
1
1
  import asyncio
2
+ from collections.abc import Iterable
3
+ from datetime import timedelta
2
4
  from typing import Dict, List, Optional
3
5
 
4
6
  from sqlalchemy import select
@@ -15,6 +17,7 @@ from dstack._internal.core.models.instances import (
15
17
  RemoteConnectionInfo,
16
18
  SSHConnectionParams,
17
19
  )
20
+ from dstack._internal.core.models.metrics import Metric
18
21
  from dstack._internal.core.models.repos import RemoteRepoCreds
19
22
  from dstack._internal.core.models.runs import (
20
23
  ClusterInfo,
@@ -48,6 +51,7 @@ from dstack._internal.server.services.jobs import (
48
51
  )
49
52
  from dstack._internal.server.services.locking import get_locker
50
53
  from dstack._internal.server.services.logging import fmt
54
+ from dstack._internal.server.services.metrics import get_job_metrics
51
55
  from dstack._internal.server.services.pools import get_instance_ssh_private_keys
52
56
  from dstack._internal.server.services.repos import (
53
57
  get_code_model,
@@ -343,6 +347,9 @@ async def _process_running_job(session: AsyncSession, job_model: JobModel):
343
347
  job_model.status = JobStatus.TERMINATING
344
348
  job_model.termination_reason = JobTerminationReason.GATEWAY_ERROR
345
349
 
350
+ if job_model.status == JobStatus.RUNNING:
351
+ await _check_gpu_utilization(session, job_model, job)
352
+
346
353
  job_model.last_processed_at = common_utils.get_current_datetime()
347
354
  await session.commit()
348
355
 
@@ -646,27 +653,67 @@ def _terminate_if_inactivity_duration_exceeded(
646
653
  run_model: RunModel, job_model: JobModel, no_connections_secs: Optional[int]
647
654
  ) -> None:
648
655
  conf = RunSpec.__response__.parse_raw(run_model.run_spec).configuration
649
- if is_core_model_instance(conf, DevEnvironmentConfiguration) and isinstance(
656
+ if not is_core_model_instance(conf, DevEnvironmentConfiguration) or not isinstance(
650
657
  conf.inactivity_duration, int
651
658
  ):
652
- logger.debug("%s: no SSH connections for %s seconds", fmt(job_model), no_connections_secs)
653
- job_model.inactivity_secs = no_connections_secs
654
- if no_connections_secs is None:
655
- # TODO(0.19 or earlier): make no_connections_secs required
656
- job_model.status = JobStatus.TERMINATING
657
- job_model.termination_reason = JobTerminationReason.INTERRUPTED_BY_NO_CAPACITY
658
- job_model.termination_reason_message = (
659
- "The selected instance was created before dstack 0.18.41"
660
- " and does not support inactivity_duration"
661
- )
662
- elif no_connections_secs >= conf.inactivity_duration:
663
- job_model.status = JobStatus.TERMINATING
664
- # TODO(0.19 or earlier): set JobTerminationReason.INACTIVITY_DURATION_EXCEEDED
665
- job_model.termination_reason = JobTerminationReason.TERMINATED_BY_SERVER
666
- job_model.termination_reason_message = (
667
- f"The job was inactive for {no_connections_secs} seconds,"
668
- f" exceeding the inactivity_duration of {conf.inactivity_duration} seconds"
669
- )
659
+ # reset in case inactivity_duration was disabled via in-place update
660
+ job_model.inactivity_secs = None
661
+ return
662
+ logger.debug("%s: no SSH connections for %s seconds", fmt(job_model), no_connections_secs)
663
+ job_model.inactivity_secs = no_connections_secs
664
+ if no_connections_secs is None:
665
+ # TODO(0.19 or earlier): make no_connections_secs required
666
+ job_model.status = JobStatus.TERMINATING
667
+ job_model.termination_reason = JobTerminationReason.INTERRUPTED_BY_NO_CAPACITY
668
+ job_model.termination_reason_message = (
669
+ "The selected instance was created before dstack 0.18.41"
670
+ " and does not support inactivity_duration"
671
+ )
672
+ elif no_connections_secs >= conf.inactivity_duration:
673
+ job_model.status = JobStatus.TERMINATING
674
+ # TODO(0.19 or earlier): set JobTerminationReason.INACTIVITY_DURATION_EXCEEDED
675
+ job_model.termination_reason = JobTerminationReason.TERMINATED_BY_SERVER
676
+ job_model.termination_reason_message = (
677
+ f"The job was inactive for {no_connections_secs} seconds,"
678
+ f" exceeding the inactivity_duration of {conf.inactivity_duration} seconds"
679
+ )
680
+
681
+
682
+ async def _check_gpu_utilization(session: AsyncSession, job_model: JobModel, job: Job) -> None:
683
+ policy = job.job_spec.utilization_policy
684
+ if policy is None:
685
+ return
686
+ after = common_utils.get_current_datetime() - timedelta(seconds=policy.time_window)
687
+ job_metrics = await get_job_metrics(session, job_model, after=after)
688
+ gpus_util_metrics: list[Metric] = []
689
+ for metric in job_metrics.metrics:
690
+ if metric.name.startswith("gpu_util_percent_gpu"):
691
+ gpus_util_metrics.append(metric)
692
+ if not gpus_util_metrics or gpus_util_metrics[0].timestamps[-1] > after + timedelta(minutes=1):
693
+ # Job has started recently, not enough points collected.
694
+ # Assuming that metrics collection interval less than 1 minute.
695
+ logger.debug("%s: GPU utilization check: not enough samples", fmt(job_model))
696
+ return
697
+ if _should_terminate_due_to_low_gpu_util(
698
+ policy.min_gpu_utilization, [m.values for m in gpus_util_metrics]
699
+ ):
700
+ logger.info("%s: GPU utilization check: terminating", fmt(job_model))
701
+ job_model.status = JobStatus.TERMINATING
702
+ # TODO(0.19 or earlier): set JobTerminationReason.TERMINATED_DUE_TO_UTILIZATION_POLICY
703
+ job_model.termination_reason = JobTerminationReason.TERMINATED_BY_SERVER
704
+ job_model.termination_reason_message = (
705
+ f"The job GPU utilization below {policy.min_gpu_utilization}%"
706
+ f" for {policy.time_window} seconds"
707
+ )
708
+ else:
709
+ logger.debug("%s: GPU utilization check: OK", fmt(job_model))
710
+
711
+
712
+ def _should_terminate_due_to_low_gpu_util(min_util: int, gpus_util: Iterable[Iterable[int]]):
713
+ for gpu_util in gpus_util:
714
+ if all(util < min_util for util in gpu_util):
715
+ return True
716
+ return False
670
717
 
671
718
 
672
719
  def _get_cluster_info(
@@ -74,6 +74,7 @@ async def _process_next_run():
74
74
  JobModel.run_id == run_model.id,
75
75
  JobModel.id.not_in(job_lockset),
76
76
  )
77
+ .order_by(JobModel.id) # take locks in order
77
78
  .with_for_update(skip_locked=True)
78
79
  )
79
80
  job_models = res.scalars().all()
@@ -35,6 +35,7 @@ from dstack._internal.core.models.runs import (
35
35
  )
36
36
  from dstack._internal.core.models.volumes import Volume
37
37
  from dstack._internal.core.services.profiles import get_termination
38
+ from dstack._internal.server import settings
38
39
  from dstack._internal.server.db import get_db, get_session_ctx
39
40
  from dstack._internal.server.models import (
40
41
  FleetModel,
@@ -195,6 +196,7 @@ async def _process_submitted_job(session: AsyncSession, job_model: JobModel):
195
196
  InstanceModel.total_blocks > InstanceModel.busy_blocks,
196
197
  )
197
198
  .options(lazyload(InstanceModel.jobs))
199
+ .order_by(InstanceModel.id) # take locks in order
198
200
  .with_for_update()
199
201
  )
200
202
  pool_instances = list(res.unique().scalars().all())
@@ -319,6 +321,7 @@ async def _process_submitted_job(session: AsyncSession, job_model: JobModel):
319
321
  select(VolumeModel)
320
322
  .where(VolumeModel.id.in_(volumes_ids))
321
323
  .options(selectinload(VolumeModel.user))
324
+ .order_by(VolumeModel.id) # take locks in order
322
325
  .with_for_update()
323
326
  )
324
327
  async with get_locker().lock_ctx(VolumeModel.__tablename__, volumes_ids):
@@ -450,7 +453,7 @@ async def _run_job_on_new_instance(
450
453
  )
451
454
  # Limit number of offers tried to prevent long-running processing
452
455
  # in case all offers fail.
453
- for backend, offer in offers[:15]:
456
+ for backend, offer in offers[: settings.MAX_OFFERS_TRIED]:
454
457
  logger.debug(
455
458
  "%s: trying %s in %s/%s for $%0.4f per hour",
456
459
  fmt(job_model),