skypilot-nightly 1.0.0.dev20250915__py3-none-any.whl → 1.0.0.dev20250918__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 skypilot-nightly might be problematic. Click here for more details.
- sky/__init__.py +4 -2
- sky/adaptors/primeintellect.py +1 -0
- sky/adaptors/seeweb.py +68 -4
- sky/authentication.py +25 -0
- sky/backends/__init__.py +3 -2
- sky/backends/backend_utils.py +16 -12
- sky/backends/cloud_vm_ray_backend.py +61 -4
- sky/catalog/primeintellect_catalog.py +95 -0
- sky/client/sdk.py +6 -0
- sky/clouds/__init__.py +2 -0
- sky/clouds/primeintellect.py +314 -0
- sky/core.py +10 -3
- sky/dashboard/out/404.html +1 -1
- sky/dashboard/out/_next/static/chunks/3015-ba5be550eb80fd8c.js +1 -0
- sky/dashboard/out/_next/static/chunks/5339.4a881570243431a5.js +51 -0
- sky/dashboard/out/_next/static/chunks/{6856-e0754534b3015377.js → 6856-9a2538f38c004652.js} +1 -1
- sky/dashboard/out/_next/static/chunks/{6990-11c8e9b982e8ffec.js → 6990-f6818c84ed8f1c86.js} +1 -1
- sky/dashboard/out/_next/static/chunks/8969-a3e3f0683e19d340.js +1 -0
- sky/dashboard/out/_next/static/chunks/9037-472ee1222cb1e158.js +6 -0
- sky/dashboard/out/_next/static/chunks/{webpack-d1e29b3aa66bf4cf.js → webpack-487697b47d8c5e50.js} +1 -1
- sky/dashboard/out/_next/static/{dG6B0i0HO4jIoKb4ZFYJ_ → k1mo5xWZrV9djgjd0moOT}/_buildManifest.js +1 -1
- sky/dashboard/out/clusters/[cluster]/[job].html +1 -1
- sky/dashboard/out/clusters/[cluster].html +1 -1
- sky/dashboard/out/clusters.html +1 -1
- sky/dashboard/out/config.html +1 -1
- sky/dashboard/out/index.html +1 -1
- sky/dashboard/out/infra/[context].html +1 -1
- sky/dashboard/out/infra.html +1 -1
- sky/dashboard/out/jobs/[job].html +1 -1
- sky/dashboard/out/jobs/pools/[pool].html +1 -1
- sky/dashboard/out/jobs.html +1 -1
- sky/dashboard/out/users.html +1 -1
- sky/dashboard/out/volumes.html +1 -1
- sky/dashboard/out/workspace/new.html +1 -1
- sky/dashboard/out/workspaces/[name].html +1 -1
- sky/dashboard/out/workspaces.html +1 -1
- sky/global_user_state.py +42 -34
- sky/jobs/server/server.py +14 -1
- sky/jobs/state.py +26 -1
- sky/provision/__init__.py +1 -0
- sky/provision/docker_utils.py +50 -3
- sky/provision/instance_setup.py +15 -1
- sky/provision/lambda_cloud/instance.py +12 -11
- sky/provision/primeintellect/__init__.py +10 -0
- sky/provision/primeintellect/config.py +11 -0
- sky/provision/primeintellect/instance.py +454 -0
- sky/provision/primeintellect/utils.py +398 -0
- sky/resources.py +9 -1
- sky/schemas/generated/servev1_pb2.py +58 -0
- sky/schemas/generated/servev1_pb2.pyi +115 -0
- sky/schemas/generated/servev1_pb2_grpc.py +322 -0
- sky/serve/serve_rpc_utils.py +179 -0
- sky/serve/serve_utils.py +29 -12
- sky/serve/server/core.py +37 -19
- sky/serve/server/impl.py +221 -129
- sky/server/common.py +13 -0
- sky/server/constants.py +3 -0
- sky/server/requests/executor.py +23 -6
- sky/server/server.py +10 -5
- sky/setup_files/dependencies.py +1 -0
- sky/skylet/constants.py +5 -3
- sky/skylet/services.py +98 -0
- sky/skylet/skylet.py +3 -1
- sky/skypilot_config.py +10 -3
- sky/templates/kubernetes-ray.yml.j2 +22 -12
- sky/templates/primeintellect-ray.yml.j2 +71 -0
- {skypilot_nightly-1.0.0.dev20250915.dist-info → skypilot_nightly-1.0.0.dev20250918.dist-info}/METADATA +39 -38
- {skypilot_nightly-1.0.0.dev20250915.dist-info → skypilot_nightly-1.0.0.dev20250918.dist-info}/RECORD +74 -62
- sky/dashboard/out/_next/static/chunks/3015-2ea98b57e318bd6e.js +0 -1
- sky/dashboard/out/_next/static/chunks/5339.c033b29835da0f35.js +0 -51
- sky/dashboard/out/_next/static/chunks/8969-0487dfbf149d9e53.js +0 -1
- sky/dashboard/out/_next/static/chunks/9037-f9800e64eb05dd1c.js +0 -6
- /sky/dashboard/out/_next/static/chunks/pages/{workspaces-7598c33a746cdc91.js → workspaces-7528cc0ef8c522c5.js} +0 -0
- /sky/dashboard/out/_next/static/{dG6B0i0HO4jIoKb4ZFYJ_ → k1mo5xWZrV9djgjd0moOT}/_ssgManifest.js +0 -0
- {skypilot_nightly-1.0.0.dev20250915.dist-info → skypilot_nightly-1.0.0.dev20250918.dist-info}/WHEEL +0 -0
- {skypilot_nightly-1.0.0.dev20250915.dist-info → skypilot_nightly-1.0.0.dev20250918.dist-info}/entry_points.txt +0 -0
- {skypilot_nightly-1.0.0.dev20250915.dist-info → skypilot_nightly-1.0.0.dev20250918.dist-info}/licenses/LICENSE +0 -0
- {skypilot_nightly-1.0.0.dev20250915.dist-info → skypilot_nightly-1.0.0.dev20250918.dist-info}/top_level.txt +0 -0
sky/serve/server/impl.py
CHANGED
|
@@ -5,6 +5,7 @@ import shlex
|
|
|
5
5
|
import signal
|
|
6
6
|
import tempfile
|
|
7
7
|
import threading
|
|
8
|
+
import typing
|
|
8
9
|
from typing import Any, Dict, List, Optional, Set, Tuple, Union
|
|
9
10
|
import uuid
|
|
10
11
|
|
|
@@ -17,10 +18,12 @@ from sky import execution
|
|
|
17
18
|
from sky import sky_logging
|
|
18
19
|
from sky import skypilot_config
|
|
19
20
|
from sky import task as task_lib
|
|
21
|
+
from sky.adaptors import common as adaptors_common
|
|
20
22
|
from sky.backends import backend_utils
|
|
21
23
|
from sky.catalog import common as service_catalog_common
|
|
22
24
|
from sky.data import storage as storage_lib
|
|
23
25
|
from sky.serve import constants as serve_constants
|
|
26
|
+
from sky.serve import serve_rpc_utils
|
|
24
27
|
from sky.serve import serve_state
|
|
25
28
|
from sky.serve import serve_utils
|
|
26
29
|
from sky.skylet import constants
|
|
@@ -36,6 +39,11 @@ from sky.utils import subprocess_utils
|
|
|
36
39
|
from sky.utils import ux_utils
|
|
37
40
|
from sky.utils import yaml_utils
|
|
38
41
|
|
|
42
|
+
if typing.TYPE_CHECKING:
|
|
43
|
+
import grpc
|
|
44
|
+
else:
|
|
45
|
+
grpc = adaptors_common.LazyImport('grpc')
|
|
46
|
+
|
|
39
47
|
logger = sky_logging.init_logger(__name__)
|
|
40
48
|
|
|
41
49
|
|
|
@@ -78,24 +86,35 @@ def _get_service_record(
|
|
|
78
86
|
"""Get the service record."""
|
|
79
87
|
noun = 'pool' if pool else 'service'
|
|
80
88
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
returncode, serve_status_payload, stderr = backend.run_on_head(
|
|
84
|
-
handle,
|
|
85
|
-
code,
|
|
86
|
-
require_outputs=True,
|
|
87
|
-
stream_logs=False,
|
|
88
|
-
separate_stderr=True)
|
|
89
|
-
try:
|
|
90
|
-
subprocess_utils.handle_returncode(returncode,
|
|
91
|
-
code,
|
|
92
|
-
f'Failed to get {noun} status',
|
|
93
|
-
stderr,
|
|
94
|
-
stream_logs=True)
|
|
95
|
-
except exceptions.CommandError as e:
|
|
96
|
-
raise RuntimeError(e.error_msg) from e
|
|
89
|
+
assert isinstance(handle, backends.CloudVmRayResourceHandle)
|
|
90
|
+
use_legacy = not handle.is_grpc_enabled_with_flag
|
|
97
91
|
|
|
98
|
-
|
|
92
|
+
if handle.is_grpc_enabled_with_flag:
|
|
93
|
+
try:
|
|
94
|
+
service_statuses = serve_rpc_utils.RpcRunner.get_service_status(
|
|
95
|
+
handle, [service_name], pool)
|
|
96
|
+
except exceptions.SkyletMethodNotImplementedError:
|
|
97
|
+
use_legacy = True
|
|
98
|
+
|
|
99
|
+
if use_legacy:
|
|
100
|
+
code = serve_utils.ServeCodeGen.get_service_status([service_name],
|
|
101
|
+
pool=pool)
|
|
102
|
+
returncode, serve_status_payload, stderr = backend.run_on_head(
|
|
103
|
+
handle,
|
|
104
|
+
code,
|
|
105
|
+
require_outputs=True,
|
|
106
|
+
stream_logs=False,
|
|
107
|
+
separate_stderr=True)
|
|
108
|
+
try:
|
|
109
|
+
subprocess_utils.handle_returncode(returncode,
|
|
110
|
+
code,
|
|
111
|
+
f'Failed to get {noun} status',
|
|
112
|
+
stderr,
|
|
113
|
+
stream_logs=True)
|
|
114
|
+
except exceptions.CommandError as e:
|
|
115
|
+
raise RuntimeError(e.error_msg) from e
|
|
116
|
+
|
|
117
|
+
service_statuses = serve_utils.load_service_status(serve_status_payload)
|
|
99
118
|
|
|
100
119
|
assert len(service_statuses) <= 1, service_statuses
|
|
101
120
|
if not service_statuses:
|
|
@@ -287,30 +306,44 @@ def up(
|
|
|
287
306
|
fore = colorama.Fore
|
|
288
307
|
|
|
289
308
|
assert controller_job_id is not None and controller_handle is not None
|
|
309
|
+
assert isinstance(controller_handle, backends.CloudVmRayResourceHandle)
|
|
310
|
+
backend = backend_utils.get_backend_from_handle(controller_handle)
|
|
311
|
+
assert isinstance(backend, backends.CloudVmRayBackend)
|
|
290
312
|
# TODO(tian): Cache endpoint locally to speedup. Endpoint won't
|
|
291
313
|
# change after the first time, so there is no consistency issue.
|
|
292
|
-
with rich_utils.safe_status(
|
|
293
|
-
ux_utils.spinner_message(
|
|
294
|
-
f'Waiting for the {noun} to register')):
|
|
295
|
-
# This function will check the controller job id in the database
|
|
296
|
-
# and return the endpoint if the job id matches. Otherwise it will
|
|
297
|
-
# return None.
|
|
298
|
-
code = serve_utils.ServeCodeGen.wait_service_registration(
|
|
299
|
-
service_name, controller_job_id, pool)
|
|
300
|
-
backend = backend_utils.get_backend_from_handle(controller_handle)
|
|
301
|
-
assert isinstance(backend, backends.CloudVmRayBackend)
|
|
302
|
-
assert isinstance(controller_handle,
|
|
303
|
-
backends.CloudVmRayResourceHandle)
|
|
304
|
-
returncode, lb_port_payload, _ = backend.run_on_head(
|
|
305
|
-
controller_handle,
|
|
306
|
-
code,
|
|
307
|
-
require_outputs=True,
|
|
308
|
-
stream_logs=False)
|
|
309
314
|
try:
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
315
|
+
with rich_utils.safe_status(
|
|
316
|
+
ux_utils.spinner_message(
|
|
317
|
+
f'Waiting for the {noun} to register')):
|
|
318
|
+
# This function will check the controller job id in the database
|
|
319
|
+
# and return the endpoint if the job id matches. Otherwise it
|
|
320
|
+
# will return None.
|
|
321
|
+
use_legacy = not controller_handle.is_grpc_enabled_with_flag
|
|
322
|
+
|
|
323
|
+
if controller_handle.is_grpc_enabled_with_flag:
|
|
324
|
+
try:
|
|
325
|
+
lb_port = serve_rpc_utils.RpcRunner.wait_service_registration( # pylint: disable=line-too-long
|
|
326
|
+
controller_handle, service_name, controller_job_id,
|
|
327
|
+
pool)
|
|
328
|
+
except exceptions.SkyletMethodNotImplementedError:
|
|
329
|
+
use_legacy = True
|
|
330
|
+
|
|
331
|
+
if use_legacy:
|
|
332
|
+
code = serve_utils.ServeCodeGen.wait_service_registration(
|
|
333
|
+
service_name, controller_job_id, pool)
|
|
334
|
+
returncode, lb_port_payload, _ = backend.run_on_head(
|
|
335
|
+
controller_handle,
|
|
336
|
+
code,
|
|
337
|
+
require_outputs=True,
|
|
338
|
+
stream_logs=False)
|
|
339
|
+
subprocess_utils.handle_returncode(
|
|
340
|
+
returncode, code,
|
|
341
|
+
f'Failed to wait for {noun} initialization',
|
|
342
|
+
lb_port_payload)
|
|
343
|
+
lb_port = serve_utils.load_service_initialization_result(
|
|
344
|
+
lb_port_payload)
|
|
345
|
+
except (exceptions.CommandError, grpc.FutureTimeoutError,
|
|
346
|
+
grpc.RpcError):
|
|
314
347
|
if serve_utils.is_consolidation_mode(pool):
|
|
315
348
|
with ux_utils.print_exception_no_traceback():
|
|
316
349
|
raise RuntimeError(
|
|
@@ -344,8 +377,6 @@ def up(
|
|
|
344
377
|
'Failed to spin up the service. Please '
|
|
345
378
|
'check the logs above for more details.') from None
|
|
346
379
|
else:
|
|
347
|
-
lb_port = serve_utils.load_service_initialization_result(
|
|
348
|
-
lb_port_payload)
|
|
349
380
|
if not serve_utils.is_consolidation_mode(pool) and not pool:
|
|
350
381
|
socket_endpoint = backend_utils.get_endpoints(
|
|
351
382
|
controller_handle.cluster_name,
|
|
@@ -461,6 +492,7 @@ def update(
|
|
|
461
492
|
f'use {ux_utils.BOLD}sky serve up{ux_utils.RESET_BOLD}',
|
|
462
493
|
)
|
|
463
494
|
|
|
495
|
+
assert isinstance(handle, backends.CloudVmRayResourceHandle)
|
|
464
496
|
backend = backend_utils.get_backend_from_handle(handle)
|
|
465
497
|
assert isinstance(backend, backends.CloudVmRayBackend)
|
|
466
498
|
|
|
@@ -503,29 +535,39 @@ def update(
|
|
|
503
535
|
controller_utils.maybe_translate_local_file_mounts_and_sync_up(
|
|
504
536
|
task, task_type='serve')
|
|
505
537
|
|
|
506
|
-
|
|
507
|
-
returncode, version_string_payload, stderr = backend.run_on_head(
|
|
508
|
-
handle,
|
|
509
|
-
code,
|
|
510
|
-
require_outputs=True,
|
|
511
|
-
stream_logs=False,
|
|
512
|
-
separate_stderr=True)
|
|
513
|
-
try:
|
|
514
|
-
subprocess_utils.handle_returncode(returncode,
|
|
515
|
-
code,
|
|
516
|
-
'Failed to add version',
|
|
517
|
-
stderr,
|
|
518
|
-
stream_logs=True)
|
|
519
|
-
except exceptions.CommandError as e:
|
|
520
|
-
raise RuntimeError(e.error_msg) from e
|
|
538
|
+
use_legacy = not handle.is_grpc_enabled_with_flag
|
|
521
539
|
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
540
|
+
if handle.is_grpc_enabled_with_flag:
|
|
541
|
+
try:
|
|
542
|
+
current_version = serve_rpc_utils.RpcRunner.add_version(
|
|
543
|
+
handle, service_name)
|
|
544
|
+
except exceptions.SkyletMethodNotImplementedError:
|
|
545
|
+
use_legacy = True
|
|
546
|
+
|
|
547
|
+
if use_legacy:
|
|
548
|
+
code = serve_utils.ServeCodeGen.add_version(service_name)
|
|
549
|
+
returncode, version_string_payload, stderr = backend.run_on_head(
|
|
550
|
+
handle,
|
|
551
|
+
code,
|
|
552
|
+
require_outputs=True,
|
|
553
|
+
stream_logs=False,
|
|
554
|
+
separate_stderr=True)
|
|
555
|
+
try:
|
|
556
|
+
subprocess_utils.handle_returncode(returncode,
|
|
557
|
+
code,
|
|
558
|
+
'Failed to add version',
|
|
559
|
+
stderr,
|
|
560
|
+
stream_logs=True)
|
|
561
|
+
except exceptions.CommandError as e:
|
|
562
|
+
raise RuntimeError(e.error_msg) from e
|
|
563
|
+
|
|
564
|
+
version_string = serve_utils.load_version_string(version_string_payload)
|
|
565
|
+
try:
|
|
566
|
+
current_version = int(version_string)
|
|
567
|
+
except ValueError as e:
|
|
568
|
+
with ux_utils.print_exception_no_traceback():
|
|
569
|
+
raise ValueError(f'Failed to parse version: {version_string}; '
|
|
570
|
+
f'Returncode: {returncode}') from e
|
|
529
571
|
|
|
530
572
|
with tempfile.NamedTemporaryFile(
|
|
531
573
|
prefix=f'{service_name}-v{current_version}',
|
|
@@ -540,23 +582,33 @@ def update(
|
|
|
540
582
|
{remote_task_yaml_path: service_file.name},
|
|
541
583
|
storage_mounts=None)
|
|
542
584
|
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
585
|
+
use_legacy = not handle.is_grpc_enabled_with_flag
|
|
586
|
+
|
|
587
|
+
if handle.is_grpc_enabled_with_flag:
|
|
588
|
+
try:
|
|
589
|
+
serve_rpc_utils.RpcRunner.update_service(
|
|
590
|
+
handle, service_name, current_version, mode, pool)
|
|
591
|
+
except exceptions.SkyletMethodNotImplementedError:
|
|
592
|
+
use_legacy = True
|
|
593
|
+
|
|
594
|
+
if use_legacy:
|
|
595
|
+
code = serve_utils.ServeCodeGen.update_service(service_name,
|
|
596
|
+
current_version,
|
|
597
|
+
mode=mode.value,
|
|
598
|
+
pool=pool)
|
|
599
|
+
returncode, _, stderr = backend.run_on_head(handle,
|
|
600
|
+
code,
|
|
601
|
+
require_outputs=True,
|
|
602
|
+
stream_logs=False,
|
|
603
|
+
separate_stderr=True)
|
|
604
|
+
try:
|
|
605
|
+
subprocess_utils.handle_returncode(returncode,
|
|
606
|
+
code,
|
|
607
|
+
f'Failed to update {noun}s',
|
|
608
|
+
stderr,
|
|
609
|
+
stream_logs=True)
|
|
610
|
+
except exceptions.CommandError as e:
|
|
611
|
+
raise RuntimeError(e.error_msg) from e
|
|
560
612
|
|
|
561
613
|
cmd = 'sky jobs pool status' if pool else 'sky serve status'
|
|
562
614
|
logger.info(
|
|
@@ -619,29 +671,44 @@ def down(
|
|
|
619
671
|
raise ValueError(f'Can only specify one of {noun}_names or all. '
|
|
620
672
|
f'Provided {argument_str!r}.')
|
|
621
673
|
|
|
622
|
-
backend = backend_utils.get_backend_from_handle(handle)
|
|
623
|
-
assert isinstance(backend, backends.CloudVmRayBackend)
|
|
624
674
|
service_names = None if all else service_names
|
|
625
|
-
code = serve_utils.ServeCodeGen.terminate_services(service_names, purge,
|
|
626
|
-
pool)
|
|
627
675
|
|
|
628
676
|
try:
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
677
|
+
assert isinstance(handle, backends.CloudVmRayResourceHandle)
|
|
678
|
+
use_legacy = not handle.is_grpc_enabled_with_flag
|
|
679
|
+
|
|
680
|
+
if handle.is_grpc_enabled_with_flag:
|
|
681
|
+
try:
|
|
682
|
+
stdout = serve_rpc_utils.RpcRunner.terminate_services(
|
|
683
|
+
handle, service_names, purge, pool)
|
|
684
|
+
except exceptions.SkyletMethodNotImplementedError:
|
|
685
|
+
use_legacy = True
|
|
686
|
+
|
|
687
|
+
if use_legacy:
|
|
688
|
+
backend = backend_utils.get_backend_from_handle(handle)
|
|
689
|
+
assert isinstance(backend, backends.CloudVmRayBackend)
|
|
690
|
+
code = serve_utils.ServeCodeGen.terminate_services(
|
|
691
|
+
service_names, purge, pool)
|
|
692
|
+
|
|
693
|
+
returncode, stdout, _ = backend.run_on_head(handle,
|
|
694
|
+
code,
|
|
695
|
+
require_outputs=True,
|
|
696
|
+
stream_logs=False)
|
|
697
|
+
|
|
698
|
+
subprocess_utils.handle_returncode(returncode, code,
|
|
699
|
+
f'Failed to terminate {noun}',
|
|
700
|
+
stdout)
|
|
633
701
|
except exceptions.FetchClusterInfoError as e:
|
|
634
702
|
raise RuntimeError(
|
|
635
703
|
'Failed to fetch controller IP. Please refresh controller status '
|
|
636
|
-
f'by `sky status -r {controller_type.value.cluster_name}` '
|
|
637
|
-
'
|
|
638
|
-
|
|
639
|
-
try:
|
|
640
|
-
subprocess_utils.handle_returncode(returncode, code,
|
|
641
|
-
f'Failed to terminate {noun}',
|
|
642
|
-
stdout)
|
|
704
|
+
f'by `sky status -r {controller_type.value.cluster_name}` and try '
|
|
705
|
+
'again.') from e
|
|
643
706
|
except exceptions.CommandError as e:
|
|
644
707
|
raise RuntimeError(e.error_msg) from e
|
|
708
|
+
except grpc.RpcError as e:
|
|
709
|
+
raise RuntimeError(f'{e.details()} ({e.code()})') from e
|
|
710
|
+
except grpc.FutureTimeoutError as e:
|
|
711
|
+
raise RuntimeError('gRPC timed out') from e
|
|
645
712
|
|
|
646
713
|
logger.info(stdout)
|
|
647
714
|
|
|
@@ -669,27 +736,40 @@ def status(
|
|
|
669
736
|
stopped_message=controller_type.value.default_hint_if_non_existent.
|
|
670
737
|
replace('service', noun))
|
|
671
738
|
|
|
672
|
-
|
|
673
|
-
|
|
739
|
+
assert isinstance(handle, backends.CloudVmRayResourceHandle)
|
|
740
|
+
use_legacy = not handle.is_grpc_enabled_with_flag
|
|
674
741
|
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
742
|
+
if handle.is_grpc_enabled_with_flag:
|
|
743
|
+
try:
|
|
744
|
+
service_records = serve_rpc_utils.RpcRunner.get_service_status(
|
|
745
|
+
handle, service_names, pool)
|
|
746
|
+
except exceptions.SkyletMethodNotImplementedError:
|
|
747
|
+
use_legacy = True
|
|
748
|
+
|
|
749
|
+
if use_legacy:
|
|
750
|
+
backend = backend_utils.get_backend_from_handle(handle)
|
|
751
|
+
assert isinstance(backend, backends.CloudVmRayBackend)
|
|
752
|
+
|
|
753
|
+
code = serve_utils.ServeCodeGen.get_service_status(service_names,
|
|
754
|
+
pool=pool)
|
|
755
|
+
returncode, serve_status_payload, stderr = backend.run_on_head(
|
|
756
|
+
handle,
|
|
757
|
+
code,
|
|
758
|
+
require_outputs=True,
|
|
759
|
+
stream_logs=False,
|
|
760
|
+
separate_stderr=True)
|
|
682
761
|
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
762
|
+
try:
|
|
763
|
+
subprocess_utils.handle_returncode(returncode,
|
|
764
|
+
code,
|
|
765
|
+
f'Failed to fetch {noun}s',
|
|
766
|
+
stderr,
|
|
767
|
+
stream_logs=True)
|
|
768
|
+
except exceptions.CommandError as e:
|
|
769
|
+
raise RuntimeError(e.error_msg) from e
|
|
770
|
+
|
|
771
|
+
service_records = serve_utils.load_service_status(serve_status_payload)
|
|
691
772
|
|
|
692
|
-
service_records = serve_utils.load_service_status(serve_status_payload)
|
|
693
773
|
# Get the endpoint for each service
|
|
694
774
|
for service_record in service_records:
|
|
695
775
|
service_record['endpoint'] = None
|
|
@@ -792,25 +872,37 @@ def _get_all_replica_targets(
|
|
|
792
872
|
handle: backends.CloudVmRayResourceHandle,
|
|
793
873
|
pool: bool) -> Set[serve_utils.ServiceComponentTarget]:
|
|
794
874
|
"""Helper function to get targets for all live replicas."""
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
returncode, serve_status_payload, stderr = backend.run_on_head(
|
|
798
|
-
handle,
|
|
799
|
-
code,
|
|
800
|
-
require_outputs=True,
|
|
801
|
-
stream_logs=False,
|
|
802
|
-
separate_stderr=True)
|
|
875
|
+
assert isinstance(handle, backends.CloudVmRayResourceHandle)
|
|
876
|
+
use_legacy = not handle.is_grpc_enabled_with_flag
|
|
803
877
|
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
878
|
+
if handle.is_grpc_enabled_with_flag:
|
|
879
|
+
try:
|
|
880
|
+
service_records = serve_rpc_utils.RpcRunner.get_service_status(
|
|
881
|
+
handle, [service_name], pool)
|
|
882
|
+
except exceptions.SkyletMethodNotImplementedError:
|
|
883
|
+
use_legacy = True
|
|
884
|
+
|
|
885
|
+
if use_legacy:
|
|
886
|
+
code = serve_utils.ServeCodeGen.get_service_status([service_name],
|
|
887
|
+
pool=pool)
|
|
888
|
+
returncode, serve_status_payload, stderr = backend.run_on_head(
|
|
889
|
+
handle,
|
|
890
|
+
code,
|
|
891
|
+
require_outputs=True,
|
|
892
|
+
stream_logs=False,
|
|
893
|
+
separate_stderr=True)
|
|
894
|
+
|
|
895
|
+
try:
|
|
896
|
+
subprocess_utils.handle_returncode(returncode,
|
|
897
|
+
code,
|
|
898
|
+
'Failed to fetch services',
|
|
899
|
+
stderr,
|
|
900
|
+
stream_logs=True)
|
|
901
|
+
except exceptions.CommandError as e:
|
|
902
|
+
raise RuntimeError(e.error_msg) from e
|
|
903
|
+
|
|
904
|
+
service_records = serve_utils.load_service_status(serve_status_payload)
|
|
812
905
|
|
|
813
|
-
service_records = serve_utils.load_service_status(serve_status_payload)
|
|
814
906
|
if not service_records:
|
|
815
907
|
raise ValueError(f'Service {service_name!r} not found.')
|
|
816
908
|
assert len(service_records) == 1
|
sky/server/common.py
CHANGED
|
@@ -515,6 +515,19 @@ def get_request_id(response: 'requests.Response') -> RequestId[T]:
|
|
|
515
515
|
return RequestId[T](request_id)
|
|
516
516
|
|
|
517
517
|
|
|
518
|
+
def get_stream_request_id(
|
|
519
|
+
response: 'requests.Response') -> Optional[RequestId[T]]:
|
|
520
|
+
"""This is same as the above function, but just for `sdk.stream_and_get.
|
|
521
|
+
We do this because `/api/stream` may choose the latest request id, and
|
|
522
|
+
we need to keep track of that information. Request id in this case can
|
|
523
|
+
be None."""
|
|
524
|
+
handle_request_error(response)
|
|
525
|
+
request_id = response.headers.get(server_constants.STREAM_REQUEST_HEADER)
|
|
526
|
+
if request_id is not None:
|
|
527
|
+
return RequestId[T](request_id)
|
|
528
|
+
return None
|
|
529
|
+
|
|
530
|
+
|
|
518
531
|
def _start_api_server(deploy: bool = False,
|
|
519
532
|
host: str = '127.0.0.1',
|
|
520
533
|
foreground: bool = False,
|
sky/server/constants.py
CHANGED
|
@@ -61,3 +61,6 @@ DASHBOARD_DIR = os.path.join(os.path.dirname(__file__), '..', 'dashboard',
|
|
|
61
61
|
|
|
62
62
|
# The interval (seconds) for the event to be restarted in the background.
|
|
63
63
|
DAEMON_RESTART_INTERVAL_SECONDS = 20
|
|
64
|
+
|
|
65
|
+
# Cookie header for stream request id.
|
|
66
|
+
STREAM_REQUEST_HEADER = 'X-SkyPilot-Stream-Request-ID'
|
sky/server/requests/executor.py
CHANGED
|
@@ -282,8 +282,8 @@ def _get_queue(schedule_type: api_requests.ScheduleType) -> RequestQueue:
|
|
|
282
282
|
|
|
283
283
|
@contextlib.contextmanager
|
|
284
284
|
def override_request_env_and_config(
|
|
285
|
-
request_body: payloads.RequestBody,
|
|
286
|
-
|
|
285
|
+
request_body: payloads.RequestBody, request_id: str,
|
|
286
|
+
request_name: str) -> Generator[None, None, None]:
|
|
287
287
|
"""Override the environment and SkyPilot config for a request."""
|
|
288
288
|
original_env = os.environ.copy()
|
|
289
289
|
try:
|
|
@@ -319,9 +319,22 @@ def override_request_env_and_config(
|
|
|
319
319
|
with skypilot_config.override_skypilot_config(
|
|
320
320
|
request_body.override_skypilot_config,
|
|
321
321
|
request_body.override_skypilot_config_path):
|
|
322
|
-
#
|
|
323
|
-
#
|
|
324
|
-
|
|
322
|
+
# Skip permission check for sky.workspaces.get request
|
|
323
|
+
# as it is used to determine which workspaces the user
|
|
324
|
+
# has access to.
|
|
325
|
+
if request_name != 'sky.workspaces.get':
|
|
326
|
+
try:
|
|
327
|
+
# Reject requests that the user does not have permission
|
|
328
|
+
# to access.
|
|
329
|
+
workspaces_core.reject_request_for_unauthorized_workspace(
|
|
330
|
+
user)
|
|
331
|
+
except exceptions.PermissionDeniedError as e:
|
|
332
|
+
logger.debug(
|
|
333
|
+
f'{request_id} permission denied to workspace: '
|
|
334
|
+
f'{skypilot_config.get_active_workspace()}: {e}')
|
|
335
|
+
raise e
|
|
336
|
+
logger.debug(
|
|
337
|
+
f'{request_id} permission granted to {request_name} request')
|
|
325
338
|
yield
|
|
326
339
|
finally:
|
|
327
340
|
# We need to call the save_timeline() since atexit will not be
|
|
@@ -402,7 +415,8 @@ def _request_execution_wrapper(request_id: str,
|
|
|
402
415
|
# captured in the log file.
|
|
403
416
|
try:
|
|
404
417
|
with sky_logging.add_debug_log_handler(request_id), \
|
|
405
|
-
override_request_env_and_config(
|
|
418
|
+
override_request_env_and_config(
|
|
419
|
+
request_body, request_id, request_name), \
|
|
406
420
|
tempstore.tempdir():
|
|
407
421
|
if sky_logging.logging_enabled(logger, sky_logging.DEBUG):
|
|
408
422
|
config = skypilot_config.to_dict()
|
|
@@ -451,6 +465,9 @@ def _request_execution_wrapper(request_id: str,
|
|
|
451
465
|
# Capture the peak RSS before GC.
|
|
452
466
|
peak_rss = max(proc.memory_info().rss,
|
|
453
467
|
metrics_lib.peak_rss_bytes)
|
|
468
|
+
# Clear request level cache to release all memory used by
|
|
469
|
+
# the request.
|
|
470
|
+
annotations.clear_request_level_cache()
|
|
454
471
|
with metrics_lib.time_it(name='release_memory',
|
|
455
472
|
group='internal'):
|
|
456
473
|
common_utils.release_memory()
|
sky/server/server.py
CHANGED
|
@@ -1571,6 +1571,15 @@ async def stream(
|
|
|
1571
1571
|
detail=f'Log path {log_path!r} does not exist')
|
|
1572
1572
|
|
|
1573
1573
|
log_path_to_stream = resolved_log_path
|
|
1574
|
+
|
|
1575
|
+
headers = {
|
|
1576
|
+
'Cache-Control': 'no-cache, no-transform',
|
|
1577
|
+
'X-Accel-Buffering': 'no',
|
|
1578
|
+
'Transfer-Encoding': 'chunked'
|
|
1579
|
+
}
|
|
1580
|
+
if request_id is not None:
|
|
1581
|
+
headers[server_constants.STREAM_REQUEST_HEADER] = request_id
|
|
1582
|
+
|
|
1574
1583
|
return fastapi.responses.StreamingResponse(
|
|
1575
1584
|
content=stream_utils.log_streamer(request_id,
|
|
1576
1585
|
log_path_to_stream,
|
|
@@ -1578,11 +1587,7 @@ async def stream(
|
|
|
1578
1587
|
tail=tail,
|
|
1579
1588
|
follow=follow),
|
|
1580
1589
|
media_type='text/plain',
|
|
1581
|
-
headers=
|
|
1582
|
-
'Cache-Control': 'no-cache, no-transform',
|
|
1583
|
-
'X-Accel-Buffering': 'no',
|
|
1584
|
-
'Transfer-Encoding': 'chunked'
|
|
1585
|
-
},
|
|
1590
|
+
headers=headers,
|
|
1586
1591
|
)
|
|
1587
1592
|
|
|
1588
1593
|
|
sky/setup_files/dependencies.py
CHANGED
|
@@ -189,6 +189,7 @@ extras_require: Dict[str, List[str]] = {
|
|
|
189
189
|
'fluidstack': [], # No dependencies needed for fluidstack
|
|
190
190
|
'cudo': ['cudo-compute>=0.1.10'],
|
|
191
191
|
'paperspace': [], # No dependencies needed for paperspace
|
|
192
|
+
'primeintellect': [], # No dependencies needed for primeintellect
|
|
192
193
|
'do': ['pydo>=0.3.0', 'azure-core>=1.24.0', 'azure-common'],
|
|
193
194
|
'vast': ['vastai-sdk>=0.1.12'],
|
|
194
195
|
'vsphere': [
|
sky/skylet/constants.py
CHANGED
|
@@ -62,7 +62,8 @@ SKY_UV_INSTALL_CMD = (f'{SKY_UV_CMD} -V >/dev/null 2>&1 || '
|
|
|
62
62
|
'curl -LsSf https://astral.sh/uv/install.sh '
|
|
63
63
|
f'| UV_INSTALL_DIR={SKY_UV_INSTALL_DIR} sh')
|
|
64
64
|
SKY_UV_PIP_CMD: str = (f'VIRTUAL_ENV={SKY_REMOTE_PYTHON_ENV} {SKY_UV_CMD} pip')
|
|
65
|
-
SKY_UV_RUN_CMD: str = (
|
|
65
|
+
SKY_UV_RUN_CMD: str = (
|
|
66
|
+
f'VIRTUAL_ENV={SKY_REMOTE_PYTHON_ENV} {SKY_UV_CMD} run --active')
|
|
66
67
|
# Deleting the SKY_REMOTE_PYTHON_ENV_NAME from the PATH and unsetting relevant
|
|
67
68
|
# VIRTUAL_ENV envvars to deactivate the environment. `deactivate` command does
|
|
68
69
|
# not work when conda is used.
|
|
@@ -153,7 +154,7 @@ CONDA_INSTALLATION_COMMANDS = (
|
|
|
153
154
|
# because for some images, conda is already installed, but not initialized.
|
|
154
155
|
# In this case, we need to initialize conda and set auto_activate_base to
|
|
155
156
|
# true.
|
|
156
|
-
'{ bash Miniconda3-Linux.sh -b; '
|
|
157
|
+
'{ bash Miniconda3-Linux.sh -b || true; '
|
|
157
158
|
'eval "$(~/miniconda3/bin/conda shell.bash hook)" && conda init && '
|
|
158
159
|
# Caller should replace {conda_auto_activate} with either true or false.
|
|
159
160
|
'conda config --set auto_activate_base {conda_auto_activate} && '
|
|
@@ -456,7 +457,8 @@ CATALOG_SCHEMA_VERSION = 'v8'
|
|
|
456
457
|
CATALOG_DIR = '~/.sky/catalogs'
|
|
457
458
|
ALL_CLOUDS = ('aws', 'azure', 'gcp', 'ibm', 'lambda', 'scp', 'oci',
|
|
458
459
|
'kubernetes', 'runpod', 'vast', 'vsphere', 'cudo', 'fluidstack',
|
|
459
|
-
'paperspace', '
|
|
460
|
+
'paperspace', 'primeintellect', 'do', 'nebius', 'ssh',
|
|
461
|
+
'hyperbolic', 'seeweb')
|
|
460
462
|
# END constants used for service catalog.
|
|
461
463
|
|
|
462
464
|
# The user ID of the SkyPilot system.
|