skypilot-nightly 1.0.0.dev20250819__py3-none-any.whl → 1.0.0.dev20250821__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.
- sky/__init__.py +5 -3
- sky/backends/cloud_vm_ray_backend.py +15 -14
- sky/backends/wheel_utils.py +2 -1
- sky/client/cli/command.py +20 -16
- sky/client/cli/flags.py +3 -3
- sky/core.py +1 -1
- sky/dashboard/out/404.html +1 -1
- sky/dashboard/out/_next/static/chunks/3015-6c9c09593b1e67b6.js +1 -0
- sky/dashboard/out/_next/static/chunks/{3785.bc5d2853355c9c47.js → 3785.d5b86f6ebc88e6e6.js} +1 -1
- sky/dashboard/out/_next/static/chunks/{9277.71481d5b2e606e33.js → 4783.c485f48348349f47.js} +8 -3
- sky/dashboard/out/_next/static/chunks/{6633-efe924b9b8136699.js → 7205-88191679e7988c57.js} +9 -4
- sky/dashboard/out/_next/static/chunks/8969-4a6f1a928fb6d370.js +1 -0
- sky/dashboard/out/_next/static/chunks/{8838.e7953f42af2b0544.js → 9946.3b7b43c217ff70ec.js} +9 -4
- sky/dashboard/out/_next/static/chunks/pages/clusters/{[cluster]-ec747e4f2dc39b57.js → [cluster]-a0527109c2fab467.js} +7 -2
- sky/dashboard/out/_next/static/chunks/pages/jobs/[job]-dd64309c3fe67ed2.js +11 -0
- sky/dashboard/out/_next/static/chunks/pages/{jobs-4b3ba1792dc6f21d.js → jobs-7421e63ac35f8fce.js} +1 -1
- sky/dashboard/out/_next/static/chunks/pages/workspaces/{[name]-65f72dee417237ef.js → [name]-de06e613e20bc977.js} +1 -1
- sky/dashboard/out/_next/static/chunks/pages/{workspaces-338de9df523d883a.js → workspaces-be35b22e2046564c.js} +1 -1
- sky/dashboard/out/_next/static/chunks/webpack-6e76f636a048e145.js +1 -0
- sky/dashboard/out/_next/static/{tYn7R2be3cQPYJfTxxE09 → wN25tc2rkvOkO-qkzIhcD}/_buildManifest.js +1 -1
- sky/dashboard/out/clusters/[cluster]/[job].html +1 -1
- sky/dashboard/out/clusters/[cluster].html +1 -1
- sky/dashboard/out/clusters.html +1 -1
- sky/dashboard/out/config.html +1 -1
- sky/dashboard/out/index.html +1 -1
- sky/dashboard/out/infra/[context].html +1 -1
- sky/dashboard/out/infra.html +1 -1
- sky/dashboard/out/jobs/[job].html +1 -1
- sky/dashboard/out/jobs/pools/[pool].html +1 -1
- sky/dashboard/out/jobs.html +1 -1
- sky/dashboard/out/users.html +1 -1
- sky/dashboard/out/volumes.html +1 -1
- sky/dashboard/out/workspace/new.html +1 -1
- sky/dashboard/out/workspaces/[name].html +1 -1
- sky/dashboard/out/workspaces.html +1 -1
- sky/exceptions.py +6 -1
- sky/global_user_state.py +18 -11
- sky/jobs/server/core.py +1 -1
- sky/models.py +1 -0
- sky/provision/aws/config.py +11 -11
- sky/provision/aws/instance.py +30 -27
- sky/provision/do/utils.py +2 -2
- sky/provision/docker_utils.py +20 -1
- sky/provision/kubernetes/network_utils.py +3 -3
- sky/provision/kubernetes/utils.py +2 -2
- sky/provision/kubernetes/volume.py +2 -0
- sky/resources.py +17 -7
- sky/serve/replica_managers.py +7 -0
- sky/serve/server/impl.py +1 -1
- sky/server/requests/payloads.py +1 -0
- sky/server/requests/serializers/encoders.py +14 -2
- sky/server/server.py +33 -0
- sky/setup_files/dependencies.py +17 -11
- sky/skypilot_config.py +4 -4
- sky/users/permission.py +2 -1
- sky/utils/common.py +27 -7
- sky/utils/common_utils.py +13 -9
- sky/utils/directory_utils.py +12 -0
- sky/utils/env_options.py +3 -0
- sky/utils/kubernetes/gpu_labeler.py +3 -3
- sky/utils/schemas.py +1 -0
- sky/utils/serialize_utils.py +16 -0
- sky/volumes/client/sdk.py +10 -7
- sky/volumes/server/core.py +12 -3
- sky/volumes/volume.py +17 -3
- {skypilot_nightly-1.0.0.dev20250819.dist-info → skypilot_nightly-1.0.0.dev20250821.dist-info}/METADATA +21 -13
- {skypilot_nightly-1.0.0.dev20250819.dist-info → skypilot_nightly-1.0.0.dev20250821.dist-info}/RECORD +76 -74
- sky/dashboard/out/_next/static/chunks/3015-bf218e4973bf5c8f.js +0 -1
- sky/dashboard/out/_next/static/chunks/8969-23c8fbdb8b397d59.js +0 -1
- sky/dashboard/out/_next/static/chunks/pages/jobs/[job]-ad2cd5aab787bc15.js +0 -6
- sky/dashboard/out/_next/static/chunks/webpack-008593a02784a2df.js +0 -1
- /sky/dashboard/out/_next/static/chunks/{1121-2edb8ab2ba080a76.js → 1121-8afcf719ea87debc.js} +0 -0
- /sky/dashboard/out/_next/static/chunks/{1141-2f60a90b7d76838e.js → 1141-943efc7aff0f0c06.js} +0 -0
- /sky/dashboard/out/_next/static/chunks/{6856-e6f350f567182e87.js → 6856-049014c6d43d127b.js} +0 -0
- /sky/dashboard/out/_next/static/chunks/pages/jobs/pools/{[pool]-7d4182df6625fe10.js → [pool]-07349868f7905d37.js} +0 -0
- /sky/dashboard/out/_next/static/{tYn7R2be3cQPYJfTxxE09 → wN25tc2rkvOkO-qkzIhcD}/_ssgManifest.js +0 -0
- {skypilot_nightly-1.0.0.dev20250819.dist-info → skypilot_nightly-1.0.0.dev20250821.dist-info}/WHEEL +0 -0
- {skypilot_nightly-1.0.0.dev20250819.dist-info → skypilot_nightly-1.0.0.dev20250821.dist-info}/entry_points.txt +0 -0
- {skypilot_nightly-1.0.0.dev20250819.dist-info → skypilot_nightly-1.0.0.dev20250821.dist-info}/licenses/LICENSE +0 -0
- {skypilot_nightly-1.0.0.dev20250819.dist-info → skypilot_nightly-1.0.0.dev20250821.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-
|
|
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/wN25tc2rkvOkO-qkzIhcD/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/wN25tc2rkvOkO-qkzIhcD/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/jobs/[job]","query":{},"buildId":"wN25tc2rkvOkO-qkzIhcD","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-
|
|
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/wN25tc2rkvOkO-qkzIhcD/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/wN25tc2rkvOkO-qkzIhcD/_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":"wN25tc2rkvOkO-qkzIhcD","assetPrefix":"/dashboard","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
|
sky/dashboard/out/jobs.html
CHANGED
|
@@ -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-
|
|
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/wN25tc2rkvOkO-qkzIhcD/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/wN25tc2rkvOkO-qkzIhcD/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/jobs","query":{},"buildId":"wN25tc2rkvOkO-qkzIhcD","assetPrefix":"/dashboard","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
|
sky/dashboard/out/users.html
CHANGED
|
@@ -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-
|
|
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/wN25tc2rkvOkO-qkzIhcD/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/wN25tc2rkvOkO-qkzIhcD/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/users","query":{},"buildId":"wN25tc2rkvOkO-qkzIhcD","assetPrefix":"/dashboard","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
|
sky/dashboard/out/volumes.html
CHANGED
|
@@ -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-
|
|
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/wN25tc2rkvOkO-qkzIhcD/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/wN25tc2rkvOkO-qkzIhcD/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/volumes","query":{},"buildId":"wN25tc2rkvOkO-qkzIhcD","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-
|
|
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/wN25tc2rkvOkO-qkzIhcD/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/wN25tc2rkvOkO-qkzIhcD/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/workspace/new","query":{},"buildId":"wN25tc2rkvOkO-qkzIhcD","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-
|
|
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/wN25tc2rkvOkO-qkzIhcD/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/wN25tc2rkvOkO-qkzIhcD/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/workspaces/[name]","query":{},"buildId":"wN25tc2rkvOkO-qkzIhcD","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-
|
|
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/wN25tc2rkvOkO-qkzIhcD/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/wN25tc2rkvOkO-qkzIhcD/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/workspaces","query":{},"buildId":"wN25tc2rkvOkO-qkzIhcD","assetPrefix":"/dashboard","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
|
sky/exceptions.py
CHANGED
|
@@ -6,11 +6,12 @@ import types
|
|
|
6
6
|
import typing
|
|
7
7
|
from typing import Any, Dict, List, Optional, Sequence
|
|
8
8
|
|
|
9
|
+
from sky.backends import backend
|
|
9
10
|
from sky.utils import env_options
|
|
11
|
+
from sky.utils import serialize_utils
|
|
10
12
|
|
|
11
13
|
if typing.TYPE_CHECKING:
|
|
12
14
|
from sky import jobs as managed_jobs
|
|
13
|
-
from sky.backends import backend
|
|
14
15
|
from sky.skylet import job_lib
|
|
15
16
|
from sky.utils import status_lib
|
|
16
17
|
|
|
@@ -92,6 +93,10 @@ def serialize_exception(e: BaseException) -> Dict[str, Any]:
|
|
|
92
93
|
attr_v = attributes[attr_k]
|
|
93
94
|
if isinstance(attr_v, types.TracebackType):
|
|
94
95
|
attributes[attr_k] = traceback.format_tb(attr_v)
|
|
96
|
+
if isinstance(attr_v, backend.ResourceHandle):
|
|
97
|
+
attributes[attr_k] = (
|
|
98
|
+
serialize_utils.prepare_handle_for_backwards_compatibility(
|
|
99
|
+
attr_v))
|
|
95
100
|
|
|
96
101
|
data = {
|
|
97
102
|
'type': e.__class__.__name__,
|
sky/global_user_state.py
CHANGED
|
@@ -55,6 +55,13 @@ _SQLALCHEMY_ENGINE_LOCK = threading.Lock()
|
|
|
55
55
|
DEFAULT_CLUSTER_EVENT_RETENTION_HOURS = 24.0
|
|
56
56
|
MIN_CLUSTER_EVENT_DAEMON_INTERVAL_SECONDS = 3600
|
|
57
57
|
|
|
58
|
+
_UNIQUE_CONSTRAINT_FAILED_ERROR_MSGS = [
|
|
59
|
+
# sqlite
|
|
60
|
+
'UNIQUE constraint failed',
|
|
61
|
+
# postgres
|
|
62
|
+
'duplicate key value violates unique constraint',
|
|
63
|
+
]
|
|
64
|
+
|
|
58
65
|
Base = declarative.declarative_base()
|
|
59
66
|
|
|
60
67
|
config_table = sqlalchemy.Table(
|
|
@@ -735,17 +742,17 @@ def add_cluster_event(cluster_name: str,
|
|
|
735
742
|
))
|
|
736
743
|
session.commit()
|
|
737
744
|
except sqlalchemy.exc.IntegrityError as e:
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
745
|
+
for msg in _UNIQUE_CONSTRAINT_FAILED_ERROR_MSGS:
|
|
746
|
+
if msg in str(e):
|
|
747
|
+
# This can happen if the cluster event is added twice.
|
|
748
|
+
# We can ignore this error unless the caller requests
|
|
749
|
+
# to expose the error.
|
|
750
|
+
if expose_duplicate_error:
|
|
751
|
+
raise db_utils.UniqueConstraintViolationError(
|
|
752
|
+
value=reason, message=str(e))
|
|
753
|
+
else:
|
|
754
|
+
return
|
|
755
|
+
raise e
|
|
749
756
|
|
|
750
757
|
|
|
751
758
|
def get_last_cluster_event(cluster_hash: str,
|
sky/jobs/server/core.py
CHANGED
|
@@ -188,11 +188,11 @@ def launch(
|
|
|
188
188
|
|
|
189
189
|
dag_uuid = str(uuid.uuid4().hex[:4])
|
|
190
190
|
dag = dag_utils.convert_entrypoint_to_dag(entrypoint)
|
|
191
|
-
dag.resolve_and_validate_volumes()
|
|
192
191
|
# Always apply the policy again here, even though it might have been applied
|
|
193
192
|
# in the CLI. This is to ensure that we apply the policy to the final DAG
|
|
194
193
|
# and get the mutated config.
|
|
195
194
|
dag, mutated_user_config = admin_policy_utils.apply(dag)
|
|
195
|
+
dag.resolve_and_validate_volumes()
|
|
196
196
|
if not dag.is_chain():
|
|
197
197
|
with ux_utils.print_exception_no_traceback():
|
|
198
198
|
raise ValueError('Only single-task or chain DAG is '
|
sky/models.py
CHANGED
sky/provision/aws/config.py
CHANGED
|
@@ -498,8 +498,8 @@ def _vpc_id_from_security_group_ids(ec2: 'mypy_boto3_ec2.ServiceResource',
|
|
|
498
498
|
return vpc_ids[0]
|
|
499
499
|
|
|
500
500
|
|
|
501
|
-
def
|
|
502
|
-
|
|
501
|
+
def get_vpc_id_by_name(ec2: 'mypy_boto3_ec2.ServiceResource', vpc_name: str,
|
|
502
|
+
region: str) -> str:
|
|
503
503
|
"""Returns the VPC ID of the unique VPC with a given name.
|
|
504
504
|
|
|
505
505
|
Exits with code 1 if:
|
|
@@ -532,7 +532,7 @@ def _get_subnet_and_vpc_id(ec2: 'mypy_boto3_ec2.ServiceResource',
|
|
|
532
532
|
use_internal_ips: bool,
|
|
533
533
|
vpc_name: Optional[str]) -> Tuple[Any, str]:
|
|
534
534
|
if vpc_name is not None:
|
|
535
|
-
vpc_id_of_sg =
|
|
535
|
+
vpc_id_of_sg = get_vpc_id_by_name(ec2, vpc_name, region)
|
|
536
536
|
elif security_group_ids:
|
|
537
537
|
vpc_id_of_sg = _vpc_id_from_security_group_ids(ec2, security_group_ids)
|
|
538
538
|
else:
|
|
@@ -614,8 +614,8 @@ def _get_or_create_vpc_security_group(ec2: 'mypy_boto3_ec2.ServiceResource',
|
|
|
614
614
|
due to AWS service issues.
|
|
615
615
|
"""
|
|
616
616
|
# Figure out which security groups with this name exist for each VPC...
|
|
617
|
-
security_group =
|
|
618
|
-
|
|
617
|
+
security_group = get_security_group_from_vpc_id(ec2, vpc_id,
|
|
618
|
+
expected_sg_name)
|
|
619
619
|
if security_group is not None:
|
|
620
620
|
return security_group
|
|
621
621
|
|
|
@@ -631,7 +631,7 @@ def _get_or_create_vpc_security_group(ec2: 'mypy_boto3_ec2.ServiceResource',
|
|
|
631
631
|
# The security group already exists, but we didn't see it
|
|
632
632
|
# because of eventual consistency.
|
|
633
633
|
logger.warning(f'{expected_sg_name} already exists when creating.')
|
|
634
|
-
security_group =
|
|
634
|
+
security_group = get_security_group_from_vpc_id(
|
|
635
635
|
ec2, vpc_id, expected_sg_name)
|
|
636
636
|
assert (security_group is not None and
|
|
637
637
|
security_group.group_name == expected_sg_name), (
|
|
@@ -646,8 +646,8 @@ def _get_or_create_vpc_security_group(ec2: 'mypy_boto3_ec2.ServiceResource',
|
|
|
646
646
|
logger.warning(message)
|
|
647
647
|
raise exceptions.NoClusterLaunchedError(message) from e
|
|
648
648
|
|
|
649
|
-
security_group =
|
|
650
|
-
|
|
649
|
+
security_group = get_security_group_from_vpc_id(ec2, vpc_id,
|
|
650
|
+
expected_sg_name)
|
|
651
651
|
assert security_group is not None, 'Failed to create security group'
|
|
652
652
|
logger.info(f'Created new security group {colorama.Style.BRIGHT}'
|
|
653
653
|
f'{security_group.group_name}{colorama.Style.RESET_ALL} '
|
|
@@ -655,9 +655,9 @@ def _get_or_create_vpc_security_group(ec2: 'mypy_boto3_ec2.ServiceResource',
|
|
|
655
655
|
return security_group
|
|
656
656
|
|
|
657
657
|
|
|
658
|
-
def
|
|
659
|
-
|
|
660
|
-
|
|
658
|
+
def get_security_group_from_vpc_id(ec2: 'mypy_boto3_ec2.ServiceResource',
|
|
659
|
+
vpc_id: str,
|
|
660
|
+
group_name: str) -> Optional[Any]:
|
|
661
661
|
"""Get security group by VPC ID and group name."""
|
|
662
662
|
existing_groups = list(
|
|
663
663
|
ec2.security_groups.filter(Filters=[{
|
sky/provision/aws/instance.py
CHANGED
|
@@ -18,6 +18,7 @@ from sky.clouds import aws as aws_cloud
|
|
|
18
18
|
from sky.clouds.utils import aws_utils
|
|
19
19
|
from sky.provision import common
|
|
20
20
|
from sky.provision import constants
|
|
21
|
+
from sky.provision.aws import config as aws_config
|
|
21
22
|
from sky.provision.aws import utils
|
|
22
23
|
from sky.utils import common_utils
|
|
23
24
|
from sky.utils import resources_utils
|
|
@@ -685,7 +686,9 @@ def terminate_instances(
|
|
|
685
686
|
filters,
|
|
686
687
|
included_instances=None,
|
|
687
688
|
excluded_instances=None)
|
|
688
|
-
default_sg =
|
|
689
|
+
default_sg = aws_config.get_security_group_from_vpc_id(
|
|
690
|
+
ec2, _get_vpc_id(provider_config),
|
|
691
|
+
aws_cloud.DEFAULT_SECURITY_GROUP_NAME)
|
|
689
692
|
if sg_name == aws_cloud.DEFAULT_SECURITY_GROUP_NAME:
|
|
690
693
|
# Case 1: The default SG is used, we don't need to ensure instance are
|
|
691
694
|
# terminated.
|
|
@@ -727,30 +730,6 @@ def terminate_instances(
|
|
|
727
730
|
# of most cloud implementations (including AWS).
|
|
728
731
|
|
|
729
732
|
|
|
730
|
-
def _get_sg_from_name(
|
|
731
|
-
ec2: Any,
|
|
732
|
-
sg_name: str,
|
|
733
|
-
) -> Any:
|
|
734
|
-
# GroupNames will only filter SGs in the default VPC, so we need to use
|
|
735
|
-
# Filters here. Ref:
|
|
736
|
-
# https://boto3.amazonaws.com/v1/documentation/api/1.26.112/reference/services/ec2/service-resource/security_groups.html # pylint: disable=line-too-long
|
|
737
|
-
sgs = ec2.security_groups.filter(Filters=[{
|
|
738
|
-
'Name': 'group-name',
|
|
739
|
-
'Values': [sg_name]
|
|
740
|
-
}])
|
|
741
|
-
num_sg = len(list(sgs))
|
|
742
|
-
if num_sg == 0:
|
|
743
|
-
logger.warning(f'Expected security group {sg_name} not found. ')
|
|
744
|
-
return None
|
|
745
|
-
if num_sg > 1:
|
|
746
|
-
# TODO(tian): Better handle this case. Maybe we can check when creating
|
|
747
|
-
# the SG and throw an error if there is already an existing SG with the
|
|
748
|
-
# same name.
|
|
749
|
-
logger.warning(f'Found {num_sg} security groups with name {sg_name}. ')
|
|
750
|
-
return None
|
|
751
|
-
return list(sgs)[0]
|
|
752
|
-
|
|
753
|
-
|
|
754
733
|
def _maybe_move_to_new_sg(
|
|
755
734
|
instance: Any,
|
|
756
735
|
expected_sg: Any,
|
|
@@ -803,7 +782,9 @@ def open_ports(
|
|
|
803
782
|
with ux_utils.print_exception_no_traceback():
|
|
804
783
|
raise ValueError('Instance with cluster name '
|
|
805
784
|
f'{cluster_name_on_cloud} not found.')
|
|
806
|
-
sg =
|
|
785
|
+
sg = aws_config.get_security_group_from_vpc_id(ec2,
|
|
786
|
+
_get_vpc_id(provider_config),
|
|
787
|
+
sg_name)
|
|
807
788
|
if sg is None:
|
|
808
789
|
with ux_utils.print_exception_no_traceback():
|
|
809
790
|
raise ValueError('Cannot find new security group '
|
|
@@ -899,7 +880,9 @@ def cleanup_ports(
|
|
|
899
880
|
# We only want to delete the SG that is dedicated to this cluster (i.e.,
|
|
900
881
|
# this cluster have opened some ports).
|
|
901
882
|
return
|
|
902
|
-
sg =
|
|
883
|
+
sg = aws_config.get_security_group_from_vpc_id(ec2,
|
|
884
|
+
_get_vpc_id(provider_config),
|
|
885
|
+
sg_name)
|
|
903
886
|
if sg is None:
|
|
904
887
|
logger.warning(
|
|
905
888
|
'Find security group failed. Skip cleanup security group.')
|
|
@@ -1010,3 +993,23 @@ def get_cluster_info(
|
|
|
1010
993
|
provider_name='aws',
|
|
1011
994
|
provider_config=provider_config,
|
|
1012
995
|
)
|
|
996
|
+
|
|
997
|
+
|
|
998
|
+
def _get_vpc_id(provider_config: Dict[str, Any]) -> str:
|
|
999
|
+
region = provider_config['region']
|
|
1000
|
+
ec2 = _default_ec2_resource(provider_config['region'])
|
|
1001
|
+
if 'vpc_name' in provider_config:
|
|
1002
|
+
return aws_config.get_vpc_id_by_name(ec2, provider_config['vpc_name'],
|
|
1003
|
+
region)
|
|
1004
|
+
else:
|
|
1005
|
+
# Retrieve the default VPC name from the region.
|
|
1006
|
+
response = ec2.meta.client.describe_vpcs(Filters=[{
|
|
1007
|
+
'Name': 'isDefault',
|
|
1008
|
+
'Values': ['true']
|
|
1009
|
+
}])
|
|
1010
|
+
if len(response['Vpcs']) == 0:
|
|
1011
|
+
raise ValueError(f'No default VPC found in region {region}')
|
|
1012
|
+
elif len(response['Vpcs']) > 1:
|
|
1013
|
+
raise ValueError(f'Multiple default VPCs found in region {region}')
|
|
1014
|
+
else:
|
|
1015
|
+
return response['Vpcs'][0]['VpcId']
|
sky/provision/do/utils.py
CHANGED
|
@@ -30,7 +30,7 @@ POSSIBLE_CREDENTIALS_PATHS = [
|
|
|
30
30
|
INITIAL_BACKOFF_SECONDS = 10
|
|
31
31
|
MAX_BACKOFF_FACTOR = 10
|
|
32
32
|
MAX_ATTEMPTS = 6
|
|
33
|
-
|
|
33
|
+
SSH_KEY_NAME_ON_DO_PREFIX = 'sky-key-'
|
|
34
34
|
|
|
35
35
|
_client = None
|
|
36
36
|
_ssh_key_id = None
|
|
@@ -125,7 +125,7 @@ def ssh_key_id(public_key: str):
|
|
|
125
125
|
|
|
126
126
|
request = {
|
|
127
127
|
'public_key': public_key,
|
|
128
|
-
'name':
|
|
128
|
+
'name': SSH_KEY_NAME_ON_DO_PREFIX + common_utils.get_user_hash(),
|
|
129
129
|
}
|
|
130
130
|
_ssh_key_id = client().ssh_keys.create(body=request)['ssh_key']
|
|
131
131
|
return _ssh_key_id
|
sky/provision/docker_utils.py
CHANGED
|
@@ -83,6 +83,21 @@ def check_docker_image(cname, docker_cmd):
|
|
|
83
83
|
return _check_helper(cname, '.Config.Image', docker_cmd)
|
|
84
84
|
|
|
85
85
|
|
|
86
|
+
def maybe_remove_container_cmds(container_name, docker_cmd):
|
|
87
|
+
"""Remove the container if it exists. If not, it will be a no-op.
|
|
88
|
+
"""
|
|
89
|
+
docker_rm = [
|
|
90
|
+
docker_cmd,
|
|
91
|
+
'rm',
|
|
92
|
+
'-f',
|
|
93
|
+
container_name,
|
|
94
|
+
'2>/dev/null',
|
|
95
|
+
'||',
|
|
96
|
+
'true',
|
|
97
|
+
]
|
|
98
|
+
return ' '.join(docker_rm)
|
|
99
|
+
|
|
100
|
+
|
|
86
101
|
def docker_start_cmds(
|
|
87
102
|
image,
|
|
88
103
|
container_name,
|
|
@@ -285,6 +300,10 @@ class DockerInitializer:
|
|
|
285
300
|
'sudo mv /tmp/daemon.json /etc/docker/daemon.json;'
|
|
286
301
|
'sudo systemctl restart docker; } || true')
|
|
287
302
|
user_docker_run_options = self.docker_config.get('run_options', [])
|
|
303
|
+
remove_container_cmd = maybe_remove_container_cmds(
|
|
304
|
+
self.container_name,
|
|
305
|
+
self.docker_cmd,
|
|
306
|
+
)
|
|
288
307
|
start_command = docker_start_cmds(
|
|
289
308
|
specific_image,
|
|
290
309
|
self.container_name,
|
|
@@ -292,7 +311,7 @@ class DockerInitializer:
|
|
|
292
311
|
self._auto_configure_shm(user_docker_run_options)),
|
|
293
312
|
self.docker_cmd,
|
|
294
313
|
)
|
|
295
|
-
self._run(start_command)
|
|
314
|
+
self._run(f'{remove_container_cmd}; {start_command}')
|
|
296
315
|
|
|
297
316
|
# SkyPilot: Setup Commands.
|
|
298
317
|
# TODO(zhwu): the following setups should be aligned with the kubernetes
|
|
@@ -4,13 +4,13 @@ import time
|
|
|
4
4
|
import typing
|
|
5
5
|
from typing import Dict, List, Optional, Tuple, Union
|
|
6
6
|
|
|
7
|
-
import sky
|
|
8
7
|
from sky import exceptions
|
|
9
8
|
from sky import sky_logging
|
|
10
9
|
from sky import skypilot_config
|
|
11
10
|
from sky.adaptors import common as adaptors_common
|
|
12
11
|
from sky.adaptors import kubernetes
|
|
13
12
|
from sky.provision.kubernetes import utils as kubernetes_utils
|
|
13
|
+
from sky.utils import directory_utils
|
|
14
14
|
from sky.utils import kubernetes_enums
|
|
15
15
|
from sky.utils import ux_utils
|
|
16
16
|
|
|
@@ -80,7 +80,7 @@ def get_networking_mode(
|
|
|
80
80
|
def fill_loadbalancer_template(namespace: str, context: Optional[str],
|
|
81
81
|
service_name: str, ports: List[int],
|
|
82
82
|
selector_key: str, selector_value: str) -> Dict:
|
|
83
|
-
template_path = os.path.join(
|
|
83
|
+
template_path = os.path.join(directory_utils.get_sky_dir(), 'templates',
|
|
84
84
|
_LOADBALANCER_TEMPLATE_NAME)
|
|
85
85
|
if not os.path.exists(template_path):
|
|
86
86
|
raise FileNotFoundError(
|
|
@@ -116,7 +116,7 @@ def fill_ingress_template(namespace: str, context: Optional[str],
|
|
|
116
116
|
service_details: List[Tuple[str, int,
|
|
117
117
|
str]], ingress_name: str,
|
|
118
118
|
selector_key: str, selector_value: str) -> Dict:
|
|
119
|
-
template_path = os.path.join(
|
|
119
|
+
template_path = os.path.join(directory_utils.get_sky_dir(), 'templates',
|
|
120
120
|
_INGRESS_TEMPLATE_NAME)
|
|
121
121
|
if not os.path.exists(template_path):
|
|
122
122
|
raise FileNotFoundError(
|
|
@@ -14,7 +14,6 @@ import typing
|
|
|
14
14
|
from typing import Any, Callable, Dict, List, Optional, Set, Tuple, Union
|
|
15
15
|
from urllib.parse import urlparse
|
|
16
16
|
|
|
17
|
-
import sky
|
|
18
17
|
from sky import clouds
|
|
19
18
|
from sky import exceptions
|
|
20
19
|
from sky import global_user_state
|
|
@@ -31,6 +30,7 @@ from sky.skylet import constants
|
|
|
31
30
|
from sky.utils import annotations
|
|
32
31
|
from sky.utils import common_utils
|
|
33
32
|
from sky.utils import config_utils
|
|
33
|
+
from sky.utils import directory_utils
|
|
34
34
|
from sky.utils import env_options
|
|
35
35
|
from sky.utils import kubernetes_enums
|
|
36
36
|
from sky.utils import schemas
|
|
@@ -2444,7 +2444,7 @@ def clean_zombie_ssh_jump_pod(namespace: str, context: Optional[str],
|
|
|
2444
2444
|
|
|
2445
2445
|
def fill_ssh_jump_template(ssh_key_secret: str, ssh_jump_image: str,
|
|
2446
2446
|
ssh_jump_name: str, service_type: str) -> Dict:
|
|
2447
|
-
template_path = os.path.join(
|
|
2447
|
+
template_path = os.path.join(directory_utils.get_sky_dir(), 'templates',
|
|
2448
2448
|
'kubernetes-ssh-jump.yml.j2')
|
|
2449
2449
|
if not os.path.exists(template_path):
|
|
2450
2450
|
raise FileNotFoundError(
|
|
@@ -203,6 +203,8 @@ def _get_pvc_spec(namespace: str,
|
|
|
203
203
|
},
|
|
204
204
|
}
|
|
205
205
|
}
|
|
206
|
+
if config.labels:
|
|
207
|
+
pvc_spec['metadata']['labels'].update(config.labels)
|
|
206
208
|
storage_class = config.config.get('storage_class_name')
|
|
207
209
|
if storage_class is not None:
|
|
208
210
|
pvc_spec['spec']['storageClassName'] = storage_class
|
sky/resources.py
CHANGED
|
@@ -1260,10 +1260,14 @@ class Resources:
|
|
|
1260
1260
|
def extract_docker_image(self) -> Optional[str]:
|
|
1261
1261
|
if self.image_id is None:
|
|
1262
1262
|
return None
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
if
|
|
1266
|
-
|
|
1263
|
+
# Handle dict image_id
|
|
1264
|
+
if len(self.image_id) == 1:
|
|
1265
|
+
# Check if the single key matches the region or is None (any region)
|
|
1266
|
+
image_key = list(self.image_id.keys())[0]
|
|
1267
|
+
if image_key == self.region or image_key is None:
|
|
1268
|
+
image_id = self.image_id[image_key]
|
|
1269
|
+
if image_id.startswith('docker:'):
|
|
1270
|
+
return image_id[len('docker:'):]
|
|
1267
1271
|
return None
|
|
1268
1272
|
|
|
1269
1273
|
def _try_validate_image_id(self) -> None:
|
|
@@ -1333,13 +1337,19 @@ class Resources:
|
|
|
1333
1337
|
'Kubernetes, please explicitly specify the cloud.') from e
|
|
1334
1338
|
|
|
1335
1339
|
if self._region is not None:
|
|
1336
|
-
|
|
1340
|
+
# If the image_id has None as key (region-agnostic),
|
|
1341
|
+
# use it for any region
|
|
1342
|
+
if None in self._image_id:
|
|
1343
|
+
# Replace None key with the actual region
|
|
1344
|
+
self._image_id = {self._region: self._image_id[None]}
|
|
1345
|
+
elif self._region not in self._image_id:
|
|
1337
1346
|
with ux_utils.print_exception_no_traceback():
|
|
1338
1347
|
raise ValueError(
|
|
1339
1348
|
f'image_id {self._image_id} should contain the image '
|
|
1340
1349
|
f'for the specified region {self._region}.')
|
|
1341
|
-
|
|
1342
|
-
|
|
1350
|
+
else:
|
|
1351
|
+
# Narrow down the image_id to the specified region.
|
|
1352
|
+
self._image_id = {self._region: self._image_id[self._region]}
|
|
1343
1353
|
|
|
1344
1354
|
# Check the image_id's are valid.
|
|
1345
1355
|
for region, image_id in self._image_id.items():
|
sky/serve/replica_managers.py
CHANGED
|
@@ -48,6 +48,13 @@ _PROCESS_POOL_REFRESH_INTERVAL = 20
|
|
|
48
48
|
_RETRY_INIT_GAP_SECONDS = 60
|
|
49
49
|
_DEFAULT_DRAIN_SECONDS = 120
|
|
50
50
|
|
|
51
|
+
# TODO(tian): Backward compatibility. Remove this after 3 minor release, i.e.
|
|
52
|
+
# 0.13.0. We move the ProcessStatus to common_utils.ProcessStatus in #6666, but
|
|
53
|
+
# old ReplicaInfo in database will still tries to unpickle using ProcessStatus
|
|
54
|
+
# in replica_managers. We set this alias to avoid breaking changes. See #6729
|
|
55
|
+
# for more details.
|
|
56
|
+
ProcessStatus = common_utils.ProcessStatus
|
|
57
|
+
|
|
51
58
|
|
|
52
59
|
# TODO(tian): Combine this with
|
|
53
60
|
# sky/spot/recovery_strategy.py::StrategyExecutor::launch
|
sky/serve/server/impl.py
CHANGED
|
@@ -129,11 +129,11 @@ def up(
|
|
|
129
129
|
f'{constants.CLUSTER_NAME_VALID_REGEX}')
|
|
130
130
|
|
|
131
131
|
dag = dag_utils.convert_entrypoint_to_dag(task)
|
|
132
|
-
dag.resolve_and_validate_volumes()
|
|
133
132
|
# Always apply the policy again here, even though it might have been applied
|
|
134
133
|
# in the CLI. This is to ensure that we apply the policy to the final DAG
|
|
135
134
|
# and get the mutated config.
|
|
136
135
|
dag, mutated_user_config = admin_policy_utils.apply(dag)
|
|
136
|
+
dag.resolve_and_validate_volumes()
|
|
137
137
|
dag.pre_mount_volumes()
|
|
138
138
|
task = dag.tasks[0]
|
|
139
139
|
assert task.service is not None
|
sky/server/requests/payloads.py
CHANGED