skypilot-nightly 1.0.0.dev20250628__py3-none-any.whl → 1.0.0.dev20250630__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (123) hide show
  1. sky/__init__.py +2 -2
  2. sky/adaptors/kubernetes.py +7 -0
  3. sky/client/cli/command.py +1 -2
  4. sky/dashboard/out/404.html +1 -1
  5. sky/dashboard/out/_next/static/NdypbqMxaYucRGfopkKXa/_buildManifest.js +1 -0
  6. sky/dashboard/out/_next/static/chunks/1043-1b39779691bb4030.js +1 -0
  7. sky/dashboard/out/_next/static/chunks/{141-fa5a20cbf401b351.js → 1141-726e5a3f00b67185.js} +2 -2
  8. sky/dashboard/out/_next/static/chunks/1272-1ef0bf0237faccdb.js +1 -0
  9. sky/dashboard/out/_next/static/chunks/1664-d65361e92b85e786.js +1 -0
  10. sky/dashboard/out/_next/static/chunks/{691.fd9292250ab089af.js → 1691.44e378727a41f3b5.js} +2 -2
  11. sky/dashboard/out/_next/static/chunks/{871-e547295e7e21399c.js → 1871-80dea41717729fa5.js} +1 -1
  12. sky/dashboard/out/_next/static/chunks/2544.27f70672535675ed.js +1 -0
  13. sky/dashboard/out/_next/static/chunks/{875.52c962183328b3f2.js → 2875.c24c6d57dc82e436.js} +1 -1
  14. sky/dashboard/out/_next/static/chunks/3256.7257acd01b481bed.js +11 -0
  15. sky/dashboard/out/_next/static/chunks/3698-52ad1ca228faa776.js +1 -0
  16. sky/dashboard/out/_next/static/chunks/3785.b3cc2bc1d49d2c3c.js +1 -0
  17. sky/dashboard/out/_next/static/chunks/3937.d7f1c55d1916c7f2.js +1 -0
  18. sky/dashboard/out/_next/static/chunks/{947-6620842ef80ae879.js → 3947-b059261d6fa88a1f.js} +1 -1
  19. sky/dashboard/out/_next/static/chunks/{697.6460bf72e760addd.js → 4697.f5421144224da9fc.js} +1 -1
  20. sky/dashboard/out/_next/static/chunks/4725.4c849b1e05c8e9ad.js +1 -0
  21. sky/dashboard/out/_next/static/chunks/5230-df791914b54d91d9.js +1 -0
  22. sky/dashboard/out/_next/static/chunks/{491.b3d264269613fe09.js → 5491.918ffed0ba7a5294.js} +1 -1
  23. sky/dashboard/out/_next/static/chunks/5739-5ea3ffa10fc884f2.js +8 -0
  24. sky/dashboard/out/_next/static/chunks/616-162f3033ffcd3d31.js +39 -0
  25. sky/dashboard/out/_next/static/chunks/6601-fcfad0ddf92ec7ab.js +1 -0
  26. sky/dashboard/out/_next/static/chunks/6989-6ff4e45dfb49d11d.js +1 -0
  27. sky/dashboard/out/_next/static/chunks/6990-d0dc765474fa0eca.js +1 -0
  28. sky/dashboard/out/_next/static/chunks/8969-909d53833da080cb.js +1 -0
  29. sky/dashboard/out/_next/static/chunks/8982.a2e214068f30a857.js +1 -0
  30. sky/dashboard/out/_next/static/chunks/{25.76c246239df93d50.js → 9025.a7c44babfe56ce09.js} +2 -2
  31. sky/dashboard/out/_next/static/chunks/{938-0a770415b5ce4649.js → 938-044ad21de8b4626b.js} +1 -1
  32. sky/dashboard/out/_next/static/chunks/9470-21d059a1dfa03f61.js +1 -0
  33. sky/dashboard/out/_next/static/chunks/9984.739ae958a066298d.js +1 -0
  34. sky/dashboard/out/_next/static/chunks/fd9d1056-61f2257a9cd8b32b.js +1 -0
  35. sky/dashboard/out/_next/static/chunks/{framework-87d061ee6ed71b28.js → framework-efc06c2733009cd3.js} +1 -1
  36. sky/dashboard/out/_next/static/chunks/main-app-68c028b1bc5e1b72.js +1 -0
  37. sky/dashboard/out/_next/static/chunks/{main-e0e2335212e72357.js → main-c0a4f1ea606d48d2.js} +1 -1
  38. sky/dashboard/out/_next/static/chunks/pages/{_app-050a9e637b057b24.js → _app-a37b06ddb64521fd.js} +2 -2
  39. sky/dashboard/out/_next/static/chunks/pages/_error-c72a1f77a3c0be1b.js +1 -0
  40. sky/dashboard/out/_next/static/chunks/pages/clusters/[cluster]/[job]-8135aba0712bda37.js +6 -0
  41. sky/dashboard/out/_next/static/chunks/pages/clusters/{[cluster]-77d4816945b04793.js → [cluster]-b8e1114e6d38218c.js} +1 -1
  42. sky/dashboard/out/_next/static/chunks/pages/clusters-9744c271a1642f76.js +1 -0
  43. sky/dashboard/out/_next/static/chunks/pages/config-a2673b256b6d416f.js +1 -0
  44. sky/dashboard/out/_next/static/chunks/pages/index-927ddeebe57a8ac3.js +1 -0
  45. sky/dashboard/out/_next/static/chunks/pages/infra/[context]-8b0809f59034d509.js +1 -0
  46. sky/dashboard/out/_next/static/chunks/pages/infra-ae9d2f705ce582c9.js +1 -0
  47. sky/dashboard/out/_next/static/chunks/pages/jobs/[job]-c4d5cfac7fbc0668.js +16 -0
  48. sky/dashboard/out/_next/static/chunks/pages/jobs-5bbdc71878f0a068.js +1 -0
  49. sky/dashboard/out/_next/static/chunks/pages/users-cd43fb3c122eedde.js +1 -0
  50. sky/dashboard/out/_next/static/chunks/pages/volumes-4ebf6484f7216387.js +1 -0
  51. sky/dashboard/out/_next/static/chunks/pages/workspace/new-5629d4e551dba1ee.js +1 -0
  52. sky/dashboard/out/_next/static/chunks/pages/workspaces/[name]-7c0187f43757a548.js +1 -0
  53. sky/dashboard/out/_next/static/chunks/pages/workspaces-06bde99155fa6292.js +1 -0
  54. sky/dashboard/out/_next/static/chunks/webpack-d427db53e54de9ce.js +1 -0
  55. sky/dashboard/out/_next/static/css/0da6afe66176678a.css +3 -0
  56. sky/dashboard/out/clusters/[cluster]/[job].html +1 -1
  57. sky/dashboard/out/clusters/[cluster].html +1 -1
  58. sky/dashboard/out/clusters.html +1 -1
  59. sky/dashboard/out/config.html +1 -1
  60. sky/dashboard/out/index.html +1 -1
  61. sky/dashboard/out/infra/[context].html +1 -1
  62. sky/dashboard/out/infra.html +1 -1
  63. sky/dashboard/out/jobs/[job].html +1 -1
  64. sky/dashboard/out/jobs.html +1 -1
  65. sky/dashboard/out/users.html +1 -1
  66. sky/dashboard/out/volumes.html +1 -1
  67. sky/dashboard/out/workspace/new.html +1 -1
  68. sky/dashboard/out/workspaces/[name].html +1 -1
  69. sky/dashboard/out/workspaces.html +1 -1
  70. sky/optimizer.py +46 -0
  71. sky/provision/__init__.py +14 -6
  72. sky/provision/kubernetes/constants.py +9 -0
  73. sky/provision/kubernetes/instance.py +17 -14
  74. sky/provision/kubernetes/volume.py +77 -15
  75. sky/skylet/constants.py +1 -0
  76. sky/task.py +12 -0
  77. sky/utils/log_utils.py +68 -0
  78. sky/volumes/server/core.py +103 -78
  79. sky/volumes/utils.py +22 -5
  80. {skypilot_nightly-1.0.0.dev20250628.dist-info → skypilot_nightly-1.0.0.dev20250630.dist-info}/METADATA +1 -1
  81. {skypilot_nightly-1.0.0.dev20250628.dist-info → skypilot_nightly-1.0.0.dev20250630.dist-info}/RECORD +87 -85
  82. sky/dashboard/out/_next/static/ZYLkkWSYZjJhLVsObh20y/_buildManifest.js +0 -1
  83. sky/dashboard/out/_next/static/chunks/230-d6e363362017ff3a.js +0 -1
  84. sky/dashboard/out/_next/static/chunks/43-f38a531f6692f281.js +0 -1
  85. sky/dashboard/out/_next/static/chunks/470-92dd1614396389be.js +0 -1
  86. sky/dashboard/out/_next/static/chunks/544.110e53813fb98e2e.js +0 -1
  87. sky/dashboard/out/_next/static/chunks/601-111d06d9ded11d00.js +0 -1
  88. sky/dashboard/out/_next/static/chunks/616-50a620ac4a23deb4.js +0 -39
  89. sky/dashboard/out/_next/static/chunks/645.961f08e39b8ce447.js +0 -1
  90. sky/dashboard/out/_next/static/chunks/664-047bc03493fda379.js +0 -1
  91. sky/dashboard/out/_next/static/chunks/785.3446c12ffdf3d188.js +0 -1
  92. sky/dashboard/out/_next/static/chunks/798-c0525dc3f21e488d.js +0 -1
  93. sky/dashboard/out/_next/static/chunks/799-3625946b2ec2eb30.js +0 -8
  94. sky/dashboard/out/_next/static/chunks/937.72796f7afe54075b.js +0 -1
  95. sky/dashboard/out/_next/static/chunks/969-d3a0b53f728d280a.js +0 -1
  96. sky/dashboard/out/_next/static/chunks/982.d7bd80ed18cad4cc.js +0 -1
  97. sky/dashboard/out/_next/static/chunks/984.e8bac186a24e5178.js +0 -1
  98. sky/dashboard/out/_next/static/chunks/989-db34c16ad7ea6155.js +0 -1
  99. sky/dashboard/out/_next/static/chunks/990-0ad5ea1699e03ee8.js +0 -1
  100. sky/dashboard/out/_next/static/chunks/fd9d1056-2821b0f0cabcd8bd.js +0 -1
  101. sky/dashboard/out/_next/static/chunks/main-app-241eb28595532291.js +0 -1
  102. sky/dashboard/out/_next/static/chunks/pages/_error-1be831200e60c5c0.js +0 -1
  103. sky/dashboard/out/_next/static/chunks/pages/clusters/[cluster]/[job]-21080826c6095f21.js +0 -6
  104. sky/dashboard/out/_next/static/chunks/pages/clusters-65b2c90320b8afb8.js +0 -1
  105. sky/dashboard/out/_next/static/chunks/pages/config-6b255eae088da6a3.js +0 -1
  106. sky/dashboard/out/_next/static/chunks/pages/index-6b0d9e5031b70c58.js +0 -1
  107. sky/dashboard/out/_next/static/chunks/pages/infra/[context]-b302aea4d65766bf.js +0 -1
  108. sky/dashboard/out/_next/static/chunks/pages/infra-ee8cc4d449945d19.js +0 -1
  109. sky/dashboard/out/_next/static/chunks/pages/jobs/[job]-64bdc0b2d3a44709.js +0 -16
  110. sky/dashboard/out/_next/static/chunks/pages/jobs-df7407b5e37d3750.js +0 -1
  111. sky/dashboard/out/_next/static/chunks/pages/users-d7684eaa04c4f58f.js +0 -1
  112. sky/dashboard/out/_next/static/chunks/pages/volumes-476b670ef33d1ecd.js +0 -1
  113. sky/dashboard/out/_next/static/chunks/pages/workspace/new-5b59bce9eb208d84.js +0 -1
  114. sky/dashboard/out/_next/static/chunks/pages/workspaces/[name]-04e1b3ad4207b1e9.js +0 -1
  115. sky/dashboard/out/_next/static/chunks/pages/workspaces-c470366a6179f16e.js +0 -1
  116. sky/dashboard/out/_next/static/chunks/webpack-75a3310ef922a299.js +0 -1
  117. sky/dashboard/out/_next/static/css/605ac87514049058.css +0 -3
  118. /sky/dashboard/out/_next/static/{ZYLkkWSYZjJhLVsObh20y → NdypbqMxaYucRGfopkKXa}/_ssgManifest.js +0 -0
  119. /sky/dashboard/out/_next/static/chunks/{804-4c9fc53aa74bc191.js → 804-9f5e98ce84d46bdd.js} +0 -0
  120. {skypilot_nightly-1.0.0.dev20250628.dist-info → skypilot_nightly-1.0.0.dev20250630.dist-info}/WHEEL +0 -0
  121. {skypilot_nightly-1.0.0.dev20250628.dist-info → skypilot_nightly-1.0.0.dev20250630.dist-info}/entry_points.txt +0 -0
  122. {skypilot_nightly-1.0.0.dev20250628.dist-info → skypilot_nightly-1.0.0.dev20250630.dist-info}/licenses/LICENSE +0 -0
  123. {skypilot_nightly-1.0.0.dev20250628.dist-info → skypilot_nightly-1.0.0.dev20250630.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/605ac87514049058.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/605ac87514049058.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-75a3310ef922a299.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-87d061ee6ed71b28.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-e0e2335212e72357.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-050a9e637b057b24.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/infra/%5Bcontext%5D-b302aea4d65766bf.js" defer=""></script><script src="/dashboard/_next/static/ZYLkkWSYZjJhLVsObh20y/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/ZYLkkWSYZjJhLVsObh20y/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/infra/[context]","query":{},"buildId":"ZYLkkWSYZjJhLVsObh20y","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/0da6afe66176678a.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/0da6afe66176678a.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-d427db53e54de9ce.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-efc06c2733009cd3.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-c0a4f1ea606d48d2.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-a37b06ddb64521fd.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/infra/%5Bcontext%5D-8b0809f59034d509.js" defer=""></script><script src="/dashboard/_next/static/NdypbqMxaYucRGfopkKXa/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/NdypbqMxaYucRGfopkKXa/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/infra/[context]","query":{},"buildId":"NdypbqMxaYucRGfopkKXa","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/605ac87514049058.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/605ac87514049058.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-75a3310ef922a299.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-87d061ee6ed71b28.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-e0e2335212e72357.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-050a9e637b057b24.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/infra-ee8cc4d449945d19.js" defer=""></script><script src="/dashboard/_next/static/ZYLkkWSYZjJhLVsObh20y/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/ZYLkkWSYZjJhLVsObh20y/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/infra","query":{},"buildId":"ZYLkkWSYZjJhLVsObh20y","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/0da6afe66176678a.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/0da6afe66176678a.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-d427db53e54de9ce.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-efc06c2733009cd3.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-c0a4f1ea606d48d2.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-a37b06ddb64521fd.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/infra-ae9d2f705ce582c9.js" defer=""></script><script src="/dashboard/_next/static/NdypbqMxaYucRGfopkKXa/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/NdypbqMxaYucRGfopkKXa/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/infra","query":{},"buildId":"NdypbqMxaYucRGfopkKXa","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/605ac87514049058.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/605ac87514049058.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-75a3310ef922a299.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-87d061ee6ed71b28.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-e0e2335212e72357.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-050a9e637b057b24.js" defer=""></script><script src="/dashboard/_next/static/chunks/616-50a620ac4a23deb4.js" defer=""></script><script src="/dashboard/_next/static/chunks/230-d6e363362017ff3a.js" defer=""></script><script src="/dashboard/_next/static/chunks/799-3625946b2ec2eb30.js" defer=""></script><script src="/dashboard/_next/static/chunks/664-047bc03493fda379.js" defer=""></script><script src="/dashboard/_next/static/chunks/804-4c9fc53aa74bc191.js" defer=""></script><script src="/dashboard/_next/static/chunks/798-c0525dc3f21e488d.js" defer=""></script><script src="/dashboard/_next/static/chunks/989-db34c16ad7ea6155.js" defer=""></script><script src="/dashboard/_next/static/chunks/470-92dd1614396389be.js" defer=""></script><script src="/dashboard/_next/static/chunks/969-d3a0b53f728d280a.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/jobs/%5Bjob%5D-64bdc0b2d3a44709.js" defer=""></script><script src="/dashboard/_next/static/ZYLkkWSYZjJhLVsObh20y/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/ZYLkkWSYZjJhLVsObh20y/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/jobs/[job]","query":{},"buildId":"ZYLkkWSYZjJhLVsObh20y","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/0da6afe66176678a.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/0da6afe66176678a.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-d427db53e54de9ce.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-efc06c2733009cd3.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-c0a4f1ea606d48d2.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-a37b06ddb64521fd.js" defer=""></script><script src="/dashboard/_next/static/chunks/616-162f3033ffcd3d31.js" defer=""></script><script src="/dashboard/_next/static/chunks/5230-df791914b54d91d9.js" defer=""></script><script src="/dashboard/_next/static/chunks/5739-5ea3ffa10fc884f2.js" defer=""></script><script src="/dashboard/_next/static/chunks/1664-d65361e92b85e786.js" defer=""></script><script src="/dashboard/_next/static/chunks/804-9f5e98ce84d46bdd.js" defer=""></script><script src="/dashboard/_next/static/chunks/1272-1ef0bf0237faccdb.js" defer=""></script><script src="/dashboard/_next/static/chunks/6989-6ff4e45dfb49d11d.js" defer=""></script><script src="/dashboard/_next/static/chunks/3698-52ad1ca228faa776.js" defer=""></script><script src="/dashboard/_next/static/chunks/9470-21d059a1dfa03f61.js" defer=""></script><script src="/dashboard/_next/static/chunks/8969-909d53833da080cb.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/jobs/%5Bjob%5D-c4d5cfac7fbc0668.js" defer=""></script><script src="/dashboard/_next/static/NdypbqMxaYucRGfopkKXa/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/NdypbqMxaYucRGfopkKXa/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/jobs/[job]","query":{},"buildId":"NdypbqMxaYucRGfopkKXa","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/605ac87514049058.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/605ac87514049058.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-75a3310ef922a299.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-87d061ee6ed71b28.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-e0e2335212e72357.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-050a9e637b057b24.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/jobs-df7407b5e37d3750.js" defer=""></script><script src="/dashboard/_next/static/ZYLkkWSYZjJhLVsObh20y/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/ZYLkkWSYZjJhLVsObh20y/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/jobs","query":{},"buildId":"ZYLkkWSYZjJhLVsObh20y","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/0da6afe66176678a.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/0da6afe66176678a.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-d427db53e54de9ce.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-efc06c2733009cd3.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-c0a4f1ea606d48d2.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-a37b06ddb64521fd.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/jobs-5bbdc71878f0a068.js" defer=""></script><script src="/dashboard/_next/static/NdypbqMxaYucRGfopkKXa/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/NdypbqMxaYucRGfopkKXa/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/jobs","query":{},"buildId":"NdypbqMxaYucRGfopkKXa","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/605ac87514049058.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/605ac87514049058.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-75a3310ef922a299.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-87d061ee6ed71b28.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-e0e2335212e72357.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-050a9e637b057b24.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/users-d7684eaa04c4f58f.js" defer=""></script><script src="/dashboard/_next/static/ZYLkkWSYZjJhLVsObh20y/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/ZYLkkWSYZjJhLVsObh20y/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/users","query":{},"buildId":"ZYLkkWSYZjJhLVsObh20y","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/0da6afe66176678a.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/0da6afe66176678a.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-d427db53e54de9ce.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-efc06c2733009cd3.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-c0a4f1ea606d48d2.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-a37b06ddb64521fd.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/users-cd43fb3c122eedde.js" defer=""></script><script src="/dashboard/_next/static/NdypbqMxaYucRGfopkKXa/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/NdypbqMxaYucRGfopkKXa/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/users","query":{},"buildId":"NdypbqMxaYucRGfopkKXa","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/605ac87514049058.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/605ac87514049058.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-75a3310ef922a299.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-87d061ee6ed71b28.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-e0e2335212e72357.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-050a9e637b057b24.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/volumes-476b670ef33d1ecd.js" defer=""></script><script src="/dashboard/_next/static/ZYLkkWSYZjJhLVsObh20y/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/ZYLkkWSYZjJhLVsObh20y/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/volumes","query":{},"buildId":"ZYLkkWSYZjJhLVsObh20y","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/0da6afe66176678a.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/0da6afe66176678a.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-d427db53e54de9ce.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-efc06c2733009cd3.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-c0a4f1ea606d48d2.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-a37b06ddb64521fd.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/volumes-4ebf6484f7216387.js" defer=""></script><script src="/dashboard/_next/static/NdypbqMxaYucRGfopkKXa/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/NdypbqMxaYucRGfopkKXa/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/volumes","query":{},"buildId":"NdypbqMxaYucRGfopkKXa","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/605ac87514049058.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/605ac87514049058.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-75a3310ef922a299.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-87d061ee6ed71b28.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-e0e2335212e72357.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-050a9e637b057b24.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/workspace/new-5b59bce9eb208d84.js" defer=""></script><script src="/dashboard/_next/static/ZYLkkWSYZjJhLVsObh20y/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/ZYLkkWSYZjJhLVsObh20y/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/workspace/new","query":{},"buildId":"ZYLkkWSYZjJhLVsObh20y","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/0da6afe66176678a.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/0da6afe66176678a.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-d427db53e54de9ce.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-efc06c2733009cd3.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-c0a4f1ea606d48d2.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-a37b06ddb64521fd.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/workspace/new-5629d4e551dba1ee.js" defer=""></script><script src="/dashboard/_next/static/NdypbqMxaYucRGfopkKXa/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/NdypbqMxaYucRGfopkKXa/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/workspace/new","query":{},"buildId":"NdypbqMxaYucRGfopkKXa","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/605ac87514049058.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/605ac87514049058.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-75a3310ef922a299.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-87d061ee6ed71b28.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-e0e2335212e72357.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-050a9e637b057b24.js" defer=""></script><script src="/dashboard/_next/static/chunks/616-50a620ac4a23deb4.js" defer=""></script><script src="/dashboard/_next/static/chunks/230-d6e363362017ff3a.js" defer=""></script><script src="/dashboard/_next/static/chunks/799-3625946b2ec2eb30.js" defer=""></script><script src="/dashboard/_next/static/chunks/664-047bc03493fda379.js" defer=""></script><script src="/dashboard/_next/static/chunks/804-4c9fc53aa74bc191.js" defer=""></script><script src="/dashboard/_next/static/chunks/798-c0525dc3f21e488d.js" defer=""></script><script src="/dashboard/_next/static/chunks/947-6620842ef80ae879.js" defer=""></script><script src="/dashboard/_next/static/chunks/989-db34c16ad7ea6155.js" defer=""></script><script src="/dashboard/_next/static/chunks/470-92dd1614396389be.js" defer=""></script><script src="/dashboard/_next/static/chunks/990-0ad5ea1699e03ee8.js" defer=""></script><script src="/dashboard/_next/static/chunks/969-d3a0b53f728d280a.js" defer=""></script><script src="/dashboard/_next/static/chunks/43-f38a531f6692f281.js" defer=""></script><script src="/dashboard/_next/static/chunks/601-111d06d9ded11d00.js" defer=""></script><script src="/dashboard/_next/static/chunks/938-0a770415b5ce4649.js" defer=""></script><script src="/dashboard/_next/static/chunks/141-fa5a20cbf401b351.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/workspaces/%5Bname%5D-04e1b3ad4207b1e9.js" defer=""></script><script src="/dashboard/_next/static/ZYLkkWSYZjJhLVsObh20y/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/ZYLkkWSYZjJhLVsObh20y/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/workspaces/[name]","query":{},"buildId":"ZYLkkWSYZjJhLVsObh20y","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/0da6afe66176678a.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/0da6afe66176678a.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-d427db53e54de9ce.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-efc06c2733009cd3.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-c0a4f1ea606d48d2.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-a37b06ddb64521fd.js" defer=""></script><script src="/dashboard/_next/static/chunks/616-162f3033ffcd3d31.js" defer=""></script><script src="/dashboard/_next/static/chunks/5230-df791914b54d91d9.js" defer=""></script><script src="/dashboard/_next/static/chunks/5739-5ea3ffa10fc884f2.js" defer=""></script><script src="/dashboard/_next/static/chunks/1664-d65361e92b85e786.js" defer=""></script><script src="/dashboard/_next/static/chunks/804-9f5e98ce84d46bdd.js" defer=""></script><script src="/dashboard/_next/static/chunks/1272-1ef0bf0237faccdb.js" defer=""></script><script src="/dashboard/_next/static/chunks/3947-b059261d6fa88a1f.js" defer=""></script><script src="/dashboard/_next/static/chunks/6989-6ff4e45dfb49d11d.js" defer=""></script><script src="/dashboard/_next/static/chunks/3698-52ad1ca228faa776.js" defer=""></script><script src="/dashboard/_next/static/chunks/9470-21d059a1dfa03f61.js" defer=""></script><script src="/dashboard/_next/static/chunks/6990-d0dc765474fa0eca.js" defer=""></script><script src="/dashboard/_next/static/chunks/8969-909d53833da080cb.js" defer=""></script><script src="/dashboard/_next/static/chunks/1043-1b39779691bb4030.js" defer=""></script><script src="/dashboard/_next/static/chunks/6601-fcfad0ddf92ec7ab.js" defer=""></script><script src="/dashboard/_next/static/chunks/938-044ad21de8b4626b.js" defer=""></script><script src="/dashboard/_next/static/chunks/1141-726e5a3f00b67185.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/workspaces/%5Bname%5D-7c0187f43757a548.js" defer=""></script><script src="/dashboard/_next/static/NdypbqMxaYucRGfopkKXa/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/NdypbqMxaYucRGfopkKXa/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/workspaces/[name]","query":{},"buildId":"NdypbqMxaYucRGfopkKXa","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/605ac87514049058.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/605ac87514049058.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-75a3310ef922a299.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-87d061ee6ed71b28.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-e0e2335212e72357.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-050a9e637b057b24.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/workspaces-c470366a6179f16e.js" defer=""></script><script src="/dashboard/_next/static/ZYLkkWSYZjJhLVsObh20y/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/ZYLkkWSYZjJhLVsObh20y/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/workspaces","query":{},"buildId":"ZYLkkWSYZjJhLVsObh20y","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/0da6afe66176678a.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/0da6afe66176678a.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-d427db53e54de9ce.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-efc06c2733009cd3.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-c0a4f1ea606d48d2.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-a37b06ddb64521fd.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/workspaces-06bde99155fa6292.js" defer=""></script><script src="/dashboard/_next/static/NdypbqMxaYucRGfopkKXa/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/NdypbqMxaYucRGfopkKXa/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/workspaces","query":{},"buildId":"NdypbqMxaYucRGfopkKXa","assetPrefix":"/dashboard","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
sky/optimizer.py CHANGED
@@ -1252,6 +1252,52 @@ def _check_specified_clouds(dag: 'dag_lib.Dag') -> None:
1252
1252
  logger.warning(
1253
1253
  f'{colorama.Fore.YELLOW}{msg}{colorama.Style.RESET_ALL}')
1254
1254
 
1255
+ _check_specified_regions(task)
1256
+
1257
+
1258
+ def _check_specified_regions(task: task_lib.Task) -> None:
1259
+ """Check if specified regions (Kubernetes contexts) are enabled.
1260
+
1261
+ Args:
1262
+ task: The task to check.
1263
+ """
1264
+ # Only check for Kubernetes now
1265
+ if not all(
1266
+ isinstance(resources.cloud, clouds.Kubernetes)
1267
+ for resources in task.resources):
1268
+ return
1269
+ # Kubernetes region is a context if set
1270
+ for resources in task.resources:
1271
+ if resources.region is None:
1272
+ continue
1273
+ existing_contexts = clouds.Kubernetes.existing_allowed_contexts()
1274
+ region = resources.region
1275
+ task_name = f' {task.name!r}' if task.name is not None else ''
1276
+ msg = f'Task{task_name} requires '
1277
+ if region not in existing_contexts:
1278
+ infra_str = f'Kubernetes/{region}'
1279
+ logger.warning(f'{infra_str} is not enabled.')
1280
+ volume_mounts_str = ''
1281
+ if task.volume_mounts:
1282
+ if len(task.volume_mounts) > 1:
1283
+ volume_mounts_str += 'volumes '
1284
+ else:
1285
+ volume_mounts_str += 'volume '
1286
+ volume_mounts_str += ', '.join(
1287
+ [f'{v.volume_name}' for v in task.volume_mounts])
1288
+ volume_mounts_str += f' with infra {infra_str}'
1289
+ if volume_mounts_str:
1290
+ msg += volume_mounts_str
1291
+ else:
1292
+ msg += f'infra {infra_str}'
1293
+ msg += (
1294
+ f' which is not enabled. To enable access, change '
1295
+ f'the task infra requirement or run: {colorama.Style.BRIGHT}'
1296
+ f'sky check {colorama.Style.RESET_ALL}'
1297
+ f'to ensure the infra is enabled.')
1298
+ with ux_utils.print_exception_no_traceback():
1299
+ raise exceptions.ResourcesUnavailableError(msg)
1300
+
1255
1301
 
1256
1302
  def _fill_in_launchable_resources(
1257
1303
  task: task_lib.Task,
sky/provision/__init__.py CHANGED
@@ -6,7 +6,7 @@ providers supported by SkyPilot need to follow.
6
6
  import functools
7
7
  import inspect
8
8
  import typing
9
- from typing import Any, Dict, List, Optional, Type
9
+ from typing import Any, Dict, List, Optional, Tuple, Type
10
10
 
11
11
  from sky import models
12
12
  from sky import sky_logging
@@ -106,7 +106,7 @@ def bootstrap_instances(
106
106
 
107
107
  @_route_to_cloud_impl
108
108
  def apply_volume(provider_name: str,
109
- config: models.VolumeConfig) -> models.VolumeConfig:
109
+ volume_config: models.VolumeConfig) -> models.VolumeConfig:
110
110
  """Create or register a volume.
111
111
 
112
112
  This function creates or registers a volume with the provided configuration,
@@ -117,15 +117,23 @@ def apply_volume(provider_name: str,
117
117
 
118
118
  @_route_to_cloud_impl
119
119
  def delete_volume(provider_name: str,
120
- config: models.VolumeConfig) -> models.VolumeConfig:
120
+ volume_config: models.VolumeConfig) -> models.VolumeConfig:
121
121
  """Delete a volume."""
122
122
  raise NotImplementedError
123
123
 
124
124
 
125
125
  @_route_to_cloud_impl
126
- def get_volume_usedby(provider_name: str,
127
- config: models.VolumeConfig) -> List[str]:
128
- """Get the usedby of a volume."""
126
+ def get_volume_usedby(
127
+ provider_name: str,
128
+ volume_config: models.VolumeConfig,
129
+ ) -> Tuple[List[str], List[str]]:
130
+ """Get the usedby of a volume.
131
+
132
+ Returns:
133
+ usedby_pods: List of pods using the volume. These may include pods
134
+ not created by SkyPilot.
135
+ usedby_clusters: List of clusters using the volume.
136
+ """
129
137
  raise NotImplementedError
130
138
 
131
139
 
@@ -15,3 +15,12 @@ SKY_K8S_EXEC_AUTH_PATH = '$HOME/skypilot-runtime/bin:$HOME/google-cloud-sdk/bin:
15
15
 
16
16
  # cache directory for kubeconfig with modified exec auth
17
17
  SKY_K8S_EXEC_AUTH_KUBECONFIG_CACHE = '~/.sky/generated/kubeconfigs'
18
+
19
+ # Labels for the Pods created by SkyPilot
20
+ TAG_RAY_CLUSTER_NAME = 'ray-cluster-name'
21
+ TAG_SKYPILOT_CLUSTER_NAME = 'skypilot-cluster-name'
22
+ TAG_POD_INITIALIZED = 'skypilot-initialized'
23
+ TAG_SKYPILOT_DEPLOYMENT_NAME = 'skypilot-deployment-name'
24
+
25
+ # Pod phases that are not holding PVCs
26
+ PVC_NOT_HOLD_POD_PHASES = ['Succeeded', 'Failed']
@@ -12,6 +12,7 @@ from sky.provision import common
12
12
  from sky.provision import constants
13
13
  from sky.provision import docker_utils
14
14
  from sky.provision.kubernetes import config as config_lib
15
+ from sky.provision.kubernetes import constants as k8s_constants
15
16
  from sky.provision.kubernetes import network_utils
16
17
  from sky.provision.kubernetes import utils as kubernetes_utils
17
18
  from sky.provision.kubernetes import volume
@@ -30,14 +31,10 @@ _MAX_RETRIES = 3
30
31
  _NUM_THREADS = subprocess_utils.get_parallel_threads('kubernetes')
31
32
 
32
33
  logger = sky_logging.init_logger(__name__)
33
- TAG_RAY_CLUSTER_NAME = 'ray-cluster-name'
34
- TAG_SKYPILOT_CLUSTER_NAME = 'skypilot-cluster-name'
35
- TAG_POD_INITIALIZED = 'skypilot-initialized'
36
- TAG_SKYPILOT_DEPLOYMENT_NAME = 'skypilot-deployment-name'
37
34
 
38
35
 
39
36
  def ray_tag_filter(cluster_name: str) -> Dict[str, str]:
40
- return {TAG_RAY_CLUSTER_NAME: cluster_name}
37
+ return {k8s_constants.TAG_RAY_CLUSTER_NAME: cluster_name}
41
38
 
42
39
 
43
40
  def _is_head(pod) -> bool:
@@ -75,7 +72,8 @@ def is_high_availability_cluster_by_kubectl(
75
72
  deployment_list = kubernetes.apps_api(
76
73
  context).list_namespaced_deployment(
77
74
  namespace,
78
- label_selector=f'{TAG_SKYPILOT_CLUSTER_NAME}={cluster_name}')
75
+ label_selector=
76
+ f'{k8s_constants.TAG_SKYPILOT_CLUSTER_NAME}={cluster_name}')
79
77
  except kubernetes.api_exception():
80
78
  return False
81
79
  # It is a high availability cluster if there is at least one deployment
@@ -280,10 +278,12 @@ def _wait_for_pods_to_schedule(namespace, context, new_nodes, timeout: int):
280
278
  while _evaluate_timeout():
281
279
  # Get all pods in a single API call using the cluster name label
282
280
  # which all pods in new_nodes should share
283
- cluster_name = new_nodes[0].metadata.labels[TAG_SKYPILOT_CLUSTER_NAME]
281
+ cluster_name = new_nodes[0].metadata.labels[
282
+ k8s_constants.TAG_SKYPILOT_CLUSTER_NAME]
284
283
  pods = kubernetes.core_api(context).list_namespaced_pod(
285
284
  namespace,
286
- label_selector=f'{TAG_SKYPILOT_CLUSTER_NAME}={cluster_name}').items
285
+ label_selector=
286
+ f'{k8s_constants.TAG_SKYPILOT_CLUSTER_NAME}={cluster_name}').items
287
287
 
288
288
  # Get the set of found pod names and check if we have all expected pods
289
289
  found_pod_names = {pod.metadata.name for pod in pods}
@@ -361,10 +361,12 @@ def _wait_for_pods_to_run(namespace, context, new_nodes):
361
361
 
362
362
  while True:
363
363
  # Get all pods in a single API call
364
- cluster_name = new_nodes[0].metadata.labels[TAG_SKYPILOT_CLUSTER_NAME]
364
+ cluster_name = new_nodes[0].metadata.labels[
365
+ k8s_constants.TAG_SKYPILOT_CLUSTER_NAME]
365
366
  all_pods = kubernetes.core_api(context).list_namespaced_pod(
366
367
  namespace,
367
- label_selector=f'{TAG_SKYPILOT_CLUSTER_NAME}={cluster_name}').items
368
+ label_selector=
369
+ f'{k8s_constants.TAG_SKYPILOT_CLUSTER_NAME}={cluster_name}').items
368
370
 
369
371
  # Get the set of found pod names and check if we have all expected pods
370
372
  found_pod_names = {pod.metadata.name for pod in all_pods}
@@ -732,7 +734,7 @@ def _create_pods(region: str, cluster_name_on_cloud: str,
732
734
  else:
733
735
  pod_spec['metadata']['labels'] = tags
734
736
  pod_spec['metadata']['labels'].update(
735
- {TAG_SKYPILOT_CLUSTER_NAME: cluster_name_on_cloud})
737
+ {k8s_constants.TAG_SKYPILOT_CLUSTER_NAME: cluster_name_on_cloud})
736
738
 
737
739
  terminating_pods = kubernetes_utils.filter_pods(namespace, context, tags,
738
740
  ['Terminating'])
@@ -841,7 +843,7 @@ def _create_pods(region: str, cluster_name_on_cloud: str,
841
843
  'podAffinityTerm': {
842
844
  'labelSelector': {
843
845
  'matchExpressions': [{
844
- 'key': TAG_SKYPILOT_CLUSTER_NAME,
846
+ 'key': k8s_constants.TAG_SKYPILOT_CLUSTER_NAME,
845
847
  'operator': 'In',
846
848
  'values': [cluster_name_on_cloud]
847
849
  }]
@@ -884,7 +886,7 @@ def _create_pods(region: str, cluster_name_on_cloud: str,
884
886
  # Add the deployment name as a label to the pod spec
885
887
  deployment_name = deployment_spec['metadata']['name']
886
888
  pod_spec_copy['metadata']['labels'][
887
- TAG_SKYPILOT_DEPLOYMENT_NAME] = deployment_name
889
+ k8s_constants.TAG_SKYPILOT_DEPLOYMENT_NAME] = deployment_name
888
890
  template_pod_spec['metadata'] = pod_spec_copy['metadata']
889
891
  template_pod_spec['spec'].update(pod_spec_copy['spec'])
890
892
  # Propagate the labels to the deployment for identification.
@@ -1289,7 +1291,8 @@ def get_command_runners(
1289
1291
 
1290
1292
  # Try to get deployment name from label first
1291
1293
  head_instance_info = instances[pod_name][0]
1292
- deployment = head_instance_info.tags.get(TAG_SKYPILOT_DEPLOYMENT_NAME)
1294
+ deployment = head_instance_info.tags.get(
1295
+ k8s_constants.TAG_SKYPILOT_DEPLOYMENT_NAME)
1293
1296
 
1294
1297
  node_list = [((namespace, context), pod_name)]
1295
1298
  head_runner = command_runner.KubernetesCommandRunner(
@@ -1,10 +1,12 @@
1
1
  """Kubernetes pvc provisioning."""
2
2
  from typing import Any, Dict, List, Optional, Tuple
3
3
 
4
+ from sky import global_user_state
4
5
  from sky import models
5
6
  from sky import sky_logging
6
7
  from sky.adaptors import kubernetes
7
8
  from sky.provision.kubernetes import config as config_lib
9
+ from sky.provision.kubernetes import constants as k8s_constants
8
10
  from sky.provision.kubernetes import utils as kubernetes_utils
9
11
  from sky.volumes import volume as volume_lib
10
12
 
@@ -45,17 +47,26 @@ def check_pvc_usage_for_pod(context: Optional[str], namespace: str,
45
47
  access_mode = pvc.spec.access_modes[0]
46
48
  if access_mode not in once_modes:
47
49
  continue
48
- usedby = _get_volume_usedby(context, namespace, pvc_name)
49
- if usedby:
50
+ usedby_pods, _ = _get_volume_usedby(context, namespace, pvc_name)
51
+ if usedby_pods:
50
52
  raise config_lib.KubernetesError(f'Volume {pvc_name} with access '
51
53
  f'mode {access_mode} is already '
52
- f'in use by {usedby}.')
54
+ f'in use by Pods {usedby_pods}.')
53
55
 
54
56
 
55
57
  def apply_volume(config: models.VolumeConfig) -> models.VolumeConfig:
56
58
  """Creates or registers a volume."""
57
59
  context, namespace = _get_context_namespace(config)
58
60
  pvc_spec = _get_pvc_spec(namespace, config)
61
+ # Check if the storage class exists
62
+ storage_class_name = pvc_spec['spec'].get('storageClassName')
63
+ if storage_class_name is not None:
64
+ try:
65
+ kubernetes.storage_api(context).read_storage_class(
66
+ name=storage_class_name)
67
+ except kubernetes.api_exception() as e:
68
+ raise config_lib.KubernetesError(
69
+ f'Check storage class {storage_class_name} error: {e}')
59
70
  create_persistent_volume_claim(namespace, context, pvc_spec)
60
71
  return config
61
72
 
@@ -76,22 +87,73 @@ def delete_volume(config: models.VolumeConfig) -> models.VolumeConfig:
76
87
  return config
77
88
 
78
89
 
79
- def _get_volume_usedby(context: Optional[str], namespace: str,
80
- pvc_name: str) -> List[str]:
81
- """Gets the usedby resources of a volume."""
82
- usedby = []
90
+ def _get_volume_usedby(
91
+ context: Optional[str],
92
+ namespace: str,
93
+ pvc_name: str,
94
+ ) -> Tuple[List[str], List[str]]:
95
+ """Gets the usedby resources of a volume.
96
+
97
+ This function returns the pods and clusters that are using the volume.
98
+ The usedby_pods is accurate, which also includes the Pods that are not
99
+ managed by SkyPilot.
100
+
101
+ Args:
102
+ context: Kubernetes context
103
+ namespace: Kubernetes namespace
104
+ pvc_name: PVC name
105
+
106
+ Returns:
107
+ usedby_pods: List of pods using the volume. These may include pods
108
+ not created by SkyPilot.
109
+ usedby_clusters: List of clusters using the volume.
110
+ """
111
+ usedby_pods = []
112
+ usedby_clusters = []
113
+ field_selector = ','.join([
114
+ f'status.phase!={phase}'
115
+ for phase in k8s_constants.PVC_NOT_HOLD_POD_PHASES
116
+ ])
117
+ cloud_to_name_map = _get_cluster_name_on_cloud_to_cluster_name_map()
83
118
  # Get all pods in the namespace
84
- pods = kubernetes.core_api(context).list_namespaced_pod(namespace=namespace)
119
+ pods = kubernetes.core_api(context).list_namespaced_pod(
120
+ namespace=namespace, field_selector=field_selector)
85
121
  for pod in pods.items:
86
- if pod.spec.volumes is not None:
87
- for volume in pod.spec.volumes:
88
- if volume.persistent_volume_claim is not None:
89
- if volume.persistent_volume_claim.claim_name == pvc_name:
90
- usedby.append(pod.metadata.name)
91
- return usedby
122
+ if pod.spec.volumes is None:
123
+ continue
124
+ for volume in pod.spec.volumes:
125
+ if volume.persistent_volume_claim is None:
126
+ continue
127
+ if volume.persistent_volume_claim.claim_name == pvc_name:
128
+ usedby_pods.append(pod.metadata.name)
129
+ # Get the real cluster name
130
+ cluster_name_on_cloud = pod.metadata.labels.get(
131
+ k8s_constants.TAG_SKYPILOT_CLUSTER_NAME)
132
+ if cluster_name_on_cloud is None:
133
+ continue
134
+ cluster_name = cloud_to_name_map.get(cluster_name_on_cloud)
135
+ if cluster_name is not None:
136
+ usedby_clusters.append(cluster_name)
137
+ if usedby_pods:
138
+ logger.debug(f'Volume {pvc_name} is used by Pods {usedby_pods}'
139
+ f' and clusters {usedby_clusters}')
140
+ return usedby_pods, usedby_clusters
141
+
142
+
143
+ def _get_cluster_name_on_cloud_to_cluster_name_map() -> Dict[str, str]:
144
+ """Gets the map from cluster name on cloud to cluster name."""
145
+ clusters = global_user_state.get_clusters()
146
+ cloud_to_name_map = {}
147
+ for cluster in clusters:
148
+ handle = cluster['handle']
149
+ if handle is None:
150
+ continue
151
+ cloud_to_name_map[handle.cluster_name_on_cloud] = cluster['name']
152
+ return cloud_to_name_map
92
153
 
93
154
 
94
- def get_volume_usedby(config: models.VolumeConfig) -> List[str]:
155
+ def get_volume_usedby(
156
+ config: models.VolumeConfig,) -> Tuple[List[str], List[str]]:
95
157
  """Gets the usedby resources of a volume."""
96
158
  context, namespace = _get_context_namespace(config)
97
159
  pvc_name = config.name_on_cloud
sky/skylet/constants.py CHANGED
@@ -481,6 +481,7 @@ MEMORY_SIZE_PATTERN = (
481
481
  ')?$')
482
482
 
483
483
  LAST_USE_TRUNC_LENGTH = 25
484
+ USED_BY_TRUNC_LENGTH = 25
484
485
 
485
486
  MIN_PRIORITY = -1000
486
487
  MAX_PRIORITY = 1000
sky/task.py CHANGED
@@ -884,6 +884,18 @@ class Task:
884
884
  def volumes(self) -> Dict[str, str]:
885
885
  return self._volumes
886
886
 
887
+ def set_volumes(self, volumes: Dict[str, str]) -> None:
888
+ """Sets the volumes for this task.
889
+
890
+ Args:
891
+ volumes: a dict of ``{mount_path: volume_name}``.
892
+ """
893
+ self._volumes = volumes
894
+
895
+ def update_volumes(self, volumes: Dict[str, str]) -> None:
896
+ """Updates the volumes for this task."""
897
+ self._volumes.update(volumes)
898
+
887
899
  def update_envs(
888
900
  self, envs: Union[None, List[Tuple[str, str]],
889
901
  Dict[str, str]]) -> 'Task':
sky/utils/log_utils.py CHANGED
@@ -573,6 +573,74 @@ def readable_time_duration(start: Optional[float],
573
573
  return diff
574
574
 
575
575
 
576
+ def human_duration(start: int, end: Optional[int] = None) -> str:
577
+ """Calculates the time elapsed between two timestamps and returns
578
+ it as a human-readable string, similar to Kubernetes' duration format.
579
+
580
+ Args:
581
+ start: The start time as a Unix timestamp (seconds since epoch).
582
+ end: The end time as a Unix timestamp (seconds since epoch).
583
+ If None, current time is used.
584
+
585
+ Returns:
586
+ A string representing the duration, e.g., "2d3h", "15m", "30s".
587
+ Returns "0s" for zero, negative durations, or if the timestamp
588
+ is invalid.
589
+ """
590
+ if not start or start <= 0:
591
+ return '0s'
592
+
593
+ if end is None:
594
+ end = int(time.time())
595
+ duration_seconds = end - start
596
+
597
+ units = {
598
+ 'y': 365 * 24 * 60 * 60,
599
+ 'd': 60 * 60 * 24,
600
+ 'h': 60 * 60,
601
+ 'm': 60,
602
+ 's': 1,
603
+ }
604
+
605
+ if duration_seconds <= 0:
606
+ return '0s'
607
+ elif duration_seconds < 60 * 2:
608
+ return f'{duration_seconds}s'
609
+
610
+ minutes = int(duration_seconds / units['m'])
611
+ if minutes < 10:
612
+ s = int(duration_seconds / units['s']) % 60
613
+ if s == 0:
614
+ return f'{minutes}m'
615
+ return f'{minutes}m{s}s'
616
+ elif minutes < 60 * 3:
617
+ return f'{minutes}m'
618
+
619
+ hours = int(duration_seconds / units['h'])
620
+ days = int(hours / 24)
621
+ years = int(hours / 24 / 365)
622
+ if hours < 8:
623
+ m = int(duration_seconds / units['m']) % 60
624
+ if m == 0:
625
+ return f'{hours}h'
626
+ return f'{hours}h{m}m'
627
+ elif hours < 48:
628
+ return f'{hours}h'
629
+ elif hours < 24 * 8:
630
+ h = hours % 24
631
+ if h == 0:
632
+ return f'{days}d'
633
+ return f'{days}d{h}h'
634
+ elif hours < 24 * 365 * 2:
635
+ return f'{days}d'
636
+ elif hours < 24 * 365 * 8:
637
+ dy = int(hours / 24) % 365
638
+ if dy == 0:
639
+ return f'{years}y'
640
+ return f'{years}y{dy}d'
641
+ return f'{years}y'
642
+
643
+
576
644
  def follow_logs(
577
645
  file: TextIO,
578
646
  *,