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.
Potentially problematic release.
This version of dstack might be problematic. Click here for more details.
- 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
|
@@ -27,7 +27,6 @@ from dstack._internal.server.testing.common import (
|
|
|
27
27
|
create_fleet,
|
|
28
28
|
create_instance,
|
|
29
29
|
create_job,
|
|
30
|
-
create_pool,
|
|
31
30
|
create_project,
|
|
32
31
|
create_repo,
|
|
33
32
|
create_run,
|
|
@@ -346,8 +345,6 @@ class TestCreateFleet:
|
|
|
346
345
|
"retry": None,
|
|
347
346
|
"max_price": None,
|
|
348
347
|
"idle_duration": None,
|
|
349
|
-
"termination_policy": None,
|
|
350
|
-
"termination_idle_time": None,
|
|
351
348
|
"type": "fleet",
|
|
352
349
|
"name": "test-fleet",
|
|
353
350
|
"reservation": None,
|
|
@@ -360,16 +357,12 @@ class TestCreateFleet:
|
|
|
360
357
|
"instance_types": None,
|
|
361
358
|
"spot_policy": None,
|
|
362
359
|
"retry": None,
|
|
363
|
-
"retry_policy": None,
|
|
364
360
|
"max_duration": None,
|
|
365
361
|
"stop_duration": None,
|
|
366
362
|
"max_price": None,
|
|
367
|
-
"pool_name": None,
|
|
368
|
-
"instance_name": None,
|
|
369
363
|
"creation_policy": None,
|
|
370
364
|
"idle_duration": None,
|
|
371
|
-
"
|
|
372
|
-
"termination_idle_time": None,
|
|
365
|
+
"utilization_policy": None,
|
|
373
366
|
"name": "",
|
|
374
367
|
"default": False,
|
|
375
368
|
"reservation": None,
|
|
@@ -393,7 +386,6 @@ class TestCreateFleet:
|
|
|
393
386
|
"unreachable": False,
|
|
394
387
|
"termination_reason": None,
|
|
395
388
|
"created": "2023-01-02T03:04:00+00:00",
|
|
396
|
-
"pool_name": None,
|
|
397
389
|
"backend": None,
|
|
398
390
|
"region": None,
|
|
399
391
|
"availability_zone": None,
|
|
@@ -471,8 +463,6 @@ class TestCreateFleet:
|
|
|
471
463
|
"retry": None,
|
|
472
464
|
"max_price": None,
|
|
473
465
|
"idle_duration": None,
|
|
474
|
-
"termination_policy": None,
|
|
475
|
-
"termination_idle_time": None,
|
|
476
466
|
"type": "fleet",
|
|
477
467
|
"name": spec.configuration.name,
|
|
478
468
|
"reservation": None,
|
|
@@ -485,16 +475,12 @@ class TestCreateFleet:
|
|
|
485
475
|
"instance_types": None,
|
|
486
476
|
"spot_policy": None,
|
|
487
477
|
"retry": None,
|
|
488
|
-
"retry_policy": None,
|
|
489
478
|
"max_duration": None,
|
|
490
479
|
"stop_duration": None,
|
|
491
480
|
"max_price": None,
|
|
492
|
-
"pool_name": None,
|
|
493
|
-
"instance_name": None,
|
|
494
481
|
"creation_policy": None,
|
|
495
482
|
"idle_duration": None,
|
|
496
|
-
"
|
|
497
|
-
"termination_idle_time": None,
|
|
483
|
+
"utilization_policy": None,
|
|
498
484
|
"name": "",
|
|
499
485
|
"default": False,
|
|
500
486
|
"reservation": None,
|
|
@@ -524,7 +510,6 @@ class TestCreateFleet:
|
|
|
524
510
|
"fleet_id": "1b0e1b45-2f8c-4ab6-8010-a0d1a3e44e0e",
|
|
525
511
|
"fleet_name": spec.configuration.name,
|
|
526
512
|
"instance_num": 0,
|
|
527
|
-
"pool_name": None,
|
|
528
513
|
"job_name": None,
|
|
529
514
|
"hostname": "1.1.1.1",
|
|
530
515
|
"status": "pending",
|
|
@@ -625,12 +610,10 @@ class TestDeleteFleets:
|
|
|
625
610
|
await add_project_member(
|
|
626
611
|
session=session, project=project, user=user, project_role=ProjectRole.USER
|
|
627
612
|
)
|
|
628
|
-
pool = await create_pool(session=session, project=project)
|
|
629
613
|
fleet = await create_fleet(session=session, project=project)
|
|
630
614
|
instance = await create_instance(
|
|
631
615
|
session=session,
|
|
632
616
|
project=project,
|
|
633
|
-
pool=pool,
|
|
634
617
|
)
|
|
635
618
|
fleet.instances.append(instance)
|
|
636
619
|
await session.commit()
|
|
@@ -652,7 +635,6 @@ class TestDeleteFleets:
|
|
|
652
635
|
):
|
|
653
636
|
user = await create_user(session, global_role=GlobalRole.USER)
|
|
654
637
|
project = await create_project(session)
|
|
655
|
-
pool = await create_pool(session=session, project=project)
|
|
656
638
|
await add_project_member(
|
|
657
639
|
session=session, project=project, user=user, project_role=ProjectRole.USER
|
|
658
640
|
)
|
|
@@ -674,7 +656,6 @@ class TestDeleteFleets:
|
|
|
674
656
|
instance = await create_instance(
|
|
675
657
|
session=session,
|
|
676
658
|
project=project,
|
|
677
|
-
pool=pool,
|
|
678
659
|
status=InstanceStatus.BUSY,
|
|
679
660
|
job=job,
|
|
680
661
|
)
|
|
@@ -742,18 +723,15 @@ class TestDeleteFleetInstances:
|
|
|
742
723
|
await add_project_member(
|
|
743
724
|
session=session, project=project, user=user, project_role=ProjectRole.USER
|
|
744
725
|
)
|
|
745
|
-
pool = await create_pool(session=session, project=project)
|
|
746
726
|
fleet = await create_fleet(session=session, project=project)
|
|
747
727
|
instance1 = await create_instance(
|
|
748
728
|
session=session,
|
|
749
729
|
project=project,
|
|
750
|
-
pool=pool,
|
|
751
730
|
instance_num=1,
|
|
752
731
|
)
|
|
753
732
|
instance2 = await create_instance(
|
|
754
733
|
session=session,
|
|
755
734
|
project=project,
|
|
756
|
-
pool=pool,
|
|
757
735
|
instance_num=2,
|
|
758
736
|
)
|
|
759
737
|
fleet.instances.append(instance1)
|
|
@@ -783,7 +761,6 @@ class TestDeleteFleetInstances:
|
|
|
783
761
|
await add_project_member(
|
|
784
762
|
session=session, project=project, user=user, project_role=ProjectRole.USER
|
|
785
763
|
)
|
|
786
|
-
pool = await create_pool(session=session, project=project)
|
|
787
764
|
fleet = await create_fleet(session=session, project=project)
|
|
788
765
|
repo = await create_repo(
|
|
789
766
|
session=session,
|
|
@@ -802,7 +779,6 @@ class TestDeleteFleetInstances:
|
|
|
802
779
|
instance = await create_instance(
|
|
803
780
|
session=session,
|
|
804
781
|
project=project,
|
|
805
|
-
pool=pool,
|
|
806
782
|
instance_num=1,
|
|
807
783
|
status=InstanceStatus.BUSY,
|
|
808
784
|
job=job,
|
|
@@ -13,6 +13,7 @@ from dstack._internal.server.services.gateways import (
|
|
|
13
13
|
)
|
|
14
14
|
from dstack._internal.server.services.projects import add_project_member
|
|
15
15
|
from dstack._internal.server.testing.common import (
|
|
16
|
+
ComputeMockSpec,
|
|
16
17
|
create_backend,
|
|
17
18
|
create_gateway,
|
|
18
19
|
create_gateway_compute,
|
|
@@ -174,7 +175,14 @@ class TestCreateGateway:
|
|
|
174
175
|
backend = await create_backend(session, project.id, backend_type=BackendType.AWS)
|
|
175
176
|
response = await client.post(
|
|
176
177
|
f"/api/project/{project.name}/gateways/create",
|
|
177
|
-
json={
|
|
178
|
+
json={
|
|
179
|
+
"configuration": {
|
|
180
|
+
"type": "gateway",
|
|
181
|
+
"name": "test",
|
|
182
|
+
"backend": "aws",
|
|
183
|
+
"region": "us",
|
|
184
|
+
},
|
|
185
|
+
},
|
|
178
186
|
headers=get_auth_headers(user.token),
|
|
179
187
|
)
|
|
180
188
|
assert response.status_code == 200
|
|
@@ -217,7 +225,14 @@ class TestCreateGateway:
|
|
|
217
225
|
g.return_value = "random-name"
|
|
218
226
|
response = await client.post(
|
|
219
227
|
f"/api/project/{project.name}/gateways/create",
|
|
220
|
-
json={
|
|
228
|
+
json={
|
|
229
|
+
"configuration": {
|
|
230
|
+
"type": "gateway",
|
|
231
|
+
"name": None,
|
|
232
|
+
"backend": "aws",
|
|
233
|
+
"region": "us",
|
|
234
|
+
},
|
|
235
|
+
},
|
|
221
236
|
headers=get_auth_headers(user.token),
|
|
222
237
|
)
|
|
223
238
|
g.assert_called_once()
|
|
@@ -258,7 +273,14 @@ class TestCreateGateway:
|
|
|
258
273
|
)
|
|
259
274
|
response = await client.post(
|
|
260
275
|
f"/api/project/{project.name}/gateways/create",
|
|
261
|
-
json={
|
|
276
|
+
json={
|
|
277
|
+
"configuration": {
|
|
278
|
+
"type": "gateway",
|
|
279
|
+
"name": "test",
|
|
280
|
+
"backend": "aws",
|
|
281
|
+
"region": "us",
|
|
282
|
+
},
|
|
283
|
+
},
|
|
262
284
|
headers=get_auth_headers(user.token),
|
|
263
285
|
)
|
|
264
286
|
assert response.status_code == 400
|
|
@@ -437,8 +459,10 @@ class TestDeleteGateway:
|
|
|
437
459
|
"dstack._internal.server.services.gateways.get_project_backend_by_type_or_error"
|
|
438
460
|
) as m:
|
|
439
461
|
aws = Mock()
|
|
462
|
+
aws.compute.return_value = Mock(spec=ComputeMockSpec)
|
|
440
463
|
aws.compute.return_value.terminate_gateway.return_value = None # success
|
|
441
464
|
gcp = Mock()
|
|
465
|
+
gcp.compute.return_value = Mock(spec=ComputeMockSpec)
|
|
442
466
|
gcp.compute.return_value.terminate_gateway.side_effect = DstackError() # fail
|
|
443
467
|
|
|
444
468
|
def get_backend(project, backend_type):
|
|
@@ -15,7 +15,6 @@ from dstack._internal.server.services.projects import add_project_member
|
|
|
15
15
|
from dstack._internal.server.testing.common import (
|
|
16
16
|
create_fleet,
|
|
17
17
|
create_instance,
|
|
18
|
-
create_pool,
|
|
19
18
|
create_project,
|
|
20
19
|
create_user,
|
|
21
20
|
get_auth_headers,
|
|
@@ -59,11 +58,6 @@ class TestListInstances:
|
|
|
59
58
|
await add_project_member(
|
|
60
59
|
session, project=projects[2], user=users[1], project_role=ProjectRole.USER
|
|
61
60
|
)
|
|
62
|
-
pools = [
|
|
63
|
-
await create_pool(session, projects[0]),
|
|
64
|
-
await create_pool(session, projects[1]),
|
|
65
|
-
await create_pool(session, projects[2]),
|
|
66
|
-
]
|
|
67
61
|
fleets = [
|
|
68
62
|
await create_fleet(
|
|
69
63
|
session,
|
|
@@ -88,7 +82,6 @@ class TestListInstances:
|
|
|
88
82
|
await create_instance(
|
|
89
83
|
session=session,
|
|
90
84
|
project=projects[0],
|
|
91
|
-
pool=pools[0],
|
|
92
85
|
fleet=fleets[0],
|
|
93
86
|
created_at=dt.datetime(2024, 1, 1, tzinfo=dt.timezone.utc),
|
|
94
87
|
name="fleet0-0",
|
|
@@ -96,7 +89,6 @@ class TestListInstances:
|
|
|
96
89
|
await create_instance(
|
|
97
90
|
session=session,
|
|
98
91
|
project=projects[1],
|
|
99
|
-
pool=pools[1],
|
|
100
92
|
fleet=fleets[1],
|
|
101
93
|
created_at=dt.datetime(2024, 1, 2, tzinfo=dt.timezone.utc),
|
|
102
94
|
name="fleet1-0",
|
|
@@ -104,7 +96,6 @@ class TestListInstances:
|
|
|
104
96
|
await create_instance(
|
|
105
97
|
session=session,
|
|
106
98
|
project=projects[2],
|
|
107
|
-
pool=pools[2],
|
|
108
99
|
fleet=fleets[2],
|
|
109
100
|
created_at=dt.datetime(2024, 1, 3, tzinfo=dt.timezone.utc),
|
|
110
101
|
name="fleet2-0",
|
|
@@ -112,7 +103,6 @@ class TestListInstances:
|
|
|
112
103
|
await create_instance(
|
|
113
104
|
session=session,
|
|
114
105
|
project=projects[2],
|
|
115
|
-
pool=pools[2],
|
|
116
106
|
fleet=fleets[2],
|
|
117
107
|
created_at=dt.datetime(2024, 1, 4, tzinfo=dt.timezone.utc),
|
|
118
108
|
instance_num=1,
|
|
@@ -14,6 +14,9 @@ from dstack._internal.server.testing.common import (
|
|
|
14
14
|
create_run,
|
|
15
15
|
create_user,
|
|
16
16
|
get_auth_headers,
|
|
17
|
+
get_instance_offer_with_availability,
|
|
18
|
+
get_job_provisioning_data,
|
|
19
|
+
get_job_runtime_data,
|
|
17
20
|
)
|
|
18
21
|
|
|
19
22
|
pytestmark = pytest.mark.usefixtures("image_config_mock")
|
|
@@ -51,15 +54,38 @@ class TestGetJobMetrics:
|
|
|
51
54
|
repo=repo,
|
|
52
55
|
user=user,
|
|
53
56
|
)
|
|
57
|
+
jpd = get_job_provisioning_data(
|
|
58
|
+
cpu_count=128, memory_gib=256, gpu_count=2, gpu_memory_gib=32
|
|
59
|
+
)
|
|
60
|
+
offer = get_instance_offer_with_availability(
|
|
61
|
+
cpu_count=64, memory_gib=128, gpu_count=1, gpu_memory_gib=32
|
|
62
|
+
)
|
|
63
|
+
jrd = get_job_runtime_data(offer=offer)
|
|
54
64
|
job = await create_job(
|
|
55
65
|
session=session,
|
|
56
66
|
run=run,
|
|
67
|
+
job_provisioning_data=jpd,
|
|
68
|
+
job_runtime_data=jrd,
|
|
69
|
+
)
|
|
70
|
+
await create_job_metrics_point(
|
|
71
|
+
session=session,
|
|
72
|
+
job_model=job,
|
|
73
|
+
timestamp=datetime(2023, 1, 2, 3, 4, 5, tzinfo=timezone.utc),
|
|
74
|
+
cpu_usage_micro=2 * 1_000_000,
|
|
75
|
+
memory_usage_bytes=256,
|
|
76
|
+
memory_working_set_bytes=128,
|
|
77
|
+
gpus_memory_usage_bytes=[256],
|
|
78
|
+
gpus_util_percent=[2],
|
|
57
79
|
)
|
|
58
80
|
await create_job_metrics_point(
|
|
59
81
|
session=session,
|
|
60
82
|
job_model=job,
|
|
61
83
|
timestamp=datetime(2023, 1, 2, 3, 4, 15, tzinfo=timezone.utc),
|
|
62
84
|
cpu_usage_micro=4 * 1_000_000,
|
|
85
|
+
memory_usage_bytes=512,
|
|
86
|
+
memory_working_set_bytes=256,
|
|
87
|
+
gpus_memory_usage_bytes=[512],
|
|
88
|
+
gpus_util_percent=[6],
|
|
63
89
|
)
|
|
64
90
|
await create_job_metrics_point(
|
|
65
91
|
session=session,
|
|
@@ -76,6 +102,7 @@ class TestGetJobMetrics:
|
|
|
76
102
|
headers=get_auth_headers(user.token),
|
|
77
103
|
)
|
|
78
104
|
assert response.status_code == 200
|
|
105
|
+
# Returns one last sample by default. Filtering is tested in services/test_metrics.py
|
|
79
106
|
assert response.json() == {
|
|
80
107
|
"metrics": [
|
|
81
108
|
{
|
|
@@ -93,11 +120,26 @@ class TestGetJobMetrics:
|
|
|
93
120
|
"timestamps": ["2023-01-02T03:04:25+00:00"],
|
|
94
121
|
"values": [512],
|
|
95
122
|
},
|
|
123
|
+
{
|
|
124
|
+
"name": "cpus_detected_num",
|
|
125
|
+
"timestamps": ["2023-01-02T03:04:25+00:00"],
|
|
126
|
+
"values": [64],
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
"name": "memory_total_bytes",
|
|
130
|
+
"timestamps": ["2023-01-02T03:04:25+00:00"],
|
|
131
|
+
"values": [137438953472],
|
|
132
|
+
},
|
|
96
133
|
{
|
|
97
134
|
"name": "gpus_detected_num",
|
|
98
135
|
"timestamps": ["2023-01-02T03:04:25+00:00"],
|
|
99
136
|
"values": [1],
|
|
100
137
|
},
|
|
138
|
+
{
|
|
139
|
+
"name": "gpu_memory_total_bytes",
|
|
140
|
+
"timestamps": ["2023-01-02T03:04:25+00:00"],
|
|
141
|
+
"values": [34359738368],
|
|
142
|
+
},
|
|
101
143
|
{
|
|
102
144
|
"name": "gpu_memory_usage_bytes_gpu0",
|
|
103
145
|
"timestamps": ["2023-01-02T03:04:25+00:00"],
|
|
@@ -503,6 +503,62 @@ class TestSetProjectMembers:
|
|
|
503
503
|
members = res.scalars().all()
|
|
504
504
|
assert len(members) == 3
|
|
505
505
|
|
|
506
|
+
@pytest.mark.asyncio
|
|
507
|
+
@pytest.mark.parametrize("test_db", ["sqlite", "postgres"], indirect=True)
|
|
508
|
+
async def test_sets_project_members_by_email(
|
|
509
|
+
self, test_db, session: AsyncSession, client: AsyncClient
|
|
510
|
+
):
|
|
511
|
+
project = await create_project(
|
|
512
|
+
session=session,
|
|
513
|
+
created_at=datetime(2023, 1, 2, 3, 4, tzinfo=timezone.utc),
|
|
514
|
+
)
|
|
515
|
+
admin = await create_user(
|
|
516
|
+
session=session,
|
|
517
|
+
created_at=datetime(2023, 1, 2, 3, 4, tzinfo=timezone.utc),
|
|
518
|
+
global_role=GlobalRole.ADMIN,
|
|
519
|
+
)
|
|
520
|
+
user1 = await create_user(
|
|
521
|
+
session=session,
|
|
522
|
+
name="user1",
|
|
523
|
+
created_at=datetime(2023, 1, 2, 3, 4, tzinfo=timezone.utc),
|
|
524
|
+
email="testemail@example.com",
|
|
525
|
+
)
|
|
526
|
+
members = [
|
|
527
|
+
{
|
|
528
|
+
"username": user1.email,
|
|
529
|
+
"project_role": ProjectRole.ADMIN,
|
|
530
|
+
},
|
|
531
|
+
]
|
|
532
|
+
body = {"members": members}
|
|
533
|
+
response = await client.post(
|
|
534
|
+
f"/api/projects/{project.name}/set_members",
|
|
535
|
+
headers=get_auth_headers(admin.token),
|
|
536
|
+
json=body,
|
|
537
|
+
)
|
|
538
|
+
assert response.status_code == 200, response.json()
|
|
539
|
+
assert response.json()["members"] == [
|
|
540
|
+
{
|
|
541
|
+
"user": {
|
|
542
|
+
"id": str(user1.id),
|
|
543
|
+
"username": user1.name,
|
|
544
|
+
"created_at": "2023-01-02T03:04:00+00:00",
|
|
545
|
+
"global_role": user1.global_role,
|
|
546
|
+
"email": user1.email,
|
|
547
|
+
"active": True,
|
|
548
|
+
"permissions": {
|
|
549
|
+
"can_create_projects": True,
|
|
550
|
+
},
|
|
551
|
+
},
|
|
552
|
+
"project_role": ProjectRole.ADMIN,
|
|
553
|
+
"permissions": {
|
|
554
|
+
"can_manage_ssh_fleets": True,
|
|
555
|
+
},
|
|
556
|
+
},
|
|
557
|
+
]
|
|
558
|
+
res = await session.execute(select(MemberModel))
|
|
559
|
+
members = res.scalars().all()
|
|
560
|
+
assert len(members) == 1
|
|
561
|
+
|
|
506
562
|
@pytest.mark.asyncio
|
|
507
563
|
@pytest.mark.parametrize("test_db", ["sqlite", "postgres"], indirect=True)
|
|
508
564
|
async def test_manager_cannot_set_project_admins(
|