skypilot-nightly 1.0.0.dev20250612__py3-none-any.whl → 1.0.0.dev20250614__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. sky/__init__.py +4 -2
  2. sky/adaptors/hyperbolic.py +8 -0
  3. sky/adaptors/kubernetes.py +3 -2
  4. sky/authentication.py +20 -2
  5. sky/backends/backend_utils.py +11 -3
  6. sky/backends/cloud_vm_ray_backend.py +2 -1
  7. sky/benchmark/benchmark_state.py +2 -1
  8. sky/catalog/data_fetchers/fetch_aws.py +1 -1
  9. sky/catalog/data_fetchers/fetch_hyperbolic.py +136 -0
  10. sky/catalog/data_fetchers/fetch_vast.py +1 -1
  11. sky/catalog/hyperbolic_catalog.py +133 -0
  12. sky/check.py +2 -1
  13. sky/cli.py +1 -1
  14. sky/client/cli.py +1 -1
  15. sky/clouds/__init__.py +2 -0
  16. sky/clouds/cloud.py +1 -1
  17. sky/clouds/gcp.py +1 -1
  18. sky/clouds/hyperbolic.py +276 -0
  19. sky/clouds/kubernetes.py +8 -2
  20. sky/clouds/ssh.py +7 -3
  21. sky/dashboard/out/404.html +1 -1
  22. sky/dashboard/out/_next/static/chunks/37-7754056a4b503e1d.js +6 -0
  23. sky/dashboard/out/_next/static/chunks/600.bd2ed8c076b720ec.js +16 -0
  24. sky/dashboard/out/_next/static/chunks/{856-0776dc6ed6000c39.js → 856-c2c39c0912285e54.js} +1 -1
  25. sky/dashboard/out/_next/static/chunks/938-245c9ac4c9e8bf15.js +1 -0
  26. sky/dashboard/out/_next/static/chunks/{webpack-208a9812ab4f61c9.js → webpack-27de3d9d450d81c6.js} +1 -1
  27. sky/dashboard/out/_next/static/css/{5d71bfc09f184bab.css → 6f84444b8f3c656c.css} +1 -1
  28. sky/dashboard/out/_next/static/{G3DXdMFu2Jzd-Dody9iq1 → nm5jrKpUZh2W0SxzyDKhz}/_buildManifest.js +1 -1
  29. sky/dashboard/out/clusters/[cluster]/[job].html +1 -1
  30. sky/dashboard/out/clusters/[cluster].html +1 -1
  31. sky/dashboard/out/clusters.html +1 -1
  32. sky/dashboard/out/config.html +1 -1
  33. sky/dashboard/out/index.html +1 -1
  34. sky/dashboard/out/infra/[context].html +1 -1
  35. sky/dashboard/out/infra.html +1 -1
  36. sky/dashboard/out/jobs/[job].html +1 -1
  37. sky/dashboard/out/jobs.html +1 -1
  38. sky/dashboard/out/users.html +1 -1
  39. sky/dashboard/out/workspace/new.html +1 -1
  40. sky/dashboard/out/workspaces/[name].html +1 -1
  41. sky/dashboard/out/workspaces.html +1 -1
  42. sky/data/storage.py +2 -2
  43. sky/jobs/state.py +43 -44
  44. sky/provision/__init__.py +1 -0
  45. sky/provision/common.py +1 -1
  46. sky/provision/gcp/config.py +1 -1
  47. sky/provision/hyperbolic/__init__.py +11 -0
  48. sky/provision/hyperbolic/config.py +10 -0
  49. sky/provision/hyperbolic/instance.py +423 -0
  50. sky/provision/hyperbolic/utils.py +373 -0
  51. sky/provision/kubernetes/instance.py +2 -1
  52. sky/provision/kubernetes/utils.py +60 -13
  53. sky/resources.py +2 -2
  54. sky/serve/serve_state.py +81 -15
  55. sky/server/requests/preconditions.py +1 -1
  56. sky/server/requests/requests.py +11 -6
  57. sky/setup_files/dependencies.py +2 -1
  58. sky/skylet/configs.py +26 -19
  59. sky/skylet/constants.py +1 -1
  60. sky/skylet/job_lib.py +3 -5
  61. sky/task.py +1 -1
  62. sky/templates/hyperbolic-ray.yml.j2 +67 -0
  63. sky/templates/kubernetes-ray.yml.j2 +1 -1
  64. sky/users/permission.py +2 -0
  65. sky/utils/common_utils.py +6 -0
  66. sky/utils/context.py +1 -1
  67. sky/utils/infra_utils.py +1 -1
  68. sky/utils/kubernetes/generate_kubeconfig.sh +1 -1
  69. {skypilot_nightly-1.0.0.dev20250612.dist-info → skypilot_nightly-1.0.0.dev20250614.dist-info}/METADATA +2 -1
  70. {skypilot_nightly-1.0.0.dev20250612.dist-info → skypilot_nightly-1.0.0.dev20250614.dist-info}/RECORD +79 -70
  71. sky/dashboard/out/_next/static/chunks/37-d8aebf1683522a0b.js +0 -6
  72. sky/dashboard/out/_next/static/chunks/600.15a0009177e86b86.js +0 -16
  73. sky/dashboard/out/_next/static/chunks/938-ab185187a63f9cdb.js +0 -1
  74. /sky/dashboard/out/_next/static/chunks/{843-6fcc4bf91ac45b39.js → 843-5011affc9540757f.js} +0 -0
  75. /sky/dashboard/out/_next/static/chunks/pages/{_app-7bbd9d39d6f9a98a.js → _app-664031f6ae737f80.js} +0 -0
  76. /sky/dashboard/out/_next/static/chunks/pages/clusters/{[cluster]-451a14e7e755ebbc.js → [cluster]-20210f8cd809063d.js} +0 -0
  77. /sky/dashboard/out/_next/static/chunks/pages/{jobs-fe233baf3d073491.js → jobs-ae7a5e9fa5a5b5f0.js} +0 -0
  78. /sky/dashboard/out/_next/static/{G3DXdMFu2Jzd-Dody9iq1 → nm5jrKpUZh2W0SxzyDKhz}/_ssgManifest.js +0 -0
  79. {skypilot_nightly-1.0.0.dev20250612.dist-info → skypilot_nightly-1.0.0.dev20250614.dist-info}/WHEEL +0 -0
  80. {skypilot_nightly-1.0.0.dev20250612.dist-info → skypilot_nightly-1.0.0.dev20250614.dist-info}/entry_points.txt +0 -0
  81. {skypilot_nightly-1.0.0.dev20250612.dist-info → skypilot_nightly-1.0.0.dev20250614.dist-info}/licenses/LICENSE +0 -0
  82. {skypilot_nightly-1.0.0.dev20250612.dist-info → skypilot_nightly-1.0.0.dev20250614.dist-info}/top_level.txt +0 -0
