skypilot-nightly 1.0.0.dev20250609__py3-none-any.whl → 1.0.0.dev20250611__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/admin_policy.py +134 -5
- sky/authentication.py +1 -7
- sky/backends/cloud_vm_ray_backend.py +9 -20
- sky/benchmark/benchmark_state.py +39 -1
- sky/cli.py +3 -5
- sky/client/cli.py +3 -5
- sky/client/sdk.py +49 -4
- sky/clouds/kubernetes.py +15 -24
- sky/dashboard/out/404.html +1 -1
- sky/dashboard/out/_next/static/chunks/211.692afc57e812ae1a.js +1 -0
- sky/dashboard/out/_next/static/chunks/350.9e123a4551f68b0d.js +1 -0
- sky/dashboard/out/_next/static/chunks/37-d8aebf1683522a0b.js +6 -0
- sky/dashboard/out/_next/static/chunks/42.d39e24467181b06b.js +6 -0
- sky/dashboard/out/_next/static/chunks/443.b2242d0efcdf5f47.js +1 -0
- sky/dashboard/out/_next/static/chunks/470-4d1a5dbe58a8a2b9.js +1 -0
- sky/dashboard/out/_next/static/chunks/{121-865d2bf8a3b84c6a.js → 491.b3d264269613fe09.js} +3 -3
- sky/dashboard/out/_next/static/chunks/513.211357a2914a34b2.js +1 -0
- sky/dashboard/out/_next/static/chunks/600.15a0009177e86b86.js +16 -0
- sky/dashboard/out/_next/static/chunks/616-d6128fa9e7cae6e6.js +39 -0
- sky/dashboard/out/_next/static/chunks/664-047bc03493fda379.js +1 -0
- sky/dashboard/out/_next/static/chunks/682.4dd5dc116f740b5f.js +6 -0
- sky/dashboard/out/_next/static/chunks/760-a89d354797ce7af5.js +1 -0
- sky/dashboard/out/_next/static/chunks/799-3625946b2ec2eb30.js +8 -0
- sky/dashboard/out/_next/static/chunks/804-4c9fc53aa74bc191.js +21 -0
- sky/dashboard/out/_next/static/chunks/843-6fcc4bf91ac45b39.js +11 -0
- sky/dashboard/out/_next/static/chunks/856-0776dc6ed6000c39.js +1 -0
- sky/dashboard/out/_next/static/chunks/901-b424d293275e1fd7.js +1 -0
- sky/dashboard/out/_next/static/chunks/938-ab185187a63f9cdb.js +1 -0
- sky/dashboard/out/_next/static/chunks/947-6620842ef80ae879.js +35 -0
- sky/dashboard/out/_next/static/chunks/969-20d54a9d998dc102.js +1 -0
- sky/dashboard/out/_next/static/chunks/973-c807fc34f09c7df3.js +1 -0
- sky/dashboard/out/_next/static/chunks/pages/_app-7bbd9d39d6f9a98a.js +20 -0
- sky/dashboard/out/_next/static/chunks/pages/clusters/[cluster]/[job]-89216c616dbaa9c5.js +6 -0
- sky/dashboard/out/_next/static/chunks/pages/clusters/[cluster]-451a14e7e755ebbc.js +6 -0
- sky/dashboard/out/_next/static/chunks/pages/clusters-e56b17fd85d0ba58.js +1 -0
- sky/dashboard/out/_next/static/chunks/pages/config-497a35a7ed49734a.js +1 -0
- sky/dashboard/out/_next/static/chunks/pages/infra/[context]-d2910be98e9227cb.js +1 -0
- sky/dashboard/out/_next/static/chunks/pages/infra-780860bcc1103945.js +1 -0
- sky/dashboard/out/_next/static/chunks/pages/jobs/[job]-b3dbf38b51cb29be.js +16 -0
- sky/dashboard/out/_next/static/chunks/pages/jobs-fe233baf3d073491.js +1 -0
- sky/dashboard/out/_next/static/chunks/pages/users-c69ffcab9d6e5269.js +1 -0
- sky/dashboard/out/_next/static/chunks/pages/workspace/new-31aa8bdcb7592635.js +1 -0
- sky/dashboard/out/_next/static/chunks/pages/workspaces/[name]-c8c2191328532b7d.js +1 -0
- sky/dashboard/out/_next/static/chunks/pages/workspaces-82e6601baa5dd280.js +1 -0
- sky/dashboard/out/_next/static/chunks/webpack-208a9812ab4f61c9.js +1 -0
- sky/dashboard/out/_next/static/css/{8b1c8321d4c02372.css → 5d71bfc09f184bab.css} +1 -1
- sky/dashboard/out/_next/static/zJqasksBQ3HcqMpA2wTUZ/_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/workspace/new.html +1 -1
- sky/dashboard/out/workspaces/[name].html +1 -1
- sky/dashboard/out/workspaces.html +1 -1
- sky/exceptions.py +18 -0
- sky/global_user_state.py +181 -74
- sky/jobs/client/sdk.py +29 -21
- sky/jobs/scheduler.py +4 -5
- sky/jobs/state.py +104 -11
- sky/jobs/utils.py +5 -5
- sky/provision/kubernetes/constants.py +9 -0
- sky/provision/kubernetes/utils.py +106 -7
- sky/serve/client/sdk.py +56 -45
- sky/server/common.py +1 -5
- sky/server/requests/executor.py +50 -20
- sky/server/requests/payloads.py +3 -0
- sky/server/requests/process.py +69 -29
- sky/server/server.py +1 -0
- sky/server/stream_utils.py +111 -55
- sky/skylet/constants.py +1 -2
- sky/skylet/job_lib.py +95 -40
- sky/skypilot_config.py +99 -25
- sky/users/permission.py +34 -17
- sky/utils/admin_policy_utils.py +41 -16
- sky/utils/context.py +21 -1
- sky/utils/controller_utils.py +16 -1
- sky/utils/kubernetes/exec_kubeconfig_converter.py +19 -47
- sky/utils/schemas.py +11 -3
- {skypilot_nightly-1.0.0.dev20250609.dist-info → skypilot_nightly-1.0.0.dev20250611.dist-info}/METADATA +1 -1
- {skypilot_nightly-1.0.0.dev20250609.dist-info → skypilot_nightly-1.0.0.dev20250611.dist-info}/RECORD +92 -81
- sky/dashboard/out/_next/static/chunks/236-619ed0248fb6fdd9.js +0 -6
- sky/dashboard/out/_next/static/chunks/293-351268365226d251.js +0 -1
- sky/dashboard/out/_next/static/chunks/37-600191c5804dcae2.js +0 -6
- sky/dashboard/out/_next/static/chunks/470-680c19413b8f808b.js +0 -1
- sky/dashboard/out/_next/static/chunks/63-e2d7b1e75e67c713.js +0 -66
- sky/dashboard/out/_next/static/chunks/682-b60cfdacc15202e8.js +0 -6
- sky/dashboard/out/_next/static/chunks/843-16c7194621b2b512.js +0 -11
- sky/dashboard/out/_next/static/chunks/856-affc52adf5403a3a.js +0 -1
- sky/dashboard/out/_next/static/chunks/969-2c584e28e6b4b106.js +0 -1
- sky/dashboard/out/_next/static/chunks/973-aed916d5b02d2d63.js +0 -1
- sky/dashboard/out/_next/static/chunks/pages/_app-5f16aba5794ee8e7.js +0 -1
- sky/dashboard/out/_next/static/chunks/pages/clusters/[cluster]/[job]-d31688d3e52736dd.js +0 -6
- sky/dashboard/out/_next/static/chunks/pages/clusters/[cluster]-e7d8710a9b0491e5.js +0 -6
- sky/dashboard/out/_next/static/chunks/pages/clusters-3c674e5d970e05cb.js +0 -1
- sky/dashboard/out/_next/static/chunks/pages/config-3aac7a015c6eede1.js +0 -6
- sky/dashboard/out/_next/static/chunks/pages/infra/[context]-46d2e4ad6c487260.js +0 -1
- sky/dashboard/out/_next/static/chunks/pages/infra-7013d816a2a0e76c.js +0 -1
- sky/dashboard/out/_next/static/chunks/pages/jobs/[job]-f7f0c9e156d328bc.js +0 -16
- sky/dashboard/out/_next/static/chunks/pages/jobs-87e60396c376292f.js +0 -1
- sky/dashboard/out/_next/static/chunks/pages/users-9355a0f13d1db61d.js +0 -16
- sky/dashboard/out/_next/static/chunks/pages/workspace/new-9a749cca1813bd27.js +0 -1
- sky/dashboard/out/_next/static/chunks/pages/workspaces/[name]-8eeb628e03902f1b.js +0 -1
- sky/dashboard/out/_next/static/chunks/pages/workspaces-8fbcc5ab4af316d0.js +0 -1
- sky/dashboard/out/_next/static/chunks/webpack-65d465f948974c0d.js +0 -1
- sky/dashboard/out/_next/static/xos0euNCptbGAM7_Q3Acl/_buildManifest.js +0 -1
- /sky/dashboard/out/_next/static/{xos0euNCptbGAM7_Q3Acl → zJqasksBQ3HcqMpA2wTUZ}/_ssgManifest.js +0 -0
- {skypilot_nightly-1.0.0.dev20250609.dist-info → skypilot_nightly-1.0.0.dev20250611.dist-info}/WHEEL +0 -0
- {skypilot_nightly-1.0.0.dev20250609.dist-info → skypilot_nightly-1.0.0.dev20250611.dist-info}/entry_points.txt +0 -0
- {skypilot_nightly-1.0.0.dev20250609.dist-info → skypilot_nightly-1.0.0.dev20250611.dist-info}/licenses/LICENSE +0 -0
- {skypilot_nightly-1.0.0.dev20250609.dist-info → skypilot_nightly-1.0.0.dev20250611.dist-info}/top_level.txt +0 -0
sky/global_user_state.py
CHANGED
@@ -6,11 +6,13 @@ Concepts:
|
|
6
6
|
- Cluster handle: (non-user facing) an opaque backend handle for us to
|
7
7
|
interact with a cluster.
|
8
8
|
"""
|
9
|
+
import functools
|
9
10
|
import json
|
10
11
|
import os
|
11
12
|
import pathlib
|
12
13
|
import pickle
|
13
14
|
import re
|
15
|
+
import threading
|
14
16
|
import time
|
15
17
|
import typing
|
16
18
|
from typing import Any, Dict, List, Optional, Set, Tuple
|
@@ -44,6 +46,9 @@ logger = sky_logging.init_logger(__name__)
|
|
44
46
|
|
45
47
|
_ENABLED_CLOUDS_KEY_PREFIX = 'enabled_clouds_'
|
46
48
|
|
49
|
+
_SQLALCHEMY_ENGINE: Optional[sqlalchemy.engine.Engine] = None
|
50
|
+
_DB_INIT_LOCK = threading.Lock()
|
51
|
+
|
47
52
|
Base = declarative.declarative_base()
|
48
53
|
|
49
54
|
config_table = sqlalchemy.Table(
|
@@ -171,11 +176,11 @@ def create_table():
|
|
171
176
|
# https://github.com/microsoft/WSL/issues/2395
|
172
177
|
# TODO(romilb): We do not enable WAL for WSL because of known issue in WSL.
|
173
178
|
# This may cause the database locked problem from WSL issue #1441.
|
174
|
-
if (
|
179
|
+
if (_SQLALCHEMY_ENGINE.dialect.name
|
175
180
|
== db_utils.SQLAlchemyDialect.SQLITE.value and
|
176
181
|
not common_utils.is_wsl()):
|
177
182
|
try:
|
178
|
-
with orm.Session(
|
183
|
+
with orm.Session(_SQLALCHEMY_ENGINE) as session:
|
179
184
|
session.execute(sqlalchemy.text('PRAGMA journal_mode=WAL'))
|
180
185
|
session.commit()
|
181
186
|
except sqlalchemy_exc.OperationalError as e:
|
@@ -185,12 +190,12 @@ def create_table():
|
|
185
190
|
# is not critical and is likely to be enabled by other processes.
|
186
191
|
|
187
192
|
# Create tables if they don't exist
|
188
|
-
Base.metadata.create_all(bind=
|
193
|
+
Base.metadata.create_all(bind=_SQLALCHEMY_ENGINE)
|
189
194
|
|
190
195
|
# For backward compatibility.
|
191
196
|
# TODO(zhwu): Remove this function after all users have migrated to
|
192
197
|
# the latest version of SkyPilot.
|
193
|
-
with orm.Session(
|
198
|
+
with orm.Session(_SQLALCHEMY_ENGINE) as session:
|
194
199
|
# Add autostop column to clusters table
|
195
200
|
db_utils.add_column_to_table_sqlalchemy(session,
|
196
201
|
'clusters',
|
@@ -298,30 +303,53 @@ def create_table():
|
|
298
303
|
session.commit()
|
299
304
|
|
300
305
|
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
306
|
+
def initialize_and_get_db() -> sqlalchemy.engine.Engine:
|
307
|
+
global _SQLALCHEMY_ENGINE
|
308
|
+
if _SQLALCHEMY_ENGINE is not None:
|
309
|
+
return _SQLALCHEMY_ENGINE
|
310
|
+
with _DB_INIT_LOCK:
|
311
|
+
if _SQLALCHEMY_ENGINE is None:
|
312
|
+
conn_string = None
|
313
|
+
if os.environ.get(constants.ENV_VAR_IS_SKYPILOT_SERVER) is not None:
|
314
|
+
conn_string = skypilot_config.get_nested(('db',), None)
|
315
|
+
if conn_string:
|
316
|
+
logger.debug(f'using db URI from {conn_string}')
|
317
|
+
_SQLALCHEMY_ENGINE = sqlalchemy.create_engine(conn_string)
|
318
|
+
else:
|
319
|
+
db_path = os.path.expanduser('~/.sky/state.db')
|
320
|
+
pathlib.Path(db_path).parents[0].mkdir(parents=True,
|
321
|
+
exist_ok=True)
|
322
|
+
_SQLALCHEMY_ENGINE = sqlalchemy.create_engine('sqlite:///' +
|
323
|
+
db_path)
|
324
|
+
create_table()
|
325
|
+
return _SQLALCHEMY_ENGINE
|
326
|
+
|
327
|
+
|
328
|
+
def _init_db(func):
|
329
|
+
"""Initialize the database."""
|
330
|
+
|
331
|
+
@functools.wraps(func)
|
332
|
+
def wrapper(*args, **kwargs):
|
333
|
+
initialize_and_get_db()
|
334
|
+
return func(*args, **kwargs)
|
335
|
+
|
336
|
+
return wrapper
|
337
|
+
|
338
|
+
|
339
|
+
@_init_db
|
314
340
|
def add_or_update_user(user: models.User) -> bool:
|
315
341
|
"""Store the mapping from user hash to user name for display purposes.
|
316
342
|
|
317
343
|
Returns:
|
318
344
|
Boolean: whether the user is newly added
|
319
345
|
"""
|
346
|
+
assert _SQLALCHEMY_ENGINE is not None
|
347
|
+
|
320
348
|
if user.name is None:
|
321
349
|
return False
|
322
350
|
|
323
|
-
with orm.Session(
|
324
|
-
if (
|
351
|
+
with orm.Session(_SQLALCHEMY_ENGINE) as session:
|
352
|
+
if (_SQLALCHEMY_ENGINE.dialect.name ==
|
325
353
|
db_utils.SQLAlchemyDialect.SQLITE.value):
|
326
354
|
# For SQLite, use INSERT OR IGNORE followed by UPDATE to detect new
|
327
355
|
# vs existing
|
@@ -343,7 +371,7 @@ def add_or_update_user(user: models.User) -> bool:
|
|
343
371
|
session.commit()
|
344
372
|
return was_inserted
|
345
373
|
|
346
|
-
elif (
|
374
|
+
elif (_SQLALCHEMY_ENGINE.dialect.name ==
|
347
375
|
db_utils.SQLAlchemyDialect.POSTGRESQL.value):
|
348
376
|
# For PostgreSQL, use INSERT ... ON CONFLICT with RETURNING to
|
349
377
|
# detect insert vs update
|
@@ -371,20 +399,25 @@ def add_or_update_user(user: models.User) -> bool:
|
|
371
399
|
raise ValueError('Unsupported database dialect')
|
372
400
|
|
373
401
|
|
402
|
+
@_init_db
|
374
403
|
def get_user(user_id: str) -> Optional[models.User]:
|
375
|
-
|
404
|
+
assert _SQLALCHEMY_ENGINE is not None
|
405
|
+
with orm.Session(_SQLALCHEMY_ENGINE) as session:
|
376
406
|
row = session.query(user_table).filter_by(id=user_id).first()
|
377
407
|
if row is None:
|
378
408
|
return None
|
379
409
|
return models.User(id=row.id, name=row.name)
|
380
410
|
|
381
411
|
|
412
|
+
@_init_db
|
382
413
|
def get_all_users() -> List[models.User]:
|
383
|
-
|
414
|
+
assert _SQLALCHEMY_ENGINE is not None
|
415
|
+
with orm.Session(_SQLALCHEMY_ENGINE) as session:
|
384
416
|
rows = session.query(user_table).all()
|
385
417
|
return [models.User(id=row.id, name=row.name) for row in rows]
|
386
418
|
|
387
419
|
|
420
|
+
@_init_db
|
388
421
|
def add_or_update_cluster(cluster_name: str,
|
389
422
|
cluster_handle: 'backends.ResourceHandle',
|
390
423
|
requested_resources: Optional[Set[Any]],
|
@@ -405,6 +438,7 @@ def add_or_update_cluster(cluster_name: str,
|
|
405
438
|
config_hash: Configuration hash for the cluster.
|
406
439
|
task_config: The config of the task being launched.
|
407
440
|
"""
|
441
|
+
assert _SQLALCHEMY_ENGINE is not None
|
408
442
|
# FIXME: launched_at will be changed when `sky launch -c` is called.
|
409
443
|
handle = pickle.dumps(cluster_handle)
|
410
444
|
cluster_launched_at = int(time.time()) if is_launch else None
|
@@ -457,7 +491,7 @@ def add_or_update_cluster(cluster_name: str,
|
|
457
491
|
'config_hash': config_hash,
|
458
492
|
})
|
459
493
|
|
460
|
-
with orm.Session(
|
494
|
+
with orm.Session(_SQLALCHEMY_ENGINE) as session:
|
461
495
|
# with_for_update() locks the row until commit() or rollback()
|
462
496
|
# is called, or until the code escapes the with block.
|
463
497
|
cluster_row = session.query(cluster_table).filter_by(
|
@@ -484,10 +518,10 @@ def add_or_update_cluster(cluster_name: str,
|
|
484
518
|
'last_creation_command': last_use,
|
485
519
|
})
|
486
520
|
|
487
|
-
if (
|
521
|
+
if (_SQLALCHEMY_ENGINE.dialect.name ==
|
488
522
|
db_utils.SQLAlchemyDialect.SQLITE.value):
|
489
523
|
insert_func = sqlite.insert
|
490
|
-
elif (
|
524
|
+
elif (_SQLALCHEMY_ENGINE.dialect.name ==
|
491
525
|
db_utils.SQLAlchemyDialect.POSTGRESQL.value):
|
492
526
|
insert_func = postgresql.insert
|
493
527
|
else:
|
@@ -562,29 +596,34 @@ def _get_user_hash_or_current_user(user_hash: Optional[str]) -> str:
|
|
562
596
|
return common_utils.get_user_hash()
|
563
597
|
|
564
598
|
|
599
|
+
@_init_db
|
565
600
|
def update_cluster_handle(cluster_name: str,
|
566
601
|
cluster_handle: 'backends.ResourceHandle'):
|
602
|
+
assert _SQLALCHEMY_ENGINE is not None
|
567
603
|
handle = pickle.dumps(cluster_handle)
|
568
|
-
with orm.Session(
|
604
|
+
with orm.Session(_SQLALCHEMY_ENGINE) as session:
|
569
605
|
session.query(cluster_table).filter_by(name=cluster_name).update(
|
570
606
|
{cluster_table.c.handle: handle})
|
571
607
|
session.commit()
|
572
608
|
|
573
609
|
|
610
|
+
@_init_db
|
574
611
|
def update_last_use(cluster_name: str):
|
575
612
|
"""Updates the last used command for the cluster."""
|
576
|
-
with orm.Session(
|
613
|
+
with orm.Session(_SQLALCHEMY_ENGINE) as session:
|
577
614
|
session.query(cluster_table).filter_by(name=cluster_name).update(
|
578
615
|
{cluster_table.c.last_use: common_utils.get_current_command()})
|
579
616
|
session.commit()
|
580
617
|
|
581
618
|
|
619
|
+
@_init_db
|
582
620
|
def remove_cluster(cluster_name: str, terminate: bool) -> None:
|
583
621
|
"""Removes cluster_name mapping."""
|
622
|
+
assert _SQLALCHEMY_ENGINE is not None
|
584
623
|
cluster_hash = _get_hash_for_existing_cluster(cluster_name)
|
585
624
|
usage_intervals = _get_cluster_usage_intervals(cluster_hash)
|
586
625
|
|
587
|
-
with orm.Session(
|
626
|
+
with orm.Session(_SQLALCHEMY_ENGINE) as session:
|
588
627
|
# usage_intervals is not None and not empty
|
589
628
|
if usage_intervals:
|
590
629
|
assert cluster_hash is not None, cluster_name
|
@@ -614,24 +653,28 @@ def remove_cluster(cluster_name: str, terminate: bool) -> None:
|
|
614
653
|
session.commit()
|
615
654
|
|
616
655
|
|
656
|
+
@_init_db
|
617
657
|
def get_handle_from_cluster_name(
|
618
658
|
cluster_name: str) -> Optional['backends.ResourceHandle']:
|
659
|
+
assert _SQLALCHEMY_ENGINE is not None
|
619
660
|
assert cluster_name is not None, 'cluster_name cannot be None'
|
620
|
-
with orm.Session(
|
661
|
+
with orm.Session(_SQLALCHEMY_ENGINE) as session:
|
621
662
|
row = session.query(cluster_table).filter_by(name=cluster_name).first()
|
622
663
|
if row is None:
|
623
664
|
return None
|
624
665
|
return pickle.loads(row.handle)
|
625
666
|
|
626
667
|
|
668
|
+
@_init_db
|
627
669
|
def get_glob_cluster_names(cluster_name: str) -> List[str]:
|
670
|
+
assert _SQLALCHEMY_ENGINE is not None
|
628
671
|
assert cluster_name is not None, 'cluster_name cannot be None'
|
629
|
-
with orm.Session(
|
630
|
-
if (
|
672
|
+
with orm.Session(_SQLALCHEMY_ENGINE) as session:
|
673
|
+
if (_SQLALCHEMY_ENGINE.dialect.name ==
|
631
674
|
db_utils.SQLAlchemyDialect.SQLITE.value):
|
632
675
|
rows = session.query(cluster_table).filter(
|
633
676
|
cluster_table.c.name.op('GLOB')(cluster_name)).all()
|
634
|
-
elif (
|
677
|
+
elif (_SQLALCHEMY_ENGINE.dialect.name ==
|
635
678
|
db_utils.SQLAlchemyDialect.POSTGRESQL.value):
|
636
679
|
rows = session.query(cluster_table).filter(
|
637
680
|
cluster_table.c.name.op('SIMILAR TO')(
|
@@ -641,10 +684,12 @@ def get_glob_cluster_names(cluster_name: str) -> List[str]:
|
|
641
684
|
return [row.name for row in rows]
|
642
685
|
|
643
686
|
|
687
|
+
@_init_db
|
644
688
|
def set_cluster_status(cluster_name: str,
|
645
689
|
status: status_lib.ClusterStatus) -> None:
|
690
|
+
assert _SQLALCHEMY_ENGINE is not None
|
646
691
|
current_time = int(time.time())
|
647
|
-
with orm.Session(
|
692
|
+
with orm.Session(_SQLALCHEMY_ENGINE) as session:
|
648
693
|
count = session.query(cluster_table).filter_by(
|
649
694
|
name=cluster_name).update({
|
650
695
|
cluster_table.c.status: status.value,
|
@@ -656,9 +701,11 @@ def set_cluster_status(cluster_name: str,
|
|
656
701
|
raise ValueError(f'Cluster {cluster_name} not found.')
|
657
702
|
|
658
703
|
|
704
|
+
@_init_db
|
659
705
|
def set_cluster_autostop_value(cluster_name: str, idle_minutes: int,
|
660
706
|
to_down: bool) -> None:
|
661
|
-
|
707
|
+
assert _SQLALCHEMY_ENGINE is not None
|
708
|
+
with orm.Session(_SQLALCHEMY_ENGINE) as session:
|
662
709
|
count = session.query(cluster_table).filter_by(
|
663
710
|
name=cluster_name).update({
|
664
711
|
cluster_table.c.autostop: idle_minutes,
|
@@ -670,24 +717,30 @@ def set_cluster_autostop_value(cluster_name: str, idle_minutes: int,
|
|
670
717
|
raise ValueError(f'Cluster {cluster_name} not found.')
|
671
718
|
|
672
719
|
|
720
|
+
@_init_db
|
673
721
|
def get_cluster_launch_time(cluster_name: str) -> Optional[int]:
|
674
|
-
|
722
|
+
assert _SQLALCHEMY_ENGINE is not None
|
723
|
+
with orm.Session(_SQLALCHEMY_ENGINE) as session:
|
675
724
|
row = session.query(cluster_table).filter_by(name=cluster_name).first()
|
676
725
|
if row is None or row.launched_at is None:
|
677
726
|
return None
|
678
727
|
return int(row.launched_at)
|
679
728
|
|
680
729
|
|
730
|
+
@_init_db
|
681
731
|
def get_cluster_info(cluster_name: str) -> Optional[Dict[str, Any]]:
|
682
|
-
|
732
|
+
assert _SQLALCHEMY_ENGINE is not None
|
733
|
+
with orm.Session(_SQLALCHEMY_ENGINE) as session:
|
683
734
|
row = session.query(cluster_table).filter_by(name=cluster_name).first()
|
684
735
|
if row is None or row.metadata is None:
|
685
736
|
return None
|
686
737
|
return json.loads(row.metadata)
|
687
738
|
|
688
739
|
|
740
|
+
@_init_db
|
689
741
|
def set_cluster_info(cluster_name: str, metadata: Dict[str, Any]) -> None:
|
690
|
-
|
742
|
+
assert _SQLALCHEMY_ENGINE is not None
|
743
|
+
with orm.Session(_SQLALCHEMY_ENGINE) as session:
|
691
744
|
count = session.query(cluster_table).filter_by(
|
692
745
|
name=cluster_name).update(
|
693
746
|
{cluster_table.c.metadata: json.dumps(metadata)})
|
@@ -697,18 +750,22 @@ def set_cluster_info(cluster_name: str, metadata: Dict[str, Any]) -> None:
|
|
697
750
|
raise ValueError(f'Cluster {cluster_name} not found.')
|
698
751
|
|
699
752
|
|
753
|
+
@_init_db
|
700
754
|
def get_cluster_storage_mounts_metadata(
|
701
755
|
cluster_name: str) -> Optional[Dict[str, Any]]:
|
702
|
-
|
756
|
+
assert _SQLALCHEMY_ENGINE is not None
|
757
|
+
with orm.Session(_SQLALCHEMY_ENGINE) as session:
|
703
758
|
row = session.query(cluster_table).filter_by(name=cluster_name).first()
|
704
759
|
if row is None or row.storage_mounts_metadata is None:
|
705
760
|
return None
|
706
761
|
return pickle.loads(row.storage_mounts_metadata)
|
707
762
|
|
708
763
|
|
764
|
+
@_init_db
|
709
765
|
def set_cluster_storage_mounts_metadata(
|
710
766
|
cluster_name: str, storage_mounts_metadata: Dict[str, Any]) -> None:
|
711
|
-
|
767
|
+
assert _SQLALCHEMY_ENGINE is not None
|
768
|
+
with orm.Session(_SQLALCHEMY_ENGINE) as session:
|
712
769
|
count = session.query(cluster_table).filter_by(
|
713
770
|
name=cluster_name).update({
|
714
771
|
cluster_table.c.storage_mounts_metadata:
|
@@ -720,12 +777,14 @@ def set_cluster_storage_mounts_metadata(
|
|
720
777
|
raise ValueError(f'Cluster {cluster_name} not found.')
|
721
778
|
|
722
779
|
|
780
|
+
@_init_db
|
723
781
|
def _get_cluster_usage_intervals(
|
724
782
|
cluster_hash: Optional[str]
|
725
783
|
) -> Optional[List[Tuple[int, Optional[int]]]]:
|
784
|
+
assert _SQLALCHEMY_ENGINE is not None
|
726
785
|
if cluster_hash is None:
|
727
786
|
return None
|
728
|
-
with orm.Session(
|
787
|
+
with orm.Session(_SQLALCHEMY_ENGINE) as session:
|
729
788
|
row = session.query(cluster_history_table).filter_by(
|
730
789
|
cluster_hash=cluster_hash).first()
|
731
790
|
if row is None or row.usage_intervals is None:
|
@@ -759,10 +818,12 @@ def _get_cluster_duration(cluster_hash: str) -> int:
|
|
759
818
|
return total_duration
|
760
819
|
|
761
820
|
|
821
|
+
@_init_db
|
762
822
|
def _set_cluster_usage_intervals(
|
763
823
|
cluster_hash: str, usage_intervals: List[Tuple[int,
|
764
824
|
Optional[int]]]) -> None:
|
765
|
-
|
825
|
+
assert _SQLALCHEMY_ENGINE is not None
|
826
|
+
with orm.Session(_SQLALCHEMY_ENGINE) as session:
|
766
827
|
count = session.query(cluster_history_table).filter_by(
|
767
828
|
cluster_hash=cluster_hash).update({
|
768
829
|
cluster_history_table.c.usage_intervals:
|
@@ -774,12 +835,14 @@ def _set_cluster_usage_intervals(
|
|
774
835
|
raise ValueError(f'Cluster hash {cluster_hash} not found.')
|
775
836
|
|
776
837
|
|
838
|
+
@_init_db
|
777
839
|
def set_owner_identity_for_cluster(cluster_name: str,
|
778
840
|
owner_identity: Optional[List[str]]) -> None:
|
841
|
+
assert _SQLALCHEMY_ENGINE is not None
|
779
842
|
if owner_identity is None:
|
780
843
|
return
|
781
844
|
owner_identity_str = json.dumps(owner_identity)
|
782
|
-
with orm.Session(
|
845
|
+
with orm.Session(_SQLALCHEMY_ENGINE) as session:
|
783
846
|
count = session.query(cluster_table).filter_by(
|
784
847
|
name=cluster_name).update(
|
785
848
|
{cluster_table.c.owner: owner_identity_str})
|
@@ -789,17 +852,21 @@ def set_owner_identity_for_cluster(cluster_name: str,
|
|
789
852
|
raise ValueError(f'Cluster {cluster_name} not found.')
|
790
853
|
|
791
854
|
|
855
|
+
@_init_db
|
792
856
|
def _get_hash_for_existing_cluster(cluster_name: str) -> Optional[str]:
|
793
|
-
|
857
|
+
assert _SQLALCHEMY_ENGINE is not None
|
858
|
+
with orm.Session(_SQLALCHEMY_ENGINE) as session:
|
794
859
|
row = session.query(cluster_table).filter_by(name=cluster_name).first()
|
795
860
|
if row is None or row.cluster_hash is None:
|
796
861
|
return None
|
797
862
|
return row.cluster_hash
|
798
863
|
|
799
864
|
|
865
|
+
@_init_db
|
800
866
|
def get_launched_resources_from_cluster_hash(
|
801
867
|
cluster_hash: str) -> Optional[Tuple[int, Any]]:
|
802
|
-
|
868
|
+
assert _SQLALCHEMY_ENGINE is not None
|
869
|
+
with orm.Session(_SQLALCHEMY_ENGINE) as session:
|
803
870
|
row = session.query(cluster_history_table).filter_by(
|
804
871
|
cluster_hash=cluster_hash).first()
|
805
872
|
if row is None:
|
@@ -841,10 +908,12 @@ def _load_storage_mounts_metadata(
|
|
841
908
|
return pickle.loads(record_storage_mounts_metadata)
|
842
909
|
|
843
910
|
|
911
|
+
@_init_db
|
844
912
|
@context_utils.cancellation_guard
|
845
913
|
def get_cluster_from_name(
|
846
914
|
cluster_name: Optional[str]) -> Optional[Dict[str, Any]]:
|
847
|
-
|
915
|
+
assert _SQLALCHEMY_ENGINE is not None
|
916
|
+
with orm.Session(_SQLALCHEMY_ENGINE) as session:
|
848
917
|
row = session.query(cluster_table).filter_by(name=cluster_name).first()
|
849
918
|
if row is None:
|
850
919
|
return None
|
@@ -878,8 +947,10 @@ def get_cluster_from_name(
|
|
878
947
|
return record
|
879
948
|
|
880
949
|
|
950
|
+
@_init_db
|
881
951
|
def get_clusters() -> List[Dict[str, Any]]:
|
882
|
-
|
952
|
+
assert _SQLALCHEMY_ENGINE is not None
|
953
|
+
with orm.Session(_SQLALCHEMY_ENGINE) as session:
|
883
954
|
rows = session.query(cluster_table).order_by(
|
884
955
|
sqlalchemy.desc(cluster_table.c.launched_at)).all()
|
885
956
|
records = []
|
@@ -915,8 +986,10 @@ def get_clusters() -> List[Dict[str, Any]]:
|
|
915
986
|
return records
|
916
987
|
|
917
988
|
|
989
|
+
@_init_db
|
918
990
|
def get_clusters_from_history() -> List[Dict[str, Any]]:
|
919
|
-
|
991
|
+
assert _SQLALCHEMY_ENGINE is not None
|
992
|
+
with orm.Session(_SQLALCHEMY_ENGINE) as session:
|
920
993
|
rows = session.query(
|
921
994
|
cluster_history_table.join(cluster_table,
|
922
995
|
cluster_history_table.c.cluster_hash ==
|
@@ -951,16 +1024,20 @@ def get_clusters_from_history() -> List[Dict[str, Any]]:
|
|
951
1024
|
return records
|
952
1025
|
|
953
1026
|
|
1027
|
+
@_init_db
|
954
1028
|
def get_cluster_names_start_with(starts_with: str) -> List[str]:
|
955
|
-
|
1029
|
+
assert _SQLALCHEMY_ENGINE is not None
|
1030
|
+
with orm.Session(_SQLALCHEMY_ENGINE) as session:
|
956
1031
|
rows = session.query(cluster_table).filter(
|
957
1032
|
cluster_table.c.name.like(f'{starts_with}%')).all()
|
958
1033
|
return [row.name for row in rows]
|
959
1034
|
|
960
1035
|
|
1036
|
+
@_init_db
|
961
1037
|
def get_cached_enabled_clouds(cloud_capability: 'cloud.CloudCapability',
|
962
1038
|
workspace: str) -> List['clouds.Cloud']:
|
963
|
-
|
1039
|
+
assert _SQLALCHEMY_ENGINE is not None
|
1040
|
+
with orm.Session(_SQLALCHEMY_ENGINE) as session:
|
964
1041
|
row = session.query(config_table).filter_by(
|
965
1042
|
key=_get_enabled_clouds_key(cloud_capability, workspace)).first()
|
966
1043
|
ret = []
|
@@ -981,14 +1058,16 @@ def get_cached_enabled_clouds(cloud_capability: 'cloud.CloudCapability',
|
|
981
1058
|
return enabled_clouds
|
982
1059
|
|
983
1060
|
|
1061
|
+
@_init_db
|
984
1062
|
def set_enabled_clouds(enabled_clouds: List[str],
|
985
1063
|
cloud_capability: 'cloud.CloudCapability',
|
986
1064
|
workspace: str) -> None:
|
987
|
-
|
988
|
-
|
1065
|
+
assert _SQLALCHEMY_ENGINE is not None
|
1066
|
+
with orm.Session(_SQLALCHEMY_ENGINE) as session:
|
1067
|
+
if (_SQLALCHEMY_ENGINE.dialect.name ==
|
989
1068
|
db_utils.SQLAlchemyDialect.SQLITE.value):
|
990
1069
|
insert_func = sqlite.insert
|
991
|
-
elif (
|
1070
|
+
elif (_SQLALCHEMY_ENGINE.dialect.name ==
|
992
1071
|
db_utils.SQLAlchemyDialect.POSTGRESQL.value):
|
993
1072
|
insert_func = postgresql.insert
|
994
1073
|
else:
|
@@ -1008,9 +1087,11 @@ def _get_enabled_clouds_key(cloud_capability: 'cloud.CloudCapability',
|
|
1008
1087
|
return _ENABLED_CLOUDS_KEY_PREFIX + workspace + '_' + cloud_capability.value
|
1009
1088
|
|
1010
1089
|
|
1090
|
+
@_init_db
|
1011
1091
|
def add_or_update_storage(storage_name: str,
|
1012
1092
|
storage_handle: 'Storage.StorageMetadata',
|
1013
1093
|
storage_status: status_lib.StorageStatus):
|
1094
|
+
assert _SQLALCHEMY_ENGINE is not None
|
1014
1095
|
storage_launched_at = int(time.time())
|
1015
1096
|
handle = pickle.dumps(storage_handle)
|
1016
1097
|
last_use = common_utils.get_current_command()
|
@@ -1021,11 +1102,11 @@ def add_or_update_storage(storage_name: str,
|
|
1021
1102
|
if not status_check(storage_status):
|
1022
1103
|
raise ValueError(f'Error in updating global state. Storage Status '
|
1023
1104
|
f'{storage_status} is passed in incorrectly')
|
1024
|
-
with orm.Session(
|
1025
|
-
if (
|
1105
|
+
with orm.Session(_SQLALCHEMY_ENGINE) as session:
|
1106
|
+
if (_SQLALCHEMY_ENGINE.dialect.name ==
|
1026
1107
|
db_utils.SQLAlchemyDialect.SQLITE.value):
|
1027
1108
|
insert_func = sqlite.insert
|
1028
|
-
elif (
|
1109
|
+
elif (_SQLALCHEMY_ENGINE.dialect.name ==
|
1029
1110
|
db_utils.SQLAlchemyDialect.POSTGRESQL.value):
|
1030
1111
|
insert_func = postgresql.insert
|
1031
1112
|
else:
|
@@ -1048,16 +1129,20 @@ def add_or_update_storage(storage_name: str,
|
|
1048
1129
|
session.commit()
|
1049
1130
|
|
1050
1131
|
|
1132
|
+
@_init_db
|
1051
1133
|
def remove_storage(storage_name: str):
|
1052
1134
|
"""Removes Storage from Database"""
|
1053
|
-
|
1135
|
+
assert _SQLALCHEMY_ENGINE is not None
|
1136
|
+
with orm.Session(_SQLALCHEMY_ENGINE) as session:
|
1054
1137
|
session.query(storage_table).filter_by(name=storage_name).delete()
|
1055
1138
|
session.commit()
|
1056
1139
|
|
1057
1140
|
|
1141
|
+
@_init_db
|
1058
1142
|
def set_storage_status(storage_name: str,
|
1059
1143
|
status: status_lib.StorageStatus) -> None:
|
1060
|
-
|
1144
|
+
assert _SQLALCHEMY_ENGINE is not None
|
1145
|
+
with orm.Session(_SQLALCHEMY_ENGINE) as session:
|
1061
1146
|
count = session.query(storage_table).filter_by(
|
1062
1147
|
name=storage_name).update({storage_table.c.status: status.value})
|
1063
1148
|
session.commit()
|
@@ -1066,18 +1151,22 @@ def set_storage_status(storage_name: str,
|
|
1066
1151
|
raise ValueError(f'Storage {storage_name} not found.')
|
1067
1152
|
|
1068
1153
|
|
1154
|
+
@_init_db
|
1069
1155
|
def get_storage_status(storage_name: str) -> Optional[status_lib.StorageStatus]:
|
1156
|
+
assert _SQLALCHEMY_ENGINE is not None
|
1070
1157
|
assert storage_name is not None, 'storage_name cannot be None'
|
1071
|
-
with orm.Session(
|
1158
|
+
with orm.Session(_SQLALCHEMY_ENGINE) as session:
|
1072
1159
|
row = session.query(storage_table).filter_by(name=storage_name).first()
|
1073
1160
|
if row:
|
1074
1161
|
return status_lib.StorageStatus[row.status]
|
1075
1162
|
return None
|
1076
1163
|
|
1077
1164
|
|
1165
|
+
@_init_db
|
1078
1166
|
def set_storage_handle(storage_name: str,
|
1079
1167
|
handle: 'Storage.StorageMetadata') -> None:
|
1080
|
-
|
1168
|
+
assert _SQLALCHEMY_ENGINE is not None
|
1169
|
+
with orm.Session(_SQLALCHEMY_ENGINE) as session:
|
1081
1170
|
count = session.query(storage_table).filter_by(
|
1082
1171
|
name=storage_name).update(
|
1083
1172
|
{storage_table.c.handle: pickle.dumps(handle)})
|
@@ -1087,25 +1176,29 @@ def set_storage_handle(storage_name: str,
|
|
1087
1176
|
raise ValueError(f'Storage{storage_name} not found.')
|
1088
1177
|
|
1089
1178
|
|
1179
|
+
@_init_db
|
1090
1180
|
def get_handle_from_storage_name(
|
1091
1181
|
storage_name: Optional[str]) -> Optional['Storage.StorageMetadata']:
|
1182
|
+
assert _SQLALCHEMY_ENGINE is not None
|
1092
1183
|
if storage_name is None:
|
1093
1184
|
return None
|
1094
|
-
with orm.Session(
|
1185
|
+
with orm.Session(_SQLALCHEMY_ENGINE) as session:
|
1095
1186
|
row = session.query(storage_table).filter_by(name=storage_name).first()
|
1096
1187
|
if row:
|
1097
1188
|
return pickle.loads(row.handle)
|
1098
1189
|
return None
|
1099
1190
|
|
1100
1191
|
|
1192
|
+
@_init_db
|
1101
1193
|
def get_glob_storage_name(storage_name: str) -> List[str]:
|
1194
|
+
assert _SQLALCHEMY_ENGINE is not None
|
1102
1195
|
assert storage_name is not None, 'storage_name cannot be None'
|
1103
|
-
with orm.Session(
|
1104
|
-
if (
|
1196
|
+
with orm.Session(_SQLALCHEMY_ENGINE) as session:
|
1197
|
+
if (_SQLALCHEMY_ENGINE.dialect.name ==
|
1105
1198
|
db_utils.SQLAlchemyDialect.SQLITE.value):
|
1106
1199
|
rows = session.query(storage_table).filter(
|
1107
1200
|
storage_table.c.name.op('GLOB')(storage_name)).all()
|
1108
|
-
elif (
|
1201
|
+
elif (_SQLALCHEMY_ENGINE.dialect.name ==
|
1109
1202
|
db_utils.SQLAlchemyDialect.POSTGRESQL.value):
|
1110
1203
|
rows = session.query(storage_table).filter(
|
1111
1204
|
storage_table.c.name.op('SIMILAR TO')(
|
@@ -1115,15 +1208,19 @@ def get_glob_storage_name(storage_name: str) -> List[str]:
|
|
1115
1208
|
return [row.name for row in rows]
|
1116
1209
|
|
1117
1210
|
|
1211
|
+
@_init_db
|
1118
1212
|
def get_storage_names_start_with(starts_with: str) -> List[str]:
|
1119
|
-
|
1213
|
+
assert _SQLALCHEMY_ENGINE is not None
|
1214
|
+
with orm.Session(_SQLALCHEMY_ENGINE) as session:
|
1120
1215
|
rows = session.query(storage_table).filter(
|
1121
1216
|
storage_table.c.name.like(f'{starts_with}%')).all()
|
1122
1217
|
return [row.name for row in rows]
|
1123
1218
|
|
1124
1219
|
|
1220
|
+
@_init_db
|
1125
1221
|
def get_storage() -> List[Dict[str, Any]]:
|
1126
|
-
|
1222
|
+
assert _SQLALCHEMY_ENGINE is not None
|
1223
|
+
with orm.Session(_SQLALCHEMY_ENGINE) as session:
|
1127
1224
|
rows = session.query(storage_table).all()
|
1128
1225
|
records = []
|
1129
1226
|
for row in rows:
|
@@ -1138,8 +1235,10 @@ def get_storage() -> List[Dict[str, Any]]:
|
|
1138
1235
|
return records
|
1139
1236
|
|
1140
1237
|
|
1238
|
+
@_init_db
|
1141
1239
|
def get_ssh_keys(user_hash: str) -> Tuple[str, str, bool]:
|
1142
|
-
|
1240
|
+
assert _SQLALCHEMY_ENGINE is not None
|
1241
|
+
with orm.Session(_SQLALCHEMY_ENGINE) as session:
|
1143
1242
|
row = session.query(ssh_key_table).filter_by(
|
1144
1243
|
user_hash=user_hash).first()
|
1145
1244
|
if row:
|
@@ -1147,12 +1246,14 @@ def get_ssh_keys(user_hash: str) -> Tuple[str, str, bool]:
|
|
1147
1246
|
return '', '', False
|
1148
1247
|
|
1149
1248
|
|
1249
|
+
@_init_db
|
1150
1250
|
def set_ssh_keys(user_hash: str, ssh_public_key: str, ssh_private_key: str):
|
1151
|
-
|
1152
|
-
|
1251
|
+
assert _SQLALCHEMY_ENGINE is not None
|
1252
|
+
with orm.Session(_SQLALCHEMY_ENGINE) as session:
|
1253
|
+
if (_SQLALCHEMY_ENGINE.dialect.name ==
|
1153
1254
|
db_utils.SQLAlchemyDialect.SQLITE.value):
|
1154
1255
|
insert_func = sqlite.insert
|
1155
|
-
elif (
|
1256
|
+
elif (_SQLALCHEMY_ENGINE.dialect.name ==
|
1156
1257
|
db_utils.SQLAlchemyDialect.POSTGRESQL.value):
|
1157
1258
|
insert_func = postgresql.insert
|
1158
1259
|
else:
|
@@ -1171,6 +1272,7 @@ def set_ssh_keys(user_hash: str, ssh_public_key: str, ssh_private_key: str):
|
|
1171
1272
|
session.commit()
|
1172
1273
|
|
1173
1274
|
|
1275
|
+
@_init_db
|
1174
1276
|
def get_cluster_yaml_str(cluster_yaml_path: Optional[str]) -> Optional[str]:
|
1175
1277
|
"""Get the cluster yaml from the database or the local file system.
|
1176
1278
|
If the cluster yaml is not in the database, check if it exists on the
|
@@ -1178,11 +1280,12 @@ def get_cluster_yaml_str(cluster_yaml_path: Optional[str]) -> Optional[str]:
|
|
1178
1280
|
|
1179
1281
|
It is assumed that the cluster yaml file is named as <cluster_name>.yml.
|
1180
1282
|
"""
|
1283
|
+
assert _SQLALCHEMY_ENGINE is not None
|
1181
1284
|
if cluster_yaml_path is None:
|
1182
1285
|
raise ValueError('Attempted to read a None YAML.')
|
1183
1286
|
cluster_file_name = os.path.basename(cluster_yaml_path)
|
1184
1287
|
cluster_name, _ = os.path.splitext(cluster_file_name)
|
1185
|
-
with orm.Session(
|
1288
|
+
with orm.Session(_SQLALCHEMY_ENGINE) as session:
|
1186
1289
|
row = session.query(cluster_yaml_table).filter_by(
|
1187
1290
|
cluster_name=cluster_name).first()
|
1188
1291
|
if row is None:
|
@@ -1210,13 +1313,15 @@ def get_cluster_yaml_dict(cluster_yaml_path: Optional[str]) -> Dict[str, Any]:
|
|
1210
1313
|
return yaml.safe_load(yaml_str)
|
1211
1314
|
|
1212
1315
|
|
1316
|
+
@_init_db
|
1213
1317
|
def set_cluster_yaml(cluster_name: str, yaml_str: str) -> None:
|
1214
1318
|
"""Set the cluster yaml in the database."""
|
1215
|
-
|
1216
|
-
|
1319
|
+
assert _SQLALCHEMY_ENGINE is not None
|
1320
|
+
with orm.Session(_SQLALCHEMY_ENGINE) as session:
|
1321
|
+
if (_SQLALCHEMY_ENGINE.dialect.name ==
|
1217
1322
|
db_utils.SQLAlchemyDialect.SQLITE.value):
|
1218
1323
|
insert_func = sqlite.insert
|
1219
|
-
elif (
|
1324
|
+
elif (_SQLALCHEMY_ENGINE.dialect.name ==
|
1220
1325
|
db_utils.SQLAlchemyDialect.POSTGRESQL.value):
|
1221
1326
|
insert_func = postgresql.insert
|
1222
1327
|
else:
|
@@ -1230,8 +1335,10 @@ def set_cluster_yaml(cluster_name: str, yaml_str: str) -> None:
|
|
1230
1335
|
session.commit()
|
1231
1336
|
|
1232
1337
|
|
1338
|
+
@_init_db
|
1233
1339
|
def remove_cluster_yaml(cluster_name: str):
|
1234
|
-
|
1340
|
+
assert _SQLALCHEMY_ENGINE is not None
|
1341
|
+
with orm.Session(_SQLALCHEMY_ENGINE) as session:
|
1235
1342
|
session.query(cluster_yaml_table).filter_by(
|
1236
1343
|
cluster_name=cluster_name).delete()
|
1237
1344
|
session.commit()
|