skypilot-nightly 1.0.0.dev20250901__py3-none-any.whl → 1.0.0.dev20250903__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 (63) hide show
  1. sky/__init__.py +2 -2
  2. sky/adaptors/runpod.py +68 -0
  3. sky/backends/backend_utils.py +5 -3
  4. sky/client/cli/command.py +20 -5
  5. sky/clouds/kubernetes.py +1 -1
  6. sky/clouds/runpod.py +17 -0
  7. sky/dashboard/out/404.html +1 -1
  8. sky/dashboard/out/_next/static/chunks/1121-ec35954c8cbea535.js +1 -0
  9. sky/dashboard/out/_next/static/chunks/3015-8089ed1e0b7e37fd.js +1 -0
  10. sky/dashboard/out/_next/static/chunks/pages/clusters/[cluster]/[job]-b77360a343d48902.js +16 -0
  11. sky/dashboard/out/_next/static/chunks/webpack-60556df644cd5d71.js +1 -0
  12. sky/dashboard/out/_next/static/{EqPZ0ygxa__3XPBVJ9dpy → yLz6EPhW_XXmnNs1I6dmS}/_buildManifest.js +1 -1
  13. sky/dashboard/out/clusters/[cluster]/[job].html +1 -1
  14. sky/dashboard/out/clusters/[cluster].html +1 -1
  15. sky/dashboard/out/clusters.html +1 -1
  16. sky/dashboard/out/config.html +1 -1
  17. sky/dashboard/out/index.html +1 -1
  18. sky/dashboard/out/infra/[context].html +1 -1
  19. sky/dashboard/out/infra.html +1 -1
  20. sky/dashboard/out/jobs/[job].html +1 -1
  21. sky/dashboard/out/jobs/pools/[pool].html +1 -1
  22. sky/dashboard/out/jobs.html +1 -1
  23. sky/dashboard/out/users.html +1 -1
  24. sky/dashboard/out/volumes.html +1 -1
  25. sky/dashboard/out/workspace/new.html +1 -1
  26. sky/dashboard/out/workspaces/[name].html +1 -1
  27. sky/dashboard/out/workspaces.html +1 -1
  28. sky/global_user_state.py +5 -2
  29. sky/models.py +1 -0
  30. sky/provision/runpod/__init__.py +3 -0
  31. sky/provision/runpod/instance.py +17 -0
  32. sky/provision/runpod/utils.py +23 -5
  33. sky/provision/runpod/volume.py +158 -0
  34. sky/server/auth/oauth2_proxy.py +6 -0
  35. sky/server/requests/payloads.py +7 -1
  36. sky/server/requests/preconditions.py +8 -7
  37. sky/server/requests/requests.py +123 -57
  38. sky/server/server.py +32 -25
  39. sky/server/stream_utils.py +14 -6
  40. sky/server/uvicorn.py +2 -1
  41. sky/templates/kubernetes-ray.yml.j2 +5 -5
  42. sky/templates/runpod-ray.yml.j2 +8 -0
  43. sky/utils/benchmark_utils.py +60 -0
  44. sky/utils/command_runner.py +4 -0
  45. sky/utils/db/migration_utils.py +20 -4
  46. sky/utils/resource_checker.py +6 -5
  47. sky/utils/schemas.py +1 -1
  48. sky/utils/volume.py +3 -0
  49. sky/volumes/client/sdk.py +28 -0
  50. sky/volumes/server/server.py +11 -1
  51. sky/volumes/utils.py +117 -68
  52. sky/volumes/volume.py +98 -39
  53. {skypilot_nightly-1.0.0.dev20250901.dist-info → skypilot_nightly-1.0.0.dev20250903.dist-info}/METADATA +33 -33
  54. {skypilot_nightly-1.0.0.dev20250901.dist-info → skypilot_nightly-1.0.0.dev20250903.dist-info}/RECORD +59 -57
  55. sky/dashboard/out/_next/static/chunks/1121-8afcf719ea87debc.js +0 -1
  56. sky/dashboard/out/_next/static/chunks/3015-6c9c09593b1e67b6.js +0 -1
  57. sky/dashboard/out/_next/static/chunks/pages/clusters/[cluster]/[job]-06afb50d25f7c61f.js +0 -16
  58. sky/dashboard/out/_next/static/chunks/webpack-6e76f636a048e145.js +0 -1
  59. /sky/dashboard/out/_next/static/{EqPZ0ygxa__3XPBVJ9dpy → yLz6EPhW_XXmnNs1I6dmS}/_ssgManifest.js +0 -0
  60. {skypilot_nightly-1.0.0.dev20250901.dist-info → skypilot_nightly-1.0.0.dev20250903.dist-info}/WHEEL +0 -0
  61. {skypilot_nightly-1.0.0.dev20250901.dist-info → skypilot_nightly-1.0.0.dev20250903.dist-info}/entry_points.txt +0 -0
  62. {skypilot_nightly-1.0.0.dev20250901.dist-info → skypilot_nightly-1.0.0.dev20250903.dist-info}/licenses/LICENSE +0 -0
  63. {skypilot_nightly-1.0.0.dev20250901.dist-info → skypilot_nightly-1.0.0.dev20250903.dist-info}/top_level.txt +0 -0
