skypilot-nightly 1.0.0.dev20250902__py3-none-any.whl → 1.0.0.dev20250903__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/runpod.py +68 -0
- sky/backends/backend_utils.py +5 -3
- sky/client/cli/command.py +20 -5
- sky/clouds/kubernetes.py +1 -1
- sky/clouds/runpod.py +17 -0
- sky/dashboard/out/404.html +1 -1
- sky/dashboard/out/_next/static/chunks/1121-ec35954c8cbea535.js +1 -0
- sky/dashboard/out/_next/static/chunks/pages/clusters/[cluster]/[job]-b77360a343d48902.js +16 -0
- sky/dashboard/out/_next/static/chunks/{webpack-0eaa6f7e63f51311.js → webpack-60556df644cd5d71.js} +1 -1
- sky/dashboard/out/_next/static/{tio0QibqY2C0F2-rPy00p → yLz6EPhW_XXmnNs1I6dmS}/_buildManifest.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/global_user_state.py +5 -2
- sky/models.py +1 -0
- sky/provision/runpod/__init__.py +3 -0
- sky/provision/runpod/instance.py +17 -0
- sky/provision/runpod/utils.py +23 -5
- sky/provision/runpod/volume.py +158 -0
- sky/server/requests/payloads.py +7 -1
- sky/server/requests/preconditions.py +8 -7
- sky/server/requests/requests.py +123 -57
- sky/server/server.py +32 -25
- sky/server/stream_utils.py +14 -6
- sky/server/uvicorn.py +2 -1
- sky/templates/kubernetes-ray.yml.j2 +5 -5
- sky/templates/runpod-ray.yml.j2 +8 -0
- sky/utils/benchmark_utils.py +60 -0
- sky/utils/command_runner.py +4 -0
- sky/utils/db/migration_utils.py +20 -4
- sky/utils/resource_checker.py +6 -5
- sky/utils/schemas.py +1 -1
- sky/utils/volume.py +3 -0
- sky/volumes/client/sdk.py +28 -0
- sky/volumes/server/server.py +11 -1
- sky/volumes/utils.py +117 -68
- sky/volumes/volume.py +98 -39
- {skypilot_nightly-1.0.0.dev20250902.dist-info → skypilot_nightly-1.0.0.dev20250903.dist-info}/METADATA +34 -34
- {skypilot_nightly-1.0.0.dev20250902.dist-info → skypilot_nightly-1.0.0.dev20250903.dist-info}/RECORD +57 -55
- sky/dashboard/out/_next/static/chunks/1121-8afcf719ea87debc.js +0 -1
- sky/dashboard/out/_next/static/chunks/pages/clusters/[cluster]/[job]-06afb50d25f7c61f.js +0 -16
- /sky/dashboard/out/_next/static/{tio0QibqY2C0F2-rPy00p → yLz6EPhW_XXmnNs1I6dmS}/_ssgManifest.js +0 -0
- {skypilot_nightly-1.0.0.dev20250902.dist-info → skypilot_nightly-1.0.0.dev20250903.dist-info}/WHEEL +0 -0
- {skypilot_nightly-1.0.0.dev20250902.dist-info → skypilot_nightly-1.0.0.dev20250903.dist-info}/entry_points.txt +0 -0
- {skypilot_nightly-1.0.0.dev20250902.dist-info → skypilot_nightly-1.0.0.dev20250903.dist-info}/licenses/LICENSE +0 -0
- {skypilot_nightly-1.0.0.dev20250902.dist-info → skypilot_nightly-1.0.0.dev20250903.dist-info}/top_level.txt +0 -0
sky/volumes/utils.py
CHANGED
|
@@ -13,6 +13,19 @@ from sky.utils import volume
|
|
|
13
13
|
|
|
14
14
|
logger = sky_logging.init_logger(__name__)
|
|
15
15
|
|
|
16
|
+
_BASIC_COLUMNS = [
|
|
17
|
+
'NAME',
|
|
18
|
+
'TYPE',
|
|
19
|
+
'INFRA',
|
|
20
|
+
'SIZE',
|
|
21
|
+
'USER',
|
|
22
|
+
'WORKSPACE',
|
|
23
|
+
'AGE',
|
|
24
|
+
'STATUS',
|
|
25
|
+
'LAST_USE',
|
|
26
|
+
'USED_BY',
|
|
27
|
+
]
|
|
28
|
+
|
|
16
29
|
|
|
17
30
|
def _get_infra_str(cloud: Optional[str], region: Optional[str],
|
|
18
31
|
zone: Optional[str]) -> str:
|
|
@@ -30,20 +43,71 @@ def _get_infra_str(cloud: Optional[str], region: Optional[str],
|
|
|
30
43
|
class VolumeTable(abc.ABC):
|
|
31
44
|
"""The volume table."""
|
|
32
45
|
|
|
46
|
+
def __init__(self, volumes: List[Dict[str, Any]], show_all: bool = False):
|
|
47
|
+
super().__init__()
|
|
48
|
+
self.table = self._create_table(show_all)
|
|
49
|
+
self._add_rows(volumes, show_all)
|
|
50
|
+
|
|
51
|
+
def _get_row_base_columns(self,
|
|
52
|
+
row: Dict[str, Any],
|
|
53
|
+
show_all: bool = False) -> List[str]:
|
|
54
|
+
"""Get the base columns for a row."""
|
|
55
|
+
# Convert last_attached_at timestamp to human readable string
|
|
56
|
+
last_attached_at = row.get('last_attached_at')
|
|
57
|
+
if last_attached_at is not None:
|
|
58
|
+
last_attached_at_str = datetime.fromtimestamp(
|
|
59
|
+
last_attached_at).strftime('%Y-%m-%d %H:%M:%S')
|
|
60
|
+
else:
|
|
61
|
+
last_attached_at_str = '-'
|
|
62
|
+
size = row.get('size', '')
|
|
63
|
+
if size:
|
|
64
|
+
size = f'{size}Gi'
|
|
65
|
+
usedby_str = '-'
|
|
66
|
+
usedby_clusters = row.get('usedby_clusters')
|
|
67
|
+
usedby_pods = row.get('usedby_pods')
|
|
68
|
+
if usedby_clusters:
|
|
69
|
+
usedby_str = f'{", ".join(usedby_clusters)}'
|
|
70
|
+
elif usedby_pods:
|
|
71
|
+
usedby_str = f'{", ".join(usedby_pods)}'
|
|
72
|
+
if show_all:
|
|
73
|
+
usedby = usedby_str
|
|
74
|
+
else:
|
|
75
|
+
usedby = common_utils.truncate_long_string(
|
|
76
|
+
usedby_str, constants.USED_BY_TRUNC_LENGTH)
|
|
77
|
+
infra = _get_infra_str(row.get('cloud'), row.get('region'),
|
|
78
|
+
row.get('zone'))
|
|
79
|
+
return [
|
|
80
|
+
row.get('name', ''),
|
|
81
|
+
row.get('type', ''),
|
|
82
|
+
infra,
|
|
83
|
+
size,
|
|
84
|
+
row.get('user_name', '-'),
|
|
85
|
+
row.get('workspace', '-'),
|
|
86
|
+
log_utils.human_duration(row.get('launched_at', 0)),
|
|
87
|
+
row.get('status', ''),
|
|
88
|
+
last_attached_at_str,
|
|
89
|
+
usedby,
|
|
90
|
+
]
|
|
91
|
+
|
|
92
|
+
def _create_table(self, show_all: bool = False) -> prettytable.PrettyTable:
|
|
93
|
+
"""Create the volume table."""
|
|
94
|
+
raise NotImplementedError
|
|
95
|
+
|
|
96
|
+
def _add_rows(self,
|
|
97
|
+
volumes: List[Dict[str, Any]],
|
|
98
|
+
show_all: bool = False) -> None:
|
|
99
|
+
"""Add rows to the volume table."""
|
|
100
|
+
raise NotImplementedError
|
|
101
|
+
|
|
33
102
|
@abc.abstractmethod
|
|
34
103
|
def format(self) -> str:
|
|
35
104
|
"""Format the volume table for display."""
|
|
36
|
-
|
|
105
|
+
raise NotImplementedError
|
|
37
106
|
|
|
38
107
|
|
|
39
108
|
class PVCVolumeTable(VolumeTable):
|
|
40
109
|
"""The PVC volume table."""
|
|
41
110
|
|
|
42
|
-
def __init__(self, volumes: List[Dict[str, Any]], show_all: bool = False):
|
|
43
|
-
super().__init__()
|
|
44
|
-
self.table = self._create_table(show_all)
|
|
45
|
-
self._add_rows(volumes, show_all)
|
|
46
|
-
|
|
47
111
|
def _create_table(self, show_all: bool = False) -> prettytable.PrettyTable:
|
|
48
112
|
"""Create the PVC volume table."""
|
|
49
113
|
# If show_all is False, show the table with the columns:
|
|
@@ -55,34 +119,13 @@ class PVCVolumeTable(VolumeTable):
|
|
|
55
119
|
# STORAGE_CLASS, ACCESS_MODE
|
|
56
120
|
|
|
57
121
|
if show_all:
|
|
58
|
-
columns = [
|
|
59
|
-
'NAME',
|
|
60
|
-
'TYPE',
|
|
61
|
-
'INFRA',
|
|
62
|
-
'SIZE',
|
|
63
|
-
'USER',
|
|
64
|
-
'WORKSPACE',
|
|
65
|
-
'AGE',
|
|
66
|
-
'STATUS',
|
|
67
|
-
'LAST_USE',
|
|
68
|
-
'USED_BY',
|
|
122
|
+
columns = _BASIC_COLUMNS + [
|
|
69
123
|
'NAME_ON_CLOUD',
|
|
70
124
|
'STORAGE_CLASS',
|
|
71
125
|
'ACCESS_MODE',
|
|
72
126
|
]
|
|
73
127
|
else:
|
|
74
|
-
columns =
|
|
75
|
-
'NAME',
|
|
76
|
-
'TYPE',
|
|
77
|
-
'INFRA',
|
|
78
|
-
'SIZE',
|
|
79
|
-
'USER',
|
|
80
|
-
'WORKSPACE',
|
|
81
|
-
'AGE',
|
|
82
|
-
'STATUS',
|
|
83
|
-
'LAST_USE',
|
|
84
|
-
'USED_BY',
|
|
85
|
-
]
|
|
128
|
+
columns = _BASIC_COLUMNS
|
|
86
129
|
|
|
87
130
|
table = log_utils.create_table(columns)
|
|
88
131
|
return table
|
|
@@ -92,42 +135,7 @@ class PVCVolumeTable(VolumeTable):
|
|
|
92
135
|
show_all: bool = False) -> None:
|
|
93
136
|
"""Add rows to the PVC volume table."""
|
|
94
137
|
for row in volumes:
|
|
95
|
-
|
|
96
|
-
last_attached_at = row.get('last_attached_at')
|
|
97
|
-
if last_attached_at is not None:
|
|
98
|
-
last_attached_at_str = datetime.fromtimestamp(
|
|
99
|
-
last_attached_at).strftime('%Y-%m-%d %H:%M:%S')
|
|
100
|
-
else:
|
|
101
|
-
last_attached_at_str = '-'
|
|
102
|
-
size = row.get('size', '')
|
|
103
|
-
if size:
|
|
104
|
-
size = f'{size}Gi'
|
|
105
|
-
usedby_str = '-'
|
|
106
|
-
usedby_clusters = row.get('usedby_clusters')
|
|
107
|
-
usedby_pods = row.get('usedby_pods')
|
|
108
|
-
if usedby_clusters:
|
|
109
|
-
usedby_str = f'{", ".join(usedby_clusters)}'
|
|
110
|
-
elif usedby_pods:
|
|
111
|
-
usedby_str = f'{", ".join(usedby_pods)}'
|
|
112
|
-
if show_all:
|
|
113
|
-
usedby = usedby_str
|
|
114
|
-
else:
|
|
115
|
-
usedby = common_utils.truncate_long_string(
|
|
116
|
-
usedby_str, constants.USED_BY_TRUNC_LENGTH)
|
|
117
|
-
infra = _get_infra_str(row.get('cloud'), row.get('region'),
|
|
118
|
-
row.get('zone'))
|
|
119
|
-
table_row = [
|
|
120
|
-
row.get('name', ''),
|
|
121
|
-
row.get('type', ''),
|
|
122
|
-
infra,
|
|
123
|
-
size,
|
|
124
|
-
row.get('user_name', '-'),
|
|
125
|
-
row.get('workspace', '-'),
|
|
126
|
-
log_utils.human_duration(row.get('launched_at', 0)),
|
|
127
|
-
row.get('status', ''),
|
|
128
|
-
last_attached_at_str,
|
|
129
|
-
usedby,
|
|
130
|
-
]
|
|
138
|
+
table_row = self._get_row_base_columns(row, show_all)
|
|
131
139
|
if show_all:
|
|
132
140
|
table_row.append(row.get('name_on_cloud', ''))
|
|
133
141
|
table_row.append(
|
|
@@ -138,7 +146,43 @@ class PVCVolumeTable(VolumeTable):
|
|
|
138
146
|
|
|
139
147
|
def format(self) -> str:
|
|
140
148
|
"""Format the PVC volume table for display."""
|
|
141
|
-
return str(self.table)
|
|
149
|
+
return 'Kubernetes PVCs:\n' + str(self.table)
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
class RunPodVolumeTable(VolumeTable):
|
|
153
|
+
"""The RunPod volume table."""
|
|
154
|
+
|
|
155
|
+
def _create_table(self, show_all: bool = False) -> prettytable.PrettyTable:
|
|
156
|
+
"""Create the RunPod volume table."""
|
|
157
|
+
# If show_all is False, show the table with the columns:
|
|
158
|
+
# NAME, TYPE, INFRA, SIZE, USER, WORKSPACE,
|
|
159
|
+
# AGE, STATUS, LAST_USE, USED_BY
|
|
160
|
+
# If show_all is True, show the table with the columns:
|
|
161
|
+
# NAME, TYPE, INFRA, SIZE, USER, WORKSPACE,
|
|
162
|
+
# AGE, STATUS, LAST_USE, USED_BY, NAME_ON_CLOUD
|
|
163
|
+
|
|
164
|
+
if show_all:
|
|
165
|
+
columns = _BASIC_COLUMNS + ['NAME_ON_CLOUD']
|
|
166
|
+
else:
|
|
167
|
+
columns = _BASIC_COLUMNS
|
|
168
|
+
|
|
169
|
+
table = log_utils.create_table(columns)
|
|
170
|
+
return table
|
|
171
|
+
|
|
172
|
+
def _add_rows(self,
|
|
173
|
+
volumes: List[Dict[str, Any]],
|
|
174
|
+
show_all: bool = False) -> None:
|
|
175
|
+
"""Add rows to the RunPod volume table."""
|
|
176
|
+
for row in volumes:
|
|
177
|
+
table_row = self._get_row_base_columns(row, show_all)
|
|
178
|
+
if show_all:
|
|
179
|
+
table_row.append(row.get('name_on_cloud', ''))
|
|
180
|
+
|
|
181
|
+
self.table.add_row(table_row)
|
|
182
|
+
|
|
183
|
+
def format(self) -> str:
|
|
184
|
+
"""Format the RunPod volume table for display."""
|
|
185
|
+
return 'RunPod Network Volumes:\n' + str(self.table)
|
|
142
186
|
|
|
143
187
|
|
|
144
188
|
def format_volume_table(volumes: List[Dict[str, Any]],
|
|
@@ -166,9 +210,14 @@ def format_volume_table(volumes: List[Dict[str, Any]],
|
|
|
166
210
|
continue
|
|
167
211
|
table_str = ''
|
|
168
212
|
for volume_type, volume_list in volumes_per_type.items():
|
|
213
|
+
if table_str:
|
|
214
|
+
table_str += '\n\n'
|
|
169
215
|
if volume_type == volume.VolumeType.PVC.value:
|
|
170
|
-
|
|
171
|
-
table_str +=
|
|
216
|
+
pvc_table = PVCVolumeTable(volume_list, show_all)
|
|
217
|
+
table_str += pvc_table.format()
|
|
218
|
+
elif volume_type == volume.VolumeType.RUNPOD_NETWORK_VOLUME.value:
|
|
219
|
+
runpod_table = RunPodVolumeTable(volume_list, show_all)
|
|
220
|
+
table_str += runpod_table.format()
|
|
172
221
|
if table_str:
|
|
173
222
|
return table_str
|
|
174
223
|
else:
|
sky/volumes/volume.py
CHANGED
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
"""Volume types and access modes."""
|
|
2
2
|
from typing import Any, Dict, Optional
|
|
3
3
|
|
|
4
|
+
from sky import clouds
|
|
4
5
|
from sky.utils import common_utils
|
|
5
6
|
from sky.utils import infra_utils
|
|
6
7
|
from sky.utils import registry
|
|
7
8
|
from sky.utils import resources_utils
|
|
8
9
|
from sky.utils import schemas
|
|
10
|
+
from sky.utils import volume as volume_lib
|
|
11
|
+
|
|
12
|
+
VOLUME_TYPE_TO_CLOUD = {
|
|
13
|
+
volume_lib.VolumeType.PVC: clouds.Kubernetes(),
|
|
14
|
+
volume_lib.VolumeType.RUNPOD_NETWORK_VOLUME: clouds.RunPod(),
|
|
15
|
+
}
|
|
9
16
|
|
|
10
17
|
|
|
11
18
|
class Volume:
|
|
@@ -42,18 +49,42 @@ class Volume:
|
|
|
42
49
|
self.region: Optional[str] = None
|
|
43
50
|
self.zone: Optional[str] = None
|
|
44
51
|
|
|
52
|
+
self._normalize_config()
|
|
53
|
+
|
|
45
54
|
@classmethod
|
|
46
|
-
def
|
|
47
|
-
"""Create a Volume instance from a dictionary."""
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
55
|
+
def from_yaml_config(cls, config: Dict[str, Any]) -> 'Volume':
|
|
56
|
+
"""Create a Volume subclass instance from a dictionary via factory."""
|
|
57
|
+
vol_type_val = config.get('type')
|
|
58
|
+
try:
|
|
59
|
+
vt = (volume_lib.VolumeType(vol_type_val)
|
|
60
|
+
if vol_type_val is not None else None)
|
|
61
|
+
except Exception: # pylint: disable=broad-except
|
|
62
|
+
vt = None
|
|
63
|
+
|
|
64
|
+
if vt is None:
|
|
65
|
+
raise ValueError(f'Invalid volume type: {vol_type_val}')
|
|
66
|
+
|
|
67
|
+
if vt == volume_lib.VolumeType.PVC:
|
|
68
|
+
return PVCVolume(name=config.get('name'),
|
|
69
|
+
type=vol_type_val,
|
|
70
|
+
infra=config.get('infra'),
|
|
71
|
+
size=config.get('size'),
|
|
72
|
+
labels=config.get('labels'),
|
|
73
|
+
resource_name=config.get('resource_name'),
|
|
74
|
+
config=config.get('config', {}))
|
|
75
|
+
if vt == volume_lib.VolumeType.RUNPOD_NETWORK_VOLUME:
|
|
76
|
+
return RunpodNetworkVolume(
|
|
77
|
+
name=config.get('name'),
|
|
78
|
+
type=vol_type_val,
|
|
79
|
+
infra=config.get('infra'),
|
|
80
|
+
size=config.get('size'),
|
|
81
|
+
labels=config.get('labels'),
|
|
82
|
+
resource_name=config.get('resource_name'),
|
|
83
|
+
config=config.get('config', {}))
|
|
84
|
+
|
|
85
|
+
raise ValueError(f'Invalid volume type: {vol_type_val}')
|
|
86
|
+
|
|
87
|
+
def to_yaml_config(self) -> Dict[str, Any]:
|
|
57
88
|
"""Convert the Volume to a dictionary."""
|
|
58
89
|
return {
|
|
59
90
|
'name': self.name,
|
|
@@ -68,32 +99,10 @@ class Volume:
|
|
|
68
99
|
'zone': self.zone,
|
|
69
100
|
}
|
|
70
101
|
|
|
71
|
-
def
|
|
72
|
-
|
|
73
|
-
name: Optional[str] = None,
|
|
74
|
-
infra: Optional[str] = None,
|
|
75
|
-
type: Optional[str] = None, # pylint: disable=redefined-builtin
|
|
76
|
-
size: Optional[str] = None) -> None:
|
|
77
|
-
"""Override the volume config with CLI options,
|
|
78
|
-
adjust and validate the config.
|
|
79
|
-
|
|
80
|
-
Args:
|
|
81
|
-
name: Volume name to override
|
|
82
|
-
infra: Infrastructure to override
|
|
83
|
-
type: Volume type to override
|
|
84
|
-
size: Volume size to override
|
|
85
|
-
"""
|
|
86
|
-
if name is not None:
|
|
87
|
-
self.name = name
|
|
88
|
-
if infra is not None:
|
|
89
|
-
self.infra = infra
|
|
90
|
-
if type is not None:
|
|
91
|
-
self.type = type
|
|
92
|
-
if size is not None:
|
|
93
|
-
self.size = size
|
|
94
|
-
|
|
102
|
+
def _normalize_config(self) -> None:
|
|
103
|
+
"""Adjust and validate the config."""
|
|
95
104
|
# Validate schema
|
|
96
|
-
common_utils.validate_schema(self.
|
|
105
|
+
common_utils.validate_schema(self.to_yaml_config(),
|
|
97
106
|
schemas.get_volume_schema(),
|
|
98
107
|
'Invalid volumes config: ')
|
|
99
108
|
|
|
@@ -125,9 +134,21 @@ class Volume:
|
|
|
125
134
|
|
|
126
135
|
def _validate_config(self) -> None:
|
|
127
136
|
"""Validate the volume config."""
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
137
|
+
cloud_obj_from_type = VOLUME_TYPE_TO_CLOUD.get(
|
|
138
|
+
volume_lib.VolumeType(self.type))
|
|
139
|
+
if self.cloud:
|
|
140
|
+
cloud_obj = registry.CLOUD_REGISTRY.from_str(self.cloud)
|
|
141
|
+
assert cloud_obj is not None
|
|
142
|
+
if not cloud_obj.is_same_cloud(cloud_obj_from_type):
|
|
143
|
+
raise ValueError(
|
|
144
|
+
f'Invalid cloud {self.cloud} for volume type {self.type}')
|
|
145
|
+
else:
|
|
146
|
+
self.cloud = str(cloud_obj_from_type)
|
|
147
|
+
cloud_obj = cloud_obj_from_type
|
|
148
|
+
assert cloud_obj is not None
|
|
149
|
+
|
|
150
|
+
self.region, self.zone = cloud_obj.validate_region_zone(
|
|
151
|
+
self.region, self.zone)
|
|
131
152
|
|
|
132
153
|
valid, err_msg = cloud_obj.is_volume_name_valid(self.name)
|
|
133
154
|
if not valid:
|
|
@@ -142,3 +163,41 @@ class Volume:
|
|
|
142
163
|
valid, err_msg = cloud_obj.is_label_valid(key, value)
|
|
143
164
|
if not valid:
|
|
144
165
|
raise ValueError(f'{err_msg}')
|
|
166
|
+
|
|
167
|
+
# Extra, type-specific validations
|
|
168
|
+
self._validate_config_extra()
|
|
169
|
+
|
|
170
|
+
# Hook methods for subclasses
|
|
171
|
+
def _validate_config_extra(self) -> None:
|
|
172
|
+
"""Additional type-specific validation.
|
|
173
|
+
|
|
174
|
+
Subclasses can override to enforce stricter rules.
|
|
175
|
+
"""
|
|
176
|
+
return
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
class PVCVolume(Volume):
|
|
180
|
+
"""Kubernetes PVC-backed volume."""
|
|
181
|
+
pass
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
class RunpodNetworkVolume(Volume):
|
|
185
|
+
"""RunPod Network Volume."""
|
|
186
|
+
|
|
187
|
+
def _validate_config_extra(self) -> None:
|
|
188
|
+
if self.size is not None:
|
|
189
|
+
try:
|
|
190
|
+
size_int = int(self.size)
|
|
191
|
+
if size_int < volume_lib.MIN_RUNPOD_NETWORK_VOLUME_SIZE_GB:
|
|
192
|
+
raise ValueError(
|
|
193
|
+
f'RunPod network volume size must be at least '
|
|
194
|
+
f'{volume_lib.MIN_RUNPOD_NETWORK_VOLUME_SIZE_GB}GB.')
|
|
195
|
+
except Exception as e: # pylint: disable=broad-except
|
|
196
|
+
raise ValueError(f'Invalid volume size {self.size!r}: '
|
|
197
|
+
f'{e}') from e
|
|
198
|
+
if not self.zone:
|
|
199
|
+
raise ValueError(
|
|
200
|
+
'RunPod DataCenterId is required to create a network '
|
|
201
|
+
'volume. Set the zone in the infra field.')
|
|
202
|
+
|
|
203
|
+
return
|
|
@@ -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.dev20250903
|
|
4
4
|
Summary: SkyPilot: Run AI on Any Infra — Unified, Faster, Cheaper.
|
|
5
5
|
Author: SkyPilot Team
|
|
6
6
|
License: Apache 2.0
|
|
@@ -145,48 +145,48 @@ Requires-Dist: grpcio>=1.63.0; extra == "server"
|
|
|
145
145
|
Requires-Dist: protobuf<7.0.0,>=5.26.1; extra == "server"
|
|
146
146
|
Requires-Dist: aiosqlite; extra == "server"
|
|
147
147
|
Provides-Extra: all
|
|
148
|
-
Requires-Dist:
|
|
148
|
+
Requires-Dist: ibm-cos-sdk; extra == "all"
|
|
149
|
+
Requires-Dist: ray[default]!=2.6.0,>=2.2.0; extra == "all"
|
|
150
|
+
Requires-Dist: vastai-sdk>=0.1.12; extra == "all"
|
|
151
|
+
Requires-Dist: aiohttp; extra == "all"
|
|
152
|
+
Requires-Dist: google-cloud-storage; extra == "all"
|
|
153
|
+
Requires-Dist: websockets; extra == "all"
|
|
154
|
+
Requires-Dist: azure-mgmt-compute>=33.0.0; extra == "all"
|
|
155
|
+
Requires-Dist: kubernetes!=32.0.0,>=20.0.0; extra == "all"
|
|
156
|
+
Requires-Dist: msgraph-sdk; extra == "all"
|
|
157
|
+
Requires-Dist: azure-storage-blob>=12.23.1; extra == "all"
|
|
158
|
+
Requires-Dist: anyio; extra == "all"
|
|
159
|
+
Requires-Dist: boto3>=1.26.1; extra == "all"
|
|
149
160
|
Requires-Dist: google-api-python-client>=2.69.0; extra == "all"
|
|
150
|
-
Requires-Dist:
|
|
151
|
-
Requires-Dist:
|
|
161
|
+
Requires-Dist: pyopenssl<24.3.0,>=23.2.0; extra == "all"
|
|
162
|
+
Requires-Dist: cudo-compute>=0.1.10; extra == "all"
|
|
163
|
+
Requires-Dist: azure-mgmt-network>=27.0.0; extra == "all"
|
|
152
164
|
Requires-Dist: pyvmomi==8.0.1.0.2; extra == "all"
|
|
153
|
-
Requires-Dist:
|
|
154
|
-
Requires-Dist: colorama<0.4.5; extra == "all"
|
|
155
|
-
Requires-Dist: azure-cli>=2.65.0; extra == "all"
|
|
156
|
-
Requires-Dist: azure-storage-blob>=12.23.1; extra == "all"
|
|
157
|
-
Requires-Dist: docker; extra == "all"
|
|
165
|
+
Requires-Dist: passlib; extra == "all"
|
|
158
166
|
Requires-Dist: azure-identity>=1.19.0; extra == "all"
|
|
159
167
|
Requires-Dist: botocore>=1.29.10; extra == "all"
|
|
160
|
-
Requires-Dist: casbin; extra == "all"
|
|
161
|
-
Requires-Dist: runpod>=1.6.1; extra == "all"
|
|
162
|
-
Requires-Dist: cudo-compute>=0.1.10; extra == "all"
|
|
163
|
-
Requires-Dist: protobuf<7.0.0,>=5.26.1; extra == "all"
|
|
164
|
-
Requires-Dist: ibm-vpc; extra == "all"
|
|
165
168
|
Requires-Dist: awscli>=1.27.10; extra == "all"
|
|
169
|
+
Requires-Dist: python-dateutil; extra == "all"
|
|
166
170
|
Requires-Dist: pyjwt; extra == "all"
|
|
167
|
-
Requires-Dist:
|
|
168
|
-
Requires-Dist:
|
|
169
|
-
Requires-Dist:
|
|
170
|
-
Requires-Dist:
|
|
171
|
-
Requires-Dist: kubernetes!=32.0.0,>=20.0.0; extra == "all"
|
|
172
|
-
Requires-Dist: vastai-sdk>=0.1.12; extra == "all"
|
|
171
|
+
Requires-Dist: oci; extra == "all"
|
|
172
|
+
Requires-Dist: ibm-cloud-sdk-core; extra == "all"
|
|
173
|
+
Requires-Dist: azure-cli>=2.65.0; extra == "all"
|
|
174
|
+
Requires-Dist: aiosqlite; extra == "all"
|
|
173
175
|
Requires-Dist: pydo>=0.3.0; extra == "all"
|
|
174
|
-
Requires-Dist:
|
|
175
|
-
Requires-Dist:
|
|
176
|
-
Requires-Dist:
|
|
176
|
+
Requires-Dist: docker; extra == "all"
|
|
177
|
+
Requires-Dist: azure-common; extra == "all"
|
|
178
|
+
Requires-Dist: colorama<0.4.5; extra == "all"
|
|
179
|
+
Requires-Dist: msrestazure; extra == "all"
|
|
180
|
+
Requires-Dist: ibm-vpc; extra == "all"
|
|
177
181
|
Requires-Dist: ibm-platform-services>=0.48.0; extra == "all"
|
|
178
|
-
Requires-Dist: google-cloud-storage; extra == "all"
|
|
179
|
-
Requires-Dist: ray[default]!=2.6.0,>=2.2.0; extra == "all"
|
|
180
|
-
Requires-Dist: grpcio>=1.63.0; extra == "all"
|
|
181
|
-
Requires-Dist: azure-mgmt-network>=27.0.0; extra == "all"
|
|
182
|
-
Requires-Dist: azure-mgmt-compute>=33.0.0; extra == "all"
|
|
183
|
-
Requires-Dist: python-dateutil; extra == "all"
|
|
184
|
-
Requires-Dist: passlib; extra == "all"
|
|
185
182
|
Requires-Dist: azure-core>=1.24.0; extra == "all"
|
|
186
|
-
Requires-Dist:
|
|
187
|
-
Requires-Dist:
|
|
188
|
-
Requires-Dist:
|
|
189
|
-
Requires-Dist:
|
|
183
|
+
Requires-Dist: sqlalchemy_adapter; extra == "all"
|
|
184
|
+
Requires-Dist: azure-core>=1.31.0; extra == "all"
|
|
185
|
+
Requires-Dist: nebius>=0.2.47; extra == "all"
|
|
186
|
+
Requires-Dist: casbin; extra == "all"
|
|
187
|
+
Requires-Dist: protobuf<7.0.0,>=5.26.1; extra == "all"
|
|
188
|
+
Requires-Dist: grpcio>=1.63.0; extra == "all"
|
|
189
|
+
Requires-Dist: runpod>=1.6.1; extra == "all"
|
|
190
190
|
Dynamic: author
|
|
191
191
|
Dynamic: classifier
|
|
192
192
|
Dynamic: description
|