skypilot-nightly 1.0.0.dev20250905__py3-none-any.whl → 1.0.0.dev20251210__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 (429) hide show
  1. sky/__init__.py +12 -2
  2. sky/adaptors/aws.py +27 -22
  3. sky/adaptors/common.py +25 -2
  4. sky/adaptors/coreweave.py +278 -0
  5. sky/adaptors/do.py +8 -2
  6. sky/adaptors/gcp.py +11 -0
  7. sky/adaptors/ibm.py +5 -2
  8. sky/adaptors/kubernetes.py +64 -0
  9. sky/adaptors/nebius.py +3 -1
  10. sky/adaptors/primeintellect.py +1 -0
  11. sky/adaptors/seeweb.py +183 -0
  12. sky/adaptors/shadeform.py +89 -0
  13. sky/adaptors/slurm.py +478 -0
  14. sky/admin_policy.py +20 -0
  15. sky/authentication.py +157 -263
  16. sky/backends/__init__.py +3 -2
  17. sky/backends/backend.py +11 -3
  18. sky/backends/backend_utils.py +630 -185
  19. sky/backends/cloud_vm_ray_backend.py +1111 -928
  20. sky/backends/local_docker_backend.py +9 -5
  21. sky/backends/task_codegen.py +971 -0
  22. sky/backends/wheel_utils.py +18 -0
  23. sky/catalog/__init__.py +8 -3
  24. sky/catalog/aws_catalog.py +4 -0
  25. sky/catalog/common.py +19 -1
  26. sky/catalog/data_fetchers/fetch_aws.py +102 -80
  27. sky/catalog/data_fetchers/fetch_gcp.py +30 -3
  28. sky/catalog/data_fetchers/fetch_nebius.py +9 -6
  29. sky/catalog/data_fetchers/fetch_runpod.py +698 -0
  30. sky/catalog/data_fetchers/fetch_seeweb.py +329 -0
  31. sky/catalog/data_fetchers/fetch_shadeform.py +142 -0
  32. sky/catalog/kubernetes_catalog.py +36 -32
  33. sky/catalog/primeintellect_catalog.py +95 -0
  34. sky/catalog/runpod_catalog.py +5 -1
  35. sky/catalog/seeweb_catalog.py +184 -0
  36. sky/catalog/shadeform_catalog.py +165 -0
  37. sky/catalog/slurm_catalog.py +243 -0
  38. sky/check.py +87 -46
  39. sky/client/cli/command.py +1004 -434
  40. sky/client/cli/flags.py +4 -2
  41. sky/{volumes/utils.py → client/cli/table_utils.py} +111 -13
  42. sky/client/cli/utils.py +79 -0
  43. sky/client/common.py +12 -2
  44. sky/client/sdk.py +188 -65
  45. sky/client/sdk_async.py +34 -33
  46. sky/cloud_stores.py +82 -3
  47. sky/clouds/__init__.py +8 -0
  48. sky/clouds/aws.py +337 -129
  49. sky/clouds/azure.py +24 -18
  50. sky/clouds/cloud.py +47 -13
  51. sky/clouds/cudo.py +16 -13
  52. sky/clouds/do.py +9 -7
  53. sky/clouds/fluidstack.py +12 -5
  54. sky/clouds/gcp.py +14 -7
  55. sky/clouds/hyperbolic.py +12 -5
  56. sky/clouds/ibm.py +12 -5
  57. sky/clouds/kubernetes.py +80 -45
  58. sky/clouds/lambda_cloud.py +12 -5
  59. sky/clouds/nebius.py +23 -9
  60. sky/clouds/oci.py +19 -12
  61. sky/clouds/paperspace.py +4 -1
  62. sky/clouds/primeintellect.py +317 -0
  63. sky/clouds/runpod.py +85 -24
  64. sky/clouds/scp.py +12 -8
  65. sky/clouds/seeweb.py +477 -0
  66. sky/clouds/shadeform.py +400 -0
  67. sky/clouds/slurm.py +578 -0
  68. sky/clouds/ssh.py +6 -3
  69. sky/clouds/utils/scp_utils.py +61 -50
  70. sky/clouds/vast.py +43 -27
  71. sky/clouds/vsphere.py +14 -16
  72. sky/core.py +296 -195
  73. sky/dashboard/out/404.html +1 -1
  74. sky/dashboard/out/_next/static/KYAhEFa3FTfq4JyKVgo-s/_buildManifest.js +1 -0
  75. sky/dashboard/out/_next/static/chunks/1141-9c810f01ff4f398a.js +11 -0
  76. sky/dashboard/out/_next/static/chunks/1871-7e202677c42f43fe.js +6 -0
  77. sky/dashboard/out/_next/static/chunks/2260-7703229c33c5ebd5.js +1 -0
  78. sky/dashboard/out/_next/static/chunks/2369.fc20f0c2c8ed9fe7.js +15 -0
  79. sky/dashboard/out/_next/static/chunks/2755.edd818326d489a1d.js +26 -0
  80. sky/dashboard/out/_next/static/chunks/3294.ddda8c6c6f9f24dc.js +1 -0
  81. sky/dashboard/out/_next/static/chunks/3785.7e245f318f9d1121.js +1 -0
  82. sky/dashboard/out/_next/static/chunks/{6601-06114c982db410b6.js → 3800-b589397dc09c5b4e.js} +1 -1
  83. sky/dashboard/out/_next/static/chunks/3850-fd5696f3bbbaddae.js +1 -0
  84. sky/dashboard/out/_next/static/chunks/4725.172ede95d1b21022.js +1 -0
  85. sky/dashboard/out/_next/static/chunks/4937.a2baa2df5572a276.js +15 -0
  86. sky/dashboard/out/_next/static/chunks/6212-7bd06f60ba693125.js +13 -0
  87. sky/dashboard/out/_next/static/chunks/6856-da20c5fd999f319c.js +1 -0
  88. sky/dashboard/out/_next/static/chunks/6990-09cbf02d3cd518c3.js +1 -0
  89. sky/dashboard/out/_next/static/chunks/7359-c8d04e06886000b3.js +30 -0
  90. sky/dashboard/out/_next/static/chunks/7615-019513abc55b3b47.js +1 -0
  91. sky/dashboard/out/_next/static/chunks/8640.5b9475a2d18c5416.js +16 -0
  92. sky/dashboard/out/_next/static/chunks/8969-452f9d5cbdd2dc73.js +1 -0
  93. sky/dashboard/out/_next/static/chunks/9025.fa408f3242e9028d.js +6 -0
  94. sky/dashboard/out/_next/static/chunks/9353-8369df1cf105221c.js +1 -0
  95. sky/dashboard/out/_next/static/chunks/9360.a536cf6b1fa42355.js +31 -0
  96. sky/dashboard/out/_next/static/chunks/9847.3aaca6bb33455140.js +30 -0
  97. sky/dashboard/out/_next/static/chunks/pages/_app-68b647e26f9d2793.js +34 -0
  98. sky/dashboard/out/_next/static/chunks/pages/clusters/[cluster]/[job]-33f525539665fdfd.js +16 -0
  99. sky/dashboard/out/_next/static/chunks/pages/clusters/[cluster]-a7565f586ef86467.js +1 -0
  100. sky/dashboard/out/_next/static/chunks/pages/clusters-9e5d47818b9bdadd.js +1 -0
  101. sky/dashboard/out/_next/static/chunks/pages/{config-dfb9bf07b13045f4.js → config-718cdc365de82689.js} +1 -1
  102. sky/dashboard/out/_next/static/chunks/pages/infra/{[context]-6563820e094f68ca.js → [context]-12c559ec4d81fdbd.js} +1 -1
  103. sky/dashboard/out/_next/static/chunks/pages/{infra-aabba60d57826e0f.js → infra-d187cd0413d72475.js} +1 -1
  104. sky/dashboard/out/_next/static/chunks/pages/jobs/[job]-895847b6cf200b04.js +16 -0
  105. sky/dashboard/out/_next/static/chunks/pages/jobs/pools/[pool]-8d0f4655400b4eb9.js +21 -0
  106. sky/dashboard/out/_next/static/chunks/pages/jobs-e5a98f17f8513a96.js +1 -0
  107. sky/dashboard/out/_next/static/chunks/pages/plugins/[...slug]-4f46050ca065d8f8.js +1 -0
  108. sky/dashboard/out/_next/static/chunks/pages/users-2f7646eb77785a2c.js +1 -0
  109. sky/dashboard/out/_next/static/chunks/pages/volumes-ef19d49c6d0e8500.js +1 -0
  110. sky/dashboard/out/_next/static/chunks/pages/workspaces/{[name]-af76bb06dbb3954f.js → [name]-96e0f298308da7e2.js} +1 -1
  111. sky/dashboard/out/_next/static/chunks/pages/{workspaces-7598c33a746cdc91.js → workspaces-cb4da3abe08ebf19.js} +1 -1
  112. sky/dashboard/out/_next/static/chunks/webpack-fba3de387ff6bb08.js +1 -0
  113. sky/dashboard/out/_next/static/css/c5a4cfd2600fc715.css +3 -0
  114. sky/dashboard/out/clusters/[cluster]/[job].html +1 -1
  115. sky/dashboard/out/clusters/[cluster].html +1 -1
  116. sky/dashboard/out/clusters.html +1 -1
  117. sky/dashboard/out/config.html +1 -1
  118. sky/dashboard/out/index.html +1 -1
  119. sky/dashboard/out/infra/[context].html +1 -1
  120. sky/dashboard/out/infra.html +1 -1
  121. sky/dashboard/out/jobs/[job].html +1 -1
  122. sky/dashboard/out/jobs/pools/[pool].html +1 -1
  123. sky/dashboard/out/jobs.html +1 -1
  124. sky/dashboard/out/plugins/[...slug].html +1 -0
  125. sky/dashboard/out/users.html +1 -1
  126. sky/dashboard/out/volumes.html +1 -1
  127. sky/dashboard/out/workspace/new.html +1 -1
  128. sky/dashboard/out/workspaces/[name].html +1 -1
  129. sky/dashboard/out/workspaces.html +1 -1
  130. sky/data/data_utils.py +92 -1
  131. sky/data/mounting_utils.py +177 -30
  132. sky/data/storage.py +200 -19
  133. sky/data/storage_utils.py +10 -45
  134. sky/exceptions.py +18 -7
  135. sky/execution.py +74 -31
  136. sky/global_user_state.py +605 -191
  137. sky/jobs/__init__.py +2 -0
  138. sky/jobs/client/sdk.py +101 -4
  139. sky/jobs/client/sdk_async.py +31 -5
  140. sky/jobs/constants.py +15 -8
  141. sky/jobs/controller.py +726 -284
  142. sky/jobs/file_content_utils.py +128 -0
  143. sky/jobs/log_gc.py +193 -0
  144. sky/jobs/recovery_strategy.py +250 -100
  145. sky/jobs/scheduler.py +271 -173
  146. sky/jobs/server/core.py +367 -114
  147. sky/jobs/server/server.py +81 -35
  148. sky/jobs/server/utils.py +89 -35
  149. sky/jobs/state.py +1498 -620
  150. sky/jobs/utils.py +771 -306
  151. sky/logs/agent.py +40 -5
  152. sky/logs/aws.py +9 -19
  153. sky/metrics/utils.py +282 -39
  154. sky/models.py +2 -0
  155. sky/optimizer.py +7 -6
  156. sky/provision/__init__.py +38 -1
  157. sky/provision/aws/config.py +34 -13
  158. sky/provision/aws/instance.py +5 -2
  159. sky/provision/azure/instance.py +5 -3
  160. sky/provision/common.py +22 -0
  161. sky/provision/cudo/instance.py +4 -3
  162. sky/provision/do/instance.py +4 -3
  163. sky/provision/docker_utils.py +112 -28
  164. sky/provision/fluidstack/instance.py +6 -5
  165. sky/provision/gcp/config.py +6 -1
  166. sky/provision/gcp/instance.py +4 -2
  167. sky/provision/hyperbolic/instance.py +4 -2
  168. sky/provision/instance_setup.py +66 -20
  169. sky/provision/kubernetes/__init__.py +2 -0
  170. sky/provision/kubernetes/config.py +7 -44
  171. sky/provision/kubernetes/constants.py +0 -1
  172. sky/provision/kubernetes/instance.py +609 -213
  173. sky/provision/kubernetes/manifests/fusermount-server-daemonset.yaml +1 -2
  174. sky/provision/kubernetes/network.py +12 -8
  175. sky/provision/kubernetes/network_utils.py +8 -25
  176. sky/provision/kubernetes/utils.py +422 -422
  177. sky/provision/kubernetes/volume.py +150 -18
  178. sky/provision/lambda_cloud/instance.py +16 -13
  179. sky/provision/nebius/instance.py +6 -2
  180. sky/provision/nebius/utils.py +103 -86
  181. sky/provision/oci/instance.py +4 -2
  182. sky/provision/paperspace/instance.py +4 -3
  183. sky/provision/primeintellect/__init__.py +10 -0
  184. sky/provision/primeintellect/config.py +11 -0
  185. sky/provision/primeintellect/instance.py +454 -0
  186. sky/provision/primeintellect/utils.py +398 -0
  187. sky/provision/provisioner.py +45 -15
  188. sky/provision/runpod/__init__.py +2 -0
  189. sky/provision/runpod/instance.py +4 -3
  190. sky/provision/runpod/volume.py +69 -13
  191. sky/provision/scp/instance.py +307 -130
  192. sky/provision/seeweb/__init__.py +11 -0
  193. sky/provision/seeweb/config.py +13 -0
  194. sky/provision/seeweb/instance.py +812 -0
  195. sky/provision/shadeform/__init__.py +11 -0
  196. sky/provision/shadeform/config.py +12 -0
  197. sky/provision/shadeform/instance.py +351 -0
  198. sky/provision/shadeform/shadeform_utils.py +83 -0
  199. sky/provision/slurm/__init__.py +12 -0
  200. sky/provision/slurm/config.py +13 -0
  201. sky/provision/slurm/instance.py +572 -0
  202. sky/provision/slurm/utils.py +583 -0
  203. sky/provision/vast/instance.py +9 -4
  204. sky/provision/vast/utils.py +10 -6
  205. sky/provision/volume.py +164 -0
  206. sky/provision/vsphere/common/ssl_helper.py +1 -1
  207. sky/provision/vsphere/common/vapiconnect.py +2 -1
  208. sky/provision/vsphere/common/vim_utils.py +3 -2
  209. sky/provision/vsphere/instance.py +8 -6
  210. sky/provision/vsphere/vsphere_utils.py +8 -1
  211. sky/resources.py +11 -3
  212. sky/schemas/api/responses.py +107 -6
  213. sky/schemas/db/global_user_state/008_skylet_ssh_tunnel_metadata.py +34 -0
  214. sky/schemas/db/global_user_state/009_last_activity_and_launched_at.py +89 -0
  215. sky/schemas/db/global_user_state/010_save_ssh_key.py +66 -0
  216. sky/schemas/db/global_user_state/011_is_ephemeral.py +34 -0
  217. sky/schemas/db/kv_cache/001_initial_schema.py +29 -0
  218. sky/schemas/db/serve_state/002_yaml_content.py +34 -0
  219. sky/schemas/db/skypilot_config/001_initial_schema.py +30 -0
  220. sky/schemas/db/spot_jobs/002_cluster_pool.py +3 -3
  221. sky/schemas/db/spot_jobs/004_job_file_contents.py +42 -0
  222. sky/schemas/db/spot_jobs/005_logs_gc.py +38 -0
  223. sky/schemas/db/spot_jobs/006_controller_pid_started_at.py +34 -0
  224. sky/schemas/db/spot_jobs/007_config_file_content.py +34 -0
  225. sky/schemas/generated/jobsv1_pb2.py +86 -0
  226. sky/schemas/generated/jobsv1_pb2.pyi +254 -0
  227. sky/schemas/generated/jobsv1_pb2_grpc.py +542 -0
  228. sky/schemas/generated/managed_jobsv1_pb2.py +76 -0
  229. sky/schemas/generated/managed_jobsv1_pb2.pyi +278 -0
  230. sky/schemas/generated/managed_jobsv1_pb2_grpc.py +278 -0
  231. sky/schemas/generated/servev1_pb2.py +58 -0
  232. sky/schemas/generated/servev1_pb2.pyi +115 -0
  233. sky/schemas/generated/servev1_pb2_grpc.py +322 -0
  234. sky/serve/autoscalers.py +2 -0
  235. sky/serve/client/impl.py +55 -21
  236. sky/serve/constants.py +4 -3
  237. sky/serve/controller.py +17 -11
  238. sky/serve/load_balancing_policies.py +1 -1
  239. sky/serve/replica_managers.py +219 -142
  240. sky/serve/serve_rpc_utils.py +179 -0
  241. sky/serve/serve_state.py +63 -54
  242. sky/serve/serve_utils.py +145 -109
  243. sky/serve/server/core.py +46 -25
  244. sky/serve/server/impl.py +311 -162
  245. sky/serve/server/server.py +21 -19
  246. sky/serve/service.py +84 -68
  247. sky/serve/service_spec.py +45 -7
  248. sky/server/auth/loopback.py +38 -0
  249. sky/server/auth/oauth2_proxy.py +12 -7
  250. sky/server/common.py +47 -24
  251. sky/server/config.py +62 -28
  252. sky/server/constants.py +9 -1
  253. sky/server/daemons.py +109 -38
  254. sky/server/metrics.py +76 -96
  255. sky/server/middleware_utils.py +166 -0
  256. sky/server/plugins.py +222 -0
  257. sky/server/requests/executor.py +384 -145
  258. sky/server/requests/payloads.py +83 -19
  259. sky/server/requests/preconditions.py +15 -13
  260. sky/server/requests/request_names.py +123 -0
  261. sky/server/requests/requests.py +511 -157
  262. sky/server/requests/serializers/decoders.py +48 -17
  263. sky/server/requests/serializers/encoders.py +102 -20
  264. sky/server/requests/serializers/return_value_serializers.py +60 -0
  265. sky/server/requests/threads.py +117 -0
  266. sky/server/rest.py +116 -24
  267. sky/server/server.py +497 -179
  268. sky/server/server_utils.py +30 -0
  269. sky/server/stream_utils.py +219 -45
  270. sky/server/uvicorn.py +30 -19
  271. sky/setup_files/MANIFEST.in +6 -1
  272. sky/setup_files/alembic.ini +8 -0
  273. sky/setup_files/dependencies.py +64 -19
  274. sky/setup_files/setup.py +44 -44
  275. sky/sky_logging.py +13 -5
  276. sky/skylet/attempt_skylet.py +116 -24
  277. sky/skylet/configs.py +3 -1
  278. sky/skylet/constants.py +139 -29
  279. sky/skylet/events.py +74 -14
  280. sky/skylet/executor/__init__.py +1 -0
  281. sky/skylet/executor/slurm.py +189 -0
  282. sky/skylet/job_lib.py +143 -105
  283. sky/skylet/log_lib.py +252 -8
  284. sky/skylet/log_lib.pyi +47 -7
  285. sky/skylet/providers/ibm/node_provider.py +12 -8
  286. sky/skylet/providers/ibm/vpc_provider.py +13 -12
  287. sky/skylet/runtime_utils.py +21 -0
  288. sky/skylet/services.py +524 -0
  289. sky/skylet/skylet.py +27 -2
  290. sky/skylet/subprocess_daemon.py +104 -28
  291. sky/skypilot_config.py +99 -79
  292. sky/ssh_node_pools/constants.py +12 -0
  293. sky/ssh_node_pools/core.py +40 -3
  294. sky/ssh_node_pools/deploy/__init__.py +4 -0
  295. sky/ssh_node_pools/deploy/deploy.py +952 -0
  296. sky/ssh_node_pools/deploy/tunnel_utils.py +199 -0
  297. sky/ssh_node_pools/deploy/utils.py +173 -0
  298. sky/ssh_node_pools/server.py +20 -21
  299. sky/{utils/kubernetes/ssh_utils.py → ssh_node_pools/utils.py} +9 -6
  300. sky/task.py +221 -104
  301. sky/templates/aws-ray.yml.j2 +1 -0
  302. sky/templates/azure-ray.yml.j2 +1 -0
  303. sky/templates/cudo-ray.yml.j2 +1 -0
  304. sky/templates/do-ray.yml.j2 +1 -0
  305. sky/templates/fluidstack-ray.yml.j2 +1 -0
  306. sky/templates/gcp-ray.yml.j2 +1 -0
  307. sky/templates/hyperbolic-ray.yml.j2 +1 -0
  308. sky/templates/ibm-ray.yml.j2 +2 -1
  309. sky/templates/jobs-controller.yaml.j2 +3 -0
  310. sky/templates/kubernetes-ray.yml.j2 +204 -55
  311. sky/templates/lambda-ray.yml.j2 +1 -0
  312. sky/templates/nebius-ray.yml.j2 +3 -0
  313. sky/templates/oci-ray.yml.j2 +1 -0
  314. sky/templates/paperspace-ray.yml.j2 +1 -0
  315. sky/templates/primeintellect-ray.yml.j2 +72 -0
  316. sky/templates/runpod-ray.yml.j2 +1 -0
  317. sky/templates/scp-ray.yml.j2 +1 -0
  318. sky/templates/seeweb-ray.yml.j2 +171 -0
  319. sky/templates/shadeform-ray.yml.j2 +73 -0
  320. sky/templates/slurm-ray.yml.j2 +85 -0
  321. sky/templates/vast-ray.yml.j2 +2 -0
  322. sky/templates/vsphere-ray.yml.j2 +1 -0
  323. sky/templates/websocket_proxy.py +188 -43
  324. sky/usage/usage_lib.py +16 -4
  325. sky/users/model.conf +1 -1
  326. sky/users/permission.py +84 -44
  327. sky/users/rbac.py +31 -3
  328. sky/utils/accelerator_registry.py +6 -3
  329. sky/utils/admin_policy_utils.py +18 -5
  330. sky/utils/annotations.py +128 -6
  331. sky/utils/asyncio_utils.py +78 -0
  332. sky/utils/atomic.py +1 -1
  333. sky/utils/auth_utils.py +153 -0
  334. sky/utils/cli_utils/status_utils.py +12 -7
  335. sky/utils/cluster_utils.py +28 -6
  336. sky/utils/command_runner.py +283 -30
  337. sky/utils/command_runner.pyi +63 -7
  338. sky/utils/common.py +3 -1
  339. sky/utils/common_utils.py +55 -7
  340. sky/utils/config_utils.py +1 -14
  341. sky/utils/context.py +127 -40
  342. sky/utils/context_utils.py +73 -18
  343. sky/utils/controller_utils.py +229 -70
  344. sky/utils/db/db_utils.py +95 -18
  345. sky/utils/db/kv_cache.py +149 -0
  346. sky/utils/db/migration_utils.py +24 -7
  347. sky/utils/env_options.py +4 -0
  348. sky/utils/git.py +559 -1
  349. sky/utils/kubernetes/create_cluster.sh +15 -30
  350. sky/utils/kubernetes/delete_cluster.sh +10 -7
  351. sky/utils/kubernetes/generate_kind_config.py +6 -66
  352. sky/utils/kubernetes/gpu_labeler.py +13 -3
  353. sky/utils/kubernetes/k8s_gpu_labeler_job.yaml +2 -1
  354. sky/utils/kubernetes/k8s_gpu_labeler_setup.yaml +16 -16
  355. sky/utils/kubernetes/kubernetes_deploy_utils.py +187 -260
  356. sky/utils/kubernetes/rsync_helper.sh +11 -3
  357. sky/utils/kubernetes/ssh-tunnel.sh +7 -376
  358. sky/utils/kubernetes_enums.py +7 -15
  359. sky/utils/lock_events.py +4 -4
  360. sky/utils/locks.py +128 -31
  361. sky/utils/log_utils.py +0 -319
  362. sky/utils/resource_checker.py +13 -10
  363. sky/utils/resources_utils.py +53 -29
  364. sky/utils/rich_utils.py +8 -4
  365. sky/utils/schemas.py +138 -52
  366. sky/utils/subprocess_utils.py +17 -4
  367. sky/utils/thread_utils.py +91 -0
  368. sky/utils/timeline.py +2 -1
  369. sky/utils/ux_utils.py +35 -1
  370. sky/utils/volume.py +88 -4
  371. sky/utils/yaml_utils.py +9 -0
  372. sky/volumes/client/sdk.py +48 -10
  373. sky/volumes/server/core.py +59 -22
  374. sky/volumes/server/server.py +46 -17
  375. sky/volumes/volume.py +54 -42
  376. sky/workspaces/core.py +57 -21
  377. sky/workspaces/server.py +13 -12
  378. sky_templates/README.md +3 -0
  379. sky_templates/__init__.py +3 -0
  380. sky_templates/ray/__init__.py +0 -0
  381. sky_templates/ray/start_cluster +183 -0
  382. sky_templates/ray/stop_cluster +75 -0
  383. {skypilot_nightly-1.0.0.dev20250905.dist-info → skypilot_nightly-1.0.0.dev20251210.dist-info}/METADATA +343 -65
  384. skypilot_nightly-1.0.0.dev20251210.dist-info/RECORD +629 -0
  385. skypilot_nightly-1.0.0.dev20251210.dist-info/top_level.txt +2 -0
  386. sky/client/cli/git.py +0 -549
  387. sky/dashboard/out/_next/static/chunks/1121-408ed10b2f9fce17.js +0 -1
  388. sky/dashboard/out/_next/static/chunks/1141-943efc7aff0f0c06.js +0 -1
  389. sky/dashboard/out/_next/static/chunks/1836-37fede578e2da5f8.js +0 -40
  390. sky/dashboard/out/_next/static/chunks/3015-86cabed5d4669ad0.js +0 -1
  391. sky/dashboard/out/_next/static/chunks/3294.c80326aec9bfed40.js +0 -6
  392. sky/dashboard/out/_next/static/chunks/3785.4872a2f3aa489880.js +0 -1
  393. sky/dashboard/out/_next/static/chunks/3850-ff4a9a69d978632b.js +0 -1
  394. sky/dashboard/out/_next/static/chunks/4045.b30465273dc5e468.js +0 -21
  395. sky/dashboard/out/_next/static/chunks/4676-9da7fdbde90b5549.js +0 -10
  396. sky/dashboard/out/_next/static/chunks/4725.10f7a9a5d3ea8208.js +0 -1
  397. sky/dashboard/out/_next/static/chunks/5339.3fda4a4010ff4e06.js +0 -51
  398. sky/dashboard/out/_next/static/chunks/6135-4b4d5e824b7f9d3c.js +0 -1
  399. sky/dashboard/out/_next/static/chunks/649.b9d7f7d10c1b8c53.js +0 -45
  400. sky/dashboard/out/_next/static/chunks/6856-dca7962af4814e1b.js +0 -1
  401. sky/dashboard/out/_next/static/chunks/6990-08b2a1cae076a943.js +0 -1
  402. sky/dashboard/out/_next/static/chunks/7325.b4bc99ce0892dcd5.js +0 -6
  403. sky/dashboard/out/_next/static/chunks/754-d0da8ab45f9509e9.js +0 -18
  404. sky/dashboard/out/_next/static/chunks/7669.1f5d9a402bf5cc42.js +0 -36
  405. sky/dashboard/out/_next/static/chunks/8969-0be3036bf86f8256.js +0 -1
  406. sky/dashboard/out/_next/static/chunks/9025.c12318fb6a1a9093.js +0 -6
  407. sky/dashboard/out/_next/static/chunks/9037-fa1737818d0a0969.js +0 -6
  408. sky/dashboard/out/_next/static/chunks/pages/_app-ce361c6959bc2001.js +0 -34
  409. sky/dashboard/out/_next/static/chunks/pages/clusters/[cluster]/[job]-1cbba24bd1bd35f8.js +0 -16
  410. sky/dashboard/out/_next/static/chunks/pages/clusters/[cluster]-0b4b35dc1dfe046c.js +0 -16
  411. sky/dashboard/out/_next/static/chunks/pages/clusters-469814d711d63b1b.js +0 -1
  412. sky/dashboard/out/_next/static/chunks/pages/jobs/[job]-dd64309c3fe67ed2.js +0 -11
  413. sky/dashboard/out/_next/static/chunks/pages/jobs/pools/[pool]-07349868f7905d37.js +0 -16
  414. sky/dashboard/out/_next/static/chunks/pages/jobs-1f70d9faa564804f.js +0 -1
  415. sky/dashboard/out/_next/static/chunks/pages/users-018bf31cda52e11b.js +0 -1
  416. sky/dashboard/out/_next/static/chunks/pages/volumes-739726d6b823f532.js +0 -1
  417. sky/dashboard/out/_next/static/chunks/webpack-4fe903277b57b523.js +0 -1
  418. sky/dashboard/out/_next/static/css/4614e06482d7309e.css +0 -3
  419. sky/dashboard/out/_next/static/mS-4qZPSkRuA1u-g2wQhg/_buildManifest.js +0 -1
  420. sky/templates/kubernetes-ssh-jump.yml.j2 +0 -94
  421. sky/utils/kubernetes/cleanup-tunnel.sh +0 -62
  422. sky/utils/kubernetes/deploy_remote_cluster.py +0 -1299
  423. sky/utils/kubernetes/ssh_jump_lifecycle_manager.py +0 -191
  424. skypilot_nightly-1.0.0.dev20250905.dist-info/RECORD +0 -547
  425. skypilot_nightly-1.0.0.dev20250905.dist-info/top_level.txt +0 -1
  426. /sky/dashboard/out/_next/static/{mS-4qZPSkRuA1u-g2wQhg → KYAhEFa3FTfq4JyKVgo-s}/_ssgManifest.js +0 -0
  427. {skypilot_nightly-1.0.0.dev20250905.dist-info → skypilot_nightly-1.0.0.dev20251210.dist-info}/WHEEL +0 -0
  428. {skypilot_nightly-1.0.0.dev20250905.dist-info → skypilot_nightly-1.0.0.dev20251210.dist-info}/entry_points.txt +0 -0
  429. {skypilot_nightly-1.0.0.dev20250905.dist-info → skypilot_nightly-1.0.0.dev20251210.dist-info}/licenses/LICENSE +0 -0
