skypilot-nightly 1.0.0.dev20250304__py3-none-any.whl → 1.0.0.dev20250305__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 CHANGED
@@ -5,7 +5,7 @@ from typing import Optional
5
5
  import urllib.request
6
6
 
7
7
  # Replaced with the current commit when building the wheels.
8
- _SKYPILOT_COMMIT_SHA = '5c126400a3a3791b34beebd5e7b5a3717efd9505'
8
+ _SKYPILOT_COMMIT_SHA = '296a22e868b9bdf1faccbe3effbfb858a5a05905'
9
9
 
10
10
 
11
11
  def _get_git_commit():
@@ -35,7 +35,7 @@ def _get_git_commit():
35
35
 
36
36
 
37
37
  __commit__ = _get_git_commit()
38
- __version__ = '1.0.0.dev20250304'
38
+ __version__ = '1.0.0.dev20250305'
39
39
  __root_dir__ = os.path.dirname(os.path.abspath(__file__))
40
40
 
41
41
 
sky/cli.py CHANGED
@@ -3034,7 +3034,7 @@ def _down_or_stop_clusters(
3034
3034
  # with the termination.
3035
3035
  hint_or_raise(controller_name, purge)
3036
3036
  except (exceptions.ClusterOwnerIdentityMismatchError,
3037
- RuntimeError) as e:
3037
+ exceptions.NotSupportedError, RuntimeError) as e:
3038
3038
  if purge:
3039
3039
  click.echo(common_utils.format_exception(e))
3040
3040
  else:
sky/client/cli.py CHANGED
@@ -3034,7 +3034,7 @@ def _down_or_stop_clusters(
3034
3034
  # with the termination.
3035
3035
  hint_or_raise(controller_name, purge)
3036
3036
  except (exceptions.ClusterOwnerIdentityMismatchError,
3037
- RuntimeError) as e:
3037
+ exceptions.NotSupportedError, RuntimeError) as e:
3038
3038
  if purge:
3039
3039
  click.echo(common_utils.format_exception(e))
3040
3040
  else:
@@ -62,6 +62,7 @@ class JobTableColumns(enum.IntEnum):
62
62
  - FAILOVER (13): Job failover history
63
63
  - DETAILS (14): Job details
64
64
  - ACTIONS (15): Available actions column