@@ -1 +1 @@
1
- <!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="/dashboard/_next/static/css/4614e06482d7309e.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/4614e06482d7309e.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/dashboard/_next/static/chunks/polyfills-78c92fac7aa8fdd8.js"></script><script src="/dashboard/_next/static/chunks/webpack-6e76f636a048e145.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-cf60a09ccd051a10.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-f15ccb73239a3bf1.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-ce361c6959bc2001.js" defer=""></script><script src="/dashboard/_next/static/chunks/616-3d59f75e2ccf9321.js" defer=""></script><script src="/dashboard/_next/static/chunks/6130-2be46d70a38f1e82.js" defer=""></script><script src="/dashboard/_next/static/chunks/5739-d67458fcb1386c92.js" defer=""></script><script src="/dashboard/_next/static/chunks/7411-b15471acd2cba716.js" defer=""></script><script src="/dashboard/_next/static/chunks/1272-1ef0bf0237faccdb.js" defer=""></script><script src="/dashboard/_next/static/chunks/754-d0da8ab45f9509e9.js" defer=""></script><script src="/dashboard/_next/static/chunks/6989-01359c57e018caa4.js" defer=""></script><script src="/dashboard/_next/static/chunks/3850-ff4a9a69d978632b.js" defer=""></script><script src="/dashboard/_next/static/chunks/8969-4a6f1a928fb6d370.js" defer=""></script><script src="/dashboard/_next/static/chunks/6135-4b4d5e824b7f9d3c.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/jobs/%5Bjob%5D-dd64309c3fe67ed2.js" defer=""></script><script src="/dashboard/_next/static/EqPZ0ygxa__3XPBVJ9dpy/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/EqPZ0ygxa__3XPBVJ9dpy/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/jobs/[job]","query":{},"buildId":"EqPZ0ygxa__3XPBVJ9dpy","assetPrefix":"/dashboard","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
1
+ <!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="/dashboard/_next/static/css/4614e06482d7309e.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/4614e06482d7309e.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/dashboard/_next/static/chunks/polyfills-78c92fac7aa8fdd8.js"></script><script src="/dashboard/_next/static/chunks/webpack-60556df644cd5d71.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-cf60a09ccd051a10.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-f15ccb73239a3bf1.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-ce361c6959bc2001.js" defer=""></script><script src="/dashboard/_next/static/chunks/616-3d59f75e2ccf9321.js" defer=""></script><script src="/dashboard/_next/static/chunks/6130-2be46d70a38f1e82.js" defer=""></script><script src="/dashboard/_next/static/chunks/5739-d67458fcb1386c92.js" defer=""></script><script src="/dashboard/_next/static/chunks/7411-b15471acd2cba716.js" defer=""></script><script src="/dashboard/_next/static/chunks/1272-1ef0bf0237faccdb.js" defer=""></script><script src="/dashboard/_next/static/chunks/754-d0da8ab45f9509e9.js" defer=""></script><script src="/dashboard/_next/static/chunks/6989-01359c57e018caa4.js" defer=""></script><script src="/dashboard/_next/static/chunks/3850-ff4a9a69d978632b.js" defer=""></script><script src="/dashboard/_next/static/chunks/8969-4a6f1a928fb6d370.js" defer=""></script><script src="/dashboard/_next/static/chunks/6135-4b4d5e824b7f9d3c.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/jobs/%5Bjob%5D-dd64309c3fe67ed2.js" defer=""></script><script src="/dashboard/_next/static/yLz6EPhW_XXmnNs1I6dmS/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/yLz6EPhW_XXmnNs1I6dmS/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/jobs/[job]","query":{},"buildId":"yLz6EPhW_XXmnNs1I6dmS","assetPrefix":"/dashboard","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
@@ -1 +1 @@
1
- <!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="/dashboard/_next/static/css/4614e06482d7309e.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/4614e06482d7309e.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/dashboard/_next/static/chunks/polyfills-78c92fac7aa8fdd8.js"></script><script src="/dashboard/_next/static/chunks/webpack-6e76f636a048e145.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-cf60a09ccd051a10.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-f15ccb73239a3bf1.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-ce361c6959bc2001.js" defer=""></script><script src="/dashboard/_next/static/chunks/616-3d59f75e2ccf9321.js" defer=""></script><script src="/dashboard/_next/static/chunks/6130-2be46d70a38f1e82.js" defer=""></script><script src="/dashboard/_next/static/chunks/5739-d67458fcb1386c92.js" defer=""></script><script src="/dashboard/_next/static/chunks/1272-1ef0bf0237faccdb.js" defer=""></script><script src="/dashboard/_next/static/chunks/754-d0da8ab45f9509e9.js" defer=""></script><script src="/dashboard/_next/static/chunks/6989-01359c57e018caa4.js" defer=""></script><script src="/dashboard/_next/static/chunks/3850-ff4a9a69d978632b.js" defer=""></script><script src="/dashboard/_next/static/chunks/8969-4a6f1a928fb6d370.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/jobs/pools/%5Bpool%5D-07349868f7905d37.js" defer=""></script><script src="/dashboard/_next/static/EqPZ0ygxa__3XPBVJ9dpy/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/EqPZ0ygxa__3XPBVJ9dpy/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/jobs/pools/[pool]","query":{},"buildId":"EqPZ0ygxa__3XPBVJ9dpy","assetPrefix":"/dashboard","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
1
+ <!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="/dashboard/_next/static/css/4614e06482d7309e.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/4614e06482d7309e.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/dashboard/_next/static/chunks/polyfills-78c92fac7aa8fdd8.js"></script><script src="/dashboard/_next/static/chunks/webpack-60556df644cd5d71.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-cf60a09ccd051a10.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-f15ccb73239a3bf1.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-ce361c6959bc2001.js" defer=""></script><script src="/dashboard/_next/static/chunks/616-3d59f75e2ccf9321.js" defer=""></script><script src="/dashboard/_next/static/chunks/6130-2be46d70a38f1e82.js" defer=""></script><script src="/dashboard/_next/static/chunks/5739-d67458fcb1386c92.js" defer=""></script><script src="/dashboard/_next/static/chunks/1272-1ef0bf0237faccdb.js" defer=""></script><script src="/dashboard/_next/static/chunks/754-d0da8ab45f9509e9.js" defer=""></script><script src="/dashboard/_next/static/chunks/6989-01359c57e018caa4.js" defer=""></script><script src="/dashboard/_next/static/chunks/3850-ff4a9a69d978632b.js" defer=""></script><script src="/dashboard/_next/static/chunks/8969-4a6f1a928fb6d370.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/jobs/pools/%5Bpool%5D-07349868f7905d37.js" defer=""></script><script src="/dashboard/_next/static/yLz6EPhW_XXmnNs1I6dmS/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/yLz6EPhW_XXmnNs1I6dmS/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/jobs/pools/[pool]","query":{},"buildId":"yLz6EPhW_XXmnNs1I6dmS","assetPrefix":"/dashboard","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
@@ -1 +1 @@
1
- <!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="/dashboard/_next/static/css/4614e06482d7309e.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/4614e06482d7309e.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/dashboard/_next/static/chunks/polyfills-78c92fac7aa8fdd8.js"></script><script src="/dashboard/_next/static/chunks/webpack-6e76f636a048e145.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-cf60a09ccd051a10.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-f15ccb73239a3bf1.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-ce361c6959bc2001.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/jobs-7421e63ac35f8fce.js" defer=""></script><script src="/dashboard/_next/static/EqPZ0ygxa__3XPBVJ9dpy/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/EqPZ0ygxa__3XPBVJ9dpy/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/jobs","query":{},"buildId":"EqPZ0ygxa__3XPBVJ9dpy","assetPrefix":"/dashboard","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
1
+ <!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="/dashboard/_next/static/css/4614e06482d7309e.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/4614e06482d7309e.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/dashboard/_next/static/chunks/polyfills-78c92fac7aa8fdd8.js"></script><script src="/dashboard/_next/static/chunks/webpack-60556df644cd5d71.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-cf60a09ccd051a10.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-f15ccb73239a3bf1.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-ce361c6959bc2001.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/jobs-7421e63ac35f8fce.js" defer=""></script><script src="/dashboard/_next/static/yLz6EPhW_XXmnNs1I6dmS/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/yLz6EPhW_XXmnNs1I6dmS/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/jobs","query":{},"buildId":"yLz6EPhW_XXmnNs1I6dmS","assetPrefix":"/dashboard","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
@@ -1 +1 @@
1
- <!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="/dashboard/_next/static/css/4614e06482d7309e.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/4614e06482d7309e.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/dashboard/_next/static/chunks/polyfills-78c92fac7aa8fdd8.js"></script><script src="/dashboard/_next/static/chunks/webpack-6e76f636a048e145.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-cf60a09ccd051a10.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-f15ccb73239a3bf1.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-ce361c6959bc2001.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/users-018bf31cda52e11b.js" defer=""></script><script src="/dashboard/_next/static/EqPZ0ygxa__3XPBVJ9dpy/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/EqPZ0ygxa__3XPBVJ9dpy/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/users","query":{},"buildId":"EqPZ0ygxa__3XPBVJ9dpy","assetPrefix":"/dashboard","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
1
+ <!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="/dashboard/_next/static/css/4614e06482d7309e.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/4614e06482d7309e.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/dashboard/_next/static/chunks/polyfills-78c92fac7aa8fdd8.js"></script><script src="/dashboard/_next/static/chunks/webpack-60556df644cd5d71.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-cf60a09ccd051a10.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-f15ccb73239a3bf1.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-ce361c6959bc2001.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/users-018bf31cda52e11b.js" defer=""></script><script src="/dashboard/_next/static/yLz6EPhW_XXmnNs1I6dmS/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/yLz6EPhW_XXmnNs1I6dmS/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/users","query":{},"buildId":"yLz6EPhW_XXmnNs1I6dmS","assetPrefix":"/dashboard","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
@@ -1 +1 @@
1
- <!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="/dashboard/_next/static/css/4614e06482d7309e.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/4614e06482d7309e.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/dashboard/_next/static/chunks/polyfills-78c92fac7aa8fdd8.js"></script><script src="/dashboard/_next/static/chunks/webpack-6e76f636a048e145.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-cf60a09ccd051a10.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-f15ccb73239a3bf1.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-ce361c6959bc2001.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/volumes-739726d6b823f532.js" defer=""></script><script src="/dashboard/_next/static/EqPZ0ygxa__3XPBVJ9dpy/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/EqPZ0ygxa__3XPBVJ9dpy/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/volumes","query":{},"buildId":"EqPZ0ygxa__3XPBVJ9dpy","assetPrefix":"/dashboard","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
1
+ <!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="/dashboard/_next/static/css/4614e06482d7309e.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/4614e06482d7309e.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/dashboard/_next/static/chunks/polyfills-78c92fac7aa8fdd8.js"></script><script src="/dashboard/_next/static/chunks/webpack-60556df644cd5d71.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-cf60a09ccd051a10.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-f15ccb73239a3bf1.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-ce361c6959bc2001.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/volumes-739726d6b823f532.js" defer=""></script><script src="/dashboard/_next/static/yLz6EPhW_XXmnNs1I6dmS/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/yLz6EPhW_XXmnNs1I6dmS/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/volumes","query":{},"buildId":"yLz6EPhW_XXmnNs1I6dmS","assetPrefix":"/dashboard","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
@@ -1 +1 @@
1
- <!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="/dashboard/_next/static/css/4614e06482d7309e.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/4614e06482d7309e.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/dashboard/_next/static/chunks/polyfills-78c92fac7aa8fdd8.js"></script><script src="/dashboard/_next/static/chunks/webpack-6e76f636a048e145.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-cf60a09ccd051a10.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-f15ccb73239a3bf1.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-ce361c6959bc2001.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/workspace/new-3f88a1c7e86a3f86.js" defer=""></script><script src="/dashboard/_next/static/EqPZ0ygxa__3XPBVJ9dpy/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/EqPZ0ygxa__3XPBVJ9dpy/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/workspace/new","query":{},"buildId":"EqPZ0ygxa__3XPBVJ9dpy","assetPrefix":"/dashboard","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
1
+ <!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="/dashboard/_next/static/css/4614e06482d7309e.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/4614e06482d7309e.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/dashboard/_next/static/chunks/polyfills-78c92fac7aa8fdd8.js"></script><script src="/dashboard/_next/static/chunks/webpack-60556df644cd5d71.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-cf60a09ccd051a10.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-f15ccb73239a3bf1.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-ce361c6959bc2001.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/workspace/new-3f88a1c7e86a3f86.js" defer=""></script><script src="/dashboard/_next/static/yLz6EPhW_XXmnNs1I6dmS/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/yLz6EPhW_XXmnNs1I6dmS/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/workspace/new","query":{},"buildId":"yLz6EPhW_XXmnNs1I6dmS","assetPrefix":"/dashboard","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
@@ -1 +1 @@
1
- <!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="/dashboard/_next/static/css/4614e06482d7309e.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/4614e06482d7309e.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/dashboard/_next/static/chunks/polyfills-78c92fac7aa8fdd8.js"></script><script src="/dashboard/_next/static/chunks/webpack-6e76f636a048e145.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-cf60a09ccd051a10.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-f15ccb73239a3bf1.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-ce361c6959bc2001.js" defer=""></script><script src="/dashboard/_next/static/chunks/616-3d59f75e2ccf9321.js" defer=""></script><script src="/dashboard/_next/static/chunks/6130-2be46d70a38f1e82.js" defer=""></script><script src="/dashboard/_next/static/chunks/5739-d67458fcb1386c92.js" defer=""></script><script src="/dashboard/_next/static/chunks/7411-b15471acd2cba716.js" defer=""></script><script src="/dashboard/_next/static/chunks/1272-1ef0bf0237faccdb.js" defer=""></script><script src="/dashboard/_next/static/chunks/7205-88191679e7988c57.js" defer=""></script><script src="/dashboard/_next/static/chunks/6989-01359c57e018caa4.js" defer=""></script><script src="/dashboard/_next/static/chunks/3850-ff4a9a69d978632b.js" defer=""></script><script src="/dashboard/_next/static/chunks/8969-4a6f1a928fb6d370.js" defer=""></script><script src="/dashboard/_next/static/chunks/6990-08b2a1cae076a943.js" defer=""></script><script src="/dashboard/_next/static/chunks/6135-4b4d5e824b7f9d3c.js" defer=""></script><script src="/dashboard/_next/static/chunks/1121-8afcf719ea87debc.js" defer=""></script><script src="/dashboard/_next/static/chunks/6601-06114c982db410b6.js" defer=""></script><script src="/dashboard/_next/static/chunks/3015-6c9c09593b1e67b6.js" defer=""></script><script src="/dashboard/_next/static/chunks/1141-943efc7aff0f0c06.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/workspaces/%5Bname%5D-de06e613e20bc977.js" defer=""></script><script src="/dashboard/_next/static/EqPZ0ygxa__3XPBVJ9dpy/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/EqPZ0ygxa__3XPBVJ9dpy/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/workspaces/[name]","query":{},"buildId":"EqPZ0ygxa__3XPBVJ9dpy","assetPrefix":"/dashboard","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
1
+ <!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="/dashboard/_next/static/css/4614e06482d7309e.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/4614e06482d7309e.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/dashboard/_next/static/chunks/polyfills-78c92fac7aa8fdd8.js"></script><script src="/dashboard/_next/static/chunks/webpack-60556df644cd5d71.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-cf60a09ccd051a10.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-f15ccb73239a3bf1.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-ce361c6959bc2001.js" defer=""></script><script src="/dashboard/_next/static/chunks/616-3d59f75e2ccf9321.js" defer=""></script><script src="/dashboard/_next/static/chunks/6130-2be46d70a38f1e82.js" defer=""></script><script src="/dashboard/_next/static/chunks/5739-d67458fcb1386c92.js" defer=""></script><script src="/dashboard/_next/static/chunks/7411-b15471acd2cba716.js" defer=""></script><script src="/dashboard/_next/static/chunks/1272-1ef0bf0237faccdb.js" defer=""></script><script src="/dashboard/_next/static/chunks/7205-88191679e7988c57.js" defer=""></script><script src="/dashboard/_next/static/chunks/6989-01359c57e018caa4.js" defer=""></script><script src="/dashboard/_next/static/chunks/3850-ff4a9a69d978632b.js" defer=""></script><script src="/dashboard/_next/static/chunks/8969-4a6f1a928fb6d370.js" defer=""></script><script src="/dashboard/_next/static/chunks/6990-08b2a1cae076a943.js" defer=""></script><script src="/dashboard/_next/static/chunks/6135-4b4d5e824b7f9d3c.js" defer=""></script><script src="/dashboard/_next/static/chunks/1121-ec35954c8cbea535.js" defer=""></script><script src="/dashboard/_next/static/chunks/6601-06114c982db410b6.js" defer=""></script><script src="/dashboard/_next/static/chunks/3015-8089ed1e0b7e37fd.js" defer=""></script><script src="/dashboard/_next/static/chunks/1141-943efc7aff0f0c06.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/workspaces/%5Bname%5D-de06e613e20bc977.js" defer=""></script><script src="/dashboard/_next/static/yLz6EPhW_XXmnNs1I6dmS/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/yLz6EPhW_XXmnNs1I6dmS/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/workspaces/[name]","query":{},"buildId":"yLz6EPhW_XXmnNs1I6dmS","assetPrefix":"/dashboard","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
@@ -1 +1 @@
1
- <!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="/dashboard/_next/static/css/4614e06482d7309e.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/4614e06482d7309e.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/dashboard/_next/static/chunks/polyfills-78c92fac7aa8fdd8.js"></script><script src="/dashboard/_next/static/chunks/webpack-6e76f636a048e145.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-cf60a09ccd051a10.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-f15ccb73239a3bf1.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-ce361c6959bc2001.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/workspaces-be35b22e2046564c.js" defer=""></script><script src="/dashboard/_next/static/EqPZ0ygxa__3XPBVJ9dpy/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/EqPZ0ygxa__3XPBVJ9dpy/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/workspaces","query":{},"buildId":"EqPZ0ygxa__3XPBVJ9dpy","assetPrefix":"/dashboard","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
1
+ <!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="/dashboard/_next/static/css/4614e06482d7309e.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/4614e06482d7309e.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/dashboard/_next/static/chunks/polyfills-78c92fac7aa8fdd8.js"></script><script src="/dashboard/_next/static/chunks/webpack-60556df644cd5d71.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-cf60a09ccd051a10.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-f15ccb73239a3bf1.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-ce361c6959bc2001.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/workspaces-be35b22e2046564c.js" defer=""></script><script src="/dashboard/_next/static/yLz6EPhW_XXmnNs1I6dmS/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/yLz6EPhW_XXmnNs1I6dmS/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/workspaces","query":{},"buildId":"yLz6EPhW_XXmnNs1I6dmS","assetPrefix":"/dashboard","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
sky/global_user_state.py CHANGED
@@ -299,7 +299,9 @@ def create_table(engine: sqlalchemy.engine.Engine):
299
299
  # a session has already been created with _SQLALCHEMY_ENGINE = e1,