sky/jobs/state.py CHANGED
@@ -161,8 +161,8 @@ def create_table(cursor, conn):
161
161
  conn.commit()
162
162
 
163
163
 
164
- # Module-level connection/cursor; thread-safe as the module is only imported
165
- # once.
164
+ # Module-level connection/cursor; thread-safe as the db is initialized once
165
+ # across all threads.
166
166
  def _get_db_path() -> str:
167
167
  """Workaround to collapse multi-step Path ops for type checker.
168
168
  Ensures _DB_PATH is str, avoiding Union[Path, str] inference.
@@ -173,8 +173,7 @@ def _get_db_path() -> str:
173
173
  return str(path)
174
174
 
175
175
 
176
- _DB_PATH = _get_db_path()
177
- _db_initialized = False
176
+ _DB_PATH = None
178
177
  _db_init_lock = threading.Lock()
179
178
 
180
179
 
@@ -183,13 +182,13 @@ def _init_db(func):
183
182
 
184
183
  @functools.wraps(func)
185
184
  def wrapper(*args, **kwargs):
186
- global _db_initialized
187
- if _db_initialized:
185
+ global _DB_PATH
186
+ if _DB_PATH is not None:
188
187
  return func(*args, **kwargs)
189
188
  with _db_init_lock:
190
- if not _db_initialized:
189
+ if _DB_PATH is None:
190
+ _DB_PATH = _get_db_path()
191
191
  db_utils.SQLiteConn(_DB_PATH, create_table)
192
- _db_initialized = True
193
192
  return func(*args, **kwargs)
194
193
 
195
194
  return wrapper
@@ -442,7 +441,7 @@ class ManagedJobScheduleState(enum.Enum):
442
441
  # === Status transition functions ===
443
442
  @_init_db
444
443
  def set_job_info(job_id: int, name: str, workspace: str, entrypoint: str):
445
- assert _db_initialized
444
+ assert _DB_PATH is not None
446
445
  with db_utils.safe_cursor(_DB_PATH) as cursor:
447
446
  cursor.execute(
448
447
  """\