@@ -1,4 +1,5 @@
1
1
  """Kubernetes adaptors"""
2
+ import functools
2
3
  import logging
3
4
  import os
4
5
  import platform
@@ -162,8 +163,61 @@ def list_kube_config_contexts():
162
163
  return kubernetes.config.list_kube_config_contexts(_get_config_file())
163
164
 
164
165
 
166
+ class ClientWrapper:
167
+ """Wrapper around the kubernetes API clients.
168
+
169
+ This is needed because we cache kubernetes.client.ApiClient and other typed
170
+ clients (e.g. kubernetes.client.CoreV1Api) and lru_cache.cache_clear() does
171
+ not call close() on the client to cleanup external resources like
172
+ semaphores. This decorator wraps the client with __del__ to ensure the
173
+ external state of kubernetes clients are properly cleaned up on GC.
174
+ """
175
+
176
+ def __init__(self, client):
177
+ self._client = client
178
+
179
+ def __getattr__(self, name):
180
+ """Delegate to the underlying client"""
181
+ return getattr(self._client, name)
182
+
183
+ def __del__(self):
184
+ """Clean up the underlying client"""
185
+ try:
186
+ real_client = None
187
+ if isinstance(self._client, kubernetes.client.ApiClient):
188
+ real_client = self._client
189
+ elif isinstance(self._client, kubernetes.watch.Watch):
190
+ real_client = getattr(self._client, '_api_client', None)
191
+ else:
192
+ # Otherwise, the client is a typed client, the typed client
193
+ # is generated by codegen and all of them should have an
194
+ # 'api_client' attribute referring to the real client.
195
+ real_client = getattr(self._client, 'api_client', None)
196
+ if real_client is not None:
197
+ real_client.close()
198
+ else:
199
+ # logger may already be cleaned up during __del__ at shutdown
200
+ if logger is not None:
201
+ logger.debug(f'No client found for {self._client}')
202
+ except Exception as e: # pylint: disable=broad-except
203
+ if logger is not None:
204
+ logger.debug(f'Error closing Kubernetes client: {e}')
205
+
206
+
207
+ def wrap_kubernetes_client(func):
208
+ """Wraps kubernetes API clients for proper cleanup."""
209
+
210
+ @functools.wraps(func)
211
+ def wrapper(*args, **kwargs):
212
+ obj = func(*args, **kwargs)
213
+ return ClientWrapper(obj)
214
+
215
+ return wrapper
216
+
217
+
165
218
  @_api_logging_decorator('urllib3', logging.ERROR)
