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