@@ -456,7 +455,7 @@ def set_job_info(job_id: int, name: str, workspace: str, entrypoint: str):
456
455
  @_init_db
457
456
  def set_pending(job_id: int, task_id: int, task_name: str, resources_str: str):
458
457
  """Set the task to pending state."""
459
- assert _db_initialized
458
+ assert _DB_PATH is not None
460
459
  with db_utils.safe_cursor(_DB_PATH) as cursor:
461
460
  cursor.execute(
462
461
  """\
@@ -484,7 +483,7 @@ def set_starting(job_id: int, task_id: int, run_timestamp: str,
484
483
  specs: The specs of the managed task.
485
484
  callback_func: The callback function.
486
485
  """
487
- assert _db_initialized
486
+ assert _DB_PATH is not None
488
487
  # Use the timestamp in the `run_timestamp` ('sky-2022-10...'), to make
489
488
  # the log directory and submission time align with each other, so as to
490
489
  # make it easier to find them based on one of the values.
@@ -524,7 +523,7 @@ def set_backoff_pending(job_id: int, task_id: int):
524
523
  This should only be used to transition from STARTING or RECOVERING back to
525
524
  PENDING.
526
525
  """
527
- assert _db_initialized
526
+ assert _DB_PATH is not None
528
527
  with db_utils.safe_cursor(_DB_PATH) as cursor:
529
528
  cursor.execute(
530
529
  """\
@@ -552,7 +551,7 @@ def set_restarting(job_id: int, task_id: int, recovering: bool):
552
551
  after using set_backoff_pending to transition back to PENDING during
553
552
  launch retry backoff.
554
553
  """
555
- assert _db_initialized
554
+ assert _DB_PATH is not None
556
555
  target_status = ManagedJobStatus.STARTING.value
557
556
  if recovering:
558
557
  target_status = ManagedJobStatus.RECOVERING.value
@@ -578,7 +577,7 @@ def set_restarting(job_id: int, task_id: int, recovering: bool):
578
577
  def set_started(job_id: int, task_id: int, start_time: float,
579
578
  callback_func: CallbackType):
580
579
  """Set the task to started state."""
581
- assert _db_initialized
580
+ assert _DB_PATH is not None
582
581
  logger.info('Job started.')
583
582
  with db_utils.safe_cursor(_DB_PATH) as cursor:
584
583
  cursor.execute(
@@ -610,7 +609,7 @@ def set_started(job_id: int, task_id: int, start_time: float,
610
609
  @_init_db
611
610
  def set_recovering(job_id: int, task_id: int, callback_func: CallbackType):
612
611
  """Set the task to recovering state, and update the job duration."""
613
- assert _db_initialized
612
+ assert _DB_PATH is not None
614
613
  logger.info('=== Recovering... ===')
615
614
  with db_utils.safe_cursor(_DB_PATH) as cursor:
616
615
  cursor.execute(
@@ -634,7 +633,7 @@ def set_recovering(job_id: int, task_id: int, callback_func: CallbackType):
634
633
  def set_recovered(job_id: int, task_id: int, recovered_time: float,
635
634
  callback_func: CallbackType):
636
635
  """Set the task to recovered."""
637
- assert _db_initialized
636
+ assert _DB_PATH is not None
638
637
  with db_utils.safe_cursor(_DB_PATH) as cursor:
639
638
  cursor.execute(
640
639
  """\
@@ -658,7 +657,7 @@ def set_recovered(job_id: int, task_id: int, recovered_time: float,
658
657
  def set_succeeded(job_id: int, task_id: int, end_time: float,
659
658
  callback_func: CallbackType):
660
659
  """Set the task to succeeded, if it is in a non-terminal state."""
661
- assert _db_initialized
660
+ assert _DB_PATH is not None
662
661
  with db_utils.safe_cursor(_DB_PATH) as cursor:
663
662
  cursor.execute(
664
663
  """\
@@ -703,7 +702,7 @@ def set_failed(
703
702
  override_terminal: If True, override the current status even if end_at
704
703
  is already set.
705
704
  """
706
- assert _db_initialized
705
+ assert _DB_PATH is not None
707
706
  assert failure_type.is_failed(), failure_type
708
707
  end_time = time.time() if end_time is None else end_time
709
708
 
@@ -761,7 +760,7 @@ def set_cancelling(job_id: int, callback_func: CallbackType):
761
760
  task_id is not needed, because we expect the job should be cancelled
762
761
  as a whole, and we should not cancel a single task.
763
762
  """
764
- assert _db_initialized
763
+ assert _DB_PATH is not None
765
764
  with db_utils.safe_cursor(_DB_PATH) as cursor:
766
765
  rows = cursor.execute(
767
766
  """\
@@ -783,7 +782,7 @@ def set_cancelled(job_id: int, callback_func: CallbackType):
783
782
 
784
783
  The set_cancelling should be called before this function.
785
784
  """
786
- assert _db_initialized
785
+ assert _DB_PATH is not None
787
786
  with db_utils.safe_cursor(_DB_PATH) as cursor:
788
787
  rows = cursor.execute(
789
788
  """\
@@ -804,7 +803,7 @@ def set_cancelled(job_id: int, callback_func: CallbackType):
804
803
  def set_local_log_file(job_id: int, task_id: Optional[int],
805
804
  local_log_file: str):
806
805
  """Set the local log file for a job."""
807
- assert _db_initialized
806
+ assert _DB_PATH is not None
808
807
  filter_str = 'spot_job_id=(?)'
809
808
  filter_args = [local_log_file, job_id]
810
809
 
@@ -822,7 +821,7 @@ def set_local_log_file(job_id: int, task_id: Optional[int],
822
821
  def get_nonterminal_job_ids_by_name(name: Optional[str],
823
822
  all_users: bool = False) -> List[int]:
824
823
  """Get non-terminal job ids by name."""
825
- assert _db_initialized
824
+ assert _DB_PATH is not None
826
825
  statuses = ', '.join(['?'] * len(ManagedJobStatus.terminal_statuses()))
827
826
  field_values = [
828
827
  status.value for status in ManagedJobStatus.terminal_statuses()
@@ -866,7 +865,7 @@ def get_schedule_live_jobs(job_id: Optional[int]) -> List[Dict[str, Any]]:
866
865
  exception: the job may have just transitioned from WAITING to LAUNCHING, but
867
866
  the controller process has not yet started.
868
867
  """
869
- assert _db_initialized
868
+ assert _DB_PATH is not None
870
869
  job_filter = '' if job_id is None else 'AND spot_job_id=(?)'
871
870
  job_value = (job_id,) if job_id is not None else ()
872
871
 
@@ -909,7 +908,7 @@ def get_jobs_to_check_status(job_id: Optional[int] = None) -> List[int]:
909
908
  - Jobs have schedule_state DONE but are in a non-terminal status
910
909
  - Legacy jobs (that is, no schedule state) that are in non-terminal status
911
910
  """
912
- assert _db_initialized
911
+ assert _DB_PATH is not None
913
912
  job_filter = '' if job_id is None else 'AND spot.spot_job_id=(?)'
914
913
  job_value = () if job_id is None else (job_id,)
915
914
 
@@ -958,7 +957,7 @@ def get_jobs_to_check_status(job_id: Optional[int] = None) -> List[int]:
958
957
  @_init_db
959
958
  def get_all_job_ids_by_name(name: Optional[str]) -> List[int]:
960
959
  """Get all job ids by name."""
961
- assert _db_initialized
960
+ assert _DB_PATH is not None
962
961
  name_filter = ''
963
962
  field_values = []
964
963
  if name is not None:
@@ -987,7 +986,7 @@ def get_all_job_ids_by_name(name: Optional[str]) -> List[int]:
987
986
  @_init_db
988
987
  def _get_all_task_ids_statuses(
989
988
  job_id: int) -> List[Tuple[int, ManagedJobStatus]]:
990
- assert _db_initialized
989
+ assert _DB_PATH is not None
991
990
  with db_utils.safe_cursor(_DB_PATH) as cursor:
992
991
  id_statuses = cursor.execute(
993
992
  """\
@@ -1035,7 +1034,7 @@ def get_failure_reason(job_id: int) -> Optional[str]:
1035
1034
 
1036
1035
  If the job has multiple tasks, we return the first failure reason.
1037
1036
  """
1038
- assert _db_initialized
1037
+ assert _DB_PATH is not None
1039
1038
  with db_utils.safe_cursor(_DB_PATH) as cursor:
1040
1039
  reason = cursor.execute(
1041
1040
  """\
@@ -1051,7 +1050,7 @@ def get_failure_reason(job_id: int) -> Optional[str]:
1051
1050
  @_init_db
1052
1051
  def get_managed_jobs(job_id: Optional[int] = None) -> List[Dict[str, Any]]:
1053
1052
  """Get managed jobs from the database."""
1054
- assert _db_initialized
1053
+ assert _DB_PATH is not None
1055
1054
  job_filter = '' if job_id is None else f'WHERE spot.spot_job_id={job_id}'
1056
1055
 
1057
1056
  # Join spot and job_info tables to get the job name for each task.
@@ -1097,7 +1096,7 @@ def get_managed_jobs(job_id: Optional[int] = None) -> List[Dict[str, Any]]:
1097
1096
  @_init_db
1098
1097
  def get_task_name(job_id: int, task_id: int) -> str:
1099
1098
  """Get the task name of a job."""
1100
- assert _db_initialized
1099
+ assert _DB_PATH is not None
1101
1100
  with db_utils.safe_cursor(_DB_PATH) as cursor:
1102
1101
  task_name = cursor.execute(
1103
1102
  """\
@@ -1110,7 +1109,7 @@ def get_task_name(job_id: int, task_id: int) -> str:
1110
1109
  @_init_db
1111
1110
  def get_latest_job_id() -> Optional[int]:
1112
1111
  """Get the latest job id."""
1113
- assert _db_initialized
1112
+ assert _DB_PATH is not None
1114
1113
  with db_utils.safe_cursor(_DB_PATH) as cursor:
1115
1114
  rows = cursor.execute("""\
1116
1115
  SELECT spot_job_id FROM spot
@@ -1123,7 +1122,7 @@ def get_latest_job_id() -> Optional[int]:
1123
1122
 
1124
1123
  @_init_db
1125
1124
  def get_task_specs(job_id: int, task_id: int) -> Dict[str, Any]:
1126
- assert _db_initialized
1125
+ assert _DB_PATH is not None
1127
1126
  with db_utils.safe_cursor(_DB_PATH) as cursor:
1128
1127
  task_specs = cursor.execute(
1129
1128
  """\
@@ -1136,7 +1135,7 @@ def get_task_specs(job_id: int, task_id: int) -> Dict[str, Any]:
1136
1135
  @_init_db
1137
1136
  def get_local_log_file(job_id: int, task_id: Optional[int]) -> Optional[str]:
1138
1137
  """Get the local log directory for a job."""
1139
- assert _db_initialized
1138
+ assert _DB_PATH is not None
1140
1139
  filter_str = 'spot_job_id=(?)'
1141
1140
  filter_args = [job_id]
1142
1141
  if task_id is not None:
@@ -1159,7 +1158,7 @@ def scheduler_set_waiting(job_id: int, dag_yaml_path: str,
1159
1158
  original_user_yaml_path: str, env_file_path: str,
1160
1159
  user_hash: str, priority: int) -> None:
1161
1160
  """Do not call without holding the scheduler lock."""
1162
- assert _db_initialized
1161
+ assert _DB_PATH is not None
1163
1162
  with db_utils.safe_cursor(_DB_PATH) as cursor:
1164
1163
  updated_count = cursor.execute(
1165
1164
  'UPDATE job_info SET '
@@ -1177,7 +1176,7 @@ def scheduler_set_waiting(job_id: int, dag_yaml_path: str,
1177
1176
  def scheduler_set_launching(job_id: int,
1178
1177
  current_state: ManagedJobScheduleState) -> None:
1179
1178
  """Do not call without holding the scheduler lock."""
1180
- assert _db_initialized
1179
+ assert _DB_PATH is not None
1181
1180
  with db_utils.safe_cursor(_DB_PATH) as cursor:
1182
1181
  updated_count = cursor.execute(
1183
1182
  'UPDATE job_info SET '
@@ -1191,7 +1190,7 @@ def scheduler_set_launching(job_id: int,
1191
1190
  @_init_db
1192
1191
  def scheduler_set_alive(job_id: int) -> None:
1193
1192
  """Do not call without holding the scheduler lock."""
1194
- assert _db_initialized
1193
+ assert _DB_PATH is not None
1195
1194
  with db_utils.safe_cursor(_DB_PATH) as cursor:
1196
1195
  updated_count = cursor.execute(
1197
1196
  'UPDATE job_info SET '
@@ -1205,7 +1204,7 @@ def scheduler_set_alive(job_id: int) -> None:
1205
1204
  @_init_db
1206
1205
  def scheduler_set_alive_backoff(job_id: int) -> None:
1207
1206
  """Do not call without holding the scheduler lock."""
1208
- assert _db_initialized
1207
+ assert _DB_PATH is not None
1209
1208
  with db_utils.safe_cursor(_DB_PATH) as cursor:
1210
1209
  updated_count = cursor.execute(
1211
1210
  'UPDATE job_info SET '
@@ -1219,7 +1218,7 @@ def scheduler_set_alive_backoff(job_id: int) -> None:
1219
1218
  @_init_db
1220
1219
  def scheduler_set_alive_waiting(job_id: int) -> None:
1221
1220
  """Do not call without holding the scheduler lock."""
1222
- assert _db_initialized
1221
+ assert _DB_PATH is not None
1223
1222
  with db_utils.safe_cursor(_DB_PATH) as cursor:
1224
1223
  updated_count = cursor.execute(
1225
1224
  'UPDATE job_info SET '
@@ -1234,7 +1233,7 @@ def scheduler_set_alive_waiting(job_id: int) -> None:
1234
1233
  @_init_db
1235
1234
  def scheduler_set_done(job_id: int, idempotent: bool = False) -> None:
1236
1235
  """Do not call without holding the scheduler lock."""
1237
- assert _db_initialized
1236
+ assert _DB_PATH is not None
1238
1237
  with db_utils.safe_cursor(_DB_PATH) as cursor:
1239
1238
  updated_count = cursor.execute(
1240
1239
  'UPDATE job_info SET '
@@ -1248,7 +1247,7 @@ def scheduler_set_done(job_id: int, idempotent: bool = False) -> None:
1248
1247
 
1249
1248
  @_init_db
1250
1249
  def set_job_controller_pid(job_id: int, pid: int):
1251
- assert _db_initialized
1250
+ assert _DB_PATH is not None
1252
1251
  with db_utils.safe_cursor(_DB_PATH) as cursor:
1253
1252
  updated_count = cursor.execute(
1254
1253
  'UPDATE job_info SET '
@@ -1259,7 +1258,7 @@ def set_job_controller_pid(job_id: int, pid: int):
1259
1258
 
1260
1259
  @_init_db
1261
1260
  def get_job_schedule_state(job_id: int) -> ManagedJobScheduleState:
1262
- assert _db_initialized
1261
+ assert _DB_PATH is not None
1263
1262
  with db_utils.safe_cursor(_DB_PATH) as cursor:
1264
1263
  state = cursor.execute(
1265
1264
  'SELECT schedule_state FROM job_info WHERE spot_job_id = (?)',
@@ -1269,7 +1268,7 @@ def get_job_schedule_state(job_id: int) -> ManagedJobScheduleState:
1269
1268
 
1270
1269
  @_init_db
1271
1270
  def get_num_launching_jobs() -> int:
1272
- assert _db_initialized
1271
+ assert _DB_PATH is not None
1273
1272
  with db_utils.safe_cursor(_DB_PATH) as cursor:
1274
1273
  return cursor.execute(
1275
1274
  'SELECT COUNT(*) '
@@ -1280,7 +1279,7 @@ def get_num_launching_jobs() -> int:
1280
1279
 
1281
1280
  @_init_db
1282
1281
  def get_num_alive_jobs() -> int:
1283
- assert _db_initialized
1282
+ assert _DB_PATH is not None
1284
1283
  with db_utils.safe_cursor(_DB_PATH) as cursor:
1285
1284
  return cursor.execute(
1286
1285
  'SELECT COUNT(*) '
@@ -1303,7 +1302,7 @@ def get_waiting_job() -> Optional[Dict[str, Any]]:
1303
1302
  Backwards compatibility note: jobs submitted before #4485 will have no
1304
1303
  schedule_state and will be ignored by this SQL query.
1305
1304
  """
1306
- assert _db_initialized
1305
+ assert _DB_PATH is not None
1307
1306
  with db_utils.safe_cursor(_DB_PATH) as cursor:
1308
1307
  # Get the highest-priority WAITING or ALIVE_WAITING job whose priority
1309
1308
  # is greater than or equal to the highest priority LAUNCHING or
@@ -1338,7 +1337,7 @@ def get_waiting_job() -> Optional[Dict[str, Any]]:
1338
1337
  @_init_db
1339
1338
  def get_workspace(job_id: int) -> str:
1340
1339
  """Get the workspace of a job."""
1341
- assert _db_initialized
1340
+ assert _DB_PATH is not None
1342
1341
  with db_utils.safe_cursor(_DB_PATH) as cursor:
1343
1342
  workspace = cursor.execute(
1344
1343
  'SELECT workspace FROM job_info WHERE spot_job_id = (?)',
sky/provision/__init__.py CHANGED
@@ -18,6 +18,7 @@ from sky.provision import common
18
18
  from sky.provision import cudo
19
19
  from sky.provision import fluidstack
20
20
  from sky.provision import gcp
21
+ from sky.provision import hyperbolic
21
22
  from sky.provision import kubernetes
22
23
  from sky.provision import lambda_cloud
23
24
  from sky.provision import nebius
sky/provision/common.py CHANGED
@@ -238,7 +238,7 @@ class Endpoint:
238
238
 
239
239
  @dataclasses.dataclass
240
240
  class SocketEndpoint(Endpoint):
241
- """Socket endpoint accesible via a host and a port."""
241
+ """Socket endpoint accessible via a host and a port."""
242
242
  port: Optional[int]
243
243
  host: str = ''
244
244
 
@@ -274,7 +274,7 @@ def _is_permission_satisfied(service_account, crm, iam, required_permissions,
274
274
  # For example, `roles/iam.serviceAccountUser` can be granted at the
275
275
  # skypilot-v1 service account level, which can be checked with
276
276
  # service_account_policy = iam.projects().serviceAccounts().getIamPolicy(
277
- # resource=f'projects/{project_id}/serviceAcccounts/{email}').execute()
277
+ # resource=f'projects/{project_id}/serviceAccounts/{email}').execute()
278
278
  # We now skip the check for `iam.serviceAccounts.actAs` permission for
279
279
  # simplicity as it can be granted at the service account level.
280
280
  def check_permissions(policy, required_permissions):
@@ -0,0 +1,11 @@
1
+ """Hyperbolic provisioner for SkyPilot."""
2
+
3
+ from sky.provision.hyperbolic.config import bootstrap_instances
4
+ from sky.provision.hyperbolic.instance import cleanup_ports
5
+ from sky.provision.hyperbolic.instance import get_cluster_info
6
+ from sky.provision.hyperbolic.instance import open_ports
7
+ from sky.provision.hyperbolic.instance import query_instances
8
+ from sky.provision.hyperbolic.instance import run_instances
9
+ from sky.provision.hyperbolic.instance import stop_instances
10
+ from sky.provision.hyperbolic.instance import terminate_instances
11
+ from sky.provision.hyperbolic.instance import wait_instances
@@ -0,0 +1,10 @@
1
+ """Hyperbolic Cloud configuration bootstrapping"""
2
+
3
+ from sky.provision import common
4
+
5
+
6
+ def bootstrap_instances(
7
+ region: str, cluster_name: str,
8
+ config: common.ProvisionConfig) -> common.ProvisionConfig:
9
+ del region, cluster_name # unused
10
+ return config