166
219
  @annotations.lru_cache(scope='request')
220
+ @wrap_kubernetes_client
167
221
  def core_api(context: Optional[str] = None):
168
222
  _load_config(context)
169
223
  return kubernetes.client.CoreV1Api()
@@ -171,6 +225,7 @@ def core_api(context: Optional[str] = None):
171
225
 
172
226
  @_api_logging_decorator('urllib3', logging.ERROR)
173
227
  @annotations.lru_cache(scope='request')
228
+ @wrap_kubernetes_client
174
229
  def storage_api(context: Optional[str] = None):
175
230
  _load_config(context)
176
231
  return kubernetes.client.StorageV1Api()
@@ -178,6 +233,7 @@ def storage_api(context: Optional[str] = None):
178
233
 
179
234
  @_api_logging_decorator('urllib3', logging.ERROR)
180
235
  @annotations.lru_cache(scope='request')
236
+ @wrap_kubernetes_client
181
237
  def auth_api(context: Optional[str] = None):
182
238
  _load_config(context)
183
239
  return kubernetes.client.RbacAuthorizationV1Api()
@@ -185,6 +241,7 @@ def auth_api(context: Optional[str] = None):
185
241
 
186
242
  @_api_logging_decorator('urllib3', logging.ERROR)
187
243
  @annotations.lru_cache(scope='request')