300
300
  # and then another thread overwrites _SQLALCHEMY_ENGINE = e2
301
301
  # which could result in e1 being garbage collected unexpectedly.
302
- def initialize_and_get_db() -> sqlalchemy.engine.Engine:
302
+ def initialize_and_get_db(
303
+ pg_pool_class: Optional[sqlalchemy.pool.Pool] = None
304
+ ) -> sqlalchemy.engine.Engine:
303
305
  global _SQLALCHEMY_ENGINE
304
306
 
305
307
  if _SQLALCHEMY_ENGINE is not None:
@@ -308,7 +310,8 @@ def initialize_and_get_db() -> sqlalchemy.engine.Engine:
308
310
  if _SQLALCHEMY_ENGINE is not None:
309
311
  return _SQLALCHEMY_ENGINE
310
312
  # get an engine to the db
311
- engine = migration_utils.get_engine('state')
313
+ engine = migration_utils.get_engine('state',
314
+ pg_pool_class=pg_pool_class)
312
315
 
313
316
  # run migrations if needed
314
317
  create_table(engine)
sky/models.py CHANGED
@@ -109,3 +109,4 @@ class VolumeConfig(pydantic.BaseModel):
109
109
  size: Optional[str]
110
110
  config: Dict[str, Any] = {}
111
111
  labels: Optional[Dict[str, str]] = None
