skypilot-nightly 1.0.0.dev20250509__py3-none-any.whl → 1.0.0.dev20251107__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of skypilot-nightly might be problematic. Click here for more details.

Files changed (512) hide show
  1. sky/__init__.py +22 -6
  2. sky/adaptors/aws.py +25 -7
  3. sky/adaptors/common.py +24 -1
  4. sky/adaptors/coreweave.py +278 -0
  5. sky/adaptors/do.py +8 -2
  6. sky/adaptors/hyperbolic.py +8 -0
  7. sky/adaptors/kubernetes.py +149 -18
  8. sky/adaptors/nebius.py +170 -17
  9. sky/adaptors/primeintellect.py +1 -0
  10. sky/adaptors/runpod.py +68 -0
  11. sky/adaptors/seeweb.py +167 -0
  12. sky/adaptors/shadeform.py +89 -0
  13. sky/admin_policy.py +187 -4
  14. sky/authentication.py +179 -225
  15. sky/backends/__init__.py +4 -2
  16. sky/backends/backend.py +22 -9
  17. sky/backends/backend_utils.py +1299 -380
  18. sky/backends/cloud_vm_ray_backend.py +1715 -518
  19. sky/backends/docker_utils.py +1 -1
  20. sky/backends/local_docker_backend.py +11 -6
  21. sky/backends/wheel_utils.py +37 -9
  22. sky/{clouds/service_catalog → catalog}/__init__.py +21 -19
  23. sky/{clouds/service_catalog → catalog}/aws_catalog.py +27 -8
  24. sky/{clouds/service_catalog → catalog}/azure_catalog.py +10 -7
  25. sky/{clouds/service_catalog → catalog}/common.py +89 -48
  26. sky/{clouds/service_catalog → catalog}/cudo_catalog.py +8 -5
  27. sky/{clouds/service_catalog → catalog}/data_fetchers/analyze.py +1 -1
  28. sky/{clouds/service_catalog → catalog}/data_fetchers/fetch_aws.py +30 -40
  29. sky/{clouds/service_catalog → catalog}/data_fetchers/fetch_cudo.py +38 -38
  30. sky/{clouds/service_catalog → catalog}/data_fetchers/fetch_gcp.py +42 -15
  31. sky/catalog/data_fetchers/fetch_hyperbolic.py +136 -0
  32. sky/{clouds/service_catalog → catalog}/data_fetchers/fetch_lambda_cloud.py +1 -0
  33. sky/catalog/data_fetchers/fetch_nebius.py +335 -0
  34. sky/catalog/data_fetchers/fetch_runpod.py +698 -0
  35. sky/catalog/data_fetchers/fetch_seeweb.py +329 -0
  36. sky/catalog/data_fetchers/fetch_shadeform.py +142 -0
  37. sky/{clouds/service_catalog → catalog}/data_fetchers/fetch_vast.py +1 -1
  38. sky/{clouds/service_catalog → catalog}/data_fetchers/fetch_vsphere.py +1 -1
  39. sky/{clouds/service_catalog → catalog}/do_catalog.py +5 -2
  40. sky/{clouds/service_catalog → catalog}/fluidstack_catalog.py +6 -3
  41. sky/{clouds/service_catalog → catalog}/gcp_catalog.py +41 -15
  42. sky/catalog/hyperbolic_catalog.py +136 -0
  43. sky/{clouds/service_catalog → catalog}/ibm_catalog.py +9 -6
  44. sky/{clouds/service_catalog → catalog}/kubernetes_catalog.py +36 -24
  45. sky/{clouds/service_catalog → catalog}/lambda_catalog.py +9 -6
  46. sky/{clouds/service_catalog → catalog}/nebius_catalog.py +9 -7
  47. sky/{clouds/service_catalog → catalog}/oci_catalog.py +9 -6
  48. sky/{clouds/service_catalog → catalog}/paperspace_catalog.py +5 -2
  49. sky/catalog/primeintellect_catalog.py +95 -0
  50. sky/{clouds/service_catalog → catalog}/runpod_catalog.py +11 -4
  51. sky/{clouds/service_catalog → catalog}/scp_catalog.py +9 -6
  52. sky/catalog/seeweb_catalog.py +184 -0
  53. sky/catalog/shadeform_catalog.py +165 -0
  54. sky/catalog/ssh_catalog.py +167 -0
  55. sky/{clouds/service_catalog → catalog}/vast_catalog.py +6 -3
  56. sky/{clouds/service_catalog → catalog}/vsphere_catalog.py +5 -2
  57. sky/check.py +491 -203
  58. sky/cli.py +5 -6005
  59. sky/client/{cli.py → cli/command.py} +2477 -1885
  60. sky/client/cli/deprecation_utils.py +99 -0
  61. sky/client/cli/flags.py +359 -0
  62. sky/client/cli/table_utils.py +320 -0
  63. sky/client/common.py +70 -32
  64. sky/client/oauth.py +82 -0
  65. sky/client/sdk.py +1203 -297
  66. sky/client/sdk_async.py +833 -0
  67. sky/client/service_account_auth.py +47 -0
  68. sky/cloud_stores.py +73 -0
  69. sky/clouds/__init__.py +13 -0
  70. sky/clouds/aws.py +358 -93
  71. sky/clouds/azure.py +105 -83
  72. sky/clouds/cloud.py +127 -36
  73. sky/clouds/cudo.py +68 -50
  74. sky/clouds/do.py +66 -48
  75. sky/clouds/fluidstack.py +63 -44
  76. sky/clouds/gcp.py +339 -110
  77. sky/clouds/hyperbolic.py +293 -0
  78. sky/clouds/ibm.py +70 -49
  79. sky/clouds/kubernetes.py +563 -162
  80. sky/clouds/lambda_cloud.py +74 -54
  81. sky/clouds/nebius.py +206 -80
  82. sky/clouds/oci.py +88 -66
  83. sky/clouds/paperspace.py +61 -44
  84. sky/clouds/primeintellect.py +317 -0
  85. sky/clouds/runpod.py +164 -74
  86. sky/clouds/scp.py +89 -83
  87. sky/clouds/seeweb.py +466 -0
  88. sky/clouds/shadeform.py +400 -0
  89. sky/clouds/ssh.py +263 -0
  90. sky/clouds/utils/aws_utils.py +10 -4
  91. sky/clouds/utils/gcp_utils.py +87 -11
  92. sky/clouds/utils/oci_utils.py +38 -14
  93. sky/clouds/utils/scp_utils.py +177 -124
  94. sky/clouds/vast.py +99 -77
  95. sky/clouds/vsphere.py +51 -40
  96. sky/core.py +349 -139
  97. sky/dag.py +15 -0
  98. sky/dashboard/out/404.html +1 -1
  99. sky/dashboard/out/_next/static/chunks/1141-e6aa9ab418717c59.js +11 -0
  100. sky/dashboard/out/_next/static/chunks/1272-1ef0bf0237faccdb.js +1 -0
  101. sky/dashboard/out/_next/static/chunks/1871-74503c8e80fd253b.js +6 -0
  102. sky/dashboard/out/_next/static/chunks/2260-7703229c33c5ebd5.js +1 -0
  103. sky/dashboard/out/_next/static/chunks/2350.fab69e61bac57b23.js +1 -0
  104. sky/dashboard/out/_next/static/chunks/2369.fc20f0c2c8ed9fe7.js +15 -0
  105. sky/dashboard/out/_next/static/chunks/2755.fff53c4a3fcae910.js +26 -0
  106. sky/dashboard/out/_next/static/chunks/3294.72362fa129305b19.js +1 -0
  107. sky/dashboard/out/_next/static/chunks/3785.ad6adaa2a0fa9768.js +1 -0
  108. sky/dashboard/out/_next/static/chunks/3850-ff4a9a69d978632b.js +1 -0
  109. sky/dashboard/out/_next/static/chunks/3937.210053269f121201.js +1 -0
  110. sky/dashboard/out/_next/static/chunks/4725.a830b5c9e7867c92.js +1 -0
  111. sky/dashboard/out/_next/static/chunks/4937.a2baa2df5572a276.js +15 -0
  112. sky/dashboard/out/_next/static/chunks/5739-d67458fcb1386c92.js +8 -0
  113. sky/dashboard/out/_next/static/chunks/6130-2be46d70a38f1e82.js +1 -0
  114. sky/dashboard/out/_next/static/chunks/616-3d59f75e2ccf9321.js +39 -0
  115. sky/dashboard/out/_next/static/chunks/6212-7bd06f60ba693125.js +13 -0
  116. sky/dashboard/out/_next/static/chunks/6601-06114c982db410b6.js +1 -0
  117. sky/dashboard/out/_next/static/chunks/6856-ef8ba11f96d8c4a3.js +1 -0
  118. sky/dashboard/out/_next/static/chunks/6989-01359c57e018caa4.js +1 -0
  119. sky/dashboard/out/_next/static/chunks/6990-32b6e2d3822301fa.js +1 -0
  120. sky/dashboard/out/_next/static/chunks/7359-c8d04e06886000b3.js +30 -0
  121. sky/dashboard/out/_next/static/chunks/7411-b15471acd2cba716.js +41 -0
  122. sky/dashboard/out/_next/static/chunks/7615-3301e838e5f25772.js +1 -0
  123. sky/dashboard/out/_next/static/chunks/8640.5b9475a2d18c5416.js +16 -0
  124. sky/dashboard/out/_next/static/chunks/8969-1e4613c651bf4051.js +1 -0
  125. sky/dashboard/out/_next/static/chunks/9025.fa408f3242e9028d.js +6 -0
  126. sky/dashboard/out/_next/static/chunks/9353-cff34f7e773b2e2b.js +1 -0
  127. sky/dashboard/out/_next/static/chunks/9360.7310982cf5a0dc79.js +31 -0
  128. sky/dashboard/out/_next/static/chunks/9847.3aaca6bb33455140.js +30 -0
  129. sky/dashboard/out/_next/static/chunks/fd9d1056-86323a29a8f7e46a.js +1 -0
  130. sky/dashboard/out/_next/static/chunks/framework-cf60a09ccd051a10.js +33 -0
  131. sky/dashboard/out/_next/static/chunks/main-app-587214043926b3cc.js +1 -0
  132. sky/dashboard/out/_next/static/chunks/main-f15ccb73239a3bf1.js +1 -0
  133. sky/dashboard/out/_next/static/chunks/pages/_app-bde01e4a2beec258.js +34 -0
  134. sky/dashboard/out/_next/static/chunks/pages/_error-c66a4e8afc46f17b.js +1 -0
  135. sky/dashboard/out/_next/static/chunks/pages/clusters/[cluster]/[job]-c736ead69c2d86ec.js +16 -0
  136. sky/dashboard/out/_next/static/chunks/pages/clusters/[cluster]-a37d2063af475a1c.js +1 -0
  137. sky/dashboard/out/_next/static/chunks/pages/clusters-d44859594e6f8064.js +1 -0
  138. sky/dashboard/out/_next/static/chunks/pages/config-dfb9bf07b13045f4.js +1 -0
  139. sky/dashboard/out/_next/static/chunks/pages/index-444f1804401f04ea.js +1 -0
  140. sky/dashboard/out/_next/static/chunks/pages/infra/[context]-c0b5935149902e6f.js +1 -0
  141. sky/dashboard/out/_next/static/chunks/pages/infra-aed0ea19df7cf961.js +1 -0
  142. sky/dashboard/out/_next/static/chunks/pages/jobs/[job]-5796e8d6aea291a0.js +16 -0
  143. sky/dashboard/out/_next/static/chunks/pages/jobs/pools/[pool]-6edeb7d06032adfc.js +21 -0
  144. sky/dashboard/out/_next/static/chunks/pages/jobs-479dde13399cf270.js +1 -0
  145. sky/dashboard/out/_next/static/chunks/pages/users-5ab3b907622cf0fe.js +1 -0
  146. sky/dashboard/out/_next/static/chunks/pages/volumes-b84b948ff357c43e.js +1 -0
  147. sky/dashboard/out/_next/static/chunks/pages/workspace/new-3f88a1c7e86a3f86.js +1 -0
  148. sky/dashboard/out/_next/static/chunks/pages/workspaces/[name]-c5a3eeee1c218af1.js +1 -0
  149. sky/dashboard/out/_next/static/chunks/pages/workspaces-22b23febb3e89ce1.js +1 -0
  150. sky/dashboard/out/_next/static/chunks/webpack-2679be77fc08a2f8.js +1 -0
  151. sky/dashboard/out/_next/static/css/0748ce22df867032.css +3 -0
  152. sky/dashboard/out/_next/static/zB0ed6ge_W1MDszVHhijS/_buildManifest.js +1 -0
  153. sky/dashboard/out/clusters/[cluster]/[job].html +1 -1
  154. sky/dashboard/out/clusters/[cluster].html +1 -1
  155. sky/dashboard/out/clusters.html +1 -1
  156. sky/dashboard/out/config.html +1 -0
  157. sky/dashboard/out/index.html +1 -1
  158. sky/dashboard/out/infra/[context].html +1 -0
  159. sky/dashboard/out/infra.html +1 -0
  160. sky/dashboard/out/jobs/[job].html +1 -1
  161. sky/dashboard/out/jobs/pools/[pool].html +1 -0
  162. sky/dashboard/out/jobs.html +1 -1
  163. sky/dashboard/out/users.html +1 -0
  164. sky/dashboard/out/volumes.html +1 -0
  165. sky/dashboard/out/workspace/new.html +1 -0
  166. sky/dashboard/out/workspaces/[name].html +1 -0
  167. sky/dashboard/out/workspaces.html +1 -0
  168. sky/data/data_utils.py +137 -1
  169. sky/data/mounting_utils.py +269 -84
  170. sky/data/storage.py +1451 -1807
  171. sky/data/storage_utils.py +43 -57
  172. sky/exceptions.py +132 -2
  173. sky/execution.py +206 -63
  174. sky/global_user_state.py +2374 -586
  175. sky/jobs/__init__.py +5 -0
  176. sky/jobs/client/sdk.py +242 -65
  177. sky/jobs/client/sdk_async.py +143 -0
  178. sky/jobs/constants.py +9 -8
  179. sky/jobs/controller.py +839 -277
  180. sky/jobs/file_content_utils.py +80 -0
  181. sky/jobs/log_gc.py +201 -0
  182. sky/jobs/recovery_strategy.py +398 -152
  183. sky/jobs/scheduler.py +315 -189
  184. sky/jobs/server/core.py +829 -255
  185. sky/jobs/server/server.py +156 -115
  186. sky/jobs/server/utils.py +136 -0
  187. sky/jobs/state.py +2092 -701
  188. sky/jobs/utils.py +1242 -160
  189. sky/logs/__init__.py +21 -0
  190. sky/logs/agent.py +108 -0
  191. sky/logs/aws.py +243 -0
  192. sky/logs/gcp.py +91 -0
  193. sky/metrics/__init__.py +0 -0
  194. sky/metrics/utils.py +443 -0
  195. sky/models.py +78 -1
  196. sky/optimizer.py +164 -70
  197. sky/provision/__init__.py +90 -4
  198. sky/provision/aws/config.py +147 -26
  199. sky/provision/aws/instance.py +135 -50
  200. sky/provision/azure/instance.py +10 -5
  201. sky/provision/common.py +13 -1
  202. sky/provision/cudo/cudo_machine_type.py +1 -1
  203. sky/provision/cudo/cudo_utils.py +14 -8
  204. sky/provision/cudo/cudo_wrapper.py +72 -71
  205. sky/provision/cudo/instance.py +10 -6
  206. sky/provision/do/instance.py +10 -6
  207. sky/provision/do/utils.py +4 -3
  208. sky/provision/docker_utils.py +114 -23
  209. sky/provision/fluidstack/instance.py +13 -8
  210. sky/provision/gcp/__init__.py +1 -0
  211. sky/provision/gcp/config.py +301 -19
  212. sky/provision/gcp/constants.py +218 -0
  213. sky/provision/gcp/instance.py +36 -8
  214. sky/provision/gcp/instance_utils.py +18 -4
  215. sky/provision/gcp/volume_utils.py +247 -0
  216. sky/provision/hyperbolic/__init__.py +12 -0
  217. sky/provision/hyperbolic/config.py +10 -0
  218. sky/provision/hyperbolic/instance.py +437 -0
  219. sky/provision/hyperbolic/utils.py +373 -0
  220. sky/provision/instance_setup.py +93 -14
  221. sky/provision/kubernetes/__init__.py +5 -0
  222. sky/provision/kubernetes/config.py +9 -52
  223. sky/provision/kubernetes/constants.py +17 -0
  224. sky/provision/kubernetes/instance.py +789 -247
  225. sky/provision/kubernetes/manifests/fusermount-server-daemonset.yaml +1 -2
  226. sky/provision/kubernetes/network.py +27 -17
  227. sky/provision/kubernetes/network_utils.py +40 -43
  228. sky/provision/kubernetes/utils.py +1192 -531
  229. sky/provision/kubernetes/volume.py +282 -0
  230. sky/provision/lambda_cloud/instance.py +22 -16
  231. sky/provision/nebius/constants.py +50 -0
  232. sky/provision/nebius/instance.py +19 -6
  233. sky/provision/nebius/utils.py +196 -91
  234. sky/provision/oci/instance.py +10 -5
  235. sky/provision/paperspace/instance.py +10 -7
  236. sky/provision/paperspace/utils.py +1 -1
  237. sky/provision/primeintellect/__init__.py +10 -0
  238. sky/provision/primeintellect/config.py +11 -0
  239. sky/provision/primeintellect/instance.py +454 -0
  240. sky/provision/primeintellect/utils.py +398 -0
  241. sky/provision/provisioner.py +110 -36
  242. sky/provision/runpod/__init__.py +5 -0
  243. sky/provision/runpod/instance.py +27 -6
  244. sky/provision/runpod/utils.py +51 -18
  245. sky/provision/runpod/volume.py +180 -0
  246. sky/provision/scp/__init__.py +15 -0
  247. sky/provision/scp/config.py +93 -0
  248. sky/provision/scp/instance.py +531 -0
  249. sky/provision/seeweb/__init__.py +11 -0
  250. sky/provision/seeweb/config.py +13 -0
  251. sky/provision/seeweb/instance.py +807 -0
  252. sky/provision/shadeform/__init__.py +11 -0
  253. sky/provision/shadeform/config.py +12 -0
  254. sky/provision/shadeform/instance.py +351 -0
  255. sky/provision/shadeform/shadeform_utils.py +83 -0
  256. sky/provision/ssh/__init__.py +18 -0
  257. sky/provision/vast/instance.py +13 -8
  258. sky/provision/vast/utils.py +10 -7
  259. sky/provision/vsphere/common/vim_utils.py +1 -2
  260. sky/provision/vsphere/instance.py +15 -10
  261. sky/provision/vsphere/vsphere_utils.py +9 -19
  262. sky/py.typed +0 -0
  263. sky/resources.py +844 -118
  264. sky/schemas/__init__.py +0 -0
  265. sky/schemas/api/__init__.py +0 -0
  266. sky/schemas/api/responses.py +225 -0
  267. sky/schemas/db/README +4 -0
  268. sky/schemas/db/env.py +90 -0
  269. sky/schemas/db/global_user_state/001_initial_schema.py +124 -0
  270. sky/schemas/db/global_user_state/002_add_workspace_to_cluster_history.py +35 -0
  271. sky/schemas/db/global_user_state/003_fix_initial_revision.py +61 -0
  272. sky/schemas/db/global_user_state/004_is_managed.py +34 -0
  273. sky/schemas/db/global_user_state/005_cluster_event.py +32 -0
  274. sky/schemas/db/global_user_state/006_provision_log.py +41 -0
  275. sky/schemas/db/global_user_state/007_cluster_event_request_id.py +34 -0
  276. sky/schemas/db/global_user_state/008_skylet_ssh_tunnel_metadata.py +34 -0
  277. sky/schemas/db/global_user_state/009_last_activity_and_launched_at.py +89 -0
  278. sky/schemas/db/global_user_state/010_save_ssh_key.py +66 -0
  279. sky/schemas/db/script.py.mako +28 -0
  280. sky/schemas/db/serve_state/001_initial_schema.py +67 -0
  281. sky/schemas/db/skypilot_config/001_initial_schema.py +30 -0
  282. sky/schemas/db/spot_jobs/001_initial_schema.py +97 -0
  283. sky/schemas/db/spot_jobs/002_cluster_pool.py +42 -0
  284. sky/schemas/db/spot_jobs/003_pool_hash.py +34 -0
  285. sky/schemas/db/spot_jobs/004_job_file_contents.py +42 -0
  286. sky/schemas/db/spot_jobs/005_logs_gc.py +38 -0
  287. sky/schemas/generated/__init__.py +0 -0
  288. sky/schemas/generated/autostopv1_pb2.py +36 -0
  289. sky/schemas/generated/autostopv1_pb2.pyi +43 -0
  290. sky/schemas/generated/autostopv1_pb2_grpc.py +146 -0
  291. sky/schemas/generated/jobsv1_pb2.py +86 -0
  292. sky/schemas/generated/jobsv1_pb2.pyi +254 -0
  293. sky/schemas/generated/jobsv1_pb2_grpc.py +542 -0
  294. sky/schemas/generated/managed_jobsv1_pb2.py +74 -0
  295. sky/schemas/generated/managed_jobsv1_pb2.pyi +278 -0
  296. sky/schemas/generated/managed_jobsv1_pb2_grpc.py +278 -0
  297. sky/schemas/generated/servev1_pb2.py +58 -0
  298. sky/schemas/generated/servev1_pb2.pyi +115 -0
  299. sky/schemas/generated/servev1_pb2_grpc.py +322 -0
  300. sky/serve/autoscalers.py +357 -5
  301. sky/serve/client/impl.py +310 -0
  302. sky/serve/client/sdk.py +47 -139
  303. sky/serve/client/sdk_async.py +130 -0
  304. sky/serve/constants.py +10 -8
  305. sky/serve/controller.py +64 -19
  306. sky/serve/load_balancer.py +106 -60
  307. sky/serve/load_balancing_policies.py +115 -1
  308. sky/serve/replica_managers.py +273 -162
  309. sky/serve/serve_rpc_utils.py +179 -0
  310. sky/serve/serve_state.py +554 -251
  311. sky/serve/serve_utils.py +733 -220
  312. sky/serve/server/core.py +66 -711
  313. sky/serve/server/impl.py +1093 -0
  314. sky/serve/server/server.py +21 -18
  315. sky/serve/service.py +133 -48
  316. sky/serve/service_spec.py +135 -16
  317. sky/serve/spot_placer.py +3 -0
  318. sky/server/auth/__init__.py +0 -0
  319. sky/server/auth/authn.py +50 -0
  320. sky/server/auth/loopback.py +38 -0
  321. sky/server/auth/oauth2_proxy.py +200 -0
  322. sky/server/common.py +475 -181
  323. sky/server/config.py +81 -23
  324. sky/server/constants.py +44 -6
  325. sky/server/daemons.py +229 -0
  326. sky/server/html/token_page.html +185 -0
  327. sky/server/metrics.py +160 -0
  328. sky/server/requests/executor.py +528 -138
  329. sky/server/requests/payloads.py +351 -17
  330. sky/server/requests/preconditions.py +21 -17
  331. sky/server/requests/process.py +112 -29
  332. sky/server/requests/request_names.py +120 -0
  333. sky/server/requests/requests.py +817 -224
  334. sky/server/requests/serializers/decoders.py +82 -31
  335. sky/server/requests/serializers/encoders.py +140 -22
  336. sky/server/requests/threads.py +106 -0
  337. sky/server/rest.py +417 -0
  338. sky/server/server.py +1290 -284
  339. sky/server/state.py +20 -0
  340. sky/server/stream_utils.py +345 -57
  341. sky/server/uvicorn.py +217 -3
  342. sky/server/versions.py +270 -0
  343. sky/setup_files/MANIFEST.in +5 -0
  344. sky/setup_files/alembic.ini +156 -0
  345. sky/setup_files/dependencies.py +136 -31
  346. sky/setup_files/setup.py +44 -42
  347. sky/sky_logging.py +102 -5
  348. sky/skylet/attempt_skylet.py +1 -0
  349. sky/skylet/autostop_lib.py +129 -8
  350. sky/skylet/configs.py +27 -20
  351. sky/skylet/constants.py +171 -19
  352. sky/skylet/events.py +105 -21
  353. sky/skylet/job_lib.py +335 -104
  354. sky/skylet/log_lib.py +297 -18
  355. sky/skylet/log_lib.pyi +44 -1
  356. sky/skylet/ray_patches/__init__.py +17 -3
  357. sky/skylet/ray_patches/autoscaler.py.diff +18 -0
  358. sky/skylet/ray_patches/cli.py.diff +19 -0
  359. sky/skylet/ray_patches/command_runner.py.diff +17 -0
  360. sky/skylet/ray_patches/log_monitor.py.diff +20 -0
  361. sky/skylet/ray_patches/resource_demand_scheduler.py.diff +32 -0
  362. sky/skylet/ray_patches/updater.py.diff +18 -0
  363. sky/skylet/ray_patches/worker.py.diff +41 -0
  364. sky/skylet/services.py +564 -0
  365. sky/skylet/skylet.py +63 -4
  366. sky/skylet/subprocess_daemon.py +103 -29
  367. sky/skypilot_config.py +506 -99
  368. sky/ssh_node_pools/__init__.py +1 -0
  369. sky/ssh_node_pools/core.py +135 -0
  370. sky/ssh_node_pools/server.py +233 -0
  371. sky/task.py +621 -137
  372. sky/templates/aws-ray.yml.j2 +10 -3
  373. sky/templates/azure-ray.yml.j2 +1 -1
  374. sky/templates/do-ray.yml.j2 +1 -1
  375. sky/templates/gcp-ray.yml.j2 +57 -0
  376. sky/templates/hyperbolic-ray.yml.j2 +67 -0
  377. sky/templates/jobs-controller.yaml.j2 +27 -24
  378. sky/templates/kubernetes-loadbalancer.yml.j2 +2 -0
  379. sky/templates/kubernetes-ray.yml.j2 +607 -51
  380. sky/templates/lambda-ray.yml.j2 +1 -1
  381. sky/templates/nebius-ray.yml.j2 +33 -12
  382. sky/templates/paperspace-ray.yml.j2 +1 -1
  383. sky/templates/primeintellect-ray.yml.j2 +71 -0
  384. sky/templates/runpod-ray.yml.j2 +9 -1
  385. sky/templates/scp-ray.yml.j2 +3 -50
  386. sky/templates/seeweb-ray.yml.j2 +108 -0
  387. sky/templates/shadeform-ray.yml.j2 +72 -0
  388. sky/templates/sky-serve-controller.yaml.j2 +22 -2
  389. sky/templates/websocket_proxy.py +178 -18
  390. sky/usage/usage_lib.py +18 -11
  391. sky/users/__init__.py +0 -0
  392. sky/users/model.conf +15 -0
  393. sky/users/permission.py +387 -0
  394. sky/users/rbac.py +121 -0
  395. sky/users/server.py +720 -0
  396. sky/users/token_service.py +218 -0
  397. sky/utils/accelerator_registry.py +34 -5
  398. sky/utils/admin_policy_utils.py +84 -38
  399. sky/utils/annotations.py +16 -5
  400. sky/utils/asyncio_utils.py +78 -0
  401. sky/utils/auth_utils.py +153 -0
  402. sky/utils/benchmark_utils.py +60 -0
  403. sky/utils/cli_utils/status_utils.py +159 -86
  404. sky/utils/cluster_utils.py +31 -9
  405. sky/utils/command_runner.py +354 -68
  406. sky/utils/command_runner.pyi +93 -3
  407. sky/utils/common.py +35 -8
  408. sky/utils/common_utils.py +310 -87
  409. sky/utils/config_utils.py +87 -5
  410. sky/utils/context.py +402 -0
  411. sky/utils/context_utils.py +222 -0
  412. sky/utils/controller_utils.py +264 -89
  413. sky/utils/dag_utils.py +31 -12
  414. sky/utils/db/__init__.py +0 -0
  415. sky/utils/db/db_utils.py +470 -0
  416. sky/utils/db/migration_utils.py +133 -0
  417. sky/utils/directory_utils.py +12 -0
  418. sky/utils/env_options.py +13 -0
  419. sky/utils/git.py +567 -0
  420. sky/utils/git_clone.sh +460 -0
  421. sky/utils/infra_utils.py +195 -0
  422. sky/utils/kubernetes/cleanup-tunnel.sh +62 -0
  423. sky/utils/kubernetes/config_map_utils.py +133 -0
  424. sky/utils/kubernetes/create_cluster.sh +13 -27
  425. sky/utils/kubernetes/delete_cluster.sh +10 -7
  426. sky/utils/kubernetes/deploy_remote_cluster.py +1299 -0
  427. sky/utils/kubernetes/exec_kubeconfig_converter.py +22 -31
  428. sky/utils/kubernetes/generate_kind_config.py +6 -66
  429. sky/utils/kubernetes/generate_kubeconfig.sh +4 -1
  430. sky/utils/kubernetes/gpu_labeler.py +5 -5
  431. sky/utils/kubernetes/kubernetes_deploy_utils.py +354 -47
  432. sky/utils/kubernetes/ssh-tunnel.sh +379 -0
  433. sky/utils/kubernetes/ssh_utils.py +221 -0
  434. sky/utils/kubernetes_enums.py +8 -15
  435. sky/utils/lock_events.py +94 -0
  436. sky/utils/locks.py +368 -0
  437. sky/utils/log_utils.py +300 -6
  438. sky/utils/perf_utils.py +22 -0
  439. sky/utils/resource_checker.py +298 -0
  440. sky/utils/resources_utils.py +249 -32
  441. sky/utils/rich_utils.py +213 -37
  442. sky/utils/schemas.py +905 -147
  443. sky/utils/serialize_utils.py +16 -0
  444. sky/utils/status_lib.py +10 -0
  445. sky/utils/subprocess_utils.py +38 -15
  446. sky/utils/tempstore.py +70 -0
  447. sky/utils/timeline.py +24 -52
  448. sky/utils/ux_utils.py +84 -15
  449. sky/utils/validator.py +11 -1
  450. sky/utils/volume.py +86 -0
  451. sky/utils/yaml_utils.py +111 -0
  452. sky/volumes/__init__.py +13 -0
  453. sky/volumes/client/__init__.py +0 -0
  454. sky/volumes/client/sdk.py +149 -0
  455. sky/volumes/server/__init__.py +0 -0
  456. sky/volumes/server/core.py +258 -0
  457. sky/volumes/server/server.py +122 -0
  458. sky/volumes/volume.py +212 -0
  459. sky/workspaces/__init__.py +0 -0
  460. sky/workspaces/core.py +655 -0
  461. sky/workspaces/server.py +101 -0
  462. sky/workspaces/utils.py +56 -0
  463. skypilot_nightly-1.0.0.dev20251107.dist-info/METADATA +675 -0
  464. skypilot_nightly-1.0.0.dev20251107.dist-info/RECORD +594 -0
  465. {skypilot_nightly-1.0.0.dev20250509.dist-info → skypilot_nightly-1.0.0.dev20251107.dist-info}/WHEEL +1 -1
  466. sky/benchmark/benchmark_state.py +0 -256
  467. sky/benchmark/benchmark_utils.py +0 -641
  468. sky/clouds/service_catalog/constants.py +0 -7
  469. sky/dashboard/out/_next/static/LksQgChY5izXjokL3LcEu/_buildManifest.js +0 -1
  470. sky/dashboard/out/_next/static/chunks/236-f49500b82ad5392d.js +0 -6
  471. sky/dashboard/out/_next/static/chunks/312-c3c8845990db8ffc.js +0 -15
  472. sky/dashboard/out/_next/static/chunks/37-0a572fe0dbb89c4d.js +0 -6
  473. sky/dashboard/out/_next/static/chunks/678-206dddca808e6d16.js +0 -59
  474. sky/dashboard/out/_next/static/chunks/845-0f8017370869e269.js +0 -1
  475. sky/dashboard/out/_next/static/chunks/979-7bf73a4c7cea0f5c.js +0 -1
  476. sky/dashboard/out/_next/static/chunks/fd9d1056-2821b0f0cabcd8bd.js +0 -1
  477. sky/dashboard/out/_next/static/chunks/framework-87d061ee6ed71b28.js +0 -33
  478. sky/dashboard/out/_next/static/chunks/main-app-241eb28595532291.js +0 -1
  479. sky/dashboard/out/_next/static/chunks/main-e0e2335212e72357.js +0 -1
  480. sky/dashboard/out/_next/static/chunks/pages/_app-e6b013bc3f77ad60.js +0 -1
  481. sky/dashboard/out/_next/static/chunks/pages/_error-1be831200e60c5c0.js +0 -1
  482. sky/dashboard/out/_next/static/chunks/pages/clusters/[cluster]/[job]-e15db85d0ea1fbe1.js +0 -1
  483. sky/dashboard/out/_next/static/chunks/pages/clusters/[cluster]-f383db7389368ea7.js +0 -1
  484. sky/dashboard/out/_next/static/chunks/pages/clusters-a93b93e10b8b074e.js +0 -1
  485. sky/dashboard/out/_next/static/chunks/pages/index-f9f039532ca8cbc4.js +0 -1
  486. sky/dashboard/out/_next/static/chunks/pages/jobs/[job]-03f279c6741fb48b.js +0 -1
  487. sky/dashboard/out/_next/static/chunks/pages/jobs-a75029b67aab6a2e.js +0 -1
  488. sky/dashboard/out/_next/static/chunks/webpack-830f59b8404e96b8.js +0 -1
  489. sky/dashboard/out/_next/static/css/c6933bbb2ce7f4dd.css +0 -3
  490. sky/jobs/dashboard/dashboard.py +0 -223
  491. sky/jobs/dashboard/static/favicon.ico +0 -0
  492. sky/jobs/dashboard/templates/index.html +0 -831
  493. sky/jobs/server/dashboard_utils.py +0 -69
  494. sky/skylet/providers/scp/__init__.py +0 -2
  495. sky/skylet/providers/scp/config.py +0 -149
  496. sky/skylet/providers/scp/node_provider.py +0 -578
  497. sky/templates/kubernetes-ssh-jump.yml.j2 +0 -94
  498. sky/utils/db_utils.py +0 -100
  499. sky/utils/kubernetes/deploy_remote_cluster.sh +0 -308
  500. sky/utils/kubernetes/ssh_jump_lifecycle_manager.py +0 -191
  501. skypilot_nightly-1.0.0.dev20250509.dist-info/METADATA +0 -361
  502. skypilot_nightly-1.0.0.dev20250509.dist-info/RECORD +0 -396
  503. /sky/{clouds/service_catalog → catalog}/config.py +0 -0
  504. /sky/{benchmark → catalog/data_fetchers}/__init__.py +0 -0
  505. /sky/{clouds/service_catalog → catalog}/data_fetchers/fetch_azure.py +0 -0
  506. /sky/{clouds/service_catalog → catalog}/data_fetchers/fetch_fluidstack.py +0 -0
  507. /sky/{clouds/service_catalog → catalog}/data_fetchers/fetch_ibm.py +0 -0
  508. /sky/{clouds/service_catalog/data_fetchers → client/cli}/__init__.py +0 -0
  509. /sky/dashboard/out/_next/static/{LksQgChY5izXjokL3LcEu → zB0ed6ge_W1MDszVHhijS}/_ssgManifest.js +0 -0
  510. {skypilot_nightly-1.0.0.dev20250509.dist-info → skypilot_nightly-1.0.0.dev20251107.dist-info}/entry_points.txt +0 -0
  511. {skypilot_nightly-1.0.0.dev20250509.dist-info → skypilot_nightly-1.0.0.dev20251107.dist-info}/licenses/LICENSE +0 -0
  512. {skypilot_nightly-1.0.0.dev20250509.dist-info → skypilot_nightly-1.0.0.dev20251107.dist-info}/top_level.txt +0 -0
