-
Notifications
You must be signed in to change notification settings - Fork 13
Expand file tree
/
Copy pathtest_cpu_disk_sizing.py
More file actions
301 lines (253 loc) · 11.6 KB
/
test_cpu_disk_sizing.py
File metadata and controls
301 lines (253 loc) · 11.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
"""
Integration tests for CPU disk sizing across multiple components.
These tests verify that CPU disk sizing works correctly when different
components (ServerlessEndpoint, CpuServerlessEndpoint, LiveServerless variants)
interact with the CPU utilities and template system.
"""
import pytest
from runpod_flash.core.resources.cpu import CpuInstanceType
from runpod_flash.core.resources.serverless import ServerlessEndpoint
from runpod_flash.core.resources.serverless_cpu import CpuServerlessEndpoint
from runpod_flash.core.resources.live_serverless import (
LiveServerless,
CpuLiveServerless,
)
from runpod_flash.core.resources.template import PodTemplate
class TestUniversalCpuDetectionIntegration:
"""Test universal CPU detection on GPU endpoint classes."""
def test_gpu_class_with_cpu_instances_auto_sizes(self):
"""Integration: GPU class with CPU instances auto-sizes correctly."""
endpoint = ServerlessEndpoint(
name="gpu_class_cpu_instances",
imageName="my-app:latest",
instanceIds=[CpuInstanceType.CPU3G_8_32],
)
# Should auto-size to 80GB (not fail with 64GB default)
assert endpoint.template is not None
assert endpoint.template.containerDiskInGb == 80
assert endpoint.instanceIds == [CpuInstanceType.CPU3G_8_32]
def test_gpu_class_with_small_cpu_instance_auto_sizes(self):
"""GPU class with small CPU instance auto-sizes from default 64GB."""
endpoint = ServerlessEndpoint(
name="gpu_class_small_cpu",
imageName="my-app:latest",
instanceIds=[CpuInstanceType.CPU3G_1_4], # 10GB limit
)
# Should auto-size from default 64GB to 10GB limit
assert endpoint.template.containerDiskInGb == 10
def test_gpu_live_class_with_cpu_instances_auto_sizes(self):
"""Integration: LiveServerless with CPU instances auto-sizes."""
# This creates a GPU-class endpoint with CPU instances
endpoint = LiveServerless(
name="gpu_live_cpu_instances",
instanceIds=[CpuInstanceType.CPU3G_4_16], # 40GB limit
)
# Should auto-size from 64GB to 40GB
assert endpoint.template.containerDiskInGb == 40
def test_instance_ids_clears_gpu_config_integration(self):
"""Integration: instanceIds clears GPU config across classes."""
# ServerlessEndpoint with both GPU and CPU specs
endpoint1 = ServerlessEndpoint(
name="test-mixed-1",
imageName="my-app:latest",
gpuIds="NVIDIA A40",
instanceIds=[CpuInstanceType.CPU3G_1_4],
)
# GPU config should be cleared
assert endpoint1.gpus == []
assert endpoint1.gpuIds == ""
assert endpoint1.instanceIds == [CpuInstanceType.CPU3G_1_4]
# LiveServerless with both GPU and CPU specs
endpoint2 = LiveServerless(
name="test-mixed-2",
gpuIds="NVIDIA A40",
instanceIds=[CpuInstanceType.CPU3G_1_4],
)
# GPU config should be cleared
assert endpoint2.gpus == []
assert endpoint2.gpuIds == ""
assert endpoint2.instanceIds == [CpuInstanceType.CPU3G_1_4]
class TestCpuDiskSizingIntegration:
"""Test CPU disk sizing across different endpoint types."""
def test_serverless_endpoint_no_auto_sizing(self):
"""Test ServerlessEndpoint (GPU) without instanceIds uses default 64GB."""
endpoint = ServerlessEndpoint(
name="test-gpu-endpoint",
imageName="test/gpu-image:latest",
)
# Should not have instanceIds specified, so no auto-sizing - uses default 64GB
assert endpoint.template is not None
assert endpoint.template.containerDiskInGb == 64
assert endpoint.instanceIds is None
def test_cpu_serverless_endpoint_auto_sizing_flow(self):
"""Test complete CPU auto-sizing flow in CpuServerlessEndpoint."""
endpoint = CpuServerlessEndpoint(
name="test-cpu-endpoint",
imageName="test/cpu-image:latest",
instanceIds=[CpuInstanceType.CPU3G_1_4, CpuInstanceType.CPU3G_2_8],
)
# Verify complete integration:
# 1. CPU utilities calculate minimum disk size
# 2. Template creation uses auto-sizing
# 3. Validation passes
assert endpoint.instanceIds == [
CpuInstanceType.CPU3G_1_4,
CpuInstanceType.CPU3G_2_8,
]
assert endpoint.template is not None
assert endpoint.template.containerDiskInGb == 10 # Minimum of 10 and 20
def test_live_serverless_cpu_integration(self):
"""Test CpuLiveServerless integrates CPU sizing with live serverless features."""
live_serverless = CpuLiveServerless(
name="test-cpu-live",
instanceIds=[CpuInstanceType.CPU5C_1_2, CpuInstanceType.CPU5C_2_4],
)
# Verify integration:
# 1. Uses CPU base image (default)
# 2. CPU utilities calculate minimum disk size
# 3. Template creation with auto-sizing
# 4. Validation passes
assert "runpod/flash-cpu:" in live_serverless.imageName
assert live_serverless.instanceIds == [
CpuInstanceType.CPU5C_1_2,
CpuInstanceType.CPU5C_2_4,
]
assert live_serverless.template is not None
assert live_serverless.template.containerDiskInGb == 15 # Minimum of 15 and 30
def test_template_integration_with_auto_sizing(self):
"""Test template creation and modification integrates with CPU sizing."""
# Start with existing template at default size
template = PodTemplate(name="base-template", imageName="test/image:v1")
default_size = template.containerDiskInGb # Should be 64GB default
# Create CPU endpoint with the template
endpoint = CpuServerlessEndpoint(
name="test-endpoint",
template=template,
instanceIds=[CpuInstanceType.CPU3G_1_4], # 10GB limit
)
# Verify template was modified for CPU sizing
assert endpoint.template.containerDiskInGb == 10
assert endpoint.template.containerDiskInGb != default_size
def test_template_integration_preserves_custom_size(self):
"""Test template integration preserves intentional custom sizing."""
# Template with explicit custom size
template = PodTemplate(
name="custom-template",
imageName="test/image:v1",
containerDiskInGb=8, # Explicit custom size
)
# Create CPU endpoint with the template
endpoint = CpuServerlessEndpoint(
name="test-endpoint",
template=template,
instanceIds=[CpuInstanceType.CPU3G_1_4], # 10GB limit
)
# Verify custom size was preserved (within limits)
assert endpoint.template.containerDiskInGb == 8
def test_validation_integration_across_components(self):
"""Test disk size validation works across different endpoint types."""
template_exceeding_limits = PodTemplate(
name="large-template",
imageName="test/image:v1",
containerDiskInGb=200, # Exceeds all CPU limits
)
# Should fail for CpuServerlessEndpoint
with pytest.raises(ValueError, match="Container disk size 200GB exceeds"):
CpuServerlessEndpoint(
name="cpu-endpoint",
template=template_exceeding_limits,
instanceIds=[CpuInstanceType.CPU3G_1_4],
)
# Should fail for CpuLiveServerless
with pytest.raises(ValueError, match="Container disk size 200GB exceeds"):
CpuLiveServerless(
name="cpu-live-endpoint",
template=template_exceeding_limits,
instanceIds=[CpuInstanceType.CPU3G_1_4],
)
# Should pass for regular ServerlessEndpoint (GPU)
gpu_endpoint = ServerlessEndpoint(
name="gpu-endpoint",
template=template_exceeding_limits,
)
assert gpu_endpoint.template.containerDiskInGb == 200
def test_mixed_cpu_generations_integration(self):
"""Test integration with mixed CPU instance generations."""
# Mix CPU3G, CPU3C, and CPU5C instances
mixed_instances = [
CpuInstanceType.CPU3G_1_4, # 10GB
CpuInstanceType.CPU3C_2_4, # 20GB
CpuInstanceType.CPU5C_1_2, # 15GB
]
endpoint = CpuServerlessEndpoint(
name="mixed-cpu-endpoint",
imageName="test/image:latest",
instanceIds=mixed_instances,
)
# Should use minimum across all generations
assert endpoint.template is not None
assert endpoint.template.containerDiskInGb == 10 # Minimum of 10, 20, 15
# Verify validation would catch excessive sizes
template_exceeding_min = PodTemplate(
name="test",
imageName="test/image:v1",
containerDiskInGb=12, # Exceeds minimum of 10GB
)
with pytest.raises(ValueError) as exc_info:
CpuServerlessEndpoint(
name="test-endpoint",
template=template_exceeding_min,
instanceIds=mixed_instances,
)
# Verify error message includes all instance types
error_msg = str(exc_info.value)
assert "cpu3g-1-4: max 10GB" in error_msg
assert "cpu3c-2-4: max 20GB" in error_msg
assert "cpu5c-1-2: max 15GB" in error_msg
class TestLiveServerlessImageDefaultsIntegration:
"""Test image defaults in live serverless variants."""
def test_live_serverless_image_defaults(self):
"""Test that LiveServerless variants use correct base images."""
gpu_live = LiveServerless(name="gpu-live")
cpu_live = CpuLiveServerless(name="cpu-live")
# Verify different base images are used
assert gpu_live.imageName != cpu_live.imageName
assert "runpod/flash:" in gpu_live.imageName
assert "runpod/flash-cpu:" in cpu_live.imageName
# Verify images can be overridden (BYOI)
custom_gpu = LiveServerless(
name="custom-gpu", imageName="nvidia/cuda:12.8.0-runtime"
)
assert custom_gpu.imageName == "nvidia/cuda:12.8.0-runtime"
def test_live_serverless_template_integration(self):
"""Test live serverless template integration with disk sizing."""
# GPU live serverless - no auto-sizing
gpu_live = LiveServerless(name="gpu-live")
assert gpu_live.template.containerDiskInGb == 64 # Default
# CPU live serverless - auto-sizing enabled
cpu_live = CpuLiveServerless(
name="cpu-live",
instanceIds=[CpuInstanceType.CPU3G_2_8],
)
assert cpu_live.template.containerDiskInGb == 20 # Auto-sized
def test_live_serverless_validation_integration(self):
"""Test live serverless validation integrates with CPU limits."""
# Custom template that exceeds CPU limits
large_template = PodTemplate(
name="large",
imageName="will-be-overridden",
containerDiskInGb=100,
)
# GPU live serverless should accept large template
gpu_live = LiveServerless(
name="gpu-live",
template=large_template,
)
assert gpu_live.template.containerDiskInGb == 100
# CPU live serverless should reject large template
with pytest.raises(ValueError, match="Container disk size 100GB exceeds"):
CpuLiveServerless(
name="cpu-live",
template=large_template,
instanceIds=[CpuInstanceType.CPU3G_1_4], # 10GB limit
)