244
+ @wrap_kubernetes_client
188
245
  def networking_api(context: Optional[str] = None):
189
246
  _load_config(context)
190
247
  return kubernetes.client.NetworkingV1Api()
@@ -192,6 +249,7 @@ def networking_api(context: Optional[str] = None):
192
249
 
193
250
  @_api_logging_decorator('urllib3', logging.ERROR)
194
251
  @annotations.lru_cache(scope='request')
252
+ @wrap_kubernetes_client
195
253
  def custom_objects_api(context: Optional[str] = None):
196
254
  _load_config(context)
197
255
  return kubernetes.client.CustomObjectsApi()
@@ -199,6 +257,7 @@ def custom_objects_api(context: Optional[str] = None):
199
257
 
200
258
  @_api_logging_decorator('urllib3', logging.ERROR)
201
259
  @annotations.lru_cache(scope='global')
260
+ @wrap_kubernetes_client
202
261
  def node_api(context: Optional[str] = None):
203
262
  _load_config(context)
204
263
  return kubernetes.client.NodeV1Api()
@@ -206,6 +265,7 @@ def node_api(context: Optional[str] = None):
206
265
 
207
266
  @_api_logging_decorator('urllib3', logging.ERROR)
208
267
  @annotations.lru_cache(scope='request')