@@ -10,7 +10,7 @@ import dataclasses
10
10
  import json
11
11
  import time
12
12
  import typing
13
- from typing import List, Optional, Set
13
+ from typing import Any, Dict, List, Optional, Set, Tuple
14
14
 
15
15
  import cachetools
16
16
 
@@ -18,6 +18,7 @@ from sky import sky_logging
18
18
  from sky import skypilot_config
19
19
  from sky.provision.gcp import constants
20
20
  from sky.provision.kubernetes import utils as kubernetes_utils
21
+ from sky.utils import resources_utils
21
22
  from sky.utils import subprocess_utils
22
23
 
23
24
  if typing.TYPE_CHECKING:
@@ -36,9 +37,10 @@ def is_tpu(resources: Optional['resources_lib.Resources']) -> bool:
36
37
  def is_tpu_vm(resources: Optional['resources_lib.Resources']) -> bool:
37
38
  if not is_tpu(resources):
38
39
  return False
39
- assert (resources is not None and len(resources.accelerators) == 1)
40
+ assert (resources is not None and resources.accelerators is not None and
41
+ len(resources.accelerators) == 1)
40
42
  acc, _ = list(resources.accelerators.items())[0]
41
- if kubernetes_utils.is_tpu_on_gke(acc):
43
+ if kubernetes_utils.is_tpu_on_gke(acc, normalize=False):
42
44
  return False