65
+ - LOG_CONTENT (16): Log content column
65
66
  """
66
67
  DROPDOWN = 0
67
68
  ID = 1
@@ -79,13 +80,14 @@ class JobTableColumns(enum.IntEnum):
79
80
  DETAILS = 13
80
81
  FAILOVER = 14
81
82
  ACTIONS = 15
83
+ LOG_CONTENT = 16
82
84
 
83
85
 
84
86
  # Column headers matching the indices above
85
87
  JOB_TABLE_COLUMNS = [
86
88
  '', 'ID', 'Task', 'Name', 'Resources', 'Submitted', 'Total Duration',
87
89
  'Job Duration', 'Status', 'Started', 'Cluster', 'Region', 'Failover',
88
- 'Recoveries', 'Details', 'Actions'
90
+ 'Recoveries', 'Details', 'Actions', 'Log Content'
89
91
  ]
90
92
 
91
93
  # This column is given by format_job_table but should be ignored.
@@ -153,14 +155,14 @@ def home():
153
155
  status_counts[task['status'].value] += 1
154
156
 
155
157
  # Add an empty column for the dropdown button and actions column
156
- # Exclude SCHED. STATE column
158
+ # Exclude SCHED. STATE and LOG_CONTENT columns
157
159
  rows = [
158
160
  [''] + row[:SCHED_STATE_COLUMN] + row[SCHED_STATE_COLUMN + 1:] +
159
161
  # Add empty cell for failover and actions column
160
- [''] + [''] for row in rows
162
+ [''] + [''] + [''] for row in rows
161
163
  ]
162
164
 
163
- # Add log content as failover history for each job
165
+ # Add log content as a regular column for each job
164
166
  for row in rows:
165
167
  job_id = str(row[JobTableColumns.ID]).strip().replace(' ⤳', '')
166
168
  if job_id and job_id != '-':
@@ -174,17 +176,21 @@ def home():
174
176
  log_content = f.read()
175
177
  row[JobTableColumns.FAILOVER] = _extract_launch_history(
176
178
  log_content)
179
+ row[JobTableColumns.LOG_CONTENT] = log_content
177
180
  else:
178
181
  row[JobTableColumns.FAILOVER] = 'Log file not found'
182
+ row[JobTableColumns.LOG_CONTENT] = 'Log file not found'
179
183
  except (IOError, OSError) as e:
180
- row[JobTableColumns.FAILOVER] = f'Error reading log: {str(e)}'
181
- app.logger.error('All managed jobs:')
184
+ error_msg = f'Error reading log: {str(e)}'
185
+ row[JobTableColumns.FAILOVER] = error_msg
186
+ row[JobTableColumns.LOG_CONTENT] = error_msg
187
+ else:
188
+ row[JobTableColumns.LOG_CONTENT] = ''
182
189
 
183
- # Validate column count
184
190
  if rows and len(rows[0]) != len(JOB_TABLE_COLUMNS):
185
191
  raise RuntimeError(
186
192
  f'Dashboard code and managed job queue code are out of sync. '
187
- f'Expected {(JOB_TABLE_COLUMNS)} columns, got {(rows[0])}')
193
+ f'Expected {JOB_TABLE_COLUMNS} columns, got {rows[0]}')
188
194
 
189
195
  # Fix STATUS color codes: '\x1b[33mCANCELLED\x1b[0m' -> 'CANCELLED'
190
196
  for row in rows:
@@ -208,26 +214,10 @@ def home():
208
214
  last_updated_timestamp=timestamp,
209
215
  status_values=status_values,
210
216
  status_counts=status_counts,
217
+ request=flask.request,
211
218
  )
212
219
  return rendered_html
213
220
 
214
221
 
215
- @app.route('/download_log/<job_id>')
216
- def download_log(job_id):
217
- try:
218
- log_path = os.path.join(
219
- os.path.expanduser(managed_job_constants.JOBS_CONTROLLER_LOGS_DIR),
220
- f'{job_id}.log')
221
- if not os.path.exists(log_path):
222
- flask.abort(404)
223
- return flask.send_file(log_path,
224
- mimetype='text/plain',
225
- as_attachment=True,
226
- download_name=f'job_{job_id}.log')
227
- except (IOError, OSError) as e:
228
- app.logger.error(f'Error downloading log for job {job_id}: {str(e)}')
229
- flask.abort(500)
230
-
231
-
232
222
  if __name__ == '__main__':
233
223
  app.run()
@@ -498,10 +498,10 @@
498
498
  <td data-full-text="{{ row[13] }}">{{ row[13] }}</td> {# Details #}
499
499
  <td>
500
500
  {% if row[1]|string|replace(' \u21B3', '') and row[1]|string|replace(' \u21B3', '') != '-' %}
501
- <a href="{{ url_for('download_log', job_id=row[1]|string|replace(' \u21B3', '')) }}"
502
- class="btn btn-sm btn-outline-secondary">
501
+ <button class="btn btn-sm btn-outline-secondary log-btn"
502
+ data-job-id="{{ row[1]|string|replace(' \u21B3', '') }}">
503
503
  controller log
504
- </a>
504
+ </button>
505
505
  {% endif %}
506
506
  </td>
507
507
  </tr>
@@ -509,6 +509,41 @@
509
509
  </tbody>
510
510
  </table>
511
511
  </div>
512
+
513
+ <!-- Hidden container for log content -->
514
+ <div style="display: none;">
515
+ {% for row in rows %}
516
+ {% if row[1]|string|replace(' \u21B3', '') and row[1]|string|replace(' \u21B3', '') != '-' %}
517
+ <pre id="log-content-{{ row[1]|string|replace(' \u21B3', '') }}">{{ row[-1]|e }}</pre>
518
+ {% endif %}
519
+ {% endfor %}
520
+ </div>
521
+
522
+ <!-- Log Modal -->
523
+ <div class="modal fade" id="logModal" tabindex="-1" aria-labelledby="logModalLabel" aria-hidden="true">
524
+ <div class="modal-dialog modal-dialog-centered modal-lg">
525
+ <div class="modal-content">
526
+ <div class="modal-header">
527
+ <h5 class="modal-title" id="logModalLabel">Controller Log</h5>
528
+ <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
529
+ </div>
530
+ <div class="modal-body">
531
+ <div id="logContent" style="white-space: pre-wrap; font-family: monospace; max-height: 70vh; overflow-y: auto; font-size: 0.85rem;"></div>
532
+ <div id="logError" class="alert alert-danger d-none">
533
+ Error loading log content. Please try again.
534
+ </div>
535
+ </div>
536
+ <div class="modal-footer">
537
+ <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
538
+ <a id="downloadLogBtn" href="#" class="btn btn-primary" download>Download</a>
539
+ </div>
540
+ </div>
541
+ </div>
542
+ </div>
543
+
544
+ <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"
545
+ integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4"
546
+ crossorigin="anonymous"></script>
512
547
  <script>
513
548
  // Folder toggle for pipelines, this will fold/unfold the rows for
514
549
  // a pipeline and its tasks.
@@ -729,6 +764,68 @@
729
764
  });
730
765
  });
731
766
  </script>
767
+ <script>
768
+ // Function to show log modal and display pre-loaded log content
769
+ function showLogModal(jobId, logContent) {
770
+ try {
771
+ // Initialize modal
772
+ const logModal = new bootstrap.Modal(document.getElementById('logModal'));
773
+ const logContentEl = document.getElementById('logContent');
774
+ const logError = document.getElementById('logError');
775
+ const downloadBtn = document.getElementById('downloadLogBtn');
776
+
777
+ // Create a Blob for download functionality
778
+ const blob = new Blob([logContent], { type: 'text/plain' });
779
+ const url = URL.createObjectURL(blob);
780
+
781
+ // Set download button href
782
+ downloadBtn.href = url;
783
+ downloadBtn.setAttribute('download', `job_${jobId}.log`);
784
+
785
+ // Clear previous content and show new content directly
786
+ logContentEl.textContent = logContent || 'No log content available';
787
+ logError.classList.add('d-none');
788
+
789
+ // Set modal title
790
+ document.getElementById('logModalLabel').textContent = `Controller Log - Job ${jobId}`;
791
+
792
+ // Show modal
793
+ logModal.show();
794
+
795
+ // Cleanup the URL object when the modal is hidden
796
+ document.getElementById('logModal').addEventListener('hidden.bs.modal', function() {
797
+ URL.revokeObjectURL(url);
798
+ }, { once: true });
799
+ } catch (error) {
800
+ console.error('Error showing log modal:', error);
801
+ document.getElementById('logError').classList.remove('d-none');
802
+ document.getElementById('logError').textContent = `Error showing log: ${error.message}`;
803
+ }
804
+ }
805
+
806
+ // Add event listeners for log buttons
807
+ document.addEventListener('DOMContentLoaded', function() {
808
+ document.addEventListener('click', function(event) {
809
+ if (event.target.closest('.log-btn')) {
810
+ try {
811
+ const button = event.target.closest('.log-btn');
812
+ const jobId = button.dataset.jobId;
813
+ const logContentEl = document.getElementById(`log-content-${jobId}`);
814
+
815
+ if (!logContentEl) {
816
+ throw new Error(`Log content element not found for job ${jobId}`);
817
+ }
818
+
819
+ const logContent = logContentEl.textContent;
820
+ showLogModal(jobId, logContent);
821
+ } catch (error) {
822
+ console.error('Error getting log content:', error);
823
+ showLogModal(jobId, `Error loading log: ${error.message}`);
824
+ }
825
+ }
826
+ });
827
+ });
828
+ </script>
732
829
  </body>
733
830
 
734
831
  </html>
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: skypilot-nightly
3
- Version: 1.0.0.dev20250304
3
+ Version: 1.0.0.dev20250305
4
4
  Summary: SkyPilot: An intercloud broker for the clouds
5
5
  Author: SkyPilot Team
6
6
  License: Apache 2.0
@@ -1,8 +1,8 @@
1
- sky/__init__.py,sha256=nBS4cQvvG4s3GLt8Ueva04qVaT4Zdxdxpq8oD7kS2SI,6428
1
+ sky/__init__.py,sha256=jx4qQ0KP5eTx7b33ZojeC61vkrA5H7sULXcKLW-vL00,6428
2
2
  sky/admin_policy.py,sha256=hPo02f_A32gCqhUueF0QYy1fMSSKqRwYEg_9FxScN_s,3248
3
3
  sky/authentication.py,sha256=hCEqi77nprQEg3ktfRL51xiiw16zwZOmFEDB_Z7fWVU,22384
4
4
  sky/check.py,sha256=NDKx_Zm7YRxPjMv82wz3ESLnGIPljaACyqVdVNM0PzY,11258
5
- sky/cli.py,sha256=FDCSA5L__Djdk2Dc5eAmbE0YsfEu9zdE8vSu51oA19Q,221469
5
+ sky/cli.py,sha256=ditGQ-K92yDT_f3a4xqjcqTU1ql33BE4uIy-ArX3BV0,221499
6
6
  sky/cloud_stores.py,sha256=kEHXd2divyra-1c3EusHxKyM5yTQlTXc6cKVXofsefA,23978
7
7
  sky/core.py,sha256=MU9hcTdh8baMGrr2ZXmbxx12vNlhajrkeyg5QtV717c,47609
8
8
  sky/dag.py,sha256=Yl7Ry26Vql5cv4YMz8g9kOUgtoCihJnw7c8NgZYakMY,3242
@@ -43,7 +43,7 @@ sky/benchmark/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
43
43
  sky/benchmark/benchmark_state.py,sha256=X8CXmuU9KgsDRhKedhFgjeRMUFWtQsjFs1qECvPG2yg,8723
44
44
  sky/benchmark/benchmark_utils.py,sha256=o4RymqSceq5mLEZL0upQM6NVEzJJQzj9s9tTm49uUTc,26365
45
45
  sky/client/__init__.py,sha256=pz6xvVSd9X-gwqbsDL0E9QOojYqM0KAD0j-NCyCIF1k,38
46
- sky/client/cli.py,sha256=FDCSA5L__Djdk2Dc5eAmbE0YsfEu9zdE8vSu51oA19Q,221469
46
+ sky/client/cli.py,sha256=ditGQ-K92yDT_f3a4xqjcqTU1ql33BE4uIy-ArX3BV0,221499
47
47
  sky/client/common.py,sha256=axDic7WOG1e78SdFm5XIwdhX7YNvf3g4k7INrsW3X4s,14611
48
48
  sky/client/sdk.py,sha256=IRx72BXqOn_WVvtOuTXfgR5zcSm_lyoXeYxa5c_2_qk,68723
49
49
  sky/clouds/__init__.py,sha256=OW6mJ-9hpJSBORCgt2LippLQEYZHNfnBW1mooRNNvxo,1416
@@ -115,9 +115,9 @@ sky/jobs/state.py,sha256=tDULLH6DVs4oKUIKhh0UAn3RzyVGuIUtEq5kW7K1Ojw,44585
115
115
  sky/jobs/utils.py,sha256=O1cOXeWXzZNxQzEZ4xwadskQr1Azm1pCRe4Ju0dfvfg,55845
116
116
  sky/jobs/client/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
117
117
  sky/jobs/client/sdk.py,sha256=4STtriCWLUq1mm-tEsh_iXC7r-U7_PY0R9X6-DNpaXs,10122
118
- sky/jobs/dashboard/dashboard.py,sha256=JaVrNUEFQPLmsDZnrR76Uo8QqcAHdgYzx7GZTxDfl9M,7885
118
+ sky/jobs/dashboard/dashboard.py,sha256=JKg8cCH_Y0sf3MoDTx85BghVEXWpp8ItPLshp09-_Js,7618
119
119
  sky/jobs/dashboard/static/favicon.ico,sha256=uYlvgxSM7gjBmXpZ8wydvZUPAbJiiix-rc2Xe5mma9s,15086
120
- sky/jobs/dashboard/templates/index.html,sha256=tz95q8O2pF7IvfY6yv0rnPyhj4DX8WX4RIVVxqFKV1Y,28519
120
+ sky/jobs/dashboard/templates/index.html,sha256=NrlTDiEHJDt7sViwWgXUSxVCyVl_IEukE5jdvN8WhtQ,33132
121
121
  sky/jobs/server/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
122
122
  sky/jobs/server/core.py,sha256=s6A3KJsSQz1GlD6qfJ-XiEg6scc3sqMTqVd1Kr6ZTIU,25113
123
123
  sky/jobs/server/dashboard_utils.py,sha256=2Mbx40W1pQqPEPHsSDbHeaF0j5cgyKy-_A9Owdwp_AQ,2315
@@ -344,9 +344,9 @@ sky/utils/kubernetes/k8s_gpu_labeler_setup.yaml,sha256=VLKT2KKimZu1GDg_4AIlIt488
344
344
  sky/utils/kubernetes/kubernetes_deploy_utils.py,sha256=otzHzpliHDCpzYT-nU9Q0ZExbiFpDPWvhxwkvchZj7k,10073
345
345
  sky/utils/kubernetes/rsync_helper.sh,sha256=h4YwrPFf9727CACnMJvF3EyK_0OeOYKKt4su_daKekw,1256
346
346
  sky/utils/kubernetes/ssh_jump_lifecycle_manager.py,sha256=Kq1MDygF2IxFmu9FXpCxqucXLmeUrvs6OtRij6XTQbo,6554
347
- skypilot_nightly-1.0.0.dev20250304.dist-info/LICENSE,sha256=emRJAvE7ngL6x0RhQvlns5wJzGI3NEQ_WMjNmd9TZc4,12170
348
- skypilot_nightly-1.0.0.dev20250304.dist-info/METADATA,sha256=jiLF-ux0ZwUp4eKySgZB9QR7PrPU24Iavg7gSuzVKcw,18173
349
- skypilot_nightly-1.0.0.dev20250304.dist-info/WHEEL,sha256=jB7zZ3N9hIM9adW7qlTAyycLYW9npaWKLRzaoVcLKcM,91
350
- skypilot_nightly-1.0.0.dev20250304.dist-info/entry_points.txt,sha256=StA6HYpuHj-Y61L2Ze-hK2IcLWgLZcML5gJu8cs6nU4,36
351
- skypilot_nightly-1.0.0.dev20250304.dist-info/top_level.txt,sha256=qA8QuiNNb6Y1OF-pCUtPEr6sLEwy2xJX06Bd_CrtrHY,4
352
- skypilot_nightly-1.0.0.dev20250304.dist-info/RECORD,,
347
+ skypilot_nightly-1.0.0.dev20250305.dist-info/LICENSE,sha256=emRJAvE7ngL6x0RhQvlns5wJzGI3NEQ_WMjNmd9TZc4,12170
348
+ skypilot_nightly-1.0.0.dev20250305.dist-info/METADATA,sha256=lAGzKAGmMJRgwB6StfHToB5grjGmOXSeJVWQbdYGkhM,18173
349
+ skypilot_nightly-1.0.0.dev20250305.dist-info/WHEEL,sha256=jB7zZ3N9hIM9adW7qlTAyycLYW9npaWKLRzaoVcLKcM,91
350
+ skypilot_nightly-1.0.0.dev20250305.dist-info/entry_points.txt,sha256=StA6HYpuHj-Y61L2Ze-hK2IcLWgLZcML5gJu8cs6nU4,36
351
+ skypilot_nightly-1.0.0.dev20250305.dist-info/top_level.txt,sha256=qA8QuiNNb6Y1OF-pCUtPEr6sLEwy2xJX06Bd_CrtrHY,4
352
+ skypilot_nightly-1.0.0.dev20250305.dist-info/RECORD,,