skypilot-nightly 1.0.0.dev20250720__py3-none-any.whl → 1.0.0.dev20250723__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 +2 -2
- sky/admin_policy.py +11 -4
- sky/backends/backend_utils.py +27 -11
- sky/backends/cloud_vm_ray_backend.py +22 -27
- sky/client/cli/command.py +38 -23
- sky/client/sdk.py +52 -7
- sky/clouds/nebius.py +2 -5
- sky/clouds/vast.py +2 -1
- sky/dashboard/out/404.html +1 -1
- sky/dashboard/out/_next/static/chunks/{1141-d8c6404a7c6fffe6.js → 1141-e49a159c30a6c4a7.js} +1 -1
- sky/dashboard/out/_next/static/chunks/1559-18717d96ef2fcbe9.js +30 -0
- sky/dashboard/out/_next/static/chunks/{1871-a821dcaaae2a3823.js → 1871-ea0e7283886407ca.js} +2 -2
- sky/dashboard/out/_next/static/chunks/2003.b82e6db40ec4c463.js +1 -0
- sky/dashboard/out/_next/static/chunks/2350.23778a2b19aabd33.js +1 -0
- sky/dashboard/out/_next/static/chunks/2369.2d6e4757f8dfc2b7.js +15 -0
- sky/dashboard/out/_next/static/chunks/{2641.5233e938f14e31a7.js → 2641.74c19c4d45a2c034.js} +1 -1
- sky/dashboard/out/_next/static/chunks/3785.59705416215ff08b.js +1 -0
- sky/dashboard/out/_next/static/chunks/4869.da729a7db3a31f43.js +16 -0
- sky/dashboard/out/_next/static/chunks/4937.d75809403fc264ac.js +15 -0
- sky/dashboard/out/_next/static/chunks/6135-2abbd0352f8ee061.js +1 -0
- sky/dashboard/out/_next/static/chunks/691.488b4aef97c28727.js +55 -0
- sky/dashboard/out/_next/static/chunks/6990-f64e03df359e04f7.js +1 -0
- sky/dashboard/out/_next/static/chunks/7411-2cc31dc0fdf2a9ad.js +41 -0
- sky/dashboard/out/_next/static/chunks/9025.4a9099bdf3ed4875.js +6 -0
- sky/dashboard/out/_next/static/chunks/{938-63fc419cb82ad9b3.js → 938-7ee806653aef0609.js} +1 -1
- sky/dashboard/out/_next/static/chunks/9847.387abf8a14d722db.js +30 -0
- sky/dashboard/out/_next/static/chunks/{9984.2b5e3fa69171bff9.js → 9984.0460de9d3adf5582.js} +1 -1
- sky/dashboard/out/_next/static/chunks/pages/_app-da491665d4289aae.js +34 -0
- sky/dashboard/out/_next/static/chunks/pages/clusters/[cluster]/{[job]-fa406155b4223d0d.js → [job]-2186770cc2de1623.js} +2 -2
- sky/dashboard/out/_next/static/chunks/pages/clusters/{[cluster]-0c37ee1ac5f3474d.js → [cluster]-95afb019ab85801c.js} +1 -1
- sky/dashboard/out/_next/static/chunks/pages/clusters-3d4be4961e1c94eb.js +1 -0
- sky/dashboard/out/_next/static/chunks/pages/index-89e7daf7b7df02e0.js +1 -0
- sky/dashboard/out/_next/static/chunks/pages/infra/[context]-a90b4fe4616dc501.js +1 -0
- sky/dashboard/out/_next/static/chunks/pages/infra-0d3d1f890c5d188a.js +1 -0
- sky/dashboard/out/_next/static/chunks/pages/jobs/{[job]-c5b357bfd9502fbe.js → [job]-dc0299ffefebcdbe.js} +2 -2
- sky/dashboard/out/_next/static/chunks/pages/jobs-49f790d12a85027c.js +1 -0
- sky/dashboard/out/_next/static/chunks/pages/{users-19e98664bdd61643.js → users-6790fcefd5487b13.js} +1 -1
- sky/dashboard/out/_next/static/chunks/pages/workspaces/[name]-6bcd4b20914d76c9.js +1 -0
- sky/dashboard/out/_next/static/chunks/pages/workspaces-5f7fe4b7d55b8612.js +1 -0
- sky/dashboard/out/_next/static/chunks/webpack-a305898dc479711e.js +1 -0
- sky/dashboard/out/_next/static/css/b3227360726f12eb.css +3 -0
- sky/dashboard/out/_next/static/mym3Ciwp-zqU7ZpOLGnrW/_buildManifest.js +1 -0
- 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.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/data/mounting_utils.py +93 -32
- sky/global_user_state.py +2 -3
- sky/jobs/state.py +2 -2
- sky/provision/nebius/utils.py +3 -6
- sky/server/common.py +4 -3
- sky/setup_files/MANIFEST.in +1 -1
- sky/setup_files/alembic.ini +0 -4
- sky/skylet/constants.py +4 -0
- sky/skypilot_config.py +5 -31
- sky/utils/common_utils.py +8 -3
- sky/utils/config_utils.py +15 -0
- sky/utils/db/migration_utils.py +44 -4
- sky/utils/locks.py +319 -0
- sky/utils/schemas.py +38 -34
- sky/utils/timeline.py +41 -0
- {skypilot_nightly-1.0.0.dev20250720.dist-info → skypilot_nightly-1.0.0.dev20250723.dist-info}/METADATA +1 -1
- {skypilot_nightly-1.0.0.dev20250720.dist-info → skypilot_nightly-1.0.0.dev20250723.dist-info}/RECORD +78 -78
- sky/dashboard/out/_next/static/chunks/1746.27d40aedc22bd2d6.js +0 -60
- sky/dashboard/out/_next/static/chunks/2544.27f70672535675ed.js +0 -1
- sky/dashboard/out/_next/static/chunks/2875.c24c6d57dc82e436.js +0 -25
- sky/dashboard/out/_next/static/chunks/3785.95b94f18aaec7233.js +0 -1
- sky/dashboard/out/_next/static/chunks/3947-b059261d6fa88a1f.js +0 -35
- sky/dashboard/out/_next/static/chunks/430.ed51037d1a4a438b.js +0 -1
- sky/dashboard/out/_next/static/chunks/4869.c7c055a5c2814f33.js +0 -16
- sky/dashboard/out/_next/static/chunks/5491.918ffed0ba7a5294.js +0 -20
- sky/dashboard/out/_next/static/chunks/6990-dcb411b566e64cde.js +0 -1
- sky/dashboard/out/_next/static/chunks/804-9f5e98ce84d46bdd.js +0 -21
- sky/dashboard/out/_next/static/chunks/9025.133e9ba5c780afeb.js +0 -6
- sky/dashboard/out/_next/static/chunks/9470-8178183f3bae198f.js +0 -1
- sky/dashboard/out/_next/static/chunks/9847.46e613d000c55859.js +0 -30
- sky/dashboard/out/_next/static/chunks/pages/_app-507712f30cd3cec3.js +0 -20
- sky/dashboard/out/_next/static/chunks/pages/clusters-102d169e87913ba1.js +0 -1
- sky/dashboard/out/_next/static/chunks/pages/index-927ddeebe57a8ac3.js +0 -1
- sky/dashboard/out/_next/static/chunks/pages/infra/[context]-8b0809f59034d509.js +0 -1
- sky/dashboard/out/_next/static/chunks/pages/infra-ae9d2f705ce582c9.js +0 -1
- sky/dashboard/out/_next/static/chunks/pages/jobs-5bbdc71878f0a068.js +0 -1
- sky/dashboard/out/_next/static/chunks/pages/workspaces/[name]-7c0187f43757a548.js +0 -1
- sky/dashboard/out/_next/static/chunks/pages/workspaces-a1e43d9ef51a9cea.js +0 -1
- sky/dashboard/out/_next/static/chunks/webpack-26cdc782eed15a7d.js +0 -1
- sky/dashboard/out/_next/static/css/5122cb0a08486fd3.css +0 -3
- sky/dashboard/out/_next/static/pTQKG61ng32Zc7gsAROFJ/_buildManifest.js +0 -1
- sky/schemas/db/skypilot_config/001_initial_schema.py +0 -30
- /sky/dashboard/out/_next/static/{pTQKG61ng32Zc7gsAROFJ → mym3Ciwp-zqU7ZpOLGnrW}/_ssgManifest.js +0 -0
- {skypilot_nightly-1.0.0.dev20250720.dist-info → skypilot_nightly-1.0.0.dev20250723.dist-info}/WHEEL +0 -0
- {skypilot_nightly-1.0.0.dev20250720.dist-info → skypilot_nightly-1.0.0.dev20250723.dist-info}/entry_points.txt +0 -0
- {skypilot_nightly-1.0.0.dev20250720.dist-info → skypilot_nightly-1.0.0.dev20250723.dist-info}/licenses/LICENSE +0 -0
- {skypilot_nightly-1.0.0.dev20250720.dist-info → skypilot_nightly-1.0.0.dev20250723.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/
|
|
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/b3227360726f12eb.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/b3227360726f12eb.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-a305898dc479711e.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-da491665d4289aae.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/workspaces-5f7fe4b7d55b8612.js" defer=""></script><script src="/dashboard/_next/static/mym3Ciwp-zqU7ZpOLGnrW/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/mym3Ciwp-zqU7ZpOLGnrW/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/workspaces","query":{},"buildId":"mym3Ciwp-zqU7ZpOLGnrW","assetPrefix":"/dashboard","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
|
sky/data/mounting_utils.py
CHANGED
|
@@ -39,19 +39,32 @@ _GOOFYS_WRAPPER = ('$(if [ -S /dev/log ] ; then '
|
|
|
39
39
|
|
|
40
40
|
|
|
41
41
|
def get_s3_mount_install_cmd() -> str:
|
|
42
|
-
"""Returns
|
|
42
|
+
"""Returns command for basic S3 mounting (goofys by default, rclone for
|
|
43
|
+
ARM64)."""
|
|
43
44
|
# TODO(aylei): maintain our goofys fork under skypilot-org
|
|
44
|
-
install_cmd = (
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
45
|
+
install_cmd = (
|
|
46
|
+
'ARCH=$(uname -m) && '
|
|
47
|
+
'if [ "$ARCH" = "aarch64" ] || [ "$ARCH" = "arm64" ]; then '
|
|
48
|
+
# Use rclone for ARM64 since goofys doesn't support it
|
|
49
|
+
# Extract core rclone installation logic without redundant ARCH check
|
|
50
|
+
' ARCH_SUFFIX="arm" && '
|
|
51
|
+
f' (which dpkg > /dev/null 2>&1 && (which rclone > /dev/null || '
|
|
52
|
+
f'(cd ~ > /dev/null && curl -O https://downloads.rclone.org/'
|
|
53
|
+
f'{RCLONE_VERSION}/rclone-{RCLONE_VERSION}-linux-${{ARCH_SUFFIX}}.deb '
|
|
54
|
+
f'&& sudo dpkg -i rclone-{RCLONE_VERSION}-linux-${{ARCH_SUFFIX}}.deb '
|
|
55
|
+
f'&& rm -f rclone-{RCLONE_VERSION}-linux-${{ARCH_SUFFIX}}.deb))) || '
|
|
56
|
+
f'(which rclone > /dev/null || (cd ~ > /dev/null && curl -O '
|
|
57
|
+
f'https://downloads.rclone.org/{RCLONE_VERSION}/'
|
|
58
|
+
f'rclone-{RCLONE_VERSION}-linux-${{ARCH_SUFFIX}}.rpm && '
|
|
59
|
+
f'sudo yum --nogpgcheck install '
|
|
60
|
+
f'rclone-{RCLONE_VERSION}-linux-${{ARCH_SUFFIX}}.rpm -y && '
|
|
61
|
+
f'rm -f rclone-{RCLONE_VERSION}-linux-${{ARCH_SUFFIX}}.rpm)); '
|
|
62
|
+
'else '
|
|
63
|
+
' sudo wget -nc https://github.com/aylei/goofys/'
|
|
64
|
+
'releases/download/0.24.0-aylei-upstream/goofys '
|
|
65
|
+
'-O /usr/local/bin/goofys && '
|
|
66
|
+
'sudo chmod 755 /usr/local/bin/goofys; '
|
|
67
|
+
'fi')
|
|
55
68
|
return install_cmd
|
|
56
69
|
|
|
57
70
|
|
|
@@ -59,15 +72,30 @@ def get_s3_mount_install_cmd() -> str:
|
|
|
59
72
|
def get_s3_mount_cmd(bucket_name: str,
|
|
60
73
|
mount_path: str,
|
|
61
74
|
_bucket_sub_path: Optional[str] = None) -> str:
|
|
62
|
-
"""Returns a command to mount an S3 bucket
|
|
75
|
+
"""Returns a command to mount an S3 bucket (goofys by default, rclone for
|
|
76
|
+
ARM64)"""
|
|
63
77
|
if _bucket_sub_path is None:
|
|
64
78
|
_bucket_sub_path = ''
|
|
65
79
|
else:
|
|
66
80
|
_bucket_sub_path = f':{_bucket_sub_path}'
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
81
|
+
|
|
82
|
+
# Use rclone for ARM64 architectures since goofys doesn't support them
|
|
83
|
+
arch_check = 'ARCH=$(uname -m) && '
|
|
84
|
+
rclone_mount = (
|
|
85
|
+
f'{FUSERMOUNT3_SOFT_LINK_CMD} && '
|
|
86
|
+
f'rclone mount :s3:{bucket_name}{_bucket_sub_path} {mount_path} '
|
|
87
|
+
'--daemon --allow-other')
|
|
88
|
+
goofys_mount = (f'{_GOOFYS_WRAPPER} -o allow_other '
|
|
89
|
+
f'--stat-cache-ttl {_STAT_CACHE_TTL} '
|
|
90
|
+
f'--type-cache-ttl {_TYPE_CACHE_TTL} '
|
|
91
|
+
f'{bucket_name}{_bucket_sub_path} {mount_path}')
|
|
92
|
+
|
|
93
|
+
mount_cmd = (f'{arch_check}'
|
|
94
|
+
f'if [ "$ARCH" = "aarch64" ] || [ "$ARCH" = "arm64" ]; then '
|
|
95
|
+
f' {rclone_mount}; '
|
|
96
|
+
f'else '
|
|
97
|
+
f' {goofys_mount}; '
|
|
98
|
+
f'fi')
|
|
71
99
|
return mount_cmd
|
|
72
100
|
|
|
73
101
|
|
|
@@ -76,17 +104,33 @@ def get_nebius_mount_cmd(nebius_profile_name: str,
|
|
|
76
104
|
endpoint_url: str,
|
|
77
105
|
mount_path: str,
|
|
78
106
|
_bucket_sub_path: Optional[str] = None) -> str:
|
|
79
|
-
"""Returns a command to
|
|
107
|
+
"""Returns a command to mount Nebius bucket (goofys by default, rclone for
|
|
108
|
+
ARM64)."""
|
|
80
109
|
if _bucket_sub_path is None:
|
|
81
110
|
_bucket_sub_path = ''
|
|
82
111
|
else:
|
|
83
112
|
_bucket_sub_path = f':{_bucket_sub_path}'
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
113
|
+
|
|
114
|
+
# Use rclone for ARM64 architectures since goofys doesn't support them
|
|
115
|
+
arch_check = 'ARCH=$(uname -m) && '
|
|
116
|
+
rclone_mount = (
|
|
117
|
+
f'{FUSERMOUNT3_SOFT_LINK_CMD} && '
|
|
118
|
+
f'AWS_PROFILE={nebius_profile_name} '
|
|
119
|
+
f'rclone mount :s3:{bucket_name}{_bucket_sub_path} {mount_path} '
|
|
120
|
+
f'--s3-endpoint {endpoint_url} --daemon --allow-other')
|
|
121
|
+
goofys_mount = (f'AWS_PROFILE={nebius_profile_name} {_GOOFYS_WRAPPER} '
|
|
122
|
+
'-o allow_other '
|
|
123
|
+
f'--stat-cache-ttl {_STAT_CACHE_TTL} '
|
|
124
|
+
f'--type-cache-ttl {_TYPE_CACHE_TTL} '
|
|
125
|
+
f'--endpoint {endpoint_url} '
|
|
126
|
+
f'{bucket_name}{_bucket_sub_path} {mount_path}')
|
|
127
|
+
|
|
128
|
+
mount_cmd = (f'{arch_check}'
|
|
129
|
+
f'if [ "$ARCH" = "aarch64" ] || [ "$ARCH" = "arm64" ]; then '
|
|
130
|
+
f' {rclone_mount}; '
|
|
131
|
+
f'else '
|
|
132
|
+
f' {goofys_mount}; '
|
|
133
|
+
f'fi')
|
|
90
134
|
return mount_cmd
|
|
91
135
|
|
|
92
136
|
|
|
@@ -236,18 +280,35 @@ def get_r2_mount_cmd(r2_credentials_path: str,
|
|
|
236
280
|
bucket_name: str,
|
|
237
281
|
mount_path: str,
|
|
238
282
|
_bucket_sub_path: Optional[str] = None) -> str:
|
|
239
|
-
"""Returns a command to
|
|
283
|
+
"""Returns a command to mount R2 bucket (goofys by default, rclone for
|
|
284
|
+
ARM64)."""
|
|
240
285
|
if _bucket_sub_path is None:
|
|
241
286
|
_bucket_sub_path = ''
|
|
242
287
|
else:
|
|
243
288
|
_bucket_sub_path = f':{_bucket_sub_path}'
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
289
|
+
|
|
290
|
+
# Use rclone for ARM64 architectures since goofys doesn't support them
|
|
291
|
+
arch_check = 'ARCH=$(uname -m) && '
|
|
292
|
+
rclone_mount = (
|
|
293
|
+
f'{FUSERMOUNT3_SOFT_LINK_CMD} && '
|
|
294
|
+
f'AWS_SHARED_CREDENTIALS_FILE={r2_credentials_path} '
|
|
295
|
+
f'AWS_PROFILE={r2_profile_name} '
|
|
296
|
+
f'rclone mount :s3:{bucket_name}{_bucket_sub_path} {mount_path} '
|
|
297
|
+
f'--s3-endpoint {endpoint_url} --daemon --allow-other')
|
|
298
|
+
goofys_mount = (f'AWS_SHARED_CREDENTIALS_FILE={r2_credentials_path} '
|
|
299
|
+
f'AWS_PROFILE={r2_profile_name} {_GOOFYS_WRAPPER} '
|
|
300
|
+
'-o allow_other '
|
|
301
|
+
f'--stat-cache-ttl {_STAT_CACHE_TTL} '
|
|
302
|
+
f'--type-cache-ttl {_TYPE_CACHE_TTL} '
|
|
303
|
+
f'--endpoint {endpoint_url} '
|
|
304
|
+
f'{bucket_name}{_bucket_sub_path} {mount_path}')
|
|
305
|
+
|
|
306
|
+
mount_cmd = (f'{arch_check}'
|
|
307
|
+
f'if [ "$ARCH" = "aarch64" ] || [ "$ARCH" = "arm64" ]; then '
|
|
308
|
+
f' {rclone_mount}; '
|
|
309
|
+
f'else '
|
|
310
|
+
f' {goofys_mount}; '
|
|
311
|
+
f'fi')
|
|
251
312
|
return mount_cmd
|
|
252
313
|
|
|
253
314
|
|
sky/global_user_state.py
CHANGED
|
@@ -17,7 +17,6 @@ import typing
|
|
|
17
17
|
from typing import Any, Dict, List, Optional, Set, Tuple
|
|
18
18
|
import uuid
|
|
19
19
|
|
|
20
|
-
from alembic import command as alembic_command
|
|
21
20
|
import sqlalchemy
|
|
22
21
|
from sqlalchemy import exc as sqlalchemy_exc
|
|
23
22
|
from sqlalchemy import orm
|
|
@@ -243,8 +242,8 @@ def create_table(engine: sqlalchemy.engine.Engine):
|
|
|
243
242
|
engine, migration_utils.GLOBAL_USER_STATE_DB_NAME)
|
|
244
243
|
# pylint: disable=line-too-long
|
|
245
244
|
alembic_config.config_ini_section = migration_utils.GLOBAL_USER_STATE_DB_NAME
|
|
246
|
-
|
|
247
|
-
|
|
245
|
+
migration_utils.safe_alembic_upgrade(
|
|
246
|
+
engine, alembic_config, migration_utils.GLOBAL_USER_STATE_VERSION)
|
|
248
247
|
|
|
249
248
|
|
|
250
249
|
def initialize_and_get_db() -> sqlalchemy.engine.Engine:
|
sky/jobs/state.py
CHANGED
|
@@ -10,7 +10,6 @@ import time
|
|
|
10
10
|
import typing
|
|
11
11
|
from typing import Any, Callable, Dict, List, Optional, Tuple, Union
|
|
12
12
|
|
|
13
|
-
from alembic import command as alembic_command
|
|
14
13
|
import colorama
|
|
15
14
|
import sqlalchemy
|
|
16
15
|
from sqlalchemy import exc as sqlalchemy_exc
|
|
@@ -134,7 +133,8 @@ def create_table(engine: sqlalchemy.engine.Engine):
|
|
|
134
133
|
alembic_config = migration_utils.get_alembic_config(
|
|
135
134
|
engine, migration_utils.SPOT_JOBS_DB_NAME)
|
|
136
135
|
alembic_config.config_ini_section = migration_utils.SPOT_JOBS_DB_NAME
|
|
137
|
-
|
|
136
|
+
migration_utils.safe_alembic_upgrade(engine, alembic_config,
|
|
137
|
+
migration_utils.SPOT_JOBS_VERSION)
|
|
138
138
|
|
|
139
139
|
|
|
140
140
|
def initialize_and_get_db() -> sqlalchemy.engine.Engine:
|
sky/provision/nebius/utils.py
CHANGED
|
@@ -41,10 +41,7 @@ def get_project_by_region(region: str) -> str:
|
|
|
41
41
|
|
|
42
42
|
# Check is there project if in config
|
|
43
43
|
project_id = skypilot_config.get_effective_region_config(
|
|
44
|
-
cloud='nebius',
|
|
45
|
-
region=None,
|
|
46
|
-
keys=(region, 'project_id'),
|
|
47
|
-
default_value=None)
|
|
44
|
+
cloud='nebius', region=region, keys=('project_id',), default_value=None)
|
|
48
45
|
if project_id is not None:
|
|
49
46
|
return project_id
|
|
50
47
|
for project in projects.items:
|
|
@@ -189,8 +186,8 @@ def launch(cluster_name_on_cloud: str,
|
|
|
189
186
|
if preset == '8gpu-128vcpu-1600gb':
|
|
190
187
|
fabric = skypilot_config.get_effective_region_config(
|
|
191
188
|
cloud='nebius',
|
|
192
|
-
region=
|
|
193
|
-
keys=(
|
|
189
|
+
region=region,
|
|
190
|
+
keys=('fabric',),
|
|
194
191
|
default_value=None)
|
|
195
192
|
|
|
196
193
|
# Auto-select fabric if network_tier=best and no fabric configured
|
sky/server/common.py
CHANGED
|
@@ -252,8 +252,9 @@ def get_dashboard_url(server_url: str,
|
|
|
252
252
|
|
|
253
253
|
|
|
254
254
|
@annotations.lru_cache(scope='global')
|
|
255
|
-
def is_api_server_local():
|
|
256
|
-
|
|
255
|
+
def is_api_server_local(endpoint: Optional[str] = None):
|
|
256
|
+
server_url = endpoint if endpoint is not None else get_server_url()
|
|
257
|
+
return server_url in AVAILABLE_LOCAL_API_SERVER_URLS
|
|
257
258
|
|
|
258
259
|
|
|
259
260
|
def _handle_non_200_server_status(
|
|
@@ -566,7 +567,7 @@ def check_server_healthy(
|
|
|
566
567
|
api_server_status = api_server_info.status
|
|
567
568
|
if api_server_status == ApiServerStatus.VERSION_MISMATCH:
|
|
568
569
|
msg = api_server_info.error
|
|
569
|
-
if is_api_server_local():
|
|
570
|
+
if is_api_server_local(endpoint):
|
|
570
571
|
# For local server, just hint user to restart the server to get
|
|
571
572
|
# a consistent version.
|
|
572
573
|
msg = _LOCAL_API_SERVER_RESTART_HINT
|
sky/setup_files/MANIFEST.in
CHANGED
sky/setup_files/alembic.ini
CHANGED
|
@@ -94,10 +94,6 @@ version_table = alembic_version_state_db
|
|
|
94
94
|
version_locations = %(here)s/../schemas/db/spot_jobs
|
|
95
95
|
version_table = alembic_version_spot_jobs_db
|
|
96
96
|
|
|
97
|
-
[sky_config_db]
|
|
98
|
-
version_locations = %(here)s/../schemas/db/skypilot_config
|
|
99
|
-
version_table = alembic_version_sky_config_db
|
|
100
|
-
|
|
101
97
|
[post_write_hooks]
|
|
102
98
|
# post_write_hooks defines scripts or Python functions that are run
|
|
103
99
|
# on newly generated revision scripts. See the documentation for further
|
sky/skylet/constants.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"""Constants for SkyPilot."""
|
|
2
|
+
import os
|
|
2
3
|
from typing import List, Tuple
|
|
3
4
|
|
|
4
5
|
from packaging import version
|
|
@@ -491,3 +492,6 @@ DEFAULT_PRIORITY = 0
|
|
|
491
492
|
|
|
492
493
|
GRACE_PERIOD_SECONDS_ENV_VAR = SKYPILOT_ENV_VAR_PREFIX + 'GRACE_PERIOD_SECONDS'
|
|
493
494
|
COST_REPORT_DEFAULT_DAYS = 30
|
|
495
|
+
|
|
496
|
+
# The directory for file locks.
|
|
497
|
+
SKY_LOCKS_DIR = os.path.expanduser('~/.sky/locks')
|
sky/skypilot_config.py
CHANGED
|
@@ -58,10 +58,8 @@ import threading
|
|
|
58
58
|
import typing
|
|
59
59
|
from typing import Any, Dict, Iterator, List, Optional, Tuple, Union
|
|
60
60
|
|
|
61
|
-
from alembic import command as alembic_command
|
|
62
61
|
import filelock
|
|
63
62
|
import sqlalchemy
|
|
64
|
-
from sqlalchemy import exc as sqlalchemy_exc
|
|
65
63
|
from sqlalchemy import orm
|
|
66
64
|
from sqlalchemy.dialects import postgresql
|
|
67
65
|
from sqlalchemy.dialects import sqlite
|
|
@@ -78,7 +76,6 @@ from sky.utils import context
|
|
|
78
76
|
from sky.utils import schemas
|
|
79
77
|
from sky.utils import ux_utils
|
|
80
78
|
from sky.utils.db import db_utils
|
|
81
|
-
from sky.utils.db import migration_utils
|
|
82
79
|
from sky.utils.kubernetes import config_map_utils
|
|
83
80
|
|
|
84
81
|
if typing.TYPE_CHECKING:
|
|
@@ -574,17 +571,11 @@ def _reload_config_as_server() -> None:
|
|
|
574
571
|
'if db config is specified, no other config is allowed')
|
|
575
572
|
|
|
576
573
|
if db_url:
|
|
577
|
-
with
|
|
574
|
+
with _DB_USE_LOCK:
|
|
578
575
|
sqlalchemy_engine = sqlalchemy.create_engine(db_url,
|
|
579
576
|
poolclass=NullPool)
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
alembic_config = migration_utils.get_alembic_config(
|
|
583
|
-
sqlalchemy_engine, migration_utils.SKYPILOT_CONFIG_DB_NAME)
|
|
584
|
-
# pylint: disable=line-too-long
|
|
585
|
-
alembic_config.config_ini_section = migration_utils.SKYPILOT_CONFIG_DB_NAME
|
|
586
|
-
alembic_command.upgrade(alembic_config,
|
|
587
|
-
migration_utils.SKYPILOT_CONFIG_VERSION)
|
|
577
|
+
db_utils.add_tables_to_db_sqlalchemy(Base.metadata,
|
|
578
|
+
sqlalchemy_engine)
|
|
588
579
|
|
|
589
580
|
def _get_config_yaml_from_db(
|
|
590
581
|
key: str) -> Optional[config_utils.Config]:
|
|
@@ -872,25 +863,8 @@ def update_api_server_config_no_lock(config: config_utils.Config) -> None:
|
|
|
872
863
|
with _DB_USE_LOCK:
|
|
873
864
|
sqlalchemy_engine = sqlalchemy.create_engine(existing_db_url,
|
|
874
865
|
poolclass=NullPool)
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
alembic_config = migration_utils.get_alembic_config(
|
|
878
|
-
sqlalchemy_engine, 'sky_config_db')
|
|
879
|
-
alembic_config.config_ini_section = 'sky_config_db'
|
|
880
|
-
try:
|
|
881
|
-
alembic_command.upgrade(alembic_config, '001')
|
|
882
|
-
except (sqlalchemy_exc.IntegrityError,
|
|
883
|
-
sqlalchemy_exc.OperationalError) as e:
|
|
884
|
-
# If the version already exists (due to concurrent
|
|
885
|
-
# initialization), we can safely ignore this error
|
|
886
|
-
if ('UNIQUE constraint failed: '
|
|
887
|
-
'alembic_version_sky_config_db.version_num'
|
|
888
|
-
in str(e) or
|
|
889
|
-
'table alembic_version_sky_config_db already exists'
|
|
890
|
-
in str(e)):
|
|
891
|
-
pass
|
|
892
|
-
else:
|
|
893
|
-
raise
|
|
866
|
+
db_utils.add_tables_to_db_sqlalchemy(Base.metadata,
|
|
867
|
+
sqlalchemy_engine)
|
|
894
868
|
|
|
895
869
|
def _set_config_yaml_to_db(key: str,
|
|
896
870
|
config: config_utils.Config):
|
sky/utils/common_utils.py
CHANGED
|
@@ -562,8 +562,9 @@ def read_yaml_all(path: str) -> List[Dict[str, Any]]:
|
|
|
562
562
|
return read_yaml_all_str(f.read())
|
|
563
563
|
|
|
564
564
|
|
|
565
|
-
def dump_yaml(path: str,
|
|
566
|
-
|
|
565
|
+
def dump_yaml(path: str,
|
|
566
|
+
config: Union[List[Dict[str, Any]], Dict[str, Any]],
|
|
567
|
+
blank: bool = False) -> None:
|
|
567
568
|
"""Dumps a YAML file.
|
|
568
569
|
|
|
569
570
|
Args:
|
|
@@ -571,7 +572,11 @@ def dump_yaml(path: str, config: Union[List[Dict[str, Any]],
|
|
|
571
572
|
config: the configuration to dump.
|
|
572
573
|
"""
|
|
573
574
|
with open(path, 'w', encoding='utf-8') as f:
|
|
574
|
-
|
|
575
|
+
contents = dump_yaml_str(config)
|
|
576
|
+
if blank and isinstance(config, dict) and len(config) == 0:
|
|
577
|
+
# when dumping to yaml, an empty dict will go in as {}.
|
|
578
|
+
contents = ''
|
|
579
|
+
f.write(contents)
|
|
575
580
|
|
|
576
581
|
|
|
577
582
|
def dump_yaml_str(config: Union[List[Dict[str, Any]], Dict[str, Any]]) -> str:
|
sky/utils/config_utils.py
CHANGED
|
@@ -248,6 +248,8 @@ def get_cloud_config_value_from_dict(
|
|
|
248
248
|
region_key = None
|
|
249
249
|
if cloud == 'kubernetes':
|
|
250
250
|
region_key = 'context_configs'
|
|
251
|
+
if cloud == 'nebius':
|
|
252
|
+
region_key = 'region_configs'
|
|
251
253
|
|
|
252
254
|
per_context_config = None
|
|
253
255
|
if region is not None and region_key is not None:
|
|
@@ -255,6 +257,19 @@ def get_cloud_config_value_from_dict(
|
|
|
255
257
|
keys=(cloud, region_key, region) + keys,
|
|
256
258
|
default_value=None,
|
|
257
259
|
override_configs=override_configs)
|
|
260
|
+
if not per_context_config and cloud == 'nebius':
|
|
261
|
+
# TODO (kyuds): Backward compatibility, remove after 0.11.0.
|
|
262
|
+
per_context_config = input_config.get_nested(
|
|
263
|
+
keys=(cloud, region) + keys,
|
|
264
|
+
default_value=None,
|
|
265
|
+
override_configs=override_configs)
|
|
266
|
+
if per_context_config is not None:
|
|
267
|
+
logger.info(
|
|
268
|
+
'Nebius configuration is using the legacy format. \n'
|
|
269
|
+
'This format will be deprecated after 0.11.0, refer to '
|
|
270
|
+
'`https://docs.skypilot.co/en/latest/reference/config.html#nebius` ' # pylint: disable=line-too-long
|
|
271
|
+
'for the new format. Please use `region_configs` to specify region specific configuration.'
|
|
272
|
+
)
|
|
258
273
|
# if no override found for specified region
|
|
259
274
|
general_config = input_config.get_nested(keys=(cloud,) + keys,
|
|
260
275
|
default_value=default_value,
|
sky/utils/db/migration_utils.py
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
"""Constants for the database schemas."""
|
|
2
2
|
|
|
3
3
|
import contextlib
|
|
4
|
+
import logging
|
|
4
5
|
import os
|
|
5
6
|
|
|
7
|
+
from alembic import command as alembic_command
|
|
6
8
|
from alembic.config import Config
|
|
9
|
+
from alembic.runtime import migration
|
|
7
10
|
import filelock
|
|
8
11
|
import sqlalchemy
|
|
9
12
|
|
|
@@ -13,10 +16,6 @@ GLOBAL_USER_STATE_DB_NAME = 'state_db'
|
|
|
13
16
|
GLOBAL_USER_STATE_VERSION = '001'
|
|
14
17
|
GLOBAL_USER_STATE_LOCK_PATH = '~/.sky/locks/.state_db.lock'
|
|
15
18
|
|
|
16
|
-
SKYPILOT_CONFIG_DB_NAME = 'skypilot_config_db'
|
|
17
|
-
SKYPILOT_CONFIG_VERSION = '001'
|
|
18
|
-
SKYPILOT_CONFIG_LOCK_PATH = '~/.sky/locks/.skypilot_config_db.lock'
|
|
19
|
-
|
|
20
19
|
SPOT_JOBS_DB_NAME = 'spot_jobs_db'
|
|
21
20
|
SPOT_JOBS_VERSION = '001'
|
|
22
21
|
SPOT_JOBS_LOCK_PATH = '~/.sky/locks/.spot_jobs_db.lock'
|
|
@@ -51,3 +50,44 @@ def get_alembic_config(engine: sqlalchemy.engine.Engine, section: str):
|
|
|
51
50
|
alembic_cfg.set_section_option(section, 'sqlalchemy.url', url)
|
|
52
51
|
|
|
53
52
|
return alembic_cfg
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def safe_alembic_upgrade(engine: sqlalchemy.engine.Engine,
|
|
56
|
+
alembic_config: Config, target_revision: str):
|
|
57
|
+
"""Only upgrade if current version is older than target.
|
|
58
|
+
|
|
59
|
+
This handles the case where a database was created with a newer version of
|
|
60
|
+
the code and we're now running older code. Since our migrations are purely
|
|
61
|
+
additive, it's safe to run a newer database with older code.
|
|
62
|
+
|
|
63
|
+
Args:
|
|
64
|
+
engine: SQLAlchemy engine for the database
|
|
65
|
+
alembic_config: Alembic configuration object
|
|
66
|
+
target_revision: Target revision to upgrade to (e.g., '001')
|
|
67
|
+
"""
|
|
68
|
+
# set alembic logger to warning level
|
|
69
|
+
alembic_logger = logging.getLogger('alembic')
|
|
70
|
+
alembic_logger.setLevel(logging.WARNING)
|
|
71
|
+
|
|
72
|
+
current_rev = None
|
|
73
|
+
|
|
74
|
+
# Get the current revision from the database
|
|
75
|
+
version_table = alembic_config.get_section_option(
|
|
76
|
+
alembic_config.config_ini_section, 'version_table', 'alembic_version')
|
|
77
|
+
|
|
78
|
+
with engine.connect() as connection:
|
|
79
|
+
context = migration.MigrationContext.configure(
|
|
80
|
+
connection, opts={'version_table': version_table})
|
|
81
|
+
current_rev = context.get_current_revision()
|
|
82
|
+
|
|
83
|
+
if current_rev is None:
|
|
84
|
+
alembic_command.upgrade(alembic_config, target_revision)
|
|
85
|
+
return
|
|
86
|
+
|
|
87
|
+
# Compare revisions - assuming they are numeric strings like '001', '002'
|
|
88
|
+
current_rev_num = int(current_rev)
|
|
89
|
+
target_rev_num = int(target_revision)
|
|
90
|
+
|
|
91
|
+
# only upgrade if current revision is older than target revision
|
|
92
|
+
if current_rev_num < target_rev_num:
|
|
93
|
+
alembic_command.upgrade(alembic_config, target_revision)
|