43
45
  if resources.accelerator_args is None:
44
46
  return True
@@ -48,7 +50,7 @@ def is_tpu_vm(resources: Optional['resources_lib.Resources']) -> bool:
48
50
  def is_tpu_vm_pod(resources: Optional['resources_lib.Resources']) -> bool:
49
51
  if not is_tpu_vm(resources):
50
52
  return False
51
- assert resources is not None
53
+ assert resources is not None and resources.accelerators is not None
52
54
  acc, _ = list(resources.accelerators.items())[0]
53
55
  return not acc.endswith('-8')
54
56
 
@@ -136,10 +138,16 @@ def _list_reservations_for_instance_type(
136
138
  For example, if we have a specific reservation with n1-highmem-8
137
139
  in us-central1-c. `sky launch --gpus V100` will fail.
138
140
  """
139
- prioritize_reservations = skypilot_config.get_nested(
140
- ('gcp', 'prioritize_reservations'), False)
141
- specific_reservations = skypilot_config.get_nested(
142
- ('gcp', 'specific_reservations'), [])
141
+ prioritize_reservations = skypilot_config.get_effective_region_config(
142
+ cloud='gcp',
143
+ region=None,
144
+ keys=('prioritize_reservations',),
145
+ default_value=False)
146
+ specific_reservations = skypilot_config.get_effective_region_config(
147
+ cloud='gcp',
148
+ region=None,
149
+ keys=('specific_reservations',),
150
+ default_value=[])
143
151
  if not prioritize_reservations and not specific_reservations:
144
152
  return []
145
153
  logger.debug(f'Querying GCP reservations for instance {instance_type!r}')
@@ -169,14 +177,23 @@ def _list_reservations_for_instance_type(
169
177
 
170
178
  def get_minimal_compute_permissions() -> List[str]:
171
179
  permissions = copy.copy(constants.VM_MINIMAL_PERMISSIONS)
172
- if skypilot_config.get_nested(('gcp', 'vpc_name'), None) is None:
180
+ if skypilot_config.get_effective_region_config(
181
+ cloud='gcp', region=None, keys=('vpc_name',),
182
+ default_value=None) is None:
173
183
  # If custom VPC is not specified, permissions to modify network are
174
184
  # required to ensure SkyPilot to be able to setup the network, and
175
185
  # allow opening ports (e.g., via `resources.ports`).
176
186
  permissions += constants.FIREWALL_PERMISSIONS
177
187
 
178
- if (skypilot_config.get_nested(('gcp', 'prioritize_reservations'), False) or
179
- skypilot_config.get_nested(('gcp', 'specific_reservations'), [])):
188
+ if (skypilot_config.get_effective_region_config(
189
+ cloud='gcp',
190
+ region=None,
191
+ keys=('prioritize_reservations',),
192
+ default_value=False) or skypilot_config.get_effective_region_config(
193
+ cloud='gcp',
194
+ region=None,
195
+ keys=('specific_reservations',),
196
+ default_value=[])):
180
197
  permissions += constants.RESERVATION_PERMISSIONS
181
198
 
182
199
  permissions += constants.GCP_MINIMAL_PERMISSIONS
@@ -190,3 +207,62 @@ def get_minimal_storage_permissions() -> List[str]:
190
207
  permissions += constants.GCP_MINIMAL_PERMISSIONS
191
208
 
192
209
  return permissions
210
+
211
+
212
+ # Get the DWS configuration for the given context in GKE.
213
+ def get_dws_config(
214
+ context: str,
215
+ k8s_kueue_local_queue_name: Optional[str],
216
+ cluster_config_overrides: Optional[Dict[str, Any]] = None,
217
+ ) -> Tuple[bool, bool, Optional[int]]:
218
+ """Get the DWS configuration for the given context.
219
+
220
+ Args:
221
+ context: The context to get the DWS configuration for.
222
+ k8s_kueue_local_queue_name: The name of the Kueue local queue.
223
+ cluster_config_overrides: The cluster config overrides.
224
+
225
+ Returns:
226
+ A tuple of (enable_flex_start,
227
+ enable_flex_start_queued_provisioning,
228
+ max_run_duration_seconds).
229
+
230
+ Raises:
231
+ ValueError: If k8s_kueue_local_queue_name is missing to enable
232
+ flex start queued provisioning for the given context.
233
+ """
234
+ dws_config = skypilot_config.get_effective_region_config(
235
+ cloud='kubernetes',
236
+ region=context,
237
+ keys=('dws',),
238
+ default_value={},
239
+ override_configs=cluster_config_overrides)
240
+ if not dws_config:
241
+ return False, False, None
242
+
243
+ enabled = dws_config.get('enabled', False)
244
+ if not enabled:
245
+ return False, False, None
246
+
247
+ enable_flex_start = False
248
+ enable_flex_start_queued_provisioning = False
249
+ max_run_duration_seconds = None
250
+ # If users already use Kueue, use the flex start with queued
251
+ # provisioning mode.
252
+ if k8s_kueue_local_queue_name:
253
+ enable_flex_start_queued_provisioning = True
254
+ else:
255
+ enable_flex_start = True
256
+
257
+ if not enable_flex_start_queued_provisioning:
258
+ return (enable_flex_start, enable_flex_start_queued_provisioning,
259
+ max_run_duration_seconds)
260
+
261
+ # Max run duration is only used in the flex start with queued
262
+ # provisioning mode.
263
+ max_run_duration = dws_config.get('max_run_duration', None)
264
+ if max_run_duration:
265
+ max_run_duration_seconds = resources_utils.parse_time_minutes(
266
+ max_run_duration) * 60
267
+ return (enable_flex_start, enable_flex_start_queued_provisioning,
268
+ max_run_duration_seconds)
@@ -105,22 +105,34 @@ class OCIConfig:
105
105
  @classmethod
106
106
  def get_compartment(cls, region):
107
107
  # Allow task(cluster)-specific compartment/VCN parameters.
108
- default_compartment_ocid = skypilot_config.get_nested(
109
- ('oci', 'default', 'compartment_ocid'), None)
110
- compartment = skypilot_config.get_nested(
111
- ('oci', region, 'compartment_ocid'), default_compartment_ocid)
108
+ default_compartment_ocid = skypilot_config.get_effective_region_config(
109
+ cloud='oci',
110
+ region='default',
111
+ keys=('compartment_ocid',),
112
+ default_value=None)
113
+ compartment = skypilot_config.get_effective_region_config(
114
+ cloud='oci',
115
+ region=region,
116
+ keys=('compartment_ocid',),
117
+ default_value=default_compartment_ocid)
112
118
  return compartment
113
119
 
114
120
  @classmethod
115
121
  def get_vcn_ocid(cls, region):
116
122
  # Will reuse the regional VCN if specified.
117
- vcn = skypilot_config.get_nested(('oci', region, 'vcn_ocid'), None)
123
+ vcn = skypilot_config.get_effective_region_config(cloud='oci',
124
+ region=region,
125
+ keys=('vcn_ocid',),
126
+ default_value=None)
118
127
  return vcn
119
128
 
120
129
  @classmethod
121
130
  def get_vcn_subnet(cls, region):
122
131
  # Will reuse the subnet if specified.
123
- vcn = skypilot_config.get_nested(('oci', region, 'vcn_subnet'), None)
132
+ vcn = skypilot_config.get_effective_region_config(cloud='oci',
133
+ region=region,
134
+ keys=('vcn_subnet',),
135
+ default_value=None)
124
136
  return vcn
125
137
 
126
138
  @classmethod
@@ -129,16 +141,22 @@ class OCIConfig:
129
141
  # we give a choice to set the default image tag (for gpu instances) in
130
142
  # the sky's user-config file (if not specified, use the hardcode one at
131
143
  # last)
132
- return skypilot_config.get_nested(('oci', 'default', 'image_tag_gpu'),
133
- 'skypilot:gpu-ubuntu-2204')
144
+ return skypilot_config.get_effective_region_config(
145
+ cloud='oci',
146
+ region='default',
147
+ keys=('image_tag_gpu',),
148
+ default_value='skypilot:gpu-ubuntu-2204')
134
149
 
135
150
  @classmethod
136
151
  def get_default_image_tag(cls) -> str:
137
152
  # Get the default image tag. Instead of hardcoding, we give a choice to
138
153
  # set the default image tag in the sky's user-config file. (if not
139
154
  # specified, use the hardcode one at last)
140
- return skypilot_config.get_nested(
141
- ('oci', 'default', 'image_tag_general'), 'skypilot:cpu-ubuntu-2204')
155
+ return skypilot_config.get_effective_region_config(
156
+ cloud='oci',
157
+ region='default',
158
+ keys=('image_tag_general',),
159
+ default_value='skypilot:cpu-ubuntu-2204')
142
160
 
143
161
  @classmethod
144
162
  def get_sky_user_config_file(cls) -> str:
@@ -152,16 +170,22 @@ class OCIConfig:
152
170
 
153
171
  @classmethod
154
172
  def get_profile(cls) -> str:
155
- return skypilot_config.get_nested(
156
- ('oci', 'default', 'oci_config_profile'), 'DEFAULT')
173
+ return skypilot_config.get_effective_region_config(
174
+ cloud='oci',
175
+ region='default',
176
+ keys=('oci_config_profile',),
177
+ default_value='DEFAULT')
157
178
 
158
179
  @classmethod
159
180
  def get_default_image_os(cls) -> str:
160
181
  # Get the default image OS. Instead of hardcoding, we give a choice to
161
182
  # set the default image OS type in the sky's user-config file. (if not
162
183
  # specified, use the hardcode one at last)
163
- return skypilot_config.get_nested(('oci', 'default', 'image_os_type'),
164
- 'ubuntu')
184
+ return skypilot_config.get_effective_region_config(
185
+ cloud='oci',
186
+ region='default',
187
+ keys=('image_os_type',),
188
+ default_value='ubuntu')
165
189
 
166
190
 
167
191
  oci_config = OCIConfig()
@@ -184,7 +184,7 @@ class SCPClient:
184
184
 
185
185
  def create_instance(self, instance_config):
186
186
  """Launch new instances."""
187
- url = f'{API_ENDPOINT}/virtual-server/v3/virtual-servers'
187
+ url = f'{API_ENDPOINT}/virtual-server/v4/virtual-servers'
188
188
  return self._post(url, instance_config)
189
189
 
190
190
  @_retry
@@ -226,105 +226,113 @@ class SCPClient:
226
226
  raise_scp_error(response)
227
227
  return response.json()
228
228
 
229
- def create_security_group(self, zone_id, vpc, sg_name):
229
+ def create_security_group(self, zone_id, vpc_id, sg_name):
230
230
  url = f'{API_ENDPOINT}/security-group/v3/security-groups'
231
231
  request_body = {
232
232
  'loggable': False,
233
233
  'securityGroupName': sg_name,
234
234
  'serviceZoneId': zone_id,
235
- 'vpcId': vpc,
236
- 'securityGroupDescription': 'skypilot sg'
235
+ 'vpcId': vpc_id,
236
+ 'securityGroupDescription': 'sky security group'
237
237
  }
238
238
  return self._post(url, request_body)
239
239
 
240
- def add_security_group_in_rule(self, sg_id):
241
- url = f'{API_ENDPOINT}/security-group/v2/security-groups/{sg_id}/rules'
242
- request_body = {
243
- 'ruleDirection': 'IN',
244
- 'services': [{
245
- 'serviceType': 'TCP',
246
- 'serviceValue': '22'
247
- }],
248
- 'sourceIpAddresses': ['0.0.0.0/0'],
249
- 'ruleDescription': 'skypilot ssh rule'
250
- }
251
- return self._post(url, request_body)
252
-
253
- def add_security_group_out_rule(self, sg_id):
254
- url = f'{API_ENDPOINT}/security-group/v2/security-groups/{sg_id}/rules'
255
- request_body = {
256
- 'ruleDirection': 'OUT',
257
- 'services': [{
258
- 'serviceType': 'TCP',
259
- 'serviceValue': '21'
260
- }, {
261
- 'serviceType': 'TCP',
262
- 'serviceValue': '22'
263
- }, {
264
- 'serviceType': 'TCP',
265
- 'serviceValue': '80'
266
- }, {
267
- 'serviceType': 'TCP',
268
- 'serviceValue': '443'
269
- }],
270
- 'destinationIpAddresses': ['0.0.0.0/0'],
271
- 'ruleDescription': 'skypilot out rule'
272
- }
273
- return self._post(url, request_body)
274
-
275
- def add_firewall_inbound_rule(self, firewall_id, internal_ip):
276
- url = f'{API_ENDPOINT}/firewall/v2/firewalls/{firewall_id}/rules'
277
- request_body = {
278
- 'sourceIpAddresses': ['0.0.0.0/0'],
279
- 'destinationIpAddresses': [internal_ip],
280
- 'services': [{
281
- 'serviceType': 'TCP',
282
- 'serviceValue': '22'
283
- }],
284
- 'ruleDirection': 'IN',
285
- 'ruleAction': 'ALLOW',
286
- 'isRuleEnabled': True,
287
- 'ruleLocationType': 'FIRST',
288
- 'ruleDescription': 'description'
289
- }
290
- return self._post(url, request_body)
291
-
292
- def add_firewall_outbound_rule(self, firewall_id, internal_ip):
293
- url = f'{API_ENDPOINT}/firewall/v2/firewalls/{firewall_id}/rules'
294
- request_body = {
295
- 'sourceIpAddresses': [internal_ip],
296
- 'destinationIpAddresses': ['0.0.0.0/0'],
297
- 'services': [{
298
- 'serviceType': 'TCP',
299
- 'serviceValue': '21'
300
- }, {
301
- 'serviceType': 'TCP',
302
- 'serviceValue': '22'
303
- }, {
304
- 'serviceType': 'TCP',
305
- 'serviceValue': '80'
306
- }, {
307
- 'serviceType': 'TCP',
308
- 'serviceValue': '443'
309
- }],
310
- 'ruleDirection': 'OUT',
311
- 'ruleAction': 'ALLOW',
312
- 'isRuleEnabled': True,
313
- 'ruleLocationType': 'FIRST',
314
- 'ruleDescription': 'description'
315
- }
316
- return self._post(url, request_body)
240
+ def _security_group_rule_not_exist(self, sg_id, direction, ports):
241
+ response = self.get_security_group_rules(sg_id)
242
+ rules = []
243
+ for rule in response:
244
+ rule_direction = rule['ruleDirection']
245
+ if rule_direction == direction:
246
+ rules.append(rule)
247
+ for rule in rules:
248
+ port_list = ','.join(rule['tcpServices'])
249
+ port = ','.join(ports)
250
+ if port == port_list:
251
+ return False
252
+ return True
253
+
254
+ def add_security_group_rule(self, sg_id, direction,
255
+ ports: Optional[List[str]]):
256
+ if ports is None:
257
+ if direction == 'IN':
258
+ ports = ['22']
259
+ else:
260
+ ports = ['21', '22', '80', '443']
261
+ services = []
262
+ for port in ports:
263
+ services.append({'serviceType': 'TCP', 'serviceValue': port})
264
+ if self._security_group_rule_not_exist(sg_id, direction, ports):
265
+ url = f'{API_ENDPOINT}/security-group/v2/security-groups/{sg_id}/rules' # pylint: disable=line-too-long
266
+ if direction == 'IN':
267
+ target_address = 'sourceIpAddresses'
268
+ else:
269
+ target_address = 'destinationIpAddresses'
270
+ request_body = {
271
+ 'ruleDirection': direction,
272
+ 'services': services,
273
+ target_address: ['0.0.0.0/0'],
274
+ 'ruleDescription': 'sky security group rule'
275
+ }
276
+ return self._post(url, request_body)
277
+
278
+ def _firewall_rule_not_exist(self, firewall_id, internal_ip, direction,
279
+ ports):
280
+ response = self.get_firewall_rules(firewall_id)
281
+ rules = []
282
+ for rule in response:
283
+ if direction == 'IN':
284
+ if internal_ip == rule['destinationIpAddresses'][0]:
285
+ rules.append(rule)
286
+ else:
287
+ if internal_ip == rule['sourceIpAddresses'][0]:
288
+ rules.append(rule)
289
+ for rule in rules:
290
+ port_list = ','.join(rule['tcpServices'])
291
+ port = ','.join(ports)
292
+ if port == port_list:
293
+ return False
294
+ return True
295
+
296
+ def add_firewall_rule(self, firewall_id, internal_ip, direction, ports):
297
+ if ports is None:
298
+ if direction == 'IN':
299
+ ports = ['22']
300
+ else:
301
+ ports = ['21', '22', '80', '443']
302
+ services = []
303
+ for port in ports:
304
+ services.append({'serviceType': 'TCP', 'serviceValue': port})
305
+ if self._firewall_rule_not_exist(firewall_id, internal_ip, direction,
306
+ ports):
307
+ url = f'{API_ENDPOINT}/firewall/v2/firewalls/{firewall_id}/rules'
308
+ if direction == 'IN':
309
+ source_ip = '0.0.0.0/0'
310
+ destination_ip = internal_ip
311
+ else:
312
+ source_ip = internal_ip
313
+ destination_ip = '0.0.0.0/0'
314
+ request_body = {
315
+ 'sourceIpAddresses': [source_ip],
316
+ 'destinationIpAddresses': [destination_ip],
317
+ 'services': services,
318
+ 'ruleDirection': direction,
319
+ 'ruleAction': 'ALLOW',
320
+ 'isRuleEnabled': True,
321
+ 'ruleLocationType': 'FIRST',
322
+ 'ruleDescription': 'sky firewall rule'
323
+ }
324
+ return self._post(url, request_body)
317
325
 
318
- def terminate_instance(self, vm_id):
319
- url = f'{API_ENDPOINT}/virtual-server/v2/virtual-servers/{vm_id}'
326
+ def terminate_instance(self, instance_id):
327
+ url = f'{API_ENDPOINT}/virtual-server/v2/virtual-servers/{instance_id}'
320
328
  return self._delete(url)
321
329
 
322
- def list_instances(self) -> List[dict]:
330
+ def get_instances(self) -> List[dict]:
323
331
  """List existing instances."""
324
332
  url = f'{API_ENDPOINT}/virtual-server/v2/virtual-servers'
325
333
  return self._get(url)
326
334
 
327
- def list_catalog(self) -> Dict[str, Any]:
335
+ def get_catalog(self) -> Dict[str, Any]:
328
336
  """List offered instances and their availability."""
329
337
  response = requests.get(f'{API_ENDPOINT}/instance-types',
330
338
  headers=self.headers)
@@ -362,89 +370,134 @@ class SCPClient:
362
370
  self.headers['X-Cmp-Timestamp'] = self.timestamp
363
371
 
364
372
  def set_signature(self, method: str, url: str) -> None:
365
-
366
373
  self.signature = self.get_signature(url=url, method=method)
367
374
  self.headers['X-Cmp-Signature'] = self.signature
368
375
 
369
- def list_nic_details(self, virtual_server_id) -> List[dict]:
370
- """List existing instances."""
371
- url = f'{API_ENDPOINT}/virtual-server/v2/virtual-servers/{virtual_server_id}/nics' # pylint: disable=line-too-long
376
+ def get_nic(self, instance_id) -> List[dict]:
377
+ url = f'{API_ENDPOINT}/virtual-server/v2/virtual-servers/{instance_id}/nics' # pylint: disable=line-too-long
372
378
  return self._get(url)
373
379
 
374
- def get_external_ip(self, virtual_server_id, ip):
375
- nic_details_list = self.list_nic_details(
376
- virtual_server_id=virtual_server_id)
377
- for nic_details in nic_details_list:
378
- if (nic_details['ip'] == ip and
379
- nic_details['subnetType'] == 'PUBLIC'):
380
- return nic_details['natIp']
380
+ def get_external_ip(self, instance_id, ip):
381
+ nics = self.get_nic(instance_id=instance_id)
382
+ for nic in nics:
383
+ if (nic['ip'] == ip and nic['subnetType'] == 'PUBLIC'):
384
+ return nic['natIp']
381
385
  return None
382
386
 
383
- def list_zones(self) -> List[dict]:
387
+ def get_zones(self) -> List[dict]:
384
388
  url = f'{API_ENDPOINT}/project/v3/projects/{self.project_id}/zones'
385
389
  return self._get(url)
386
390
 
387
- def list_products(self, service_zone_id) -> List[dict]:
388
- url = f'{API_ENDPOINT}/product/v2/zones/{service_zone_id}/products'
389
- return self._get(url)
390
-
391
- def list_product_groups(self, service_zone_id) -> List[dict]:
392
- url = f'{API_ENDPOINT}/product/v2/zones/{service_zone_id}/product-groups' # pylint: disable=line-too-long
393
- return self._get(url)
394
-
395
- def list_vpcs(self, service_zone_id) -> List[dict]:
391
+ def get_vpcs(self, service_zone_id) -> List[dict]:
396
392
  url = f'{API_ENDPOINT}/vpc/v2/vpcs?serviceZoneId={service_zone_id}'
397
393
  return self._get(url)
398
394
 
399
- def list_subnets(self) -> List[dict]:
395
+ def get_subnets(self) -> List[dict]:
400
396
  url = f'{API_ENDPOINT}/subnet/v2/subnets?subnetTypes=PUBLIC'
401
397
  return self._get(url)
402
398
 
403
- def del_security_group(self, sg_id):
399
+ def delete_security_group(self, sg_id):
404
400
  url = f'{API_ENDPOINT}/security-group/v2/security-groups/{sg_id}'
405
401
  return self._delete(url)
406
402
 
407
- def del_firwall_rules(self, firewall_id, rule_id_list):
403
+ def delete_firewall_rule(self, firewall_id, rule_ids):
408
404
  url = f'{API_ENDPOINT}/firewall/v2/firewalls/{firewall_id}/rules'
409
- request_body = {'ruleDeletionType': 'PARTIAL', 'ruleIds': rule_id_list}
405
+ request_body = {'ruleDeletionType': 'PARTIAL', 'ruleIds': rule_ids}
410
406
  return self._delete(url, request_body=request_body)
411
407
 
412
- def list_security_groups(self, vpc_id=None, sg_name=None):
408
+ def get_security_groups(self, vpc_id=None, sg_name=None):
413
409
  url = f'{API_ENDPOINT}/security-group/v2/security-groups'
414
410
  parameter = []
415
411
  if vpc_id is not None:
416
412
  parameter.append('vpcId=' + vpc_id)
417
413
  if sg_name is not None:
418
414
  parameter.append('securityGroupName=' + sg_name)
419
- if parameter:
415
+ if len(parameter) > 0:
420
416
  url = url + '?' + '&'.join(parameter)
421
417
  return self._get(url)
422
418
 
423
- def list_igw(self):
419
+ def get_internet_gateway(self):
424
420
  url = f'{API_ENDPOINT}/internet-gateway/v2/internet-gateways'
425
421
  return self._get(url)
426
422
 
427
- def get_vm_info(self, vm_id):
428
- url = f'{API_ENDPOINT}/virtual-server/v3/virtual-servers/{vm_id}'
429
- return self._get(url, contents_key=None)
430
-
431
- def get_firewal_rule_info(self, firewall_id, rule_id):
423
+ def get_firewall_rule_info(self, firewall_id, rule_id):
432
424
  url = f'{API_ENDPOINT}/firewall/v2/firewalls/{firewall_id}/rules/{rule_id}' # pylint: disable=line-too-long
433
425
  return self._get(url, contents_key=None)
434
426
 
435
- def list_firwalls(self):
427
+ def get_firewalls(self):
436
428
  url = f'{API_ENDPOINT}/firewall/v2/firewalls'
437
429
  return self._get(url)
438
430
 
439
- def list_service_zone_names(self):
431
+ def get_service_zone_names(self):
440
432
  url = f'{API_ENDPOINT}/project/v3/projects/{self.project_id}/zones'
441
433
  zone_contents = self._get(url)
442
434
  return [content['serviceZoneName'] for content in zone_contents]
443
435
 
444
- def start_instance(self, vm_id):
445
- url = f'{API_ENDPOINT}/virtual-server/v2/virtual-servers/{vm_id}/start'
436
+ def start_instance(self, instance_id):
437
+ url = f'{API_ENDPOINT}/virtual-server/v2/virtual-servers/{instance_id}/start' # pylint: disable=line-too-long
446
438
  return self._post(url=url, request_body={})
447
439
 
448
- def stop_instance(self, vm_id):
449
- url = f'{API_ENDPOINT}/virtual-server/v2/virtual-servers/{vm_id}/stop'
440
+ def stop_instance(self, instance_id):
441
+ url = f'{API_ENDPOINT}/virtual-server/v2/virtual-servers/{instance_id}/stop' # pylint: disable=line-too-long
450
442
  return self._post(url=url, request_body={})
443
+
444
+ def get_security_group_rules(self, sg_id):
445
+ url = f'{API_ENDPOINT}/security-group/v2/security-groups/{sg_id}/rules'
446
+ return self._get(url)
447
+
448
+ def get_firewall_rules(self, firewall_id):
449
+ url = f'{API_ENDPOINT}/firewall/v2/firewalls/{firewall_id}/rules'
450
+ return self._get(url)
451
+
452
+ def get_instance_info(self, instance_id):
453
+ url = f'{API_ENDPOINT}/virtual-server/v3/virtual-servers/{instance_id}'
454
+ return self._get(url=url, contents_key=None)
455
+
456
+ def create_vpc(self, zone_id):
457
+ vpc_name = 'skyvpc' + zone_id[5:10]
458
+ request_body = {
459
+ 'serviceZoneId': zone_id,
460
+ 'vpcName': vpc_name,
461
+ 'vpcDescription': 'sky vpc'
462
+ }
463
+ url = f'{API_ENDPOINT}/vpc/v3/vpcs'
464
+ return self._post(url, request_body)
465
+
466
+ def create_subnet(self, vpc_id, zone_id):
467
+ subnet_name = 'skysubnet' + zone_id[5:10]
468
+ request_body = {
469
+ 'subnetCidrBlock': '192.168.0.0/24',
470
+ 'subnetName': subnet_name,
471
+ 'subnetType': 'PUBLIC',
472
+ 'vpcId': vpc_id,
473
+ 'subnetDescription': 'sky subnet'
474
+ }
475
+ url = f'{API_ENDPOINT}/subnet/v2/subnets'
476
+ return self._post(url, request_body)
477
+
478
+ def create_internet_gateway(self, vpc_id):
479
+ request_body = {
480
+ 'firewallEnabled': True,
481
+ 'firewallLoggable': False,
482
+ 'internetGatewayType': 'SHARED',
483
+ 'vpcId': vpc_id,
484
+ 'internetGatewayDescription': 'sky internet gateway'
485
+ }
486
+ url = f'{API_ENDPOINT}/internet-gateway/v4/internet-gateways'
487
+ return self._post(url, request_body)
488
+
489
+ def get_vpc_info(self, vpc_id):
490
+ url = f'{API_ENDPOINT}/vpc/v2/vpcs/{vpc_id}'
491
+ return self._get(url=url, contents_key=None)
492
+
493
+ def get_subnet_info(self, subnet_id):
494
+ url = f'{API_ENDPOINT}/subnet/v2/subnets/{subnet_id}'
495
+ return self._get(url=url, contents_key=None)
496
+
497
+ def get_internet_gateway_info(self, internet_gateway_id):
498
+ url = f'{API_ENDPOINT}/internet-gateway/v2/internet-gateways/{internet_gateway_id}' # pylint: disable=line-too-long
499
+ return self._get(url=url, contents_key=None)
500
+
501
+ def get_key_pairs(self):
502
+ url = f'{API_ENDPOINT}/key-pair/v1/key-pairs'
503
+ return self._get(url=url, contents_key=None)