268
+ @wrap_kubernetes_client
209
269
  def apps_api(context: Optional[str] = None):
210
270
  _load_config(context)
211
271
  return kubernetes.client.AppsV1Api()
@@ -213,6 +273,7 @@ def apps_api(context: Optional[str] = None):
213
273
 
214
274
  @_api_logging_decorator('urllib3', logging.ERROR)
215
275
  @annotations.lru_cache(scope='request')
276
+ @wrap_kubernetes_client
216
277
  def batch_api(context: Optional[str] = None):
217
278
  _load_config(context)
218
279
  return kubernetes.client.BatchV1Api()
@@ -220,6 +281,7 @@ def batch_api(context: Optional[str] = None):
220
281
 
221
282
  @_api_logging_decorator('urllib3', logging.ERROR)
222
283
  @annotations.lru_cache(scope='request')
284
+ @wrap_kubernetes_client
223
285
  def api_client(context: Optional[str] = None):
224
286
  _load_config(context)
225
287
  return kubernetes.client.ApiClient()
@@ -227,6 +289,7 @@ def api_client(context: Optional[str] = None):
227
289
 
228
290
  @_api_logging_decorator('urllib3', logging.ERROR)
229
291
  @annotations.lru_cache(scope='request')
292
+ @wrap_kubernetes_client
230
293
  def custom_resources_api(context: Optional[str] = None):
231
294
  _load_config(context)
232
295
  return kubernetes.client.CustomObjectsApi()
@@ -234,6 +297,7 @@ def custom_resources_api(context: Optional[str] = None):
234
297
 
235
298
  @_api_logging_decorator('urllib3', logging.ERROR)
236
299
  @annotations.lru_cache(scope='request')
300
+ @wrap_kubernetes_client
237
301
  def watch(context: Optional[str] = None):
238
302
  _load_config(context)
239
303
  return kubernetes.watch.Watch()
sky/adaptors/nebius.py CHANGED
@@ -136,7 +136,9 @@ SKY_CHECK_NAME = 'Nebius (for Nebius Object Storae)'
136
136
 
137
137
 
138
138
  def request_error():
139
- return nebius.aio.service_error.RequestError
139
+ # pylint: disable=import-outside-toplevel
140
+ from nebius.aio import service_error
141
+ return service_error.RequestError
140
142
 
141
143
 
142
144
  def compute():
@@ -0,0 +1 @@
1
+ """Prime Intellect cloud adaptor."""
sky/adaptors/seeweb.py ADDED
@@ -0,0 +1,183 @@
1
+ """ Seeweb Adaptor """
2
+ import configparser
3
+ import pathlib
4
+ from typing import Optional
5
+
6
+ import pydantic
7
+ import requests # type: ignore
8
+
9
+ from sky.adaptors import common
10
+ from sky.utils import annotations
11
+
12
+
13
+ class SeewebError(Exception):
14
+ """Base exception for Seeweb adaptor errors."""
15
+
16
+
17
+ class SeewebCredentialsFileNotFound(SeewebError):
18
+ """Raised when the Seeweb credentials file is missing."""
19
+
20
+
21
+ class SeewebApiKeyMissing(SeewebError):
22
+ """Raised when the Seeweb API key is missing or empty."""
23
+
24
+
25
+ class SeewebAuthenticationError(SeewebError):
26
+ """Raised when authenticating with Seeweb API fails."""
27
+
28
+
29
+ _IMPORT_ERROR_MESSAGE = ('Failed to import dependencies for Seeweb.'
30
+ 'Try pip install "skypilot[seeweb]"')
31
+
32
+ ecsapi = common.LazyImport(
33
+ 'ecsapi',
34
+ import_error_message=_IMPORT_ERROR_MESSAGE,
35
+ )
36
+ boto3 = common.LazyImport('boto3', import_error_message=_IMPORT_ERROR_MESSAGE)
37
+ botocore = common.LazyImport('botocore',
38
+ import_error_message=_IMPORT_ERROR_MESSAGE)
39
+
40
+ _LAZY_MODULES = (ecsapi, boto3, botocore)
41
+
42
+
43
+ @common.load_lazy_modules(_LAZY_MODULES)
44
+ def check_compute_credentials() -> bool:
45
+ """Checks if the user has access credentials to Seeweb's compute service.
46
+
47
+ Returns True if credentials are valid; otherwise raises a SeewebError.
48
+ """
49
+ # Read API key from standard Seeweb configuration file
50
+ key_path = pathlib.Path('~/.seeweb_cloud/seeweb_keys').expanduser()
51
+ if not key_path.exists():
52
+ raise SeewebCredentialsFileNotFound(
53
+ 'Missing Seeweb API key file ~/.seeweb_cloud/seeweb_keys')
54
+
55
+ parser = configparser.ConfigParser()
56
+ parser.read(key_path)
57
+ try:
58
+ api_key = parser['DEFAULT']['api_key'].strip()
59
+ except KeyError as e:
60
+ raise SeewebApiKeyMissing(
61
+ 'Missing api_key in ~/.seeweb_cloud/seeweb_keys') from e
62
+ if not api_key:
63
+ raise SeewebApiKeyMissing(
64
+ 'Empty api_key in ~/.seeweb_cloud/seeweb_keys')
65
+
66
+ # Test connection by fetching servers list to validate the key
67
+ try:
68
+ seeweb_client = ecsapi.Api(token=api_key)
69
+ try:
70
+ seeweb_client.fetch_servers()
71
+ except pydantic.ValidationError:
72
+ # Fallback: fetch raw JSON to validate authentication
73
+ # pylint: disable=protected-access
74
+ base_url = seeweb_client._Api__generate_base_url() # type: ignore
75
+ headers = seeweb_client._Api__generate_authentication_headers(
76
+ ) # type: ignore
77
+ url = f'{base_url}/servers'
78
+ resp = requests.get(url, headers=headers, timeout=15)
79
+ resp.raise_for_status()
80
+ # If we get here, authentication worked even if schema mismatches
81
+ except Exception as e: # pylint: disable=broad-except
82
+ raise SeewebAuthenticationError(
83
+ f'Unable to authenticate with Seeweb API: {e}') from e
84
+
85
+ return True
86
+
87
+
88
+ @common.load_lazy_modules(_LAZY_MODULES)
89
+ def check_storage_credentials() -> bool:
90
+ """Checks if the user has access credentials to Seeweb's storage service.
91
+
92
+ Mirrors compute credentials validation.
93
+ """
94
+ return check_compute_credentials()
95
+
96
+
97
+ @common.load_lazy_modules(_LAZY_MODULES)
98
+ @annotations.lru_cache(scope='global', maxsize=1)
99
+ def client():
100
+ """Returns an authenticated ecsapi.Api object."""
101
+ # Create authenticated client using the same credential pattern
102
+ key_path = pathlib.Path('~/.seeweb_cloud/seeweb_keys').expanduser()
103
+ if not key_path.exists():
104
+ raise SeewebCredentialsFileNotFound(
105
+ 'Missing Seeweb API key file ~/.seeweb_cloud/seeweb_keys')
106
+
107
+ parser = configparser.ConfigParser()
108
+ parser.read(key_path)
109
+ try:
110
+ api_key = parser['DEFAULT']['api_key'].strip()
111
+ except KeyError as e:
112
+ raise SeewebApiKeyMissing(
113
+ 'Missing api_key in ~/.seeweb_cloud/seeweb_keys') from e
114
+ if not api_key:
115
+ raise SeewebApiKeyMissing(
116
+ 'Empty api_key in ~/.seeweb_cloud/seeweb_keys')
117
+
118
+ api = ecsapi.Api(token=api_key)
119
+
120
+ # Monkey-patch fetch_servers to be tolerant to API schema mismatches.
121
+ orig_fetch_servers = api.fetch_servers
122
+ orig_delete_server = api.delete_server
123
+
124
+ def _tolerant_fetch_servers(
125
+ timeout: Optional[int] = None): # type: ignore[override]
126
+ try:
127
+ return orig_fetch_servers(timeout=timeout)
128
+ except pydantic.ValidationError:
129
+ # Fallback path: fetch raw JSON, drop snapshot fields, then validate
130
+ # pylint: disable=protected-access
131
+ base_url = api._Api__generate_base_url() # type: ignore
132
+ headers = api._Api__generate_authentication_headers(
133
+ ) # type: ignore
134
+ url = f'{base_url}/servers'
135
+ resp = requests.get(url, headers=headers, timeout=timeout or 15)
136
+ resp.raise_for_status()
137
+ data = resp.json()
138
+ try:
139
+ servers = data.get('server', [])
140
+ for s in servers:
141
+ s.pop('last_restored_snapshot', None)
142
+ group = s.get('group')
143
+ if isinstance(group, dict):
144
+ group_name = group.get('name')
145
+ s['group'] = group_name if isinstance(
146
+ group_name, str) else str(group_name)
147
+ except (KeyError, TypeError, ValueError):
148
+ pass
149
+ server_list_response_cls = ecsapi._server._ServerListResponse
150
+ servers_response = server_list_response_cls.model_validate(data)
151
+ return servers_response.server
152
+
153
+ api.fetch_servers = _tolerant_fetch_servers # type: ignore[assignment]
154
+
155
+ def _tolerant_delete_server(server_name: str,
156
+ timeout: Optional[int] = None):
157
+ try:
158
+ return orig_delete_server(server_name, timeout=timeout)
159
+ except pydantic.ValidationError:
160
+ # Fallback: perform raw DELETE and interpret not_found as success
161
+ # pylint: disable=protected-access
162
+ base_url = api._Api__generate_base_url() # type: ignore
163
+ headers = api._Api__generate_authentication_headers(
164
+ ) # type: ignore
165
+ url = f'{base_url}/servers/{server_name}'
166
+ resp = requests.delete(url, headers=headers, timeout=timeout or 15)
167
+ # Treat 404 as idempotent success
168
+ if resp.status_code == 404:
169
+ return None
170
+ # Some APIs return {status: 'not_found', message: ...}
171
+ try:
172
+ data = resp.json()
173
+ if isinstance(data, dict) and data.get('status') == 'not_found':
174
+ return None
175
+ except (ValueError, TypeError):
176
+ pass
177
+ # If not clearly not_found, re-raise original behavior
178
+ resp.raise_for_status()
179
+ # Best-effort: return None to indicate deletion requested
180
+ return None
181
+
182
+ api.delete_server = _tolerant_delete_server # type: ignore[assignment]
183
+ return api
@@ -0,0 +1,89 @@
1
+ """Shadeform cloud adaptor."""
2
+
3
+ import functools
4
+ import socket
5
+ from typing import Any, Dict, List, Optional
6
+
7
+ import requests
8
+
9
+ from sky import sky_logging
10
+ from sky.provision.shadeform import shadeform_utils
11
+ from sky.utils import common_utils
12
+
13
+ logger = sky_logging.init_logger(__name__)
14
+
15
+ _shadeform_sdk = None
16
+
17
+
18
+ def import_package(func):
19
+
20
+ @functools.wraps(func)
21
+ def wrapper(*args, **kwargs):
22
+ global _shadeform_sdk
23
+ if _shadeform_sdk is None:
24
+ try:
25
+ import shadeform as _shadeform # pylint: disable=import-outside-toplevel
26
+ _shadeform_sdk = _shadeform
27
+ except ImportError:
28
+ raise ImportError(
29
+ 'Failed to import dependencies for Shadeform. '
30
+ 'Try pip install "skypilot[shadeform]"') from None
31
+ return func(*args, **kwargs)
32
+
33
+ return wrapper
34
+
35
+
36
+ @import_package
37
+ def shadeform():
38
+ """Return the shadeform package."""
39
+ return _shadeform_sdk
40
+
41
+
42
+ def list_ssh_keys() -> List[Dict[str, Any]]:
43
+ """List all SSH keys in Shadeform account."""
44
+ try:
45
+ response = shadeform_utils.get_ssh_keys()
46
+ return response.get('ssh_keys', [])
47
+ except (ValueError, KeyError, requests.exceptions.RequestException) as e:
48
+ logger.warning(f'Failed to list SSH keys from Shadeform: {e}')
49
+ return []
50
+
51
+
52
+ def add_ssh_key_to_shadeform(public_key: str) -> Optional[str]:
53
+ """Add SSH key to Shadeform if it doesn't already exist.
54
+
55
+ Args:
56
+ public_key: The SSH public key string.
57
+
58
+ Returns:
59
+ The name of the key if added successfully, None otherwise.
60
+ """
61
+ try:
62
+ # Check if key already exists
63
+ existing_keys = list_ssh_keys()
64
+ key_exists = False
65
+ key_id = None
66
+ for key in existing_keys:
67
+ if key.get('public_key') == public_key:
68
+ key_exists = True
69
+ key_id = key.get('id')
70
+ break
71
+
72
+ if key_exists:
73
+ logger.info('SSH key already exists in Shadeform account')
74
+ return key_id
75
+
76
+ # Generate a unique key name
77
+ hostname = socket.gethostname()
78
+ key_name = f'skypilot-{hostname}-{common_utils.get_user_hash()[:8]}'
79
+
80
+ # Add the key
81
+ response = shadeform_utils.add_ssh_key(name=key_name,
82
+ public_key=public_key)
83
+ key_id = response['id']
84
+ logger.info(f'Added SSH key to Shadeform: {key_name, key_id}')
85
+ return key_id
86
+
87
+ except (ValueError, KeyError, requests.exceptions.RequestException) as e:
88
+ logger.warning(f'Failed to add SSH key to Shadeform: {e}')
89
+ return None