skypilot-nightly 1.0.0.dev20251029__py3-none-any.whl → 1.0.0.dev20251101__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of skypilot-nightly might be problematic. Click here for more details.
- sky/__init__.py +2 -2
- sky/adaptors/aws.py +25 -7
- sky/client/cli/command.py +47 -23
- sky/clouds/aws.py +59 -11
- sky/dashboard/out/404.html +1 -1
- sky/dashboard/out/_next/static/chunks/2755.d6dc6d530fed0b61.js +26 -0
- sky/dashboard/out/_next/static/chunks/{webpack-485984ca04e021d0.js → webpack-e38d5319cd10a3a0.js} +1 -1
- 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/pools/[pool].html +1 -1
- sky/dashboard/out/jobs.html +1 -1
- sky/dashboard/out/users.html +1 -1
- sky/dashboard/out/volumes.html +1 -1
- sky/dashboard/out/workspace/new.html +1 -1
- sky/dashboard/out/workspaces/[name].html +1 -1
- sky/dashboard/out/workspaces.html +1 -1
- sky/data/mounting_utils.py +32 -2
- sky/jobs/constants.py +2 -0
- sky/jobs/controller.py +62 -67
- sky/jobs/file_content_utils.py +80 -0
- sky/jobs/log_gc.py +201 -0
- sky/jobs/scheduler.py +15 -2
- sky/jobs/server/core.py +85 -13
- sky/jobs/server/server.py +12 -11
- sky/jobs/server/utils.py +28 -10
- sky/jobs/state.py +216 -40
- sky/jobs/utils.py +60 -22
- sky/metrics/utils.py +18 -0
- sky/schemas/api/responses.py +1 -0
- sky/schemas/db/spot_jobs/004_job_file_contents.py +42 -0
- sky/schemas/db/spot_jobs/005_logs_gc.py +38 -0
- sky/schemas/generated/managed_jobsv1_pb2.py +39 -35
- sky/schemas/generated/managed_jobsv1_pb2.pyi +21 -5
- sky/serve/server/server.py +8 -7
- sky/server/common.py +21 -15
- sky/server/constants.py +1 -1
- sky/server/daemons.py +23 -17
- sky/server/requests/executor.py +7 -3
- sky/server/requests/request_names.py +80 -0
- sky/server/server.py +103 -35
- sky/skylet/constants.py +6 -1
- sky/skylet/events.py +7 -0
- sky/skylet/services.py +18 -7
- sky/ssh_node_pools/server.py +5 -4
- sky/task.py +4 -42
- sky/templates/kubernetes-ray.yml.j2 +1 -1
- sky/templates/websocket_proxy.py +140 -12
- sky/users/permission.py +4 -1
- sky/utils/db/migration_utils.py +1 -1
- sky/utils/resource_checker.py +4 -1
- sky/utils/schemas.py +23 -4
- sky/volumes/server/server.py +4 -3
- sky/workspaces/server.py +7 -6
- {skypilot_nightly-1.0.0.dev20251029.dist-info → skypilot_nightly-1.0.0.dev20251101.dist-info}/METADATA +36 -36
- {skypilot_nightly-1.0.0.dev20251029.dist-info → skypilot_nightly-1.0.0.dev20251101.dist-info}/RECORD +67 -62
- sky/dashboard/out/_next/static/chunks/2755.a239c652bf8684dd.js +0 -26
- /sky/dashboard/out/_next/static/{DabuSAKsc_y0wyJxpTIdQ → 8ixeA0NVQJN8HUdijid8b}/_buildManifest.js +0 -0
- /sky/dashboard/out/_next/static/{DabuSAKsc_y0wyJxpTIdQ → 8ixeA0NVQJN8HUdijid8b}/_ssgManifest.js +0 -0
- {skypilot_nightly-1.0.0.dev20251029.dist-info → skypilot_nightly-1.0.0.dev20251101.dist-info}/WHEEL +0 -0
- {skypilot_nightly-1.0.0.dev20251029.dist-info → skypilot_nightly-1.0.0.dev20251101.dist-info}/entry_points.txt +0 -0
- {skypilot_nightly-1.0.0.dev20251029.dist-info → skypilot_nightly-1.0.0.dev20251101.dist-info}/licenses/LICENSE +0 -0
- {skypilot_nightly-1.0.0.dev20251029.dist-info → skypilot_nightly-1.0.0.dev20251101.dist-info}/top_level.txt +0 -0
sky/templates/websocket_proxy.py
CHANGED
|
@@ -11,15 +11,23 @@ This script is useful for users who do not have local Kubernetes credentials.
|
|
|
11
11
|
import asyncio
|
|
12
12
|
from http.cookiejar import MozillaCookieJar
|
|
13
13
|
import os
|
|
14
|
+
import struct
|
|
14
15
|
import sys
|
|
15
|
-
|
|
16
|
+
import time
|
|
17
|
+
from typing import Dict, Optional
|
|
16
18
|
from urllib.request import Request
|
|
17
19
|
|
|
20
|
+
import requests
|
|
18
21
|
import websockets
|
|
19
22
|
from websockets.asyncio.client import ClientConnection
|
|
20
23
|
from websockets.asyncio.client import connect
|
|
21
24
|
|
|
25
|
+
from sky.server import constants
|
|
26
|
+
from sky.server.server import KubernetesSSHMessageType
|
|
27
|
+
from sky.skylet import constants as skylet_constants
|
|
28
|
+
|
|
22
29
|
BUFFER_SIZE = 2**16 # 64KB
|
|
30
|
+
HEARTBEAT_INTERVAL_SECONDS = 10
|
|
23
31
|
|
|
24
32
|
# Environment variable for a file path to the API cookie file.
|
|
25
33
|
# Keep in sync with server/constants.py
|
|
@@ -28,6 +36,8 @@ API_COOKIE_FILE_ENV_VAR = 'SKYPILOT_API_COOKIE_FILE'
|
|
|
28
36
|
# Keep in sync with server/constants.py
|
|
29
37
|
API_COOKIE_FILE_DEFAULT_LOCATION = '~/.sky/cookies.txt'
|
|
30
38
|
|
|
39
|
+
MAX_UNANSWERED_PINGS = 100
|
|
40
|
+
|
|
31
41
|
|
|
32
42
|
def _get_cookie_header(url: str) -> Dict[str, str]:
|
|
33
43
|
"""Extract Cookie header value from a cookie jar for a specific URL"""
|
|
@@ -49,7 +59,7 @@ def _get_cookie_header(url: str) -> Dict[str, str]:
|
|
|
49
59
|
return {'Cookie': cookie_header}
|
|
50
60
|
|
|
51
61
|
|
|
52
|
-
async def main(url: str) -> None:
|
|
62
|
+
async def main(url: str, timestamps_supported: bool) -> None:
|
|
53
63
|
cookie_header = _get_cookie_header(url)
|
|
54
64
|
async with connect(url,
|
|
55
65
|
ping_interval=None,
|
|
@@ -75,45 +85,149 @@ async def main(url: str) -> None:
|
|
|
75
85
|
asyncio.streams.FlowControlMixin, sys.stdout) # type: ignore
|
|
76
86
|
stdout_writer = asyncio.StreamWriter(transport, protocol, None,
|
|
77
87
|
loop)
|
|
88
|
+
# Dictionary to store last ping time for latency measurement
|
|
89
|
+
last_ping_time_dict: Optional[Dict[int, float]] = None
|
|
90
|
+
if timestamps_supported:
|
|
91
|
+
last_ping_time_dict = {}
|
|
92
|
+
|
|
93
|
+
# Use an Event to signal when websocket is closed
|
|
94
|
+
websocket_closed_event = asyncio.Event()
|
|
95
|
+
websocket_lock = asyncio.Lock()
|
|
78
96
|
|
|
79
|
-
await asyncio.gather(
|
|
80
|
-
|
|
97
|
+
await asyncio.gather(
|
|
98
|
+
stdin_to_websocket(stdin_reader, websocket,
|
|
99
|
+
timestamps_supported, websocket_closed_event,
|
|
100
|
+
websocket_lock),
|
|
101
|
+
websocket_to_stdout(websocket, stdout_writer,
|
|
102
|
+
timestamps_supported, last_ping_time_dict,
|
|
103
|
+
websocket_closed_event, websocket_lock),
|
|
104
|
+
latency_monitor(websocket, last_ping_time_dict,
|
|
105
|
+
websocket_closed_event, websocket_lock),
|
|
106
|
+
return_exceptions=True)
|
|
81
107
|
finally:
|
|
82
108
|
if old_settings:
|
|
83
109
|
termios.tcsetattr(sys.stdin.fileno(), termios.TCSADRAIN,
|
|
84
110
|
old_settings)
|
|
85
111
|
|
|
86
112
|
|
|
113
|
+
async def latency_monitor(websocket: ClientConnection,
|
|
114
|
+
last_ping_time_dict: Optional[dict],
|
|
115
|
+
websocket_closed_event: asyncio.Event,
|
|
116
|
+
websocket_lock: asyncio.Lock):
|
|
117
|
+
"""Periodically send PING messages (type 1) to measure latency."""
|
|
118
|
+
if last_ping_time_dict is None:
|
|
119
|
+
return
|
|
120
|
+
next_id = 0
|
|
121
|
+
while not websocket_closed_event.is_set():
|
|
122
|
+
try:
|
|
123
|
+
await asyncio.sleep(HEARTBEAT_INTERVAL_SECONDS)
|
|
124
|
+
if len(last_ping_time_dict) >= MAX_UNANSWERED_PINGS:
|
|
125
|
+
# We are not getting responses, clear the dictionary so
|
|
126
|
+
# as not to grow unbounded.
|
|
127
|
+
last_ping_time_dict.clear()
|
|
128
|
+
ping_time = time.time()
|
|
129
|
+
next_id += 1
|
|
130
|
+
last_ping_time_dict[next_id] = ping_time
|
|
131
|
+
message_header_bytes = struct.pack(
|
|
132
|
+
'!BI', KubernetesSSHMessageType.PINGPONG.value, next_id)
|
|
133
|
+
try:
|
|
134
|
+
async with websocket_lock:
|
|
135
|
+
await websocket.send(message_header_bytes)
|
|
136
|
+
except websockets.exceptions.ConnectionClosed as e:
|
|
137
|
+
# Websocket is already closed.
|
|
138
|
+
print(f'Failed to send PING message: {e}', file=sys.stderr)
|
|
139
|
+
break
|
|
140
|
+
except Exception as e:
|
|
141
|
+
print(f'Error in latency_monitor: {e}', file=sys.stderr)
|
|
142
|
+
websocket_closed_event.set()
|
|
143
|
+
raise e
|
|
144
|
+
|
|
145
|
+
|
|
87
146
|
async def stdin_to_websocket(reader: asyncio.StreamReader,
|
|
88
|
-
websocket: ClientConnection
|
|
147
|
+
websocket: ClientConnection,
|
|
148
|
+
timestamps_supported: bool,
|
|
149
|
+
websocket_closed_event: asyncio.Event,
|
|
150
|
+
websocket_lock: asyncio.Lock):
|
|
89
151
|
try:
|
|
90
|
-
while
|
|
152
|
+
while not websocket_closed_event.is_set():
|
|
91
153
|
# Read at most BUFFER_SIZE bytes, this not affect
|
|
92
154
|
# responsiveness since it will return as soon as
|
|
93
155
|
# there is at least one byte.
|
|
94
156
|
# The BUFFER_SIZE is chosen to be large enough to improve
|
|
95
157
|
# throughput.
|
|
96
158
|
data = await reader.read(BUFFER_SIZE)
|
|
159
|
+
|
|
97
160
|
if not data:
|
|
98
161
|
break
|
|
99
|
-
|
|
162
|
+
if timestamps_supported:
|
|
163
|
+
# Send message with type 0 to indicate data.
|
|
164
|
+
message_type_bytes = struct.pack(
|
|
165
|
+
'!B', KubernetesSSHMessageType.REGULAR_DATA.value)
|
|
166
|
+
data = message_type_bytes + data
|
|
167
|
+
async with websocket_lock:
|
|
168
|
+
await websocket.send(data)
|
|
169
|
+
|
|
100
170
|
except Exception as e: # pylint: disable=broad-except
|
|
101
171
|
print(f'Error in stdin_to_websocket: {e}', file=sys.stderr)
|
|
102
172
|
finally:
|
|
103
|
-
|
|
173
|
+
async with websocket_lock:
|
|
174
|
+
await websocket.close()
|
|
175
|
+
websocket_closed_event.set()
|
|
104
176
|
|
|
105
177
|
|
|
106
178
|
async def websocket_to_stdout(websocket: ClientConnection,
|
|
107
|
-
writer: asyncio.StreamWriter
|
|
179
|
+
writer: asyncio.StreamWriter,
|
|
180
|
+
timestamps_supported: bool,
|
|
181
|
+
last_ping_time_dict: Optional[dict],
|
|
182
|
+
websocket_closed_event: asyncio.Event,
|
|
183
|
+
websocket_lock: asyncio.Lock):
|
|
108
184
|
try:
|
|
109
|
-
while
|
|
185
|
+
while not websocket_closed_event.is_set():
|
|
110
186
|
message = await websocket.recv()
|
|
187
|
+
if (timestamps_supported and len(message) > 0 and
|
|
188
|
+
last_ping_time_dict is not None):
|
|
189
|
+
message_type = struct.unpack('!B', message[:1])[0]
|
|
190
|
+
if message_type == KubernetesSSHMessageType.REGULAR_DATA.value:
|
|
191
|
+
# Regular data - strip type byte and write to stdout
|
|
192
|
+
message = message[1:]
|
|
193
|
+
elif message_type == KubernetesSSHMessageType.PINGPONG.value:
|
|
194
|
+
# PONG response - calculate latency and send measurement
|
|
195
|
+
if not len(message) == struct.calcsize('!BI'):
|
|
196
|
+
raise ValueError(
|
|
197
|
+
f'Invalid PONG message length: {len(message)}')
|
|
198
|
+
pong_id = struct.unpack('!I', message[1:5])[0]
|
|
199
|
+
pong_time = time.time()
|
|
200
|
+
|
|
201
|
+
ping_time = last_ping_time_dict.pop(pong_id, None)
|
|
202
|
+
|
|
203
|
+
if ping_time is None:
|
|
204
|
+
continue
|
|
205
|
+
|
|
206
|
+
latency_seconds = pong_time - ping_time
|
|
207
|
+
latency_ms = int(latency_seconds * 1000)
|
|
208
|
+
|
|
209
|
+
# Send latency measurement (type 2)
|
|
210
|
+
message_type_bytes = struct.pack(
|
|
211
|
+
'!B',
|
|
212
|
+
KubernetesSSHMessageType.LATENCY_MEASUREMENT.value)
|
|
213
|
+
latency_bytes = struct.pack('!Q', latency_ms)
|
|
214
|
+
message = message_type_bytes + latency_bytes
|
|
215
|
+
# Send to server.
|
|
216
|
+
async with websocket_lock:
|
|
217
|
+
await websocket.send(message)
|
|
218
|
+
continue
|
|
219
|
+
# No timestamps support, write directly
|
|
111
220
|
writer.write(message)
|
|
112
221
|
await writer.drain()
|
|
113
222
|
except websockets.exceptions.ConnectionClosed:
|
|
114
223
|
print('WebSocket connection closed', file=sys.stderr)
|
|
115
224
|
except Exception as e: # pylint: disable=broad-except
|
|
116
225
|
print(f'Error in websocket_to_stdout: {e}', file=sys.stderr)
|
|
226
|
+
raise e
|
|
227
|
+
finally:
|
|
228
|
+
async with websocket_lock:
|
|
229
|
+
await websocket.close()
|
|
230
|
+
websocket_closed_event.set()
|
|
117
231
|
|
|
118
232
|
|
|
119
233
|
if __name__ == '__main__':
|
|
@@ -123,11 +237,25 @@ if __name__ == '__main__':
|
|
|
123
237
|
# TODO(aylei): Remove this after 0.10.0
|
|
124
238
|
server_url = f'http://{server_url}'
|
|
125
239
|
|
|
240
|
+
health_url = f'{server_url}/api/health'
|
|
241
|
+
health_response = requests.get(health_url)
|
|
242
|
+
health_data = health_response.json()
|
|
243
|
+
timestamps_are_supported = int(health_data['api_version']) > 21
|
|
244
|
+
disable_latency_measurement = os.environ.get(
|
|
245
|
+
skylet_constants.SSH_DISABLE_LATENCY_MEASUREMENT_ENV_VAR, '0') == '1'
|
|
246
|
+
timestamps_are_supported = (timestamps_are_supported and
|
|
247
|
+
not disable_latency_measurement)
|
|
248
|
+
|
|
126
249
|
server_proto, server_fqdn = server_url.split('://')
|
|
127
250
|
websocket_proto = 'ws'
|
|
128
251
|
if server_proto == 'https':
|
|
129
252
|
websocket_proto = 'wss'
|
|
130
253
|
server_url = f'{websocket_proto}://{server_fqdn}'
|
|
254
|
+
|
|
255
|
+
client_version_str = (f'&client_version={constants.API_VERSION}'
|
|
256
|
+
if timestamps_are_supported else '')
|
|
257
|
+
|
|
131
258
|
websocket_url = (f'{server_url}/kubernetes-pod-ssh-proxy'
|
|
132
|
-
f'?cluster_name={sys.argv[2]}'
|
|
133
|
-
|
|
259
|
+
f'?cluster_name={sys.argv[2]}'
|
|
260
|
+
f'{client_version_str}')
|
|
261
|
+
asyncio.run(main(websocket_url, timestamps_are_supported))
|
sky/users/permission.py
CHANGED
|
@@ -43,7 +43,6 @@ class PermissionService:
|
|
|
43
43
|
with _policy_lock():
|
|
44
44
|
global _enforcer_instance
|
|
45
45
|
if _enforcer_instance is None:
|
|
46
|
-
_enforcer_instance = self
|
|
47
46
|
engine = global_user_state.initialize_and_get_db()
|
|
48
47
|
db_utils.add_all_tables_to_db_sqlalchemy(
|
|
49
48
|
sqlalchemy_adapter.Base.metadata, engine)
|
|
@@ -53,6 +52,10 @@ class PermissionService:
|
|
|
53
52
|
'model.conf')
|
|
54
53
|
enforcer = casbin.Enforcer(model_path, adapter)
|
|
55
54
|
self.enforcer = enforcer
|
|
55
|
+
# Only set the enforcer instance once the enforcer
|
|
56
|
+
# is successfully initialized, if we change it and then fail
|
|
57
|
+
# we will set it to None and all subsequent calls will fail.
|
|
58
|
+
_enforcer_instance = self
|
|
56
59
|
self._maybe_initialize_policies()
|
|
57
60
|
self._maybe_initialize_basic_auth_user()
|
|
58
61
|
else:
|
sky/utils/db/migration_utils.py
CHANGED
|
@@ -22,7 +22,7 @@ GLOBAL_USER_STATE_VERSION = '010'
|
|
|
22
22
|
GLOBAL_USER_STATE_LOCK_PATH = f'~/.sky/locks/.{GLOBAL_USER_STATE_DB_NAME}.lock'
|
|
23
23
|
|
|
24
24
|
SPOT_JOBS_DB_NAME = 'spot_jobs_db'
|
|
25
|
-
SPOT_JOBS_VERSION = '
|
|
25
|
+
SPOT_JOBS_VERSION = '005'
|
|
26
26
|
SPOT_JOBS_LOCK_PATH = f'~/.sky/locks/.{SPOT_JOBS_DB_NAME}.lock'
|
|
27
27
|
|
|
28
28
|
SERVE_DB_NAME = 'serve_db'
|
sky/utils/resource_checker.py
CHANGED
|
@@ -278,7 +278,10 @@ def _get_active_resources(
|
|
|
278
278
|
from sky.jobs.server import core as managed_jobs_core
|
|
279
279
|
try:
|
|
280
280
|
filtered_jobs, _, _, _ = managed_jobs_core.queue_v2(
|
|
281
|
-
refresh=False,
|
|
281
|
+
refresh=False,
|
|
282
|
+
skip_finished=True,
|
|
283
|
+
all_users=True,
|
|
284
|
+
fields=['job_id', 'user_hash', 'workspace'])
|
|
282
285
|
return filtered_jobs
|
|
283
286
|
except exceptions.ClusterNotUpError:
|
|
284
287
|
logger.warning('All jobs should be finished.')
|
sky/utils/schemas.py
CHANGED
|
@@ -1190,7 +1190,13 @@ def get_config_schema():
|
|
|
1190
1190
|
'consolidation_mode': {
|
|
1191
1191
|
'type': 'boolean',
|
|
1192
1192
|
'default': False,
|
|
1193
|
-
}
|
|
1193
|
+
},
|
|
1194
|
+
'controller_logs_gc_retention_hours': {
|
|
1195
|
+
'type': 'integer',
|
|
1196
|
+
},
|
|
1197
|
+
'task_logs_gc_retention_hours': {
|
|
1198
|
+
'type': 'integer',
|
|
1199
|
+
},
|
|
1194
1200
|
},
|
|
1195
1201
|
},
|
|
1196
1202
|
'bucket': {
|
|
@@ -1592,10 +1598,10 @@ def get_config_schema():
|
|
|
1592
1598
|
|
|
1593
1599
|
allowed_workspace_cloud_names = list(constants.ALL_CLOUDS) + ['cloudflare']
|
|
1594
1600
|
# Create pattern for not supported clouds, i.e.
|
|
1595
|
-
# all clouds except gcp, kubernetes, ssh
|
|
1601
|
+
# all clouds except aws, gcp, kubernetes, ssh, nebius
|
|
1596
1602
|
not_supported_clouds = [
|
|
1597
1603
|
cloud for cloud in allowed_workspace_cloud_names
|
|
1598
|
-
if cloud.lower() not in ['gcp', 'kubernetes', 'ssh', 'nebius']
|
|
1604
|
+
if cloud.lower() not in ['aws', 'gcp', 'kubernetes', 'ssh', 'nebius']
|
|
1599
1605
|
]
|
|
1600
1606
|
not_supported_cloud_regex = '|'.join(not_supported_clouds)
|
|
1601
1607
|
workspaces_schema = {
|
|
@@ -1606,7 +1612,8 @@ def get_config_schema():
|
|
|
1606
1612
|
'type': 'object',
|
|
1607
1613
|
'additionalProperties': False,
|
|
1608
1614
|
'patternProperties': {
|
|
1609
|
-
# Pattern for
|
|
1615
|
+
# Pattern for clouds with no workspace-specific config -
|
|
1616
|
+
# only allow 'disabled' property.
|
|
1610
1617
|
f'^({not_supported_cloud_regex})$': {
|
|
1611
1618
|
'type': 'object',
|
|
1612
1619
|
'additionalProperties': False,
|
|
@@ -1641,6 +1648,18 @@ def get_config_schema():
|
|
|
1641
1648
|
},
|
|
1642
1649
|
'additionalProperties': False,
|
|
1643
1650
|
},
|
|
1651
|
+
'aws': {
|
|
1652
|
+
'type': 'object',
|
|
1653
|
+
'properties': {
|
|
1654
|
+
'profile': {
|
|
1655
|
+
'type': 'string'
|
|
1656
|
+
},
|
|
1657
|
+
'disabled': {
|
|
1658
|
+
'type': 'boolean'
|
|
1659
|
+
},
|
|
1660
|
+
},
|
|
1661
|
+
'additionalProperties': False,
|
|
1662
|
+
},
|
|
1644
1663
|
'ssh': {
|
|
1645
1664
|
'type': 'object',
|
|
1646
1665
|
'required': [],
|
sky/volumes/server/server.py
CHANGED
|
@@ -7,6 +7,7 @@ from sky import exceptions
|
|
|
7
7
|
from sky import sky_logging
|
|
8
8
|
from sky.server.requests import executor
|
|
9
9
|
from sky.server.requests import payloads
|
|
10
|
+
from sky.server.requests import request_names
|
|
10
11
|
from sky.server.requests import requests as requests_lib
|
|
11
12
|
from sky.utils import registry
|
|
12
13
|
from sky.utils import volume as volume_utils
|
|
@@ -27,7 +28,7 @@ async def volume_list(request: fastapi.Request) -> None:
|
|
|
27
28
|
request_body = payloads.RequestBody(**auth_user_env_vars_kwargs)
|
|
28
29
|
await executor.schedule_request_async(
|
|
29
30
|
request_id=request.state.request_id,
|
|
30
|
-
request_name=
|
|
31
|
+
request_name=request_names.RequestName.VOLUME_LIST,
|
|
31
32
|
request_body=request_body,
|
|
32
33
|
func=core.volume_list,
|
|
33
34
|
schedule_type=requests_lib.ScheduleType.SHORT,
|
|
@@ -40,7 +41,7 @@ async def volume_delete(request: fastapi.Request,
|
|
|
40
41
|
"""Deletes a volume."""
|
|
41
42
|
await executor.schedule_request_async(
|
|
42
43
|
request_id=request.state.request_id,
|
|
43
|
-
request_name=
|
|
44
|
+
request_name=request_names.RequestName.VOLUME_DELETE,
|
|
44
45
|
request_body=volume_delete_body,
|
|
45
46
|
func=core.volume_delete,
|
|
46
47
|
schedule_type=requests_lib.ScheduleType.LONG,
|
|
@@ -114,7 +115,7 @@ async def volume_apply(request: fastapi.Request,
|
|
|
114
115
|
detail='Runpod network volume is only supported on Runpod')
|
|
115
116
|
await executor.schedule_request_async(
|
|
116
117
|
request_id=request.state.request_id,
|
|
117
|
-
request_name=
|
|
118
|
+
request_name=request_names.RequestName.VOLUME_APPLY,
|
|
118
119
|
request_body=volume_apply_body,
|
|
119
120
|
func=core.volume_apply,
|
|
120
121
|
schedule_type=requests_lib.ScheduleType.LONG,
|
sky/workspaces/server.py
CHANGED
|
@@ -4,6 +4,7 @@ import fastapi
|
|
|
4
4
|
|
|
5
5
|
from sky.server.requests import executor
|
|
6
6
|
from sky.server.requests import payloads
|
|
7
|
+
from sky.server.requests import request_names
|
|
7
8
|
from sky.server.requests import requests as api_requests
|
|
8
9
|
from sky.workspaces import core
|
|
9
10
|
|
|
@@ -24,7 +25,7 @@ async def get(request: fastapi.Request) -> None:
|
|
|
24
25
|
|
|
25
26
|
await executor.schedule_request_async(
|
|
26
27
|
request_id=request.state.request_id,
|
|
27
|
-
request_name=
|
|
28
|
+
request_name=request_names.RequestName.WORKSPACES_GET,
|
|
28
29
|
request_body=request_body,
|
|
29
30
|
func=core.get_workspaces,
|
|
30
31
|
schedule_type=api_requests.ScheduleType.SHORT,
|
|
@@ -37,7 +38,7 @@ async def update(request: fastapi.Request,
|
|
|
37
38
|
"""Updates a specific workspace configuration."""
|
|
38
39
|
await executor.schedule_request_async(
|
|
39
40
|
request_id=request.state.request_id,
|
|
40
|
-
request_name=
|
|
41
|
+
request_name=request_names.RequestName.WORKSPACES_UPDATE,
|
|
41
42
|
request_body=update_workspace_body,
|
|
42
43
|
func=core.update_workspace,
|
|
43
44
|
schedule_type=api_requests.ScheduleType.SHORT,
|
|
@@ -50,7 +51,7 @@ async def create(request: fastapi.Request,
|
|
|
50
51
|
"""Creates a new workspace configuration."""
|
|
51
52
|
await executor.schedule_request_async(
|
|
52
53
|
request_id=request.state.request_id,
|
|
53
|
-
request_name=
|
|
54
|
+
request_name=request_names.RequestName.WORKSPACES_CREATE,
|
|
54
55
|
request_body=create_workspace_body,
|
|
55
56
|
func=core.create_workspace,
|
|
56
57
|
schedule_type=api_requests.ScheduleType.SHORT,
|
|
@@ -63,7 +64,7 @@ async def delete(request: fastapi.Request,
|
|
|
63
64
|
"""Deletes a workspace configuration."""
|
|
64
65
|
await executor.schedule_request_async(
|
|
65
66
|
request_id=request.state.request_id,
|
|
66
|
-
request_name=
|
|
67
|
+
request_name=request_names.RequestName.WORKSPACES_DELETE,
|
|
67
68
|
request_body=delete_workspace_body,
|
|
68
69
|
func=core.delete_workspace,
|
|
69
70
|
schedule_type=api_requests.ScheduleType.SHORT,
|
|
@@ -80,7 +81,7 @@ async def get_config(request: fastapi.Request) -> None:
|
|
|
80
81
|
get_config_body = payloads.GetConfigBody(**auth_user_env_vars_kwargs)
|
|
81
82
|
await executor.schedule_request_async(
|
|
82
83
|
request_id=request.state.request_id,
|
|
83
|
-
request_name=
|
|
84
|
+
request_name=request_names.RequestName.WORKSPACES_GET_CONFIG,
|
|
84
85
|
request_body=get_config_body,
|
|
85
86
|
func=core.get_config,
|
|
86
87
|
schedule_type=api_requests.ScheduleType.SHORT,
|
|
@@ -93,7 +94,7 @@ async def update_config(request: fastapi.Request,
|
|
|
93
94
|
"""Updates the entire SkyPilot configuration."""
|
|
94
95
|
await executor.schedule_request_async(
|
|
95
96
|
request_id=request.state.request_id,
|
|
96
|
-
request_name=
|
|
97
|
+
request_name=request_names.RequestName.WORKSPACES_UPDATE_CONFIG,
|
|
97
98
|
request_body=update_config_body,
|
|
98
99
|
func=core.update_config,
|
|
99
100
|
schedule_type=api_requests.ScheduleType.SHORT,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: skypilot-nightly
|
|
3
|
-
Version: 1.0.0.
|
|
3
|
+
Version: 1.0.0.dev20251101
|
|
4
4
|
Summary: SkyPilot: Run AI on Any Infra — Unified, Faster, Cheaper.
|
|
5
5
|
Author: SkyPilot Team
|
|
6
6
|
License: Apache 2.0
|
|
@@ -387,51 +387,51 @@ Requires-Dist: protobuf<7.0.0,>=5.26.1; extra == "shadeform"
|
|
|
387
387
|
Requires-Dist: aiosqlite; extra == "shadeform"
|
|
388
388
|
Requires-Dist: greenlet; extra == "shadeform"
|
|
389
389
|
Provides-Extra: all
|
|
390
|
-
Requires-Dist:
|
|
391
|
-
Requires-Dist:
|
|
392
|
-
Requires-Dist:
|
|
390
|
+
Requires-Dist: azure-cli>=2.65.0; extra == "all"
|
|
391
|
+
Requires-Dist: aiohttp; extra == "all"
|
|
392
|
+
Requires-Dist: google-api-python-client>=2.69.0; extra == "all"
|
|
393
393
|
Requires-Dist: azure-core>=1.31.0; extra == "all"
|
|
394
|
-
Requires-Dist:
|
|
395
|
-
Requires-Dist:
|
|
394
|
+
Requires-Dist: botocore>=1.29.10; extra == "all"
|
|
395
|
+
Requires-Dist: colorama<0.4.5; extra == "all"
|
|
396
|
+
Requires-Dist: docker; extra == "all"
|
|
397
|
+
Requires-Dist: protobuf<7.0.0,>=5.26.1; extra == "all"
|
|
398
|
+
Requires-Dist: runpod>=1.6.1; extra == "all"
|
|
396
399
|
Requires-Dist: azure-mgmt-network>=27.0.0; extra == "all"
|
|
397
|
-
Requires-Dist:
|
|
398
|
-
Requires-Dist:
|
|
400
|
+
Requires-Dist: ibm-vpc; extra == "all"
|
|
401
|
+
Requires-Dist: sqlalchemy_adapter; extra == "all"
|
|
402
|
+
Requires-Dist: awscli>=1.27.10; extra == "all"
|
|
403
|
+
Requires-Dist: anyio; extra == "all"
|
|
404
|
+
Requires-Dist: kubernetes!=32.0.0,>=20.0.0; extra == "all"
|
|
405
|
+
Requires-Dist: pydo>=0.3.0; extra == "all"
|
|
406
|
+
Requires-Dist: grpcio>=1.63.0; extra == "all"
|
|
407
|
+
Requires-Dist: tomli; python_version < "3.11" and extra == "all"
|
|
408
|
+
Requires-Dist: passlib; extra == "all"
|
|
399
409
|
Requires-Dist: nebius>=0.2.47; extra == "all"
|
|
400
|
-
Requires-Dist:
|
|
410
|
+
Requires-Dist: azure-core>=1.24.0; extra == "all"
|
|
411
|
+
Requires-Dist: ibm-cloud-sdk-core; extra == "all"
|
|
401
412
|
Requires-Dist: vastai-sdk>=0.1.12; extra == "all"
|
|
402
|
-
Requires-Dist:
|
|
403
|
-
Requires-Dist:
|
|
413
|
+
Requires-Dist: ibm-platform-services>=0.48.0; extra == "all"
|
|
414
|
+
Requires-Dist: pyjwt; extra == "all"
|
|
415
|
+
Requires-Dist: cudo-compute>=0.1.10; extra == "all"
|
|
416
|
+
Requires-Dist: ray[default]>=2.6.1; extra == "all"
|
|
404
417
|
Requires-Dist: aiosqlite; extra == "all"
|
|
418
|
+
Requires-Dist: oci; extra == "all"
|
|
419
|
+
Requires-Dist: ibm-cos-sdk; extra == "all"
|
|
405
420
|
Requires-Dist: pyopenssl<24.3.0,>=23.2.0; extra == "all"
|
|
406
|
-
Requires-Dist:
|
|
421
|
+
Requires-Dist: ecsapi>=0.2.0; extra == "all"
|
|
422
|
+
Requires-Dist: msgraph-sdk; extra == "all"
|
|
423
|
+
Requires-Dist: boto3>=1.26.1; extra == "all"
|
|
424
|
+
Requires-Dist: casbin; extra == "all"
|
|
407
425
|
Requires-Dist: greenlet; extra == "all"
|
|
408
|
-
Requires-Dist:
|
|
409
|
-
Requires-Dist:
|
|
426
|
+
Requires-Dist: pyvmomi==8.0.1.0.2; extra == "all"
|
|
427
|
+
Requires-Dist: python-dateutil; extra == "all"
|
|
428
|
+
Requires-Dist: azure-storage-blob>=12.23.1; extra == "all"
|
|
429
|
+
Requires-Dist: azure-identity>=1.19.0; extra == "all"
|
|
410
430
|
Requires-Dist: google-cloud-storage; extra == "all"
|
|
431
|
+
Requires-Dist: msrestazure; extra == "all"
|
|
432
|
+
Requires-Dist: azure-common; extra == "all"
|
|
411
433
|
Requires-Dist: websockets; extra == "all"
|
|
412
434
|
Requires-Dist: azure-mgmt-compute>=33.0.0; extra == "all"
|
|
413
|
-
Requires-Dist: msrestazure; extra == "all"
|
|
414
|
-
Requires-Dist: tomli; python_version < "3.11" and extra == "all"
|
|
415
|
-
Requires-Dist: ecsapi>=0.2.0; extra == "all"
|
|
416
|
-
Requires-Dist: python-dateutil; extra == "all"
|
|
417
|
-
Requires-Dist: passlib; extra == "all"
|
|
418
|
-
Requires-Dist: kubernetes!=32.0.0,>=20.0.0; extra == "all"
|
|
419
|
-
Requires-Dist: docker; extra == "all"
|
|
420
|
-
Requires-Dist: anyio; extra == "all"
|
|
421
|
-
Requires-Dist: ibm-cos-sdk; extra == "all"
|
|
422
|
-
Requires-Dist: pyvmomi==8.0.1.0.2; extra == "all"
|
|
423
|
-
Requires-Dist: pyjwt; extra == "all"
|
|
424
|
-
Requires-Dist: oci; extra == "all"
|
|
425
|
-
Requires-Dist: azure-storage-blob>=12.23.1; extra == "all"
|
|
426
|
-
Requires-Dist: cudo-compute>=0.1.10; extra == "all"
|
|
427
|
-
Requires-Dist: azure-core>=1.24.0; extra == "all"
|
|
428
|
-
Requires-Dist: aiohttp; extra == "all"
|
|
429
|
-
Requires-Dist: protobuf<7.0.0,>=5.26.1; extra == "all"
|
|
430
|
-
Requires-Dist: botocore>=1.29.10; extra == "all"
|
|
431
|
-
Requires-Dist: azure-cli>=2.65.0; extra == "all"
|
|
432
|
-
Requires-Dist: boto3>=1.26.1; extra == "all"
|
|
433
|
-
Requires-Dist: pydo>=0.3.0; extra == "all"
|
|
434
|
-
Requires-Dist: ibm-platform-services>=0.48.0; extra == "all"
|
|
435
435
|
Provides-Extra: remote
|
|
436
436
|
Requires-Dist: grpcio>=1.63.0; extra == "remote"
|
|
437
437
|
Requires-Dist: protobuf<7.0.0,>=5.26.1; extra == "remote"
|