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
sky/clouds/kubernetes.py CHANGED
@@ -1,4 +1,5 @@
1
1
  """Kubernetes."""
2
+ import concurrent.futures
2
3
  import os
3
4
  import re
4
5
  import subprocess
@@ -25,6 +26,7 @@ from sky.provision.kubernetes.utils import normalize_tpu_accelerator_name
25
26
  from sky.skylet import constants
26
27
  from sky.utils import annotations
27
28
  from sky.utils import common_utils
29
+ from sky.utils import env_options
28
30
  from sky.utils import kubernetes_enums
29
31
  from sky.utils import registry
30
32
  from sky.utils import resources_utils
@@ -47,9 +49,6 @@ _FUSERMOUNT_SHARED_DIR = '/var/run/fusermount'
47
49
  class Kubernetes(clouds.Cloud):
48
50
  """Kubernetes."""
49
51
 
50
- SKY_SSH_KEY_SECRET_NAME = 'sky-ssh-keys'
51
- SKY_SSH_JUMP_NAME = 'sky-ssh-jump-pod'
52
-
53
52
  # Limit the length of the cluster name to avoid exceeding the limit of 63
54
53
  # characters for Kubernetes resources. We limit to 42 characters (63-21) to
55
54
  # allow additional characters for creating ingress services to expose ports.
@@ -62,6 +61,7 @@ class Kubernetes(clouds.Cloud):
62
61
  _SUPPORTS_SERVICE_ACCOUNT_ON_REMOTE = True
63
62
 
64
63
  _DEFAULT_NUM_VCPUS = 2
64
+ _DEFAULT_NUM_VCPUS_WITH_GPU = 4
65
65
  _DEFAULT_MEMORY_CPU_RATIO = 1
66
66
  _DEFAULT_MEMORY_CPU_RATIO_WITH_GPU = 4 # Allocate more memory for GPU tasks
67
67
  _REPR = 'Kubernetes'
@@ -97,44 +97,52 @@ class Kubernetes(clouds.Cloud):
97
97
  # Set of contexts that has logged as temporarily unreachable
98
98
  logged_unreachable_contexts: Set[str] = set()
99
99
 
100
- @property
101
- def ssh_key_secret_field_name(self):
102
- # Use a fresh user hash to avoid conflicts in the secret object naming.
103
- # This can happen when the controller is reusing the same user hash
104
- # through USER_ID_ENV_VAR but has a different SSH key.
105
- fresh_user_hash = common_utils.generate_user_hash()
106
- return f'ssh-publickey-{fresh_user_hash}'
107
-
108
100
  @classmethod
109
101
  def _unsupported_features_for_resources(
110
- cls, resources: 'resources_lib.Resources'
102
+ cls,
103
+ resources: 'resources_lib.Resources',
104
+ region: Optional[str] = None,
111
105
  ) -> Dict[clouds.CloudImplementationFeatures, str]:
112
106
  # TODO(aylei): features need to be regional (per context) to make
113
107
  # multi-kubernetes selection/failover work.
114
108
  unsupported_features = cls._CLOUD_UNSUPPORTED_FEATURES.copy()
115
- context = resources.region
109
+ context = region if region is not None else resources.region
116
110
  if context is None:
117
- context = kubernetes_utils.get_current_kube_config_context_name()
111
+ contexts = cls.existing_allowed_contexts()
112
+ else:
113
+ contexts = [context]
118
114
  unsupported_features[clouds.CloudImplementationFeatures.STOP] = (
119
115
  'Stopping clusters is not supported on Kubernetes.')
120
116
  unsupported_features[clouds.CloudImplementationFeatures.AUTOSTOP] = (
121
117
  'Auto-stop is not supported on Kubernetes.')
