skypilot-nightly 1.0.0.dev2024053101__py3-none-any.whl → 1.0.0.dev2025022801__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.
Files changed (299) hide show
  1. sky/__init__.py +64 -32
  2. sky/adaptors/aws.py +23 -6
  3. sky/adaptors/azure.py +432 -15
  4. sky/adaptors/cloudflare.py +5 -5
  5. sky/adaptors/common.py +19 -9
  6. sky/adaptors/do.py +20 -0
  7. sky/adaptors/gcp.py +3 -2
  8. sky/adaptors/kubernetes.py +122 -88
  9. sky/adaptors/nebius.py +100 -0
  10. sky/adaptors/oci.py +39 -1
  11. sky/adaptors/vast.py +29 -0
  12. sky/admin_policy.py +101 -0
  13. sky/authentication.py +117 -98
  14. sky/backends/backend.py +52 -20
  15. sky/backends/backend_utils.py +669 -557
  16. sky/backends/cloud_vm_ray_backend.py +1099 -808
  17. sky/backends/local_docker_backend.py +14 -8
  18. sky/backends/wheel_utils.py +38 -20
  19. sky/benchmark/benchmark_utils.py +22 -23
  20. sky/check.py +76 -27
  21. sky/cli.py +1586 -1139
  22. sky/client/__init__.py +1 -0
  23. sky/client/cli.py +5683 -0
  24. sky/client/common.py +345 -0
  25. sky/client/sdk.py +1765 -0
  26. sky/cloud_stores.py +283 -19
  27. sky/clouds/__init__.py +7 -2
  28. sky/clouds/aws.py +303 -112
  29. sky/clouds/azure.py +185 -179
  30. sky/clouds/cloud.py +115 -37
  31. sky/clouds/cudo.py +29 -22
  32. sky/clouds/do.py +313 -0
  33. sky/clouds/fluidstack.py +44 -54
  34. sky/clouds/gcp.py +206 -65
  35. sky/clouds/ibm.py +26 -21
  36. sky/clouds/kubernetes.py +345 -91
  37. sky/clouds/lambda_cloud.py +40 -29
  38. sky/clouds/nebius.py +297 -0
  39. sky/clouds/oci.py +129 -90
  40. sky/clouds/paperspace.py +22 -18
  41. sky/clouds/runpod.py +53 -34
  42. sky/clouds/scp.py +28 -24
  43. sky/clouds/service_catalog/__init__.py +19 -13
  44. sky/clouds/service_catalog/aws_catalog.py +29 -12
  45. sky/clouds/service_catalog/azure_catalog.py +33 -6
  46. sky/clouds/service_catalog/common.py +95 -75
  47. sky/clouds/service_catalog/constants.py +3 -3
  48. sky/clouds/service_catalog/cudo_catalog.py +13 -3
  49. sky/clouds/service_catalog/data_fetchers/fetch_aws.py +36 -21
  50. sky/clouds/service_catalog/data_fetchers/fetch_azure.py +31 -4
  51. sky/clouds/service_catalog/data_fetchers/fetch_cudo.py +8 -117
  52. sky/clouds/service_catalog/data_fetchers/fetch_fluidstack.py +197 -44
  53. sky/clouds/service_catalog/data_fetchers/fetch_gcp.py +224 -36
  54. sky/clouds/service_catalog/data_fetchers/fetch_lambda_cloud.py +44 -24
  55. sky/clouds/service_catalog/data_fetchers/fetch_vast.py +147 -0
  56. sky/clouds/service_catalog/data_fetchers/fetch_vsphere.py +1 -1
  57. sky/clouds/service_catalog/do_catalog.py +111 -0
  58. sky/clouds/service_catalog/fluidstack_catalog.py +2 -2
  59. sky/clouds/service_catalog/gcp_catalog.py +16 -2
  60. sky/clouds/service_catalog/ibm_catalog.py +2 -2
  61. sky/clouds/service_catalog/kubernetes_catalog.py +192 -70
  62. sky/clouds/service_catalog/lambda_catalog.py +8 -3
  63. sky/clouds/service_catalog/nebius_catalog.py +116 -0
  64. sky/clouds/service_catalog/oci_catalog.py +31 -4
  65. sky/clouds/service_catalog/paperspace_catalog.py +2 -2
  66. sky/clouds/service_catalog/runpod_catalog.py +2 -2
  67. sky/clouds/service_catalog/scp_catalog.py +2 -2
  68. sky/clouds/service_catalog/vast_catalog.py +104 -0
  69. sky/clouds/service_catalog/vsphere_catalog.py +2 -2
  70. sky/clouds/utils/aws_utils.py +65 -0
  71. sky/clouds/utils/azure_utils.py +91 -0
  72. sky/clouds/utils/gcp_utils.py +5 -9
  73. sky/clouds/utils/oci_utils.py +47 -5
  74. sky/clouds/utils/scp_utils.py +4 -3
  75. sky/clouds/vast.py +280 -0
  76. sky/clouds/vsphere.py +22 -18
  77. sky/core.py +361 -107
  78. sky/dag.py +41 -28
  79. sky/data/data_transfer.py +37 -0
  80. sky/data/data_utils.py +211 -32
  81. sky/data/mounting_utils.py +182 -30
  82. sky/data/storage.py +2118 -270
  83. sky/data/storage_utils.py +126 -5
  84. sky/exceptions.py +179 -8
  85. sky/execution.py +158 -85
  86. sky/global_user_state.py +150 -34
  87. sky/jobs/__init__.py +12 -10
  88. sky/jobs/client/__init__.py +0 -0
  89. sky/jobs/client/sdk.py +302 -0
  90. sky/jobs/constants.py +49 -11
  91. sky/jobs/controller.py +161 -99
  92. sky/jobs/dashboard/dashboard.py +171 -25
  93. sky/jobs/dashboard/templates/index.html +572 -60
  94. sky/jobs/recovery_strategy.py +157 -156
  95. sky/jobs/scheduler.py +307 -0
  96. sky/jobs/server/__init__.py +1 -0
  97. sky/jobs/server/core.py +598 -0
  98. sky/jobs/server/dashboard_utils.py +69 -0
  99. sky/jobs/server/server.py +190 -0
  100. sky/jobs/state.py +627 -122
  101. sky/jobs/utils.py +615 -206
  102. sky/models.py +27 -0
  103. sky/optimizer.py +142 -83
  104. sky/provision/__init__.py +20 -5
  105. sky/provision/aws/config.py +124 -42
  106. sky/provision/aws/instance.py +130 -53
  107. sky/provision/azure/__init__.py +7 -0
  108. sky/{skylet/providers → provision}/azure/azure-config-template.json +19 -7
  109. sky/provision/azure/config.py +220 -0
  110. sky/provision/azure/instance.py +1012 -37
  111. sky/provision/common.py +31 -3
  112. sky/provision/constants.py +25 -0
  113. sky/provision/cudo/__init__.py +2 -1
  114. sky/provision/cudo/cudo_utils.py +112 -0
  115. sky/provision/cudo/cudo_wrapper.py +37 -16
  116. sky/provision/cudo/instance.py +28 -12
  117. sky/provision/do/__init__.py +11 -0
  118. sky/provision/do/config.py +14 -0
  119. sky/provision/do/constants.py +10 -0
  120. sky/provision/do/instance.py +287 -0
  121. sky/provision/do/utils.py +301 -0
  122. sky/provision/docker_utils.py +82 -46
  123. sky/provision/fluidstack/fluidstack_utils.py +57 -125
  124. sky/provision/fluidstack/instance.py +15 -43
  125. sky/provision/gcp/config.py +19 -9
  126. sky/provision/gcp/constants.py +7 -1
  127. sky/provision/gcp/instance.py +55 -34
  128. sky/provision/gcp/instance_utils.py +339 -80
  129. sky/provision/gcp/mig_utils.py +210 -0
  130. sky/provision/instance_setup.py +172 -133
  131. sky/provision/kubernetes/__init__.py +1 -0
  132. sky/provision/kubernetes/config.py +104 -90
  133. sky/provision/kubernetes/constants.py +8 -0
  134. sky/provision/kubernetes/instance.py +680 -325
  135. sky/provision/kubernetes/manifests/smarter-device-manager-daemonset.yaml +3 -0
  136. sky/provision/kubernetes/network.py +54 -20
  137. sky/provision/kubernetes/network_utils.py +70 -21
  138. sky/provision/kubernetes/utils.py +1370 -251
  139. sky/provision/lambda_cloud/__init__.py +11 -0
  140. sky/provision/lambda_cloud/config.py +10 -0
  141. sky/provision/lambda_cloud/instance.py +265 -0
  142. sky/{clouds/utils → provision/lambda_cloud}/lambda_utils.py +24 -23
  143. sky/provision/logging.py +1 -1
  144. sky/provision/nebius/__init__.py +11 -0
  145. sky/provision/nebius/config.py +11 -0
  146. sky/provision/nebius/instance.py +285 -0
  147. sky/provision/nebius/utils.py +318 -0
  148. sky/provision/oci/__init__.py +15 -0
  149. sky/provision/oci/config.py +51 -0
  150. sky/provision/oci/instance.py +436 -0
  151. sky/provision/oci/query_utils.py +681 -0
  152. sky/provision/paperspace/constants.py +6 -0
  153. sky/provision/paperspace/instance.py +4 -3
  154. sky/provision/paperspace/utils.py +2 -0
  155. sky/provision/provisioner.py +207 -130
  156. sky/provision/runpod/__init__.py +1 -0
  157. sky/provision/runpod/api/__init__.py +3 -0
  158. sky/provision/runpod/api/commands.py +119 -0
  159. sky/provision/runpod/api/pods.py +142 -0
  160. sky/provision/runpod/instance.py +64 -8
  161. sky/provision/runpod/utils.py +239 -23
  162. sky/provision/vast/__init__.py +10 -0
  163. sky/provision/vast/config.py +11 -0
  164. sky/provision/vast/instance.py +247 -0
  165. sky/provision/vast/utils.py +162 -0
  166. sky/provision/vsphere/common/vim_utils.py +1 -1
  167. sky/provision/vsphere/instance.py +8 -18
  168. sky/provision/vsphere/vsphere_utils.py +1 -1
  169. sky/resources.py +247 -102
  170. sky/serve/__init__.py +9 -9
  171. sky/serve/autoscalers.py +361 -299
  172. sky/serve/client/__init__.py +0 -0
  173. sky/serve/client/sdk.py +366 -0
  174. sky/serve/constants.py +12 -3
  175. sky/serve/controller.py +106 -36
  176. sky/serve/load_balancer.py +63 -12
  177. sky/serve/load_balancing_policies.py +84 -2
  178. sky/serve/replica_managers.py +42 -34
  179. sky/serve/serve_state.py +62 -32
  180. sky/serve/serve_utils.py +271 -160
  181. sky/serve/server/__init__.py +0 -0
  182. sky/serve/{core.py → server/core.py} +271 -90
  183. sky/serve/server/server.py +112 -0
  184. sky/serve/service.py +52 -16
  185. sky/serve/service_spec.py +95 -32
  186. sky/server/__init__.py +1 -0
  187. sky/server/common.py +430 -0
  188. sky/server/constants.py +21 -0
  189. sky/server/html/log.html +174 -0
  190. sky/server/requests/__init__.py +0 -0
  191. sky/server/requests/executor.py +472 -0
  192. sky/server/requests/payloads.py +487 -0
  193. sky/server/requests/queues/__init__.py +0 -0
  194. sky/server/requests/queues/mp_queue.py +76 -0
  195. sky/server/requests/requests.py +567 -0
  196. sky/server/requests/serializers/__init__.py +0 -0
  197. sky/server/requests/serializers/decoders.py +192 -0
  198. sky/server/requests/serializers/encoders.py +166 -0
  199. sky/server/server.py +1106 -0
  200. sky/server/stream_utils.py +141 -0
  201. sky/setup_files/MANIFEST.in +2 -5
  202. sky/setup_files/dependencies.py +159 -0
  203. sky/setup_files/setup.py +14 -125
  204. sky/sky_logging.py +59 -14
  205. sky/skylet/autostop_lib.py +2 -2
  206. sky/skylet/constants.py +183 -50
  207. sky/skylet/events.py +22 -10
  208. sky/skylet/job_lib.py +403 -258
  209. sky/skylet/log_lib.py +111 -71
  210. sky/skylet/log_lib.pyi +6 -0
  211. sky/skylet/providers/command_runner.py +6 -8
  212. sky/skylet/providers/ibm/node_provider.py +2 -2
  213. sky/skylet/providers/scp/config.py +11 -3
  214. sky/skylet/providers/scp/node_provider.py +8 -8
  215. sky/skylet/skylet.py +3 -1
  216. sky/skylet/subprocess_daemon.py +69 -17
  217. sky/skypilot_config.py +119 -57
  218. sky/task.py +205 -64
  219. sky/templates/aws-ray.yml.j2 +37 -7
  220. sky/templates/azure-ray.yml.j2 +27 -82
  221. sky/templates/cudo-ray.yml.j2 +7 -3
  222. sky/templates/do-ray.yml.j2 +98 -0
  223. sky/templates/fluidstack-ray.yml.j2 +7 -4
  224. sky/templates/gcp-ray.yml.j2 +26 -6
  225. sky/templates/ibm-ray.yml.j2 +3 -2
  226. sky/templates/jobs-controller.yaml.j2 +46 -11
  227. sky/templates/kubernetes-ingress.yml.j2 +7 -0
  228. sky/templates/kubernetes-loadbalancer.yml.j2 +7 -0
  229. sky/templates/{kubernetes-port-forward-proxy-command.sh.j2 → kubernetes-port-forward-proxy-command.sh} +51 -7
  230. sky/templates/kubernetes-ray.yml.j2 +292 -25
  231. sky/templates/lambda-ray.yml.j2 +30 -40
  232. sky/templates/nebius-ray.yml.j2 +79 -0
  233. sky/templates/oci-ray.yml.j2 +18 -57
  234. sky/templates/paperspace-ray.yml.j2 +10 -6
  235. sky/templates/runpod-ray.yml.j2 +26 -4
  236. sky/templates/scp-ray.yml.j2 +3 -2
  237. sky/templates/sky-serve-controller.yaml.j2 +12 -1
  238. sky/templates/skypilot-server-kubernetes-proxy.sh +36 -0
  239. sky/templates/vast-ray.yml.j2 +70 -0
  240. sky/templates/vsphere-ray.yml.j2 +8 -3
  241. sky/templates/websocket_proxy.py +64 -0
  242. sky/usage/constants.py +10 -1
  243. sky/usage/usage_lib.py +130 -37
  244. sky/utils/accelerator_registry.py +35 -51
  245. sky/utils/admin_policy_utils.py +147 -0
  246. sky/utils/annotations.py +51 -0
  247. sky/utils/cli_utils/status_utils.py +81 -23
  248. sky/utils/cluster_utils.py +356 -0
  249. sky/utils/command_runner.py +452 -89
  250. sky/utils/command_runner.pyi +77 -3
  251. sky/utils/common.py +54 -0
  252. sky/utils/common_utils.py +319 -108
  253. sky/utils/config_utils.py +204 -0
  254. sky/utils/control_master_utils.py +48 -0
  255. sky/utils/controller_utils.py +548 -266
  256. sky/utils/dag_utils.py +93 -32
  257. sky/utils/db_utils.py +18 -4
  258. sky/utils/env_options.py +29 -7
  259. sky/utils/kubernetes/create_cluster.sh +8 -60
  260. sky/utils/kubernetes/deploy_remote_cluster.sh +243 -0
  261. sky/utils/kubernetes/exec_kubeconfig_converter.py +73 -0
  262. sky/utils/kubernetes/generate_kubeconfig.sh +336 -0
  263. sky/utils/kubernetes/gpu_labeler.py +4 -4
  264. sky/utils/kubernetes/k8s_gpu_labeler_job.yaml +4 -3
  265. sky/utils/kubernetes/kubernetes_deploy_utils.py +228 -0
  266. sky/utils/kubernetes/rsync_helper.sh +24 -0
  267. sky/utils/kubernetes/ssh_jump_lifecycle_manager.py +1 -1
  268. sky/utils/log_utils.py +240 -33
  269. sky/utils/message_utils.py +81 -0
  270. sky/utils/registry.py +127 -0
  271. sky/utils/resources_utils.py +94 -22
  272. sky/utils/rich_utils.py +247 -18
  273. sky/utils/schemas.py +284 -64
  274. sky/{status_lib.py → utils/status_lib.py} +12 -7
  275. sky/utils/subprocess_utils.py +212 -46
  276. sky/utils/timeline.py +12 -7
  277. sky/utils/ux_utils.py +168 -15
  278. skypilot_nightly-1.0.0.dev2025022801.dist-info/METADATA +363 -0
  279. skypilot_nightly-1.0.0.dev2025022801.dist-info/RECORD +352 -0
  280. {skypilot_nightly-1.0.0.dev2024053101.dist-info → skypilot_nightly-1.0.0.dev2025022801.dist-info}/WHEEL +1 -1
  281. sky/clouds/cloud_registry.py +0 -31
  282. sky/jobs/core.py +0 -330
  283. sky/skylet/providers/azure/__init__.py +0 -2
  284. sky/skylet/providers/azure/azure-vm-template.json +0 -301
  285. sky/skylet/providers/azure/config.py +0 -170
  286. sky/skylet/providers/azure/node_provider.py +0 -466
  287. sky/skylet/providers/lambda_cloud/__init__.py +0 -2
  288. sky/skylet/providers/lambda_cloud/node_provider.py +0 -320
  289. sky/skylet/providers/oci/__init__.py +0 -2
  290. sky/skylet/providers/oci/node_provider.py +0 -488
  291. sky/skylet/providers/oci/query_helper.py +0 -383
  292. sky/skylet/providers/oci/utils.py +0 -21
  293. sky/utils/cluster_yaml_utils.py +0 -24
  294. sky/utils/kubernetes/generate_static_kubeconfig.sh +0 -137
  295. skypilot_nightly-1.0.0.dev2024053101.dist-info/METADATA +0 -315
  296. skypilot_nightly-1.0.0.dev2024053101.dist-info/RECORD +0 -275
  297. {skypilot_nightly-1.0.0.dev2024053101.dist-info → skypilot_nightly-1.0.0.dev2025022801.dist-info}/LICENSE +0 -0
  298. {skypilot_nightly-1.0.0.dev2024053101.dist-info → skypilot_nightly-1.0.0.dev2025022801.dist-info}/entry_points.txt +0 -0
  299. {skypilot_nightly-1.0.0.dev2024053101.dist-info → skypilot_nightly-1.0.0.dev2025022801.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,141 @@
1
+ """Utilities for streaming logs from response."""
2
+
3
+ import asyncio
4
+ import collections
5
+ import pathlib
6
+ from typing import AsyncGenerator, Deque, Optional
7
+
8
+ import aiofiles
9
+ import fastapi
10
+
11
+ from sky import sky_logging
12
+ from sky.server.requests import requests as requests_lib
13
+ from sky.utils import message_utils
14
+ from sky.utils import rich_utils
15
+
16
+ logger = sky_logging.init_logger(__name__)
17
+
18
+
19
+ async def _yield_log_file_with_payloads_skipped(
20
+ log_file) -> AsyncGenerator[str, None]:
21
+ async for line in log_file:
22
+ if not line:
23
+ return
24
+ is_payload, line_str = message_utils.decode_payload(
25
+ line.decode('utf-8'), raise_for_mismatch=False)
26
+ if is_payload:
27
+ continue
28
+
29
+ yield line_str
30
+
31
+
32
+ async def log_streamer(request_id: Optional[str],
33
+ log_path: pathlib.Path,
34
+ plain_logs: bool = False,
35
+ tail: Optional[int] = None,
36
+ follow: bool = True) -> AsyncGenerator[str, None]:
37
+ """Streams the logs of a request."""
38
+
39
+ if request_id is not None:
40
+ status_msg = rich_utils.EncodedStatusMessage(
41
+ f'[dim]Checking request: {request_id}[/dim]')
42
+ request_task = requests_lib.get_request(request_id)
43
+
44
+ if request_task is None:
45
+ raise fastapi.HTTPException(
46
+ status_code=404, detail=f'Request {request_id} not found')
47
+ request_id = request_task.request_id
48
+
49
+ # Do not show the waiting spinner if the request is a fast, non-blocking
50
+ # request.
51
+ show_request_waiting_spinner = (not plain_logs and
52
+ request_task.schedule_type
53
+ == requests_lib.ScheduleType.LONG)
54
+
55
+ if show_request_waiting_spinner:
56
+ yield status_msg.init()
57
+ yield status_msg.start()
58
+ is_waiting_msg_logged = False
59
+ waiting_msg = (f'Waiting for {request_task.name!r} request to be '
60
+ f'scheduled: {request_id}')
61
+ while request_task.status < requests_lib.RequestStatus.RUNNING:
62
+ if show_request_waiting_spinner:
63
+ yield status_msg.update(f'[dim]{waiting_msg}[/dim]')
64
+ elif plain_logs and not is_waiting_msg_logged:
65
+ is_waiting_msg_logged = True
66
+ # Use smaller padding (1024 bytes) to force browser rendering
67
+ yield f'{waiting_msg}' + ' ' * 4096 + '\n'
68
+ # Sleep 0 to yield, so other coroutines can run. This busy waiting
69
+ # loop is performance critical for short-running requests, so we do
70
+ # not want to yield too long.
71
+ await asyncio.sleep(0.1)
72
+ request_task = requests_lib.get_request(request_id)
73
+ if not follow:
74
+ break
75
+ if show_request_waiting_spinner:
76
+ yield status_msg.stop()
77
+
78
+ # Find last n lines of the log file. Do not read the whole file into memory.
79
+ async with aiofiles.open(log_path, 'rb') as f:
80
+ if tail is not None:
81
+ # TODO(zhwu): this will include the control lines for rich status,
82
+ # which may not lead to exact tail lines when showing on the client
83
+ # side.
84
+ lines: Deque[str] = collections.deque(maxlen=tail)
85
+ async for line_str in _yield_log_file_with_payloads_skipped(f):
86
+ lines.append(line_str)
87
+ for line_str in lines:
88
+ yield line_str
89
+
90
+ while True:
91
+ # Sleep 0 to yield control to allow other coroutines to run,
92
+ # while keeps the loop tight to make log stream responsive.
93
+ await asyncio.sleep(0)
94
+ line: Optional[bytes] = await f.readline()
95
+ if not line:
96
+ if request_id is not None:
97
+ request_task = requests_lib.get_request(request_id)
98
+ if request_task.status > requests_lib.RequestStatus.RUNNING:
99
+ if (request_task.status ==
100
+ requests_lib.RequestStatus.CANCELLED):
101
+ yield (f'{request_task.name!r} request {request_id}'
102
+ ' cancelled\n')
103
+ break
104
+ if not follow:
105
+ break
106
+ # Sleep shortly to avoid storming the DB and CPU, this has
107
+ # little impact on the responsivness here since we are waiting
108
+ # for a new line to come in.
109
+ await asyncio.sleep(0.1)
110
+ continue
111
+ line_str = line.decode('utf-8')
112
+ if plain_logs:
113
+ is_payload, line_str = message_utils.decode_payload(
114
+ line_str, raise_for_mismatch=False)
115
+ if is_payload:
116
+ continue
117
+ yield line_str
118
+
119
+
120
+ def stream_response(
121
+ request_id: str, logs_path: pathlib.Path,
122
+ background_tasks: fastapi.BackgroundTasks
123
+ ) -> fastapi.responses.StreamingResponse:
124
+
125
+ async def on_disconnect():
126
+ logger.info(f'User terminated the connection for request '
127
+ f'{request_id}')
128
+ requests_lib.kill_requests([request_id])
129
+
130
+ # The background task will be run after returning a response.
131
+ # https://fastapi.tiangolo.com/tutorial/background-tasks/
132
+ background_tasks.add_task(on_disconnect)
133
+
134
+ return fastapi.responses.StreamingResponse(
135
+ log_streamer(request_id, logs_path),
136
+ media_type='text/plain',
137
+ headers={
138
+ 'Cache-Control': 'no-cache, no-transform',
139
+ 'X-Accel-Buffering': 'no',
140
+ 'Transfer-Encoding': 'chunked'
141
+ })
@@ -1,15 +1,11 @@
1
1
  include sky/backends/monkey_patches/*.py
2
2
  exclude sky/clouds/service_catalog/data_fetchers/analyze.py
3
3
  include sky/provision/kubernetes/manifests/*
4
+ include sky/provision/azure/*
4
5
  include sky/setup_files/*
5
6
  include sky/skylet/*.sh
6
7
  include sky/skylet/LICENSE
7
- include sky/skylet/providers/azure/*
8
- include sky/skylet/providers/gcp/*
9
8
  include sky/skylet/providers/ibm/*
10
- include sky/skylet/providers/kubernetes/*
11
- include sky/skylet/providers/lambda_cloud/*
12
- include sky/skylet/providers/oci/*
13
9
  include sky/skylet/providers/scp/*
14
10
  include sky/skylet/providers/*.py
15
11
  include sky/skylet/ray_patches/*.patch
@@ -18,3 +14,4 @@ include sky/jobs/dashboard/templates/*
18
14
  include sky/jobs/dashboard/static/*
19
15
  include sky/templates/*
20
16
  include sky/utils/kubernetes/*
17
+ include sky/server/html/*
@@ -0,0 +1,159 @@
1
+ """Dependencies for SkyPilot.
2
+
3
+ This file is imported by setup.py, so:
4
+ - It may not be able to import other skypilot modules, since sys.path may not be
5
+ correct.
6
+ - It should not import any dependencies, as they may not be installed yet.
7
+ """
8
+ import sys
9
+ from typing import Dict, List
10
+
11
+ install_requires = [
12
+ 'wheel',
13
+ 'cachetools',
14
+ # NOTE: ray requires click>=7.0.
15
+ 'click >= 7.0',
16
+ 'colorama',
17
+ 'cryptography',
18
+ # Jinja has a bug in older versions because of the lack of pinning
19
+ # the version of the underlying markupsafe package. See:
20
+ # https://github.com/pallets/jinja/issues/1585
21
+ 'jinja2 >= 3.0',
22
+ 'jsonschema',
23
+ 'networkx',
24
+ 'pandas>=1.3.0',
25
+ 'pendulum',
26
+ # PrettyTable with version >=2.0.0 is required for the support of
27
+ # `add_rows` method.
28
+ 'PrettyTable >= 2.0.0',
29
+ 'python-dotenv',
30
+ 'rich',
31
+ 'tabulate',
32
+ # Light weight requirement, can be replaced with "typing" once
33
+ # we deprecate Python 3.7 (this will take a while).
34
+ 'typing_extensions',
35
+ 'filelock >= 3.6.0',
36
+ 'packaging',
37
+ 'psutil',
38
+ 'pulp',
39
+ # Cython 3.0 release breaks PyYAML 5.4.*
40
+ # (https://github.com/yaml/pyyaml/issues/601)
41
+ # <= 3.13 may encounter https://github.com/ultralytics/yolov5/issues/414
42
+ 'pyyaml > 3.13, != 5.4.*',
43
+ 'requests',
44
+ 'fastapi',
45
+ 'uvicorn[standard]',
46
+ # Some pydantic versions are not compatible with ray. Adopted from ray's
47
+ # setup.py:
48
+ # https://github.com/ray-project/ray/blob/ray-2.9.3/python/setup.py#L254
49
+ # We need pydantic>=2.0.0 for API server and client.
50
+ 'pydantic!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.*,!=2.4.*,<3,>2',
51
+ # Required for Form data by pydantic
52
+ 'python-multipart',
53
+ 'aiofiles',
54
+ 'httpx',
55
+ 'setproctitle',
56
+ ]
57
+
58
+ local_ray = [
59
+ # Lower version of ray will cause dependency conflict for
60
+ # click/grpcio/protobuf.
61
+ # Excluded 2.6.0 as it has a bug in the cluster launcher:
62
+ # https://github.com/ray-project/ray/releases/tag/ray-2.6.1
63
+ 'ray[default] >= 2.2.0, != 2.6.0',
64
+ ]
65
+
66
+ remote = [
67
+ # Adopted from ray's setup.py:
68
+ # https://github.com/ray-project/ray/blob/ray-2.9.3/python/setup.py#L251-L252
69
+ # SkyPilot: != 1.48.0 is required to avoid the error where ray dashboard
70
+ # fails to start when ray start is called (#2054).
71
+ # Tracking issue: https://github.com/ray-project/ray/issues/30984
72
+ 'grpcio >= 1.32.0, != 1.48.0; python_version < \'3.10\'',
73
+ 'grpcio >= 1.42.0, != 1.48.0; python_version >= \'3.10\'',
74
+ # Adopted from ray's setup.py:
75
+ # https://github.com/ray-project/ray/blob/ray-2.9.3/python/setup.py#L343
76
+ 'protobuf >= 3.15.3, != 3.19.5',
77
+ ]
78
+
79
+ # NOTE: Change the templates/jobs-controller.yaml.j2 file if any of the
80
+ # following packages dependencies are changed.
81
+ aws_dependencies = [
82
+ # botocore does not work with urllib3>=2.0.0, according to
83
+ # https://github.com/boto/botocore/issues/2926
84
+ # We have to explicitly pin the version to optimize the time for
85
+ # poetry install. See https://github.com/orgs/python-poetry/discussions/7937
86
+ 'urllib3<2',
87
+ # NOTE: this installs CLI V1. To use AWS SSO (e.g., `aws sso login`), users
88
+ # should instead use CLI V2 which is not pip-installable. See
89
+ # https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html.
90
+ 'awscli>=1.27.10',
91
+ 'botocore>=1.29.10',
92
+ 'boto3>=1.26.1',
93
+ # NOTE: required by awscli. To avoid ray automatically installing
94
+ # the latest version.
95
+ 'colorama < 0.4.5',
96
+ ]
97
+
98
+ # azure-cli cannot be installed normally by uv, so we need to work around it in
99
+ # a few places.
100
+ AZURE_CLI = 'azure-cli>=2.65.0'
101
+
102
+ extras_require: Dict[str, List[str]] = {
103
+ 'aws': aws_dependencies,
104
+ # TODO(zongheng): azure-cli is huge and takes a long time to install.
105
+ # Tracked in: https://github.com/Azure/azure-cli/issues/7387
106
+ # azure-identity is needed in node_provider.
107
+ # We need azure-identity>=1.13.0 to enable the customization of the
108
+ # timeout of AzureCliCredential.
109
+ 'azure': [
110
+ AZURE_CLI,
111
+ 'azure-core>=1.31.0',
112
+ 'azure-identity>=1.19.0',
113
+ 'azure-mgmt-network>=27.0.0',
114
+ 'azure-mgmt-compute>=33.0.0',
115
+ 'azure-storage-blob>=12.23.1',
116
+ 'msgraph-sdk',
117
+ ] + local_ray,
118
+ # We need google-api-python-client>=2.69.0 to enable 'discardLocalSsd'
119
+ # parameter for stopping instances. Reference:
120
+ # https://github.com/googleapis/google-api-python-client/commit/f6e9d3869ed605b06f7cbf2e8cf2db25108506e6
121
+ 'gcp': ['google-api-python-client>=2.69.0', 'google-cloud-storage'],
122
+ 'ibm': [
123
+ 'ibm-cloud-sdk-core', 'ibm-vpc', 'ibm-platform-services', 'ibm-cos-sdk'
124
+ ] + local_ray,
125
+ 'docker': ['docker'] + local_ray,
126
+ 'lambda': local_ray,
127
+ 'cloudflare': aws_dependencies,
128
+ 'scp': local_ray,
129
+ 'oci': ['oci'] + local_ray,
130
+ # Kubernetes 32.0.0 has an authentication bug: https://github.com/kubernetes-client/python/issues/2333 # pylint: disable=line-too-long
131
+ 'kubernetes': ['kubernetes>=20.0.0,!=32.0.0'],
132
+ 'remote': remote,
133
+ # For the container registry auth api. Reference:
134
+ # https://github.com/runpod/runpod-python/releases/tag/1.6.1
135
+ 'runpod': ['runpod>=1.6.1'],
136
+ 'fluidstack': [], # No dependencies needed for fluidstack
137
+ 'cudo': ['cudo-compute>=0.1.10'],
138
+ 'paperspace': [], # No dependencies needed for paperspace
139
+ 'do': ['pydo>=0.3.0', 'azure-core>=1.24.0', 'azure-common'],
140
+ 'vast': ['vastai-sdk>=0.1.12'],
141
+ 'vsphere': [
142
+ 'pyvmomi==8.0.1.0.2',
143
+ # vsphere-automation-sdk is also required, but it does not have
144
+ # pypi release, which cause failure of our pypi release.
145
+ # https://peps.python.org/pep-0440/#direct-references
146
+ # We have the instruction for its installation in our
147
+ # docs instead.
148
+ # 'vsphere-automation-sdk @ git+https://github.com/vmware/vsphere-automation-sdk-python.git@v8.0.1.0' pylint: disable=line-too-long
149
+ ],
150
+ 'nebius': ['nebius>=0.2.0',]
151
+ }
152
+
153
+ # Nebius needs python3.10. If python 3.9 [all] will not install nebius
154
+ if sys.version_info < (3, 10):
155
+ filtered_keys = [k for k in extras_require if k != 'nebius']
156
+ extras_require['all'] = sum(
157
+ [v for k, v in extras_require.items() if k != 'nebius'], [])
158
+ else:
159
+ extras_require['all'] = sum(extras_require.values(), [])
sky/setup_files/setup.py CHANGED
@@ -1,3 +1,4 @@
1
+ # pylint: skip-file
1
2
  """SkyPilot.
2
3
 
3
4
  SkyPilot is a framework for easily running machine learning* workloads on any
@@ -12,25 +13,33 @@ and would love to hear more about how we can better support your requirements -
12
13
  please join us in [this
13
14
  discussion](https://github.com/skypilot-org/skypilot/discussions/1016)
14
15
  """
15
-
16
16
  import atexit
17
17
  import io
18
18
  import os
19
19
  import platform
20
20
  import re
21
+ import runpy
21
22
  import subprocess
22
23
  import sys
23
- from typing import Dict, List
24
24
 
25
25
  import setuptools
26
26
 
27
+ # __file__ is setup.py at the root of the repo. We shouldn't assume it's a
28
+ # symlink - e.g. in the sdist it's resolved to a normal file.
27
29
  ROOT_DIR = os.path.dirname(__file__)
30
+ DEPENDENCIES_FILE_PATH = os.path.join(ROOT_DIR, 'sky', 'setup_files',
31
+ 'dependencies.py')
28
32
  INIT_FILE_PATH = os.path.join(ROOT_DIR, 'sky', '__init__.py')
29
33
  _COMMIT_FAILURE_MESSAGE = (
30
34
  'WARNING: SkyPilot fail to {verb} the commit hash in '
31
35
  f'{INIT_FILE_PATH!r} (SkyPilot can still be normally used): '
32
36
  '{error}')
33
37
 
38
+ # setuptools does not include the script dir on the search path, so we can't
39
+ # just do `import dependencies`. Instead, use runpy to manually load it. Note:
40
+ # dependencies here is a dict, not a module, so we access it by subscripting.
41
+ dependencies = runpy.run_path(DEPENDENCIES_FILE_PATH)
42
+
34
43
  original_init_content = None
35
44
 
36
45
  system = platform.system()
@@ -130,126 +139,6 @@ def parse_readme(readme: str) -> str:
130
139
  return readme
131
140
 
132
141
 
133
- install_requires = [
134
- 'wheel',
135
- 'cachetools',
136
- # NOTE: ray requires click>=7.0.
137
- 'click >= 7.0',
138
- 'colorama',
139
- 'cryptography',
140
- # Jinja has a bug in older versions because of the lack of pinning
141
- # the version of the underlying markupsafe package. See:
142
- # https://github.com/pallets/jinja/issues/1585
143
- 'jinja2 >= 3.0',
144
- 'jsonschema',
145
- 'networkx',
146
- 'pandas>=1.3.0',
147
- 'pendulum',
148
- # PrettyTable with version >=2.0.0 is required for the support of
149
- # `add_rows` method.
150
- 'PrettyTable >= 2.0.0',
151
- 'python-dotenv',
152
- 'rich',
153
- 'tabulate',
154
- # Light weight requirement, can be replaced with "typing" once
155
- # we deprecate Python 3.7 (this will take a while).
156
- "typing_extensions",
157
- 'filelock >= 3.6.0',
158
- 'packaging',
159
- 'psutil',
160
- 'pulp',
161
- # Cython 3.0 release breaks PyYAML 5.4.* (https://github.com/yaml/pyyaml/issues/601)
162
- # <= 3.13 may encounter https://github.com/ultralytics/yolov5/issues/414
163
- 'pyyaml > 3.13, != 5.4.*',
164
- 'requests',
165
- ]
166
-
167
- local_ray = [
168
- # Lower version of ray will cause dependency conflict for
169
- # click/grpcio/protobuf.
170
- # Excluded 2.6.0 as it has a bug in the cluster launcher:
171
- # https://github.com/ray-project/ray/releases/tag/ray-2.6.1
172
- 'ray[default] >= 2.2.0, != 2.6.0',
173
- ]
174
-
175
- remote = [
176
- # Adopted from ray's setup.py: https://github.com/ray-project/ray/blob/ray-2.4.0/python/setup.py
177
- # SkyPilot: != 1.48.0 is required to avoid the error where ray dashboard fails to start when
178
- # ray start is called (#2054).
179
- # Tracking issue: https://github.com/ray-project/ray/issues/30984
180
- "grpcio >= 1.32.0, <= 1.49.1, != 1.48.0; python_version < '3.10' and sys_platform == 'darwin'", # noqa:E501
181
- "grpcio >= 1.42.0, <= 1.49.1, != 1.48.0; python_version >= '3.10' and sys_platform == 'darwin'", # noqa:E501
182
- # Original issue: https://github.com/ray-project/ray/issues/33833
183
- "grpcio >= 1.32.0, <= 1.51.3, != 1.48.0; python_version < '3.10' and sys_platform != 'darwin'", # noqa:E501
184
- "grpcio >= 1.42.0, <= 1.51.3, != 1.48.0; python_version >= '3.10' and sys_platform != 'darwin'", # noqa:E501
185
- # Adopted from ray's setup.py:
186
- # https://github.com/ray-project/ray/blob/ray-2.9.3/python/setup.py#L343
187
- 'protobuf >= 3.15.3, != 3.19.5',
188
- # Some pydantic versions are not compatible with ray. Adopted from ray's
189
- # setup.py: https://github.com/ray-project/ray/blob/ray-2.9.3/python/setup.py#L254
190
- 'pydantic!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.*,!=2.4.*,<3',
191
- ]
192
-
193
- # NOTE: Change the templates/jobs-controller.yaml.j2 file if any of the
194
- # following packages dependencies are changed.
195
- aws_dependencies = [
196
- # botocore does not work with urllib3>=2.0.0, according to https://github.com/boto/botocore/issues/2926
197
- # We have to explicitly pin the version to optimize the time for
198
- # poetry install. See https://github.com/orgs/python-poetry/discussions/7937
199
- 'urllib3<2',
200
- # NOTE: this installs CLI V1. To use AWS SSO (e.g., `aws sso login`), users
201
- # should instead use CLI V2 which is not pip-installable. See
202
- # https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html.
203
- 'awscli>=1.27.10',
204
- 'botocore>=1.29.10',
205
- 'boto3>=1.26.1',
206
- # NOTE: required by awscli. To avoid ray automatically installing
207
- # the latest version.
208
- 'colorama < 0.4.5',
209
- ]
210
-
211
- extras_require: Dict[str, List[str]] = {
212
- 'aws': aws_dependencies,
213
- # TODO(zongheng): azure-cli is huge and takes a long time to install.
214
- # Tracked in: https://github.com/Azure/azure-cli/issues/7387
215
- # azure-identity is needed in node_provider.
216
- # We need azure-identity>=1.13.0 to enable the customization of the
217
- # timeout of AzureCliCredential.
218
- 'azure': [
219
- 'azure-cli>=2.31.0', 'azure-core', 'azure-identity>=1.13.0',
220
- 'azure-mgmt-network'
221
- ] + local_ray,
222
- # We need google-api-python-client>=2.69.0 to enable 'discardLocalSsd'
223
- # parameter for stopping instances.
224
- # Reference: https://github.com/googleapis/google-api-python-client/commit/f6e9d3869ed605b06f7cbf2e8cf2db25108506e6
225
- 'gcp': ['google-api-python-client>=2.69.0', 'google-cloud-storage'],
226
- 'ibm': [
227
- 'ibm-cloud-sdk-core', 'ibm-vpc', 'ibm-platform-services', 'ibm-cos-sdk'
228
- ] + local_ray,
229
- 'docker': ['docker'] + local_ray,
230
- 'lambda': local_ray,
231
- 'cloudflare': aws_dependencies,
232
- 'scp': local_ray,
233
- 'oci': ['oci'] + local_ray,
234
- 'kubernetes': ['kubernetes>=20.0.0'],
235
- 'remote': remote,
236
- 'runpod': ['runpod>=1.5.1'],
237
- 'fluidstack': [], # No dependencies needed for fluidstack
238
- 'cudo': ['cudo-compute>=0.1.10'],
239
- 'paperspace': [], # No dependencies needed for paperspace
240
- 'vsphere': [
241
- 'pyvmomi==8.0.1.0.2',
242
- # vsphere-automation-sdk is also required, but it does not have
243
- # pypi release, which cause failure of our pypi release.
244
- # https://peps.python.org/pep-0440/#direct-references
245
- # We have the instruction for its installation in our
246
- # docs instead.
247
- # 'vsphere-automation-sdk @ git+https://github.com/vmware/vsphere-automation-sdk-python.git@v8.0.1.0'
248
- ],
249
- }
250
-
251
- extras_require['all'] = sum(extras_require.values(), [])
252
-
253
142
  long_description = ''
254
143
  readme_filepath = 'README.md'
255
144
  # When sky/backends/wheel_utils.py builds wheels, it will not contain the
@@ -276,8 +165,8 @@ setuptools.setup(
276
165
  long_description_content_type='text/markdown',
277
166
  setup_requires=['wheel'],
278
167
  requires_python='>=3.7',
279
- install_requires=install_requires,
280
- extras_require=extras_require,
168
+ install_requires=dependencies['install_requires'],
169
+ extras_require=dependencies['extras_require'],
281
170
  entry_points={
282
171
  'console_scripts': ['sky = sky.cli:cli'],
283
172
  },
@@ -297,6 +186,6 @@ setuptools.setup(
297
186
  'Homepage': 'https://github.com/skypilot-org/skypilot',
298
187
  'Issues': 'https://github.com/skypilot-org/skypilot/issues',
299
188
  'Discussion': 'https://github.com/skypilot-org/skypilot/discussions',
300
- 'Documentation': 'https://skypilot.readthedocs.io/en/latest/',
189
+ 'Documentation': 'https://docs.skypilot.co/',
301
190
  },
302
191
  )
sky/sky_logging.py CHANGED
@@ -1,20 +1,27 @@
1
1
  """Logging utilities."""
2
2
  import builtins
3
3
  import contextlib
4
+ from datetime import datetime
4
5
  import logging
6
+ import os
5
7
  import sys
6
8
  import threading
7
9
 
8
10
  import colorama
9
11
 
12
+ from sky.skylet import constants
10
13
  from sky.utils import env_options
11
14
  from sky.utils import rich_utils
12
15
 
13
- # If the SKYPILOT_MINIMIZE_LOGGING environment variable is set to True,
14
- # remove logging prefixes and unnecessary information in optimizer
15
- _FORMAT = (None if env_options.Options.MINIMIZE_LOGGING.get() else
16
- '%(levelname).1s %(asctime)s %(filename)s:%(lineno)d] %(message)s')
16
+ # UX: Should we show logging prefixes and some extra information in optimizer?
17
+ _FORMAT = '%(levelname).1s %(asctime)s %(filename)s:%(lineno)d] %(message)s'
17
18
  _DATE_FORMAT = '%m-%d %H:%M:%S'
19
+ _SENSITIVE_LOGGER = ['sky.provisioner', 'sky.optimizer']
20
+
21
+
22
+ def _show_logging_prefix():
23
+ return env_options.Options.SHOW_DEBUG_INFO.get(
24
+ ) or not env_options.Options.MINIMIZE_LOGGING.get()
18
25
 
19
26
 
20
27
  class NewLineFormatter(logging.Formatter):
@@ -34,17 +41,11 @@ class NewLineFormatter(logging.Formatter):
34
41
  return msg
35
42
 
36
43
 
37
- class RichSafeStreamHandler(logging.StreamHandler):
38
-
39
- def emit(self, record: logging.LogRecord) -> None:
40
- with rich_utils.safe_logger():
41
- return super().emit(record)
42
-
43
-
44
44
  _root_logger = logging.getLogger('sky')
45
45
  _default_handler = None
46
46
  _logging_config = threading.local()
47
47
 
48
+ NO_PREFIX_FORMATTER = NewLineFormatter(None, datefmt=_DATE_FORMAT)
48
49
  FORMATTER = NewLineFormatter(_FORMAT, datefmt=_DATE_FORMAT)
49
50
  DIM_FORMATTER = NewLineFormatter(_FORMAT, datefmt=_DATE_FORMAT, dim=True)
50
51
 
@@ -60,17 +61,37 @@ def _setup_logger():
60
61
  _root_logger.setLevel(logging.DEBUG)
61
62
  global _default_handler
62
63
  if _default_handler is None:
63
- _default_handler = RichSafeStreamHandler(sys.stdout)
64
+ _default_handler = rich_utils.RichSafeStreamHandler(sys.stdout)
64
65
  _default_handler.flush = sys.stdout.flush # type: ignore
65
66
  if env_options.Options.SHOW_DEBUG_INFO.get():
66
67
  _default_handler.setLevel(logging.DEBUG)
67
68
  else:
68
69
  _default_handler.setLevel(logging.INFO)
69
70
  _root_logger.addHandler(_default_handler)
70
- _default_handler.setFormatter(FORMATTER)
71
+ if _show_logging_prefix():
72
+ _default_handler.setFormatter(FORMATTER)
73
+ else:
74
+ _default_handler.setFormatter(NO_PREFIX_FORMATTER)
71
75
  # Setting this will avoid the message
72
76
  # being propagated to the parent logger.
73
77
  _root_logger.propagate = False
78
+ if env_options.Options.SUPPRESS_SENSITIVE_LOG.get():
79
+ # If the sensitive log is enabled, we reinitialize a new handler
80
+ # and force set the level to INFO to suppress the debug logs
81
+ # for certain loggers.
82
+ for logger_name in _SENSITIVE_LOGGER:
83
+ logger = logging.getLogger(logger_name)
84
+ handler_to_logger = rich_utils.RichSafeStreamHandler(sys.stdout)
85
+ handler_to_logger.flush = sys.stdout.flush # type: ignore
86
+ logger.addHandler(handler_to_logger)
87
+ logger.setLevel(logging.INFO)
88
+ if _show_logging_prefix():
89
+ handler_to_logger.setFormatter(FORMATTER)
90
+ else:
91
+ handler_to_logger.setFormatter(NO_PREFIX_FORMATTER)
92
+ # Do not propagate to the parent logger to avoid parent
93
+ # logger printing the logs.
94
+ logger.propagate = False
74
95
 
75
96
 
76
97
  def reload_logger():
@@ -91,10 +112,21 @@ def reload_logger():
91
112
  _setup_logger()
92
113
 
93
114
 
94
- def init_logger(name: str):
115
+ def init_logger(name: str) -> logging.Logger:
95
116
  return logging.getLogger(name)
96
117
 
97
118
 
119
+ @contextlib.contextmanager
120
+ def set_logging_level(logger: str, level: int):
121
+ logger = logging.getLogger(logger)
122
+ original_level = logger.level
123
+ logger.setLevel(level)
124
+ try:
125
+ yield
126
+ finally:
127
+ logger.setLevel(original_level)
128
+
129
+
98
130
  @contextlib.contextmanager
99
131
  def silent():
100
132
  """Make all sky_logging.print() and logger.{info, warning...} silent.
@@ -128,3 +160,16 @@ def is_silent():
128
160
  # threads.
129
161
  _logging_config.is_silent = False
130
162
  return _logging_config.is_silent
163
+
164
+
165
+ def get_run_timestamp() -> str:
166
+ return 'sky-' + datetime.now().strftime('%Y-%m-%d-%H-%M-%S-%f')
167
+
168
+
169
+ def generate_tmp_logging_file_path(file_name: str) -> str:
170
+ """Generate an absolute path of a tmp file for logging."""
171
+ run_timestamp = get_run_timestamp()
172
+ log_dir = os.path.join(constants.SKY_LOGS_DIRECTORY, run_timestamp)
173
+ log_path = os.path.expanduser(os.path.join(log_dir, file_name))
174
+
175
+ return log_path
@@ -9,7 +9,7 @@ import psutil
9
9
  from sky import sky_logging
10
10
  from sky.skylet import configs
11
11
  from sky.skylet import constants
12
- from sky.utils import common_utils
12
+ from sky.utils import message_utils
13
13
 
14
14
  logger = sky_logging.init_logger(__name__)
15
15
 
@@ -85,7 +85,7 @@ def get_is_autostopping() -> bool:
85
85
  def get_is_autostopping_payload() -> str:
86
86
  """Payload for whether the cluster is in the process of autostopping."""
87
87
  is_autostopping = get_is_autostopping()
88
- return common_utils.encode_payload(is_autostopping)
88
+ return message_utils.encode_payload(is_autostopping)
89
89
 
90
90
 
91
91
  def get_last_active_time() -> float: