anyscale 0.26.29__py3-none-any.whl → 0.26.30__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.
- anyscale/__init__.py +10 -0
- anyscale/_private/anyscale_client/anyscale_client.py +69 -0
- anyscale/_private/anyscale_client/common.py +38 -0
- anyscale/_private/anyscale_client/fake_anyscale_client.py +11 -0
- anyscale/_private/docgen/__main__.py +4 -0
- anyscale/commands/command_examples.py +10 -0
- anyscale/commands/job_queue_commands.py +295 -104
- anyscale/commands/list_util.py +14 -1
- anyscale/commands/machine_pool_commands.py +14 -2
- anyscale/commands/service_commands.py +6 -12
- anyscale/commands/workspace_commands_v2.py +462 -25
- anyscale/controllers/job_controller.py +5 -210
- anyscale/job_queue/__init__.py +89 -0
- anyscale/job_queue/_private/job_queue_sdk.py +158 -0
- anyscale/job_queue/commands.py +130 -0
- anyscale/job_queue/models.py +284 -0
- anyscale/scripts.py +1 -1
- anyscale/utils/ssh_websocket_proxy.py +178 -0
- anyscale/version.py +1 -1
- {anyscale-0.26.29.dist-info → anyscale-0.26.30.dist-info}/METADATA +3 -1
- {anyscale-0.26.29.dist-info → anyscale-0.26.30.dist-info}/RECORD +26 -21
- {anyscale-0.26.29.dist-info → anyscale-0.26.30.dist-info}/LICENSE +0 -0
- {anyscale-0.26.29.dist-info → anyscale-0.26.30.dist-info}/NOTICE +0 -0
- {anyscale-0.26.29.dist-info → anyscale-0.26.30.dist-info}/WHEEL +0 -0
- {anyscale-0.26.29.dist-info → anyscale-0.26.30.dist-info}/entry_points.txt +0 -0
- {anyscale-0.26.29.dist-info → anyscale-0.26.30.dist-info}/top_level.txt +0 -0
anyscale/__init__.py
CHANGED
@@ -25,6 +25,7 @@ from anyscale import (
|
|
25
25
|
image,
|
26
26
|
integrations,
|
27
27
|
job,
|
28
|
+
job_queue,
|
28
29
|
llm,
|
29
30
|
organization_invitation,
|
30
31
|
project,
|
@@ -46,6 +47,7 @@ from anyscale.compute_config import ComputeConfigSDK
|
|
46
47
|
from anyscale.connect import ClientBuilder
|
47
48
|
from anyscale.image import ImageSDK
|
48
49
|
from anyscale.job import JobSDK
|
50
|
+
from anyscale.job_queue import JobQueueSDK
|
49
51
|
from anyscale.llm import LLMSDK
|
50
52
|
from anyscale.organization_invitation import OrganizationInvitationSDK
|
51
53
|
from anyscale.project import ProjectSDK
|
@@ -119,6 +121,7 @@ class Anyscale:
|
|
119
121
|
client=self._anyscale_client
|
120
122
|
)
|
121
123
|
self._job_sdk = JobSDK(client=self._anyscale_client)
|
124
|
+
self._job_queue_sdk = JobQueueSDK(client=self._anyscale_client)
|
122
125
|
self._service_sdk = ServiceSDK(client=self._anyscale_client)
|
123
126
|
self._compute_config_sdk = ComputeConfigSDK(client=self._anyscale_client)
|
124
127
|
self._cloud_sdk = CloudSDK(client=self._anyscale_client)
|
@@ -146,6 +149,9 @@ class Anyscale:
|
|
146
149
|
client=client, logger=logger, timer=timer
|
147
150
|
)
|
148
151
|
obj._job_sdk = JobSDK(client=client, logger=logger, timer=timer) # noqa: SLF001
|
152
|
+
obj._job_queue_sdk = JobQueueSDK( # noqa: SLF001
|
153
|
+
client=client, logger=logger, timer=timer
|
154
|
+
)
|
149
155
|
obj._service_sdk = ServiceSDK( # noqa: SLF001
|
150
156
|
client=client, logger=logger, timer=timer
|
151
157
|
)
|
@@ -187,6 +193,10 @@ class Anyscale:
|
|
187
193
|
def job(self) -> JobSDK: # noqa: F811
|
188
194
|
return self._job_sdk
|
189
195
|
|
196
|
+
@property
|
197
|
+
def job_queue(self) -> JobQueueSDK: # noqa: F811
|
198
|
+
return self._job_queue_sdk
|
199
|
+
|
190
200
|
@property
|
191
201
|
def service(self) -> ServiceSDK: # noqa: F811
|
192
202
|
return self._service_sdk
|
@@ -60,6 +60,7 @@ from anyscale.client.openapi_client.models import (
|
|
60
60
|
Dataset as InternalDataset,
|
61
61
|
DatasetUpload,
|
62
62
|
DecoratedComputeTemplate,
|
63
|
+
DecoratedjobqueueListResponse,
|
63
64
|
DecoratedlistserviceapimodelListResponse,
|
64
65
|
DecoratedProductionServiceV2APIModel,
|
65
66
|
DecoratedSession,
|
@@ -68,6 +69,8 @@ from anyscale.client.openapi_client.models import (
|
|
68
69
|
FineTunedModel,
|
69
70
|
FinetunedmodelListResponse,
|
70
71
|
InternalProductionJob,
|
72
|
+
JobQueueSortDirective,
|
73
|
+
JobQueuesQuery,
|
71
74
|
ListResourceQuotasQuery,
|
72
75
|
OrganizationCollaborator,
|
73
76
|
OrganizationInvitation,
|
@@ -75,13 +78,18 @@ from anyscale.client.openapi_client.models import (
|
|
75
78
|
ResourceQuotaStatus,
|
76
79
|
ServerSessionToken,
|
77
80
|
SessionSshKey,
|
81
|
+
SessionState,
|
78
82
|
StartSessionOptions,
|
79
83
|
StopSessionOptions,
|
80
84
|
WorkspaceDataplaneProxiedArtifacts,
|
81
85
|
)
|
82
86
|
from anyscale.client.openapi_client.models.create_schedule import CreateSchedule
|
87
|
+
from anyscale.client.openapi_client.models.decorated_job_queue import DecoratedJobQueue
|
83
88
|
from anyscale.client.openapi_client.models.decorated_schedule import DecoratedSchedule
|
84
89
|
from anyscale.client.openapi_client.models.production_job import ProductionJob
|
90
|
+
from anyscale.client.openapi_client.models.update_job_queue_request import (
|
91
|
+
UpdateJobQueueRequest,
|
92
|
+
)
|
85
93
|
from anyscale.client.openapi_client.rest import ApiException as InternalApiException
|
86
94
|
from anyscale.cluster_compute import parse_cluster_compute_name_version
|
87
95
|
from anyscale.feature_flags import FLAG_DEFAULT_WORKING_DIR_FOR_PROJ
|
@@ -1154,6 +1162,67 @@ class AnyscaleClient(AnyscaleClientInterface):
|
|
1154
1162
|
)
|
1155
1163
|
return job_runs
|
1156
1164
|
|
1165
|
+
@handle_api_exceptions
|
1166
|
+
def get_job_queue(self, job_queue_id: str) -> Optional[DecoratedJobQueue]:
|
1167
|
+
try:
|
1168
|
+
return self._internal_api_client.get_job_queue_api_v2_job_queues_job_queue_id_get(
|
1169
|
+
job_queue_id
|
1170
|
+
).result
|
1171
|
+
except InternalApiException as e:
|
1172
|
+
if e.status == 404:
|
1173
|
+
return None
|
1174
|
+
|
1175
|
+
raise e from None
|
1176
|
+
|
1177
|
+
@handle_api_exceptions
|
1178
|
+
def update_job_queue(
|
1179
|
+
self,
|
1180
|
+
job_queue_id: str,
|
1181
|
+
max_concurrency: Optional[int] = None,
|
1182
|
+
idle_timeout_s: Optional[int] = None,
|
1183
|
+
) -> DecoratedJobQueue:
|
1184
|
+
if max_concurrency is None and idle_timeout_s is None:
|
1185
|
+
raise ValueError("No fields to update")
|
1186
|
+
|
1187
|
+
return self._internal_api_client.update_job_queue_api_v2_job_queues_job_queue_id_put(
|
1188
|
+
job_queue_id,
|
1189
|
+
update_job_queue_request=UpdateJobQueueRequest(
|
1190
|
+
max_concurrency=max_concurrency, idle_timeout_sec=idle_timeout_s,
|
1191
|
+
),
|
1192
|
+
).result
|
1193
|
+
|
1194
|
+
@handle_api_exceptions
|
1195
|
+
def list_job_queues(
|
1196
|
+
self,
|
1197
|
+
*,
|
1198
|
+
name: Optional[str] = None,
|
1199
|
+
creator_id: Optional[str] = None,
|
1200
|
+
cluster_status: Optional[SessionState] = None,
|
1201
|
+
project: Optional[str] = None,
|
1202
|
+
cloud: Optional[str] = None,
|
1203
|
+
count: Optional[int] = None,
|
1204
|
+
paging_token: Optional[str] = None,
|
1205
|
+
sorting_directives: Optional[List[JobQueueSortDirective]] = None,
|
1206
|
+
) -> DecoratedjobqueueListResponse:
|
1207
|
+
cloud_id = self.get_cloud_id(cloud_name=cloud) if cloud else None
|
1208
|
+
project_id = (
|
1209
|
+
self.get_project_id(parent_cloud_id=cloud_id, name=project)
|
1210
|
+
if project
|
1211
|
+
else None
|
1212
|
+
)
|
1213
|
+
|
1214
|
+
return self._internal_api_client.list_job_queues_api_v2_job_queues_post(
|
1215
|
+
job_queues_query=JobQueuesQuery(
|
1216
|
+
name=name,
|
1217
|
+
creator_id=creator_id,
|
1218
|
+
cluster_status=cluster_status,
|
1219
|
+
project_id=project_id,
|
1220
|
+
cloud_id=cloud_id,
|
1221
|
+
paging=PageQuery(count=count, paging_token=paging_token),
|
1222
|
+
sorting_directives=sorting_directives,
|
1223
|
+
),
|
1224
|
+
)
|
1225
|
+
|
1157
1226
|
@handle_api_exceptions
|
1158
1227
|
def rollout_service(
|
1159
1228
|
self, model: ApplyProductionServiceV2Model
|
@@ -15,19 +15,23 @@ from anyscale.client.openapi_client.models import (
|
|
15
15
|
CreateResourceQuota,
|
16
16
|
CreateUserProjectCollaborator,
|
17
17
|
DecoratedComputeTemplate,
|
18
|
+
DecoratedjobqueueListResponse,
|
18
19
|
DecoratedlistserviceapimodelListResponse,
|
19
20
|
DecoratedProductionServiceV2APIModel,
|
20
21
|
DeletedPlatformFineTunedModel,
|
21
22
|
FineTunedModel,
|
22
23
|
InternalProductionJob,
|
24
|
+
JobQueueSortDirective,
|
23
25
|
OrganizationCollaborator,
|
24
26
|
OrganizationInvitation,
|
25
27
|
Project,
|
26
28
|
ResourceQuota,
|
27
29
|
ServerSessionToken,
|
30
|
+
SessionState,
|
28
31
|
WorkspaceDataplaneProxiedArtifacts,
|
29
32
|
)
|
30
33
|
from anyscale.client.openapi_client.models.create_schedule import CreateSchedule
|
34
|
+
from anyscale.client.openapi_client.models.decorated_job_queue import DecoratedJobQueue
|
31
35
|
from anyscale.client.openapi_client.models.decorated_schedule import DecoratedSchedule
|
32
36
|
from anyscale.client.openapi_client.models.decorated_session import DecoratedSession
|
33
37
|
from anyscale.client.openapi_client.models.production_job import ProductionJob
|
@@ -366,6 +370,24 @@ class AnyscaleClientInterface(ABC):
|
|
366
370
|
"""
|
367
371
|
raise NotImplementedError
|
368
372
|
|
373
|
+
@abstractmethod
|
374
|
+
def get_job_queue(self, job_queue_id: str) -> Optional[DecoratedJobQueue]:
|
375
|
+
"""Get a job queue by id.
|
376
|
+
|
377
|
+
Returns None if not found.
|
378
|
+
"""
|
379
|
+
raise NotImplementedError
|
380
|
+
|
381
|
+
@abstractmethod
|
382
|
+
def update_job_queue(
|
383
|
+
self,
|
384
|
+
job_queue_id: str,
|
385
|
+
max_concurrency: Optional[int] = None,
|
386
|
+
idle_timeout_s: Optional[int] = None,
|
387
|
+
) -> DecoratedJobQueue:
|
388
|
+
"""Update a job queue."""
|
389
|
+
raise NotImplementedError
|
390
|
+
|
369
391
|
@abstractmethod
|
370
392
|
def get_job_runs(self, job_id: str) -> List[APIJobRun]:
|
371
393
|
"""Returns all job runs for a given job id.
|
@@ -374,6 +396,22 @@ class AnyscaleClientInterface(ABC):
|
|
374
396
|
"""
|
375
397
|
raise NotImplementedError
|
376
398
|
|
399
|
+
@abstractmethod
|
400
|
+
def list_job_queues(
|
401
|
+
self,
|
402
|
+
*,
|
403
|
+
name: Optional[str] = None,
|
404
|
+
creator_id: Optional[str] = None,
|
405
|
+
cluster_status: Optional[SessionState] = None,
|
406
|
+
project: Optional[str] = None,
|
407
|
+
cloud: Optional[str] = None,
|
408
|
+
count: Optional[int] = None,
|
409
|
+
paging_token: Optional[str] = None,
|
410
|
+
sorting_directives: Optional[List[JobQueueSortDirective]] = None,
|
411
|
+
) -> DecoratedjobqueueListResponse:
|
412
|
+
"""List job queues."""
|
413
|
+
raise NotImplementedError
|
414
|
+
|
377
415
|
@abstractmethod
|
378
416
|
def rollout_service(
|
379
417
|
self, model: ApplyProductionServiceV2Model
|
@@ -49,6 +49,7 @@ from anyscale.client.openapi_client.models import (
|
|
49
49
|
WorkspaceDataplaneProxiedArtifacts,
|
50
50
|
)
|
51
51
|
from anyscale.client.openapi_client.models.create_schedule import CreateSchedule
|
52
|
+
from anyscale.client.openapi_client.models.decorated_job_queue import DecoratedJobQueue
|
52
53
|
from anyscale.client.openapi_client.models.decorated_schedule import DecoratedSchedule
|
53
54
|
from anyscale.client.openapi_client.models.decorated_session import DecoratedSession
|
54
55
|
from anyscale.client.openapi_client.models.session_ssh_key import SessionSshKey
|
@@ -150,6 +151,7 @@ class FakeAnyscaleClient(AnyscaleClientInterface):
|
|
150
151
|
self._deleted_services: Dict[str, DecoratedProductionServiceV2APIModel] = {}
|
151
152
|
self._jobs: Dict[str, ProductionJob] = {}
|
152
153
|
self._job_runs: Dict[str, List[APIJobRun]] = defaultdict(list)
|
154
|
+
self._job_queues: Dict[str, DecoratedJobQueue] = {}
|
153
155
|
self._project_to_id: Dict[Optional[str] : Dict[Optional[str], str]] = {}
|
154
156
|
self._project_collaborators: Dict[str, List[CreateUserProjectCollaborator]] = {}
|
155
157
|
self._rolled_out_model: Optional[ApplyProductionServiceV2Model] = None
|
@@ -702,6 +704,15 @@ class FakeAnyscaleClient(AnyscaleClientInterface):
|
|
702
704
|
def update_job_run(self, prod_job_id: str, model: APIJobRun):
|
703
705
|
self._job_runs[prod_job_id].append(model)
|
704
706
|
|
707
|
+
def list_job_queues(self) -> List[DecoratedJobQueue]:
|
708
|
+
return list(self._job_queues.values())
|
709
|
+
|
710
|
+
def get_job_queue(self, job_queue_id: str) -> Optional[DecoratedJobQueue]:
|
711
|
+
return self._job_queues.get(job_queue_id, None)
|
712
|
+
|
713
|
+
def update_job_queue(self, model: DecoratedJobQueue):
|
714
|
+
self._job_queues[model.id] = model
|
715
|
+
|
705
716
|
def register_project_by_name(
|
706
717
|
self,
|
707
718
|
name: str,
|
@@ -527,8 +527,12 @@ ALL_MODULES = [
|
|
527
527
|
cli_prefix="anyscale machine-pool",
|
528
528
|
cli_commands=[
|
529
529
|
machine_pool_commands.create_machine_pool,
|
530
|
+
machine_pool_commands.update_machine_pool,
|
530
531
|
machine_pool_commands.delete_machine_pool,
|
532
|
+
machine_pool_commands.attach_machine_pool_to_cloud,
|
533
|
+
machine_pool_commands.detach_machine_pool_from_cloud,
|
531
534
|
machine_pool_commands.list_machine_pools,
|
535
|
+
machine_pool_commands.describe,
|
532
536
|
],
|
533
537
|
sdk_prefix="anyscale.machine_pool",
|
534
538
|
sdk_commands=[],
|
@@ -312,6 +312,16 @@ MACHINE POOL ID Clouds
|
|
312
312
|
can-testing mp_8ogdz85mdwxb8a92yo44nn84ox
|
313
313
|
"""
|
314
314
|
|
315
|
+
MACHINE_POOL_ATTACH_EXAMPLE = """\
|
316
|
+
$ anyscale machine-pool attach --name can-testing --cloud my-cloud
|
317
|
+
Attached machine pool 'can-testing' to cloud 'my-cloud'.
|
318
|
+
"""
|
319
|
+
|
320
|
+
MACHINE_POOL_DETACH_EXAMPLE = """\
|
321
|
+
$ anyscale machine-pool detach --name can-testing --cloud my-cloud
|
322
|
+
Detached machine pool 'can-testing' from cloud 'my-cloud'.
|
323
|
+
"""
|
324
|
+
|
315
325
|
LLM_MODELS_GET_EXAMPLE = """
|
316
326
|
$ anyscale llm model get --model-id my-model-id
|
317
327
|
Output
|