122
- # Allow spot instances if supported by the cluster
123
- try:
124
- spot_label_key, _ = kubernetes_utils.get_spot_label(context)
125
- if spot_label_key is not None:
126
- unsupported_features.pop(
127
- clouds.CloudImplementationFeatures.SPOT_INSTANCE, None)
128
- # Allow custom network tier if supported by the cluster
129
- # (e.g., Nebius clusters with high performance networking)
130
- network_type, _ = cls._detect_network_type(context,
131
- resources.network_tier)
132
- if network_type.supports_high_performance_networking():
133
- unsupported_features.pop(
134
- clouds.CloudImplementationFeatures.CUSTOM_NETWORK_TIER,
135
- None)
136
- except exceptions.KubeAPIUnreachableError as e:
137
- cls._log_unreachable_context(context, str(e))
118
+ for context in contexts:
119
+ # Allow spot instances if supported by the cluster
120
+ try:
121
+ # Run spot label check and network type detection concurrently
122
+ # as they are independent operations
123
+ with concurrent.futures.ThreadPoolExecutor(
124
+ max_workers=2) as executor:
125
+ spot_future = executor.submit(
126
+ kubernetes_utils.get_spot_label, context)
127
+ network_future = executor.submit(cls._detect_network_type,
128
+ context,
129
+ resources.network_tier)
130
+
131
+ spot_label_key, _ = spot_future.result()
132
+ if spot_label_key is not None:
133
+ unsupported_features.pop(
134
+ clouds.CloudImplementationFeatures.SPOT_INSTANCE,
135
+ None)
136
+
137
+ # Allow custom network tier if supported by the cluster
138
+ # (e.g., Nebius clusters with high performance networking)
139
+ network_type, _ = network_future.result()
140
+ if network_type.supports_high_performance_networking():
141
+ unsupported_features.pop(
142
+ clouds.CloudImplementationFeatures.
143
+ CUSTOM_NETWORK_TIER, None)
144
+ except exceptions.KubeAPIUnreachableError as e:
145
+ cls._log_unreachable_context(context, str(e))
138
146
  return unsupported_features
139
147
 
140
148
  @classmethod
@@ -187,6 +195,12 @@ class Kubernetes(clouds.Cloud):
187
195
  ctx for ctx in all_contexts if not ctx.startswith('ssh-')
188
196
  ]
189
197
 
198
+ allow_all_contexts = allowed_contexts == 'all' or (
199
+ allowed_contexts is None and
200
+ env_options.Options.ALLOW_ALL_KUBERNETES_CONTEXTS.get())
201
+ if allow_all_contexts:
202
+ allowed_contexts = all_contexts
203
+
190
204
  if allowed_contexts is None:
191
205
  # Try kubeconfig if present
192
206
  current_context = (
@@ -244,10 +258,15 @@ class Kubernetes(clouds.Cloud):
244
258
  'refresh Kubernetes availability if permanent.')
245
259
 
246
260
  @classmethod
247
- def regions_with_offering(cls, instance_type: Optional[str],
248
- accelerators: Optional[Dict[str, int]],
249
- use_spot: bool, region: Optional[str],
250
- zone: Optional[str]) -> List[clouds.Region]:
261
+ def regions_with_offering(
262
+ cls,
263
+ instance_type: Optional[str],
264
+ accelerators: Optional[Dict[str, int]],
265
+ use_spot: bool,
266
+ region: Optional[str],
267
+ zone: Optional[str],
268
+ resources: Optional['resources_lib.Resources'] = None,
269
+ ) -> List[clouds.Region]:
251
270
  del accelerators, zone, use_spot # unused
252
271
  existing_contexts = cls.existing_allowed_contexts()
253
272
 
@@ -257,6 +276,19 @@ class Kubernetes(clouds.Cloud):
257
276
 
258
277
  if region is not None:
259
278
  regions = [r for r in regions if r.name == region]
279
+ if resources is not None:
280
+ filtered_regions = []
281
+ resources_required_features = resources.get_required_cloud_features(
282
+ )
283
+ for r in regions:
284
+ try:
285
+ cls.check_features_are_supported(
286
+ resources, resources_required_features, r.name)
287
+ filtered_regions.append(r)
288
+ except exceptions.NotSupportedError as e:
289
+ logger.info(f'Filter out context: {r.name}, reason: {e}')
290
+ continue
291
+ regions = filtered_regions
260
292
 
261
293
  # Check if requested instance type will fit in the cluster.
262
294
  # TODO(zhwu,romilb): autoscaler type needs to be regional (per
@@ -516,9 +548,6 @@ class Kubernetes(clouds.Cloud):
516
548
  return image_id
517
549
 
518
550
  image_id = _get_image_id(resources)
519
- # TODO(romilb): Create a lightweight image for SSH jump host
520
- ssh_jump_image = catalog.get_image_id_from_tag(self.IMAGE_CPU,
521
- clouds='kubernetes')
522
551
 
523
552
  # Set environment variables for the pod. Note that SkyPilot env vars
524
553
  # are set separately when the task is run. These env vars are
@@ -566,6 +595,7 @@ class Kubernetes(clouds.Cloud):
566
595
  port_mode = network_utils.get_port_mode(None, context)
567
596
 
568
597
  remote_identity = skypilot_config.get_effective_region_config(
598
+ # TODO(kyuds): Support SSH node pools as well.
569
599
  cloud='kubernetes',
570
600
  region=context,
571
601
  keys=('remote_identity',),
@@ -640,6 +670,7 @@ class Kubernetes(clouds.Cloud):
640
670
 
641
671
  k8s_kueue_local_queue_name = (
642
672
  skypilot_config.get_effective_region_config(
673
+ # TODO(kyuds): Support SSH node pools as well.
643
674
  cloud='kubernetes',
644
675
  region=context,
645
676
  keys=('kueue', 'local_queue_name'),
@@ -654,6 +685,7 @@ class Kubernetes(clouds.Cloud):
654
685
  if enable_flex_start_queued_provisioning or enable_flex_start:
655
686
  # DWS is only supported in GKE, check the autoscaler type.
656
687
  autoscaler_type = skypilot_config.get_effective_region_config(
688
+ # TODO(kyuds): Support SSH node pools as well.
657
689
  cloud='kubernetes',
658
690
  region=context,
659
691
  keys=('autoscaler',),
@@ -677,8 +709,12 @@ class Kubernetes(clouds.Cloud):
677
709
  timeout = self._calculate_provision_timeout(
678
710
  num_nodes, volume_mounts, enable_flex_start or
679
711
  enable_flex_start_queued_provisioning)
712
+
713
+ # Use _REPR, instead of directly using 'kubernetes' as the config key,
714
+ # because it could be SSH node pool as well.
715
+ cloud_config_str = self._REPR.lower()
680
716
  timeout = skypilot_config.get_effective_region_config(
681
- cloud='kubernetes',
717
+ cloud=cloud_config_str,
682
718
  region=context,
683
719
  keys=('provision_timeout',),
684
720
  default_value=timeout,
@@ -692,13 +728,8 @@ class Kubernetes(clouds.Cloud):
692
728
  'accelerator_count': str(acc_count),
693
729
  'timeout': str(timeout),
694
730
  'k8s_port_mode': port_mode.value,
695
- 'k8s_networking_mode': network_utils.get_networking_mode(
696
- None, context=context).value,
697
- 'k8s_ssh_key_secret_name': self.SKY_SSH_KEY_SECRET_NAME,
698
731
  'k8s_acc_label_key': k8s_acc_label_key,
699
732
  'k8s_acc_label_values': k8s_acc_label_values,
700
- 'k8s_ssh_jump_name': self.SKY_SSH_JUMP_NAME,
701
- 'k8s_ssh_jump_image': ssh_jump_image,
702
733
  'k8s_service_account_name': k8s_service_account_name,
703
734
  'k8s_automount_sa_token': 'true',
704
735
  'k8s_fuse_device_required': fuse_device_required,
@@ -796,7 +827,8 @@ class Kubernetes(clouds.Cloud):
796
827
  accelerators=resources.accelerators,
797
828
  use_spot=resources.use_spot,
798
829
  region=resources.region,
799
- zone=resources.zone)
830
+ zone=resources.zone,
831
+ resources=resources)
800
832
  if not regions:
801
833
  return resources_utils.FeasibleResources([], [], None)
802
834
  resources = resources.copy(accelerators=None)
@@ -841,6 +873,8 @@ class Kubernetes(clouds.Cloud):
841
873
  from_instance_type(default_instance_type))
842
874
 
843
875
  gpu_task_cpus = k8s_instance_type.cpus
876
+ if resources.cpus is None:
877
+ gpu_task_cpus = self._DEFAULT_NUM_VCPUS_WITH_GPU * acc_count
844
878
  # Special handling to bump up memory multiplier for GPU instances
845
879
  gpu_task_memory = (float(resources.memory.strip('+')) if
846
880
  resources.memory is not None else gpu_task_cpus *
@@ -854,7 +888,8 @@ class Kubernetes(clouds.Cloud):
854
888
  accelerators=None,
855
889
  use_spot=resources.use_spot,
856
890
  region=resources.region,
857
- zone=resources.zone)
891
+ zone=resources.zone,
892
+ resources=resources)
858
893
  if not available_regions:
859
894
  return resources_utils.FeasibleResources([], [], None)
860
895
  # No fuzzy lists for Kubernetes
@@ -59,7 +59,9 @@ class Lambda(clouds.Cloud):
59
59
 
60
60
  @classmethod
61
61
  def _unsupported_features_for_resources(
62
- cls, resources: 'resources_lib.Resources'
62
+ cls,
63
+ resources: 'resources_lib.Resources',
64
+ region: Optional[str] = None,
63
65
  ) -> Dict[clouds.CloudImplementationFeatures, str]:
64
66
  del resources # unused
65
67
  return cls._CLOUD_UNSUPPORTED_FEATURES
@@ -69,10 +71,15 @@ class Lambda(clouds.Cloud):
69
71
  return cls._MAX_CLUSTER_NAME_LEN_LIMIT
70
72
 
71
73
  @classmethod
72
- def regions_with_offering(cls, instance_type: str,
73
- accelerators: Optional[Dict[str, int]],
74
- use_spot: bool, region: Optional[str],
75
- zone: Optional[str]) -> List[clouds.Region]:
74
+ def regions_with_offering(
75
+ cls,
76
+ instance_type: str,
77
+ accelerators: Optional[Dict[str, int]],
78
+ use_spot: bool,
79
+ region: Optional[str],
80
+ zone: Optional[str],
81
+ resources: Optional['resources_lib.Resources'] = None,
82
+ ) -> List[clouds.Region]:
76
83
  assert zone is None, 'Lambda does not support zones.'
77
84
  del accelerators, zone # unused
78
85
  if use_spot:
sky/clouds/nebius.py CHANGED
@@ -78,7 +78,9 @@ class Nebius(clouds.Cloud):
78
78
 
79
79
  @classmethod
80
80
  def _unsupported_features_for_resources(
81
- cls, resources: 'resources_lib.Resources'
81
+ cls,
82
+ resources: 'resources_lib.Resources',
83
+ region: Optional[str] = None,
82
84
  ) -> Dict[clouds.CloudImplementationFeatures, str]:
83
85
  unsupported = cls._CLOUD_UNSUPPORTED_FEATURES.copy()
84
86
 
@@ -101,10 +103,15 @@ class Nebius(clouds.Cloud):
101
103
  return cls._MAX_CLUSTER_NAME_LEN_LIMIT
102
104
 
103
105
  @classmethod
104
- def regions_with_offering(cls, instance_type: str,
105
- accelerators: Optional[Dict[str, int]],
106
- use_spot: bool, region: Optional[str],
107
- zone: Optional[str]) -> List[clouds.Region]:
106
+ def regions_with_offering(
107
+ cls,
108
+ instance_type: str,
109
+ accelerators: Optional[Dict[str, int]],
110
+ use_spot: bool,
111
+ region: Optional[str],
112
+ zone: Optional[str],
113
+ resources: Optional['resources_lib.Resources'] = None,
114
+ ) -> List[clouds.Region]:
108
115
  assert zone is None, 'Nebius does not support zones.'
109
116
  del accelerators, zone # unused
110
117
  regions = catalog.get_region_zones_for_instance_type(
@@ -245,9 +252,12 @@ class Nebius(clouds.Cloud):
245
252
  'filesystem_mount_tag': f'filesystem-skypilot-{i+1}'
246
253
  })
247
254
 
255
+ use_static_ip_address = skypilot_config.get_nested(
256
+ ('nebius', 'use_static_ip_address'), default_value=False)
248
257
  resources_vars: Dict[str, Any] = {
249
258
  'instance_type': resources.instance_type,
250
259
  'custom_resources': custom_resources,
260
+ 'use_static_ip_address': use_static_ip_address,
251
261
  'region': region.name,
252
262
  'image_id': image_family,
253
263
  # Nebius does not support specific zones.
@@ -364,10 +374,10 @@ class Nebius(clouds.Cloud):
364
374
  f'{_INDENT_PREFIX} $ nebius --format json iam whoami|jq -r \'.user_profile.tenants[0].tenant_id\' > {nebius.tenant_id_path()} \n') # pylint: disable=line-too-long
365
375
  if not nebius.is_token_or_cred_file_exist():
366
376
  return False, f'{token_cred_msg}'
367
- sdk = nebius.sdk()
368
377
  tenant_id = nebius.get_tenant_id()
369
378
  if tenant_id is None:
370
379
  return False, f'{tenant_msg}'
380
+ sdk = nebius.sdk()
371
381
  try:
372
382
  service = nebius.iam().ProjectServiceClient(sdk)
373
383
  service.list(
@@ -445,9 +455,13 @@ class Nebius(clouds.Cloud):
445
455
  del workspace_config # Unused
446
456
  sdk = nebius.sdk()
447
457
  profile_client = nebius.iam().ProfileServiceClient(sdk)
448
- profile = nebius.sync_call(
449
- profile_client.get(nebius.iam().GetProfileRequest(),
450
- timeout=nebius.READ_TIMEOUT))
458
+ try:
459
+ profile = nebius.sync_call(
460
+ profile_client.get(nebius.iam().GetProfileRequest(),
461
+ timeout=nebius.READ_TIMEOUT))
462
+ except Exception as e:
463
+ raise exceptions.CloudUserIdentityError(
464
+ f'Error getting Nebius profile: {e}')
451
465
  if profile.user_profile is not None:
452
466
  if profile.user_profile.attributes is None:
453
467
  raise exceptions.CloudUserIdentityError(
sky/clouds/oci.py CHANGED
@@ -28,6 +28,7 @@ from typing import Any, Dict, Iterator, List, Optional, Tuple, Union
28
28
  from sky import catalog
29
29
  from sky import clouds
30
30
  from sky import exceptions
31
+ from sky.adaptors import common
31
32
  from sky.adaptors import oci as oci_adaptor
32
33
  from sky.clouds.utils import oci_utils
33
34
  from sky.provision.oci.query_utils import query_helper
@@ -68,7 +69,9 @@ class OCI(clouds.Cloud):
68
69
 
69
70
  @classmethod
70
71
  def _unsupported_features_for_resources(
71
- cls, resources: 'resources_lib.Resources'
72
+ cls,
73
+ resources: 'resources_lib.Resources',
74
+ region: Optional[str] = None,
72
75
  ) -> Dict[clouds.CloudImplementationFeatures, str]:
73
76
  unsupported_features = {
74
77
  clouds.CloudImplementationFeatures.CLONE_DISK_FROM_CLUSTER:
@@ -95,10 +98,15 @@ class OCI(clouds.Cloud):
95
98
  return cls._MAX_CLUSTER_NAME_LEN_LIMIT
96
99
 
97
100
  @classmethod
98
- def regions_with_offering(cls, instance_type: str,
99
- accelerators: Optional[Dict[str, int]],
100
- use_spot: bool, region: Optional[str],
101
- zone: Optional[str]) -> List[clouds.Region]:
101
+ def regions_with_offering(
102
+ cls,
103
+ instance_type: str,
104
+ accelerators: Optional[Dict[str, int]],
105
+ use_spot: bool,
106
+ region: Optional[str],
107
+ zone: Optional[str],
108
+ resources: Optional['resources_lib.Resources'] = None,
109
+ ) -> List[clouds.Region]:
102
110
  del accelerators # unused
103
111
 
104
112
  regions = catalog.get_region_zones_for_instance_type(
@@ -454,13 +462,12 @@ class OCI(clouds.Cloud):
454
462
  f'{cls._INDENT_PREFIX} region=us-sanjose-1\n'
455
463
  f'{cls._INDENT_PREFIX} key_file=~/.oci/oci_api_key.pem')
456
464
 
457
- try:
458
- # pylint: disable=import-outside-toplevel,unused-import
459
- import oci
460
- except ImportError:
461
- return False, ('`oci` is not installed. Install it with: '
462
- 'pip install oci\n'
463
- f'{cls._INDENT_PREFIX}{short_credential_help_str}')
465
+ dependency_error_msg = (
466
+ '`oci` is not installed. Install it with: '
467
+ 'pip install oci\n'
468
+ f'{cls._INDENT_PREFIX}{short_credential_help_str}')
469
+ if not common.can_import_modules(['oci']):
470
+ return False, dependency_error_msg
464
471
 
465
472
  conf_file = oci_adaptor.get_config_file()
466
473
 
sky/clouds/paperspace.py CHANGED
@@ -60,7 +60,9 @@ class Paperspace(clouds.Cloud):
60
60
 
61
61
  @classmethod
62
62
  def _unsupported_features_for_resources(
63
- cls, resources: 'resources_lib.Resources'
63
+ cls,
64
+ resources: 'resources_lib.Resources',
65
+ region: Optional[str] = None,
64
66
  ) -> Dict[clouds.CloudImplementationFeatures, str]:
65
67
  """The features not supported based on the resources provided.
66
68
 
@@ -86,6 +88,7 @@ class Paperspace(clouds.Cloud):
86
88
  use_spot: bool,
87
89
  region: Optional[str],
88
90
  zone: Optional[str],
91
+ resources: Optional['resources_lib.Resources'] = None,
89
92
  ) -> List[clouds.Region]:
90
93
  assert zone is None, 'Paperspace does not support zones.'
91
94
  del accelerators, zone # unused