112
+ id_on_cloud: Optional[str] = None
@@ -9,3 +9,6 @@ from sky.provision.runpod.instance import run_instances
9
9
  from sky.provision.runpod.instance import stop_instances
10
10
  from sky.provision.runpod.instance import terminate_instances
11
11
  from sky.provision.runpod.instance import wait_instances
12
+ from sky.provision.runpod.volume import apply_volume
13
+ from sky.provision.runpod.volume import delete_volume
14
+ from sky.provision.runpod.volume import get_volume_usedby
@@ -80,6 +80,21 @@ def run_instances(region: str, cluster_name_on_cloud: str,
80
80
  created_instance_ids=[])
81
81
 
82
82
  created_instance_ids = []
83
+ volume_mounts = config.node_config.get('VolumeMounts', [])
84
+ network_volume_id = None
85
+ volume_mount_path = None
86
+ if volume_mounts:
87
+ if len(volume_mounts) > 1:
88
+ logger.warning(
89
+ f'RunPod only supports one network volume mount, '
90
+ f'but {len(volume_mounts)} are specified. Only the first one '
91
+ f'will be used.')
92
+ volume_mount = volume_mounts[0]
93
+ network_volume_id = volume_mount.get('VolumeIdOnCloud')
94
+ volume_mount_path = volume_mount.get('MountPath')
95
+ if network_volume_id is None or volume_mount_path is None:
96
+ raise RuntimeError(
97
+ 'Network volume ID and mount path must be specified.')
83
98
  for _ in range(to_start_count):
