skypilot-nightly 1.0.0.dev20250527__py3-none-any.whl → 1.0.0.dev20250529__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.
- sky/__init__.py +2 -2
- sky/adaptors/kubernetes.py +13 -1
- sky/backends/cloud_vm_ray_backend.py +2 -2
- sky/check.py +4 -1
- sky/cli.py +13 -3
- sky/client/cli.py +13 -3
- sky/client/oauth.py +82 -0
- sky/client/sdk.py +60 -10
- sky/clouds/kubernetes.py +2 -2
- sky/clouds/service_catalog/data_fetchers/fetch_gcp.py +3 -3
- sky/dashboard/out/404.html +1 -1
- sky/dashboard/out/_next/static/HvNkg7hqKM1p0ptAcdDcF/_buildManifest.js +1 -0
- sky/dashboard/out/_next/static/chunks/121-8f55ee3fa6301784.js +20 -0
- sky/dashboard/out/_next/static/chunks/{573-82bd40a37af834f1.js → 173-7db8607cefc20f70.js} +5 -5
- sky/dashboard/out/_next/static/chunks/236-90e5498a5b00ec29.js +6 -0
- sky/dashboard/out/_next/static/chunks/293-351268365226d251.js +1 -0
- sky/dashboard/out/_next/static/chunks/303-2c7b0f7af571710b.js +6 -0
- sky/dashboard/out/_next/static/chunks/470-4d003c441839094d.js +1 -0
- sky/dashboard/out/_next/static/chunks/578-9146658cead92981.js +6 -0
- sky/dashboard/out/_next/static/chunks/843-256ec920f6d5f41f.js +11 -0
- sky/dashboard/out/_next/static/chunks/856-59a1760784c9e770.js +1 -0
- sky/dashboard/out/_next/static/chunks/973-1a09cac61cfcc1e1.js +1 -0
- sky/dashboard/out/_next/static/chunks/pages/clusters/[cluster]/[job]-159bffb2fa34ed54.js +6 -0
- sky/dashboard/out/_next/static/chunks/pages/clusters/{[cluster]-e23fcddf60578a0d.js → [cluster]-9506c00257d10dbd.js} +1 -1
- sky/dashboard/out/_next/static/chunks/pages/{clusters-8afda8efa5b74997.js → clusters-943992b84fd6f4ee.js} +1 -1
- sky/dashboard/out/_next/static/chunks/pages/config-7c48919fe030bc43.js +6 -0
- sky/dashboard/out/_next/static/chunks/pages/infra/[context]-909f1ceb0fcf1b99.js +1 -0
- sky/dashboard/out/_next/static/chunks/pages/infra-d4c6875c88771e17.js +1 -0
- sky/dashboard/out/_next/static/chunks/pages/jobs/[job]-6b80e9e0c6aa16a1.js +6 -0
- sky/dashboard/out/_next/static/chunks/pages/{jobs-ff7e8e377d02b651.js → jobs-a4efc09e61988f8d.js} +1 -1
- sky/dashboard/out/_next/static/chunks/pages/users-b2634885d67c49a6.js +6 -0
- sky/dashboard/out/_next/static/chunks/pages/workspace/{new-63763ffa3edb4508.js → new-579b3203c7c19d84.js} +1 -1
- sky/dashboard/out/_next/static/chunks/pages/workspaces/{[name]-3ede7a13caf23375.js → [name]-9388e38fac73ee8f.js} +1 -1
- sky/dashboard/out/_next/static/chunks/pages/workspaces-610c49ae3619ee85.js +1 -0
- sky/dashboard/out/_next/static/css/ffd1cd601648c303.css +3 -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 -0
- 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/workspace/new.html +1 -1
- sky/dashboard/out/workspaces/[name].html +1 -1
- sky/dashboard/out/workspaces.html +1 -1
- sky/exceptions.py +1 -1
- sky/global_user_state.py +181 -134
- sky/jobs/client/sdk.py +1 -0
- sky/jobs/constants.py +2 -0
- sky/jobs/controller.py +3 -5
- sky/jobs/recovery_strategy.py +148 -102
- sky/jobs/scheduler.py +23 -8
- sky/jobs/server/core.py +16 -0
- sky/jobs/state.py +130 -35
- sky/jobs/utils.py +30 -4
- sky/provision/kubernetes/utils.py +4 -4
- sky/resources.py +16 -1
- sky/server/common.py +6 -2
- sky/server/html/token_page.html +32 -6
- sky/server/server.py +9 -6
- sky/setup_files/dependencies.py +8 -1
- sky/skylet/constants.py +5 -1
- sky/task.py +26 -0
- sky/templates/jobs-controller.yaml.j2 +2 -1
- sky/utils/db_utils.py +34 -46
- sky/utils/schemas.py +12 -0
- sky/utils/subprocess_utils.py +2 -3
- {skypilot_nightly-1.0.0.dev20250527.dist-info → skypilot_nightly-1.0.0.dev20250529.dist-info}/METADATA +4 -1
- {skypilot_nightly-1.0.0.dev20250527.dist-info → skypilot_nightly-1.0.0.dev20250529.dist-info}/RECORD +78 -73
- sky/dashboard/out/_next/static/D5bjIfl4Ob3SV3LJz3CO0/_buildManifest.js +0 -1
- sky/dashboard/out/_next/static/chunks/236-e220ba0c35bf089e.js +0 -6
- sky/dashboard/out/_next/static/chunks/470-1d784f5c8750744a.js +0 -1
- sky/dashboard/out/_next/static/chunks/488-50d843fdb5396d32.js +0 -15
- sky/dashboard/out/_next/static/chunks/578-24f35aa98d38d638.js +0 -6
- sky/dashboard/out/_next/static/chunks/627-31b701e69f52db0c.js +0 -1
- sky/dashboard/out/_next/static/chunks/843-e35d71cf1c7f706e.js +0 -11
- sky/dashboard/out/_next/static/chunks/990-f85643b521f7ca65.js +0 -1
- sky/dashboard/out/_next/static/chunks/pages/clusters/[cluster]/[job]-339b59921ccfe266.js +0 -1
- sky/dashboard/out/_next/static/chunks/pages/config-72b8c6c2edfd0e39.js +0 -6
- sky/dashboard/out/_next/static/chunks/pages/infra-1521baab6992916b.js +0 -1
- sky/dashboard/out/_next/static/chunks/pages/jobs/[job]-4d913940b4fa6f5a.js +0 -1
- sky/dashboard/out/_next/static/chunks/pages/users-9900af52acf8648d.js +0 -1
- sky/dashboard/out/_next/static/chunks/pages/workspaces-72330c4d0fc9a4a2.js +0 -1
- sky/dashboard/out/_next/static/css/6a1c0d711a4bdaf1.css +0 -3
- /sky/dashboard/out/_next/static/{D5bjIfl4Ob3SV3LJz3CO0 → HvNkg7hqKM1p0ptAcdDcF}/_ssgManifest.js +0 -0
- /sky/dashboard/out/_next/static/chunks/pages/{_app-3985f074c163a856.js → _app-a631df412d8172de.js} +0 -0
- {skypilot_nightly-1.0.0.dev20250527.dist-info → skypilot_nightly-1.0.0.dev20250529.dist-info}/WHEEL +0 -0
- {skypilot_nightly-1.0.0.dev20250527.dist-info → skypilot_nightly-1.0.0.dev20250529.dist-info}/entry_points.txt +0 -0
- {skypilot_nightly-1.0.0.dev20250527.dist-info → skypilot_nightly-1.0.0.dev20250529.dist-info}/licenses/LICENSE +0 -0
- {skypilot_nightly-1.0.0.dev20250527.dist-info → skypilot_nightly-1.0.0.dev20250529.dist-info}/top_level.txt +0 -0
sky/global_user_state.py
CHANGED
@@ -10,6 +10,7 @@ import json
|
|
10
10
|
import os
|
11
11
|
import pathlib
|
12
12
|
import pickle
|
13
|
+
import re
|
13
14
|
import time
|
14
15
|
import typing
|
15
16
|
from typing import Any, Dict, List, Optional, Set, Tuple
|
@@ -18,6 +19,7 @@ import uuid
|
|
18
19
|
import sqlalchemy
|
19
20
|
from sqlalchemy import exc as sqlalchemy_exc
|
20
21
|
from sqlalchemy import orm
|
22
|
+
from sqlalchemy.dialects import postgresql
|
21
23
|
from sqlalchemy.dialects import sqlite
|
22
24
|
from sqlalchemy.ext import declarative
|
23
25
|
|
@@ -43,7 +45,14 @@ _ENABLED_CLOUDS_KEY_PREFIX = 'enabled_clouds_'
|
|
43
45
|
_DB_PATH = os.path.expanduser('~/.sky/state.db')
|
44
46
|
pathlib.Path(_DB_PATH).parents[0].mkdir(parents=True, exist_ok=True)
|
45
47
|
|
46
|
-
|
48
|
+
if os.environ.get(constants.SKYPILOT_API_SERVER_DB_URL_ENV_VAR):
|
49
|
+
# If SKYPILOT_API_SERVER_DB_URL_ENV_VAR is set, use it as the database URI.
|
50
|
+
logger.debug(
|
51
|
+
f'using db URI from {constants.SKYPILOT_API_SERVER_DB_URL_ENV_VAR}')
|
52
|
+
_SQLALCHEMY_ENGINE = sqlalchemy.create_engine(
|
53
|
+
os.environ.get(constants.SKYPILOT_API_SERVER_DB_URL_ENV_VAR))
|
54
|
+
else:
|
55
|
+
_SQLALCHEMY_ENGINE = sqlalchemy.create_engine('sqlite:///' + _DB_PATH)
|
47
56
|
|
48
57
|
Base = declarative.declarative_base()
|
49
58
|
|
@@ -125,6 +134,26 @@ cluster_history_table = sqlalchemy.Table(
|
|
125
134
|
)
|
126
135
|
|
127
136
|
|
137
|
+
def _glob_to_similar(glob_pattern):
|
138
|
+
"""Converts a glob pattern to a PostgreSQL LIKE pattern."""
|
139
|
+
|
140
|
+
# Escape special LIKE characters that are not special in glob
|
141
|
+
glob_pattern = glob_pattern.replace('%', '\\%').replace('_', '\\_')
|
142
|
+
|
143
|
+
# Convert glob wildcards to LIKE wildcards
|
144
|
+
like_pattern = glob_pattern.replace('*', '%').replace('?', '_')
|
145
|
+
|
146
|
+
# Handle character classes, including negation
|
147
|
+
def replace_char_class(match):
|
148
|
+
group = match.group(0)
|
149
|
+
if group.startswith('[!'):
|
150
|
+
return '[^' + group[2:-1] + ']'
|
151
|
+
return group
|
152
|
+
|
153
|
+
like_pattern = re.sub(r'\[(!)?.*?\]', replace_char_class, like_pattern)
|
154
|
+
return like_pattern
|
155
|
+
|
156
|
+
|
128
157
|
def create_table():
|
129
158
|
# Enable WAL mode to avoid locking issues.
|
130
159
|
# See: issue #1441 and PR #1509
|
@@ -152,31 +181,52 @@ def create_table():
|
|
152
181
|
# the latest version of SkyPilot.
|
153
182
|
with orm.Session(_SQLALCHEMY_ENGINE) as session:
|
154
183
|
# Add autostop column to clusters table
|
155
|
-
db_utils.add_column_to_table_sqlalchemy(session,
|
156
|
-
'
|
184
|
+
db_utils.add_column_to_table_sqlalchemy(session,
|
185
|
+
'clusters',
|
186
|
+
'autostop',
|
187
|
+
sqlalchemy.Integer(),
|
188
|
+
default_statement='DEFAULT -1')
|
157
189
|
|
158
|
-
db_utils.add_column_to_table_sqlalchemy(
|
159
|
-
|
190
|
+
db_utils.add_column_to_table_sqlalchemy(
|
191
|
+
session,
|
192
|
+
'clusters',
|
193
|
+
'metadata',
|
194
|
+
sqlalchemy.Text(),
|
195
|
+
default_statement='DEFAULT \'{}\'')
|
160
196
|
|
161
|
-
db_utils.add_column_to_table_sqlalchemy(session,
|
162
|
-
'
|
197
|
+
db_utils.add_column_to_table_sqlalchemy(session,
|
198
|
+
'clusters',
|
199
|
+
'to_down',
|
200
|
+
sqlalchemy.Integer(),
|
201
|
+
default_statement='DEFAULT 0')
|
163
202
|
|
164
203
|
# The cloud identity that created the cluster.
|
165
|
-
db_utils.add_column_to_table_sqlalchemy(
|
166
|
-
|
204
|
+
db_utils.add_column_to_table_sqlalchemy(
|
205
|
+
session,
|
206
|
+
'clusters',
|
207
|
+
'owner',
|
208
|
+
sqlalchemy.Text(),
|
209
|
+
default_statement='DEFAULT NULL')
|
167
210
|
|
168
|
-
db_utils.add_column_to_table_sqlalchemy(
|
169
|
-
|
170
|
-
|
211
|
+
db_utils.add_column_to_table_sqlalchemy(
|
212
|
+
session,
|
213
|
+
'clusters',
|
214
|
+
'cluster_hash',
|
215
|
+
sqlalchemy.Text(),
|
216
|
+
default_statement='DEFAULT NULL')
|
171
217
|
|
172
|
-
db_utils.add_column_to_table_sqlalchemy(
|
173
|
-
|
174
|
-
|
218
|
+
db_utils.add_column_to_table_sqlalchemy(
|
219
|
+
session,
|
220
|
+
'clusters',
|
221
|
+
'storage_mounts_metadata',
|
222
|
+
sqlalchemy.LargeBinary(),
|
223
|
+
default_statement='DEFAULT NULL')
|
175
224
|
db_utils.add_column_to_table_sqlalchemy(
|
176
225
|
session,
|
177
226
|
'clusters',
|
178
227
|
'cluster_ever_up',
|
179
|
-
|
228
|
+
sqlalchemy.Integer(),
|
229
|
+
default_statement='DEFAULT 0',
|
180
230
|
# Set the value to 1 so that all the existing clusters before #2977
|
181
231
|
# are considered as ever up, i.e:
|
182
232
|
# existing cluster's default (null) -> 1;
|
@@ -185,28 +235,39 @@ def create_table():
|
|
185
235
|
# clusters were never really UP, setting it to 1 means they won't be
|
186
236
|
# auto-deleted during any failover.
|
187
237
|
value_to_replace_existing_entries=1)
|
188
|
-
db_utils.add_column_to_table_sqlalchemy(session, 'clusters',
|
189
|
-
'status_updated_at',
|
190
|
-
'INTEGER DEFAULT null')
|
191
238
|
db_utils.add_column_to_table_sqlalchemy(
|
192
239
|
session,
|
193
240
|
'clusters',
|
194
|
-
'
|
195
|
-
|
241
|
+
'status_updated_at',
|
242
|
+
sqlalchemy.Integer(),
|
243
|
+
default_statement='DEFAULT NULL')
|
244
|
+
db_utils.add_column_to_table_sqlalchemy(
|
245
|
+
session,
|
246
|
+
'clusters',
|
247
|
+
'user_hasha',
|
248
|
+
sqlalchemy.Text(),
|
249
|
+
default_statement='DEFAULT NULL',
|
196
250
|
value_to_replace_existing_entries=common_utils.get_user_hash())
|
197
|
-
db_utils.add_column_to_table_sqlalchemy(
|
198
|
-
|
199
|
-
|
251
|
+
db_utils.add_column_to_table_sqlalchemy(
|
252
|
+
session,
|
253
|
+
'clusters',
|
254
|
+
'config_hash',
|
255
|
+
sqlalchemy.Text(),
|
256
|
+
default_statement='DEFAULT NULL')
|
200
257
|
|
201
|
-
db_utils.add_column_to_table_sqlalchemy(
|
202
|
-
|
203
|
-
|
258
|
+
db_utils.add_column_to_table_sqlalchemy(
|
259
|
+
session,
|
260
|
+
'cluster_history',
|
261
|
+
'user_hash',
|
262
|
+
sqlalchemy.Text(),
|
263
|
+
default_statement='DEFAULT NULL')
|
204
264
|
|
205
265
|
db_utils.add_column_to_table_sqlalchemy(
|
206
266
|
session,
|
207
267
|
'clusters',
|
208
268
|
'workspace',
|
209
|
-
|
269
|
+
sqlalchemy.Text(),
|
270
|
+
default_statement='DEFAULT \'default\'',
|
210
271
|
value_to_replace_existing_entries=constants.
|
211
272
|
SKYPILOT_DEFAULT_WORKSPACE)
|
212
273
|
session.commit()
|
@@ -223,20 +284,18 @@ def add_or_update_user(user: models.User):
|
|
223
284
|
with orm.Session(_SQLALCHEMY_ENGINE) as session:
|
224
285
|
if (_SQLALCHEMY_ENGINE.dialect.name ==
|
225
286
|
db_utils.SQLAlchemyDialect.SQLITE.value):
|
226
|
-
|
227
|
-
name=user.name)
|
228
|
-
do_update_stmt = insert_stmnt.on_conflict_do_update(
|
229
|
-
index_elements=[user_table.c.id],
|
230
|
-
set_={user_table.c.name: user.name})
|
231
|
-
session.execute(do_update_stmt)
|
287
|
+
insert_func = sqlite.insert
|
232
288
|
elif (_SQLALCHEMY_ENGINE.dialect.name ==
|
233
289
|
db_utils.SQLAlchemyDialect.POSTGRESQL.value):
|
234
|
-
|
235
|
-
session.rollback()
|
236
|
-
raise ValueError('Unsupported database dialect')
|
290
|
+
insert_func = postgresql.insert
|
237
291
|
else:
|
238
|
-
session.rollback()
|
239
292
|
raise ValueError('Unsupported database dialect')
|
293
|
+
insert_stmnt = insert_func(user_table).values(id=user.id,
|
294
|
+
name=user.name)
|
295
|
+
do_update_stmt = insert_stmnt.on_conflict_do_update(
|
296
|
+
index_elements=[user_table.c.id],
|
297
|
+
set_={user_table.c.name: user.name})
|
298
|
+
session.execute(do_update_stmt)
|
240
299
|
session.commit()
|
241
300
|
|
242
301
|
|
@@ -348,76 +407,67 @@ def add_or_update_cluster(cluster_name: str,
|
|
348
407
|
|
349
408
|
if (_SQLALCHEMY_ENGINE.dialect.name ==
|
350
409
|
db_utils.SQLAlchemyDialect.SQLITE.value):
|
351
|
-
|
352
|
-
name=cluster_name,
|
353
|
-
**conditional_values,
|
354
|
-
handle=handle,
|
355
|
-
status=status.value,
|
356
|
-
# set metadata to server default ('{}')
|
357
|
-
# set owner to server default (null)
|
358
|
-
cluster_hash=cluster_hash,
|
359
|
-
# set storage_mounts_metadata to server default (null)
|
360
|
-
status_updated_at=status_updated_at,
|
361
|
-
)
|
362
|
-
do_update_stmt = insert_stmnt.on_conflict_do_update(
|
363
|
-
index_elements=[cluster_table.c.name],
|
364
|
-
set_={
|
365
|
-
**conditional_values,
|
366
|
-
cluster_table.c.handle: handle,
|
367
|
-
cluster_table.c.status: status.value,
|
368
|
-
# do not update metadata value
|
369
|
-
# do not update owner value
|
370
|
-
cluster_table.c.cluster_hash: cluster_hash,
|
371
|
-
# do not update storage_mounts_metadata
|
372
|
-
cluster_table.c.status_updated_at: status_updated_at,
|
373
|
-
# do not update user_hash
|
374
|
-
})
|
375
|
-
session.execute(do_update_stmt)
|
410
|
+
insert_func = sqlite.insert
|
376
411
|
elif (_SQLALCHEMY_ENGINE.dialect.name ==
|
377
412
|
db_utils.SQLAlchemyDialect.POSTGRESQL.value):
|
378
|
-
|
379
|
-
session.rollback()
|
380
|
-
raise ValueError('Unsupported database dialect')
|
413
|
+
insert_func = postgresql.insert
|
381
414
|
else:
|
382
415
|
session.rollback()
|
383
416
|
raise ValueError('Unsupported database dialect')
|
384
417
|
|
418
|
+
insert_stmnt = insert_func(cluster_table).values(
|
419
|
+
name=cluster_name,
|
420
|
+
**conditional_values,
|
421
|
+
handle=handle,
|
422
|
+
status=status.value,
|
423
|
+
# set metadata to server default ('{}')
|
424
|
+
# set owner to server default (null)
|
425
|
+
cluster_hash=cluster_hash,
|
426
|
+
# set storage_mounts_metadata to server default (null)
|
427
|
+
status_updated_at=status_updated_at,
|
428
|
+
)
|
429
|
+
do_update_stmt = insert_stmnt.on_conflict_do_update(
|
430
|
+
index_elements=[cluster_table.c.name],
|
431
|
+
set_={
|
432
|
+
**conditional_values,
|
433
|
+
cluster_table.c.handle: handle,
|
434
|
+
cluster_table.c.status: status.value,
|
435
|
+
# do not update metadata value
|
436
|
+
# do not update owner value
|
437
|
+
cluster_table.c.cluster_hash: cluster_hash,
|
438
|
+
# do not update storage_mounts_metadata
|
439
|
+
cluster_table.c.status_updated_at: status_updated_at,
|
440
|
+
# do not update user_hash
|
441
|
+
})
|
442
|
+
session.execute(do_update_stmt)
|
443
|
+
|
385
444
|
# Modify cluster history table
|
386
445
|
launched_nodes = getattr(cluster_handle, 'launched_nodes', None)
|
387
446
|
launched_resources = getattr(cluster_handle, 'launched_resources', None)
|
388
447
|
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
session.execute(do_update_stmt)
|
413
|
-
elif (_SQLALCHEMY_ENGINE.dialect.name ==
|
414
|
-
db_utils.SQLAlchemyDialect.POSTGRESQL.value):
|
415
|
-
# TODO(syang) support postgres dialect
|
416
|
-
session.rollback()
|
417
|
-
raise ValueError('Unsupported database dialect')
|
418
|
-
else:
|
419
|
-
session.rollback()
|
420
|
-
raise ValueError('Unsupported database dialect')
|
448
|
+
insert_stmnt = insert_func(cluster_history_table).values(
|
449
|
+
cluster_hash=cluster_hash,
|
450
|
+
name=cluster_name,
|
451
|
+
num_nodes=launched_nodes,
|
452
|
+
requested_resources=pickle.dumps(requested_resources),
|
453
|
+
launched_resources=pickle.dumps(launched_resources),
|
454
|
+
usage_intervals=pickle.dumps(usage_intervals),
|
455
|
+
user_hash=user_hash)
|
456
|
+
do_update_stmt = insert_stmnt.on_conflict_do_update(
|
457
|
+
index_elements=[cluster_history_table.c.cluster_hash],
|
458
|
+
set_={
|
459
|
+
cluster_history_table.c.name: cluster_name,
|
460
|
+
cluster_history_table.c.num_nodes: launched_nodes,
|
461
|
+
cluster_history_table.c.requested_resources:
|
462
|
+
pickle.dumps(requested_resources),
|
463
|
+
cluster_history_table.c.launched_resources:
|
464
|
+
pickle.dumps(launched_resources),
|
465
|
+
cluster_history_table.c.usage_intervals:
|
466
|
+
pickle.dumps(usage_intervals),
|
467
|
+
cluster_history_table.c.user_hash: user_hash
|
468
|
+
})
|
469
|
+
session.execute(do_update_stmt)
|
470
|
+
|
421
471
|
session.commit()
|
422
472
|
|
423
473
|
|
@@ -504,9 +554,9 @@ def get_glob_cluster_names(cluster_name: str) -> List[str]:
|
|
504
554
|
cluster_table.c.name.op('GLOB')(cluster_name)).all()
|
505
555
|
elif (_SQLALCHEMY_ENGINE.dialect.name ==
|
506
556
|
db_utils.SQLAlchemyDialect.POSTGRESQL.value):
|
507
|
-
|
508
|
-
|
509
|
-
|
557
|
+
rows = session.query(cluster_table).filter(
|
558
|
+
cluster_table.c.name.op('SIMILAR TO')(
|
559
|
+
_glob_to_similar(cluster_name))).all()
|
510
560
|
else:
|
511
561
|
raise ValueError('Unsupported database dialect')
|
512
562
|
return [row.name for row in rows]
|
@@ -741,6 +791,7 @@ def get_cluster_from_name(
|
|
741
791
|
'config_hash': row.config_hash,
|
742
792
|
'workspace': row.workspace,
|
743
793
|
}
|
794
|
+
|
744
795
|
return record
|
745
796
|
|
746
797
|
|
@@ -849,21 +900,19 @@ def set_enabled_clouds(enabled_clouds: List[str],
|
|
849
900
|
with orm.Session(_SQLALCHEMY_ENGINE) as session:
|
850
901
|
if (_SQLALCHEMY_ENGINE.dialect.name ==
|
851
902
|
db_utils.SQLAlchemyDialect.SQLITE.value):
|
852
|
-
|
853
|
-
key=_get_enabled_clouds_key(cloud_capability, workspace),
|
854
|
-
value=json.dumps(enabled_clouds))
|
855
|
-
do_update_stmt = insert_stmnt.on_conflict_do_update(
|
856
|
-
index_elements=[config_table.c.key],
|
857
|
-
set_={config_table.c.value: json.dumps(enabled_clouds)})
|
858
|
-
session.execute(do_update_stmt)
|
903
|
+
insert_func = sqlite.insert
|
859
904
|
elif (_SQLALCHEMY_ENGINE.dialect.name ==
|
860
905
|
db_utils.SQLAlchemyDialect.POSTGRESQL.value):
|
861
|
-
|
862
|
-
session.rollback()
|
863
|
-
raise ValueError('Unsupported database dialect')
|
906
|
+
insert_func = postgresql.insert
|
864
907
|
else:
|
865
|
-
session.rollback()
|
866
908
|
raise ValueError('Unsupported database dialect')
|
909
|
+
insert_stmnt = insert_func(config_table).values(
|
910
|
+
key=_get_enabled_clouds_key(cloud_capability, workspace),
|
911
|
+
value=json.dumps(enabled_clouds))
|
912
|
+
do_update_stmt = insert_stmnt.on_conflict_do_update(
|
913
|
+
index_elements=[config_table.c.key],
|
914
|
+
set_={config_table.c.value: json.dumps(enabled_clouds)})
|
915
|
+
session.execute(do_update_stmt)
|
867
916
|
session.commit()
|
868
917
|
|
869
918
|
|
@@ -888,29 +937,27 @@ def add_or_update_storage(storage_name: str,
|
|
888
937
|
with orm.Session(_SQLALCHEMY_ENGINE) as session:
|
889
938
|
if (_SQLALCHEMY_ENGINE.dialect.name ==
|
890
939
|
db_utils.SQLAlchemyDialect.SQLITE.value):
|
891
|
-
|
892
|
-
name=storage_name,
|
893
|
-
handle=handle,
|
894
|
-
last_use=last_use,
|
895
|
-
launched_at=storage_launched_at,
|
896
|
-
status=storage_status.value)
|
897
|
-
do_update_stmt = insert_stmnt.on_conflict_do_update(
|
898
|
-
index_elements=[storage_table.c.name],
|
899
|
-
set_={
|
900
|
-
storage_table.c.handle: handle,
|
901
|
-
storage_table.c.last_use: last_use,
|
902
|
-
storage_table.c.launched_at: storage_launched_at,
|
903
|
-
storage_table.c.status: storage_status.value
|
904
|
-
})
|
905
|
-
session.execute(do_update_stmt)
|
940
|
+
insert_func = sqlite.insert
|
906
941
|
elif (_SQLALCHEMY_ENGINE.dialect.name ==
|
907
942
|
db_utils.SQLAlchemyDialect.POSTGRESQL.value):
|
908
|
-
|
909
|
-
session.rollback()
|
910
|
-
raise ValueError('Unsupported database dialect')
|
943
|
+
insert_func = postgresql.insert
|
911
944
|
else:
|
912
|
-
session.rollback()
|
913
945
|
raise ValueError('Unsupported database dialect')
|
946
|
+
insert_stmnt = insert_func(storage_table).values(
|
947
|
+
name=storage_name,
|
948
|
+
handle=handle,
|
949
|
+
last_use=last_use,
|
950
|
+
launched_at=storage_launched_at,
|
951
|
+
status=storage_status.value)
|
952
|
+
do_update_stmt = insert_stmnt.on_conflict_do_update(
|
953
|
+
index_elements=[storage_table.c.name],
|
954
|
+
set_={
|
955
|
+
storage_table.c.handle: handle,
|
956
|
+
storage_table.c.last_use: last_use,
|
957
|
+
storage_table.c.launched_at: storage_launched_at,
|
958
|
+
storage_table.c.status: storage_status.value
|
959
|
+
})
|
960
|
+
session.execute(do_update_stmt)
|
914
961
|
session.commit()
|
915
962
|
|
916
963
|
|
@@ -973,9 +1020,9 @@ def get_glob_storage_name(storage_name: str) -> List[str]:
|
|
973
1020
|
storage_table.c.name.op('GLOB')(storage_name)).all()
|
974
1021
|
elif (_SQLALCHEMY_ENGINE.dialect.name ==
|
975
1022
|
db_utils.SQLAlchemyDialect.POSTGRESQL.value):
|
976
|
-
|
977
|
-
|
978
|
-
|
1023
|
+
rows = session.query(storage_table).filter(
|
1024
|
+
storage_table.c.name.op('SIMILAR TO')(
|
1025
|
+
_glob_to_similar(storage_name))).all()
|
979
1026
|
else:
|
980
1027
|
raise ValueError('Unsupported database dialect')
|
981
1028
|
return [row.name for row in rows]
|
sky/jobs/client/sdk.py
CHANGED
@@ -46,6 +46,7 @@ def launch(
|
|
46
46
|
task: sky.Task, or sky.Dag (experimental; 1-task only) to launch as a
|
47
47
|
managed job.
|
48
48
|
name: Name of the managed job.
|
49
|
+
priority: Priority of the managed job.
|
49
50
|
_need_confirmation: (Internal only) Whether to show a confirmation
|
50
51
|
prompt before launching the job.
|
51
52
|
|
sky/jobs/constants.py
CHANGED
sky/jobs/controller.py
CHANGED
@@ -179,8 +179,8 @@ class JobsController:
|
|
179
179
|
cluster_name = managed_job_utils.generate_managed_job_cluster_name(
|
180
180
|
task.name, self._job_id)
|
181
181
|
self._strategy_executor = recovery_strategy.StrategyExecutor.make(
|
182
|
-
cluster_name, self._backend, task, self._job_id)
|
183
|
-
managed_job_state.
|
182
|
+
cluster_name, self._backend, task, self._job_id, task_id)
|
183
|
+
managed_job_state.set_starting(
|
184
184
|
self._job_id,
|
185
185
|
task_id,
|
186
186
|
self._backend.run_timestamp,
|
@@ -197,9 +197,7 @@ class JobsController:
|
|
197
197
|
f'{task.name!r}); {constants.TASK_ID_ENV_VAR}: {task_id_env_var}')
|
198
198
|
|
199
199
|
logger.info('Started monitoring.')
|
200
|
-
|
201
|
-
task_id=task_id,
|
202
|
-
callback_func=callback_func)
|
200
|
+
|
203
201
|
remote_job_submitted_at = self._strategy_executor.launch()
|
204
202
|
assert remote_job_submitted_at is not None, remote_job_submitted_at
|
205
203
|
|