84
99
  node_type = 'head' if head_instance_id is None else 'worker'
85
100
  try:
@@ -97,6 +112,8 @@ def run_instances(region: str, cluster_name_on_cloud: str,
97
112
  bid_per_gpu=config.node_config['BidPerGPU'],
98
113
  docker_login_config=config.provider_config.get(
99
114
  'docker_login_config'),
115
+ network_volume_id=network_volume_id,
116
+ volume_mount_path=volume_mount_path,
100
117
  )
101
118
  except Exception as e: # pylint: disable=broad-except
102
119
  logger.warning(f'run_instances error: {e}')
@@ -263,11 +263,23 @@ def _create_template_for_docker_login(
263
263
  return login_config.format_image(image_name), create_template_resp['id']
264
264
 
265
265
 
266
- def launch(cluster_name: str, node_type: str, instance_type: str, region: str,
267
- zone: str, disk_size: int, image_name: str,
268
- ports: Optional[List[int]], public_key: str,
269
- preemptible: Optional[bool], bid_per_gpu: float,
270
- docker_login_config: Optional[Dict[str, str]]) -> str:
266
+ def launch(
267
+ cluster_name: str,
268
+ node_type: str,
269
+ instance_type: str,
270
+ region: str,
271
+ zone: str,
272
+ disk_size: int,
273
+ image_name: str,
274
+ ports: Optional[List[int]],
275
+ public_key: str,
276
+ preemptible: Optional[bool],
277
+ bid_per_gpu: float,
278
+ docker_login_config: Optional[Dict[str, str]],
279
+ *,
280
+ network_volume_id: Optional[str] = None,
281
+ volume_mount_path: Optional[str] = None,
282
+ ) -> str:
271
283
  """Launches an instance with the given parameters.
272
284
 
273
285
  For CPU instances, we directly use the instance_type for launching the
@@ -337,6 +349,12 @@ def launch(cluster_name: str, node_type: str, instance_type: str, region: str,
337
349
  'template_id': template_id,
338
350
  }
339
351
 
352
+ # Optional network volume mount.
353
+ if volume_mount_path is not None:
354
+ params['volume_mount_path'] = volume_mount_path
355
+ if network_volume_id is not None:
356
+ params['network_volume_id'] = network_volume_id
357
+
340
358
  # GPU instance types start with f'{gpu_count}x',
341
359
  # CPU instance types start with 'cpu'.
342
360
  is_cpu_instance = instance_type.startswith('cpu')
@@ -0,0 +1,158 @@
1
+ """RunPod network volume provisioning."""
2
+ from typing import Any, Dict, List, Optional, Tuple
3
+
4
+ from sky import global_user_state
5
+ from sky import models
6
+ from sky import sky_logging
7
+ from sky.adaptors import runpod
8
+ from sky.utils import common_utils
9
+ from sky.utils import volume as volume_lib
10
+
11
+ logger = sky_logging.init_logger(__name__)
12
+
13
+
14
+ def _list_volumes() -> List[Dict[str, Any]]:
15
+ # GET /v1/networkvolumes returns a list
16
+ result = runpod.rest_request('GET', '/networkvolumes')
17
+ if isinstance(result, list):
18
+ return result
19
+ # Some deployments may wrap the list.
20
+ if isinstance(result, dict):
21
+ for key in ('items', 'data', 'networkVolumes'):
22
+ if key in result and isinstance(result[key], list):
23
+ return result[key]
24
+ return []
25
+
26
+
27
+ def apply_volume(config: models.VolumeConfig) -> models.VolumeConfig:
28
+ """Create or resolve a RunPod network volume via REST API.
29
+
30
+ If a volume with the same `name_on_cloud` exists, reuse it. Otherwise,
31
+ create a new one using POST /v1/networkvolumes.
32
+ """
33
+ name_on_cloud = config.name_on_cloud
34
+ assert name_on_cloud is not None
35
+
36
+ vol_id = _try_resolve_volume_id(name_on_cloud)
37
+ if vol_id is None:
38
+ # Create new volume via REST
39
+ size = config.size
40
+ if size is None:
41
+ raise RuntimeError(
42
+ 'RunPod network volume size must be specified to create '
43
+ 'a volume.')
44
+ try:
45
+ size_int = int(size)
46
+ if size_int < volume_lib.MIN_RUNPOD_NETWORK_VOLUME_SIZE_GB:
47
+ raise RuntimeError(
48
+ f'RunPod network volume size must be at least '
49
+ f'{volume_lib.MIN_RUNPOD_NETWORK_VOLUME_SIZE_GB}GB.')
50
+ except Exception as e: # pylint: disable=broad-except
51
+ raise RuntimeError(f'Invalid volume size {size!r}: {e}') from e
52
+ data_center_id = config.zone
53
+ if not data_center_id:
54
+ raise RuntimeError(
55
+ 'RunPod DataCenterId is required to create a network '
56
+ 'volume. Set the zone in the infra field.')
57
+ payload = {
58
+ 'dataCenterId': data_center_id,
59
+ 'name': name_on_cloud,
60
+ 'size': size_int,
61
+ }
62
+ resp = runpod.rest_request('POST', '/networkvolumes', json=payload)
63
+ if isinstance(resp, dict):
64
+ config.id_on_cloud = resp.get('id')
65
+ else:
66
+ raise RuntimeError(
67
+ f'Failed to create RunPod network volume: {resp}')
68
+ logger.info(f'Created RunPod network volume {name_on_cloud} '
69
+ f'(id={config.id_on_cloud})')
70
+ return config
71
+
72
+ # Use existing matched volume
73
+ config.id_on_cloud = vol_id
74
+ logger.debug(f'Using existing RunPod network volume {name_on_cloud} '
75
+ f'(id={config.id_on_cloud})')
76
+ return config
77
+
78
+
79
+ def delete_volume(config: models.VolumeConfig) -> models.VolumeConfig:
80
+ """Deletes a RunPod network volume via REST API if id is known or
81
+ resolvable. If the volume id is not known, try to resolve it by name.
82
+ """
83
+ name_on_cloud = config.name_on_cloud
84
+ vol_id = config.id_on_cloud
85
+ if not vol_id:
86
+ vol_id = _try_resolve_volume_id(name_on_cloud)
87
+ if not vol_id:
88
+ logger.warning(
89
+ f'RunPod network volume id not found for {name_on_cloud}; '
90
+ f'skip delete')
91
+ return config
92
+ runpod.rest_request('DELETE', f'/networkvolumes/{vol_id}')
93
+ logger.info(f'Deleted RunPod network volume {name_on_cloud} '
94
+ f'(id={vol_id})')
95
+ return config
96
+
97
+
98
+ def _try_resolve_volume_id(name_on_cloud: str) -> Optional[str]:
99
+ vols = _list_volumes()
100
+ matched = next((v for v in vols if v.get('name') == name_on_cloud), None)
101
+ if matched is not None:
102
+ return matched.get('id')
103
+ return None
104
+
105
+
106
+ def get_volume_usedby(
107
+ config: models.VolumeConfig,) -> Tuple[List[str], List[str]]:
108
+ """Gets the clusters currently using this RunPod network volume.
109
+
110
+ Returns:
111
+ (usedby_pods, usedby_clusters)
112
+ usedby_clusters contains SkyPilot cluster display names inferred from
113
+ pod names, which may be wrong.
114
+ """
115
+ vol_id = config.id_on_cloud
116
+ name_on_cloud = config.name_on_cloud
117
+ if vol_id is None:
118
+ vol_id = _try_resolve_volume_id(name_on_cloud)
119
+ if vol_id is None:
120
+ return [], []
121
+
122
+ # Query all pods for current user and filter by networkVolumeId
123
+ query = """
124
+ query Pods {
125
+ myself {
126
+ pods {
127
+ id
128
+ name
129
+ networkVolumeId
130
+ }
131
+ }
132
+ }
133
+ """
134
+ resp = runpod.runpod.api.graphql.run_graphql_query(query)
135
+ pods = resp.get('data', {}).get('myself', {}).get('pods', [])
136
+ used_pods = [p for p in pods if p.get('networkVolumeId') == vol_id]
137
+ usedby_pod_names = [p.get('name') for p in used_pods if p.get('name')]
138
+
139
+ # Map pod names back to SkyPilot cluster names using heuristics.
140
+ clusters = global_user_state.get_clusters()
141
+ cluster_names: List[str] = []
142
+ user_hash = common_utils.get_user_hash()
143
+ for pod_name in usedby_pod_names:
144
+ matched = None
145
+ for c in clusters:
146
+ display = c.get('name')
147
+ if not display:
148
+ continue
149
+ # Heuristic: RunPod pod name is f"{cluster}-{user_hash}-{xxx}"
150
+ # This can be wrong.
151
+ cluster_prefix = display + '-' + user_hash + '-'
152
+ if pod_name.startswith(cluster_prefix):
153
+ matched = display
154
+ break
155
+ if matched and matched not in cluster_names:
156
+ cluster_names.append(matched)
157
+
158
+ return usedby_pod_names, cluster_names
@@ -12,9 +12,11 @@ import aiohttp
12
12
  import fastapi
13
13
  import starlette.middleware.base
14
14
 
15
+ from sky import global_user_state
15
16
  from sky import models
16
17
  from sky import sky_logging
17
18
  from sky.server.auth import authn
19
+ from sky.users import permission
18
20
  from sky.utils import common_utils
19
21
 
20
22
  logger = sky_logging.init_logger(__name__)
@@ -149,6 +151,10 @@ class OAuth2ProxyMiddleware(starlette.middleware.base.BaseHTTPMiddleware):
149
151
  'return user info, check your oauth2-proxy'
150
152
  'setup.'
151
153
  })
154
+ newly_added = global_user_state.add_or_update_user(auth_user)
155
+ if newly_added:
156
+ permission.permission_service.add_user_if_not_exists(
157
+ auth_user.id)
152
158
  request.state.auth_user = auth_user
153
159
  await authn.override_user_info_in_request_body(
154
160
  request, auth_user)
@@ -309,7 +309,8 @@ class StatusBody(RequestBody):
309
309
  cluster_names: Optional[List[str]] = None
310
310
  refresh: common_lib.StatusRefreshMode = common_lib.StatusRefreshMode.NONE
311
311
  all_users: bool = True
312
- include_credentials: bool = False
312
+ # TODO (kyuds): default to False post 0.10.5
313
+ include_credentials: bool = True
313
314
 
314
315
 
315
316
  class StartBody(RequestBody):
@@ -464,6 +465,11 @@ class VolumeDeleteBody(RequestBody):
464
465
  names: List[str]
465
466
 
466
467
 
468
+ class VolumeListBody(RequestBody):
469
+ """The request body for the volume list endpoint."""
470
+ pass
471
+
472
+
467
473
  class EndpointsBody(RequestBody):
468
474
  """The request body for the endpoint."""
469
475
  cluster: str
@@ -162,13 +162,14 @@ class ClusterStartCompletePrecondition(Precondition):
162
162
  # We unify these situations into a single state: the process of starting
163
163
  # the cluster is done (either normally or abnormally) but cluster is not
164
164
  # in UP status.
165
- requests = api_requests.get_request_tasks(
166
- status=[
167
- api_requests.RequestStatus.RUNNING,
168
- api_requests.RequestStatus.PENDING
169
- ],
170
- include_request_names=['sky.launch', 'sky.start'],
171
- cluster_names=[self.cluster_name])
165
+ requests = await api_requests.get_request_tasks_async(
166
+ req_filter=api_requests.RequestTaskFilter(
167
+ status=[
168
+ api_requests.RequestStatus.RUNNING,
169
+ api_requests.RequestStatus.PENDING
170
+ ],
171
+ include_request_names=['sky.launch', 'sky.start'],
172
+ cluster_names=[self.cluster_name]))
172
173
  if len(requests) == 0:
173
174
  # No running or pending tasks, the start process is done.
174
175
  return True, None